summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorMyungJoo Ham <myungjoo.ham@samsung.com>2017-10-11 15:16:57 +0900
committerMyungJoo Ham <myungjoo.ham@samsung.com>2017-10-11 15:16:57 +0900
commit915c76ded744c0f5f151402b9fa69f3fd8452573 (patch)
treeca6a387466543248890f346847acaa8343989b22 /Source
parent317dbdb79761ef65e45c7358cfc7571c6afa54ad (diff)
downloadcmake-915c76ded744c0f5f151402b9fa69f3fd8452573.tar.gz
cmake-915c76ded744c0f5f151402b9fa69f3fd8452573.tar.bz2
cmake-915c76ded744c0f5f151402b9fa69f3fd8452573.zip
Imported Upstream version 3.9.4upstream/3.9.4
Diffstat (limited to 'Source')
-rw-r--r--Source/.cvsignore5
-rw-r--r--Source/.gitattributes4
-rw-r--r--Source/CMakeInstallDestinations.cmake54
-rw-r--r--Source/CMakeLists.txt696
-rw-r--r--Source/CMakeSourceDir.txt.in1
-rwxr-xr-xSource/CMakeVersion.bash2
-rw-r--r--Source/CMakeVersion.cmake7
-rw-r--r--Source/CMakeVersionCompute.cmake29
-rw-r--r--Source/CMakeVersionSource.cmake9
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.cxx137
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.h81
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx560
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.h152
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx500
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.h129
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx690
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.h147
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.cxx288
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.h88
-rw-r--r--Source/CPack/OSXScriptLauncher.cxx129
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx1296
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h158
-rw-r--r--Source/CPack/WiX/cmWIXAccessControlList.cxx126
-rw-r--r--Source/CPack/WiX/cmWIXAccessControlList.h34
-rw-r--r--Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx82
-rw-r--r--Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h34
-rw-r--r--Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx95
-rw-r--r--Source/CPack/WiX/cmWIXFeaturesSourceWriter.h32
-rw-r--r--Source/CPack/WiX/cmWIXFilesSourceWriter.cxx164
-rw-r--r--Source/CPack/WiX/cmWIXFilesSourceWriter.h43
-rw-r--r--Source/CPack/WiX/cmWIXPatch.cxx99
-rw-r--r--Source/CPack/WiX/cmWIXPatch.h37
-rw-r--r--Source/CPack/WiX/cmWIXPatchParser.cxx160
-rw-r--r--Source/CPack/WiX/cmWIXPatchParser.h90
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx157
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.h35
-rw-r--r--Source/CPack/WiX/cmWIXShortcut.cxx105
-rw-r--r--Source/CPack/WiX/cmWIXShortcut.h60
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.cxx249
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.h73
-rw-r--r--Source/CPack/cmCPack7zGenerator.cxx15
-rw-r--r--Source/CPack/cmCPack7zGenerator.h29
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx323
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.h46
-rw-r--r--Source/CPack/cmCPackBundleGenerator.cxx263
-rw-r--r--Source/CPack/cmCPackBundleGenerator.h29
-rw-r--r--Source/CPack/cmCPackComponentGroup.cxx41
-rw-r--r--Source/CPack/cmCPackComponentGroup.h56
-rw-r--r--Source/CPack/cmCPackConfigure.h.in13
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.cxx54
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.h15
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.cxx105
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.h15
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx1001
-rw-r--r--Source/CPack/cmCPackDebGenerator.h44
-rw-r--r--Source/CPack/cmCPackDocumentMacros.cxx16
-rw-r--r--Source/CPack/cmCPackDocumentMacros.h21
-rw-r--r--Source/CPack/cmCPackDocumentVariables.cxx122
-rw-r--r--Source/CPack/cmCPackDocumentVariables.h21
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx948
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.h52
-rw-r--r--Source/CPack/cmCPackGenerator.cxx1655
-rw-r--r--Source/CPack/cmCPackGenerator.h143
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx228
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.h44
-rw-r--r--Source/CPack/cmCPackLog.cxx222
-rw-r--r--Source/CPack/cmCPackLog.h87
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx1012
-rw-r--r--Source/CPack/cmCPackNSISGenerator.h73
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.cxx240
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.h36
-rw-r--r--Source/CPack/cmCPackPKGGenerator.cxx352
-rw-r--r--Source/CPack/cmCPackPKGGenerator.h92
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx971
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.h97
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.cxx258
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.h53
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx476
-rw-r--r--Source/CPack/cmCPackRPMGenerator.h41
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx108
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.h28
-rw-r--r--Source/CPack/cmCPackTGZGenerator.cxx23
-rw-r--r--Source/CPack/cmCPackTGZGenerator.h22
-rw-r--r--Source/CPack/cmCPackTXZGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackTXZGenerator.h29
-rw-r--r--Source/CPack/cmCPackTarBZip2Generator.cxx22
-rw-r--r--Source/CPack/cmCPackTarBZip2Generator.h22
-rw-r--r--Source/CPack/cmCPackTarCompressGenerator.cxx23
-rw-r--r--Source/CPack/cmCPackTarCompressGenerator.h23
-rw-r--r--Source/CPack/cmCPackZIPGenerator.cxx23
-rw-r--r--Source/CPack/cmCPackZIPGenerator.h21
-rw-r--r--Source/CPack/cpack.cxx606
-rw-r--r--Source/CPack/cygwin.readme69
-rw-r--r--Source/CTest/cmCTestBZR.cxx492
-rw-r--r--Source/CTest/cmCTestBZR.h41
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.cxx102
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.h32
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx532
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.h70
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx214
-rw-r--r--Source/CTest/cmCTestBuildCommand.h72
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx1181
-rw-r--r--Source/CTest/cmCTestBuildHandler.h128
-rw-r--r--Source/CTest/cmCTestCVS.cxx245
-rw-r--r--Source/CTest/cmCTestCVS.h44
-rw-r--r--Source/CTest/cmCTestCommand.h29
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx156
-rw-r--r--Source/CTest/cmCTestConfigureCommand.h64
-rw-r--r--Source/CTest/cmCTestConfigureHandler.cxx152
-rw-r--r--Source/CTest/cmCTestConfigureHandler.h22
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx50
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h68
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx2809
-rw-r--r--Source/CTest/cmCTestCoverageHandler.h105
-rw-r--r--Source/CTest/cmCTestCurl.cxx276
-rw-r--r--Source/CTest/cmCTestCurl.h53
-rw-r--r--Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx39
-rw-r--r--Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h65
-rw-r--r--Source/CTest/cmCTestGIT.cxx577
-rw-r--r--Source/CTest/cmCTestGIT.h46
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx163
-rw-r--r--Source/CTest/cmCTestGenericHandler.h67
-rw-r--r--Source/CTest/cmCTestGlobalVC.cxx108
-rw-r--r--Source/CTest/cmCTestGlobalVC.h49
-rw-r--r--Source/CTest/cmCTestHG.cxx292
-rw-r--r--Source/CTest/cmCTestHG.h39
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx324
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h45
-rw-r--r--Source/CTest/cmCTestLaunch.cxx676
-rw-r--r--Source/CTest/cmCTestLaunch.h41
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.cxx64
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.h76
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx1498
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h121
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx888
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h105
-rw-r--r--Source/CTest/cmCTestP4.cxx529
-rw-r--r--Source/CTest/cmCTestP4.h76
-rw-r--r--Source/CTest/cmCTestReadCustomFilesCommand.cxx34
-rw-r--r--Source/CTest/cmCTestReadCustomFilesCommand.h60
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.cxx64
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.h64
-rw-r--r--Source/CTest/cmCTestRunTest.cxx790
-rw-r--r--Source/CTest/cmCTestRunTest.h98
-rw-r--r--Source/CTest/cmCTestSVN.cxx517
-rw-r--r--Source/CTest/cmCTestSVN.h63
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx967
-rw-r--r--Source/CTest/cmCTestScriptHandler.h84
-rw-r--r--Source/CTest/cmCTestSleepCommand.cxx44
-rw-r--r--Source/CTest/cmCTestSleepCommand.h61
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx169
-rw-r--r--Source/CTest/cmCTestStartCommand.h71
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx332
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h96
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx1862
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h104
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx142
-rw-r--r--Source/CTest/cmCTestTestCommand.h80
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx2759
-rw-r--r--Source/CTest/cmCTestTestHandler.h203
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx139
-rw-r--r--Source/CTest/cmCTestUpdateCommand.h56
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx487
-rw-r--r--Source/CTest/cmCTestUpdateHandler.h45
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx79
-rw-r--r--Source/CTest/cmCTestUploadCommand.h64
-rw-r--r--Source/CTest/cmCTestUploadHandler.cxx92
-rw-r--r--Source/CTest/cmCTestUploadHandler.h24
-rw-r--r--Source/CTest/cmCTestVC.cxx170
-rw-r--r--Source/CTest/cmCTestVC.h72
-rw-r--r--Source/CTest/cmParseBlanketJSCoverage.cxx139
-rw-r--r--Source/CTest/cmParseBlanketJSCoverage.h42
-rw-r--r--Source/CTest/cmParseCacheCoverage.cxx204
-rw-r--r--Source/CTest/cmParseCacheCoverage.h32
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.cxx171
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.h45
-rw-r--r--Source/CTest/cmParseDelphiCoverage.cxx229
-rw-r--r--Source/CTest/cmParseDelphiCoverage.h38
-rw-r--r--Source/CTest/cmParseGTMCoverage.cxx230
-rw-r--r--Source/CTest/cmParseGTMCoverage.h38
-rw-r--r--Source/CTest/cmParseJacocoCoverage.cxx184
-rw-r--r--Source/CTest/cmParseJacocoCoverage.h53
-rw-r--r--Source/CTest/cmParseMumpsCoverage.cxx153
-rw-r--r--Source/CTest/cmParseMumpsCoverage.h33
-rw-r--r--Source/CTest/cmParsePHPCoverage.cxx212
-rw-r--r--Source/CTest/cmParsePHPCoverage.h38
-rw-r--r--Source/CTest/cmProcess.cxx238
-rw-r--r--Source/CTest/cmProcess.h51
-rw-r--r--Source/Checks/cm_c11_thread_local.c5
-rw-r--r--Source/Checks/cm_c11_thread_local.cmake33
-rw-r--r--Source/Checks/cm_cxx14_cstdio.cmake33
-rw-r--r--Source/Checks/cm_cxx14_cstdio.cpp5
-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.cmake58
-rw-r--r--Source/Checks/cm_cxx_gnu_fallthrough.cxx11
-rw-r--r--Source/Checks/cm_cxx_make_unique.cxx6
-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_unique_ptr.cxx6
-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.txt35
-rw-r--r--Source/CursesDialog/ccmake.cxx218
-rw-r--r--Source/CursesDialog/cmCursesBoolWidget.cxx73
-rw-r--r--Source/CursesDialog/cmCursesBoolWidget.h30
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.cxx127
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.h37
-rw-r--r--Source/CursesDialog/cmCursesDummyWidget.cxx29
-rw-r--r--Source/CursesDialog/cmCursesDummyWidget.h29
-rw-r--r--Source/CursesDialog/cmCursesFilePathWidget.cxx25
-rw-r--r--Source/CursesDialog/cmCursesFilePathWidget.h26
-rw-r--r--Source/CursesDialog/cmCursesForm.cxx34
-rw-r--r--Source/CursesDialog/cmCursesForm.h36
-rw-r--r--Source/CursesDialog/cmCursesLabelWidget.cxx33
-rw-r--r--Source/CursesDialog/cmCursesLabelWidget.h33
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx179
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.h37
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx1289
-rw-r--r--Source/CursesDialog/cmCursesMainForm.h60
-rw-r--r--Source/CursesDialog/cmCursesOptionsWidget.cxx85
-rw-r--r--Source/CursesDialog/cmCursesOptionsWidget.h38
-rw-r--r--Source/CursesDialog/cmCursesPathWidget.cxx77
-rw-r--r--Source/CursesDialog/cmCursesPathWidget.h35
-rw-r--r--Source/CursesDialog/cmCursesStandardIncludes.h65
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.cxx232
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.h35
-rw-r--r--Source/CursesDialog/cmCursesWidget.cxx44
-rw-r--r--Source/CursesDialog/cmCursesWidget.h50
-rw-r--r--Source/CursesDialog/form/.gitattributes1
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt14
-rw-r--r--Source/CursesDialog/form/cmFormConfigure.h.in14
-rw-r--r--Source/CursesDialog/form/fld_attr.c8
-rw-r--r--Source/CursesDialog/form/fld_def.c4
-rw-r--r--Source/CursesDialog/form/fld_ftlink.c2
-rw-r--r--Source/CursesDialog/form/fld_newftyp.c2
-rw-r--r--Source/CursesDialog/form/form.h16
-rw-r--r--Source/CursesDialog/form/form.priv.h8
-rw-r--r--Source/CursesDialog/form/frm_def.c4
-rw-r--r--Source/CursesDialog/form/frm_driver.c23
-rw-r--r--Source/CursesDialog/form/frm_post.c5
-rw-r--r--Source/CursesDialog/form/frm_req_name.c6
-rw-r--r--Source/LexerParser/.clang-tidy6
-rw-r--r--Source/LexerParser/.gitattributes17
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.cxx2072
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.h (renamed from Source/cmCommandArgumentLexer.h)153
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.in.l (renamed from Source/cmCommandArgumentLexer.in.l)49
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.cxx (renamed from Source/cmCommandArgumentParser.cxx)1360
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.y191
-rw-r--r--Source/LexerParser/cmCommandArgumentParserTokens.h82
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.cxx (renamed from Source/cmDependsJavaLexer.cxx)2266
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.h (renamed from Source/cmDependsJavaLexer.h)210
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.in.l (renamed from Source/cmDependsJavaLexer.in.l)43
-rw-r--r--Source/LexerParser/cmDependsJavaParser.cxx (renamed from Source/cmDependsJavaParser.cxx)3978
-rw-r--r--Source/LexerParser/cmDependsJavaParser.y (renamed from Source/cmDependsJavaParser.y)53
-rw-r--r--Source/LexerParser/cmDependsJavaParserTokens.h264
-rw-r--r--Source/LexerParser/cmExprLexer.cxx2033
-rw-r--r--Source/LexerParser/cmExprLexer.h (renamed from Source/cmExprLexer.h)202
-rw-r--r--Source/LexerParser/cmExprLexer.in.l57
-rw-r--r--Source/LexerParser/cmExprParser.cxx1698
-rw-r--r--Source/LexerParser/cmExprParser.y164
-rw-r--r--Source/LexerParser/cmExprParserTokens.h86
-rw-r--r--Source/LexerParser/cmFortranLexer.cxx2511
-rw-r--r--Source/LexerParser/cmFortranLexer.h (renamed from Source/cmDependsFortranLexer.h)202
-rw-r--r--Source/LexerParser/cmFortranLexer.in.l (renamed from Source/cmDependsFortranLexer.in.l)86
-rw-r--r--Source/LexerParser/cmFortranParser.cxx (renamed from Source/cmDependsFortranParser.cxx)1476
-rw-r--r--Source/LexerParser/cmFortranParser.y247
-rw-r--r--Source/LexerParser/cmFortranParserTokens.h149
-rw-r--r--Source/LexerParser/cmListFileLexer.c2688
-rw-r--r--Source/LexerParser/cmListFileLexer.in.l (renamed from Source/cmListFileLexer.in.l)382
-rw-r--r--Source/Modules/FindJsonCpp.cmake107
-rw-r--r--Source/Modules/FindLibRHash.cmake73
-rw-r--r--Source/Modules/FindLibUV.cmake121
-rw-r--r--Source/QtDialog/AddCacheEntry.cxx84
-rw-r--r--Source/QtDialog/AddCacheEntry.h31
-rw-r--r--Source/QtDialog/CMakeLists.txt190
-rw-r--r--Source/QtDialog/CMakeSetup.cxx296
-rw-r--r--Source/QtDialog/CMakeSetup64.pngbin0 -> 7213 bytes
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx986
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h40
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui9
-rw-r--r--Source/QtDialog/Compilers.h8
-rw-r--r--Source/QtDialog/FirstConfigure.cxx240
-rw-r--r--Source/QtDialog/FirstConfigure.h160
-rw-r--r--Source/QtDialog/Info.plist.in34
-rw-r--r--Source/QtDialog/MacInstallDialog.ui103
-rw-r--r--Source/QtDialog/QCMake.cxx404
-rw-r--r--Source/QtDialog/QCMake.h90
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx443
-rw-r--r--Source/QtDialog/QCMakeCacheView.h76
-rw-r--r--Source/QtDialog/QCMakeWidgets.cxx88
-rw-r--r--Source/QtDialog/QCMakeWidgets.h33
-rw-r--r--Source/QtDialog/QMacInstallDialog.cxx121
-rw-r--r--Source/QtDialog/QMacInstallDialog.h20
-rw-r--r--Source/QtDialog/QtDialogCPack.cmake.in3
-rw-r--r--Source/QtDialog/RegexExplorer.cxx166
-rw-r--r--Source/QtDialog/RegexExplorer.h39
-rw-r--r--Source/QtDialog/RegexExplorer.ui182
-rw-r--r--Source/QtDialog/WarningMessagesDialog.cxx86
-rw-r--r--Source/QtDialog/WarningMessagesDialog.h65
-rw-r--r--Source/QtDialog/WarningMessagesDialog.ui173
-rw-r--r--Source/QtDialog/cmake-gui.desktop (renamed from Source/QtDialog/CMake.desktop)2
-rwxr-xr-xSource/QtDialog/postflight.sh.in3
-rwxr-xr-xSource/QtDialog/postupgrade.sh.in2
-rw-r--r--Source/QtIFW/CMake.DeveloperReference.HTML.qs.in21
-rw-r--r--Source/QtIFW/CMake.Dialogs.QtGUI.qs.in21
-rw-r--r--Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in21
-rw-r--r--Source/QtIFW/CMake.qs.in24
-rw-r--r--Source/QtIFW/cmake.org.html7
-rw-r--r--Source/QtIFW/controlscript.qs6
-rw-r--r--Source/QtIFW/installscript.qs.in27
-rw-r--r--Source/bindexplib.cxx405
-rw-r--r--Source/bindexplib.h24
-rw-r--r--Source/cmAddCompileOptionsCommand.cxx31
-rw-r--r--Source/cmAddCompileOptionsCommand.h64
-rw-r--r--Source/cmAddCustomCommandCommand.cxx448
-rw-r--r--Source/cmAddCustomCommandCommand.h176
-rw-r--r--Source/cmAddCustomTargetCommand.cxx248
-rw-r--r--Source/cmAddCustomTargetCommand.h94
-rw-r--r--Source/cmAddDefinitionsCommand.cxx32
-rw-r--r--Source/cmAddDefinitionsCommand.h67
-rw-r--r--Source/cmAddDependenciesCommand.cxx56
-rw-r--r--Source/cmAddDependenciesCommand.h66
-rw-r--r--Source/cmAddExecutableCommand.cxx273
-rw-r--r--Source/cmAddExecutableCommand.h117
-rw-r--r--Source/cmAddLibraryCommand.cxx433
-rw-r--r--Source/cmAddLibraryCommand.h148
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx117
-rw-r--r--Source/cmAddSubDirectoryCommand.h85
-rw-r--r--Source/cmAddTestCommand.cxx143
-rw-r--r--Source/cmAddTestCommand.h89
-rw-r--r--Source/cmAlgorithms.h405
-rw-r--r--Source/cmArchiveWrite.cxx383
-rw-r--r--Source/cmArchiveWrite.h135
-rw-r--r--Source/cmAuxSourceDirectoryCommand.cxx97
-rw-r--r--Source/cmAuxSourceDirectoryCommand.h70
-rw-r--r--Source/cmBase32.cxx99
-rw-r--r--Source/cmBase32.h33
-rw-r--r--Source/cmBootstrapCommands1.cxx91
-rw-r--r--Source/cmBootstrapCommands2.cxx102
-rw-r--r--Source/cmBreakCommand.cxx81
-rw-r--r--Source/cmBreakCommand.h61
-rw-r--r--Source/cmBuildCommand.cxx191
-rw-r--r--Source/cmBuildCommand.h76
-rw-r--r--Source/cmBuildNameCommand.cxx87
-rw-r--r--Source/cmBuildNameCommand.h83
-rw-r--r--Source/cmCLocaleEnvironmentScope.cxx54
-rw-r--r--Source/cmCLocaleEnvironmentScope.h27
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx122
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.h90
-rw-r--r--Source/cmCMakeMinimumRequired.cxx143
-rw-r--r--Source/cmCMakeMinimumRequired.h74
-rw-r--r--Source/cmCMakePolicyCommand.cxx165
-rw-r--r--Source/cmCMakePolicyCommand.h124
-rw-r--r--Source/cmCPackPropertiesGenerator.cxx48
-rw-r--r--Source/cmCPackPropertiesGenerator.h38
-rw-r--r--Source/cmCPluginAPI.cxx762
-rw-r--r--Source/cmCPluginAPI.h250
-rw-r--r--Source/cmCTest.cxx3389
-rw-r--r--Source/cmCTest.h505
-rw-r--r--Source/cmCacheManager.cxx878
-rw-r--r--Source/cmCacheManager.h249
-rw-r--r--Source/cmCallVisualStudioMacro.cxx353
-rw-r--r--Source/cmCallVisualStudioMacro.h21
-rw-r--r--Source/cmCommand.cxx33
-rw-r--r--Source/cmCommand.h142
-rw-r--r--Source/cmCommandArgumentLexer.cxx2077
-rw-r--r--Source/cmCommandArgumentParser.y246
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx332
-rw-r--r--Source/cmCommandArgumentParserHelper.h61
-rw-r--r--Source/cmCommandArgumentParserTokens.h92
-rw-r--r--Source/cmCommandArgumentsHelper.cxx242
-rw-r--r--Source/cmCommandArgumentsHelper.h258
-rw-r--r--Source/cmCommands.cxx415
-rw-r--r--Source/cmCommands.h32
-rw-r--r--Source/cmCommonTargetGenerator.cxx238
-rw-r--r--Source/cmCommonTargetGenerator.h66
-rw-r--r--Source/cmComputeComponentGraph.cxx78
-rw-r--r--Source/cmComputeComponentGraph.h38
-rw-r--r--Source/cmComputeLinkDepends.cxx650
-rw-r--r--Source/cmComputeLinkDepends.h114
-rw-r--r--Source/cmComputeLinkInformation.cxx1322
-rw-r--r--Source/cmComputeLinkInformation.h124
-rw-r--r--Source/cmComputeTargetDepends.cxx547
-rw-r--r--Source/cmComputeTargetDepends.h55
-rw-r--r--Source/cmConditionEvaluator.cxx756
-rw-r--r--Source/cmConditionEvaluator.h92
-rw-r--r--Source/cmConfigure.cmake.h.in83
-rw-r--r--Source/cmConfigureFileCommand.cxx157
-rw-r--r--Source/cmConfigureFileCommand.h103
-rw-r--r--Source/cmContinueCommand.cxx33
-rw-r--r--Source/cmContinueCommand.h36
-rw-r--r--Source/cmConvertMSBuildXMLToJSON.py453
-rw-r--r--Source/cmCoreTryCompile.cxx1139
-rw-r--r--Source/cmCoreTryCompile.h34
-rw-r--r--Source/cmCreateTestSourceList.cxx151
-rw-r--r--Source/cmCreateTestSourceList.h80
-rw-r--r--Source/cmCryptoHash.cxx248
-rw-r--r--Source/cmCryptoHash.h128
-rw-r--r--Source/cmCurl.cxx58
-rw-r--r--Source/cmCurl.h13
-rw-r--r--Source/cmCustomCommand.cxx178
-rw-r--r--Source/cmCustomCommand.h73
-rw-r--r--Source/cmCustomCommandGenerator.cxx210
-rw-r--r--Source/cmCustomCommandGenerator.h42
-rw-r--r--Source/cmCustomCommandLines.h29
-rw-r--r--Source/cmDefinePropertyCommand.cxx141
-rw-r--r--Source/cmDefinePropertyCommand.h84
-rw-r--r--Source/cmDefinitions.cxx223
-rw-r--r--Source/cmDefinitions.h98
-rw-r--r--Source/cmDepends.cxx263
-rw-r--r--Source/cmDepends.h59
-rw-r--r--Source/cmDependsC.cxx511
-rw-r--r--Source/cmDependsC.h66
-rw-r--r--Source/cmDependsFortran.cxx1133
-rw-r--r--Source/cmDependsFortran.h60
-rw-r--r--Source/cmDependsFortranLexer.cxx2414
-rw-r--r--Source/cmDependsFortranParser.h96
-rw-r--r--Source/cmDependsFortranParser.y288
-rw-r--r--Source/cmDependsFortranParserTokens.h122
-rw-r--r--Source/cmDependsJava.cxx31
-rw-r--r--Source/cmDependsJava.h42
-rw-r--r--Source/cmDependsJavaParserHelper.cxx407
-rw-r--r--Source/cmDependsJavaParserHelper.h88
-rw-r--r--Source/cmDependsJavaParserTokens.h254
-rw-r--r--Source/cmDisallowedCommand.cxx31
-rw-r--r--Source/cmDisallowedCommand.h51
-rw-r--r--Source/cmDocumentCompileDefinitions.h34
-rw-r--r--Source/cmDocumentGeneratorExpressions.h98
-rw-r--r--Source/cmDocumentLocationUndefined.h24
-rw-r--r--Source/cmDocumentVariables.cxx2030
-rw-r--r--Source/cmDocumentVariables.h21
-rw-r--r--Source/cmDocumentation.cxx2199
-rw-r--r--Source/cmDocumentation.h249
-rw-r--r--Source/cmDocumentationEntry.h36
-rw-r--r--Source/cmDocumentationFormatter.cxx268
-rw-r--r--Source/cmDocumentationFormatter.h71
-rw-r--r--Source/cmDocumentationFormatterDocbook.cxx254
-rw-r--r--Source/cmDocumentationFormatterDocbook.h43
-rw-r--r--Source/cmDocumentationFormatterHTML.cxx288
-rw-r--r--Source/cmDocumentationFormatterHTML.h42
-rw-r--r--Source/cmDocumentationFormatterMan.cxx102
-rw-r--r--Source/cmDocumentationFormatterMan.h43
-rw-r--r--Source/cmDocumentationFormatterText.cxx180
-rw-r--r--Source/cmDocumentationFormatterText.h40
-rw-r--r--Source/cmDocumentationFormatterUsage.cxx63
-rw-r--r--Source/cmDocumentationFormatterUsage.h31
-rw-r--r--Source/cmDocumentationSection.cxx79
-rw-r--r--Source/cmDocumentationSection.h65
-rw-r--r--Source/cmDynamicLoader.cxx78
-rw-r--r--Source/cmDynamicLoader.h32
-rw-r--r--Source/cmELF.cxx815
-rw-r--r--Source/cmELF.h48
-rw-r--r--Source/cmElseCommand.cxx21
-rw-r--r--Source/cmElseCommand.h72
-rw-r--r--Source/cmElseIfCommand.cxx20
-rw-r--r--Source/cmElseIfCommand.h72
-rw-r--r--Source/cmEnableLanguageCommand.cxx41
-rw-r--r--Source/cmEnableLanguageCommand.h69
-rw-r--r--Source/cmEnableTestingCommand.cxx20
-rw-r--r--Source/cmEnableTestingCommand.h59
-rw-r--r--Source/cmEndForEachCommand.cxx23
-rw-r--r--Source/cmEndForEachCommand.h79
-rw-r--r--Source/cmEndFunctionCommand.cxx23
-rw-r--r--Source/cmEndFunctionCommand.h79
-rw-r--r--Source/cmEndIfCommand.cxx29
-rw-r--r--Source/cmEndIfCommand.h72
-rw-r--r--Source/cmEndMacroCommand.cxx23
-rw-r--r--Source/cmEndMacroCommand.h79
-rw-r--r--Source/cmEndWhileCommand.cxx32
-rw-r--r--Source/cmEndWhileCommand.h79
-rw-r--r--Source/cmExecProgramCommand.cxx301
-rw-r--r--Source/cmExecProgramCommand.h89
-rw-r--r--Source/cmExecuteProcessCommand.cxx387
-rw-r--r--Source/cmExecuteProcessCommand.h100
-rw-r--r--Source/cmExecutionStatus.h62
-rw-r--r--Source/cmExpandedCommandArgument.cxx40
-rw-r--r--Source/cmExpandedCommandArgument.h38
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx204
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.h66
-rw-r--r--Source/cmExportBuildFileGenerator.cxx386
-rw-r--r--Source/cmExportBuildFileGenerator.h81
-rw-r--r--Source/cmExportCommand.cxx455
-rw-r--r--Source/cmExportCommand.h106
-rw-r--r--Source/cmExportFileGenerator.cxx1174
-rw-r--r--Source/cmExportFileGenerator.h201
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx138
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h72
-rw-r--r--Source/cmExportInstallFileGenerator.cxx594
-rw-r--r--Source/cmExportInstallFileGenerator.h88
-rw-r--r--Source/cmExportLibraryDependencies.cxx204
-rw-r--r--Source/cmExportLibraryDependencies.h100
-rw-r--r--Source/cmExportLibraryDependenciesCommand.cxx176
-rw-r--r--Source/cmExportLibraryDependenciesCommand.h34
-rw-r--r--Source/cmExportSet.cxx30
-rw-r--r--Source/cmExportSet.h37
-rw-r--r--Source/cmExportSetMap.cxx37
-rw-r--r--Source/cmExportSetMap.h25
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx159
-rw-r--r--Source/cmExportTryCompileFileGenerator.h81
-rw-r--r--Source/cmExprLexer.cxx1928
-rw-r--r--Source/cmExprLexer.in.l74
-rw-r--r--Source/cmExprParser.cxx1433
-rw-r--r--Source/cmExprParser.y170
-rw-r--r--Source/cmExprParserHelper.cxx85
-rw-r--r--Source/cmExprParserHelper.h46
-rw-r--r--Source/cmExprParserTokens.h76
-rw-r--r--Source/cmExternalMakefileProjectGenerator.cxx90
-rw-r--r--Source/cmExternalMakefileProjectGenerator.h90
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx1028
-rw-r--r--Source/cmExtraCodeBlocksGenerator.h60
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx710
-rw-r--r--Source/cmExtraCodeLiteGenerator.h72
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx1764
-rw-r--r--Source/cmExtraEclipseCDT4Generator.h117
-rw-r--r--Source/cmExtraKateGenerator.cxx316
-rw-r--r--Source/cmExtraKateGenerator.h46
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx578
-rw-r--r--Source/cmExtraSublimeTextGenerator.h71
-rw-r--r--Source/cmFLTKWrapUICommand.cxx158
-rw-r--r--Source/cmFLTKWrapUICommand.h67
-rw-r--r--Source/cmFileCommand.cxx3625
-rw-r--r--Source/cmFileCommand.h258
-rw-r--r--Source/cmFileLock.cxx60
-rw-r--r--Source/cmFileLock.h65
-rw-r--r--Source/cmFileLockPool.cxx158
-rw-r--r--Source/cmFileLockPool.h90
-rw-r--r--Source/cmFileLockResult.cxx92
-rw-r--r--Source/cmFileLockResult.h77
-rw-r--r--Source/cmFileLockUnix.cxx78
-rw-r--r--Source/cmFileLockWin32.cxx88
-rw-r--r--Source/cmFileMonitor.cxx389
-rw-r--r--Source/cmFileMonitor.h32
-rw-r--r--Source/cmFilePathChecksum.cxx88
-rw-r--r--Source/cmFilePathChecksum.h65
-rw-r--r--Source/cmFileTimeComparison.cxx217
-rw-r--r--Source/cmFileTimeComparison.h18
-rw-r--r--Source/cmFindBase.cxx675
-rw-r--r--Source/cmFindBase.h52
-rw-r--r--Source/cmFindCommon.cxx520
-rw-r--r--Source/cmFindCommon.h113
-rw-r--r--Source/cmFindFileCommand.cxx26
-rw-r--r--Source/cmFindFileCommand.h37
-rw-r--r--Source/cmFindLibraryCommand.cxx525
-rw-r--r--Source/cmFindLibraryCommand.h55
-rw-r--r--Source/cmFindPackageCommand.cxx2809
-rw-r--r--Source/cmFindPackageCommand.h179
-rw-r--r--Source/cmFindPathCommand.cxx227
-rw-r--r--Source/cmFindPathCommand.h53
-rw-r--r--Source/cmFindProgramCommand.cxx291
-rw-r--r--Source/cmFindProgramCommand.h66
-rw-r--r--Source/cmForEachCommand.cxx255
-rw-r--r--Source/cmForEachCommand.h101
-rw-r--r--Source/cmFortranParser.h160
-rw-r--r--Source/cmFortranParserImpl.cxx361
-rw-r--r--Source/cmFunctionBlocker.h39
-rw-r--r--Source/cmFunctionCommand.cxx258
-rw-r--r--Source/cmFunctionCommand.h95
-rw-r--r--Source/cmGeneratedFileStream.cxx180
-rw-r--r--Source/cmGeneratedFileStream.h49
-rw-r--r--Source/cmGeneratorExpression.cxx464
-rw-r--r--Source/cmGeneratorExpression.h157
-rw-r--r--Source/cmGeneratorExpressionContext.cxx22
-rw-r--r--Source/cmGeneratorExpressionContext.h46
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx280
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h103
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx216
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.h50
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx1692
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h114
-rw-r--r--Source/cmGeneratorExpressionLexer.cxx111
-rw-r--r--Source/cmGeneratorExpressionLexer.h33
-rw-r--r--Source/cmGeneratorExpressionNode.cxx1897
-rw-r--r--Source/cmGeneratorExpressionNode.h54
-rw-r--r--Source/cmGeneratorExpressionParser.cxx258
-rw-r--r--Source/cmGeneratorExpressionParser.h30
-rw-r--r--Source/cmGeneratorTarget.cxx5663
-rw-r--r--Source/cmGeneratorTarget.h857
-rw-r--r--Source/cmGetCMakePropertyCommand.cxx91
-rw-r--r--Source/cmGetCMakePropertyCommand.h68
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx123
-rw-r--r--Source/cmGetDirectoryPropertyCommand.h75
-rw-r--r--Source/cmGetFilenameComponentCommand.cxx151
-rw-r--r--Source/cmGetFilenameComponentCommand.h80
-rw-r--r--Source/cmGetPropertyCommand.cxx448
-rw-r--r--Source/cmGetPropertyCommand.h102
-rw-r--r--Source/cmGetSourceFilePropertyCommand.cxx57
-rw-r--r--Source/cmGetSourceFilePropertyCommand.h62
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx105
-rw-r--r--Source/cmGetTargetPropertyCommand.h64
-rw-r--r--Source/cmGetTestPropertyCommand.cxx50
-rw-r--r--Source/cmGetTestPropertyCommand.h61
-rw-r--r--Source/cmGhsMultiGpj.cxx34
-rw-r--r--Source/cmGhsMultiGpj.h27
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx661
-rw-r--r--Source/cmGhsMultiTargetGenerator.h120
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx52
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h44
-rw-r--r--Source/cmGlobalCommonGenerator.cxx14
-rw-r--r--Source/cmGlobalCommonGenerator.h22
-rw-r--r--Source/cmGlobalGenerator.cxx3485
-rw-r--r--Source/cmGlobalGenerator.h595
-rw-r--r--Source/cmGlobalGeneratorFactory.h60
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx490
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h133
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx77
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h43
-rw-r--r--Source/cmGlobalKdevelopGenerator.cxx923
-rw-r--r--Source/cmGlobalKdevelopGenerator.h31
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.cxx89
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.h39
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.cxx72
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.h40
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx77
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h50
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx1977
-rw-r--r--Source/cmGlobalNinjaGenerator.h371
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx1139
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h201
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx1132
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h195
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx311
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h55
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx260
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h58
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx287
-rw-r--r--Source/cmGlobalVisualStudio14Generator.h51
-rw-r--r--Source/cmGlobalVisualStudio15Generator.cxx206
-rw-r--r--Source/cmGlobalVisualStudio15Generator.h54
-rw-r--r--Source/cmGlobalVisualStudio6Generator.cxx421
-rw-r--r--Source/cmGlobalVisualStudio6Generator.h105
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx300
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h73
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx1107
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h184
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx557
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h67
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx150
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h29
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx983
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h159
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx61
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h52
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx4758
-rw-r--r--Source/cmGlobalXCodeGenerator.h264
-rw-r--r--Source/cmGraphAdjacencyList.h38
-rw-r--r--Source/cmGraphVizWriter.cxx533
-rw-r--r--Source/cmGraphVizWriter.h65
-rw-r--r--Source/cmHexFileConverter.cxx228
-rw-r--r--Source/cmHexFileConverter.h20
-rw-r--r--Source/cmIDEFlagTable.h44
-rw-r--r--Source/cmIDEOptions.cxx213
-rw-r--r--Source/cmIDEOptions.h71
-rw-r--r--Source/cmIfCommand.cxx928
-rw-r--r--Source/cmIfCommand.h264
-rw-r--r--Source/cmIncludeCommand.cxx171
-rw-r--r--Source/cmIncludeCommand.h82
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx132
-rw-r--r--Source/cmIncludeDirectoryCommand.h80
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.cxx104
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.h71
-rw-r--r--Source/cmIncludeRegularExpressionCommand.cxx32
-rw-r--r--Source/cmIncludeRegularExpressionCommand.h63
-rw-r--r--Source/cmInstallCommand.cxx1620
-rw-r--r--Source/cmInstallCommand.h339
-rw-r--r--Source/cmInstallCommandArguments.cxx202
-rw-r--r--Source/cmInstallCommandArguments.h118
-rw-r--r--Source/cmInstallDirectoryGenerator.cxx128
-rw-r--r--Source/cmInstallDirectoryGenerator.h45
-rw-r--r--Source/cmInstallExportAndroidMKGenerator.cxx140
-rw-r--r--Source/cmInstallExportAndroidMKGenerator.h37
-rw-r--r--Source/cmInstallExportGenerator.cxx244
-rw-r--r--Source/cmInstallExportGenerator.h57
-rw-r--r--Source/cmInstallFilesCommand.cxx159
-rw-r--r--Source/cmInstallFilesCommand.h88
-rw-r--r--Source/cmInstallFilesGenerator.cxx117
-rw-r--r--Source/cmInstallFilesGenerator.h45
-rw-r--r--Source/cmInstallGenerator.cxx259
-rw-r--r--Source/cmInstallGenerator.h70
-rw-r--r--Source/cmInstallProgramsCommand.cxx127
-rw-r--r--Source/cmInstallProgramsCommand.h83
-rw-r--r--Source/cmInstallScriptGenerator.cxx52
-rw-r--r--Source/cmInstallScriptGenerator.h26
-rw-r--r--Source/cmInstallTargetGenerator.cxx817
-rw-r--r--Source/cmInstallTargetGenerator.h119
-rw-r--r--Source/cmInstallTargetsCommand.cxx74
-rw-r--r--Source/cmInstallTargetsCommand.h67
-rw-r--r--Source/cmInstallType.h13
-rw-r--r--Source/cmInstalledFile.cxx121
-rw-r--r--Source/cmInstalledFile.h75
-rw-r--r--Source/cmLinkDirectoriesCommand.cxx64
-rw-r--r--Source/cmLinkDirectoriesCommand.h64
-rw-r--r--Source/cmLinkItem.h162
-rw-r--r--Source/cmLinkLibrariesCommand.cxx56
-rw-r--r--Source/cmLinkLibrariesCommand.h69
-rw-r--r--Source/cmLinkLineComputer.cxx192
-rw-r--r--Source/cmLinkLineComputer.h60
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx102
-rw-r--r--Source/cmLinkLineDeviceComputer.h52
-rw-r--r--Source/cmLinkedTree.h193
-rw-r--r--Source/cmListCommand.cxx673
-rw-r--r--Source/cmListCommand.h110
-rw-r--r--Source/cmListFileCache.cxx626
-rw-r--r--Source/cmListFileCache.h170
-rw-r--r--Source/cmListFileLexer.c2417
-rw-r--r--Source/cmListFileLexer.h39
-rw-r--r--Source/cmLoadCacheCommand.cxx177
-rw-r--r--Source/cmLoadCacheCommand.h73
-rw-r--r--Source/cmLoadCommandCommand.cxx285
-rw-r--r--Source/cmLoadCommandCommand.h76
-rw-r--r--Source/cmLocalCommonGenerator.cxx79
-rw-r--r--Source/cmLocalCommonGenerator.h41
-rw-r--r--Source/cmLocalGenerator.cxx4074
-rw-r--r--Source/cmLocalGenerator.h535
-rw-r--r--Source/cmLocalGhsMultiGenerator.cxx33
-rw-r--r--Source/cmLocalGhsMultiGenerator.h29
-rw-r--r--Source/cmLocalNinjaGenerator.cxx501
-rw-r--r--Source/cmLocalNinjaGenerator.h129
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx2331
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h352
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx136
-rw-r--r--Source/cmLocalVisualStudio10Generator.h24
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx1956
-rw-r--r--Source/cmLocalVisualStudio6Generator.h103
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx2701
-rw-r--r--Source/cmLocalVisualStudio7Generator.h129
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx193
-rw-r--r--Source/cmLocalVisualStudioGenerator.h67
-rw-r--r--Source/cmLocalXCodeGenerator.cxx81
-rw-r--r--Source/cmLocalXCodeGenerator.h39
-rw-r--r--Source/cmLocale.h27
-rw-r--r--Source/cmMSVC60LinkLineComputer.cxx40
-rw-r--r--Source/cmMSVC60LinkLineComputer.h28
-rw-r--r--Source/cmMachO.cxx363
-rw-r--r--Source/cmMachO.h47
-rw-r--r--Source/cmMacroCommand.cxx325
-rw-r--r--Source/cmMacroCommand.h99
-rw-r--r--Source/cmMakeDepend.cxx364
-rw-r--r--Source/cmMakeDepend.h150
-rw-r--r--Source/cmMakeDirectoryCommand.cxx41
-rw-r--r--Source/cmMakeDirectoryCommand.h69
-rw-r--r--Source/cmMakefile.cxx6234
-rw-r--r--Source/cmMakefile.h1077
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx761
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.h31
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx1226
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h39
-rw-r--r--Source/cmMakefileTargetGenerator.cxx2312
-rw-r--r--Source/cmMakefileTargetGenerator.h206
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx96
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.h27
-rw-r--r--Source/cmMarkAsAdvancedCommand.cxx73
-rw-r--r--Source/cmMarkAsAdvancedCommand.h73
-rw-r--r--Source/cmMathCommand.cxx56
-rw-r--r--Source/cmMathCommand.h65
-rw-r--r--Source/cmMessageCommand.cxx98
-rw-r--r--Source/cmMessageCommand.h81
-rw-r--r--Source/cmMessenger.cxx203
-rw-r--r--Source/cmMessenger.h39
-rw-r--r--Source/cmNewLineStyle.cxx67
-rw-r--r--Source/cmNewLineStyle.h29
-rw-r--r--Source/cmNinjaLinkLineComputer.cxx22
-rw-r--r--Source/cmNinjaLinkLineComputer.h33
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx1239
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h46
-rw-r--r--Source/cmNinjaTargetGenerator.cxx1347
-rw-r--r--Source/cmNinjaTargetGenerator.h140
-rw-r--r--Source/cmNinjaTypes.h26
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx183
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.h29
-rw-r--r--Source/cmOSXBundleGenerator.cxx195
-rw-r--r--Source/cmOSXBundleGenerator.h52
-rw-r--r--Source/cmObject.h51
-rw-r--r--Source/cmOptionCommand.cxx77
-rw-r--r--Source/cmOptionCommand.h66
-rw-r--r--Source/cmOrderDirectories.cxx486
-rw-r--r--Source/cmOrderDirectories.h60
-rw-r--r--Source/cmOutputConverter.cxx636
-rw-r--r--Source/cmOutputConverter.h135
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx650
-rw-r--r--Source/cmOutputRequiredFilesCommand.h89
-rw-r--r--Source/cmParseArgumentsCommand.cxx244
-rw-r--r--Source/cmParseArgumentsCommand.h34
-rw-r--r--Source/cmPathLabel.cxx30
-rw-r--r--Source/cmPathLabel.h37
-rw-r--r--Source/cmPolicies.cxx1105
-rw-r--r--Source/cmPolicies.h334
-rw-r--r--Source/cmProcessOutput.cxx173
-rw-r--r--Source/cmProcessOutput.h88
-rw-r--r--Source/cmProcessTools.cxx101
-rw-r--r--Source/cmProcessTools.h56
-rw-r--r--Source/cmProjectCommand.cxx277
-rw-r--r--Source/cmProjectCommand.h73
-rw-r--r--Source/cmProperty.cxx36
-rw-r--r--Source/cmProperty.h40
-rw-r--r--Source/cmPropertyDefinition.cxx49
-rw-r--r--Source/cmPropertyDefinition.h52
-rw-r--r--Source/cmPropertyDefinitionMap.cxx130
-rw-r--r--Source/cmPropertyDefinitionMap.h39
-rw-r--r--Source/cmPropertyMap.cxx136
-rw-r--r--Source/cmPropertyMap.h42
-rw-r--r--Source/cmQTWrapCPPCommand.cxx100
-rw-r--r--Source/cmQTWrapCPPCommand.h59
-rw-r--r--Source/cmQTWrapUICommand.cxx127
-rw-r--r--Source/cmQTWrapUICommand.h61
-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/cmQtAutomoc.cxx1299
-rw-r--r--Source/cmQtAutomoc.h96
-rw-r--r--Source/cmRST.cxx420
-rw-r--r--Source/cmRST.h98
-rw-r--r--Source/cmRemoveCommand.cxx62
-rw-r--r--Source/cmRemoveCommand.h69
-rw-r--r--Source/cmRemoveDefinitionsCommand.cxx32
-rw-r--r--Source/cmRemoveDefinitionsCommand.h57
-rw-r--r--Source/cmReturnCommand.cxx20
-rw-r--r--Source/cmReturnCommand.h69
-rw-r--r--Source/cmRulePlaceholderExpander.cxx318
-rw-r--r--Source/cmRulePlaceholderExpander.h82
-rw-r--r--Source/cmScriptGenerator.cxx191
-rw-r--r--Source/cmScriptGenerator.h72
-rw-r--r--Source/cmSearchPath.cxx224
-rw-r--r--Source/cmSearchPath.h52
-rw-r--r--Source/cmSeparateArgumentsCommand.cxx121
-rw-r--r--Source/cmSeparateArgumentsCommand.h80
-rw-r--r--Source/cmServer.cxx375
-rw-r--r--Source/cmServer.h93
-rw-r--r--Source/cmServerConnection.cxx377
-rw-r--r--Source/cmServerConnection.h95
-rw-r--r--Source/cmServerDictionary.h96
-rw-r--r--Source/cmServerProtocol.cxx1181
-rw-r--r--Source/cmServerProtocol.h158
-rw-r--r--Source/cmSetCommand.cxx179
-rw-r--r--Source/cmSetCommand.h151
-rw-r--r--Source/cmSetDirectoryPropertiesCommand.cxx76
-rw-r--r--Source/cmSetDirectoryPropertiesCommand.h74
-rw-r--r--Source/cmSetPropertyCommand.cxx515
-rw-r--r--Source/cmSetPropertyCommand.h101
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx155
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.h71
-rw-r--r--Source/cmSetTargetPropertiesCommand.cxx123
-rw-r--r--Source/cmSetTargetPropertiesCommand.h166
-rw-r--r--Source/cmSetTestsPropertiesCommand.cxx113
-rw-r--r--Source/cmSetTestsPropertiesCommand.h80
-rw-r--r--Source/cmSiteNameCommand.cxx90
-rw-r--r--Source/cmSiteNameCommand.h60
-rw-r--r--Source/cmSourceFile.cxx490
-rw-r--r--Source/cmSourceFile.h65
-rw-r--r--Source/cmSourceFileLocation.cxx349
-rw-r--r--Source/cmSourceFileLocation.h36
-rw-r--r--Source/cmSourceGroup.cxx115
-rw-r--r--Source/cmSourceGroup.h37
-rw-r--r--Source/cmSourceGroupCommand.cxx296
-rw-r--r--Source/cmSourceGroupCommand.h74
-rw-r--r--Source/cmStandardIncludes.cxx16
-rw-r--r--Source/cmStandardIncludes.h384
-rw-r--r--Source/cmStandardLexer.h84
-rw-r--r--Source/cmState.cxx855
-rw-r--r--Source/cmState.h195
-rw-r--r--Source/cmStateDirectory.cxx528
-rw-r--r--Source/cmStateDirectory.h83
-rw-r--r--Source/cmStatePrivate.h96
-rw-r--r--Source/cmStateSnapshot.cxx437
-rw-r--r--Source/cmStateSnapshot.h88
-rw-r--r--Source/cmStateTypes.h64
-rw-r--r--Source/cmStringCommand.cxx1034
-rw-r--r--Source/cmStringCommand.h201
-rw-r--r--Source/cmSubdirCommand.cxx76
-rw-r--r--Source/cmSubdirCommand.h78
-rw-r--r--Source/cmSubdirDependsCommand.cxx21
-rw-r--r--Source/cmSubdirDependsCommand.h78
-rw-r--r--Source/cmSystemTools.cxx3488
-rw-r--r--Source/cmSystemTools.h340
-rw-r--r--Source/cmTarget.cxx7770
-rw-r--r--Source/cmTarget.h786
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx71
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.h87
-rw-r--r--Source/cmTargetCompileFeaturesCommand.cxx57
-rw-r--r--Source/cmTargetCompileFeaturesCommand.h34
-rw-r--r--Source/cmTargetCompileOptionsCommand.cxx71
-rw-r--r--Source/cmTargetCompileOptionsCommand.h88
-rw-r--r--Source/cmTargetDepend.h54
-rw-r--r--Source/cmTargetExport.h25
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx133
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.h106
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx527
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h195
-rw-r--r--Source/cmTargetLinkLibraryType.h13
-rw-r--r--Source/cmTargetPropCommandBase.cxx191
-rw-r--r--Source/cmTargetPropCommandBase.h54
-rw-r--r--Source/cmTargetPropertyComputer.cxx92
-rw-r--r--Source/cmTargetPropertyComputer.h110
-rw-r--r--Source/cmTargetSourcesCommand.cxx47
-rw-r--r--Source/cmTargetSourcesCommand.h43
-rw-r--r--Source/cmTest.cxx186
-rw-r--r--Source/cmTest.h57
-rw-r--r--Source/cmTestGenerator.cxx194
-rw-r--r--Source/cmTestGenerator.h50
-rw-r--r--Source/cmTimestamp.cxx172
-rw-r--r--Source/cmTimestamp.h30
-rw-r--r--Source/cmTryCompileCommand.cxx47
-rw-r--r--Source/cmTryCompileCommand.h114
-rw-r--r--Source/cmTryRunCommand.cxx359
-rw-r--r--Source/cmTryRunCommand.h94
-rw-r--r--Source/cmUnexpectedCommand.cxx22
-rw-r--r--Source/cmUnexpectedCommand.h37
-rw-r--r--Source/cmUnsetCommand.cxx62
-rw-r--r--Source/cmUnsetCommand.h67
-rw-r--r--Source/cmUseMangledMesaCommand.cxx101
-rw-r--r--Source/cmUseMangledMesaCommand.h86
-rw-r--r--Source/cmUtilitySourceCommand.cxx133
-rw-r--r--Source/cmUtilitySourceCommand.h91
-rw-r--r--Source/cmUtils.hxx17
-rw-r--r--Source/cmUuid.cxx175
-rw-r--r--Source/cmUuid.h49
-rw-r--r--Source/cmVS10CLFlagTable.h464
-rw-r--r--Source/cmVS10CSharpFlagTable.h120
-rw-r--r--Source/cmVS10CudaFlagTable.h51
-rw-r--r--Source/cmVS10CudaHostFlagTable.h35
-rw-r--r--Source/cmVS10LibFlagTable.h154
-rw-r--r--Source/cmVS10LinkFlagTable.h533
-rw-r--r--Source/cmVS10MASMFlagTable.h76
-rw-r--r--Source/cmVS10NASMFlagTable.h50
-rw-r--r--Source/cmVS10RCFlagTable.h7
-rw-r--r--Source/cmVS11CLFlagTable.h500
-rw-r--r--Source/cmVS11CSharpFlagTable.h120
-rw-r--r--Source/cmVS11LibFlagTable.h154
-rw-r--r--Source/cmVS11LinkFlagTable.h558
-rw-r--r--Source/cmVS11MASMFlagTable.h76
-rw-r--r--Source/cmVS11RCFlagTable.h7
-rw-r--r--Source/cmVS12CLFlagTable.h508
-rw-r--r--Source/cmVS12CSharpFlagTable.h120
-rw-r--r--Source/cmVS12LibFlagTable.h154
-rw-r--r--Source/cmVS12LinkFlagTable.h558
-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.cxx394
-rw-r--r--Source/cmVSSetupHelper.h154
-rw-r--r--Source/cmVariableRequiresCommand.cxx74
-rw-r--r--Source/cmVariableRequiresCommand.h83
-rw-r--r--Source/cmVariableWatch.cxx115
-rw-r--r--Source/cmVariableWatch.h59
-rw-r--r--Source/cmVariableWatchCommand.cxx142
-rw-r--r--Source/cmVariableWatchCommand.h70
-rw-r--r--Source/cmVersion.cxx35
-rw-r--r--Source/cmVersion.h25
-rw-r--r--Source/cmVersionConfig.h.in16
-rw-r--r--Source/cmVersionMacros.h19
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx4727
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h178
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.cxx162
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.h37
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx509
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h78
-rw-r--r--Source/cmVisualStudioSlnData.cxx39
-rw-r--r--Source/cmVisualStudioSlnData.h38
-rw-r--r--Source/cmVisualStudioSlnParser.cxx410
-rw-r--r--Source/cmVisualStudioSlnParser.h39
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.cxx132
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.h56
-rw-r--r--Source/cmWhileCommand.cxx157
-rw-r--r--Source/cmWhileCommand.h89
-rw-r--r--Source/cmWin32ProcessExecution.cxx884
-rw-r--r--Source/cmWin32ProcessExecution.h169
-rw-r--r--Source/cmWorkingDirectory.cxx24
-rw-r--r--Source/cmWorkingDirectory.h25
-rw-r--r--Source/cmWriteFileCommand.cxx88
-rw-r--r--Source/cmWriteFileCommand.h74
-rw-r--r--Source/cmXCode21Object.cxx71
-rw-r--r--Source/cmXCode21Object.h24
-rw-r--r--Source/cmXCodeObject.cxx319
-rw-r--r--Source/cmXCodeObject.h265
-rw-r--r--Source/cmXCodeScheme.cxx227
-rw-r--r--Source/cmXCodeScheme.h50
-rw-r--r--Source/cmXMLParser.cxx145
-rw-r--r--Source/cmXMLParser.h47
-rw-r--r--Source/cmXMLSafe.cxx102
-rw-r--r--Source/cmXMLSafe.h27
-rw-r--r--Source/cmXMLWriter.cxx141
-rw-r--r--Source/cmXMLWriter.h118
-rw-r--r--Source/cm_auto_ptr.hxx (renamed from Source/kwsys/auto_ptr.hxx.in)189
-rw-r--r--Source/cm_codecvt.cxx243
-rw-r--r--Source/cm_codecvt.hxx66
-rw-r--r--Source/cm_get_date.c7
-rw-r--r--Source/cm_get_date.h19
-rw-r--r--Source/cm_sha2.c1617
-rw-r--r--Source/cm_sha2.h140
-rw-r--r--Source/cm_sha2_mangle.h51
-rw-r--r--Source/cm_sys_stat.h14
-rw-r--r--Source/cm_unordered_map.hxx25
-rw-r--r--Source/cm_unordered_set.hxx25
-rw-r--r--Source/cm_utf8.c83
-rw-r--r--Source/cm_utf8.h13
-rw-r--r--Source/cmake.cxx5210
-rw-r--r--Source/cmake.h704
-rw-r--r--Source/cmake.version.manifest18
-rw-r--r--Source/cmakemain.cxx758
-rw-r--r--Source/cmaketest.h.in16
-rw-r--r--Source/cmakewizard.cxx155
-rw-r--r--Source/cmakewizard.h42
-rw-r--r--Source/cmakexbuild.cxx71
-rw-r--r--Source/cmcldeps.cxx150
-rw-r--r--Source/cmcmd.cxx1666
-rw-r--r--Source/cmcmd.h32
-rwxr-xr-xSource/cmparseMSBuildXML.py6
-rw-r--r--Source/cmw9xcom.cxx45
-rw-r--r--Source/ctest.cxx453
-rw-r--r--Source/dir.dox7
-rw-r--r--Source/dir.dox.in7
-rw-r--r--Source/kwsys/.gitattributes13
-rw-r--r--Source/kwsys/Base64.c238
-rw-r--r--Source/kwsys/Base64.h.in88
-rw-r--r--Source/kwsys/CMakeEmptyInputFile.in1
-rw-r--r--Source/kwsys/CMakeLists.txt608
-rw-r--r--Source/kwsys/CONTRIBUTING.rst49
-rw-r--r--Source/kwsys/CPU.h.in125
-rw-r--r--Source/kwsys/CTestConfig.cmake14
-rw-r--r--Source/kwsys/CTestCustom.cmake.in14
-rw-r--r--Source/kwsys/CommandLineArguments.cxx860
-rw-r--r--Source/kwsys/CommandLineArguments.hxx.in167
-rw-r--r--Source/kwsys/Configure.h.in162
-rw-r--r--Source/kwsys/Configure.hxx.in176
-rw-r--r--Source/kwsys/ConsoleBuf.hxx.in394
-rw-r--r--Source/kwsys/Copyright.txt17
-rw-r--r--Source/kwsys/Directory.cxx208
-rw-r--r--Source/kwsys/Directory.hxx.in28
-rw-r--r--Source/kwsys/DynamicLoader.cxx422
-rw-r--r--Source/kwsys/DynamicLoader.hxx.in50
-rw-r--r--Source/kwsys/Encoding.h.in69
-rw-r--r--Source/kwsys/Encoding.hxx.in78
-rw-r--r--Source/kwsys/EncodingC.c72
-rw-r--r--Source/kwsys/EncodingCXX.cxx277
-rw-r--r--Source/kwsys/FStream.cxx55
-rw-r--r--Source/kwsys/FStream.hxx.in276
-rw-r--r--Source/kwsys/FundamentalType.h.in146
-rw-r--r--Source/kwsys/Glob.cxx519
-rw-r--r--Source/kwsys/Glob.hxx.in103
-rw-r--r--Source/kwsys/IOStream.cxx303
-rw-r--r--Source/kwsys/IOStream.hxx.in152
-rw-r--r--Source/kwsys/MD5.c540
-rw-r--r--Source/kwsys/MD5.h.in64
-rw-r--r--Source/kwsys/Process.h.in356
-rw-r--r--Source/kwsys/ProcessUNIX.c2483
-rw-r--r--Source/kwsys/ProcessWin32.c2601
-rw-r--r--Source/kwsys/README.rst37
-rw-r--r--Source/kwsys/README.txt10
-rw-r--r--Source/kwsys/RegularExpression.cxx1673
-rw-r--r--Source/kwsys/RegularExpression.hxx.in209
-rw-r--r--Source/kwsys/SharedForward.h.in628
-rw-r--r--Source/kwsys/String.c97
-rw-r--r--Source/kwsys/String.h.in36
-rw-r--r--Source/kwsys/String.hxx.in70
-rw-r--r--Source/kwsys/System.c782
-rw-r--r--Source/kwsys/System.h.in125
-rw-r--r--Source/kwsys/SystemInformation.cxx4743
-rw-r--r--Source/kwsys/SystemInformation.hxx.in124
-rw-r--r--Source/kwsys/SystemTools.cxx5127
-rw-r--r--Source/kwsys/SystemTools.hxx.in627
-rw-r--r--Source/kwsys/Terminal.c334
-rw-r--r--Source/kwsys/Terminal.h.in191
-rw-r--r--Source/kwsys/hash_fun.hxx.in125
-rw-r--r--Source/kwsys/hash_map.hxx.in346
-rw-r--r--Source/kwsys/hash_set.hxx.in319
-rw-r--r--Source/kwsys/hashtable.hxx.in842
-rwxr-xr-xSource/kwsys/kwsysHeaderDump.pl13
-rw-r--r--Source/kwsys/kwsysPlatformTests.cmake110
-rw-r--r--Source/kwsys/kwsysPlatformTestsC.c55
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx539
-rw-r--r--Source/kwsys/kwsysPrivate.h19
-rw-r--r--Source/kwsys/kwsys_cstddef.hxx.in35
-rw-r--r--Source/kwsys/kwsys_ios_fstream.h.in46
-rw-r--r--Source/kwsys/kwsys_ios_iosfwd.h.in49
-rw-r--r--Source/kwsys/kwsys_ios_iostream.h.in99
-rw-r--r--Source/kwsys/kwsys_ios_sstream.h.in199
-rw-r--r--Source/kwsys/kwsys_stl.hxx.in49
-rw-r--r--Source/kwsys/kwsys_stl_string.hxx.in123
-rw-r--r--Source/kwsys/testAutoPtr.cxx166
-rw-r--r--Source/kwsys/testCommandLineArguments.cxx243
-rw-r--r--Source/kwsys/testCommandLineArguments1.cxx113
-rw-r--r--Source/kwsys/testConsoleBuf.cxx773
-rw-r--r--Source/kwsys/testConsoleBuf.hxx17
-rw-r--r--Source/kwsys/testConsoleBufChild.cxx55
-rw-r--r--Source/kwsys/testDynamicLoader.cxx108
-rw-r--r--Source/kwsys/testDynload.c15
-rw-r--r--Source/kwsys/testEncode.c31
-rw-r--r--Source/kwsys/testEncoding.cxx281
-rw-r--r--Source/kwsys/testFStream.cxx113
-rw-r--r--Source/kwsys/testFail.c31
-rw-r--r--Source/kwsys/testHashSTL.cxx52
-rw-r--r--Source/kwsys/testIOS.cxx216
-rw-r--r--Source/kwsys/testProcess.c626
-rw-r--r--Source/kwsys/testSharedForward.c.in27
-rw-r--r--Source/kwsys/testSystemInformation.cxx78
-rw-r--r--Source/kwsys/testSystemTools.cxx1063
-rw-r--r--Source/kwsys/testSystemTools.h.in18
-rw-r--r--Source/kwsys/testTerminal.c19
1111 files changed, 167230 insertions, 153433 deletions
diff --git a/Source/.cvsignore b/Source/.cvsignore
deleted file mode 100644
index 31e286c6d..000000000
--- a/Source/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-ccommand___Win32_Debug
-Debug
-cmake___Win32_Debug
-ctest___Win32_Debug
-CMakeSetup.map
diff --git a/Source/.gitattributes b/Source/.gitattributes
index cf4dabd86..0f829a368 100644
--- a/Source/.gitattributes
+++ b/Source/.gitattributes
@@ -1,2 +1,2 @@
-# Preserve upstream indentation style.
-cm_sha2.* whitespace=indent-with-non-tab
+# Do not format third-party sources.
+/kwsys/** -format.clang-format
diff --git a/Source/CMakeInstallDestinations.cmake b/Source/CMakeInstallDestinations.cmake
new file mode 100644
index 000000000..28f4e87ad
--- /dev/null
+++ b/Source/CMakeInstallDestinations.cmake
@@ -0,0 +1,54 @@
+# Keep formatting here consistent with bootstrap script expectations.
+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_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_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_MAN_DIR_DEFAULT "man") # OTHER
+ set(CMAKE_XDGDATA_DIR_DEFAULT "share") # OTHER
+endif()
+
+set(CMAKE_BIN_DIR_DESC "bin")
+set(CMAKE_DATA_DIR_DESC "data")
+set(CMAKE_DOC_DIR_DESC "docs")
+set(CMAKE_MAN_DIR_DESC "man pages")
+set(CMAKE_XDGDATA_DIR_DESC "XDG specific files")
+
+set(CMake_INSTALL_INFIX "" CACHE STRING "")
+set_property(CACHE CMake_INSTALL_INFIX PROPERTY HELPSTRING
+ "Intermediate installation path (empty by default)"
+ )
+mark_as_advanced(CMake_INSTALL_INFIX)
+
+foreach(v
+ CMAKE_BIN_DIR
+ CMAKE_DATA_DIR
+ CMAKE_DOC_DIR
+ CMAKE_MAN_DIR
+ CMAKE_XDGDATA_DIR
+ )
+ # Populate the cache with empty values so we know when the user sets them.
+ set(${v} "" CACHE STRING "")
+ set_property(CACHE ${v} PROPERTY HELPSTRING
+ "Location under install prefix for ${${v}_DESC} (default \"${${v}_DEFAULT}\")"
+ )
+ set_property(CACHE ${v} PROPERTY ADVANCED 1)
+
+ # Use the default when the user did not set this variable.
+ if(NOT ${v})
+ set(${v} "${CMake_INSTALL_INFIX}${${v}_DEFAULT}")
+ endif()
+ # Remove leading slash to treat as relative to install prefix.
+ string(REGEX REPLACE "^/" "" ${v} "${${v}}")
+endforeach()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8412e3e86..40403ca25 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -1,14 +1,6 @@
-#=============================================================================
-# CMake - Cross Platform Makefile Generator
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
include(CheckIncludeFile)
# Check if we can build support for ELF parsing.
if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD")
@@ -18,12 +10,50 @@ else()
endif()
if(HAVE_ELF_H)
set(CMAKE_USE_ELF_PARSER 1)
+elseif(HAIKU)
+ # On Haiku, we need to include elf32.h from the private headers
+ set(CMake_HAIKU_INCLUDE_DIRS
+ /boot/system/develop/headers/private/system
+ /boot/system/develop/headers/private/system/arch/x86
+ )
+
+ set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS})
+ CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H)
+ unset(CMAKE_REQUIRED_INCLUDES)
+
+ if(HAVE_ELF32_H)
+ set(CMAKE_USE_ELF_PARSER 1)
+ else()
+ unset(CMake_HAIKU_INCLUDE_DIRS)
+ set(CMAKE_USE_ELF_PARSER)
+ endif()
else()
set(CMAKE_USE_ELF_PARSER)
endif()
+if(APPLE)
+ set(CMAKE_USE_MACH_PARSER 1)
+endif()
+
set(EXECUTABLE_OUTPUT_PATH ${CMake_BIN_DIR})
+if(WIN32)
+ # ensure Unicode friendly APIs are used on Windows
+ add_definitions(-DUNICODE -D_UNICODE)
+
+ # minimize windows.h content
+ add_definitions(-DWIN32_LEAN_AND_MEAN)
+endif()
+
+# configure the .dox.in file
+if(CMake_BUILD_DEVELOPER_REFERENCE)
+ configure_file(
+ "${CMake_SOURCE_DIR}/Source/dir.dox.in"
+ "${CMake_BINARY_DIR}/Source/dir.dox"
+ @ONLY
+ )
+endif()
+
# configure the .h file
configure_file(
"${CMake_SOURCE_DIR}/Source/cmConfigure.cmake.h.in"
@@ -38,94 +68,78 @@ configure_file(
"${CMake_BINARY_DIR}/Source/CPack/cmCPackConfigure.h"
)
+# Tell CMake executable in the build tree where to find the source tree.
+configure_file(
+ "${CMake_SOURCE_DIR}/Source/CMakeSourceDir.txt.in"
+ "${CMake_BINARY_DIR}/CMakeFiles/CMakeSourceDir.txt" @ONLY
+ )
+
# add the include path to find the .h
include_directories(
"${CMake_BINARY_DIR}/Source"
"${CMake_SOURCE_DIR}/Source"
+ "${CMake_SOURCE_DIR}/Source/LexerParser"
${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)
-option(CMAKE_REGENERATE_YACCLEX
- "Regenerate YACC and LEXX files" OFF)
-mark_as_advanced(CMAKE_REGENERATE_YACCLEX)
-if(CMAKE_REGENERATE_YACCLEX)
- set(parsersLexers cmDependsFortran cmCommandArgument cmExpr)
- find_program(YACC_EXECUTABLE
- NAMES yacc bison
- PATHS /usr/bin
- DOC "Yacc or Bison executable")
- find_program(FLEX_EXECUTABLE
- NAMES flex
- PATHS /usr/bin
- DOC "Flex executable")
- mark_as_advanced(YACC_EXECUTABLE FLEX_EXECUTABLE)
- if(YACC_EXECUTABLE)
- set(BISON_FLAGS)
- if(YACC_EXECUTABLE MATCHES "bison")
- set(BISON_FLAGS "--yacc")
- endif()
- set(yacc_files)
- foreach(name ${parsersLexers})
- set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}Parser.y")
- set(dst "${CMAKE_CURRENT_BINARY_DIR}/${name}Parser.cxx")
- set(hdr "${CMAKE_CURRENT_BINARY_DIR}/${name}ParserTokens.h")
- add_custom_command(
- OUTPUT "${dst}"
- DEPENDS "${src}"
- COMMAND
- ${YACC_EXECUTABLE}
- --name-prefix=${name}_yy --defines=${hdr} -o${dst} ${src}
- )
- set(yacc_files ${yacc_files} "${dst}")
- endforeach()
- add_custom_target(RerunYacc DEPENDS ${yacc_files})
- endif()
- if(FLEX_EXECUTABLE)
- set(lex_files)
- foreach(name ${parsersLexers})
- set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}Lexer.in.l")
- set(dst "${CMAKE_CURRENT_BINARY_DIR}/${name}Lexer.cxx")
- set(hdr "${CMAKE_CURRENT_BINARY_DIR}/${name}Lexer.h")
- add_custom_command(
- OUTPUT "${dst}"
- DEPENDS "${src}"
- COMMAND
- ${FLEX_EXECUTABLE}
- --prefix=${name}_yy --header-file=${hdr} -o${dst} ${src}
- )
- set(lex_files ${lex_files} "${dst}")
- endforeach()
- add_custom_target(RerunLex DEPENDS ${lex_files})
- endif()
-
-endif()
-
# Check if we can build the ELF parser.
if(CMAKE_USE_ELF_PARSER)
set(ELF_SRCS cmELF.h cmELF.cxx)
endif()
+# Check if we can build the Mach-O parser.
+if(CMAKE_USE_MACH_PARSER)
+ set(MACH_SRCS cmMachO.h cmMachO.cxx)
+endif()
+
#
# Sources for CMakeLib
#
set(SRCS
- cmStandardIncludes.cxx
+ # Lexers/Parsers
+ LexerParser/cmCommandArgumentLexer.cxx
+ LexerParser/cmCommandArgumentLexer.h
+ LexerParser/cmCommandArgumentLexer.in.l
+ LexerParser/cmCommandArgumentParser.cxx
+ LexerParser/cmCommandArgumentParserTokens.h
+ LexerParser/cmCommandArgumentParser.y
+ LexerParser/cmDependsJavaLexer.cxx
+ LexerParser/cmDependsJavaLexer.h
+ LexerParser/cmDependsJavaLexer.in.l
+ LexerParser/cmDependsJavaParser.cxx
+ LexerParser/cmDependsJavaParserTokens.h
+ LexerParser/cmDependsJavaParser.y
+ LexerParser/cmExprLexer.cxx
+ LexerParser/cmExprLexer.h
+ LexerParser/cmExprLexer.in.l
+ LexerParser/cmExprParser.cxx
+ LexerParser/cmExprParserTokens.h
+ LexerParser/cmExprParser.y
+ LexerParser/cmFortranLexer.cxx
+ LexerParser/cmFortranLexer.h
+ LexerParser/cmFortranLexer.in.l
+ LexerParser/cmFortranParser.cxx
+ LexerParser/cmFortranParserTokens.h
+ LexerParser/cmFortranParser.y
+ LexerParser/cmListFileLexer.c
+ LexerParser/cmListFileLexer.in.l
+
cmArchiveWrite.cxx
- cmBootstrapCommands1.cxx
- cmBootstrapCommands2.cxx
+ cmBase32.cxx
cmCacheManager.cxx
cmCacheManager.h
- cmCommands.cxx
- cmCommands.h
- cmCommandArgumentLexer.cxx
- cmCommandArgumentParser.cxx
+ cmCLocaleEnvironmentScope.h
+ cmCLocaleEnvironmentScope.cxx
cmCommandArgumentParserHelper.cxx
+ cmCommonTargetGenerator.cxx
+ cmCommonTargetGenerator.h
cmComputeComponentGraph.cxx
cmComputeComponentGraph.h
cmComputeLinkDepends.cxx
@@ -134,8 +148,12 @@ set(SRCS
cmComputeLinkInformation.h
cmComputeTargetDepends.h
cmComputeTargetDepends.cxx
+ cmCPackPropertiesGenerator.h
+ cmCPackPropertiesGenerator.cxx
cmCryptoHash.cxx
cmCryptoHash.h
+ cmCurl.cxx
+ cmCurl.h
cmCustomCommand.cxx
cmCustomCommand.h
cmCustomCommandGenerator.cxx
@@ -148,37 +166,25 @@ set(SRCS
cmDependsC.h
cmDependsFortran.cxx
cmDependsFortran.h
- cmDependsFortranLexer.cxx
- cmDependsFortranParser.cxx
- cmDependsFortranParser.h
cmDependsJava.cxx
cmDependsJava.h
- cmDependsJavaLexer.cxx
- cmDependsJavaParser.cxx
cmDependsJavaParserHelper.cxx
cmDependsJavaParserHelper.h
cmDocumentation.cxx
cmDocumentationFormatter.cxx
- cmDocumentationFormatterHTML.cxx
- cmDocumentationFormatterDocbook.cxx
- cmDocumentationFormatterMan.cxx
- cmDocumentationFormatterText.cxx
- cmDocumentationFormatterUsage.cxx
cmDocumentationSection.cxx
- cmDocumentCompileDefinitions.h
- cmDocumentGeneratorExpressions.h
- cmDocumentLocationUndefined.h
- cmDocumentVariables.cxx
cmDynamicLoader.cxx
cmDynamicLoader.h
${ELF_SRCS}
- cmExprLexer.cxx
- cmExprParser.cxx
cmExprParserHelper.cxx
+ cmExportBuildAndroidMKGenerator.h
+ cmExportBuildAndroidMKGenerator.cxx
cmExportBuildFileGenerator.h
cmExportBuildFileGenerator.cxx
cmExportFileGenerator.h
cmExportFileGenerator.cxx
+ cmExportInstallAndroidMKGenerator.h
+ cmExportInstallAndroidMKGenerator.cxx
cmExportInstallFileGenerator.h
cmExportInstallFileGenerator.cxx
cmExportTryCompileFileGenerator.h
@@ -187,27 +193,50 @@ set(SRCS
cmExportSet.cxx
cmExportSetMap.h
cmExportSetMap.cxx
+ cmExternalMakefileProjectGenerator.cxx
+ cmExternalMakefileProjectGenerator.h
cmExtraCodeBlocksGenerator.cxx
cmExtraCodeBlocksGenerator.h
+ cmExtraCodeLiteGenerator.cxx
+ cmExtraCodeLiteGenerator.h
cmExtraEclipseCDT4Generator.cxx
cmExtraEclipseCDT4Generator.h
+ cmExtraKateGenerator.cxx
+ cmExtraKateGenerator.h
cmExtraSublimeTextGenerator.cxx
cmExtraSublimeTextGenerator.h
+ cmFileLock.cxx
+ cmFileLock.h
+ cmFileLockPool.cxx
+ cmFileLockPool.h
+ cmFileLockResult.cxx
+ cmFileLockResult.h
+ cmFilePathChecksum.cxx
+ cmFilePathChecksum.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
+ cmFortranParserImpl.cxx
cmGeneratedFileStream.cxx
+ cmGeneratorExpressionContext.cxx
+ cmGeneratorExpressionContext.h
cmGeneratorExpressionDAGChecker.cxx
cmGeneratorExpressionDAGChecker.h
+ cmGeneratorExpressionEvaluationFile.cxx
+ cmGeneratorExpressionEvaluationFile.h
cmGeneratorExpressionEvaluator.cxx
cmGeneratorExpressionEvaluator.h
cmGeneratorExpressionLexer.cxx
cmGeneratorExpressionLexer.h
+ cmGeneratorExpressionNode.cxx
+ cmGeneratorExpressionNode.h
cmGeneratorExpressionParser.cxx
cmGeneratorExpressionParser.h
cmGeneratorExpression.cxx
cmGeneratorExpression.h
cmGeneratorTarget.cxx
cmGeneratorTarget.h
+ cmGlobalCommonGenerator.cxx
+ cmGlobalCommonGenerator.h
cmGlobalGenerator.cxx
cmGlobalGenerator.h
cmGlobalGeneratorFactory.h
@@ -219,6 +248,8 @@ set(SRCS
cmInstallGenerator.h
cmInstallGenerator.cxx
cmInstallExportGenerator.cxx
+ cmInstalledFile.h
+ cmInstalledFile.cxx
cmInstallFilesGenerator.h
cmInstallFilesGenerator.cxx
cmInstallScriptGenerator.h
@@ -227,28 +258,45 @@ set(SRCS
cmInstallTargetGenerator.cxx
cmInstallDirectoryGenerator.h
cmInstallDirectoryGenerator.cxx
+ cmLinkedTree.h
+ cmLinkItem.h
+ cmLinkLineComputer.cxx
+ cmLinkLineComputer.h
+ cmLinkLineDeviceComputer.cxx
+ cmLinkLineDeviceComputer.h
cmListFileCache.cxx
cmListFileCache.h
- cmListFileLexer.c
+ cmLocalCommonGenerator.cxx
+ cmLocalCommonGenerator.h
cmLocalGenerator.cxx
cmLocalGenerator.h
+ cmRulePlaceholderExpander.cxx
+ cmRulePlaceholderExpander.h
cmLocalUnixMakefileGenerator3.cxx
- cmMakeDepend.cxx
- cmMakeDepend.h
+ cmLocale.h
+ ${MACH_SRCS}
cmMakefile.cxx
cmMakefile.h
cmMakefileTargetGenerator.cxx
cmMakefileExecutableTargetGenerator.cxx
cmMakefileLibraryTargetGenerator.cxx
cmMakefileUtilityTargetGenerator.cxx
+ cmMessenger.cxx
+ cmMessenger.h
+ cmMSVC60LinkLineComputer.cxx
+ cmMSVC60LinkLineComputer.h
cmOSXBundleGenerator.cxx
cmOSXBundleGenerator.h
+ cmOutputConverter.cxx
+ cmOutputConverter.h
cmNewLineStyle.h
cmNewLineStyle.cxx
cmOrderDirectories.cxx
cmOrderDirectories.h
cmPolicies.h
cmPolicies.cxx
+ cmProcessOutput.cxx
+ cmProcessOutput.h
cmProcessTools.cxx
cmProcessTools.h
cmProperty.cxx
@@ -259,8 +307,14 @@ set(SRCS
cmPropertyDefinitionMap.h
cmPropertyMap.cxx
cmPropertyMap.h
- cmQtAutomoc.cxx
- cmQtAutomoc.h
+ cmQtAutoGeneratorCommon.cxx
+ cmQtAutoGeneratorCommon.h
+ cmQtAutoGeneratorInitializer.cxx
+ cmQtAutoGeneratorInitializer.h
+ cmQtAutoGenerators.cxx
+ cmQtAutoGenerators.h
+ cmRST.cxx
+ cmRST.h
cmScriptGenerator.h
cmScriptGenerator.cxx
cmSourceFile.cxx
@@ -269,34 +323,279 @@ set(SRCS
cmSourceFileLocation.h
cmSourceGroup.cxx
cmSourceGroup.h
+ cmState.cxx
+ cmState.h
+ cmStateDirectory.cxx
+ cmStateDirectory.h
+ cmStateSnapshot.cxx
+ cmStateSnapshot.h
+ cmStateTypes.h
cmSystemTools.cxx
cmSystemTools.h
cmTarget.cxx
cmTarget.h
+ cmTargetPropertyComputer.cxx
+ cmTargetPropertyComputer.h
cmTargetExport.h
cmTest.cxx
cmTest.h
cmTestGenerator.cxx
cmTestGenerator.h
+ cmUuid.cxx
cmVariableWatch.cxx
cmVariableWatch.h
cmVersion.cxx
cmVersion.h
+ cmWorkingDirectory.cxx
+ cmWorkingDirectory.h
cmXMLParser.cxx
cmXMLParser.h
cmXMLSafe.cxx
cmXMLSafe.h
+ cmXMLWriter.cxx
+ cmXMLWriter.h
cmake.cxx
cmake.h
- cmakewizard.cxx
- cmakewizard.h
- cm_sha2.h
- cm_sha2.c
+ cmCommand.cxx
+ cmCommand.h
+ cmCommands.cxx
+ cmCommands.h
+ cmAddCompileOptionsCommand.cxx
+ cmAddCompileOptionsCommand.h
+ cmAddCustomCommandCommand.cxx
+ cmAddCustomCommandCommand.h
+ cmAddCustomTargetCommand.cxx
+ cmAddCustomTargetCommand.h
+ cmAddDefinitionsCommand.cxx
+ cmAddDefinitionsCommand.h
+ cmAddDependenciesCommand.cxx
+ cmAddDependenciesCommand.h
+ cmAddExecutableCommand.cxx
+ cmAddExecutableCommand.h
+ cmAddLibraryCommand.cxx
+ cmAddLibraryCommand.h
+ cmAddSubDirectoryCommand.cxx
+ cmAddSubDirectoryCommand.h
+ cmAddTestCommand.cxx
+ cmAddTestCommand.h
+ cmAuxSourceDirectoryCommand.cxx
+ cmAuxSourceDirectoryCommand.h
+ cmBreakCommand.cxx
+ cmBreakCommand.h
+ cmBuildCommand.cxx
+ cmBuildCommand.h
+ cmBuildNameCommand.cxx
+ cmBuildNameCommand.h
+ cmCMakeHostSystemInformationCommand.cxx
+ cmCMakeHostSystemInformationCommand.h
+ cmCMakeMinimumRequired.cxx
+ cmCMakeMinimumRequired.h
+ cmCMakePolicyCommand.cxx
+ cmCMakePolicyCommand.h
+ cmCommandArgumentsHelper.cxx
+ cmCommandArgumentsHelper.h
+ cmConditionEvaluator.cxx
+ cmConditionEvaluator.h
+ cmConfigureFileCommand.cxx
+ cmConfigureFileCommand.h
+ cmContinueCommand.cxx
+ cmContinueCommand.h
+ cmCoreTryCompile.cxx
+ cmCoreTryCompile.h
+ cmCreateTestSourceList.cxx
+ cmCreateTestSourceList.h
+ cmDefinePropertyCommand.cxx
+ cmDefinePropertyCommand.h
+ cmDisallowedCommand.cxx
+ cmDisallowedCommand.h
+ cmEnableLanguageCommand.cxx
+ cmEnableLanguageCommand.h
+ cmEnableTestingCommand.cxx
+ cmEnableTestingCommand.h
+ cmExecProgramCommand.cxx
+ cmExecProgramCommand.h
+ cmExecuteProcessCommand.cxx
+ cmExecuteProcessCommand.h
+ cmExpandedCommandArgument.cxx
+ cmExpandedCommandArgument.h
+ cmExportCommand.cxx
+ cmExportCommand.h
+ cmExportLibraryDependenciesCommand.cxx
+ cmExportLibraryDependenciesCommand.h
+ cmFLTKWrapUICommand.cxx
+ cmFLTKWrapUICommand.h
+ cmFileCommand.cxx
+ cmFileCommand.h
+ cmFindBase.cxx
+ cmFindBase.h
+ cmFindCommon.cxx
+ cmFindCommon.h
+ cmFindFileCommand.cxx
+ cmFindFileCommand.h
+ cmFindLibraryCommand.cxx
+ cmFindLibraryCommand.h
+ cmFindPackageCommand.cxx
+ cmFindPackageCommand.h
+ cmFindPathCommand.cxx
+ cmFindPathCommand.h
+ cmFindProgramCommand.cxx
+ cmFindProgramCommand.h
+ cmForEachCommand.cxx
+ cmForEachCommand.h
+ cmFunctionCommand.cxx
+ cmFunctionCommand.h
+ cmGetCMakePropertyCommand.cxx
+ cmGetCMakePropertyCommand.h
+ cmGetDirectoryPropertyCommand.cxx
+ cmGetDirectoryPropertyCommand.h
+ cmGetFilenameComponentCommand.cxx
+ cmGetFilenameComponentCommand.h
+ cmGetPropertyCommand.cxx
+ cmGetPropertyCommand.h
+ cmGetSourceFilePropertyCommand.cxx
+ cmGetSourceFilePropertyCommand.h
+ cmGetTargetPropertyCommand.cxx
+ cmGetTargetPropertyCommand.h
+ cmGetTestPropertyCommand.cxx
+ cmGetTestPropertyCommand.h
+ cmHexFileConverter.cxx
+ cmHexFileConverter.h
+ cmIfCommand.cxx
+ cmIfCommand.h
+ cmIncludeCommand.cxx
+ cmIncludeCommand.h
+ cmIncludeDirectoryCommand.cxx
+ cmIncludeDirectoryCommand.h
+ cmIncludeExternalMSProjectCommand.cxx
+ cmIncludeExternalMSProjectCommand.h
+ cmIncludeRegularExpressionCommand.cxx
+ cmIncludeRegularExpressionCommand.h
+ cmInstallCommand.cxx
+ cmInstallCommand.h
+ cmInstallCommandArguments.cxx
+ cmInstallCommandArguments.h
+ cmInstallFilesCommand.cxx
+ cmInstallFilesCommand.h
+ cmInstallProgramsCommand.cxx
+ cmInstallProgramsCommand.h
+ cmInstallTargetsCommand.cxx
+ cmInstallTargetsCommand.h
+ cmLinkDirectoriesCommand.cxx
+ cmLinkDirectoriesCommand.h
+ cmLinkLibrariesCommand.cxx
+ cmLinkLibrariesCommand.h
+ cmListCommand.cxx
+ cmListCommand.h
+ cmLoadCacheCommand.cxx
+ cmLoadCacheCommand.h
+ cmLoadCommandCommand.cxx
+ cmLoadCommandCommand.h
+ cmMacroCommand.cxx
+ cmMacroCommand.h
+ cmMakeDirectoryCommand.cxx
+ cmMakeDirectoryCommand.h
+ cmMarkAsAdvancedCommand.cxx
+ cmMarkAsAdvancedCommand.h
+ cmMathCommand.cxx
+ cmMathCommand.h
+ cmMessageCommand.cxx
+ cmMessageCommand.h
+ cmOptionCommand.cxx
+ cmOptionCommand.h
+ cmOutputRequiredFilesCommand.cxx
+ cmOutputRequiredFilesCommand.h
+ cmParseArgumentsCommand.cxx
+ cmParseArgumentsCommand.h
+ cmPathLabel.cxx
+ cmPathLabel.h
+ cmProjectCommand.cxx
+ cmProjectCommand.h
+ cmQTWrapCPPCommand.cxx
+ cmQTWrapCPPCommand.h
+ cmQTWrapUICommand.cxx
+ cmQTWrapUICommand.h
+ cmRemoveCommand.cxx
+ cmRemoveCommand.h
+ cmRemoveDefinitionsCommand.cxx
+ cmRemoveDefinitionsCommand.h
+ cmReturnCommand.cxx
+ cmReturnCommand.h
+ cmSearchPath.cxx
+ cmSearchPath.h
+ cmSeparateArgumentsCommand.cxx
+ cmSeparateArgumentsCommand.h
+ cmSetCommand.cxx
+ cmSetCommand.h
+ cmSetDirectoryPropertiesCommand.cxx
+ cmSetDirectoryPropertiesCommand.h
+ cmSetPropertyCommand.cxx
+ cmSetPropertyCommand.h
+ cmSetSourceFilesPropertiesCommand.cxx
+ cmSetSourceFilesPropertiesCommand.h
+ cmSetTargetPropertiesCommand.cxx
+ cmSetTargetPropertiesCommand.h
+ cmSetTestsPropertiesCommand.cxx
+ cmSetTestsPropertiesCommand.h
+ cmSiteNameCommand.cxx
+ cmSiteNameCommand.h
+ cmSourceGroupCommand.cxx
+ cmSourceGroupCommand.h
+ cmStringCommand.cxx
+ cmStringCommand.h
+ cmSubdirCommand.cxx
+ cmSubdirCommand.h
+ cmSubdirDependsCommand.cxx
+ cmSubdirDependsCommand.h
+ cmTargetCompileDefinitionsCommand.cxx
+ cmTargetCompileDefinitionsCommand.h
+ cmTargetCompileFeaturesCommand.cxx
+ cmTargetCompileFeaturesCommand.h
+ cmTargetCompileOptionsCommand.cxx
+ cmTargetCompileOptionsCommand.h
+ cmTargetIncludeDirectoriesCommand.cxx
+ cmTargetIncludeDirectoriesCommand.h
+ cmTargetLinkLibrariesCommand.cxx
+ cmTargetLinkLibrariesCommand.h
+ cmTargetPropCommandBase.cxx
+ cmTargetPropCommandBase.h
+ cmTargetSourcesCommand.cxx
+ cmTargetSourcesCommand.h
+ cmTimestamp.cxx
+ cmTimestamp.h
+ cmTryCompileCommand.cxx
+ cmTryCompileCommand.h
+ cmTryRunCommand.cxx
+ cmTryRunCommand.h
+ cmUnexpectedCommand.cxx
+ cmUnexpectedCommand.h
+ cmUnsetCommand.cxx
+ cmUnsetCommand.h
+ cmUseMangledMesaCommand.cxx
+ cmUseMangledMesaCommand.h
+ cmUtilitySourceCommand.cxx
+ cmUtilitySourceCommand.h
+ cmVariableRequiresCommand.cxx
+ cmVariableRequiresCommand.h
+ cmVariableWatchCommand.cxx
+ cmVariableWatchCommand.h
+ cmWhileCommand.cxx
+ cmWhileCommand.h
+ cmWriteFileCommand.cxx
+ cmWriteFileCommand.h
+
+ cm_auto_ptr.hxx
+ cm_get_date.h
+ cm_get_date.c
cm_utf8.h
cm_utf8.c
+ cm_codecvt.hxx
+ cm_codecvt.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)
@@ -307,6 +606,7 @@ if(APPLE)
set(SRCS ${SRCS}
cmXCodeObject.cxx
cmXCode21Object.cxx
+ cmXCodeScheme.cxx
cmGlobalXCodeGenerator.cxx
cmGlobalXCodeGenerator.h
cmLocalXCodeGenerator.cxx
@@ -318,6 +618,7 @@ if (WIN32)
set(SRCS ${SRCS}
cmCallVisualStudioMacro.cxx
cmCallVisualStudioMacro.h
+ bindexplib.cxx
)
if(NOT UNIX)
@@ -330,8 +631,6 @@ if (WIN32)
cmGlobalNMakeMakefileGenerator.h
cmGlobalJOMMakefileGenerator.cxx
cmGlobalJOMMakefileGenerator.h
- cmGlobalVisualStudio6Generator.cxx
- cmGlobalVisualStudio6Generator.h
cmGlobalVisualStudio71Generator.cxx
cmGlobalVisualStudio71Generator.h
cmGlobalVisualStudio7Generator.cxx
@@ -344,6 +643,8 @@ if (WIN32)
cmVisualStudioGeneratorOptions.cxx
cmVisualStudio10TargetGenerator.h
cmVisualStudio10TargetGenerator.cxx
+ cmVisualStudio10ToolsetOptions.h
+ cmVisualStudio10ToolsetOptions.cxx
cmLocalVisualStudio10Generator.cxx
cmLocalVisualStudio10Generator.h
cmGlobalVisualStudio10Generator.h
@@ -352,14 +653,15 @@ if (WIN32)
cmGlobalVisualStudio11Generator.cxx
cmGlobalVisualStudio12Generator.h
cmGlobalVisualStudio12Generator.cxx
+ cmGlobalVisualStudio14Generator.h
+ cmGlobalVisualStudio14Generator.cxx
+ cmGlobalVisualStudio15Generator.h
+ cmGlobalVisualStudio15Generator.cxx
cmGlobalVisualStudioGenerator.cxx
cmGlobalVisualStudioGenerator.h
- cmGlobalWatcomWMakeGenerator.cxx
cmIDEFlagTable.h
cmIDEOptions.cxx
cmIDEOptions.h
- cmLocalVisualStudio6Generator.cxx
- cmLocalVisualStudio6Generator.h
cmLocalVisualStudio7Generator.cxx
cmLocalVisualStudio7Generator.h
cmLocalVisualStudioGenerator.cxx
@@ -370,12 +672,33 @@ if (WIN32)
cmVisualStudioSlnParser.cxx
cmVisualStudioWCEPlatformParser.h
cmVisualStudioWCEPlatformParser.cxx
- cmWin32ProcessExecution.cxx
- cmWin32ProcessExecution.h
+ cmGlobalGhsMultiGenerator.cxx
+ cmGlobalGhsMultiGenerator.h
+ cmLocalGhsMultiGenerator.cxx
+ cmLocalGhsMultiGenerator.h
+ cmGhsMultiTargetGenerator.cxx
+ cmGhsMultiTargetGenerator.h
+ cmGhsMultiGpj.cxx
+ cmGhsMultiGpj.h
+ cmVSSetupHelper.cxx
+ cmVSSetupHelper.h
)
+
+ # Add a manifest file to executables on Windows to allow for
+ # GetVersion to work properly on Windows 8 and above.
+ set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake.version.manifest)
endif()
endif ()
+# Watcom support
+if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set_property(SOURCE cmake.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_USE_WMAKE)
+ list(APPEND SRCS
+ cmGlobalWatcomWMakeGenerator.cxx
+ cmGlobalWatcomWMakeGenerator.h
+ )
+endif()
+
# Ninja support
set(SRCS ${SRCS}
cmGlobalNinjaGenerator.cxx
@@ -389,29 +712,69 @@ set(SRCS ${SRCS}
cmNinjaNormalTargetGenerator.h
cmNinjaUtilityTargetGenerator.cxx
cmNinjaUtilityTargetGenerator.h
+ cmNinjaLinkLineComputer.cxx
+ cmNinjaLinkLineComputer.h
)
-if(WIN32 AND NOT CYGWIN AND NOT BORLAND)
+
+# Temporary variable for tools targets
+set(_tools)
+
+if(WIN32 AND NOT CYGWIN)
set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501)
- add_executable(cmcldeps cmcldeps.cxx)
+ add_executable(cmcldeps cmcldeps.cxx ${MANIFEST_FILE})
+ list(APPEND _tools cmcldeps)
target_link_libraries(cmcldeps CMakeLib)
- install(TARGETS cmcldeps DESTINATION bin)
endif()
+foreach(v CURL_CA_BUNDLE CURL_CA_PATH)
+ if(${v})
+ set_property(SOURCE cmCurl.cxx APPEND PROPERTY COMPILE_DEFINITIONS ${v}="${${v}}")
+ endif()
+endforeach()
+
+foreach(check
+ STAT_HAS_ST_MTIM
+ STAT_HAS_ST_MTIMESPEC
+ )
+ if(KWSYS_CXX_${check}_COMPILED) # abuse KWSys check cache entry
+ set(CMake_${check} 1)
+ else()
+ set(CMake_${check} 0)
+ endif()
+ set_property(SOURCE cmFileTimeComparison.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_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES}
${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES}
- ${CMAKE_CURL_LIBRARIES} )
+ ${CMAKE_CURL_LIBRARIES}
+ ${CMAKE_JSONCPP_LIBRARIES}
+ ${CMAKE_LIBUV_LIBRARIES}
+ ${CMAKE_LIBRHASH_LIBRARIES}
+ ${CMake_KWIML_LIBRARIES}
+ )
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
+ # the atomic instructions are implemented using libatomic on some platforms,
+ # so linking to that may be required
+ check_library_exists(atomic __atomic_fetch_add_4 "" LIBATOMIC_NEEDED)
+ if(LIBATOMIC_NEEDED)
+ target_link_libraries(CMakeLib atomic)
+ endif()
+endif()
# On Apple we need CoreFoundation
if(APPLE)
target_link_libraries(CMakeLib "-framework CoreFoundation")
endif()
-# On some platforms we need the rpcrt4 library for the VS 7 generators.
-if(CMAKE_BUILD_ON_VISUAL_STUDIO OR MINGW)
- target_link_libraries(CMakeLib rpcrt4)
+if(WIN32 AND NOT UNIX)
+ # We need the rpcrt4 library on Windows.
+ # We need the crypt32 library on Windows for crypto/cert APIs.
+ target_link_libraries(CMakeLib rpcrt4 crypt32)
endif()
#
@@ -435,10 +798,15 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestConfigureHandler.cxx
CTest/cmCTestCoverageCommand.cxx
CTest/cmCTestCoverageHandler.cxx
+ CTest/cmCTestCurl.cxx
CTest/cmParseMumpsCoverage.cxx
CTest/cmParseCacheCoverage.cxx
CTest/cmParseGTMCoverage.cxx
+ CTest/cmParseJacocoCoverage.cxx
+ CTest/cmParseBlanketJSCoverage.cxx
CTest/cmParsePHPCoverage.cxx
+ CTest/cmParseCoberturaCoverage.cxx
+ CTest/cmParseDelphiCoverage.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestGenericHandler.cxx
CTest/cmCTestHandlerCommand.cxx
@@ -475,6 +843,8 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestGIT.h
CTest/cmCTestHG.cxx
CTest/cmCTestHG.h
+ CTest/cmCTestP4.cxx
+ CTest/cmCTestP4.h
)
# Build CTestLib
@@ -482,6 +852,12 @@ add_library(CTestLib ${CTEST_SRCS})
target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_LIBRARIES})
#
+# CPack
+#
+include_directories(
+ "${CMake_SOURCE_DIR}/Source/CPack"
+ )
+#
# Sources for CPack
#
set(CPACK_SRCS
@@ -493,11 +869,24 @@ set(CPACK_SRCS
CPack/cmCPackNSISGenerator.cxx
CPack/cmCPackSTGZGenerator.cxx
CPack/cmCPackTGZGenerator.cxx
+ CPack/cmCPackTXZGenerator.cxx
CPack/cmCPackTarBZip2Generator.cxx
CPack/cmCPackTarCompressGenerator.cxx
CPack/cmCPackZIPGenerator.cxx
- CPack/cmCPackDocumentVariables.cxx
- CPack/cmCPackDocumentMacros.cxx
+ CPack/cmCPack7zGenerator.cxx
+ )
+# CPack IFW generator
+set(CPACK_SRCS ${CPACK_SRCS}
+ CPack/IFW/cmCPackIFWCommon.cxx
+ CPack/IFW/cmCPackIFWCommon.h
+ CPack/IFW/cmCPackIFWGenerator.cxx
+ CPack/IFW/cmCPackIFWGenerator.h
+ CPack/IFW/cmCPackIFWInstaller.cxx
+ CPack/IFW/cmCPackIFWInstaller.h
+ CPack/IFW/cmCPackIFWPackage.cxx
+ CPack/IFW/cmCPackIFWPackage.h
+ CPack/IFW/cmCPackIFWRepository.cxx
+ CPack/IFW/cmCPackIFWRepository.h
)
if(CYGWIN)
@@ -517,8 +906,25 @@ endif()
if(WIN32)
set(CPACK_SRCS ${CPACK_SRCS}
CPack/WiX/cmCPackWIXGenerator.cxx
- CPack/WiX/cmWIXSourceWriter.cxx
+ CPack/WiX/cmCPackWIXGenerator.h
+ CPack/WiX/cmWIXAccessControlList.cxx
+ CPack/WiX/cmWIXAccessControlList.h
+ CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
+ CPack/WiX/cmWIXDirectoriesSourceWriter.h
+ CPack/WiX/cmWIXFeaturesSourceWriter.cxx
+ CPack/WiX/cmWIXFeaturesSourceWriter.h
+ CPack/WiX/cmWIXFilesSourceWriter.cxx
+ CPack/WiX/cmWIXFilesSourceWriter.h
+ CPack/WiX/cmWIXPatch.cxx
+ CPack/WiX/cmWIXPatch.h
+ CPack/WiX/cmWIXPatchParser.cxx
+ CPack/WiX/cmWIXPatchParser.h
CPack/WiX/cmWIXRichTextFormatWriter.cxx
+ CPack/WiX/cmWIXRichTextFormatWriter.h
+ CPack/WiX/cmWIXShortcut.cxx
+ CPack/WiX/cmWIXShortcut.h
+ CPack/WiX/cmWIXSourceWriter.cxx
+ CPack/WiX/cmWIXSourceWriter.h
)
endif()
@@ -527,16 +933,35 @@ if(APPLE)
CPack/cmCPackBundleGenerator.cxx
CPack/cmCPackDragNDropGenerator.cxx
CPack/cmCPackOSXX11Generator.cxx
+ CPack/cmCPackPKGGenerator.cxx
CPack/cmCPackPackageMakerGenerator.cxx
+ CPack/cmCPackProductBuildGenerator.cxx
)
endif()
# Build CPackLib
add_library(CPackLib ${CPACK_SRCS})
target_link_libraries(CPackLib CMakeLib)
+if(APPLE)
+ # Some compilers produce errors in the CoreServices framework headers.
+ # Ideally such errors should be fixed by either the compiler vendor
+ # or the framework source, but we try to workaround it and build anyway.
+ # If it does not work, build with reduced functionality and warn.
+ check_include_file("CoreServices/CoreServices.h" HAVE_CoreServices)
+ if(HAVE_CoreServices)
+ set_property(SOURCE CPack/cmCPackDragNDropGenerator.cxx PROPERTY COMPILE_DEFINITIONS HAVE_CoreServices)
+ target_link_libraries(CPackLib "-framework CoreServices")
+ else()
+ message(WARNING "This compiler does not appear to support\n"
+ " #include <CoreServices/CoreServices.h>\n"
+ "Some CPack functionality may be limited.\n"
+ "See CMakeFiles/CMakeError.log for details of the failure.")
+ endif()
+endif()
if(APPLE)
add_executable(cmakexbuild cmakexbuild.cxx)
+ list(APPEND _tools cmakexbuild)
target_link_libraries(cmakexbuild CMakeLib)
add_executable(OSXScriptLauncher
CPack/OSXScriptLauncher.cxx)
@@ -545,25 +970,31 @@ if(APPLE)
endif()
# Build CMake executable
-add_executable(cmake cmakemain.cxx)
+add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE})
+list(APPEND _tools cmake)
target_link_libraries(cmake CMakeLib)
-# Build special executable for running programs on Windows 98.
-# Included on any Windows (unconditional packaging required!).
-if(WIN32)
- if(NOT UNIX)
- add_executable(cmw9xcom cmw9xcom.cxx)
- target_link_libraries(cmw9xcom CMakeLib)
- install(TARGETS cmw9xcom DESTINATION bin)
- endif()
+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()
# Build CTest executable
-add_executable(ctest ctest.cxx)
+add_executable(ctest ctest.cxx ${MANIFEST_FILE})
+list(APPEND _tools ctest)
target_link_libraries(ctest CTestLib)
# Build CPack executable
-add_executable(cpack CPack/cpack.cxx)
+add_executable(cpack CPack/cpack.cxx ${MANIFEST_FILE})
+list(APPEND _tools cpack)
target_link_libraries(cpack CPackLib)
# Curses GUI
@@ -580,9 +1011,14 @@ endif()
include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
-install(TARGETS cmake ctest cpack DESTINATION bin)
-if(APPLE)
- install(TARGETS cmakexbuild DESTINATION bin)
-endif()
+# Install tools
+
+foreach(_tool ${_tools})
+ CMake_OPTIONAL_COMPONENT(${_tool})
+ install(TARGETS ${_tool} DESTINATION ${CMAKE_BIN_DIR} ${COMPONENT})
+endforeach()
install(FILES cmCPluginAPI.h DESTINATION ${CMAKE_DATA_DIR}/include)
+
+# Unset temporary variables
+unset(_tools)
diff --git a/Source/CMakeSourceDir.txt.in b/Source/CMakeSourceDir.txt.in
new file mode 100644
index 000000000..5e6a988c0
--- /dev/null
+++ b/Source/CMakeSourceDir.txt.in
@@ -0,0 +1 @@
+@CMake_SOURCE_DIR@
diff --git a/Source/CMakeVersion.bash b/Source/CMakeVersion.bash
index 4794e608d..853b0ca28 100755
--- a/Source/CMakeVersion.bash
+++ b/Source/CMakeVersion.bash
@@ -3,5 +3,5 @@
if test "x$1" = "x-f"; then shift ; n='*' ; else n='\{8\}' ; fi
if test "$#" -gt 0; then echo 1>&2 "usage: CMakeVersion.bash [-f]"; exit 1; fi
sed -i -e '
-s/\(^set(CMake_VERSION_TWEAK\) [0-9]'"$n"'\(.*\)/\1 '"$(date +%Y%m%d)"'\2/
+s/\(^set(CMake_VERSION_PATCH\) [0-9]'"$n"'\(.*\)/\1 '"$(date +%Y%m%d)"'\2/
' "${BASH_SOURCE%/*}/CMakeVersion.cmake"
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index fd315ce6c..ecf511607 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,6 +1,5 @@
# CMake version number components.
-set(CMake_VERSION_MAJOR 2)
-set(CMake_VERSION_MINOR 8)
-set(CMake_VERSION_PATCH 12)
-set(CMake_VERSION_TWEAK 2)
+set(CMake_VERSION_MAJOR 3)
+set(CMake_VERSION_MINOR 9)
+set(CMake_VERSION_PATCH 4)
#set(CMake_VERSION_RC 0)
diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake
new file mode 100644
index 000000000..d9218d731
--- /dev/null
+++ b/Source/CMakeVersionCompute.cmake
@@ -0,0 +1,29 @@
+# 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
index 05e265c03..5ea1de3f4 100644
--- a/Source/CMakeVersionSource.cmake
+++ b/Source/CMakeVersionSource.cmake
@@ -23,15 +23,8 @@ if(EXISTS ${CMake_SOURCE_DIR}/.git/HEAD)
WORKING_DIRECTORY ${CMake_SOURCE_DIR}
)
if(dirty)
- set(CMake_VERSION_SOURCE "${CMake_VERSION_SOURCE}-dirty")
+ set(CMake_VERSION_IS_DIRTY 1)
endif()
endif()
endif()
-elseif(EXISTS ${CMake_SOURCE_DIR}/CVS/Repository)
- file(READ ${CMake_SOURCE_DIR}/CVS/Repository repo)
- set(branch "")
- if("${repo}" MATCHES "\\.git/")
- string(REGEX REPLACE ".*\\.git/([^\r\n]*).*" "-\\1" branch "${repo}")
- endif()
- set(CMake_VERSION_SOURCE "cvs${branch}")
endif()
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
new file mode 100644
index 000000000..e8f05bd50
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx
@@ -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. */
+#include "cmCPackIFWCommon.h"
+
+#include "cmCPackGenerator.h"
+#include "cmCPackIFWGenerator.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmVersionConfig.h"
+#include "cmXMLWriter.h"
+
+#include <sstream>
+#include <utility>
+#include <vector>
+
+cmCPackIFWCommon::cmCPackIFWCommon()
+ : Generator(CM_NULLPTR)
+{
+}
+
+const char* cmCPackIFWCommon::GetOption(const std::string& op) const
+{
+ return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op)
+ : CM_NULLPTR;
+}
+
+bool cmCPackIFWCommon::IsOn(const std::string& op) const
+{
+ return this->Generator ? this->Generator->cmCPackGenerator::IsOn(op) : false;
+}
+
+bool cmCPackIFWCommon::IsSetToOff(const std::string& op) const
+{
+ return this->Generator ? this->Generator->cmCPackGenerator::IsSetToOff(op)
+ : false;
+}
+
+bool cmCPackIFWCommon::IsSetToEmpty(const std::string& op) const
+{
+ return this->Generator ? this->Generator->cmCPackGenerator::IsSetToEmpty(op)
+ : false;
+}
+
+bool cmCPackIFWCommon::IsVersionLess(const char* version)
+{
+ if (!this->Generator) {
+ return false;
+ }
+
+ return cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->Generator->FrameworkVersion.data(), version);
+}
+
+bool cmCPackIFWCommon::IsVersionGreater(const char* version)
+{
+ if (!this->Generator) {
+ return false;
+ }
+
+ return cmSystemTools::VersionCompare(
+ cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion.data(),
+ version);
+}
+
+bool cmCPackIFWCommon::IsVersionEqual(const char* version)
+{
+ if (!this->Generator) {
+ return false;
+ }
+
+ return cmSystemTools::VersionCompare(
+ cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion.data(),
+ 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);
+ if (args.empty()) {
+ return;
+ }
+
+ std::size_t i = 0;
+ std::size_t c = args.size();
+ if (c % 2) {
+ argsOut[""] = args[i];
+ ++i;
+ }
+
+ --c;
+ for (; i < c; i += 2) {
+ argsOut[args[i]] = args[i + 1];
+ }
+}
+
+void cmCPackIFWCommon::ExpandListArgument(
+ const std::string& arg, std::multimap<std::string, std::string>& argsOut)
+{
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(arg, args, false);
+ if (args.empty()) {
+ return;
+ }
+
+ std::size_t i = 0;
+ std::size_t c = args.size();
+ if (c % 2) {
+ argsOut.insert(std::pair<std::string, std::string>("", args[i]));
+ ++i;
+ }
+
+ --c;
+ for (; i < c; i += 2) {
+ argsOut.insert(std::pair<std::string, std::string>(args[i], args[i + 1]));
+ }
+}
+
+void cmCPackIFWCommon::WriteGeneratedByToStrim(cmXMLWriter& xout)
+{
+ if (!this->Generator) {
+ return;
+ }
+
+ std::ostringstream comment;
+ comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
+ << "for QtIFW ";
+ if (this->IsVersionEqual("1.9.9")) {
+ comment << "less 2.0";
+ } else {
+ comment << this->Generator->FrameworkVersion;
+ }
+ comment << " tools at " << cmTimestamp().CurrentTime("", true);
+ xout.Comment(comment.str().c_str());
+}
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h
new file mode 100644
index 000000000..354d84966
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWCommon.h
@@ -0,0 +1,81 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWCommon_h
+#define cmCPackIFWCommon_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+
+class cmCPackIFWGenerator;
+class cmXMLWriter;
+
+/** \class cmCPackIFWCommon
+ * \brief A base class for CPack IFW generator implementation subclasses
+ */
+class cmCPackIFWCommon
+{
+public:
+ // Constructor
+
+ /**
+ * Construct Part
+ */
+ cmCPackIFWCommon();
+
+public:
+ // Internal implementation
+
+ const char* GetOption(const std::string& op) const;
+ bool IsOn(const std::string& op) const;
+ bool IsSetToOff(const std::string& op) const;
+ bool IsSetToEmpty(const std::string& op) const;
+
+ /**
+ * Compare \a version with QtIFW framework version
+ */
+ bool IsVersionLess(const char* version);
+
+ /**
+ * Compare \a version with QtIFW framework version
+ */
+ bool IsVersionGreater(const char* version);
+
+ /**
+ * Compare \a version with QtIFW framework version
+ */
+ bool IsVersionEqual(const char* version);
+
+ /** Expand the list argument containing the map of the key-value pairs.
+ * If the number of elements is odd, then the first value is used as the
+ * default value with an empty key.
+ * Any values with the same keys will be permanently overwritten.
+ */
+ static void ExpandListArgument(const std::string& arg,
+ std::map<std::string, std::string>& argsOut);
+
+ /** Expand the list argument containing the multimap of the key-value pairs.
+ * If the number of elements is odd, then the first value is used as the
+ * default value with an empty key.
+ */
+ static void ExpandListArgument(
+ const std::string& arg, std::multimap<std::string, std::string>& argsOut);
+
+ cmCPackIFWGenerator* Generator;
+
+protected:
+ void WriteGeneratedByToStrim(cmXMLWriter& xout);
+};
+
+#define cmCPackIFWLogger(logType, msg) \
+ do { \
+ std::ostringstream cmCPackLog_msg; \
+ cmCPackLog_msg << msg; \
+ if (Generator) { \
+ Generator->Logger->Log(cmCPackLog::LOG_##logType, __FILE__, __LINE__, \
+ cmCPackLog_msg.str().c_str()); \
+ } \
+ } while (false)
+
+#endif // cmCPackIFWCommon_h
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
new file mode 100644
index 000000000..226ea0a29
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -0,0 +1,560 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWGenerator.h"
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+#include "cmCPackIFWCommon.h"
+#include "cmCPackIFWInstaller.h"
+#include "cmCPackIFWPackage.h"
+#include "cmCPackIFWRepository.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <utility>
+
+cmCPackIFWGenerator::cmCPackIFWGenerator()
+{
+ this->Generator = this;
+}
+
+cmCPackIFWGenerator::~cmCPackIFWGenerator()
+{
+}
+
+int cmCPackIFWGenerator::PackageFiles()
+{
+ cmCPackIFWLogger(OUTPUT, "- Configuration" << std::endl);
+
+ // Installer configuragion
+ this->Installer.GenerateInstallerFile();
+
+ // Packages configuration
+ this->Installer.GeneratePackageFiles();
+
+ std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ std::string ifwTmpFile = ifwTLD;
+ ifwTmpFile += "/IFWOutput.log";
+
+ // Run repogen
+ if (!this->Installer.RemoteRepositories.empty()) {
+ std::string ifwCmd = this->RepoGen;
+
+ if (this->IsVersionLess("2.0.0")) {
+ ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+ }
+
+ ifwCmd += " -p " + 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;
+ }
+ }
+
+ if (!this->OnlineOnly && !this->DownloadedPackages.empty()) {
+ ifwCmd += " -i ";
+ std::set<cmCPackIFWPackage*>::iterator it =
+ this->DownloadedPackages.begin();
+ ifwCmd += (*it)->Name;
+ ++it;
+ while (it != this->DownloadedPackages.end()) {
+ ifwCmd += "," + (*it)->Name;
+ ++it;
+ }
+ }
+ ifwCmd += " " + this->toplevel + "/repository";
+ cmCPackIFWLogger(VERBOSE, "Execute: " << 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);
+ if (!res || retVal) {
+ cmGeneratedFileStream ofs(ifwTmpFile.c_str());
+ ofs << "# Run command: " << 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);
+ 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(OUTPUT, "- repository: " << this->toplevel
+ << "/repository generated"
+ << std::endl);
+ }
+
+ // Run binary creator
+ {
+ std::string ifwCmd = this->BinCreator;
+ ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+
+ if (!this->Installer.Resources.empty()) {
+ ifwCmd += " -r ";
+ std::vector<std::string>::iterator it =
+ this->Installer.Resources.begin();
+ std::string path = this->toplevel + "/resources/";
+ ifwCmd += path + *it;
+ ++it;
+ while (it != this->Installer.Resources.end()) {
+ ifwCmd += "," + path + *it;
+ ++it;
+ }
+ }
+
+ ifwCmd += " -p " + 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;
+ }
+ }
+
+ if (this->OnlineOnly) {
+ ifwCmd += " --online-only";
+ } else if (!this->DownloadedPackages.empty() &&
+ !this->Installer.RemoteRepositories.empty()) {
+ ifwCmd += " -e ";
+ std::set<cmCPackIFWPackage*>::iterator it =
+ this->DownloadedPackages.begin();
+ ifwCmd += (*it)->Name;
+ ++it;
+ while (it != this->DownloadedPackages.end()) {
+ ifwCmd += "," + (*it)->Name;
+ ++it;
+ }
+ } else if (!this->DependentPackages.empty()) {
+ ifwCmd += " -i ";
+ // Binary
+ std::set<cmCPackIFWPackage*>::iterator bit =
+ this->BinaryPackages.begin();
+ while (bit != this->BinaryPackages.end()) {
+ ifwCmd += (*bit)->Name + ",";
+ ++bit;
+ }
+ // Depend
+ DependenceMap::iterator it = this->DependentPackages.begin();
+ ifwCmd += it->second.Name;
+ ++it;
+ while (it != this->DependentPackages.end()) {
+ ifwCmd += "," + it->second.Name;
+ ++it;
+ }
+ }
+ // TODO: set correct name for multipackages
+ if (!this->packageFileNames.empty()) {
+ ifwCmd += " " + this->packageFileNames[0];
+ } else {
+ ifwCmd += " installer";
+ }
+ cmCPackIFWLogger(VERBOSE, "Execute: " << 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);
+ if (!res || retVal) {
+ cmGeneratedFileStream ofs(ifwTmpFile.c_str());
+ ofs << "# Run command: " << 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);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
+{
+ const char* defPrefix = this->cmCPackGenerator::GetPackagingInstallPrefix();
+
+ std::string tmpPref = defPrefix ? defPrefix : "";
+
+ if (this->Components.empty()) {
+ tmpPref += "packages/" + this->GetRootPackageName() + "/data";
+ }
+
+ this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());
+
+ return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX");
+}
+
+const char* cmCPackIFWGenerator::GetOutputExtension()
+{
+ return this->ExecutableSuffix.c_str();
+}
+
+int cmCPackIFWGenerator::InitializeInternal()
+{
+ // Search Qt Installer Framework tools
+
+ const std::string BinCreatorOpt = "CPACK_IFW_BINARYCREATOR_EXECUTABLE";
+ const std::string RepoGenOpt = "CPACK_IFW_REPOGEN_EXECUTABLE";
+ const std::string FrameworkVersionOpt = "CPACK_IFW_FRAMEWORK_VERSION";
+
+ if (!this->IsSet(BinCreatorOpt) || !this->IsSet(RepoGenOpt) ||
+ !this->IsSet(FrameworkVersionOpt)) {
+ this->ReadListFile("CPackIFW.cmake");
+ }
+
+ // Look 'binarycreator' executable (needs)
+
+ const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
+ if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) {
+ this->BinCreator = "";
+ } 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"
+ << std::endl);
+ return 0;
+ }
+
+ // Look 'repogen' executable (optional)
+
+ const char* RepoGenStr = this->GetOption(RepoGenOpt);
+ if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) {
+ this->RepoGen = "";
+ } else {
+ this->RepoGen = RepoGenStr;
+ }
+
+ // Framework version
+ if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) {
+ this->FrameworkVersion = FrameworkVersionSrt;
+ } else {
+ this->FrameworkVersion = "1.9.9";
+ }
+
+ // Variables that Change Behavior
+
+ // Resolve duplicate names
+ this->ResolveDuplicateNames =
+ this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");
+
+ // Additional packages dirs
+ this->PkgsDirsVector.clear();
+ if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
+ cmSystemTools::ExpandListArgument(dirs, this->PkgsDirsVector);
+ }
+
+ // Installer
+ this->Installer.Generator = this;
+ this->Installer.ConfigureFromOptions();
+
+ // Repository
+ this->Repository.Generator = this;
+ this->Repository.Name = "Unspecified";
+ if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) {
+ this->Repository.Url = site;
+ this->Installer.RemoteRepositories.push_back(&this->Repository);
+ }
+
+ // 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);
+ }
+ }
+
+ if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
+ this->OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
+ } else if (const char* cpackDownloadAll =
+ this->GetOption("CPACK_DOWNLOAD_ALL")) {
+ this->OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
+ } else {
+ this->OnlineOnly = false;
+ }
+
+ if (!this->Installer.RemoteRepositories.empty() && this->RepoGen.empty()) {
+ cmCPackIFWLogger(ERROR,
+ "Cannot find QtIFW repository generator \"repogen\": "
+ "likely it is not installed, or not in your PATH"
+ << std::endl);
+ return 0;
+ }
+
+ // 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";
+ }
+ }
+ } else {
+ this->ExecutableSuffix = this->cmCPackGenerator::GetOutputExtension();
+ }
+
+ return this->Superclass::InitializeInternal();
+}
+
+std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
+ const std::string& componentName)
+{
+ const std::string prefix = "packages/";
+ const std::string suffix = "/data";
+
+ if (this->componentPackageMethod == this->ONE_PACKAGE) {
+ return std::string(prefix + this->GetRootPackageName() + suffix);
+ }
+
+ return prefix +
+ this->GetComponentPackageName(&this->Components[componentName]) + suffix;
+}
+
+cmCPackComponent* cmCPackIFWGenerator::GetComponent(
+ const std::string& projectName, const std::string& componentName)
+{
+ ComponentsMap::iterator cit = this->Components.find(componentName);
+ if (cit != this->Components.end()) {
+ return &(cit->second);
+ }
+
+ cmCPackComponent* component =
+ this->cmCPackGenerator::GetComponent(projectName, componentName);
+ if (!component) {
+ return component;
+ }
+
+ std::string name = this->GetComponentPackageName(component);
+ PackagesMap::iterator pit = this->Packages.find(name);
+ if (pit != this->Packages.end()) {
+ return component;
+ }
+
+ cmCPackIFWPackage* package = &this->Packages[name];
+ package->Name = name;
+ package->Generator = this;
+ if (package->ConfigureFromComponent(component)) {
+ package->Installer = &this->Installer;
+ this->Installer.Packages.insert(
+ std::pair<std::string, cmCPackIFWPackage*>(name, package));
+ this->ComponentPackages.insert(
+ std::pair<cmCPackComponent*, cmCPackIFWPackage*>(component, package));
+ if (component->IsDownloaded) {
+ this->DownloadedPackages.insert(package);
+ } else {
+ this->BinaryPackages.insert(package);
+ }
+ } else {
+ this->Packages.erase(name);
+ cmCPackIFWLogger(ERROR, "Cannot configure package \""
+ << name << "\" for component \"" << component->Name
+ << "\"" << std::endl);
+ }
+
+ return component;
+}
+
+cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
+ const std::string& projectName, const std::string& groupName)
+{
+ cmCPackComponentGroup* group =
+ this->cmCPackGenerator::GetComponentGroup(projectName, groupName);
+ if (!group) {
+ return group;
+ }
+
+ std::string name = this->GetGroupPackageName(group);
+ PackagesMap::iterator pit = this->Packages.find(name);
+ if (pit != this->Packages.end()) {
+ return group;
+ }
+
+ cmCPackIFWPackage* package = &this->Packages[name];
+ package->Name = name;
+ package->Generator = this;
+ if (package->ConfigureFromGroup(group)) {
+ package->Installer = &this->Installer;
+ this->Installer.Packages.insert(
+ std::pair<std::string, cmCPackIFWPackage*>(name, package));
+ this->GroupPackages.insert(
+ std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>(group, package));
+ this->BinaryPackages.insert(package);
+ } else {
+ this->Packages.erase(name);
+ cmCPackIFWLogger(ERROR, "Cannot configure package \""
+ << name << "\" for component group \"" << group->Name
+ << "\"" << std::endl);
+ }
+ return group;
+}
+
+enum cmCPackGenerator::CPackSetDestdirSupport
+cmCPackIFWGenerator::SupportsSetDestdir() const
+{
+ return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED;
+}
+
+bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const
+{
+ return false;
+}
+
+bool cmCPackIFWGenerator::SupportsComponentInstallation() const
+{
+ return true;
+}
+
+bool cmCPackIFWGenerator::IsOnePackage() const
+{
+ return this->componentPackageMethod == cmCPackGenerator::ONE_PACKAGE;
+}
+
+std::string cmCPackIFWGenerator::GetRootPackageName()
+{
+ // Default value
+ std::string name = "root";
+ if (const char* optIFW_PACKAGE_GROUP =
+ this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
+ // Configure from root group
+ cmCPackIFWPackage package;
+ package.Generator = this;
+ package.ConfigureFromGroup(optIFW_PACKAGE_GROUP);
+ name = package.Name;
+ } else if (const char* optIFW_PACKAGE_NAME =
+ this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
+ // Configure from root package name
+ name = optIFW_PACKAGE_NAME;
+ } else if (const char* optPACKAGE_NAME =
+ this->GetOption("CPACK_PACKAGE_NAME")) {
+ // Configure from package name
+ name = optPACKAGE_NAME;
+ }
+ return name;
+}
+
+std::string cmCPackIFWGenerator::GetGroupPackageName(
+ cmCPackComponentGroup* group) const
+{
+ std::string name;
+ if (!group) {
+ return name;
+ }
+ if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) {
+ return package->Name;
+ }
+ const char* option =
+ this->GetOption("CPACK_IFW_COMPONENT_GROUP_" +
+ cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
+ name = option ? option : group->Name;
+ if (group->ParentGroup) {
+ cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup);
+ bool dot = !this->ResolveDuplicateNames;
+ if (dot && name.substr(0, package->Name.size()) == package->Name) {
+ dot = false;
+ }
+ if (dot) {
+ name = package->Name + "." + name;
+ }
+ }
+ return name;
+}
+
+std::string cmCPackIFWGenerator::GetComponentPackageName(
+ cmCPackComponent* component) const
+{
+ std::string name;
+ if (!component) {
+ return name;
+ }
+ if (cmCPackIFWPackage* package = this->GetComponentPackage(component)) {
+ return package->Name;
+ }
+ std::string prefix = "CPACK_IFW_COMPONENT_" +
+ cmsys::SystemTools::UpperCase(component->Name) + "_";
+ const char* option = this->GetOption(prefix + "NAME");
+ name = option ? option : component->Name;
+ if (component->Group) {
+ cmCPackIFWPackage* package = this->GetGroupPackage(component->Group);
+ if ((this->componentPackageMethod ==
+ cmCPackGenerator::ONE_PACKAGE_PER_GROUP) ||
+ this->IsOn(prefix + "COMMON")) {
+ return package->Name;
+ }
+ bool dot = !this->ResolveDuplicateNames;
+ if (dot && name.substr(0, package->Name.size()) == package->Name) {
+ dot = false;
+ }
+ if (dot) {
+ name = package->Name + "." + name;
+ }
+ }
+ return name;
+}
+
+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;
+}
+
+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;
+}
+
+cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository(
+ const std::string& repositoryName)
+{
+ RepositoriesMap::iterator rit = this->Repositories.find(repositoryName);
+ if (rit != this->Repositories.end()) {
+ return &(rit->second);
+ }
+
+ cmCPackIFWRepository* repository = &this->Repositories[repositoryName];
+ repository->Name = repositoryName;
+ repository->Generator = this;
+ if (repository->ConfigureFromOptions()) {
+ if (repository->Update == cmCPackIFWRepository::None) {
+ this->Installer.RemoteRepositories.push_back(repository);
+ } else {
+ this->Repository.RepositoryUpdate.push_back(repository);
+ }
+ } else {
+ this->Repositories.erase(repositoryName);
+ repository = CM_NULLPTR;
+ cmCPackIFWLogger(WARNING, "Invalid repository \""
+ << repositoryName << "\""
+ << " configuration. Repository will be skipped."
+ << std::endl);
+ }
+ return repository;
+}
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h
new file mode 100644
index 000000000..8348ceeec
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.h
@@ -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. */
+#ifndef cmCPackIFWGenerator_h
+#define cmCPackIFWGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+#include "cmCPackIFWCommon.h"
+#include "cmCPackIFWInstaller.h"
+#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
+{
+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 cmCPackIFWCommon::GetOption;
+ using cmCPackIFWCommon::IsOn;
+ using cmCPackIFWCommon::IsSetToOff;
+ using cmCPackIFWCommon::IsSetToEmpty;
+
+ /**
+ * Construct IFW generator
+ */
+ cmCPackIFWGenerator();
+
+ /**
+ * Destruct IFW generator
+ */
+ ~cmCPackIFWGenerator() CM_OVERRIDE;
+
+protected:
+ // cmCPackGenerator reimplementation
+
+ /**
+ * @brief Initialize generator
+ * @return 0 on failure
+ */
+ int InitializeInternal() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
+ const char* GetPackagingInstallPrefix() CM_OVERRIDE;
+
+ /**
+ * @brief Extension of binary installer
+ * @return Executable suffix or value from default implementation
+ */
+ const char* GetOutputExtension() CM_OVERRIDE;
+
+ std::string GetComponentInstallDirNameSuffix(
+ const std::string& componentName) CM_OVERRIDE;
+
+ /**
+ * @brief Get Component
+ * @param projectName Project name
+ * @param componentName Component name
+ *
+ * This method calls the base implementation.
+ *
+ * @return Pointer to component
+ */
+ cmCPackComponent* GetComponent(const std::string& projectName,
+ const std::string& componentName) CM_OVERRIDE;
+
+ /**
+ * @brief Get group of component
+ * @param projectName Project name
+ * @param groupName Component group name
+ *
+ * This method calls the base implementation.
+ *
+ * @return Pointer to component group
+ */
+ cmCPackComponentGroup* GetComponentGroup(
+ const std::string& projectName, const std::string& groupName) CM_OVERRIDE;
+
+ enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const
+ CM_OVERRIDE;
+ bool SupportsAbsoluteDestination() const CM_OVERRIDE;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
+
+protected:
+ // Methods
+
+ bool IsOnePackage() const;
+
+ std::string GetRootPackageName();
+
+ std::string GetGroupPackageName(cmCPackComponentGroup* group) const;
+ std::string GetComponentPackageName(cmCPackComponent* component) const;
+
+ cmCPackIFWPackage* GetGroupPackage(cmCPackComponentGroup* group) const;
+ cmCPackIFWPackage* GetComponentPackage(cmCPackComponent* component) const;
+
+ cmCPackIFWRepository* GetRepository(const std::string& repositoryName);
+
+protected:
+ // Data
+
+ friend class cmCPackIFWPackage;
+ friend class cmCPackIFWCommon;
+ friend class cmCPackIFWInstaller;
+ friend class cmCPackIFWRepository;
+
+ // Installer
+ cmCPackIFWInstaller Installer;
+ // Repository
+ cmCPackIFWRepository Repository;
+ // Collection of packages
+ PackagesMap Packages;
+ // Collection of repositories
+ RepositoriesMap Repositories;
+ // Collection of binary packages
+ std::set<cmCPackIFWPackage*> BinaryPackages;
+ // Collection of downloaded packages
+ std::set<cmCPackIFWPackage*> DownloadedPackages;
+ // Dependent packages
+ DependenceMap DependentPackages;
+ std::map<cmCPackComponent*, cmCPackIFWPackage*> ComponentPackages;
+ std::map<cmCPackComponentGroup*, cmCPackIFWPackage*> GroupPackages;
+
+private:
+ std::string RepoGen;
+ std::string BinCreator;
+ std::string FrameworkVersion;
+ std::string ExecutableSuffix;
+
+ bool OnlineOnly;
+ bool ResolveDuplicateNames;
+ std::vector<std::string> PkgsDirsVector;
+};
+
+#endif
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
new file mode 100644
index 000000000..288e924e5
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -0,0 +1,500 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWInstaller.h"
+
+#include "cmCPackIFWCommon.h"
+#include "cmCPackIFWGenerator.h"
+#include "cmCPackIFWPackage.h"
+#include "cmCPackIFWRepository.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmXMLWriter.h"
+
+#include <sstream>
+#include <stddef.h>
+#include <utility>
+
+cmCPackIFWInstaller::cmCPackIFWInstaller()
+{
+}
+
+void cmCPackIFWInstaller::printSkippedOptionWarning(
+ const std::string& optionName, const std::string& optionValue)
+{
+ cmCPackIFWLogger(
+ WARNING, "Option "
+ << optionName << " is set to \"" << optionValue
+ << "\" but will be skipped because the specified file does not exist."
+ << std::endl);
+}
+
+void cmCPackIFWInstaller::ConfigureFromOptions()
+{
+ // Name;
+ if (const char* optIFW_PACKAGE_NAME =
+ this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
+ this->Name = optIFW_PACKAGE_NAME;
+ } else if (const char* optPACKAGE_NAME =
+ this->GetOption("CPACK_PACKAGE_NAME")) {
+ this->Name = optPACKAGE_NAME;
+ } else {
+ this->Name = "Your package";
+ }
+
+ // Title;
+ if (const char* optIFW_PACKAGE_TITLE =
+ this->GetOption("CPACK_IFW_PACKAGE_TITLE")) {
+ this->Title = optIFW_PACKAGE_TITLE;
+ } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
+ this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
+ this->Title = optPACKAGE_DESCRIPTION_SUMMARY;
+ } else {
+ this->Title = "Your package description";
+ }
+
+ // Version;
+ if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = option;
+ } else {
+ this->Version = "1.0.0";
+ }
+
+ // Publisher
+ if (const char* optIFW_PACKAGE_PUBLISHER =
+ this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
+ this->Publisher = optIFW_PACKAGE_PUBLISHER;
+ } else if (const char* optPACKAGE_VENDOR =
+ GetOption("CPACK_PACKAGE_VENDOR")) {
+ this->Publisher = optPACKAGE_VENDOR;
+ }
+
+ // ProductUrl
+ if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) {
+ this->ProductUrl = option;
+ }
+
+ // ApplicationIcon
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->InstallerApplicationIcon = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option);
+ }
+ }
+
+ // WindowIcon
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->InstallerWindowIcon = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option);
+ }
+ }
+
+ // Logo
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->Logo = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option);
+ }
+ }
+
+ // Watermark
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->Watermark = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option);
+ }
+ }
+
+ // Banner
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->Banner = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option);
+ }
+ }
+
+ // Background
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->Background = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option);
+ }
+ }
+
+ // WizardStyle
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
+ // Setting the user value in any case
+ this->WizardStyle = option;
+ // Check known values
+ if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" &&
+ this->WizardStyle != "Mac" && this->WizardStyle != "Classic") {
+ cmCPackIFWLogger(
+ WARNING, "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
+ << option << "\". Expected values are: Modern, Aero, Mac, Classic."
+ << std::endl);
+ }
+ }
+
+ // WizardDefaultWidth
+ if (const char* option =
+ this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
+ this->WizardDefaultWidth = option;
+ }
+
+ // WizardDefaultHeight
+ if (const char* option =
+ this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
+ this->WizardDefaultHeight = option;
+ }
+
+ // TitleColor
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
+ this->TitleColor = option;
+ }
+
+ // Start menu
+ if (const char* optIFW_START_MENU_DIR =
+ this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
+ this->StartMenuDir = optIFW_START_MENU_DIR;
+ } else {
+ this->StartMenuDir = Name;
+ }
+
+ // Default target directory for installation
+ if (const char* optIFW_TARGET_DIRECTORY =
+ this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
+ 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;
+ } else {
+ this->TargetDir = "@RootDir@/usr/local";
+ }
+
+ // Default target directory for installation with administrator rights
+ if (const char* option =
+ this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
+ this->AdminTargetDir = option;
+ }
+
+ // Maintenance tool
+ if (const char* optIFW_MAINTENANCE_TOOL =
+ this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
+ this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
+ }
+
+ // Maintenance tool ini file
+ if (const char* optIFW_MAINTENANCE_TOOL_INI =
+ this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
+ this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
+ }
+
+ // Allow non-ASCII characters
+ if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
+ if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
+ this->AllowNonAsciiCharacters = "true";
+ } else {
+ this->AllowNonAsciiCharacters = "false";
+ }
+ }
+
+ // Space in path
+ if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
+ if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
+ this->AllowSpaceInPath = "true";
+ } else {
+ this->AllowSpaceInPath = "false";
+ }
+ }
+
+ // Control script
+ if (const char* optIFW_CONTROL_SCRIPT =
+ this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
+ this->ControlScript = optIFW_CONTROL_SCRIPT;
+ }
+
+ // Resources
+ if (const char* optIFW_PACKAGE_RESOURCES =
+ this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
+ this->Resources.clear();
+ cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES,
+ this->Resources);
+ }
+}
+
+/** \class cmCPackIFWResourcesParser
+ * \brief Helper class that parse resources form .qrc (Qt)
+ */
+class cmCPackIFWResourcesParser : public cmXMLParser
+{
+public:
+ cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
+ : installer(i)
+ , file(false)
+ {
+ this->path = i->Directory + "/resources";
+ }
+
+ bool ParseResource(size_t r)
+ {
+ this->hasFiles = false;
+ this->hasErrors = false;
+
+ this->basePath =
+ cmSystemTools::GetFilenamePath(this->installer->Resources[r]);
+
+ this->ParseFile(this->installer->Resources[r].data());
+
+ return this->hasFiles && !this->hasErrors;
+ }
+
+ cmCPackIFWInstaller* installer;
+ bool file, hasFiles, hasErrors;
+ std::string path, basePath;
+
+protected:
+ void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
+ {
+ this->file = name == "file";
+ if (file) {
+ this->hasFiles = true;
+ }
+ }
+
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ if (this->file) {
+ std::string content(data, data + length);
+ content = cmSystemTools::TrimWhitespace(content);
+ std::string source = this->basePath + "/" + content;
+ std::string destination = this->path + "/" + content;
+ if (!cmSystemTools::CopyFileIfDifferent(source.data(),
+ destination.data())) {
+ this->hasErrors = true;
+ }
+ }
+ }
+
+ void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
+};
+
+void cmCPackIFWInstaller::GenerateInstallerFile()
+{
+ // Lazy directory initialization
+ if (this->Directory.empty() && this->Generator) {
+ this->Directory = this->Generator->toplevel;
+ }
+
+ // Output stream
+ cmGeneratedFileStream fout((this->Directory + "/config/config.xml").data());
+ cmXMLWriter xout(fout);
+
+ xout.StartDocument();
+
+ WriteGeneratedByToStrim(xout);
+
+ xout.StartElement("Installer");
+
+ xout.Element("Name", this->Name);
+ xout.Element("Version", this->Version);
+ xout.Element("Title", this->Title);
+
+ if (!this->Publisher.empty()) {
+ xout.Element("Publisher", this->Publisher);
+ }
+
+ if (!this->ProductUrl.empty()) {
+ xout.Element("ProductUrl", this->ProductUrl);
+ }
+
+ // ApplicationIcon
+ if (!this->InstallerApplicationIcon.empty()) {
+ std::string name =
+ cmSystemTools::GetFilenameName(this->InstallerApplicationIcon);
+ std::string path = this->Directory + "/config/" + name;
+ name = cmSystemTools::GetFilenameWithoutExtension(name);
+ cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon,
+ path);
+ xout.Element("InstallerApplicationIcon", name);
+ }
+
+ // WindowIcon
+ if (!this->InstallerWindowIcon.empty()) {
+ std::string name =
+ cmSystemTools::GetFilenameName(this->InstallerWindowIcon);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path);
+ xout.Element("InstallerWindowIcon", name);
+ }
+
+ // Logo
+ if (!this->Logo.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->Logo);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path);
+ xout.Element("Logo", name);
+ }
+
+ // Banner
+ if (!this->Banner.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->Banner);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->Banner, path);
+ xout.Element("Banner", name);
+ }
+
+ // Watermark
+ if (!this->Watermark.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->Watermark);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->Watermark, path);
+ xout.Element("Watermark", name);
+ }
+
+ // Background
+ if (!this->Background.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->Background);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->Background, path);
+ xout.Element("Background", name);
+ }
+
+ // WizardStyle
+ if (!this->WizardStyle.empty()) {
+ xout.Element("WizardStyle", this->WizardStyle);
+ }
+
+ // WizardDefaultWidth
+ if (!this->WizardDefaultWidth.empty()) {
+ xout.Element("WizardDefaultWidth", this->WizardDefaultWidth);
+ }
+
+ // WizardDefaultHeight
+ if (!this->WizardDefaultHeight.empty()) {
+ xout.Element("WizardDefaultHeight", this->WizardDefaultHeight);
+ }
+
+ // TitleColor
+ if (!this->TitleColor.empty()) {
+ xout.Element("TitleColor", this->TitleColor);
+ }
+
+ // Start menu
+ if (!this->IsVersionLess("2.0")) {
+ xout.Element("StartMenuDir", this->StartMenuDir);
+ }
+
+ // Target dir
+ if (!this->TargetDir.empty()) {
+ xout.Element("TargetDir", this->TargetDir);
+ }
+
+ // Admin target dir
+ if (!this->AdminTargetDir.empty()) {
+ xout.Element("AdminTargetDir", this->AdminTargetDir);
+ }
+
+ // Remote repositories
+ if (!this->RemoteRepositories.empty()) {
+ xout.StartElement("RemoteRepositories");
+ for (RepositoriesVector::iterator rit = this->RemoteRepositories.begin();
+ rit != this->RemoteRepositories.end(); ++rit) {
+ (*rit)->WriteRepositoryConfig(xout);
+ }
+ xout.EndElement();
+ }
+
+ // Maintenance tool
+ if (!this->IsVersionLess("2.0") && !this->MaintenanceToolName.empty()) {
+ xout.Element("MaintenanceToolName", this->MaintenanceToolName);
+ }
+
+ // Maintenance tool ini file
+ if (!this->IsVersionLess("2.0") && !this->MaintenanceToolIniFile.empty()) {
+ xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile);
+ }
+
+ // Different allows
+ if (this->IsVersionLess("2.0")) {
+ // CPack IFW default policy
+ xout.Comment("CPack IFW default policy for QtIFW less 2.0");
+ xout.Element("AllowNonAsciiCharacters", "true");
+ xout.Element("AllowSpaceInPath", "true");
+ } else {
+ if (!this->AllowNonAsciiCharacters.empty()) {
+ xout.Element("AllowNonAsciiCharacters", this->AllowNonAsciiCharacters);
+ }
+ if (!this->AllowSpaceInPath.empty()) {
+ xout.Element("AllowSpaceInPath", this->AllowSpaceInPath);
+ }
+ }
+
+ // Control script (copy to config dir)
+ if (!this->IsVersionLess("2.0") && !this->ControlScript.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->ControlScript);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->ControlScript, path);
+ xout.Element("ControlScript", name);
+ }
+
+ // Resources (copy to resources dir)
+ if (!this->Resources.empty()) {
+ std::vector<std::string> resources;
+ cmCPackIFWResourcesParser parser(this);
+ for (size_t i = 0; i < this->Resources.size(); i++) {
+ if (parser.ParseResource(i)) {
+ 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);
+ } else {
+ cmCPackIFWLogger(WARNING, "Can't copy resources from \""
+ << this->Resources[i]
+ << "\". Resource will be skipped." << std::endl);
+ }
+ }
+ this->Resources = resources;
+ }
+
+ xout.EndElement();
+ xout.EndDocument();
+}
+
+void cmCPackIFWInstaller::GeneratePackageFiles()
+{
+ if (this->Packages.empty() || this->Generator->IsOnePackage()) {
+ // Generate default package
+ cmCPackIFWPackage package;
+ package.Generator = this->Generator;
+ package.Installer = this;
+ // Check package group
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
+ package.ConfigureFromGroup(option);
+ std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
+ cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
+ if (!GetOption(forcedOption)) {
+ package.ForcedInstallation = "true";
+ }
+ } else {
+ package.ConfigureFromOptions();
+ }
+ package.GeneratePackageFile();
+ return;
+ }
+
+ // Generate packages meta information
+ for (PackagesMap::iterator pit = this->Packages.begin();
+ pit != this->Packages.end(); ++pit) {
+ cmCPackIFWPackage* package = pit->second;
+ package->GeneratePackageFile();
+ }
+}
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
new file mode 100644
index 000000000..b635f4222
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -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. */
+#ifndef cmCPackIFWInstaller_h
+#define cmCPackIFWInstaller_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCPackIFWCommon.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCPackIFWPackage;
+class cmCPackIFWRepository;
+
+/** \class cmCPackIFWInstaller
+ * \brief A binary installer to be created CPack IFW generator
+ */
+class cmCPackIFWInstaller : public cmCPackIFWCommon
+{
+public:
+ // Types
+
+ typedef std::map<std::string, cmCPackIFWPackage*> PackagesMap;
+ typedef std::vector<cmCPackIFWRepository*> RepositoriesVector;
+
+public:
+ // Constructor
+
+ /**
+ * Construct installer
+ */
+ cmCPackIFWInstaller();
+
+public:
+ // Configuration
+
+ /// Name of the product being installed
+ std::string Name;
+
+ /// Version number of the product being installed
+ std::string Version;
+
+ /// Name of the installer as displayed on the title bar
+ std::string Title;
+
+ /// Publisher of the software (as shown in the Windows Control Panel)
+ std::string Publisher;
+
+ /// URL to a page that contains product information on your web site
+ std::string ProductUrl;
+
+ /// Filename for a custom installer icon
+ std::string InstallerApplicationIcon;
+
+ /// Filename for a custom window icon
+ std::string InstallerWindowIcon;
+
+ /// Filename for a logo
+ std::string Logo;
+
+ /// Filename for a watermark
+ std::string Watermark;
+
+ /// Filename for a banner
+ std::string Banner;
+
+ /// Filename for a background
+ std::string Background;
+
+ /// Wizard style name
+ std::string WizardStyle;
+
+ /// Wizard width
+ std::string WizardDefaultWidth;
+
+ /// Wizard height
+ std::string WizardDefaultHeight;
+
+ /// Title color
+ std::string TitleColor;
+
+ /// Name of the default program group in the Windows Start menu
+ std::string StartMenuDir;
+
+ /// Default target directory for installation
+ std::string TargetDir;
+
+ /// Default target directory for installation with administrator rights
+ std::string AdminTargetDir;
+
+ /// Filename of the generated maintenance tool
+ std::string MaintenanceToolName;
+
+ /// Filename for the configuration of the generated maintenance tool
+ std::string MaintenanceToolIniFile;
+
+ /// Set to true if the installation path can contain non-ASCII characters
+ std::string AllowNonAsciiCharacters;
+
+ /// Set to false if the installation path cannot contain space characters
+ std::string AllowSpaceInPath;
+
+ /// Filename for a custom installer control script
+ std::string ControlScript;
+
+ /// List of resources to include in the installer binary
+ std::vector<std::string> Resources;
+
+public:
+ // Internal implementation
+
+ void ConfigureFromOptions();
+
+ void GenerateInstallerFile();
+
+ void GeneratePackageFiles();
+
+ PackagesMap Packages;
+ RepositoriesVector RemoteRepositories;
+ std::string Directory;
+
+protected:
+ void printSkippedOptionWarning(const std::string& optionName,
+ const std::string& optionValue);
+};
+
+#endif // cmCPackIFWInstaller_h
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
new file mode 100644
index 000000000..c5311c31c
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -0,0 +1,690 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWPackage.h"
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackIFWCommon.h"
+#include "cmCPackIFWGenerator.h"
+#include "cmCPackIFWInstaller.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmGeneratedFileStream.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)
+{
+}
+
+//------------------------------------------------------- DependenceStruct ---
+cmCPackIFWPackage::DependenceStruct::DependenceStruct()
+{
+}
+
+cmCPackIFWPackage::DependenceStruct::DependenceStruct(
+ const std::string& dependence)
+{
+ // Search compare section
+ size_t pos = std::string::npos;
+ if ((pos = dependence.find("<=")) != std::string::npos) {
+ this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
+ this->Compare.Value = dependence.substr(pos + 2);
+ } else if ((pos = dependence.find(">=")) != std::string::npos) {
+ this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
+ this->Compare.Value = dependence.substr(pos + 2);
+ } else if ((pos = dependence.find('<')) != std::string::npos) {
+ this->Compare.Type = cmCPackIFWPackage::CompareLess;
+ this->Compare.Value = dependence.substr(pos + 1);
+ } else if ((pos = dependence.find('=')) != std::string::npos) {
+ this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+ this->Compare.Value = dependence.substr(pos + 1);
+ } else if ((pos = dependence.find('>')) != std::string::npos) {
+ this->Compare.Type = cmCPackIFWPackage::CompareGreater;
+ this->Compare.Value = dependence.substr(pos + 1);
+ } else if ((pos = dependence.find('-')) != std::string::npos) {
+ this->Compare.Type = cmCPackIFWPackage::CompareNone;
+ this->Compare.Value = dependence.substr(pos + 1);
+ }
+ size_t dashPos = dependence.find('-');
+ if (dashPos != std::string::npos) {
+ pos = dashPos;
+ }
+ this->Name =
+ pos == std::string::npos ? dependence : dependence.substr(0, pos);
+}
+
+std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
+{
+ if (this->Compare.Type == cmCPackIFWPackage::CompareNone) {
+ return this->Name;
+ }
+
+ std::string result = this->Name;
+
+ if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
+ !this->Compare.Value.empty()) {
+ result += "-";
+ }
+
+ if (this->Compare.Type == cmCPackIFWPackage::CompareLessOrEqual) {
+ result += "<=";
+ } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreaterOrEqual) {
+ result += ">=";
+ } else if (this->Compare.Type == cmCPackIFWPackage::CompareLess) {
+ result += "<";
+ } else if (this->Compare.Type == cmCPackIFWPackage::CompareEqual) {
+ result += "=";
+ } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreater) {
+ result += ">";
+ }
+
+ result += this->Compare.Value;
+
+ return result;
+}
+
+//------------------------------------------------------ cmCPackIFWPackage ---
+cmCPackIFWPackage::cmCPackIFWPackage()
+ : Installer(CM_NULLPTR)
+{
+}
+
+std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
+{
+ if (!component) {
+ return "";
+ }
+ const char* option =
+ this->GetOption("CPACK_IFW_COMPONENT_" +
+ cmsys::SystemTools::UpperCase(component->Name) + "_NAME");
+ return option ? option : component->Name;
+}
+
+void cmCPackIFWPackage::DefaultConfiguration()
+{
+ this->DisplayName.clear();
+ this->Description.clear();
+ this->Version = "";
+ this->ReleaseDate = "";
+ this->Script = "";
+ this->Licenses.clear();
+ this->UserInterfaces.clear();
+ this->Translations.clear();
+ this->SortingPriority = "";
+ this->UpdateText = "";
+ this->Default = "";
+ this->Essential = "";
+ this->Virtual = "";
+ this->ForcedInstallation = "";
+ this->RequiresAdminRights = "";
+}
+
+// Defaul configuration (all in one package)
+int cmCPackIFWPackage::ConfigureFromOptions()
+{
+ // Restore defaul configuration
+ this->DefaultConfiguration();
+
+ // Name
+ this->Name = this->Generator->GetRootPackageName();
+
+ // Display name
+ if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) {
+ this->DisplayName[""] = option;
+ } else {
+ this->DisplayName[""] = "Your package";
+ }
+
+ // Description
+ if (const char* option =
+ this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
+ this->Description[""] = option;
+ } else {
+ this->Description[""] = "Your package description";
+ }
+
+ // Version
+ if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = option;
+ } else {
+ this->Version = "1.0.0";
+ }
+
+ this->ForcedInstallation = "true";
+
+ return 1;
+}
+
+int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
+{
+ if (!component) {
+ return 0;
+ }
+
+ // Restore defaul configuration
+ this->DefaultConfiguration();
+
+ std::string prefix = "CPACK_IFW_COMPONENT_" +
+ cmsys::SystemTools::UpperCase(component->Name) + "_";
+
+ // Display name
+ this->DisplayName[""] = component->DisplayName;
+
+ // Description
+ this->Description[""] = component->Description;
+
+ // Version
+ if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
+ this->Version = optVERSION;
+ } else if (const char* optPACKAGE_VERSION =
+ this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = optPACKAGE_VERSION;
+ } else {
+ this->Version = "1.0.0";
+ }
+
+ // Script
+ if (const char* option = this->GetOption(prefix + "SCRIPT")) {
+ this->Script = option;
+ }
+
+ // User interfaces
+ if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ this->UserInterfaces.clear();
+ cmSystemTools::ExpandListArgument(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]);
+ }
+ }
+
+ // Licenses
+ if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ this->Licenses.clear();
+ cmSystemTools::ExpandListArgument(option, this->Licenses);
+ if (this->Licenses.size() % 2 != 0) {
+ cmCPackIFWLogger(
+ WARNING,
+ prefix << "LICENSES"
+ << " should contain pairs of <display_name> and <file_path>."
+ << std::endl);
+ this->Licenses.clear();
+ }
+ }
+
+ // Priority
+ if (const char* option = this->GetOption(prefix + "PRIORITY")) {
+ this->SortingPriority = option;
+ cmCPackIFWLogger(
+ WARNING, "The \"PRIORITY\" option is set "
+ << "for component \"" << component->Name << "\", but there option is "
+ << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
+ << std::endl);
+ }
+
+ // Default
+ this->Default = component->IsDisabledByDefault ? "false" : "true";
+
+ // Essential
+ if (this->IsOn(prefix + "ESSENTIAL")) {
+ this->Essential = "true";
+ }
+
+ // Virtual
+ this->Virtual = component->IsHidden ? "true" : "";
+
+ // ForcedInstallation
+ this->ForcedInstallation = component->IsRequired ? "true" : "false";
+
+ return this->ConfigureFromPrefix(prefix);
+}
+
+int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
+{
+ if (!group) {
+ return 0;
+ }
+
+ // Restore defaul configuration
+ this->DefaultConfiguration();
+
+ std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" +
+ cmsys::SystemTools::UpperCase(group->Name) + "_";
+
+ this->DisplayName[""] = group->DisplayName;
+ this->Description[""] = group->Description;
+
+ // Version
+ if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
+ this->Version = optVERSION;
+ } else if (const char* optPACKAGE_VERSION =
+ this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = optPACKAGE_VERSION;
+ } else {
+ this->Version = "1.0.0";
+ }
+
+ // Script
+ if (const char* option = this->GetOption(prefix + "SCRIPT")) {
+ this->Script = option;
+ }
+
+ // User interfaces
+ if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ this->UserInterfaces.clear();
+ cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
+ }
+
+ // Licenses
+ if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ this->Licenses.clear();
+ cmSystemTools::ExpandListArgument(option, this->Licenses);
+ if (this->Licenses.size() % 2 != 0) {
+ cmCPackIFWLogger(
+ WARNING,
+ prefix << "LICENSES"
+ << " should contain pairs of <display_name> and <file_path>."
+ << std::endl);
+ this->Licenses.clear();
+ }
+ }
+
+ // Priority
+ if (const char* option = this->GetOption(prefix + "PRIORITY")) {
+ this->SortingPriority = option;
+ cmCPackIFWLogger(
+ WARNING, "The \"PRIORITY\" option is set "
+ << "for component group \"" << group->Name
+ << "\", but there option is "
+ << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
+ << std::endl);
+ }
+
+ return this->ConfigureFromPrefix(prefix);
+}
+
+int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
+{
+ // Group configuration
+
+ cmCPackComponentGroup group;
+ std::string prefix =
+ "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_";
+
+ if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) {
+ group.DisplayName = option;
+ } else {
+ group.DisplayName = group.Name;
+ }
+
+ if (const char* option = this->GetOption(prefix + "DESCRIPTION")) {
+ group.Description = option;
+ }
+ group.IsBold = this->IsOn(prefix + "BOLD_TITLE");
+ group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED");
+
+ // Package configuration
+
+ group.Name = groupName;
+
+ if (Generator) {
+ this->Name = this->Generator->GetGroupPackageName(&group);
+ } else {
+ this->Name = group.Name;
+ }
+
+ return this->ConfigureFromGroup(&group);
+}
+
+// Common options for components and groups
+int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
+{
+ // Temporary variable for full option name
+ std::string option;
+
+ // Display name
+ option = prefix + "DISPLAY_NAME";
+ if (this->IsSetToEmpty(option)) {
+ this->DisplayName.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->ExpandListArgument(value, this->DisplayName);
+ }
+
+ // Description
+ option = prefix + "DESCRIPTION";
+ if (this->IsSetToEmpty(option)) {
+ this->Description.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->ExpandListArgument(value, this->Description);
+ }
+
+ // Release date
+ option = prefix + "RELEASE_DATE";
+ if (this->IsSetToEmpty(option)) {
+ this->ReleaseDate.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->ReleaseDate = value;
+ }
+
+ // Sorting priority
+ option = prefix + "SORTING_PRIORITY";
+ if (this->IsSetToEmpty(option)) {
+ this->SortingPriority.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->SortingPriority = value;
+ }
+
+ // Update text
+ option = prefix + "UPDATE_TEXT";
+ if (this->IsSetToEmpty(option)) {
+ this->UpdateText.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->UpdateText = value;
+ }
+
+ // Translations
+ option = prefix + "TRANSLATIONS";
+ if (this->IsSetToEmpty(option)) {
+ this->Translations.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->Translations.clear();
+ cmSystemTools::ExpandListArgument(value, this->Translations);
+ }
+
+ // QtIFW dependencies
+ std::vector<std::string> deps;
+ option = prefix + "DEPENDS";
+ if (const char* value = this->GetOption(option)) {
+ cmSystemTools::ExpandListArgument(value, deps);
+ }
+ option = prefix + "DEPENDENCIES";
+ if (const char* value = this->GetOption(option)) {
+ cmSystemTools::ExpandListArgument(value, deps);
+ }
+ for (std::vector<std::string>::iterator dit = deps.begin();
+ dit != deps.end(); ++dit) {
+ DependenceStruct dep(*dit);
+ if (this->Generator->Packages.count(dep.Name)) {
+ cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
+ dep.Name = depPkg.Name;
+ }
+ bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0;
+ DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name];
+ if (!hasDep) {
+ depRef = dep;
+ }
+ this->AlienDependencies.insert(&depRef);
+ }
+
+ // Automatic dependency on
+ option = prefix + "AUTO_DEPEND_ON";
+ 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);
+ if (this->Generator->Packages.count(dep.Name)) {
+ cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
+ dep.Name = depPkg.Name;
+ }
+ bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0;
+ DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name];
+ if (!hasDep) {
+ depRef = dep;
+ }
+ this->AlienAutoDependOn.insert(&depRef);
+ }
+ }
+
+ // Visibility
+ option = prefix + "VIRTUAL";
+ if (this->IsSetToEmpty(option)) {
+ this->Virtual.clear();
+ } else if (this->IsOn(option)) {
+ this->Virtual = "true";
+ }
+
+ // Default selection
+ option = prefix + "DEFAULT";
+ if (this->IsSetToEmpty(option)) {
+ this->Default.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ std::string lowerValue = cmsys::SystemTools::LowerCase(value);
+ if (lowerValue == "true") {
+ this->Default = "true";
+ } else if (lowerValue == "false") {
+ this->Default = "false";
+ } else if (lowerValue == "script") {
+ this->Default = "script";
+ } else {
+ this->Default = value;
+ }
+ }
+
+ // Forsed installation
+ option = prefix + "FORCED_INSTALLATION";
+ if (this->IsSetToEmpty(option)) {
+ this->ForcedInstallation.clear();
+ } else if (this->IsOn(option)) {
+ this->ForcedInstallation = "true";
+ } else if (this->IsSetToOff(option)) {
+ this->ForcedInstallation = "false";
+ }
+
+ // Requires admin rights
+ option = prefix + "REQUIRES_ADMIN_RIGHTS";
+ if (this->IsSetToEmpty(option)) {
+ this->RequiresAdminRights.clear();
+ } else if (this->IsOn(option)) {
+ this->RequiresAdminRights = "true";
+ } else if (this->IsSetToOff(option)) {
+ this->RequiresAdminRights = "false";
+ }
+
+ return 1;
+}
+
+void cmCPackIFWPackage::GeneratePackageFile()
+{
+ // Lazy directory initialization
+ if (this->Directory.empty()) {
+ if (this->Installer) {
+ this->Directory = this->Installer->Directory + "/packages/" + this->Name;
+ } else if (this->Generator) {
+ this->Directory = this->Generator->toplevel + "/packages/" + this->Name;
+ }
+ }
+
+ // Output stream
+ cmGeneratedFileStream fout((this->Directory + "/meta/package.xml").data());
+ cmXMLWriter xout(fout);
+
+ xout.StartDocument();
+
+ WriteGeneratedByToStrim(xout);
+
+ xout.StartElement("Package");
+
+ // DisplayName (with translations)
+ for (std::map<std::string, std::string>::iterator it =
+ this->DisplayName.begin();
+ it != this->DisplayName.end(); ++it) {
+ xout.StartElement("DisplayName");
+ if (!it->first.empty()) {
+ xout.Attribute("xml:lang", it->first);
+ }
+ xout.Content(it->second);
+ xout.EndElement();
+ }
+
+ // Description (with translations)
+ for (std::map<std::string, std::string>::iterator it =
+ this->Description.begin();
+ it != this->Description.end(); ++it) {
+ xout.StartElement("Description");
+ if (!it->first.empty()) {
+ xout.Attribute("xml:lang", it->first);
+ }
+ xout.Content(it->second);
+ xout.EndElement();
+ }
+
+ // Update text
+ if (!this->UpdateText.empty()) {
+ xout.Element("UpdateText", this->UpdateText);
+ }
+
+ xout.Element("Name", this->Name);
+ xout.Element("Version", this->Version);
+
+ if (!this->ReleaseDate.empty()) {
+ xout.Element("ReleaseDate", this->ReleaseDate);
+ } else {
+ xout.Element("ReleaseDate", cmTimestamp().CurrentTime("%Y-%m-%d", true));
+ }
+
+ // Script (copy to meta dir)
+ if (!this->Script.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->Script);
+ std::string path = this->Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->Script, path);
+ xout.Element("Script", name);
+ }
+
+ // 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]);
+ std::string path = this->Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i], path);
+ userInterfaces[i] = name;
+ }
+ if (!userInterfaces.empty()) {
+ xout.StartElement("UserInterfaces");
+ for (size_t i = 0; i < userInterfaces.size(); i++) {
+ xout.Element("UserInterface", userInterfaces[i]);
+ }
+ 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]);
+ std::string path = this->Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(translations[i], path);
+ translations[i] = name;
+ }
+ if (!translations.empty()) {
+ xout.StartElement("Translations");
+ for (size_t i = 0; i < translations.size(); i++) {
+ xout.Element("Translation", translations[i]);
+ }
+ 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 (std::set<cmCPackIFWPackage*>::iterator it = this->Dependencies.begin();
+ it != this->Dependencies.end(); ++it) {
+ compDepSet.insert(DependenceStruct((*it)->Name));
+ }
+ // Write dependencies
+ if (!compDepSet.empty()) {
+ std::ostringstream dependencies;
+ std::set<DependenceStruct>::iterator it = compDepSet.begin();
+ dependencies << it->NameWithCompare();
+ ++it;
+ while (it != compDepSet.end()) {
+ dependencies << "," << it->NameWithCompare();
+ ++it;
+ }
+ xout.Element("Dependencies", dependencies.str());
+ }
+
+ // Automatic dependency on
+ std::set<DependenceStruct> compAutoDepSet;
+ for (std::set<DependenceStruct*>::iterator ait =
+ this->AlienAutoDependOn.begin();
+ ait != this->AlienAutoDependOn.end(); ++ait) {
+ compAutoDepSet.insert(*(*ait));
+ }
+ // Write automatic dependency on
+ if (!compAutoDepSet.empty()) {
+ std::ostringstream dependencies;
+ std::set<DependenceStruct>::iterator it = compAutoDepSet.begin();
+ dependencies << it->NameWithCompare();
+ ++it;
+ while (it != compAutoDepSet.end()) {
+ dependencies << "," << it->NameWithCompare();
+ ++it;
+ }
+ xout.Element("AutoDependOn", dependencies.str());
+ }
+
+ // Licenses (copy to meta dir)
+ std::vector<std::string> licenses = this->Licenses;
+ for (size_t i = 1; i < licenses.size(); i += 2) {
+ std::string name = cmSystemTools::GetFilenameName(licenses[i]);
+ std::string path = this->Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(licenses[i], path);
+ licenses[i] = name;
+ }
+ if (!licenses.empty()) {
+ xout.StartElement("Licenses");
+ for (size_t i = 0; i < licenses.size(); i += 2) {
+ xout.StartElement("License");
+ xout.Attribute("name", licenses[i]);
+ xout.Attribute("file", licenses[i + 1]);
+ xout.EndElement();
+ }
+ xout.EndElement();
+ }
+
+ if (!this->ForcedInstallation.empty()) {
+ xout.Element("ForcedInstallation", this->ForcedInstallation);
+ }
+
+ if (!this->RequiresAdminRights.empty()) {
+ xout.Element("RequiresAdminRights", this->RequiresAdminRights);
+ }
+
+ if (!this->Virtual.empty()) {
+ xout.Element("Virtual", this->Virtual);
+ } else if (!this->Default.empty()) {
+ xout.Element("Default", this->Default);
+ }
+
+ // Essential
+ if (!this->Essential.empty()) {
+ xout.Element("Essential", this->Essential);
+ }
+
+ // Priority
+ if (!this->SortingPriority.empty()) {
+ xout.Element("SortingPriority", this->SortingPriority);
+ }
+
+ xout.EndElement();
+ xout.EndDocument();
+}
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
new file mode 100644
index 000000000..cec59b03c
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -0,0 +1,147 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWPackage_h
+#define cmCPackIFWPackage_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCPackIFWCommon.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmCPackComponent;
+class cmCPackComponentGroup;
+class cmCPackIFWInstaller;
+
+/** \class cmCPackIFWPackage
+ * \brief A single component to be installed by CPack IFW generator
+ */
+class cmCPackIFWPackage : public cmCPackIFWCommon
+{
+public:
+ // Types
+
+ enum CompareTypes
+ {
+ CompareNone = 0x0,
+ CompareEqual = 0x1,
+ CompareLess = 0x2,
+ CompareLessOrEqual = 0x3,
+ CompareGreater = 0x4,
+ CompareGreaterOrEqual = 0x5
+ };
+
+ struct CompareStruct
+ {
+ CompareStruct();
+
+ unsigned int Type;
+ std::string Value;
+ };
+
+ struct DependenceStruct
+ {
+ DependenceStruct();
+ DependenceStruct(const std::string& dependence);
+
+ std::string Name;
+ CompareStruct Compare;
+
+ std::string NameWithCompare() const;
+
+ bool operator<(const DependenceStruct& other) const
+ {
+ return Name < other.Name;
+ }
+ };
+
+public:
+ // [Con|De]structor
+
+ /**
+ * Construct package
+ */
+ cmCPackIFWPackage();
+
+public:
+ // Configuration
+
+ /// Human-readable name of the component
+ std::map<std::string, std::string> DisplayName;
+
+ /// Human-readable description of the component
+ std::map<std::string, std::string> Description;
+
+ /// Version number of the component
+ std::string Version;
+
+ /// Date when this component version was released
+ std::string ReleaseDate;
+
+ /// Domain-like identification for this component
+ std::string Name;
+
+ /// File name of a script being loaded
+ std::string Script;
+
+ /// List of license agreements to be accepted by the installing user
+ std::vector<std::string> Licenses;
+
+ /// List of pages to load
+ std::vector<std::string> UserInterfaces;
+
+ /// List of translation files to load
+ std::vector<std::string> Translations;
+
+ /// Priority of the component in the tree
+ std::string SortingPriority;
+
+ /// Description added to the component description
+ std::string UpdateText;
+
+ /// Set to true to preselect the component in the installer
+ std::string Default;
+
+ /// Marks the package as essential to force a restart of the MaintenanceTool
+ std::string Essential;
+
+ /// Set to true to hide the component from the installer
+ std::string Virtual;
+
+ /// Determines that the package must always be installed
+ std::string ForcedInstallation;
+
+ /// Package needs to be installed with elevated permissions
+ std::string RequiresAdminRights;
+
+public:
+ // Internal implementation
+
+ std::string GetComponentName(cmCPackComponent* component);
+
+ void DefaultConfiguration();
+
+ int ConfigureFromOptions();
+ int ConfigureFromComponent(cmCPackComponent* component);
+ int ConfigureFromGroup(cmCPackComponentGroup* group);
+ int ConfigureFromGroup(const std::string& groupName);
+ int ConfigureFromPrefix(const std::string& prefix);
+
+ void GeneratePackageFile();
+
+ // Pointer to installer
+ cmCPackIFWInstaller* Installer;
+ // Collection of dependencies
+ std::set<cmCPackIFWPackage*> Dependencies;
+ // Collection of unresolved dependencies
+ std::set<DependenceStruct*> AlienDependencies;
+ // Collection of unresolved automatic dependency on
+ std::set<DependenceStruct*> AlienAutoDependOn;
+ // Patch to package directory
+ std::string Directory;
+};
+
+#endif // cmCPackIFWPackage_h
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx
new file mode 100644
index 000000000..b115db057
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -0,0 +1,288 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWRepository.h"
+
+#include "cmCPackIFWGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmXMLWriter.h"
+
+#include <stddef.h>
+
+cmCPackIFWRepository::cmCPackIFWRepository()
+ : Update(cmCPackIFWRepository::None)
+{
+}
+
+bool cmCPackIFWRepository::IsValid() const
+{
+ bool valid = true;
+
+ switch (this->Update) {
+ case cmCPackIFWRepository::None:
+ valid = !this->Url.empty();
+ break;
+ case cmCPackIFWRepository::Add:
+ valid = !this->Url.empty();
+ break;
+ case cmCPackIFWRepository::Remove:
+ valid = !this->Url.empty();
+ break;
+ case cmCPackIFWRepository::Replace:
+ valid = !this->OldUrl.empty() && !this->NewUrl.empty();
+ break;
+ }
+
+ return valid;
+}
+
+bool cmCPackIFWRepository::ConfigureFromOptions()
+{
+ // Name;
+ if (this->Name.empty()) {
+ return false;
+ }
+
+ std::string prefix =
+ "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(this->Name) + "_";
+
+ // Update
+ if (this->IsOn(prefix + "ADD")) {
+ this->Update = cmCPackIFWRepository::Add;
+ } else if (IsOn(prefix + "REMOVE")) {
+ this->Update = cmCPackIFWRepository::Remove;
+ } else if (IsOn(prefix + "REPLACE")) {
+ this->Update = cmCPackIFWRepository::Replace;
+ } else {
+ this->Update = cmCPackIFWRepository::None;
+ }
+
+ // Url
+ if (const char* url = this->GetOption(prefix + "URL")) {
+ this->Url = url;
+ } else {
+ this->Url = "";
+ }
+
+ // Old url
+ if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) {
+ this->OldUrl = oldUrl;
+ } else {
+ this->OldUrl = "";
+ }
+
+ // New url
+ if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) {
+ this->NewUrl = newUrl;
+ } else {
+ this->NewUrl = "";
+ }
+
+ // Enabled
+ if (this->IsOn(prefix + "DISABLED")) {
+ this->Enabled = "0";
+ } else {
+ this->Enabled = "";
+ }
+
+ // Username
+ if (const char* username = this->GetOption(prefix + "USERNAME")) {
+ this->Username = username;
+ } else {
+ this->Username = "";
+ }
+
+ // Password
+ if (const char* password = this->GetOption(prefix + "PASSWORD")) {
+ this->Password = password;
+ } else {
+ this->Password = "";
+ }
+
+ // DisplayName
+ if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) {
+ this->DisplayName = displayName;
+ } else {
+ this->DisplayName = "";
+ }
+
+ return this->IsValid();
+}
+
+/** \class cmCPackeIFWUpdatesPatcher
+ * \brief Helper class that parses and patch Updates.xml file (QtIFW)
+ */
+class cmCPackeIFWUpdatesPatcher : public cmXMLParser
+{
+public:
+ cmCPackeIFWUpdatesPatcher(cmCPackIFWRepository* r, cmXMLWriter& x)
+ : repository(r)
+ , xout(x)
+ , patched(false)
+ {
+ }
+
+ cmCPackIFWRepository* repository;
+ cmXMLWriter& xout;
+ bool patched;
+
+protected:
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
+ this->xout.StartElement(name);
+ this->StartFragment(atts);
+ }
+
+ void StartFragment(const char** atts)
+ {
+ for (size_t i = 0; atts[i]; i += 2) {
+ const char* key = atts[i];
+ const char* value = atts[i + 1];
+ this->xout.Attribute(key, value);
+ }
+ }
+
+ void EndElement(const std::string& name) CM_OVERRIDE
+ {
+ if (name == "Updates" && !this->patched) {
+ this->repository->WriteRepositoryUpdates(this->xout);
+ this->patched = true;
+ }
+ this->xout.EndElement();
+ if (this->patched) {
+ return;
+ }
+ if (name == "Checksum") {
+ this->repository->WriteRepositoryUpdates(this->xout);
+ this->patched = true;
+ }
+ }
+
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ std::string content(data, data + length);
+ if (content == "" || content == " " || content == " " ||
+ content == "\n") {
+ return;
+ }
+ this->xout.Content(content);
+ }
+};
+
+bool cmCPackIFWRepository::PatchUpdatesXml()
+{
+ // Lazy directory initialization
+ if (this->Directory.empty() && this->Generator) {
+ this->Directory = this->Generator->toplevel;
+ }
+
+ // Filenames
+ std::string updatesXml = this->Directory + "/repository/Updates.xml";
+ std::string updatesPatchXml =
+ this->Directory + "/repository/UpdatesPatch.xml";
+
+ // Output stream
+ cmGeneratedFileStream fout(updatesPatchXml.data());
+ cmXMLWriter xout(fout);
+
+ xout.StartDocument();
+
+ this->WriteGeneratedByToStrim(xout);
+
+ // Patch
+ {
+ cmCPackeIFWUpdatesPatcher patcher(this, xout);
+ patcher.ParseFile(updatesXml.data());
+ }
+
+ xout.EndDocument();
+
+ fout.Close();
+
+ return cmSystemTools::RenameFile(updatesPatchXml.data(), updatesXml.data());
+}
+
+void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout)
+{
+ xout.StartElement("Repository");
+
+ // Url
+ xout.Element("Url", this->Url);
+ // Enabled
+ if (!this->Enabled.empty()) {
+ xout.Element("Enabled", this->Enabled);
+ }
+ // Username
+ if (!this->Username.empty()) {
+ xout.Element("Username", this->Username);
+ }
+ // Password
+ if (!this->Password.empty()) {
+ xout.Element("Password", this->Password);
+ }
+ // DisplayName
+ if (!this->DisplayName.empty()) {
+ xout.Element("DisplayName", this->DisplayName);
+ }
+
+ xout.EndElement();
+}
+
+void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout)
+{
+ xout.StartElement("Repository");
+
+ switch (this->Update) {
+ case cmCPackIFWRepository::None:
+ break;
+ case cmCPackIFWRepository::Add:
+ xout.Attribute("action", "add");
+ break;
+ case cmCPackIFWRepository::Remove:
+ xout.Attribute("action", "remove");
+ break;
+ case cmCPackIFWRepository::Replace:
+ xout.Attribute("action", "replace");
+ break;
+ }
+
+ // Url
+ if (this->Update == cmCPackIFWRepository::Add ||
+ this->Update == cmCPackIFWRepository::Remove) {
+ xout.Attribute("url", this->Url);
+ } else if (Update == cmCPackIFWRepository::Replace) {
+ xout.Attribute("oldUrl", this->OldUrl);
+ xout.Attribute("newUrl", this->NewUrl);
+ }
+ // Enabled
+ if (!this->Enabled.empty()) {
+ xout.Attribute("enabled", this->Enabled);
+ }
+ // Username
+ if (!this->Username.empty()) {
+ xout.Attribute("username", this->Username);
+ }
+ // Password
+ if (!this->Password.empty()) {
+ xout.Attribute("password", this->Password);
+ }
+ // DisplayName
+ if (!this->DisplayName.empty()) {
+ xout.Attribute("displayname", this->DisplayName);
+ }
+
+ xout.EndElement();
+}
+
+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);
+ }
+ xout.EndElement();
+ }
+}
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h
new file mode 100644
index 000000000..227cfae7a
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWRepository.h
@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWRepository_h
+#define cmCPackIFWRepository_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCPackIFWCommon.h"
+
+#include <string>
+#include <vector>
+
+class cmXMLWriter;
+
+/** \class cmCPackIFWRepository
+ * \brief A remote repository to be created CPack IFW generator
+ */
+class cmCPackIFWRepository : public cmCPackIFWCommon
+{
+public:
+ // Types
+
+ enum Action
+ {
+ None,
+ Add,
+ Remove,
+ Replace
+ };
+
+ typedef std::vector<cmCPackIFWRepository*> RepositoriesVector;
+
+public:
+ // Constructor
+
+ /**
+ * Construct repository
+ */
+ cmCPackIFWRepository();
+
+public:
+ // Configuration
+
+ /// Internal repository name
+ std::string Name;
+
+ /// Optional update action
+ Action Update;
+
+ /// Is points to a list of available components
+ std::string Url;
+
+ /// Is points to a list that will replaced
+ std::string OldUrl;
+
+ /// Is points to a list that will replace to
+ std::string NewUrl;
+
+ /// With "0" disabling this repository
+ std::string Enabled;
+
+ /// Is used as user on a protected repository
+ std::string Username;
+
+ /// Is password to use on a protected repository
+ std::string Password;
+
+ /// Is optional string to display instead of the URL
+ std::string DisplayName;
+
+public:
+ // Internal implementation
+
+ bool IsValid() const;
+
+ bool ConfigureFromOptions();
+
+ bool PatchUpdatesXml();
+
+ void WriteRepositoryConfig(cmXMLWriter& xout);
+ void WriteRepositoryUpdate(cmXMLWriter& xout);
+ void WriteRepositoryUpdates(cmXMLWriter& xout);
+
+ RepositoriesVector RepositoryUpdate;
+ std::string Directory;
+};
+
+#endif // cmCPackIFWRepository_h
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
index a9842c1df..b48bf1214 100644
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ b/Source/CPack/OSXScriptLauncher.cxx
@@ -1,90 +1,76 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/ios/fstream>
-#include <cmsys/ios/iostream>
+/* 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 <iostream>
+#include <stddef.h>
+#include <string>
+#include <vector>
#include <CoreFoundation/CoreFoundation.h>
// For the PATH_MAX constant
#include <sys/syslimits.h>
-#define DebugError(x) \
- ofs << x << cmsys_ios::endl; \
- cmsys_ios::cout << x << cmsys_ios::endl
+#define DebugError(x) \
+ ofs << x << std::endl; \
+ std::cout << x << std::endl
int main(int argc, char* argv[])
{
- //if ( cmsys::SystemTools::FileExists(
- cmsys_stl::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory();
- cmsys_ios::ofstream ofs("/tmp/output.txt");
+ // if ( cmsys::SystemTools::FileExists(
+ cmsys::ofstream ofs("/tmp/output.txt");
CFStringRef fileName;
CFBundleRef appBundle;
CFURLRef scriptFileURL;
- UInt8 *path;
+ UInt8* path;
- //get CF URL for script
- if (! (appBundle = CFBundleGetMainBundle()))
- {
+ // get CF URL for script
+ if (!(appBundle = CFBundleGetMainBundle())) {
DebugError("Cannot get main bundle");
return 1;
- }
+ }
fileName = CFSTR("RuntimeScript");
- if (! (scriptFileURL = CFBundleCopyResourceURL(appBundle, fileName, NULL,
- NULL)))
- {
+ if (!(scriptFileURL =
+ CFBundleCopyResourceURL(appBundle, fileName, NULL, NULL))) {
DebugError("CFBundleCopyResourceURL failed");
return 1;
- }
+ }
- //create path string
- if (! (path = new UInt8[PATH_MAX]))
- {
+ // create path string
+ if (!(path = new UInt8[PATH_MAX])) {
return 1;
- }
+ }
- //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)
- {
+ // 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) {
DebugError("CFURLGetFileSystemRepresentation failed");
return 1;
- }
+ }
- //dispose of the CF variable
+ // dispose of the CF variable
CFRelease(scriptFileURL);
- cmsys_stl::string fullScriptPath = reinterpret_cast<char*>(path);
- delete [] path;
-
+ std::string fullScriptPath = reinterpret_cast<char*>(path);
+ delete[] path;
- if (! cmsys::SystemTools::FileExists(fullScriptPath.c_str()))
- {
+ if (!cmsys::SystemTools::FileExists(fullScriptPath.c_str())) {
return 1;
- }
+ }
- cmsys_stl::string scriptDirectory = cmsys::SystemTools::GetFilenamePath(
- fullScriptPath);
- ofs << fullScriptPath.c_str() << cmsys_ios::endl;
- cmsys_stl::vector<const char*> args;
+ std::string scriptDirectory =
+ cmsys::SystemTools::GetFilenamePath(fullScriptPath);
+ ofs << fullScriptPath << std::endl;
+ std::vector<const char*> args;
args.push_back(fullScriptPath.c_str());
int cc;
- for ( cc = 1; cc < argc; ++ cc )
- {
+ for (cc = 1; cc < argc; ++cc) {
args.push_back(argv[cc]);
- }
+ }
args.push_back(0);
cmsysProcess* cp = cmsysProcess_New();
@@ -97,49 +83,36 @@ 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, 0)) {
// Translate NULL characters in the output into valid text.
- // Visual Studio 7 puts these characters in the output of its
- // build process.
- for(int i=0; i < length; ++i)
- {
- if(data[i] == '\0')
- {
+ for (int i = 0; i < length; ++i) {
+ if (data[i] == '\0') {
data[i] = ' ';
- }
}
- cmsys_ios::cout.write(data, length);
}
+ std::cout.write(data, length);
+ }
cmsysProcess_WaitForExit(cp, 0);
bool result = true;
- if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
- {
- if ( cmsysProcess_GetExitValue(cp) != 0 )
- {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
+ if (cmsysProcess_GetExitValue(cp) != 0) {
result = false;
- }
}
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) {
const char* exception_str = cmsysProcess_GetExceptionString(cp);
std::cerr << exception_str << std::endl;
result = false;
- }
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
const char* error_str = cmsysProcess_GetErrorString(cp);
std::cerr << error_str << std::endl;
result = false;
- }
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
const char* error_str = "Process terminated due to timeout\n";
std::cerr << error_str << std::endl;
result = false;
- }
+ }
cmsysProcess_Delete(cp);
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index cc9dec7b8..274dfd0ce 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -1,110 +1,130 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackWIXGenerator.h"
-#include <cmSystemTools.h>
-#include <cmGeneratedFileStream.h>
-#include <CPack/cmCPackLog.h>
-#include <CPack/cmCPackComponentGroup.h>
-
-#include "cmWIXSourceWriter.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmCryptoHash.h"
+#include "cmGeneratedFileStream.h"
+#include "cmInstalledFile.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/SystemTools.hxx>
-#include <cmsys/Directory.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/SystemTools.hxx"
#include <rpc.h> // for GUID generation
+cmCPackWIXGenerator::cmCPackWIXGenerator()
+ : Patch(0)
+ , ComponentGuidType(cmWIXSourceWriter::WIX_GENERATED_GUID)
+{
+}
+
+cmCPackWIXGenerator::~cmCPackWIXGenerator()
+{
+ if (this->Patch) {
+ delete this->Patch;
+ }
+}
+
int cmCPackWIXGenerator::InitializeInternal()
{
componentPackageMethod = ONE_PACKAGE;
+ this->Patch = new cmWIXPatch(this->Logger);
return this->Superclass::InitializeInternal();
}
-bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command)
+bool cmCPackWIXGenerator::RunWiXCommand(std::string const& command)
{
- std::string cpackTopLevel;
- if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
- {
- return false;
- }
+ std::string logFileName = this->CPackTopLevel + "/wix.log";
- std::string logFileName = 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,
- &returnValue, 0, cmSystemTools::OUTPUT_NONE);
+ &output, &returnValue, 0,
+ cmSystemTools::OUTPUT_NONE);
- std::ofstream logFile(logFileName.c_str(), std::ios::app);
+ cmsys::ofstream logFile(logFileName.c_str(), std::ios::app);
logFile << command << std::endl;
logFile << output;
logFile.close();
- if(!status || returnValue)
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem running WiX candle. "
- "Please check '" << logFileName << "' for errors." << std::endl);
+ if (!status || returnValue) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running WiX candle. "
+ "Please check '"
+ << logFileName << "' for errors." << std::endl);
return false;
- }
+ }
return true;
}
-bool cmCPackWIXGenerator::RunCandleCommand(
- const std::string& sourceFile, const std::string& objectFile)
+bool cmCPackWIXGenerator::RunCandleCommand(std::string const& sourceFile,
+ std::string const& objectFile)
{
std::string executable;
- if(!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable))
- {
+ if (!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable)) {
return false;
- }
+ }
- std::stringstream command;
+ std::ostringstream command;
command << QuotePath(executable);
command << " -nologo";
command << " -arch " << GetArchitecture();
command << " -out " << QuotePath(objectFile);
+
+ for (extension_set_t::const_iterator i = CandleExtensions.begin();
+ i != CandleExtensions.end(); ++i) {
+ command << " -ext " << QuotePath(*i);
+ }
+
+ AddCustomFlags("CPACK_WIX_CANDLE_EXTRA_FLAGS", command);
+
command << " " << QuotePath(sourceFile);
return RunWiXCommand(command.str());
}
-bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles)
+bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
{
std::string executable;
- if(!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable))
- {
+ if (!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable)) {
return false;
- }
+ }
- std::stringstream command;
+ std::ostringstream command;
command << QuotePath(executable);
command << " -nologo";
command << " -out " << QuotePath(packageFileNames.at(0));
- command << " -ext WixUIExtension";
+
+ for (extension_set_t::const_iterator i = this->LightExtensions.begin();
+ i != this->LightExtensions.end(); ++i) {
+ command << " -ext " << QuotePath(*i);
+ }
+
const char* const cultures = GetOption("CPACK_WIX_CULTURES");
- if(cultures)
- {
+ if (cultures) {
command << " -cultures:" << cultures;
- }
+ }
+
+ AddCustomFlags("CPACK_WIX_LIGHT_EXTRA_FLAGS", command);
+
command << " " << objectFiles;
return RunWiXCommand(command.str());
@@ -112,114 +132,193 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles)
int cmCPackWIXGenerator::PackageFiles()
{
- if(!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag())
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Fatal WiX Generator Error" << std::endl);
+ if (!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Fatal WiX Generator Error"
+ << std::endl);
return false;
- }
+ }
return true;
}
bool cmCPackWIXGenerator::InitializeWiXConfiguration()
{
- if(!ReadListFile("CPackWIX.cmake"))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error while executing CPackWIX.cmake" << std::endl);
+ if (!ReadListFile("CPackWIX.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while executing CPackWIX.cmake"
+ << std::endl);
return false;
- }
+ }
- if(GetOption("CPACK_WIX_PRODUCT_GUID") == 0)
- {
+ if (GetOption("CPACK_WIX_PRODUCT_GUID") == 0) {
std::string guid = GenerateGUID();
SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str());
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "CPACK_WIX_PRODUCT_GUID implicitly set to " << guid << " . "
- << std::endl);
- }
+ "CPACK_WIX_PRODUCT_GUID implicitly set to " << guid << " . "
+ << std::endl);
+ }
- if(GetOption("CPACK_WIX_UPGRADE_GUID") == 0)
- {
+ if (GetOption("CPACK_WIX_UPGRADE_GUID") == 0) {
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);
+ }
- std::string cpackTopLevel;
- if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
- {
+ if (!RequireOption("CPACK_TOPLEVEL_DIRECTORY", this->CPackTopLevel)) {
return false;
- }
+ }
- if(GetOption("CPACK_WIX_LICENSE_RTF") == 0)
- {
- std::string licenseFilename = cpackTopLevel + "/License.rtf";
+ if (GetOption("CPACK_WIX_LICENSE_RTF") == 0) {
+ std::string licenseFilename = this->CPackTopLevel + "/License.rtf";
SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str());
- if(!CreateLicenseFile())
- {
+ if (!CreateLicenseFile()) {
return false;
+ }
+ }
+
+ if (GetOption("CPACK_PACKAGE_VENDOR") == 0) {
+ std::string defaultVendor = "Humanity";
+ SetOption("CPACK_PACKAGE_VENDOR", defaultVendor.c_str());
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "CPACK_PACKAGE_VENDOR implicitly set to "
+ << defaultVendor << " . " << std::endl);
+ }
+
+ if (GetOption("CPACK_WIX_UI_REF") == 0) {
+ std::string defaultRef = "WixUI_InstallDir";
+
+ if (!this->Components.empty()) {
+ defaultRef = "WixUI_FeatureTree";
+ }
+
+ SetOption("CPACK_WIX_UI_REF", defaultRef.c_str());
+ }
+
+ const char* packageContact = GetOption("CPACK_PACKAGE_CONTACT");
+ if (packageContact != 0 && GetOption("CPACK_WIX_PROPERTY_ARPCONTACT") == 0) {
+ SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact);
+ }
+
+ CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions);
+ CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", this->CandleExtensions);
+
+ this->LightExtensions.insert("WixUIExtension");
+ CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions);
+ CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions);
+
+ const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
+ if (patchFilePath) {
+ std::vector<std::string> patchFilePaths;
+ cmSystemTools::ExpandListArgument(patchFilePath, patchFilePaths);
+
+ for (size_t i = 0; i < patchFilePaths.size(); ++i) {
+ if (!this->Patch->LoadFragments(patchFilePaths[i])) {
+ return false;
}
}
+ }
+
+ // 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"))) {
+ this->ComponentGuidType = cmWIXSourceWriter::CMAKE_GENERATED_GUID;
+ }
return true;
}
bool cmCPackWIXGenerator::PackageFilesImpl()
{
- if(!InitializeWiXConfiguration())
- {
+ if (!InitializeWiXConfiguration()) {
return false;
- }
+ }
- if(!CreateWiXVariablesIncludeFile())
- {
- return false;
- }
+ CreateWiXVariablesIncludeFile();
+ CreateWiXPropertiesIncludeFile();
+ CreateWiXProductFragmentIncludeFile();
- if(!CreateWiXSourceFiles())
- {
+ if (!CreateWiXSourceFiles()) {
return false;
+ }
+
+ AppendUserSuppliedExtraSources();
+
+ 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];
+
+ std::string baseName =
+ cmSystemTools::GetFilenameWithoutLastExtension(sourceFilename);
+
+ unsigned int counter = 0;
+ std::string uniqueBaseName = baseName;
+
+ while (usedBaseNames.find(uniqueBaseName) != usedBaseNames.end()) {
+ std::ostringstream tmp;
+ tmp << baseName << ++counter;
+ uniqueBaseName = tmp.str();
}
- std::stringstream objectFiles;
- for(size_t i = 0; i < wixSources.size(); ++i)
- {
- const std::string& sourceFilename = wixSources[i];
+ usedBaseNames.insert(uniqueBaseName);
std::string objectFilename =
- cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj";
+ this->CPackTopLevel + "/" + uniqueBaseName + ".wixobj";
- if(!RunCandleCommand(sourceFilename, objectFilename))
- {
+ if (!RunCandleCommand(sourceFilename, objectFilename)) {
return false;
- }
+ }
objectFiles << " " << QuotePath(objectFilename);
- }
+ }
+
+ AppendUserSuppliedExtraObjects(objectFiles);
return RunLightCommand(objectFiles.str());
}
-bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
+void cmCPackWIXGenerator::AppendUserSuppliedExtraSources()
{
- std::string cpackTopLevel;
- if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
- {
- return false;
- }
+ const char* cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES");
+ if (!cpackWixExtraSources)
+ return;
- std::string includeFilename =
- cpackTopLevel + "/cpack_variables.wxi";
+ cmSystemTools::ExpandListArgument(cpackWixExtraSources, this->WixSources);
+}
+
+void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream)
+{
+ const char* cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS");
+ if (!cpackWixExtraObjects)
+ return;
+
+ std::vector<std::string> expandedExtraObjects;
+
+ cmSystemTools::ExpandListArgument(cpackWixExtraObjects,
+ expandedExtraObjects);
+
+ for (size_t i = 0; i < expandedExtraObjects.size(); ++i) {
+ stream << " " << QuotePath(expandedExtraObjects[i]);
+ }
+}
+
+void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
+{
+ std::string includeFilename = this->CPackTopLevel + "/cpack_variables.wxi";
+
+ cmWIXSourceWriter includeFile(this->Logger, includeFilename,
+ this->ComponentGuidType,
+ cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
- cmWIXSourceWriter includeFile(Logger, includeFilename, true);
CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID");
CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID");
CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR");
@@ -230,250 +329,476 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER",
- GetOption("CPACK_PACKAGE_NAME"));
+ GetOption("CPACK_PACKAGE_NAME"));
CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
+ CopyDefinition(includeFile, "CPACK_WIX_UI_REF");
+}
- return true;
+void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
+{
+ std::string includeFilename = this->CPackTopLevel + "/properties.wxi";
+
+ cmWIXSourceWriter includeFile(this->Logger, includeFilename,
+ this->ComponentGuidType,
+ cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
+
+ 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];
+
+ if (name.length() > prefix.length() &&
+ name.substr(0, prefix.length()) == prefix) {
+ std::string id = name.substr(prefix.length());
+ std::string value = GetOption(name.c_str());
+
+ includeFile.BeginElement("Property");
+ includeFile.AddAttribute("Id", id);
+ includeFile.AddAttribute("Value", value);
+ includeFile.EndElement("Property");
+ }
+ }
+
+ if (GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION") == 0) {
+ includeFile.BeginElement("Property");
+ includeFile.AddAttribute("Id", "INSTALL_ROOT");
+ includeFile.AddAttribute("Secure", "yes");
+
+ includeFile.BeginElement("RegistrySearch");
+ includeFile.AddAttribute("Id", "FindInstallLocation");
+ includeFile.AddAttribute("Root", "HKLM");
+ includeFile.AddAttribute(
+ "Key", "Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Uninstall\\[WIX_UPGRADE_DETECTED]");
+ includeFile.AddAttribute("Name", "InstallLocation");
+ includeFile.AddAttribute("Type", "raw");
+ includeFile.EndElement("RegistrySearch");
+ includeFile.EndElement("Property");
+
+ includeFile.BeginElement("SetProperty");
+ includeFile.AddAttribute("Id", "ARPINSTALLLOCATION");
+ includeFile.AddAttribute("Value", "[INSTALL_ROOT]");
+ includeFile.AddAttribute("After", "CostFinalize");
+ includeFile.EndElement("SetProperty");
+ }
}
-void cmCPackWIXGenerator::CopyDefinition(
- cmWIXSourceWriter &source, const std::string &name)
+void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile()
+{
+ std::string includeFilename = this->CPackTopLevel + "/product_fragment.wxi";
+
+ cmWIXSourceWriter includeFile(this->Logger, includeFilename,
+ this->ComponentGuidType,
+ cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
+
+ this->Patch->ApplyFragment("#PRODUCT", includeFile);
+}
+
+void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source,
+ std::string const& name)
{
const char* value = GetOption(name.c_str());
- if(value)
- {
+ if (value) {
AddDefinition(source, name, value);
- }
+ }
}
void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source,
- const std::string& name, const std::string& value)
+ std::string const& name,
+ std::string const& value)
{
- std::stringstream tmp;
+ std::ostringstream tmp;
tmp << name << "=\"" << value << '"';
- source.AddProcessingInstruction("define",
- cmWIXSourceWriter::WindowsCodepageToUtf8(tmp.str()));
+ source.AddProcessingInstruction("define", tmp.str());
}
bool cmCPackWIXGenerator::CreateWiXSourceFiles()
{
- std::string cpackTopLevel;
- if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
- {
- return false;
- }
-
+ // if install folder is supposed to be set absolutely, the default
+ // component guid "*" cannot be used
std::string directoryDefinitionsFilename =
- cpackTopLevel + "/directories.wxs";
+ this->CPackTopLevel + "/directories.wxs";
- wixSources.push_back(directoryDefinitionsFilename);
+ this->WixSources.push_back(directoryDefinitionsFilename);
- cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename);
+ cmWIXDirectoriesSourceWriter directoryDefinitions(
+ this->Logger, directoryDefinitionsFilename, this->ComponentGuidType);
directoryDefinitions.BeginElement("Fragment");
+ std::string installRoot;
+ if (!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", installRoot)) {
+ return false;
+ }
+
directoryDefinitions.BeginElement("Directory");
directoryDefinitions.AddAttribute("Id", "TARGETDIR");
directoryDefinitions.AddAttribute("Name", "SourceDir");
- directoryDefinitions.BeginElement("Directory");
- if(GetArchitecture() == "x86")
- {
- directoryDefinitions.AddAttribute("Id", "ProgramFilesFolder");
- }
- else
- {
- directoryDefinitions.AddAttribute("Id", "ProgramFiles64Folder");
- }
+ size_t installRootSize =
+ directoryDefinitions.BeginInstallationPrefixDirectory(GetRootFolderId(),
+ installRoot);
- std::vector<std::string> install_root;
+ std::string fileDefinitionsFilename = this->CPackTopLevel + "/files.wxs";
- std::string tmp;
- if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", tmp))
- {
- return false;
- }
+ this->WixSources.push_back(fileDefinitionsFilename);
- cmSystemTools::SplitPath(tmp.c_str(), install_root);
+ cmWIXFilesSourceWriter fileDefinitions(this->Logger, fileDefinitionsFilename,
+ this->ComponentGuidType);
- if(!install_root.empty() && install_root.back().empty())
- {
- install_root.pop_back();
- }
+ fileDefinitions.BeginElement("Fragment");
+
+ std::string featureDefinitionsFilename =
+ this->CPackTopLevel + "/features.wxs";
- for(size_t i = 1; i < install_root.size(); ++i)
- {
- directoryDefinitions.BeginElement("Directory");
+ this->WixSources.push_back(featureDefinitionsFilename);
- if(i == install_root.size() - 1)
- {
- directoryDefinitions.AddAttribute("Id", "INSTALL_ROOT");
- }
- else
- {
- std::stringstream ss;
- ss << "INSTALL_PREFIX_" << i;
- directoryDefinitions.AddAttribute("Id", ss.str());
- }
+ cmWIXFeaturesSourceWriter featureDefinitions(
+ this->Logger, featureDefinitionsFilename, this->ComponentGuidType);
+
+ featureDefinitions.BeginElement("Fragment");
+
+ featureDefinitions.BeginElement("Feature");
+ featureDefinitions.AddAttribute("Id", "ProductFeature");
+ featureDefinitions.AddAttribute("Display", "expand");
+ featureDefinitions.AddAttribute("Absent", "disallow");
+ featureDefinitions.AddAttribute("ConfigurableDirectory", "INSTALL_ROOT");
- directoryDefinitions.AddAttribute("Name", install_root[i]);
+ std::string cpackPackageName;
+ if (!RequireOption("CPACK_PACKAGE_NAME", cpackPackageName)) {
+ return false;
}
- size_t directoryCounter = 0;
- size_t fileCounter = 0;
+ std::string featureTitle = cpackPackageName;
+ if (const char* title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) {
+ featureTitle = title;
+ }
+ featureDefinitions.AddAttribute("Title", featureTitle);
+ if (const char* desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) {
+ featureDefinitions.AddAttribute("Description", desc);
+ }
+ featureDefinitions.AddAttribute("Level", "1");
+ this->Patch->ApplyFragment("#PRODUCTFEATURE", featureDefinitions);
- std::string fileDefinitionsFilename =
- cpackTopLevel + "/files.wxs";
+ const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY");
+ if (package) {
+ featureDefinitions.CreateCMakePackageRegistryEntry(
+ package, GetOption("CPACK_WIX_UPGRADE_GUID"));
+ }
- wixSources.push_back(fileDefinitionsFilename);
+ if (!CreateFeatureHierarchy(featureDefinitions)) {
+ return false;
+ }
- cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename);
- fileDefinitions.BeginElement("Fragment");
+ featureDefinitions.EndElement("Feature");
- std::string featureDefinitionsFilename =
- cpackTopLevel +"/features.wxs";
+ std::set<cmWIXShortcuts::Type> emittedShortcutTypes;
- wixSources.push_back(featureDefinitionsFilename);
+ cmWIXShortcuts globalShortcuts;
+ if (Components.empty()) {
+ AddComponentsToFeature(toplevel, "ProductFeature", directoryDefinitions,
+ fileDefinitions, featureDefinitions,
+ globalShortcuts);
- cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename);
- featureDefinitions.BeginElement("Fragment");
+ 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;
- featureDefinitions.BeginElement("Feature");
- featureDefinitions.AddAttribute("Id", "ProductFeature");
- featureDefinitions.AddAttribute("Title", Name);
- featureDefinitions.AddAttribute("Level", "1");
- featureDefinitions.EndElement();
+ std::string componentPath = toplevel;
+ componentPath += "/";
+ componentPath += component.Name;
- featureDefinitions.BeginElement("FeatureRef");
- featureDefinitions.AddAttribute("Id", "ProductFeature");
+ std::string componentFeatureId = "CM_C_" + component.Name;
- const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
- std::vector<std::string> cpackPkgExecutables;
- std::string regKey;
- if ( cpackPackageExecutables )
- {
- cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPkgExecutables);
- if ( cpackPkgExecutables.size() % 2 != 0 )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
- "<icon name>." << std::endl);
- cpackPkgExecutables.clear();
- }
+ cmWIXShortcuts featureShortcuts;
+ AddComponentsToFeature(componentPath, componentFeatureId,
+ directoryDefinitions, fileDefinitions,
+ featureDefinitions, featureShortcuts);
- const char *cpackVendor = GetOption("CPACK_PACKAGE_VENDOR");
- const char *cpackPkgName = GetOption("CPACK_PACKAGE_NAME");
- if (!cpackVendor || !cpackPkgName)
- {
- cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_PACKAGE_VENDOR and "
- "CPACK_PACKAGE_NAME must be defined for shortcut creation" << std::endl);
- cpackPkgExecutables.clear();
- }
- else
- {
- regKey = std::string("Software/") + cpackVendor + "/" + cpackPkgName;
+ featureShortcuts.AddShortcutTypes(emittedShortcutTypes);
+
+ if (!CreateShortcuts(component.Name, componentFeatureId,
+ featureShortcuts, false, fileDefinitions,
+ featureDefinitions)) {
+ return false;
}
}
+ }
- std::vector<std::string> dirIdExecutables;
- AddDirectoryAndFileDefinitons(
- toplevel, "INSTALL_ROOT",
- directoryDefinitions, fileDefinitions, featureDefinitions,
- directoryCounter, fileCounter, cpackPkgExecutables, dirIdExecutables);
-
- directoryDefinitions.EndElement();
- directoryDefinitions.EndElement();
-
- if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0)
- {
- fileDefinitions.BeginElement("DirectoryRef");
- fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
- fileDefinitions.BeginElement("Component");
- fileDefinitions.AddAttribute("Id", "SHORTCUT");
- fileDefinitions.AddAttribute("Guid", "*");
-
- std::vector<std::string>::iterator it;
- for ( it = dirIdExecutables.begin() ;
- it != dirIdExecutables.end();
- ++it)
- {
- std::string fileName = *it++;
- std::string iconName = *it++;
- std::string directoryId = *it;
-
- fileDefinitions.BeginElement("Shortcut");
- std::string shortcutName = fileName; // the iconName is mor likely to contain blanks early on
- std::string::size_type const dotPos = shortcutName.find('.');
- if(std::string::npos == dotPos)
- { shortcutName = shortcutName.substr(0, dotPos); }
- fileDefinitions.AddAttribute("Id", "SHORTCUT_" + shortcutName);
- fileDefinitions.AddAttribute("Name", iconName);
- std::string target = "[" + directoryId + "]" + fileName;
- fileDefinitions.AddAttribute("Target", target);
- fileDefinitions.AddAttribute("WorkingDirectory", directoryId);
- fileDefinitions.EndElement();
- }
- fileDefinitions.BeginElement("Shortcut");
- fileDefinitions.AddAttribute("Id", "UNINSTALL");
- std::string pkgName = GetOption("CPACK_PACKAGE_NAME");
- fileDefinitions.AddAttribute("Name", "Uninstall " + pkgName);
- fileDefinitions.AddAttribute("Description", "Uninstalls " + pkgName);
- fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe");
- fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]");
- fileDefinitions.EndElement();
- fileDefinitions.BeginElement("RemoveFolder");
- fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
- fileDefinitions.AddAttribute("On", "uninstall");
- fileDefinitions.EndElement();
- fileDefinitions.BeginElement("RegistryValue");
- fileDefinitions.AddAttribute("Root", "HKCU");
- fileDefinitions.AddAttribute("Key", regKey);
- fileDefinitions.AddAttribute("Name", "installed");
- fileDefinitions.AddAttribute("Type", "integer");
- fileDefinitions.AddAttribute("Value", "1");
- fileDefinitions.AddAttribute("KeyPath", "yes");
-
- featureDefinitions.BeginElement("ComponentRef");
- featureDefinitions.AddAttribute("Id", "SHORTCUT");
- featureDefinitions.EndElement();
- directoryDefinitions.BeginElement("Directory");
- directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder");
- directoryDefinitions.BeginElement("Directory");
- directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
- const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
- directoryDefinitions.AddAttribute("Name", startMenuFolder);
- }
-
- featureDefinitions.EndElement();
- featureDefinitions.EndElement();
- fileDefinitions.EndElement();
- directoryDefinitions.EndElement();
+ bool emitUninstallShortcut =
+ emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) !=
+ emittedShortcutTypes.end();
+
+ if (!CreateShortcuts(std::string(), "ProductFeature", globalShortcuts,
+ emitUninstallShortcut, fileDefinitions,
+ featureDefinitions)) {
+ return false;
+ }
+
+ featureDefinitions.EndElement("Fragment");
+ fileDefinitions.EndElement("Fragment");
+
+ directoryDefinitions.EndInstallationPrefixDirectory(installRootSize);
+
+ if (emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) !=
+ emittedShortcutTypes.end()) {
+ directoryDefinitions.EmitStartMenuFolder(
+ GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"));
+ }
+
+ if (emittedShortcutTypes.find(cmWIXShortcuts::DESKTOP) !=
+ emittedShortcutTypes.end()) {
+ directoryDefinitions.EmitDesktopFolder();
+ }
+
+ if (emittedShortcutTypes.find(cmWIXShortcuts::STARTUP) !=
+ emittedShortcutTypes.end()) {
+ directoryDefinitions.EmitStartupFolder();
+ }
+
+ directoryDefinitions.EndElement("Directory");
+ directoryDefinitions.EndElement("Fragment");
+
+ if (!GenerateMainSourceFileFromTemplate()) {
+ return false;
+ }
+
+ return this->Patch->CheckForUnappliedFragments();
+}
+
+std::string cmCPackWIXGenerator::GetRootFolderId() const
+{
+ if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
+ return "";
+ }
+
+ std::string result = "ProgramFiles<64>Folder";
+
+ const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID");
+ if (rootFolderId) {
+ result = rootFolderId;
+ }
+ if (GetArchitecture() == "x86") {
+ cmSystemTools::ReplaceString(result, "<64>", "");
+ } else {
+ cmSystemTools::ReplaceString(result, "<64>", "64");
+ }
+
+ return result;
+}
+
+bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
+{
std::string wixTemplate = FindTemplate("WIX.template.in");
- if(GetOption("CPACK_WIX_TEMPLATE") != 0)
- {
+ if (GetOption("CPACK_WIX_TEMPLATE") != 0) {
wixTemplate = GetOption("CPACK_WIX_TEMPLATE");
- }
- if(wixTemplate.empty())
- {
+ }
+
+ if (wixTemplate.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Could not find CPack WiX template file WIX.template.in" << std::endl);
+ "Could not find CPack WiX template file WIX.template.in"
+ << std::endl);
return false;
- }
+ }
- std::string mainSourceFilePath = cpackTopLevel + "/main.wxs";
+ 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.c_str(), mainSourceFilePath.c_str())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed creating '"
+ << mainSourceFilePath << "'' from template." << std::endl);
return false;
+ }
+
+ this->WixSources.push_back(mainSourceFilePath);
+
+ return true;
+}
+
+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;
+ 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;
+
+ if (!component.Group) {
+ featureDefinitions.EmitFeatureForComponent(component, *this->Patch);
+ }
+ }
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::AddComponentsToFeature(
+ std::string const& rootPath, std::string const& featureId,
+ cmWIXDirectoriesSourceWriter& directoryDefinitions,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions, cmWIXShortcuts& shortcuts)
+{
+ featureDefinitions.BeginElement("FeatureRef");
+ featureDefinitions.AddAttribute("Id", featureId);
+
+ std::vector<std::string> cpackPackageExecutablesList;
+ const char* cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
+ if (cpackPackageExecutables) {
+ cmSystemTools::ExpandListArgument(cpackPackageExecutables,
+ cpackPackageExecutablesList);
+ if (cpackPackageExecutablesList.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
+ "<text label>."
+ << std::endl);
+ return false;
+ }
+ }
+
+ std::vector<std::string> cpackPackageDesktopLinksList;
+ const char* cpackPackageDesktopLinks =
+ GetOption("CPACK_CREATE_DESKTOP_LINKS");
+ if (cpackPackageDesktopLinks) {
+ cmSystemTools::ExpandListArgument(cpackPackageDesktopLinks,
+ cpackPackageDesktopLinksList);
+ }
+
+ AddDirectoryAndFileDefinitions(
+ rootPath, "INSTALL_ROOT", directoryDefinitions, fileDefinitions,
+ featureDefinitions, cpackPackageExecutablesList,
+ cpackPackageDesktopLinksList, shortcuts);
+
+ featureDefinitions.EndElement("FeatureRef");
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::CreateShortcuts(
+ std::string const& cpackComponentName, std::string const& featureId,
+ cmWIXShortcuts const& shortcuts, bool emitUninstallShortcut,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions)
+{
+ if (!shortcuts.empty(cmWIXShortcuts::START_MENU)) {
+ if (!this->CreateShortcutsOfSpecificType(
+ cmWIXShortcuts::START_MENU, cpackComponentName, featureId, "",
+ shortcuts, emitUninstallShortcut, fileDefinitions,
+ featureDefinitions)) {
+ return false;
+ }
+ }
+
+ if (!shortcuts.empty(cmWIXShortcuts::DESKTOP)) {
+ if (!this->CreateShortcutsOfSpecificType(
+ cmWIXShortcuts::DESKTOP, cpackComponentName, featureId, "DESKTOP",
+ shortcuts, false, fileDefinitions, featureDefinitions)) {
+ return false;
}
+ }
- wixSources.push_back(mainSourceFilePath);
+ if (!shortcuts.empty(cmWIXShortcuts::STARTUP)) {
+ if (!this->CreateShortcutsOfSpecificType(
+ cmWIXShortcuts::STARTUP, cpackComponentName, featureId, "STARTUP",
+ shortcuts, false, fileDefinitions, featureDefinitions)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType(
+ cmWIXShortcuts::Type type, std::string const& cpackComponentName,
+ std::string const& featureId, std::string const& idPrefix,
+ cmWIXShortcuts const& shortcuts, bool emitUninstallShortcut,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions)
+{
+ std::string directoryId;
+ switch (type) {
+ case cmWIXShortcuts::START_MENU:
+ directoryId = "PROGRAM_MENU_FOLDER";
+ break;
+ case cmWIXShortcuts::DESKTOP:
+ directoryId = "DesktopFolder";
+ break;
+ case cmWIXShortcuts::STARTUP:
+ directoryId = "StartupFolder";
+ break;
+ default:
+ return false;
+ }
+
+ featureDefinitions.BeginElement("FeatureRef");
+ featureDefinitions.AddAttribute("Id", featureId);
+
+ std::string cpackVendor;
+ if (!RequireOption("CPACK_PACKAGE_VENDOR", cpackVendor)) {
+ return false;
+ }
+
+ std::string cpackPackageName;
+ if (!RequireOption("CPACK_PACKAGE_NAME", cpackPackageName)) {
+ return false;
+ }
+
+ std::string idSuffix;
+ if (!cpackComponentName.empty()) {
+ idSuffix += "_";
+ idSuffix += cpackComponentName;
+ }
+
+ std::string componentId = "CM_SHORTCUT";
+ if (idPrefix.size()) {
+ componentId += "_" + idPrefix;
+ }
+
+ componentId += idSuffix;
+
+ fileDefinitions.BeginElement("DirectoryRef");
+ fileDefinitions.AddAttribute("Id", directoryId);
+
+ fileDefinitions.BeginElement("Component");
+ fileDefinitions.AddAttribute("Id", componentId);
+ fileDefinitions.AddAttribute(
+ "Guid", fileDefinitions.CreateGuidFromComponentId(componentId));
+
+ this->Patch->ApplyFragment(componentId, fileDefinitions);
+
+ std::string registryKey =
+ std::string("Software\\") + cpackVendor + "\\" + cpackPackageName;
+
+ shortcuts.EmitShortcuts(type, registryKey, cpackComponentName,
+ fileDefinitions);
+
+ if (type == cmWIXShortcuts::START_MENU) {
+ fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" +
+ idSuffix);
+ }
+
+ if (emitUninstallShortcut) {
+ fileDefinitions.EmitUninstallShortcut(cpackPackageName);
+ }
+
+ fileDefinitions.EndElement("Component");
+ fileDefinitions.EndElement("DirectoryRef");
+
+ featureDefinitions.EmitComponentRef(componentId);
+ featureDefinitions.EndElement("FeatureRef");
return true;
}
@@ -481,162 +806,162 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
bool cmCPackWIXGenerator::CreateLicenseFile()
{
std::string licenseSourceFilename;
- if(!RequireOption("CPACK_RESOURCE_FILE_LICENSE", licenseSourceFilename))
- {
+ if (!RequireOption("CPACK_RESOURCE_FILE_LICENSE", licenseSourceFilename)) {
return false;
- }
+ }
std::string licenseDestinationFilename;
- if(!RequireOption("CPACK_WIX_LICENSE_RTF", licenseDestinationFilename))
- {
+ if (!RequireOption("CPACK_WIX_LICENSE_RTF", licenseDestinationFilename)) {
return false;
- }
+ }
std::string extension = GetRightmostExtension(licenseSourceFilename);
- if(extension == ".rtf")
- {
- cmSystemTools::CopyAFile(
- licenseSourceFilename.c_str(),
- licenseDestinationFilename.c_str());
- }
- else if(extension == ".txt")
- {
+ if (extension == ".rtf") {
+ cmSystemTools::CopyAFile(licenseSourceFilename.c_str(),
+ licenseDestinationFilename.c_str());
+ } else if (extension == ".txt") {
cmWIXRichTextFormatWriter rtfWriter(licenseDestinationFilename);
- std::ifstream licenseSource(licenseSourceFilename.c_str());
+ cmsys::ifstream licenseSource(licenseSourceFilename.c_str());
std::string line;
- while(std::getline(licenseSource, line))
- {
+ while (std::getline(licenseSource, line)) {
rtfWriter.AddText(line);
rtfWriter.AddText("\n");
- }
}
- else
- {
+ } else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "unsupported WiX License file extension '" <<
- extension << "'" << std::endl);
+ "unsupported WiX License file extension '"
+ << extension << "'" << std::endl);
return false;
- }
+ }
return true;
}
-void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
- const std::string& topdir,
- const std::string& directoryId,
- cmWIXSourceWriter& directoryDefinitions,
- cmWIXSourceWriter& fileDefinitions,
- cmWIXSourceWriter& featureDefinitions,
- size_t& directoryCounter,
- size_t& fileCounter,
- const std::vector<std::string>& pkgExecutables,
- std::vector<std::string>& dirIdExecutables)
+void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
+ std::string const& topdir, std::string const& directoryId,
+ cmWIXDirectoriesSourceWriter& directoryDefinitions,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions,
+ std::vector<std::string> const& packageExecutables,
+ std::vector<std::string> const& desktopExecutables,
+ cmWIXShortcuts& shortcuts)
{
cmsys::Directory dir;
dir.Load(topdir.c_str());
- for(size_t i = 0; i < dir.GetNumberOfFiles(); ++i)
- {
+ std::string relativeDirectoryPath =
+ cmSystemTools::RelativePath(toplevel.c_str(), topdir.c_str());
+
+ if (relativeDirectoryPath.empty()) {
+ relativeDirectoryPath = ".";
+ }
+
+ cmInstalledFile const* directoryInstalledFile = this->GetInstalledFile(
+ this->RelativePathWithoutComponentPrefix(relativeDirectoryPath));
+
+ bool emptyDirectory = dir.GetNumberOfFiles() == 2;
+ bool createDirectory = false;
+
+ if (emptyDirectory) {
+ createDirectory = true;
+ }
+
+ if (directoryInstalledFile) {
+ if (directoryInstalledFile->HasProperty("CPACK_WIX_ACL")) {
+ createDirectory = true;
+ }
+ }
+
+ if (createDirectory) {
+ std::string componentId = fileDefinitions.EmitComponentCreateFolder(
+ directoryId, GenerateGUID(), directoryInstalledFile);
+ featureDefinitions.EmitComponentRef(componentId);
+ }
+
+ if (emptyDirectory) {
+ return;
+ }
+
+ for (size_t i = 0; i < dir.GetNumberOfFiles(); ++i) {
std::string fileName = dir.GetFile(static_cast<unsigned long>(i));
- if(fileName == "." || fileName == "..")
- {
+ if (fileName == "." || fileName == "..") {
continue;
- }
+ }
std::string fullPath = topdir + "/" + fileName;
- if(cmSystemTools::FileIsDirectory(fullPath.c_str()))
- {
- std::stringstream tmp;
- tmp << "DIR_ID_" << ++directoryCounter;
- std::string subDirectoryId = tmp.str();
+ std::string relativePath =
+ cmSystemTools::RelativePath(toplevel.c_str(), fullPath.c_str());
+
+ std::string id = PathToId(relativePath);
+
+ if (cmSystemTools::FileIsDirectory(fullPath.c_str())) {
+ std::string subDirectoryId = std::string("CM_D") + id;
directoryDefinitions.BeginElement("Directory");
directoryDefinitions.AddAttribute("Id", subDirectoryId);
directoryDefinitions.AddAttribute("Name", fileName);
+ this->Patch->ApplyFragment(subDirectoryId, directoryDefinitions);
+
+ AddDirectoryAndFileDefinitions(
+ fullPath, subDirectoryId, directoryDefinitions, fileDefinitions,
+ featureDefinitions, packageExecutables, desktopExecutables, shortcuts);
+
+ directoryDefinitions.EndElement("Directory");
+ } else {
+ cmInstalledFile const* installedFile = this->GetInstalledFile(
+ this->RelativePathWithoutComponentPrefix(relativePath));
- AddDirectoryAndFileDefinitons(
- fullPath, subDirectoryId,
- directoryDefinitions,
- fileDefinitions,
- featureDefinitions,
- directoryCounter,
- fileCounter,
- pkgExecutables,
- dirIdExecutables);
- directoryDefinitions.EndElement();
+ if (installedFile) {
+ shortcuts.CreateFromProperties(id, directoryId, *installedFile);
}
- else
- {
- std::stringstream tmp;
- tmp << "_ID_" << ++fileCounter;
- std::string idSuffix = tmp.str();
-
- std::string componentId = std::string("CMP") + idSuffix;
- std::string fileId = std::string("FILE") + idSuffix;
-
- fileDefinitions.BeginElement("DirectoryRef");
- fileDefinitions.AddAttribute("Id", directoryId);
-
- fileDefinitions.BeginElement("Component");
- fileDefinitions.AddAttribute("Id", componentId);
- fileDefinitions.AddAttribute("Guid", "*");
-
- fileDefinitions.BeginElement("File");
- fileDefinitions.AddAttribute("Id", fileId);
- fileDefinitions.AddAttribute("Source", fullPath);
- fileDefinitions.AddAttribute("KeyPath", "yes");
-
- fileDefinitions.EndElement();
- fileDefinitions.EndElement();
- fileDefinitions.EndElement();
-
- featureDefinitions.BeginElement("ComponentRef");
- featureDefinitions.AddAttribute("Id", componentId);
- featureDefinitions.EndElement();
-
- std::vector<std::string>::const_iterator it;
- for (it = pkgExecutables.begin() ;
- it != pkgExecutables.end() ;
- ++it)
- {
- std::string execName = *it++;
- std::string iconName = *it;
+
+ std::string componentId = fileDefinitions.EmitComponentFile(
+ directoryId, id, fullPath, *(this->Patch), installedFile);
+
+ featureDefinitions.EmitComponentRef(componentId);
+
+ for (size_t j = 0; j < packageExecutables.size(); ++j) {
+ std::string const& executableName = packageExecutables[j++];
+ std::string const& textLabel = packageExecutables[j];
if (cmSystemTools::LowerCase(fileName) ==
- cmSystemTools::LowerCase(execName) + ".exe")
- {
- dirIdExecutables.push_back(fileName);
- dirIdExecutables.push_back(iconName);
- dirIdExecutables.push_back(directoryId);
+ cmSystemTools::LowerCase(executableName) + ".exe") {
+ cmWIXShortcut shortcut;
+ shortcut.label = textLabel;
+ shortcut.workingDirectoryId = directoryId;
+ shortcuts.insert(cmWIXShortcuts::START_MENU, id, shortcut);
+
+ if (!desktopExecutables.empty() &&
+ std::find(desktopExecutables.begin(), desktopExecutables.end(),
+ executableName) != desktopExecutables.end()) {
+ shortcuts.insert(cmWIXShortcuts::DESKTOP, id, shortcut);
}
}
}
}
+ }
}
-bool cmCPackWIXGenerator::RequireOption(
- const std::string& name, std::string &value) const
+bool cmCPackWIXGenerator::RequireOption(std::string const& name,
+ std::string& value) const
{
const char* tmp = GetOption(name.c_str());
- if(tmp)
- {
+ if (tmp) {
value = tmp;
return true;
- }
- else
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Required variable " << name << " not set" << std::endl);
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Required variable "
+ << name << " not set" << std::endl);
return false;
- }
+ }
}
std::string cmCPackWIXGenerator::GetArchitecture() const
@@ -644,14 +969,11 @@ std::string cmCPackWIXGenerator::GetArchitecture() const
std::string void_p_size;
RequireOption("CPACK_WIX_SIZEOF_VOID_P", void_p_size);
- if(void_p_size == "8")
- {
+ if (void_p_size == "8") {
return "x64";
- }
- else
- {
+ } else {
return "x86";
- }
+ }
}
std::string cmCPackWIXGenerator::GenerateGUID()
@@ -659,30 +981,174 @@ std::string cmCPackWIXGenerator::GenerateGUID()
UUID guid;
UuidCreate(&guid);
- unsigned char *tmp = 0;
- UuidToString(&guid, &tmp);
+ unsigned short* tmp = 0;
+ UuidToStringW(&guid, &tmp);
- std::string result(reinterpret_cast<char*>(tmp));
- RpcStringFree(&tmp);
+ std::string result =
+ cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp));
+ RpcStringFreeW(&tmp);
return cmSystemTools::UpperCase(result);
}
-std::string cmCPackWIXGenerator::QuotePath(const std::string& path)
+std::string cmCPackWIXGenerator::QuotePath(std::string const& path)
{
return std::string("\"") + path + '"';
}
std::string cmCPackWIXGenerator::GetRightmostExtension(
- const std::string& filename)
+ std::string const& filename)
{
std::string extension;
std::string::size_type i = filename.rfind(".");
- if(i != std::string::npos)
- {
+ if (i != std::string::npos) {
extension = filename.substr(i);
- }
+ }
return cmSystemTools::LowerCase(extension);
}
+
+std::string cmCPackWIXGenerator::PathToId(std::string const& path)
+{
+ id_map_t::const_iterator i = PathToIdMap.find(path);
+ if (i != PathToIdMap.end())
+ return i->second;
+
+ std::string id = CreateNewIdForPath(path);
+ return id;
+}
+
+std::string cmCPackWIXGenerator::CreateNewIdForPath(std::string const& path)
+{
+ std::vector<std::string> components;
+ cmSystemTools::SplitPath(path.c_str(), components, false);
+
+ size_t replacementCount = 0;
+
+ std::string identifier;
+ std::string currentComponent;
+
+ for (size_t i = 1; i < components.size(); ++i) {
+ if (i != 1)
+ identifier += '.';
+
+ currentComponent =
+ NormalizeComponentForId(components[i], replacementCount);
+
+ identifier += currentComponent;
+ }
+
+ std::string idPrefix = "P";
+ size_t replacementPercent = replacementCount * 100 / identifier.size();
+ if (replacementPercent > 33 || identifier.size() > 60) {
+ identifier = CreateHashedId(path, currentComponent);
+ idPrefix = "H";
+ }
+
+ std::ostringstream result;
+ result << idPrefix << "_" << identifier;
+
+ size_t ambiguityCount = ++IdAmbiguityCounter[identifier];
+
+ if (ambiguityCount > 999) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while trying to generate a unique Id for '"
+ << path << "'" << std::endl);
+
+ return std::string();
+ } else if (ambiguityCount > 1) {
+ result << "_" << ambiguityCount;
+ }
+
+ std::string resultString = result.str();
+
+ PathToIdMap[path] = resultString;
+
+ return resultString;
+}
+
+std::string cmCPackWIXGenerator::CreateHashedId(
+ std::string const& path, std::string const& normalizedFilename)
+{
+ cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
+ std::string const hash = sha1.HashString(path);
+
+ std::string identifier;
+ identifier += hash.substr(0, 7) + "_";
+
+ const size_t maxFileNameLength = 52;
+ if (normalizedFilename.length() > maxFileNameLength) {
+ identifier += normalizedFilename.substr(0, maxFileNameLength - 3);
+ identifier += "...";
+ } else {
+ identifier += normalizedFilename;
+ }
+
+ return identifier;
+}
+
+std::string cmCPackWIXGenerator::NormalizeComponentForId(
+ std::string const& component, size_t& replacementCount)
+{
+ std::string result;
+ result.resize(component.size());
+
+ for (size_t i = 0; i < component.size(); ++i) {
+ char c = component[i];
+ if (IsLegalIdCharacter(c)) {
+ result[i] = c;
+ } else {
+ result[i] = '_';
+ ++replacementCount;
+ }
+ }
+
+ return result;
+}
+
+bool cmCPackWIXGenerator::IsLegalIdCharacter(char c)
+{
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') || c == '_' || c == '.';
+}
+
+void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName,
+ extension_set_t& extensions)
+{
+ const char* variableContent = GetOption(variableName.c_str());
+ if (!variableContent)
+ return;
+
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(variableContent, list);
+ extensions.insert(list.begin(), list.end());
+}
+
+void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName,
+ std::ostream& stream)
+{
+ const char* variableContent = GetOption(variableName.c_str());
+ if (!variableContent)
+ return;
+
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(variableContent, list);
+
+ for (std::vector<std::string>::const_iterator i = list.begin();
+ i != list.end(); ++i) {
+ stream << " " << QuotePath(*i);
+ }
+}
+
+std::string cmCPackWIXGenerator::RelativePathWithoutComponentPrefix(
+ std::string const& path)
+{
+ if (this->Components.empty()) {
+ return path;
+ }
+
+ std::string::size_type pos = path.find('/');
+
+ return path.substr(pos + 1);
+}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index aaccf9d46..b2633a7f9 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -1,24 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackWIXGenerator_h
#define cmCPackWIXGenerator_h
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
+
+#include "cmWIXPatch.h"
+#include "cmWIXShortcut.h"
-#include <string>
#include <map>
+#include <string>
class cmWIXSourceWriter;
+class cmWIXDirectoriesSourceWriter;
+class cmWIXFilesSourceWriter;
+class cmWIXFeaturesSourceWriter;
/** \class cmCPackWIXGenerator
* \brief A generator for WIX files
@@ -28,78 +24,136 @@ class cmCPackWIXGenerator : public cmCPackGenerator
public:
cmCPackTypeMacro(cmCPackWIXGenerator, cmCPackGenerator);
+ cmCPackWIXGenerator();
+ ~cmCPackWIXGenerator();
+
protected:
virtual int InitializeInternal();
virtual int PackageFiles();
- virtual const char* GetOutputExtension()
- {
- return ".msi";
- }
+ virtual const char* GetOutputExtension() { return ".msi"; }
virtual enum CPackSetDestdirSupport SupportsSetDestdir() const
- {
+ {
return SETDESTDIR_UNSUPPORTED;
- }
+ }
- virtual bool SupportsAbsoluteDestination() const
- {
- return false;
- }
+ virtual bool SupportsAbsoluteDestination() const { return false; }
- virtual bool SupportsComponentInstallation() const
- {
- return false;
- }
+ virtual bool SupportsComponentInstallation() const { 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;
+
bool InitializeWiXConfiguration();
bool PackageFilesImpl();
- bool CreateWiXVariablesIncludeFile();
+ void CreateWiXVariablesIncludeFile();
- void CopyDefinition(
- cmWIXSourceWriter &source, const std::string &name);
+ void CreateWiXPropertiesIncludeFile();
- void AddDefinition(cmWIXSourceWriter& source,
- const std::string& name, const std::string& value);
+ void CreateWiXProductFragmentIncludeFile();
+
+ void CopyDefinition(cmWIXSourceWriter& source, std::string const& name);
+
+ void AddDefinition(cmWIXSourceWriter& source, std::string const& name,
+ std::string const& value);
bool CreateWiXSourceFiles();
- bool CreateLicenseFile();
+ std::string GetRootFolderId() const;
+
+ bool GenerateMainSourceFileFromTemplate();
- bool RunWiXCommand(const std::string& command);
+ bool CreateFeatureHierarchy(cmWIXFeaturesSourceWriter& featureDefinitions);
- bool RunCandleCommand(
- const std::string& sourceFile, const std::string& objectFile);
+ bool AddComponentsToFeature(
+ std::string const& rootPath, std::string const& featureId,
+ cmWIXDirectoriesSourceWriter& directoryDefinitions,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions, cmWIXShortcuts& shortcuts);
- bool RunLightCommand(const std::string& objectFiles);
+ bool CreateShortcuts(std::string const& cpackComponentName,
+ std::string const& featureId,
+ cmWIXShortcuts const& shortcuts,
+ bool emitUninstallShortcut,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions);
- void AddDirectoryAndFileDefinitons(const std::string& topdir,
- const std::string& directoryId,
- cmWIXSourceWriter& directoryDefinitions,
- cmWIXSourceWriter& fileDefinitions,
- cmWIXSourceWriter& featureDefinitions,
- size_t& directoryCounter,
- size_t& fileCounter,
- const std::vector<std::string>& pkgExecutables,
- std::vector<std::string>& dirIdExecutables
- );
+ bool CreateShortcutsOfSpecificType(
+ cmWIXShortcuts::Type type, std::string const& cpackComponentName,
+ std::string const& featureId, std::string const& idPrefix,
+ cmWIXShortcuts const& shortcuts, bool emitUninstallShortcut,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions);
+
+ void AppendUserSuppliedExtraSources();
+
+ void AppendUserSuppliedExtraObjects(std::ostream& stream);
+
+ bool CreateLicenseFile();
+ bool RunWiXCommand(std::string const& command);
- bool RequireOption(const std::string& name, std::string& value) const;
+ bool RunCandleCommand(std::string const& sourceFile,
+ std::string const& objectFile);
+
+ bool RunLightCommand(std::string const& objectFiles);
+
+ void AddDirectoryAndFileDefinitions(
+ std::string const& topdir, std::string const& directoryId,
+ cmWIXDirectoriesSourceWriter& directoryDefinitions,
+ cmWIXFilesSourceWriter& fileDefinitions,
+ cmWIXFeaturesSourceWriter& featureDefinitions,
+ std::vector<std::string> const& packageExecutables,
+ std::vector<std::string> const& desktopExecutables,
+ cmWIXShortcuts& shortcuts);
+
+ bool RequireOption(std::string const& name, std::string& value) const;
std::string GetArchitecture() const;
static std::string GenerateGUID();
- static std::string QuotePath(const std::string& path);
+ static std::string QuotePath(std::string const& path);
+
+ static std::string GetRightmostExtension(std::string const& filename);
+
+ std::string PathToId(std::string const& path);
+
+ std::string CreateNewIdForPath(std::string const& path);
+
+ static std::string CreateHashedId(std::string const& path,
+ std::string const& normalizedFilename);
+
+ std::string NormalizeComponentForId(std::string const& component,
+ size_t& replacementCount);
+
+ static bool IsLegalIdCharacter(char c);
+
+ void CollectExtensions(std::string const& variableName,
+ extension_set_t& extensions);
+
+ void AddCustomFlags(std::string const& variableName, std::ostream& stream);
+
+ std::string RelativePathWithoutComponentPrefix(std::string const& path);
+
+ std::vector<std::string> WixSources;
+ id_map_t PathToIdMap;
+ ambiguity_map_t IdAmbiguityCounter;
+
+ extension_set_t CandleExtensions;
+ extension_set_t LightExtensions;
+
+ std::string CPackTopLevel;
- static std::string GetRightmostExtension(const std::string& filename);
+ cmWIXPatch* Patch;
- std::vector<std::string> wixSources;
+ cmWIXSourceWriter::GuidType ComponentGuidType;
};
#endif
diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx
new file mode 100644
index 000000000..744a93298
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx
@@ -0,0 +1,126 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWIXAccessControlList.h"
+
+#include "cmCPackGenerator.h"
+
+#include "cmSystemTools.h"
+
+cmWIXAccessControlList::cmWIXAccessControlList(
+ cmCPackLog* logger, cmInstalledFile const& installedFile,
+ cmWIXSourceWriter& sourceWriter)
+ : Logger(logger)
+ , InstalledFile(installedFile)
+ , SourceWriter(sourceWriter)
+{
+}
+
+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]);
+ }
+
+ return true;
+}
+
+void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
+{
+ std::string::size_type pos = entry.find('=');
+ if (pos == std::string::npos) {
+ this->ReportError(entry, "Did not find mandatory '='");
+ return;
+ }
+
+ std::string user_and_domain = entry.substr(0, pos);
+ std::string permission_string = entry.substr(pos + 1);
+
+ pos = user_and_domain.find('@');
+ std::string user;
+ std::string domain;
+ if (pos != std::string::npos) {
+ user = user_and_domain.substr(0, pos);
+ domain = user_and_domain.substr(pos + 1);
+ } else {
+ user = user_and_domain;
+ }
+
+ std::vector<std::string> permissions =
+ cmSystemTools::tokenize(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]));
+ }
+ this->SourceWriter.EndElement("Permission");
+}
+
+void cmWIXAccessControlList::ReportError(std::string const& entry,
+ std::string const& message)
+{
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed processing ACL entry '"
+ << entry << "': " << message << std::endl);
+}
+
+bool cmWIXAccessControlList::IsBooleanAttribute(std::string const& name)
+{
+ static const char* validAttributes[] = {
+ /* clang-format needs this comment to break after the opening brace */
+ "Append",
+ "ChangePermission",
+ "CreateChild",
+ "CreateFile",
+ "CreateLink",
+ "CreateSubkeys",
+ "Delete",
+ "DeleteChild",
+ "EnumerateSubkeys",
+ "Execute",
+ "FileAllRights",
+ "GenericAll",
+ "GenericExecute",
+ "GenericRead",
+ "GenericWrite",
+ "Notify",
+ "Read",
+ "ReadAttributes",
+ "ReadExtendedAttributes",
+ "ReadPermission",
+ "SpecificRightsAll",
+ "Synchronize",
+ "TakeOwnership",
+ "Traverse",
+ "Write",
+ "WriteAttributes",
+ "WriteExtendedAttributes",
+ 0
+ };
+
+ size_t i = 0;
+ while (validAttributes[i]) {
+ if (name == validAttributes[i++])
+ return true;
+ }
+
+ return false;
+}
+
+void cmWIXAccessControlList::EmitBooleanAttribute(std::string const& entry,
+ std::string const& name)
+{
+ if (!this->IsBooleanAttribute(name)) {
+ std::ostringstream message;
+ message << "Unknown boolean attribute '" << name << "'";
+ this->ReportError(entry, message.str());
+ }
+
+ this->SourceWriter.AddAttribute(name, "yes");
+}
diff --git a/Source/CPack/WiX/cmWIXAccessControlList.h b/Source/CPack/WiX/cmWIXAccessControlList.h
new file mode 100644
index 000000000..2a23f2f37
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXAccessControlList.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 cmWIXAccessControlList_h
+#define cmWIXAccessControlList_h
+
+#include "cmWIXSourceWriter.h"
+
+#include "cmCPackLog.h"
+#include "cmInstalledFile.h"
+
+class cmWIXAccessControlList
+{
+public:
+ cmWIXAccessControlList(cmCPackLog* logger,
+ cmInstalledFile const& installedFile,
+ cmWIXSourceWriter& sourceWriter);
+
+ bool Apply();
+
+private:
+ void CreatePermissionElement(std::string const& entry);
+
+ void ReportError(std::string const& entry, std::string const& message);
+
+ bool IsBooleanAttribute(std::string const& name);
+
+ void EmitBooleanAttribute(std::string const& entry, std::string const& name);
+
+ cmCPackLog* Logger;
+ cmInstalledFile const& InstalledFile;
+ cmWIXSourceWriter& SourceWriter;
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
new file mode 100644
index 000000000..975dffb4f
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
@@ -0,0 +1,82 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWIXDirectoriesSourceWriter.h"
+
+cmWIXDirectoriesSourceWriter::cmWIXDirectoriesSourceWriter(
+ cmCPackLog* logger, std::string const& filename, GuidType componentGuidType)
+ : cmWIXSourceWriter(logger, filename, componentGuidType)
+{
+}
+
+void cmWIXDirectoriesSourceWriter::EmitStartMenuFolder(
+ std::string const& startMenuFolder)
+{
+ BeginElement("Directory");
+ AddAttribute("Id", "ProgramMenuFolder");
+
+ BeginElement("Directory");
+ AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+ AddAttribute("Name", startMenuFolder);
+ EndElement("Directory");
+
+ EndElement("Directory");
+}
+
+void cmWIXDirectoriesSourceWriter::EmitDesktopFolder()
+{
+ BeginElement("Directory");
+ AddAttribute("Id", "DesktopFolder");
+ AddAttribute("Name", "Desktop");
+ EndElement("Directory");
+}
+
+void cmWIXDirectoriesSourceWriter::EmitStartupFolder()
+{
+ BeginElement("Directory");
+ AddAttribute("Id", "StartupFolder");
+ AddAttribute("Name", "Startup");
+ EndElement("Directory");
+}
+
+size_t cmWIXDirectoriesSourceWriter::BeginInstallationPrefixDirectory(
+ std::string const& programFilesFolderId,
+ std::string const& installRootString)
+{
+ size_t offset = 1;
+ if (!programFilesFolderId.empty()) {
+ BeginElement("Directory");
+ AddAttribute("Id", programFilesFolderId);
+ offset = 0;
+ }
+
+ std::vector<std::string> installRoot;
+
+ cmSystemTools::SplitPath(installRootString.c_str(), installRoot);
+
+ if (!installRoot.empty() && installRoot.back().empty()) {
+ installRoot.pop_back();
+ }
+
+ for (size_t i = 1; i < installRoot.size(); ++i) {
+ BeginElement("Directory");
+
+ if (i == installRoot.size() - 1) {
+ AddAttribute("Id", "INSTALL_ROOT");
+ } else {
+ std::ostringstream tmp;
+ tmp << "INSTALL_PREFIX_" << i;
+ AddAttribute("Id", tmp.str());
+ }
+
+ AddAttribute("Name", installRoot[i]);
+ }
+
+ return installRoot.size() - offset;
+}
+
+void cmWIXDirectoriesSourceWriter::EndInstallationPrefixDirectory(size_t size)
+{
+ for (size_t i = 0; i < size; ++i) {
+ EndElement("Directory");
+ }
+}
diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
new file mode 100644
index 000000000..8233331a3
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.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 cmWIXDirectoriesSourceWriter_h
+#define cmWIXDirectoriesSourceWriter_h
+
+#include "cmWIXSourceWriter.h"
+
+#include "cmCPackGenerator.h"
+
+#include <string>
+
+/** \class cmWIXDirectoriesSourceWriter
+ * \brief Helper class to generate directories.wxs
+ */
+class cmWIXDirectoriesSourceWriter : public cmWIXSourceWriter
+{
+public:
+ cmWIXDirectoriesSourceWriter(cmCPackLog* logger, std::string const& filename,
+ GuidType componentGuidType);
+
+ void EmitStartMenuFolder(std::string const& startMenuFolder);
+
+ void EmitDesktopFolder();
+
+ void EmitStartupFolder();
+
+ size_t BeginInstallationPrefixDirectory(
+ std::string const& programFilesFolderId,
+ std::string const& installRootString);
+
+ void EndInstallationPrefixDirectory(size_t size);
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
new file mode 100644
index 000000000..0be43776e
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
@@ -0,0 +1,95 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWIXFeaturesSourceWriter.h"
+
+cmWIXFeaturesSourceWriter::cmWIXFeaturesSourceWriter(
+ cmCPackLog* logger, std::string const& filename, GuidType componentGuidType)
+ : cmWIXSourceWriter(logger, filename, componentGuidType)
+{
+}
+
+void cmWIXFeaturesSourceWriter::CreateCMakePackageRegistryEntry(
+ std::string const& package, std::string const& upgradeGuid)
+{
+ BeginElement("Component");
+ AddAttribute("Id", "CM_PACKAGE_REGISTRY");
+ AddAttribute("Directory", "TARGETDIR");
+ AddAttribute("Guid", CreateGuidFromComponentId("CM_PACKAGE_REGISTRY"));
+
+ std::string registryKey =
+ std::string("Software\\Kitware\\CMake\\Packages\\") + package;
+
+ BeginElement("RegistryValue");
+ AddAttribute("Root", "HKLM");
+ AddAttribute("Key", registryKey);
+ AddAttribute("Name", upgradeGuid);
+ AddAttribute("Type", "string");
+ AddAttribute("Value", "[INSTALL_ROOT]");
+ AddAttribute("KeyPath", "yes");
+ EndElement("RegistryValue");
+
+ EndElement("Component");
+}
+
+void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup(
+ cmCPackComponentGroup const& group, cmWIXPatch& patch)
+{
+ BeginElement("Feature");
+ AddAttribute("Id", "CM_G_" + group.Name);
+
+ if (group.IsExpandedByDefault) {
+ AddAttribute("Display", "expand");
+ }
+
+ AddAttributeUnlessEmpty("Title", group.DisplayName);
+ AddAttributeUnlessEmpty("Description", group.Description);
+
+ 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 (std::vector<cmCPackComponent*>::const_iterator i =
+ group.Components.begin();
+ i != group.Components.end(); ++i) {
+ EmitFeatureForComponent(**i, patch);
+ }
+
+ EndElement("Feature");
+}
+
+void cmWIXFeaturesSourceWriter::EmitFeatureForComponent(
+ cmCPackComponent const& component, cmWIXPatch& patch)
+{
+ BeginElement("Feature");
+ AddAttribute("Id", "CM_C_" + component.Name);
+
+ AddAttributeUnlessEmpty("Title", component.DisplayName);
+ AddAttributeUnlessEmpty("Description", component.Description);
+
+ if (component.IsRequired) {
+ AddAttribute("Absent", "disallow");
+ }
+
+ if (component.IsHidden) {
+ AddAttribute("Display", "hidden");
+ }
+
+ if (component.IsDisabledByDefault) {
+ AddAttribute("Level", "2");
+ }
+
+ patch.ApplyFragment("CM_C_" + component.Name, *this);
+
+ EndElement("Feature");
+}
+
+void cmWIXFeaturesSourceWriter::EmitComponentRef(std::string const& id)
+{
+ BeginElement("ComponentRef");
+ AddAttribute("Id", id);
+ EndElement("ComponentRef");
+}
diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
new file mode 100644
index 000000000..e751ca719
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
@@ -0,0 +1,32 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmWIXFeaturesSourceWriter_h
+#define cmWIXFeaturesSourceWriter_h
+
+#include "cmWIXPatch.h"
+#include "cmWIXSourceWriter.h"
+
+#include "cmCPackGenerator.h"
+
+/** \class cmWIXFeaturesSourceWriter
+ * \brief Helper class to generate features.wxs
+ */
+class cmWIXFeaturesSourceWriter : public cmWIXSourceWriter
+{
+public:
+ cmWIXFeaturesSourceWriter(cmCPackLog* logger, std::string const& filename,
+ GuidType componentGuidType);
+
+ void CreateCMakePackageRegistryEntry(std::string const& package,
+ std::string const& upgradeGuid);
+
+ void EmitFeatureForComponentGroup(const cmCPackComponentGroup& group,
+ cmWIXPatch& patch);
+
+ void EmitFeatureForComponent(const cmCPackComponent& component,
+ cmWIXPatch& patch);
+
+ void EmitComponentRef(std::string const& id);
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
new file mode 100644
index 000000000..b4cd1a3d6
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.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 "cmWIXFilesSourceWriter.h"
+
+#include "cmWIXAccessControlList.h"
+
+#include "cmInstalledFile.h"
+
+#include "cmSystemTools.h"
+#include "cmUuid.h"
+
+#include "cm_sys_stat.h"
+
+cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
+ std::string const& filename,
+ GuidType componentGuidType)
+ : cmWIXSourceWriter(logger, filename, componentGuidType)
+{
+}
+
+void cmWIXFilesSourceWriter::EmitShortcut(std::string const& id,
+ cmWIXShortcut const& shortcut,
+ std::string const& shortcutPrefix,
+ size_t shortcutIndex)
+{
+ std::ostringstream shortcutId;
+ shortcutId << shortcutPrefix << id;
+
+ if (shortcutIndex > 0) {
+ shortcutId << "_" << shortcutIndex;
+ }
+
+ std::string fileId = std::string("CM_F") + id;
+
+ BeginElement("Shortcut");
+ AddAttribute("Id", shortcutId.str());
+ AddAttribute("Name", shortcut.label);
+ std::string target = "[#" + fileId + "]";
+ AddAttribute("Target", target);
+ AddAttribute("WorkingDirectory", shortcut.workingDirectoryId);
+ EndElement("Shortcut");
+}
+
+void cmWIXFilesSourceWriter::EmitRemoveFolder(std::string const& id)
+{
+ BeginElement("RemoveFolder");
+ AddAttribute("Id", id);
+ AddAttribute("On", "uninstall");
+ EndElement("RemoveFolder");
+}
+
+void cmWIXFilesSourceWriter::EmitInstallRegistryValue(
+ std::string const& registryKey, std::string const& cpackComponentName,
+ std::string const& suffix)
+{
+ std::string valueName;
+ if (!cpackComponentName.empty()) {
+ valueName = cpackComponentName + "_";
+ }
+
+ valueName += "installed";
+ valueName += suffix;
+
+ BeginElement("RegistryValue");
+ AddAttribute("Root", "HKCU");
+ AddAttribute("Key", registryKey);
+ AddAttribute("Name", valueName);
+ AddAttribute("Type", "integer");
+ AddAttribute("Value", "1");
+ AddAttribute("KeyPath", "yes");
+ EndElement("RegistryValue");
+}
+
+void cmWIXFilesSourceWriter::EmitUninstallShortcut(
+ std::string const& packageName)
+{
+ BeginElement("Shortcut");
+ AddAttribute("Id", "UNINSTALL");
+ AddAttribute("Name", "Uninstall " + packageName);
+ AddAttribute("Description", "Uninstalls " + packageName);
+ AddAttribute("Target", "[SystemFolder]msiexec.exe");
+ AddAttribute("Arguments", "/x [ProductCode]");
+ EndElement("Shortcut");
+}
+
+std::string cmWIXFilesSourceWriter::EmitComponentCreateFolder(
+ std::string const& directoryId, std::string const& guid,
+ cmInstalledFile const* installedFile)
+{
+ std::string componentId = std::string("CM_C_EMPTY_") + directoryId;
+
+ BeginElement("DirectoryRef");
+ AddAttribute("Id", directoryId);
+
+ BeginElement("Component");
+ AddAttribute("Id", componentId);
+ AddAttribute("Guid", guid);
+
+ BeginElement("CreateFolder");
+
+ if (installedFile) {
+ cmWIXAccessControlList acl(Logger, *installedFile, *this);
+ acl.Apply();
+ }
+
+ EndElement("CreateFolder");
+ EndElement("Component");
+ EndElement("DirectoryRef");
+
+ return componentId;
+}
+
+std::string cmWIXFilesSourceWriter::EmitComponentFile(
+ std::string const& directoryId, std::string const& id,
+ std::string const& filePath, cmWIXPatch& patch,
+ cmInstalledFile const* installedFile)
+{
+ std::string componentId = std::string("CM_C") + id;
+ std::string fileId = std::string("CM_F") + id;
+
+ std::string guid = CreateGuidFromComponentId(componentId);
+
+ BeginElement("DirectoryRef");
+ AddAttribute("Id", directoryId);
+
+ BeginElement("Component");
+ AddAttribute("Id", componentId);
+ AddAttribute("Guid", guid);
+
+ if (installedFile) {
+ if (installedFile->GetPropertyAsBool("CPACK_NEVER_OVERWRITE")) {
+ AddAttribute("NeverOverwrite", "yes");
+ }
+ if (installedFile->GetPropertyAsBool("CPACK_PERMANENT")) {
+ AddAttribute("Permanent", "yes");
+ }
+ }
+
+ patch.ApplyFragment(componentId, *this);
+ BeginElement("File");
+ AddAttribute("Id", fileId);
+ AddAttribute("Source", filePath);
+ AddAttribute("KeyPath", "yes");
+
+ mode_t fileMode = 0;
+ cmSystemTools::GetPermissions(filePath.c_str(), fileMode);
+
+ if (!(fileMode & S_IWRITE)) {
+ AddAttribute("ReadOnly", "yes");
+ }
+ patch.ApplyFragment(fileId, *this);
+
+ if (installedFile) {
+ cmWIXAccessControlList acl(Logger, *installedFile, *this);
+ acl.Apply();
+ }
+
+ EndElement("File");
+
+ EndElement("Component");
+ EndElement("DirectoryRef");
+
+ return componentId;
+}
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h
new file mode 100644
index 000000000..dc9c636d3
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h
@@ -0,0 +1,43 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmWIXFilesSourceWriter_h
+#define cmWIXFilesSourceWriter_h
+
+#include "cmWIXSourceWriter.h"
+
+#include "cmWIXPatch.h"
+#include "cmWIXShortcut.h"
+
+#include "cmCPackGenerator.h"
+
+/** \class cmWIXFilesSourceWriter
+ * \brief Helper class to generate files.wxs
+ */
+class cmWIXFilesSourceWriter : public cmWIXSourceWriter
+{
+public:
+ cmWIXFilesSourceWriter(cmCPackLog* logger, std::string const& filename,
+ GuidType componentGuidType);
+
+ void EmitShortcut(std::string const& id, cmWIXShortcut const& shortcut,
+ std::string const& shortcutPrefix, size_t shortcutIndex);
+
+ void EmitRemoveFolder(std::string const& id);
+
+ void EmitInstallRegistryValue(std::string const& registryKey,
+ std::string const& cpackComponentName,
+ std::string const& suffix);
+
+ void EmitUninstallShortcut(std::string const& packageName);
+
+ std::string EmitComponentCreateFolder(std::string const& directoryId,
+ std::string const& guid,
+ cmInstalledFile const* installedFile);
+
+ std::string EmitComponentFile(std::string const& directoryId,
+ std::string const& id,
+ std::string const& filePath, cmWIXPatch& patch,
+ cmInstalledFile const* installedFile);
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx
new file mode 100644
index 000000000..287a644bb
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXPatch.cxx
@@ -0,0 +1,99 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWIXPatch.h"
+
+#include "cmCPackGenerator.h"
+
+cmWIXPatch::cmWIXPatch(cmCPackLog* logger)
+ : Logger(logger)
+{
+}
+
+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);
+ return false;
+ }
+
+ return true;
+}
+
+void cmWIXPatch::ApplyFragment(std::string const& id,
+ cmWIXSourceWriter& writer)
+{
+ cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id);
+ if (i == Fragments.end())
+ 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);
+ }
+ this->ApplyElementChildren(fragment, writer);
+
+ Fragments.erase(i);
+}
+
+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;
+
+ switch (node->type()) {
+ case cmWIXPatchNode::ELEMENT:
+ ApplyElement(dynamic_cast<const cmWIXPatchElement&>(*node), writer);
+ break;
+ case cmWIXPatchNode::TEXT:
+ writer.AddTextNode(dynamic_cast<const cmWIXPatchText&>(*node).text);
+ break;
+ }
+ }
+}
+
+void cmWIXPatch::ApplyElement(const cmWIXPatchElement& element,
+ cmWIXSourceWriter& writer)
+{
+ 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);
+ }
+
+ this->ApplyElementChildren(element, writer);
+
+ writer.EndElement(element.name);
+}
+
+bool cmWIXPatch::CheckForUnappliedFragments()
+{
+ std::string fragmentList;
+ for (cmWIXPatchParser::fragment_map_t::const_iterator i = Fragments.begin();
+ i != Fragments.end(); ++i) {
+ if (!fragmentList.empty()) {
+ fragmentList += ", ";
+ }
+
+ fragmentList += "'";
+ fragmentList += i->first;
+ fragmentList += "'";
+ }
+
+ if (!fragmentList.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Some XML patch fragments did not have matching IDs: "
+ << fragmentList << std::endl);
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/CPack/WiX/cmWIXPatch.h b/Source/CPack/WiX/cmWIXPatch.h
new file mode 100644
index 000000000..a4c9e714d
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXPatch.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 cmWIXPatch_h
+#define cmWIXPatch_h
+
+#include "cmWIXPatchParser.h"
+#include "cmWIXSourceWriter.h"
+
+#include <string>
+
+/** \class cmWIXPatch
+ * \brief Class that maintains and applies patch fragments
+ */
+class cmWIXPatch
+{
+public:
+ cmWIXPatch(cmCPackLog* logger);
+
+ bool LoadFragments(std::string const& patchFilePath);
+
+ void ApplyFragment(std::string const& id, cmWIXSourceWriter& writer);
+
+ bool CheckForUnappliedFragments();
+
+private:
+ void ApplyElementChildren(const cmWIXPatchElement& element,
+ cmWIXSourceWriter& writer);
+
+ void ApplyElement(const cmWIXPatchElement& element,
+ cmWIXSourceWriter& writer);
+
+ cmCPackLog* Logger;
+
+ cmWIXPatchParser::fragment_map_t Fragments;
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx
new file mode 100644
index 000000000..0dcc74ae0
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXPatchParser.cxx
@@ -0,0 +1,160 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWIXPatchParser.h"
+
+#include "cmCPackGenerator.h"
+
+#include "cm_expat.h"
+
+cmWIXPatchNode::Type cmWIXPatchText::type()
+{
+ return cmWIXPatchNode::TEXT;
+}
+
+cmWIXPatchNode::Type cmWIXPatchElement::type()
+{
+ return cmWIXPatchNode::ELEMENT;
+}
+
+cmWIXPatchNode::~cmWIXPatchNode()
+{
+}
+
+cmWIXPatchElement::~cmWIXPatchElement()
+{
+ for (child_list_t::iterator i = children.begin(); i != children.end(); ++i) {
+ delete *i;
+ }
+}
+
+cmWIXPatchParser::cmWIXPatchParser(fragment_map_t& fragments,
+ cmCPackLog* logger)
+ : Logger(logger)
+ , State(BEGIN_DOCUMENT)
+ , Valid(true)
+ , Fragments(fragments)
+{
+}
+
+void cmWIXPatchParser::StartElement(const std::string& name, const char** atts)
+{
+ if (State == BEGIN_DOCUMENT) {
+ if (name == "CPackWiXPatch") {
+ State = BEGIN_FRAGMENTS;
+ } else {
+ ReportValidationError("Expected root element 'CPackWiXPatch'");
+ }
+ } else if (State == BEGIN_FRAGMENTS) {
+ if (name == "CPackWiXFragment") {
+ State = INSIDE_FRAGMENT;
+ StartFragment(atts);
+ } else {
+ ReportValidationError("Expected 'CPackWixFragment' element");
+ }
+ } else if (State == INSIDE_FRAGMENT) {
+ cmWIXPatchElement& parent = *ElementStack.back();
+
+ cmWIXPatchElement* element = new cmWIXPatchElement;
+ parent.children.push_back(element);
+
+ element->name = name;
+
+ for (size_t i = 0; atts[i]; i += 2) {
+ std::string key = atts[i];
+ std::string value = atts[i + 1];
+
+ element->attributes[key] = value;
+ }
+
+ ElementStack.push_back(element);
+ }
+}
+
+void cmWIXPatchParser::StartFragment(const char** attributes)
+{
+ cmWIXPatchElement* new_element = CM_NULLPTR;
+ /* find the id of for fragment */
+ for (size_t i = 0; attributes[i]; i += 2) {
+ const std::string key = attributes[i];
+ const std::string value = attributes[i + 1];
+
+ if (key == "Id") {
+ if (Fragments.find(value) != Fragments.end()) {
+ std::ostringstream tmp;
+ tmp << "Invalid reuse of 'CPackWixFragment' 'Id': " << value;
+ ReportValidationError(tmp.str());
+ }
+
+ new_element = &Fragments[value];
+ ElementStack.push_back(new_element);
+ }
+ }
+
+ /* add any additional attributes for the fragement */
+ if (!new_element) {
+ ReportValidationError("No 'Id' specified for 'CPackWixFragment' element");
+ } else {
+ for (size_t i = 0; attributes[i]; i += 2) {
+ const std::string key = attributes[i];
+ const std::string value = attributes[i + 1];
+
+ if (key != "Id") {
+ new_element->attributes[key] = value;
+ }
+ }
+ }
+}
+
+void cmWIXPatchParser::EndElement(const std::string& name)
+{
+ if (State == INSIDE_FRAGMENT) {
+ if (name == "CPackWiXFragment") {
+ State = BEGIN_FRAGMENTS;
+ ElementStack.clear();
+ } else {
+ ElementStack.pop_back();
+ }
+ }
+}
+
+void cmWIXPatchParser::CharacterDataHandler(const char* data, int length)
+{
+ const char* whitespace = "\x20\x09\x0d\x0a";
+
+ if (State == INSIDE_FRAGMENT) {
+ cmWIXPatchElement& parent = *ElementStack.back();
+
+ std::string text(data, length);
+
+ std::string::size_type first = text.find_first_not_of(whitespace);
+ std::string::size_type last = text.find_last_not_of(whitespace);
+
+ if (first != std::string::npos && last != std::string::npos) {
+ cmWIXPatchText* text_node = new cmWIXPatchText;
+ text_node->text = text.substr(first, last - first + 1);
+
+ parent.children.push_back(text_node);
+ }
+ }
+}
+
+void cmWIXPatchParser::ReportError(int line, int column, const char* msg)
+{
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while processing XML patch file at "
+ << line << ":" << column << ": " << msg << std::endl);
+ Valid = false;
+}
+
+void cmWIXPatchParser::ReportValidationError(std::string const& message)
+{
+ ReportError(
+ XML_GetCurrentLineNumber(static_cast<XML_Parser>(this->Parser)),
+ XML_GetCurrentColumnNumber(static_cast<XML_Parser>(this->Parser)),
+ message.c_str());
+}
+
+bool cmWIXPatchParser::IsValid() const
+{
+ return Valid;
+}
diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h
new file mode 100644
index 000000000..52c7e3524
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXPatchParser.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 cmCPackWIXPatchParser_h
+#define cmCPackWIXPatchParser_h
+
+#include "cmCPackLog.h"
+
+#include "cmXMLParser.h"
+
+#include <map>
+#include <vector>
+
+struct cmWIXPatchNode
+{
+ enum Type
+ {
+ TEXT,
+ ELEMENT
+ };
+
+ virtual ~cmWIXPatchNode();
+
+ virtual Type type() = 0;
+};
+
+struct cmWIXPatchText : public cmWIXPatchNode
+{
+ virtual Type type();
+
+ std::string text;
+};
+
+struct cmWIXPatchElement : cmWIXPatchNode
+{
+ virtual Type type();
+
+ ~cmWIXPatchElement();
+
+ typedef std::vector<cmWIXPatchNode*> child_list_t;
+ typedef std::map<std::string, std::string> attributes_t;
+
+ std::string name;
+ child_list_t children;
+ attributes_t attributes;
+};
+
+/** \class cmWIXPatchParser
+ * \brief Helper class that parses XML patch files (CPACK_WIX_PATCH_FILE)
+ */
+class cmWIXPatchParser : public cmXMLParser
+{
+public:
+ typedef std::map<std::string, cmWIXPatchElement> fragment_map_t;
+
+ cmWIXPatchParser(fragment_map_t& Fragments, cmCPackLog* logger);
+
+private:
+ virtual void StartElement(const std::string& name, const char** atts);
+
+ void StartFragment(const char** attributes);
+
+ virtual void EndElement(const std::string& name);
+
+ virtual void CharacterDataHandler(const char* data, int length);
+
+ virtual void ReportError(int line, int column, const char* msg);
+
+ void ReportValidationError(std::string const& message);
+
+ bool IsValid() const;
+
+ cmCPackLog* Logger;
+
+ enum ParserState
+ {
+ BEGIN_DOCUMENT,
+ BEGIN_FRAGMENTS,
+ INSIDE_FRAGMENT
+ };
+
+ ParserState State;
+
+ bool Valid;
+
+ fragment_map_t& Fragments;
+
+ std::vector<cmWIXPatchElement*> ElementStack;
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
index 774c22c76..2c99a2284 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
@@ -1,22 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWIXRichTextFormatWriter.h"
-#include <cmVersion.h>
+#include "cmVersion.h"
cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
- const std::string& filename):
- file(filename.c_str(), std::ios::binary)
+ std::string const& filename)
+ : File(filename.c_str(), std::ios::binary)
{
StartGroup();
WriteHeader();
@@ -29,48 +19,58 @@ cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
/* I haven't seen this in the RTF spec but
* wordpad terminates its RTF like this */
- file << "\r\n";
- file.put(0);
+ File << "\r\n";
+ File.put(0);
}
-void cmWIXRichTextFormatWriter::AddText(const std::string& text)
+void cmWIXRichTextFormatWriter::AddText(std::string const& text)
{
typedef unsigned char rtf_byte_t;
- for(size_t i = 0; i < text.size(); ++i)
- {
+ for (size_t i = 0; i < text.size(); ++i) {
rtf_byte_t c = rtf_byte_t(text[i]);
- switch(c)
- {
- case '\\':
- file << "\\\\";
- break;
- case '{':
- file << "\\{";
- break;
- case '}':
- file << "\\}";
- break;
- case '\n':
- file << "\\par\r\n";
- break;
- case '\r':
- continue;
- default:
- {
- if(c <= 0x7F)
- {
- file << c;
- }
- else
- {
- file << "[NON-ASCII-" << int(c) << "]";
+ switch (c) {
+ case '\\':
+ File << "\\\\";
+ break;
+ case '{':
+ File << "\\{";
+ break;
+ case '}':
+ File << "\\}";
+ break;
+ case '\n':
+ File << "\\par\r\n";
+ break;
+ case '\r':
+ continue;
+ default: {
+ if (c <= 0x7F) {
+ File << c;
+ } else {
+ if (c <= 0xC0) {
+ EmitInvalidCodepoint(c);
+ } else if (c < 0xE0 && i + 1 < text.size()) {
+ EmitUnicodeCodepoint((text[i + 1] & 0x3F) | ((c & 0x1F) << 6));
+ i += 1;
+ } else if (c < 0xF0 && i + 2 < text.size()) {
+ EmitUnicodeCodepoint((text[i + 2] & 0x3F) |
+ ((text[i + 1] & 0x3F) << 6) |
+ ((c & 0xF) << 12));
+ i += 2;
+ } else if (c < 0xF8 && i + 3 < text.size()) {
+ EmitUnicodeCodepoint(
+ (text[i + 3] & 0x3F) | ((text[i + 2] & 0x3F) << 6) |
+ ((text[i + 1] & 0x3F) << 12) | ((c & 0x7) << 18));
+ i += 3;
+ } else {
+ EmitInvalidCodepoint(c);
}
}
- break;
- }
+ } break;
}
+ }
}
void cmWIXRichTextFormatWriter::WriteHeader()
@@ -82,6 +82,7 @@ void cmWIXRichTextFormatWriter::WriteHeader()
ControlWord("deflang1031");
WriteFontTable();
+ WriteColorTable();
WriteGenerator();
}
@@ -99,11 +100,27 @@ void cmWIXRichTextFormatWriter::WriteFontTable()
EndGroup();
}
+void cmWIXRichTextFormatWriter::WriteColorTable()
+{
+ StartGroup();
+ ControlWord("colortbl ;");
+ ControlWord("red255");
+ ControlWord("green0");
+ ControlWord("blue0;");
+ ControlWord("red0");
+ ControlWord("green255");
+ ControlWord("blue0;");
+ ControlWord("red0");
+ ControlWord("green0");
+ ControlWord("blue255;");
+ EndGroup();
+}
+
void cmWIXRichTextFormatWriter::WriteGenerator()
{
StartGroup();
NewControlWord("generator");
- file << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
+ File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
EndGroup();
}
@@ -116,22 +133,54 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
ControlWord("fs20");
}
-void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword)
+void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
{
- file << "\\" << keyword;
+ File << "\\" << keyword;
}
-void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword)
+void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword)
{
- file << "\\*\\" << keyword;
+ File << "\\*\\" << keyword;
}
void cmWIXRichTextFormatWriter::StartGroup()
{
- file.put('{');
+ File.put('{');
}
void cmWIXRichTextFormatWriter::EndGroup()
{
- file.put('}');
+ File.put('}');
+}
+
+void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c)
+{
+ // Do not emit byte order mark (BOM)
+ if (c == 0xFEFF) {
+ return;
+ } else if (c <= 0xFFFF) {
+ EmitUnicodeSurrogate(c);
+ } else {
+ c -= 0x10000;
+ EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800);
+ EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00);
+ }
+}
+
+void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c)
+{
+ ControlWord("u");
+ if (c <= 32767) {
+ File << c;
+ } else {
+ File << (c - 65536);
+ }
+ File << "?";
+}
+
+void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c)
+{
+ ControlWord("cf1 ");
+ File << "[INVALID-BYTE-" << int(c) << "]";
+ ControlWord("cf0 ");
}
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
index 10b67c39f..30df87814 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmWIXRichTextFormatWriter_h
#define cmWIXRichTextFormatWriter_h
-#include <fstream>
+#include "cmConfigure.h"
+
+#include "cmsys/FStream.hxx"
+#include <string>
/** \class cmWIXRichtTextFormatWriter
* \brief Helper class to generate Rich Text Format (RTF) documents
@@ -22,25 +15,31 @@
class cmWIXRichTextFormatWriter
{
public:
- cmWIXRichTextFormatWriter(const std::string& filename);
+ cmWIXRichTextFormatWriter(std::string const& filename);
~cmWIXRichTextFormatWriter();
- void AddText(const std::string& text);
+ void AddText(std::string const& text);
private:
void WriteHeader();
void WriteFontTable();
+ void WriteColorTable();
void WriteGenerator();
void WriteDocumentPrefix();
- void ControlWord(const std::string& keyword);
- void NewControlWord(const std::string& keyword);
+ void ControlWord(std::string const& keyword);
+ void NewControlWord(std::string const& keyword);
void StartGroup();
void EndGroup();
- std::ofstream file;
+ void EmitUnicodeCodepoint(int c);
+ void EmitUnicodeSurrogate(int c);
+
+ void EmitInvalidCodepoint(int c);
+
+ cmsys::ofstream File;
};
#endif
diff --git a/Source/CPack/WiX/cmWIXShortcut.cxx b/Source/CPack/WiX/cmWIXShortcut.cxx
new file mode 100644
index 000000000..e5dea94c4
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXShortcut.cxx
@@ -0,0 +1,105 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWIXShortcut.h"
+
+#include "cmWIXFilesSourceWriter.h"
+
+void cmWIXShortcuts::insert(Type type, std::string const& id,
+ cmWIXShortcut const& shortcut)
+{
+ this->Shortcuts[type][id].push_back(shortcut);
+}
+
+bool cmWIXShortcuts::empty(Type type) const
+{
+ return this->Shortcuts.find(type) == this->Shortcuts.end();
+}
+
+bool cmWIXShortcuts::EmitShortcuts(
+ Type type, std::string const& registryKey,
+ std::string const& cpackComponentName,
+ cmWIXFilesSourceWriter& fileDefinitions) const
+{
+ shortcut_type_map_t::const_iterator i = this->Shortcuts.find(type);
+
+ if (i == this->Shortcuts.end()) {
+ return false;
+ }
+
+ shortcut_id_map_t const& id_map = i->second;
+
+ std::string shortcutPrefix;
+ std::string registrySuffix;
+
+ switch (type) {
+ case START_MENU:
+ shortcutPrefix = "CM_S";
+ break;
+ case DESKTOP:
+ shortcutPrefix = "CM_DS";
+ registrySuffix = "_desktop";
+ break;
+ case STARTUP:
+ shortcutPrefix = "CM_SS";
+ registrySuffix = "_startup";
+ break;
+ default:
+ 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 (size_t shortcutListIndex = 0; shortcutListIndex < shortcutList.size();
+ ++shortcutListIndex) {
+ cmWIXShortcut const& shortcut = shortcutList[shortcutListIndex];
+ fileDefinitions.EmitShortcut(id, shortcut, shortcutPrefix,
+ shortcutListIndex);
+ }
+ }
+
+ fileDefinitions.EmitInstallRegistryValue(registryKey, cpackComponentName,
+ registrySuffix);
+
+ return true;
+}
+
+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);
+ }
+}
+
+void cmWIXShortcuts::CreateFromProperties(std::string const& id,
+ std::string const& directoryId,
+ cmInstalledFile const& installedFile)
+{
+ CreateFromProperty("CPACK_START_MENU_SHORTCUTS", START_MENU, id, directoryId,
+ installedFile);
+
+ CreateFromProperty("CPACK_DESKTOP_SHORTCUTS", DESKTOP, id, directoryId,
+ installedFile);
+
+ CreateFromProperty("CPACK_STARTUP_SHORTCUTS", STARTUP, id, directoryId,
+ installedFile);
+}
+
+void cmWIXShortcuts::CreateFromProperty(std::string const& propertyName,
+ Type type, std::string const& id,
+ std::string const& directoryId,
+ cmInstalledFile const& installedFile)
+{
+ std::vector<std::string> list;
+ installedFile.GetPropertyAsList(propertyName, list);
+
+ for (size_t i = 0; i < list.size(); ++i) {
+ cmWIXShortcut shortcut;
+ shortcut.label = list[i];
+ shortcut.workingDirectoryId = directoryId;
+ insert(type, id, shortcut);
+ }
+}
diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h
new file mode 100644
index 000000000..23ddc6a3f
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXShortcut.h
@@ -0,0 +1,60 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmWIXShortcut_h
+#define cmWIXShortcut_h
+
+#include "cmInstalledFile.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmWIXFilesSourceWriter;
+
+struct cmWIXShortcut
+{
+ std::string label;
+ std::string workingDirectoryId;
+};
+
+class cmWIXShortcuts
+{
+public:
+ enum Type
+ {
+ START_MENU,
+ DESKTOP,
+ STARTUP
+ };
+
+ typedef std::vector<cmWIXShortcut> shortcut_list_t;
+ typedef std::map<std::string, shortcut_list_t> shortcut_id_map_t;
+
+ void insert(Type type, std::string const& id, cmWIXShortcut const& shortcut);
+
+ bool empty(Type type) const;
+
+ bool EmitShortcuts(Type type, std::string const& registryKey,
+ std::string const& cpackComponentName,
+ cmWIXFilesSourceWriter& fileDefinitions) const;
+
+ void AddShortcutTypes(std::set<Type>& types);
+
+ void CreateFromProperties(std::string const& id,
+ std::string const& directoryId,
+ cmInstalledFile const& installedFile);
+
+private:
+ typedef std::map<Type, shortcut_id_map_t> shortcut_type_map_t;
+
+ void CreateFromProperty(std::string const& propertyName, Type type,
+ std::string const& id,
+ std::string const& directoryId,
+ cmInstalledFile const& installedFile);
+
+ shortcut_type_map_t Shortcuts;
+ shortcut_id_map_t EmptyIdMap;
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx
index af7ba807f..a86e28d1c 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx
@@ -1,189 +1,184 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWIXSourceWriter.h"
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
+
+#include "cmUuid.h"
#include <windows.h>
cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
- const std::string& filename,
- bool isIncludeFile):
- Logger(logger),
- file(filename.c_str()),
- state(DEFAULT)
+ std::string const& filename,
+ GuidType componentGuidType,
+ RootElementType rootElementType)
+ : Logger(logger)
+ , File(filename.c_str())
+ , State(DEFAULT)
+ , SourceFilename(filename)
+ , ComponentGuidType(componentGuidType)
{
WriteXMLDeclaration();
- if(isIncludeFile)
- {
+ if (rootElementType == INCLUDE_ELEMENT_ROOT) {
BeginElement("Include");
- }
- else
- {
+ } else {
BeginElement("Wix");
- }
+ }
AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi");
}
cmWIXSourceWriter::~cmWIXSourceWriter()
{
- while(elements.size())
- {
- EndElement();
- }
+ if (Elements.size() > 1) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, Elements.size() - 1
+ << " WiX elements were still open when closing '"
+ << SourceFilename << "'" << std::endl);
+ return;
+ }
+
+ EndElement(Elements.back());
}
-void cmWIXSourceWriter::BeginElement(const std::string& name)
+void cmWIXSourceWriter::BeginElement(std::string const& name)
{
- if(state == BEGIN)
- {
- file << ">";
- }
+ if (State == BEGIN) {
+ File << ">";
+ }
- file << "\n";
- Indent(elements.size());
- file << "<" << name;
+ File << "\n";
+ Indent(Elements.size());
+ File << "<" << name;
- elements.push_back(name);
- state = BEGIN;
+ Elements.push_back(name);
+ State = BEGIN;
}
-void cmWIXSourceWriter::EndElement()
+void cmWIXSourceWriter::EndElement(std::string const& name)
{
- if(elements.empty())
- {
+ if (Elements.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "can not end WiX element with no open elements" << std::endl);
+ "can not end WiX element with no open elements in '"
+ << SourceFilename << "'" << std::endl);
return;
- }
-
- if(state == DEFAULT)
- {
- file << "\n";
- Indent(elements.size()-1);
- file << "</" << elements.back() << ">";
- }
- else
- {
- file << "/>";
- }
+ }
- elements.pop_back();
- state = DEFAULT;
+ if (Elements.back() != name) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "WiX element <"
+ << Elements.back() << "> can not be closed by </" << name
+ << "> in '" << SourceFilename << "'" << std::endl);
+ return;
+ }
+
+ if (State == DEFAULT) {
+ File << "\n";
+ Indent(Elements.size() - 1);
+ File << "</" << Elements.back() << ">";
+ } else {
+ File << "/>";
+ }
+
+ Elements.pop_back();
+ State = DEFAULT;
}
-void cmWIXSourceWriter::AddProcessingInstruction(
- const std::string& target, const std::string& content)
+void cmWIXSourceWriter::AddTextNode(std::string const& text)
{
- if(state == BEGIN)
- {
- file << ">";
- }
+ if (State == BEGIN) {
+ File << ">";
+ }
- file << "\n";
- Indent(elements.size());
- file << "<?" << target << " " << content << "?>";
+ if (Elements.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "can not add text without open WiX element in '"
+ << SourceFilename << "'" << std::endl);
+ return;
+ }
- state = DEFAULT;
+ File << this->EscapeAttributeValue(text);
+ State = DEFAULT;
}
-void cmWIXSourceWriter::AddAttribute(
- const std::string& key, const std::string& value)
+void cmWIXSourceWriter::AddProcessingInstruction(std::string const& target,
+ std::string const& content)
{
- std::string utf8 = WindowsCodepageToUtf8(value);
+ if (State == BEGIN) {
+ File << ">";
+ }
- file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"';
+ File << "\n";
+ Indent(Elements.size());
+ File << "<?" << target << " " << content << "?>";
+
+ State = DEFAULT;
}
-std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value)
+void cmWIXSourceWriter::AddAttribute(std::string const& key,
+ std::string const& value)
{
- if(value.empty())
- {
- return std::string();
- }
-
- int characterCount = MultiByteToWideChar(
- CP_ACP, 0, value.c_str(), static_cast<int>(value.size()), 0, 0);
-
- if(characterCount == 0)
- {
- return std::string();
- }
-
- std::vector<wchar_t> utf16(characterCount);
-
- MultiByteToWideChar(
- CP_ACP, 0, value.c_str(), static_cast<int>(value.size()),
- &utf16[0], static_cast<int>(utf16.size()));
-
- int utf8ByteCount = WideCharToMultiByte(
- CP_UTF8, 0, &utf16[0], static_cast<int>(utf16.size()), 0, 0, 0, 0);
-
- if(utf8ByteCount == 0)
- {
- return std::string();
- }
-
- std::vector<char> utf8(utf8ByteCount);
-
- WideCharToMultiByte(CP_UTF8, 0, &utf16[0], static_cast<int>(utf16.size()),
- &utf8[0], static_cast<int>(utf8.size()), 0, 0);
+ File << " " << key << "=\"" << EscapeAttributeValue(value) << '"';
+}
- return std::string(&utf8[0], utf8.size());
+void cmWIXSourceWriter::AddAttributeUnlessEmpty(std::string const& key,
+ std::string const& value)
+{
+ if (!value.empty()) {
+ AddAttribute(key, value);
+ }
}
+std::string cmWIXSourceWriter::CreateGuidFromComponentId(
+ std::string const& componentId)
+{
+ std::string guid = "*";
+ if (this->ComponentGuidType == CMAKE_GENERATED_GUID) {
+ std::string md5 = cmSystemTools::ComputeStringMD5(componentId);
+ cmUuid uuid;
+ std::vector<unsigned char> ns;
+ guid = uuid.FromMd5(ns, md5);
+ }
+ return guid;
+}
void cmWIXSourceWriter::WriteXMLDeclaration()
{
- file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+ File << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
}
void cmWIXSourceWriter::Indent(size_t count)
{
- for(size_t i = 0; i < count; ++i)
- {
- file << " ";
- }
+ for (size_t i = 0; i < count; ++i) {
+ File << " ";
+ }
}
-std::string cmWIXSourceWriter::EscapeAttributeValue(
- const std::string& value)
+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)
- {
+ for (size_t i = 0; i < value.size(); ++i) {
c = value[i];
- switch(c)
- {
- case '<':
- result += "&lt;";
- break;
- case '&':
- result +="&amp;";
- break;
- case '"':
- result += "&quot;";
- break;
- default:
- result += c;
- break;
- }
+ switch (c) {
+ case '<':
+ result += "&lt;";
+ break;
+ case '>':
+ result += "&gt;";
+ break;
+ case '&':
+ result += "&amp;";
+ break;
+ case '"':
+ result += "&quot;";
+ break;
+ default:
+ result += c;
+ break;
}
+ }
return result;
}
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h
index 1dafc1ff2..4af1ed6ed 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXSourceWriter.h
@@ -1,23 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmWIXSourceWriter_h
#define cmWIXSourceWriter_h
-#include <vector>
-#include <string>
-#include <fstream>
+#include "cmCPackLog.h"
-#include <CPack/cmCPackLog.h>
+#include "cmsys/FStream.hxx"
+
+#include <string>
+#include <vector>
/** \class cmWIXSourceWriter
* \brief Helper class to generate XML WiX source files
@@ -25,22 +16,42 @@
class cmWIXSourceWriter
{
public:
- cmWIXSourceWriter(cmCPackLog* logger,
- const std::string& filename, bool isIncludeFile = false);
+ enum GuidType
+ {
+ WIX_GENERATED_GUID,
+ CMAKE_GENERATED_GUID
+ };
+
+ enum RootElementType
+ {
+ WIX_ELEMENT_ROOT,
+ INCLUDE_ELEMENT_ROOT
+ };
+
+ cmWIXSourceWriter(cmCPackLog* logger, std::string const& filename,
+ GuidType componentGuidType,
+ RootElementType rootElementType = WIX_ELEMENT_ROOT);
~cmWIXSourceWriter();
- void BeginElement(const std::string& name);
+ void BeginElement(std::string const& name);
+
+ void EndElement(std::string const& name);
- void EndElement();
+ void AddTextNode(std::string const& text);
- void AddProcessingInstruction(
- const std::string& target, const std::string& content);
+ void AddProcessingInstruction(std::string const& target,
+ std::string const& content);
- void AddAttribute(
- const std::string& key, const std::string& value);
+ void AddAttribute(std::string const& key, std::string const& value);
- static std::string WindowsCodepageToUtf8(const std::string& value);
+ void AddAttributeUnlessEmpty(std::string const& key,
+ std::string const& value);
+
+ std::string CreateGuidFromComponentId(std::string const& componentId);
+
+protected:
+ cmCPackLog* Logger;
private:
enum State
@@ -53,15 +64,17 @@ private:
void Indent(size_t count);
- static std::string EscapeAttributeValue(const std::string& value);
+ static std::string EscapeAttributeValue(std::string const& value);
- cmCPackLog* Logger;
+ cmsys::ofstream File;
+
+ State State;
- std::ofstream file;
+ std::vector<std::string> Elements;
- State state;
+ std::string SourceFilename;
- std::vector<std::string> elements;
+ GuidType ComponentGuidType;
};
#endif
diff --git a/Source/CPack/cmCPack7zGenerator.cxx b/Source/CPack/cmCPack7zGenerator.cxx
new file mode 100644
index 000000000..f0c41a2a1
--- /dev/null
+++ b/Source/CPack/cmCPack7zGenerator.cxx
@@ -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. */
+#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
new file mode 100644
index 000000000..42a47810c
--- /dev/null
+++ b/Source/CPack/cmCPack7zGenerator.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 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 6e7b8d7c8..575c94924 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -1,86 +1,91 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackArchiveGenerator.h"
-#include "cmake.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
-#include <errno.h>
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Directory.hxx>
-#include <cm_libarchive.h>
+#include <map>
+#include <ostream>
+#include <utility>
+#include <vector>
-//----------------------------------------------------------------------
cmCPackArchiveGenerator::cmCPackArchiveGenerator(cmArchiveWrite::Compress t,
- cmArchiveWrite::Type at)
+ std::string const& format)
{
this->Compress = t;
- this->Archive = at;
+ this->ArchiveFormat = format;
}
-//----------------------------------------------------------------------
cmCPackArchiveGenerator::~cmCPackArchiveGenerator()
{
}
-//----------------------------------------------------------------------
+std::string cmCPackArchiveGenerator::GetArchiveComponentFileName(
+ const std::string& component, bool isGroupName)
+{
+ std::string componentUpper(cmSystemTools::UpperCase(component));
+ std::string packageFileName;
+
+ if (this->IsSet("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME")) {
+ packageFileName +=
+ this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME");
+ } else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
+ packageFileName += GetComponentPackageFileName(
+ this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName);
+ } else {
+ packageFileName += GetComponentPackageFileName(
+ this->GetOption("CPACK_PACKAGE_FILE_NAME"), component, isGroupName);
+ }
+
+ packageFileName += this->GetOutputExtension();
+
+ return packageFileName;
+}
+
int cmCPackArchiveGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
-int cmCPackArchiveGenerator::addOneComponentToArchive(cmArchiveWrite& archive,
- cmCPackComponent* component)
+int cmCPackArchiveGenerator::addOneComponentToArchive(
+ cmArchiveWrite& archive, cmCPackComponent* component)
{
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, " - packaging component: "
- << component->Name
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ " - packaging component: " << component->Name << std::endl);
// Add the files of this component to the archive
std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- localToplevel += "/"+ component->Name;
- std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
+ localToplevel += "/" + component->Name;
// Change to local toplevel
- cmSystemTools::ChangeDirectory(localToplevel.c_str());
+ cmWorkingDirectory workdir(localToplevel);
std::string filePrefix;
- if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY"))
- {
+ if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
filePrefix += "/";
- }
+ }
+ const char* installPrefix =
+ this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ if (installPrefix && installPrefix[0] == '/' && installPrefix[1] != 0) {
+ // add to file prefix and remove the leading '/'
+ filePrefix += installPrefix + 1;
+ filePrefix += "/";
+ }
std::vector<std::string>::const_iterator fileIt;
for (fileIt = component->Files.begin(); fileIt != component->Files.end();
- ++fileIt )
- {
+ ++fileIt) {
std::string rp = filePrefix + *fileIt;
- cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding file: "
- << rp << std::endl);
- archive.Add(rp);
- if (!archive)
- {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file: " << rp << std::endl);
+ archive.Add(rp, 0, CM_NULLPTR, false);
+ if (!archive) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging files: "
- << archive.GetError()
- << std::endl);
+ << archive.GetError() << std::endl);
return 0;
- }
}
- // Go back to previous dir
- cmSystemTools::ChangeDirectory(dir.c_str());
+ }
return 1;
}
@@ -89,226 +94,188 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(cmArchiveWrite& archive,
* an declare and open the associated
* cmArchiveWrite 'archive' object.
*/
-#define DECLARE_AND_OPEN_ARCHIVE(filename,archive) \
-cmGeneratedFileStream gf; \
-gf.Open(filename.c_str(), false, true); \
-if (!GenerateHeader(&gf)) \
- { \
- cmCPackLogger(cmCPackLog::LOG_ERROR, \
- "Problem to generate Header for archive < " \
- << filename \
- << ">." << std::endl); \
- return 0; \
- } \
-cmArchiveWrite archive(gf,this->Compress, this->Archive); \
-if (!archive) \
- { \
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem to create archive < " \
- << filename \
- << ">. ERROR =" \
- << archive.GetError() \
- << std::endl); \
- return 0; \
+#define DECLARE_AND_OPEN_ARCHIVE(filename, archive) \
+ cmGeneratedFileStream gf; \
+ gf.Open((filename).c_str(), false, true); \
+ if (!GenerateHeader(&gf)) { \
+ cmCPackLogger(cmCPackLog::LOG_ERROR, \
+ "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; \
}
-//----------------------------------------------------------------------
int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
{
packageFileNames.clear();
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
- if (!ignoreGroup)
- {
+ if (!ignoreGroup) {
std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
- for (compGIt=this->ComponentGroups.begin();
- compGIt!=this->ComponentGroups.end(); ++compGIt)
- {
+ for (compGIt = this->ComponentGroups.begin();
+ compGIt != this->ComponentGroups.end(); ++compGIt) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first
- << std::endl);
+ << compGIt->first << std::endl);
// Begin the archive for this group
- std::string packageFileName= std::string(toplevel);
- packageFileName += "/"+
- GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- compGIt->first,
- true)
- + this->GetOutputExtension();
+ std::string packageFileName = std::string(toplevel) + "/" +
+ this->GetArchiveComponentFileName(compGIt->first, true);
+
// open a block in order to automatically close archive
// at the end of the block
{
- DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive);
+ 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 (compIt = (compGIt->second).Components.begin();
+ compIt != (compGIt->second).Components.end(); ++compIt) {
// Add the files of this component to the archive
- addOneComponentToArchive(archive,*compIt);
- }
+ addOneComponentToArchive(archive, *compIt);
+ }
}
// add the generated package to package file names list
packageFileNames.push_back(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 (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
// Does the component belong to a group?
- if (compIt->second.Group==NULL)
- {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Component <"
- << compIt->second.Name
- << "> does not belong to any group, package it separately."
- << std::endl);
+ if (compIt->second.Group == CM_NULLPTR) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE, "Component <"
+ << compIt->second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
std::string localToplevel(
- this->GetOption("CPACK_TEMPORARY_DIRECTORY")
- );
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
std::string packageFileName = std::string(toplevel);
- localToplevel += "/"+ compIt->first;
- packageFileName += "/"+
- GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- compIt->first,
- false)
- + this->GetOutputExtension();
+ localToplevel += "/" + compIt->first;
+ packageFileName +=
+ "/" + this->GetArchiveComponentFileName(compIt->first, false);
+
{
- DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive);
+ DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// Add the files of this component to the archive
- addOneComponentToArchive(archive,&(compIt->second));
+ addOneComponentToArchive(archive, &(compIt->second));
}
// add the generated package to package file names list
packageFileNames.push_back(packageFileName);
- }
}
}
+ }
// CPACK_COMPONENTS_IGNORE_GROUPS is set
// We build 1 package per component
- else
- {
+ else {
std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt=this->Components.begin();
- compIt!=this->Components.end(); ++compIt )
- {
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
std::string packageFileName = std::string(toplevel);
- localToplevel += "/"+ compIt->first;
- packageFileName += "/"+
- GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- compIt->first,
- false)
- + this->GetOutputExtension();
+ localToplevel += "/" + compIt->first;
+ packageFileName +=
+ "/" + this->GetArchiveComponentFileName(compIt->first, false);
+
{
- DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive);
+ DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// Add the files of this component to the archive
- addOneComponentToArchive(archive,&(compIt->second));
+ addOneComponentToArchive(archive, &(compIt->second));
}
// add the generated package to package file names list
packageFileNames.push_back(packageFileName);
- }
}
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCPackArchiveGenerator::PackageComponentsAllInOne()
{
// reset the package file names
packageFileNames.clear();
packageFileNames.push_back(std::string(toplevel));
- packageFileNames[0] += "/"
- +std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
- + this->GetOutputExtension();
+ packageFileNames[0] += "/";
+
+ if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
+ packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME");
+ } else {
+ packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ }
+
+ packageFileNames[0] += this->GetOutputExtension();
+
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging all groups in one package..."
"(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE is set)"
- << std::endl);
- DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive);
+ << std::endl);
+ 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 (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
// Add the files of this component to the archive
- addOneComponentToArchive(archive,&(compIt->second));
- }
+ addOneComponentToArchive(archive, &(compIt->second));
+ }
// archive goes out of scope so it will finalized and closed.
return 1;
}
-//----------------------------------------------------------------------
int cmCPackArchiveGenerator::PackageFiles()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
- << toplevel << std::endl);
+ 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)
- {
+ 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.
- else
- {
- return PackageComponents(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
- }
+ return PackageComponents(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
// CASE 3 : NON COMPONENT package.
- DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive);
+ DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
std::vector<std::string>::const_iterator fileIt;
- std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(toplevel.c_str());
- for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
- {
+ cmWorkingDirectory workdir(toplevel);
+ for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
// Get the relative path to the file
- std::string rp = cmSystemTools::RelativePath(toplevel.c_str(),
- fileIt->c_str());
- archive.Add(rp);
- if(!archive)
- {
+ std::string rp =
+ cmSystemTools::RelativePath(toplevel.c_str(), fileIt->c_str());
+ archive.Add(rp, 0, CM_NULLPTR, false);
+ if (!archive) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< "
- << *fileIt
- << "> to archive <"
- << packageFileNames[0] << "> .ERROR ="
- << archive.GetError()
- << std::endl);
+ << *fileIt << "> to archive <" << packageFileNames[0]
+ << "> .ERROR =" << archive.GetError() << std::endl);
return 0;
- }
}
- cmSystemTools::ChangeDirectory(dir.c_str());
+ }
// The destructor of cmArchiveWrite will close and finish the write
return 1;
}
-//----------------------------------------------------------------------
-int cmCPackArchiveGenerator::GenerateHeader(std::ostream*)
+int cmCPackArchiveGenerator::GenerateHeader(std::ostream* /*unused*/)
{
return 1;
}
-bool cmCPackArchiveGenerator::SupportsComponentInstallation() const {
+bool cmCPackArchiveGenerator::SupportsComponentInstallation() const
+{
// The Component installation support should only
// be activated if explicitly requested by the user
// (for backward compatibility reason)
- if (IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL"))
- {
- return true;
- }
- else
- {
- return false;
- }
+ return IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL");
}
diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h
index 6411b1ebf..e7116c466 100644
--- a/Source/CPack/cmCPackArchiveGenerator.h
+++ b/Source/CPack/cmCPackArchiveGenerator.h
@@ -1,21 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackArchiveGenerator_h
#define cmCPackArchiveGenerator_h
+#include "cmConfigure.h"
+
#include "cmArchiveWrite.h"
#include "cmCPackGenerator.h"
+#include <iosfwd>
+#include <string>
+
+class cmCPackComponent;
/** \class cmCPackArchiveGenerator
* \brief A generator base for libarchive generation.
@@ -24,21 +20,27 @@
*
*/
class cmCPackArchiveGenerator : public cmCPackGenerator
- {
+{
public:
- cmTypeMacro(cmCPackArchiveGenerator, cmCPackGenerator);
+ typedef cmCPackGenerator Superclass;
/**
* Construct generator
*/
- cmCPackArchiveGenerator(cmArchiveWrite::Compress, cmArchiveWrite::Type);
- virtual ~cmCPackArchiveGenerator();
+ cmCPackArchiveGenerator(cmArchiveWrite::Compress, std::string const& format);
+ ~cmCPackArchiveGenerator() CM_OVERRIDE;
// Used to add a header to the archive
virtual int GenerateHeader(std::ostream* os);
// component support
- virtual bool SupportsComponentInstallation() const;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
+
+private:
+ // get archive component filename
+ std::string GetArchiveComponentFileName(const std::string& component,
+ bool isGroupName);
+
protected:
- virtual int InitializeInternal();
+ int InitializeInternal() CM_OVERRIDE;
/**
* Add the files belonging to the specified component
* to the provided (already opened) archive.
@@ -54,7 +56,7 @@ protected:
* method will call either PackageComponents or
* PackageComponentsAllInOne.
*/
- int PackageFiles();
+ int PackageFiles() CM_OVERRIDE;
/**
* The method used to package files when component
* install is used. This will create one
@@ -66,9 +68,9 @@ protected:
* components will be put in a single installer.
*/
int PackageComponentsAllInOne();
- virtual const char* GetOutputExtension() = 0;
+ const char* GetOutputExtension() CM_OVERRIDE = 0;
cmArchiveWrite::Compress Compress;
- cmArchiveWrite::Type Archive;
- };
+ std::string ArchiveFormat;
+};
#endif
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx
index 6c994f13f..d5389014a 100644
--- a/Source/CPack/cmCPackBundleGenerator.cxx
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -1,48 +1,47 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackBundleGenerator.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include <sstream>
+#include <vector>
-#include "cmCPackBundleGenerator.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
-#include <cmsys/RegularExpression.hxx>
-
-//----------------------------------------------------------------------
cmCPackBundleGenerator::cmCPackBundleGenerator()
{
}
-//----------------------------------------------------------------------
cmCPackBundleGenerator::~cmCPackBundleGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackBundleGenerator::InitializeInternal()
{
const char* name = this->GetOption("CPACK_BUNDLE_NAME");
- if(0 == name)
- {
+ if (0 == name) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPACK_BUNDLE_NAME must be set to use the Bundle generator."
- << std::endl);
+ "CPACK_BUNDLE_NAME must be set to use the Bundle generator."
+ << std::endl);
return 0;
+ }
+
+ if (this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")) {
+ const std::string codesign_path = cmSystemTools::FindProgram(
+ "codesign", std::vector<std::string>(), false);
+
+ if (codesign_path.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate codesign command"
+ << std::endl);
+ return 0;
}
+ this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path.c_str());
+ }
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
{
this->InstallPrefix = "/";
@@ -52,118 +51,129 @@ const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
return this->InstallPrefix.c_str();
}
-//----------------------------------------------------------------------
-int cmCPackBundleGenerator::PackageFiles()
+int cmCPackBundleGenerator::ConstructBundle()
{
// Get required arguments ...
const std::string cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME")
- ? this->GetOption("CPACK_BUNDLE_NAME") : "";
- if(cpack_bundle_name.empty())
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPACK_BUNDLE_NAME must be set."
- << std::endl);
+ ? this->GetOption("CPACK_BUNDLE_NAME")
+ : "";
+ if (cpack_bundle_name.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set."
+ << std::endl);
return 0;
- }
+ }
const std::string cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST")
- ? this->GetOption("CPACK_BUNDLE_PLIST") : "";
- if(cpack_bundle_plist.empty())
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPACK_BUNDLE_PLIST must be set."
- << std::endl);
+ ? this->GetOption("CPACK_BUNDLE_PLIST")
+ : "";
+ if (cpack_bundle_plist.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set."
+ << std::endl);
return 0;
- }
+ }
const std::string cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON")
- ? this->GetOption("CPACK_BUNDLE_ICON") : "";
- if(cpack_bundle_icon.empty())
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPACK_BUNDLE_ICON must be set."
- << std::endl);
+ ? this->GetOption("CPACK_BUNDLE_ICON")
+ : "";
+ if (cpack_bundle_icon.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set."
+ << std::endl);
return 0;
- }
+ }
// Get optional arguments ...
const std::string cpack_bundle_startup_command =
this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND")
- ? this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND") : "";
+ ? this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND")
+ : "";
// The staging directory contains everything that will end-up inside the
// final disk image ...
- cmOStringStream staging;
+ std::ostringstream staging;
staging << toplevel;
- cmOStringStream contents;
- contents << staging.str() << "/" << cpack_bundle_name
- << ".app/" << "Contents";
+ std::ostringstream contents;
+ contents << staging.str() << "/" << cpack_bundle_name << ".app/"
+ << "Contents";
- cmOStringStream application;
- application << contents.str() << "/" << "MacOS";
+ std::ostringstream application;
+ application << contents.str() << "/"
+ << "MacOS";
- cmOStringStream resources;
- resources << contents.str() << "/" << "Resources";
+ std::ostringstream resources;
+ resources << contents.str() << "/"
+ << "Resources";
// Install a required, user-provided bundle metadata file ...
- cmOStringStream plist_source;
+ std::ostringstream plist_source;
plist_source << cpack_bundle_plist;
- cmOStringStream plist_target;
- plist_target << contents.str() << "/" << "Info.plist";
+ std::ostringstream plist_target;
+ plist_target << contents.str() << "/"
+ << "Info.plist";
- if(!this->CopyFile(plist_source, plist_target))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ if (!this->CopyFile(plist_source, plist_target)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"Error copying plist. Check the value of CPACK_BUNDLE_PLIST."
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
// Install a user-provided bundle icon ...
- cmOStringStream icon_source;
+ std::ostringstream icon_source;
icon_source << cpack_bundle_icon;
- cmOStringStream icon_target;
+ std::ostringstream icon_target;
icon_target << resources.str() << "/" << cpack_bundle_name << ".icns";
- if(!this->CopyFile(icon_source, icon_target))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ if (!this->CopyFile(icon_source, icon_target)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"Error copying bundle icon. Check the value of CPACK_BUNDLE_ICON."
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
// Optionally a user-provided startup command (could be an
// executable or a script) ...
- if(!cpack_bundle_startup_command.empty())
- {
- cmOStringStream command_source;
+ if (!cpack_bundle_startup_command.empty()) {
+ std::ostringstream command_source;
command_source << cpack_bundle_startup_command;
- cmOStringStream command_target;
+ std::ostringstream command_target;
command_target << application.str() << "/" << cpack_bundle_name;
- if(!this->CopyFile(command_source, command_target))
- {
+ if (!this->CopyFile(command_source, command_target)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error copying startup command. "
" Check the value of CPACK_BUNDLE_STARTUP_COMMAND."
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
cmSystemTools::SetPermissions(command_target.str().c_str(), 0777);
- }
+ }
+
+ return 1;
+}
+
+int cmCPackBundleGenerator::PackageFiles()
+{
+ if (!this->ConstructBundle()) {
+ return 0;
+ }
+
+ if (!this->SignBundle(toplevel)) {
+ return 0;
+ }
return this->CreateDMG(toplevel, packageFileNames[0]);
}
@@ -172,3 +182,102 @@ bool cmCPackBundleGenerator::SupportsComponentInstallation() const
{
return false;
}
+
+int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
+{
+ const std::string cpack_apple_cert_app =
+ this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")
+ ? this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")
+ : "";
+
+ // codesign the application.
+ 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";
+
+ // A list of additional files to sign, ie. frameworks and plugins.
+ const std::string sign_parameter =
+ this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
+ ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
+ : "--deep -f";
+
+ const std::string sign_files =
+ this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES")
+ ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES")
+ : "";
+
+ std::vector<std::string> relFiles;
+ cmSystemTools::ExpandListArgument(sign_files, relFiles);
+
+ // sign the files supplied by the user, ie. frameworks.
+ for (std::vector<std::string>::iterator it = relFiles.begin();
+ it != relFiles.end(); ++it) {
+ std::ostringstream temp_sign_file_cmd;
+ temp_sign_file_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+ temp_sign_file_cmd << " " << sign_parameter << " -s \""
+ << cpack_apple_cert_app;
+ temp_sign_file_cmd << "\" -i ";
+ 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 << "\"";
+
+ if (!this->RunCommand(temp_sign_file_cmd, &output)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error signing file:" << bundle_path << *it << std::endl
+ << output << std::endl);
+
+ return 0;
+ }
+ }
+
+ // sign main binary
+ std::ostringstream temp_sign_binary_cmd;
+ temp_sign_binary_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+ temp_sign_binary_cmd << " " << sign_parameter << " -s \""
+ << cpack_apple_cert_app;
+ temp_sign_binary_cmd << "\" \"" << bundle_path << "\"";
+
+ if (!this->RunCommand(temp_sign_binary_cmd, &output)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error signing the application binary." << std::endl
+ << output
+ << std::endl);
+
+ return 0;
+ }
+
+ // sign app bundle
+ std::ostringstream temp_codesign_cmd;
+ temp_codesign_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+ temp_codesign_cmd << " " << sign_parameter << " -s \""
+ << cpack_apple_cert_app << "\"";
+ if (this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")) {
+ temp_codesign_cmd << " --entitlements ";
+ temp_codesign_cmd << this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS");
+ }
+ temp_codesign_cmd << " \"" << bundle_path << "\"";
+
+ if (!this->RunCommand(temp_codesign_cmd, &output)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error signing the application package." << std::endl
+ << output
+ << std::endl);
+
+ return 0;
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Application has been codesigned"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ (this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")
+ ? "with entitlement sandboxing"
+ : "without entitlement sandboxing")
+ << std::endl);
+ }
+
+ return 1;
+}
diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h
index ed0187dd4..861fe4b09 100644
--- a/Source/CPack/cmCPackBundleGenerator.h
+++ b/Source/CPack/cmCPackBundleGenerator.h
@@ -1,19 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackBundleGenerator_h
#define cmCPackBundleGenerator_h
+#include "cmConfigure.h"
+
+#include <string>
+
#include "cmCPackDragNDropGenerator.h"
+#include "cmCPackGenerator.h"
/** \class cmCPackBundleGenerator
* \brief A generator for OSX bundles
@@ -29,10 +24,12 @@ public:
virtual ~cmCPackBundleGenerator();
protected:
- virtual int InitializeInternal();
- virtual const char* GetPackagingInstallPrefix();
- int PackageFiles();
- bool SupportsComponentInstallation() const;
+ int InitializeInternal() CM_OVERRIDE;
+ const char* GetPackagingInstallPrefix() CM_OVERRIDE;
+ int ConstructBundle();
+ int SignBundle(const std::string& src_dir);
+ int PackageFiles() CM_OVERRIDE;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
std::string InstallPrefix;
};
diff --git a/Source/CPack/cmCPackComponentGroup.cxx b/Source/CPack/cmCPackComponentGroup.cxx
index f93eca823..e39398ad5 100644
--- a/Source/CPack/cmCPackComponentGroup.cxx
+++ b/Source/CPack/cmCPackComponentGroup.cxx
@@ -1,44 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackComponentGroup.h"
+
#include "cmSystemTools.h"
-#include <vector>
+
#include <string>
+#include <vector>
-//----------------------------------------------------------------------
-unsigned long cmCPackComponent::GetInstalledSize(const char* installDir) const
+unsigned long cmCPackComponent::GetInstalledSize(
+ const std::string& installDir) const
{
- if (this->TotalSize != 0)
- {
+ if (this->TotalSize != 0) {
return this->TotalSize;
- }
+ }
std::vector<std::string>::const_iterator fileIt;
- for (fileIt = this->Files.begin(); fileIt != this->Files.end(); ++fileIt)
- {
+ for (fileIt = this->Files.begin(); fileIt != this->Files.end(); ++fileIt) {
std::string path = installDir;
path += '/';
path += *fileIt;
- this->TotalSize += cmSystemTools::FileLength(path.c_str());
- }
+ this->TotalSize += cmSystemTools::FileLength(path);
+ }
return this->TotalSize;
}
-//----------------------------------------------------------------------
-unsigned long
-cmCPackComponent::GetInstalledSizeInKbytes(const char* installDir) const
+unsigned long cmCPackComponent::GetInstalledSizeInKbytes(
+ const std::string& installDir) const
{
unsigned long result = (GetInstalledSize(installDir) + 512) / 1024;
- return result? result : 1;
+ return result ? result : 1;
}
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index abae3724e..26d69ba68 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackComponentGroup_h
#define cmCPackComponentGroup_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
class cmCPackComponentGroup;
@@ -42,9 +35,15 @@ public:
class cmCPackComponent
{
public:
- cmCPackComponent() : Group(0), IsRequired(true), IsHidden(false),
- IsDisabledByDefault(false), IsDownloaded(false),
- TotalSize(0) { }
+ cmCPackComponent()
+ : Group(CM_NULLPTR)
+ , IsRequired(true)
+ , IsHidden(false)
+ , IsDisabledByDefault(false)
+ , IsDownloaded(false)
+ , TotalSize(0)
+ {
+ }
/// The name of the component (used to reference the component).
std::string Name;
@@ -53,7 +52,7 @@ public:
std::string DisplayName;
/// The component group that contains this component (if any).
- cmCPackComponentGroup *Group;
+ cmCPackComponentGroup* Group;
/// Whether this component group must always be installed.
bool IsRequired : 1;
@@ -73,17 +72,21 @@ public:
std::string Description;
/// The installation types that this component is a part of.
- std::vector<cmCPackInstallationType *> InstallationTypes;
+ std::vector<cmCPackInstallationType*> InstallationTypes;
/// If IsDownloaded is true, the name of the archive file that
/// contains the files that are part of this component.
std::string ArchiveFile;
+ /// The file to pass to --component-plist when using the
+ /// productbuild generator.
+ std::string Plist;
+
/// The components that this component depends on.
- std::vector<cmCPackComponent *> Dependencies;
+ std::vector<cmCPackComponent*> Dependencies;
/// The components that depend on this component.
- std::vector<cmCPackComponent *> ReverseDependencies;
+ std::vector<cmCPackComponent*> ReverseDependencies;
/// The list of installed files that are part of this component.
std::vector<std::string> Files;
@@ -94,13 +97,13 @@ public:
/// Get the total installed size of all of the files in this
/// component, in bytes. installDir is the directory into which the
/// component was installed.
- unsigned long GetInstalledSize(const char* installDir) const;
+ unsigned long GetInstalledSize(const std::string& installDir) const;
/// Identical to GetInstalledSize, but returns the result in
/// kilobytes.
- unsigned long GetInstalledSizeInKbytes(const char* installDir) const;
+ unsigned long GetInstalledSizeInKbytes(const std::string& installDir) const;
- private:
+private:
mutable unsigned long TotalSize;
};
@@ -110,7 +113,10 @@ public:
class cmCPackComponentGroup
{
public:
- cmCPackComponentGroup() : ParentGroup(0) { }
+ cmCPackComponentGroup()
+ : ParentGroup(CM_NULLPTR)
+ {
+ }
/// The name of the group (used to reference the group).
std::string Name;
@@ -131,7 +137,7 @@ public:
std::vector<cmCPackComponent*> Components;
/// The parent group of this component group (if any).
- cmCPackComponentGroup *ParentGroup;
+ cmCPackComponentGroup* ParentGroup;
/// The subgroups of this group.
std::vector<cmCPackComponentGroup*> Subgroups;
diff --git a/Source/CPack/cmCPackConfigure.h.in b/Source/CPack/cmCPackConfigure.h.in
index 3d7702e1a..8ac1661ec 100644
--- a/Source/CPack/cmCPackConfigure.h.in
+++ b/Source/CPack/cmCPackConfigure.h.in
@@ -1,11 +1,2 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index 6605f16e0..2119f782b 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -1,38 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackCygwinBinaryGenerator.h"
-#include "cmake.h"
+#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/SystemTools.hxx"
-//----------------------------------------------------------------------
cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator()
{
}
-//----------------------------------------------------------------------
cmCPackCygwinBinaryGenerator::~cmCPackCygwinBinaryGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackCygwinBinaryGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
@@ -40,7 +26,6 @@ int cmCPackCygwinBinaryGenerator::InitializeInternal()
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
int cmCPackCygwinBinaryGenerator::PackageFiles()
{
std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
@@ -50,8 +35,7 @@ int cmCPackCygwinBinaryGenerator::PackageFiles()
std::string manifest = "/usr/share/doc/";
manifest += packageName;
manifest += "/MANIFEST";
- std::string manifestFile
- = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ std::string manifestFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
// Create a MANIFEST file that contains all of the files in
// the tar file
std::string tempdir = manifestFile;
@@ -59,14 +43,13 @@ int cmCPackCygwinBinaryGenerator::PackageFiles()
// create an extra scope to force the stream
// 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)
- {
- // remove the temp dir and replace with /usr
- ofs << (*i).substr(tempdir.size()) << "\n";
+ cmGeneratedFileStream ofs(manifestFile.c_str());
+ for (std::vector<std::string>::const_iterator i = files.begin();
+ i != files.end(); ++i) {
+ // remove the temp dir and replace with /usr
+ ofs << (*i).substr(tempdir.size()) << "\n";
}
- ofs << manifest << "\n";
+ ofs << manifest << "\n";
}
// add the manifest file to the list of all files
files.push_back(manifestFile);
@@ -78,14 +61,13 @@ int cmCPackCygwinBinaryGenerator::PackageFiles()
const char* cmCPackCygwinBinaryGenerator::GetOutputExtension()
{
this->OutputExtension = "-";
- const char* patchNumber =this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
- if(!patchNumber)
- {
+ const char* patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
+ if (!patchNumber) {
patchNumber = "1";
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_CYGWIN_PATCH_NUMBER not specified using 1"
- << std::endl);
- }
+ << std::endl);
+ }
this->OutputExtension += patchNumber;
this->OutputExtension += ".tar.bz2";
return this->OutputExtension.c_str();
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.h b/Source/CPack/cmCPackCygwinBinaryGenerator.h
index 38f6df17d..58e80bda7 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.h
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.h
@@ -1,15 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackCygwinBinaryGenerator_h
#define cmCPackCygwinBinaryGenerator_h
@@ -28,6 +18,7 @@ public:
*/
cmCPackCygwinBinaryGenerator();
virtual ~cmCPackCygwinBinaryGenerator();
+
protected:
virtual int InitializeInternal();
int PackageFiles();
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index f1e8539b9..2c289f668 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -1,58 +1,43 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackCygwinSourceGenerator.h"
-#include "cmake.h"
+#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include <cmsys/SystemTools.hxx>
+#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 <windows.h>
-# include <sys/stat.h>
+#include "cm_sys_stat.h"
+#include <windows.h>
#endif
-//----------------------------------------------------------------------
cmCPackCygwinSourceGenerator::cmCPackCygwinSourceGenerator()
{
}
-//----------------------------------------------------------------------
cmCPackCygwinSourceGenerator::~cmCPackCygwinSourceGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackCygwinSourceGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "0");
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
int cmCPackCygwinSourceGenerator::PackageFiles()
{
// Create a tar file of the sources
- std::string packageDirFileName
- = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ std::string packageDirFileName =
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY");
packageDirFileName += ".tar.bz2";
packageFileNames[0] = packageDirFileName;
std::string output;
@@ -60,10 +45,9 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
// to create tar.bz2 file with the list of source
// files
this->Compress = cmArchiveWrite::CompressBZip2;
- if ( !this->cmCPackTarBZip2Generator::PackageFiles() )
- {
+ if (!this->cmCPackTarBZip2Generator::PackageFiles()) {
return 0;
- }
+ }
// Now create a tar file that contains the above .tar.bz2 file
// and the CPACK_CYGWIN_PATCH_FILE and CPACK_TOPLEVEL_DIRECTORY
// files
@@ -81,47 +65,41 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
// to the toplevel cpack temp dir
// copy the patch file into place
- if(!this->GetOption("CPACK_CYGWIN_PATCH_FILE"))
- {
+ if (!this->GetOption("CPACK_CYGWIN_PATCH_FILE")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"No patch file specified for cygwin sources.");
return 0;
- }
- if(!cmSystemTools::CopyFileAlways(
- this->GetOption("CPACK_CYGWIN_PATCH_FILE"),
- this->GetOption("CPACK_TOPLEVEL_DIRECTORY")))
- {
+ }
+ if (!cmSystemTools::CopyFileAlways(
+ this->GetOption("CPACK_CYGWIN_PATCH_FILE"),
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"))) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "problem copying: ["
- << this->GetOption("CPACK_CYGWIN_PATCH_FILE") << "]\nto\n["
- << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
+ << this->GetOption("CPACK_CYGWIN_PATCH_FILE") << "]\nto\n["
+ << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
return 0;
- }
- if(!this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"))
- {
+ }
+ if (!this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"No build script specified for cygwin sources.");
return 0;
- }
+ }
// copy the build script into place
- if(!cmSystemTools::CopyFileAlways(
- this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"),
- this->GetOption("CPACK_TOPLEVEL_DIRECTORY")))
- {
+ if (!cmSystemTools::CopyFileAlways(
+ this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"),
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"))) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "problem copying: "
- << this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT") << "\nto\n"
- << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
+ << this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT") << "\nto\n"
+ << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
return 0;
- }
- std::string outerTarFile
- = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ }
+ std::string outerTarFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
outerTarFile += "-";
const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
- if(!patch)
- {
+ if (!patch) {
cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER"
- << " not specified, defaulting to 1\n");
+ << " not specified, defaulting to 1\n");
patch = "1";
- }
+ }
outerTarFile += patch;
outerTarFile += "-src.tar.bz2";
std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
@@ -131,8 +109,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"));
std::string patchFile = tmpDir;
patchFile += "/";
- patchFile += cmSystemTools::GetFilenameName(
- this->GetOption("CPACK_CYGWIN_PATCH_FILE"));
+ patchFile +=
+ cmSystemTools::GetFilenameName(this->GetOption("CPACK_CYGWIN_PATCH_FILE"));
std::string file = cmSystemTools::GetFilenameName(compressOutFile);
std::string sourceTar = cmSystemTools::GetFilenamePath(compressOutFile);
@@ -151,10 +129,9 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
packageFileNames[0] = outerTarFile;
/* update the toplevel dir */
toplevel = tmpDir;
- if ( !this->cmCPackTarBZip2Generator::PackageFiles() )
- {
+ if (!this->cmCPackTarBZip2Generator::PackageFiles()) {
return 0;
- }
+ }
return 1;
}
@@ -169,14 +146,12 @@ const char* cmCPackCygwinSourceGenerator::GetOutputExtension()
{
this->OutputExtension = "-";
const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
- if(!patch)
- {
+ if (!patch) {
cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER"
- << " not specified, defaulting to 1\n");
+ << " not specified, defaulting to 1\n");
patch = "1";
- }
+ }
this->OutputExtension += patch;
this->OutputExtension += "-src.tar.bz2";
return this->OutputExtension.c_str();
}
-
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.h b/Source/CPack/cmCPackCygwinSourceGenerator.h
index 9d98a9b95..896de1d3e 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.h
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.h
@@ -1,15 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackCygwinSourceGenerator_h
#define cmCPackCygwinSourceGenerator_h
@@ -28,6 +18,7 @@ public:
*/
cmCPackCygwinSourceGenerator();
virtual ~cmCPackCygwinSourceGenerator();
+
protected:
const char* GetPackagingInstallPrefix();
virtual int InitializeInternal();
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 4494e8a18..af54fce33 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -1,25 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDebGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
+#include "cmArchiveWrite.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cm_sys_stat.h"
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Glob.hxx>
-
-#include <limits.h> // USHRT_MAX
+#include "cmsys/Glob.hxx"
+#include <limits.h>
+#include <map>
+#include <ostream>
+#include <set>
+#include <stdio.h>
+#include <string.h>
+#include <utility>
// NOTE:
// A debian package .deb is simply an 'ar' archive. The only subtle difference
@@ -27,91 +25,85 @@
// 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);
+static int ar_append(const char* archive,
+ const std::vector<std::string>& files);
-//----------------------------------------------------------------------
cmCPackDebGenerator::cmCPackDebGenerator()
{
}
-//----------------------------------------------------------------------
cmCPackDebGenerator::~cmCPackDebGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackDebGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
- if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR")))
- {
+ if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
this->SetOption("CPACK_SET_DESTDIR", "I_ON");
- }
+ }
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
-int cmCPackDebGenerator::PackageOnePack(std::string initialTopLevel,
- std::string packageName)
- {
+int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
+ std::string const& packageName)
+{
int retval = 1;
// Begin the archive for this pack
std::string localToplevel(initialTopLevel);
- std::string packageFileName(
- cmSystemTools::GetParentDirectory(toplevel.c_str())
- );
+ std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
std::string outputFileName(
- std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
- +"-"+packageName + this->GetOutputExtension()
- );
+ std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + "-" +
+ packageName + this->GetOutputExtension());
- localToplevel += "/"+ packageName;
+ localToplevel += "/" + packageName;
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str());
- packageFileName += "/"+ outputFileName;
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
/* replace the TEMPORARY package file name */
this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
+ packageFileName.c_str());
// Tell CPackDeb.cmake the name of the component GROUP.
- this->SetOption("CPACK_DEB_PACKAGE_COMPONENT",packageName.c_str());
+ 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;
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("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("WDIR"));
+ std::string findExpr(this->GetOption("GEN_WDIR"));
findExpr += "/*";
gl.RecurseOn();
- if ( !gl.FindFiles(findExpr) )
- {
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory" << std::endl);
+ "Cannot find any files in the installed directory"
+ << std::endl);
return 0;
- }
+ }
packageFiles = gl.GetFiles();
int res = createDeb();
- if (res != 1)
- {
+ 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);
return retval;
}
-//----------------------------------------------------------------------
int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
{
int retval = 1;
@@ -122,461 +114,576 @@ 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)
- {
+ if (!ignoreGroup) {
std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
- for (compGIt=this->ComponentGroups.begin();
- compGIt!=this->ComponentGroups.end(); ++compGIt)
- {
+ for (compGIt = this->ComponentGroups.begin();
+ compGIt != this->ComponentGroups.end(); ++compGIt) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first
- << std::endl);
+ << compGIt->first << std::endl);
// Begin the archive for this group
- retval &= PackageOnePack(initialTopLevel,compGIt->first);
- }
+ retval &= PackageOnePack(initialTopLevel, compGIt->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 (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
// Does the component belong to a group?
- if (compIt->second.Group==NULL)
- {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Component <"
+ if (compIt->second.Group == CM_NULLPTR) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE, "Component <"
<< compIt->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, compIt->first);
}
}
+ }
// CPACK_COMPONENTS_IGNORE_GROUPS is set
// We build 1 package per component
- else
- {
+ else {
std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt=this->Components.begin();
- compIt!=this->Components.end(); ++compIt )
- {
- retval &= PackageOnePack(initialTopLevel,compIt->first);
- }
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
+ retval &= PackageOnePack(initialTopLevel, compIt->first);
}
+ }
return retval;
}
//----------------------------------------------------------------------
-int cmCPackDebGenerator::PackageComponentsAllInOne()
+int cmCPackDebGenerator::PackageComponentsAllInOne(
+ const std::string& compInstDirName)
{
int retval = 1;
- std::string compInstDirName;
/* Reset package file name list it will be populated during the
* component packaging run*/
packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- compInstDirName = "ALL_COMPONENTS_IN_ONE";
-
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging all groups in one package..."
"(CPACK_COMPONENTS_ALL_[GROUPS_]IN_ONE_PACKAGE is set)"
- << std::endl);
+ << std::endl);
// The ALL GROUPS in ONE package case
std::string localToplevel(initialTopLevel);
- std::string packageFileName(
- cmSystemTools::GetParentDirectory(toplevel.c_str())
- );
+ std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
std::string outputFileName(
- std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
- + this->GetOutputExtension()
- );
+ std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
+ this->GetOutputExtension());
// all GROUP in one vs all COMPONENT in one
- localToplevel += "/"+compInstDirName;
+ // if must be here otherwise non component paths have a trailing / while
+ // components don't
+ if (!compInstDirName.empty()) {
+ localToplevel += "/" + compInstDirName;
+ }
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str());
- packageFileName += "/"+ outputFileName;
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
/* replace the TEMPORARY package file name */
this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
- // Tell CPackDeb.cmake the path where the component is.
- std::string component_path = "/";
- component_path += 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);
+ packageFileName.c_str());
+
+ if (!compInstDirName.empty()) {
+ // Tell CPackDeb.cmake the path where the component is.
+ std::string component_path = "/";
+ component_path += 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);
retval = 0;
return retval;
- }
+ }
cmsys::Glob gl;
- std::string findExpr(this->GetOption("WDIR"));
+ std::string findExpr(this->GetOption("GEN_WDIR"));
findExpr += "/*";
gl.RecurseOn();
- if ( !gl.FindFiles(findExpr) )
- {
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory" << std::endl);
+ "Cannot find any files in the installed directory"
+ << std::endl);
return 0;
- }
+ }
packageFiles = gl.GetFiles();
int res = createDeb();
- if (res != 1)
- {
+ 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);
return retval;
}
-//----------------------------------------------------------------------
int cmCPackDebGenerator::PackageFiles()
{
- int retval = -1;
-
/* Are we in the component packaging case */
if (WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL GROUPS or 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();
- }
+ if (componentPackageMethod == ONE_PACKAGE) {
+ return PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
+ }
// 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.
- else
- {
- return PackageComponents(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
- }
+ return PackageComponents(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
// CASE 3 : NON COMPONENT package.
- else
- {
- if (!this->ReadListFile("CPackDeb.cmake"))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error while execution CPackDeb.cmake" << std::endl);
- retval = 0;
- }
- else
- {
- packageFiles = files;
- return createDeb();
- }
- }
- return retval;
+ return PackageComponentsAllInOne("");
}
int cmCPackDebGenerator::createDeb()
{
- const char* cmakeExecutable = this->GetOption("CMAKE_COMMAND");
-
// debian-binary file
- std::string dbfilename;
- dbfilename += this->GetOption("WDIR");
- dbfilename += "/debian-binary";
- { // the scope is needed for cmGeneratedFileStream
+ 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;
- ctlfilename = this->GetOption("WDIR");
- ctlfilename += "/control";
+ std::string ctlfilename = strGenWDIR + "/control";
// debian policy enforce lower case for package name
// mandatory entries:
std::string debian_pkg_name = cmsys::SystemTools::LowerCase(
- this->GetOption("CPACK_DEBIAN_PACKAGE_NAME") );
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
const char* debian_pkg_version =
- this->GetOption("CPACK_DEBIAN_PACKAGE_VERSION");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
const char* debian_pkg_section =
- this->GetOption("CPACK_DEBIAN_PACKAGE_SECTION");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION");
const char* debian_pkg_priority =
- this->GetOption("CPACK_DEBIAN_PACKAGE_PRIORITY");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY");
const char* debian_pkg_arch =
- this->GetOption("CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
- const char* maintainer = this->GetOption("CPACK_DEBIAN_PACKAGE_MAINTAINER");
- const char* desc = this->GetOption("CPACK_DEBIAN_PACKAGE_DESCRIPTION");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
+ const char* maintainer =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
+ const char* desc = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
// optional entries
- const char* debian_pkg_dep = this->GetOption("CPACK_DEBIAN_PACKAGE_DEPENDS");
+ const char* debian_pkg_dep =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS");
const char* debian_pkg_rec =
- this->GetOption("CPACK_DEBIAN_PACKAGE_RECOMMENDS");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS");
const char* debian_pkg_sug =
- this->GetOption("CPACK_DEBIAN_PACKAGE_SUGGESTS");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS");
const char* debian_pkg_url =
- this->GetOption("CPACK_DEBIAN_PACKAGE_HOMEPAGE");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE");
const char* debian_pkg_predep =
- this->GetOption("CPACK_DEBIAN_PACKAGE_PREDEPENDS");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS");
const char* debian_pkg_enhances =
- this->GetOption("CPACK_DEBIAN_PACKAGE_ENHANCES");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES");
const char* debian_pkg_breaks =
- this->GetOption("CPACK_DEBIAN_PACKAGE_BREAKS");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS");
const char* debian_pkg_conflicts =
- this->GetOption("CPACK_DEBIAN_PACKAGE_CONFLICTS");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS");
const char* debian_pkg_provides =
- this->GetOption("CPACK_DEBIAN_PACKAGE_PROVIDES");
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES");
const char* debian_pkg_replaces =
- this->GetOption("CPACK_DEBIAN_PACKAGE_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
+ { // 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_dep && *debian_pkg_dep)
- {
+ 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)
- {
+ }
+ if (debian_pkg_rec && *debian_pkg_rec) {
out << "Recommends: " << debian_pkg_rec << "\n";
- }
- if(debian_pkg_sug && *debian_pkg_sug)
- {
+ }
+ if (debian_pkg_sug && *debian_pkg_sug) {
out << "Suggests: " << debian_pkg_sug << "\n";
- }
- if(debian_pkg_url && *debian_pkg_url)
- {
+ }
+ if (debian_pkg_url && *debian_pkg_url) {
out << "Homepage: " << debian_pkg_url << "\n";
- }
- if (debian_pkg_predep && *debian_pkg_predep)
- {
+ }
+ if (debian_pkg_predep && *debian_pkg_predep) {
out << "Pre-Depends: " << debian_pkg_predep << "\n";
- }
- if (debian_pkg_enhances && *debian_pkg_enhances)
- {
+ }
+ if (debian_pkg_enhances && *debian_pkg_enhances) {
out << "Enhances: " << debian_pkg_enhances << "\n";
- }
- if (debian_pkg_breaks && *debian_pkg_breaks)
- {
+ }
+ if (debian_pkg_breaks && *debian_pkg_breaks) {
out << "Breaks: " << debian_pkg_breaks << "\n";
- }
- if (debian_pkg_conflicts && *debian_pkg_conflicts)
- {
+ }
+ if (debian_pkg_conflicts && *debian_pkg_conflicts) {
out << "Conflicts: " << debian_pkg_conflicts << "\n";
- }
- if (debian_pkg_provides && *debian_pkg_provides)
- {
+ }
+ if (debian_pkg_provides && *debian_pkg_provides) {
out << "Provides: " << debian_pkg_provides << "\n";
- }
- if (debian_pkg_replaces && *debian_pkg_replaces)
- {
+ }
+ 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->c_str());
- }
+ 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;
+ }
+
+ const std::string shlibsfilename = strGenWDIR + "/shlibs";
+
+ const char* debian_pkg_shlibs =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS");
+ 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());
+ out << debian_pkg_shlibs;
+ out << std::endl;
+ }
+
+ 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());
+ out << "#!/bin/sh\n\n"
+ "set -e\n\n"
+ "if [ \"$1\" = \"configure\" ]; then\n"
+ "\tldconfig\n"
+ "fi\n";
+ }
+ if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) {
+ cmGeneratedFileStream out(postrm.c_str());
+ out << "#!/bin/sh\n\n"
+ "set -e\n\n"
+ "if [ \"$1\" = \"remove\" ]; then\n"
+ "\tldconfig\n"
+ "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);
+ }
+
+ const char* debian_archive_type =
+ this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE");
+ if (!debian_archive_type) {
+ debian_archive_type = "paxr";
+ }
+
+ 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
- std::string cmd;
- if (NULL != this->GetOption("CPACK_DEBIAN_FAKEROOT_EXECUTABLE")) {
- cmd += this->GetOption("CPACK_DEBIAN_FAKEROOT_EXECUTABLE");
- }
- cmd += " \"";
- cmd += cmakeExecutable;
- cmd += "\" -E tar cfz data.tar.gz ";
-
- // 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 = std::string(this->GetOption("WDIR")).length();
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "WDIR: \"" << this->GetOption("WDIR")
- << "\", length = " << topLevelLength
- << std::endl);
- std::set<std::string> installDirs;
for (std::vector<std::string>::const_iterator fileIt =
- packageFiles.begin();
- fileIt != packageFiles.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);
- if (installDirs.find(relativeDir) == installDirs.end())
- {
- installDirs.insert(relativeDir);
- cmd += " .";
- cmd += relativeDir;
+ 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, "..");
}
}
- std::string output;
- int retval = -1;
- int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output,
- &retval, this->GetOption("WDIR"), this->GeneratorVerbose, 0);
-
- if ( !res || retval )
- {
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/Deb.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << cmd.c_str() << std::endl
- << "# Working directory: " << toplevel << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running tar command: "
- << cmd.c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
- return 0;
+ 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;
- md5filename = this->GetOption("WDIR");
- md5filename += "/md5sums";
-
- { // the scope is needed for cmGeneratedFileStream
+ std::string md5filename = strGenWDIR + "/md5sums";
+ {
+ // the scope is needed for cmGeneratedFileStream
cmGeneratedFileStream out(md5filename.c_str());
- std::vector<std::string>::const_iterator fileIt;
-// std::string topLevelWithTrailingSlash = toplevel;
+
std::string topLevelWithTrailingSlash =
- this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY");
topLevelWithTrailingSlash += '/';
- for ( fileIt = packageFiles.begin();
- fileIt != packageFiles.end(); ++ fileIt )
- {
- cmd = "\"";
- cmd += cmakeExecutable;
- cmd += "\" -E md5sum \"";
- cmd += *fileIt;
- cmd += "\"";
- //std::string output;
- //int retVal = -1;
- res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output,
- &retval, toplevel.c_str(), this->GeneratorVerbose, 0);
+ 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;
+ }
+
+ char md5sum[33];
+ if (!cmSystemTools::ComputeFileMD5(*fileIt, md5sum)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of "
+ << *fileIt << std::endl);
+ }
+
+ md5sum[32] = 0;
+
+ 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(), "");
+ cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(),
+ "");
out << output;
- }
+ }
// each line contains a eol.
// Do not end the md5sum file with yet another (invalid)
+ }
+
+ 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;
}
- cmd = "";
- if (NULL != this->GetOption("CPACK_DEBIAN_FAKEROOT_EXECUTABLE"))
- {
- cmd = this->GetOption("CPACK_DEBIAN_FAKEROOT_EXECUTABLE");
+ // 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;
}
- cmd += " \"";
- cmd += cmakeExecutable;
- cmd += "\" -E tar cfz control.tar.gz ./control ./md5sums";
- const char* controlExtra =
- this->GetOption("CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA");
- if( controlExtra )
- {
- 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->c_str());
- std::string localcopy = this->GetOption("WDIR");
- localcopy += "/";
- localcopy += filenamename;
- // if we can copy the file, it means it does exist, let's add it:
- if( cmsys::SystemTools::CopyFileIfDifferent(
- i->c_str(), localcopy.c_str()) )
- {
- // debian is picky and need relative to ./ path in the tar.gz
- cmd += " ./";
- cmd += filenamename;
- }
+ }
+
+ // 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);
}
- res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output,
- &retval, this->GetOption("WDIR"), this->GeneratorVerbose, 0);
- if ( !res || retval )
- {
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/Deb.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << cmd.c_str() << std::endl
- << "# Working directory: " << toplevel << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running tar command: "
- << cmd.c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
- return 0;
+ 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);
}
- // ar -r your-package-name.deb debian-binary control.tar.gz data.tar.gz
+ // 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 = this->GetOption("WDIR");
- topLevelString += "/";
+ std::string topLevelString = strGenWDIR + "/";
arFiles.push_back(topLevelString + "debian-binary");
arFiles.push_back(topLevelString + "control.tar.gz");
- arFiles.push_back(topLevelString + "data.tar.gz");
- std::string outputFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- outputFileName += "/";
- outputFileName += this->GetOption("CPACK_OUTPUT_FILE_NAME");
- res = ar_append(outputFileName.c_str(), arFiles);
- if ( res!=0 )
- {
- std::string tmpFile = this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
+ 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;
return 0;
- }
+ }
return 1;
}
bool cmCPackDebGenerator::SupportsComponentInstallation() const
- {
- if (IsOn("CPACK_DEB_COMPONENT_INSTALL"))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
+{
+ return IsOn("CPACK_DEB_COMPONENT_INSTALL");
+}
std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
- const std::string& componentName)
- {
+ const std::string& componentName)
+{
if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
return componentName;
}
@@ -586,18 +693,13 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
- std::string groupVar = "CPACK_COMPONENT_" +
- cmSystemTools::UpperCase(componentName) + "_GROUP";
- if (NULL != GetOption(groupVar.c_str()))
- {
- return std::string(GetOption(groupVar.c_str()));
- }
- else
- {
- return componentName;
- }
+ std::string groupVar =
+ "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
+ if (CM_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/
@@ -640,65 +742,61 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
* SUCH DAMAGE.
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define ARMAG "!<arch>\n" /* ar "magic number" */
-#define SARMAG 8 /* strlen(ARMAG); */
+#define ARMAG "!<arch>\n" /* ar "magic number" */
+#define SARMAG 8 /* strlen(ARMAG); */
-#define AR_EFMT1 "#1/" /* extended format #1 */
-#define ARFMAG "`\n"
+#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 */
+#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; \
-}
+#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 */
+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)
+static const char* ar_rname(const char* path)
{
- const char *ind = strrchr(path, '/');
- return (ind ) ? ind + 1 : 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 char ar_hb[sizeof(HDR) + 1]; /* real header */
static size_t ar_already_written;
@@ -715,80 +813,88 @@ static size_t ar_already_written;
* 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 int copy_ar(CF* cfp, off_t size)
{
static char pad = '\n';
off_t sz = size;
size_t nr, nw;
- char buf[8*1024];
+ char buf[8 * 1024];
- if (sz == 0)
+ 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) {
+ (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)
+ for (size_t off = 0; off < nr; nr -= off, off += nw) {
+ if ((nw = fwrite(buf + off, 1, nr, to)) < nr) {
return -1;
+ }
}
- if (sz)
+ }
+ if (sz) {
return -2;
+ }
- if (cfp->flags & WPAD && (size + ar_already_written) & 1
- && fwrite(&pad, 1, 1, to) != 1)
+ 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)
+static int put_arobj(CF* cfp, struct stat* sb)
{
int result = 0;
- struct ar_hdr *hdr;
+ 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.) */
+ /* 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. */
+ /* 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,
- 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,
- sb->st_mode, (long long)sb->st_size, ARFMAG);
- }
- off_t size = sb->st_size;
+ }
+ 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))
+ if (fwrite(ar_hb, 1, sizeof(HDR), cfp->wFile) != sizeof(HDR)) {
return -1;
+ }
if (lname) {
- if (fwrite(name, 1, lname, cfp->wFile) != lname)
+ if (fwrite(name, 1, lname, cfp->wFile) != lname) {
return -2;
- ar_already_written = lname;
}
+ ar_already_written = lname;
+ }
result = copy_ar(cfp, size);
ar_already_written = 0;
return result;
@@ -800,42 +906,41 @@ static int put_arobj(CF *cfp, struct stat *sb)
* 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)
+static int ar_append(const char* archive,
+ const std::vector<std::string>& files)
{
int eval = 0;
- FILE* aFile = fopen(archive, "wb+");
- if (aFile!=NULL) {
+ 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(NULL, 0, aFile, archive, WPAD);
- for(std::vector<std::string>::const_iterator fileIt = files.begin();
- fileIt!=files.end(); ++fileIt) {
+ 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 = fopen(filename, "rb");
- if (file == NULL) {
+ 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) {
+ if (result != 0) {
eval = -2;
break;
- }
}
}
- else {
- eval = -3;
- }
- fclose(aFile);
+ } else {
+ eval = -3;
}
- else {
+ fclose(aFile);
+ } else {
eval = -4;
- }
+ }
return eval;
}
diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h
index d678cfacf..e7cde1145 100644
--- a/Source/CPack/cmCPackDebGenerator.h
+++ b/Source/CPack/cmCPackDebGenerator.h
@@ -1,21 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackDebGenerator_h
#define cmCPackDebGenerator_h
+#include "cmConfigure.h"
#include "cmCPackGenerator.h"
+#include <string>
+#include <vector>
+
/** \class cmCPackDebGenerator
* \brief A generator for Debian packages
*
@@ -29,28 +23,29 @@ public:
* Construct generator
*/
cmCPackDebGenerator();
- virtual ~cmCPackDebGenerator();
+ ~cmCPackDebGenerator() CM_OVERRIDE;
static bool CanGenerate()
- {
+ {
#ifdef __APPLE__
// on MacOS enable CPackDeb iff dpkg is found
std::vector<std::string> locations;
locations.push_back("/sw/bin"); // Fink
locations.push_back("/opt/local/bin"); // MacPorts
- return cmSystemTools::FindProgram("dpkg",locations) != "" ? true : false;
+ return cmSystemTools::FindProgram("dpkg", locations) != "" ? true : false;
#else
// legacy behavior on other systems
return true;
#endif
- }
+ }
protected:
- virtual int InitializeInternal();
+ int InitializeInternal() CM_OVERRIDE;
/**
* This method factors out the work done in component packaging case.
*/
- int PackageOnePack(std::string initialToplevel, std::string packageName);
+ int PackageOnePack(std::string const& initialToplevel,
+ std::string const& packageName);
/**
* The method used to package files when component
* install is used. This will create one
@@ -61,17 +56,16 @@ protected:
* Special case of component install where all
* components will be put in a single installer.
*/
- int PackageComponentsAllInOne();
- virtual int PackageFiles();
- virtual const char* GetOutputExtension() { return ".deb"; }
- virtual bool SupportsComponentInstallation() const;
- virtual std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName);
+ int PackageComponentsAllInOne(const std::string& compInstDirName);
+ int PackageFiles() CM_OVERRIDE;
+ const char* GetOutputExtension() CM_OVERRIDE { return ".deb"; }
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
+ std::string GetComponentInstallDirNameSuffix(
+ const std::string& componentName) CM_OVERRIDE;
private:
int createDeb();
std::vector<std::string> packageFiles;
-
};
#endif
diff --git a/Source/CPack/cmCPackDocumentMacros.cxx b/Source/CPack/cmCPackDocumentMacros.cxx
deleted file mode 100644
index ddc75a4b4..000000000
--- a/Source/CPack/cmCPackDocumentMacros.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "cmCPackDocumentMacros.h"
-
-void cmCPackDocumentMacros::GetMacrosDocumentation(
- std::vector<cmDocumentationEntry>& )
-{
- // Commented-out example of use
- //
- // cmDocumentationEntry e("cpack_<macro>",
- // "Brief Description"
- // "which may be on several lines.",
- // "Long description in pre-formatted format"
- // " blah\n"
- // " blah\n"
- //);
- //v.push_back(e);
-}
diff --git a/Source/CPack/cmCPackDocumentMacros.h b/Source/CPack/cmCPackDocumentMacros.h
deleted file mode 100644
index 544f74f5f..000000000
--- a/Source/CPack/cmCPackDocumentMacros.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmCPackDocumentMacros_h
-#define cmCPackDocumentMacros_h
-#include "cmStandardIncludes.h"
-class cmCPackDocumentMacros
-{
-public:
- static void GetMacrosDocumentation(std::vector<cmDocumentationEntry>& v);
-};
-
-#endif
diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx
deleted file mode 100644
index 8b16ae985..000000000
--- a/Source/CPack/cmCPackDocumentVariables.cxx
+++ /dev/null
@@ -1,122 +0,0 @@
-#include "cmCPackDocumentVariables.h"
-#include "cmake.h"
-
-void cmCPackDocumentVariables::DefineVariables(cmake* cm)
-{
- // Subsection: variables defined/used by cpack,
- // which are common to all CPack generators
-
- cm->DefineProperty
- ("CPACK_PACKAGING_INSTALL_PREFIX", cmProperty::VARIABLE,
- "The prefix used in the built package.",
- "Each CPack generator has a default value (like /usr)."
- " This default value may"
- " be overwritten from the CMakeLists.txt or the cpack command line"
- " by setting an alternative value.\n"
- "e.g. "
- " set(CPACK_PACKAGING_INSTALL_PREFIX \"/opt\")\n"
- "This is not the same purpose as CMAKE_INSTALL_PREFIX which"
- " is used when installing from the build tree without building"
- " a package."
- "", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", cmProperty::VARIABLE,
- "Boolean toggle to include/exclude top level directory.",
- "When preparing a package CPack installs the item under"
- " the so-called top level directory. The purpose of"
- " is to include (set to 1 or ON or TRUE) the top level directory"
- " in the package or not (set to 0 or OFF or FALSE).\n"
- "Each CPack generator has a built-in default value for this"
- " variable. E.g. Archive generators (ZIP, TGZ, ...) includes"
- " the top level whereas RPM or DEB don't. The user may override"
- " the default value by setting this variable.\n"
- "There is a similar variable "
- "CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY "
- "which may be used to override the behavior for the component"
- " packaging case which may have different default value for"
- " historical (now backward compatibility) reason.", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY", cmProperty::VARIABLE,
- "Boolean toggle to include/exclude top level directory "
- "(component case).",
- "Similar usage as CPACK_INCLUDE_TOPLEVEL_DIRECTORY"
- " but for the component case. "
- "See CPACK_INCLUDE_TOPLEVEL_DIRECTORY documentation for"
- " the detail.", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_SET_DESTDIR", cmProperty::VARIABLE,
- "Boolean toggle to make CPack use DESTDIR mechanism when"
- " packaging.", "DESTDIR means DESTination DIRectory."
- " It is commonly used by makefile "
- "users in order to install software at non-default location. It "
- "is a basic relocation mechanism that should not be used on"
- " Windows (see CMAKE_INSTALL_PREFIX documentation). "
- "It is usually invoked like this:\n"
- " make DESTDIR=/home/john install\n"
- "which will install the concerned software using the"
- " installation prefix, e.g. \"/usr/local\" prepended with "
- "the DESTDIR value which finally gives \"/home/john/usr/local\"."
- " When preparing a package, CPack first installs the items to be "
- "packaged in a local (to the build tree) directory by using the "
- "same DESTDIR mechanism. Nevertheless, if "
- "CPACK_SET_DESTDIR is set then CPack will set DESTDIR before"
- " doing the local install. The most noticeable difference is"
- " that without CPACK_SET_DESTDIR, CPack uses "
- "CPACK_PACKAGING_INSTALL_PREFIX as a prefix whereas with "
- "CPACK_SET_DESTDIR set, CPack will use CMAKE_INSTALL_PREFIX as"
- " a prefix.\n"
- "Manually setting CPACK_SET_DESTDIR may help (or simply be"
- " necessary) if some install rules uses absolute "
- "DESTINATION (see CMake INSTALL command)."
- " However, starting with"
- " CPack/CMake 2.8.3 RPM and DEB installers tries to handle DESTDIR"
- " automatically so that it is seldom necessary for the user to set"
- " it.", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_INSTALL_SCRIPT", cmProperty::VARIABLE,
- "Extra CMake script provided by the user.",
- "If set this CMake script will be executed by CPack "
- "during its local [CPack-private] installation "
- "which is done right before packaging the files."
- " The script is not called by e.g.: make install.", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_ABSOLUTE_DESTINATION_FILES", cmProperty::VARIABLE,
- "List of files which have been installed using "
- " an ABSOLUTE DESTINATION path.",
- "This variable is a Read-Only variable which is set internally"
- " by CPack during installation and before packaging using"
- " CMAKE_ABSOLUTE_DESTINATION_FILES defined in cmake_install.cmake "
- "scripts. The value can be used within CPack project configuration"
- " file and/or CPack<GEN>.cmake file of <GEN> generator.", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", cmProperty::VARIABLE,
- "Ask CPack to warn each time a file with absolute INSTALL"
- " DESTINATION is encountered.",
- "This variable triggers the definition of "
- "CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION when CPack runs"
- " cmake_install.cmake scripts.", false,
- "Variables common to all CPack generators");
-
- cm->DefineProperty
- ("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", cmProperty::VARIABLE,
- "Ask CPack to error out as soon as a file with absolute INSTALL"
- " DESTINATION is encountered.",
- "The fatal error is emitted before the installation of "
- "the offending file takes place. Some CPack generators, like NSIS,"
- "enforce this internally. "
- "This variable triggers the definition of"
- "CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION when CPack runs"
- "Variables common to all CPack generators");
-}
diff --git a/Source/CPack/cmCPackDocumentVariables.h b/Source/CPack/cmCPackDocumentVariables.h
deleted file mode 100644
index e7971be13..000000000
--- a/Source/CPack/cmCPackDocumentVariables.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmCPackDocumentVariables_h
-#define cmCPackDocumentVariables_h
-class cmake;
-class cmCPackDocumentVariables
-{
-public:
- static void DefineVariables(cmake* cm);
-};
-
-#endif
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index d973c0134..d26d5bc1a 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -1,66 +1,70 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDragNDropGenerator.h"
+
+#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
-#include "cmSystemTools.h"
#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <iomanip>
+#include <map>
+#include <stdlib.h>
+
+#include <CoreFoundation/CoreFoundation.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>
+#endif
static const char* SLAHeader =
-"data 'LPic' (5000) {\n"
-" $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n"
-" $\"0008 0003 0000 0001 0004 0000 0004 0005\"\n"
-" $\"0000 000E 0006 0001 0005 0007 0000 0007\"\n"
-" $\"0008 0000 0047 0009 0000 0034 000A 0001\"\n"
-" $\"0035 000B 0001 0020 000C 0000 0011 000D\"\n"
-" $\"0000 005B 0004 0000 0033 000F 0001 000C\"\n"
-" $\"0010 0000 000B 000E 0000\"\n"
-"};\n"
-"\n";
+ "data 'LPic' (5000) {\n"
+ " $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n"
+ " $\"0008 0003 0000 0001 0004 0000 0004 0005\"\n"
+ " $\"0000 000E 0006 0001 0005 0007 0000 0007\"\n"
+ " $\"0008 0000 0047 0009 0000 0034 000A 0001\"\n"
+ " $\"0035 000B 0001 0020 000C 0000 0011 000D\"\n"
+ " $\"0000 005B 0004 0000 0033 000F 0001 000C\"\n"
+ " $\"0010 0000 000B 000E 0000\"\n"
+ "};\n"
+ "\n";
static const char* SLASTREnglish =
-"resource 'STR#' (5002, \"English\") {\n"
-" {\n"
-" \"English\",\n"
-" \"Agree\",\n"
-" \"Disagree\",\n"
-" \"Print\",\n"
-" \"Save...\",\n"
-" \"You agree to the License Agreement terms when you click \"\n"
-" \"the \\\"Agree\\\" button.\",\n"
-" \"Software License Agreement\",\n"
-" \"This text cannot be saved. This disk may be full or locked, "
-"or the \"\n"
-" \"file may be locked.\",\n"
-" \"Unable to print. Make sure you have selected a printer.\"\n"
-" }\n"
-"};\n"
-"\n";
-
-//----------------------------------------------------------------------
+ "resource 'STR#' (5002, \"English\") {\n"
+ " {\n"
+ " \"English\",\n"
+ " \"Agree\",\n"
+ " \"Disagree\",\n"
+ " \"Print\",\n"
+ " \"Save...\",\n"
+ " \"You agree to the License Agreement terms when you click \"\n"
+ " \"the \\\"Agree\\\" button.\",\n"
+ " \"Software License Agreement\",\n"
+ " \"This text cannot be saved. This disk may be full or locked, "
+ "or the \"\n"
+ " \"file may be locked.\",\n"
+ " \"Unable to print. Make sure you have selected a printer.\"\n"
+ " }\n"
+ "};\n"
+ "\n";
+
cmCPackDragNDropGenerator::cmCPackDragNDropGenerator()
+ : singleLicense(false)
{
// default to one package file for components
this->componentPackageMethod = ONE_PACKAGE;
}
-//----------------------------------------------------------------------
cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackDragNDropGenerator::InitializeInternal()
{
// Starting with Xcode 4.3, look in "/Applications/Xcode.app" first:
@@ -69,89 +73,125 @@ int cmCPackDragNDropGenerator::InitializeInternal()
paths.push_back("/Applications/Xcode.app/Contents/Developer/Tools");
paths.push_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);
+ 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);
return 0;
- }
+ }
this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());
- const std::string setfile_path = cmSystemTools::FindProgram("SetFile",
- paths, false);
- if(setfile_path.empty())
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot locate SetFile command"
- << std::endl);
+ const std::string setfile_path =
+ cmSystemTools::FindProgram("SetFile", paths, false);
+ if (setfile_path.empty()) {
+ 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);
+ const std::string rez_path = cmSystemTools::FindProgram("Rez", paths, false);
+ if (rez_path.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate Rez command"
+ << std::endl);
return 0;
- }
+ }
this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
+ if (this->IsSet("CPACK_DMG_SLA_DIR")) {
+ slaDirectory = this->GetOption("CPACK_DMG_SLA_DIR");
+ if (!slaDirectory.empty() && this->IsSet("CPACK_RESOURCE_FILE_LICENSE")) {
+ std::string license_file =
+ this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
+ if (!license_file.empty() &&
+ (license_file.find("CPack.GenericLicense.txt") ==
+ std::string::npos)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_OUTPUT,
+ "Both CPACK_DMG_SLA_DIR and CPACK_RESOURCE_FILE_LICENSE specified, "
+ "using CPACK_RESOURCE_FILE_LICENSE as a license for all languages."
+ << std::endl);
+ singleLicense = true;
+ }
+ }
+ if (!this->IsSet("CPACK_DMG_SLA_LANGUAGES")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_DMG_SLA_DIR set but no languages defined "
+ "(set CPACK_DMG_SLA_LANGUAGES)"
+ << std::endl);
+ return 0;
+ }
+ if (!cmSystemTools::FileExists(slaDirectory, false)) {
+ 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);
+ 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";
+ if (!singleLicense && !cmSystemTools::FileExists(license)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Missing license file "
+ << languages[i] << ".license.txt" << std::endl);
+ return 0;
+ }
+ std::string menu = slaDirectory + "/" + languages[i] + ".menu.txt";
+ if (!cmSystemTools::FileExists(menu)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Missing menu file "
+ << languages[i] << ".menu.txt" << std::endl);
+ return 0;
+ }
+ }
+ }
+
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
const char* cmCPackDragNDropGenerator::GetOutputExtension()
{
return ".dmg";
}
-//----------------------------------------------------------------------
int cmCPackDragNDropGenerator::PackageFiles()
{
// gather which directories to make dmg files for
// multiple directories occur if packaging components or groups separately
// monolith
- if(this->Components.empty())
- {
+ if (this->Components.empty()) {
return this->CreateDMG(toplevel, packageFileNames[0]);
- }
+ }
// component install
std::vector<std::string> package_files;
std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt=this->Components.begin();
- compIt!=this->Components.end(); ++compIt )
- {
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
std::string name = GetComponentInstallDirNameSuffix(compIt->first);
package_files.push_back(name);
- }
+ }
std::sort(package_files.begin(), package_files.end());
- package_files.erase(std::unique(package_files.begin(),
- package_files.end()),
+ package_files.erase(std::unique(package_files.begin(), package_files.end()),
package_files.end());
-
// loop to create dmg files
packageFileNames.clear();
- for(size_t i=0; i<package_files.size(); i++)
- {
+ for (size_t i = 0; i < package_files.size(); i++) {
std::string full_package_name = std::string(toplevel) + std::string("/");
- if(package_files[i] == "ALL_IN_ONE")
- {
+ if (package_files[i] == "ALL_IN_ONE") {
full_package_name += this->GetOption("CPACK_PACKAGE_FILE_NAME");
- }
- else
- {
+ } else {
full_package_name += package_files[i];
- }
+ }
full_package_name += std::string(GetOutputExtension());
packageFileNames.push_back(full_package_name);
@@ -159,385 +199,514 @@ int cmCPackDragNDropGenerator::PackageFiles()
src_dir += "/";
src_dir += package_files[i];
- if(0 == this->CreateDMG(src_dir, full_package_name))
- {
+ if (0 == this->CreateDMG(src_dir, full_package_name)) {
return 0;
- }
}
+ }
return 1;
}
-//----------------------------------------------------------------------
-bool cmCPackDragNDropGenerator::CopyFile(cmOStringStream& source,
- cmOStringStream& target)
+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().c_str(),
+ target.str().c_str())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error copying "
+ << source.str() << " to " << target.str() << std::endl);
return false;
- }
+ }
+
+ return true;
+}
+
+bool cmCPackDragNDropGenerator::CreateEmptyFile(std::ostringstream& target,
+ size_t size)
+{
+ 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);
+ }
return true;
}
-//----------------------------------------------------------------------
-bool cmCPackDragNDropGenerator::RunCommand(cmOStringStream& command,
- std::string* output)
+bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
+ std::string* output)
{
int exit_code = 1;
- bool result = cmSystemTools::RunSingleCommand(
- command.str().c_str(),
- output,
- &exit_code,
- 0,
- this->GeneratorVerbose,
- 0);
+ bool result =
+ cmSystemTools::RunSingleCommand(command.str().c_str(), output, output,
+ &exit_code, 0, this->GeneratorVerbose, 0);
- if(!result || exit_code)
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error executing: "
- << command.str()
- << std::endl);
+ if (!result || exit_code) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error executing: " << command.str()
+ << std::endl);
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------
int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
const std::string& output_file)
{
// Get optional arguments ...
const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON")
- ? this->GetOption("CPACK_PACKAGE_ICON") : "";
+ ? this->GetOption("CPACK_PACKAGE_ICON")
+ : "";
const std::string cpack_dmg_volume_name =
this->GetOption("CPACK_DMG_VOLUME_NAME")
? this->GetOption("CPACK_DMG_VOLUME_NAME")
- : this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ : this->GetOption("CPACK_PACKAGE_FILE_NAME");
- const std::string cpack_dmg_format =
- this->GetOption("CPACK_DMG_FORMAT")
- ? this->GetOption("CPACK_DMG_FORMAT") : "UDZO";
+ const std::string cpack_dmg_format = this->GetOption("CPACK_DMG_FORMAT")
+ ? this->GetOption("CPACK_DMG_FORMAT")
+ : "UDZO";
// Get optional arguments ...
std::string cpack_license_file =
- this->GetOption("CPACK_RESOURCE_FILE_LICENSE") ?
- this->GetOption("CPACK_RESOURCE_FILE_LICENSE") : "";
+ this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
+ ? this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
+ : "";
const std::string cpack_dmg_background_image =
this->GetOption("CPACK_DMG_BACKGROUND_IMAGE")
- ? this->GetOption("CPACK_DMG_BACKGROUND_IMAGE") : "";
+ ? this->GetOption("CPACK_DMG_BACKGROUND_IMAGE")
+ : "";
- const std::string cpack_dmg_ds_store =
- this->GetOption("CPACK_DMG_DS_STORE")
- ? this->GetOption("CPACK_DMG_DS_STORE") : "";
+ const std::string cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE")
+ ? this->GetOption("CPACK_DMG_DS_STORE")
+ : "";
+
+ const std::string cpack_dmg_languages =
+ this->GetOption("CPACK_DMG_SLA_LANGUAGES")
+ ? this->GetOption("CPACK_DMG_SLA_LANGUAGES")
+ : "";
+
+ const std::string cpack_dmg_ds_store_setup_script =
+ this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
+ ? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
+ : "";
+
+ const bool cpack_dmg_disable_applications_symlink =
+ this->IsOn("CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK");
// only put license on dmg if is user provided
- if(!cpack_license_file.empty() &&
- cpack_license_file.find("CPack.GenericLicense.txt") != std::string::npos)
- {
+ if (!cpack_license_file.empty() &&
+ cpack_license_file.find("CPack.GenericLicense.txt") !=
+ std::string::npos) {
+ cpack_license_file = "";
+ }
+
+ // use sla_dir if both sla_dir and license_file are set
+ if (!cpack_license_file.empty() && !slaDirectory.empty() && !singleLicense) {
cpack_license_file = "";
}
// The staging directory contains everything that will end-up inside the
// final disk image ...
- cmOStringStream staging;
+ std::ostringstream staging;
staging << src_dir;
// Add a symlink to /Applications so users can drag-and-drop the bundle
- // into it
- cmOStringStream application_link;
- application_link << staging.str() << "/Applications";
- cmSystemTools::CreateSymlink("/Applications",
- application_link.str().c_str());
+ // into it unless this behaviour was disabled
+ if (!cpack_dmg_disable_applications_symlink) {
+ std::ostringstream application_link;
+ application_link << staging.str() << "/Applications";
+ cmSystemTools::CreateSymlink("/Applications", application_link.str());
+ }
// Optionally add a custom volume icon ...
- if(!cpack_package_icon.empty())
- {
- cmOStringStream package_icon_source;
+ if (!cpack_package_icon.empty()) {
+ std::ostringstream package_icon_source;
package_icon_source << cpack_package_icon;
- cmOStringStream package_icon_destination;
+ std::ostringstream package_icon_destination;
package_icon_destination << staging.str() << "/.VolumeIcon.icns";
- if(!this->CopyFile(package_icon_source, package_icon_destination))
- {
+ if (!this->CopyFile(package_icon_source, package_icon_destination)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error copying disk volume icon. "
+ "Error copying disk volume icon. "
"Check the value of CPACK_PACKAGE_ICON."
- << std::endl);
+ << std::endl);
return 0;
- }
}
+ }
// Optionally add a custom .DS_Store file
// (e.g. for setting background/layout) ...
- if(!cpack_dmg_ds_store.empty())
- {
- cmOStringStream package_settings_source;
+ if (!cpack_dmg_ds_store.empty()) {
+ std::ostringstream package_settings_source;
package_settings_source << cpack_dmg_ds_store;
- cmOStringStream package_settings_destination;
+ std::ostringstream package_settings_destination;
package_settings_destination << staging.str() << "/.DS_Store";
- if(!this->CopyFile(package_settings_source, package_settings_destination))
- {
+ if (!this->CopyFile(package_settings_source,
+ package_settings_destination)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error copying disk volume settings file. "
+ "Error copying disk volume settings file. "
"Check the value of CPACK_DMG_DS_STORE."
- << std::endl);
+ << std::endl);
return 0;
- }
}
+ }
// Optionally add a custom background image ...
- if(!cpack_dmg_background_image.empty())
- {
- cmOStringStream package_background_source;
+ // Make sure the background file type is the same as the custom image
+ // and that the file is hidden so it doesn't show up.
+ if (!cpack_dmg_background_image.empty()) {
+ const std::string extension =
+ cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image);
+ std::ostringstream package_background_source;
package_background_source << cpack_dmg_background_image;
- cmOStringStream package_background_destination;
- package_background_destination << staging.str() << "/background.png";
+ std::ostringstream package_background_destination;
+ package_background_destination << staging.str()
+ << "/.background/background" << extension;
- if(!this->CopyFile(package_background_source,
- package_background_destination))
- {
+ if (!this->CopyFile(package_background_source,
+ package_background_destination)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error copying disk volume background image. "
+ "Error copying disk volume background image. "
"Check the value of CPACK_DMG_BACKGROUND_IMAGE."
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
+ }
- cmOStringStream temp_background_hiding_command;
- temp_background_hiding_command << this->GetOption("CPACK_COMMAND_SETFILE");
- temp_background_hiding_command << " -a V \"";
- temp_background_hiding_command << package_background_destination.str();
- temp_background_hiding_command << "\"";
+ bool remount_image =
+ !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty();
- if(!this->RunCommand(temp_background_hiding_command))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error setting attributes on disk volume background image."
- << std::endl);
+ std::string temp_image_format = "UDZO";
+
+ // Create 1 MB dummy padding file in staging area when we need to remount
+ // image, so we have enough space for storing changes ...
+ if (remount_image) {
+ 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);
return 0;
- }
}
+ temp_image_format = "UDRW";
+ }
// Create a temporary read-write disk image ...
std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
temp_image += "/temp.dmg";
- cmOStringStream temp_image_command;
+ 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 << " -format UDRW";
+ temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\"";
+ temp_image_command << " -format " << temp_image_format;
temp_image_command << " \"" << temp_image << "\"";
- if(!this->RunCommand(temp_image_command))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error generating temporary disk image."
- << std::endl);
+ if (!this->RunCommand(temp_image_command)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error generating temporary disk image." << std::endl);
return 0;
- }
+ }
- // Optionally set the custom icon flag for the image ...
- if(!cpack_package_icon.empty())
- {
- cmOStringStream temp_mount;
+ if (remount_image) {
+ // Store that we have a failure so that we always unmount the image
+ // before we exit.
+ bool had_error = false;
- cmOStringStream attach_command;
+ std::ostringstream attach_command;
attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
attach_command << " attach";
attach_command << " \"" << temp_image << "\"";
std::string attach_output;
- if(!this->RunCommand(attach_command, &attach_output))
- {
+ if (!this->RunCommand(attach_command, &attach_output)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error attaching temporary disk image."
- << std::endl);
+ "Error attaching temporary disk image." << std::endl);
return 0;
- }
+ }
cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
mountpoint_regex.find(attach_output.c_str());
- temp_mount << mountpoint_regex.match(1);
+ std::string const temp_mount = mountpoint_regex.match(1);
- cmOStringStream setfile_command;
- setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
- setfile_command << " -a C";
- setfile_command << " \"" << temp_mount.str() << "\"";
+ // 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);
- if(!this->RunCommand(setfile_command))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error assigning custom icon to temporary disk image."
- << std::endl);
+ had_error = true;
+ }
- return 0;
+ // Optionally set the custom icon flag for the image ...
+ if (!had_error && !cpack_package_icon.empty()) {
+ std::ostringstream setfile_command;
+ setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
+ setfile_command << " -a C";
+ setfile_command << " \"" << temp_mount << "\"";
+
+ if (!this->RunCommand(setfile_command)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error assigning custom icon to temporary disk image."
+ << std::endl);
+
+ had_error = true;
}
+ }
+
+ // Optionally we can execute a custom apple script to generate
+ // the .DS_Store for the volume folder ...
+ if (!had_error && !cpack_dmg_ds_store_setup_script.empty()) {
+ std::ostringstream setup_script_command;
+ setup_script_command << "osascript"
+ << " \"" << cpack_dmg_ds_store_setup_script << "\""
+ << " \"" << cpack_dmg_volume_name << "\"";
+ std::string error;
+ if (!this->RunCommand(setup_script_command, &error)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error executing custom script on disk image."
+ << std::endl
+ << error << std::endl);
- cmOStringStream detach_command;
+ had_error = true;
+ }
+ }
+
+ std::ostringstream detach_command;
detach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
detach_command << " detach";
- detach_command << " \"" << temp_mount.str() << "\"";
+ detach_command << " \"" << temp_mount << "\"";
- if(!this->RunCommand(detach_command))
- {
+ if (!this->RunCommand(detach_command)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error detaching temporary disk image."
- << std::endl);
+ "Error detaching temporary disk image." << std::endl);
return 0;
- }
}
- if(!cpack_license_file.empty())
- {
+ if (had_error) {
+ return 0;
+ }
+ }
+
+ 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::ifstream ifs;
- ifs.open(cpack_license_file.c_str());
- if(ifs.is_open())
- {
- cmGeneratedFileStream osf(sla_r.c_str());
- osf << "#include <CoreServices/CoreServices.r>\n\n";
- osf << SLAHeader;
- osf << "\n";
- osf << "data 'TEXT' (5002, \"English\") {\n";
- while(ifs.good())
- {
- std::string line;
- std::getline(ifs, line);
- // escape quotes
- std::string::size_type pos = line.find('\"');
- while(pos != std::string::npos)
+ std::vector<std::string> languages;
+ if (!oldStyle) {
+ cmSystemTools::ExpandListArgument(cpack_dmg_languages, languages);
+ }
+
+ cmGeneratedFileStream ofs(sla_r.c_str());
+ ofs << "#include <CoreServices/CoreServices.r>\n\n";
+ if (oldStyle) {
+ ofs << SLAHeader;
+ ofs << "\n";
+ } else {
+ /*
+ * LPic Layout
+ * (https://github.com/pypt/dmg-add-license/blob/master/main.c)
+ * as far as I can tell (no official documentation seems to exist):
+ * struct LPic {
+ * uint16_t default_language; // points to a resid, defaulting to 0,
+ * // which is the first set language
+ * uint16_t length;
+ * struct {
+ * uint16_t language_code;
+ * uint16_t resid;
+ * uint16_t encoding; // Encoding from TextCommon.h,
+ * // forcing MacRoman (0) for now. Might need to
+ * // allow overwrite per license by user later
+ * } item[1];
+ * }
+ */
+
+ // Create vector first for readability, then iterate to write to ofs
+ std::vector<uint16_t> header_data;
+ header_data.push_back(0);
+ 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);
+ CFStringRef iso_language =
+ CFLocaleCreateCanonicalLanguageIdentifierFromString(
+ NULL, language_cfstring);
+ if (!iso_language) {
+ 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,
+ kCFStringEncodingMacRoman);
+ LangCode lang = 0;
+ RegionCode region = 0;
+#ifdef HAVE_CoreServices
+ OSStatus err =
+ LocaleStringToLangAndRegionCodes(iso_language_cstr, &lang, &region);
+ if (err != noErr)
+#endif
{
- line.replace(pos, 1, "\\\"");
- pos = line.find('\"', pos+2);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "No language/region code available for "
+ << iso_language_cstr << std::endl);
+ free(iso_language_cstr);
+ return 0;
}
- // break up long lines to avoid Rez errors
- std::vector<std::string> lines;
- const size_t max_line_length = 512;
- for(size_t i=0; i<line.size(); i+= max_line_length)
- {
- int line_length = max_line_length;
- if(i+max_line_length > line.size())
- line_length = line.size()-i;
- lines.push_back(line.substr(i, line_length));
- }
+#ifdef HAVE_CoreServices
+ free(iso_language_cstr);
+ header_data.push_back(region);
+ header_data.push_back(i);
+ header_data.push_back(0);
+#endif
+ }
+ ofs << "data 'LPic' (5000) {\n";
+ ofs << std::hex << std::uppercase << std::setfill('0');
- for(size_t i=0; i<lines.size(); i++)
- {
- osf << " \"" << lines[i] << "\"\n";
- }
- osf << " \"\\n\"\n";
+ for (size_t i = 0; i < header_data.size(); ++i) {
+ if (i % 8 == 0) {
+ ofs << " $\"";
+ }
+
+ ofs << std::setw(4) << header_data[i];
+
+ if (i % 8 == 7 || i == header_data.size() - 1) {
+ ofs << "\"\n";
+ } else {
+ ofs << " ";
+ }
}
- osf << "};\n";
- osf << "\n";
- osf << SLASTREnglish;
- ifs.close();
- osf.close();
+ ofs << "};\n\n";
+ // Reset ofs options
+ ofs << std::dec << std::nouppercase << std::setfill(' ');
}
- // convert to UDCO
- std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- temp_udco += "/temp-udco.dmg";
+ bool have_write_license_error = false;
+ std::string error;
- cmOStringStream udco_image_command;
- udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
- udco_image_command << " convert \"" << temp_image << "\"";
- udco_image_command << " -format UDCO";
- udco_image_command << " -o \"" << temp_udco << "\"";
+ if (oldStyle) {
+ if (!this->WriteLicense(ofs, 0, "", cpack_license_file, &error)) {
+ have_write_license_error = true;
+ }
+ } else {
+ for (size_t i = 0; i < languages.size() && !have_write_license_error;
+ ++i) {
+ if (singleLicense) {
+ if (!this->WriteLicense(ofs, i + 5000, languages[i],
+ cpack_license_file, &error)) {
+ have_write_license_error = true;
+ }
+ } else {
+ if (!this->WriteLicense(ofs, i + 5000, languages[i], "", &error)) {
+ have_write_license_error = true;
+ }
+ }
+ }
+ }
- std::string error;
- if(!this->RunCommand(udco_image_command, &error))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error converting to UDCO dmg for adding SLA." << std::endl
- << error
- << std::endl);
+ ofs.Close();
+
+ if (have_write_license_error) {
+ 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::ostringstream udco_image_command;
+ udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
+ udco_image_command << " convert \"" << temp_image << "\"";
+ udco_image_command << " -format UDZO";
+ udco_image_command << " -ov -o \"" << temp_udzo << "\"";
+
+ if (!this->RunCommand(udco_image_command, &error)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error converting to UDCO dmg for adding SLA."
+ << std::endl
+ << error << std::endl);
+ return 0;
}
+ temp_image = temp_udzo;
+ }
// unflatten dmg
- cmOStringStream unflatten_command;
+ std::ostringstream unflatten_command;
unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
unflatten_command << " unflatten ";
- unflatten_command << "\"" << temp_udco << "\"";
+ unflatten_command << "\"" << temp_image << "\"";
- if(!this->RunCommand(unflatten_command, &error))
- {
+ if (!this->RunCommand(unflatten_command, &error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error unflattening dmg for adding SLA." << std::endl
- << error
- << std::endl);
+ "Error unflattening dmg for adding SLA." << std::endl
+ << error
+ << std::endl);
return 0;
- }
+ }
// Rez the SLA
- cmOStringStream embed_sla_command;
+ std::ostringstream embed_sla_command;
embed_sla_command << this->GetOption("CPACK_COMMAND_REZ");
+ const char* sysroot = this->GetOption("CPACK_OSX_SYSROOT");
+ if (sysroot && sysroot[0] != '\0') {
+ embed_sla_command << " -isysroot \"" << sysroot << "\"";
+ }
embed_sla_command << " \"" << sla_r << "\"";
embed_sla_command << " -a -o ";
- embed_sla_command << "\"" << temp_udco << "\"";
+ embed_sla_command << "\"" << temp_image << "\"";
- if(!this->RunCommand(embed_sla_command, &error))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding SLA." << std::endl
- << error
- << std::endl);
+ if (!this->RunCommand(embed_sla_command, &error)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding SLA." << std::endl
+ << error
+ << std::endl);
return 0;
- }
+ }
// flatten dmg
- cmOStringStream flatten_command;
+ std::ostringstream flatten_command;
flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
flatten_command << " flatten ";
- flatten_command << "\"" << temp_udco << "\"";
+ flatten_command << "\"" << temp_image << "\"";
- if(!this->RunCommand(flatten_command, &error))
- {
+ if (!this->RunCommand(flatten_command, &error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error flattening dmg for adding SLA." << std::endl
- << error
- << std::endl);
+ "Error flattening dmg for adding SLA." << std::endl
+ << error
+ << std::endl);
return 0;
- }
-
- temp_image = temp_udco;
+ }
}
-
// Create the final compressed read-only disk image ...
- cmOStringStream final_image_command;
+ std::ostringstream final_image_command;
final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
final_image_command << " convert \"" << temp_image << "\"";
final_image_command << " -format ";
@@ -546,14 +715,12 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
final_image_command << " zlib-level=9";
final_image_command << " -o \"" << output_file << "\"";
- if(!this->RunCommand(final_image_command))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error compressing disk image."
- << std::endl);
+ if (!this->RunCommand(final_image_command)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error compressing disk image."
+ << std::endl);
return 0;
- }
+ }
return 1;
}
@@ -563,9 +730,8 @@ bool cmCPackDragNDropGenerator::SupportsComponentInstallation() const
return true;
}
-std::string
-cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
- const std::string& componentName)
+std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
+ const std::string& componentName)
{
// we want to group components together that go in the same dmg package
std::string package_file_name = this->GetOption("CPACK_PACKAGE_FILE_NAME");
@@ -577,27 +743,153 @@ cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
// 3. ignore groups - if grouping is defined, it is ignored
// and each component goes in its own package
- if(this->componentPackageMethod == ONE_PACKAGE)
- {
+ if (this->componentPackageMethod == ONE_PACKAGE) {
return "ALL_IN_ONE";
- }
+ }
- if(this->componentPackageMethod == ONE_PACKAGE_PER_GROUP)
- {
+ if (this->componentPackageMethod == ONE_PACKAGE_PER_GROUP) {
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
- std::string groupVar = "CPACK_COMPONENT_" +
- cmSystemTools::UpperCase(componentName) + "_GROUP";
- const char* _groupName = GetOption(groupVar.c_str());
- if (_groupName)
- {
+ std::string groupVar =
+ "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
+ const char* _groupName = GetOption(groupVar);
+ if (_groupName) {
std::string groupName = _groupName;
- groupName = GetComponentPackageFileName(package_file_name,
- groupName, true);
+ groupName =
+ GetComponentPackageFileName(package_file_name, groupName, true);
return groupName;
- }
}
+ }
return GetComponentPackageFileName(package_file_name, componentName, false);
}
+
+bool cmCPackDragNDropGenerator::WriteLicense(
+ cmGeneratedFileStream& outputStream, int licenseNumber,
+ std::string licenseLanguage, std::string licenseFile, std::string* error)
+{
+ if (!licenseFile.empty() && !singleLicense) {
+ licenseNumber = 5002;
+ licenseLanguage = "English";
+ }
+
+ // License header
+ outputStream << "data 'TEXT' (" << licenseNumber << ", \"" << licenseLanguage
+ << "\") {\n";
+ // License body
+ std::string actual_license = !licenseFile.empty()
+ ? licenseFile
+ : (slaDirectory + "/" + licenseLanguage + ".license.txt");
+ cmsys::ifstream license_ifs;
+ license_ifs.open(actual_license.c_str());
+ if (license_ifs.is_open()) {
+ while (license_ifs.good()) {
+ std::string line;
+ std::getline(license_ifs, line);
+ if (!line.empty()) {
+ EscapeQuotesAndBackslashes(line);
+ std::vector<std::string> lines;
+ if (!this->BreakLongLine(line, lines, error)) {
+ return false;
+ }
+ for (size_t i = 0; i < lines.size(); ++i) {
+ outputStream << " \"" << lines[i] << "\"\n";
+ }
+ }
+ outputStream << " \"\\n\"\n";
+ }
+ license_ifs.close();
+ }
+
+ // End of License
+ outputStream << "};\n\n";
+ if (!licenseFile.empty() && !singleLicense) {
+ outputStream << SLASTREnglish;
+ } else {
+ // Menu header
+ outputStream << "resource 'STR#' (" << licenseNumber << ", \""
+ << licenseLanguage << "\") {\n";
+ outputStream << " {\n";
+
+ // Menu body
+ cmsys::ifstream menu_ifs;
+ menu_ifs.open(
+ (slaDirectory + "/" + licenseLanguage + ".menu.txt").c_str());
+ if (menu_ifs.is_open()) {
+ size_t lines_written = 0;
+ while (menu_ifs.good()) {
+ // Lines written from original file, not from broken up lines
+ std::string line;
+ std::getline(menu_ifs, line);
+ if (!line.empty()) {
+ EscapeQuotesAndBackslashes(line);
+ std::vector<std::string> lines;
+ if (!this->BreakLongLine(line, lines, error)) {
+ return false;
+ }
+ for (size_t i = 0; i < lines.size(); ++i) {
+ std::string comma;
+ // We need a comma after every complete string,
+ // but not on the very last line
+ if (lines_written != 8 && i == lines.size() - 1) {
+ comma = ",";
+ } else {
+ comma = "";
+ }
+ outputStream << " \"" << lines[i] << "\"" << comma << "\n";
+ }
+ ++lines_written;
+ }
+ }
+ menu_ifs.close();
+ }
+
+ // End of menu
+ outputStream << " }\n";
+ outputStream << "};\n";
+ outputStream << "\n";
+ }
+
+ return true;
+}
+
+bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
+ std::vector<std::string>& lines,
+ std::string* error)
+{
+ const size_t max_line_length = 512;
+ for (size_t i = 0; i < line.size(); i += max_line_length) {
+ size_t line_length = max_line_length;
+ if (i + line_length > line.size()) {
+ line_length = line.size() - i;
+ } 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 "
+ "(or character sequences not broken up by spaces or newlines) "
+ "in your license file which are more than 512 characters long.";
+ return false;
+ }
+ lines.push_back(line.substr(i, line_length));
+ }
+ return true;
+}
+
+void cmCPackDragNDropGenerator::EscapeQuotesAndBackslashes(std::string& line)
+{
+ std::string::size_type backslash_pos = line.find('\\');
+ while (backslash_pos != std::string::npos) {
+ line.replace(backslash_pos, 1, "\\\\");
+ backslash_pos = line.find('\\', backslash_pos + 2);
+ }
+
+ std::string::size_type quote_pos = line.find('\"');
+ while (quote_pos != std::string::npos) {
+ line.replace(quote_pos, 1, "\\\"");
+ quote_pos = line.find('\"', quote_pos + 2);
+ }
+}
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index 808c61886..ae2cc173f 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -1,20 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackDragNDropGenerator_h
#define cmCPackDragNDropGenerator_h
+#include "cmConfigure.h"
+
+#include <sstream>
+#include <stddef.h>
+#include <string>
+#include <vector>
+
#include "cmCPackGenerator.h"
+class cmGeneratedFileStream;
+
/** \class cmCPackDragNDropGenerator
* \brief A generator for OSX drag-n-drop installs
*/
@@ -27,21 +26,32 @@ public:
virtual ~cmCPackDragNDropGenerator();
protected:
- virtual int InitializeInternal();
- virtual const char* GetOutputExtension();
- int PackageFiles();
- bool SupportsComponentInstallation() const;
-
+ int InitializeInternal() CM_OVERRIDE;
+ const char* GetOutputExtension() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
- bool CopyFile(cmOStringStream& source, cmOStringStream& target);
- bool RunCommand(cmOStringStream& command, std::string* output = 0);
+ 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);
+ std::string GetComponentInstallDirNameSuffix(
+ const std::string& componentName) CM_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);
+ bool BreakLongLine(const std::string& line, std::vector<std::string>& lines,
+ std::string* error);
+ void EscapeQuotesAndBackslashes(std::string& line);
};
#endif
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 3c685bd9d..d8e2753cf 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -1,124 +1,104 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackGenerator.h"
-#include "cmMakefile.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <utility>
+
+#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
-#include "cmake.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
+#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
-#include "cmCPackComponentGroup.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateSnapshot.h"
+#include "cmWorkingDirectory.h"
#include "cmXMLSafe.h"
-
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Glob.hxx>
-#include <algorithm>
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
#if defined(__HAIKU__)
-#include <StorageKit.h>
+#include <FindDirectory.h>
+#include <StorageDefs.h>
#endif
-//----------------------------------------------------------------------
cmCPackGenerator::cmCPackGenerator()
{
this->GeneratorVerbose = cmSystemTools::OUTPUT_NONE;
- this->MakefileMap = 0;
- this->Logger = 0;
+ this->MakefileMap = CM_NULLPTR;
+ this->Logger = CM_NULLPTR;
this->componentPackageMethod = ONE_PACKAGE_PER_GROUP;
}
-//----------------------------------------------------------------------
cmCPackGenerator::~cmCPackGenerator()
{
- this->MakefileMap = 0;
+ this->MakefileMap = CM_NULLPTR;
}
-//----------------------------------------------------------------------
-void cmCPackGeneratorProgress(const char *msg, float prog, void* ptr)
+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 char* msg, float progress)
{
(void)progress;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
}
-//----------------------------------------------------------------------
int cmCPackGenerator::PrepareNames()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Create temp directory." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Create temp directory." << std::endl);
// 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);
- return 0;
- }
- else if (SETDESTDIR_SHOULD_NOT_BE_USED==SupportsSetDestdir())
- {
- cmCPackLogger(cmCPackLog::LOG_WARNING,
- "CPACK_SET_DESTDIR is set to ON but it is "
- << "usually a bad idea to do that with '"
- << Name << "' generator. Use at your own risk."
- << std::endl);
- }
+ 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);
+ return 0;
+ }
+ if (SETDESTDIR_SHOULD_NOT_BE_USED == SupportsSetDestdir()) {
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_SET_DESTDIR is set to ON but it is "
+ << "usually a bad idea to do that with '" << Name
+ << "' generator. Use at your own risk." << std::endl);
+ }
}
std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
tempDirectory += "/_CPack_Packages/";
const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
- if ( toplevelTag )
- {
+ if (toplevelTag) {
tempDirectory += toplevelTag;
tempDirectory += "/";
- }
+ }
tempDirectory += this->GetOption("CPACK_GENERATOR");
std::string topDirectory = tempDirectory;
const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
- if(!pfname)
- {
+ if (!pfname) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_FILE_NAME not specified" << std::endl);
return 0;
- }
+ }
std::string outName = pfname;
tempDirectory += "/" + outName;
- if(!this->GetOutputExtension())
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "No output extension specified" << std::endl);
+ if (!this->GetOutputExtension()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "No output extension specified"
+ << std::endl);
return 0;
- }
+ }
outName += this->GetOutputExtension();
const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
- if(!pdir)
- {
+ if (!pdir) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_DIRECTORY not specified" << std::endl);
return 0;
- }
+ }
std::string destFile = pdir;
this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile.c_str());
@@ -131,442 +111,408 @@ int cmCPackGenerator::PrepareNames()
this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
outFile.c_str());
this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath());
- this->SetOptionIfNotSet("CPACK_NATIVE_INSTALL_DIRECTORY",
+ this->SetOptionIfNotSet(
+ "CPACK_NATIVE_INSTALL_DIRECTORY",
cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str());
this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY",
tempDirectory.c_str());
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 ( !cmSystemTools::FileExists(descFileName) )
- {
+ "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 (!cmSystemTools::FileExists(descFileName)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find description file name: ["
- << descFileName << "]" << std::endl);
+ << descFileName << "]" << std::endl);
return 0;
- }
- std::ifstream ifs(descFileName);
- if ( !ifs )
- {
+ }
+ cmsys::ifstream ifs(descFileName);
+ if (!ifs) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot open description file name: " << descFileName << std::endl);
+ "Cannot open description file name: " << descFileName
+ << std::endl);
return 0;
- }
- cmOStringStream ostr;
+ }
+ std::ostringstream ostr;
std::string line;
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Read description file: " << descFileName << std::endl);
- while ( ifs && cmSystemTools::GetLineFromStream(ifs, line) )
- {
+ "Read description file: " << descFileName << std::endl);
+ while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) {
ostr << cmXMLSafe(line) << std::endl;
- }
- this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
}
- if ( !this->GetOption("CPACK_PACKAGE_DESCRIPTION") )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
+ }
+ if (!this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"Project description not specified. Please specify "
"CPACK_PACKAGE_DESCRIPTION or CPACK_PACKAGE_DESCRIPTION_FILE."
- << std::endl);
+ << std::endl);
return 0;
+ }
+ 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);
+ return 0;
}
+ }
this->SetOptionIfNotSet("CPACK_REMOVE_TOPLEVEL_DIRECTORY", "1");
return 1;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::InstallProject()
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Install projects" << std::endl);
this->CleanTemporaryDirectory();
- std::string bareTempInstallDirectory
- = this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
+ 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"));
- if (!setDestDir)
- {
+ bool setDestDir = cmSystemTools::IsOn(this->GetOption("CPACK_SET_DESTDIR")) |
+ cmSystemTools::IsInternallyOn(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.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem creating temporary directory: "
- << (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
- << std::endl);
+ "Problem creating temporary directory: "
+ << (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
+ << std::endl);
return 0;
- }
+ }
- if ( setDestDir )
- {
+ if (setDestDir) {
std::string destDir = "DESTDIR=";
destDir += tempInstallDirectory;
- cmSystemTools::PutEnv(destDir.c_str());
- }
- else
- {
+ cmSystemTools::PutEnv(destDir);
+ } else {
// Make sure there is no destdir
cmSystemTools::PutEnv("DESTDIR=");
- }
+ }
// If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
// as listed
- if ( !this->InstallProjectViaInstallCommands(
- setDestDir, tempInstallDirectory) )
- {
+ if (!this->InstallProjectViaInstallCommands(setDestDir,
+ tempInstallDirectory)) {
return 0;
- }
+ }
// If the CPackConfig file sets CPACK_INSTALL_SCRIPT then run them
// as listed
- if ( !this->InstallProjectViaInstallScript(
- setDestDir, tempInstallDirectory) )
- {
+ if (!this->InstallProjectViaInstallScript(setDestDir,
+ tempInstallDirectory)) {
return 0;
- }
+ }
// 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)) {
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.c_str()) )
- {
+ if (!this->InstallProjectViaInstallCMakeProjects(setDestDir,
+ bareTempInstallDirectory)) {
return 0;
- }
+ }
- if ( setDestDir )
- {
+ if (setDestDir) {
cmSystemTools::PutEnv("DESTDIR=");
- }
+ }
return res;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstallCommands(
- bool setDestDir, const char* tempInstallDirectory)
+ bool setDestDir, const std::string& tempInstallDirectory)
{
- (void) setDestDir;
+ (void)setDestDir;
const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
- if ( installCommands && *installCommands )
- {
+ if (installCommands && *installCommands) {
std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX=";
tempInstallDirectoryEnv += tempInstallDirectory;
- cmSystemTools::PutEnv(tempInstallDirectoryEnv.c_str());
+ cmSystemTools::PutEnv(tempInstallDirectoryEnv);
std::vector<std::string> installCommandsVector;
- cmSystemTools::ExpandListArgument(installCommands,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->c_str()
- << std::endl);
+ for (it = installCommandsVector.begin(); it != installCommandsVector.end();
+ ++it) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << *it << std::endl);
std::string output;
int retVal = 1;
- bool resB = cmSystemTools::RunSingleCommand(it->c_str(), &output,
- &retVal, 0, this->GeneratorVerbose, 0);
- if ( !resB || retVal )
- {
+ bool resB =
+ cmSystemTools::RunSingleCommand(it->c_str(), &output, &output, &retVal,
+ CM_NULLPTR, this->GeneratorVerbose, 0);
+ if (!resB || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/InstallOutput.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << it->c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem running install command: " << it->c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors"
- << std::endl);
+ ofs << "# Run command: " << *it << 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);
return 0;
- }
}
}
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstalledDirectories(
- bool setDestDir, const char* tempInstallDirectory)
+ bool setDestDir, const std::string& tempInstallDirectory)
{
(void)setDestDir;
(void)tempInstallDirectory;
std::vector<cmsys::RegularExpression> ignoreFilesRegex;
const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
- if ( cpackIgnoreFiles )
- {
+ 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 )
- {
+ for (it = ignoreFilesRegexString.begin();
+ it != ignoreFilesRegexString.end(); ++it) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Create ignore files regex for: " << it->c_str() << std::endl);
+ "Create ignore files regex for: " << *it << std::endl);
ignoreFilesRegex.push_back(it->c_str());
- }
}
- const char* installDirectories
- = this->GetOption("CPACK_INSTALLED_DIRECTORIES");
- if ( installDirectories && *installDirectories )
- {
+ }
+ const char* installDirectories =
+ this->GetOption("CPACK_INSTALLED_DIRECTORIES");
+ if (installDirectories && *installDirectories) {
std::vector<std::string> installDirectoriesVector;
cmSystemTools::ExpandListArgument(installDirectories,
- installDirectoriesVector);
- if ( installDirectoriesVector.size() % 2 != 0 )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ installDirectoriesVector);
+ if (installDirectoriesVector.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> and "
"<subdirectory>. The <subdirectory> can be '.' to be installed in "
- "the toplevel directory of installation." << std::endl);
+ "the toplevel directory of installation."
+ << std::endl);
return 0;
- }
+ }
std::vector<std::string>::iterator it;
- const char* tempDir = tempInstallDirectory;
- for ( it = installDirectoriesVector.begin();
- it != installDirectoriesVector.end();
- ++it )
- {
- std::list<std::pair<std::string,std::string> > symlinkedFiles;
+ const std::string& tempDir = tempInstallDirectory;
+ for (it = installDirectoriesVector.begin();
+ it != installDirectoriesVector.end(); ++it) {
+ std::vector<std::pair<std::string, std::string> > symlinkedFiles;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
cmsys::Glob gl;
- std::string top = it->c_str();
- it ++;
- std::string subdir = it->c_str();
+ std::string top = *it;
+ it++;
+ std::string subdir = *it;
std::string findExpr = top;
findExpr += "/*";
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install directory: " << top << std::endl);
+ "- Install directory: " << top << std::endl);
gl.RecurseOn();
- if ( !gl.FindFiles(findExpr) )
- {
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory" << std::endl);
+ "Cannot find any files in the installed directory"
+ << std::endl);
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 (gfit = files.begin(); gfit != files.end(); ++gfit) {
bool skip = false;
- std::string &inFile = *gfit;
- for ( regIt= ignoreFilesRegex.begin();
- regIt!= ignoreFilesRegex.end();
- ++ regIt)
- {
- if ( regIt->find(inFile.c_str()) )
- {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Ignore file: "
- << inFile.c_str() << std::endl);
+ std::string inFile = *gfit;
+ if (cmSystemTools::FileIsDirectory(*gfit)) {
+ inFile += '/';
+ }
+ for (regIt = ignoreFilesRegex.begin(); regIt != ignoreFilesRegex.end();
+ ++regIt) {
+ if (regIt->find(inFile.c_str())) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Ignore file: " << inFile << std::endl);
skip = true;
- }
}
- if ( skip )
- {
+ }
+ if (skip) {
continue;
- }
+ }
std::string filePath = tempDir;
- filePath += "/" + subdir + "/"
- + cmSystemTools::RelativePath(top.c_str(), gfit->c_str());
+ filePath += "/" + subdir + "/" +
+ cmSystemTools::RelativePath(top.c_str(), gfit->c_str());
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy file: "
- << inFile.c_str() << " -> " << filePath.c_str() << std::endl);
+ << inFile << " -> " << filePath << std::endl);
/* If the file is a symlink we will have to re-create it */
- if ( cmSystemTools::FileIsSymlink(inFile.c_str()))
- {
+ if (cmSystemTools::FileIsSymlink(inFile)) {
std::string targetFile;
std::string inFileRelative =
- cmSystemTools::RelativePath(top.c_str(),inFile.c_str());
- cmSystemTools::ReadSymlink(inFile.c_str(),targetFile);
- symlinkedFiles.push_back(std::pair<std::string,
- std::string>(targetFile,inFileRelative));
- }
+ cmSystemTools::RelativePath(top.c_str(), inFile.c_str());
+ cmSystemTools::ReadSymlink(inFile, targetFile);
+ symlinkedFiles.push_back(
+ std::pair<std::string, std::string>(targetFile, 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())
- ) )
- {
+ 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.c_str() << " -> " << filePath.c_str() << std::endl);
+ << inFile << " -> " << filePath << std::endl);
return 0;
- }
}
+ }
/* rebuild symlinks in the installed tree */
- if (symlinkedFiles.size()>0)
- {
- std::list< std::pair<std::string,std::string> >::iterator symlinkedIt;
+ 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);
- cmSystemTools::ChangeDirectory(goToDir.c_str());
- for (symlinkedIt=symlinkedFiles.begin();
- symlinkedIt != symlinkedFiles.end();
- ++symlinkedIt)
- {
+ goToDir += "/" + 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 (!cmSystemTools::CreateSymlink((symlinkedIt->first).c_str(),
- (symlinkedIt->second).c_str()))
- {
+ << symlinkedIt->second << "--> "
+ << symlinkedIt->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: "
+ << destDir << "\nTrying to create symlink: "
+ << symlinkedIt->second << "--> "
+ << symlinkedIt->first << std::endl);
+ }
+ if (!cmSystemTools::CreateSymlink(symlinkedIt->first,
+ symlinkedIt->second)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create symlink: "
<< symlinkedIt->second << "--> "
<< symlinkedIt->first << std::endl);
return 0;
- }
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: "
- << curDir <<std::endl);
- cmSystemTools::ChangeDirectory(curDir.c_str());
}
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir
+ << std::endl);
}
}
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstallScript(
- bool setDestDir, const char* tempInstallDirectory)
+ bool setDestDir, const std::string& tempInstallDirectory)
{
- const char* cmakeScripts
- = this->GetOption("CPACK_INSTALL_SCRIPT");
- if ( cmakeScripts && *cmakeScripts )
- {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install scripts: " << cmakeScripts << std::endl);
+ const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPT");
+ if (cmakeScripts && *cmakeScripts) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts
+ << std::endl);
std::vector<std::string> cmakeScriptsVector;
- cmSystemTools::ExpandListArgument(cmakeScripts,
- cmakeScriptsVector);
+ cmSystemTools::ExpandListArgument(cmakeScripts, cmakeScriptsVector);
std::vector<std::string>::iterator it;
- for ( it = cmakeScriptsVector.begin();
- it != cmakeScriptsVector.end();
- ++it )
- {
- std::string installScript = it->c_str();
+ for (it = cmakeScriptsVector.begin(); it != cmakeScriptsVector.end();
+ ++it) {
+ std::string installScript = *it;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install script: " << installScript << std::endl);
+ "- Install script: " << installScript << std::endl);
- if ( setDestDir )
- {
+ 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.
std::string dir;
- if (this->GetOption("CPACK_INSTALL_PREFIX"))
- {
+ if (this->GetOption("CPACK_INSTALL_PREFIX")) {
dir += this->GetOption("CPACK_INSTALL_PREFIX");
- }
+ }
this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str());
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ cmCPackLogger(
+ cmCPackLog::LOG_DEBUG,
"- Using DESTDIR + CPACK_INSTALL_PREFIX... (this->SetOption)"
- << std::endl);
+ << std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'" << std::endl);
- }
- else
- {
- this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory);
+ "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
+ << std::endl);
+ } else {
+ this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Using non-DESTDIR install... (this->SetOption)" << std::endl);
+ "- Using non-DESTDIR install... (this->SetOption)"
+ << std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
- << "'" << std::endl);
- }
+ "- Setting CMAKE_INSTALL_PREFIX to '"
+ << tempInstallDirectory << "'" << std::endl);
+ }
this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR",
- tempInstallDirectory);
+ tempInstallDirectory.c_str());
this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
- tempInstallDirectory);
- int res = this->MakefileMap->ReadListFile(0, installScript.c_str());
- if ( cmSystemTools::GetErrorOccuredFlag() || !res )
- {
+ tempInstallDirectory.c_str());
+ int res = this->MakefileMap->ReadListFile(installScript.c_str());
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
return 0;
- }
}
}
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
- bool setDestDir, const char* baseTempInstallDirectory)
+ bool setDestDir, const std::string& baseTempInstallDirectory)
{
- const char* cmakeProjects
- = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
- const char* cmakeGenerator
- = this->GetOption("CPACK_CMAKE_GENERATOR");
+ const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
+ const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
std::string absoluteDestFiles;
- if ( cmakeProjects && *cmakeProjects )
- {
- if ( !cmakeGenerator )
- {
+ if (cmakeProjects && *cmakeProjects) {
+ if (!cmakeGenerator) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_INSTALL_CMAKE_PROJECTS is specified, but "
"CPACK_CMAKE_GENERATOR is not. CPACK_CMAKE_GENERATOR "
"is required to install the project."
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
std::vector<std::string> cmakeProjectsVector;
- cmSystemTools::ExpandListArgument(cmakeProjects,
- cmakeProjectsVector);
+ cmSystemTools::ExpandListArgument(cmakeProjects, cmakeProjectsVector);
std::vector<std::string>::iterator it;
- for ( it = cmakeProjectsVector.begin();
- it != cmakeProjectsVector.end();
- ++it )
- {
- if ( it+1 == cmakeProjectsVector.end() ||
- it+2 == cmakeProjectsVector.end() ||
- it+3 == cmakeProjectsVector.end() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ for (it = cmakeProjectsVector.begin(); it != cmakeProjectsVector.end();
+ ++it) {
+ if (it + 1 == cmakeProjectsVector.end() ||
+ it + 2 == cmakeProjectsVector.end() ||
+ it + 3 == cmakeProjectsVector.end()) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"Not enough items on list: CPACK_INSTALL_CMAKE_PROJECTS. "
"CPACK_INSTALL_CMAKE_PROJECTS should hold quadruplet of install "
"directory, install project name, install component, and install "
"subdirectory."
- << std::endl);
+ << std::endl);
return 0;
- }
- std::string installDirectory = it->c_str();
+ }
+ std::string installDirectory = *it;
++it;
- std::string installProjectName = it->c_str();
+ std::string installProjectName = *it;
++it;
- std::string installComponent = it->c_str();
+ std::string installComponent = *it;
++it;
- std::string installSubDirectory = it->c_str();
+ std::string installSubDirectory = *it;
std::string installFile = installDirectory + "/cmake_install.cmake";
std::vector<std::string> componentsVector;
@@ -579,131 +525,115 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
* (this works at CPack time too)
*/
if (this->SupportsComponentInstallation() &
- !(this->IsSet("CPACK_MONOLITHIC_INSTALL")))
- {
+ !(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) {
// Determine the installation types for this project (if provided).
- std::string installTypesVar = "CPACK_"
- + cmSystemTools::UpperCase(installComponent) + "_INSTALL_TYPES";
- const char *installTypes = this->GetOption(installTypesVar.c_str());
- if (installTypes && *installTypes)
- {
+ std::string installTypesVar = "CPACK_" +
+ cmSystemTools::UpperCase(installComponent) + "_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.c_str(),
- installTypeIt->c_str());
- }
+ installTypeIt != installTypesVector.end(); ++installTypeIt) {
+ this->GetInstallationType(installProjectName, *installTypeIt);
}
+ }
// Determine the set of components that will be used in this project
- std::string componentsVar
- = "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent);
- const char *components = this->GetOption(componentsVar.c_str());
- if (components && *components)
- {
+ std::string componentsVar =
+ "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent);
+ 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.c_str(), compIt->c_str());
- }
- componentInstall = true;
+ compIt != componentsVector.end(); ++compIt) {
+ GetComponent(installProjectName, *compIt);
}
+ componentInstall = true;
}
- if (componentsVector.empty())
- {
+ }
+ if (componentsVector.empty()) {
componentsVector.push_back(installComponent);
- }
+ }
- const char* buildConfig = this->GetOption("CPACK_BUILD_CONFIG");
- cmGlobalGenerator* globalGenerator
- = this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
+ const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG");
+ std::string buildConfig = buildConfigCstr ? buildConfigCstr : "";
+ cmGlobalGenerator* globalGenerator =
+ this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
cmakeGenerator);
+ if (!globalGenerator) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Specified package generator not found. "
+ "CPACK_CMAKE_GENERATOR value is invalid."
+ << std::endl);
+ return 0;
+ }
// set the global flag for unix style paths on cmSystemTools as
// soon as the generator is set. This allows gmake to be used
// on windows.
cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
// Does this generator require pre-install?
- if ( globalGenerator->GetPreinstallTargetName() )
- {
- globalGenerator->FindMakeProgram(this->MakefileMap);
- const char* cmakeMakeProgram
- = this->MakefileMap->GetDefinition("CMAKE_MAKE_PROGRAM");
- std::string buildCommand
- = globalGenerator->GenerateBuildCommand(cmakeMakeProgram,
- installProjectName.c_str(), 0, 0,
- globalGenerator->GetPreinstallTargetName(),
- buildConfig, false, false);
+ 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);
+ "- 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,
- &retVal,
- installDirectory.c_str(),
- this->GeneratorVerbose, 0);
- if ( !resB || retVal )
- {
+ 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.c_str() << std::endl
- << "# Directory: " << installDirectory.c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem running install command: " << buildCommand.c_str()
- << std::endl
- << "Please check " << tmpFile.c_str() << " for errors"
- << std::endl);
+ 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;
- }
}
+ }
delete globalGenerator;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install project: " << installProjectName << std::endl);
+ "- 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)
- {
+ componentIt != componentsVector.end(); ++componentIt) {
std::string tempInstallDirectory = baseTempInstallDirectory;
installComponent = *componentIt;
- if (componentInstall)
- {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install component: " << installComponent
- << std::endl);
- }
+ if (componentInstall) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install component: "
+ << installComponent << std::endl);
+ }
- cmake cm;
+ cmake cm(cmake::RoleScript);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
cm.AddCMakePaths();
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
- cmGlobalGenerator gg;
- gg.SetCMakeInstance(&cm);
- cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
- cmMakefile *mf = lg->GetMakefile();
- std::string realInstallDirectory = tempInstallDirectory;
- if ( !installSubDirectory.empty() && installSubDirectory != "/" )
- {
- realInstallDirectory += installSubDirectory;
- }
- if (componentInstall)
- {
+ 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.
@@ -713,20 +643,17 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// one install directory for each component.
tempInstallDirectory +=
GetComponentInstallDirNameSuffix(installComponent);
- if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY"))
- {
+ if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
tempInstallDirectory += "/";
tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
- }
}
+ }
- if (!setDestDir)
- {
+ if (!setDestDir) {
tempInstallDirectory += this->GetPackagingInstallPrefix();
- }
+ }
- if ( setDestDir )
- {
+ 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
@@ -739,37 +666,32 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// 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->GetOption("CPACK_SET_DESTDIR"))) {
this->SetOption("CPACK_INSTALL_PREFIX",
this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
- }
+ }
std::string dir;
- if (this->GetOption("CPACK_INSTALL_PREFIX"))
- {
+ if (this->GetOption("CPACK_INSTALL_PREFIX")) {
dir += this->GetOption("CPACK_INSTALL_PREFIX");
- }
+ }
mf->AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
cmCPackLogger(
cmCPackLog::LOG_DEBUG,
"- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf->AddDefinition)"
- << std::endl);
+ << std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
- << std::endl);
+ << std::endl);
// Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
// exists:
//
- if (cmSystemTools::StringStartsWith(dir.c_str(), "/"))
- {
+ if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) {
dir = tempInstallDirectory + dir;
- }
- else
- {
+ } else {
dir = tempInstallDirectory + "/" + dir;
- }
+ }
/*
* We must re-set DESTDIR for each component
* We must not add the CPACK_INSTALL_PREFIX part because
@@ -781,274 +703,237 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
* - Because it was already used for component install
* in order to put things in subdirs...
*/
- cmSystemTools::PutEnv(
- (std::string("DESTDIR=")+tempInstallDirectory).c_str()
- );
- 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);
+ 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
- {
+ } else {
mf->AddDefinition("CMAKE_INSTALL_PREFIX",
tempInstallDirectory.c_str());
- if ( !cmsys::SystemTools::MakeDirectory(
- tempInstallDirectory.c_str()))
- {
+ if (!cmsys::SystemTools::MakeDirectory(
+ tempInstallDirectory.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
- << tempInstallDirectory << std::endl);
+ << tempInstallDirectory << std::endl);
return 0;
- }
+ }
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Using non-DESTDIR install... (mf->AddDefinition)"
- << std::endl);
+ << std::endl);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Setting CMAKE_INSTALL_PREFIX to '"
- << tempInstallDirectory
- << "'" << std::endl);
- }
+ << tempInstallDirectory << "'" << std::endl);
+ }
- if ( buildConfig && *buildConfig )
- {
- mf->AddDefinition("BUILD_TYPE", buildConfig);
- }
- std::string installComponentLowerCase
- = cmSystemTools::LowerCase(installComponent);
- if ( installComponentLowerCase != "all" )
- {
+ 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());
- }
+ }
// 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")))
- {
+ 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)
- {
+ if (componentInstall) {
cmsys::Glob glB;
findExpr += "/*";
glB.RecurseOn();
+ glB.SetRecurseListDirs(true);
glB.FindFiles(findExpr);
filesBefore = glB.GetFiles();
- std::sort(filesBefore.begin(),filesBefore.end());
- }
+ 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 (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");
- }
+ this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf->AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION",
+ "1");
+ }
// do installation
- int res = mf->ReadListFile(0, installFile.c_str());
+ 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 (mf->GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
+ mf->AddDefinition(
+ "CPACK_ABSOLUTE_DESTINATION_FILES",
+ mf->GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES"));
+ }
// Now rebuild the list of files after installation
// of the current component (if we are in component install)
- if (componentInstall)
- {
+ 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::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());
+ 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)
- {
+ for (fit = result.begin(); fit != diff; ++fit) {
localFileName =
- cmSystemTools::RelativePath(InstallPrefix, fit->c_str());
+ cmSystemTools::RelativePath(InstallPrefix, fit->c_str());
localFileName =
- localFileName.substr(localFileName.find_first_not_of('/'),
- std::string::npos);
+ 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);
- }
+ << localFileName << "> to component <"
+ << installComponent << ">" << std::endl);
}
+ }
- if (NULL !=mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
- if (absoluteDestFiles.length()>0) {
- absoluteDestFiles +=";";
+ 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);
+ "Got some ABSOLUTE DESTINATION FILES: "
+ << absoluteDestFiles << std::endl);
// define component specific var
- if (componentInstall)
- {
+ if (componentInstall) {
std::string absoluteDestFileComponent =
- std::string("CPACK_ABSOLUTE_DESTINATION_FILES")
- + "_" + GetComponentInstallDirNameSuffix(installComponent);
- if (NULL != this->GetOption(absoluteDestFileComponent.c_str()))
- {
- std::string absoluteDestFilesListComponent =
- this->GetOption(absoluteDestFileComponent.c_str());
- absoluteDestFilesListComponent +=";";
- absoluteDestFilesListComponent +=
- mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
- this->SetOption(absoluteDestFileComponent.c_str(),
- absoluteDestFilesListComponent.c_str());
- }
- else
- {
- this->SetOption(absoluteDestFileComponent.c_str(),
- mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
- }
+ 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 )
- {
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
return 0;
- }
}
}
}
+ }
this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
absoluteDestFiles.c_str());
return 1;
}
-//----------------------------------------------------------------------
bool cmCPackGenerator::ReadListFile(const char* moduleName)
{
bool retval;
std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);
- retval = this->MakefileMap->ReadListFile(0, fullPath.c_str());
+ retval = this->MakefileMap->ReadListFile(fullPath.c_str());
// include FATAL_ERROR and ERROR in the return status
- retval = retval && (! cmSystemTools::GetErrorOccuredFlag());
+ retval = retval && (!cmSystemTools::GetErrorOccuredFlag());
return retval;
}
-//----------------------------------------------------------------------
-void cmCPackGenerator::SetOptionIfNotSet(const char* op,
- const char* value)
+void cmCPackGenerator::SetOptionIfNotSet(const std::string& op,
+ const char* value)
{
const char* def = this->MakefileMap->GetDefinition(op);
- if ( def && *def )
- {
+ if (def && *def) {
return;
- }
+ }
this->SetOption(op, value);
}
-//----------------------------------------------------------------------
-void cmCPackGenerator::SetOption(const char* op, const char* value)
+void cmCPackGenerator::SetOption(const std::string& op, const char* value)
{
- if ( !op )
- {
- return;
- }
- if ( !value )
- {
+ if (!value) {
this->MakefileMap->RemoveDefinition(op);
return;
- }
+ }
cmCPackLogger(cmCPackLog::LOG_DEBUG, this->GetNameOfClass()
- << "::SetOption(" << op << ", " << value << ")" << std::endl);
+ << "::SetOption(" << op << ", " << value << ")"
+ << std::endl);
this->MakefileMap->AddDefinition(op, value);
}
-//----------------------------------------------------------------------
int cmCPackGenerator::DoPackage()
{
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "Create package using " << this->Name.c_str() << 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
- if ( !this->PrepareNames() )
- {
+ if (!this->PrepareNames()) {
return 0;
- }
+ }
// Digest Component grouping specification
- if ( !this->PrepareGroupingKind() )
- {
+ if (!this->PrepareGroupingKind()) {
return 0;
- }
+ }
- if ( cmSystemTools::IsOn(
- 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);
- if ( !cmSystemTools::RepeatedRemoveDirectory(toplevelDirectory) )
- {
+ if (cmSystemTools::IsOn(
+ 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);
+ if (!cmSystemTools::RepeatedRemoveDirectory(toplevelDirectory)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem removing toplevel directory: "
- << toplevelDirectory
- << std::endl);
+ "Problem removing toplevel directory: "
+ << toplevelDirectory << std::endl);
return 0;
- }
}
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "About to install project " << std::endl);
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "About to install project "
+ << std::endl);
- if ( !this->InstallProject() )
- {
+ if (!this->InstallProject()) {
return 0;
- }
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Done install project " << std::endl);
-
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl);
- const char* tempPackageFileName = this->GetOption(
- "CPACK_TEMPORARY_PACKAGE_FILE_NAME");
- const char* packageFileName = this->GetOption("CPACK_OUTPUT_FILE_PATH");
+ const char* tempPackageFileName =
+ this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
@@ -1056,28 +941,27 @@ int cmCPackGenerator::DoPackage()
std::string findExpr = tempDirectory;
findExpr += "/*";
gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
gl.SetRecurseThroughSymlinks(false);
- if ( !gl.FindFiles(findExpr) )
- {
+ if (!gl.FindFiles(findExpr)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the packaging tree" << std::endl);
+ "Cannot find any files in the packaging tree" << std::endl);
return 0;
- }
+ }
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl);
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Package files to: "
- << (tempPackageFileName ? tempPackageFileName : "(NULL)") << std::endl);
- if ( cmSystemTools::FileExists(tempPackageFileName) )
- {
+ << (tempPackageFileName ? tempPackageFileName : "(NULL)")
+ << std::endl);
+ if (cmSystemTools::FileExists(tempPackageFileName)) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove old package file"
- << std::endl);
+ << std::endl);
cmSystemTools::RemoveFile(tempPackageFileName);
- }
- if ( cmSystemTools::IsOn(this->GetOption(
- "CPACK_INCLUDE_TOPLEVEL_DIRECTORY")) )
- {
+ }
+ if (cmSystemTools::IsOn(
+ this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
tempDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- }
+ }
// The files to be installed
files = gl.GetFiles();
@@ -1088,14 +972,17 @@ int cmCPackGenerator::DoPackage()
* may update this during PackageFiles.
* (either putting several names or updating the provided one)
*/
- packageFileNames.push_back(tempPackageFileName);
+ packageFileNames.push_back(tempPackageFileName ? tempPackageFileName : "");
toplevel = tempDirectory;
- if ( !this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag())
- {
+ if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
+
+ /* Prepare checksum algorithm*/
+ const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+ CM_AUTO_PTR<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : "");
/*
* Copy the generated packages to final destination
@@ -1104,64 +991,66 @@ int cmCPackGenerator::DoPackage()
* (because the specific generator did 'normalize' it)
*/
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Copying final package(s) ["
- <<packageFileNames.size()
- <<"]:"<<std::endl);
+ << packageFileNames.size() << "]:" << std::endl);
std::vector<std::string>::iterator it;
/* now copy package one by one */
- for (it=packageFileNames.begin();it!=packageFileNames.end();++it)
- {
+ for (it = packageFileNames.begin(); it != packageFileNames.end(); ++it) {
std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
+ std::string filename(cmSystemTools::GetFilenameName(*it));
tempPackageFileName = it->c_str();
- tmpPF += "/"+cmSystemTools::GetFilenameName(*it);
- packageFileName = tmpPF.c_str();
+ tmpPF += "/" + filename;
+ const char* packageFileName = tmpPF.c_str();
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy final package(s): "
- << (tempPackageFileName ? tempPackageFileName : "(NULL)" )
- << " to "
- << (packageFileName ? packageFileName : "(NULL)")
- << std::endl);
- if ( !cmSystemTools::CopyFileIfDifferent(tempPackageFileName,
- packageFileName) )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the package: "
- << (tempPackageFileName ? tempPackageFileName : "(NULL)" )
- << " to "
- << (packageFileName ? packageFileName : "(NULL)")
- << std::endl);
+ << (tempPackageFileName ? tempPackageFileName : "(NULL)")
+ << " to " << (packageFileName ? packageFileName : "(NULL)")
+ << std::endl);
+ if (!cmSystemTools::CopyFileIfDifferent(tempPackageFileName,
+ packageFileName)) {
+ cmCPackLogger(
+ 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);
+ << packageFileName << " generated." << std::endl);
+
+ /* Generate checksum file */
+ if (crypto.get() != CM_NULLPTR) {
+ std::string hashFile(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
+ hashFile +=
+ "/" + filename.substr(0, filename.rfind(this->GetOutputExtension()));
+ hashFile += "." + cmSystemTools::LowerCase(algo);
+ cmsys::ofstream outF(hashFile.c_str());
+ if (!outF) {
+ 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);
}
+ }
return 1;
}
-//----------------------------------------------------------------------
-int cmCPackGenerator::Initialize(const char* name, cmMakefile* mf)
+int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf)
{
this->MakefileMap = mf;
this->Name = name;
- if ( !this->SetCMakeRoot() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot initialize the generator" << std::endl);
- return 0;
- }
// set the running generator name
this->SetOption("CPACK_GENERATOR", this->Name.c_str());
// Load the project specific config file
- const char* config =
- this->GetOption("CPACK_PROJECT_CONFIG_FILE");
- if(config)
- {
+ const char* config = this->GetOption("CPACK_PROJECT_CONFIG_FILE");
+ if (config) {
mf->ReadListFile(config);
- }
+ }
int result = this->InitializeInternal();
- if (cmSystemTools::GetErrorOccuredFlag())
- {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return 0;
- }
+ }
// If a generator subclass did not already set this option in its
// InitializeInternal implementation, and the project did not already set
@@ -1171,513 +1060,423 @@ int cmCPackGenerator::Initialize(const char* name, cmMakefile* mf)
return result;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::InitializeInternal()
{
return 1;
}
-//----------------------------------------------------------------------
-bool cmCPackGenerator::IsSet(const char* name) const
+bool cmCPackGenerator::IsSet(const std::string& name) const
{
return this->MakefileMap->IsSet(name);
}
-//----------------------------------------------------------------------
-bool cmCPackGenerator::IsOn(const char* name) const
+bool cmCPackGenerator::IsOn(const std::string& name) const
{
return cmSystemTools::IsOn(GetOption(name));
}
-//----------------------------------------------------------------------
-const char* cmCPackGenerator::GetOption(const char* op) const
+bool cmCPackGenerator::IsSetToOff(const std::string& op) const
+{
+ const char* ret = this->MakefileMap->GetDefinition(op);
+ if (ret && *ret) {
+ return cmSystemTools::IsOff(ret);
+ }
+ return false;
+}
+
+bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const
{
const char* ret = this->MakefileMap->GetDefinition(op);
- if(!ret)
- {
+ if (ret) {
+ return !*ret;
+ }
+ return false;
+}
+
+const char* cmCPackGenerator::GetOption(const std::string& op) const
+{
+ const char* ret = this->MakefileMap->GetDefinition(op);
+ if (!ret) {
cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Warning, GetOption return NULL for: "
- << op
- << std::endl);
- }
+ "Warning, GetOption return NULL for: " << op << std::endl);
+ }
return ret;
}
-//----------------------------------------------------------------------
-int cmCPackGenerator::SetCMakeRoot()
+std::vector<std::string> cmCPackGenerator::GetOptions() const
{
- // use the CMAKE_ROOT from cmake which should have been
- // found by now
- const char* root=
- this->MakefileMap->GetDefinition("CMAKE_ROOT");
-
- if(root)
- {
- this->CMakeRoot = root;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: "
- << this->CMakeRoot.c_str() << std::endl);
- this->SetOption("CMAKE_ROOT", this->CMakeRoot.c_str());
- return 1;
- }
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Could not find CMAKE_ROOT !!!"
- << std::endl
- << "CMake has most likely not been installed correctly."
- << std::endl
- <<"Modules directory not found in"
- << std::endl);
- return 0;
+ return this->MakefileMap->GetDefinitions();
}
-//----------------------------------------------------------------------
int cmCPackGenerator::PackageFiles()
{
return 0;
}
-//----------------------------------------------------------------------
const char* cmCPackGenerator::GetInstallPath()
{
- if ( !this->InstallPath.empty() )
- {
+ if (!this->InstallPath.empty()) {
return this->InstallPath.c_str();
- }
+ }
#if defined(_WIN32) && !defined(__CYGWIN__)
- const char* prgfiles = cmsys::SystemTools::GetEnv("ProgramFiles");
- const char* sysDrive = cmsys::SystemTools::GetEnv("SystemDrive");
- if ( prgfiles )
- {
+ std::string prgfiles;
+ std::string sysDrive;
+ if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
this->InstallPath = prgfiles;
- }
- else if ( sysDrive )
- {
+ } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
this->InstallPath = sysDrive;
this->InstallPath += "/Program Files";
- }
- else
- {
+ } else {
this->InstallPath = "c:/Program Files";
- }
+ }
this->InstallPath += "/";
this->InstallPath += this->GetOption("CPACK_PACKAGE_NAME");
this->InstallPath += "-";
this->InstallPath += this->GetOption("CPACK_PACKAGE_VERSION");
#elif defined(__HAIKU__)
- BPath dir;
- if (find_directory(B_COMMON_DIRECTORY, &dir) == B_OK)
- {
- this->InstallPath = dir.Path();
- }
- else
- {
- this->InstallPath = "/boot/common";
- }
+ char dir[B_PATH_NAME_LENGTH];
+ if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) ==
+ B_OK) {
+ this->InstallPath = dir;
+ } else {
+ this->InstallPath = "/boot/system";
+ }
#else
this->InstallPath = "/usr/local/";
#endif
return this->InstallPath.c_str();
}
-//----------------------------------------------------------------------
const char* cmCPackGenerator::GetPackagingInstallPrefix()
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "GetPackagingInstallPrefix: '"
- << this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'" << std::endl);
+ << this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
+ << std::endl);
return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
}
-//----------------------------------------------------------------------
std::string cmCPackGenerator::FindTemplate(const char* name)
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for template: "
- << (name ? name : "(NULL)") << std::endl);
+ << (name ? name : "(NULL)") << std::endl);
std::string ffile = this->MakefileMap->GetModulesFile(name);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Found template: "
- << ffile.c_str() << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Found template: " << ffile
+ << std::endl);
return ffile;
}
-//----------------------------------------------------------------------
bool cmCPackGenerator::ConfigureString(const std::string& inString,
- std::string& outString)
+ std::string& outString)
{
- this->MakefileMap->ConfigureString(inString,
- outString, true, false);
+ this->MakefileMap->ConfigureString(inString, outString, true, false);
return true;
}
-//----------------------------------------------------------------------
-bool cmCPackGenerator::ConfigureFile(const char* inName,
- const char* outName, bool copyOnly /* = false */)
+bool cmCPackGenerator::ConfigureFile(const char* inName, const char* outName,
+ bool copyOnly /* = false */)
{
- return this->MakefileMap->ConfigureFile(inName, outName,
- copyOnly, true, false) == 1;
+ return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
+ false) == 1;
}
-//----------------------------------------------------------------------
int cmCPackGenerator::CleanTemporaryDirectory()
{
- std::string tempInstallDirectoryWithPostfix
- = this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
+ std::string tempInstallDirectoryWithPostfix =
+ this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
const char* tempInstallDirectory = tempInstallDirectoryWithPostfix.c_str();
- if(cmsys::SystemTools::FileExists(tempInstallDirectory))
- {
+ if (cmsys::SystemTools::FileExists(tempInstallDirectory)) {
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Clean temporary : "
- << tempInstallDirectory << std::endl);
- if(!cmSystemTools::RepeatedRemoveDirectory(tempInstallDirectory))
- {
+ "- Clean temporary : " << tempInstallDirectory << std::endl);
+ if (!cmSystemTools::RepeatedRemoveDirectory(tempInstallDirectory)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem removing temporary directory: " <<
- tempInstallDirectory
- << std::endl);
+ "Problem removing temporary directory: "
+ << tempInstallDirectory << std::endl);
return 0;
- }
}
+ }
return 1;
}
-//----------------------------------------------------------------------
+cmInstalledFile const* cmCPackGenerator::GetInstalledFile(
+ std::string const& name) const
+{
+ cmake const* cm = this->MakefileMap->GetCMakeInstance();
+ return cm->GetInstalledFile(name);
+}
+
int cmCPackGenerator::PrepareGroupingKind()
{
// find a component package method specified by the user
ComponentPackageMethod method = UNKNOWN_COMPONENT_PACKAGE_METHOD;
- if(this->GetOption("CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE"))
- {
+ if (this->GetOption("CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE")) {
method = ONE_PACKAGE;
- }
+ }
- if(this->GetOption("CPACK_COMPONENTS_IGNORE_GROUPS"))
- {
+ if (this->GetOption("CPACK_COMPONENTS_IGNORE_GROUPS")) {
method = ONE_PACKAGE_PER_COMPONENT;
- }
+ }
- if(this->GetOption("CPACK_COMPONENTS_ONE_PACKAGE_PER_GROUP"))
- {
+ if (this->GetOption("CPACK_COMPONENTS_ONE_PACKAGE_PER_GROUP")) {
method = ONE_PACKAGE_PER_GROUP;
- }
+ }
std::string groupingType;
// Second way to specify grouping
- if (NULL != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
- groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
+ if (CM_NULLPTR != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
+ groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
}
- if (groupingType.length()>0)
- {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
- << this->Name << "]"
- << " requested component grouping = "<< groupingType <<std::endl);
- if (groupingType == "ALL_COMPONENTS_IN_ONE")
- {
+ if (!groupingType.empty()) {
+ 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")
- {
+ } else if (groupingType == "IGNORE") {
method = ONE_PACKAGE_PER_COMPONENT;
- }
- else if (groupingType == "ONE_PER_GROUP")
- {
+ } else if (groupingType == "ONE_PER_GROUP") {
method = ONE_PACKAGE_PER_GROUP;
- }
- else
- {
- cmCPackLogger(cmCPackLog::LOG_WARNING, "["
+ } else {
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING, "["
<< this->Name << "]"
- << " requested component grouping type <"<< groupingType
+ << " requested component grouping type <" << groupingType
<< "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
<< std::endl);
- }
}
+ }
// Some components were defined but NO group
// fallback to default if not group based
- if(method == ONE_PACKAGE_PER_GROUP &&
- this->ComponentGroups.empty() && !this->Components.empty())
- {
- if(componentPackageMethod == ONE_PACKAGE)
- {
+ if (method == ONE_PACKAGE_PER_GROUP && this->ComponentGroups.empty() &&
+ !this->Components.empty()) {
+ if (componentPackageMethod == ONE_PACKAGE) {
method = ONE_PACKAGE;
- }
- else
- {
+ } else {
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);
}
+ cmCPackLogger(
+ 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
- if(method != UNKNOWN_COMPONENT_PACKAGE_METHOD)
- {
+ if (method != UNKNOWN_COMPONENT_PACKAGE_METHOD) {
componentPackageMethod = method;
- }
+ }
- const char* method_names[] =
- {
- "ALL_COMPONENTS_IN_ONE",
- "IGNORE_GROUPS",
- "ONE_PER_GROUP"
- };
+ 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;
}
-//----------------------------------------------------------------------
std::string cmCPackGenerator::GetComponentInstallDirNameSuffix(
- const std::string& componentName) {
+ const std::string& componentName)
+{
return componentName;
}
-//----------------------------------------------------------------------
std::string cmCPackGenerator::GetComponentPackageFileName(
- const std::string& initialPackageFileName,
- const std::string& groupOrComponentName,
- bool isGroupName) {
+ const std::string& initialPackageFileName,
+ const std::string& groupOrComponentName, bool isGroupName)
+{
/*
* the default behavior is to use the
* component [group] name as a suffix
*/
- std::string suffix="-"+groupOrComponentName;
+ std::string suffix = "-" + groupOrComponentName;
/* check if we should use DISPLAY name */
- std::string dispNameVar = "CPACK_"+Name+"_USE_DISPLAY_NAME_IN_FILENAME";
- if (IsOn(dispNameVar.c_str()))
- {
+ std::string dispNameVar = "CPACK_" + Name + "_USE_DISPLAY_NAME_IN_FILENAME";
+ if (IsOn(dispNameVar)) {
/* the component Group case */
- if (isGroupName)
- {
- std::string groupDispVar = "CPACK_COMPONENT_GROUP_"
- + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
- const char* groupDispName = GetOption(groupDispVar.c_str());
- if (groupDispName)
- {
- suffix = "-"+std::string(groupDispName);
- }
+ if (isGroupName) {
+ std::string groupDispVar = "CPACK_COMPONENT_GROUP_" +
+ cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
+ const char* groupDispName = GetOption(groupDispVar);
+ if (groupDispName) {
+ suffix = "-" + std::string(groupDispName);
}
+ }
/* the [single] component case */
- else
- {
- std::string dispVar = "CPACK_COMPONENT_"
- + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
- const char* dispName = GetOption(dispVar.c_str());
- if(dispName)
- {
- suffix = "-"+std::string(dispName);
- }
- }
+ else {
+ std::string dispVar = "CPACK_COMPONENT_" +
+ cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
+ const char* dispName = GetOption(dispVar);
+ if (dispName) {
+ suffix = "-" + std::string(dispName);
}
+ }
+ }
return initialPackageFileName + suffix;
}
-//----------------------------------------------------------------------
enum cmCPackGenerator::CPackSetDestdirSupport
cmCPackGenerator::SupportsSetDestdir() const
{
return cmCPackGenerator::SETDESTDIR_SUPPORTED;
}
-//----------------------------------------------------------------------
bool cmCPackGenerator::SupportsAbsoluteDestination() const
{
return true;
}
-//----------------------------------------------------------------------
bool cmCPackGenerator::SupportsComponentInstallation() const
{
return false;
}
-//----------------------------------------------------------------------
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()));
}
-//----------------------------------------------------------------------
-cmCPackInstallationType*
-cmCPackGenerator::GetInstallationType(const char *projectName,
- const char *name)
+cmCPackInstallationType* cmCPackGenerator::GetInstallationType(
+ const std::string& projectName, const std::string& name)
{
- (void) projectName;
+ (void)projectName;
bool hasInstallationType = this->InstallationTypes.count(name) != 0;
- cmCPackInstallationType *installType = &this->InstallationTypes[name];
- if (!hasInstallationType)
- {
+ cmCPackInstallationType* installType = &this->InstallationTypes[name];
+ if (!hasInstallationType) {
// Define the installation type
- std::string macroPrefix = "CPACK_INSTALL_TYPE_"
- + cmsys::SystemTools::UpperCase(name);
+ std::string macroPrefix =
+ "CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name);
installType->Name = name;
- const char* displayName
- = this->GetOption((macroPrefix + "_DISPLAY_NAME").c_str());
- if (displayName && *displayName)
- {
+ const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ if (displayName && *displayName) {
installType->DisplayName = displayName;
- }
- else
- {
+ } else {
installType->DisplayName = installType->Name;
- }
-
- installType->Index = static_cast<unsigned>(
- this->InstallationTypes.size());
}
+
+ installType->Index = static_cast<unsigned>(this->InstallationTypes.size());
+ }
return installType;
}
-//----------------------------------------------------------------------
-cmCPackComponent*
-cmCPackGenerator::GetComponent(const char *projectName, const char *name)
+cmCPackComponent* cmCPackGenerator::GetComponent(
+ const std::string& projectName, const std::string& name)
{
bool hasComponent = this->Components.count(name) != 0;
- cmCPackComponent *component = &this->Components[name];
- if (!hasComponent)
- {
+ cmCPackComponent* component = &this->Components[name];
+ if (!hasComponent) {
// Define the component
- std::string macroPrefix = "CPACK_COMPONENT_"
- + cmsys::SystemTools::UpperCase(name);
+ std::string macroPrefix =
+ "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name);
component->Name = name;
- const char* displayName
- = this->GetOption((macroPrefix + "_DISPLAY_NAME").c_str());
- if (displayName && *displayName)
- {
+ const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ if (displayName && *displayName) {
component->DisplayName = displayName;
- }
- else
- {
+ } else {
component->DisplayName = component->Name;
- }
- component->IsHidden
- = this->IsSet((macroPrefix + "_HIDDEN").c_str());
- component->IsRequired
- = this->IsSet((macroPrefix + "_REQUIRED").c_str());
- component->IsDisabledByDefault
- = this->IsSet((macroPrefix + "_DISABLED").c_str());
- component->IsDownloaded
- = this->IsSet((macroPrefix + "_DOWNLOADED").c_str())
- || cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
-
- const char* archiveFile = this->GetOption((macroPrefix +
- "_ARCHIVE_FILE").c_str());
- if (archiveFile && *archiveFile)
- {
+ }
+ component->IsHidden = this->IsOn(macroPrefix + "_HIDDEN");
+ 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"));
+
+ const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
+ if (archiveFile && *archiveFile) {
component->ArchiveFile = archiveFile;
- }
+ }
+
+ const char* plist = this->GetOption(macroPrefix + "_PLIST");
+ if (plist && *plist) {
+ component->Plist = plist;
+ }
- const char* groupName = this->GetOption((macroPrefix + "_GROUP").c_str());
- if (groupName && *groupName)
- {
+ const char* groupName = this->GetOption(macroPrefix + "_GROUP");
+ if (groupName && *groupName) {
component->Group = GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
- }
- else
- {
- component->Group = 0;
- }
+ } else {
+ component->Group = CM_NULLPTR;
+ }
- const char* description
- = this->GetOption((macroPrefix + "_DESCRIPTION").c_str());
- if (description && *description)
- {
+ const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
+ if (description && *description) {
component->Description = description;
- }
+ }
// Determine the installation types.
- const char *installTypes
- = this->GetOption((macroPrefix + "_INSTALL_TYPES").c_str());
- if (installTypes && *installTypes)
- {
+ 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)
- {
+ installTypesIt != installTypesVector.end(); ++installTypesIt) {
component->InstallationTypes.push_back(
- this->GetInstallationType(projectName, installTypesIt->c_str()));
- }
+ this->GetInstallationType(projectName, *installTypesIt));
}
+ }
// Determine the component dependencies.
- const char *depends = this->GetOption((macroPrefix + "_DEPENDS").c_str());
- if (depends && *depends)
- {
+ 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->c_str());
+ for (dependIt = dependsVector.begin(); dependIt != dependsVector.end();
+ ++dependIt) {
+ cmCPackComponent* child = GetComponent(projectName, *dependIt);
component->Dependencies.push_back(child);
child->ReverseDependencies.push_back(component);
- }
}
}
+ }
return component;
}
-//----------------------------------------------------------------------
-cmCPackComponentGroup*
-cmCPackGenerator::GetComponentGroup(const char *projectName, const char *name)
+cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
+ const std::string& projectName, const std::string& name)
{
- (void) projectName;
- std::string macroPrefix = "CPACK_COMPONENT_GROUP_"
- + cmsys::SystemTools::UpperCase(name);
+ (void)projectName;
+ std::string macroPrefix =
+ "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(name);
bool hasGroup = this->ComponentGroups.count(name) != 0;
- cmCPackComponentGroup *group = &this->ComponentGroups[name];
- if (!hasGroup)
- {
+ cmCPackComponentGroup* group = &this->ComponentGroups[name];
+ if (!hasGroup) {
// Define the group
group->Name = name;
- const char* displayName
- = this->GetOption((macroPrefix + "_DISPLAY_NAME").c_str());
- if (displayName && *displayName)
- {
+ const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ if (displayName && *displayName) {
group->DisplayName = displayName;
- }
- else
- {
+ } else {
group->DisplayName = group->Name;
- }
+ }
- const char* description
- = this->GetOption((macroPrefix + "_DESCRIPTION").c_str());
- if (description && *description)
- {
+ const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
+ if (description && *description) {
group->Description = description;
- }
- group->IsBold
- = this->IsSet((macroPrefix + "_BOLD_TITLE").c_str());
- group->IsExpandedByDefault
- = this->IsSet((macroPrefix + "_EXPANDED").c_str());
- const char* parentGroupName
- = this->GetOption((macroPrefix + "_PARENT_GROUP").c_str());
- if (parentGroupName && *parentGroupName)
- {
+ }
+ group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE");
+ group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED");
+ const char* parentGroupName =
+ this->GetOption(macroPrefix + "_PARENT_GROUP");
+ if (parentGroupName && *parentGroupName) {
group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
group->ParentGroup->Subgroups.push_back(group);
- }
- else
- {
- group->ParentGroup = 0;
- }
+ } else {
+ group->ParentGroup = CM_NULLPTR;
}
+ }
return group;
}
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 8fafef93d..45777fa05 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -1,66 +1,38 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackGenerator_h
#define cmCPackGenerator_h
-#include "cmObject.h"
-#include "cmSystemTools.h"
+#include "cmConfigure.h"
+
#include <map>
+#include <sstream>
+#include <string>
#include <vector>
-#include "cmCPackComponentGroup.h" // cmCPackComponent and friends
- // Forward declarations are insufficient since we use them in
- // std::map data members below...
-
-#define cmCPackTypeMacro(class, superclass) \
- cmTypeMacro(class, superclass); \
- static cmCPackGenerator* CreateGenerator() { return new class; }
-
-#define cmCPackLogger(logType, msg) \
- do { \
- cmOStringStream cmCPackLog_msg; \
- cmCPackLog_msg << msg; \
- this->Logger->Log(logType, __FILE__, __LINE__,\
- cmCPackLog_msg.str().c_str());\
- } while ( 0 )
-
-#ifdef cerr
-# undef cerr
-#endif
-#define cerr no_cerr_use_cmCPack_Log
-
-#ifdef cout
-# undef cout
-#endif
-#define cout no_cout_use_cmCPack_Log
+#include "cmCPackComponentGroup.h"
+#include "cmSystemTools.h"
-class cmMakefile;
class cmCPackLog;
+class cmInstalledFile;
+class cmMakefile;
/** \class cmCPackGenerator
* \brief A superclass of all CPack Generators
*
*/
-class cmCPackGenerator : public cmObject
+class cmCPackGenerator
{
public:
- cmTypeMacro(cmCPackGenerator, cmObject);
+ virtual const char* GetNameOfClass() = 0;
/**
* If verbose then more information is printed out
*/
void SetVerbose(bool val)
- { this->GeneratorVerbose = val ?
- cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE; }
+ {
+ this->GeneratorVerbose =
+ val ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE;
+ }
/**
* Returns true if the generator may work on this system.
@@ -90,7 +62,7 @@ public:
/**
* Initialize generator
*/
- int Initialize(const char* name, cmMakefile* mf);
+ int Initialize(const std::string& name, cmMakefile* mf);
/**
* Construct generator
@@ -99,14 +71,14 @@ public:
virtual ~cmCPackGenerator();
//! Set and get the options
- void SetOption(const char* op, const char* value);
- void SetOptionIfNotSet(const char* op, const char* value);
- const char* GetOption(const char* op) const;
- bool IsSet(const char* name) const;
- bool IsOn(const char* name) const;
-
- //! Set all the variables
- int SetCMakeRoot();
+ void SetOption(const std::string& op, const char* value);
+ void SetOptionIfNotSet(const std::string& op, const char* value);
+ const char* GetOption(const std::string& op) const;
+ std::vector<std::string> GetOptions() const;
+ bool IsSet(const std::string& name) const;
+ bool IsOn(const std::string& name) const;
+ bool IsSetToOff(const std::string& op) const;
+ bool IsSetToEmpty(const std::string& op) const;
//! Set the logger
void SetLogger(cmCPackLog* log) { this->Logger = log; }
@@ -130,8 +102,10 @@ protected:
int CleanTemporaryDirectory();
+ cmInstalledFile const* GetInstalledFile(std::string const& name) const;
+
virtual const char* GetOutputExtension() { return ".cpack"; }
- virtual const char* GetOutputPostfix() { return 0; }
+ virtual const char* GetOutputPostfix() { return CM_NULLPTR; }
/**
* Prepare requested grouping kind from CPACK_xxx vars
@@ -154,25 +128,25 @@ protected:
* default is "componentName"
*/
virtual std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName);
+ const std::string& componentName);
/**
* CPack specific generator may mangle CPACK_PACKAGE_FILE_NAME
* with CPACK_COMPONENT_xxxx_<NAME>_DISPLAY_NAME if
* CPACK_<GEN>_USE_DISPLAY_NAME_IN_FILENAME is ON.
- * @param[in] initialPackageFileName
- * @param[in] groupOrComponentName
- * @param[in] isGroupName
+ * @param[in] initialPackageFileName the initial package name to be mangled
+ * @param[in] groupOrComponentName the name of the group/component
+ * @param[in] isGroupName true if previous name refers to a group,
+ * false otherwise
*/
virtual std::string GetComponentPackageFileName(
- const std::string& initialPackageFileName,
- const std::string& groupOrComponentName,
- bool isGroupName);
+ const std::string& initialPackageFileName,
+ const std::string& groupOrComponentName, bool isGroupName);
/**
* Package the list of files and/or components which
* has been prepared by the beginning of DoPackage.
- * @pre @ref toplevel has been filled-in
+ * @pre the @ref toplevel has been filled-in
* @pre the list of file @ref files has been populated
* @pre packageFileNames contains at least 1 entry
* @post packageFileNames may have been updated and contains
@@ -184,26 +158,26 @@ protected:
virtual std::string FindTemplate(const char* name);
virtual bool ConfigureFile(const char* inName, const char* outName,
- bool copyOnly = false);
+ bool copyOnly = false);
virtual bool ConfigureString(const std::string& input, std::string& output);
virtual int InitializeInternal();
-
//! Run install commands if specified
virtual int InstallProjectViaInstallCommands(
- bool setDestDir, const char* tempInstallDirectory);
+ bool setDestDir, const std::string& tempInstallDirectory);
virtual int InstallProjectViaInstallScript(
- bool setDestDir, const char* tempInstallDirectory);
+ bool setDestDir, const std::string& tempInstallDirectory);
virtual int InstallProjectViaInstalledDirectories(
- bool setDestDir, const char* tempInstallDirectory);
+ bool setDestDir, const std::string& tempInstallDirectory);
virtual int InstallProjectViaInstallCMakeProjects(
- bool setDestDir, const char* tempInstallDirectory);
+ bool setDestDir, const std::string& tempInstallDirectory);
/**
* The various level of support of
* CPACK_SET_DESTDIR used by the generator.
*/
- enum CPackSetDestdirSupport {
+ enum CPackSetDestdirSupport
+ {
/* the generator works with or without it */
SETDESTDIR_SUPPORTED,
/* the generator works best if automatically handled */
@@ -246,12 +220,12 @@ protected:
* @return true if component installation is supported and wanted.
*/
virtual bool WantsComponentInstallation() const;
- virtual cmCPackInstallationType* GetInstallationType(const char *projectName,
- const char* name);
- virtual cmCPackComponent* GetComponent(const char *projectName,
- const char* name);
- virtual cmCPackComponentGroup* GetComponentGroup(const char *projectName,
- const char* name);
+ virtual cmCPackInstallationType* GetInstallationType(
+ const std::string& projectName, const std::string& name);
+ virtual cmCPackComponent* GetComponent(const std::string& projectName,
+ const std::string& name);
+ virtual cmCPackComponentGroup* GetComponentGroup(
+ const std::string& projectName, const std::string& name);
cmSystemTools::OutputOption GeneratorVerbose;
std::string Name;
@@ -284,10 +258,6 @@ protected:
*/
std::vector<std::string> files;
- std::string CPackSelf;
- std::string CMakeSelf;
- std::string CMakeRoot;
-
std::map<std::string, cmCPackInstallationType> InstallationTypes;
/**
* The set of components.
@@ -322,8 +292,23 @@ protected:
ComponentPackageMethod componentPackageMethod;
cmCPackLog* Logger;
+
private:
cmMakefile* MakefileMap;
};
+#define cmCPackTypeMacro(klass, superclass) \
+ typedef superclass Superclass; \
+ const char* GetNameOfClass() CM_OVERRIDE { return #klass; } \
+ static cmCPackGenerator* CreateGenerator() { return new klass; } \
+ class cmCPackTypeMacro_UseTrailingSemicolon
+
+#define cmCPackLogger(logType, msg) \
+ do { \
+ std::ostringstream cmCPackLog_msg; \
+ cmCPackLog_msg << msg; \
+ this->Logger->Log(logType, __FILE__, __LINE__, \
+ cmCPackLog_msg.str().c_str()); \
+ } while (false)
+
#endif
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index b36c2a2f8..31f48c7e3 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -1,196 +1,176 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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"
#include "cmCPackGenerator.h"
+#include "cmCPackLog.h"
+#include "cmCPackNSISGenerator.h"
+#include "cmCPackSTGZGenerator.h"
#include "cmCPackTGZGenerator.h"
+#include "cmCPackTXZGenerator.h"
#include "cmCPackTarBZip2Generator.h"
#include "cmCPackTarCompressGenerator.h"
#include "cmCPackZIPGenerator.h"
-#include "cmCPackSTGZGenerator.h"
-#include "cmCPackNSISGenerator.h"
#ifdef __APPLE__
-# include "cmCPackDragNDropGenerator.h"
-# include "cmCPackBundleGenerator.h"
-# include "cmCPackPackageMakerGenerator.h"
-# include "cmCPackOSXX11Generator.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"
+#if !defined(_WIN32) && !defined(__QNXNTO__) && !defined(__BEOS__) && \
+ !defined(__HAIKU__)
+#include "cmCPackDebGenerator.h"
+#include "cmCPackRPMGenerator.h"
#endif
#ifdef _WIN32
-# include "WiX/cmCPackWIXGenerator.h"
-#endif
-
-#include "cmCPackLog.h"
-
-#if defined(__BORLANDC__)
-# pragma warn -8008 /* condition is always true */
+#include "WiX/cmCPackWIXGenerator.h"
#endif
-//----------------------------------------------------------------------
cmCPackGeneratorFactory::cmCPackGeneratorFactory()
{
- if (cmCPackTGZGenerator::CanGenerate())
- {
+ if (cmCPackTGZGenerator::CanGenerate()) {
this->RegisterGenerator("TGZ", "Tar GZip compression",
- cmCPackTGZGenerator::CreateGenerator);
- }
- if (cmCPackSTGZGenerator::CanGenerate())
- {
+ cmCPackTGZGenerator::CreateGenerator);
+ }
+ if (cmCPackTXZGenerator::CanGenerate()) {
+ this->RegisterGenerator("TXZ", "Tar XZ compression",
+ cmCPackTXZGenerator::CreateGenerator);
+ }
+ if (cmCPackSTGZGenerator::CanGenerate()) {
this->RegisterGenerator("STGZ", "Self extracting Tar GZip compression",
- cmCPackSTGZGenerator::CreateGenerator);
- }
- if (cmCPackNSISGenerator::CanGenerate())
- {
+ cmCPackSTGZGenerator::CreateGenerator);
+ }
+ if (cmCPackNSISGenerator::CanGenerate()) {
this->RegisterGenerator("NSIS", "Null Soft Installer",
- cmCPackNSISGenerator::CreateGenerator);
+ cmCPackNSISGenerator::CreateGenerator);
this->RegisterGenerator("NSIS64", "Null Soft Installer (64-bit)",
- cmCPackNSISGenerator::CreateGenerator64);
- }
+ cmCPackNSISGenerator::CreateGenerator64);
+ }
+ if (cmCPackIFWGenerator::CanGenerate()) {
+ this->RegisterGenerator("IFW", "Qt Installer Framework",
+ cmCPackIFWGenerator::CreateGenerator);
+ }
#ifdef __CYGWIN__
- if (cmCPackCygwinBinaryGenerator::CanGenerate())
- {
+ if (cmCPackCygwinBinaryGenerator::CanGenerate()) {
this->RegisterGenerator("CygwinBinary", "Cygwin Binary Installer",
cmCPackCygwinBinaryGenerator::CreateGenerator);
- }
- if (cmCPackCygwinSourceGenerator::CanGenerate())
- {
+ }
+ if (cmCPackCygwinSourceGenerator::CanGenerate()) {
this->RegisterGenerator("CygwinSource", "Cygwin Source Installer",
cmCPackCygwinSourceGenerator::CreateGenerator);
- }
+ }
#endif
- if (cmCPackZIPGenerator::CanGenerate())
- {
+ if (cmCPackZIPGenerator::CanGenerate()) {
this->RegisterGenerator("ZIP", "ZIP file format",
- cmCPackZIPGenerator::CreateGenerator);
- }
+ cmCPackZIPGenerator::CreateGenerator);
+ }
+ if (cmCPack7zGenerator::CanGenerate()) {
+ this->RegisterGenerator("7Z", "7-Zip file format",
+ cmCPack7zGenerator::CreateGenerator);
+ }
#ifdef _WIN32
- if (cmCPackWIXGenerator::CanGenerate())
- {
+ if (cmCPackWIXGenerator::CanGenerate()) {
this->RegisterGenerator("WIX", "MSI file format via WiX tools",
- cmCPackWIXGenerator::CreateGenerator);
- }
+ cmCPackWIXGenerator::CreateGenerator);
+ }
#endif
- if (cmCPackTarBZip2Generator::CanGenerate())
- {
+ if (cmCPackTarBZip2Generator::CanGenerate()) {
this->RegisterGenerator("TBZ2", "Tar BZip2 compression",
- cmCPackTarBZip2Generator::CreateGenerator);
- }
- if (cmCPackTarCompressGenerator::CanGenerate())
- {
+ cmCPackTarBZip2Generator::CreateGenerator);
+ }
+ if (cmCPackTarCompressGenerator::CanGenerate()) {
this->RegisterGenerator("TZ", "Tar Compress compression",
- cmCPackTarCompressGenerator::CreateGenerator);
- }
+ cmCPackTarCompressGenerator::CreateGenerator);
+ }
#ifdef __APPLE__
- if (cmCPackDragNDropGenerator::CanGenerate())
- {
+ if (cmCPackDragNDropGenerator::CanGenerate()) {
this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop",
- cmCPackDragNDropGenerator::CreateGenerator);
- }
- if (cmCPackBundleGenerator::CanGenerate())
- {
+ cmCPackDragNDropGenerator::CreateGenerator);
+ }
+ if (cmCPackBundleGenerator::CanGenerate()) {
this->RegisterGenerator("Bundle", "Mac OSX bundle",
- cmCPackBundleGenerator::CreateGenerator);
- }
- if (cmCPackPackageMakerGenerator::CanGenerate())
- {
+ cmCPackBundleGenerator::CreateGenerator);
+ }
+ if (cmCPackPackageMakerGenerator::CanGenerate()) {
this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker installer",
- cmCPackPackageMakerGenerator::CreateGenerator);
- }
- if (cmCPackOSXX11Generator::CanGenerate())
- {
+ cmCPackPackageMakerGenerator::CreateGenerator);
+ }
+ if (cmCPackOSXX11Generator::CanGenerate()) {
this->RegisterGenerator("OSXX11", "Mac OSX X11 bundle",
- cmCPackOSXX11Generator::CreateGenerator);
- }
+ cmCPackOSXX11Generator::CreateGenerator);
+ }
+ if (cmCPackProductBuildGenerator::CanGenerate()) {
+ this->RegisterGenerator("productbuild", "Mac OSX pkg",
+ cmCPackProductBuildGenerator::CreateGenerator);
+ }
#endif
-#if !defined(_WIN32) \
- && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__)
- if (cmCPackDebGenerator::CanGenerate())
- {
+#if !defined(_WIN32) && !defined(__QNXNTO__) && !defined(__BEOS__) && \
+ !defined(__HAIKU__)
+ if (cmCPackDebGenerator::CanGenerate()) {
this->RegisterGenerator("DEB", "Debian packages",
- cmCPackDebGenerator::CreateGenerator);
- }
- if (cmCPackRPMGenerator::CanGenerate())
- {
+ cmCPackDebGenerator::CreateGenerator);
+ }
+ if (cmCPackRPMGenerator::CanGenerate()) {
this->RegisterGenerator("RPM", "RPM packages",
- cmCPackRPMGenerator::CreateGenerator);
- }
+ cmCPackRPMGenerator::CreateGenerator);
+ }
#endif
}
-//----------------------------------------------------------------------
cmCPackGeneratorFactory::~cmCPackGeneratorFactory()
{
- std::vector<cmCPackGenerator*>::iterator it;
- for ( it = this->Generators.begin(); it != this->Generators.end(); ++ it )
- {
- delete *it;
- }
+ cmDeleteAll(this->Generators);
}
-//----------------------------------------------------------------------
-cmCPackGenerator* cmCPackGeneratorFactory::NewGenerator(const char* name)
+cmCPackGenerator* cmCPackGeneratorFactory::NewGenerator(
+ const std::string& name)
{
cmCPackGenerator* gen = this->NewGeneratorInternal(name);
- if ( !gen )
- {
- return 0;
- }
+ if (!gen) {
+ return CM_NULLPTR;
+ }
this->Generators.push_back(gen);
gen->SetLogger(this->Logger);
return gen;
}
-//----------------------------------------------------------------------
cmCPackGenerator* cmCPackGeneratorFactory::NewGeneratorInternal(
- const char* name)
+ const std::string& name)
{
- if ( !name )
- {
- return 0;
- }
- cmCPackGeneratorFactory::t_GeneratorCreatorsMap::iterator it
- = this->GeneratorCreators.find(name);
- if ( it == this->GeneratorCreators.end() )
- {
- return 0;
- }
+ cmCPackGeneratorFactory::t_GeneratorCreatorsMap::iterator it =
+ this->GeneratorCreators.find(name);
+ if (it == this->GeneratorCreators.end()) {
+ return CM_NULLPTR;
+ }
return (it->second)();
}
-//----------------------------------------------------------------------
-void cmCPackGeneratorFactory::RegisterGenerator(const char* name,
- const char* generatorDescription,
+void cmCPackGeneratorFactory::RegisterGenerator(
+ const std::string& name, const char* generatorDescription,
CreateGeneratorCall* createGenerator)
{
- if ( !name || !createGenerator )
- {
+ if (!createGenerator) {
cmCPack_Log(this->Logger, cmCPackLog::LOG_ERROR,
- "Cannot register generator" << std::endl);
+ "Cannot register generator" << std::endl);
return;
- }
+ }
this->GeneratorCreators[name] = createGenerator;
this->GeneratorDescriptions[name] = generatorDescription;
}
diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h
index dff2e49eb..7f633e473 100644
--- a/Source/CPack/cmCPackGeneratorFactory.h
+++ b/Source/CPack/cmCPackGeneratorFactory.h
@@ -1,56 +1,50 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackGeneratorFactory_h
#define cmCPackGeneratorFactory_h
-#include "cmObject.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
-class cmCPackLog;
class cmCPackGenerator;
+class cmCPackLog;
/** \class cmCPackGeneratorFactory
* \brief A container for CPack generators
*
*/
-class cmCPackGeneratorFactory : public cmObject
+class cmCPackGeneratorFactory
{
public:
- cmTypeMacro(cmCPackGeneratorFactory, cmObject);
-
cmCPackGeneratorFactory();
~cmCPackGeneratorFactory();
//! Get the generator
- cmCPackGenerator* NewGenerator(const char* name);
+ cmCPackGenerator* NewGenerator(const std::string& name);
void DeleteGenerator(cmCPackGenerator* gen);
typedef cmCPackGenerator* CreateGeneratorCall();
- void RegisterGenerator(const char* name,
- const char* generatorDescription,
- CreateGeneratorCall* createGenerator);
+ void RegisterGenerator(const std::string& name,
+ const char* generatorDescription,
+ CreateGeneratorCall* createGenerator);
void SetLogger(cmCPackLog* logger) { this->Logger = logger; }
- typedef std::map<cmStdString, cmStdString> DescriptionsMap;
+ typedef std::map<std::string, std::string> DescriptionsMap;
const DescriptionsMap& GetGeneratorsList() const
- { return this->GeneratorDescriptions; }
+ {
+ return this->GeneratorDescriptions;
+ }
private:
- cmCPackGenerator* NewGeneratorInternal(const char* name);
+ cmCPackGenerator* NewGeneratorInternal(const std::string& name);
std::vector<cmCPackGenerator*> Generators;
- typedef std::map<cmStdString, CreateGeneratorCall*> t_GeneratorCreatorsMap;
+ typedef std::map<std::string, CreateGeneratorCall*> t_GeneratorCreatorsMap;
t_GeneratorCreatorsMap GeneratorCreators;
DescriptionsMap GeneratorDescriptions;
cmCPackLog* Logger;
diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx
index 4e8bf0f4e..5c7123959 100644
--- a/Source/CPack/cmCPackLog.cxx
+++ b/Source/CPack/cmCPackLog.cxx
@@ -1,21 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackLog.h"
+#include "cmConfigure.h"
+#include <iostream>
+
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------
cmCPackLog::cmCPackLog()
{
this->Verbose = false;
@@ -24,57 +16,47 @@ cmCPackLog::cmCPackLog()
this->NewLine = true;
this->LastTag = cmCPackLog::NOTAG;
-#undef cerr
-#undef cout
this->DefaultOutput = &std::cout;
this->DefaultError = &std::cerr;
- this->LogOutput = 0;
+ this->LogOutput = CM_NULLPTR;
this->LogOutputCleanup = false;
}
-//----------------------------------------------------------------------
cmCPackLog::~cmCPackLog()
{
- this->SetLogOutputStream(0);
+ this->SetLogOutputStream(CM_NULLPTR);
}
-//----------------------------------------------------------------------
void cmCPackLog::SetLogOutputStream(std::ostream* os)
{
- if ( this->LogOutputCleanup && this->LogOutput )
- {
+ if (this->LogOutputCleanup && this->LogOutput) {
delete this->LogOutput;
- }
+ }
this->LogOutputCleanup = false;
this->LogOutput = os;
}
-//----------------------------------------------------------------------
bool cmCPackLog::SetLogOutputFile(const char* fname)
{
- cmGeneratedFileStream *cg = 0;
- if ( fname )
- {
+ cmGeneratedFileStream* cg = CM_NULLPTR;
+ if (fname) {
cg = new cmGeneratedFileStream(fname);
- }
- if ( cg && !*cg )
- {
+ }
+ if (cg && !*cg) {
delete cg;
- cg = 0;
- }
+ cg = CM_NULLPTR;
+ }
this->SetLogOutputStream(cg);
- if ( !cg )
- {
+ if (!cg) {
return false;
- }
+ }
this->LogOutputCleanup = true;
return true;
}
-//----------------------------------------------------------------------
-void cmCPackLog::Log(int tag, const char* file, int line,
- const char* msg, size_t length)
+void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,
+ size_t length)
{
// By default no logging
bool display = false;
@@ -82,144 +64,118 @@ void cmCPackLog::Log(int tag, const char* file, int line,
// Display file and line number if debug
bool useFileAndLine = this->Debug;
- bool output = false;
- bool debug = false;
+ bool output = false;
+ bool debug = false;
bool warning = false;
- bool error = false;
+ bool error = false;
bool verbose = false;
// When writing in file, add list of tags whenever tag changes.
std::string tagString;
bool needTagString = false;
- if ( this->LogOutput && this->LastTag != tag )
- {
+ if (this->LogOutput && this->LastTag != tag) {
needTagString = true;
- }
+ }
- if ( tag & LOG_OUTPUT )
- {
+ if (tag & LOG_OUTPUT) {
output = true;
display = true;
- if ( needTagString )
- {
- if ( tagString.size() > 0 ) { tagString += ","; }
- tagString = "VERBOSE";
+ if (needTagString) {
+ if (!tagString.empty()) {
+ tagString += ",";
}
+ tagString = "VERBOSE";
}
- if ( tag & LOG_WARNING )
- {
+ }
+ if (tag & LOG_WARNING) {
warning = true;
display = true;
- if ( needTagString )
- {
- if ( tagString.size() > 0 ) { tagString += ","; }
- tagString = "WARNING";
+ if (needTagString) {
+ if (!tagString.empty()) {
+ tagString += ",";
}
+ tagString = "WARNING";
}
- if ( tag & LOG_ERROR )
- {
+ }
+ if (tag & LOG_ERROR) {
error = true;
display = true;
- if ( needTagString )
- {
- if ( tagString.size() > 0 ) { tagString += ","; }
- tagString = "ERROR";
+ if (needTagString) {
+ if (!tagString.empty()) {
+ tagString += ",";
}
+ tagString = "ERROR";
}
- if ( tag & LOG_DEBUG && this->Debug )
- {
+ }
+ if (tag & LOG_DEBUG && this->Debug) {
debug = true;
display = true;
- if ( needTagString )
- {
- if ( tagString.size() > 0 ) { tagString += ","; }
- tagString = "DEBUG";
+ if (needTagString) {
+ if (!tagString.empty()) {
+ tagString += ",";
}
- useFileAndLine = true;
+ tagString = "DEBUG";
}
- if ( tag & LOG_VERBOSE && this->Verbose )
- {
+ useFileAndLine = true;
+ }
+ if (tag & LOG_VERBOSE && this->Verbose) {
verbose = true;
display = true;
- if ( needTagString )
- {
- if ( tagString.size() > 0 ) { tagString += ","; }
- tagString = "VERBOSE";
+ if (needTagString) {
+ if (!tagString.empty()) {
+ tagString += ",";
}
+ tagString = "VERBOSE";
}
- if ( this->Quiet )
- {
+ }
+ if (this->Quiet) {
display = false;
+ }
+ if (this->LogOutput) {
+ if (needTagString) {
+ *this->LogOutput << "[" << file << ":" << line << " " << tagString
+ << "] ";
}
- if ( this->LogOutput )
- {
- if ( needTagString )
- {
- *this->LogOutput << "[" << file << ":" << line << " "
- << tagString << "] ";
- }
this->LogOutput->write(msg, length);
- }
+ }
this->LastTag = tag;
- if ( !display )
- {
+ if (!display) {
return;
- }
- if ( this->NewLine )
- {
- if ( error && !this->ErrorPrefix.empty() )
- {
- *this->DefaultError << this->ErrorPrefix.c_str();
- }
- else if ( warning && !this->WarningPrefix.empty() )
- {
- *this->DefaultError << this->WarningPrefix.c_str();
- }
- else if ( output && !this->OutputPrefix.empty() )
- {
- *this->DefaultOutput << this->OutputPrefix.c_str();
- }
- else if ( verbose && !this->VerbosePrefix.empty() )
- {
- *this->DefaultOutput << this->VerbosePrefix.c_str();
- }
- else if ( debug && !this->DebugPrefix.empty() )
- {
- *this->DefaultOutput << this->DebugPrefix.c_str();
- }
- else if ( !this->Prefix.empty() )
- {
- *this->DefaultOutput << this->Prefix.c_str();
- }
- if ( useFileAndLine )
- {
- if ( error || warning )
- {
+ }
+ if (this->NewLine) {
+ if (error && !this->ErrorPrefix.empty()) {
+ *this->DefaultError << this->ErrorPrefix;
+ } else if (warning && !this->WarningPrefix.empty()) {
+ *this->DefaultError << this->WarningPrefix;
+ } else if (output && !this->OutputPrefix.empty()) {
+ *this->DefaultOutput << this->OutputPrefix;
+ } else if (verbose && !this->VerbosePrefix.empty()) {
+ *this->DefaultOutput << this->VerbosePrefix;
+ } else if (debug && !this->DebugPrefix.empty()) {
+ *this->DefaultOutput << this->DebugPrefix;
+ } else if (!this->Prefix.empty()) {
+ *this->DefaultOutput << this->Prefix;
+ }
+ if (useFileAndLine) {
+ if (error || warning) {
*this->DefaultError << file << ":" << line << " ";
- }
- else
- {
+ } else {
*this->DefaultOutput << file << ":" << line << " ";
- }
}
}
- if ( error || warning )
- {
+ }
+ if (error || warning) {
this->DefaultError->write(msg, length);
this->DefaultError->flush();
- }
- else
- {
+ } else {
this->DefaultOutput->write(msg, length);
this->DefaultOutput->flush();
- }
- if ( msg[length-1] == '\n' || length > 2 )
- {
+ }
+ if (msg[length - 1] == '\n' || length > 2) {
this->NewLine = true;
- }
+ }
- if ( error )
- {
+ if (error) {
cmSystemTools::SetErrorOccured();
- }
+ }
}
diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h
index 812f1de27..10deda450 100644
--- a/Source/CPack/cmCPackLog.h
+++ b/Source/CPack/cmCPackLog.h
@@ -1,51 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackLog_h
#define cmCPackLog_h
-#include "cmObject.h"
-
-#define cmCPack_Log(ctSelf, logType, msg) \
- do { \
- cmOStringStream cmCPackLog_msg; \
- cmCPackLog_msg << msg; \
- (ctSelf)->Log(logType, __FILE__, __LINE__, cmCPackLog_msg.str().c_str());\
- } while ( 0 )
+#include "cmConfigure.h" // IWYU pragma: keep
-#ifdef cerr
-# undef cerr
-#endif
-#define cerr no_cerr_use_cmCPack_Log
-
-#ifdef cout
-# undef cout
-#endif
-#define cout no_cout_use_cmCPack_Log
+#include <ostream>
+#include <string.h>
+#include <string>
+#define cmCPack_Log(ctSelf, logType, msg) \
+ do { \
+ std::ostringstream cmCPackLog_msg; \
+ cmCPackLog_msg << msg; \
+ (ctSelf)->Log(logType, __FILE__, __LINE__, cmCPackLog_msg.str().c_str()); \
+ } while (false)
/** \class cmCPackLog
* \brief A container for CPack generators
*
*/
-class cmCPackLog : public cmObject
+class cmCPackLog
{
public:
- cmTypeMacro(cmCPackLog, cmObject);
-
cmCPackLog();
~cmCPackLog();
- enum __log_tags {
+ enum __log_tags
+ {
NOTAG = 0,
LOG_OUTPUT = 0x1,
LOG_VERBOSE = 0x2,
@@ -56,19 +38,19 @@ public:
//! Various signatures for logging.
void Log(const char* file, int line, const char* msg)
- {
+ {
this->Log(LOG_OUTPUT, file, line, msg);
- }
+ }
void Log(const char* file, int line, const char* msg, size_t length)
- {
+ {
this->Log(LOG_OUTPUT, file, line, msg, length);
- }
+ }
void Log(int tag, const char* file, int line, const char* msg)
- {
+ {
this->Log(tag, file, line, msg, strlen(msg));
- }
+ }
void Log(int tag, const char* file, int line, const char* msg,
- size_t length);
+ size_t length);
//! Set Verbose
void VerboseOn() { this->SetVerbose(true); }
@@ -103,12 +85,12 @@ public:
//! Set the various prefixes for the logging. SetPrefix sets the generic
// prefix that overwrittes missing ones.
- void SetPrefix(std::string pfx) { this->Prefix = pfx; }
- void SetOutputPrefix(std::string pfx) { this->OutputPrefix = pfx; }
- void SetVerbosePrefix(std::string pfx) { this->VerbosePrefix = pfx; }
- void SetDebugPrefix(std::string pfx) { this->DebugPrefix = pfx; }
- void SetWarningPrefix(std::string pfx) { this->WarningPrefix = pfx; }
- void SetErrorPrefix(std::string pfx) { this->ErrorPrefix = pfx; }
+ 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; }
+ void SetDebugPrefix(std::string const& pfx) { this->DebugPrefix = pfx; }
+ void SetWarningPrefix(std::string const& pfx) { this->WarningPrefix = pfx; }
+ void SetErrorPrefix(std::string const& pfx) { this->ErrorPrefix = pfx; }
private:
bool Verbose;
@@ -126,11 +108,11 @@ private:
std::string WarningPrefix;
std::string ErrorPrefix;
- std::ostream *DefaultOutput;
- std::ostream *DefaultError;
+ std::ostream* DefaultOutput;
+ std::ostream* DefaultError;
std::string LogOutputFileName;
- std::ostream *LogOutput;
+ std::ostream* LogOutput;
// Do we need to cleanup log output stream
bool LogOutputCleanup;
};
@@ -139,13 +121,16 @@ class cmCPackLogWrite
{
public:
cmCPackLogWrite(const char* data, size_t length)
- : Data(data), Length(length) {}
+ : Data(data)
+ , Length(length)
+ {
+ }
const char* Data;
size_t Length;
};
-inline std::ostream& operator<< (std::ostream& os, const cmCPackLogWrite& c)
+inline std::ostream& operator<<(std::ostream& os, const cmCPackLogWrite& c)
{
os.write(c.Data, c.Length);
os.flush();
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 62bfa91d4..9697a3832 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -1,165 +1,176 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackNSISGenerator.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmCPackLog.h"
#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/Directory.hxx>
-#include <cmsys/RegularExpression.hxx>
+#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)
{
Nsis64 = nsis64;
}
-//----------------------------------------------------------------------
cmCPackNSISGenerator::~cmCPackNSISGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackNSISGenerator::PackageFiles()
{
// TODO: Fix nsis to force out file name
std::string nsisInFileName = this->FindTemplate("NSIS.template.in");
- if ( nsisInFileName.size() == 0 )
- {
+ if (nsisInFileName.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPack error: Could not find NSIS installer template file."
- << std::endl);
+ "CPack error: Could not find NSIS installer template file."
+ << std::endl);
return false;
- }
- std::string nsisInInstallOptions
- = this->FindTemplate("NSIS.InstallOptions.ini.in");
- if ( nsisInInstallOptions.size() == 0 )
- {
+ }
+ std::string nsisInInstallOptions =
+ this->FindTemplate("NSIS.InstallOptions.ini.in");
+ if (nsisInInstallOptions.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPack error: Could not find NSIS installer options file."
- << std::endl);
+ "CPack error: Could not find NSIS installer options file."
+ << std::endl);
return false;
- }
+ }
std::string nsisFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
std::string tmpFile = nsisFileName;
tmpFile += "/NSISOutput.log";
std::string nsisInstallOptions = nsisFileName + "/NSIS.InstallOptions.ini";
nsisFileName += "/project.nsi";
- cmOStringStream str;
+ std::ostringstream str;
std::vector<std::string>::const_iterator it;
- for ( it = files.begin(); it != files.end(); ++ it )
- {
- std::string fileN = cmSystemTools::RelativePath(toplevel.c_str(),
- it->c_str());
- if (!this->Components.empty())
- {
- // Strip off the component part of the path.
- fileN = fileN.substr(fileN.find('/')+1, std::string::npos);
+ for (it = files.begin(); it != files.end(); ++it) {
+ std::string outputDir = "$INSTDIR";
+ std::string fileN =
+ cmSystemTools::RelativePath(toplevel.c_str(), it->c_str());
+ if (!this->Components.empty()) {
+ const std::string::size_type pos = fileN.find('/');
+
+ // Use the custom component install directory if we have one
+ if (pos != std::string::npos) {
+ const std::string componentName = fileN.substr(0, pos);
+ outputDir = CustomComponentInstallDirectory(componentName);
+ } else {
+ outputDir = CustomComponentInstallDirectory(fileN);
}
- cmSystemTools::ReplaceString(fileN, "/", "\\");
- str << " Delete \"$INSTDIR\\" << fileN.c_str() << "\"" << std::endl;
+
+ // Strip off the component part of the path.
+ fileN = fileN.substr(pos + 1);
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Files: "
- << str.str().c_str() << std::endl);
+ std::replace(fileN.begin(), fileN.end(), '/', '\\');
+
+ str << " Delete \"" << outputDir << "\\" << fileN << "\"" << 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;
- cmOStringStream dstr;
- for ( sit = dirs.begin(); sit != dirs.end(); ++ sit )
- {
+ std::ostringstream dstr;
+ for (sit = dirs.begin(); sit != dirs.end(); ++sit) {
std::string componentName;
- std::string fileN = cmSystemTools::RelativePath(toplevel.c_str(),
- sit->c_str());
- if ( fileN.empty() )
- {
+ std::string fileN =
+ cmSystemTools::RelativePath(toplevel.c_str(), sit->c_str());
+ if (fileN.empty()) {
continue;
- }
- if (!Components.empty())
- {
+ }
+ if (!Components.empty()) {
// If this is a component installation, strip off the component
// part of the path.
std::string::size_type slash = fileN.find('/');
- if (slash != std::string::npos)
- {
+ if (slash != std::string::npos) {
// If this is a component installation, determine which component it
// is.
componentName = fileN.substr(0, slash);
// Strip off the component part of the path.
- fileN = fileN.substr(slash+1, std::string::npos);
- }
+ fileN = fileN.substr(slash + 1);
}
- cmSystemTools::ReplaceString(fileN, "/", "\\");
- dstr << " RMDir \"$INSTDIR\\" << fileN.c_str() << "\"" << std::endl;
- if (!componentName.empty())
- {
+ }
+ std::replace(fileN.begin(), fileN.end(), '/', '\\');
+
+ const std::string componentOutputDir =
+ CustomComponentInstallDirectory(componentName);
+
+ dstr << " RMDir \"" << componentOutputDir << "\\" << fileN << "\""
+ << std::endl;
+ if (!componentName.empty()) {
this->Components[componentName].Directories.push_back(fileN);
- }
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Dirs: "
- << dstr.str().c_str() << std::endl);
- this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES",
- dstr.str().c_str());
-
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " << nsisInFileName
- << " to " << nsisFileName << std::endl);
- if(this->IsSet("CPACK_NSIS_MUI_ICON")
- || this->IsSet("CPACK_NSIS_MUI_UNIICON"))
- {
+ }
+ 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);
+ if (this->IsSet("CPACK_NSIS_MUI_ICON") ||
+ this->IsSet("CPACK_NSIS_MUI_UNIICON")) {
std::string installerIconCode;
- if(this->IsSet("CPACK_NSIS_MUI_ICON"))
- {
+ if (this->IsSet("CPACK_NSIS_MUI_ICON")) {
installerIconCode += "!define MUI_ICON \"";
installerIconCode += this->GetOption("CPACK_NSIS_MUI_ICON");
installerIconCode += "\"\n";
- }
- if(this->IsSet("CPACK_NSIS_MUI_UNIICON"))
- {
+ }
+ if (this->IsSet("CPACK_NSIS_MUI_UNIICON")) {
installerIconCode += "!define MUI_UNICON \"";
installerIconCode += this->GetOption("CPACK_NSIS_MUI_UNIICON");
installerIconCode += "\"\n";
- }
+ }
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_ICON_CODE",
installerIconCode.c_str());
- }
- if(this->IsSet("CPACK_PACKAGE_ICON"))
- {
+ }
+ if (this->IsSet("CPACK_PACKAGE_ICON")) {
std::string installerIconCode = "!define MUI_HEADERIMAGE_BITMAP \"";
installerIconCode += this->GetOption("CPACK_PACKAGE_ICON");
installerIconCode += "\"\n";
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE",
installerIconCode.c_str());
- }
-
- if(this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN"))
- {
+ }
+
+ 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";
+ 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";
+ 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 += "\\";
@@ -167,11 +178,10 @@ int cmCPackNSISGenerator::PackageFiles()
installerRunCode += "\"\n";
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE",
installerRunCode.c_str());
- }
+ }
// Setup all of the component sections
- if (this->Components.empty())
- {
+ if (this->Components.empty()) {
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", "");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC", "");
this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS", "");
@@ -180,9 +190,7 @@ int cmCPackNSISGenerator::PackageFiles()
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", "");
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", "");
this->SetOptionIfNotSet("CPACK_NSIS_SECTION_SELECTED_VARS", "");
- }
- else
- {
+ } else {
std::string componentCode;
std::string sectionList;
std::string selectedVarsList;
@@ -190,71 +198,59 @@ int cmCPackNSISGenerator::PackageFiles()
std::string groupDescriptions;
std::string installTypesCode;
std::string defines;
- cmOStringStream macrosOut;
+ std::ostringstream macrosOut;
bool anyDownloadedComponents = false;
// Create installation types. The order is significant, so we first fill
// in a vector based on the indices, and print them in that order.
- std::vector<cmCPackInstallationType *>
- installTypes(this->InstallationTypes.size());
+ 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;
+ 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)
- {
+ installTypeIt2 != installTypes.end(); ++installTypeIt2) {
installTypesCode += "InstType \"";
installTypesCode += (*installTypeIt2)->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 == 0)
- {
+ groupIt != this->ComponentGroups.end(); ++groupIt) {
+ if (groupIt->second.ParentGroup == CM_NULLPTR) {
componentCode +=
this->CreateComponentGroupDescription(&groupIt->second, macrosOut);
- }
+ }
// Add the group description, if any.
- if (!groupIt->second.Description.empty())
- {
- groupDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${"
- + groupIt->first + "} \""
- + this->TranslateNewlines(groupIt->second.Description) + "\"\n";
- }
+ if (!groupIt->second.Description.empty()) {
+ groupDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${" +
+ groupIt->first + "} \"" +
+ this->TranslateNewlines(groupIt->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 (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
+ if (compIt->second.Files.empty()) {
// NSIS cannot cope with components that have no files.
continue;
- }
+ }
anyDownloadedComponents =
anyDownloadedComponents || compIt->second.IsDownloaded;
- if (!compIt->second.Group)
- {
- componentCode
- += this->CreateComponentDescription(&compIt->second, macrosOut);
- }
+ if (!compIt->second.Group) {
+ componentCode +=
+ this->CreateComponentDescription(&compIt->second, macrosOut);
+ }
// Add this component to the various section lists.
sectionList += " !insertmacro \"${MacroName}\" \"";
@@ -264,41 +260,33 @@ int cmCPackNSISGenerator::PackageFiles()
selectedVarsList += "Var " + compIt->first + "_was_installed\n";
// Add the component description, if any.
- if (!compIt->second.Description.empty())
- {
- componentDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${"
- + compIt->first + "} \""
- + this->TranslateNewlines(compIt->second.Description) + "\"\n";
- }
+ if (!compIt->second.Description.empty()) {
+ componentDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${" +
+ compIt->first + "} \"" +
+ this->TranslateNewlines(compIt->second.Description) + "\"\n";
}
+ }
componentCode += macrosOut.str();
- if (componentDescriptions.empty() && groupDescriptions.empty())
- {
+ if (componentDescriptions.empty() && groupDescriptions.empty()) {
// Turn off the "Description" box
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC",
"!define MUI_COMPONENTSPAGE_NODESC");
- }
- else
- {
- componentDescriptions =
- "!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN\n"
- + componentDescriptions
- + groupDescriptions
- + "!insertmacro MUI_FUNCTION_DESCRIPTION_END\n";
+ } else {
+ componentDescriptions = "!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN\n" +
+ componentDescriptions + groupDescriptions +
+ "!insertmacro MUI_FUNCTION_DESCRIPTION_END\n";
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC",
componentDescriptions.c_str());
- }
+ }
- if (anyDownloadedComponents)
- {
+ if (anyDownloadedComponents) {
defines += "!define CPACK_USES_DOWNLOAD\n";
- if (cmSystemTools::IsOn(this->GetOption("CPACK_ADD_REMOVE")))
- {
+ if (cmSystemTools::IsOn(this->GetOption("CPACK_ADD_REMOVE"))) {
defines += "!define CPACK_NSIS_ADD_REMOVE\n";
- }
}
+ }
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES",
installTypesCode.c_str());
@@ -312,7 +300,7 @@ int cmCPackNSISGenerator::PackageFiles()
this->SetOptionIfNotSet("CPACK_NSIS_SECTION_SELECTED_VARS",
selectedVarsList.c_str());
this->SetOption("CPACK_NSIS_DEFINES", defines.c_str());
- }
+ }
this->ConfigureFile(nsisInInstallOptions.c_str(),
nsisInstallOptions.c_str());
@@ -320,479 +308,412 @@ int cmCPackNSISGenerator::PackageFiles()
std::string nsisCmd = "\"";
nsisCmd += this->GetOption("CPACK_INSTALLER_PROGRAM");
nsisCmd += "\" \"" + nsisFileName + "\"";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd.c_str()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
std::string output;
int retVal = 1;
- bool res = cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output,
- &retVal, 0, this->GeneratorVerbose, 0);
- if ( !res || retVal )
- {
+ bool res =
+ cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
+ CM_NULLPTR, this->GeneratorVerbose, 0);
+ if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << nsisCmd.c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
+ ofs << "# Run command: " << nsisCmd << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running NSIS command: "
- << nsisCmd.c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
+ << nsisCmd << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCPackNSISGenerator::InitializeInternal()
{
- if ( cmSystemTools::IsOn(this->GetOption(
- "CPACK_INCLUDE_TOPLEVEL_DIRECTORY")) )
- {
- cmCPackLogger(cmCPackLog::LOG_WARNING,
+ if (cmSystemTools::IsOn(
+ 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", 0);
- }
+ << std::endl);
+ this->SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", CM_NULLPTR);
+ }
cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackNSISGenerator::Initialize()"
- << std::endl);
+ << 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 (Nsis64) {
+ 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 && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath) )
- {
+ }
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "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;
- }
+ }
- if (gotRegValue)
- {
+ if (gotRegValue) {
path.push_back(nsisPath);
- }
+ }
#endif
nsisPath = cmSystemTools::FindProgram("makensis", path, false);
- if ( nsisPath.empty() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ if (nsisPath.empty()) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"Cannot find NSIS compiler makensis: likely it is not installed, "
"or not in your PATH"
- << std::endl);
-
- if (!gotRegValue)
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Could not read NSIS registry value. This is usually caused by "
- "NSIS not being installed. Please install NSIS from "
- "http://nsis.sourceforge.net"
- << std::endl);
- }
+ << std::endl);
+
+ if (!gotRegValue) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Could not read NSIS registry value. This is usually caused by "
+ "NSIS not being installed. Please install NSIS from "
+ "http://nsis.sourceforge.net"
+ << std::endl);
+ }
return 0;
- }
+ }
std::string nsisCmd = "\"" + nsisPath + "\" " NSIS_OPT "VERSION";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Test NSIS version: "
- << nsisCmd.c_str() << 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, &retVal, 0, this->GeneratorVerbose, 0);
+ bool resS =
+ cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
+ CM_NULLPTR, this->GeneratorVerbose, 0);
cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
- if ( !resS || retVal ||
- (!versionRex.find(output) && !versionRexCVS.find(output))
- )
- {
+ 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());
- ofs << "# Run command: " << nsisCmd.c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem checking NSIS version with command: "
- << nsisCmd.c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
+ 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);
return 0;
- }
- if ( versionRex.find(output))
- {
+ }
+ 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);
- if ( nsisVersion < minNSISVersion )
- {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: " << nsisVersion
+ << std::endl);
+ if (nsisVersion < minNSISVersion) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPack requires NSIS Version 2.09 or greater. "
- "NSIS found on the system was: "
- << nsisVersion << std::endl);
+ "CPack requires NSIS Version 2.09 or greater. "
+ "NSIS found on the system was: "
+ << nsisVersion << std::endl);
return 0;
- }
}
- if ( versionRexCVS.find(output))
- {
+ }
+ if (versionRexCVS.find(output)) {
// No version check for NSIS cvs build
cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: CVS "
- << versionRexCVS.match(1).c_str() << std::endl);
- }
+ << versionRexCVS.match(1) << std::endl);
+ }
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str());
this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin");
- const char* cpackPackageExecutables
- = this->GetOption("CPACK_PACKAGE_EXECUTABLES");
- const char* cpackPackageDeskTopLinks
- = this->GetOption("CPACK_CREATE_DESKTOP_LINKS");
- const char* cpackNsisExecutablesDirectory
- = this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
+ const char* cpackPackageExecutables =
+ this->GetOption("CPACK_PACKAGE_EXECUTABLES");
+ const char* cpackPackageDeskTopLinks =
+ this->GetOption("CPACK_CREATE_DESKTOP_LINKS");
+ const char* cpackNsisExecutablesDirectory =
+ this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
std::vector<std::string> cpackPackageDesktopLinksVector;
- if(cpackPackageDeskTopLinks)
- {
+ 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: "
- << *i << std::endl);
- }
+ << 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: " << *i << std::endl);
}
- else
- {
+ } else {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: "
- << "not set" << std::endl);
- }
+ << "not set" << std::endl);
+ }
- cmOStringStream str;
- cmOStringStream deleteStr;
+ std::ostringstream str;
+ std::ostringstream deleteStr;
- if ( cpackPackageExecutables )
- {
+ if (cpackPackageExecutables) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
- << cpackPackageExecutables << "." << std::endl);
+ << cpackPackageExecutables << "." << std::endl);
std::vector<std::string> cpackPackageExecutablesVector;
cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPackageExecutablesVector);
- if ( cpackPackageExecutablesVector.size() % 2 != 0 )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ cpackPackageExecutablesVector);
+ if (cpackPackageExecutablesVector.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
- "<icon name>." << std::endl);
+ "<icon name>."
+ << std::endl);
return 0;
- }
+ }
std::vector<std::string>::iterator it;
- for ( it = cpackPackageExecutablesVector.begin();
- it != cpackPackageExecutablesVector.end();
- ++it )
- {
+ for (it = cpackPackageExecutablesVector.begin();
+ it != cpackPackageExecutablesVector.end(); ++it) {
std::string execName = *it;
- ++ it;
+ ++it;
std::string linkName = *it;
- str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\"
- << linkName << ".lnk\" \"$INSTDIR\\"
- << cpackNsisExecutablesDirectory << "\\" << execName << ".exe\""
- << std::endl;
+ str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
+ << ".lnk\" \"$INSTDIR\\" << cpackNsisExecutablesDirectory << "\\"
+ << execName << ".exe\"" << std::endl;
deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
- << ".lnk\"" << std::endl;
+ << ".lnk\"" << std::endl;
// see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
// if so add a desktop link
- if(cpackPackageDesktopLinksVector.size() &&
- std::find(cpackPackageDesktopLinksVector.begin(),
- cpackPackageDesktopLinksVector.end(),
- execName)
- != cpackPackageDesktopLinksVector.end())
- {
+ if (!cpackPackageDesktopLinksVector.empty() &&
+ std::find(cpackPackageDesktopLinksVector.begin(),
+ cpackPackageDesktopLinksVector.end(),
+ execName) != cpackPackageDesktopLinksVector.end()) {
str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
- str << " CreateShortCut \"$DESKTOP\\"
- << linkName << ".lnk\" \"$INSTDIR\\"
- << cpackNsisExecutablesDirectory << "\\" << execName << ".exe\""
- << std::endl;
+ str << " CreateShortCut \"$DESKTOP\\" << linkName
+ << ".lnk\" \"$INSTDIR\\" << cpackNsisExecutablesDirectory << "\\"
+ << execName << ".exe\"" << std::endl;
deleteStr << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
- deleteStr << " Delete \"$DESKTOP\\" << linkName
- << ".lnk\"" << std::endl;
- }
+ deleteStr << " Delete \"$DESKTOP\\" << linkName << ".lnk\""
+ << std::endl;
}
}
+ }
this->CreateMenuLinks(str, deleteStr);
this->SetOptionIfNotSet("CPACK_NSIS_CREATE_ICONS", str.str().c_str());
- this->SetOptionIfNotSet("CPACK_NSIS_DELETE_ICONS",
- deleteStr.str().c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_DELETE_ICONS", deleteStr.str().c_str());
this->SetOptionIfNotSet("CPACK_NSIS_COMPRESSOR", "lzma");
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
-void cmCPackNSISGenerator::CreateMenuLinks( cmOStringStream& str,
- cmOStringStream& deleteStr)
+void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
+ std::ostream& deleteStr)
{
- const char* cpackMenuLinks
- = this->GetOption("CPACK_NSIS_MENU_LINKS");
- if(!cpackMenuLinks)
- {
+ const char* cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS");
+ if (!cpackMenuLinks) {
return;
- }
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackMenuLinks: "
- << cpackMenuLinks << "." << std::endl);
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "The cpackMenuLinks: " << cpackMenuLinks << "." << std::endl);
std::vector<std::string> cpackMenuLinksVector;
- cmSystemTools::ExpandListArgument(cpackMenuLinks,
- cpackMenuLinksVector);
- if ( cpackMenuLinksVector.size() % 2 != 0 )
- {
+ cmSystemTools::ExpandListArgument(cpackMenuLinks, cpackMenuLinksVector);
+ if (cpackMenuLinksVector.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
"CPACK_NSIS_MENU_LINKS should contain pairs of <shortcut target> and "
- "<shortcut label>." << std::endl);
+ "<shortcut label>."
+ << std::endl);
return;
- }
+ }
- cmsys::RegularExpression urlRegex;
- urlRegex.compile("^(mailto:|(ftps?|https?|news)://).*$");
+ static cmsys::RegularExpression urlRegex(
+ "^(mailto:|(ftps?|https?|news)://).*$");
std::vector<std::string>::iterator it;
- for ( it = cpackMenuLinksVector.begin();
- it != cpackMenuLinksVector.end();
- ++it )
- {
+ for (it = cpackMenuLinksVector.begin(); it != cpackMenuLinksVector.end();
+ ++it) {
std::string sourceName = *it;
const bool url = urlRegex.find(sourceName);
// Convert / to \ in filenames, but not in urls:
//
- if(!url)
- {
- cmSystemTools::ReplaceString(sourceName, "/", "\\");
- }
+ if (!url) {
+ std::replace(sourceName.begin(), sourceName.end(), '/', '\\');
+ }
- ++ it;
+ ++it;
std::string linkName = *it;
- if(!url)
- {
- str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\"
- << linkName << ".lnk\" \"$INSTDIR\\" << sourceName << "\""
- << std::endl;
+ if (!url) {
+ str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
+ << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" << std::endl;
deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
<< ".lnk\"" << std::endl;
- }
- else
- {
- str << " WriteINIStr \"$SMPROGRAMS\\$STARTMENU_FOLDER\\"
- << linkName << ".url\" \"InternetShortcut\" \"URL\" \""
- << sourceName << "\""
+ } else {
+ str << " WriteINIStr \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
+ << ".url\" \"InternetShortcut\" \"URL\" \"" << sourceName << "\""
<< std::endl;
deleteStr << " 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;
- if(this->IsSet(desktop.c_str()))
- {
+ if (this->IsSet(desktop)) {
str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
- str << " CreateShortCut \"$DESKTOP\\"
- << linkName << ".lnk\" \"$INSTDIR\\" << sourceName << "\""
- << std::endl;
+ str << " CreateShortCut \"$DESKTOP\\" << linkName
+ << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" << std::endl;
deleteStr << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
- deleteStr << " Delete \"$DESKTOP\\" << linkName
- << ".lnk\"" << std::endl;
- }
+ deleteStr << " Delete \"$DESKTOP\\" << linkName << ".lnk\""
+ << std::endl;
}
+ }
}
-//----------------------------------------------------------------------
-bool cmCPackNSISGenerator::GetListOfSubdirectories(const char* topdir,
- std::vector<std::string>& dirs)
+bool cmCPackNSISGenerator::GetListOfSubdirectories(
+ const char* topdir, std::vector<std::string>& dirs)
{
cmsys::Directory dir;
dir.Load(topdir);
- size_t fileNum;
- for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
- {
- if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
- strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
- {
- cmsys_stl::string fullPath = topdir;
- fullPath += "/";
- fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if(cmsys::SystemTools::FileIsDirectory(fullPath.c_str()) &&
- !cmsys::SystemTools::FileIsSymlink(fullPath.c_str()))
- {
- if (!this->GetListOfSubdirectories(fullPath.c_str(), dirs))
- {
+ for (unsigned long i = 0; i < dir.GetNumberOfFiles(); ++i) {
+ const char* fileName = dir.GetFile(i);
+ if (strcmp(fileName, ".") != 0 && strcmp(fileName, "..") != 0) {
+ std::string const fullPath =
+ std::string(topdir).append("/").append(fileName);
+ if (cmsys::SystemTools::FileIsDirectory(fullPath) &&
+ !cmsys::SystemTools::FileIsSymlink(fullPath)) {
+ if (!this->GetListOfSubdirectories(fullPath.c_str(), dirs)) {
return false;
- }
}
}
}
+ }
dirs.push_back(topdir);
return true;
}
-//----------------------------------------------------------------------
enum cmCPackGenerator::CPackSetDestdirSupport
cmCPackNSISGenerator::SupportsSetDestdir() const
{
return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED;
}
-//----------------------------------------------------------------------
bool cmCPackNSISGenerator::SupportsAbsoluteDestination() const
{
- return false;
+ return false;
}
-//----------------------------------------------------------------------
bool cmCPackNSISGenerator::SupportsComponentInstallation() const
{
- return true;
+ return true;
}
-//----------------------------------------------------------------------
-std::string
-cmCPackNSISGenerator::
-CreateComponentDescription(cmCPackComponent *component,
- cmOStringStream& macrosOut)
+std::string cmCPackNSISGenerator::CreateComponentDescription(
+ cmCPackComponent* component, std::ostream& macrosOut)
{
// Basic description of the component
std::string componentCode = "Section ";
- if (component->IsDisabledByDefault)
- {
+ if (component->IsDisabledByDefault) {
componentCode += "/o ";
- }
+ }
componentCode += "\"";
- if (component->IsHidden)
- {
+ if (component->IsHidden) {
componentCode += "-";
- }
+ }
componentCode += component->DisplayName + "\" " + component->Name + "\n";
- if (component->IsRequired)
- {
+ if (component->IsRequired) {
componentCode += " SectionIn RO\n";
- }
- else if (!component->InstallationTypes.empty())
- {
- cmOStringStream out;
- std::vector<cmCPackInstallationType *>::iterator installTypeIter;
+ } else if (!component->InstallationTypes.empty()) {
+ std::ostringstream out;
+ std::vector<cmCPackInstallationType*>::iterator installTypeIter;
for (installTypeIter = component->InstallationTypes.begin();
installTypeIter != component->InstallationTypes.end();
- ++installTypeIter)
- {
+ ++installTypeIter) {
out << " " << (*installTypeIter)->Index;
- }
- componentCode += " SectionIn" + out.str() + "\n";
}
- componentCode += " SetOutPath \"$INSTDIR\"\n";
+ componentCode += " SectionIn" + out.str() + "\n";
+ }
+
+ const std::string componentOutputDir =
+ CustomComponentInstallDirectory(component->Name);
+ componentCode += " SetOutPath \"" + componentOutputDir + "\"\n";
// Create the actual installation commands
- if (component->IsDownloaded)
- {
- if (component->ArchiveFile.empty())
- {
+ if (component->IsDownloaded) {
+ if (component->ArchiveFile.empty()) {
// Compute the name of the archive.
std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
packagesDir += ".dummy";
- cmOStringStream out;
- out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir)
- << "-" << component->Name << ".zip";
+ std::ostringstream out;
+ out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
+ << component->Name << ".zip";
component->ArchiveFile = out.str();
- }
+ }
// Create the directory for the upload area
const char* userUploadDirectory =
this->GetOption("CPACK_UPLOAD_DIRECTORY");
std::string uploadDirectory;
- if (userUploadDirectory && *userUploadDirectory)
- {
+ if (userUploadDirectory && *userUploadDirectory) {
uploadDirectory = userUploadDirectory;
- }
- else
- {
- uploadDirectory= this->GetOption("CPACK_PACKAGE_DIRECTORY");
+ } else {
+ uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
uploadDirectory += "/CPackUploads";
- }
- if(!cmSystemTools::FileExists(uploadDirectory.c_str()))
- {
- if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str()))
- {
+ }
+ if (!cmSystemTools::FileExists(uploadDirectory.c_str())) {
+ if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Unable to create NSIS upload directory " << uploadDirectory
- << std::endl);
+ "Unable to create NSIS upload directory "
+ << uploadDirectory << std::endl);
return "";
- }
}
+ }
// Remove the old archive, if one exists
std::string archiveFile = uploadDirectory + '/' + component->ArchiveFile;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Building downloaded component archive: "
- << archiveFile << std::endl);
- if (cmSystemTools::FileExists(archiveFile.c_str(), true))
- {
- if (!cmSystemTools::RemoveFile(archiveFile.c_str()))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Unable to remove archive file " << archiveFile
- << std::endl);
+ "- Building downloaded component archive: " << archiveFile
+ << std::endl);
+ if (cmSystemTools::FileExists(archiveFile.c_str(), true)) {
+ if (!cmSystemTools::RemoveFile(archiveFile)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Unable to remove archive file "
+ << archiveFile << std::endl);
return "";
- }
}
+ }
// Find a ZIP program
- if (!this->IsSet("ZIP_EXECUTABLE"))
- {
+ if (!this->IsSet("ZIP_EXECUTABLE")) {
this->ReadListFile("CPackZIP.cmake");
- if (!this->IsSet("ZIP_EXECUTABLE"))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Unable to find ZIP program"
- << std::endl);
+ if (!this->IsSet("ZIP_EXECUTABLE")) {
+ 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");
@@ -804,29 +725,25 @@ CreateComponentDescription(cmCPackComponent *component,
// 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"));
+ bool needQuotesInFile =
+ cmSystemTools::IsOn(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)
- {
- if ( needQuotesInFile )
- {
+ for (fileIt = component->Files.begin(); fileIt != component->Files.end();
+ ++fileIt) {
+ if (needQuotesInFile) {
out << "\"";
- }
+ }
out << *fileIt;
- if ( needQuotesInFile )
- {
+ if (needQuotesInFile) {
out << "\"";
- }
+ }
out << std::endl;
- totalSize += cmSystemTools::FileLength((dirName + *fileIt).c_str());
- }
+ totalSize += cmSystemTools::FileLength(dirName + *fileIt);
+ }
}
// Build the archive in the upload area
@@ -836,30 +753,30 @@ CreateComponentDescription(cmCPackComponent *component,
zipListFileName.c_str());
std::string output;
int retVal = -1;
- int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &retVal,
- dirName.c_str(),
+ int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
+ &retVal, dirName.c_str(),
cmSystemTools::OUTPUT_NONE, 0);
- if ( !res || retVal )
- {
+ if (!res || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/CompressZip.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << cmd.c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
+ ofs << "# Run command: " << cmd << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running zip command: "
- << cmd.c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
+ << cmd << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return "";
}
// Create the NSIS code to download this file on-the-fly.
unsigned long totalSizeInKbytes = (totalSize + 512) / 1024;
- if (totalSizeInKbytes == 0)
- {
+ if (totalSizeInKbytes == 0) {
totalSizeInKbytes = 1;
- }
- cmOStringStream out;
+ }
+ std::ostringstream out;
+ /* clang-format off */
out << " AddSize " << totalSizeInKbytes << "\n"
<< " Push \"" << component->ArchiveFile << "\"\n"
<< " Call DownloadFile\n"
@@ -869,13 +786,12 @@ CreateComponentDescription(cmCPackComponent *component,
" StrCmp $2 \"success\" +2 0\n"
" MessageBox MB_OK \"Failed to unzip $2\"\n"
" Delete $INSTDIR\\$0\n";
+ /* clang-format on */
componentCode += out.str();
- }
- else
- {
- componentCode += " File /r \"${INST_DIR}\\" +
- component->Name + "\\*.*\"\n";
- }
+ } else {
+ componentCode +=
+ " File /r \"${INST_DIR}\\" + component->Name + "\\*.*\"\n";
+ }
componentCode += "SectionEnd\n";
// Macro used to remove the component
@@ -884,32 +800,24 @@ CreateComponentDescription(cmCPackComponent *component,
<< component->Name << "\n";
std::vector<std::string>::iterator pathIt;
std::string path;
- for (pathIt = component->Files.begin();
- pathIt != component->Files.end();
- ++pathIt)
- {
+ for (pathIt = component->Files.begin(); pathIt != component->Files.end();
+ ++pathIt) {
path = *pathIt;
- cmSystemTools::ReplaceString(path, "/", "\\");
- macrosOut << " Delete \"$INSTDIR\\"
- << path.c_str()
- << "\"\n";
- }
+ std::replace(path.begin(), path.end(), '/', '\\');
+ macrosOut << " Delete \"" << componentOutputDir << "\\" << path << "\"\n";
+ }
for (pathIt = component->Directories.begin();
- pathIt != component->Directories.end();
- ++pathIt)
- {
+ pathIt != component->Directories.end(); ++pathIt) {
path = *pathIt;
- cmSystemTools::ReplaceString(path, "/", "\\");
- macrosOut << " RMDir \"$INSTDIR\\"
- << path.c_str()
- << "\"\n";
- }
+ std::replace(path.begin(), path.end(), '/', '\\');
+ macrosOut << " RMDir \"" << componentOutputDir << "\\" << path << "\"\n";
+ }
macrosOut << " noremove_" << component->Name << ":\n";
macrosOut << "!macroend\n";
// Macro used to select each of the components that this component
// depends on.
- std::set<cmCPackComponent *> visited;
+ std::set<cmCPackComponent*> visited;
macrosOut << "!macro Select_" << component->Name << "_depends\n";
macrosOut << CreateSelectionDependenciesDescription(component, visited);
macrosOut << "!macroend\n";
@@ -923,24 +831,19 @@ CreateComponentDescription(cmCPackComponent *component,
return componentCode;
}
-//----------------------------------------------------------------------
-std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription
- (cmCPackComponent *component,
- std::set<cmCPackComponent *>& visited)
+std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription(
+ cmCPackComponent* component, std::set<cmCPackComponent*>& visited)
{
// Don't visit a component twice
- if (visited.count(component))
- {
+ if (visited.count(component)) {
return std::string();
- }
+ }
visited.insert(component);
- cmOStringStream out;
- std::vector<cmCPackComponent *>::iterator dependIt;
+ std::ostringstream out;
+ std::vector<cmCPackComponent*>::iterator dependIt;
for (dependIt = component->Dependencies.begin();
- dependIt != component->Dependencies.end();
- ++dependIt)
- {
+ dependIt != component->Dependencies.end(); ++dependIt) {
// Write NSIS code to select this dependency
out << " SectionGetFlags ${" << (*dependIt)->Name << "} $0\n";
out << " IntOp $0 $0 | ${SF_SELECTED}\n";
@@ -949,30 +852,24 @@ std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription
<< "_selected 0 + ${SF_SELECTED}\n";
// Recurse
out << CreateSelectionDependenciesDescription(*dependIt, visited).c_str();
- }
+ }
return out.str();
}
-
-//----------------------------------------------------------------------
-std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription
- (cmCPackComponent *component,
- std::set<cmCPackComponent *>& visited)
+std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription(
+ cmCPackComponent* component, std::set<cmCPackComponent*>& visited)
{
// Don't visit a component twice
- if (visited.count(component))
- {
+ if (visited.count(component)) {
return std::string();
- }
+ }
visited.insert(component);
- cmOStringStream out;
- std::vector<cmCPackComponent *>::iterator dependIt;
+ std::ostringstream out;
+ std::vector<cmCPackComponent*>::iterator dependIt;
for (dependIt = component->ReverseDependencies.begin();
- dependIt != component->ReverseDependencies.end();
- ++dependIt)
- {
+ dependIt != component->ReverseDependencies.end(); ++dependIt) {
// Write NSIS code to deselect this dependency
out << " SectionGetFlags ${" << (*dependIt)->Name << "} $0\n";
out << " IntOp $1 ${SF_SELECTED} ~\n";
@@ -981,62 +878,59 @@ std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription
out << " IntOp $" << (*dependIt)->Name << "_selected 0 + 0\n";
// Recurse
- out <<
- CreateDeselectionDependenciesDescription(*dependIt, visited).c_str();
- }
+ out
+ << CreateDeselectionDependenciesDescription(*dependIt, visited).c_str();
+ }
return out.str();
}
-//----------------------------------------------------------------------
-std::string
-cmCPackNSISGenerator::
-CreateComponentGroupDescription(cmCPackComponentGroup *group,
- cmOStringStream& macrosOut)
+std::string cmCPackNSISGenerator::CreateComponentGroupDescription(
+ cmCPackComponentGroup* group, std::ostream& macrosOut)
{
- if (group->Components.empty() && group->Subgroups.empty())
- {
+ if (group->Components.empty() && group->Subgroups.empty()) {
// Silently skip empty groups. NSIS doesn't support them.
return std::string();
- }
+ }
std::string code = "SectionGroup ";
- if (group->IsExpandedByDefault)
- {
+ if (group->IsExpandedByDefault) {
code += "/e ";
- }
- if (group->IsBold)
- {
+ }
+ if (group->IsBold) {
code += "\"!" + group->DisplayName + "\" " + group->Name + "\n";
- }
- else
- {
+ } else {
code += "\"" + group->DisplayName + "\" " + group->Name + "\n";
- }
+ }
std::vector<cmCPackComponentGroup*>::iterator groupIt;
for (groupIt = group->Subgroups.begin(); groupIt != group->Subgroups.end();
- ++groupIt)
- {
+ ++groupIt) {
code += this->CreateComponentGroupDescription(*groupIt, macrosOut);
- }
+ }
std::vector<cmCPackComponent*>::iterator comp;
- for (comp = group->Components.begin();
- comp != group->Components.end();
- ++comp)
- {
- if ((*comp)->Files.empty())
- {
+ for (comp = group->Components.begin(); comp != group->Components.end();
+ ++comp) {
+ if ((*comp)->Files.empty()) {
continue;
- }
+ }
code += this->CreateComponentDescription(*comp, macrosOut);
- }
+ }
code += "SectionGroupEnd\n";
return code;
}
+std::string cmCPackNSISGenerator::CustomComponentInstallDirectory(
+ const std::string& componentName)
+{
+ const char* outputDir =
+ this->GetOption("CPACK_NSIS_" + componentName + "_INSTALL_DIRECTORY");
+ const std::string componentOutputDir = (outputDir ? outputDir : "$INSTDIR");
+ return componentOutputDir;
+}
+
std::string cmCPackNSISGenerator::TranslateNewlines(std::string str)
{
cmSystemTools::ReplaceString(str, "\n", "$\\r$\\n");
diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h
index e46fbdab7..77be3256d 100644
--- a/Source/CPack/cmCPackNSISGenerator.h
+++ b/Source/CPack/cmCPackNSISGenerator.h
@@ -1,21 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackNSISGenerator_h
#define cmCPackNSISGenerator_h
+#include "cmConfigure.h"
#include "cmCPackGenerator.h"
+
+#include <iosfwd>
#include <set>
+#include <string>
+#include <vector>
+
+class cmCPackComponent;
+class cmCPackComponentGroup;
/** \class cmCPackNSISGenerator
* \brief A generator for NSIS files
@@ -28,54 +26,57 @@ public:
cmCPackTypeMacro(cmCPackNSISGenerator, cmCPackGenerator);
static cmCPackGenerator* CreateGenerator64()
- { return new cmCPackNSISGenerator(true); }
+ {
+ return new cmCPackNSISGenerator(true);
+ }
/**
* Construct generator
*/
cmCPackNSISGenerator(bool nsis64 = false);
- virtual ~cmCPackNSISGenerator();
+ ~cmCPackNSISGenerator() CM_OVERRIDE;
protected:
- virtual int InitializeInternal();
- void CreateMenuLinks( cmOStringStream& str,
- cmOStringStream& deleteStr);
- int PackageFiles();
- virtual const char* GetOutputExtension() { return ".exe"; }
- virtual const char* GetOutputPostfix() { return "win32"; }
+ int InitializeInternal() CM_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"; }
bool GetListOfSubdirectories(const char* dir,
- std::vector<std::string>& dirs);
+ std::vector<std::string>& dirs);
- enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const;
- virtual bool SupportsAbsoluteDestination() const;
- virtual bool SupportsComponentInstallation() const;
+ enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const
+ CM_OVERRIDE;
+ bool SupportsAbsoluteDestination() const CM_OVERRIDE;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
/// Produce a string that contains the NSIS code to describe a
/// particular component. Any added macros will be emitted via
/// macrosOut.
- std::string
- CreateComponentDescription(cmCPackComponent *component,
- cmOStringStream& macrosOut);
+ std::string CreateComponentDescription(cmCPackComponent* component,
+ std::ostream& macrosOut);
/// Produce NSIS code that selects all of the components that this component
/// depends on, recursively.
- std::string CreateSelectionDependenciesDescription
- (cmCPackComponent *component,
- std::set<cmCPackComponent *>& visited);
+ std::string CreateSelectionDependenciesDescription(
+ cmCPackComponent* component, std::set<cmCPackComponent*>& visited);
/// Produce NSIS code that de-selects all of the components that are
/// dependent on this component, recursively.
- std::string CreateDeselectionDependenciesDescription
- (cmCPackComponent *component,
- std::set<cmCPackComponent *>& visited);
+ std::string CreateDeselectionDependenciesDescription(
+ cmCPackComponent* component, std::set<cmCPackComponent*>& visited);
/// Produce a string that contains the NSIS code to describe a
/// particular component group, including its components. Any
/// added macros will be emitted via macrosOut.
- std::string
- CreateComponentGroupDescription(cmCPackComponentGroup *group,
- cmOStringStream& macrosOut);
+ std::string CreateComponentGroupDescription(cmCPackComponentGroup* group,
+ std::ostream& macrosOut);
+
+ /// Returns the custom install directory if available for the specified
+ /// component, otherwise $INSTDIR is returned.
+ std::string CustomComponentInstallDirectory(
+ const std::string& componentName);
/// Translations any newlines found in the string into \\r\\n, so that the
/// resulting string can be used within NSIS.
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 76e15fb84..8ea88a87a 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -1,79 +1,60 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackOSXX11Generator.h"
-#include "cmake.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmCPackLog.h"
+#include <sstream>
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Glob.hxx>
-#include <sys/stat.h>
+#include "cmCPackGenerator.h"
+#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cm_sys_stat.h"
-//----------------------------------------------------------------------
cmCPackOSXX11Generator::cmCPackOSXX11Generator()
{
}
-//----------------------------------------------------------------------
cmCPackOSXX11Generator::~cmCPackOSXX11Generator()
{
}
-//----------------------------------------------------------------------
int cmCPackOSXX11Generator::PackageFiles()
{
// TODO: Use toplevel ?
// It is used! Is this an obsolete comment?
- const char* cpackPackageExecutables
- = this->GetOption("CPACK_PACKAGE_EXECUTABLES");
- if ( cpackPackageExecutables )
- {
+ const char* cpackPackageExecutables =
+ this->GetOption("CPACK_PACKAGE_EXECUTABLES");
+ if (cpackPackageExecutables) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
- << cpackPackageExecutables << "." << std::endl);
- cmOStringStream str;
- cmOStringStream deleteStr;
+ << cpackPackageExecutables << "." << std::endl);
+ std::ostringstream str;
+ std::ostringstream deleteStr;
std::vector<std::string> cpackPackageExecutablesVector;
cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPackageExecutablesVector);
- if ( cpackPackageExecutablesVector.size() % 2 != 0 )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ cpackPackageExecutablesVector);
+ if (cpackPackageExecutablesVector.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
- "<icon name>." << std::endl);
+ "<icon name>."
+ << std::endl);
return 0;
- }
+ }
std::vector<std::string>::iterator it;
- for ( it = cpackPackageExecutablesVector.begin();
- it != cpackPackageExecutablesVector.end();
- ++it )
- {
+ for (it = cpackPackageExecutablesVector.begin();
+ it != cpackPackageExecutablesVector.end(); ++it) {
std::string cpackExecutableName = *it;
- ++ it;
+ ++it;
this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME",
- cpackExecutableName.c_str());
- }
+ cpackExecutableName.c_str());
}
+ }
// Disk image directories
std::string diskImageDirectory = toplevel;
- std::string diskImageBackgroundImageDir
- = diskImageDirectory + "/.background";
-
+ std::string diskImageBackgroundImageDir =
+ diskImageDirectory + "/.background";
// App bundle directories
std::string packageDirFileName = toplevel;
@@ -93,48 +74,44 @@ int cmCPackOSXX11Generator::PackageFiles()
const char* contDir = contentsDirectory.c_str();
const char* rsrcFile = resourceFileName.c_str();
const char* iconFile = this->GetOption("CPACK_PACKAGE_ICON");
- if ( iconFile )
- {
- std::string iconFileName = cmsys::SystemTools::GetFilenameName(
- iconFile);
- if ( !cmSystemTools::FileExists(iconFile) )
- {
+ if (iconFile) {
+ std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile);
+ if (!cmSystemTools::FileExists(iconFile)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find icon file: "
- << iconFile << ". Please check CPACK_PACKAGE_ICON setting."
- << std::endl);
+ << iconFile
+ << ". Please check CPACK_PACKAGE_ICON setting."
+ << std::endl);
return 0;
- }
+ }
std::string destFileName = resourcesDirectory + "/" + iconFileName;
this->ConfigureFile(iconFile, destFileName.c_str(), true);
this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName.c_str());
- }
+ }
std::string applicationsLinkName = diskImageDirectory + "/Applications";
- cmSystemTools::CreateSymlink("/Applications", applicationsLinkName.c_str());
+ cmSystemTools::CreateSymlink("/Applications", applicationsLinkName);
- if (
- !this->CopyResourcePlistFile("VolumeIcon.icns",
- diskImageDirectory.c_str(),
- ".VolumeIcon.icns", true ) ||
- !this->CopyResourcePlistFile("DS_Store", diskImageDirectory.c_str(),
- ".DS_Store", true ) ||
- !this->CopyResourcePlistFile("background.png",
- diskImageBackgroundImageDir.c_str(), "background.png", true ) ||
- !this->CopyResourcePlistFile("RuntimeScript", dir) ||
- !this->CopyResourcePlistFile("OSXX11.Info.plist", contDir,
- "Info.plist" ) ||
- !this->CopyResourcePlistFile("OSXX11.main.scpt", scrDir,
- "main.scpt", true ) ||
- !this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir,
- rsrcFile, true) ||
- !this->CopyResourcePlistFile("OSXScriptLauncher", appdir,
- this->GetOption("CPACK_PACKAGE_FILE_NAME"), true)
- )
- {
+ if (!this->CopyResourcePlistFile("VolumeIcon.icns", diskImageDirectory,
+ ".VolumeIcon.icns", true) ||
+ !this->CopyResourcePlistFile("DS_Store", diskImageDirectory, ".DS_Store",
+ true) ||
+ !this->CopyResourcePlistFile("background.png",
+ diskImageBackgroundImageDir,
+ "background.png", true) ||
+ !this->CopyResourcePlistFile("RuntimeScript", dir) ||
+ !this->CopyResourcePlistFile("OSXX11.Info.plist", contDir,
+ "Info.plist") ||
+ !this->CopyResourcePlistFile("OSXX11.main.scpt", scrDir, "main.scpt",
+ true) ||
+ !this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir, rsrcFile,
+ true) ||
+ !this->CopyResourcePlistFile("OSXScriptLauncher", appdir,
+ this->GetOption("CPACK_PACKAGE_FILE_NAME"),
+ true)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
// Two of the files need to have execute permission, so ensure they do:
std::string runTimeScript = dir;
@@ -146,88 +123,81 @@ int cmCPackOSXX11Generator::PackageFiles()
appScriptName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
mode_t mode;
- if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode))
- {
+ if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) {
mode |= (S_IXUSR | S_IXGRP | S_IXOTH);
cmsys::SystemTools::SetPermissions(runTimeScript.c_str(), mode);
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Setting: " << runTimeScript
- << " to permission: " << mode << std::endl);
- }
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Setting: " << runTimeScript << " to permission: " << mode
+ << std::endl);
+ }
- if (cmsys::SystemTools::GetPermissions(appScriptName.c_str(), mode))
- {
+ if (cmsys::SystemTools::GetPermissions(appScriptName.c_str(), mode)) {
mode |= (S_IXUSR | S_IXGRP | S_IXOTH);
cmsys::SystemTools::SetPermissions(appScriptName.c_str(), mode);
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Setting: " << appScriptName
- << " to permission: " << mode << std::endl);
- }
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Setting: " << appScriptName << " to permission: " << mode
+ << std::endl);
+ }
std::string output;
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/hdiutilOutput.log";
- cmOStringStream dmgCmd;
+ std::ostringstream dmgCmd;
dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
- << "\" create -ov -format UDZO -srcfolder \""
- << diskImageDirectory.c_str()
+ << "\" create -ov -format UDZO -srcfolder \"" << diskImageDirectory
<< "\" \"" << packageFileNames[0] << "\"";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Compress disk image using command: "
- << dmgCmd.str().c_str() << std::endl);
+ 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,
- &retVal, 0,
- this->GeneratorVerbose, 0);
- if ( res && !retVal )
- {
+ while (numTries > 0) {
+ res =
+ cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output, &output,
+ &retVal, 0, this->GeneratorVerbose, 0);
+ if (res && !retVal) {
numTries = -1;
break;
- }
+ }
cmSystemTools::Delay(500);
numTries--;
- }
- if ( !res || retVal )
- {
+ }
+ if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << dmgCmd.str().c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
+ ofs << "# Run command: " << dmgCmd.str() << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
- << dmgCmd.str().c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
+ << dmgCmd.str() << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
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() )
- {
+ if (pkgPath.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
pkgPath.c_str());
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
/*
-bool cmCPackOSXX11Generator::CopyCreateResourceFile(const char* name)
+bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name)
{
std::string uname = cmSystemTools::UpperCase(name);
std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
@@ -264,44 +234,40 @@ bool cmCPackOSXX11Generator::CopyCreateResourceFile(const char* name)
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
<< (inFileName ? inFileName : "(NULL)")
- << " to " << destFileName.c_str() << std::endl);
+ << " to " << destFileName << std::endl);
this->ConfigureFile(inFileName, destFileName.c_str());
return true;
}
*/
-//----------------------------------------------------------------------
-bool cmCPackOSXX11Generator::CopyResourcePlistFile(const char* name,
- const char* dir, const char* outputFileName /* = 0 */,
- bool copyOnly /* = false */)
+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 inFileName = this->FindTemplate(inFName.c_str());
- if ( inFileName.empty() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: "
- << inFName << std::endl);
+ if (inFileName.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find input file: " << inFName << std::endl);
return false;
- }
+ }
- if ( !outputFileName )
- {
- outputFileName = name;
- }
+ if (!outputFileName) {
+ outputFileName = name.c_str();
+ }
std::string destFileName = dir;
destFileName += "/";
destFileName += outputFileName;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << inFileName.c_str() << " to " << destFileName.c_str() << std::endl);
+ << inFileName << " to " << destFileName << std::endl);
this->ConfigureFile(inFileName.c_str(), destFileName.c_str(), copyOnly);
return true;
}
-//----------------------------------------------------------------------
const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix()
{
this->InstallPrefix = "/";
diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h
index b7bd24396..0eebc6dd1 100644
--- a/Source/CPack/cmCPackOSXX11Generator.h
+++ b/Source/CPack/cmCPackOSXX11Generator.h
@@ -1,18 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackOSXX11Generator_h
#define cmCPackOSXX11Generator_h
+#include "cmConfigure.h"
+
+#include <string>
+
#include "cmCPackGenerator.h"
/** \class cmCPackOSXX11Generator
@@ -32,14 +26,16 @@ public:
virtual ~cmCPackOSXX11Generator();
protected:
- virtual int InitializeInternal();
- int PackageFiles();
- virtual const char* GetPackagingInstallPrefix();
- virtual const char* GetOutputExtension() { return ".dmg"; }
-
- //bool CopyCreateResourceFile(const char* name, const char* dir);
- bool CopyResourcePlistFile(const char* name, const char* dir,
- const char* outputFileName = 0, bool copyOnly = false);
+ virtual int InitializeInternal() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
+ const char* GetPackagingInstallPrefix() CM_OVERRIDE;
+ const char* GetOutputExtension() CM_OVERRIDE { return ".dmg"; }
+
+ // bool CopyCreateResourceFile(const std::string& name,
+ // const std::string& dir);
+ bool CopyResourcePlistFile(const std::string& name, const std::string& dir,
+ const char* outputFileName = 0,
+ bool copyOnly = false);
std::string InstallPrefix;
};
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
new file mode 100644
index 000000000..70ae267fb
--- /dev/null
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -0,0 +1,352 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackPKGGenerator.h"
+
+#include <vector>
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+#include "cmXMLWriter.h"
+
+cmCPackPKGGenerator::cmCPackPKGGenerator()
+{
+ this->componentPackageMethod = ONE_PACKAGE;
+}
+
+cmCPackPKGGenerator::~cmCPackPKGGenerator()
+{
+}
+
+bool cmCPackPKGGenerator::SupportsComponentInstallation() const
+{
+ return true;
+}
+
+int cmCPackPKGGenerator::InitializeInternal()
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackPKGGenerator::Initialize()"
+ << std::endl);
+
+ return this->Superclass::InitializeInternal();
+}
+
+std::string cmCPackPKGGenerator::GetPackageName(
+ const cmCPackComponent& component)
+{
+ if (component.ArchiveFile.empty()) {
+ std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ packagesDir += ".dummy";
+ std::ostringstream out;
+ out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
+ << component.Name << ".pkg";
+ return out.str();
+ } else {
+ return component.ArchiveFile + ".pkg";
+ }
+}
+
+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);
+ return;
+ }
+
+ std::string distributionFile = metapackageFile;
+ distributionFile += "/Contents/distribution.dist";
+
+ // Create the choice outline, which provides a tree-based view of
+ // the components in their groups.
+ std::ostringstream choiceOut;
+ cmXMLWriter xout(choiceOut, 1);
+ 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);
+ }
+ }
+
+ // 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) {
+ xout.StartElement("line");
+ xout.Attribute("choice", compIt->first + "Choice");
+ xout.Content(""); // Avoid self-closing tag.
+ xout.EndElement();
+ }
+ }
+ if (!this->PostFlightComponent.Name.empty()) {
+ xout.StartElement("line");
+ xout.Attribute("choice", PostFlightComponent.Name + "Choice");
+ xout.Content(""); // Avoid self-closing tag.
+ xout.EndElement();
+ }
+ xout.EndElement(); // choices-outline>
+
+ // Create the actual choices
+ for (groupIt = this->ComponentGroups.begin();
+ groupIt != this->ComponentGroups.end(); ++groupIt) {
+ CreateChoice(groupIt->second, xout);
+ }
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
+ CreateChoice(compIt->second, xout);
+ }
+
+ if (!this->PostFlightComponent.Name.empty()) {
+ CreateChoice(PostFlightComponent, xout);
+ }
+
+ this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str());
+
+ // Create the distribution.dist file in the metapackage to turn it
+ // into a distribution package.
+ this->ConfigureFile(distributionTemplate.c_str(), distributionFile.c_str());
+}
+
+void cmCPackPKGGenerator::CreateChoiceOutline(
+ const cmCPackComponentGroup& group, cmXMLWriter& xout)
+{
+ 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);
+ }
+
+ std::vector<cmCPackComponent*>::const_iterator compIt;
+ for (compIt = group.Components.begin(); compIt != group.Components.end();
+ ++compIt) {
+ xout.StartElement("line");
+ xout.Attribute("choice", (*compIt)->Name + "Choice");
+ xout.Content(""); // Avoid self-closing tag.
+ xout.EndElement();
+ }
+ xout.EndElement();
+}
+
+void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group,
+ cmXMLWriter& xout)
+{
+ xout.StartElement("choice");
+ xout.Attribute("id", group.Name + "Choice");
+ xout.Attribute("title", group.DisplayName);
+ xout.Attribute("start_selected", "true");
+ xout.Attribute("start_enabled", "true");
+ xout.Attribute("start_visible", "true");
+ if (!group.Description.empty()) {
+ xout.Attribute("description", group.Description);
+ }
+ xout.EndElement();
+}
+
+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;
+
+ xout.StartElement("choice");
+ xout.Attribute("id", component.Name + "Choice");
+ xout.Attribute("title", component.DisplayName);
+ xout.Attribute(
+ "start_selected",
+ component.IsDisabledByDefault && !component.IsRequired ? "false" : "true");
+ xout.Attribute("start_enabled", component.IsRequired ? "false" : "true");
+ xout.Attribute("start_visible", component.IsHidden ? "false" : "true");
+ if (!component.Description.empty()) {
+ xout.Attribute("description", component.Description);
+ }
+ if (!component.Dependencies.empty() ||
+ !component.ReverseDependencies.empty()) {
+ // The "selected" expression is evaluated each time any choice is
+ // selected, for all choices *except* the one that the user
+ // selected. A component is marked selected if it has been
+ // selected (my.choice.selected in Javascript) and all of the
+ // components it depends on have been selected (transitively) or
+ // if any of the components that depend on it have been selected
+ // (transitively). Assume that we have components A, B, C, D, and
+ // E, where each component depends on the previous component (B
+ // depends on A, C depends on B, D depends on C, and E depends on
+ // D). The expression we build for the component C will be
+ // my.choice.selected && B && A || D || E
+ // 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::set<const cmCPackComponent*> visited;
+ AddDependencyAttributes(component, visited, selected);
+ visited.clear();
+ AddReverseDependencyAttributes(component, visited, selected);
+ xout.Attribute("selected", selected.str());
+ }
+ xout.StartElement("pkg-ref");
+ xout.Attribute("id", packageId);
+ xout.EndElement(); // pkg-ref
+ xout.EndElement(); // choice
+
+ // Create a description of the package associated with this
+ // component.
+ std::string relativePackageLocation = "Contents/Packages/";
+ relativePackageLocation += 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");
+ unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName);
+
+ xout.StartElement("pkg-ref");
+ xout.Attribute("id", packageId);
+ xout.Attribute("version", this->GetOption("CPACK_PACKAGE_VERSION"));
+ xout.Attribute("installKBytes", installedSize);
+ xout.Attribute("auth", "Admin");
+ xout.Attribute("onConclusion", "None");
+ if (component.IsDownloaded) {
+ xout.Content(this->GetOption("CPACK_DOWNLOAD_SITE"));
+ xout.Content(this->GetPackageName(component));
+ } else {
+ xout.Content("file:./");
+ xout.Content(relativePackageLocation);
+ }
+ xout.EndElement(); // pkg-ref
+}
+
+void cmCPackPKGGenerator::AddDependencyAttributes(
+ const cmCPackComponent& component,
+ std::set<const cmCPackComponent*>& visited, std::ostringstream& out)
+{
+ if (visited.find(&component) != visited.end()) {
+ return;
+ }
+ 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);
+ }
+}
+
+void cmCPackPKGGenerator::AddReverseDependencyAttributes(
+ const cmCPackComponent& component,
+ std::set<const cmCPackComponent*>& visited, std::ostringstream& out)
+{
+ if (visited.find(&component) != visited.end()) {
+ return;
+ }
+ 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);
+ }
+}
+
+bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
+ const std::string& dirName)
+{
+ std::string uname = cmSystemTools::UpperCase(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);
+ return false;
+ }
+ if (!cmSystemTools::FileExists(inFileName)) {
+ 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: "
+ << ext
+ << ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
+ << std::endl);
+ return false;
+ }
+
+ std::string destFileName = dirName;
+ destFileName += '/';
+ destFileName += name + ext;
+
+ // Set this so that distribution.dist gets the right name (without
+ // the path).
+ this->SetOption("CPACK_RESOURCE_FILE_" + uname + "_NOPATH",
+ (name + ext).c_str());
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << (inFileName ? inFileName : "(NULL)")
+ << " to " << destFileName << std::endl);
+ this->ConfigureFile(inFileName, destFileName.c_str());
+ return true;
+}
+
+bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
+ const char* outName)
+{
+ if (!outName) {
+ outName = name.c_str();
+ }
+
+ std::string inFName = "CPack.";
+ inFName += name;
+ inFName += ".in";
+ std::string inFileName = this->FindTemplate(inFName.c_str());
+ if (inFileName.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find input file: " << inFName << std::endl);
+ return false;
+ }
+
+ std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ destFileName += "/";
+ destFileName += outName;
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
+ << inFileName << " to " << destFileName << std::endl);
+ this->ConfigureFile(inFileName.c_str(), destFileName.c_str());
+ return true;
+}
+
+int cmCPackPKGGenerator::CopyInstallScript(const std::string& resdir,
+ const std::string& script,
+ const std::string& name)
+{
+ std::string dst = resdir;
+ dst += "/";
+ dst += name;
+ cmSystemTools::CopyFileAlways(script, dst);
+ cmSystemTools::SetPermissions(dst.c_str(), 0777);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "copy script : " << script << "\ninto " << dst << std::endl);
+
+ return 1;
+}
diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h
new file mode 100644
index 000000000..f873c5936
--- /dev/null
+++ b/Source/CPack/cmCPackPKGGenerator.h
@@ -0,0 +1,92 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackPKGGenerator_h
+#define cmCPackPKGGenerator_h
+
+#include "cmConfigure.h"
+
+#include <set>
+#include <sstream>
+#include <string>
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+
+class cmXMLWriter;
+
+/** \class cmCPackPKGGenerator
+ * \brief A generator for pkg files
+ *
+ */
+class cmCPackPKGGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackPKGGenerator, cmCPackGenerator);
+
+ /**
+ * Construct generator
+ */
+ cmCPackPKGGenerator();
+ virtual ~cmCPackPKGGenerator();
+
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
+
+protected:
+ int InitializeInternal() CM_OVERRIDE;
+ const char* GetOutputPostfix() CM_OVERRIDE { return "darwin"; }
+
+ // Copies or creates the resource file with the given name to the
+ // package or package staging directory dirName. The variable
+ // CPACK_RESOURCE_FILE_${NAME} (where ${NAME} is the uppercased
+ // version of name) specifies the input file to use for this file,
+ // which will be configured via ConfigureFile.
+ bool CopyCreateResourceFile(const std::string& name,
+ const std::string& dirName);
+ bool CopyResourcePlistFile(const std::string& name, const char* outName = 0);
+
+ int CopyInstallScript(const std::string& resdir, const std::string& script,
+ const std::string& name);
+
+ // Retrieve the name of package file that will be generated for this
+ // component. The name is just the file name with extension, and
+ // does not include the subdirectory.
+ std::string GetPackageName(const cmCPackComponent& component);
+
+ // Writes a distribution.dist file, which turns a metapackage into a
+ // full-fledged distribution. This file is used to describe
+ // inter-component dependencies. metapackageFile is the name of the
+ // metapackage for the distribution. Only valid for a
+ // component-based install.
+ void WriteDistributionFile(const char* metapackageFile);
+
+ // Subroutine of WriteDistributionFile that writes out the
+ // dependency attributes for inter-component dependencies.
+ void AddDependencyAttributes(const cmCPackComponent& component,
+ std::set<const cmCPackComponent*>& visited,
+ std::ostringstream& out);
+
+ // Subroutine of WriteDistributionFile that writes out the
+ // reverse dependency attributes for inter-component dependencies.
+ void AddReverseDependencyAttributes(
+ const cmCPackComponent& component,
+ std::set<const cmCPackComponent*>& visited, std::ostringstream& out);
+
+ // Generates XML that encodes the hierarchy of component groups and
+ // their components in a form that can be used by distribution
+ // metapackages.
+ void CreateChoiceOutline(const cmCPackComponentGroup& group,
+ cmXMLWriter& xout);
+
+ /// Create the "choice" XML element to describe a component group
+ /// for the installer GUI.
+ void CreateChoice(const cmCPackComponentGroup& group, cmXMLWriter& xout);
+
+ /// Create the "choice" XML element to describe a component for the
+ /// installer GUI.
+ void CreateChoice(const cmCPackComponent& component, cmXMLWriter& xout);
+
+ // The PostFlight component when creating a metapackage
+ cmCPackComponent PostFlightComponent;
+};
+
+#endif
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index c617a3e32..8db7cfb3d 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -1,166 +1,123 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackPackageMakerGenerator.h"
-#include "cmake.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <assert.h>
+#include <map>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmXMLWriter.h"
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Glob.hxx>
+static inline unsigned int getVersion(unsigned int major, unsigned int minor)
+{
+ assert(major < 256 && minor < 256);
+ return ((major & 0xFF) << 16 | minor);
+}
-//----------------------------------------------------------------------
cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator()
{
this->PackageMakerVersion = 0.0;
- this->PackageCompatibilityVersion = 10.4;
+ this->PackageCompatibilityVersion = getVersion(10, 4);
}
-//----------------------------------------------------------------------
cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator()
{
}
-//----------------------------------------------------------------------
bool cmCPackPackageMakerGenerator::SupportsComponentInstallation() const
{
- return this->PackageCompatibilityVersion >= 10.4;
+ return this->PackageCompatibilityVersion >= getVersion(10, 4);
}
-//----------------------------------------------------------------------
-int cmCPackPackageMakerGenerator::CopyInstallScript(const char* resdir,
- const char* script,
- const char* name)
-{
- std::string dst = resdir;
- dst += "/";
- dst += name;
- cmSystemTools::CopyFileAlways(script, dst.c_str());
- cmSystemTools::SetPermissions(dst.c_str(),0777);
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "copy script : " << script << "\ninto " << dst.c_str() <<
- std::endl);
-
- return 1;
-}
-
-//----------------------------------------------------------------------
int cmCPackPackageMakerGenerator::PackageFiles()
{
// TODO: Use toplevel
// It is used! Is this an obsolete comment?
std::string resDir; // Where this package's resources will go.
- std::string packageDirFileName
- = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- if (this->Components.empty())
- {
+ std::string packageDirFileName =
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ if (this->Components.empty()) {
packageDirFileName += ".pkg";
resDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
resDir += "/Resources";
- }
- else
- {
+ } else {
packageDirFileName += ".mpkg";
- if ( !cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str()))
- {
+ if (!cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "unable to create package directory "
- << packageDirFileName << std::endl);
- return 0;
- }
+ "unable to create package directory " << packageDirFileName
+ << std::endl);
+ return 0;
+ }
resDir = packageDirFileName;
resDir += "/Contents";
- if ( !cmsys::SystemTools::MakeDirectory(resDir.c_str()))
- {
+ if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"unable to create package subdirectory " << resDir
- << std::endl);
- return 0;
- }
+ << std::endl);
+ return 0;
+ }
resDir += "/Resources";
- if ( !cmsys::SystemTools::MakeDirectory(resDir.c_str()))
- {
+ if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"unable to create package subdirectory " << resDir
- << std::endl);
- return 0;
- }
+ << std::endl);
+ return 0;
+ }
resDir += "/en.lproj";
- }
+ }
const char* preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT");
const char* postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT");
const char* postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT");
- if(this->Components.empty())
- {
+ if (this->Components.empty()) {
// Create directory structure
std::string preflightDirName = resDir + "/PreFlight";
std::string postflightDirName = resDir + "/PostFlight";
// if preflight or postflight scripts not there create directories
// of the same name, I think this makes it work
- if(!preflight)
- {
- if ( !cmsys::SystemTools::MakeDirectory(preflightDirName.c_str()))
- {
+ if (!preflight) {
+ if (!cmsys::SystemTools::MakeDirectory(preflightDirName.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating installer directory: "
- << preflightDirName.c_str() << std::endl);
+ << preflightDirName << std::endl);
return 0;
- }
}
- if(!postflight)
- {
- if ( !cmsys::SystemTools::MakeDirectory(postflightDirName.c_str()))
- {
+ }
+ if (!postflight) {
+ if (!cmsys::SystemTools::MakeDirectory(postflightDirName.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating installer directory: "
- << postflightDirName.c_str() << std::endl);
+ << postflightDirName << std::endl);
return 0;
- }
}
+ }
// if preflight, postflight, or postupgrade are set
// then copy them into the resource directory and make
// them executable
- if(preflight)
- {
- this->CopyInstallScript(resDir.c_str(),
- preflight,
- "preflight");
- }
- if(postflight)
- {
- this->CopyInstallScript(resDir.c_str(),
- postflight,
- "postflight");
- }
- if(postupgrade)
- {
- this->CopyInstallScript(resDir.c_str(),
- postupgrade,
- "postupgrade");
- }
+ if (preflight) {
+ this->CopyInstallScript(resDir, preflight, "preflight");
}
- else if(postflight)
- {
+ if (postflight) {
+ this->CopyInstallScript(resDir, postflight, "postflight");
+ }
+ if (postupgrade) {
+ this->CopyInstallScript(resDir, postupgrade, "postupgrade");
+ }
+ } else if (postflight) {
// create a postflight component to house the script
this->PostFlightComponent.Name = "PostFlight";
this->PostFlightComponent.DisplayName = "PostFlight";
@@ -169,121 +126,101 @@ int cmCPackPackageMakerGenerator::PackageFiles()
// empty directory for pkg contents
std::string packageDir = toplevel + "/" + PostFlightComponent.Name;
- if (!cmsys::SystemTools::MakeDirectory(packageDir.c_str()))
- {
+ if (!cmsys::SystemTools::MakeDirectory(packageDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating component packages directory: "
- << packageDir.c_str() << std::endl);
+ << packageDir << std::endl);
return 0;
- }
+ }
// create package
std::string packageFileDir = packageDirFileName + "/Contents/Packages/";
- if (!cmsys::SystemTools::MakeDirectory(packageFileDir.c_str()))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem creating component PostFlight Packages directory: "
- << packageFileDir.c_str() << std::endl);
+ if (!cmsys::SystemTools::MakeDirectory(packageFileDir.c_str())) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Problem creating component PostFlight Packages directory: "
+ << packageFileDir << std::endl);
return 0;
- }
- std::string packageFile = packageFileDir +
- this->GetPackageName(PostFlightComponent);
- if (!this->GenerateComponentPackage(packageFile.c_str(),
- packageDir.c_str(),
- PostFlightComponent))
- {
+ }
+ std::string packageFile =
+ packageFileDir + this->GetPackageName(PostFlightComponent);
+ if (!this->GenerateComponentPackage(
+ packageFile.c_str(), packageDir.c_str(), PostFlightComponent)) {
return 0;
- }
+ }
// copy postflight script into resource directory of .pkg
std::string resourceDir = packageFile + "/Contents/Resources";
- this->CopyInstallScript(resourceDir.c_str(),
- postflight,
- "postflight");
- }
+ this->CopyInstallScript(resourceDir, postflight, "postflight");
+ }
- if (!this->Components.empty())
- {
+ if (!this->Components.empty()) {
// Create the directory where component packages will be built.
std::string basePackageDir = packageDirFileName;
basePackageDir += "/Contents/Packages";
- if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str()))
- {
+ if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating component packages directory: "
- << basePackageDir.c_str() << std::endl);
+ << basePackageDir << std::endl);
return 0;
- }
+ }
// Create the directory where downloaded component packages will
// be placed.
const char* userUploadDirectory =
this->GetOption("CPACK_UPLOAD_DIRECTORY");
std::string uploadDirectory;
- if (userUploadDirectory && *userUploadDirectory)
- {
+ if (userUploadDirectory && *userUploadDirectory) {
uploadDirectory = userUploadDirectory;
- }
- else
- {
- uploadDirectory= this->GetOption("CPACK_PACKAGE_DIRECTORY");
+ } else {
+ uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
uploadDirectory += "/CPackUploads";
- }
+ }
// Create packages for each component
bool warnedAboutDownloadCompatibility = false;
std::map<std::string, cmCPackComponent>::iterator compIt;
for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt)
- {
+ ++compIt) {
std::string packageFile;
- if (compIt->second.IsDownloaded)
- {
- if (this->PackageCompatibilityVersion >= 10.5 &&
- this->PackageMakerVersion >= 3.0)
- {
+ if (compIt->second.IsDownloaded) {
+ if (this->PackageCompatibilityVersion >= getVersion(10, 5) &&
+ this->PackageMakerVersion >= 3.0) {
// Build this package within the upload directory.
packageFile = uploadDirectory;
- if(!cmSystemTools::FileExists(uploadDirectory.c_str()))
- {
- if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str()))
- {
+ if (!cmSystemTools::FileExists(uploadDirectory.c_str())) {
+ if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Unable to create package upload directory "
- << uploadDirectory << std::endl);
+ << uploadDirectory << std::endl);
return 0;
- }
}
}
- else if (!warnedAboutDownloadCompatibility)
- {
- if (this->PackageCompatibilityVersion < 10.5)
- {
+ } else if (!warnedAboutDownloadCompatibility) {
+ if (this->PackageCompatibilityVersion < getVersion(10, 5)) {
cmCPackLogger(
cmCPackLog::LOG_WARNING,
"CPack warning: please set CPACK_OSX_PACKAGE_VERSION to 10.5 "
"or greater enable downloaded packages. CPack will build a "
"non-downloaded package."
- << std::endl);
- }
+ << std::endl);
+ }
- if (this->PackageMakerVersion < 3)
- {
+ if (this->PackageMakerVersion < 3) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
- "CPack warning: unable to build downloaded "
+ "CPack warning: unable to build downloaded "
"packages with PackageMaker versions prior "
"to 3.0. CPack will build a non-downloaded package."
- << std::endl);
- }
+ << std::endl);
+ }
warnedAboutDownloadCompatibility = true;
- }
}
+ }
- if (packageFile.empty())
- {
+ if (packageFile.empty()) {
// Build this package within the overall distribution
// metapackage.
packageFile = basePackageDir;
@@ -291,7 +228,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
// We're not downloading this component, even if the user
// requested it.
compIt->second.IsDownloaded = false;
- }
+ }
packageFile += '/';
packageFile += GetPackageName(compIt->second);
@@ -299,106 +236,91 @@ int cmCPackPackageMakerGenerator::PackageFiles()
std::string packageDir = toplevel;
packageDir += '/';
packageDir += compIt->first;
- if (!this->GenerateComponentPackage(packageFile.c_str(),
- packageDir.c_str(),
- compIt->second))
- {
+ if (!this->GenerateComponentPackage(
+ packageFile.c_str(), packageDir.c_str(), compIt->second)) {
return 0;
- }
}
}
+ }
this->SetOption("CPACK_MODULE_VERSION_SUFFIX", "");
// Copy or create all of the resource files we need.
- if ( !this->CopyCreateResourceFile("License", resDir.c_str())
- || !this->CopyCreateResourceFile("ReadMe", resDir.c_str())
- || !this->CopyCreateResourceFile("Welcome", resDir.c_str())
- || !this->CopyResourcePlistFile("Info.plist")
- || !this->CopyResourcePlistFile("Description.plist") )
- {
+ if (!this->CopyCreateResourceFile("License", resDir) ||
+ !this->CopyCreateResourceFile("ReadMe", resDir) ||
+ !this->CopyCreateResourceFile("Welcome", resDir) ||
+ !this->CopyResourcePlistFile("Info.plist") ||
+ !this->CopyResourcePlistFile("Description.plist")) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
- if (this->Components.empty())
- {
+ if (this->Components.empty()) {
// Use PackageMaker to build the package.
- cmOStringStream pkgCmd;
+ std::ostringstream pkgCmd;
pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
<< "\" -build -p \"" << packageDirFileName << "\"";
- if (this->Components.empty())
- {
+ if (this->Components.empty()) {
pkgCmd << " -f \"" << this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- }
- else
- {
+ } else {
pkgCmd << " -mi \"" << this->GetOption("CPACK_TEMPORARY_DIRECTORY")
<< "/packages/";
- }
+ }
pkgCmd << "\" -r \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
<< "/Resources\" -i \""
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
<< "/Info.plist\" -d \""
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
<< "/Description.plist\"";
- if ( this->PackageMakerVersion > 2.0 )
- {
+ if (this->PackageMakerVersion > 2.0) {
pkgCmd << " -v";
- }
+ }
if (!RunPackageMaker(pkgCmd.str().c_str(), packageDirFileName.c_str()))
return 0;
- }
- else
- {
+ } 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";
- cmOStringStream dmgCmd;
+ std::ostringstream dmgCmd;
dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
- << "\" create -ov -format UDZO -srcfolder \"" << packageDirFileName
- << "\" \"" << packageFileNames[0] << "\"";
+ << "\" create -ov -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,
- &retVal, 0, this->GeneratorVerbose,
- 0);
- if ( res && !retVal )
- {
+ while (numTries > 0) {
+ res =
+ cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output, &output,
+ &retVal, 0, this->GeneratorVerbose, 0);
+ if (res && !retVal) {
numTries = -1;
break;
- }
+ }
cmSystemTools::Delay(500);
numTries--;
- }
- if ( !res || retVal )
- {
+ }
+ if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << dmgCmd.str().c_str() << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
+ ofs << "# Run command: " << dmgCmd.str() << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
- << dmgCmd.str().c_str() << std::endl
- << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
+ << dmgCmd.str() << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCPackPackageMakerGenerator::InitializeInternal()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "cmCPackPackageMakerGenerator::Initialize()" << std::endl);
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
// Starting with Xcode 4.3, PackageMaker is a separate app, and you
@@ -415,42 +337,33 @@ 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.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");
std::string pkgPath;
- const char *inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM");
- if (inst_program && *inst_program)
- {
+ const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM");
+ if (inst_program && *inst_program) {
pkgPath = inst_program;
- }
- else
- {
+ } else {
pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false);
- if ( pkgPath.empty() )
- {
+ if (pkgPath.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find PackageMaker compiler"
- << std::endl);
+ << std::endl);
return 0;
- }
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
}
+ this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
+ }
// Get path to the real PackageMaker, not a symlink:
- pkgPath = cmSystemTools::GetRealPath(pkgPath.c_str());
+ pkgPath = cmSystemTools::GetRealPath(pkgPath);
// Up from there to find the version.plist file in the "Contents" dir:
std::string contents_dir;
contents_dir = cmSystemTools::GetFilenamePath(pkgPath);
@@ -458,179 +371,93 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
std::string versionFile = contents_dir + "/version.plist";
- if ( !cmSystemTools::FileExists(versionFile.c_str()) )
- {
+ if (!cmSystemTools::FileExists(versionFile.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find PackageMaker compiler version file: "
- << versionFile.c_str()
- << std::endl);
+ "Cannot find PackageMaker compiler version file: "
+ << versionFile << std::endl);
return 0;
- }
+ }
- std::ifstream ifs(versionFile.c_str());
- if ( !ifs )
- {
+ cmsys::ifstream ifs(versionFile.c_str());
+ if (!ifs) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot open PackageMaker compiler version file" << std::endl);
+ "Cannot open PackageMaker compiler version file"
+ << std::endl);
return 0;
- }
+ }
// Check the PackageMaker version
cmsys::RegularExpression rexKey("<key>CFBundleShortVersionString</key>");
cmsys::RegularExpression rexVersion("<string>([0-9]+.[0-9.]+)</string>");
std::string line;
bool foundKey = false;
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
- if ( rexKey.find(line) )
- {
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
+ if (rexKey.find(line)) {
foundKey = true;
break;
- }
}
- if ( !foundKey )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
+ }
+ if (!foundKey) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
"Cannot find CFBundleShortVersionString in the PackageMaker compiler "
- "version file" << std::endl);
+ "version file"
+ << std::endl);
return 0;
- }
- if ( !cmSystemTools::GetLineFromStream(ifs, line) ||
- !rexVersion.find(line) )
- {
+ }
+ if (!cmSystemTools::GetLineFromStream(ifs, line) || !rexVersion.find(line)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem reading the PackageMaker compiler version file: "
- << versionFile.c_str() << std::endl);
+ "Problem reading the PackageMaker compiler version file: "
+ << versionFile << std::endl);
return 0;
- }
+ }
this->PackageMakerVersion = atof(rexVersion.match(1).c_str());
- if ( this->PackageMakerVersion < 1.0 )
- {
+ if (this->PackageMakerVersion < 1.0) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Require PackageMaker 1.0 or higher"
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
cmCPackLogger(cmCPackLog::LOG_DEBUG, "PackageMaker version is: "
- << this->PackageMakerVersion << std::endl);
+ << 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
// user requested.
- const char *packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION");
- if (packageCompat && *packageCompat)
- {
- this->PackageCompatibilityVersion = atof(packageCompat);
- }
- else if (this->GetOption("CPACK_DOWNLOAD_SITE"))
- {
+ const char* packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION");
+ if (packageCompat && *packageCompat) {
+ unsigned int majorVersion = 10;
+ unsigned int minorVersion = 5;
+ int res = sscanf(packageCompat, "%u.%u", &majorVersion, &minorVersion);
+ if (res == 2) {
+ this->PackageCompatibilityVersion =
+ getVersion(majorVersion, minorVersion);
+ }
+ } else if (this->GetOption("CPACK_DOWNLOAD_SITE")) {
this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.5");
- this->PackageCompatibilityVersion = 10.5;
- }
- else if (this->GetOption("CPACK_COMPONENTS_ALL"))
- {
+ this->PackageCompatibilityVersion = getVersion(10, 5);
+ } else if (this->GetOption("CPACK_COMPONENTS_ALL")) {
this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.4");
- this->PackageCompatibilityVersion = 10.4;
- }
- else
- {
+ this->PackageCompatibilityVersion = getVersion(10, 4);
+ } else {
this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.3");
- this->PackageCompatibilityVersion = 10.3;
- }
+ this->PackageCompatibilityVersion = getVersion(10, 3);
+ }
std::vector<std::string> no_paths;
pkgPath = cmSystemTools::FindProgram("hdiutil", no_paths, false);
- if ( pkgPath.empty() )
- {
+ if (pkgPath.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
- << std::endl);
+ << std::endl);
return 0;
- }
+ }
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
pkgPath.c_str());
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
-bool cmCPackPackageMakerGenerator::CopyCreateResourceFile(const char* name,
- const char* dirName)
-{
- std::string uname = cmSystemTools::UpperCase(name);
- std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
- const char* inFileName = this->GetOption(cpackVar.c_str());
- if ( !inFileName )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str()
- << " not specified. It should point to "
- << (name ? name : "(NULL)")
- << ".rtf, " << name
- << ".html, or " << name << ".txt file" << std::endl);
- return false;
- }
- if ( !cmSystemTools::FileExists(inFileName) )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find "
- << (name ? name : "(NULL)")
- << " 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: "
- << ext << ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
- << std::endl);
- return false;
- }
-
- std::string destFileName = dirName;
- destFileName += '/';
- destFileName += name + ext;
-
- // Set this so that distribution.dist gets the right name (without
- // the path).
- this->SetOption(("CPACK_RESOURCE_FILE_" + uname + "_NOPATH").c_str(),
- (name + ext).c_str());
-
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << (inFileName ? inFileName : "(NULL)")
- << " to " << destFileName.c_str() << std::endl);
- this->ConfigureFile(inFileName, destFileName.c_str());
- return true;
-}
-
-bool cmCPackPackageMakerGenerator::CopyResourcePlistFile(const char* name,
- const char* outName)
-{
- if (!outName)
- {
- outName = name;
- }
-
- std::string inFName = "CPack.";
- inFName += name;
- inFName += ".in";
- std::string inFileName = this->FindTemplate(inFName.c_str());
- if ( inFileName.empty() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: "
- << inFName << std::endl);
- return false;
- }
-
- std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- destFileName += "/";
- destFileName += outName;
-
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << inFileName.c_str() << " to " << destFileName.c_str() << std::endl);
- this->ConfigureFile(inFileName.c_str(), destFileName.c_str());
- return true;
-}
-
-//----------------------------------------------------------------------
-bool cmCPackPackageMakerGenerator::RunPackageMaker(const char *command,
- const char *packageFile)
+bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command,
+ const char* packageFile)
{
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/PackageMakerOutput.log";
@@ -638,100 +465,72 @@ bool cmCPackPackageMakerGenerator::RunPackageMaker(const char *command,
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
std::string output;
int retVal = 1;
- bool res = cmSystemTools::RunSingleCommand(command, &output, &retVal, 0,
- this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ command, &output, &output, &retVal, 0, this->GeneratorVerbose, 0);
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker"
- << std::endl);
- if ( !res || retVal )
- {
+ << std::endl);
+ if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << command << std::endl
- << "# Output:" << std::endl
- << output.c_str() << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem running PackageMaker command: " << command
- << std::endl << "Please check " << tmpFile.c_str() << " for errors"
- << 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);
return false;
- }
+ }
// sometimes the command finishes but the directory is not yet
// created, so try 10 times to see if it shows up
int tries = 10;
- while(tries > 0 &&
- !cmSystemTools::FileExists(packageFile))
- {
+ while (tries > 0 && !cmSystemTools::FileExists(packageFile)) {
cmSystemTools::Delay(500);
tries--;
- }
- if(!cmSystemTools::FileExists(packageFile))
- {
- cmCPackLogger(
- cmCPackLog::LOG_ERROR,
- "Problem running PackageMaker command: " << command
- << std::endl << "Package not created: " << packageFile
- << std::endl);
+ }
+ if (!cmSystemTools::FileExists(packageFile)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running PackageMaker command: "
+ << command << std::endl
+ << "Package not created: " << packageFile << std::endl);
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------
-std::string
-cmCPackPackageMakerGenerator::GetPackageName(const cmCPackComponent& component)
-{
- if (component.ArchiveFile.empty())
- {
- std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- packagesDir += ".dummy";
- cmOStringStream out;
- out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir)
- << "-" << component.Name << ".pkg";
- return out.str();
- }
- else
- {
- return component.ArchiveFile + ".pkg";
- }
-}
-
-//----------------------------------------------------------------------
-bool
-cmCPackPackageMakerGenerator::
-GenerateComponentPackage(const char *packageFile,
- const char *packageDir,
- const cmCPackComponent& component)
+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
- cmOStringStream pkgCmd;
+ std::ostringstream pkgCmd;
- if (this->PackageCompatibilityVersion < 10.5 ||
- this->PackageMakerVersion < 3.0)
- {
+ if (this->PackageCompatibilityVersion < getVersion(10, 5) ||
+ 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::ofstream out(descriptionFile.c_str());
- out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl
- << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
- << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" << std::endl
- << "<plist version=\"1.4\">" << std::endl
- << "<dict>" << std::endl
- << " <key>IFPkgDescriptionTitle</key>" << std::endl
- << " <string>" << component.DisplayName << "</string>" << std::endl
- << " <key>IFPkgDescriptionVersion</key>" << std::endl
- << " <string>" << this->GetOption("CPACK_PACKAGE_VERSION")
- << "</string>" << std::endl
- << " <key>IFPkgDescriptionDescription</key>" << std::endl
- << " <string>" + this->EscapeForXML(component.Description)
- << "</string>" << std::endl
- << "</dict>" << std::endl
- << "</plist>" << std::endl;
+ cmsys::ofstream out(descriptionFile.c_str());
+ cmXMLWriter xout(out);
+ xout.StartDocument();
+ xout.Doctype("plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"");
+ xout.StartElement("plist");
+ xout.Attribute("version", "1.4");
+ xout.StartElement("dict");
+ xout.Element("key", "IFPkgDescriptionTitle");
+ xout.Element("string", component.DisplayName);
+ xout.Element("key", "IFPkgDescriptionVersion");
+ xout.Element("string", this->GetOption("CPACK_PACKAGE_VERSION"));
+ xout.Element("key", "IFPkgDescriptionDescription");
+ xout.Element("string", component.Description);
+ xout.EndElement(); // dict
+ xout.EndElement(); // plist
+ xout.EndDocument();
out.close();
// Create the Info.plist file for this component
@@ -741,20 +540,17 @@ GenerateComponentPackage(const char *packageFile,
moduleVersionSuffix.c_str());
std::string infoFileName = component.Name;
infoFileName += "-Info.plist";
- if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str()))
- {
+ if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) {
return false;
- }
+ }
pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
<< "\" -build -p \"" << packageFile << "\""
<< " -f \"" << packageDir << "\""
- << " -i \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
- << "/" << infoFileName << "\""
+ << " -i \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "/"
+ << infoFileName << "\""
<< " -d \"" << descriptionFile << "\"";
- }
- else
- {
+ } else {
// Create a "flat" package on Mac OS X 10.5 and newer. Flat
// packages are stored in a single file, rather than a directory
// like normal packages, and can be downloaded by the installer
@@ -769,270 +565,11 @@ GenerateComponentPackage(const char *packageFile,
pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
<< "\" --root \"" << packageDir << "\""
- << " --id " << pkgId
- << " --target " << this->GetOption("CPACK_OSX_PACKAGE_VERSION")
- << " --out \"" << packageFile << "\"";
- }
+ << " --id " << pkgId << " --target "
+ << this->GetOption("CPACK_OSX_PACKAGE_VERSION") << " --out \""
+ << packageFile << "\"";
+ }
// Run PackageMaker
return RunPackageMaker(pkgCmd.str().c_str(), packageFile);
}
-
-//----------------------------------------------------------------------
-void
-cmCPackPackageMakerGenerator::
-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);
- return;
- }
-
- std::string distributionFile = metapackageFile;
- distributionFile += "/Contents/distribution.dist";
-
- // Create the choice outline, which provides a tree-based view of
- // the components in their groups.
- cmOStringStream choiceOut;
- choiceOut << "<choices-outline>" << std::endl;
-
- // 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, choiceOut);
- }
- }
-
- // 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)
- {
- choiceOut << "<line choice=\"" << compIt->first << "Choice\"></line>"
- << std::endl;
- }
- }
- if(!this->PostFlightComponent.Name.empty())
- {
- choiceOut << "<line choice=\"" << PostFlightComponent.Name
- << "Choice\"></line>" << std::endl;
- }
- choiceOut << "</choices-outline>" << std::endl;
-
- // Create the actual choices
- for (groupIt = this->ComponentGroups.begin();
- groupIt != this->ComponentGroups.end();
- ++groupIt)
- {
- CreateChoice(groupIt->second, choiceOut);
- }
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt)
- {
- CreateChoice(compIt->second, choiceOut);
- }
-
- if(!this->PostFlightComponent.Name.empty())
- {
- CreateChoice(PostFlightComponent, choiceOut);
- }
-
- this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str());
-
- // Create the distribution.dist file in the metapackage to turn it
- // into a distribution package.
- this->ConfigureFile(distributionTemplate.c_str(),
- distributionFile.c_str());
-}
-
-//----------------------------------------------------------------------
-void
-cmCPackPackageMakerGenerator::
-CreateChoiceOutline(const cmCPackComponentGroup& group, cmOStringStream& out)
-{
- out << "<line choice=\"" << group.Name << "Choice\">" << std::endl;
- std::vector<cmCPackComponentGroup*>::const_iterator groupIt;
- for (groupIt = group.Subgroups.begin(); groupIt != group.Subgroups.end();
- ++groupIt)
- {
- CreateChoiceOutline(**groupIt, out);
- }
-
- std::vector<cmCPackComponent*>::const_iterator compIt;
- for (compIt = group.Components.begin(); compIt != group.Components.end();
- ++compIt)
- {
- out << " <line choice=\"" << (*compIt)->Name << "Choice\"></line>"
- << std::endl;
- }
- out << "</line>" << std::endl;
-}
-
-//----------------------------------------------------------------------
-void
-cmCPackPackageMakerGenerator::CreateChoice(const cmCPackComponentGroup& group,
- cmOStringStream& out)
-{
- out << "<choice id=\"" << group.Name << "Choice\" "
- << "title=\"" << group.DisplayName << "\" "
- << "start_selected=\"true\" "
- << "start_enabled=\"true\" "
- << "start_visible=\"true\" ";
- if (!group.Description.empty())
- {
- out << "description=\"" << EscapeForXML(group.Description)
- << "\"";
- }
- out << "></choice>" << std::endl;
-}
-
-//----------------------------------------------------------------------
-void
-cmCPackPackageMakerGenerator::CreateChoice(const cmCPackComponent& component,
- cmOStringStream& out)
-{
- std::string packageId = "com.";
- packageId += this->GetOption("CPACK_PACKAGE_VENDOR");
- packageId += '.';
- packageId += this->GetOption("CPACK_PACKAGE_NAME");
- packageId += '.';
- packageId += component.Name;
-
- out << "<choice id=\"" << component.Name << "Choice\" "
- << "title=\"" << component.DisplayName << "\" "
- << "start_selected=\""
- << (component.IsDisabledByDefault &&
- !component.IsRequired? "false" : "true")
- << "\" "
- << "start_enabled=\""
- << (component.IsRequired? "false" : "true")
- << "\" "
- << "start_visible=\"" << (component.IsHidden? "false" : "true") << "\" ";
- if (!component.Description.empty())
- {
- out << "description=\"" << EscapeForXML(component.Description)
- << "\" ";
- }
- if (!component.Dependencies.empty() ||
- !component.ReverseDependencies.empty())
- {
- // The "selected" expression is evaluated each time any choice is
- // selected, for all choices *except* the one that the user
- // selected. A component is marked selected if it has been
- // selected (my.choice.selected in Javascript) and all of the
- // components it depends on have been selected (transitively) or
- // if any of the components that depend on it have been selected
- // (transitively). Assume that we have components A, B, C, D, and
- // E, where each component depends on the previous component (B
- // depends on A, C depends on B, D depends on C, and E depends on
- // D). The expression we build for the component C will be
- // my.choice.selected && B && A || D || E
- // 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.
- out << "selected=\"my.choice.selected";
- std::set<const cmCPackComponent *> visited;
- AddDependencyAttributes(component, visited, out);
- visited.clear();
- AddReverseDependencyAttributes(component, visited, out);
- out << "\"";
- }
- out << ">" << std::endl;
- out << " <pkg-ref id=\"" << packageId << "\"></pkg-ref>" << std::endl;
- out << "</choice>" << std::endl;
-
- // Create a description of the package associated with this
- // component.
- std::string relativePackageLocation = "Contents/Packages/";
- relativePackageLocation += this->GetPackageName(component);
-
- // Determine the installed size of the package.
- std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- dirName += '/';
- dirName += component.Name;
- unsigned long installedSize
- = component.GetInstalledSizeInKbytes(dirName.c_str());
-
- out << "<pkg-ref id=\"" << packageId << "\" "
- << "version=\"" << this->GetOption("CPACK_PACKAGE_VERSION") << "\" "
- << "installKBytes=\"" << installedSize << "\" "
- << "auth=\"Admin\" onConclusion=\"None\">";
- if (component.IsDownloaded)
- {
- out << this->GetOption("CPACK_DOWNLOAD_SITE")
- << this->GetPackageName(component);
- }
- else
- {
- out << "file:./" << relativePackageLocation;
- }
- out << "</pkg-ref>" << std::endl;
-}
-
-//----------------------------------------------------------------------
-void
-cmCPackPackageMakerGenerator::
-AddDependencyAttributes(const cmCPackComponent& component,
- std::set<const cmCPackComponent *>& visited,
- cmOStringStream& out)
-{
- if (visited.find(&component) != visited.end())
- {
- return;
- }
- visited.insert(&component);
-
- std::vector<cmCPackComponent *>::const_iterator dependIt;
- for (dependIt = component.Dependencies.begin();
- dependIt != component.Dependencies.end();
- ++dependIt)
- {
- out << " &amp;&amp; choices['" <<
- (*dependIt)->Name << "Choice'].selected";
- AddDependencyAttributes(**dependIt, visited, out);
- }
-}
-
-//----------------------------------------------------------------------
-void
-cmCPackPackageMakerGenerator::
-AddReverseDependencyAttributes(const cmCPackComponent& component,
- std::set<const cmCPackComponent *>& visited,
- cmOStringStream& out)
-{
- if (visited.find(&component) != visited.end())
- {
- return;
- }
- 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);
- }
-}
-
-//----------------------------------------------------------------------
-std::string cmCPackPackageMakerGenerator::EscapeForXML(std::string str)
-{
- cmSystemTools::ReplaceString(str, "&", "&amp;");
- cmSystemTools::ReplaceString(str, "<", "&lt;");
- cmSystemTools::ReplaceString(str, ">", "&gt;");
- cmSystemTools::ReplaceString(str, "\"", "&quot;");
- return str;
-}
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h
index ba3d968f6..62745152b 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.h
+++ b/Source/CPack/cmCPackPackageMakerGenerator.h
@@ -1,20 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackPackageMakerGenerator_h
#define cmCPackPackageMakerGenerator_h
+#include "cmConfigure.h"
#include "cmCPackGenerator.h"
+#include "cmCPackPKGGenerator.h"
class cmCPackComponent;
@@ -24,99 +16,38 @@ class cmCPackComponent;
* http://developer.apple.com/documentation/Darwin
* /Reference/ManPages/man1/packagemaker.1.html
*/
-class cmCPackPackageMakerGenerator : public cmCPackGenerator
+class cmCPackPackageMakerGenerator : public cmCPackPKGGenerator
{
public:
- cmCPackTypeMacro(cmCPackPackageMakerGenerator, cmCPackGenerator);
+ cmCPackTypeMacro(cmCPackPackageMakerGenerator, cmCPackPKGGenerator);
/**
* Construct generator
*/
cmCPackPackageMakerGenerator();
virtual ~cmCPackPackageMakerGenerator();
-
- virtual bool SupportsComponentInstallation() const;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
protected:
- int CopyInstallScript(const char* resdir,
- const char* script,
- const char* name);
- virtual int InitializeInternal();
- int PackageFiles();
- virtual const char* GetOutputExtension() { return ".dmg"; }
- virtual const char* GetOutputPostfix() { return "darwin"; }
-
- // Copies or creates the resource file with the given name to the
- // package or package staging directory dirName. The variable
- // CPACK_RESOURCE_FILE_${NAME} (where ${NAME} is the uppercased
- // version of name) specifies the input file to use for this file,
- // which will be configured via ConfigureFile.
- bool CopyCreateResourceFile(const char* name, const char *dirName);
- bool CopyResourcePlistFile(const char* name, const char* outName = 0);
+ int InitializeInternal() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
+ const char* GetOutputExtension() CM_OVERRIDE { return ".dmg"; }
// Run PackageMaker with the given command line, which will (if
// successful) produce the given package file. Returns true if
// PackageMaker succeeds, false otherwise.
- bool RunPackageMaker(const char *command, const char *packageFile);
-
- // Retrieve the name of package file that will be generated for this
- // component. The name is just the file name with extension, and
- // does not include the subdirectory.
- std::string GetPackageName(const cmCPackComponent& component);
+ bool RunPackageMaker(const char* command, const char* packageFile);
// Generate a package in the file packageFile for the given
// component. All of the files within this component are stored in
// the directory packageDir. Returns true if successful, false
// otherwise.
- bool GenerateComponentPackage(const char *packageFile,
- const char *packageDir,
+ bool GenerateComponentPackage(const char* packageFile,
+ const char* packageDir,
const cmCPackComponent& component);
- // Writes a distribution.dist file, which turns a metapackage into a
- // full-fledged distribution. This file is used to describe
- // inter-component dependencies. metapackageFile is the name of the
- // metapackage for the distribution. Only valid for a
- // component-based install.
- void WriteDistributionFile(const char* metapackageFile);
-
- // Subroutine of WriteDistributionFile that writes out the
- // dependency attributes for inter-component dependencies.
- void AddDependencyAttributes(const cmCPackComponent& component,
- std::set<const cmCPackComponent *>& visited,
- cmOStringStream& out);
-
- // Subroutine of WriteDistributionFile that writes out the
- // reverse dependency attributes for inter-component dependencies.
- void
- AddReverseDependencyAttributes(const cmCPackComponent& component,
- std::set<const cmCPackComponent *>& visited,
- cmOStringStream& out);
-
- // Generates XML that encodes the hierarchy of component groups and
- // their components in a form that can be used by distribution
- // metapackages.
- void CreateChoiceOutline(const cmCPackComponentGroup& group,
- cmOStringStream& out);
-
- /// Create the "choice" XML element to describe a component group
- /// for the installer GUI.
- void CreateChoice(const cmCPackComponentGroup& group,
- cmOStringStream& out);
-
- /// Create the "choice" XML element to describe a component for the
- /// installer GUI.
- void CreateChoice(const cmCPackComponent& component,
- cmOStringStream& out);
-
- // Escape the given string to make it usable as an XML attribute
- // value.
- std::string EscapeForXML(std::string str);
-
- // The PostFlight component when creating a metapackage
- cmCPackComponent PostFlightComponent;
-
double PackageMakerVersion;
- double PackageCompatibilityVersion;
+ unsigned int PackageCompatibilityVersion;
};
#endif
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
new file mode 100644
index 000000000..1389eaa5a
--- /dev/null
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -0,0 +1,258 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackProductBuildGenerator.h"
+
+#include <map>
+#include <sstream>
+#include <stddef.h>
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+
+cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
+{
+ this->componentPackageMethod = ONE_PACKAGE;
+}
+
+cmCPackProductBuildGenerator::~cmCPackProductBuildGenerator()
+{
+}
+
+int cmCPackProductBuildGenerator::PackageFiles()
+{
+ // TODO: Use toplevel
+ // It is used! Is this an obsolete comment?
+
+ std::string packageDirFileName =
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+
+ // Create the directory where component packages will be built.
+ std::string basePackageDir = packageDirFileName;
+ basePackageDir += "/Contents/Packages";
+ if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating component packages directory: "
+ << basePackageDir << std::endl);
+ return 0;
+ }
+
+ if (!this->Components.empty()) {
+ 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;
+ if (!this->GenerateComponentPackage(basePackageDir,
+ GetPackageName(compIt->second),
+ packageDir, &compIt->second)) {
+ return 0;
+ }
+ }
+ } else {
+ if (!this->GenerateComponentPackage(basePackageDir,
+ this->GetOption("CPACK_PACKAGE_NAME"),
+ toplevel, NULL)) {
+ return 0;
+ }
+ }
+
+ std::string resDir = packageDirFileName + "/Contents";
+
+ if (this->IsSet("CPACK_PRODUCTBUILD_RESOURCES_DIR")) {
+ std::string userResDir =
+ this->GetOption("CPACK_PRODUCTBUILD_RESOURCES_DIR");
+
+ if (!cmSystemTools::CopyADirectory(userResDir, resDir)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
+ << std::endl);
+ return 0;
+ }
+ }
+
+ // Copy or create all of the resource files we need.
+ if (!this->CopyCreateResourceFile("License", resDir) ||
+ !this->CopyCreateResourceFile("ReadMe", resDir) ||
+ !this->CopyCreateResourceFile("Welcome", resDir)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the License, ReadMe and Welcome files"
+ << std::endl);
+ return 0;
+ }
+
+ // combine package(s) into a distribution
+ WriteDistributionFile(packageDirFileName.c_str());
+ std::ostringstream pkgCmd;
+
+ std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
+ std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD");
+ std::string identityName;
+ if (const char* n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) {
+ identityName = n;
+ }
+ std::string keychainPath;
+ if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) {
+ keychainPath = p;
+ }
+
+ pkgCmd << productbuild << " --distribution \"" << packageDirFileName
+ << "/Contents/distribution.dist\""
+ << " --package-path \"" << packageDirFileName << "/Contents/Packages"
+ << "\""
+ << " --resources \"" << resDir << "\""
+ << " --version \"" << version << "\""
+ << (identityName.empty() ? "" : " --sign \"" + identityName + "\"")
+ << (keychainPath.empty() ? ""
+ : " --keychain \"" + keychainPath + "\"")
+ << " \"" << packageFileNames[0] << "\"";
+
+ // Run ProductBuild
+ return RunProductBuild(pkgCmd.str());
+}
+
+int cmCPackProductBuildGenerator::InitializeInternal()
+{
+ this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/Applications");
+
+ std::vector<std::string> no_paths;
+ std::string program =
+ cmSystemTools::FindProgram("pkgbuild", no_paths, false);
+ if (program.empty()) {
+ 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);
+ return 0;
+ }
+ this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program.c_str());
+
+ return this->Superclass::InitializeInternal();
+}
+
+bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command)
+{
+ std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ tmpFile += "/ProductBuildOutput.log";
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
+ std::string output, error_output;
+ int retVal = 1;
+ bool res =
+ cmSystemTools::RunSingleCommand(command.c_str(), &output, &error_output,
+ &retVal, 0, this->GeneratorVerbose, 0);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl);
+ if (!res || retVal) {
+ cmGeneratedFileStream ofs(tmpFile.c_str());
+ ofs << "# Run command: " << command << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running command: " << command << std::endl
+ << "Please check " << tmpFile
+ << " for errors" << std::endl);
+ return false;
+ }
+ return true;
+}
+
+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;
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Building component package: "
+ << packageFile << std::endl);
+
+ const char* comp_name = component ? component->Name.c_str() : NULL;
+
+ const char* preflight = this->GetComponentScript("PREFLIGHT", comp_name);
+ const char* postflight = this->GetComponentScript("POSTFLIGHT", comp_name);
+
+ std::string resDir = packageFileDir;
+ if (component) {
+ resDir += "/";
+ resDir += component->Name;
+ }
+ std::string scriptDir = resDir + "/scripts";
+
+ if (!cmsys::SystemTools::MakeDirectory(scriptDir.c_str())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating installer directory: " << scriptDir
+ << std::endl);
+ return 0;
+ }
+
+ // if preflight, postflight, or postupgrade are set
+ // then copy them into the script directory and make
+ // them executable
+ if (preflight) {
+ this->CopyInstallScript(scriptDir, preflight, "preinstall");
+ }
+ if (postflight) {
+ this->CopyInstallScript(scriptDir, postflight, "postinstall");
+ }
+
+ // 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");
+ if (component) {
+ pkgId += '.';
+ pkgId += component->Name;
+ }
+
+ std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
+ std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD");
+ std::string identityName;
+ if (const char* n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) {
+ identityName = n;
+ }
+ std::string keychainPath;
+ if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) {
+ keychainPath = p;
+ }
+
+ pkgCmd << pkgbuild << " --root \"" << packageDir << "\""
+ << " --identifier \"" << pkgId << "\""
+ << " --scripts \"" << scriptDir << "\""
+ << " --version \"" << version << "\""
+ << " --install-location \"/\""
+ << (identityName.empty() ? "" : " --sign \"" + identityName + "\"")
+ << (keychainPath.empty() ? ""
+ : " --keychain \"" + keychainPath + "\"")
+ << " \"" << packageFile << "\"";
+
+ if (component && !component->Plist.empty()) {
+ pkgCmd << " --component-plist \"" << component->Plist << "\"";
+ }
+
+ // Run ProductBuild
+ return RunProductBuild(pkgCmd.str());
+}
+
+const char* cmCPackProductBuildGenerator::GetComponentScript(
+ const char* script, const char* component_name)
+{
+ std::string scriptname = std::string("CPACK_") + script + "_";
+ if (component_name) {
+ scriptname += cmSystemTools::UpperCase(component_name);
+ scriptname += "_";
+ }
+ scriptname += "SCRIPT";
+
+ return this->GetOption(scriptname);
+}
diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h
new file mode 100644
index 000000000..12093a0e8
--- /dev/null
+++ b/Source/CPack/cmCPackProductBuildGenerator.h
@@ -0,0 +1,53 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackProductBuildGenerator_h
+#define cmCPackProductBuildGenerator_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#include "cmCPackGenerator.h"
+#include "cmCPackPKGGenerator.h"
+
+class cmCPackComponent;
+
+/** \class cmCPackProductBuildGenerator
+ * \brief A generator for ProductBuild files
+ *
+ */
+class cmCPackProductBuildGenerator : public cmCPackPKGGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackProductBuildGenerator, cmCPackPKGGenerator);
+
+ /**
+ * Construct generator
+ */
+ cmCPackProductBuildGenerator();
+ virtual ~cmCPackProductBuildGenerator();
+
+protected:
+ int InitializeInternal() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
+ const char* GetOutputExtension() CM_OVERRIDE { return ".pkg"; }
+
+ // Run ProductBuild with the given command line, which will (if
+ // successful) produce the given package file. Returns true if
+ // ProductBuild succeeds, false otherwise.
+ bool RunProductBuild(const std::string& command);
+
+ // Generate a package in the file packageFile for the given
+ // component. All of the files within this component are stored in
+ // the directory packageDir. Returns true if successful, false
+ // otherwise.
+ bool GenerateComponentPackage(const std::string& packageFileDir,
+ const std::string& packageFileName,
+ const std::string& packageDir,
+ const cmCPackComponent* component);
+
+ const char* GetComponentScript(const char* script,
+ const char* script_component);
+};
+
+#endif
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 66a419405..8ec03c236 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -1,99 +1,103 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackRPMGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <algorithm>
+#include <ctype.h>
+#include <map>
+#include <ostream>
+#include <utility>
+#include <vector>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCPackRPMGenerator.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------
cmCPackRPMGenerator::cmCPackRPMGenerator()
{
}
-//----------------------------------------------------------------------
cmCPackRPMGenerator::~cmCPackRPMGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackRPMGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
- if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR")))
- {
+ if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
this->SetOption("CPACK_SET_DESTDIR", "I_ON");
- }
+ }
/* Replace space in CPACK_PACKAGE_NAME in order to avoid
* rpmbuild scream on unwanted space in filename issue
* Moreover RPM file do not usually embed space in filename
*/
if (this->GetOption("CPACK_PACKAGE_NAME")) {
- std::string packageName=this->GetOption("CPACK_PACKAGE_NAME");
- cmSystemTools::ReplaceString(packageName," ","-");
- this->SetOption("CPACK_PACKAGE_NAME",packageName.c_str());
+ std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
+ std::replace(packageName.begin(), packageName.end(), ' ', '-');
+ this->SetOption("CPACK_PACKAGE_NAME", packageName.c_str());
}
/* same for CPACK_PACKAGE_FILE_NAME */
if (this->GetOption("CPACK_PACKAGE_FILE_NAME")) {
- std::string packageName=this->GetOption("CPACK_PACKAGE_FILE_NAME");
- cmSystemTools::ReplaceString(packageName," ","-");
- this->SetOption("CPACK_PACKAGE_FILE_NAME",packageName.c_str());
+ std::string packageName = this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ std::replace(packageName.begin(), packageName.end(), ' ', '-');
+ this->SetOption("CPACK_PACKAGE_FILE_NAME", packageName.c_str());
}
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
-int cmCPackRPMGenerator::PackageOnePack(std::string initialToplevel,
- std::string packageName)
+void cmCPackRPMGenerator::AddGeneratedPackageNames()
+{
+ // add the generated packages to package file names list
+ std::string fileNames(this->GetOption("GEN_CPACK_OUTPUT_FILES"));
+ 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));
+}
+
+int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
+ std::string const& packageName)
{
int retval = 1;
// Begin the archive for this pack
std::string localToplevel(initialToplevel);
- std::string packageFileName(
- cmSystemTools::GetParentDirectory(toplevel.c_str())
- );
+ std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
std::string outputFileName(
- GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- packageName,
- true)
- + this->GetOutputExtension()
- );
+ GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
+ packageName, true) +
+ this->GetOutputExtension());
- localToplevel += "/"+ packageName;
+ localToplevel += "/" + packageName;
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str());
- packageFileName += "/"+ outputFileName;
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
/* replace the TEMPORARY package file name */
this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
packageFileName.c_str());
// Tell CPackRPM.cmake the name of the component NAME.
- this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",packageName.c_str());
+ 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;
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("CPackRPM.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake"
+ << std::endl);
retval = 0;
- }
- // add the generated package to package file names list
- packageFileNames.push_back(packageFileName);
+ }
+
return retval;
}
-//----------------------------------------------------------------------
int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
{
int retval = 1;
@@ -102,165 +106,319 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- // 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);
- retval &= PackageOnePack(initialTopLevel,compGIt->first);
+ const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");
+
+ if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") &&
+ !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) {
+ // check if we need to set CPACK_RPM_DEBUGINFO_PACKAGE because non of
+ // the components is setting per component debuginfo package variable
+ bool shouldSet = true;
+
+ if (ignoreGroup) {
+ std::map<std::string, cmCPackComponent>::iterator compIt;
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
+ std::string component(compIt->first);
+ std::transform(component.begin(), component.end(), component.begin(),
+ ::toupper);
+
+ if (this->IsOn("CPACK_RPM_" + compIt->first + "_DEBUGINFO_PACKAGE") ||
+ this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
+ shouldSet = false;
+ break;
+ }
}
- // 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 )
- {
- // Does the component belong to a group?
- if (compIt->second.Group==NULL)
- {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Component <"
- << compIt->second.Name
- << "> does not belong to any group, package it separately."
- << std::endl);
- retval &= PackageOnePack(initialTopLevel,compIt->first);
+ } else {
+ std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
+ for (compGIt = this->ComponentGroups.begin();
+ compGIt != this->ComponentGroups.end(); ++compGIt) {
+ std::string component(compGIt->first);
+ std::transform(component.begin(), component.end(), component.begin(),
+ ::toupper);
+
+ if (this->IsOn("CPACK_RPM_" + compGIt->first + "_DEBUGINFO_PACKAGE") ||
+ this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
+ shouldSet = false;
+ break;
}
}
+
+ if (shouldSet) {
+ 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) {
+ std::string component(compIt->first);
+ std::transform(component.begin(), component.end(),
+ component.begin(), ::toupper);
+
+ if (this->IsOn("CPACK_RPM_" + compIt->first +
+ "_DEBUGINFO_PACKAGE") ||
+ this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) {
+ shouldSet = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (shouldSet) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Setting "
+ << "CPACK_RPM_DEBUGINFO_PACKAGE because "
+ << "CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is set but "
+ << " none of the "
+ << "CPACK_RPM_<component>_DEBUGINFO_PACKAGE variables "
+ << "are set." << std::endl);
+ this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON");
+ }
+ }
+
+ if (mainComponent) {
+ if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
+ this->SetOption("GENERATE_SPEC_PARTS", "ON");
}
- // 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);
+
+ std::string mainComponentUpper(mainComponent);
+ std::transform(mainComponentUpper.begin(), mainComponentUpper.end(),
+ mainComponentUpper.begin(), ::toupper);
+
+ // 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();
+
+ std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
+ for (compGIt = this->ComponentGroups.begin();
+ compGIt != this->ComponentGroups.end(); ++compGIt) {
+ std::string component(compGIt->first);
+ std::transform(component.begin(), component.end(), component.begin(),
+ ::toupper);
+
+ if (mainComponentUpper == component) {
+ // main component will be handled last
+ mainCompGIt = compGIt;
+ continue;
+ }
+
+ 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();
+ 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) {
+ std::string component(compIt->first);
+ std::transform(component.begin(), component.end(), component.begin(),
+ ::toupper);
+
+ if (mainComponentUpper == component) {
+ // main component will be handled last
+ mainCompIt = compIt;
+ continue;
+ }
+
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE, "Component <"
+ << compIt->second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ retval &= PackageOnePack(initialTopLevel, compIt->first);
+ }
+ }
+
+ if (retval) {
+ this->SetOption("GENERATE_SPEC_PARTS", "OFF");
+
+ if (mainCompGIt != this->ComponentGroups.end()) {
+ retval &= PackageOnePack(initialTopLevel, mainCompGIt->first);
+ } else if (mainCompIt != this->Components.end()) {
+ retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+ << " to non existing component.\n");
+ retval = 0;
+ }
}
}
+ // CPACK_COMPONENTS_IGNORE_GROUPS is set
+ // We build 1 package per component
+ else {
+ std::map<std::string, cmCPackComponent>::iterator mainCompIt =
+ this->Components.end();
+
+ std::map<std::string, cmCPackComponent>::iterator compIt;
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt) {
+ std::string component(compIt->first);
+ std::transform(component.begin(), component.end(), component.begin(),
+ ::toupper);
+
+ if (mainComponentUpper == component) {
+ // main component will be handled last
+ mainCompIt = compIt;
+ continue;
+ }
+
+ retval &= PackageOnePack(initialTopLevel, compIt->first);
+ }
+
+ if (retval) {
+ this->SetOption("GENERATE_SPEC_PARTS", "OFF");
+
+ if (mainCompIt != this->Components.end()) {
+ retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+ << " to non existing component.\n");
+ retval = 0;
+ }
+ }
+ }
+ } else if (!this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") ||
+ this->Components.size() == 1) {
+ // 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);
+ retval &= PackageOnePack(initialTopLevel, compGIt->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) {
+ // Does the component belong to a group?
+ if (compIt->second.Group == CM_NULLPTR) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE, "Component <"
+ << compIt->second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ retval &= PackageOnePack(initialTopLevel, compIt->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);
+ }
+ }
+ } else {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT not set but"
+ << " it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE"
+ << " being set.\n");
+ retval = 0;
+ }
+
+ if (retval) {
+ AddGeneratedPackageNames();
+ }
+
return retval;
}
-//----------------------------------------------------------------------
-int cmCPackRPMGenerator::PackageComponentsAllInOne()
+int cmCPackRPMGenerator::PackageComponentsAllInOne(
+ const std::string& compInstDirName)
{
int retval = 1;
- std::string compInstDirName;
/* Reset package file name list it will be populated during the
* component packaging run*/
packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- compInstDirName = "ALL_COMPONENTS_IN_ONE";
+ if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
+ this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON");
+ }
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging all groups in one package..."
"(CPACK_COMPONENTS_ALL_[GROUPS_]IN_ONE_PACKAGE is set)"
- << std::endl);
+ << std::endl);
// The ALL GROUPS in ONE package case
std::string localToplevel(initialTopLevel);
- std::string packageFileName(
- cmSystemTools::GetParentDirectory(toplevel.c_str())
- );
+ std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
std::string outputFileName(
- std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
- + this->GetOutputExtension()
- );
+ std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
+ this->GetOutputExtension());
// all GROUP in one vs all COMPONENT in one
- localToplevel += "/"+compInstDirName;
+ localToplevel += "/" + compInstDirName;
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str());
- packageFileName += "/"+ outputFileName;
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
/* replace the TEMPORARY package file name */
this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
- // Tell CPackRPM.cmake the path where the component is.
- std::string component_path = "/";
- component_path += compInstDirName;
- 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);
+ packageFileName.c_str());
+
+ if (!compInstDirName.empty()) {
+ // Tell CPackRPM.cmake the path where the component is.
+ std::string component_path = "/";
+ component_path += compInstDirName;
+ this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
+ component_path.c_str());
+ }
+
+ if (this->ReadListFile("CPackRPM.cmake")) {
+ AddGeneratedPackageNames();
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake"
+ << std::endl);
retval = 0;
- }
- // add the generated package to package file names list
- packageFileNames.push_back(packageFileName);
+ }
return retval;
}
-//----------------------------------------------------------------------
int cmCPackRPMGenerator::PackageFiles()
{
- int retval = 1;
-
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
- << toplevel << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
/* Are we in the component packaging case */
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();
- }
+ if (componentPackageMethod == ONE_PACKAGE) {
+ return PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
+ }
// 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.
- else
- {
- return PackageComponents(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
- }
+ return PackageComponents(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
// CASE 3 : NON COMPONENT package.
- else
- {
- if (!this->ReadListFile("CPackRPM.cmake"))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error while execution CPackRPM.cmake" << std::endl);
- retval = 0;
- }
- }
-
- if (!this->IsSet("RPMBUILD_EXECUTABLE"))
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find rpmbuild" << std::endl);
- retval = 0;
- }
- return retval;
+ return PackageComponentsAllInOne("");
}
bool cmCPackRPMGenerator::SupportsComponentInstallation() const
- {
- if (IsOn("CPACK_RPM_COMPONENT_INSTALL"))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
+{
+ return IsOn("CPACK_RPM_COMPONENT_INSTALL");
+}
std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
- const std::string& componentName)
- {
+ const std::string& componentName)
+{
if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
return componentName;
}
@@ -270,14 +428,10 @@ std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
- std::string groupVar = "CPACK_COMPONENT_" +
- cmSystemTools::UpperCase(componentName) + "_GROUP";
- if (NULL != GetOption(groupVar.c_str()))
- {
- return std::string(GetOption(groupVar.c_str()));
- }
- else
- {
- return componentName;
- }
+ std::string groupVar =
+ "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
+ if (CM_NULLPTR != GetOption(groupVar)) {
+ return std::string(GetOption(groupVar));
}
+ return componentName;
+}
diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h
index a7722bc58..52cfc13ed 100644
--- a/Source/CPack/cmCPackRPMGenerator.h
+++ b/Source/CPack/cmCPackRPMGenerator.h
@@ -1,21 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackRPMGenerator_h
#define cmCPackRPMGenerator_h
+#include "cmConfigure.h"
#include "cmCPackGenerator.h"
+#include <string>
+
/** \class cmCPackRPMGenerator
* \brief A generator for RPM packages
* The idea of the CPack RPM generator is to use
@@ -33,10 +26,10 @@ public:
* Construct generator
*/
cmCPackRPMGenerator();
- virtual ~cmCPackRPMGenerator();
+ ~cmCPackRPMGenerator() CM_OVERRIDE;
static bool CanGenerate()
- {
+ {
#ifdef __APPLE__
// on MacOS enable CPackRPM iff rpmbuild is found
std::vector<std::string> locations;
@@ -47,15 +40,16 @@ public:
// legacy behavior on other systems
return true;
#endif
- }
+ }
protected:
- virtual int InitializeInternal();
- virtual int PackageFiles();
+ int InitializeInternal() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
/**
* This method factors out the work done in component packaging case.
*/
- int PackageOnePack(std::string initialToplevel, std::string packageName);
+ int PackageOnePack(std::string const& initialToplevel,
+ std::string const& packageName);
/**
* The method used to package files when component
* install is used. This will create one
@@ -66,12 +60,13 @@ protected:
* Special case of component install where all
* components will be put in a single installer.
*/
- int PackageComponentsAllInOne();
- virtual const char* GetOutputExtension() { return ".rpm"; }
- virtual bool SupportsComponentInstallation() const;
- virtual std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName);
+ int PackageComponentsAllInOne(const std::string& compInstDirName);
+ const char* GetOutputExtension() CM_OVERRIDE { return ".rpm"; }
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
+ std::string GetComponentInstallDirNameSuffix(
+ const std::string& componentName) CM_OVERRIDE;
+ void AddGeneratedPackageNames();
};
#endif
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 9b6cf14df..c54161426 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -1,102 +1,81 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackSTGZGenerator.h"
-#include "cmake.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmCPackLog.h"
+#include "cmsys/FStream.hxx"
+#include <sstream>
+#include <stdio.h>
+#include <string>
+#include <vector>
-#include <cmsys/ios/sstream>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include "cmCPackGenerator.h"
+#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+#include "cm_sys_stat.h"
-//----------------------------------------------------------------------
cmCPackSTGZGenerator::cmCPackSTGZGenerator()
{
}
-//----------------------------------------------------------------------
cmCPackSTGZGenerator::~cmCPackSTGZGenerator()
{
}
-//----------------------------------------------------------------------
int cmCPackSTGZGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "0");
std::string inFile = this->FindTemplate("CPack.STGZ_Header.sh.in");
- if ( inFile.empty() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find template file: "
- << inFile.c_str() << std::endl);
+ if (inFile.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find template file: " << inFile << std::endl);
return 0;
- }
+ }
this->SetOptionIfNotSet("CPACK_STGZ_HEADER_FILE", inFile.c_str());
this->SetOptionIfNotSet("CPACK_AT_SIGN", "@");
return this->Superclass::InitializeInternal();
}
-//----------------------------------------------------------------------
int cmCPackSTGZGenerator::PackageFiles()
{
- bool retval = true;
- if ( !this->Superclass::PackageFiles() )
- {
+ bool retval = true;
+ if (!this->Superclass::PackageFiles()) {
return 0;
- }
+ }
/* TGZ generator (our Superclass) may
* 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)
- {
+ for (std::vector<std::string>::iterator it = packageFileNames.begin();
+ it != packageFileNames.end(); ++it) {
retval &= cmSystemTools::SetPermissions((*it).c_str(),
-#if defined( _MSC_VER ) || defined( __MINGW32__ )
- S_IREAD | S_IWRITE | S_IEXEC
-#elif defined( __BORLANDC__ )
- S_IRUSR | S_IWUSR | S_IXUSR
+#if defined(_MSC_VER) || defined(__MINGW32__)
+ S_IREAD | S_IWRITE | S_IEXEC
#else
- S_IRUSR | S_IWUSR | S_IXUSR |
- S_IRGRP | S_IWGRP | S_IXGRP |
- S_IROTH | S_IWOTH | S_IXOTH
+ S_IRUSR | S_IWUSR | S_IXUSR |
+ S_IRGRP | S_IWGRP | S_IXGRP |
+ S_IROTH | S_IWOTH | S_IXOTH
#endif
- );
+ );
}
return retval;
}
-//----------------------------------------------------------------------
int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Writing header" << std::endl);
- cmsys_ios::ostringstream str;
+ std::ostringstream str;
int counter = 0;
std::string inLicFile = this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
std::string line;
- std::ifstream ilfs(inLicFile.c_str());
+ cmsys::ifstream ilfs(inLicFile.c_str());
std::string licenseText;
- while ( cmSystemTools::GetLineFromStream(ilfs, line) )
- {
+ while (cmSystemTools::GetLineFromStream(ilfs, line)) {
licenseText += line + "\n";
- }
+ }
this->SetOptionIfNotSet("CPACK_RESOURCE_FILE_LICENSE_CONTENT",
licenseText.c_str());
@@ -104,12 +83,11 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
// Create the header
std::string inFile = this->GetOption("CPACK_STGZ_HEADER_FILE");
- std::ifstream ifs(inFile.c_str());
+ cmsys::ifstream ifs(inFile.c_str());
std::string packageHeaderText;
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
packageHeaderText += line + "\n";
- }
+ }
// Configure in the values
std::string res;
@@ -117,22 +95,20 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
// Count the lines
const char* ptr = res.c_str();
- while ( *ptr )
- {
- if ( *ptr == '\n' )
- {
- counter ++;
- }
- ++ptr;
+ while (*ptr) {
+ if (*ptr == '\n') {
+ counter++;
}
- counter ++;
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Number of lines: " << counter << std::endl);
+ ++ptr;
+ }
+ counter++;
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Number of lines: " << counter
+ << std::endl);
char buffer[1024];
sprintf(buffer, "%d", counter);
cmSystemTools::ReplaceString(res, headerLengthTag, buffer);
// Write in file
- *os << res.c_str();
+ *os << res;
return this->Superclass::GenerateHeader(os);
}
diff --git a/Source/CPack/cmCPackSTGZGenerator.h b/Source/CPack/cmCPackSTGZGenerator.h
index ccceec806..8304e8076 100644
--- a/Source/CPack/cmCPackSTGZGenerator.h
+++ b/Source/CPack/cmCPackSTGZGenerator.h
@@ -1,21 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackSTGZGenerator_h
#define cmCPackSTGZGenerator_h
+#include "cmConfigure.h"
+#include "cmCPackGenerator.h"
#include "cmCPackTGZGenerator.h"
+#include <iosfwd>
+
/** \class cmCPackSTGZGenerator
* \brief A generator for Self extractable TGZ files
*
@@ -29,13 +23,13 @@ public:
* Construct generator
*/
cmCPackSTGZGenerator();
- virtual ~cmCPackSTGZGenerator();
+ ~cmCPackSTGZGenerator() CM_OVERRIDE;
protected:
- int PackageFiles();
- virtual int InitializeInternal();
- int GenerateHeader(std::ostream* os);
- virtual const char* GetOutputExtension() { return ".sh"; }
+ int PackageFiles() CM_OVERRIDE;
+ int InitializeInternal() CM_OVERRIDE;
+ int GenerateHeader(std::ostream* os) CM_OVERRIDE;
+ const char* GetOutputExtension() CM_OVERRIDE { return ".sh"; }
};
#endif
diff --git a/Source/CPack/cmCPackTGZGenerator.cxx b/Source/CPack/cmCPackTGZGenerator.cxx
index 509c7f80a..eaf8186fe 100644
--- a/Source/CPack/cmCPackTGZGenerator.cxx
+++ b/Source/CPack/cmCPackTGZGenerator.cxx
@@ -1,26 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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,
- cmArchiveWrite::TypeTAR)
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressGZip, "paxr")
{
}
-//----------------------------------------------------------------------
cmCPackTGZGenerator::~cmCPackTGZGenerator()
{
}
-
diff --git a/Source/CPack/cmCPackTGZGenerator.h b/Source/CPack/cmCPackTGZGenerator.h
index 3a9fc6b41..9426b3a01 100644
--- a/Source/CPack/cmCPackTGZGenerator.h
+++ b/Source/CPack/cmCPackTGZGenerator.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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
@@ -27,9 +20,10 @@ public:
* Construct generator
*/
cmCPackTGZGenerator();
- virtual ~cmCPackTGZGenerator();
+ ~cmCPackTGZGenerator() CM_OVERRIDE;
+
protected:
- virtual const char* GetOutputExtension() { return ".tar.gz"; }
+ const char* GetOutputExtension() CM_OVERRIDE { return ".tar.gz"; }
};
#endif
diff --git a/Source/CPack/cmCPackTXZGenerator.cxx b/Source/CPack/cmCPackTXZGenerator.cxx
new file mode 100644
index 000000000..e55e903e9
--- /dev/null
+++ b/Source/CPack/cmCPackTXZGenerator.cxx
@@ -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. */
+#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
new file mode 100644
index 000000000..3b96e2d78
--- /dev/null
+++ b/Source/CPack/cmCPackTXZGenerator.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 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
index ae73c3795..c7a3dd429 100644
--- a/Source/CPack/cmCPackTarBZip2Generator.cxx
+++ b/Source/CPack/cmCPackTarBZip2Generator.cxx
@@ -1,25 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackTarBZip2Generator.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "cmArchiveWrite.h"
+#include "cmCPackArchiveGenerator.h"
-#include "cmCPackTarBZip2Generator.h"
-//----------------------------------------------------------------------
cmCPackTarBZip2Generator::cmCPackTarBZip2Generator()
- :cmCPackArchiveGenerator(cmArchiveWrite::CompressBZip2,
- cmArchiveWrite::TypeTAR)
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressBZip2, "paxr")
{
}
-//----------------------------------------------------------------------
cmCPackTarBZip2Generator::~cmCPackTarBZip2Generator()
{
}
-
diff --git a/Source/CPack/cmCPackTarBZip2Generator.h b/Source/CPack/cmCPackTarBZip2Generator.h
index 74c244e5a..9b4b8f4ff 100644
--- a/Source/CPack/cmCPackTarBZip2Generator.h
+++ b/Source/CPack/cmCPackTarBZip2Generator.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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
@@ -26,9 +19,10 @@ public:
* Construct generator
*/
cmCPackTarBZip2Generator();
- virtual ~cmCPackTarBZip2Generator();
+ ~cmCPackTarBZip2Generator() CM_OVERRIDE;
+
protected:
- virtual const char* GetOutputExtension() { return ".tar.bz2"; }
+ const char* GetOutputExtension() CM_OVERRIDE { return ".tar.bz2"; }
};
#endif
diff --git a/Source/CPack/cmCPackTarCompressGenerator.cxx b/Source/CPack/cmCPackTarCompressGenerator.cxx
index df294084c..0a7cd978c 100644
--- a/Source/CPack/cmCPackTarCompressGenerator.cxx
+++ b/Source/CPack/cmCPackTarCompressGenerator.cxx
@@ -1,26 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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,
- cmArchiveWrite::TypeTAR)
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressCompress, "paxr")
{
}
-//----------------------------------------------------------------------
cmCPackTarCompressGenerator::~cmCPackTarCompressGenerator()
{
}
-
diff --git a/Source/CPack/cmCPackTarCompressGenerator.h b/Source/CPack/cmCPackTarCompressGenerator.h
index 7ff9a0ade..381d6eb2f 100644
--- a/Source/CPack/cmCPackTarCompressGenerator.h
+++ b/Source/CPack/cmCPackTarCompressGenerator.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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 "cmCPackTGZGenerator.h"
+#include "cmConfigure.h"
+
+#include "cmCPackArchiveGenerator.h"
+#include "cmCPackGenerator.h"
/** \class cmCPackTarCompressGenerator
* \brief A generator for TarCompress files
@@ -26,10 +19,10 @@ public:
* Construct generator
*/
cmCPackTarCompressGenerator();
- virtual ~cmCPackTarCompressGenerator();
+ ~cmCPackTarCompressGenerator() CM_OVERRIDE;
protected:
- virtual const char* GetOutputExtension() { return ".tar.Z"; }
+ const char* GetOutputExtension() CM_OVERRIDE { return ".tar.Z"; }
};
#endif
diff --git a/Source/CPack/cmCPackZIPGenerator.cxx b/Source/CPack/cmCPackZIPGenerator.cxx
index e6e4e77d0..6b77c363d 100644
--- a/Source/CPack/cmCPackZIPGenerator.cxx
+++ b/Source/CPack/cmCPackZIPGenerator.cxx
@@ -1,26 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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,
- cmArchiveWrite::TypeZIP)
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressNone, "zip")
{
}
-//----------------------------------------------------------------------
cmCPackZIPGenerator::~cmCPackZIPGenerator()
{
}
-
diff --git a/Source/CPack/cmCPackZIPGenerator.h b/Source/CPack/cmCPackZIPGenerator.h
index 70e1a5fa8..00c872029 100644
--- a/Source/CPack/cmCPackZIPGenerator.h
+++ b/Source/CPack/cmCPackZIPGenerator.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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
@@ -27,10 +20,10 @@ public:
* Construct generator
*/
cmCPackZIPGenerator();
- virtual ~cmCPackZIPGenerator();
+ ~cmCPackZIPGenerator() CM_OVERRIDE;
protected:
- virtual const char* GetOutputExtension() { return ".zip"; }
+ const char* GetOutputExtension() CM_OVERRIDE { return ".zip"; }
};
#endif
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index b18891858..a44bc3d68 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -1,184 +1,105 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSystemTools.h"
+/* 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
-// Need these for documentation support.
-#include "cmake.h"
-#include "cmDocumentation.h"
-#include "cmCPackDocumentVariables.h"
-#include "cmCPackDocumentMacros.h"
-#include "cmCPackGeneratorFactory.h"
#include "cmCPackGenerator.h"
-#include "cmake.h"
+#include "cmCPackGeneratorFactory.h"
+#include "cmCPackLog.h"
+#include "cmDocumentation.h"
+#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-#include "cmCPackLog.h"
-
-#include <cmsys/CommandLineArguments.hxx>
-#include <cmsys/SystemTools.hxx>
-
-//----------------------------------------------------------------------------
-static const char * cmDocumentationName[][3] =
-{
- {0,
- " cpack - Packaging driver provided by CMake.", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char * cmDocumentationUsage[][3] =
-{
- {0,
- " cpack -G <generator> [options]",
- 0},
- {0,0,0}
+static const char* cmDocumentationName[][2] = {
+ { CM_NULLPTR, " cpack - Packaging driver provided by CMake." },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationDescription[][3] =
-{
- {0,
- "The \"cpack\" executable is the CMake packaging program. "
- "CMake-generated build trees created for projects that use "
- "the INSTALL_* commands have packaging support. "
- "This program will generate the package.", 0},
- CMAKE_STANDARD_INTRODUCTION,
- {0,0,0}
+static const char* cmDocumentationUsage[][2] = {
+ { CM_NULLPTR, " cpack -G <generator> [options]" },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationOptions[][3] =
-{
- {"-G <generator>", "Use the specified generator to generate package.",
- "CPack may support multiple native packaging systems on certain "
- "platforms. A generator is responsible for generating input files for "
- "particular system and invoking that systems. Possible generator names "
- "are specified in the Generators section." },
- {"-C <Configuration>", "Specify the project configuration",
- "This option specifies the configuration that the project was build "
- "with, for example 'Debug', 'Release'." },
- {"-D <var>=<value>", "Set a CPack variable.", \
- "Set a variable that can be used by the generator."}, \
- {"--config <config file>", "Specify the config file.",
- "Specify the config file to use to create the package. By default "
- "CPackConfig.cmake in the current directory will be used." },
- {"--verbose,-V","enable verbose output","Run cpack with verbose output."},
- {"--debug","enable debug output (for CPack developers)",
- "Run cpack with debug output (for CPack developers)."},
- {"-P <package name>","override/define CPACK_PACKAGE_NAME",
- "If the package name is not specified on cpack commmand line then"
- "CPack.cmake defines it as CMAKE_PROJECT_NAME"},
- {"-R <package version>","override/define CPACK_PACKAGE_VERSION",
- "If version is not specified on cpack command line then"
- "CPack.cmake defines it from CPACK_PACKAGE_VERSION_[MAJOR|MINOR|PATCH]"
- "look into CPack.cmake for detail"},
- {"-B <package directory>","override/define CPACK_PACKAGE_DIRECTORY",
- "The directory where CPack will be doing its packaging work."
- "The resulting package will be found there. Inside this directory"
- "CPack creates '_CPack_Packages' sub-directory which is the"
- "CPack temporary directory."},
- {"--vendor <vendor name>","override/define CPACK_PACKAGE_VENDOR",
- "If vendor is not specified on cpack command line "
- "(or inside CMakeLists.txt) then"
- "CPack.cmake defines it with a default value"},
- {"--help-command cmd [file]", "Print help for a single command and exit.",
- "Full documentation specific to the given command is displayed. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-command-list [file]", "List available commands and exit.",
- "The list contains all commands for which help may be obtained by using "
- "the --help-command argument followed by a command name. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-commands [file]", "Print help for all commands and exit.",
- "Full documentation specific for all current command is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-variable var [file]",
- "Print help for a single variable and exit.",
- "Full documentation specific to the given variable is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-variable-list [file]", "List documented variables and exit.",
- "The list contains all variables for which help may be obtained by using "
- "the --help-variable argument followed by a variable name. If a file is "
- "specified, the help is written into it."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-variables [file]", "Print help for all variables and exit.",
- "Full documentation for all variables is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {0,0,0}
+static const char* cmDocumentationOptions[][2] = {
+ { "-G <generator>", "Use the specified generator to generate package." },
+ { "-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 }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationSeeAlso[][3] =
-{
- {0, "cmake", 0},
- {0, "ccmake", 0},
- {0, 0, 0}
-};
-
-//----------------------------------------------------------------------------
-int cpackUnknownArgument(const char*, void*)
+int cpackUnknownArgument(const char* /*unused*/, void* /*unused*/)
{
return 1;
}
-//----------------------------------------------------------------------------
struct cpackDefinitions
{
- typedef std::map<cmStdString, cmStdString> MapType;
+ typedef std::map<std::string, std::string> MapType;
MapType Map;
- cmCPackLog *Log;
+ cmCPackLog* Log;
};
-//----------------------------------------------------------------------------
int cpackDefinitionArgument(const char* argument, const char* cValue,
- void* call_data)
+ void* call_data)
{
(void)argument;
cpackDefinitions* def = static_cast<cpackDefinitions*>(call_data);
std::string value = cValue;
- size_t pos = value.find_first_of("=");
- if ( pos == std::string::npos )
- {
+ size_t pos = value.find_first_of('=');
+ if (pos == std::string::npos) {
cmCPack_Log(def->Log, cmCPackLog::LOG_ERROR,
- "Please specify CPack definitions as: KEY=VALUE" << std::endl);
+ "Please specify CPack definitions as: KEY=VALUE" << std::endl);
return 0;
- }
+ }
std::string key = value.substr(0, pos);
value = value.c_str() + pos + 1;
def->Map[key] = value;
cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG, "Set CPack variable: "
- << key.c_str() << " to \"" << value.c_str() << "\"" << std::endl);
+ << key << " to \"" << value << "\"" << std::endl);
return 1;
}
-
-//----------------------------------------------------------------------------
// this is CPack.
-int main (int argc, char *argv[])
+int main(int argc, char const* const* argv)
{
- cmSystemTools::FindExecutableDirectory(argv[0]);
+#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(argc, argv);
+ argc = args.argc();
+ argv = args.argv();
+
+ cmSystemTools::FindCMakeResources(argv[0]);
cmCPackLog log;
log.SetErrorPrefix("CPack Error: ");
@@ -188,12 +109,12 @@ int main (int argc, char *argv[])
cmSystemTools::EnableMSVCDebugHook();
- if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
- {
+ if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Current working directory cannot be established." << std::endl);
+ "Current working directory cannot be established."
+ << std::endl);
return 1;
- }
+ }
std::string generator;
bool help = false;
@@ -223,9 +144,9 @@ int main (int argc, char *argv[])
// Help arguments
arg.AddArgument("--help", argT::NO_ARGUMENT, &help, "CPack help");
arg.AddArgument("--help-full", argT::SPACE_ARGUMENT, &helpFull,
- "CPack help");
+ "CPack help");
arg.AddArgument("--help-html", argT::SPACE_ARGUMENT, &helpHTML,
- "CPack help");
+ "CPack help");
arg.AddArgument("--help-man", argT::SPACE_ARGUMENT, &helpMAN, "CPack help");
arg.AddArgument("--version", argT::NO_ARGUMENT, &helpVersion, "CPack help");
@@ -233,61 +154,61 @@ int main (int argc, char *argv[])
arg.AddArgument("--verbose", argT::NO_ARGUMENT, &verbose, "-V");
arg.AddArgument("--debug", argT::NO_ARGUMENT, &debug, "-V");
arg.AddArgument("--config", argT::SPACE_ARGUMENT, &cpackConfigFile,
- "CPack configuration file");
+ "CPack configuration file");
arg.AddArgument("-C", argT::SPACE_ARGUMENT, &cpackBuildConfig,
- "CPack build configuration");
- arg.AddArgument("-G", argT::SPACE_ARGUMENT,
- &generator, "CPack generator");
- arg.AddArgument("-P", argT::SPACE_ARGUMENT,
- &cpackProjectName, "CPack project name");
- arg.AddArgument("-R", argT::SPACE_ARGUMENT,
- &cpackProjectVersion, "CPack project version");
- arg.AddArgument("-B", argT::SPACE_ARGUMENT,
- &cpackProjectDirectory, "CPack project directory");
- arg.AddArgument("--patch", argT::SPACE_ARGUMENT,
- &cpackProjectPatch, "CPack project patch");
- arg.AddArgument("--vendor", argT::SPACE_ARGUMENT,
- &cpackProjectVendor, "CPack project vendor");
- arg.AddCallback("-D", argT::SPACE_ARGUMENT,
- cpackDefinitionArgument, &definitions, "CPack Definitions");
+ "CPack build configuration");
+ arg.AddArgument("-G", argT::SPACE_ARGUMENT, &generator, "CPack generator");
+ arg.AddArgument("-P", argT::SPACE_ARGUMENT, &cpackProjectName,
+ "CPack project name");
+ arg.AddArgument("-R", argT::SPACE_ARGUMENT, &cpackProjectVersion,
+ "CPack project version");
+ arg.AddArgument("-B", argT::SPACE_ARGUMENT, &cpackProjectDirectory,
+ "CPack project directory");
+ arg.AddArgument("--patch", argT::SPACE_ARGUMENT, &cpackProjectPatch,
+ "CPack project patch");
+ arg.AddArgument("--vendor", argT::SPACE_ARGUMENT, &cpackProjectVendor,
+ "CPack project vendor");
+ arg.AddCallback("-D", argT::SPACE_ARGUMENT, cpackDefinitionArgument,
+ &definitions, "CPack Definitions");
arg.SetUnknownArgumentCallback(cpackUnknownArgument);
// Parse command line
int parsed = arg.Parse();
// Setup logging
- if ( verbose )
- {
+ if (verbose) {
log.SetVerbose(verbose);
cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose" << std::endl);
- }
- if ( debug )
- {
+ }
+ if (debug) {
log.SetDebug(debug);
cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl);
- }
+ }
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
- "Read CPack config file: " << cpackConfigFile.c_str() << std::endl);
-
- cmake cminst;
- cminst.RemoveUnscriptableCommands();
- cmGlobalGenerator cmgg;
- cmgg.SetCMakeInstance(&cminst);
- cmsys::auto_ptr<cmLocalGenerator> cmlg(cmgg.CreateLocalGenerator());
- cmMakefile* globalMF = cmlg->GetMakefile();
+ "Read CPack config file: " << cpackConfigFile << std::endl);
+
+ cmake cminst(cmake::RoleScript);
+ cminst.SetHomeDirectory("");
+ cminst.SetHomeOutputDirectory("");
+ cminst.GetCurrentSnapshot().SetDefaultDefinitions();
+ cmGlobalGenerator cmgg(&cminst);
+ CM_AUTO_PTR<cmMakefile> globalMF(
+ new cmMakefile(&cmgg, cminst.GetCurrentSnapshot()));
+#if defined(__CYGWIN__)
+ globalMF->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0");
+#endif
bool cpackConfigFileSpecified = true;
- if ( cpackConfigFile.empty() )
- {
+ if (cpackConfigFile.empty()) {
cpackConfigFile = cmSystemTools::GetCurrentWorkingDirectory();
cpackConfigFile += "/CPackConfig.cmake";
cpackConfigFileSpecified = false;
- }
+ }
cmCPackGeneratorFactory generators;
generators.SetLogger(&log);
- cmCPackGenerator* cpackGenerator = 0;
+ cmCPackGenerator* cpackGenerator = CM_NULLPTR;
cmDocumentation doc;
doc.addCPackStandardDocSections();
@@ -296,304 +217,219 @@ int main (int argc, char *argv[])
* should launch cpack using "cpackConfigFile" if it exists
* in the current directory.
*/
- if((doc.CheckOptions(argc, argv,"-G")) && !(argc==1))
- {
- help = true;
- }
- else
- {
- help = false;
- }
+ help = doc.CheckOptions(argc, argv, "-G") && argc != 1;
// This part is used for cpack documentation lookup as well.
cminst.AddCMakePaths();
- if ( parsed && !help )
- {
+ if (parsed && !help) {
// 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(0, systemFile.c_str()))
- {
+ if (!globalMF->ReadListFile(systemFile.c_str())) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Error reading CMakeDetermineSystem.cmake" << std::endl);
+ "Error reading CMakeDetermineSystem.cmake" << std::endl);
return 1;
- }
+ }
systemFile =
globalMF->GetModulesFile("CMakeSystemSpecificInformation.cmake");
- if (!globalMF->ReadListFile(0, systemFile.c_str()))
- {
+ if (!globalMF->ReadListFile(systemFile.c_str())) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Error reading CMakeSystemSpecificInformation.cmake" << std::endl);
+ "Error reading CMakeSystemSpecificInformation.cmake"
+ << std::endl);
return 1;
- }
+ }
- if ( cmSystemTools::FileExists(cpackConfigFile.c_str()) )
- {
- cpackConfigFile =
- cmSystemTools::CollapseFullPath(cpackConfigFile.c_str());
+ if (!cpackBuildConfig.empty()) {
+ globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
+ }
+
+ if (cmSystemTools::FileExists(cpackConfigFile.c_str())) {
+ cpackConfigFile = cmSystemTools::CollapseFullPath(cpackConfigFile);
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
- "Read CPack configuration file: " << cpackConfigFile.c_str()
- << std::endl);
- if ( !globalMF->ReadListFile(0, cpackConfigFile.c_str()) )
- {
+ "Read CPack configuration file: " << cpackConfigFile
+ << std::endl);
+ if (!globalMF->ReadListFile(cpackConfigFile.c_str())) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Problem reading CPack config file: \""
- << cpackConfigFile.c_str() << "\"" << std::endl);
+ "Problem reading CPack config file: \""
+ << cpackConfigFile << "\"" << std::endl);
return 1;
- }
}
- else if ( cpackConfigFileSpecified )
- {
+ } else if (cpackConfigFileSpecified) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Cannot find CPack config file: \"" << cpackConfigFile.c_str()
- << "\"" << std::endl);
+ "Cannot find CPack config file: \"" << cpackConfigFile
+ << "\"" << std::endl);
return 1;
- }
+ }
- if ( !generator.empty() )
- {
+ if (!generator.empty()) {
globalMF->AddDefinition("CPACK_GENERATOR", generator.c_str());
- }
- if ( !cpackProjectName.empty() )
- {
+ }
+ if (!cpackProjectName.empty()) {
globalMF->AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName.c_str());
- }
- if ( !cpackProjectVersion.empty() )
- {
+ }
+ if (!cpackProjectVersion.empty()) {
globalMF->AddDefinition("CPACK_PACKAGE_VERSION",
- cpackProjectVersion.c_str());
- }
- if ( !cpackProjectVendor.empty() )
- {
+ cpackProjectVersion.c_str());
+ }
+ if (!cpackProjectVendor.empty()) {
globalMF->AddDefinition("CPACK_PACKAGE_VENDOR",
- cpackProjectVendor.c_str());
- }
+ cpackProjectVendor.c_str());
+ }
// 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() )
- {
+ if (!cpackProjectDirectory.empty()) {
globalMF->AddDefinition("CPACK_PACKAGE_DIRECTORY",
cpackProjectDirectory.c_str());
- }
+ }
// The value has not been set on the command line
- else
- {
+ 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"))
- {
+ if (!globalMF->IsSet("CPACK_PACKAGE_DIRECTORY")) {
globalMF->AddDefinition("CPACK_PACKAGE_DIRECTORY",
cpackProjectDirectory.c_str());
- }
- }
- if ( !cpackBuildConfig.empty() )
- {
- globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
}
+ }
cpackDefinitions::MapType::iterator cdit;
- for ( cdit = definitions.Map.begin();
- cdit != definitions.Map.end();
- ++cdit )
- {
- globalMF->AddDefinition(cdit->first.c_str(), cdit->second.c_str());
- }
+ for (cdit = definitions.Map.begin(); cdit != definitions.Map.end();
+ ++cdit) {
+ globalMF->AddDefinition(cdit->first, cdit->second.c_str());
+ }
const char* cpackModulesPath =
globalMF->GetDefinition("CPACK_MODULE_PATH");
- if ( cpackModulesPath )
- {
+ if (cpackModulesPath) {
globalMF->AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath);
- }
+ }
const char* genList = globalMF->GetDefinition("CPACK_GENERATOR");
- if ( !genList )
- {
- cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "CPack generator not specified" << std::endl);
- parsed = 0;
- }
- else
- {
+ if (!genList) {
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified"
+ << std::endl);
+ } else {
std::vector<std::string> generatorsVector;
- cmSystemTools::ExpandListArgument(genList,
- generatorsVector);
+ cmSystemTools::ExpandListArgument(genList, generatorsVector);
std::vector<std::string>::iterator it;
- for ( it = generatorsVector.begin();
- it != generatorsVector.end();
- ++it )
- {
+ for (it = generatorsVector.begin(); it != generatorsVector.end(); ++it) {
const char* gen = it->c_str();
- cmMakefile newMF(*globalMF);
- cmMakefile* mf = &newMF;
+ cmMakefile::ScopePushPop raii(globalMF.get());
+ cmMakefile* mf = globalMF.get();
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
- "Specified generator: " << gen << std::endl);
- if ( parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME") )
- {
+ "Specified generator: " << gen << std::endl);
+ if (parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME")) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "CPack project name not specified" << std::endl);
+ "CPack project name not specified" << std::endl);
parsed = 0;
- }
+ }
if (parsed &&
!(mf->GetDefinition("CPACK_PACKAGE_VERSION") ||
(mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR") &&
mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR") &&
- mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH"))))
- {
+ mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")))) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "CPack project version not specified" << std::endl
- << "Specify CPACK_PACKAGE_VERSION, or "
- "CPACK_PACKAGE_VERSION_MAJOR, "
- "CPACK_PACKAGE_VERSION_MINOR, and CPACK_PACKAGE_VERSION_PATCH."
- << std::endl);
+ "CPack project version not specified"
+ << std::endl
+ << "Specify CPACK_PACKAGE_VERSION, or "
+ "CPACK_PACKAGE_VERSION_MAJOR, "
+ "CPACK_PACKAGE_VERSION_MINOR, and "
+ "CPACK_PACKAGE_VERSION_PATCH."
+ << std::endl);
parsed = 0;
- }
- if ( parsed )
- {
+ }
+ if (parsed) {
cpackGenerator = generators.NewGenerator(gen);
- if ( !cpackGenerator )
- {
+ if (!cpackGenerator) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Cannot initialize CPack generator: "
- << gen << std::endl);
+ "Cannot initialize CPack generator: " << gen
+ << std::endl);
parsed = 0;
- }
- if ( parsed && !cpackGenerator->Initialize(gen, mf) )
- {
+ }
+ if (parsed && !cpackGenerator->Initialize(gen, mf)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Cannot initialize the generator " << gen << std::endl);
+ "Cannot initialize the generator " << gen
+ << std::endl);
parsed = 0;
- }
+ }
- if ( !mf->GetDefinition("CPACK_INSTALL_COMMANDS") &&
- !mf->GetDefinition("CPACK_INSTALLED_DIRECTORIES") &&
- !mf->GetDefinition("CPACK_INSTALL_CMAKE_PROJECTS") )
- {
- cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ if (!mf->GetDefinition("CPACK_INSTALL_COMMANDS") &&
+ !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_INSTALLED_DIRECTORIES."
- << std::endl);
+ << std::endl);
parsed = 0;
- }
- if ( parsed )
- {
-#ifdef _WIN32
- std::string comspec = "cmw9xcom.exe";
- cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
-#endif
-
+ }
+ 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, "For project: "
- << projName << std::endl);
+ << cpackGenerator->GetNameOfClass() << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
+ "For project: " << projName << std::endl);
const char* projVersion =
mf->GetDefinition("CPACK_PACKAGE_VERSION");
- if ( !projVersion )
- {
- const char* projVersionMajor
- = mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");
- const char* projVersionMinor
- = mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");
- const char* projVersionPatch
- = mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
- cmOStringStream ostr;
+ if (!projVersion) {
+ const char* projVersionMajor =
+ mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");
+ const char* projVersionMinor =
+ mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");
+ const char* projVersionPatch =
+ mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
+ std::ostringstream ostr;
ostr << projVersionMajor << "." << projVersionMinor << "."
- << projVersionPatch;
- mf->AddDefinition("CPACK_PACKAGE_VERSION",
- ostr.str().c_str());
- }
+ << projVersionPatch;
+ mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str().c_str());
+ }
int res = cpackGenerator->DoPackage();
- if ( !res )
- {
+ if (!res) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Error when generating package: " << projName << std::endl);
+ "Error when generating package: " << projName
+ << std::endl);
return 1;
- }
}
}
}
}
}
+ }
/* In this case we are building the documentation object
* instance in order to create appropriate structure
* in order to satisfy the appropriate --help-xxx request
*/
- if ( help )
- {
+ if (help) {
// Construct and print requested documentation.
doc.SetName("cpack");
- doc.SetSection("Name",cmDocumentationName);
- doc.SetSection("Usage",cmDocumentationUsage);
- doc.SetSection("Description",cmDocumentationDescription);
- doc.PrependSection("Options",cmDocumentationOptions);
-
- // statically (in C++ code) defined variables
- cmCPackDocumentVariables::DefineVariables(&cminst);
-
- std::vector<cmDocumentationEntry> commands;
-
- std::string docedFile;
- std::string docPath;
- cmDocumentation::documentedModulesList_t docedModList;
-
- docedFile = globalMF->GetModulesFile("CPack.cmake");
- if (docedFile.length()!=0)
- {
- docPath = cmSystemTools::GetFilenamePath(docedFile.c_str());
- doc.getDocumentedModulesListInDir(docPath,"CPack*.cmake",docedModList);
- }
-
- // parse the files for documentation.
- cmDocumentation::documentedModulesList_t::iterator docedIt;
- for (docedIt = docedModList.begin();
- docedIt!= docedModList.end(); ++docedIt)
- {
- doc.GetStructuredDocFromFile(
- (docedIt->first).c_str(),
- commands,&cminst);
- }
-
- std::map<std::string,cmDocumentationSection *> propDocs;
- cminst.GetPropertiesDocumentation(propDocs);
- doc.SetSections(propDocs);
- cminst.GetCommandDocumentation(commands,true,false);
- // statically (in C++ code) defined macros/commands
- cmCPackDocumentMacros::GetMacrosDocumentation(commands);
- doc.SetSection("Commands",commands);
+ doc.SetSection("Name", cmDocumentationName);
+ doc.SetSection("Usage", cmDocumentationUsage);
+ doc.PrependSection("Options", cmDocumentationOptions);
std::vector<cmDocumentationEntry> v;
cmCPackGeneratorFactory::DescriptionsMap::const_iterator generatorIt;
- for( generatorIt = generators.GetGeneratorsList().begin();
- generatorIt != generators.GetGeneratorsList().end();
- ++ generatorIt )
- {
+ for (generatorIt = generators.GetGeneratorsList().begin();
+ generatorIt != generators.GetGeneratorsList().end(); ++generatorIt) {
cmDocumentationEntry e;
- e.Name = generatorIt->first.c_str();
- e.Brief = generatorIt->second.c_str();
- e.Full = "";
+ e.Name = generatorIt->first;
+ e.Brief = generatorIt->second;
v.push_back(e);
- }
- doc.SetSection("Generators",v);
-
- doc.SetSeeAlsoList(cmDocumentationSeeAlso);
-#undef cout
- return doc.PrintRequestedDocumentation(std::cout)? 0:1;
-#define cout no_cout_use_cmCPack_Log
}
+ doc.SetSection("Generators", v);
- if (cmSystemTools::GetErrorOccuredFlag())
- {
+ return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
+ }
+
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return 1;
- }
+ }
return 0;
}
diff --git a/Source/CPack/cygwin.readme b/Source/CPack/cygwin.readme
deleted file mode 100644
index c0cd4b913..000000000
--- a/Source/CPack/cygwin.readme
+++ /dev/null
@@ -1,69 +0,0 @@
-http://cygwin.com/setup.html
-
-
-Need to produce two tar files:
-
-Source-
-
-- create subdirs
-- copy src
-- duplicate src
-- configure files into duplicate src
- CPack.cygwin-readme.in
- CPack.cygwin-install.sh.in
- CPack.setup.hint.in
-- diff duplicate src and orig src
-- write diff into toplevel
-- create tar file call super class
-
-cmake-2.2.3-1
-
-
-1. a source release
-cmake-2.2.3-2-src.tar.bz2
-
-cmake-2.2.3-2.patch has cmake-2.2.3/CYGWIN-PATCHES/cmake.README cmake-2.2.3/CYGWIN-PATCHES/setup.hint
-cmake-2.2.3-2.sh -> script to create cygwin release
-cmake-2.2.3.tar.bz2 -> unmodified cmake sources for 2.2.3
-
-
-
-
-
-2 a binary release
-cmake-2.2.3-2.tar.bz2
-
-normal binary release with use as the root of the tree:
-
-Here is the bootstrap command used:
-
- ${SOURCE_DIR}/bootstrap --prefix=/usr --datadir=/share/cmake-${VER} \
- --docdir=/share/doc/cmake-${VER} --mandir=/share/man
-
-CMAKE_DOC_DIR /share/doc/${PKG}-${VER}
-CMAKE_MAN_DIR /share/man
-CMAKE_DATA_DIR /share/${PKG}-${VER}
-
-Here is the directory stucture:
-
-usr/bin/cmake.exe
-usr/share/doc/cmake-2.2.3/MANIFEST ***
-usr/share/doc/Cygwin/cmake-2.2.3-2.README ****
-usr/share/cmake-2.2.3/Modules
-
-
-
-usr/bin
-usr/share/cmake-2.2.3/include
-usr/share/cmake-2.2.3/Modules/Platform
-usr/share/cmake-2.2.3/Modules
-usr/share/cmake-2.2.3/Templates
-usr/share/cmake-2.2.3
-usr/share/doc/cmake-2.2.3
-usr/share/doc/Cygwin
-usr/share/doc
-usr/share/man/man1
-usr/share/man
-usr/share
-usr
-
diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index 381c70ce5..94f39c265 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -1,163 +1,148 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBZR.h"
#include "cmCTest.h"
+#include "cmCTestVC.h"
+#include "cmProcessTools.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmXMLSafe.h"
-
-#include <cmsys/RegularExpression.hxx>
-
-#include <cm_expat.h>
-//----------------------------------------------------------------------------
-extern "C"
-int cmBZRXMLParserUnknownEncodingHandler(void*,
- const XML_Char *name,
- XML_Encoding *info)
+#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)
{
- static const int latin1[]=
- {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
- 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
- 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F,
- 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
- 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178,
- 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
- 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
- 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
- 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
- 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
- 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
- 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
- 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
- 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
- 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
- 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
- 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
- };
+ static const int latin1[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
+ 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A,
+ 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C,
+ 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
+ 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
+ 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
+ 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D,
+ 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020,
+ 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F,
+ 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
+ 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, 0x00A0, 0x00A1,
+ 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA,
+ 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
+ 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC,
+ 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5,
+ 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE,
+ 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
+ 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9,
+ 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2,
+ 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
+ 0x00FC, 0x00FD, 0x00FE, 0x00FF
+ };
// The BZR xml output plugin can use some encodings that are not
// recognized by expat. This will lead to an error, e.g. "Error
// parsing bzr log xml: unknown encoding", the following is a
// workaround for these unknown encodings.
- if(name == std::string("ascii") || name == std::string("cp1252") ||
- name == std::string("ANSI_X3.4-1968"))
- {
- for(unsigned int i=0;i<256;++i) info->map[i] = latin1[i];
- return 1;
+ if (name == std::string("ascii") || name == std::string("cp1252") ||
+ name == std::string("ANSI_X3.4-1968")) {
+ for (unsigned int i = 0; i < 256; ++i) {
+ info->map[i] = latin1[i];
}
+ return 1;
+ }
return 0;
}
-//----------------------------------------------------------------------------
-cmCTestBZR::cmCTestBZR(cmCTest* ct, std::ostream& log):
- cmCTestGlobalVC(ct, log)
+cmCTestBZR::cmCTestBZR(cmCTest* ct, std::ostream& log)
+ : cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
- // Even though it is specified in the documention, with bzr 1.13
+ // Even though it is specified in the documentation, with bzr 1.13
// BZR_PROGRESS_BAR has no effect. In the future this bug might be fixed.
// Since it doesn't hurt, we specify this environment variable.
cmSystemTools::PutEnv("BZR_PROGRESS_BAR=none");
}
-//----------------------------------------------------------------------------
cmCTestBZR::~cmCTestBZR()
{
}
-//----------------------------------------------------------------------------
-class cmCTestBZR::InfoParser: public cmCTestVC::LineParser
+class cmCTestBZR::InfoParser : public cmCTestVC::LineParser
{
public:
- InfoParser(cmCTestBZR* bzr, const char* prefix):
- BZR(bzr), CheckOutFound(false)
- {
+ InfoParser(cmCTestBZR* bzr, const char* prefix)
+ : BZR(bzr)
+ , CheckOutFound(false)
+ {
this->SetLog(&bzr->Log, prefix);
this->RegexCheckOut.compile("checkout of branch: *([^\t\r\n]+)$");
this->RegexParent.compile("parent branch: *([^\t\r\n]+)$");
- }
+ }
+
private:
cmCTestBZR* BZR;
bool CheckOutFound;
cmsys::RegularExpression RegexCheckOut;
cmsys::RegularExpression RegexParent;
- virtual bool ProcessLine()
- {
- if(this->RegexCheckOut.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexCheckOut.find(this->Line)) {
this->BZR->URL = this->RegexCheckOut.match(1);
CheckOutFound = true;
- }
- else if(!CheckOutFound && this->RegexParent.find(this->Line))
- {
+ } else if (!CheckOutFound && this->RegexParent.find(this->Line)) {
this->BZR->URL = this->RegexParent.match(1);
- }
- return true;
}
+ return true;
+ }
};
-//----------------------------------------------------------------------------
-class cmCTestBZR::RevnoParser: public cmCTestVC::LineParser
+class cmCTestBZR::RevnoParser : public cmCTestVC::LineParser
{
public:
- RevnoParser(cmCTestBZR* bzr, const char* prefix, std::string& rev):
- Rev(rev)
- {
+ RevnoParser(cmCTestBZR* bzr, const char* prefix, std::string& rev)
+ : Rev(rev)
+ {
this->SetLog(&bzr->Log, prefix);
this->RegexRevno.compile("^([0-9]+)$");
- }
+ }
+
private:
std::string& Rev;
cmsys::RegularExpression RegexRevno;
- virtual bool ProcessLine()
- {
- if(this->RegexRevno.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexRevno.find(this->Line)) {
this->Rev = this->RegexRevno.match(1);
- }
- return true;
}
+ return true;
+ }
};
-//----------------------------------------------------------------------------
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", 0};
+ const char* bzr_info[] = { bzr, "info", CM_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", 0};
+ const char* bzr_revno[] = { bzr, "revno", CM_NULLPTR };
std::string rev;
RevnoParser rout(this, "revno-out> ", rev);
OutputLogger rerr(this->Log, "revno-err> ");
@@ -166,51 +151,55 @@ std::string cmCTestBZR::LoadInfo()
return rev;
}
-void cmCTestBZR::NoteOldRevision()
+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");
+ << this->OldRevision << "\n");
this->PriorRev.Rev = this->OldRevision;
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestBZR::NoteNewRevision()
+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");
+ << 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):
- OutputLogger(bzr->Log, prefix), BZR(bzr),
- EmailRegex("(.*) <([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+)>")
- { this->InitializeParser(); }
- ~LogParser() { this->CleanupParser(); }
-
- virtual int InitializeParser()
- {
- int res = cmXMLParser::InitializeParser();
- if (res)
- {
- XML_SetUnknownEncodingHandler(static_cast<XML_Parser>(this->Parser),
- cmBZRXMLParserUnknownEncodingHandler, 0);
- }
- return res;
- }
+ LogParser(cmCTestBZR* bzr, const char* prefix)
+ : OutputLogger(bzr->Log, prefix)
+ , BZR(bzr)
+ , EmailRegex("(.*) <([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+)>")
+ {
+ this->InitializeParser();
+ }
+ ~LogParser() CM_OVERRIDE { this->CleanupParser(); }
+
+ int InitializeParser() CM_OVERRIDE
+ {
+ int res = cmXMLParser::InitializeParser();
+ if (res) {
+ XML_SetUnknownEncodingHandler(static_cast<XML_Parser>(this->Parser),
+ cmBZRXMLParserUnknownEncodingHandler,
+ CM_NULLPTR);
+ }
+ return res;
+ }
+
private:
cmCTestBZR* BZR;
typedef cmCTestBZR::Revision Revision;
- typedef cmCTestBZR::Change Change;
+ typedef cmCTestBZR::Change Change;
Revision Rev;
std::vector<Change> Changes;
Change CurChange;
@@ -218,198 +207,164 @@ private:
cmsys::RegularExpression EmailRegex;
- virtual bool ProcessChunk(const char* data, int length)
- {
+ bool ProcessChunk(const char* data, int length) CM_OVERRIDE
+ {
this->OutputLogger::ProcessChunk(data, length);
this->ParseChunk(data, length);
return true;
- }
+ }
- virtual void StartElement(const char* name, const char**)
- {
+ void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
+ {
this->CData.clear();
- if(strcmp(name, "log") == 0)
- {
+ if (name == "log") {
this->Rev = Revision();
this->Changes.clear();
- }
+ }
// affected-files can contain blocks of
// modified, unknown, renamed, kind-changed, removed, conflicts, added
- else if(strcmp(name, "modified") == 0
- || strcmp(name, "renamed") == 0
- || strcmp(name, "kind-changed") == 0)
- {
+ else if (name == "modified" || name == "renamed" ||
+ name == "kind-changed") {
this->CurChange = Change();
this->CurChange.Action = 'M';
- }
- else if(strcmp(name, "added") == 0)
- {
+ } else if (name == "added") {
this->CurChange = Change();
this->CurChange = 'A';
- }
- else if(strcmp(name, "removed") == 0)
- {
+ } else if (name == "removed") {
this->CurChange = Change();
this->CurChange = 'D';
- }
- else if(strcmp(name, "unknown") == 0
- || strcmp(name, "conflicts") == 0)
- {
+ } else if (name == "unknown" || name == "conflicts") {
// Should not happen here
this->CurChange = Change();
- }
}
+ }
- virtual void CharacterDataHandler(const char* data, int length)
- {
- this->CData.insert(this->CData.end(), data, data+length);
- }
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ this->CData.insert(this->CData.end(), data, data + length);
+ }
- virtual void EndElement(const char* name)
- {
- if(strcmp(name, "log") == 0)
- {
+ void EndElement(const std::string& name) CM_OVERRIDE
+ {
+ if (name == "log") {
this->BZR->DoRevision(this->Rev, this->Changes);
- }
- else if((strcmp(name, "file") == 0 || strcmp(name, "directory") == 0)
- && !this->CData.empty())
- {
+ } else if (!this->CData.empty() &&
+ (name == "file" || name == "directory")) {
this->CurChange.Path.assign(&this->CData[0], this->CData.size());
cmSystemTools::ConvertToUnixSlashes(this->CurChange.Path);
this->Changes.push_back(this->CurChange);
- }
- else if(strcmp(name, "symlink") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "symlink") {
// symlinks have an arobase at the end in the log
- this->CurChange.Path.assign(&this->CData[0], this->CData.size()-1);
+ this->CurChange.Path.assign(&this->CData[0], this->CData.size() - 1);
cmSystemTools::ConvertToUnixSlashes(this->CurChange.Path);
this->Changes.push_back(this->CurChange);
- }
- else if(strcmp(name, "committer") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "committer") {
this->Rev.Author.assign(&this->CData[0], this->CData.size());
- if(this->EmailRegex.find(this->Rev.Author))
- {
+ if (this->EmailRegex.find(this->Rev.Author)) {
this->Rev.Author = this->EmailRegex.match(1);
this->Rev.EMail = this->EmailRegex.match(2);
- }
}
- else if(strcmp(name, "timestamp") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "timestamp") {
this->Rev.Date.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "message") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "message") {
this->Rev.Log.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "revno") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "revno") {
this->Rev.Rev.assign(&this->CData[0], this->CData.size());
- }
- this->CData.clear();
}
+ this->CData.clear();
+ }
- virtual void ReportError(int, int, const char* msg)
- {
+ void ReportError(int /*line*/, int /*column*/, const char* msg) CM_OVERRIDE
+ {
this->BZR->Log << "Error parsing bzr log xml: " << msg << "\n";
- }
+ }
};
-//----------------------------------------------------------------------------
-class cmCTestBZR::UpdateParser: public cmCTestVC::LineParser
+class cmCTestBZR::UpdateParser : public cmCTestVC::LineParser
{
public:
- UpdateParser(cmCTestBZR* bzr, const char* prefix): BZR(bzr)
- {
+ UpdateParser(cmCTestBZR* bzr, const char* prefix)
+ : BZR(bzr)
+ {
this->SetLog(&bzr->Log, prefix);
this->RegexUpdate.compile("^([-+R?XCP ])([NDKM ])([* ]) +(.+)$");
- }
+ }
+
private:
cmCTestBZR* BZR;
cmsys::RegularExpression RegexUpdate;
- virtual bool ProcessChunk(const char* first, int length)
- {
+ bool ProcessChunk(const char* first, int length) CM_OVERRIDE
+ {
bool last_is_new_line = (*first == '\r' || *first == '\n');
const char* const last = first + length;
- for(const char* c = first; c != last; ++c)
- {
- if(*c == '\r' || *c == '\n')
- {
- if(!last_is_new_line)
- {
+ for (const char* c = first; c != last; ++c) {
+ if (*c == '\r' || *c == '\n') {
+ if (!last_is_new_line) {
// Log this line.
- if(this->Log && this->Prefix)
- {
+ if (this->Log && this->Prefix) {
*this->Log << this->Prefix << this->Line << "\n";
- }
+ }
// Hand this line to the subclass implementation.
- if(!this->ProcessLine())
- {
+ if (!this->ProcessLine()) {
this->Line = "";
return false;
- }
+ }
this->Line = "";
last_is_new_line = true;
- }
}
- else
- {
+ } else {
// Append this character to the line under construction.
this->Line.append(1, *c);
last_is_new_line = false;
- }
}
- return true;
}
+ return true;
+ }
- bool ProcessLine()
- {
- if(this->RegexUpdate.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexUpdate.find(this->Line)) {
this->DoPath(this->RegexUpdate.match(1)[0],
this->RegexUpdate.match(2)[0],
- this->RegexUpdate.match(3)[0],
- this->RegexUpdate.match(4));
- }
- return true;
+ this->RegexUpdate.match(3)[0], this->RegexUpdate.match(4));
}
+ return true;
+ }
void DoPath(char c0, char c1, char c2, std::string path)
- {
- if(path.empty()) return;
+ {
+ if (path.empty()) {
+ return;
+ }
cmSystemTools::ConvertToUnixSlashes(path);
const std::string dir = cmSystemTools::GetFilenamePath(path);
const std::string name = cmSystemTools::GetFilenameName(path);
- if ( c0=='C' )
- {
+ if (c0 == 'C') {
this->BZR->Dirs[dir][name].Status = PathConflicting;
return;
- }
+ }
- if ( c1=='M' || c1=='K' || c1=='N' || c1=='D' || c2 =='*' )
- {
+ if (c1 == 'M' || c1 == 'K' || c1 == 'N' || c1 == 'D' || c2 == '*') {
this->BZR->Dirs[dir][name].Status = PathUpdated;
return;
- }
}
+ }
};
-//----------------------------------------------------------------------------
bool cmCTestBZR::UpdateImpl()
{
// Get user-specified update options.
std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
- if(opts.empty())
- {
+ if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("BZRUpdateOptions");
- }
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(opts.c_str());
+ }
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
// TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
@@ -418,15 +373,14 @@ bool cmCTestBZR::UpdateImpl()
bzr_update.push_back(this->CommandLineTool.c_str());
bzr_update.push_back("pull");
- for(std::vector<cmStdString>::const_iterator ai = args.begin();
- ai != args.end(); ++ai)
- {
+ for (std::vector<std::string>::const_iterator ai = args.begin();
+ ai != args.end(); ++ai) {
bzr_update.push_back(ai->c_str());
- }
+ }
bzr_update.push_back(this->URL.c_str());
- bzr_update.push_back(0);
+ bzr_update.push_back(CM_NULLPTR);
// For some reason bzr uses stderr to display the update status.
OutputLogger out(this->Log, "pull-out> ");
@@ -434,90 +388,88 @@ bool cmCTestBZR::UpdateImpl()
return this->RunUpdateCommand(&bzr_update[0], &out, &err);
}
-//----------------------------------------------------------------------------
-void cmCTestBZR::LoadRevisions()
+bool cmCTestBZR::LoadRevisions()
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n"
- " " << std::flush);
+ " "
+ << std::flush);
// We are interested in every revision included in the update.
this->Revisions.clear();
std::string revs;
- if(atoi(this->OldRevision.c_str()) <= atoi(this->NewRevision.c_str()))
- {
+ if (atoi(this->OldRevision.c_str()) <= atoi(this->NewRevision.c_str())) {
// DoRevision takes care of discarding the information about OldRevision
revs = this->OldRevision + ".." + this->NewRevision;
- }
- else
- {
- return;
- }
+ } else {
+ return true;
+ }
// 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(), 0};
+ const char* bzr_log[] = {
+ bzr, "log", "-v", "-r", revs.c_str(), "--xml", this->URL.c_str(),
+ CM_NULLPTR
+ };
{
- LogParser out(this, "log-out> ");
- OutputLogger err(this->Log, "log-err> ");
- this->RunChild(bzr_log, &out, &err);
+ LogParser out(this, "log-out> ");
+ OutputLogger err(this->Log, "log-err> ");
+ this->RunChild(bzr_log, &out, &err);
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
+ return true;
}
-//----------------------------------------------------------------------------
-class cmCTestBZR::StatusParser: public cmCTestVC::LineParser
+class cmCTestBZR::StatusParser : public cmCTestVC::LineParser
{
public:
- StatusParser(cmCTestBZR* bzr, const char* prefix): BZR(bzr)
- {
+ StatusParser(cmCTestBZR* bzr, const char* prefix)
+ : BZR(bzr)
+ {
this->SetLog(&bzr->Log, prefix);
this->RegexStatus.compile("^([-+R?XCP ])([NDKM ])([* ]) +(.+)$");
- }
+ }
+
private:
cmCTestBZR* BZR;
cmsys::RegularExpression RegexStatus;
- bool ProcessLine()
- {
- if(this->RegexStatus.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexStatus.find(this->Line)) {
this->DoPath(this->RegexStatus.match(1)[0],
this->RegexStatus.match(2)[0],
- this->RegexStatus.match(3)[0],
- this->RegexStatus.match(4));
- }
- return true;
+ this->RegexStatus.match(3)[0], this->RegexStatus.match(4));
}
+ return true;
+ }
void DoPath(char c0, char c1, char c2, std::string path)
- {
- if(path.empty()) return;
+ {
+ if (path.empty()) {
+ return;
+ }
cmSystemTools::ConvertToUnixSlashes(path);
- if ( c0=='C' )
- {
+ if (c0 == 'C') {
this->BZR->DoModification(PathConflicting, path);
return;
- }
+ }
- if ( c0 == '+' || c0 == 'R' || c0 == 'P'
- || c1=='M' || c1=='K' || c1=='N' || c1=='D'
- || c2 =='*' )
- {
+ if (c0 == '+' || c0 == 'R' || c0 == 'P' || c1 == 'M' || c1 == 'K' ||
+ c1 == 'N' || c1 == 'D' || c2 == '*') {
this->BZR->DoModification(PathModified, path);
return;
- }
}
+ }
};
-//----------------------------------------------------------------------------
-void cmCTestBZR::LoadModifications()
+bool cmCTestBZR::LoadModifications()
{
// Run "bzr status" which reports local modifications.
const char* bzr = this->CommandLineTool.c_str();
- const char* bzr_status[] = {bzr, "status", "-SV", 0};
+ const char* bzr_status[] = { bzr, "status", "-SV", CM_NULLPTR };
StatusParser out(this, "status-out> ");
OutputLogger err(this->Log, "status-err> ");
this->RunChild(bzr_status, &out, &err);
+ return true;
}
diff --git a/Source/CTest/cmCTestBZR.h b/Source/CTest/cmCTestBZR.h
index df688e1ee..2e8e88f95 100644
--- a/Source/CTest/cmCTestBZR.h
+++ b/Source/CTest/cmCTestBZR.h
@@ -1,53 +1,52 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestBZR_h
#define cmCTestBZR_h
+#include "cmConfigure.h"
+
#include "cmCTestGlobalVC.h"
+#include <iosfwd>
+#include <string>
+
+class cmCTest;
+
/** \class cmCTestBZR
* \brief Interaction with bzr command-line tool
*
*/
-class cmCTestBZR: public cmCTestGlobalVC
+class cmCTestBZR : public cmCTestGlobalVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestBZR(cmCTest* ctest, std::ostream& log);
- virtual ~cmCTestBZR();
+ ~cmCTestBZR() CM_OVERRIDE;
private:
// Implement cmCTestVC internal API.
- virtual void NoteOldRevision();
- virtual void NoteNewRevision();
- virtual bool UpdateImpl();
+ bool NoteOldRevision() CM_OVERRIDE;
+ bool NoteNewRevision() CM_OVERRIDE;
+ bool UpdateImpl() CM_OVERRIDE;
// URL of repository directory checked out in the working tree.
std::string URL;
std::string LoadInfo();
- void LoadModifications();
- void LoadRevisions();
+ bool LoadModifications() CM_OVERRIDE;
+ bool LoadRevisions() CM_OVERRIDE;
// Parsing helper classes.
class InfoParser;
- class RevnoParser;
class LogParser;
- class UpdateParser;
+ class RevnoParser;
class StatusParser;
+ class UpdateParser;
+
friend class InfoParser;
- friend class RevnoParser;
friend class LogParser;
+ friend class RevnoParser;
friend class UpdateParser;
friend class StatusParser;
};
diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx
index 934481b88..beee53a13 100644
--- a/Source/CTest/cmCTestBatchTestHandler.cxx
+++ b/Source/CTest/cmCTestBatchTestHandler.cxx
@@ -1,64 +1,55 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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 "cmProcess.h"
-#include "cmStandardIncludes.h"
+
#include "cmCTest.h"
+#include "cmCTestMultiProcessHandler.h"
+#include "cmCTestTestHandler.h"
+#include "cmProcess.h"
#include "cmSystemTools.h"
-#include <stdlib.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";
- std::fstream fout;
- fout.open(this->Script.c_str(), std::ios::out);
+ 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)
- {
+ 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::fstream& fout)
+void cmCTestBatchTestHandler::WriteSrunArgs(int test, std::ostream& fout)
{
cmCTestTestHandler::cmCTestTestProperties* properties =
- this->Properties[test];
+ this->Properties[test];
fout << "srun ";
- //fout << "--jobid=" << test << " ";
+ // fout << "--jobid=" << test << " ";
fout << "-J=" << properties->Name << " ";
- //Write dependency information
- /*if(this->Tests[test].size() > 0)
+ // Write dependency information
+ /*if(!this->Tests[test].empty())
{
fout << "-P=afterany";
for(TestSet::iterator i = this->Tests[test].begin();
@@ -68,18 +59,15 @@ void cmCTestBatchTestHandler::WriteSrunArgs(int test, std::fstream& fout)
}
fout << " ";
}*/
- if(properties->RunSerial)
- {
+ if (properties->RunSerial) {
fout << "--exclusive ";
- }
- if(properties->Processors > 1)
- {
+ }
+ if (properties->Processors > 1) {
fout << "-n" << properties->Processors << " ";
- }
+ }
}
-//---------------------------------------------------------
-void cmCTestBatchTestHandler::WriteTestCommand(int test, std::fstream& fout)
+void cmCTestBatchTestHandler::WriteTestCommand(int test, std::ostream& fout)
{
std::vector<std::string> args = this->Properties[test]->Args;
std::vector<std::string> processArgs;
@@ -88,47 +76,41 @@ void cmCTestBatchTestHandler::WriteTestCommand(int test, std::fstream& fout)
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
+ // 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)
- {
+ 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)
- {
+ ++i; // the test name
+ ++i; // the executable (command)
+ if (args.size() > 2) {
fout << "'";
- }
- while(i != args.end())
- {
- fout << "\"" << *i << "\""; //args to the test executable
+ }
+ while (i != args.end()) {
+ fout << "\"" << *i << "\""; // args to the test executable
++i;
- if(i == args.end() && args.size() > 2)
- {
+ if (i == args.end() && args.size() > 2) {
fout << "'";
- }
- fout << " ";
}
- //TODO ZACH build TestResult.FullCommandLine
- //this->TestResult.FullCommandLine = this->TestCommand;
+ 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");
+ args.push_back(this->CTest->GetBinaryDir() + "/Testing/CTestBatch.txt");
sbatch.SetCommand("sbatch");
sbatch.SetCommandArguments(args);
diff --git a/Source/CTest/cmCTestBatchTestHandler.h b/Source/CTest/cmCTestBatchTestHandler.h
index ab0d081ae..4a5dac1d6 100644
--- a/Source/CTest/cmCTestBatchTestHandler.h
+++ b/Source/CTest/cmCTestBatchTestHandler.h
@@ -1,22 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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 <cmStandardIncludes.h>
-#include <cmCTestTestHandler.h>
-#include <cmCTestMultiProcessHandler.h>
-#include <cmCTestRunTest.h>
+#include "cmConfigure.h"
+
+#include "cmCTestMultiProcessHandler.h"
+#include "cmsys/FStream.hxx"
+#include <string>
/** \class cmCTestBatchTestHandler
* \brief run parallel ctest
@@ -26,12 +17,13 @@
class cmCTestBatchTestHandler : public cmCTestMultiProcessHandler
{
public:
- ~cmCTestBatchTestHandler();
- virtual void RunTests();
+ ~cmCTestBatchTestHandler() CM_OVERRIDE;
+ void RunTests() CM_OVERRIDE;
+
protected:
void WriteBatchScript();
- void WriteSrunArgs(int test, std::fstream& fout);
- void WriteTestCommand(int test, std::fstream& fout);
+ void WriteSrunArgs(int test, std::ostream& fout);
+ void WriteTestCommand(int test, std::ostream& fout);
void SubmitBatchScript();
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 4fa3c53b9..cc290715c 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -1,47 +1,35 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBuildAndTestHandler.h"
-#include "cmSystemTools.h"
#include "cmCTest.h"
-#include "cmake.h"
-#include "cmGlobalGenerator.h"
-#include <cmsys/Process.h>
#include "cmCTestTestHandler.h"
+#include "cmGlobalGenerator.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->BuildTwoConfig = false;
+ this->BuildNoClean = false;
+ this->BuildNoCMake = false;
this->Timeout = 0;
}
-//----------------------------------------------------------------------
void cmCTestBuildAndTestHandler::Initialize()
{
- this->BuildTargets.erase(
- this->BuildTargets.begin(), this->BuildTargets.end());
+ this->BuildTargets.clear();
this->Superclass::Initialize();
}
-//----------------------------------------------------------------------
const char* cmCTestBuildAndTestHandler::GetOutput()
{
return this->Output.c_str();
}
-//----------------------------------------------------------------------
int cmCTestBuildAndTestHandler::ProcessHandler()
{
this->Output = "";
@@ -52,271 +40,235 @@ int cmCTestBuildAndTestHandler::ProcessHandler()
return retv;
}
-//----------------------------------------------------------------------
int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
- cmOStringStream &out, std::string &cmakeOutString, std::string &cwd,
- cmake *cm)
+ std::ostringstream& out,
+ std::string& cmakeOutString,
+ cmake* cm)
{
unsigned int k;
std::vector<std::string> args;
- args.push_back(this->CTest->GetCMakeExecutable());
+ args.push_back(cmSystemTools::GetCMakeCommand());
args.push_back(this->SourceDir);
- if(this->BuildGenerator.size())
- {
+ if (!this->BuildGenerator.empty()) {
std::string generator = "-G";
generator += this->BuildGenerator;
args.push_back(generator);
- }
- if(this->BuildGeneratorToolset.size())
- {
+ }
+ if (!this->BuildGeneratorPlatform.empty()) {
+ std::string platform = "-A";
+ platform += this->BuildGeneratorPlatform;
+ args.push_back(platform);
+ }
+ if (!this->BuildGeneratorToolset.empty()) {
std::string toolset = "-T";
toolset += this->BuildGeneratorToolset;
args.push_back(toolset);
- }
+ }
- const char* config = 0;
- if ( this->CTest->GetConfigType().size() > 0 )
- {
+ const char* config = CM_NULLPTR;
+ if (!this->CTest->GetConfigType().empty()) {
config = this->CTest->GetConfigType().c_str();
- }
+ }
#ifdef CMAKE_INTDIR
- if(!config)
- {
+ if (!config) {
config = CMAKE_INTDIR;
- }
+ }
#endif
- if ( config )
- {
- std::string btype
- = "-DCMAKE_BUILD_TYPE:STRING=" + std::string(config);
+ if (config) {
+ std::string btype = "-DCMAKE_BUILD_TYPE:STRING=" + std::string(config);
args.push_back(btype);
- }
+ }
- for(k=0; k < this->BuildOptions.size(); ++k)
- {
+ for (k = 0; k < this->BuildOptions.size(); ++k) {
args.push_back(this->BuildOptions[k]);
- }
- if (cm->Run(args) != 0)
- {
+ }
+ if (cm->Run(args) != 0) {
out << "Error: cmake execution failed\n";
out << cmakeOutString << "\n";
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
- if(outstring)
- {
+ if (outstring) {
*outstring = out.str();
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE, out.str() << std::endl);
- }
- return 1;
}
+ return 1;
+ }
// do another config?
- if(this->BuildTwoConfig)
- {
- if (cm->Run(args) != 0)
- {
+ if (this->BuildTwoConfig) {
+ if (cm->Run(args) != 0) {
out << "Error: cmake execution failed\n";
out << cmakeOutString << "\n";
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
- if(outstring)
- {
+ if (outstring) {
*outstring = out.str();
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE, out.str() << std::endl);
- }
- return 1;
}
+ return 1;
}
+ }
out << "======== CMake output ======\n";
out << cmakeOutString;
out << "======== End CMake output ======\n";
return 0;
}
-//----------------------------------------------------------------------
-void CMakeMessageCallback(const char* m, const char*, bool&, void* s)
+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 , void * s)
+void CMakeProgressCallback(const char* msg, float /*unused*/, void* s)
{
std::string* out = (std::string*)s;
*out += msg;
*out += "\n";
}
-//----------------------------------------------------------------------
-void CMakeStdoutCallback(const char* m, int len, void* s)
+void CMakeOutputCallback(const char* m, size_t len, void* s)
{
std::string* out = (std::string*)s;
out->append(m, len);
}
-struct cmSetupOutputCaptureCleanup
+
+class cmCTestBuildAndTestCaptureRAII
{
- ~cmSetupOutputCaptureCleanup()
+ cmake& CM;
+
+public:
+ cmCTestBuildAndTestCaptureRAII(cmake& cm, std::string& s)
+ : CM(cm)
{
- cmSystemTools::SetErrorCallback(0, 0);
- cmSystemTools::SetStdoutCallback(0, 0);
+ cmSystemTools::SetMessageCallback(CMakeMessageCallback, &s);
+ cmSystemTools::SetStdoutCallback(CMakeOutputCallback, &s);
+ cmSystemTools::SetStderrCallback(CMakeOutputCallback, &s);
+ this->CM.SetProgressCallback(CMakeProgressCallback, &s);
+ }
+ ~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);
}
};
-//----------------------------------------------------------------------
int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
{
- unsigned int k;
- std::string cmakeOutString;
- cmSystemTools::SetErrorCallback(CMakeMessageCallback, &cmakeOutString);
- cmSystemTools::SetStdoutCallback(CMakeStdoutCallback, &cmakeOutString);
- // make sure SetStdoutCallback and SetErrorCallback are set to null
- // after this function exits so that they do not point at a destroyed
- // string cmakeOutString
- cmSetupOutputCaptureCleanup cleanup;
- static_cast<void>(cleanup);
- cmOStringStream out;
-
// if the generator and make program are not specified then it is an error
- if (!this->BuildGenerator.size() || !this->BuildMakeProgram.size())
- {
- if(outstring)
- {
- *outstring =
- "--build-and-test requires that both the generator and makeprogram "
- "be provided using the --build-generator and --build-makeprogram "
- "command line options. ";
- }
- return 1;
+ if (this->BuildGenerator.empty()) {
+ if (outstring) {
+ *outstring = "--build-and-test requires that the generator "
+ "be provided using the --build-generator "
+ "command line option. ";
}
+ return 1;
+ }
- if ( this->CTest->GetConfigType().size() == 0 &&
- this->ConfigSample.size())
- {
+ cmake cm(cmake::RoleProject);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ std::string cmakeOutString;
+ cmCTestBuildAndTestCaptureRAII captureRAII(cm, cmakeOutString);
+ static_cast<void>(captureRAII);
+ std::ostringstream out;
+
+ if (this->CTest->GetConfigType().empty() && !this->ConfigSample.empty()) {
// use the config sample to set the ConfigType
std::string fullPath;
std::string resultingConfig;
std::vector<std::string> extraPaths;
std::vector<std::string> failed;
- fullPath =
- cmCTestTestHandler::FindExecutable(this->CTest,
- this->ConfigSample.c_str(),
- resultingConfig,
- extraPaths,
- failed);
- if (fullPath.size() && resultingConfig.size())
- {
+ fullPath = cmCTestTestHandler::FindExecutable(
+ this->CTest, this->ConfigSample.c_str(), resultingConfig, extraPaths,
+ failed);
+ if (!fullPath.empty() && !resultingConfig.empty()) {
this->CTest->SetConfigType(resultingConfig.c_str());
- }
- out << "Using config sample with results: "
- << fullPath << " and " << resultingConfig << std::endl;
}
+ out << "Using config sample with results: " << fullPath << " and "
+ << resultingConfig << std::endl;
+ }
// we need to honor the timeout specified, the timeout include cmake, build
// and test time
double clock_start = cmSystemTools::GetTime();
// make sure the binary dir is there
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- out << "Internal cmake changing into directory: "
- << this->BinaryDir << std::endl;
- if (!cmSystemTools::FileIsDirectory(this->BinaryDir.c_str()))
- {
+ out << "Internal cmake changing into directory: " << this->BinaryDir
+ << std::endl;
+ if (!cmSystemTools::FileIsDirectory(this->BinaryDir)) {
cmSystemTools::MakeDirectory(this->BinaryDir.c_str());
- }
- cmSystemTools::ChangeDirectory(this->BinaryDir.c_str());
-
- // should we cmake?
- cmake cm;
- cm.SetProgressCallback(CMakeProgressCallback, &cmakeOutString);
+ }
+ cmWorkingDirectory workdir(this->BinaryDir);
- if(this->BuildNoCMake)
- {
- cm.SetGlobalGenerator(cm.CreateGlobalGenerator(
- this->BuildGenerator.c_str()));
+ 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);
- }
- else
- {
+
+ // Load the cache to make CMAKE_MAKE_PROGRAM available.
+ cm.LoadCache(this->BinaryDir);
+ } else {
// do the cmake step, no timeout here since it is not a sub process
- if (this->RunCMake(outstring,out,cmakeOutString,cwd,&cm))
- {
+ if (this->RunCMake(outstring, out, cmakeOutString, &cm)) {
return 1;
- }
}
+ }
// do the build
std::vector<std::string>::iterator tarIt;
- if ( this->BuildTargets.size() == 0 )
- {
+ if (this->BuildTargets.empty()) {
this->BuildTargets.push_back("");
- }
- for ( tarIt = this->BuildTargets.begin();
- tarIt != this->BuildTargets.end(); ++ tarIt )
- {
+ }
+ for (tarIt = this->BuildTargets.begin(); tarIt != this->BuildTargets.end();
+ ++tarIt) {
double remainingTime = 0;
- if (this->Timeout > 0)
- {
+ if (this->Timeout > 0) {
remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
- if (remainingTime <= 0)
- {
- if(outstring)
- {
+ if (remainingTime <= 0) {
+ if (outstring) {
*outstring = "--build-and-test timeout exceeded. ";
- }
- return 1;
}
+ return 1;
}
+ }
std::string output;
- const char* config = 0;
- if ( this->CTest->GetConfigType().size() > 0 )
- {
+ const char* config = CM_NULLPTR;
+ if (!this->CTest->GetConfigType().empty()) {
config = this->CTest->GetConfigType().c_str();
- }
+ }
#ifdef CMAKE_INTDIR
- if(!config)
- {
+ if (!config) {
config = CMAKE_INTDIR;
- }
+ }
#endif
- if(!config)
- {
+ if (!config) {
config = "Debug";
- }
+ }
int retVal = cm.GetGlobalGenerator()->Build(
- this->SourceDir.c_str(), this->BinaryDir.c_str(),
- this->BuildProject.c_str(), tarIt->c_str(),
- &output, this->BuildMakeProgram.c_str(),
- config,
- !this->BuildNoClean,
- false, remainingTime);
+ this->SourceDir, this->BinaryDir, this->BuildProject, *tarIt, output,
+ this->BuildMakeProgram, config, !this->BuildNoClean, false, false,
+ remainingTime);
out << output;
// if the build failed then return
- if (retVal)
- {
- if(outstring)
- {
- *outstring = out.str();
- }
- return 1;
+ if (retVal) {
+ if (outstring) {
+ *outstring = out.str();
}
+ return 1;
}
- if(outstring)
- {
- *outstring = out.str();
- }
+ }
+ if (outstring) {
+ *outstring = out.str();
+ }
// if no test was specified then we are done
- if (!this->TestCommand.size())
- {
+ if (this->TestCommand.empty()) {
return 0;
- }
+ }
// now run the compiled test if we can find it
// store the final location in fullPath
@@ -324,219 +276,169 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
std::string resultingConfig;
std::vector<std::string> extraPaths;
// if this->ExecutableDirectory is set try that as well
- if (this->ExecutableDirectory.size())
- {
+ if (!this->ExecutableDirectory.empty()) {
std::string tempPath = this->ExecutableDirectory;
tempPath += "/";
tempPath += this->TestCommand;
extraPaths.push_back(tempPath);
- }
+ }
std::vector<std::string> failed;
fullPath =
- cmCTestTestHandler::FindExecutable(this->CTest,
- this->TestCommand.c_str(),
- resultingConfig,
- extraPaths,
- failed);
+ cmCTestTestHandler::FindExecutable(this->CTest, this->TestCommand.c_str(),
+ resultingConfig, extraPaths, failed);
- if(!cmSystemTools::FileExists(fullPath.c_str()))
- {
+ if (!cmSystemTools::FileExists(fullPath.c_str())) {
out << "Could not find path to executable, perhaps it was not built: "
- << this->TestCommand << "\n";
+ << this->TestCommand << "\n";
out << "tried to find it in these places:\n";
- out << fullPath.c_str() << "\n";
- for(unsigned int i=0; i < failed.size(); ++i)
- {
+ out << fullPath << "\n";
+ for (unsigned int i = 0; i < failed.size(); ++i) {
out << failed[i] << "\n";
- }
- if(outstring)
- {
- *outstring = out.str();
- }
- else
- {
+ }
+ if (outstring) {
+ *outstring = out.str();
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
- }
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
- return 1;
}
+ return 1;
+ }
std::vector<const char*> testCommand;
testCommand.push_back(fullPath.c_str());
- for(k=0; k < this->TestCommandArgs.size(); ++k)
- {
+ for (size_t k = 0; k < this->TestCommandArgs.size(); ++k) {
testCommand.push_back(this->TestCommandArgs[k].c_str());
- }
- testCommand.push_back(0);
+ }
+ testCommand.push_back(CM_NULLPTR);
std::string outs;
int retval = 0;
// run the test from the this->BuildRunDir if set
- if(this->BuildRunDir.size())
- {
+ if (!this->BuildRunDir.empty()) {
out << "Run test in directory: " << this->BuildRunDir << "\n";
- cmSystemTools::ChangeDirectory(this->BuildRunDir.c_str());
- }
+ cmSystemTools::ChangeDirectory(this->BuildRunDir);
+ }
out << "Running test command: \"" << fullPath << "\"";
- for(k=0; k < this->TestCommandArgs.size(); ++k)
- {
+ for (size_t k = 0; k < this->TestCommandArgs.size(); ++k) {
out << " \"" << this->TestCommandArgs[k] << "\"";
- }
+ }
out << "\n";
// how much time is remaining
double remainingTime = 0;
- if (this->Timeout > 0)
- {
+ if (this->Timeout > 0) {
remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
- if (remainingTime <= 0)
- {
- if(outstring)
- {
+ if (remainingTime <= 0) {
+ if (outstring) {
*outstring = "--build-and-test timeout exceeded. ";
- }
- return 1;
}
+ return 1;
}
+ }
- int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, 0,
- remainingTime, 0);
+ int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval,
+ CM_NULLPTR, remainingTime, CM_NULLPTR);
- if(runTestRes != cmsysProcess_State_Exited || retval != 0)
- {
+ if (runTestRes != cmsysProcess_State_Exited || retval != 0) {
out << "Test command failed: " << testCommand[0] << "\n";
retval = 1;
- }
+ }
out << outs << "\n";
- if(outstring)
- {
+ if (outstring) {
*outstring = out.str();
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, OUTPUT, out.str() << std::endl);
- }
+ }
return retval;
}
-//----------------------------------------------------------------------
int cmCTestBuildAndTestHandler::ProcessCommandLineArguments(
const std::string& currentArg, size_t& idx,
const std::vector<std::string>& allArgs)
{
// --build-and-test options
- if(currentArg.find("--build-and-test",0) == 0 && idx < allArgs.size() - 1)
- {
- if(idx+2 < allArgs.size())
- {
+ if (currentArg.find("--build-and-test", 0) == 0 &&
+ idx < allArgs.size() - 1) {
+ if (idx + 2 < allArgs.size()) {
idx++;
this->SourceDir = allArgs[idx];
idx++;
this->BinaryDir = allArgs[idx];
// dir must exist before CollapseFullPath is called
cmSystemTools::MakeDirectory(this->BinaryDir.c_str());
- this->BinaryDir
- = cmSystemTools::CollapseFullPath(this->BinaryDir.c_str());
- this->SourceDir
- = cmSystemTools::CollapseFullPath(this->SourceDir.c_str());
- }
- else
- {
+ this->BinaryDir = cmSystemTools::CollapseFullPath(this->BinaryDir);
+ this->SourceDir = cmSystemTools::CollapseFullPath(this->SourceDir);
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "--build-and-test must have source and binary dir" << std::endl);
+ "--build-and-test must have source and binary dir"
+ << std::endl);
return 0;
- }
}
- if(currentArg.find("--build-target",0) == 0 && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--build-target", 0) == 0 && idx < allArgs.size() - 1) {
idx++;
this->BuildTargets.push_back(allArgs[idx]);
- }
- if(currentArg.find("--build-nocmake",0) == 0)
- {
+ }
+ if (currentArg.find("--build-nocmake", 0) == 0) {
this->BuildNoCMake = true;
- }
- if(currentArg.find("--build-run-dir",0) == 0 && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--build-run-dir", 0) == 0 && idx < allArgs.size() - 1) {
idx++;
this->BuildRunDir = allArgs[idx];
- }
- if(currentArg.find("--build-two-config",0) == 0)
- {
+ }
+ if (currentArg.find("--build-two-config", 0) == 0) {
this->BuildTwoConfig = true;
- }
- if(currentArg.find("--build-exe-dir",0) == 0 && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--build-exe-dir", 0) == 0 && idx < allArgs.size() - 1) {
idx++;
this->ExecutableDirectory = allArgs[idx];
- }
- if(currentArg.find("--test-timeout",0) == 0 && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--test-timeout", 0) == 0 && idx < allArgs.size() - 1) {
idx++;
this->Timeout = atof(allArgs[idx].c_str());
- }
- if(currentArg == "--build-generator" && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg == "--build-generator" && idx < allArgs.size() - 1) {
idx++;
this->BuildGenerator = allArgs[idx];
- }
- if(currentArg == "--build-generator-toolset" &&
- idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg == "--build-generator-platform" && idx < allArgs.size() - 1) {
+ idx++;
+ this->BuildGeneratorPlatform = allArgs[idx];
+ }
+ if (currentArg == "--build-generator-toolset" && idx < allArgs.size() - 1) {
idx++;
this->BuildGeneratorToolset = allArgs[idx];
- }
- if(currentArg.find("--build-project",0) == 0 && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--build-project", 0) == 0 && idx < allArgs.size() - 1) {
idx++;
this->BuildProject = allArgs[idx];
- }
- if(currentArg.find("--build-makeprogram",0) == 0 &&
- idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--build-makeprogram", 0) == 0 &&
+ idx < allArgs.size() - 1) {
idx++;
this->BuildMakeProgram = allArgs[idx];
- }
- if(currentArg.find("--build-config-sample",0) == 0 &&
- idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--build-config-sample", 0) == 0 &&
+ idx < allArgs.size() - 1) {
idx++;
this->ConfigSample = allArgs[idx];
- }
- if(currentArg.find("--build-noclean",0) == 0)
- {
+ }
+ if (currentArg.find("--build-noclean", 0) == 0) {
this->BuildNoClean = true;
- }
- if(currentArg.find("--build-options",0) == 0 && idx < allArgs.size() - 1)
- {
- ++idx;
- bool done = false;
- while(idx < allArgs.size() && !done)
- {
+ }
+ if (currentArg.find("--build-options", 0) == 0) {
+ while (idx + 1 < allArgs.size() && allArgs[idx + 1] != "--build-target" &&
+ allArgs[idx + 1] != "--test-command") {
+ ++idx;
this->BuildOptions.push_back(allArgs[idx]);
- if(idx+1 < allArgs.size()
- && (allArgs[idx+1] == "--build-target" ||
- allArgs[idx+1] == "--test-command"))
- {
- done = true;
- }
- else
- {
- ++idx;
- }
- }
}
- if(currentArg.find("--test-command",0) == 0 && idx < allArgs.size() - 1)
- {
+ }
+ if (currentArg.find("--test-command", 0) == 0 && idx < allArgs.size() - 1) {
++idx;
this->TestCommand = allArgs[idx];
- while(idx+1 < allArgs.size())
- {
+ while (idx + 1 < allArgs.size()) {
++idx;
this->TestCommandArgs.push_back(allArgs[idx]);
- }
}
+ }
return 1;
}
-
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index ca50c6452..2e85e9fed 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -1,21 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestBuildAndTestHandler_h
#define cmCTestBuildAndTestHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
+
+#include <sstream>
+#include <stddef.h>
+#include <string>
+#include <vector>
class cmake;
@@ -26,17 +21,17 @@ class cmake;
class cmCTestBuildAndTestHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestBuildAndTestHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
//! Set all the build and test arguments
- virtual int ProcessCommandLineArguments(
- const std::string& currentArg, size_t& idx,
- const std::vector<std::string>& allArgs);
+ int ProcessCommandLineArguments(const std::string& currentArg, size_t& idx,
+ const std::vector<std::string>& allArgs)
+ CM_OVERRIDE;
/*
* Get the output variable
@@ -45,35 +40,34 @@ public:
cmCTestBuildAndTestHandler();
- virtual void Initialize();
+ void Initialize() CM_OVERRIDE;
protected:
///! Run CMake and build a test and then run it as a single test.
int RunCMakeAndTest(std::string* output);
- int RunCMake(std::string* outstring, cmOStringStream &out,
- std::string &cmakeOutString,
- std::string &cwd, cmake *cm);
+ int RunCMake(std::string* outstring, std::ostringstream& out,
+ std::string& cmakeOutString, cmake* cm);
- cmStdString Output;
+ std::string Output;
- std::string BuildGenerator;
- std::string BuildGeneratorToolset;
+ std::string BuildGenerator;
+ std::string BuildGeneratorPlatform;
+ std::string BuildGeneratorToolset;
std::vector<std::string> BuildOptions;
- bool BuildTwoConfig;
- std::string BuildMakeProgram;
- std::string ConfigSample;
- std::string SourceDir;
- std::string BinaryDir;
- std::string BuildProject;
- std::string TestCommand;
- bool BuildNoClean;
- std::string BuildRunDir;
- std::string ExecutableDirectory;
+ bool BuildTwoConfig;
+ std::string BuildMakeProgram;
+ std::string ConfigSample;
+ std::string SourceDir;
+ std::string BinaryDir;
+ std::string BuildProject;
+ std::string TestCommand;
+ bool BuildNoClean;
+ std::string BuildRunDir;
+ std::string ExecutableDirectory;
std::vector<std::string> TestCommandArgs;
std::vector<std::string> BuildTargets;
- bool BuildNoCMake;
- double Timeout;
+ bool BuildNoCMake;
+ double Timeout;
};
#endif
-
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 1f63185c1..4c8276007 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -1,71 +1,60 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBuildCommand.h"
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
#include "cmCTestBuildHandler.h"
-#include "cmake.h"
+#include "cmCTestGenericHandler.h"
#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+#include <sstream>
+#include <string.h>
+
+class cmExecutionStatus;
-//----------------------------------------------------------------------------
cmCTestBuildCommand::cmCTestBuildCommand()
{
- this->GlobalGenerator = 0;
+ 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] = 0;
+ this->Arguments[ctb_LAST] = CM_NULLPTR;
this->Last = ctb_LAST;
}
-//----------------------------------------------------------------------------
cmCTestBuildCommand::~cmCTestBuildCommand()
{
- if ( this->GlobalGenerator )
- {
+ if (this->GlobalGenerator) {
delete this->GlobalGenerator;
- this->GlobalGenerator = 0;
- }
+ this->GlobalGenerator = CM_NULLPTR;
+ }
}
-//----------------------------------------------------------------------------
cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
{
- cmCTestGenericHandler* handler
- = this->CTest->GetInitializedHandler("build");
- if ( !handler )
- {
+ cmCTestGenericHandler* handler = this->CTest->GetInitializedHandler("build");
+ if (!handler) {
this->SetError("internal CTest error. Cannot instantiate build handler");
- return 0;
- }
- this->Handler = (cmCTestBuildHandler*)handler;
-
- const char* ctestBuildCommand
- = this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
- if ( ctestBuildCommand && *ctestBuildCommand )
- {
- this->CTest->SetCTestConfiguration("MakeCommand", ctestBuildCommand);
- }
- else
- {
- const char* cmakeGeneratorName
- = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
- const char* cmakeProjectName
- = (this->Values[ctb_PROJECT_NAME] && *this->Values[ctb_PROJECT_NAME])
+ return CM_NULLPTR;
+ }
+ this->Handler = (cmCTestBuildHandler*)handler;
+
+ const char* ctestBuildCommand =
+ this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
+ if (ctestBuildCommand && *ctestBuildCommand) {
+ this->CTest->SetCTestConfiguration("MakeCommand", ctestBuildCommand,
+ this->Quiet);
+ } 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");
@@ -74,77 +63,73 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
// CTEST_CONFIGURATION_TYPE script variable, or ctest -C command
// line argument... in that order.
//
- const char* ctestBuildConfiguration
- = this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
- const char* cmakeBuildConfiguration
- = (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
+ const char* ctestBuildConfiguration =
+ this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
+ const char* cmakeBuildConfiguration =
+ (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
? this->Values[ctb_CONFIGURATION]
: ((ctestBuildConfiguration && *ctestBuildConfiguration)
- ? ctestBuildConfiguration
- : this->CTest->GetConfigType().c_str());
+ ? ctestBuildConfiguration
+ : this->CTest->GetConfigType().c_str());
- const char* cmakeBuildAdditionalFlags
- = (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
+ const char* cmakeBuildAdditionalFlags =
+ (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
? this->Values[ctb_FLAGS]
: this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
- const char* cmakeBuildTarget
- = (this->Values[ctb_TARGET] && *this->Values[ctb_TARGET])
+ const char* cmakeBuildTarget =
+ (this->Values[ctb_TARGET] && *this->Values[ctb_TARGET])
? this->Values[ctb_TARGET]
: this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
- if ( cmakeGeneratorName && *cmakeGeneratorName &&
- cmakeProjectName && *cmakeProjectName )
- {
- if ( !cmakeBuildConfiguration )
- {
+ if (cmakeGeneratorName && *cmakeGeneratorName && cmakeProjectName &&
+ *cmakeProjectName) {
+ if (!cmakeBuildConfiguration) {
cmakeBuildConfiguration = "Release";
- }
- if ( this->GlobalGenerator )
- {
- if ( strcmp(this->GlobalGenerator->GetName(),
- cmakeGeneratorName) != 0 )
- {
+ }
+ if (this->GlobalGenerator) {
+ if (this->GlobalGenerator->GetName() != cmakeGeneratorName) {
delete this->GlobalGenerator;
- this->GlobalGenerator = 0;
- }
+ this->GlobalGenerator = CM_NULLPTR;
}
- if ( !this->GlobalGenerator )
- {
+ }
+ if (!this->GlobalGenerator) {
this->GlobalGenerator =
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);
+ cmSystemTools::SetFatalErrorOccured();
+ return CM_NULLPTR;
}
- this->GlobalGenerator->FindMakeProgram(this->Makefile);
- const char* cmakeMakeProgram
- = this->Makefile->GetDefinition("CMAKE_MAKE_PROGRAM");
- if(strlen(cmakeBuildConfiguration) == 0)
- {
- const char* config = 0;
+ }
+ if (strlen(cmakeBuildConfiguration) == 0) {
+ const char* config = CM_NULLPTR;
#ifdef CMAKE_INTDIR
config = CMAKE_INTDIR;
#endif
- if(!config)
- {
+ if (!config) {
config = "Debug";
- }
- cmakeBuildConfiguration = config;
}
+ cmakeBuildConfiguration = config;
+ }
std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory");
- std::string buildCommand
- = this->GlobalGenerator->
- GenerateBuildCommand(cmakeMakeProgram,
- cmakeProjectName, dir.c_str(),
- cmakeBuildAdditionalFlags, cmakeBuildTarget,
- cmakeBuildConfiguration, true, false);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "SetMakeCommand:"
- << buildCommand.c_str() << "\n");
- this->CTest->SetCTestConfiguration("MakeCommand", buildCommand.c_str());
- }
- else
- {
- cmOStringStream ostr;
+ std::string buildCommand =
+ this->GlobalGenerator->GenerateCMakeBuildCommand(
+ cmakeBuildTarget ? cmakeBuildTarget : "", cmakeBuildConfiguration,
+ cmakeBuildAdditionalFlags ? cmakeBuildAdditionalFlags : "",
+ this->Makefile->IgnoreErrorsCMP0061());
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "SetMakeCommand:" << buildCommand << "\n",
+ this->Quiet);
+ this->CTest->SetCTestConfiguration("MakeCommand", buildCommand.c_str(),
+ this->Quiet);
+ } else {
+ std::ostringstream ostr;
+ /* 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."
@@ -156,39 +141,38 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
"\n"
"Alternatively, set CTEST_BUILD_COMMAND to build the project "
"with a custom command line.";
- this->SetError(ostr.str().c_str());
- return 0;
- }
+ /* clang-format on */
+ this->SetError(ostr.str());
+ return CM_NULLPTR;
}
+ }
- if(const char* useLaunchers =
- this->Makefile->GetDefinition("CTEST_USE_LAUNCHERS"))
- {
- this->CTest->SetCTestConfiguration("UseLaunchers", useLaunchers);
- }
+ if (const char* useLaunchers =
+ this->Makefile->GetDefinition("CTEST_USE_LAUNCHERS")) {
+ this->CTest->SetCTestConfiguration("UseLaunchers", useLaunchers,
+ this->Quiet);
+ }
+ handler->SetQuiet(this->Quiet);
return handler;
}
-
bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status)
+ cmExecutionStatus& status)
{
- bool ret = cmCTestHandlerCommand::InitialPass(args, status);
- if ( this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS])
- {
- cmOStringStream str;
+ 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->Values[ctb_NUMBER_WARNINGS]
- && *this->Values[ctb_NUMBER_WARNINGS])
- {
- cmOStringStream str;
+ this->Makefile->AddDefinition(this->Values[ctb_NUMBER_ERRORS],
+ str.str().c_str());
+ }
+ 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());
- }
+ this->Makefile->AddDefinition(this->Values[ctb_NUMBER_WARNINGS],
+ str.str().c_str());
+ }
return ret;
}
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index cabc39b32..9cf6a9652 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -1,21 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestBuildCommand_h
#define cmCTestBuildCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestHandlerCommand.h"
-class cmGlobalGenerator;
+#include <string>
+#include <vector>
+
class cmCTestBuildHandler;
+class cmCTestGenericHandler;
+class cmCommand;
+class cmExecutionStatus;
+class cmGlobalGenerator;
/** \class cmCTestBuild
* \brief Run a ctest script
@@ -25,62 +24,34 @@ class cmCTestBuildHandler;
class cmCTestBuildCommand : public cmCTestHandlerCommand
{
public:
-
cmCTestBuildCommand();
- ~cmCTestBuildCommand();
+ ~cmCTestBuildCommand() CM_OVERRIDE;
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestBuildCommand* ni = new cmCTestBuildCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "ctest_build";}
+ std::string GetName() const CM_OVERRIDE { return "ctest_build"; }
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Build the project.";
- }
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_build([BUILD build_dir] [TARGET target] [RETURN_VALUE res]\n"
- " [APPEND][NUMBER_ERRORS val] [NUMBER_WARNINGS val])\n"
- "Builds the given build directory and stores results in Build.xml. "
- "If no BUILD is given, the CTEST_BINARY_DIRECTORY variable is used.\n"
- "The TARGET variable can be used to specify a build target. If none "
- "is specified, the \"all\" target will be built.\n"
- "The RETURN_VALUE option specifies a variable in which to store the "
- "return value of the native build tool. "
- "The NUMBER_ERRORS and NUMBER_WARNINGS options specify variables in "
- "which to store the number of build errors and warnings detected."
- "\n"
- CTEST_COMMAND_APPEND_OPTION_DOCS;
- }
-
- cmTypeMacro(cmCTestBuildCommand, cmCTestHandlerCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
cmGlobalGenerator* GlobalGenerator;
protected:
cmCTestBuildHandler* Handler;
- enum {
+ enum
+ {
ctb_BUILD = ct_LAST,
ctb_NUMBER_ERRORS,
ctb_NUMBER_WARNINGS,
@@ -91,8 +62,7 @@ protected:
ctb_LAST
};
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
};
-
#endif
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 39eeb70a3..18ef05c67 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -1,43 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBuildHandler.h"
+#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmake.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-#include "cmGeneratedFileStream.h"
-#include "cmXMLSafe.h"
#include "cmFileTimeComparison.h"
-
-//#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/Directory.hxx>
-
-// used for sleep
-#ifdef _WIN32
-#include "windows.h"
-#endif
-
+#include "cmGeneratedFileStream.h"
+#include "cmMakefile.h"
+#include "cmProcessOutput.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 <time.h>
-#include <math.h>
-#include <float.h>
-
-#if defined(__BORLANDC__)
-# pragma warn -8060 /* possibly incorrect assignment */
-#endif
+#include <string.h>
static const char* cmCTestErrorMatches[] = {
"^[Bb]us [Ee]rror",
@@ -69,13 +48,13 @@ static const char* cmCTestErrorMatches[] = {
"^CMake Error.*:",
":[ \\t]cannot find",
":[ \\t]can't find",
- ": \\*\\*\\* No rule to make target \\`.*\\'. Stop",
+ ": \\*\\*\\* No rule to make target [`'].*\\'. Stop",
": \\*\\*\\* 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 \\`.*\\'",
+ ": Unrecognized option [`'].*\\'",
"\", 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 ::",
@@ -95,7 +74,7 @@ static const char* cmCTestErrorMatches[] = {
"^The project cannot be built\\.",
"^\\[ERROR\\]",
"^Command .* failed with exit code",
- 0
+ CM_NULLPTR
};
static const char* cmCTestErrorExceptions[] = {
@@ -104,12 +83,13 @@ static const char* cmCTestErrorExceptions[] = {
": warning",
": \\(Warning\\)",
": note",
+ "Note:",
"makefile:",
"Makefile:",
":[ \\t]+Where:",
"([^ :]+):([0-9]+): Warning",
"------ Build started: .* ------",
- 0
+ CM_NULLPTR
};
static const char* cmCTestWarningMatches[] = {
@@ -134,7 +114,7 @@ static const char* cmCTestWarningMatches[] = {
"cc-[0-9]* CC: REMARK File = .*, Line = [0-9]*",
"^CMake Warning.*:",
"^\\[WARNING\\]",
- 0
+ CM_NULLPTR
};
static const char* cmCTestWarningExceptions[] = {
@@ -154,7 +134,7 @@ static const char* cmCTestWarningExceptions[] = {
"ld32: WARNING 85: definition of dataKey in",
"cc: warning 422: Unknown option \"\\+b",
"_with_warning_C",
- 0
+ CM_NULLPTR
};
struct cmCTestBuildCompileErrorWarningRex
@@ -164,19 +144,17 @@ struct cmCTestBuildCompileErrorWarningRex
int LineIndex;
};
-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 },
- { "^([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 },
- { 0, 0, 0 }
+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 },
+ { "^([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 }
};
-//----------------------------------------------------------------------
cmCTestBuildHandler::cmCTestBuildHandler()
{
this->MaxPreContext = 10;
@@ -190,7 +168,6 @@ cmCTestBuildHandler::cmCTestBuildHandler()
this->UseCTestLaunch = false;
}
-//----------------------------------------------------------------------
void cmCTestBuildHandler::Initialize()
{
this->Superclass::Initialize();
@@ -236,133 +213,113 @@ void cmCTestBuildHandler::Initialize()
this->UseCTestLaunch = false;
}
-//----------------------------------------------------------------------
-void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
+void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile* mf)
{
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_MATCH",
- this->CustomErrorMatches);
+ this->CustomErrorMatches);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_EXCEPTION",
- this->CustomErrorExceptions);
+ this->CustomErrorExceptions);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_MATCH",
- this->CustomWarningMatches);
+ this->CustomWarningMatches);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_EXCEPTION",
- this->CustomWarningExceptions);
- this->CTest->PopulateCustomInteger(mf,
- "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS",
- this->MaxErrors);
- this->CTest->PopulateCustomInteger(mf,
- "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS",
- this->MaxWarnings);
+ this->CustomWarningExceptions);
+ this->CTest->PopulateCustomInteger(
+ mf, "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS", this->MaxErrors);
+ this->CTest->PopulateCustomInteger(
+ mf, "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS", this->MaxWarnings);
int n = -1;
this->CTest->PopulateCustomInteger(mf, "CTEST_CUSTOM_ERROR_PRE_CONTEXT", n);
- if (n != -1)
- {
+ if (n != -1) {
this->MaxPreContext = static_cast<size_t>(n);
- }
+ }
n = -1;
this->CTest->PopulateCustomInteger(mf, "CTEST_CUSTOM_ERROR_POST_CONTEXT", n);
- if (n != -1)
- {
+ if (n != -1) {
this->MaxPostContext = static_cast<size_t>(n);
- }
+ }
// Record the user-specified custom warning rules.
- if(const char* customWarningMatchers =
- mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH"))
- {
+ if (const char* customWarningMatchers =
+ mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH")) {
cmSystemTools::ExpandListArgument(customWarningMatchers,
this->ReallyCustomWarningMatches);
- }
- if(const char* customWarningExceptions =
- mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION"))
- {
+ }
+ if (const char* customWarningExceptions =
+ mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION")) {
cmSystemTools::ExpandListArgument(customWarningExceptions,
this->ReallyCustomWarningExceptions);
- }
+ }
}
-//----------------------------------------------------------------------
std::string cmCTestBuildHandler::GetMakeCommand()
{
- std::string makeCommand
- = this->CTest->GetCTestConfiguration("MakeCommand");
- cmCTestLog(this->CTest,
- HANDLER_VERBOSE_OUTPUT, "MakeCommand:" << makeCommand <<
- "\n");
+ std::string makeCommand = this->CTest->GetCTestConfiguration("MakeCommand");
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "MakeCommand:" << makeCommand << "\n", this->Quiet);
std::string configType = this->CTest->GetConfigType();
- if (configType == "")
- {
- configType
- = this->CTest->GetCTestConfiguration("DefaultCTestConfigurationType");
- }
- if (configType == "")
- {
+ if (configType == "") {
+ configType =
+ this->CTest->GetCTestConfiguration("DefaultCTestConfigurationType");
+ }
+ if (configType == "") {
configType = "Release";
- }
+ }
- cmSystemTools::ReplaceString(makeCommand,
- "${CTEST_CONFIGURATION_TYPE}", configType.c_str());
+ cmSystemTools::ReplaceString(makeCommand, "${CTEST_CONFIGURATION_TYPE}",
+ configType.c_str());
return makeCommand;
}
-//----------------------------------------------------------------------
-//clearly it would be nice if this were broken up into a few smaller
-//functions and commented...
+// clearly it would be nice if this were broken up into a few smaller
+// functions and commented...
int cmCTestBuildHandler::ProcessHandler()
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Build project" << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Build project" << std::endl,
+ this->Quiet);
// do we have time for this
- if (this->CTest->GetRemainingTimeAllowed() < 120)
- {
+ if (this->CTest->GetRemainingTimeAllowed() < 120) {
return 0;
- }
+ }
int entry;
- for ( entry = 0;
- cmCTestWarningErrorFileLine[entry].RegularExpressionString;
- ++ entry )
- {
+ for (entry = 0; cmCTestWarningErrorFileLine[entry].RegularExpressionString;
+ ++entry) {
cmCTestBuildHandler::cmCTestCompileErrorWarningRex r;
- if ( r.RegularExpression.compile(
- cmCTestWarningErrorFileLine[entry].RegularExpressionString) )
- {
+ if (r.RegularExpression.compile(
+ cmCTestWarningErrorFileLine[entry].RegularExpressionString)) {
r.FileIndex = cmCTestWarningErrorFileLine[entry].FileIndex;
r.LineIndex = cmCTestWarningErrorFileLine[entry].LineIndex;
this->ErrorWarningFileLineRegex.push_back(r);
- }
- else
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem Compiling regular expression: "
- << cmCTestWarningErrorFileLine[entry].RegularExpressionString
- << std::endl);
- }
+ } else {
+ cmCTestLog(
+ this->CTest, ERROR_MESSAGE, "Problem Compiling regular expression: "
+ << cmCTestWarningErrorFileLine[entry].RegularExpressionString
+ << std::endl);
}
+ }
// Determine build command and build directory
std::string makeCommand = this->GetMakeCommand();
- if ( makeCommand.size() == 0 )
- {
+ if (makeCommand.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find MakeCommand key in the DartConfiguration.tcl"
- << std::endl);
+ "Cannot find MakeCommand key in the DartConfiguration.tcl"
+ << std::endl);
return -1;
- }
+ }
- const std::string &buildDirectory
- = this->CTest->GetCTestConfiguration("BuildDirectory");
- if ( buildDirectory.size() == 0 )
- {
+ const std::string& buildDirectory =
+ this->CTest->GetCTestConfiguration("BuildDirectory");
+ if (buildDirectory.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find BuildDirectory key in the DartConfiguration.tcl"
- << std::endl);
+ "Cannot find BuildDirectory key in the DartConfiguration.tcl"
+ << std::endl);
return -1;
- }
+ }
std::string const& useLaunchers =
this->CTest->GetCTestConfiguration("UseLaunchers");
@@ -371,94 +328,81 @@ int cmCTestBuildHandler::ProcessHandler()
// Create a last build log
cmGeneratedFileStream ofs;
double elapsed_time_start = cmSystemTools::GetTime();
- if ( !this->StartLogFile("Build", ofs) )
- {
+ if (!this->StartLogFile("Build", ofs)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build log file"
- << std::endl);
- }
+ << std::endl);
+ }
// Create lists of regular expression strings for errors, error exceptions,
// warnings and warning exceptions.
- std::vector<cmStdString>::size_type cc;
- for ( cc = 0; cmCTestErrorMatches[cc]; cc ++ )
- {
+ std::vector<std::string>::size_type cc;
+ for (cc = 0; cmCTestErrorMatches[cc]; cc++) {
this->CustomErrorMatches.push_back(cmCTestErrorMatches[cc]);
- }
- for ( cc = 0; cmCTestErrorExceptions[cc]; cc ++ )
- {
+ }
+ for (cc = 0; cmCTestErrorExceptions[cc]; cc++) {
this->CustomErrorExceptions.push_back(cmCTestErrorExceptions[cc]);
- }
- for ( cc = 0; cmCTestWarningMatches[cc]; cc ++ )
- {
+ }
+ for (cc = 0; cmCTestWarningMatches[cc]; cc++) {
this->CustomWarningMatches.push_back(cmCTestWarningMatches[cc]);
- }
+ }
- for ( cc = 0; cmCTestWarningExceptions[cc]; cc ++ )
- {
+ for (cc = 0; cmCTestWarningExceptions[cc]; cc++) {
this->CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]);
- }
+ }
// Pre-compile regular expressions objects for all regular expressions
- std::vector<cmStdString>::iterator it;
-
-#define cmCTestBuildHandlerPopulateRegexVector(strings, regexes) \
- regexes.clear(); \
- cmCTestLog(this->CTest, DEBUG, this << "Add " #regexes \
- << std::endl); \
- for ( it = strings.begin(); it != strings.end(); ++it ) \
- { \
- cmCTestLog(this->CTest, DEBUG, "Add " #strings ": " \
- << it->c_str() << std::endl); \
- regexes.push_back(it->c_str()); \
- }
- cmCTestBuildHandlerPopulateRegexVector(
- this->CustomErrorMatches, this->ErrorMatchRegex);
- cmCTestBuildHandlerPopulateRegexVector(
- this->CustomErrorExceptions, this->ErrorExceptionRegex);
- cmCTestBuildHandlerPopulateRegexVector(
- this->CustomWarningMatches, this->WarningMatchRegex);
- cmCTestBuildHandlerPopulateRegexVector(
- this->CustomWarningExceptions, this->WarningExceptionRegex);
-
+ 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) { \
+ cmCTestOptionalLog(this->CTest, DEBUG, \
+ "Add " #strings ": " << *it << std::endl, \
+ this->Quiet); \
+ (regexes).push_back(it->c_str()); \
+ }
+ cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorMatches,
+ this->ErrorMatchRegex);
+ cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorExceptions,
+ this->ErrorExceptionRegex);
+ cmCTestBuildHandlerPopulateRegexVector(this->CustomWarningMatches,
+ this->WarningMatchRegex);
+ cmCTestBuildHandlerPopulateRegexVector(this->CustomWarningExceptions,
+ this->WarningExceptionRegex);
// Determine source and binary tree substitutions to simplify the output.
this->SimplifySourceDir = "";
this->SimplifyBuildDir = "";
- if ( this->CTest->GetCTestConfiguration("SourceDirectory").size() > 20 )
- {
- std::string srcdir
- = this->CTest->GetCTestConfiguration("SourceDirectory") + "/";
+ 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] == '/' )
- {
+ for (cc = srcdir.size() - 2; cc > 0; cc--) {
+ if (srcdir[cc] == '/') {
srcdirrep = srcdir.c_str() + cc;
srcdirrep = "/..." + srcdirrep;
- srcdir = srcdir.substr(0, cc+1);
+ srcdir = srcdir.substr(0, cc + 1);
break;
- }
}
- this->SimplifySourceDir = srcdir;
}
- if ( this->CTest->GetCTestConfiguration("BuildDirectory").size() > 20 )
- {
- std::string bindir
- = this->CTest->GetCTestConfiguration("BuildDirectory") + "/";
+ this->SimplifySourceDir = srcdir;
+ }
+ 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] == '/' )
- {
+ for (cc = bindir.size() - 2; cc > 0; cc--) {
+ if (bindir[cc] == '/') {
bindirrep = bindir.c_str() + cc;
bindirrep = "/..." + bindirrep;
- bindir = bindir.substr(0, cc+1);
+ bindir = bindir.substr(0, cc + 1);
break;
- }
}
- this->SimplifyBuildDir = bindir;
}
-
+ this->SimplifyBuildDir = bindir;
+ }
// Ok, let's do the build
@@ -467,16 +411,14 @@ int cmCTestBuildHandler::ProcessHandler()
this->StartBuildTime = cmSystemTools::GetTime();
int retVal = 0;
int res = cmsysProcess_State_Exited;
- if ( !this->CTest->GetShowOnly() )
- {
+ if (!this->CTest->GetShowOnly()) {
res = this->RunMakeCommand(makeCommand.c_str(), &retVal,
- buildDirectory.c_str(), 0, ofs);
- }
- else
- {
- cmCTestLog(this->CTest, DEBUG, "Build with command: " << makeCommand
- << std::endl);
- }
+ buildDirectory.c_str(), 0, ofs);
+ } else {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Build with command: " << makeCommand << std::endl,
+ this->Quiet);
+ }
// Remember end build time and calculate elapsed time
this->EndBuild = this->CTest->CurrentTime();
@@ -485,154 +427,141 @@ int cmCTestBuildHandler::ProcessHandler()
// 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(), "/.../");
- cmSystemTools::ReplaceString(
- evit->PreContext, this->SimplifySourceDir.c_str(), "/.../");
- cmSystemTools::ReplaceString(
- evit->PostContext, this->SimplifySourceDir.c_str(), "/.../");
- }
+ if (!this->SimplifySourceDir.empty()) {
+ for (evit = this->ErrorsAndWarnings.begin();
+ evit != this->ErrorsAndWarnings.end(); ++evit) {
+ cmSystemTools::ReplaceString(evit->Text, this->SimplifySourceDir.c_str(),
+ "/.../");
+ cmSystemTools::ReplaceString(evit->PreContext,
+ this->SimplifySourceDir.c_str(), "/.../");
+ 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(), "/.../");
- cmSystemTools::ReplaceString(
- evit->PreContext, this->SimplifyBuildDir.c_str(), "/.../");
- cmSystemTools::ReplaceString(
- evit->PostContext, this->SimplifyBuildDir.c_str(), "/.../");
- }
+ }
+
+ if (!this->SimplifyBuildDir.empty()) {
+ for (evit = this->ErrorsAndWarnings.begin();
+ evit != this->ErrorsAndWarnings.end(); ++evit) {
+ cmSystemTools::ReplaceString(evit->Text, this->SimplifyBuildDir.c_str(),
+ "/.../");
+ cmSystemTools::ReplaceString(evit->PreContext,
+ this->SimplifyBuildDir.c_str(), "/.../");
+ cmSystemTools::ReplaceString(evit->PostContext,
+ this->SimplifyBuildDir.c_str(), "/.../");
}
+ }
// Generate XML output
cmGeneratedFileStream xofs;
- if(!this->StartResultingXML(cmCTest::PartBuild, "Build", xofs))
- {
+ if (!this->StartResultingXML(cmCTest::PartBuild, "Build", xofs)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build XML file"
- << std::endl);
+ << std::endl);
return -1;
- }
- this->GenerateXMLHeader(xofs);
- if(this->UseCTestLaunch)
- {
- this->GenerateXMLLaunched(xofs);
- }
- else
- {
- this->GenerateXMLLogScraped(xofs);
- }
- this->GenerateXMLFooter(xofs, elapsed_build_time);
-
- if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0)
- {
+ }
+ cmXMLWriter xml(xofs);
+ this->GenerateXMLHeader(xml);
+ if (this->UseCTestLaunch) {
+ this->GenerateXMLLaunched(xml);
+ } else {
+ this->GenerateXMLLogScraped(xml);
+ }
+ 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);
- }
+ << 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;
}
-//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os)
+void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml)
{
- this->CTest->StartXML(os, this->AppendXML);
- os << "<Build>\n"
- << "\t<StartDateTime>" << this->StartBuild << "</StartDateTime>\n"
- << "\t<StartBuildTime>" <<
- static_cast<unsigned int>(this->StartBuildTime)
- << "</StartBuildTime>\n"
- << "<BuildCommand>"
- << cmXMLSafe(this->GetMakeCommand())
- << "</BuildCommand>" << std::endl;
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("Build");
+ xml.Element("StartDateTime", this->StartBuild);
+ xml.Element("StartBuildTime",
+ static_cast<unsigned int>(this->StartBuildTime));
+ xml.Element("BuildCommand", this->GetMakeCommand());
}
-//----------------------------------------------------------------------------
class cmCTestBuildHandler::FragmentCompare
{
public:
- FragmentCompare(cmFileTimeComparison* ftc): FTC(ftc) {}
- FragmentCompare(): FTC(0) {}
- bool operator()(std::string const& l, std::string const& r)
- {
+ FragmentCompare(cmFileTimeComparison* ftc)
+ : FTC(ftc)
+ {
+ }
+ FragmentCompare()
+ : FTC(CM_NULLPTR)
+ {
+ }
+ 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->FileTimeCompare(l.c_str(), r.c_str(), &result) &&
+ result != 0) {
return result < 0;
- }
- else
- {
- return l < r;
- }
}
+ return l < r;
+ }
+
private:
cmFileTimeComparison* FTC;
};
-//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os)
+void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
{
- if(this->CTestLaunchDir.empty())
- {
+ if (this->CTestLaunchDir.empty()) {
return;
- }
+ }
// Sort XML fragments in chronological order.
cmFileTimeComparison ftc;
FragmentCompare fragmentCompare(&ftc);
- typedef std::set<cmStdString, FragmentCompare> Fragments;
+ typedef std::set<std::string, FragmentCompare> Fragments;
Fragments fragments(fragmentCompare);
+ // only report the first 50 warnings and first 50 errors
+ int numErrorsAllowed = this->MaxErrors;
+ int numWarningsAllowed = this->MaxWarnings;
// Identify fragments on disk.
cmsys::Directory launchDir;
- launchDir.Load(this->CTestLaunchDir.c_str());
+ launchDir.Load(this->CTestLaunchDir);
unsigned long n = launchDir.GetNumberOfFiles();
- for(unsigned long i=0; i < n; ++i)
- {
+ for (unsigned long i = 0; i < n; ++i) {
const char* fname = launchDir.GetFile(i);
- if(this->IsLaunchedErrorFile(fname))
- {
+ if (this->IsLaunchedErrorFile(fname) && numErrorsAllowed) {
+ numErrorsAllowed--;
fragments.insert(this->CTestLaunchDir + "/" + fname);
++this->TotalErrors;
- }
- else if(this->IsLaunchedWarningFile(fname))
- {
+ } else if (this->IsLaunchedWarningFile(fname) && numWarningsAllowed) {
+ numWarningsAllowed--;
fragments.insert(this->CTestLaunchDir + "/" + fname);
++this->TotalWarnings;
- }
}
+ }
// Copy the fragments into the final XML file.
- for(Fragments::const_iterator fi = fragments.begin();
- fi != fragments.end(); ++fi)
- {
- this->GenerateXMLLaunchedFragment(os, fi->c_str());
- }
+ for (Fragments::const_iterator fi = fragments.begin(); fi != fragments.end();
+ ++fi) {
+ xml.FragmentFile(fi->c_str());
+ }
}
-//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
+void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
{
std::vector<cmCTestBuildErrorWarning>& ew = this->ErrorsAndWarnings;
std::vector<cmCTestBuildErrorWarning>::iterator it;
@@ -643,136 +572,101 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
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.c_str());
+ srcdir = cmSystemTools::CollapseFullPath(srcdir);
srcdir += "/";
- for ( it = ew.begin();
- it != ew.end() && (numErrorsAllowed || numWarningsAllowed); it++ )
- {
- cmCTestBuildErrorWarning *cm = &(*it);
+ for (it = ew.begin();
+ it != ew.end() && (numErrorsAllowed || numWarningsAllowed); it++) {
+ cmCTestBuildErrorWarning* cm = &(*it);
if ((cm->Error && numErrorsAllowed) ||
- (!cm->Error && numWarningsAllowed))
- {
- if (cm->Error)
- {
+ (!cm->Error && numWarningsAllowed)) {
+ if (cm->Error) {
numErrorsAllowed--;
- }
- else
- {
+ } else {
numWarningsAllowed--;
- }
- os << "\t<" << (cm->Error ? "Error" : "Warning") << ">\n"
- << "\t\t<BuildLogLine>" << cm->LogLine << "</BuildLogLine>\n"
- << "\t\t<Text>" << cmXMLSafe(cm->Text).Quotes(false)
- << "\n</Text>" << std::endl;
+ }
+ 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 )
- {
+ for (rit = this->ErrorWarningFileLineRegex.begin();
+ rit != this->ErrorWarningFileLineRegex.end(); ++rit) {
cmsys::RegularExpression* re = &rit->RegularExpression;
- if ( re->find(cm->Text.c_str() ) )
- {
+ if (re->find(cm->Text.c_str())) {
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);
- if(cm->SourceFile.find("/.../") != cm->SourceFile.npos)
- {
+ if (cm->SourceFile.find("/.../") != std::string::npos) {
cmSystemTools::ReplaceString(cm->SourceFile, "/.../", "");
- std::string::size_type p = cm->SourceFile.find("/");
- if(p != cm->SourceFile.npos)
- {
- cm->SourceFile = cm->SourceFile.substr(
- p+1, cm->SourceFile.size()-p);
- }
+ std::string::size_type p = cm->SourceFile.find('/');
+ if (p != std::string::npos) {
+ cm->SourceFile =
+ cm->SourceFile.substr(p + 1, cm->SourceFile.size() - p);
}
- else
- {
+ } else {
// make sure it is a full path with the correct case
- cm->SourceFile = cmSystemTools::CollapseFullPath(
- cm->SourceFile.c_str());
- cmSystemTools::ReplaceString(
- cm->SourceFile, srcdir.c_str(), "");
- }
+ cm->SourceFile = cmSystemTools::CollapseFullPath(cm->SourceFile);
+ cmSystemTools::ReplaceString(cm->SourceFile, srcdir.c_str(), "");
+ }
cm->LineNumber = atoi(re->match(rit->LineIndex).c_str());
break;
- }
}
- if ( !cm->SourceFile.empty() && cm->LineNumber >= 0 )
- {
- if ( cm->SourceFile.size() > 0 )
- {
- os << "\t\t<SourceFile>" << cm->SourceFile << "</SourceFile>"
- << std::endl;
- }
- if ( cm->SourceFileTail.size() > 0 )
- {
- os << "\t\t<SourceFileTail>" << cm->SourceFileTail
- << "</SourceFileTail>" << std::endl;
- }
- if ( cm->LineNumber >= 0 )
- {
- os << "\t\t<SourceLineNumber>" << cm->LineNumber
- << "</SourceLineNumber>" << std::endl;
- }
+ }
+ if (!cm->SourceFile.empty() && cm->LineNumber >= 0) {
+ if (!cm->SourceFile.empty()) {
+ xml.Element("SourceFile", cm->SourceFile);
+ }
+ if (!cm->SourceFileTail.empty()) {
+ xml.Element("SourceFileTail", cm->SourceFileTail);
+ }
+ if (cm->LineNumber >= 0) {
+ xml.Element("SourceLineNumber", cm->LineNumber);
}
- os << "\t\t<PreContext>" << cmXMLSafe(cm->PreContext).Quotes(false)
- << "</PreContext>\n"
- << "\t\t<PostContext>" << cmXMLSafe(cm->PostContext).Quotes(false);
+ }
+ xml.Element("PreContext", cm->PreContext);
+ xml.StartElement("PostContext");
+ xml.Content(cm->PostContext);
// is this the last warning or error, if so notify
if ((cm->Error && !numErrorsAllowed) ||
- (!cm->Error && !numWarningsAllowed))
- {
- os << "\nThe maximum number of reported warnings or errors has been "
- "reached!!!\n";
- }
- os << "</PostContext>\n"
- << "\t\t<RepeatCount>0</RepeatCount>\n"
- << "</" << (cm->Error ? "Error" : "Warning") << ">\n\n"
- << std::endl;
+ (!cm->Error && !numWarningsAllowed)) {
+ xml.Content("\nThe maximum number of reported warnings or errors "
+ "has been reached!!!\n");
}
+ xml.EndElement(); // PostContext
+ xml.Element("RepeatCount", "0");
+ xml.EndElement(); // "Error" / "Warning"
}
+ }
}
-//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLFooter(std::ostream& os,
+void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
double elapsed_build_time)
{
- os << "\t<Log Encoding=\"base64\" Compression=\"/bin/gzip\">\n\t</Log>\n"
- << "\t<EndDateTime>" << this->EndBuild << "</EndDateTime>\n"
- << "\t<EndBuildTime>" << static_cast<unsigned int>(this->EndBuildTime)
- << "</EndBuildTime>\n"
- << "<ElapsedMinutes>" << static_cast<int>(elapsed_build_time/6)/10.0
- << "</ElapsedMinutes>"
- << "</Build>" << std::endl;
- this->CTest->EndXML(os);
-}
-
-//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLLaunchedFragment(std::ostream& os,
- const char* fname)
-{
- std::ifstream fin(fname, std::ios::in | std::ios::binary);
- std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- os << line << "\n";
- }
+ xml.StartElement("Log");
+ xml.Attribute("Encoding", "base64");
+ xml.Attribute("Compression", "bin/gzip");
+ 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.EndElement(); // Build
+ this->CTest->EndXML(xml);
}
-//----------------------------------------------------------------------------
bool cmCTestBuildHandler::IsLaunchedErrorFile(const char* fname)
{
// error-{hash}.xml
- return (strncmp(fname, "error-", 6) == 0 &&
- strcmp(fname+strlen(fname)-4, ".xml") == 0);
+ return (cmHasLiteralPrefix(fname, "error-") &&
+ strcmp(fname + strlen(fname) - 4, ".xml") == 0);
}
-//----------------------------------------------------------------------------
bool cmCTestBuildHandler::IsLaunchedWarningFile(const char* fname)
{
// warning-{hash}.xml
- return (strncmp(fname, "warning-", 8) == 0 &&
- strcmp(fname+strlen(fname)-4, ".xml") == 0);
+ return (cmHasLiteralPrefix(fname, "warning-") &&
+ strcmp(fname + strlen(fname) - 4, ".xml") == 0);
}
//######################################################################
@@ -780,12 +674,12 @@ bool cmCTestBuildHandler::IsLaunchedWarningFile(const char* fname)
//######################################################################
//######################################################################
-//----------------------------------------------------------------------------
class cmCTestBuildHandler::LaunchHelper
{
public:
LaunchHelper(cmCTestBuildHandler* handler);
~LaunchHelper();
+
private:
cmCTestBuildHandler* Handler;
cmCTest* CTest;
@@ -795,19 +689,16 @@ private:
std::vector<std::string> const& matchers);
};
-//----------------------------------------------------------------------------
-cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler):
- Handler(handler), CTest(handler->CTest)
+cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
+ : Handler(handler)
+ , CTest(handler->CTest)
{
std::string tag = this->CTest->GetCurrentTag();
- if(tag.empty())
- {
+ if (tag.empty()) {
// This is not for a dashboard submission, so there is no XML.
// Skip enabling the launchers.
this->Handler->UseCTestLaunch = false;
- }
- else
- {
+ } else {
// Compute a directory in which to store launcher fragments.
std::string& launchDir = this->Handler->CTestLaunchDir;
launchDir = this->CTest->GetBinaryDir();
@@ -816,36 +707,31 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler):
launchDir += "/Build";
// Clean out any existing launcher fragments.
- cmSystemTools::RemoveADirectory(launchDir.c_str());
+ cmSystemTools::RemoveADirectory(launchDir);
- if(this->Handler->UseCTestLaunch)
- {
+ if (this->Handler->UseCTestLaunch) {
// Enable launcher fragments.
cmSystemTools::MakeDirectory(launchDir.c_str());
this->WriteLauncherConfig();
std::string launchEnv = "CTEST_LAUNCH_LOGS=";
launchEnv += launchDir;
- cmSystemTools::PutEnv(launchEnv.c_str());
- }
+ cmSystemTools::PutEnv(launchEnv);
}
+ }
// If not using launchers, make sure they passthru.
- if(!this->Handler->UseCTestLaunch)
- {
+ if (!this->Handler->UseCTestLaunch) {
cmSystemTools::UnsetEnv("CTEST_LAUNCH_LOGS");
- }
+ }
}
-//----------------------------------------------------------------------------
cmCTestBuildHandler::LaunchHelper::~LaunchHelper()
{
- if(this->Handler->UseCTestLaunch)
- {
+ if (this->Handler->UseCTestLaunch) {
cmSystemTools::UnsetEnv("CTEST_LAUNCH_LOGS");
- }
+ }
}
-//----------------------------------------------------------------------------
void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig()
{
this->WriteScrapeMatchers("Warning",
@@ -861,55 +747,50 @@ void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig()
fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n";
}
-//----------------------------------------------------------------------------
-void
-cmCTestBuildHandler::LaunchHelper
-::WriteScrapeMatchers(const char* purpose,
- std::vector<std::string> const& matchers)
+void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers(
+ const char* purpose, std::vector<std::string> const& matchers)
{
- if(matchers.empty())
- {
+ 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)
- {
+ for (std::vector<std::string>::const_iterator mi = matchers.begin();
+ mi != matchers.end(); ++mi) {
fout << *mi << "\n";
- }
+ }
}
-//----------------------------------------------------------------------
-int cmCTestBuildHandler::RunMakeCommand(const char* command,
- int* retVal, const char* dir, int timeout, std::ofstream& ofs)
+int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
+ const char* dir, int timeout,
+ std::ostream& ofs, Encoding encoding)
{
// First generate the command and arguments
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
+ std::vector<std::string> args = cmSystemTools::ParseArguments(command);
- if(args.size() < 1)
- {
+ if (args.empty()) {
return false;
- }
+ }
std::vector<const char*> argv;
- for(std::vector<cmStdString>::const_iterator a = args.begin();
- a != args.end(); ++a)
- {
+ for (std::vector<std::string>::const_iterator a = args.begin();
+ a != args.end(); ++a) {
argv.push_back(a->c_str());
- }
- argv.push_back(0);
+ }
+ argv.push_back(CM_NULLPTR);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command:");
+ 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 )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " \"" << *ait << "\"");
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
+ for (ait = argv.begin(); ait != argv.end() && *ait; ++ait) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " \"" << *ait << "\"", this->Quiet);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl,
+ this->Quiet);
// Optionally use make rule launchers to record errors and warnings.
LaunchHelper launchHelper(this);
@@ -929,12 +810,16 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command,
char* data;
int length;
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Each symbol represents " << tick_len << " bytes of output."
- << std::endl
- << (this->UseCTestLaunch? "" :
- " '!' represents an error and '*' a warning.\n")
- << " " << std::flush);
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents "
+ << tick_len << " bytes of output." << std::endl
+ << (this->UseCTestLaunch
+ ? ""
+ : " '!' represents an error and '*' a warning.\n")
+ << " " << std::flush,
+ this->Quiet);
// Initialize building structures
this->BuildProcessingQueue.clear();
@@ -949,94 +834,97 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command,
// For every chunk of data
int res;
- while((res = cmsysProcess_WaitForData(cp, &data, &length, 0)))
- {
+ while ((res = cmsysProcess_WaitForData(cp, &data, &length, CM_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)
- {
- if(data[cc] == 0)
- {
+ for (int cc = 0; cc < length; ++cc) {
+ if (data[cc] == 0) {
data[cc] = '\n';
- }
}
+ }
// Process the chunk of data
- if ( res == cmsysProcess_Pipe_STDERR )
- {
- this->ProcessBuffer(data, length, tick, tick_len, ofs,
- &this->BuildProcessingErrorQueue);
- }
- else
- {
- this->ProcessBuffer(data, length, tick, tick_len, ofs,
- &this->BuildProcessingQueue);
- }
+ if (res == cmsysProcess_Pipe_STDERR) {
+ processOutput.DecodeText(data, length, strdata, 1);
+ this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
+ &this->BuildProcessingErrorQueue);
+ } else {
+ processOutput.DecodeText(data, length, strdata, 2);
+ this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
+ &this->BuildProcessingQueue);
}
-
- this->ProcessBuffer(0, 0, tick, tick_len, ofs, &this->BuildProcessingQueue);
- this->ProcessBuffer(0, 0, tick, tick_len, ofs,
- &this->BuildProcessingErrorQueue);
- cmCTestLog(this->CTest, OUTPUT, " Size of output: "
- << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl);
+ }
+ processOutput.DecodeText(std::string(), strdata, 1);
+ if (!strdata.empty()) {
+ this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
+ &this->BuildProcessingErrorQueue);
+ }
+ processOutput.DecodeText(std::string(), strdata, 2);
+ if (!strdata.empty()) {
+ this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
+ &this->BuildProcessingQueue);
+ }
+
+ this->ProcessBuffer(CM_NULLPTR, 0, tick, tick_len, ofs,
+ &this->BuildProcessingQueue);
+ this->ProcessBuffer(CM_NULLPTR, 0, tick, tick_len, ofs,
+ &this->BuildProcessingErrorQueue);
+ 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, 0);
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
int result = cmsysProcess_GetState(cp);
- if(result == cmsysProcess_State_Exited)
- {
- if (retVal)
- {
+ if (result == cmsysProcess_State_Exited) {
+ if (retVal) {
*retVal = cmsysProcess_GetExitValue(cp);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Command exited with the value: " << *retVal << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Command exited with the value: " << *retVal
+ << std::endl,
+ this->Quiet);
// if a non zero return value
- if (*retVal)
- {
+ if (*retVal) {
// If there was an error running command, report that on the
// dashboard.
cmCTestBuildErrorWarning errorwarning;
- errorwarning.LogLine = 1;
- errorwarning.Text
- = "*** WARNING non-zero return value in ctest from: ";
- errorwarning.Text += argv[0];
- errorwarning.PreContext = "";
+ errorwarning.LogLine = 1;
+ errorwarning.Text =
+ "*** WARNING non-zero return value in ctest from: ";
+ errorwarning.Text += argv[0];
+ errorwarning.PreContext = "";
errorwarning.PostContext = "";
- errorwarning.Error = false;
+ errorwarning.Error = false;
this->ErrorsAndWarnings.push_back(errorwarning);
- this->TotalWarnings ++;
- }
+ this->TotalWarnings++;
}
}
- else if(result == cmsysProcess_State_Exception)
- {
- if (retVal)
- {
+ } else if (result == cmsysProcess_State_Exception) {
+ if (retVal) {
*retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this->CTest, WARNING, "There was an exception: " << *retVal
- << std::endl);
- }
- }
- else if(result == cmsysProcess_State_Expired)
- {
- cmCTestLog(this->CTest, WARNING, "There was a timeout" << std::endl);
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "There was an exception: " << *retVal << std::endl,
+ this->Quiet);
}
- else if(result == cmsysProcess_State_Error)
- {
+ } else if (result == cmsysProcess_State_Expired) {
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "There was a timeout" << std::endl, this->Quiet);
+ } else if (result == cmsysProcess_State_Error) {
// 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.LogLine = 1;
+ errorwarning.Text = "*** ERROR executing: ";
+ errorwarning.Text += cmsysProcess_GetErrorString(cp);
+ errorwarning.PreContext = "";
errorwarning.PostContext = "";
- errorwarning.Error = true;
+ errorwarning.Error = true;
this->ErrorsAndWarnings.push_back(errorwarning);
- this->TotalErrors ++;
+ this->TotalErrors++;
cmCTestLog(this->CTest, ERROR_MESSAGE, "There was an error: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
- }
+ << cmsysProcess_GetErrorString(cp) << std::endl);
+ }
cmsysProcess_Delete(cp);
return result;
@@ -1047,55 +935,43 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command,
//######################################################################
//######################################################################
-//----------------------------------------------------------------------
-void cmCTestBuildHandler::ProcessBuffer(const char* data, int length,
- size_t& tick, size_t tick_len, std::ofstream& ofs,
- t_BuildProcessingQueueType* queue)
+void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
+ size_t& tick, size_t tick_len,
+ std::ostream& ofs,
+ t_BuildProcessingQueueType* queue)
{
const std::string::size_type tick_line_len = 50;
const char* ptr;
- for ( ptr = data; ptr < data+length; ptr ++ )
- {
+ for (ptr = data; ptr < data + length; ptr++) {
queue->push_back(*ptr);
- }
+ }
this->BuildOutputLogSize += length;
// until there are any lines left in the buffer
- while ( 1 )
- {
+ while (true) {
// Find the end of line
t_BuildProcessingQueueType::iterator it;
- for ( it = queue->begin();
- it != queue->end();
- ++ it )
- {
- if ( *it == '\n' )
- {
+ for (it = queue->begin(); it != queue->end(); ++it) {
+ if (*it == '\n') {
break;
- }
}
+ }
// Once certain number of errors or warnings reached, ignore future errors
// or warnings.
- if ( this->TotalWarnings >= this->MaxWarnings )
- {
+ if (this->TotalWarnings >= this->MaxWarnings) {
this->WarningQuotaReached = true;
- }
- if ( this->TotalErrors >= this->MaxErrors )
- {
+ }
+ if (this->TotalErrors >= this->MaxErrors) {
this->ErrorQuotaReached = true;
- }
+ }
// If the end of line was found
- if ( it != queue->end() )
- {
+ if (it != queue->end()) {
// Create a contiguous array for the line
this->CurrentProcessingLine.clear();
- t_BuildProcessingQueueType::iterator cit;
- for ( cit = queue->begin(); cit != it; ++cit )
- {
- this->CurrentProcessingLine.push_back(*cit);
- }
+ this->CurrentProcessingLine.insert(this->CurrentProcessingLine.end(),
+ queue->begin(), it);
this->CurrentProcessingLine.push_back(0);
const char* line = &*this->CurrentProcessingLine.begin();
@@ -1103,120 +979,107 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, int length,
int lineType = this->ProcessSingleLine(line);
// Erase the line from the queue
- queue->erase(queue->begin(), it+1);
+ queue->erase(queue->begin(), it + 1);
// Depending on the line type, produce error or warning, or nothing
cmCTestBuildErrorWarning errorwarning;
bool found = false;
- switch ( lineType )
- {
- case b_WARNING_LINE:
- this->LastTickChar = '*';
- errorwarning.Error = false;
- found = true;
- this->TotalWarnings ++;
- break;
- case b_ERROR_LINE:
- this->LastTickChar = '!';
- errorwarning.Error = true;
- found = true;
- this->TotalErrors ++;
- break;
- }
- if ( found )
- {
+ switch (lineType) {
+ case b_WARNING_LINE:
+ this->LastTickChar = '*';
+ errorwarning.Error = false;
+ found = true;
+ this->TotalWarnings++;
+ break;
+ case b_ERROR_LINE:
+ this->LastTickChar = '!';
+ errorwarning.Error = true;
+ found = true;
+ this->TotalErrors++;
+ break;
+ }
+ if (found) {
// This is an error or warning, so generate report
- errorwarning.LogLine = static_cast<int>(this->OutputLineCounter+1);
- errorwarning.Text = line;
- errorwarning.PreContext = "";
+ errorwarning.LogLine = static_cast<int>(this->OutputLineCounter + 1);
+ errorwarning.Text = line;
+ errorwarning.PreContext = "";
errorwarning.PostContext = "";
// Copy pre-context to report
- std::deque<cmStdString>::iterator pcit;
- for ( pcit = this->PreContext.begin();
- pcit != this->PreContext.end();
- ++pcit )
- {
+ std::deque<std::string>::iterator pcit;
+ for (pcit = this->PreContext.begin(); pcit != this->PreContext.end();
+ ++pcit) {
errorwarning.PreContext += *pcit + "\n";
- }
+ }
this->PreContext.clear();
// Store report
this->ErrorsAndWarnings.push_back(errorwarning);
- this->LastErrorOrWarning = this->ErrorsAndWarnings.end()-1;
+ this->LastErrorOrWarning = this->ErrorsAndWarnings.end() - 1;
this->PostContextCount = 0;
- }
- else
- {
+ } else {
// This is not an error or warning.
// So, figure out if this is a post-context line
- if ( this->ErrorsAndWarnings.size() &&
- this->LastErrorOrWarning != this->ErrorsAndWarnings.end() &&
- this->PostContextCount < this->MaxPostContext )
- {
- this->PostContextCount ++;
+ if (!this->ErrorsAndWarnings.empty() &&
+ this->LastErrorOrWarning != this->ErrorsAndWarnings.end() &&
+ this->PostContextCount < this->MaxPostContext) {
+ this->PostContextCount++;
this->LastErrorOrWarning->PostContext += line;
- if ( this->PostContextCount < this->MaxPostContext )
- {
+ if (this->PostContextCount < this->MaxPostContext) {
this->LastErrorOrWarning->PostContext += "\n";
- }
}
- else
- {
+ } else {
// Otherwise store pre-context for the next error
this->PreContext.push_back(line);
- if ( this->PreContext.size() > this->MaxPreContext )
- {
+ if (this->PreContext.size() > this->MaxPreContext) {
this->PreContext.erase(this->PreContext.begin(),
- this->PreContext.end()-this->MaxPreContext);
- }
+ this->PreContext.end() -
+ this->MaxPreContext);
}
}
- this->OutputLineCounter ++;
}
- else
- {
+ this->OutputLineCounter++;
+ } else {
break;
- }
}
+ }
// Now that the buffer is processed, display missing ticks
int tickDisplayed = false;
- while ( this->BuildOutputLogSize > (tick * tick_len) )
- {
- tick ++;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, this->LastTickChar);
+ while (this->BuildOutputLogSize > (tick * tick_len)) {
+ tick++;
+ cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT,
+ this->LastTickChar, this->Quiet);
tickDisplayed = true;
- if ( tick % tick_line_len == 0 && tick > 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Size: "
- << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl
- << " ");
- }
+ if (tick % tick_line_len == 0 && tick > 0) {
+ cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size: "
+ << ((this->BuildOutputLogSize + 512) / 1024) << "K"
+ << std::endl
+ << " ",
+ this->Quiet);
}
- if ( tickDisplayed )
- {
+ }
+ if (tickDisplayed) {
this->LastTickChar = '.';
- }
+ }
// And if this is verbose output, display the content of the chunk
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(data, length));
+ cmCTestLogWrite(data, length));
// Always store the chunk to the file
ofs << cmCTestLogWrite(data, length);
}
-//----------------------------------------------------------------------
int cmCTestBuildHandler::ProcessSingleLine(const char* data)
{
- if(this->UseCTestLaunch)
- {
+ if (this->UseCTestLaunch) {
// No log scraping when using launchers.
return b_REGULAR_LINE;
- }
+ }
- cmCTestLog(this->CTest, DEBUG, "Line: [" << data << "]" << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, "Line: [" << data << "]" << std::endl,
+ this->Quiet);
std::vector<cmsys::RegularExpression>::iterator it;
@@ -1225,86 +1088,76 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data)
// Check for regular expressions
- if ( !this->ErrorQuotaReached )
- {
+ if (!this->ErrorQuotaReached) {
// Errors
int wrxCnt = 0;
- for ( it = this->ErrorMatchRegex.begin();
- it != this->ErrorMatchRegex.end();
- ++ it )
- {
- if ( it->find(data) )
- {
+ for (it = this->ErrorMatchRegex.begin(); it != this->ErrorMatchRegex.end();
+ ++it) {
+ if (it->find(data)) {
errorLine = 1;
- cmCTestLog(this->CTest, DEBUG, " Error Line: " << data
- << " (matches: " << this->CustomErrorMatches[wrxCnt] << ")"
- << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Error Line: " << data << " (matches: "
+ << this->CustomErrorMatches[wrxCnt]
+ << ")" << std::endl,
+ this->Quiet);
break;
- }
- wrxCnt ++;
}
+ wrxCnt++;
+ }
// Error exceptions
wrxCnt = 0;
- for ( it = this->ErrorExceptionRegex.begin();
- it != this->ErrorExceptionRegex.end();
- ++ it )
- {
- if ( it->find(data) )
- {
+ for (it = this->ErrorExceptionRegex.begin();
+ it != this->ErrorExceptionRegex.end(); ++it) {
+ if (it->find(data)) {
errorLine = 0;
- cmCTestLog(this->CTest, DEBUG, " Not an error Line: " << data
- << " (matches: " << this->CustomErrorExceptions[wrxCnt] << ")"
- << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, " Not an error Line: "
+ << data << " (matches: "
+ << this->CustomErrorExceptions[wrxCnt] << ")"
+ << std::endl,
+ this->Quiet);
break;
- }
- wrxCnt ++;
}
+ wrxCnt++;
}
- if ( !this->WarningQuotaReached )
- {
+ }
+ if (!this->WarningQuotaReached) {
// Warnings
int wrxCnt = 0;
- for ( it = this->WarningMatchRegex.begin();
- it != this->WarningMatchRegex.end();
- ++ it )
- {
- if ( it->find(data) )
- {
+ for (it = this->WarningMatchRegex.begin();
+ it != this->WarningMatchRegex.end(); ++it) {
+ if (it->find(data)) {
warningLine = 1;
- cmCTestLog(this->CTest, DEBUG,
- " Warning Line: " << data
- << " (matches: " << this->CustomWarningMatches[wrxCnt] << ")"
- << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, " Warning Line: "
+ << data << " (matches: "
+ << this->CustomWarningMatches[wrxCnt] << ")"
+ << std::endl,
+ this->Quiet);
break;
- }
- wrxCnt ++;
}
+ wrxCnt++;
+ }
wrxCnt = 0;
// Warning exceptions
- for ( it = this->WarningExceptionRegex.begin();
- it != this->WarningExceptionRegex.end();
- ++ it )
- {
- if ( it->find(data) )
- {
+ for (it = this->WarningExceptionRegex.begin();
+ it != this->WarningExceptionRegex.end(); ++it) {
+ if (it->find(data)) {
warningLine = 0;
- cmCTestLog(this->CTest, DEBUG, " Not a warning Line: " << data
- << " (matches: " << this->CustomWarningExceptions[wrxCnt] << ")"
- << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, " Not a warning Line: "
+ << data << " (matches: "
+ << this->CustomWarningExceptions[wrxCnt] << ")"
+ << std::endl,
+ this->Quiet);
break;
- }
- wrxCnt ++;
}
+ wrxCnt++;
}
- if ( errorLine )
- {
+ }
+ if (errorLine) {
return b_ERROR_LINE;
- }
- if ( warningLine )
- {
+ }
+ if (warningLine) {
return b_WARNING_LINE;
- }
+ }
return b_REGULAR_LINE;
}
-
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 439efd604..ef3cddf1b 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -1,25 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestBuildHandler_h
#define cmCTestBuildHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmProcessOutput.h"
+#include "cmsys/RegularExpression.hxx"
+#include <deque>
+#include <iosfwd>
+#include <stddef.h>
+#include <string>
+#include <vector>
class cmMakefile;
+class cmXMLWriter;
/** \class cmCTestBuildHandler
* \brief A class that handles ctest -S invocations
@@ -28,79 +25,80 @@ class cmMakefile;
class cmCTestBuildHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestBuildHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
+ typedef cmProcessOutput::Encoding Encoding;
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
cmCTestBuildHandler();
- void PopulateCustomVectors(cmMakefile *mf);
+ void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
/**
* Initialize handler
*/
- virtual void Initialize();
+ void Initialize() CM_OVERRIDE;
- int GetTotalErrors() { return this->TotalErrors;}
- int GetTotalWarnings() { return this->TotalWarnings;}
+ int GetTotalErrors() { return this->TotalErrors; }
+ int GetTotalWarnings() { return this->TotalWarnings; }
private:
std::string GetMakeCommand();
//! 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 timeout,
- std::ofstream& ofs);
+ int RunMakeCommand(const char* command, int* retVal, const char* dir,
+ int timeout, std::ostream& ofs,
+ Encoding encoding = cmProcessOutput::Auto);
- enum {
+ enum
+ {
b_REGULAR_LINE,
b_WARNING_LINE,
b_ERROR_LINE
};
class cmCTestCompileErrorWarningRex
- {
+ {
public:
cmCTestCompileErrorWarningRex() {}
int FileIndex;
int LineIndex;
cmsys::RegularExpression RegularExpression;
- };
+ };
struct cmCTestBuildErrorWarning
{
- bool Error;
- int LogLine;
+ bool Error;
+ int LogLine;
std::string Text;
std::string SourceFile;
std::string SourceFileTail;
- int LineNumber;
+ int LineNumber;
std::string PreContext;
std::string PostContext;
};
// generate the XML output
- void GenerateXMLHeader(std::ostream& os);
- void GenerateXMLLaunched(std::ostream& os);
- void GenerateXMLLogScraped(std::ostream& os);
- void GenerateXMLFooter(std::ostream& os, double elapsed_build_time);
- void GenerateXMLLaunchedFragment(std::ostream& os, const char* fname);
+ void GenerateXMLHeader(cmXMLWriter& xml);
+ void GenerateXMLLaunched(cmXMLWriter& xml);
+ void GenerateXMLLogScraped(cmXMLWriter& xml);
+ void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time);
bool IsLaunchedErrorFile(const char* fname);
bool IsLaunchedWarningFile(const char* fname);
- std::string StartBuild;
- std::string EndBuild;
- double StartBuildTime;
- double EndBuildTime;
+ std::string StartBuild;
+ std::string EndBuild;
+ double StartBuildTime;
+ double EndBuildTime;
- std::vector<cmStdString> CustomErrorMatches;
- std::vector<cmStdString> CustomErrorExceptions;
- std::vector<cmStdString> CustomWarningMatches;
- std::vector<cmStdString> CustomWarningExceptions;
+ std::vector<std::string> CustomErrorMatches;
+ std::vector<std::string> CustomErrorExceptions;
+ std::vector<std::string> CustomWarningMatches;
+ std::vector<std::string> CustomWarningExceptions;
std::vector<std::string> ReallyCustomWarningMatches;
std::vector<std::string> ReallyCustomWarningExceptions;
std::vector<cmCTestCompileErrorWarningRex> ErrorWarningFileLineRegex;
@@ -112,39 +110,41 @@ private:
typedef std::deque<char> t_BuildProcessingQueueType;
- void ProcessBuffer(const char* data, int length, size_t& tick,
- size_t tick_len, std::ofstream& ofs, t_BuildProcessingQueueType* queue);
+ void ProcessBuffer(const char* data, size_t length, size_t& tick,
+ size_t tick_len, std::ostream& ofs,
+ t_BuildProcessingQueueType* queue);
int ProcessSingleLine(const char* data);
- t_BuildProcessingQueueType BuildProcessingQueue;
- t_BuildProcessingQueueType BuildProcessingErrorQueue;
- size_t BuildOutputLogSize;
- std::vector<char> CurrentProcessingLine;
+ t_BuildProcessingQueueType BuildProcessingQueue;
+ t_BuildProcessingQueueType BuildProcessingErrorQueue;
+ size_t BuildOutputLogSize;
+ std::vector<char> CurrentProcessingLine;
- cmStdString SimplifySourceDir;
- cmStdString SimplifyBuildDir;
- size_t OutputLineCounter;
+ std::string SimplifySourceDir;
+ std::string SimplifyBuildDir;
+ size_t OutputLineCounter;
typedef std::vector<cmCTestBuildErrorWarning> t_ErrorsAndWarningsVector;
- t_ErrorsAndWarningsVector ErrorsAndWarnings;
- t_ErrorsAndWarningsVector::iterator LastErrorOrWarning;
- size_t PostContextCount;
- size_t MaxPreContext;
- size_t MaxPostContext;
- std::deque<cmStdString> PreContext;
+ t_ErrorsAndWarningsVector ErrorsAndWarnings;
+ t_ErrorsAndWarningsVector::iterator LastErrorOrWarning;
+ size_t PostContextCount;
+ size_t MaxPreContext;
+ size_t MaxPostContext;
+ std::deque<std::string> PreContext;
- int TotalErrors;
- int TotalWarnings;
- char LastTickChar;
+ int TotalErrors;
+ int TotalWarnings;
+ char LastTickChar;
- bool ErrorQuotaReached;
- bool WarningQuotaReached;
+ bool ErrorQuotaReached;
+ bool WarningQuotaReached;
- int MaxErrors;
- int MaxWarnings;
+ int MaxErrors;
+ int MaxWarnings;
bool UseCTestLaunch;
std::string CTestLaunchDir;
class LaunchHelper;
+
friend class LaunchHelper;
class FragmentCompare;
};
diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx
index 726950704..fad360ba4 100644
--- a/Source/CTest/cmCTestCVS.cxx
+++ b/Source/CTest/cmCTestCVS.cxx
@@ -1,38 +1,31 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCVS.h"
#include "cmCTest.h"
+#include "cmProcessTools.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <utility>
-//----------------------------------------------------------------------------
-cmCTestCVS::cmCTestCVS(cmCTest* ct, std::ostream& log): cmCTestVC(ct, log)
+cmCTestCVS::cmCTestCVS(cmCTest* ct, std::ostream& log)
+ : cmCTestVC(ct, log)
{
}
-//----------------------------------------------------------------------------
cmCTestCVS::~cmCTestCVS()
{
}
-//----------------------------------------------------------------------------
-class cmCTestCVS::UpdateParser: public cmCTestVC::LineParser
+class cmCTestCVS::UpdateParser : public cmCTestVC::LineParser
{
public:
- UpdateParser(cmCTestCVS* cvs, const char* prefix): CVS(cvs)
- {
+ UpdateParser(cmCTestCVS* cvs, const char* prefix)
+ : CVS(cvs)
+ {
this->SetLog(&cvs->Log, prefix);
// See "man cvs", section "update output".
this->RegexFileUpdated.compile("^([UP]) *(.*)");
@@ -43,7 +36,8 @@ public:
this->RegexFileRemoved2.compile(
"cvs[^ ]* update: "
"warning: `?([^']*)'? is not \\(any longer\\) pertinent");
- }
+ }
+
private:
cmCTestCVS* CVS;
cmsys::RegularExpression RegexFileUpdated;
@@ -52,266 +46,233 @@ private:
cmsys::RegularExpression RegexFileRemoved1;
cmsys::RegularExpression RegexFileRemoved2;
- virtual bool ProcessLine()
- {
- if(this->RegexFileUpdated.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexFileUpdated.find(this->Line)) {
this->DoFile(PathUpdated, this->RegexFileUpdated.match(2));
- }
- else if(this->RegexFileModified.find(this->Line))
- {
+ } else if (this->RegexFileModified.find(this->Line)) {
this->DoFile(PathModified, this->RegexFileModified.match(2));
- }
- else if(this->RegexFileConflicting.find(this->Line))
- {
+ } else if (this->RegexFileConflicting.find(this->Line)) {
this->DoFile(PathConflicting, this->RegexFileConflicting.match(2));
- }
- else if(this->RegexFileRemoved1.find(this->Line))
- {
+ } else if (this->RegexFileRemoved1.find(this->Line)) {
this->DoFile(PathUpdated, this->RegexFileRemoved1.match(1));
- }
- else if(this->RegexFileRemoved2.find(this->Line))
- {
+ } else if (this->RegexFileRemoved2.find(this->Line)) {
this->DoFile(PathUpdated, this->RegexFileRemoved2.match(1));
- }
- return true;
}
+ return true;
+ }
void DoFile(PathStatus status, std::string const& file)
- {
+ {
std::string dir = cmSystemTools::GetFilenamePath(file);
std::string name = cmSystemTools::GetFilenameName(file);
this->CVS->Dirs[dir][name] = status;
- }
+ }
};
-//----------------------------------------------------------------------------
bool cmCTestCVS::UpdateImpl()
{
// Get user-specified update options.
std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
- if(opts.empty())
- {
+ if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("CVSUpdateOptions");
- if(opts.empty())
- {
+ if (opts.empty()) {
opts = "-dP";
- }
}
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(opts.c_str());
+ }
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
// Specify the start time for nightly testing.
- if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
- {
+ if (this->CTest->GetTestModel() == cmCTest::NIGHTLY) {
args.push_back("-D" + this->GetNightlyTime() + " UTC");
- }
+ }
// Run "cvs update" to update the work tree.
std::vector<char const*> cvs_update;
cvs_update.push_back(this->CommandLineTool.c_str());
cvs_update.push_back("-z3");
cvs_update.push_back("update");
- for(std::vector<cmStdString>::const_iterator ai = args.begin();
- ai != args.end(); ++ai)
- {
+ for (std::vector<std::string>::const_iterator ai = args.begin();
+ ai != args.end(); ++ai) {
cvs_update.push_back(ai->c_str());
- }
- cvs_update.push_back(0);
+ }
+ cvs_update.push_back(CM_NULLPTR);
UpdateParser out(this, "up-out> ");
UpdateParser err(this, "up-err> ");
return this->RunUpdateCommand(&cvs_update[0], &out, &err);
}
-//----------------------------------------------------------------------------
-class cmCTestCVS::LogParser: public cmCTestVC::LineParser
+class cmCTestCVS::LogParser : public cmCTestVC::LineParser
{
public:
typedef cmCTestCVS::Revision Revision;
- LogParser(cmCTestCVS* cvs, const char* prefix, std::vector<Revision>& revs):
- CVS(cvs), Revisions(revs), Section(SectionHeader)
- {
+ 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->RegexRevision.compile("^revision +([^ ]*) *$");
this->RegexBranches.compile("^branches: .*$");
this->RegexPerson.compile("^date: +([^;]+); +author: +([^;]+);");
- }
+ }
+
private:
cmCTestCVS* CVS;
std::vector<Revision>& Revisions;
cmsys::RegularExpression RegexRevision;
cmsys::RegularExpression RegexBranches;
cmsys::RegularExpression RegexPerson;
- enum SectionType { SectionHeader, SectionRevisions, SectionEnd };
+ enum SectionType
+ {
+ SectionHeader,
+ SectionRevisions,
+ SectionEnd
+ };
SectionType Section;
Revision Rev;
- virtual bool ProcessLine()
- {
- if(this->Line == ("======================================="
- "======================================"))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->Line == ("======================================="
+ "======================================")) {
// This line ends the revision list.
- if(this->Section == SectionRevisions)
- {
+ if (this->Section == SectionRevisions) {
this->FinishRevision();
- }
- this->Section = SectionEnd;
}
- else if(this->Line == "----------------------------")
- {
+ this->Section = SectionEnd;
+ } else if (this->Line == "----------------------------") {
// This line divides revisions from the header and each other.
- if(this->Section == SectionHeader)
- {
+ if (this->Section == SectionHeader) {
this->Section = SectionRevisions;
- }
- else if(this->Section == SectionRevisions)
- {
+ } else if (this->Section == SectionRevisions) {
this->FinishRevision();
- }
}
- else if(this->Section == SectionRevisions)
- {
- if(!this->Rev.Log.empty())
- {
+ } else if (this->Section == SectionRevisions) {
+ if (!this->Rev.Log.empty()) {
// Continue the existing log.
this->Rev.Log += this->Line;
this->Rev.Log += "\n";
- }
- else if(this->Rev.Rev.empty() && this->RegexRevision.find(this->Line))
- {
+ } else if (this->Rev.Rev.empty() &&
+ this->RegexRevision.find(this->Line)) {
this->Rev.Rev = this->RegexRevision.match(1);
- }
- else if(this->Rev.Date.empty() && this->RegexPerson.find(this->Line))
- {
+ } else if (this->Rev.Date.empty() &&
+ this->RegexPerson.find(this->Line)) {
this->Rev.Date = this->RegexPerson.match(1);
this->Rev.Author = this->RegexPerson.match(2);
- }
- else if(!this->RegexBranches.find(this->Line))
- {
+ } else if (!this->RegexBranches.find(this->Line)) {
// Start the log.
this->Rev.Log += this->Line;
this->Rev.Log += "\n";
- }
}
- return this->Section != SectionEnd;
}
+ return this->Section != SectionEnd;
+ }
void FinishRevision()
- {
- if(!this->Rev.Rev.empty())
- {
+ {
+ if (!this->Rev.Rev.empty()) {
// Record this revision.
+ /* clang-format off */
this->CVS->Log << "Found revision " << this->Rev.Rev << "\n"
<< " author = " << this->Rev.Author << "\n"
<< " date = " << this->Rev.Date << "\n";
+ /* clang-format on */
this->Revisions.push_back(this->Rev);
// We only need two revisions.
- if(this->Revisions.size() >= 2)
- {
+ if (this->Revisions.size() >= 2) {
this->Section = SectionEnd;
- }
}
- this->Rev = Revision();
}
+ this->Rev = Revision();
+ }
};
-//----------------------------------------------------------------------------
std::string cmCTestCVS::ComputeBranchFlag(std::string const& dir)
{
// Compute the tag file location for this directory.
std::string tagFile = this->SourceDirectory;
- if(!dir.empty())
- {
+ if (!dir.empty()) {
tagFile += "/";
tagFile += dir;
- }
+ }
tagFile += "/CVS/Tag";
// Lookup the branch in the tag file, if any.
std::string tagLine;
- std::ifstream tagStream(tagFile.c_str());
- if(tagStream && cmSystemTools::GetLineFromStream(tagStream, tagLine) &&
- tagLine.size() > 1 && tagLine[0] == 'T')
- {
+ cmsys::ifstream tagStream(tagFile.c_str());
+ 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);
return flag;
- }
- else
- {
- // Use the default branch.
- return "-b";
- }
+ }
+ // Use the default branch.
+ return "-b";
}
-//----------------------------------------------------------------------------
-void cmCTestCVS::LoadRevisions(std::string const& file,
- const char* branchFlag,
+void cmCTestCVS::LoadRevisions(std::string const& file, const char* branchFlag,
std::vector<Revision>& revisions)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
// 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(), 0};
+ const char* cvs_log[] = { cvs, "log", "-N",
+ branchFlag, file.c_str(), CM_NULLPTR };
LogParser out(this, "log-out> ", revisions);
OutputLogger err(this->Log, "log-err> ");
this->RunChild(cvs_log, &out, &err);
}
-//----------------------------------------------------------------------------
-void cmCTestCVS::WriteXMLDirectory(std::ostream& xml,
- std::string const& path,
+void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir)
{
- const char* slash = path.empty()? "":"/";
- xml << "\t<Directory>\n"
- << "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n";
+ const char* slash = path.empty() ? "" : "/";
+ xml.StartElement("Directory");
+ xml.Element("Name", path);
// Lookup the branch checked out in the working tree.
std::string branchFlag = this->ComputeBranchFlag(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)
- {
+ for (Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi) {
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);
- }
+ }
this->LoadRevisions(full, branchFlag.c_str(), revisions);
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);
- }
- xml << "\t</Directory>\n";
+ }
+ xml.EndElement(); // Directory
}
-//----------------------------------------------------------------------------
-bool cmCTestCVS::WriteXMLUpdates(std::ostream& xml)
+bool cmCTestCVS::WriteXMLUpdates(cmXMLWriter& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per updated file):\n"
- " " << std::flush);
+ " "
+ << std::flush);
- for(std::map<cmStdString, Directory>::const_iterator
- di = this->Dirs.begin(); di != this->Dirs.end(); ++di)
- {
+ for (std::map<std::string, Directory>::const_iterator di =
+ this->Dirs.begin();
+ di != this->Dirs.end(); ++di) {
this->WriteXMLDirectory(xml, di->first, di->second);
- }
+ }
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h
index b7fe567d8..1208cfad6 100644
--- a/Source/CTest/cmCTestCVS.h
+++ b/Source/CTest/cmCTestCVS.h
@@ -1,51 +1,55 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestCVS_h
#define cmCTestCVS_h
+#include "cmConfigure.h"
+
#include "cmCTestVC.h"
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmXMLWriter;
+
/** \class cmCTestCVS
* \brief Interaction with cvs command-line tool
*
*/
-class cmCTestCVS: public cmCTestVC
+class cmCTestCVS : public cmCTestVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestCVS(cmCTest* ctest, std::ostream& log);
- virtual ~cmCTestCVS();
+ ~cmCTestCVS() CM_OVERRIDE;
private:
// Implement cmCTestVC internal API.
- virtual bool UpdateImpl();
- virtual bool WriteXMLUpdates(std::ostream& xml);
+ bool UpdateImpl() CM_OVERRIDE;
+ bool WriteXMLUpdates(cmXMLWriter& xml) CM_OVERRIDE;
// Update status for files in each directory.
- class Directory: public std::map<cmStdString, PathStatus> {};
- std::map<cmStdString, Directory> Dirs;
+ class Directory : public std::map<std::string, PathStatus>
+ {
+ };
+ std::map<std::string, Directory> Dirs;
std::string ComputeBranchFlag(std::string const& dir);
void LoadRevisions(std::string const& file, const char* branchFlag,
std::vector<Revision>& revisions);
- void WriteXMLDirectory(std::ostream& xml, std::string const& path,
+ void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir);
// Parsing helper classes.
- class UpdateParser;
class LogParser;
- friend class UpdateParser;
+ class UpdateParser;
+
friend class LogParser;
+ friend class UpdateParser;
};
#endif
diff --git a/Source/CTest/cmCTestCommand.h b/Source/CTest/cmCTestCommand.h
index e2ebba8fd..6fc237aac 100644
--- a/Source/CTest/cmCTestCommand.h
+++ b/Source/CTest/cmCTestCommand.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestCommand_h
#define cmCTestCommand_h
@@ -27,14 +18,14 @@ class cmCTestScriptHandler;
class cmCTestCommand : public cmCommand
{
public:
-
- cmCTestCommand() {this->CTest = 0; this->CTestScriptHandler = 0;}
-
- cmCTest *CTest;
- cmCTestScriptHandler *CTestScriptHandler;
-
- cmTypeMacro(cmCTestCommand, cmCommand);
+ cmCTestCommand()
+ {
+ this->CTest = CM_NULLPTR;
+ this->CTestScriptHandler = CM_NULLPTR;
+ }
+
+ cmCTest* CTest;
+ cmCTestScriptHandler* CTestScriptHandler;
};
-
#endif
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index db33cb68e..73e893df3 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -1,24 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestConfigureCommand.h"
-#include "cmGlobalGenerator.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#include <sstream>
+#include <string.h>
+#include <vector>
cmCTestConfigureCommand::cmCTestConfigureCommand()
{
this->Arguments[ctc_OPTIONS] = "OPTIONS";
- this->Arguments[ctc_LAST] = 0;
+ this->Arguments[ctc_LAST] = CM_NULLPTR;
this->Last = ctc_LAST;
}
@@ -26,130 +24,130 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
{
std::vector<std::string> options;
- if (this->Values[ctc_OPTIONS])
- {
+ if (this->Values[ctc_OPTIONS]) {
cmSystemTools::ExpandListArgument(this->Values[ctc_OPTIONS], options);
- }
+ }
- if ( this->CTest->GetCTestConfiguration("BuildDirectory").empty() )
- {
- this->SetError("Build directory not specified. Either use BUILD "
+ if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) {
+ this->SetError(
+ "Build directory not specified. Either use BUILD "
"argument to CTEST_CONFIGURE command or set CTEST_BINARY_DIRECTORY "
"variable");
- return 0;
- }
+ return CM_NULLPTR;
+ }
- const char* ctestConfigureCommand
- = this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
+ const char* ctestConfigureCommand =
+ this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
- if ( ctestConfigureCommand && *ctestConfigureCommand )
- {
+ if (ctestConfigureCommand && *ctestConfigureCommand) {
this->CTest->SetCTestConfiguration("ConfigureCommand",
- ctestConfigureCommand);
- }
- else
- {
- const char* cmakeGeneratorName
- = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
- if ( cmakeGeneratorName && *cmakeGeneratorName )
- {
- const std::string& source_dir
- = this->CTest->GetCTestConfiguration("SourceDirectory");
- if ( source_dir.empty() )
- {
- this->SetError("Source directory not specified. Either use SOURCE "
+ ctestConfigureCommand, this->Quiet);
+ } else {
+ const char* cmakeGeneratorName =
+ this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
+ if (cmakeGeneratorName && *cmakeGeneratorName) {
+ const std::string& source_dir =
+ this->CTest->GetCTestConfiguration("SourceDirectory");
+ if (source_dir.empty()) {
+ this->SetError(
+ "Source directory not specified. Either use SOURCE "
"argument to CTEST_CONFIGURE command or set CTEST_SOURCE_DIRECTORY "
"variable");
- return 0;
- }
+ return CM_NULLPTR;
+ }
const std::string cmakelists_file = source_dir + "/CMakeLists.txt";
- if ( !cmSystemTools::FileExists(cmakelists_file.c_str()) )
- {
- cmOStringStream e;
- e << "CMakeLists.txt file does not exist ["
- << cmakelists_file << "]";
- this->SetError(e.str().c_str());
- return 0;
- }
+ if (!cmSystemTools::FileExists(cmakelists_file.c_str())) {
+ std::ostringstream e;
+ e << "CMakeLists.txt file does not exist [" << cmakelists_file << "]";
+ this->SetError(e.str());
+ return CM_NULLPTR;
+ }
bool multiConfig = false;
bool cmakeBuildTypeInOptions = false;
- cmGlobalGenerator *gg =
+ cmGlobalGenerator* gg =
this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
cmakeGeneratorName);
- if(gg)
- {
+ if (gg) {
multiConfig = gg->IsMultiConfig();
delete gg;
- }
+ }
std::string cmakeConfigureCommand = "\"";
- cmakeConfigureCommand += this->CTest->GetCMakeExecutable();
+ cmakeConfigureCommand += cmSystemTools::GetCMakeCommand();
cmakeConfigureCommand += "\"";
std::vector<std::string>::const_iterator it;
std::string option;
- for (it= options.begin(); it!=options.end(); ++it)
- {
+ for (it = options.begin(); it != options.end(); ++it) {
option = *it;
cmakeConfigureCommand += " \"";
cmakeConfigureCommand += option;
cmakeConfigureCommand += "\"";
- if ((0 != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
- (0 != strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING=")))
- {
+ if ((CM_NULLPTR != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
+ (CM_NULLPTR !=
+ strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING="))) {
cmakeBuildTypeInOptions = true;
- }
}
+ }
if (!multiConfig && !cmakeBuildTypeInOptions &&
- !this->CTest->GetConfigType().empty())
- {
+ !this->CTest->GetConfigType().empty()) {
cmakeConfigureCommand += " \"-DCMAKE_BUILD_TYPE:STRING=";
cmakeConfigureCommand += this->CTest->GetConfigType();
cmakeConfigureCommand += "\"";
- }
+ }
+
+ if (this->Makefile->IsOn("CTEST_USE_LAUNCHERS")) {
+ cmakeConfigureCommand += " \"-DCTEST_USE_LAUNCHERS:BOOL=TRUE\"";
+ }
cmakeConfigureCommand += " \"-G";
cmakeConfigureCommand += cmakeGeneratorName;
cmakeConfigureCommand += "\"";
+ const char* cmakeGeneratorPlatform =
+ this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM");
+ if (cmakeGeneratorPlatform && *cmakeGeneratorPlatform) {
+ cmakeConfigureCommand += " \"-A";
+ cmakeConfigureCommand += cmakeGeneratorPlatform;
+ cmakeConfigureCommand += "\"";
+ }
+
const char* cmakeGeneratorToolset =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET");
- if(cmakeGeneratorToolset && *cmakeGeneratorToolset)
- {
+ if (cmakeGeneratorToolset && *cmakeGeneratorToolset) {
cmakeConfigureCommand += " \"-T";
cmakeConfigureCommand += cmakeGeneratorToolset;
cmakeConfigureCommand += "\"";
- }
+ }
cmakeConfigureCommand += " \"";
cmakeConfigureCommand += source_dir;
cmakeConfigureCommand += "\"";
- this->CTest->SetCTestConfiguration("ConfigureCommand",
- cmakeConfigureCommand.c_str());
- }
- else
- {
- this->SetError("Configure command is not specified. If this is a "
+ this->CTest->SetCTestConfiguration(
+ "ConfigureCommand", cmakeConfigureCommand.c_str(), this->Quiet);
+ } else {
+ this->SetError(
+ "Configure command is not specified. If this is a "
"\"built with CMake\" project, set CTEST_CMAKE_GENERATOR. If not, "
"set CTEST_CONFIGURE_COMMAND.");
- return 0;
- }
+ return CM_NULLPTR;
}
+ }
- cmCTestGenericHandler* handler
- = this->CTest->GetInitializedHandler("configure");
- if ( !handler )
- {
+ cmCTestGenericHandler* handler =
+ this->CTest->GetInitializedHandler("configure");
+ if (!handler) {
this->SetError(
"internal CTest error. Cannot instantiate configure handler");
- return 0;
- }
+ return CM_NULLPTR;
+ }
+ handler->SetQuiet(this->Quiet);
return handler;
}
diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h
index b343fc1e9..917f5ab8b 100644
--- a/Source/CTest/cmCTestConfigureCommand.h
+++ b/Source/CTest/cmCTestConfigureCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestConfigureCommand_h
#define cmCTestConfigureCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestHandlerCommand.h"
+#include <string>
+
+class cmCTestGenericHandler;
+class cmCommand;
+
/** \class cmCTestConfigure
* \brief Run a ctest script
*
@@ -27,58 +25,28 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestConfigureCommand* ni = new cmCTestConfigureCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "ctest_configure";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Configure the project build tree.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_configure([BUILD build_dir] [SOURCE source_dir] [APPEND]\n"
- " [OPTIONS options] [RETURN_VALUE res])\n"
- "Configures the given build directory and stores results in "
- "Configure.xml. "
- "If no BUILD is given, the CTEST_BINARY_DIRECTORY variable is used. "
- "If no SOURCE is given, the CTEST_SOURCE_DIRECTORY variable is used. "
- "The OPTIONS argument specifies command line arguments to pass to "
- "the configuration tool. "
- "The RETURN_VALUE option specifies a variable in which to store the "
- "return value of the native build tool."
- "\n"
- CTEST_COMMAND_APPEND_OPTION_DOCS;
- }
-
- cmTypeMacro(cmCTestConfigureCommand, cmCTestHandlerCommand);
+ std::string GetName() const CM_OVERRIDE { return "ctest_configure"; }
protected:
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
- enum {
+ enum
+ {
ctc_FIRST = ct_LAST,
ctc_OPTIONS,
ctc_LAST
};
};
-
#endif
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index 7c4129864..5d87f3fb4 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -1,132 +1,104 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestConfigureHandler.h"
#include "cmCTest.h"
#include "cmGeneratedFileStream.h"
-#include "cmake.h"
-#include "cmXMLSafe.h"
-#include <cmsys/Process.h>
+#include "cmSystemTools.h"
+#include "cmXMLWriter.h"
+#include <ostream>
+#include <string>
-//----------------------------------------------------------------------
cmCTestConfigureHandler::cmCTestConfigureHandler()
{
}
-//----------------------------------------------------------------------
void cmCTestConfigureHandler::Initialize()
{
this->Superclass::Initialize();
}
-//----------------------------------------------------------------------
-//clearly it would be nice if this were broken up into a few smaller
-//functions and commented...
+// clearly it would be nice if this were broken up into a few smaller
+// functions and commented...
int cmCTestConfigureHandler::ProcessHandler()
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Configure project" << std::endl);
- std::string cCommand
- = this->CTest->GetCTestConfiguration("ConfigureCommand");
- if ( cCommand.size() == 0 )
- {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Configure project" << std::endl, this->Quiet);
+ std::string cCommand =
+ this->CTest->GetCTestConfiguration("ConfigureCommand");
+ if (cCommand.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find ConfigureCommand key in the DartConfiguration.tcl"
- << std::endl);
+ "Cannot find ConfigureCommand key in the DartConfiguration.tcl"
+ << std::endl);
return -1;
- }
+ }
- std::string buildDirectory
- = this->CTest->GetCTestConfiguration("BuildDirectory");
- if ( buildDirectory.size() == 0 )
- {
+ std::string buildDirectory =
+ this->CTest->GetCTestConfiguration("BuildDirectory");
+ if (buildDirectory.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find BuildDirectory key in the DartConfiguration.tcl"
- << std::endl);
+ "Cannot find BuildDirectory key in the DartConfiguration.tcl"
+ << std::endl);
return -1;
- }
+ }
double elapsed_time_start = cmSystemTools::GetTime();
std::string output;
int retVal = 0;
int res = 0;
- if ( !this->CTest->GetShowOnly() )
- {
+ if (!this->CTest->GetShowOnly()) {
cmGeneratedFileStream os;
- if(!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os))
- {
+ if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open configure file"
- << std::endl);
+ << std::endl);
return 1;
- }
+ }
std::string start_time = this->CTest->CurrentTime();
- unsigned int start_time_time = static_cast<unsigned int>(
- cmSystemTools::GetTime());
+ unsigned int start_time_time =
+ static_cast<unsigned int>(cmSystemTools::GetTime());
cmGeneratedFileStream ofs;
this->StartLogFile("Configure", ofs);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Configure with command: "
- << cCommand.c_str() << std::endl);
- res = this->CTest->RunMakeCommand(cCommand.c_str(), &output,
- &retVal, buildDirectory.c_str(),
- 0, 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);
- if ( ofs )
- {
+ if (ofs) {
ofs.close();
- }
-
- if ( os )
- {
- this->CTest->StartXML(os, this->AppendXML);
- os << "<Configure>\n"
- << "\t<StartDateTime>" << start_time << "</StartDateTime>"
- << std::endl
- << "\t<StartConfigureTime>" << start_time_time
- << "</StartConfigureTime>\n";
-
- if ( res == cmsysProcess_State_Exited && retVal )
- {
- os << retVal;
- }
- os << "<ConfigureCommand>" << cCommand.c_str() << "</ConfigureCommand>"
- << std::endl;
- cmCTestLog(this->CTest, DEBUG, "End" << std::endl);
- os << "<Log>" << cmXMLSafe(output) << "</Log>" << std::endl;
- std::string end_time = this->CTest->CurrentTime();
- os << "\t<ConfigureStatus>" << retVal << "</ConfigureStatus>\n"
- << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
- << "\t<EndConfigureTime>" <<
- static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</EndConfigureTime>\n"
- << "<ElapsedMinutes>"
- << static_cast<int>(
- (cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << "</ElapsedMinutes>"
- << "</Configure>" << std::endl;
- this->CTest->EndXML(os);
- }
}
- else
- {
- cmCTestLog(this->CTest, DEBUG, "Configure with command: " << cCommand
- << std::endl);
+
+ if (os) {
+ cmXMLWriter xml(os);
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("Configure");
+ xml.Element("StartDateTime", start_time);
+ xml.Element("StartConfigureTime", start_time_time);
+ xml.Element("ConfigureCommand", cCommand);
+ cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
+ 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.EndElement(); // Configure
+ this->CTest->EndXML(xml);
}
- if (! res || retVal )
- {
+ } else {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Configure with command: " << cCommand << std::endl,
+ this->Quiet);
+ }
+ if (!res || retVal) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error(s) when configuring the project" << std::endl);
+ "Error(s) when configuring the project" << std::endl);
return -1;
- }
+ }
return 0;
}
diff --git a/Source/CTest/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h
index d880bd7df..2b452829c 100644
--- a/Source/CTest/cmCTestConfigureHandler.h
+++ b/Source/CTest/cmCTestConfigureHandler.h
@@ -1,21 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestConfigureHandler_h
#define cmCTestConfigureHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
/** \class cmCTestConfigureHandler
* \brief A class that handles ctest -S invocations
@@ -24,16 +14,16 @@
class cmCTestConfigureHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestConfigureHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
cmCTestConfigureHandler();
- void Initialize();
+ void Initialize() CM_OVERRIDE;
};
#endif
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 72ff720d3..535da586d 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -1,72 +1,60 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCoverageCommand.h"
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
-//----------------------------------------------------------------------------
+class cmCTestGenericHandler;
+
cmCTestCoverageCommand::cmCTestCoverageCommand()
{
this->LabelsMentioned = false;
}
-//----------------------------------------------------------------------------
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
{
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "CoverageCommand", "CTEST_COVERAGE_COMMAND");
-
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "CoverageCommand", "CTEST_COVERAGE_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "CoverageExtraFlags", "CTEST_COVERAGE_EXTRA_FLAGS",
+ this->Quiet);
cmCTestCoverageHandler* handler = static_cast<cmCTestCoverageHandler*>(
this->CTest->GetInitializedHandler("coverage"));
- if ( !handler )
- {
+ if (!handler) {
this->SetError("internal CTest error. Cannot instantiate test handler");
- return 0;
- }
+ return CM_NULLPTR;
+ }
// If a LABELS option was given, select only files with the labels.
- if(this->LabelsMentioned)
- {
+ if (this->LabelsMentioned) {
handler->SetLabelFilter(this->Labels);
- }
+ }
+ handler->SetQuiet(this->Quiet);
return handler;
}
-//----------------------------------------------------------------------------
bool cmCTestCoverageCommand::CheckArgumentKeyword(std::string const& arg)
{
// Look for arguments specific to this command.
- if(arg == "LABELS")
- {
+ 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)
- {
+ 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 2fe762c45..78c4f61f6 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestCoverageCommand_h
#define cmCTestCoverageCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestHandlerCommand.h"
+#include <set>
+#include <string>
+
+class cmCTestGenericHandler;
+class cmCommand;
+
/** \class cmCTestCoverage
* \brief Run a ctest script
*
@@ -22,58 +21,31 @@
class cmCTestCoverageCommand : public cmCTestHandlerCommand
{
public:
-
cmCTestCoverageCommand();
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestCoverageCommand* ni = new cmCTestCoverageCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "ctest_coverage";}
+ std::string GetName() const CM_OVERRIDE { return "ctest_coverage"; }
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Collect coverage tool results.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_coverage([BUILD build_dir] [RETURN_VALUE res] [APPEND]\n"
- " [LABELS label1 [label2 [...]]])\n"
- "Perform the coverage of the given build directory and stores results "
- "in Coverage.xml. The second argument is a variable that will hold "
- "value."
- "\n"
- "The LABELS option filters the coverage report to include only "
- "source files labeled with at least one of the labels specified."
- "\n"
- CTEST_COMMAND_APPEND_OPTION_DOCS;
- }
-
- cmTypeMacro(cmCTestCoverageCommand, cmCTestHandlerCommand);
+ typedef cmCTestHandlerCommand Superclass;
protected:
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
- virtual bool CheckArgumentKeyword(std::string const& arg);
- virtual bool CheckArgumentValue(std::string const& arg);
+ bool CheckArgumentKeyword(std::string const& arg) CM_OVERRIDE;
+ bool CheckArgumentValue(std::string const& arg) CM_OVERRIDE;
enum
{
@@ -82,9 +54,7 @@ protected:
};
bool LabelsMentioned;
- std::set<cmStdString> Labels;
+ std::set<std::string> Labels;
};
-
#endif
-
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 20aded2b5..28fae1c7e 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -1,124 +1,109 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCoverageHandler.h"
-#include "cmParsePHPCoverage.h"
-#include "cmParseGTMCoverage.h"
-#include "cmParseCacheCoverage.h"
+
#include "cmCTest.h"
-#include "cmake.h"
-#include "cmMakefile.h"
-#include "cmSystemTools.h"
#include "cmGeneratedFileStream.h"
-#include "cmXMLSafe.h"
-
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/stl/iterator>
-#include <cmsys/stl/algorithm>
+#include "cmParseBlanketJSCoverage.h"
+#include "cmParseCacheCoverage.h"
+#include "cmParseCoberturaCoverage.h"
+#include "cmParseDelphiCoverage.h"
+#include "cmParseGTMCoverage.h"
+#include "cmParseJacocoCoverage.h"
+#include "cmParsePHPCoverage.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 <math.h>
-#include <float.h>
+#include <utility>
-#define SAFEDIV(x,y) (((y)!=0)?((x)/(y)):(0))
+class cmMakefile;
+
+#define SAFEDIV(x, y) (((y) != 0) ? ((x) / (y)) : (0))
class cmCTestRunProcess
{
public:
cmCTestRunProcess()
- {
- this->Process = cmsysProcess_New();
- this->PipeState = -1;
- this->TimeOut = -1;
- }
+ {
+ this->Process = cmsysProcess_New();
+ this->PipeState = -1;
+ this->TimeOut = -1;
+ }
~cmCTestRunProcess()
- {
- if(!(this->PipeState == -1)
- && !(this->PipeState == cmsysProcess_Pipe_None )
- && !(this->PipeState == cmsysProcess_Pipe_Timeout))
- {
- this->WaitForExit();
- }
- cmsysProcess_Delete(this->Process);
- }
+ {
+ if (!(this->PipeState == -1) &&
+ !(this->PipeState == cmsysProcess_Pipe_None) &&
+ !(this->PipeState == cmsysProcess_Pipe_Timeout)) {
+ this->WaitForExit();
+ }
+ cmsysProcess_Delete(this->Process);
+ }
void SetCommand(const char* command)
- {
- this->CommandLineStrings.clear();
- this->CommandLineStrings.push_back(command);;
- }
+ {
+ this->CommandLineStrings.clear();
+ this->CommandLineStrings.push_back(command);
+ ;
+ }
void AddArgument(const char* arg)
- {
- if(arg)
- {
- this->CommandLineStrings.push_back(arg);
- }
- }
- void SetWorkingDirectory(const char* dir)
- {
- this->WorkingDirectory = dir;
- }
- void SetTimeout(double t)
- {
- this->TimeOut = t;
+ {
+ if (arg) {
+ this->CommandLineStrings.push_back(arg);
}
+ }
+ void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
+ void SetTimeout(double 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());
- }
- args.push_back(0); // null terminate
- cmsysProcess_SetCommand(this->Process, &*args.begin());
- if(this->WorkingDirectory.size())
- {
- 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);
- }
- cmsysProcess_Execute(this->Process);
- this->PipeState = cmsysProcess_GetState(this->Process);
- // if the process is running or exited return true
- if(this->PipeState == cmsysProcess_State_Executing
- || this->PipeState == cmsysProcess_State_Exited)
- {
- return true;
- }
- return false;
- }
+ {
+ 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());
+ }
+ args.push_back(CM_NULLPTR); // null terminate
+ cmsysProcess_SetCommand(this->Process, &*args.begin());
+ 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);
+ }
+ cmsysProcess_Execute(this->Process);
+ this->PipeState = cmsysProcess_GetState(this->Process);
+ // if the process is running or exited return true
+ return this->PipeState == cmsysProcess_State_Executing ||
+ this->PipeState == cmsysProcess_State_Exited;
+ }
void SetStdoutFile(const char* fname)
- {
+ {
cmsysProcess_SetPipeFile(this->Process, cmsysProcess_Pipe_STDOUT, fname);
- }
+ }
void SetStderrFile(const char* fname)
- {
+ {
cmsysProcess_SetPipeFile(this->Process, cmsysProcess_Pipe_STDERR, fname);
- }
- int WaitForExit(double* timeout =0)
- {
- this->PipeState = cmsysProcess_WaitForExit(this->Process,
- timeout);
- return this->PipeState;
- }
- int GetProcessState() { return this->PipeState;}
+ }
+ int WaitForExit(double* timeout = CM_NULLPTR)
+ {
+ this->PipeState = cmsysProcess_WaitForExit(this->Process, timeout);
+ return this->PipeState;
+ }
+ int GetProcessState() { return this->PipeState; }
+
private:
int PipeState;
cmsysProcess* Process;
@@ -127,26 +112,21 @@ private:
double TimeOut;
};
-
-//----------------------------------------------------------------------
-
-//----------------------------------------------------------------------
cmCTestCoverageHandler::cmCTestCoverageHandler()
{
}
-//----------------------------------------------------------------------
void cmCTestCoverageHandler::Initialize()
{
this->Superclass::Initialize();
this->CustomCoverageExclude.clear();
this->SourceLabels.clear();
+ this->TargetDirs.clear();
this->LabelIdMap.clear();
this->Labels.clear();
this->LabelFilter.clear();
}
-//----------------------------------------------------------------------------
void cmCTestCoverageHandler::CleanCoverageLogFiles(std::ostream& log)
{
std::string logGlob = this->CTest->GetCTestConfiguration("BuildDirectory");
@@ -154,195 +134,172 @@ void cmCTestCoverageHandler::CleanCoverageLogFiles(std::ostream& log)
logGlob += this->CTest->GetCurrentTag();
logGlob += "/CoverageLog*";
cmsys::Glob gl;
- gl.FindFiles(logGlob.c_str());
+ 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)
- {
+ for (std::vector<std::string>::const_iterator fi = files.begin();
+ fi != files.end(); ++fi) {
log << "Removing old coverage log: " << *fi << "\n";
- cmSystemTools::RemoveFile(fi->c_str());
- }
+ cmSystemTools::RemoveFile(*fi);
+ }
}
-//----------------------------------------------------------------------
bool cmCTestCoverageHandler::StartCoverageLogFile(
cmGeneratedFileStream& covLogFile, int logFileCount)
{
char covLogFilename[1024];
sprintf(covLogFilename, "CoverageLog-%d", logFileCount);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Open file: "
- << covLogFilename << std::endl);
- if(!this->StartResultingXML(cmCTest::PartCoverage,
- covLogFilename, covLogFile))
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open log file: "
- << covLogFilename << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Open file: " << covLogFilename << std::endl,
+ this->Quiet);
+ if (!this->StartResultingXML(cmCTest::PartCoverage, covLogFilename,
+ covLogFile)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open log file: " << covLogFilename << std::endl);
return false;
- }
- std::string local_start_time = this->CTest->CurrentTime();
- this->CTest->StartXML(covLogFile, this->AppendXML);
- covLogFile << "<CoverageLog>" << std::endl
- << "\t<StartDateTime>" << local_start_time << "</StartDateTime>"
- << "\t<StartTime>"
- << static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</StartTime>"
- << std::endl;
+ }
return true;
}
-//----------------------------------------------------------------------
void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr,
- int logFileCount)
+ int logFileCount)
{
- std::string local_end_time = this->CTest->CurrentTime();
- ostr << "\t<EndDateTime>" << local_end_time << "</EndDateTime>" << std::endl
- << "\t<EndTime>" <<
- static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</EndTime>" << std::endl
- << "</CoverageLog>" << std::endl;
- this->CTest->EndXML(ostr);
char covLogFilename[1024];
sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Close file: "
- << covLogFilename << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Close file: " << covLogFilename << std::endl,
+ this->Quiet);
ostr.Close();
}
-//----------------------------------------------------------------------
+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()));
+}
+
+void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml)
+{
+ xml.Element("EndDateTime", this->CTest->CurrentTime());
+ xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
+ xml.EndElement(); // CoverageLog
+ this->CTest->EndXML(xml);
+}
+
bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
- const char* srcDir,
- const char* binDir)
+ const char* srcDir,
+ const char* binDir)
{
- if(this->IsFilteredOut(file))
- {
+ 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) )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " File " << file
- << " is excluded in CTestCustom.ctest" << std::endl;);
+ 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);
return false;
- }
}
+ }
std::string fSrcDir = cmSystemTools::CollapseFullPath(srcDir);
std::string fBinDir = cmSystemTools::CollapseFullPath(binDir);
std::string fFile = cmSystemTools::CollapseFullPath(file);
- bool sourceSubDir = cmSystemTools::IsSubDirectory(fFile.c_str(),
- fSrcDir.c_str());
- bool buildSubDir = cmSystemTools::IsSubDirectory(fFile.c_str(),
- fBinDir.c_str());
+ bool sourceSubDir = cmSystemTools::IsSubDirectory(fFile, fSrcDir);
+ bool buildSubDir = cmSystemTools::IsSubDirectory(fFile, fBinDir);
// Always check parent directory of the file.
- std::string fileDir = cmSystemTools::GetFilenamePath(fFile.c_str());
+ std::string fileDir = cmSystemTools::GetFilenamePath(fFile);
std::string checkDir;
// We also need to check the binary/source directory pair.
- if ( sourceSubDir && buildSubDir )
- {
- if ( fSrcDir.size() > fBinDir.size() )
- {
+ if (sourceSubDir && buildSubDir) {
+ if (fSrcDir.size() > fBinDir.size()) {
checkDir = fSrcDir;
- }
- else
- {
+ } else {
checkDir = fBinDir;
- }
}
- else if ( sourceSubDir )
- {
+ } else if (sourceSubDir) {
checkDir = fSrcDir;
- }
- else if ( buildSubDir )
- {
+ } else if (buildSubDir) {
checkDir = fBinDir;
- }
- std::string ndc
- = cmSystemTools::FileExistsInParentDirectories(".NoDartCoverage",
- fFile.c_str(), checkDir.c_str());
- if ( ndc.size() )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found: " << ndc.c_str()
- << " so skip coverage of " << file << std::endl);
+ }
+ std::string ndc = cmSystemTools::FileExistsInParentDirectories(
+ ".NoDartCoverage", fFile.c_str(), checkDir.c_str());
+ if (!ndc.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found: " << ndc << " so skip coverage of " << file
+ << std::endl,
+ this->Quiet);
return false;
- }
+ }
// By now checkDir should be set to parent directory of the file.
// Get the relative path to the file an apply it to the opposite directory.
// If it is the same as fileDir, then ignore, otherwise check.
std::string relPath;
- if(checkDir.size() )
- {
- relPath = cmSystemTools::RelativePath(checkDir.c_str(),
- fFile.c_str());
- }
- else
- {
+ if (!checkDir.empty()) {
+ relPath = cmSystemTools::RelativePath(checkDir.c_str(), fFile.c_str());
+ } else {
relPath = fFile;
- }
- if ( checkDir == fSrcDir )
- {
+ }
+ if (checkDir == fSrcDir) {
checkDir = fBinDir;
- }
- else
- {
+ } else {
checkDir = fSrcDir;
- }
+ }
fFile = checkDir + "/" + relPath;
- fFile = cmSystemTools::GetFilenamePath(fFile.c_str());
+ fFile = cmSystemTools::GetFilenamePath(fFile);
- if ( fileDir == fFile )
- {
+ if (fileDir == fFile) {
// This is in-source build, so we trust the previous check.
return true;
- }
-
- ndc = cmSystemTools::FileExistsInParentDirectories(".NoDartCoverage",
- fFile.c_str(), checkDir.c_str());
- if ( ndc.size() )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found: " << ndc.c_str()
- << " so skip coverage of: " << file << std::endl);
+ }
+
+ ndc = cmSystemTools::FileExistsInParentDirectories(
+ ".NoDartCoverage", fFile.c_str(), checkDir.c_str());
+ if (!ndc.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found: " << ndc << " so skip coverage of: " << file
+ << std::endl,
+ this->Quiet);
return false;
- }
+ }
// Ok, nothing in source tree, nothing in binary tree
return true;
}
-//----------------------------------------------------------------------
-//clearly it would be nice if this were broken up into a few smaller
-//functions and commented...
+// clearly it would be nice if this were broken up into a few smaller
+// functions and commented...
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() < 120) {
return error;
- }
+ }
std::string coverage_start_time = this->CTest->CurrentTime();
- unsigned int coverage_start_time_time = static_cast<unsigned int>(
- cmSystemTools::GetTime());
- std::string sourceDir
- = this->CTest->GetCTestConfiguration("SourceDirectory");
- std::string binaryDir
- = this->CTest->GetCTestConfiguration("BuildDirectory");
+ unsigned int coverage_start_time_time =
+ static_cast<unsigned int>(cmSystemTools::GetTime());
+ std::string sourceDir =
+ this->CTest->GetCTestConfiguration("SourceDirectory");
+ std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory");
this->LoadLabels();
cmGeneratedFileStream ofs;
double elapsed_time_start = cmSystemTools::GetTime();
- if ( !this->StartLogFile("Coverage", ofs) )
- {
+ if (!this->StartLogFile("Coverage", ofs)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot create LastCoverage.log file" << std::endl);
- }
+ "Cannot create LastCoverage.log file" << std::endl);
+ }
ofs << "Performing coverage: " << elapsed_time_start << std::endl;
this->CleanCoverageLogFiles(ofs);
@@ -350,376 +307,384 @@ int cmCTestCoverageHandler::ProcessHandler()
cmSystemTools::ConvertToUnixSlashes(sourceDir);
cmSystemTools::ConvertToUnixSlashes(binaryDir);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Performing coverage" << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Performing coverage" << std::endl, this->Quiet);
cmCTestCoverageHandlerContainer cont;
cont.Error = error;
cont.SourceDir = sourceDir;
cont.BinaryDir = binaryDir;
cont.OFS = &ofs;
+ cont.Quiet = this->Quiet;
// setup the regex exclude stuff
this->CustomCoverageExcludeRegex.clear();
- std::vector<cmStdString>::iterator rexIt;
- for ( rexIt = this->CustomCoverageExclude.begin();
- rexIt != this->CustomCoverageExclude.end();
- ++ rexIt )
- {
+ 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()));
- }
+ }
- if(this->HandleBullseyeCoverage(&cont))
- {
+ if (this->HandleBullseyeCoverage(&cont)) {
return cont.Error;
- }
+ }
int file_count = 0;
file_count += this->HandleGCovCoverage(&cont);
error = cont.Error;
- if ( file_count < 0 )
- {
+ if (file_count < 0) {
return error;
- }
+ }
+ file_count += this->HandleLCovCoverage(&cont);
+ error = cont.Error;
+ if (file_count < 0) {
+ return error;
+ }
file_count += this->HandleTracePyCoverage(&cont);
error = cont.Error;
- if ( file_count < 0 )
- {
+ if (file_count < 0) {
return error;
- }
+ }
file_count += this->HandlePHPCoverage(&cont);
error = cont.Error;
- if ( file_count < 0 )
- {
+ if (file_count < 0) {
return error;
- }
+ }
+ file_count += this->HandleCoberturaCoverage(&cont);
+ error = cont.Error;
+ if (file_count < 0) {
+ return error;
+ }
+
file_count += this->HandleMumpsCoverage(&cont);
error = cont.Error;
- if ( file_count < 0 )
- {
+ if (file_count < 0) {
return error;
- }
+ }
+ file_count += this->HandleJacocoCoverage(&cont);
+ error = cont.Error;
+ if (file_count < 0) {
+ return error;
+ }
+
+ file_count += this->HandleBlanketJSCoverage(&cont);
+ error = cont.Error;
+ if (file_count < 0) {
+ return error;
+ }
+
+ file_count += this->HandleDelphiCoverage(&cont);
+ error = cont.Error;
+ if (file_count < 0) {
+ return error;
+ }
std::set<std::string> uncovered = this->FindUncoveredFiles(&cont);
- if ( file_count == 0 )
- {
- cmCTestLog(this->CTest, WARNING,
+ if (file_count == 0 && this->ExtraCoverageGlobs.empty()) {
+ cmCTestOptionalLog(
+ this->CTest, WARNING,
" Cannot find any coverage files. Ignoring Coverage request."
- << std::endl);
+ << std::endl,
+ this->Quiet);
return error;
- }
+ }
cmGeneratedFileStream covSumFile;
cmGeneratedFileStream covLogFile;
+ cmXMLWriter covSumXML(covSumFile);
+ cmXMLWriter covLogXML(covLogFile);
- if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile))
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot open coverage summary file." << std::endl);
+ if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage",
+ covSumFile)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file."
+ << std::endl);
return -1;
- }
+ }
+ covSumFile.setf(std::ios::fixed, std::ios::floatfield);
+ covSumFile.precision(2);
- this->CTest->StartXML(covSumFile, this->AppendXML);
+ this->CTest->StartXML(covSumXML, this->AppendXML);
// Produce output xml files
- covSumFile << "<Coverage>" << std::endl
- << "\t<StartDateTime>" << coverage_start_time << "</StartDateTime>"
- << std::endl
- << "\t<StartTime>" << coverage_start_time_time << "</StartTime>"
- << std::endl;
+ covSumXML.StartElement("Coverage");
+ covSumXML.Element("StartDateTime", coverage_start_time);
+ covSumXML.Element("StartTime", coverage_start_time_time);
int logFileCount = 0;
- if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
- {
+ if (!this->StartCoverageLogFile(covLogFile, logFileCount)) {
return -1;
- }
+ }
+ this->StartCoverageLogXML(covLogXML);
cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator fileIterator;
int cnt = 0;
long total_tested = 0;
long total_untested = 0;
- //std::string fullSourceDir = sourceDir + "/";
- //std::string fullBinaryDir = binaryDir + "/";
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Accumulating results (each . represents one file):" << std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
+ // std::string fullSourceDir = sourceDir + "/";
+ // std::string fullBinaryDir = binaryDir + "/";
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ " Accumulating results (each . represents one file):" << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
std::vector<std::string> errorsWhileAccumulating;
file_count = 0;
- for ( fileIterator = cont.TotalCoverage.begin();
- fileIterator != cont.TotalCoverage.end();
- ++fileIterator )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
- file_count ++;
- if ( file_count % 50 == 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " processed: " << file_count
- << " out of "
- << cont.TotalCoverage.size() << std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
- }
+ for (fileIterator = cont.TotalCoverage.begin();
+ fileIterator != cont.TotalCoverage.end(); ++fileIterator) {
+ 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,
+ 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());
- if ( !shouldIDoCoverage )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- ".NoDartCoverage found, so skip coverage check for: "
- << fullFileName.c_str()
- << std::endl);
+ bool shouldIDoCoverage = this->ShouldIDoCoverage(
+ fullFileName.c_str(), sourceDir.c_str(), binaryDir.c_str());
+ if (!shouldIDoCoverage) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ ".NoDartCoverage found, so skip coverage check for: "
+ << fullFileName << std::endl,
+ this->Quiet);
continue;
- }
+ }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Process file: " << fullFileName << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Process file: " << fullFileName << std::endl,
+ this->Quiet);
- if ( !cmSystemTools::FileExists(fullFileName.c_str()) )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: "
- << fullFileName.c_str() << std::endl);
+ if (!cmSystemTools::FileExists(fullFileName.c_str())) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot find file: " << fullFileName << std::endl);
continue;
- }
+ }
- if ( ++cnt % 100 == 0 )
- {
+ if (++cnt % 100 == 0) {
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
- logFileCount ++;
- if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
- {
+ logFileCount++;
+ if (!this->StartCoverageLogFile(covLogFile, logFileCount)) {
return -1;
- }
}
+ this->StartCoverageLogXML(covLogXML);
+ }
- const std::string fileName
- = cmSystemTools::GetFilenameName(fullFileName.c_str());
+ const std::string fileName = cmSystemTools::GetFilenameName(fullFileName);
std::string shortFileName =
this->CTest->GetShortPathToFile(fullFileName.c_str());
- const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov
- = fileIterator->second;
- covLogFile << "\t<File Name=\"" << cmXMLSafe(fileName)
- << "\" FullPath=\"" << cmXMLSafe(shortFileName) << "\">\n"
- << "\t\t<Report>" << std::endl;
-
- std::ifstream ifs(fullFileName.c_str());
- if ( !ifs)
- {
- cmOStringStream ostr;
- ostr << "Cannot open source file: " << fullFileName.c_str();
+ const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov =
+ fileIterator->second;
+ covLogXML.StartElement("File");
+ covLogXML.Attribute("Name", fileName);
+ covLogXML.Attribute("FullPath", shortFileName);
+ covLogXML.StartElement("Report");
+
+ cmsys::ifstream ifs(fullFileName.c_str());
+ if (!ifs) {
+ std::ostringstream ostr;
+ ostr << "Cannot open source file: " << fullFileName;
errorsWhileAccumulating.push_back(ostr.str());
- error ++;
+ error++;
continue;
- }
+ }
int tested = 0;
int untested = 0;
cmCTestCoverageHandlerContainer::SingleFileCoverageVector::size_type cc;
std::string line;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Actually performing coverage for: " << fullFileName << std::endl);
- for ( cc= 0; cc < fcov.size(); cc ++ )
- {
- if ( !cmSystemTools::GetLineFromStream(ifs, line) &&
- cc != fcov.size() -1 )
- {
- cmOStringStream ostr;
- ostr << "Problem reading source file: " << fullFileName.c_str()
- << " line:" << cc << " out total: " << fcov.size()-1;
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Actually performing coverage for: " << fullFileName
+ << std::endl,
+ this->Quiet);
+ for (cc = 0; cc < fcov.size(); cc++) {
+ if (!cmSystemTools::GetLineFromStream(ifs, line) &&
+ cc != fcov.size() - 1) {
+ std::ostringstream ostr;
+ ostr << "Problem reading source file: " << fullFileName
+ << " line:" << cc << " out total: " << fcov.size() - 1;
errorsWhileAccumulating.push_back(ostr.str());
- error ++;
+ error++;
break;
- }
- covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc]
- << "\">"
- << cmXMLSafe(line) << "</Line>" << std::endl;
- if ( fcov[cc] == 0 )
- {
- untested ++;
- }
- else if ( fcov[cc] > 0 )
- {
- tested ++;
- }
}
- if ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
- cmOStringStream ostr;
- ostr << "Looks like there are more lines in the file: " << line;
- errorsWhileAccumulating.push_back(ostr.str());
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", cc);
+ covLogXML.Attribute("Count", fcov[cc]);
+ covLogXML.Content(line);
+ covLogXML.EndElement(); // Line
+ if (fcov[cc] == 0) {
+ untested++;
+ } else if (fcov[cc] > 0) {
+ tested++;
}
+ }
+ if (cmSystemTools::GetLineFromStream(ifs, line)) {
+ std::ostringstream ostr;
+ ostr << "Looks like there are more lines in the file: " << fullFileName;
+ errorsWhileAccumulating.push_back(ostr.str());
+ }
float cper = 0;
float cmet = 0;
- if ( tested + untested > 0 )
- {
+ if (tested + untested > 0) {
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)));
- }
+ static_cast<float>(tested + untested)));
+ cmet = (SAFEDIV(static_cast<float>(tested + 10),
+ static_cast<float>(tested + untested + 10)));
+ }
total_tested += tested;
total_untested += untested;
- covLogFile << "\t\t</Report>" << std::endl
- << "\t</File>" << std::endl;
- covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName)
- << "\" FullPath=\"" << cmXMLSafe(
- this->CTest->GetShortPathToFile(fullFileName.c_str()))
- << "\" Covered=\"" << (tested+untested > 0 ? "true":"false") << "\">\n"
- << "\t\t<LOCTested>" << tested << "</LOCTested>\n"
- << "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n"
- << "\t\t<PercentCoverage>";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cper) << "</PercentCoverage>\n"
- << "\t\t<CoverageMetric>";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cmet) << "</CoverageMetric>\n";
- this->WriteXMLLabels(covSumFile, shortFileName);
- covSumFile << "\t</File>" << std::endl;
- }
-
- //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)
- {
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
+ covSumXML.StartElement("File");
+ covSumXML.Attribute("Name", fileName);
+ covSumXML.Attribute("FullPath",
+ this->CTest->GetShortPathToFile(fullFileName.c_str()));
+ covSumXML.Attribute("Covered", tested + untested > 0 ? "true" : "false");
+ covSumXML.Element("LOCTested", tested);
+ covSumXML.Element("LOCUnTested", untested);
+ covSumXML.Element("PercentCoverage", cper);
+ covSumXML.Element("CoverageMetric", cmet);
+ this->WriteXMLLabels(covSumXML, shortFileName);
+ covSumXML.EndElement(); // File
+ }
+
+ // 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;
- covLogFile << "\t<File Name=\"" << cmXMLSafe(fileName)
- << "\" FullPath=\"" << cmXMLSafe(*i) << "\">\n"
- << "\t\t<Report>" << std::endl;
+ covLogXML.StartElement("File");
+ covLogXML.Attribute("Name", fileName);
+ covLogXML.Attribute("FullPath", *i);
+ covLogXML.StartElement("Report");
- std::ifstream ifs(fullPath.c_str());
- if (!ifs)
- {
- cmOStringStream ostr;
- ostr << "Cannot open source file: " << fullPath.c_str();
+ cmsys::ifstream ifs(fullPath.c_str());
+ if (!ifs) {
+ std::ostringstream ostr;
+ ostr << "Cannot open source file: " << fullPath;
errorsWhileAccumulating.push_back(ostr.str());
- error ++;
+ error++;
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
continue;
- }
+ }
int untested = 0;
std::string line;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Actually performing coverage for: " << i->c_str() << std::endl);
- while (cmSystemTools::GetLineFromStream(ifs, line))
- {
- covLogFile << "\t\t<Line Number=\"" << untested << "\" Count=\"0\">"
- << cmXMLSafe(line) << "</Line>" << std::endl;
- untested ++;
- }
- covLogFile << "\t\t</Report>\n\t</File>" << std::endl;
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Actually performing coverage for: " << *i << std::endl,
+ this->Quiet);
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", untested);
+ covLogXML.Attribute("Count", 0);
+ covLogXML.Content(line);
+ covLogXML.EndElement(); // Line
+ untested++;
+ }
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
total_untested += untested;
- covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName)
- << "\" FullPath=\"" << cmXMLSafe(i->c_str())
- << "\" Covered=\"true\">\n"
- << "\t\t<LOCTested>0</LOCTested>\n"
- << "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n"
- << "\t\t<PercentCoverage>0</PercentCoverage>\n"
- << "\t\t<CoverageMetric>0</CoverageMetric>\n";
- this->WriteXMLLabels(covSumFile, *i);
- covSumFile << "\t</File>" << std::endl;
- }
-
+ covSumXML.StartElement("File");
+ covSumXML.Attribute("Name", fileName);
+ covSumXML.Attribute("FullPath", *i);
+ covSumXML.Attribute("Covered", "true");
+ covSumXML.Element("LOCTested", 0);
+ covSumXML.Element("LOCUnTested", untested);
+ covSumXML.Element("PercentCoverage", 0);
+ covSumXML.Element("CoverageMetric", 0);
+ this->WriteXMLLabels(covSumXML, *i);
+ covSumXML.EndElement(); // File
+ }
+
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
- if ( errorsWhileAccumulating.size() > 0 )
- {
+ if (!errorsWhileAccumulating.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error(s) while accumulating results:" << std::endl);
+ "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->c_str() << std::endl);
- }
+ for (erIt = errorsWhileAccumulating.begin();
+ erIt != errorsWhileAccumulating.end(); ++erIt) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " " << *erIt << std::endl);
}
+ }
long total_lines = total_tested + total_untested;
- float percent_coverage = 100 * SAFEDIV(static_cast<float>(total_tested),
- static_cast<float>(total_lines));
- if ( total_lines == 0 )
- {
+ float percent_coverage = 100 *
+ SAFEDIV(static_cast<float>(total_tested), static_cast<float>(total_lines));
+ if (total_lines == 0) {
percent_coverage = 0;
- }
+ }
std::string end_time = this->CTest->CurrentTime();
- covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
- << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
- << "\t<LOC>" << total_lines << "</LOC>\n"
- << "\t<PercentCoverage>";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (percent_coverage)<< "</PercentCoverage>\n"
- << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
- << "\t<EndTime>" <<
- static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</EndTime>\n";
- covSumFile << "<ElapsedMinutes>" <<
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << "</ElapsedMinutes>"
- << "</Coverage>" << std::endl;
- this->CTest->EndXML(covSumFile);
-
- 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);
+ covSumXML.Element("LOCTested", total_tested);
+ covSumXML.Element("LOCUntested", total_untested);
+ 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.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);
ofs << "\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;
-
+ << "\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;
- if ( error )
- {
+ if (error) {
return -1;
- }
+ }
return 0;
}
-//----------------------------------------------------------------------
-void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile *mf)
+void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf)
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Add coverage exclude regular expressions." << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Add coverage exclude regular expressions." << std::endl,
+ this->Quiet);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_COVERAGE_EXCLUDE",
- this->CustomCoverageExclude);
+ this->CustomCoverageExclude);
this->CTest->PopulateCustomVector(mf, "CTEST_EXTRA_COVERAGE_GLOB",
- this->ExtraCoverageGlobs);
- std::vector<cmStdString>::iterator it;
- for ( it = this->CustomCoverageExclude.begin();
- it != this->CustomCoverageExclude.end();
- ++ it )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Add coverage exclude: "
- << it->c_str() << std::endl);
- }
- for ( it = this->ExtraCoverageGlobs.begin();
- it != this->ExtraCoverageGlobs.end(); ++it)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Add coverage glob: "
- << it->c_str() << std::endl);
- }
+ this->ExtraCoverageGlobs);
+ std::vector<std::string>::iterator it;
+ for (it = this->CustomCoverageExclude.begin();
+ it != this->CustomCoverageExclude.end(); ++it) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Add coverage exclude: " << *it << std::endl,
+ this->Quiet);
+ }
+ for (it = this->ExtraCoverageGlobs.begin();
+ it != this->ExtraCoverageGlobs.end(); ++it) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Add coverage glob: " << *it << std::endl,
+ this->Quiet);
+ }
}
-//----------------------------------------------------------------------
// Fix for issue #4971 where the case of the drive letter component of
// the filenames might be different when analyzing gcov output.
//
@@ -731,130 +696,262 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile *mf)
#define fnc(s) s
#endif
-//----------------------------------------------------------------------
-bool IsFileInDir(const std::string &infile, const std::string &indir)
+bool IsFileInDir(const std::string& infile, const std::string& indir)
{
- std::string file = cmSystemTools::CollapseFullPath(infile.c_str());
- std::string dir = cmSystemTools::CollapseFullPath(indir.c_str());
-
- if (
- file.size() > dir.size() &&
- (fnc(file.substr(0, dir.size())) == fnc(dir)) &&
- file[dir.size()] == '/'
- )
- {
- return true;
- }
+ std::string file = cmSystemTools::CollapseFullPath(infile);
+ std::string dir = cmSystemTools::CollapseFullPath(indir);
- return false;
+ return file.size() > dir.size() &&
+ fnc(file.substr(0, dir.size())) == fnc(dir) && file[dir.size()] == '/';
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::HandlePHPCoverage(
cmCTestCoverageHandlerContainer* cont)
{
cmParsePHPCoverage cov(*cont, this->CTest);
std::string coverageDir = this->CTest->GetBinaryDir() + "/xdebugCoverage";
- if(cmSystemTools::FileIsDirectory(coverageDir.c_str()))
- {
+ if (cmSystemTools::FileIsDirectory(coverageDir)) {
cov.ReadPHPCoverageDirectory(coverageDir.c_str());
- }
+ }
+ return static_cast<int>(cont->TotalCoverage.size());
+}
+
+int cmCTestCoverageHandler::HandleCoberturaCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ cmParseCoberturaCoverage cov(*cont, this->CTest);
+
+ // Assume the coverage.xml is in the binary directory
+ // check for the COBERTURADIR environment variable,
+ // if it doesn't exist or is empty, assume the
+ // binary directory is used.
+ std::string coverageXMLFile;
+ if (!cmSystemTools::GetEnv("COBERTURADIR", coverageXMLFile) ||
+ coverageXMLFile.empty()) {
+ coverageXMLFile = this->CTest->GetBinaryDir();
+ }
+ // build the find file string with the directory from above
+ coverageXMLFile += "/coverage.xml";
+
+ if (cmSystemTools::FileExists(coverageXMLFile.c_str())) {
+ // If file exists, parse it
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Parsing Cobertura XML file: " << coverageXMLFile
+ << std::endl,
+ this->Quiet);
+ cov.ReadCoverageXML(coverageXMLFile.c_str());
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find Cobertura XML file: " << coverageXMLFile
+ << std::endl,
+ this->Quiet);
+ }
return static_cast<int>(cont->TotalCoverage.size());
}
-//----------------------------------------------------------------------
+
int cmCTestCoverageHandler::HandleMumpsCoverage(
cmCTestCoverageHandlerContainer* cont)
{
// try gtm coverage
cmParseGTMCoverage cov(*cont, this->CTest);
- std::string coverageFile = this->CTest->GetBinaryDir() +
- "/gtm_coverage.mcov";
- if(cmSystemTools::FileExists(coverageFile.c_str()))
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Parsing Cache Coverage: " << coverageFile
- << std::endl);
+ std::string coverageFile =
+ this->CTest->GetBinaryDir() + "/gtm_coverage.mcov";
+ if (cmSystemTools::FileExists(coverageFile.c_str())) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Parsing Cache Coverage: " << coverageFile << std::endl,
+ this->Quiet);
cov.ReadCoverageFile(coverageFile.c_str());
return static_cast<int>(cont->TotalCoverage.size());
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Cannot find foobar GTM coverage file: " << coverageFile
- << std::endl);
- }
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find GTM coverage file: " << coverageFile
+ << std::endl,
+ this->Quiet);
cmParseCacheCoverage ccov(*cont, this->CTest);
- coverageFile = this->CTest->GetBinaryDir() +
- "/cache_coverage.cmcov";
- if(cmSystemTools::FileExists(coverageFile.c_str()))
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Parsing Cache Coverage: " << coverageFile
- << std::endl);
+ coverageFile = this->CTest->GetBinaryDir() + "/cache_coverage.cmcov";
+ if (cmSystemTools::FileExists(coverageFile.c_str())) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Parsing Cache Coverage: " << coverageFile << std::endl,
+ this->Quiet);
ccov.ReadCoverageFile(coverageFile.c_str());
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Cannot find Cache coverage file: " << coverageFile
- << std::endl);
- }
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find Cache coverage file: " << coverageFile
+ << std::endl,
+ this->Quiet);
+ }
return static_cast<int>(cont->TotalCoverage.size());
}
struct cmCTestCoverageHandlerLocale
{
cmCTestCoverageHandlerLocale()
- {
- if(const char* l = cmSystemTools::GetEnv("LC_ALL"))
- {
+ {
+ std::string l;
+ if (cmSystemTools::GetEnv("LC_ALL", l)) {
lc_all = l;
- }
- if(lc_all != "C")
- {
+ }
+ if (lc_all != "C") {
cmSystemTools::PutEnv("LC_ALL=C");
- }
}
+ }
~cmCTestCoverageHandlerLocale()
- {
- if(!lc_all.empty())
- {
- cmSystemTools::PutEnv(("LC_ALL=" + lc_all).c_str());
- }
- else
- {
+ {
+ if (!lc_all.empty()) {
+ cmSystemTools::PutEnv("LC_ALL=" + lc_all);
+ } else {
cmSystemTools::UnsetEnv("LC_ALL");
- }
}
+ }
std::string lc_all;
};
-//----------------------------------------------------------------------
+int cmCTestCoverageHandler::HandleJacocoCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ cmParseJacocoCoverage cov = cmParseJacocoCoverage(*cont, this->CTest);
+
+ // Search in the source directory.
+ cmsys::Glob g1;
+ std::vector<std::string> files;
+ g1.SetRecurse(true);
+
+ std::string SourceDir =
+ this->CTest->GetCTestConfiguration("SourceDirectory");
+ std::string coverageFile = SourceDir + "/*jacoco.xml";
+
+ g1.FindFiles(coverageFile);
+ files = g1.GetFiles();
+
+ // ...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());
+ }
+
+ if (!files.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found Jacoco Files, Performing Coverage" << std::endl,
+ this->Quiet);
+ cov.LoadCoverageData(files);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find Jacoco coverage files: " << coverageFile
+ << std::endl,
+ this->Quiet);
+ }
+ return static_cast<int>(cont->TotalCoverage.size());
+}
+
+int cmCTestCoverageHandler::HandleDelphiCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ cmParseDelphiCoverage cov = cmParseDelphiCoverage(*cont, this->CTest);
+ cmsys::Glob g;
+ std::vector<std::string> files;
+ g.SetRecurse(true);
+
+ std::string BinDir = this->CTest->GetBinaryDir();
+ std::string coverageFile = BinDir + "/*(*.pas).html";
+
+ g.FindFiles(coverageFile);
+ files = g.GetFiles();
+ if (!files.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found Delphi HTML Files, Performing Coverage"
+ << std::endl,
+ this->Quiet);
+ cov.LoadCoverageData(files);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find Delphi coverage files: " << coverageFile
+ << std::endl,
+ this->Quiet);
+ }
+ return static_cast<int>(cont->TotalCoverage.size());
+}
+
+int cmCTestCoverageHandler::HandleBlanketJSCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ cmParseBlanketJSCoverage cov = cmParseBlanketJSCoverage(*cont, this->CTest);
+ std::string SourceDir =
+ this->CTest->GetCTestConfiguration("SourceDirectory");
+
+ // Look for something other than output.json, still JSON extension.
+ std::string coverageFile = SourceDir + "/*.json";
+ cmsys::Glob g;
+ std::vector<std::string> files;
+ std::vector<std::string> blanketFiles;
+ g.FindFiles(coverageFile);
+ files = g.GetFiles();
+ // Ensure that the JSON files found are the result of the
+ // 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());
+ cmSystemTools::GetLineFromStream(in, line);
+ cmSystemTools::GetLineFromStream(in, line);
+ if (line.find("node-jscoverage") != std::string::npos) {
+ blanketFiles.push_back(files[fileEntry]);
+ }
+ }
+ // Take all files with the node-jscoverage string and parse those
+ if (!blanketFiles.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found BlanketJS output JSON, Performing Coverage"
+ << std::endl,
+ this->Quiet);
+ cov.LoadCoverageData(files);
+ } else {
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find BlanketJS coverage files: " << coverageFile << std::endl,
+ this->Quiet);
+ }
+ return static_cast<int>(cont->TotalCoverage.size());
+}
int cmCTestCoverageHandler::HandleGCovCoverage(
cmCTestCoverageHandlerContainer* cont)
{
- std::string gcovCommand
- = this->CTest->GetCTestConfiguration("CoverageCommand");
- std::string gcovExtraFlags
- = this->CTest->GetCTestConfiguration("CoverageExtraFlags");
+ std::string gcovCommand =
+ this->CTest->GetCTestConfiguration("CoverageCommand");
+ if (gcovCommand.empty()) {
+ cmCTestLog(this->CTest, WARNING, "Could not find gcov." << std::endl);
+ return 0;
+ }
+ std::string gcovExtraFlags =
+ this->CTest->GetCTestConfiguration("CoverageExtraFlags");
+
+ // Immediately skip to next coverage option since codecov is only for Intel
+ // compiler
+ if (gcovCommand == "codecov") {
+ return 0;
+ }
// Style 1
- std::string st1gcovOutputRex1
- = "[0-9]+\\.[0-9]+% of [0-9]+ (source |)lines executed in file (.*)$";
+ std::string st1gcovOutputRex1 =
+ "[0-9]+\\.[0-9]+% of [0-9]+ (source |)lines executed in file (.*)$";
std::string st1gcovOutputRex2 = "^Creating (.*\\.gcov)\\.";
cmsys::RegularExpression st1re1(st1gcovOutputRex1.c_str());
cmsys::RegularExpression st1re2(st1gcovOutputRex2.c_str());
-
// Style 2
std::string st2gcovOutputRex1 = "^File *[`'](.*)'$";
- std::string st2gcovOutputRex2
- = "Lines executed: *[0-9]+\\.[0-9]+% of [0-9]+$";
+ std::string st2gcovOutputRex2 =
+ "Lines executed: *[0-9]+\\.[0-9]+% of [0-9]+$";
std::string st2gcovOutputRex3 = "^(.*)reating [`'](.*\\.gcov)'";
std::string st2gcovOutputRex4 = "^(.*):unexpected EOF *$";
std::string st2gcovOutputRex5 = "^(.*):cannot open source file*$";
- std::string st2gcovOutputRex6
- = "^(.*):source file is newer than graph file `(.*)'$";
+ std::string st2gcovOutputRex6 =
+ "^(.*):source file is newer than graph file `(.*)'$";
cmsys::RegularExpression st2re1(st2gcovOutputRex1.c_str());
cmsys::RegularExpression st2re2(st2gcovOutputRex2.c_str());
cmsys::RegularExpression st2re3(st2gcovOutputRex3.c_str());
@@ -866,29 +963,29 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
this->FindGCovFiles(files);
std::vector<std::string>::iterator it;
- if ( files.size() == 0 )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Cannot find any GCov coverage files."
- << std::endl);
+ if (files.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find any GCov coverage files." << std::endl,
+ this->Quiet);
// No coverage files is a valid thing, so the exit code is 0
return 0;
- }
+ }
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
cmSystemTools::MakeDirectory(tempDir.c_str());
- cmSystemTools::ChangeDirectory(tempDir.c_str());
+ cmWorkingDirectory workdir(tempDir);
int gcovStyle = 0;
std::set<std::string> missingFiles;
- std::string actualSourceFile = "";
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Processing coverage (each . represents one file):" << std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
+ std::string actualSourceFile;
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ " Processing coverage (each . represents one file):" << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
int file_count = 0;
// make sure output from gcov is in English!
@@ -899,257 +996,216 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
// 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 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
+ for (it = files.begin(); it != files.end(); ++it) {
+ 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->c_str());
- std::string command = "\"" + gcovCommand + "\" " +
- gcovExtraFlags + " " +
- "-o \"" + fileDir + "\" " +
- "\"" + *it + "\"";
+ std::string fileDir = cmSystemTools::GetFilenamePath(*it);
+ std::string command = "\"" + gcovCommand + "\" " + gcovExtraFlags + " " +
+ "-o \"" + fileDir + "\" " + "\"" + *it + "\"";
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, command.c_str()
- << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ command << std::endl, this->Quiet);
- std::string output = "";
- std::string errors = "";
+ std::string output;
+ std::string errors;
int retVal = 0;
- *cont->OFS << "* Run coverage for: " << fileDir.c_str() << std::endl;
- *cont->OFS << " Command: " << command.c_str() << std::endl;
- int res = this->CTest->RunCommand(command.c_str(), &output, &errors,
- &retVal, tempDir.c_str(), 0 /*this->TimeOut*/);
-
- *cont->OFS << " Output: " << output.c_str() << std::endl;
- *cont->OFS << " Errors: " << errors.c_str() << std::endl;
- if ( ! res )
- {
+ *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*/);
+
+ *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->c_str() << std::endl);
+ "Problem running coverage on file: " << *it << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Command produced error: " << errors << std::endl);
- cont->Error ++;
+ "Command produced error: " << errors << std::endl);
+ cont->Error++;
continue;
- }
- if ( retVal != 0 )
- {
+ }
+ if (retVal != 0) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
- << retVal << " while processing: " << it->c_str() << std::endl);
+ << retVal << " while processing: " << *it << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Command produced error: " << cont->Error << std::endl);
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Command produced error: " << cont->Error << std::endl);
+ }
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
"--------------------------------------------------------------"
- << std::endl
- << output << std::endl
- << "--------------------------------------------------------------"
- << std::endl);
+ << std::endl
+ << output << std::endl
+ << "--------------------------------------------------------------"
+ << std::endl,
+ this->Quiet);
- std::vector<cmStdString> lines;
- std::vector<cmStdString>::iterator line;
+ std::vector<std::string> lines;
+ std::vector<std::string>::iterator line;
cmSystemTools::Split(output.c_str(), lines);
- for ( line = lines.begin(); line != lines.end(); ++line)
- {
+ for (line = lines.begin(); line != lines.end(); ++line) {
std::string sourceFile;
std::string gcovFile;
- cmCTestLog(this->CTest, DEBUG, "Line: [" << line->c_str() << "]"
- << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Line: [" << *line << "]" << std::endl, this->Quiet);
- if ( line->size() == 0 )
- {
+ if (line->empty()) {
// Ignore empty line; probably style 2
- }
- else if ( st1re1.find(line->c_str()) )
- {
- if ( gcovStyle == 0 )
- {
+ } else if (st1re1.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 1;
- }
- if ( gcovStyle != 1 )
- {
+ }
+ if (gcovStyle != 1) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e1"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
+ }
actualSourceFile = "";
sourceFile = st1re1.match(2);
- }
- else if ( st1re2.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+ } else if (st1re2.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 1;
- }
- if ( gcovStyle != 1 )
- {
+ }
+ if (gcovStyle != 1) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e2"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
+ }
gcovFile = st1re2.match(1);
- }
- else if ( st2re1.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+ } else if (st2re1.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 2;
- }
- if ( gcovStyle != 2 )
- {
+ }
+ if (gcovStyle != 2) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e3"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
+ }
actualSourceFile = "";
sourceFile = st2re1.match(1);
- }
- else if ( st2re2.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+ } else if (st2re2.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 2;
- }
- if ( gcovStyle != 2 )
- {
+ }
+ if (gcovStyle != 2) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e4"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
}
- else if ( st2re3.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+ } else if (st2re3.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 2;
- }
- if ( gcovStyle != 2 )
- {
+ }
+ if (gcovStyle != 2) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e5"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
+ }
gcovFile = st2re3.match(2);
- }
- else if ( st2re4.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+ } else if (st2re4.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 2;
- }
- if ( gcovStyle != 2 )
- {
+ }
+ if (gcovStyle != 2) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e6"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
-
- cmCTestLog(this->CTest, WARNING, "Warning: " << st2re4.match(1)
- << " had unexpected EOF" << std::endl);
}
- else if ( st2re5.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "Warning: " << st2re4.match(1)
+ << " had unexpected EOF" << std::endl,
+ this->Quiet);
+ } else if (st2re5.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 2;
- }
- if ( gcovStyle != 2 )
- {
+ }
+ if (gcovStyle != 2) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e7"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
-
- cmCTestLog(this->CTest, WARNING, "Warning: Cannot open file: "
- << st2re5.match(1) << std::endl);
}
- else if ( st2re6.find(line->c_str() ) )
- {
- if ( gcovStyle == 0 )
- {
+
+ cmCTestOptionalLog(this->CTest, WARNING, "Warning: Cannot open file: "
+ << st2re5.match(1) << std::endl,
+ this->Quiet);
+ } else if (st2re6.find(line->c_str())) {
+ if (gcovStyle == 0) {
gcovStyle = 2;
- }
- if ( gcovStyle != 2 )
- {
+ }
+ if (gcovStyle != 2) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e8"
- << std::endl);
- cont->Error ++;
+ << std::endl);
+ cont->Error++;
break;
- }
-
- cmCTestLog(this->CTest, WARNING, "Warning: File: " << st2re6.match(1)
- << " is newer than " << st2re6.match(2) << std::endl);
}
- else
- {
+
+ 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->c_str() << "]"
- << std::endl);
- cont->Error ++;
- //abort();
- }
+ if (*line != "No executable lines" &&
+ !cmSystemTools::StringStartsWith(line->c_str(), "Removing ")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output line: ["
+ << *line << "]" << std::endl);
+ cont->Error++;
+ // abort();
}
-
+ }
// If the last line of gcov output gave us a valid value for gcovFile,
// and we have an actualSourceFile, then insert a (or add to existing)
// SingleFileCoverageVector for actualSourceFile:
//
- if ( !gcovFile.empty() && !actualSourceFile.empty() )
- {
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector& vec
- = cont->TotalCoverage[actualSourceFile];
-
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " in gcovFile: "
- << gcovFile << std::endl);
-
- std::ifstream ifile(gcovFile.c_str());
- if ( ! ifile )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: "
- << gcovFile << std::endl);
- }
- else
- {
+ if (!gcovFile.empty() && !actualSourceFile.empty()) {
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector& vec =
+ cont->TotalCoverage[actualSourceFile];
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " in gcovFile: " << gcovFile << std::endl,
+ this->Quiet);
+
+ cmsys::ifstream ifile(gcovFile.c_str());
+ if (!ifile) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open file: " << gcovFile << std::endl);
+ } else {
long cnt = -1;
std::string nl;
- while ( cmSystemTools::GetLineFromStream(ifile, nl) )
- {
- cnt ++;
+ while (cmSystemTools::GetLineFromStream(ifile, nl)) {
+ cnt++;
- //TODO: Handle gcov 3.0 non-coverage lines
+ // TODO: Handle gcov 3.0 non-coverage lines
// Skip empty lines
- if ( !nl.size() )
- {
+ if (nl.empty()) {
continue;
- }
+ }
// Skip unused lines
- if ( nl.size() < 12 )
- {
+ if (nl.size() < 12) {
continue;
- }
+ }
// Read the coverage count from the beginning of the gcov output
// line
@@ -1160,120 +1216,364 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
// output line
std::string lineNumber = nl.substr(10, 5);
- int lineIdx = atoi(lineNumber.c_str())-1;
- if ( lineIdx >= 0 )
- {
- while ( vec.size() <= static_cast<size_t>(lineIdx) )
- {
+ int lineIdx = atoi(lineNumber.c_str()) - 1;
+ if (lineIdx >= 0) {
+ while (vec.size() <= static_cast<size_t>(lineIdx)) {
vec.push_back(-1);
- }
+ }
// Initially all entries are -1 (not used). If we get coverage
// information, increment it to 0 first.
- if ( vec[lineIdx] < 0 )
- {
- if ( cov > 0 || prefix.find("#") != prefix.npos )
- {
+ if (vec[lineIdx] < 0) {
+ if (cov > 0 || prefix.find('#') != std::string::npos) {
vec[lineIdx] = 0;
- }
}
+ }
vec[lineIdx] += cov;
- }
}
}
-
- actualSourceFile = "";
}
+ actualSourceFile = "";
+ }
- if ( !sourceFile.empty() && actualSourceFile.empty() )
- {
+ if (!sourceFile.empty() && actualSourceFile.empty()) {
gcovFile = "";
// Is it in the source dir or the binary dir?
//
- if ( IsFileInDir(sourceFile, cont->SourceDir) )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " produced s: "
- << sourceFile.c_str() << std::endl);
- *cont->OFS << " produced in source dir: " << sourceFile.c_str()
- << std::endl;
- actualSourceFile
- = cmSystemTools::CollapseFullPath(sourceFile.c_str());
- }
- else if ( IsFileInDir(sourceFile, cont->BinaryDir) )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " produced b: "
- << sourceFile.c_str() << std::endl);
- *cont->OFS << " produced in binary dir: " << sourceFile.c_str()
- << std::endl;
- actualSourceFile
- = cmSystemTools::CollapseFullPath(sourceFile.c_str());
- }
+ if (IsFileInDir(sourceFile, cont->SourceDir)) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " produced s: " << sourceFile << std::endl,
+ this->Quiet);
+ *cont->OFS << " produced in source dir: " << sourceFile
+ << std::endl;
+ actualSourceFile = cmSystemTools::CollapseFullPath(sourceFile);
+ } else if (IsFileInDir(sourceFile, cont->BinaryDir)) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " produced b: " << sourceFile << std::endl,
+ this->Quiet);
+ *cont->OFS << " produced in binary dir: " << sourceFile
+ << std::endl;
+ actualSourceFile = cmSystemTools::CollapseFullPath(sourceFile);
+ }
- if ( actualSourceFile.empty() )
- {
- if ( missingFiles.find(sourceFile) == missingFiles.end() )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Something went wrong" << std::endl);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Cannot find file: ["
- << sourceFile.c_str() << "]" << std::endl);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " in source dir: ["
- << cont->SourceDir.c_str() << "]"
- << std::endl);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " or binary dir: ["
- << cont->BinaryDir.size() << "]"
- << std::endl);
+ if (actualSourceFile.empty()) {
+ if (missingFiles.find(sourceFile) == missingFiles.end()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Something went wrong" << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Cannot find file: [" << sourceFile << "]"
+ << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " in source dir: [" << cont->SourceDir << "]"
+ << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " or binary dir: [" << cont->BinaryDir.size()
+ << "]" << std::endl,
+ this->Quiet);
*cont->OFS << " Something went wrong. Cannot find file: "
- << sourceFile.c_str()
- << " in source dir: " << cont->SourceDir.c_str()
- << " or binary dir: " << cont->BinaryDir.c_str() << std::endl;
+ << sourceFile << " in source dir: " << cont->SourceDir
+ << " or binary dir: " << cont->BinaryDir << std::endl;
missingFiles.insert(sourceFile);
- }
}
}
}
+ }
file_count++;
- if ( file_count % 50 == 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " processed: " << file_count
- << " out of " << files.size() << std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
+ if (file_count % 50 == 0) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " processed: " << file_count << " out of "
+ << files.size() << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
+ }
+ }
+
+ return file_count;
+}
+
+int cmCTestCoverageHandler::HandleLCovCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ std::string lcovCommand =
+ this->CTest->GetCTestConfiguration("CoverageCommand");
+ std::string lcovExtraFlags =
+ this->CTest->GetCTestConfiguration("CoverageExtraFlags");
+ if (lcovCommand != "codecov") {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Not a valid Intel Coverage command." << std::endl,
+ this->Quiet);
+ return 0;
+ }
+ // There is only percentage completed output from LCOV
+ std::string st2lcovOutputRex3 = "[0-9]+%";
+ cmsys::RegularExpression st2re3(st2lcovOutputRex3.c_str());
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " This is coverage command: " << lcovCommand << std::endl,
+ this->Quiet);
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " These are coverage command flags: " << lcovExtraFlags
+ << std::endl,
+ this->Quiet);
+
+ std::vector<std::string> files;
+ if (!this->FindLCovFiles(files)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error while finding LCov files.\n");
+ return 0;
+ }
+ std::vector<std::string>::iterator it;
+
+ if (files.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find any LCov coverage files." << std::endl,
+ this->Quiet);
+ // No coverage files is a valid thing, so the exit code is 0
+ return 0;
+ }
+ std::string testingDir = this->CTest->GetBinaryDir();
+
+ std::set<std::string> missingFiles;
+
+ std::string actualSourceFile;
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ " Processing coverage (each . represents one file):" << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
+ int file_count = 0;
+
+ // make sure output from lcov is in English!
+ cmCTestCoverageHandlerLocale locale_C;
+ static_cast<void>(locale_C);
+
+ // 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) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush,
+ this->Quiet);
+ std::string fileDir = cmSystemTools::GetFilenamePath(*it);
+ cmWorkingDirectory workdir(fileDir);
+ std::string command = "\"" + lcovCommand + "\" " + lcovExtraFlags + " ";
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Current coverage dir: " << fileDir << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ command << std::endl, this->Quiet);
+
+ std::string output;
+ std::string errors;
+ 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*/);
+
+ *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);
+ 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,
+ "Command produced error: " << cont->Error << std::endl);
+ }
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "--------------------------------------------------------------"
+ << std::endl
+ << output << std::endl
+ << "--------------------------------------------------------------"
+ << std::endl,
+ this->Quiet);
+
+ std::vector<std::string> lines;
+ std::vector<std::string>::iterator line;
+
+ cmSystemTools::Split(output.c_str(), lines);
+
+ for (line = lines.begin(); line != lines.end(); ++line) {
+ std::string sourceFile;
+ std::string lcovFile;
+
+ if (line->empty()) {
+ // Ignore empty line
+ }
+ // Look for LCOV files in binary directory
+ // Intel Compiler creates a CodeCoverage dir for each subfolder and
+ // each subfolder has LCOV files
+ cmsys::Glob gl;
+ gl.RecurseOn();
+ gl.RecurseThroughSymlinksOff();
+ std::string dir;
+ std::vector<std::string> lcovFiles;
+ dir = this->CTest->GetBinaryDir();
+ std::string daGlob;
+ daGlob = dir;
+ daGlob += "/*.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());
+
+ for (std::vector<std::string>::iterator a = lcovFiles.begin();
+ a != lcovFiles.end(); ++a) {
+ lcovFile = *a;
+ cmsys::ifstream srcead(lcovFile.c_str());
+ if (!srcead) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open file: " << lcovFile << std::endl);
+ }
+ std::string srcname;
+
+ int success = cmSystemTools::GetLineFromStream(srcead, srcname);
+ if (!success) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error while parsing lcov file '"
+ << lcovFile << "':"
+ << " No source file name found!" << std::endl);
+ return 0;
+ }
+ srcname = srcname.substr(18);
+ // We can directly read found LCOV files to determine the source
+ // files
+ sourceFile = srcname;
+ actualSourceFile = srcname;
+
+ for (std::vector<std::string>::iterator t = lcovFiles.begin();
+ t != lcovFiles.end(); ++t) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found LCOV File: " << *t << std::endl,
+ this->Quiet);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "SourceFile: " << sourceFile << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "lCovFile: " << lcovFile << std::endl, this->Quiet);
+
+ // If we have some LCOV files to process
+ if (!lcovFile.empty() && !actualSourceFile.empty()) {
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector& vec =
+ cont->TotalCoverage[actualSourceFile];
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " in lcovFile: " << lcovFile << std::endl,
+ this->Quiet);
+
+ cmsys::ifstream ifile(lcovFile.c_str());
+ if (!ifile) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open file: " << lcovFile << std::endl);
+ } else {
+ long cnt = -1;
+ std::string nl;
+
+ // Skip the first line
+ cmSystemTools::GetLineFromStream(ifile, nl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "File is ready, start reading." << std::endl,
+ this->Quiet);
+ while (cmSystemTools::GetLineFromStream(ifile, nl)) {
+ cnt++;
+
+ // Skip empty lines
+ if (nl.empty()) {
+ continue;
+ }
+
+ // Skip unused lines
+ if (nl.size() < 12) {
+ continue;
+ }
+
+ // Read the coverage count from the beginning of the lcov
+ // output line
+ std::string prefix = nl.substr(0, 17);
+ int cov = atoi(prefix.c_str());
+
+ // Read the line number starting at the 17th character of the
+ // lcov output line
+ std::string lineNumber = nl.substr(17, 7);
+
+ int lineIdx = atoi(lineNumber.c_str()) - 1;
+ if (lineIdx >= 0) {
+ while (vec.size() <= static_cast<size_t>(lineIdx)) {
+ vec.push_back(-1);
+ }
+
+ // Initially all entries are -1 (not used). If we get coverage
+ // information, increment it to 0 first.
+ if (vec[lineIdx] < 0) {
+ if (cov > 0 || prefix.find('#') != std::string::npos) {
+ vec[lineIdx] = 0;
+ }
+ }
+
+ vec[lineIdx] += cov;
+ }
+ }
+ }
+
+ actualSourceFile = "";
+ }
}
}
- cmSystemTools::ChangeDirectory(currentDirectory.c_str());
+ file_count++;
+
+ if (file_count % 50 == 0) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " processed: " << file_count << " out of "
+ << files.size() << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
+ }
+ }
+
return file_count;
}
-//----------------------------------------------------------------------------
void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
{
cmsys::Glob gl;
gl.RecurseOn();
gl.RecurseThroughSymlinksOff();
- for(LabelMapType::const_iterator lmi = this->TargetDirs.begin();
- lmi != this->TargetDirs.end(); ++lmi)
- {
+ for (LabelMapType::const_iterator lmi = this->TargetDirs.begin();
+ lmi != this->TargetDirs.end(); ++lmi) {
// Skip targets containing no interesting labels.
- if(!this->IntersectsFilter(lmi->second))
- {
+ if (!this->IntersectsFilter(lmi->second)) {
continue;
- }
+ }
// Coverage files appear next to their object files in the target
// support directory.
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " globbing for coverage in: " << lmi->first << std::endl);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " globbing for coverage in: " << lmi->first << std::endl, this->Quiet);
std::string daGlob = lmi->first;
daGlob += "/*.da";
gl.FindFiles(daGlob);
@@ -1282,10 +1582,42 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
daGlob += "/*.gcda";
gl.FindFiles(daGlob);
files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
- }
+ }
+}
+
+bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
+{
+ cmsys::Glob gl;
+ gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is
+ // used while compiling.
+ gl.RecurseThroughSymlinksOff();
+ std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
+ cmWorkingDirectory workdir(buildDir);
+
+ // Run profmerge to merge all *.dyn files into dpi files
+ if (!cmSystemTools::RunSingleCommand("profmerge")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Error while running profmerge.\n");
+ return false;
+ }
+
+ // DPI file should appear in build directory
+ std::string daGlob;
+ daGlob = buildDir;
+ daGlob += "/*.dpi";
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " looking for dpi files in: " << daGlob << std::endl,
+ this->Quiet);
+ if (!gl.FindFiles(daGlob)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error while finding files matching " << daGlob << std::endl);
+ return false;
+ }
+ files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Now searching in: " << daGlob << std::endl, this->Quiet);
+ return true;
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::HandleTracePyCoverage(
cmCTestCoverageHandlerContainer* cont)
{
@@ -1296,338 +1628,290 @@ int cmCTestCoverageHandler::HandleTracePyCoverage(
gl.FindFiles(daGlob);
std::vector<std::string> files = gl.GetFiles();
- if ( files.size() == 0 )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Cannot find any Python Trace.py coverage files."
- << std::endl);
+ if (files.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Cannot find any Python Trace.py coverage files."
+ << std::endl,
+ this->Quiet);
// No coverage files is a valid thing, so the exit code is 0
return 0;
- }
+ }
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
cmSystemTools::MakeDirectory(tempDir.c_str());
- cmSystemTools::ChangeDirectory(tempDir.c_str());
-
- cmSystemTools::ChangeDirectory(currentDirectory.c_str());
std::vector<std::string>::iterator fileIt;
int file_count = 0;
- for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
- {
+ for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
std::string fileName = this->FindFile(cont, *fileIt);
- if ( fileName.empty() )
- {
+ if (fileName.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find source Python file corresponding to: "
- << fileIt->c_str() << std::endl);
+ "Cannot find source Python file corresponding to: "
+ << *fileIt << std::endl);
continue;
- }
+ }
- std::string actualSourceFile
- = cmSystemTools::CollapseFullPath(fileName.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Check coverage for file: " << actualSourceFile.c_str()
- << std::endl);
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector* vec
- = &cont->TotalCoverage[actualSourceFile];
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " in file: " << fileIt->c_str() << std::endl);
- std::ifstream ifile(fileIt->c_str());
- if ( ! ifile )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: "
- << fileIt->c_str() << std::endl);
- }
- else
- {
+ std::string actualSourceFile = cmSystemTools::CollapseFullPath(fileName);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Check coverage for file: " << actualSourceFile
+ << std::endl,
+ this->Quiet);
+ 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());
+ if (!ifile) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open file: " << *fileIt << std::endl);
+ } else {
long cnt = -1;
std::string nl;
- while ( cmSystemTools::GetLineFromStream(ifile, nl) )
- {
- cnt ++;
+ while (cmSystemTools::GetLineFromStream(ifile, nl)) {
+ cnt++;
// Skip empty lines
- if ( !nl.size() )
- {
+ if (nl.empty()) {
continue;
- }
+ }
// Skip unused lines
- if ( nl.size() < 12 )
- {
+ if (nl.size() < 12) {
continue;
- }
+ }
// Read the coverage count from the beginning of the Trace.py output
// line
std::string prefix = nl.substr(0, 6);
- if ( prefix[5] != ' ' && prefix[5] != ':' )
- {
+ if (prefix[5] != ' ' && prefix[5] != ':') {
// This is a hack. We should really do something more elaborate
prefix = nl.substr(0, 7);
- if ( prefix[6] != ' ' && prefix[6] != ':' )
- {
+ if (prefix[6] != ' ' && prefix[6] != ':') {
prefix = nl.substr(0, 8);
- if ( prefix[7] != ' ' && prefix[7] != ':' )
- {
+ if (prefix[7] != ' ' && prefix[7] != ':') {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Currently the limit is maximum coverage of 999999"
- << std::endl);
- }
+ "Currently the limit is maximum coverage of 999999"
+ << std::endl);
}
}
+ }
int cov = atoi(prefix.c_str());
- if ( prefix[prefix.size()-1] != ':' )
- {
+ if (prefix[prefix.size() - 1] != ':') {
// This line does not have ':' so no coverage here. That said,
// Trace.py does not handle not covered lines versus comments etc.
// So, this will be set to 0.
cov = 0;
- }
- cmCTestLog(this->CTest, DEBUG, "Prefix: " << prefix.c_str()
- << " cov: " << cov
- << std::endl);
+ }
+ cmCTestOptionalLog(
+ this->CTest, DEBUG,
+ "Prefix: " << prefix << " cov: " << cov << std::endl, this->Quiet);
// Read the line number starting at the 10th character of the gcov
// output line
long lineIdx = cnt;
- if ( lineIdx >= 0 )
- {
- while ( vec->size() <=
- static_cast<size_t>(lineIdx) )
- {
+ if (lineIdx >= 0) {
+ while (vec->size() <= static_cast<size_t>(lineIdx)) {
vec->push_back(-1);
- }
+ }
// Initially all entries are -1 (not used). If we get coverage
// information, increment it to 0 first.
- if ( (*vec)[lineIdx] < 0 )
- {
- if ( cov >= 0 )
- {
+ if ((*vec)[lineIdx] < 0) {
+ if (cov >= 0) {
(*vec)[lineIdx] = 0;
- }
}
- (*vec)[lineIdx] += cov;
}
+ (*vec)[lineIdx] += cov;
}
}
- ++ file_count;
}
- cmSystemTools::ChangeDirectory(currentDirectory.c_str());
+ ++file_count;
+ }
return file_count;
}
-//----------------------------------------------------------------------
std::string cmCTestCoverageHandler::FindFile(
- cmCTestCoverageHandlerContainer* cont,
- std::string fileName)
+ cmCTestCoverageHandlerContainer* cont, std::string const& fileName)
{
- std::string fileNameNoE
- = cmSystemTools::GetFilenameWithoutLastExtension(fileName);
+ std::string fileNameNoE =
+ 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.c_str())) {
return fullName;
- }
+ }
fullName = cont->BinaryDir + "/" + fileNameNoE + ".py";
- if ( cmSystemTools::FileExists(fullName.c_str()) )
- {
+ if (cmSystemTools::FileExists(fullName.c_str())) {
return fullName;
- }
+ }
return "";
}
// This is a header put on each marked up source file
-namespace
-{
- const char* bullseyeHelp[] =
- {" Coverage produced by bullseye covbr tool: ",
- " www.bullseye.com/help/ref_covbr.html",
- " * An arrow --> indicates incomplete coverage.",
- " * An X indicates a function that was invoked, a switch label that ",
- " was exercised, a try-block that finished, or an exception handler ",
- " that was invoked.",
- " * A T or F indicates a boolean decision that evaluated true or false,",
- " respectively.",
- " * A t or f indicates a boolean condition within a decision if the ",
- " condition evaluated true or false, respectively.",
- " * A k indicates a constant decision or condition.",
- " * The slash / means this probe is excluded from summary results. ",
- 0};
+namespace {
+const char* bullseyeHelp[] = {
+ " Coverage produced by bullseye covbr tool: ",
+ " www.bullseye.com/help/ref_covbr.html",
+ " * An arrow --> indicates incomplete coverage.",
+ " * An X indicates a function that was invoked, a switch label that ",
+ " was exercised, a try-block that finished, or an exception handler ",
+ " that was invoked.",
+ " * A T or F indicates a boolean decision that evaluated true or false,",
+ " respectively.",
+ " * A t or f indicates a boolean condition within a decision if the ",
+ " 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
+};
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
cmCTestCoverageHandlerContainer* cont,
- std::set<cmStdString>& coveredFileNames,
- std::vector<std::string>& files,
+ std::set<std::string>& coveredFileNames, std::vector<std::string>& files,
std::vector<std::string>& filesFullPath)
{
- if(files.size() != filesFullPath.size())
- {
+ if (files.size() != filesFullPath.size()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Files and full path files not the same size?:\n");
return 0;
- }
+ }
// create the output stream for the CoverageLog-N.xml file
cmGeneratedFileStream covLogFile;
+ cmXMLWriter covLogXML(covLogFile);
int logFileCount = 0;
- if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
- {
+ if (!this->StartCoverageLogFile(covLogFile, logFileCount)) {
return -1;
- }
+ }
+ this->StartCoverageLogXML(covLogXML);
// for each file run covbr on that file to get the coverage
// information for that file
std::string outputFile;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "run covbr: "
- << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "run covbr: " << std::endl, this->Quiet);
- if(!this->RunBullseyeCommand(cont, "covbr", 0, outputFile))
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error running covbr for." << "\n");
+ if (!this->RunBullseyeCommand(cont, "covbr", CM_NULLPTR, outputFile)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "error running covbr for."
+ << "\n");
return -1;
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "covbr output in " << outputFile
- << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "covbr output in " << outputFile << std::endl,
+ this->Quiet);
// open the output file
- std::ifstream fin(outputFile.c_str());
- if(!fin)
- {
+ cmsys::ifstream fin(outputFile.c_str());
+ if (!fin) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot open coverage file: " <<
- outputFile.c_str() << std::endl);
+ "Cannot open coverage file: " << outputFile << std::endl);
return 0;
- }
- std::map<cmStdString, cmStdString> fileMap;
+ }
+ 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)
- {
+ for (std::vector<std::string>::iterator f = files.begin(); f != files.end();
+ ++f, ++fp) {
fileMap[*f] = *fp;
- }
+ }
- int count =0; // keep count of the number of files
+ int count = 0; // keep count of the number of files
// Now parse each line from the bullseye cov log file
std::string lineIn;
bool valid = false; // are we in a valid output file
- int line = 0; // line of the current file
- cmStdString file;
- while(cmSystemTools::GetLineFromStream(fin, lineIn))
- {
+ int line = 0; // line of the current file
+ std::string file;
+ while (cmSystemTools::GetLineFromStream(fin, lineIn)) {
bool startFile = false;
- if(lineIn.size() > 1 && lineIn[lineIn.size()-1] == ':')
- {
- file = lineIn.substr(0, lineIn.size()-1);
- if(coveredFileNames.find(file) != coveredFileNames.end())
- {
+ if (lineIn.size() > 1 && lineIn[lineIn.size() - 1] == ':') {
+ file = lineIn.substr(0, lineIn.size() - 1);
+ if (coveredFileNames.find(file) != coveredFileNames.end()) {
startFile = true;
- }
}
- if(startFile)
- {
+ }
+ if (startFile) {
// if we are in a valid file close it because a new one started
- if(valid)
- {
- covLogFile << "\t\t</Report>" << std::endl
- << "\t</File>" << std::endl;
- }
+ if (valid) {
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
+ }
// only allow 100 files in each log file
- if ( count != 0 && count % 100 == 0 )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "start a new log file: "
- << count
- << std::endl);
+ if (count != 0 && count % 100 == 0) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "start a new log file: " << count << std::endl,
+ this->Quiet);
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
- logFileCount ++;
- if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
- {
+ logFileCount++;
+ if (!this->StartCoverageLogFile(covLogFile, logFileCount)) {
return -1;
- }
- count++; // move on one
}
- std::map<cmStdString, cmStdString>::iterator
- i = fileMap.find(file);
+ this->StartCoverageLogXML(covLogXML);
+ count++; // move on one
+ }
+ std::map<std::string, std::string>::iterator i = fileMap.find(file);
// if the file should be covered write out the header for that file
- if(i != fileMap.end())
- {
+ if (i != fileMap.end()) {
// we have a new file so count it in the output
count++;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Produce coverage for file: "
- << file.c_str() << " " << count
- << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Produce coverage for file: " << file << " "
+ << count << std::endl,
+ this->Quiet);
// start the file output
- covLogFile << "\t<File Name=\""
- << cmXMLSafe(i->first)
- << "\" FullPath=\"" << cmXMLSafe(
- this->CTest->GetShortPathToFile(
- i->second.c_str())) << "\">" << std::endl
- << "\t\t<Report>" << std::endl;
+ covLogXML.StartElement("File");
+ covLogXML.Attribute("Name", i->first);
+ covLogXML.Attribute(
+ "FullPath", this->CTest->GetShortPathToFile(i->second.c_str()));
+ covLogXML.StartElement("Report");
// write the bullseye header
- line =0;
- for(int k =0; bullseyeHelp[k] != 0; ++k)
- {
- covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
- << cmXMLSafe(bullseyeHelp[k])
- << "</Line>" << std::endl;
+ line = 0;
+ for (int k = 0; bullseyeHelp[k] != CM_NULLPTR; ++k) {
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", line);
+ covLogXML.Attribute("Count", -1);
+ covLogXML.Content(bullseyeHelp[k]);
+ covLogXML.EndElement(); // Line
line++;
- }
- valid = true; // we are in a valid file section
}
- else
- {
+ valid = true; // we are in a valid file section
+ } else {
// this is not a file that we want coverage for
valid = false;
- }
}
+ }
// we are not at a start file, and we are in a valid file output the line
- else if(valid)
- {
- covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
- << cmXMLSafe(lineIn)
- << "</Line>" << std::endl;
+ else if (valid) {
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", line);
+ covLogXML.Attribute("Count", -1);
+ covLogXML.Content(lineIn);
+ covLogXML.EndElement(); // Line
line++;
- }
}
+ }
// if we ran out of lines a valid file then close that file
- if(valid)
- {
- covLogFile << "\t\t</Report>" << std::endl
- << "\t</File>" << std::endl;
- }
+ if (valid) {
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
+ }
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
return 1;
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::RunBullseyeCommand(
- cmCTestCoverageHandlerContainer* cont,
- const char* cmd,
- const char* arg,
+ cmCTestCoverageHandlerContainer* cont, const char* cmd, const char* arg,
std::string& outputFile)
{
std::string program = cmSystemTools::FindProgram(cmd);
- if(program.size() == 0)
- {
+ if (program.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find :" << cmd << "\n");
return 0;
- }
- if(arg)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Run : " << program.c_str() << " " << arg << "\n");
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Run : " << program.c_str() << "\n");
- }
+ }
+ if (arg) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Run : " << program << " " << arg << "\n", this->Quiet);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Run : " << program << "\n", this->Quiet);
+ }
// create a process object and start it
cmCTestRunProcess runCoverageSrc;
runCoverageSrc.SetCommand(program.c_str());
@@ -1641,52 +1925,46 @@ int cmCTestCoverageHandler::RunBullseyeCommand(
stderrFile += ".stderr";
runCoverageSrc.SetStdoutFile(stdoutFile.c_str());
runCoverageSrc.SetStderrFile(stderrFile.c_str());
- if(!runCoverageSrc.StartProcess())
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Could not run : "
- << program.c_str() << " " << arg << "\n"
- << "kwsys process state : "
- << runCoverageSrc.GetProcessState());
+ if (!runCoverageSrc.StartProcess()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Could not run : " << program << " " << arg << "\n"
+ << "kwsys process state : "
+ << runCoverageSrc.GetProcessState());
return 0;
- }
+ }
// since we set the output file names wait for it to end
runCoverageSrc.WaitForExit();
outputFile = stdoutFile;
return 1;
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::RunBullseyeSourceSummary(
cmCTestCoverageHandlerContainer* cont)
{
// Run the covsrc command and create a temp outputfile
std::string outputFile;
- if(!this->RunBullseyeCommand(cont, "covsrc", "-c", outputFile))
- {
+ if (!this->RunBullseyeCommand(cont, "covsrc", "-c", outputFile)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "error running covsrc:\n");
return 0;
- }
+ }
std::ostream& tmpLog = *cont->OFS;
// copen the Coverage.xml file in the Testing directory
cmGeneratedFileStream covSumFile;
- if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile))
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot open coverage summary file." << std::endl);
+ cmXMLWriter xml(covSumFile);
+ if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage",
+ covSumFile)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file."
+ << std::endl);
return 0;
- }
- this->CTest->StartXML(covSumFile, this->AppendXML);
+ }
+ this->CTest->StartXML(xml, this->AppendXML);
double elapsed_time_start = cmSystemTools::GetTime();
std::string coverage_start_time = this->CTest->CurrentTime();
- covSumFile << "<Coverage>" << std::endl
- << "\t<StartDateTime>"
- << coverage_start_time << "</StartDateTime>"
- << std::endl
- << "\t<StartTime>"
- << static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</StartTime>"
- << std::endl;
+ xml.StartElement("Coverage");
+ xml.Element("StartDateTime", coverage_start_time);
+ xml.Element("StartTime",
+ static_cast<unsigned int>(cmSystemTools::GetTime()));
std::string stdline;
std::string errline;
// expected output:
@@ -1703,66 +1981,53 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
double total_tested = 0;
double total_untested = 0;
double total_functions = 0;
- double percent_coverage =0;
- double number_files = 0;
+ double percent_coverage = 0;
+ double number_files = 0;
std::vector<std::string> coveredFiles;
std::vector<std::string> coveredFilesFullPath;
// Read and parse the summary output file
- std::ifstream fin(outputFile.c_str());
- if(!fin)
- {
+ cmsys::ifstream fin(outputFile.c_str());
+ if (!fin) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot open coverage summary file: " <<
- outputFile.c_str() << std::endl);
+ "Cannot open coverage summary file: " << outputFile
+ << std::endl);
return 0;
- }
- std::set<cmStdString> coveredFileNames;
- while(cmSystemTools::GetLineFromStream(fin, stdline))
- {
+ }
+ std::set<std::string> coveredFileNames;
+ while (cmSystemTools::GetLineFromStream(fin, stdline)) {
// if we have a line of output from stdout
- if(stdline.size())
- {
+ if (!stdline.empty()) {
// parse the comma separated output
- this->ParseBullsEyeCovsrcLine(stdline,
- sourceFile,
- functionsCalled,
- totalFunctions,
- percentFunction,
- branchCovered,
- totalBranches,
- percentBranch);
+ this->ParseBullsEyeCovsrcLine(
+ stdline, sourceFile, functionsCalled, totalFunctions, percentFunction,
+ branchCovered, totalBranches, percentBranch);
// The first line is the header
- if(sourceFile == "Source" || sourceFile == "Total")
- {
+ if (sourceFile == "Source" || sourceFile == "Total") {
continue;
- }
+ }
std::string file = sourceFile;
coveredFileNames.insert(file);
- if(!cmSystemTools::FileIsFullPath(sourceFile.c_str()))
- {
+ if (!cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
// file will be relative to the binary dir
file = cont->BinaryDir;
file += "/";
file += sourceFile;
- }
- file = cmSystemTools::CollapseFullPath(file.c_str());
- bool shouldIDoCoverage
- = this->ShouldIDoCoverage(file.c_str(),
- cont->SourceDir.c_str(),
- cont->BinaryDir.c_str());
- if ( !shouldIDoCoverage )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- ".NoDartCoverage found, so skip coverage check for: "
- << file.c_str()
- << std::endl);
+ }
+ file = cmSystemTools::CollapseFullPath(file);
+ bool shouldIDoCoverage = this->ShouldIDoCoverage(
+ file.c_str(), cont->SourceDir.c_str(), cont->BinaryDir.c_str());
+ if (!shouldIDoCoverage) {
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ ".NoDartCoverage found, so skip coverage check for: " << file
+ << std::endl,
+ this->Quiet);
continue;
- }
+ }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Doing coverage for: "
- << file.c_str()
- << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Doing coverage for: " << file << std::endl,
+ this->Quiet);
coveredFiles.push_back(sourceFile);
coveredFilesFullPath.push_back(file);
@@ -1772,116 +2037,89 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
total_tested += functionsCalled;
total_untested += (totalFunctions - functionsCalled);
- std::string fileName = cmSystemTools::GetFilenameName(file.c_str());
+ std::string fileName = cmSystemTools::GetFilenameName(file);
std::string shortFileName =
this->CTest->GetShortPathToFile(file.c_str());
float cper = static_cast<float>(percentBranch + percentFunction);
- if(totalBranches > 0)
- {
+ if (totalBranches > 0) {
cper /= 2.0f;
- }
- percent_coverage += cper;
+ }
+ percent_coverage += static_cast<double>(cper);
float cmet = static_cast<float>(percentFunction + percentBranch);
- if(totalBranches > 0)
- {
+ if (totalBranches > 0) {
cmet /= 2.0f;
- }
+ }
cmet /= 100.0f;
- tmpLog << stdline.c_str() << "\n";
+ tmpLog << stdline << "\n";
tmpLog << fileName << "\n";
- tmpLog << "functionsCalled: " << functionsCalled/100 << "\n";
- tmpLog << "totalFunctions: " << totalFunctions/100 << "\n";
+ tmpLog << "functionsCalled: " << functionsCalled / 100 << "\n";
+ tmpLog << "totalFunctions: " << totalFunctions / 100 << "\n";
tmpLog << "percentFunction: " << percentFunction << "\n";
tmpLog << "branchCovered: " << branchCovered << "\n";
tmpLog << "totalBranches: " << totalBranches << "\n";
tmpLog << "percentBranch: " << percentBranch << "\n";
tmpLog << "percentCoverage: " << percent_coverage << "\n";
tmpLog << "coverage metric: " << cmet << "\n";
- covSumFile << "\t<File Name=\"" << cmXMLSafe(sourceFile)
- << "\" FullPath=\"" << cmXMLSafe(shortFileName)
- << "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n"
- << "\t\t<BranchesTested>"
- << branchCovered
- << "</BranchesTested>\n"
- << "\t\t<BranchesUnTested>"
- << totalBranches - branchCovered
- << "</BranchesUnTested>\n"
- << "\t\t<FunctionsTested>"
- << functionsCalled
- << "</FunctionsTested>\n"
- << "\t\t<FunctionsUnTested>"
- << totalFunctions - functionsCalled
- << "</FunctionsUnTested>\n"
- // Hack for conversion of function to loc assume a function
- // has 100 lines of code
- << "\t\t<LOCTested>" << functionsCalled *100
- << "</LOCTested>\n"
- << "\t\t<LOCUnTested>"
- << (totalFunctions - functionsCalled)*100
- << "</LOCUnTested>\n"
- << "\t\t<PercentCoverage>";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cper) << "</PercentCoverage>\n"
- << "\t\t<CoverageMetric>";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cmet) << "</CoverageMetric>\n";
- this->WriteXMLLabels(covSumFile, shortFileName);
- covSumFile << "\t</File>" << std::endl;
- }
- }
+ xml.StartElement("File");
+ xml.Attribute("Name", sourceFile);
+ xml.Attribute("FullPath", shortFileName);
+ xml.Attribute("Covered", cmet > 0 ? "true" : "false");
+ xml.Element("BranchesTested", branchCovered);
+ xml.Element("BranchesUnTested", totalBranches - branchCovered);
+ xml.Element("FunctionsTested", functionsCalled);
+ xml.Element("FunctionsUnTested", totalFunctions - functionsCalled);
+ // Hack for conversion of function to loc assume a function
+ // has 100 lines of code
+ xml.Element("LOCTested", functionsCalled * 100);
+ xml.Element("LOCUnTested", (totalFunctions - functionsCalled) * 100);
+ xml.Element("PercentCoverage", cper);
+ xml.Element("CoverageMetric", cmet);
+ this->WriteXMLLabels(xml, shortFileName);
+ xml.EndElement(); // File
+ }
+ }
std::string end_time = this->CTest->CurrentTime();
- covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
- << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
- << "\t<LOC>" << total_functions << "</LOC>\n"
- << "\t<PercentCoverage>";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile
- << SAFEDIV(percent_coverage,number_files)<< "</PercentCoverage>\n"
- << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
- << "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</EndTime>\n";
- covSumFile
- << "<ElapsedMinutes>" <<
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << "</ElapsedMinutes>"
- << "</Coverage>" << std::endl;
- this->CTest->EndXML(covSumFile);
+ xml.Element("LOCTested", total_tested);
+ xml.Element("LOCUntested", total_untested);
+ 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.EndElement(); // Coverage
+ this->CTest->EndXML(xml);
// Now create the coverage information for each file
- return this->RunBullseyeCoverageBranch(cont,
- coveredFileNames,
- coveredFiles,
+ return this->RunBullseyeCoverageBranch(cont, coveredFileNames, coveredFiles,
coveredFilesFullPath);
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::HandleBullseyeCoverage(
cmCTestCoverageHandlerContainer* cont)
{
- const char* covfile = cmSystemTools::GetEnv("COVFILE");
- if(!covfile || strlen(covfile) == 0)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " COVFILE environment variable not found, not running "
- " bullseye\n");
+ std::string covfile;
+ if (!cmSystemTools::GetEnv("COVFILE", covfile) || covfile.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " COVFILE environment variable not found, not running "
+ " bullseye\n",
+ this->Quiet);
return 0;
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " run covsrc with COVFILE=["
- << covfile
- << "]" << std::endl);
- if(!this->RunBullseyeSourceSummary(cont))
- {
+ }
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " run covsrc with COVFILE=[" << covfile << "]" << std::endl, this->Quiet);
+ if (!this->RunBullseyeSourceSummary(cont)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error running bullseye summary.\n");
return 0;
- }
- cmCTestLog(this->CTest, DEBUG, "HandleBullseyeCoverage return 1 "
- << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "HandleBullseyeCoverage return 1 " << std::endl,
+ this->Quiet);
return 1;
}
@@ -1892,141 +2130,113 @@ bool cmCTestCoverageHandler::GetNextInt(std::string const& inputLine,
std::string::size_type start = pos;
pos = inputLine.find(',', start);
value = atoi(inputLine.substr(start, pos).c_str());
- if(pos == inputLine.npos)
- {
+ if (pos == std::string::npos) {
return true;
- }
+ }
pos++;
return true;
}
bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine(
- std::string const& inputLine,
- std::string& sourceFile,
- int& functionsCalled,
- int& totalFunctions,
- int& percentFunction,
- int& branchCovered,
- int& totalBranches,
- int& percentBranch)
+ std::string const& inputLine, std::string& sourceFile, int& functionsCalled,
+ int& totalFunctions, int& percentFunction, int& branchCovered,
+ int& totalBranches, int& percentBranch)
{
// find the first comma
std::string::size_type pos = inputLine.find(',');
- if(pos == inputLine.npos)
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing string : "
- << inputLine.c_str() << "\n");
+ if (pos == std::string::npos) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error parsing string : " << inputLine << "\n");
return false;
- }
+ }
// the source file has "" around it so extract out the file name
- sourceFile = inputLine.substr(1,pos-2);
+ sourceFile = inputLine.substr(1, pos - 2);
pos++;
- if(!this->GetNextInt(inputLine, pos, functionsCalled))
- {
+ if (!this->GetNextInt(inputLine, pos, functionsCalled)) {
return false;
- }
- if(!this->GetNextInt(inputLine, pos, totalFunctions))
- {
+ }
+ if (!this->GetNextInt(inputLine, pos, totalFunctions)) {
return false;
- }
- if(!this->GetNextInt(inputLine, pos, percentFunction))
- {
+ }
+ if (!this->GetNextInt(inputLine, pos, percentFunction)) {
return false;
- }
- if(!this->GetNextInt(inputLine, pos, branchCovered))
- {
+ }
+ if (!this->GetNextInt(inputLine, pos, branchCovered)) {
return false;
- }
- if(!this->GetNextInt(inputLine, pos, totalBranches))
- {
+ }
+ if (!this->GetNextInt(inputLine, pos, totalBranches)) {
return false;
- }
- if(!this->GetNextInt(inputLine, pos, percentBranch))
- {
+ }
+ if (!this->GetNextInt(inputLine, pos, percentBranch)) {
return false;
- }
+ }
// should be at the end now
- if(pos != inputLine.npos)
- {
+ if (pos != std::string::npos) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing input : "
- << inputLine.c_str() << " last pos not npos = " << pos <<
- "\n");
- }
+ << inputLine << " last pos not npos = " << pos << "\n");
+ }
return true;
}
-//----------------------------------------------------------------------
int cmCTestCoverageHandler::GetLabelId(std::string const& label)
{
LabelIdMapType::iterator i = this->LabelIdMap.find(label);
- if(i == this->LabelIdMap.end())
- {
+ if (i == this->LabelIdMap.end()) {
int n = int(this->Labels.size());
this->Labels.push_back(label);
LabelIdMapType::value_type entry(label, n);
i = this->LabelIdMap.insert(entry).first;
- }
+ }
return i->second;
}
-//----------------------------------------------------------------------
void cmCTestCoverageHandler::LoadLabels()
{
std::string fileList = this->CTest->GetBinaryDir();
fileList += cmake::GetCMakeFilesDirectory();
fileList += "/TargetDirectories.txt";
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " target directory list [" << fileList << "]\n");
- std::ifstream finList(fileList.c_str());
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " target directory list [" << fileList << "]\n",
+ this->Quiet);
+ cmsys::ifstream finList(fileList.c_str());
std::string line;
- while(cmSystemTools::GetLineFromStream(finList, line))
- {
+ while (cmSystemTools::GetLineFromStream(finList, line)) {
this->LoadLabels(line.c_str());
- }
+ }
}
-//----------------------------------------------------------------------
void cmCTestCoverageHandler::LoadLabels(const char* dir)
{
LabelSet& dirLabels = this->TargetDirs[dir];
std::string fname = dir;
fname += "/Labels.txt";
- std::ifstream fin(fname.c_str());
- if(!fin)
- {
+ cmsys::ifstream fin(fname.c_str());
+ if (!fin) {
return;
- }
+ }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " loading labels from [" << fname << "]\n");
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " loading labels from [" << fname << "]\n", this->Quiet);
bool inTarget = true;
std::string source;
std::string line;
std::vector<int> targetLabels;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- if(line.empty() || line[0] == '#')
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (line.empty() || line[0] == '#') {
// Ignore blank and comment lines.
continue;
- }
- else if(line[0] == ' ')
- {
+ }
+ if (line[0] == ' ') {
// Label lines appear indented by one space.
std::string label = line.substr(1);
int id = this->GetLabelId(label);
dirLabels.insert(id);
- if(inTarget)
- {
+ if (inTarget) {
targetLabels.push_back(id);
- }
- else
- {
+ } else {
this->SourceLabels[source].insert(id);
- }
}
- else
- {
+ } else {
// Non-indented lines specify a source file name. The first one
// is the end of the target-wide labels.
inTarget = false;
@@ -2035,117 +2245,96 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
// Label the source with the target labels.
LabelSet& labelSet = this->SourceLabels[source];
- for(std::vector<int>::const_iterator li = targetLabels.begin();
- li != targetLabels.end(); ++li)
- {
- labelSet.insert(*li);
- }
- }
+ labelSet.insert(targetLabels.begin(), targetLabels.end());
}
+ }
}
-//----------------------------------------------------------------------
-void cmCTestCoverageHandler::WriteXMLLabels(std::ofstream& os,
+void cmCTestCoverageHandler::WriteXMLLabels(cmXMLWriter& xml,
std::string const& source)
{
LabelMapType::const_iterator li = this->SourceLabels.find(source);
- if(li != this->SourceLabels.end() && !li->second.empty())
- {
- os << "\t\t<Labels>\n";
- for(LabelSet::const_iterator lsi = li->second.begin();
- lsi != li->second.end(); ++lsi)
- {
- os << "\t\t\t<Label>" << cmXMLSafe(this->Labels[*lsi]) << "</Label>\n";
- }
- os << "\t\t</Labels>\n";
- }
+ 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]);
+ }
+ xml.EndElement(); // Labels
+ }
}
-//----------------------------------------------------------------------------
-void
-cmCTestCoverageHandler::SetLabelFilter(std::set<cmStdString> const& labels)
+void cmCTestCoverageHandler::SetLabelFilter(
+ std::set<std::string> const& labels)
{
this->LabelFilter.clear();
- for(std::set<cmStdString>::const_iterator li = labels.begin();
- li != labels.end(); ++li)
- {
+ for (std::set<std::string>::const_iterator li = labels.begin();
+ li != labels.end(); ++li) {
this->LabelFilter.insert(this->GetLabelId(*li));
- }
+ }
}
-//----------------------------------------------------------------------
bool cmCTestCoverageHandler::IntersectsFilter(LabelSet const& labels)
{
// If there is no label filter then nothing is filtered out.
- if(this->LabelFilter.empty())
- {
+ if (this->LabelFilter.empty()) {
return true;
- }
+ }
std::vector<int> ids;
- cmsys_stl::set_intersection
- (labels.begin(), labels.end(),
- this->LabelFilter.begin(), this->LabelFilter.end(),
- cmsys_stl::back_inserter(ids));
+ std::set_intersection(labels.begin(), labels.end(),
+ this->LabelFilter.begin(), this->LabelFilter.end(),
+ std::back_inserter(ids));
return !ids.empty();
}
-//----------------------------------------------------------------------
bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source)
{
// If there is no label filter then nothing is filtered out.
- if(this->LabelFilter.empty())
- {
+ if (this->LabelFilter.empty()) {
return false;
- }
+ }
// 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);
- if(li != this->SourceLabels.end())
- {
+ if (li != this->SourceLabels.end()) {
return !this->IntersectsFilter(li->second);
- }
+ }
return true;
}
-//----------------------------------------------------------------------
std::set<std::string> cmCTestCoverageHandler::FindUncoveredFiles(
cmCTestCoverageHandlerContainer* cont)
{
std::set<std::string> extraMatches;
- for(std::vector<cmStdString>::iterator i = this->ExtraCoverageGlobs.begin();
- i != this->ExtraCoverageGlobs.end(); ++i)
- {
+ for (std::vector<std::string>::iterator i = this->ExtraCoverageGlobs.begin();
+ i != this->ExtraCoverageGlobs.end(); ++i) {
cmsys::Glob gl;
gl.RecurseOn();
gl.RecurseThroughSymlinksOff();
std::string glob = cont->SourceDir + "/" + *i;
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::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()));
}
}
+ }
- if(extraMatches.size())
- {
- for(cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator i =
- cont->TotalCoverage.begin(); i != cont->TotalCoverage.end(); ++i)
- {
- std::string shortPath = this->CTest->GetShortPathToFile(
- i->first.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());
extraMatches.erase(shortPath);
- }
}
+ }
return extraMatches;
}
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 92b0b2285..933f60660 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -1,25 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestCoverageHandler_h
#define cmCTestCoverageHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
class cmGeneratedFileStream;
+class cmMakefile;
+class cmXMLWriter;
+
class cmCTestCoverageHandlerContainer
{
public:
@@ -30,73 +28,87 @@ public:
typedef std::map<std::string, SingleFileCoverageVector> TotalCoverageMap;
TotalCoverageMap TotalCoverage;
std::ostream* OFS;
+ bool Quiet;
};
/** \class cmCTestCoverageHandler
- * \brief A class that handles coverage computaiton for ctest
+ * \brief A class that handles coverage computation for ctest
*
*/
class cmCTestCoverageHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestCoverageHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
cmCTestCoverageHandler();
- virtual void Initialize();
+ void Initialize() CM_OVERRIDE;
/**
* This method is called when reading CTest custom file
*/
- void PopulateCustomVectors(cmMakefile *mf);
+ void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
/** Report coverage only for sources with these labels. */
- void SetLabelFilter(std::set<cmStdString> const& labels);
+ void SetLabelFilter(std::set<std::string> const& labels);
private:
bool ShouldIDoCoverage(const char* file, const char* srcDir,
- const char* binDir);
+ const char* binDir);
void CleanCoverageLogFiles(std::ostream& log);
bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
+ void StartCoverageLogXML(cmXMLWriter& xml);
+ void EndCoverageLogXML(cmXMLWriter& xml);
+
//! Handle coverage using GCC's GCov
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
void FindGCovFiles(std::vector<std::string>& files);
+ //! Handle coverage using Intel's LCov
+ int HandleLCovCoverage(cmCTestCoverageHandlerContainer* cont);
+ bool FindLCovFiles(std::vector<std::string>& files);
+
//! Handle coverage using xdebug php coverage
int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
+
+ //! Handle coverage for Python with coverage.py
+ int HandleCoberturaCoverage(cmCTestCoverageHandlerContainer* cont);
+
//! Handle coverage for mumps
int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
+ //! Handle coverage for Jacoco
+ int HandleJacocoCoverage(cmCTestCoverageHandlerContainer* cont);
+
+ //! Handle coverage for Delphi (Pascal)
+ int HandleDelphiCoverage(cmCTestCoverageHandlerContainer* cont);
+
+ //! Handle coverage for Jacoco
+ int HandleBlanketJSCoverage(cmCTestCoverageHandlerContainer* cont);
+
//! Handle coverage using Bullseye
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
int RunBullseyeSourceSummary(cmCTestCoverageHandlerContainer* cont);
int RunBullseyeCoverageBranch(cmCTestCoverageHandlerContainer* cont,
- std::set<cmStdString>& coveredFileNames,
+ std::set<std::string>& coveredFileNames,
std::vector<std::string>& files,
std::vector<std::string>& filesFullPath);
- int RunBullseyeCommand(
- cmCTestCoverageHandlerContainer* cont,
- const char* cmd,
- const char* arg,
- std::string& outputFile);
- bool ParseBullsEyeCovsrcLine(
- std::string const& inputLine,
- std::string& sourceFile,
- int& functionsCalled,
- int& totalFunctions,
- int& percentFunction,
- int& branchCovered,
- int& totalBranches,
- int& percentBranch);
- bool GetNextInt(std::string const& inputLine,
- std::string::size_type& pos,
+ int RunBullseyeCommand(cmCTestCoverageHandlerContainer* cont,
+ const char* cmd, const char* arg,
+ std::string& outputFile);
+ bool ParseBullsEyeCovsrcLine(std::string const& inputLine,
+ std::string& sourceFile, int& functionsCalled,
+ int& totalFunctions, int& percentFunction,
+ int& branchCovered, int& totalBranches,
+ int& percentBranch);
+ bool GetNextInt(std::string const& inputLine, std::string::size_type& pos,
int& value);
//! Handle Python coverage using Python's Trace.py
int HandleTracePyCoverage(cmCTestCoverageHandlerContainer* cont);
@@ -104,23 +116,24 @@ private:
// Find the source file based on the source and build tree. This is used for
// Trace.py mode, since that one does not tell us where the source file is.
std::string FindFile(cmCTestCoverageHandlerContainer* cont,
- std::string fileName);
+ std::string const& fileName);
std::set<std::string> FindUncoveredFiles(
cmCTestCoverageHandlerContainer* cont);
- std::vector<cmStdString> CustomCoverageExclude;
+ std::vector<std::string> CustomCoverageExclude;
std::vector<cmsys::RegularExpression> CustomCoverageExcludeRegex;
- std::vector<cmStdString> ExtraCoverageGlobs;
-
+ std::vector<std::string> ExtraCoverageGlobs;
// Map from source file to label ids.
- class LabelSet: public std::set<int> {};
- typedef std::map<cmStdString, LabelSet> LabelMapType;
+ class LabelSet : public std::set<int>
+ {
+ };
+ typedef std::map<std::string, LabelSet> LabelMapType;
LabelMapType SourceLabels;
LabelMapType TargetDirs;
// Map from label name to label id.
- typedef std::map<cmStdString, int> LabelIdMapType;
+ typedef std::map<std::string, int> LabelIdMapType;
LabelIdMapType LabelIdMap;
std::vector<std::string> Labels;
int GetLabelId(std::string const& label);
@@ -128,7 +141,7 @@ private:
// Label reading and writing methods.
void LoadLabels();
void LoadLabels(const char* dir);
- void WriteXMLLabels(std::ofstream& os, std::string const& source);
+ void WriteXMLLabels(cmXMLWriter& xml, std::string const& source);
// Label-based filtering.
std::set<int> LabelFilter;
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
new file mode 100644
index 000000000..b80ea5ade
--- /dev/null
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -0,0 +1,276 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestCurl.h"
+
+#include "cmCTest.h"
+#include "cmSystemTools.h"
+
+#include "cmConfigure.h"
+#include <ostream>
+#include <stdio.h>
+
+cmCTestCurl::cmCTestCurl(cmCTest* ctest)
+{
+ this->CTest = ctest;
+ this->SetProxyType();
+ this->UseHttp10 = false;
+ // In windows, this will init the winsock stuff
+ ::curl_global_init(CURL_GLOBAL_ALL);
+ // default is to verify https
+ this->VerifyPeerOff = false;
+ this->VerifyHostOff = false;
+ this->Quiet = false;
+ this->TimeOutSeconds = 0;
+ this->Curl = curl_easy_init();
+}
+
+cmCTestCurl::~cmCTestCurl()
+{
+ ::curl_easy_cleanup(this->Curl);
+ ::curl_global_cleanup();
+}
+
+std::string cmCTestCurl::Escape(std::string const& source)
+{
+ char* data1 = curl_easy_escape(this->Curl, source.c_str(), 0);
+ std::string ret = data1;
+ curl_free(data1);
+ return ret;
+}
+
+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);
+ const char* chPtr = static_cast<char*>(ptr);
+ vec->insert(vec->end(), 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);
+
+ 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") {
+ this->VerifyPeerOff = true;
+ }
+ if (*i == "CURLOPT_SSL_VERIFYHOST_OFF") {
+ this->VerifyHostOff = true;
+ }
+ }
+}
+
+bool cmCTestCurl::InitCurl()
+{
+ if (!this->Curl) {
+ return false;
+ }
+ if (this->VerifyPeerOff) {
+ curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+ if (this->VerifyHostOff) {
+ curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+ if (!this->HTTPProxy.empty()) {
+ curl_easy_setopt(this->Curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
+ curl_easy_setopt(this->Curl, CURLOPT_PROXYTYPE, this->HTTPProxyType);
+ if (!this->HTTPProxyAuth.empty()) {
+ curl_easy_setopt(this->Curl, CURLOPT_PROXYUSERPWD,
+ this->HTTPProxyAuth.c_str());
+ }
+ }
+ if (this->UseHttp10) {
+ curl_easy_setopt(this->Curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ }
+ // enable HTTP ERROR parsing
+ curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
+
+ // if there is little to no activity for too long stop submitting
+ if (this->TimeOutSeconds) {
+ curl_easy_setopt(this->Curl, CURLOPT_LOW_SPEED_LIMIT, 1);
+ curl_easy_setopt(this->Curl, CURLOPT_LOW_SPEED_TIME, this->TimeOutSeconds);
+ }
+
+ return true;
+}
+
+bool cmCTestCurl::UploadFile(std::string const& local_file,
+ std::string const& url, std::string const& fields,
+ std::string& response)
+{
+ response = "";
+ if (!this->InitCurl()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Initialization of curl failed");
+ return false;
+ }
+ /* enable uploading */
+ curl_easy_setopt(this->Curl, CURLOPT_UPLOAD, 1);
+
+ /* HTTP PUT please */
+ ::curl_easy_setopt(this->Curl, CURLOPT_PUT, 1);
+ ::curl_easy_setopt(this->Curl, CURLOPT_VERBOSE, 1);
+
+ FILE* ftpfile = cmsys::SystemTools::Fopen(local_file, "rb");
+ if (!ftpfile) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Could not open file for upload: " << local_file << "\n");
+ return false;
+ }
+ // set the url
+ std::string upload_url = url;
+ upload_url += "?";
+ upload_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);
+ unsigned long filelen = cmSystemTools::FileLength(local_file);
+ // and give the size of the upload (optional)
+ ::curl_easy_setopt(this->Curl, CURLOPT_INFILESIZE,
+ static_cast<long>(filelen));
+ ::curl_easy_setopt(this->Curl, CURLOPT_WRITEFUNCTION,
+ curlWriteMemoryCallback);
+ ::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");
+ // 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,
+ this->Quiet);
+ 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_FAILONERROR, 1);
+ // Now run off and do what you've been told!
+ ::curl_easy_perform(this->Curl);
+ ::fclose(ftpfile);
+ ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, NULL);
+ ::curl_slist_free_all(headers);
+
+ if (!responseData.empty()) {
+ response = std::string(responseData.begin(), responseData.end());
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Curl response: [" << response << "]\n", this->Quiet);
+ }
+ std::string curlDebug;
+ if (!debugData.empty()) {
+ curlDebug = std::string(debugData.begin(), debugData.end());
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Curl debug: [" << curlDebug << "]\n", this->Quiet);
+ }
+ if (response.empty()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "No response from server.\n"
+ << curlDebug);
+ return false;
+ }
+ return true;
+}
+
+bool cmCTestCurl::HttpRequest(std::string const& url,
+ std::string const& fields, std::string& response)
+{
+ response = "";
+ cmCTestOptionalLog(this->CTest, DEBUG, "HttpRequest\n"
+ << "url: " << url << "\n"
+ << "fields " << fields << "\n",
+ this->Quiet);
+ if (!this->InitCurl()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Initialization of curl failed");
+ return false;
+ }
+ curl_easy_setopt(this->Curl, CURLOPT_POST, 1);
+ curl_easy_setopt(this->Curl, CURLOPT_POSTFIELDS, fields.c_str());
+ ::curl_easy_setopt(this->Curl, CURLOPT_URL, url.c_str());
+ ::curl_easy_setopt(this->Curl, CURLOPT_FOLLOWLOCATION, 1);
+ // set response options
+ ::curl_easy_setopt(this->Curl, CURLOPT_WRITEFUNCTION,
+ curlWriteMemoryCallback);
+ ::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_FAILONERROR, 1);
+
+ // Add headers if any were specified.
+ struct curl_slist* headers = CM_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,
+ this->Quiet);
+ headers = ::curl_slist_append(headers, h->c_str());
+ }
+ }
+
+ ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers);
+ CURLcode res = ::curl_easy_perform(this->Curl);
+ ::curl_slist_free_all(headers);
+
+ if (!responseData.empty()) {
+ response = std::string(responseData.begin(), responseData.end());
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Curl response: [" << response << "]\n", this->Quiet);
+ }
+ if (!debugData.empty()) {
+ std::string curlDebug = std::string(debugData.begin(), debugData.end());
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Curl debug: [" << curlDebug << "]\n", this->Quiet);
+ }
+ cmCTestOptionalLog(this->CTest, DEBUG, "Curl res: " << res << "\n",
+ this->Quiet);
+ return (res == 0);
+}
+
+void cmCTestCurl::SetProxyType()
+{
+ this->HTTPProxy = "";
+ // this is the default
+ this->HTTPProxyType = CURLPROXY_HTTP;
+ this->HTTPProxyAuth = "";
+ if (cmSystemTools::GetEnv("HTTP_PROXY", this->HTTPProxy)) {
+ std::string port;
+ if (cmSystemTools::GetEnv("HTTP_PROXY_PORT", port)) {
+ this->HTTPProxy += ":";
+ this->HTTPProxy += port;
+ }
+ std::string type;
+ if (cmSystemTools::GetEnv("HTTP_PROXY_TYPE", type)) {
+ // HTTP/SOCKS4/SOCKS5
+ if (type == "HTTP") {
+ this->HTTPProxyType = CURLPROXY_HTTP;
+ } else if (type == "SOCKS4") {
+ this->HTTPProxyType = CURLPROXY_SOCKS4;
+ } else if (type == "SOCKS5") {
+ this->HTTPProxyType = CURLPROXY_SOCKS5;
+ }
+ }
+ cmSystemTools::GetEnv("HTTP_PROXY_USER", this->HTTPProxyAuth);
+ std::string passwd;
+ if (cmSystemTools::GetEnv("HTTP_PROXY_PASSWD", passwd)) {
+ this->HTTPProxyAuth += ":";
+ this->HTTPProxyAuth += passwd;
+ }
+ }
+}
diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h
new file mode 100644
index 000000000..427a39232
--- /dev/null
+++ b/Source/CTest/cmCTestCurl.h
@@ -0,0 +1,53 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCTestCurl_h
+#define cmCTestCurl_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_curl.h"
+#include <string>
+#include <vector>
+
+class cmCTest;
+
+class cmCTestCurl
+{
+public:
+ cmCTestCurl(cmCTest*);
+ ~cmCTestCurl();
+ bool UploadFile(std::string const& url, std::string const& file,
+ std::string const& fields, std::string& response);
+ bool HttpRequest(std::string const& url, std::string const& fields,
+ std::string& response);
+ // currently only supports CURLOPT_SSL_VERIFYPEER_OFF
+ // and CURLOPT_SSL_VERIFYHOST_OFF
+ void SetCurlOptions(std::vector<std::string> const& args);
+ void SetHttpHeaders(std::vector<std::string> const& v)
+ {
+ this->HttpHeaders = v;
+ }
+ void SetUseHttp10On() { this->UseHttp10 = true; }
+ void SetTimeOutSeconds(int s) { this->TimeOutSeconds = s; }
+ void SetQuiet(bool b) { this->Quiet = b; }
+ std::string Escape(std::string const& source);
+
+protected:
+ void SetProxyType();
+ bool InitCurl();
+
+private:
+ cmCTest* CTest;
+ CURL* Curl;
+ std::vector<std::string> HttpHeaders;
+ std::string HTTPProxyAuth;
+ std::string HTTPProxy;
+ curl_proxytype HTTPProxyType;
+ bool VerifyHostOff;
+ bool VerifyPeerOff;
+ bool UseHttp10;
+ bool Quiet;
+ int TimeOutSeconds;
+};
+
+#endif
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
index abc33de68..f4531a1ee 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
@@ -1,36 +1,27 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestEmptyBinaryDirectoryCommand.h"
#include "cmCTestScriptHandler.h"
-bool cmCTestEmptyBinaryDirectoryCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+#include <sstream>
+
+class cmExecutionStatus;
+
+bool cmCTestEmptyBinaryDirectoryCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus& /*unused*/)
{
- if(args.size() != 1 )
- {
+ if (args.size() != 1) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- if ( !cmCTestScriptHandler::EmptyBinaryDirectory(args[0].c_str()) )
- {
- cmOStringStream ostr;
- ostr << "problem removing the binary directory: " << args[0].c_str();
- this->SetError(ostr.str().c_str());
+ if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0].c_str())) {
+ std::ostringstream ostr;
+ ostr << "problem removing the binary directory: " << args[0];
+ this->SetError(ostr.str());
return false;
- }
+ }
return true;
}
-
-
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
index a763fe9e9..503ed234d 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestEmptyBinaryDirectoryCommand_h
#define cmCTestEmptyBinaryDirectoryCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestCommand.h"
+#include <string>
+#include <vector>
+
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmCTestEmptyBinaryDirectory
* \brief Run a ctest script
*
@@ -23,56 +22,26 @@
class cmCTestEmptyBinaryDirectoryCommand : public cmCTestCommand
{
public:
-
cmCTestEmptyBinaryDirectoryCommand() {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- cmCTestEmptyBinaryDirectoryCommand* ni
- = new cmCTestEmptyBinaryDirectoryCommand;
+ cmCommand* Clone() CM_OVERRIDE
+ {
+ cmCTestEmptyBinaryDirectoryCommand* ni =
+ new cmCTestEmptyBinaryDirectoryCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_empty_binary_directory";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "empties the binary directory";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_empty_binary_directory( directory )\n"
- "Removes a binary directory. This command will perform some checks "
- "prior to deleting the directory in an attempt to avoid malicious "
- "or accidental directory deletion.";
- }
-
- cmTypeMacro(cmCTestEmptyBinaryDirectoryCommand, cmCTestCommand);
-
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 5b3449181..230aedf3b 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -1,74 +1,65 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestGIT.h"
+#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 "cmSystemTools.h"
-#include "cmXMLSafe.h"
-
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/ios/sstream>
-#include <cmsys/Process.h>
-#include <sys/types.h>
-#include <time.h>
-#include <ctype.h>
-
-//----------------------------------------------------------------------------
static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major,
unsigned int minor, unsigned int fix)
{
// 1.6.5.0 maps to 10605000
- return fix + minor*1000 + major*100000 + epic*10000000;
+ return fix + minor * 1000 + major * 100000 + epic * 10000000;
}
-//----------------------------------------------------------------------------
-cmCTestGIT::cmCTestGIT(cmCTest* ct, std::ostream& log):
- cmCTestGlobalVC(ct, log)
+cmCTestGIT::cmCTestGIT(cmCTest* ct, std::ostream& log)
+ : cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
this->CurrentGitVersion = 0;
}
-//----------------------------------------------------------------------------
cmCTestGIT::~cmCTestGIT()
{
}
-//----------------------------------------------------------------------------
-class cmCTestGIT::OneLineParser: public cmCTestVC::LineParser
+class cmCTestGIT::OneLineParser : public cmCTestVC::LineParser
{
public:
- OneLineParser(cmCTestGIT* git, const char* prefix,
- std::string& l): Line1(l)
- {
+ OneLineParser(cmCTestGIT* git, const char* prefix, std::string& l)
+ : Line1(l)
+ {
this->SetLog(&git->Log, prefix);
- }
+ }
+
private:
std::string& Line1;
- virtual bool ProcessLine()
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
// Only the first line is of interest.
this->Line1 = this->Line;
return false;
- }
+ }
};
-//----------------------------------------------------------------------------
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", "--", 0};
+ const char* git_rev_list[] = { git, "rev-list", "-n", "1",
+ "HEAD", "--", CM_NULLPTR };
std::string rev;
OneLineParser out(this, "rl-out> ", rev);
OutputLogger err(this->Log, "rl-err> ");
@@ -76,93 +67,88 @@ std::string cmCTestGIT::GetWorkingRevision()
return rev;
}
-//----------------------------------------------------------------------------
-void cmCTestGIT::NoteOldRevision()
+bool cmCTestGIT::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ << this->OldRevision << "\n");
this->PriorRev.Rev = this->OldRevision;
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestGIT::NoteNewRevision()
+bool cmCTestGIT::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ << this->NewRevision << "\n");
+ return true;
}
-//----------------------------------------------------------------------------
std::string cmCTestGIT::FindGitDir()
{
std::string git_dir;
// 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", 0};
+ char const* git_rev_parse[] = { git, "rev-parse", "--git-dir", CM_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))
- {
+ if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, CM_NULLPTR,
+ cmProcessOutput::UTF8)) {
git_dir = git_dir_line;
- }
- if(git_dir.empty())
- {
+ }
+ if (git_dir.empty()) {
git_dir = ".git";
- }
+ }
// Git reports a relative path only when the .git directory is in
// the current directory.
- if(git_dir[0] == '.')
- {
+ if (git_dir[0] == '.') {
git_dir = this->SourceDirectory + "/" + git_dir;
- }
+ }
#if defined(_WIN32) && !defined(__CYGWIN__)
- else if(git_dir[0] == '/')
- {
+ 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()))
- {
- char const* cygpath[] = {cygpath_exe.c_str(), "-w", git_dir.c_str(), 0};
+ if (cmSystemTools::FileExists(cygpath_exe.c_str())) {
+ 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))
- {
+ if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, CM_NULLPTR,
+ cmProcessOutput::UTF8)) {
git_dir = git_dir_line;
- }
}
}
+ }
#endif
return git_dir;
}
-//----------------------------------------------------------------------------
std::string cmCTestGIT::FindTopDir()
{
std::string top_dir = this->SourceDirectory;
// 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", 0};
+ char const* git_rev_parse[] = { git, "rev-parse", "--show-cdup",
+ CM_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) &&
- !cdup.empty())
- {
+ if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, CM_NULLPTR,
+ cmProcessOutput::UTF8) &&
+ !cdup.empty()) {
top_dir += "/";
top_dir += cdup;
- top_dir = cmSystemTools::CollapseFullPath(top_dir.c_str());
- }
+ top_dir = cmSystemTools::CollapseFullPath(top_dir);
+ }
return top_dir;
}
-//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateByFetchAndReset()
{
const char* git = this->CommandLineTool.c_str();
@@ -174,146 +160,163 @@ bool cmCTestGIT::UpdateByFetchAndReset()
// Add user-specified update options.
std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
- if(opts.empty())
- {
+ if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("GITUpdateOptions");
- }
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(opts.c_str());
- for(std::vector<cmStdString>::const_iterator ai = args.begin();
- ai != args.end(); ++ai)
- {
+ }
+ 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());
- }
+ }
// Sentinel argument.
- git_fetch.push_back(0);
+ git_fetch.push_back(CM_NULLPTR);
// Fetch upstream refs.
OutputLogger fetch_out(this->Log, "fetch-out> ");
OutputLogger fetch_err(this->Log, "fetch-err> ");
- if(!this->RunUpdateCommand(&git_fetch[0], &fetch_out, &fetch_err))
- {
+ if (!this->RunUpdateCommand(&git_fetch[0], &fetch_out, &fetch_err)) {
return false;
- }
+ }
// Identify the merge head that would be used by "git pull".
std::string sha1;
{
- std::string fetch_head = this->FindGitDir() + "/FETCH_HEAD";
- std::ifstream fin(fetch_head.c_str(), std::ios::in | std::ios::binary);
- if(!fin)
- {
- this->Log << "Unable to open " << fetch_head << "\n";
- return false;
+ std::string fetch_head = this->FindGitDir() + "/FETCH_HEAD";
+ cmsys::ifstream fin(fetch_head.c_str(), std::ios::in | std::ios::binary);
+ if (!fin) {
+ this->Log << "Unable to open " << fetch_head << "\n";
+ return false;
}
- std::string line;
- while(sha1.empty() && cmSystemTools::GetLineFromStream(fin, line))
- {
- this->Log << "FETCH_HEAD> " << line << "\n";
- if(line.find("\tnot-for-merge\t") == line.npos)
- {
- std::string::size_type pos = line.find('\t');
- if(pos != line.npos)
- {
- sha1 = line.substr(0, pos);
+ std::string line;
+ while (sha1.empty() && cmSystemTools::GetLineFromStream(fin, line)) {
+ this->Log << "FETCH_HEAD> " << line << "\n";
+ if (line.find("\tnot-for-merge\t") == std::string::npos) {
+ std::string::size_type pos = line.find('\t');
+ if (pos != std::string::npos) {
+ sha1 = line.substr(0, pos);
}
}
}
- if(sha1.empty())
- {
- this->Log << "FETCH_HEAD has no upstream branch candidate!\n";
- return false;
+ if (sha1.empty()) {
+ this->Log << "FETCH_HEAD has no upstream branch candidate!\n";
+ return false;
}
}
// Reset the local branch to point at that tracked from upstream.
- char const* git_reset[] = {git, "reset", "--hard", sha1.c_str(), 0};
+ char const* git_reset[] = { git, "reset", "--hard", sha1.c_str(),
+ CM_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);
}
-//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateByCustom(std::string const& custom)
{
std::vector<std::string> git_custom_command;
cmSystemTools::ExpandListArgument(custom, git_custom_command, 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)
- {
+ 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.push_back(0);
+ }
+ git_custom.push_back(CM_NULLPTR);
OutputLogger custom_out(this->Log, "custom-out> ");
OutputLogger custom_err(this->Log, "custom-err> ");
return this->RunUpdateCommand(&git_custom[0], &custom_out, &custom_err);
}
-//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateInternal()
{
std::string custom = this->CTest->GetCTestConfiguration("GITUpdateCustom");
- if(!custom.empty())
- {
+ if (!custom.empty()) {
return this->UpdateByCustom(custom);
- }
+ }
return this->UpdateByFetchAndReset();
}
-//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateImpl()
{
- if(!this->UpdateInternal())
- {
+ if (!this->UpdateInternal()) {
return false;
- }
+ }
std::string top_dir = this->FindTopDir();
const char* git = this->CommandLineTool.c_str();
const char* recursive = "--recursive";
+ const char* sync_recursive = "--recursive";
+
+ // Git < 1.6.5 did not support submodule --recursive
+ if (this->GetGitVersion() < cmCTestGITVersion(1, 6, 5, 0)) {
+ recursive = CM_NULLPTR;
+ // No need to require >= 1.6.5 if there are no submodules.
+ if (cmSystemTools::FileExists((top_dir + "/.gitmodules").c_str())) {
+ this->Log << "Git < 1.6.5 cannot update submodules recursively\n";
+ }
+ }
- // Git < 1.6.5.0 did not support --recursive
- if(this->GetGitVersion() < cmCTestGITVersion(1,6,5,0))
- {
- recursive = 0;
- // No need to require >= 1.6.5.0 if there are no submodules.
- if(cmSystemTools::FileExists((top_dir + "/.gitmodules").c_str()))
- {
- this->Log << "Git < 1.6.5.0 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;
+ // No need to require >= 1.8.1 if there are no submodules.
+ if (cmSystemTools::FileExists((top_dir + "/.gitmodules").c_str())) {
+ this->Log << "Git < 1.8.1 cannot synchronize submodules recursively\n";
}
+ }
- char const* git_submodule[] = {git, "submodule", "update", recursive, 0};
OutputLogger submodule_out(this->Log, "submodule-out> ");
OutputLogger submodule_err(this->Log, "submodule-err> ");
+
+ bool ret;
+
+ 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 };
+ ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err,
+ top_dir.c_str());
+
+ if (!ret) {
+ return false;
+ }
+ }
+
+ char const* git_submodule_sync[] = { git, "submodule", "sync",
+ sync_recursive, CM_NULLPTR };
+ ret = this->RunChild(git_submodule_sync, &submodule_out, &submodule_err,
+ top_dir.c_str());
+
+ if (!ret) {
+ return false;
+ }
+
+ char const* git_submodule[] = { git, "submodule", "update", recursive,
+ CM_NULLPTR };
return this->RunChild(git_submodule, &submodule_out, &submodule_err,
top_dir.c_str());
}
-//----------------------------------------------------------------------------
unsigned int cmCTestGIT::GetGitVersion()
{
- if(!this->CurrentGitVersion)
- {
+ if (!this->CurrentGitVersion) {
const char* git = this->CommandLineTool.c_str();
- char const* git_version[] = {git, "--version", 0};
+ char const* git_version[] = { git, "--version", CM_NULLPTR };
std::string version;
OneLineParser version_out(this, "version-out> ", version);
OutputLogger version_err(this->Log, "version-err> ");
- unsigned int v[4] = {0,0,0,0};
- if(this->RunChild(git_version, &version_out, &version_err) &&
- sscanf(version.c_str(), "git version %u.%u.%u.%u",
- &v[0], &v[1], &v[2], &v[3]) >= 3)
- {
+ unsigned int v[4] = { 0, 0, 0, 0 };
+ if (this->RunChild(git_version, &version_out, &version_err) &&
+ sscanf(version.c_str(), "git version %u.%u.%u.%u", &v[0], &v[1], &v[2],
+ &v[3]) >= 3) {
this->CurrentGitVersion = cmCTestGITVersion(v[0], v[1], v[2], v[3]);
- }
}
+ }
return this->CurrentGitVersion;
}
-//----------------------------------------------------------------------------
/* Diff format:
:src-mode dst-mode src-sha1 dst-sha1 status\0
@@ -324,76 +327,73 @@ unsigned int cmCTestGIT::GetGitVersion()
line appears only for lines with status 'C' or 'R'. See 'git help
diff-tree' for details.
*/
-class cmCTestGIT::DiffParser: public cmCTestVC::LineParser
+class cmCTestGIT::DiffParser : public cmCTestVC::LineParser
{
public:
- DiffParser(cmCTestGIT* git, const char* prefix):
- LineParser('\0', false), GIT(git), DiffField(DiffFieldNone)
- {
+ DiffParser(cmCTestGIT* git, const char* prefix)
+ : LineParser('\0', false)
+ , GIT(git)
+ , DiffField(DiffFieldNone)
+ {
this->SetLog(&git->Log, prefix);
- }
+ }
typedef cmCTestGIT::Change Change;
std::vector<Change> Changes;
+
protected:
cmCTestGIT* GIT;
- enum DiffFieldType { DiffFieldNone, DiffFieldChange,
- DiffFieldSrc, DiffFieldDst };
+ enum DiffFieldType
+ {
+ DiffFieldNone,
+ DiffFieldChange,
+ DiffFieldSrc,
+ DiffFieldDst
+ };
DiffFieldType DiffField;
Change CurChange;
void DiffReset()
- {
+ {
this->DiffField = DiffFieldNone;
this->Changes.clear();
- }
+ }
- virtual bool ProcessLine()
- {
- if(this->Line[0] == ':')
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->Line[0] == ':') {
this->DiffField = DiffFieldChange;
this->CurChange = Change();
- }
- if(this->DiffField == DiffFieldChange)
- {
+ }
+ if (this->DiffField == DiffFieldChange) {
// :src-mode dst-mode src-sha1 dst-sha1 status
- if(this->Line[0] != ':')
- {
+ if (this->Line[0] != ':') {
this->DiffField = DiffFieldNone;
return true;
- }
- const char* src_mode_first = this->Line.c_str()+1;
- const char* src_mode_last = this->ConsumeField(src_mode_first);
+ }
+ const char* src_mode_first = this->Line.c_str() + 1;
+ const char* src_mode_last = this->ConsumeField(src_mode_first);
const char* dst_mode_first = this->ConsumeSpace(src_mode_last);
- const char* dst_mode_last = this->ConsumeField(dst_mode_first);
+ const char* dst_mode_last = this->ConsumeField(dst_mode_first);
const char* src_sha1_first = this->ConsumeSpace(dst_mode_last);
- const char* src_sha1_last = this->ConsumeField(src_sha1_first);
+ const char* src_sha1_last = this->ConsumeField(src_sha1_first);
const char* dst_sha1_first = this->ConsumeSpace(src_sha1_last);
- const char* dst_sha1_last = this->ConsumeField(dst_sha1_first);
- const char* status_first = this->ConsumeSpace(dst_sha1_last);
- const char* status_last = this->ConsumeField(status_first);
- if(status_first != status_last)
- {
+ const char* dst_sha1_last = this->ConsumeField(dst_sha1_first);
+ const char* status_first = this->ConsumeSpace(dst_sha1_last);
+ const char* status_last = this->ConsumeField(status_first);
+ if (status_first != status_last) {
this->CurChange.Action = *status_first;
this->DiffField = DiffFieldSrc;
- }
- else
- {
+ } else {
this->DiffField = DiffFieldNone;
- }
}
- else if(this->DiffField == DiffFieldSrc)
- {
+ } else if (this->DiffField == DiffFieldSrc) {
// src-path
- if(this->CurChange.Action == 'C')
- {
+ if (this->CurChange.Action == 'C') {
// Convert copy to addition of destination.
this->CurChange.Action = 'A';
this->DiffField = DiffFieldDst;
- }
- else if(this->CurChange.Action == 'R')
- {
+ } else if (this->CurChange.Action == 'R') {
// Convert rename to deletion of source and addition of destination.
this->CurChange.Action = 'D';
this->CurChange.Path = this->Line;
@@ -401,37 +401,36 @@ protected:
this->CurChange = Change('A');
this->DiffField = DiffFieldDst;
- }
- else
- {
+ } else {
this->CurChange.Path = this->Line;
this->Changes.push_back(this->CurChange);
this->DiffField = this->DiffFieldNone;
- }
}
- else if(this->DiffField == DiffFieldDst)
- {
+ } else if (this->DiffField == DiffFieldDst) {
// dst-path
this->CurChange.Path = this->Line;
this->Changes.push_back(this->CurChange);
this->DiffField = this->DiffFieldNone;
- }
- return true;
}
+ return true;
+ }
const char* ConsumeSpace(const char* c)
- {
- while(*c && isspace(*c)) { ++c; }
- return c;
+ {
+ while (*c && isspace(*c)) {
+ ++c;
}
- const char* ConsumeField(const char* c)
- {
- while(*c && !isspace(*c)) { ++c; }
return c;
+ }
+ const char* ConsumeField(const char* c)
+ {
+ while (*c && !isspace(*c)) {
+ ++c;
}
+ return c;
+ }
};
-//----------------------------------------------------------------------------
/* Commit format:
commit ...\n
@@ -451,18 +450,25 @@ protected:
The header may have more fields. See 'git help diff-tree'.
*/
-class cmCTestGIT::CommitParser: public cmCTestGIT::DiffParser
+class cmCTestGIT::CommitParser : public cmCTestGIT::DiffParser
{
public:
- CommitParser(cmCTestGIT* git, const char* prefix):
- DiffParser(git, prefix), Section(SectionHeader)
- {
+ CommitParser(cmCTestGIT* git, const char* prefix)
+ : DiffParser(git, prefix)
+ , Section(SectionHeader)
+ {
this->Separator = SectionSep[this->Section];
- }
+ }
private:
typedef cmCTestGIT::Revision Revision;
- enum SectionType { SectionHeader, SectionBody, SectionDiff, SectionCount };
+ enum SectionType
+ {
+ SectionHeader,
+ SectionBody,
+ SectionDiff,
+ SectionCount
+ };
static char const SectionSep[SectionCount];
SectionType Section;
Revision Rev;
@@ -473,142 +479,147 @@ private:
std::string EMail;
unsigned long Time;
long TimeZone;
- Person(): Name(), EMail(), Time(0), TimeZone(0) {}
+ Person()
+ : Name()
+ , EMail()
+ , Time(0)
+ , TimeZone(0)
+ {
+ }
};
void ParsePerson(const char* str, Person& person)
- {
+ {
// Person Name <person@domain.com> 1234567890 +0000
const char* c = str;
- while(*c && isspace(*c)) { ++c; }
+ while (*c && isspace(*c)) {
+ ++c;
+ }
const char* name_first = c;
- while(*c && *c != '<') { ++c; }
+ while (*c && *c != '<') {
+ ++c;
+ }
const char* name_last = c;
- while(name_last != name_first && isspace(*(name_last-1))) { --name_last; }
- person.Name.assign(name_first, name_last-name_first);
+ while (name_last != name_first && isspace(*(name_last - 1))) {
+ --name_last;
+ }
+ person.Name.assign(name_first, name_last - name_first);
- const char* email_first = *c? ++c : c;
- while(*c && *c != '>') { ++c; }
- const char* email_last = *c? c++ : c;
- person.EMail.assign(email_first, email_last-email_first);
+ const char* email_first = *c ? ++c : c;
+ while (*c && *c != '>') {
+ ++c;
+ }
+ 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);
- }
+ }
- virtual bool ProcessLine()
- {
- if(this->Line.empty())
- {
- if(this->Section == SectionBody && this->LineEnd == '\0')
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->Line.empty()) {
+ if (this->Section == SectionBody && this->LineEnd == '\0') {
// Skip SectionDiff
this->NextSection();
- }
- this->NextSection();
}
- else
- {
- switch(this->Section)
- {
- case SectionHeader: this->DoHeaderLine(); break;
- case SectionBody: this->DoBodyLine(); break;
- case SectionDiff: this->DiffParser::ProcessLine(); break;
- case SectionCount: break; // never happens
- }
+ this->NextSection();
+ } else {
+ switch (this->Section) {
+ case SectionHeader:
+ this->DoHeaderLine();
+ break;
+ case SectionBody:
+ this->DoBodyLine();
+ break;
+ case SectionDiff:
+ this->DiffParser::ProcessLine();
+ break;
+ case SectionCount:
+ break; // never happens
}
- return true;
}
+ return true;
+ }
void NextSection()
- {
- this->Section = SectionType((this->Section+1) % SectionCount);
+ {
+ this->Section = SectionType((this->Section + 1) % SectionCount);
this->Separator = SectionSep[this->Section];
- if(this->Section == SectionHeader)
- {
+ if (this->Section == SectionHeader) {
this->GIT->DoRevision(this->Rev, this->Changes);
this->Rev = Revision();
this->DiffReset();
- }
}
+ }
void DoHeaderLine()
- {
+ {
// Look for header fields that we need.
- if(strncmp(this->Line.c_str(), "commit ", 7) == 0)
- {
- this->Rev.Rev = this->Line.c_str()+7;
- }
- else if(strncmp(this->Line.c_str(), "author ", 7) == 0)
- {
+ if (cmHasLiteralPrefix(this->Line.c_str(), "commit ")) {
+ this->Rev.Rev = this->Line.c_str() + 7;
+ } else if (cmHasLiteralPrefix(this->Line.c_str(), "author ")) {
Person author;
- this->ParsePerson(this->Line.c_str()+7, 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(strncmp(this->Line.c_str(), "committer ", 10) == 0)
- {
+ } else if (cmHasLiteralPrefix(this->Line.c_str(), "committer ")) {
Person committer;
- this->ParsePerson(this->Line.c_str()+10, committer);
+ this->ParsePerson(this->Line.c_str() + 10, committer);
this->Rev.Committer = committer.Name;
this->Rev.CommitterEMail = committer.EMail;
this->Rev.CommitDate = this->FormatDateTime(committer);
- }
}
+ }
void DoBodyLine()
- {
+ {
// Commit log lines are indented by 4 spaces.
- if(this->Line.size() >= 4)
- {
+ if (this->Line.size() >= 4) {
this->Rev.Log += this->Line.substr(4);
- }
- this->Rev.Log += "\n";
}
+ this->Rev.Log += "\n";
+ }
std::string FormatDateTime(Person const& person)
- {
+ {
// Convert the time to a human-readable format that is also easy
// to machine-parse: "CCYY-MM-DD hh:mm:ss".
time_t seconds = static_cast<time_t>(person.Time);
struct tm* t = gmtime(&seconds);
char dt[1024];
- sprintf(dt, "%04d-%02d-%02d %02d:%02d:%02d",
- t->tm_year+1900, t->tm_mon+1, t->tm_mday,
- t->tm_hour, t->tm_min, t->tm_sec);
+ sprintf(dt, "%04d-%02d-%02d %02d:%02d:%02d", t->tm_year + 1900,
+ t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
std::string out = dt;
// Add the time-zone field "+zone" or "-zone".
char tz[32];
- if(person.TimeZone >= 0)
- {
+ if (person.TimeZone >= 0) {
sprintf(tz, " +%04ld", person.TimeZone);
- }
- else
- {
+ } else {
sprintf(tz, " -%04ld", -person.TimeZone);
- }
+ }
out += tz;
return out;
- }
+ }
};
-char const cmCTestGIT::CommitParser::SectionSep[SectionCount] =
-{'\n', '\n', '\0'};
+char const cmCTestGIT::CommitParser::SectionSep[SectionCount] = { '\n', '\n',
+ '\0' };
-//----------------------------------------------------------------------------
-void cmCTestGIT::LoadRevisions()
+bool cmCTestGIT::LoadRevisions()
{
// Use 'git rev-list ... | git diff-tree ...' to get revisions.
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(), "--", 0};
- const char* git_diff_tree[] =
- {git, "diff-tree", "--stdin", "--always", "-z", "-r", "--pretty=raw",
- "--encoding=utf-8", 0};
+ const char* git_rev_list[] = { git, "rev-list", "--reverse",
+ range.c_str(), "--", CM_NULLPTR };
+ const char* git_diff_tree[] = {
+ git, "diff-tree", "--stdin", "--always", "-z",
+ "-r", "--pretty=raw", "--encoding=utf-8", CM_NULLPTR
+ };
this->Log << this->ComputeCommandLine(git_rev_list) << " | "
<< this->ComputeCommandLine(git_diff_tree) << "\n";
@@ -619,34 +630,38 @@ void cmCTestGIT::LoadRevisions()
CommitParser out(this, "dt-out> ");
OutputLogger err(this->Log, "dt-err> ");
- this->RunProcess(cp, &out, &err);
+ this->RunProcess(cp, &out, &err, cmProcessOutput::UTF8);
// Send one extra zero-byte to terminate the last record.
out.Process("", 1);
cmsysProcess_Delete(cp);
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestGIT::LoadModifications()
+bool cmCTestGIT::LoadModifications()
{
const char* git = this->CommandLineTool.c_str();
// Use 'git update-index' to refresh the index w.r.t. the work tree.
- const char* git_update_index[] = {git, "update-index", "--refresh", 0};
+ const char* git_update_index[] = { git, "update-index", "--refresh",
+ CM_NULLPTR };
OutputLogger ui_out(this->Log, "ui-out> ");
OutputLogger ui_err(this->Log, "ui-err> ");
- this->RunChild(git_update_index, &ui_out, &ui_err);
+ this->RunChild(git_update_index, &ui_out, &ui_err, CM_NULLPTR,
+ cmProcessOutput::UTF8);
// Use 'git diff-index' to get modified files.
- const char* git_diff_index[] = {git, "diff-index", "-z", "HEAD", "--", 0};
+ const char* git_diff_index[] = { git, "diff-index", "-z",
+ "HEAD", "--", CM_NULLPTR };
DiffParser out(this, "di-out> ");
OutputLogger err(this->Log, "di-err> ");
- this->RunChild(git_diff_index, &out, &err);
+ this->RunChild(git_diff_index, &out, &err, CM_NULLPTR,
+ cmProcessOutput::UTF8);
- for(std::vector<Change>::const_iterator ci = out.Changes.begin();
- ci != out.Changes.end(); ++ci)
- {
+ for (std::vector<Change>::const_iterator ci = out.Changes.begin();
+ ci != out.Changes.end(); ++ci) {
this->DoModification(PathModified, ci->Path);
- }
+ }
+ return true;
}
diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h
index f4fae8f9d..4bf8294e6 100644
--- a/Source/CTest/cmCTestGIT.h
+++ b/Source/CTest/cmCTestGIT.h
@@ -1,38 +1,36 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestGIT_h
#define cmCTestGIT_h
+#include "cmConfigure.h"
+
#include "cmCTestGlobalVC.h"
+#include <iosfwd>
+#include <string>
+
+class cmCTest;
+
/** \class cmCTestGIT
* \brief Interaction with git command-line tool
*
*/
-class cmCTestGIT: public cmCTestGlobalVC
+class cmCTestGIT : public cmCTestGlobalVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestGIT(cmCTest* ctest, std::ostream& log);
- virtual ~cmCTestGIT();
+ ~cmCTestGIT() CM_OVERRIDE;
private:
unsigned int CurrentGitVersion;
unsigned int GetGitVersion();
std::string GetWorkingRevision();
- virtual void NoteOldRevision();
- virtual void NoteNewRevision();
- virtual bool UpdateImpl();
+ bool NoteOldRevision() CM_OVERRIDE;
+ bool NoteNewRevision() CM_OVERRIDE;
+ bool UpdateImpl() CM_OVERRIDE;
std::string FindGitDir();
std::string FindTopDir();
@@ -41,17 +39,19 @@ private:
bool UpdateByCustom(std::string const& custom);
bool UpdateInternal();
- void LoadRevisions();
- void LoadModifications();
+ bool LoadRevisions() CM_OVERRIDE;
+ bool LoadModifications() CM_OVERRIDE;
-public: // needed by older Sun compilers
+ // "public" needed by older Sun compilers
+public:
// Parsing helper classes.
- class OneLineParser;
- class DiffParser;
class CommitParser;
- friend class OneLineParser;
- friend class DiffParser;
+ class DiffParser;
+ class OneLineParser;
+
friend class CommitParser;
+ friend class DiffParser;
+ friend class OneLineParser;
};
#endif
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 5338f307b..19034c01b 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -1,171 +1,138 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestGenericHandler.h"
-#include "cmSystemTools.h"
+
+#include "cmConfigure.h"
+#include <sstream>
+#include <utility>
#include "cmCTest.h"
+#include "cmSystemTools.h"
-//----------------------------------------------------------------------
cmCTestGenericHandler::cmCTestGenericHandler()
{
this->HandlerVerbose = cmSystemTools::OUTPUT_NONE;
- this->CTest = 0;
+ this->CTest = CM_NULLPTR;
this->SubmitIndex = 0;
this->AppendXML = false;
+ this->Quiet = false;
+ this->TestLoad = 0;
}
-//----------------------------------------------------------------------
cmCTestGenericHandler::~cmCTestGenericHandler()
{
}
-//----------------------------------------------------------------------
-void cmCTestGenericHandler::SetOption(const char* op, const char* value)
+void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
{
- if ( !op )
- {
- return;
- }
- if ( !value )
- {
- cmCTestGenericHandler::t_StringToString::iterator remit
- = this->Options.find(op);
- if ( remit != this->Options.end() )
- {
+ if (!value) {
+ cmCTestGenericHandler::t_StringToString::iterator remit =
+ this->Options.find(op);
+ if (remit != this->Options.end()) {
this->Options.erase(remit);
- }
- return;
}
+ return;
+ }
this->Options[op] = value;
}
-//----------------------------------------------------------------------
-void cmCTestGenericHandler::SetPersistentOption(const char* op,
+void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
const char* value)
{
this->SetOption(op, value);
- if ( !op )
- {
- return;
- }
- if ( !value )
- {
- cmCTestGenericHandler::t_StringToString::iterator remit
- = this->PersistentOptions.find(op);
- if ( remit != this->PersistentOptions.end() )
- {
+ if (!value) {
+ cmCTestGenericHandler::t_StringToString::iterator remit =
+ this->PersistentOptions.find(op);
+ if (remit != this->PersistentOptions.end()) {
this->PersistentOptions.erase(remit);
- }
- return;
}
+ return;
+ }
this->PersistentOptions[op] = value;
}
-//----------------------------------------------------------------------
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.c_str()] = it->second.c_str();
- }
+ for (it = this->PersistentOptions.begin();
+ it != this->PersistentOptions.end(); ++it) {
+ this->Options[it->first] = it->second;
+ }
}
-//----------------------------------------------------------------------
-const char* cmCTestGenericHandler::GetOption(const char* op)
+const char* cmCTestGenericHandler::GetOption(const std::string& op)
{
- cmCTestGenericHandler::t_StringToString::iterator remit
- = this->Options.find(op);
- if ( remit == this->Options.end() )
- {
- return 0;
- }
+ cmCTestGenericHandler::t_StringToString::iterator remit =
+ this->Options.find(op);
+ if (remit == this->Options.end()) {
+ return CM_NULLPTR;
+ }
return remit->second.c_str();
}
-//----------------------------------------------------------------------
bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,
const char* name,
cmGeneratedFileStream& xofs)
{
- if ( !name )
- {
+ if (!name) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot create resulting XML file without providing the name"
- << std::endl;);
+ "Cannot create resulting XML file without providing the name"
+ << std::endl;);
return false;
- }
- cmOStringStream ostr;
+ }
+ std::ostringstream ostr;
ostr << name;
- if ( this->SubmitIndex > 0 )
- {
+ if (this->SubmitIndex > 0) {
ostr << "_" << this->SubmitIndex;
- }
+ }
ostr << ".xml";
- if(this->CTest->GetCurrentTag().empty())
- {
+ if (this->CTest->GetCurrentTag().empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Current Tag empty, this may mean NightlyStartTime / "
"CTEST_NIGHTLY_START_TIME was not set correctly. Or "
"maybe you forgot to call ctest_start() before calling "
- "ctest_configure()." << std::endl);
+ "ctest_configure()."
+ << std::endl);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
- if( !this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(),
- ostr.str().c_str(), xofs, true) )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot create resulting XML file: " << ostr.str().c_str()
- << std::endl);
+ }
+ 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);
return false;
- }
+ }
this->CTest->AddSubmitFile(part, ostr.str().c_str());
return true;
}
-//----------------------------------------------------------------------
bool cmCTestGenericHandler::StartLogFile(const char* name,
- cmGeneratedFileStream& xofs)
+ cmGeneratedFileStream& xofs)
{
- if ( !name )
- {
+ if (!name) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot create log file without providing the name" << std::endl;);
+ "Cannot create log file without providing the name"
+ << std::endl;);
return false;
- }
- cmOStringStream ostr;
+ }
+ std::ostringstream ostr;
ostr << "Last" << name;
- if ( this->SubmitIndex > 0 )
- {
+ if (this->SubmitIndex > 0) {
ostr << "_" << this->SubmitIndex;
- }
- if ( !this->CTest->GetCurrentTag().empty() )
- {
+ }
+ if (!this->CTest->GetCurrentTag().empty()) {
ostr << "_" << this->CTest->GetCurrentTag();
- }
+ }
ostr << ".log";
- if( !this->CTest->OpenOutputFile("Temporary", ostr.str().c_str(), xofs) )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create log file: "
- << ostr.str().c_str() << std::endl);
+ if (!this->CTest->OpenOutputFile("Temporary", ostr.str(), xofs)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create log file: " << ostr.str() << std::endl);
return false;
- }
+ }
return true;
}
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index ba8febb61..e881252c9 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -1,45 +1,42 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestGenericHandler_h
#define cmCTestGenericHandler_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <stddef.h>
+#include <string>
+#include <vector>
-#include "cmObject.h"
#include "cmCTest.h"
-#include "cmSystemTools.h" //OutputOption
+#include "cmSystemTools.h"
-class cmMakefile;
class cmCTestCommand;
class cmGeneratedFileStream;
+class cmMakefile;
/** \class cmCTestGenericHandler
* \brief A superclass of all CTest Handlers
*
*/
-class cmCTestGenericHandler : public cmObject
+class cmCTestGenericHandler
{
public:
/**
* If verbose then more informaiton is printed out
*/
void SetVerbose(bool val)
- { this->HandlerVerbose = val ?
- cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE; }
+ {
+ this->HandlerVerbose =
+ val ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE;
+ }
/**
* Populate internals from CTest custom scripts
*/
- virtual void PopulateCustomVectors(cmMakefile *) {}
+ virtual void PopulateCustomVectors(cmMakefile*) {}
/**
* Do the actual processing. Subclass has to override it.
@@ -52,7 +49,10 @@ public:
*/
virtual int ProcessCommandLineArguments(
const std::string& /*currentArg*/, size_t& /*idx*/,
- const std::vector<std::string>& /*allArgs*/) { return 1; }
+ const std::vector<std::string>& /*allArgs*/)
+ {
+ return 1;
+ }
/**
* Initialize handler
@@ -71,31 +71,33 @@ public:
cmCTestGenericHandler();
virtual ~cmCTestGenericHandler();
- typedef std::map<cmStdString,cmStdString> t_StringToString;
+ typedef std::map<std::string, std::string> t_StringToString;
+ void SetPersistentOption(const std::string& op, const char* value);
+ void SetOption(const std::string& op, const char* value);
+ const char* GetOption(const std::string& op);
- void SetPersistentOption(const char* op, const char* value);
- void SetOption(const char* op, const char* value);
- const char* GetOption(const char* op);
-
- void SetCommand(cmCTestCommand* command)
- {
- this->Command = command;
- }
+ void SetCommand(cmCTestCommand* command) { this->Command = command; }
void SetSubmitIndex(int idx) { this->SubmitIndex = idx; }
int GetSubmitIndex() { return this->SubmitIndex; }
void SetAppendXML(bool b) { this->AppendXML = b; }
+ void SetQuiet(bool b) { this->Quiet = b; }
+ bool GetQuiet() { return this->Quiet; }
+ void SetTestLoad(unsigned long load) { this->TestLoad = load; }
+ unsigned long GetTestLoad() const { return this->TestLoad; }
protected:
- bool StartResultingXML(cmCTest::Part part,
- const char* name, cmGeneratedFileStream& xofs);
+ bool StartResultingXML(cmCTest::Part part, const char* name,
+ cmGeneratedFileStream& xofs);
bool StartLogFile(const char* name, cmGeneratedFileStream& xofs);
bool AppendXML;
+ bool Quiet;
+ unsigned long TestLoad;
cmSystemTools::OutputOption HandlerVerbose;
- cmCTest *CTest;
+ cmCTest* CTest;
t_StringToString Options;
t_StringToString PersistentOptions;
@@ -104,4 +106,3 @@ protected:
};
#endif
-
diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx
index 8c51102e5..25294b5ae 100644
--- a/Source/CTest/cmCTestGlobalVC.cxx
+++ b/Source/CTest/cmCTestGlobalVC.cxx
@@ -1,50 +1,37 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestGlobalVC.h"
#include "cmCTest.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
-#include <cmsys/RegularExpression.hxx>
+#include <ostream>
+#include <utility>
-//----------------------------------------------------------------------------
-cmCTestGlobalVC::cmCTestGlobalVC(cmCTest* ct, std::ostream& log):
- cmCTestVC(ct, log)
+cmCTestGlobalVC::cmCTestGlobalVC(cmCTest* ct, std::ostream& log)
+ : cmCTestVC(ct, log)
{
this->PriorRev = this->Unknown;
}
-//----------------------------------------------------------------------------
cmCTestGlobalVC::~cmCTestGlobalVC()
{
}
-//----------------------------------------------------------------------------
const char* cmCTestGlobalVC::LocalPath(std::string const& path)
{
return path.c_str();
}
-//----------------------------------------------------------------------------
void cmCTestGlobalVC::DoRevision(Revision const& revision,
std::vector<Change> const& changes)
{
// Ignore changes in the old revision.
- if(revision.Rev == this->OldRevision)
- {
+ if (revision.Rev == this->OldRevision) {
this->PriorRev = revision;
return;
- }
+ }
// Indicate we found a revision.
cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
@@ -54,27 +41,27 @@ void cmCTestGlobalVC::DoRevision(Revision const& revision,
// Report this revision.
Revision const& rev = this->Revisions.back();
+ /* clang-format off */
this->Log << "Found revision " << rev.Rev << "\n"
<< " author = " << rev.Author << "\n"
<< " date = " << rev.Date << "\n";
+ /* 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 (std::vector<Change>::const_iterator ci = changes.begin();
+ ci != changes.end(); ++ci) {
+ if (const char* local = this->LocalPath(ci->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.PriorRev = file.Rev ? file.Rev : &this->PriorRev;
file.Rev = &rev;
- this->Log << " " << ci->Action << " " << local << " " << "\n";
- }
+ this->Log << " " << ci->Action << " " << local << " "
+ << "\n";
}
+ }
}
-//----------------------------------------------------------------------------
void cmCTestGlobalVC::DoModification(PathStatus status,
std::string const& path)
{
@@ -84,59 +71,54 @@ void cmCTestGlobalVC::DoModification(PathStatus status,
file.Status = status;
// For local modifications the current rev is unknown and the
// prior rev is the latest from svn.
- if(!file.Rev && !file.PriorRev)
- {
+ if (!file.Rev && !file.PriorRev) {
file.PriorRev = &this->PriorRev;
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmCTestGlobalVC::WriteXMLDirectory(std::ostream& xml,
+void cmCTestGlobalVC::WriteXMLDirectory(cmXMLWriter& xml,
std::string const& path,
Directory const& dir)
{
- const char* slash = path.empty()? "":"/";
- xml << "\t<Directory>\n"
- << "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n";
- for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi)
- {
+ 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);
- }
- xml << "\t</Directory>\n";
+ }
+ xml.EndElement(); // Directory
}
-//----------------------------------------------------------------------------
-void cmCTestGlobalVC::WriteXMLGlobal(std::ostream& xml)
+void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml)
{
- if(!this->NewRevision.empty())
- {
- xml << "\t<Revision>" << this->NewRevision << "</Revision>\n";
- }
- if(!this->OldRevision.empty() && this->OldRevision != this->NewRevision)
- {
- xml << "\t<PriorRevision>" << this->OldRevision << "</PriorRevision>\n";
- }
+ if (!this->NewRevision.empty()) {
+ xml.Element("Revision", this->NewRevision);
+ }
+ if (!this->OldRevision.empty() && this->OldRevision != this->NewRevision) {
+ xml.Element("PriorRevision", this->OldRevision);
+ }
}
-//----------------------------------------------------------------------------
-bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml)
+bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml)
{
+ bool result = true;
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n"
- " " << std::flush);
- this->LoadRevisions();
+ " "
+ << std::flush);
+ result = this->LoadRevisions() && result;
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
- this->LoadModifications();
+ result = this->LoadModifications() && result;
this->WriteXMLGlobal(xml);
- for(std::map<cmStdString, Directory>::const_iterator
- di = this->Dirs.begin(); di != this->Dirs.end(); ++di)
- {
+ for (std::map<std::string, Directory>::const_iterator di =
+ this->Dirs.begin();
+ di != this->Dirs.end(); ++di) {
this->WriteXMLDirectory(xml, di->first, di->second);
- }
+ }
- return true;
+ return result;
}
diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h
index a648a5982..a5273d3dd 100644
--- a/Source/CTest/cmCTestGlobalVC.h
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -1,46 +1,53 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestGlobalVC_h
#define cmCTestGlobalVC_h
+#include "cmConfigure.h"
+
#include "cmCTestVC.h"
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmXMLWriter;
+
/** \class cmCTestGlobalVC
* \brief Base class for handling globally-versioned trees
*
*/
-class cmCTestGlobalVC: public cmCTestVC
+class cmCTestGlobalVC : public cmCTestVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestGlobalVC(cmCTest* ctest, std::ostream& log);
- virtual ~cmCTestGlobalVC();
+ ~cmCTestGlobalVC() CM_OVERRIDE;
protected:
// Implement cmCTestVC internal API.
- virtual bool WriteXMLUpdates(std::ostream& xml);
+ bool WriteXMLUpdates(cmXMLWriter& xml) CM_OVERRIDE;
/** Represent a vcs-reported action for one path in a revision. */
struct Change
{
char Action;
std::string Path;
- Change(char a = '?'): Action(a) {}
+ Change(char a = '?')
+ : Action(a)
+ {
+ }
};
// Update status for files in each directory.
- class Directory: public std::map<cmStdString, File> {};
- std::map<cmStdString, Directory> Dirs;
+ class Directory : public std::map<std::string, File>
+ {
+ };
+ std::map<std::string, Directory> Dirs;
// Old and new repository revisions.
std::string OldRevision;
@@ -57,11 +64,11 @@ protected:
virtual void DoRevision(Revision const& revision,
std::vector<Change> const& changes);
virtual void DoModification(PathStatus status, std::string const& path);
- virtual void LoadModifications() = 0;
- virtual void LoadRevisions() = 0;
+ virtual bool LoadModifications() = 0;
+ virtual bool LoadRevisions() = 0;
- virtual void WriteXMLGlobal(std::ostream& xml);
- void WriteXMLDirectory(std::ostream& xml, std::string const& path,
+ virtual void WriteXMLGlobal(cmXMLWriter& xml);
+ void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir);
};
diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx
index 86a7617f1..49f9a6500 100644
--- a/Source/CTest/cmCTestHG.cxx
+++ b/Source/CTest/cmCTestHG.cxx
@@ -1,105 +1,102 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestHG.h"
#include "cmCTest.h"
+#include "cmCTestVC.h"
+#include "cmProcessTools.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <ostream>
+#include <vector>
-//----------------------------------------------------------------------------
-cmCTestHG::cmCTestHG(cmCTest* ct, std::ostream& log):
- cmCTestGlobalVC(ct, log)
+cmCTestHG::cmCTestHG(cmCTest* ct, std::ostream& log)
+ : cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
}
-//----------------------------------------------------------------------------
cmCTestHG::~cmCTestHG()
{
}
-//----------------------------------------------------------------------------
-class cmCTestHG::IdentifyParser: public cmCTestVC::LineParser
+class cmCTestHG::IdentifyParser : public cmCTestVC::LineParser
{
public:
- IdentifyParser(cmCTestHG* hg, const char* prefix,
- std::string& rev): Rev(rev)
- {
+ IdentifyParser(cmCTestHG* hg, const char* prefix, std::string& rev)
+ : Rev(rev)
+ {
this->SetLog(&hg->Log, prefix);
this->RegexIdentify.compile("^([0-9a-f]+)");
- }
+ }
+
private:
std::string& Rev;
cmsys::RegularExpression RegexIdentify;
- bool ProcessLine()
- {
- if(this->RegexIdentify.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexIdentify.find(this->Line)) {
this->Rev = this->RegexIdentify.match(1);
return false;
- }
- return true;
}
+ return true;
+ }
};
-//----------------------------------------------------------------------------
-class cmCTestHG::StatusParser: public cmCTestVC::LineParser
+class cmCTestHG::StatusParser : public cmCTestVC::LineParser
{
public:
- StatusParser(cmCTestHG* hg, const char* prefix): HG(hg)
- {
+ StatusParser(cmCTestHG* hg, const char* prefix)
+ : HG(hg)
+ {
this->SetLog(&hg->Log, prefix);
this->RegexStatus.compile("([MARC!?I]) (.*)");
- }
+ }
private:
cmCTestHG* HG;
cmsys::RegularExpression RegexStatus;
- bool ProcessLine()
- {
- if(this->RegexStatus.find(this->Line))
- {
- this->DoPath(this->RegexStatus.match(1)[0],
- this->RegexStatus.match(2));
- }
- return true;
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexStatus.find(this->Line)) {
+ this->DoPath(this->RegexStatus.match(1)[0], this->RegexStatus.match(2));
}
+ return true;
+ }
void DoPath(char status, std::string const& path)
- {
- if(path.empty()) return;
+ {
+ if (path.empty()) {
+ return;
+ }
// See "hg help status". Note that there is no 'conflict' status.
- switch(status)
- {
- case 'M': case 'A': case '!': case 'R':
+ switch (status) {
+ case 'M':
+ case 'A':
+ case '!':
+ case 'R':
this->HG->DoModification(PathModified, path);
break;
- case 'I': case '?': case 'C': case ' ': default:
+ case 'I':
+ case '?':
+ case 'C':
+ case ' ':
+ default:
break;
- }
}
+ }
};
-//----------------------------------------------------------------------------
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", 0};
+ const char* hg_identify[] = { hg, "identify", "-i", CM_NULLPTR };
std::string rev;
IdentifyParser out(this, "rev-out> ", rev);
OutputLogger err(this->Log, "rev-err> ");
@@ -107,33 +104,32 @@ std::string cmCTestHG::GetWorkingRevision()
return rev;
}
-//----------------------------------------------------------------------------
-void cmCTestHG::NoteOldRevision()
+bool cmCTestHG::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ << this->OldRevision << "\n");
this->PriorRev.Rev = this->OldRevision;
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestHG::NoteNewRevision()
+bool cmCTestHG::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ << this->NewRevision << "\n");
+ return true;
}
-//----------------------------------------------------------------------------
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", 0};
- OutputLogger out(this->Log, "pull-out> ");
- OutputLogger err(this->Log, "pull-err> ");
- this->RunChild(&hg_pull[0], &out, &err);
+ const char* hg = this->CommandLineTool.c_str();
+ const char* hg_pull[] = { hg, "pull", "-v", CM_NULLPTR };
+ OutputLogger out(this->Log, "pull-out> ");
+ OutputLogger err(this->Log, "pull-err> ");
+ this->RunChild(&hg_pull[0], &out, &err);
}
// TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
@@ -145,33 +141,34 @@ bool cmCTestHG::UpdateImpl()
// Add user-specified update options.
std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
- if(opts.empty())
- {
+ if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("HGUpdateOptions");
- }
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(opts.c_str());
- for(std::vector<cmStdString>::const_iterator ai = args.begin();
- ai != args.end(); ++ai)
- {
+ }
+ 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());
- }
+ }
// Sentinel argument.
- hg_update.push_back(0);
+ hg_update.push_back(CM_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):
- OutputLogger(hg->Log, prefix), HG(hg) { this->InitializeParser(); }
- ~LogParser() { this->CleanupParser(); }
+ LogParser(cmCTestHG* hg, const char* prefix)
+ : OutputLogger(hg->Log, prefix)
+ , HG(hg)
+ {
+ this->InitializeParser();
+ }
+ ~LogParser() CM_OVERRIDE { this->CleanupParser(); }
private:
cmCTestHG* HG;
@@ -182,119 +179,92 @@ private:
Change CurChange;
std::vector<char> CData;
- virtual bool ProcessChunk(const char* data, int length)
- {
+ bool ProcessChunk(const char* data, int length) CM_OVERRIDE
+ {
this->OutputLogger::ProcessChunk(data, length);
this->ParseChunk(data, length);
return true;
- }
+ }
- virtual void StartElement(const char* name, const char** atts)
- {
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
this->CData.clear();
- if(strcmp(name, "logentry") == 0)
- {
+ if (name == "logentry") {
this->Rev = Revision();
- if(const char* rev = this->FindAttribute(atts, "revision"))
- {
+ if (const char* rev = this->FindAttribute(atts, "revision")) {
this->Rev.Rev = rev;
- }
- this->Changes.clear();
}
+ this->Changes.clear();
}
+ }
- virtual void CharacterDataHandler(const char* data, int length)
- {
- this->CData.insert(this->CData.end(), data, data+length);
- }
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ this->CData.insert(this->CData.end(), data, data + length);
+ }
- virtual void EndElement(const char* name)
- {
- if(strcmp(name, "logentry") == 0)
- {
+ void EndElement(const std::string& name) CM_OVERRIDE
+ {
+ if (name == "logentry") {
this->HG->DoRevision(this->Rev, this->Changes);
- }
- else if(strcmp(name, "author") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "author") {
this->Rev.Author.assign(&this->CData[0], this->CData.size());
- }
- else if ( strcmp(name, "email") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "email") {
this->Rev.EMail.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "date") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "date") {
this->Rev.Date.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "msg") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "msg") {
this->Rev.Log.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "files") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "files") {
std::vector<std::string> paths = this->SplitCData();
- for(unsigned int i = 0; i < paths.size(); ++i)
- {
+ for (unsigned int i = 0; i < paths.size(); ++i) {
// Updated by default, will be modified using file_adds and
// file_dels.
this->CurChange = Change('U');
this->CurChange.Path = paths[i];
this->Changes.push_back(this->CurChange);
- }
}
- else if(strcmp(name, "file_adds") == 0 && !this->CData.empty())
- {
+ } 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)
- {
+ 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';
- }
}
}
- else if(strcmp(name, "file_dels") == 0 && !this->CData.empty())
- {
+ } 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)
- {
+ 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';
- }
}
}
- this->CData.clear();
}
+ this->CData.clear();
+ }
std::vector<std::string> SplitCData()
- {
+ {
std::vector<std::string> output;
std::string currPath;
- for(unsigned int i=0; i < this->CData.size(); ++i)
- {
- if(this->CData[i] != ' ')
- {
+ for (unsigned int i = 0; i < this->CData.size(); ++i) {
+ if (this->CData[i] != ' ') {
currPath += this->CData[i];
- }
- else
- {
+ } else {
output.push_back(currPath);
currPath = "";
- }
}
+ }
output.push_back(currPath);
return output;
- }
+ }
- virtual void ReportError(int, int, const char* msg)
- {
+ void ReportError(int /*line*/, int /*column*/, const char* msg) CM_OVERRIDE
+ {
this->HG->Log << "Error parsing hg log xml: " << msg << "\n";
- }
+ }
};
-//----------------------------------------------------------------------------
-void cmCTestHG::LoadRevisions()
+bool cmCTestHG::LoadRevisions()
{
// Use 'hg log' to get revisions in a xml format.
//
@@ -304,19 +274,20 @@ void cmCTestHG::LoadRevisions()
// proper XML escapes.
std::string range = this->OldRevision + ":" + this->NewRevision;
const char* hg = this->CommandLineTool.c_str();
- const char* hgXMLTemplate =
- "<logentry\n"
- " revision=\"{node|short}\">\n"
- " <author>{author|person}</author>\n"
- " <email>{author|email}</email>\n"
- " <date>{date|isodate}</date>\n"
- " <msg>{desc}</msg>\n"
- " <files>{files}</files>\n"
- " <file_adds>{file_adds}</file_adds>\n"
- " <file_dels>{file_dels}</file_dels>\n"
- "</logentry>\n";
- const char* hg_log[] = {hg, "log","--removed", "-r", range.c_str(),
- "--template", hgXMLTemplate, 0};
+ const char* hgXMLTemplate = "<logentry\n"
+ " revision=\"{node|short}\">\n"
+ " <author>{author|person}</author>\n"
+ " <email>{author|email}</email>\n"
+ " <date>{date|isodate}</date>\n"
+ " <msg>{desc}</msg>\n"
+ " <files>{files}</files>\n"
+ " <file_adds>{file_adds}</file_adds>\n"
+ " <file_dels>{file_dels}</file_dels>\n"
+ "</logentry>\n";
+ const char* hg_log[] = {
+ hg, "log", "--removed", "-r", range.c_str(),
+ "--template", hgXMLTemplate, CM_NULLPTR
+ };
LogParser out(this, "log-out> ");
out.Process("<?xml version=\"1.0\"?>\n"
@@ -324,15 +295,16 @@ void cmCTestHG::LoadRevisions()
OutputLogger err(this->Log, "log-err> ");
this->RunChild(hg_log, &out, &err);
out.Process("</log>\n");
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestHG::LoadModifications()
+bool cmCTestHG::LoadModifications()
{
// Use 'hg status' to get modified files.
const char* hg = this->CommandLineTool.c_str();
- const char* hg_status[] = {hg, "status", 0};
+ const char* hg_status[] = { hg, "status", CM_NULLPTR };
StatusParser out(this, "status-out> ");
OutputLogger err(this->Log, "status-err> ");
this->RunChild(hg_status, &out, &err);
+ return true;
}
diff --git a/Source/CTest/cmCTestHG.h b/Source/CTest/cmCTestHG.h
index 1eaf9337e..ec9eaffe8 100644
--- a/Source/CTest/cmCTestHG.h
+++ b/Source/CTest/cmCTestHG.h
@@ -1,47 +1,46 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestHG_h
#define cmCTestHG_h
+#include "cmConfigure.h"
+
#include "cmCTestGlobalVC.h"
+#include <iosfwd>
+#include <string>
+
+class cmCTest;
+
/** \class cmCTestHG
* \brief Interaction with Mercurial command-line tool
*
*/
-class cmCTestHG: public cmCTestGlobalVC
+class cmCTestHG : public cmCTestGlobalVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestHG(cmCTest* ctest, std::ostream& log);
- virtual ~cmCTestHG();
+ ~cmCTestHG() CM_OVERRIDE;
private:
std::string GetWorkingRevision();
- virtual void NoteOldRevision();
- virtual void NoteNewRevision();
- virtual bool UpdateImpl();
+ bool NoteOldRevision() CM_OVERRIDE;
+ bool NoteNewRevision() CM_OVERRIDE;
+ bool UpdateImpl() CM_OVERRIDE;
- void LoadRevisions();
- void LoadModifications();
+ bool LoadRevisions() CM_OVERRIDE;
+ bool LoadModifications() CM_OVERRIDE;
// Parsing helper classes.
class IdentifyParser;
- class StatusParser;
class LogParser;
+ class StatusParser;
+
friend class IdentifyParser;
- friend class StatusParser;
friend class LogParser;
+ friend class StatusParser;
};
#endif
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 2e2feb047..c99e450d0 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -1,63 +1,139 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestHandlerCommand.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmMakefile.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(0);
- }
+ 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;
}
-bool cmCTestHandlerCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+namespace {
+// class to save and restore the error state for ctest_* commands
+// if a ctest_* command has a CAPTURE_CMAKE_ERROR then put the error
+// state into there and restore the system wide error to what
+// it was before the command ran
+class SaveRestoreErrorState
{
+public:
+ SaveRestoreErrorState()
+ {
+ this->InitialErrorState = cmSystemTools::GetErrorOccuredFlag();
+ cmSystemTools::ResetErrorOccuredFlag(); // rest the error state
+ this->CaptureCMakeErrorValue = false;
+ }
+ // if the function has a CAPTURE_CMAKE_ERROR then we should restore
+ // the error state to what it was before the function was run
+ // if not then let the error state be what it is
+ void CaptureCMakeError() { this->CaptureCMakeErrorValue = true; }
+ ~SaveRestoreErrorState()
+ {
+ // if we are not saving the return value then make sure
+ // if it was in error it goes back to being in error
+ // otherwise leave it be what it is
+ if (!this->CaptureCMakeErrorValue) {
+ if (this->InitialErrorState) {
+ cmSystemTools::SetErrorOccured();
+ }
+ return;
+ }
+ // if we have saved the error in a return variable
+ // then put things back exactly like they were
+ bool currentState = cmSystemTools::GetErrorOccuredFlag();
+ // if the state changed during this command we need
+ // to handle it, if not then nothing needs to be done
+ if (currentState != this->InitialErrorState) {
+ // restore the initial error state
+ if (this->InitialErrorState) {
+ cmSystemTools::SetErrorOccured();
+ } else {
+ cmSystemTools::ResetErrorOccuredFlag();
+ }
+ }
+ }
+
+private:
+ bool InitialErrorState;
+ bool CaptureCMakeErrorValue;
+};
+}
+
+bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/)
+{
+ // save error state and restore it if needed
+ SaveRestoreErrorState errorState;
// Allocate space for argument values.
this->Values.clear();
- this->Values.resize(this->Last, 0);
+ this->Values.resize(this->Last, CM_NULLPTR);
// Process input arguments.
this->ArgumentDoing = ArgumentDoingNone;
- for(unsigned int i=0; i < args.size(); ++i)
- {
+ // 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]))
- {
- cmOStringStream e;
+ if (!this->CheckArgumentKeyword(args[i]) &&
+ !this->CheckArgumentValue(args[i])) {
+ std::ostringstream e;
e << "called with unknown argument \"" << args[i] << "\".";
- this->SetError(e.str().c_str());
- return false;
- }
-
- // Quit if an argument is invalid.
- if(this->ArgumentDoing == ArgumentDoingError)
- {
- return false;
+ this->SetError(e.str());
+ foundBadArgument = true;
+ }
+ // note bad argument
+ if (this->ArgumentDoing == ArgumentDoingError) {
+ foundBadArgument = true;
+ }
+ }
+ bool capureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
+ *this->Values[ct_CAPTURE_CMAKE_ERROR]);
+ // now that arguments are parsed check to see if there is a
+ // CAPTURE_CMAKE_ERROR specified let the errorState object know.
+ if (capureCMakeError) {
+ 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 (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
}
+ // return success because failure is recorded in CAPTURE_CMAKE_ERROR
+ return true;
}
+ // return failure because of bad argument
+ return false;
+ }
// Set the config type of this ctest to the current value of the
// CTEST_CONFIGURATION_TYPE script variable if it is defined.
@@ -65,134 +141,156 @@ bool cmCTestHandlerCommand
// line.
const char* ctestConfigType =
this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE");
- if (ctestConfigType)
- {
+ if (ctestConfigType) {
this->CTest->SetConfigType(ctestConfigType);
- }
+ }
- if ( this->Values[ct_BUILD] )
- {
- this->CTest->SetCTestConfiguration("BuildDirectory",
- cmSystemTools::CollapseFullPath(
- this->Values[ct_BUILD]).c_str());
- }
- else
- {
+ if (this->Values[ct_BUILD]) {
+ this->CTest->SetCTestConfiguration(
+ "BuildDirectory",
+ cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(),
+ this->Quiet);
+ } else {
const char* bdir =
this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
- if(bdir)
- {
- this->
- CTest->SetCTestConfiguration("BuildDirectory",
- cmSystemTools::CollapseFullPath(bdir).c_str());
- }
- else
- {
- 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);
- this->CTest->SetCTestConfiguration("SourceDirectory",
- cmSystemTools::CollapseFullPath(
- this->Values[ct_SOURCE]).c_str());
+ if (bdir) {
+ this->CTest->SetCTestConfiguration(
+ "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(),
+ this->Quiet);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "CTEST_BINARY_DIRECTORY not set"
+ << std::endl;);
}
- else
- {
- this->CTest->SetCTestConfiguration("SourceDirectory",
+ }
+ if (this->Values[ct_SOURCE]) {
+ cmCTestLog(this->CTest, DEBUG, "Set source directory to: "
+ << this->Values[ct_SOURCE] << std::endl);
+ this->CTest->SetCTestConfiguration(
+ "SourceDirectory",
+ cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
+ this->Quiet);
+ } else {
+ this->CTest->SetCTestConfiguration(
+ "SourceDirectory",
cmSystemTools::CollapseFullPath(
- this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")).c_str());
- }
+ this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY"))
+ .c_str(),
+ this->Quiet);
+ }
+
+ if (const char* changeId =
+ this->Makefile->GetDefinition("CTEST_CHANGE_ID")) {
+ this->CTest->SetCTestConfiguration("ChangeId", changeId, this->Quiet);
+ }
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);
- return false;
+ 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, err << " error from command\n");
+ }
+ return true;
}
+ return false;
+ }
handler->SetAppendXML(this->AppendXML);
handler->PopulateCustomVectors(this->Makefile);
- if ( this->Values[ct_SUBMIT_INDEX] )
- {
- if(!this->CTest->GetDropSiteCDash() && this->CTest->GetDartVersion() <= 1)
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
+ 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
- {
+ << 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]));
- }
}
- std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(
- this->CTest->GetCTestConfiguration("BuildDirectory").c_str());
+ }
+ cmWorkingDirectory workdir(
+ this->CTest->GetCTestConfiguration("BuildDirectory"));
int res = handler->ProcessHandler();
- if ( this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE])
- {
- cmOStringStream str;
+ 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());
+ this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE],
+ str.str().c_str());
+ }
+ this->ProcessAdditionalValues(handler);
+ // log the error message if there was an error
+ if (capureCMakeError) {
+ const char* returnString = "0";
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ returnString = "-1";
+ const char* err = this->GetError();
+ // print out the error if it is not "unknown error" which means
+ // there was no message
+ if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, err);
+ }
}
- cmSystemTools::ChangeDirectory(current_dir.c_str());
+ // store the captured cmake error state 0 or -1
+ this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
+ returnString);
+ }
return true;
}
-//----------------------------------------------------------------------------
+void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
+{
+}
+
bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
{
// Look for non-value arguments common to all commands.
- if(arg == "APPEND")
- {
+ 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])
- {
+ 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;
}
-//----------------------------------------------------------------------------
bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg)
{
- if(this->ArgumentDoing == ArgumentDoingKeyword)
- {
+ if (this->ArgumentDoing == ArgumentDoingKeyword) {
this->ArgumentDoing = ArgumentDoingNone;
unsigned int k = this->ArgumentIndex;
- if(this->Values[k])
- {
- cmOStringStream e;
+ 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");
+ 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 8ef2b8028..0ea061225 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -1,20 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestHandlerCommand_h
#define cmCTestHandlerCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestCommand.h"
+#include <stddef.h>
+#include <string>
+#include <vector>
+
class cmCTestGenericHandler;
+class cmExecutionStatus;
/** \class cmCTestHandler
* \brief Run a ctest script
@@ -27,27 +25,33 @@ public:
cmCTestHandlerCommand();
/**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual std::string GetName() const = 0;
+
+ /**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- cmTypeMacro(cmCTestHandlerCommand, cmCTestCommand);
+ 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
- };
+ };
protected:
virtual cmCTestGenericHandler* InitializeHandler() = 0;
+ virtual void ProcessAdditionalValues(cmCTestGenericHandler* handler);
+
// Command argument handling.
virtual bool CheckArgumentKeyword(std::string const& arg);
virtual bool CheckArgumentValue(std::string const& arg);
@@ -62,6 +66,7 @@ protected:
unsigned int ArgumentIndex;
bool AppendXML;
+ bool Quiet;
std::string ReturnVariable;
std::vector<const char*> Arguments;
@@ -69,9 +74,9 @@ protected:
size_t Last;
};
-#define CTEST_COMMAND_APPEND_OPTION_DOCS \
- "The APPEND option marks results for append to those previously " \
- "submitted to a dashboard server since the last ctest_start. " \
+#define CTEST_COMMAND_APPEND_OPTION_DOCS \
+ "The APPEND option marks results for append to those previously " \
+ "submitted to a dashboard server since the last ctest_start. " \
"Append semantics are defined by the dashboard server in use."
#endif
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 9831d0200..5b213518a 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -1,37 +1,43 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestLaunch.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCTestLaunch.h"
+#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 "cmStateSnapshot.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
+#include "cm_auto_ptr.hxx"
#include "cmake.h"
-#include <cmsys/MD5.h>
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
+#ifdef _WIN32
+#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 = 0;
+ this->Process = CM_NULLPTR;
this->ExitCode = 1;
this->CWD = cmSystemTools::GetCurrentWorkingDirectory();
- if(!this->ParseArguments(argc, argv))
- {
+ if (!this->ParseArguments(argc, argv)) {
return;
- }
+ }
this->ComputeFileNames();
@@ -41,148 +47,117 @@ cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
this->Process = cmsysProcess_New();
}
-//----------------------------------------------------------------------------
cmCTestLaunch::~cmCTestLaunch()
{
cmsysProcess_Delete(this->Process);
- if(!this->Passthru)
- {
- cmSystemTools::RemoveFile(this->LogOut.c_str());
- cmSystemTools::RemoveFile(this->LogErr.c_str());
- }
+ if (!this->Passthru) {
+ cmSystemTools::RemoveFile(this->LogOut);
+ cmSystemTools::RemoveFile(this->LogErr);
+ }
}
-//----------------------------------------------------------------------------
bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv)
{
// Launcher options occur first and are separated from the real
// command line by a '--' option.
- enum Doing { DoingNone,
- DoingOutput,
- DoingSource,
- DoingLanguage,
- DoingTargetName,
- DoingTargetType,
- DoingBuildDir,
- DoingCount };
+ enum Doing
+ {
+ DoingNone,
+ DoingOutput,
+ DoingSource,
+ DoingLanguage,
+ DoingTargetName,
+ DoingTargetType,
+ DoingBuildDir,
+ DoingCount,
+ DoingFilterPrefix
+ };
Doing doing = DoingNone;
int arg0 = 0;
- for(int i=1; !arg0 && i < argc; ++i)
- {
+ for (int i = 1; !arg0 && i < argc; ++i) {
const char* arg = argv[i];
- if(strcmp(arg, "--") == 0)
- {
- arg0 = i+1;
- }
- else if(strcmp(arg, "--output") == 0)
- {
+ if (strcmp(arg, "--") == 0) {
+ arg0 = i + 1;
+ } else if (strcmp(arg, "--output") == 0) {
doing = DoingOutput;
- }
- else if(strcmp(arg, "--source") == 0)
- {
+ } else if (strcmp(arg, "--source") == 0) {
doing = DoingSource;
- }
- else if(strcmp(arg, "--language") == 0)
- {
+ } else if (strcmp(arg, "--language") == 0) {
doing = DoingLanguage;
- }
- else if(strcmp(arg, "--target-name") == 0)
- {
+ } else if (strcmp(arg, "--target-name") == 0) {
doing = DoingTargetName;
- }
- else if(strcmp(arg, "--target-type") == 0)
- {
+ } else if (strcmp(arg, "--target-type") == 0) {
doing = DoingTargetType;
- }
- else if(strcmp(arg, "--build-dir") == 0)
- {
+ } else if (strcmp(arg, "--build-dir") == 0) {
doing = DoingBuildDir;
- }
- else if(doing == DoingOutput)
- {
+ } else if (strcmp(arg, "--filter-prefix") == 0) {
+ doing = DoingFilterPrefix;
+ } else if (doing == DoingOutput) {
this->OptionOutput = arg;
doing = DoingNone;
- }
- else if(doing == DoingSource)
- {
+ } else if (doing == DoingSource) {
this->OptionSource = arg;
doing = DoingNone;
- }
- else if(doing == DoingLanguage)
- {
+ } else if (doing == DoingLanguage) {
this->OptionLanguage = arg;
- if(this->OptionLanguage == "CXX")
- {
+ if (this->OptionLanguage == "CXX") {
this->OptionLanguage = "C++";
- }
- doing = DoingNone;
}
- else if(doing == DoingTargetName)
- {
+ doing = DoingNone;
+ } else if (doing == DoingTargetName) {
this->OptionTargetName = arg;
doing = DoingNone;
- }
- else if(doing == DoingTargetType)
- {
+ } else if (doing == DoingTargetType) {
this->OptionTargetType = arg;
doing = DoingNone;
- }
- else if(doing == DoingBuildDir)
- {
+ } else if (doing == DoingBuildDir) {
this->OptionBuildDir = arg;
doing = DoingNone;
- }
+ } else if (doing == DoingFilterPrefix) {
+ this->OptionFilterPrefix = arg;
+ doing = DoingNone;
}
+ }
// Extract the real command line.
- if(arg0)
- {
+ if (arg0) {
this->RealArgC = argc - arg0;
this->RealArgV = argv + arg0;
- for(int i=0; i < this->RealArgC; ++i)
- {
+ for (int i = 0; i < this->RealArgC; ++i) {
this->HandleRealArg(this->RealArgV[i]);
- }
- return true;
- }
- else
- {
- this->RealArgC = 0;
- this->RealArgV = 0;
- std::cerr << "No launch/command separator ('--') found!\n";
- return false;
}
+ return true;
+ }
+ this->RealArgC = 0;
+ this->RealArgV = CM_NULLPTR;
+ std::cerr << "No launch/command separator ('--') found!\n";
+ return false;
}
-//----------------------------------------------------------------------------
void cmCTestLaunch::HandleRealArg(const char* arg)
{
#ifdef _WIN32
// Expand response file arguments.
- if(arg[0] == '@' && cmSystemTools::FileExists(arg+1))
- {
- std::ifstream fin(arg+1);
+ if (arg[0] == '@' && cmSystemTools::FileExists(arg + 1)) {
+ cmsys::ifstream fin(arg + 1);
std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
cmSystemTools::ParseWindowsCommandLine(line.c_str(), this->RealArgs);
- }
- return;
}
+ return;
+ }
#endif
this->RealArgs.push_back(arg);
}
-//----------------------------------------------------------------------------
void cmCTestLaunch::ComputeFileNames()
{
// We just passthru the behavior of the real command unless the
// CTEST_LAUNCH_LOGS environment variable is set.
const char* d = getenv("CTEST_LAUNCH_LOGS");
- if(!(d && *d))
- {
+ if (!(d && *d)) {
return;
- }
+ }
this->Passthru = false;
// The environment variable specifies the directory into which we
@@ -193,18 +168,14 @@ void cmCTestLaunch::ComputeFileNames()
// We hash the input command working dir and command line to obtain
// a repeatable and (probably) unique name for log files.
- char hash[32];
- cmsysMD5* md5 = cmsysMD5_New();
- cmsysMD5_Initialize(md5);
- cmsysMD5_Append(md5, (unsigned char const*)(this->CWD.c_str()), -1);
- for(std::vector<std::string>::const_iterator ai = this->RealArgs.begin();
- ai != this->RealArgs.end(); ++ai)
- {
- cmsysMD5_Append(md5, (unsigned char const*)ai->c_str(), -1);
- }
- cmsysMD5_FinalizeHex(md5, hash);
- cmsysMD5_Delete(md5);
- this->LogHash.assign(hash, 32);
+ 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);
+ }
+ this->LogHash = md5.FinalizeHex();
// We store stdout and stderr in temporary log files.
this->LogOut = this->LogDir;
@@ -217,82 +188,88 @@ void cmCTestLaunch::ComputeFileNames()
this->LogErr += "-err.txt";
}
-//----------------------------------------------------------------------------
void cmCTestLaunch::RunChild()
{
// Ignore noopt make rules
- if(this->RealArgs.empty() || this->RealArgs[0] == ":")
- {
+ if (this->RealArgs.empty() || this->RealArgs[0] == ":") {
this->ExitCode = 0;
return;
- }
+ }
// Prepare to run the real command.
cmsysProcess* cp = this->Process;
cmsysProcess_SetCommand(cp, this->RealArgV);
- std::ofstream fout;
- std::ofstream ferr;
- if(this->Passthru)
- {
+ cmsys::ofstream fout;
+ cmsys::ofstream ferr;
+ if (this->Passthru) {
// In passthru mode we just share the output pipes.
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
- }
- else
- {
+ } else {
// In full mode we record the child output pipes to log files.
- fout.open(this->LogOut.c_str(),
- std::ios::out | std::ios::binary);
- ferr.open(this->LogErr.c_str(),
- std::ios::out | std::ios::binary);
- }
+ fout.open(this->LogOut.c_str(), std::ios::out | std::ios::binary);
+ ferr.open(this->LogErr.c_str(), std::ios::out | std::ios::binary);
+ }
+
+#ifdef _WIN32
+ // Do this so that newline transformation is not done when writing to cout
+ // and cerr below.
+ _setmode(fileno(stdout), _O_BINARY);
+ _setmode(fileno(stderr), _O_BINARY);
+#endif
// Run the real command.
cmsysProcess_Execute(cp);
// Record child stdout and stderr if necessary.
- if(!this->Passthru)
- {
- char* data = 0;
+ if (!this->Passthru) {
+ char* data = CM_NULLPTR;
int length = 0;
- while(int p = cmsysProcess_WaitForData(cp, &data, &length, 0))
- {
- if(p == cmsysProcess_Pipe_STDOUT)
- {
- fout.write(data, length);
- std::cout.write(data, length);
+ cmProcessOutput processOutput;
+ std::string strdata;
+ while (int p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) {
+ if (p == cmsysProcess_Pipe_STDOUT) {
+ processOutput.DecodeText(data, length, strdata, 1);
+ fout.write(strdata.c_str(), strdata.size());
+ std::cout.write(strdata.c_str(), strdata.size());
this->HaveOut = true;
- }
- else if(p == cmsysProcess_Pipe_STDERR)
- {
- ferr.write(data, length);
- std::cerr.write(data, length);
+ } else if (p == cmsysProcess_Pipe_STDERR) {
+ processOutput.DecodeText(data, length, strdata, 2);
+ ferr.write(strdata.c_str(), strdata.size());
+ std::cerr.write(strdata.c_str(), strdata.size());
this->HaveErr = true;
- }
}
}
+ processOutput.DecodeText(std::string(), strdata, 1);
+ if (!strdata.empty()) {
+ fout.write(strdata.c_str(), strdata.size());
+ std::cout.write(strdata.c_str(), strdata.size());
+ }
+ processOutput.DecodeText(std::string(), strdata, 2);
+ if (!strdata.empty()) {
+ ferr.write(strdata.c_str(), strdata.size());
+ std::cerr.write(strdata.c_str(), strdata.size());
+ }
+ }
// Wait for the real command to finish.
- cmsysProcess_WaitForExit(cp, 0);
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
this->ExitCode = cmsysProcess_GetExitValue(cp);
}
-//----------------------------------------------------------------------------
int cmCTestLaunch::Run()
{
- if(!this->Process)
- {
+ if (!this->Process) {
std::cerr << "Could not allocate cmsysProcess instance!\n";
return -1;
- }
+ }
this->RunChild();
- if(this->CheckResults())
- {
+ if (this->CheckResults()) {
return this->ExitCode;
- }
+ }
this->LoadConfig();
this->WriteXML();
@@ -300,13 +277,11 @@ int cmCTestLaunch::Run()
return this->ExitCode;
}
-//----------------------------------------------------------------------------
void cmCTestLaunch::LoadLabels()
{
- if(this->OptionBuildDir.empty() || this->OptionTargetName.empty())
- {
+ if (this->OptionBuildDir.empty() || this->OptionTargetName.empty()) {
return;
- }
+ }
// Labels are listed in per-target files.
std::string fname = this->OptionBuildDir;
@@ -320,42 +295,35 @@ void cmCTestLaunch::LoadLabels()
cmSystemTools::ConvertToUnixSlashes(source);
// Load the labels file.
- std::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
- if(!fin) { return; }
+ cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
+ if (!fin) {
+ return;
+ }
bool inTarget = true;
bool inSource = false;
std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- if(line.empty() || line[0] == '#')
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (line.empty() || line[0] == '#') {
// Ignore blank and comment lines.
continue;
- }
- else if(line[0] == ' ')
- {
+ }
+ if (line[0] == ' ') {
// Label lines appear indented by one space.
- if(inTarget || inSource)
- {
- this->Labels.insert(line.c_str()+1);
- }
+ if (inTarget || inSource) {
+ this->Labels.insert(line.c_str() + 1);
}
- else if(!this->OptionSource.empty() && !inSource)
- {
+ } else if (!this->OptionSource.empty() && !inSource) {
// Non-indented lines specify a source file name. The first one
// is the end of the target-wide labels. Use labels following a
// matching source.
inTarget = false;
inSource = this->SourceMatches(line, source);
- }
- else
- {
+ } else {
return;
- }
}
+ }
}
-//----------------------------------------------------------------------------
bool cmCTestLaunch::SourceMatches(std::string const& lhs,
std::string const& rhs)
{
@@ -366,251 +334,212 @@ bool cmCTestLaunch::SourceMatches(std::string const& lhs,
return lhs == rhs;
}
-//----------------------------------------------------------------------------
bool cmCTestLaunch::IsError() const
{
return this->ExitCode != 0;
}
-//----------------------------------------------------------------------------
void cmCTestLaunch::WriteXML()
{
// Name the xml file.
std::string logXML = this->LogDir;
- logXML += this->IsError()? "error-" : "warning-";
+ logXML += this->IsError() ? "error-" : "warning-";
logXML += this->LogHash;
logXML += ".xml";
// Use cmGeneratedFileStream to atomically create the report file.
cmGeneratedFileStream fxml(logXML.c_str());
- fxml << "\t<Failure type=\""
- << (this->IsError()? "Error" : "Warning") << "\">\n";
- this->WriteXMLAction(fxml);
- this->WriteXMLCommand(fxml);
- this->WriteXMLResult(fxml);
- this->WriteXMLLabels(fxml);
- fxml << "\t</Failure>\n";
+ 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
}
-//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
{
- fxml << "\t\t<!-- Meta-information about the build action -->\n";
- fxml << "\t\t<Action>\n";
+ xml.Comment("Meta-information about the build action");
+ xml.StartElement("Action");
// TargetName
- if(!this->OptionTargetName.empty())
- {
- fxml << "\t\t\t<TargetName>"
- << cmXMLSafe(this->OptionTargetName)
- << "</TargetName>\n";
- }
+ if (!this->OptionTargetName.empty()) {
+ xml.Element("TargetName", this->OptionTargetName);
+ }
// Language
- if(!this->OptionLanguage.empty())
- {
- fxml << "\t\t\t<Language>"
- << cmXMLSafe(this->OptionLanguage)
- << "</Language>\n";
- }
+ if (!this->OptionLanguage.empty()) {
+ xml.Element("Language", this->OptionLanguage);
+ }
// SourceFile
- if(!this->OptionSource.empty())
- {
+ if (!this->OptionSource.empty()) {
std::string source = this->OptionSource;
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()) &&
- cmSystemTools::IsSubDirectory(source.c_str(),
- this->SourceDir.c_str()))
- {
- source = cmSystemTools::RelativePath(this->SourceDir.c_str(),
- source.c_str());
- }
-
- fxml << "\t\t\t<SourceFile>"
- << cmXMLSafe(source)
- << "</SourceFile>\n";
+ if (cmSystemTools::FileIsFullPath(this->SourceDir.c_str()) &&
+ cmSystemTools::FileIsFullPath(source.c_str()) &&
+ cmSystemTools::IsSubDirectory(source, this->SourceDir)) {
+ source =
+ cmSystemTools::RelativePath(this->SourceDir.c_str(), source.c_str());
}
+ xml.Element("SourceFile", source);
+ }
+
// OutputFile
- if(!this->OptionOutput.empty())
- {
- fxml << "\t\t\t<OutputFile>"
- << cmXMLSafe(this->OptionOutput)
- << "</OutputFile>\n";
- }
+ if (!this->OptionOutput.empty()) {
+ xml.Element("OutputFile", this->OptionOutput);
+ }
// OutputType
- const char* outputType = 0;
- if(!this->OptionTargetType.empty())
- {
- if(this->OptionTargetType == "EXECUTABLE")
- {
+ const char* outputType = CM_NULLPTR;
+ if (!this->OptionTargetType.empty()) {
+ if (this->OptionTargetType == "EXECUTABLE") {
outputType = "executable";
- }
- else if(this->OptionTargetType == "SHARED_LIBRARY")
- {
+ } else if (this->OptionTargetType == "SHARED_LIBRARY") {
outputType = "shared library";
- }
- else if(this->OptionTargetType == "MODULE_LIBRARY")
- {
+ } else if (this->OptionTargetType == "MODULE_LIBRARY") {
outputType = "module library";
- }
- else if(this->OptionTargetType == "STATIC_LIBRARY")
- {
+ } else if (this->OptionTargetType == "STATIC_LIBRARY") {
outputType = "static library";
- }
}
- else if(!this->OptionSource.empty())
- {
+ } else if (!this->OptionSource.empty()) {
outputType = "object file";
- }
- if(outputType)
- {
- fxml << "\t\t\t<OutputType>"
- << cmXMLSafe(outputType)
- << "</OutputType>\n";
- }
+ }
+ if (outputType) {
+ xml.Element("OutputType", outputType);
+ }
- fxml << "\t\t</Action>\n";
+ xml.EndElement(); // Action
}
-//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLCommand(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml)
{
- fxml << "\n";
- fxml << "\t\t<!-- Details of command -->\n";
- fxml << "\t\t<Command>\n";
- if(!this->CWD.empty())
- {
- fxml << "\t\t\t<WorkingDirectory>"
- << cmXMLSafe(this->CWD)
- << "</WorkingDirectory>\n";
- }
- for(std::vector<std::string>::const_iterator ai = this->RealArgs.begin();
- ai != this->RealArgs.end(); ++ai)
- {
- fxml << "\t\t\t<Argument>"
- << cmXMLSafe(ai->c_str())
- << "</Argument>\n";
- }
- fxml << "\t\t</Command>\n";
+ xml.Comment("Details of command");
+ xml.StartElement("Command");
+ if (!this->CWD.empty()) {
+ xml.Element("WorkingDirectory", this->CWD);
+ }
+ for (std::vector<std::string>::const_iterator ai = this->RealArgs.begin();
+ ai != this->RealArgs.end(); ++ai) {
+ xml.Element("Argument", *ai);
+ }
+ xml.EndElement(); // Command
}
-//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLResult(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml)
{
- fxml << "\n";
- fxml << "\t\t<!-- Result of command -->\n";
- fxml << "\t\t<Result>\n";
+ xml.Comment("Result of command");
+ xml.StartElement("Result");
// StdOut
- fxml << "\t\t\t<StdOut>";
- this->DumpFileToXML(fxml, this->LogOut);
- fxml << "</StdOut>\n";
+ xml.StartElement("StdOut");
+ this->DumpFileToXML(xml, this->LogOut);
+ xml.EndElement(); // StdOut
// StdErr
- fxml << "\t\t\t<StdErr>";
- this->DumpFileToXML(fxml, this->LogErr);
- fxml << "</StdErr>\n";
+ xml.StartElement("StdErr");
+ this->DumpFileToXML(xml, this->LogErr);
+ xml.EndElement(); // StdErr
// ExitCondition
- fxml << "\t\t\t<ExitCondition>";
+ xml.StartElement("ExitCondition");
cmsysProcess* cp = this->Process;
- switch (cmsysProcess_GetState(cp))
- {
+ switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Starting:
- fxml << "No process has been executed"; break;
+ xml.Content("No process has been executed");
+ break;
case cmsysProcess_State_Executing:
- fxml << "The process is still executing"; break;
+ xml.Content("The process is still executing");
+ break;
case cmsysProcess_State_Disowned:
- fxml << "Disowned"; break;
+ xml.Content("Disowned");
+ break;
case cmsysProcess_State_Killed:
- fxml << "Killed by parent"; break;
+ xml.Content("Killed by parent");
+ break;
case cmsysProcess_State_Expired:
- fxml << "Killed when timeout expired"; break;
+ xml.Content("Killed when timeout expired");
+ break;
case cmsysProcess_State_Exited:
- fxml << this->ExitCode; break;
+ xml.Content(this->ExitCode);
+ break;
case cmsysProcess_State_Exception:
- fxml << "Terminated abnormally: "
- << cmXMLSafe(cmsysProcess_GetExceptionString(cp)); break;
+ xml.Content("Terminated abnormally: ");
+ xml.Content(cmsysProcess_GetExceptionString(cp));
+ break;
case cmsysProcess_State_Error:
- fxml << "Error administrating child process: "
- << cmXMLSafe(cmsysProcess_GetErrorString(cp)); break;
- };
- fxml << "</ExitCondition>\n";
+ xml.Content("Error administrating child process: ");
+ xml.Content(cmsysProcess_GetErrorString(cp));
+ break;
+ };
+ xml.EndElement(); // ExitCondition
- fxml << "\t\t</Result>\n";
+ xml.EndElement(); // Result
}
-//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLLabels(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml)
{
this->LoadLabels();
- if(!this->Labels.empty())
- {
- fxml << "\n";
- fxml << "\t\t<!-- Interested parties -->\n";
- fxml << "\t\t<Labels>\n";
- for(std::set<cmStdString>::const_iterator li = this->Labels.begin();
- li != this->Labels.end(); ++li)
- {
- fxml << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n";
- }
- fxml << "\t\t</Labels>\n";
- }
+ 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);
+ }
+ xml.EndElement(); // Labels
+ }
}
-//----------------------------------------------------------------------------
-void cmCTestLaunch::DumpFileToXML(std::ostream& fxml,
- std::string const& fname)
+void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname)
{
- std::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
std::string line;
const char* sep = "";
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- fxml << sep << cmXMLSafe(line).Quotes(false);
- sep = "\n";
+
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (MatchesFilterPrefix(line)) {
+ continue;
}
+
+ xml.Content(sep);
+ xml.Content(line);
+ sep = "\n";
+ }
}
-//----------------------------------------------------------------------------
bool cmCTestLaunch::CheckResults()
{
// Skip XML in passthru mode.
- if(this->Passthru)
- {
+ if (this->Passthru) {
return true;
- }
+ }
// We always report failure for error conditions.
- if(this->IsError())
- {
+ if (this->IsError()) {
return false;
- }
+ }
// Scrape the output logs to look for warnings.
- if((this->HaveErr && this->ScrapeLog(this->LogErr)) ||
- (this->HaveOut && this->ScrapeLog(this->LogOut)))
- {
+ if ((this->HaveErr && this->ScrapeLog(this->LogErr)) ||
+ (this->HaveOut && this->ScrapeLog(this->LogOut))) {
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
void cmCTestLaunch::LoadScrapeRules()
{
- if(this->ScrapeRulesLoaded)
- {
+ if (this->ScrapeRulesLoaded) {
return;
- }
+ }
this->ScrapeRulesLoaded = true;
// Common compiler warning formats. These are much simpler than the
@@ -625,95 +554,86 @@ void cmCTestLaunch::LoadScrapeRules()
this->LoadScrapeRules("WarningSuppress", this->RegexWarningSuppress);
}
-//----------------------------------------------------------------------------
-void
-cmCTestLaunch
-::LoadScrapeRules(const char* purpose,
- std::vector<cmsys::RegularExpression>& regexps)
+void cmCTestLaunch::LoadScrapeRules(
+ const char* purpose, std::vector<cmsys::RegularExpression>& regexps)
{
std::string fname = this->LogDir;
fname += "Custom";
fname += purpose;
fname += ".txt";
- std::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
+ 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()))
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (rex.compile(line.c_str())) {
regexps.push_back(rex);
- }
}
+ }
}
-//----------------------------------------------------------------------------
bool cmCTestLaunch::ScrapeLog(std::string const& fname)
{
this->LoadScrapeRules();
// Look for log file lines matching warning expressions but not
// suppression expressions.
- std::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- if(this->Match(line.c_str(), this->RegexWarning) &&
- !this->Match(line.c_str(), this->RegexWarningSuppress))
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (MatchesFilterPrefix(line)) {
+ continue;
+ }
+
+ if (this->Match(line, this->RegexWarning) &&
+ !this->Match(line, this->RegexWarningSuppress)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
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 (std::vector<cmsys::RegularExpression>::iterator ri = regexps.begin();
+ ri != regexps.end(); ++ri) {
+ if (ri->find(line.c_str())) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
+bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const
+{
+ return !this->OptionFilterPrefix.empty() &&
+ cmSystemTools::StringStartsWith(line, this->OptionFilterPrefix.c_str());
+}
+
int cmCTestLaunch::Main(int argc, const char* const argv[])
{
- if(argc == 2)
- {
+ if (argc == 2) {
std::cerr << "ctest --launch: this mode is for internal CTest use only"
<< std::endl;
return 1;
- }
+ }
cmCTestLaunch self(argc, argv);
return self.Run();
}
-//----------------------------------------------------------------------------
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-#include <cmsys/auto_ptr.hxx>
void cmCTestLaunch::LoadConfig()
{
- cmake cm;
- cmGlobalGenerator gg;
- gg.SetCMakeInstance(&cm);
- cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
- cmMakefile* mf = lg->GetMakefile();
+ cmake cm(cmake::RoleScript);
+ 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(0, fname.c_str()))
- {
+ if (cmSystemTools::FileExists(fname.c_str()) &&
+ mf->ReadListFile(fname.c_str())) {
this->SourceDir = mf->GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
cmSystemTools::ConvertToUnixSlashes(this->SourceDir);
- }
+ }
}
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index 7457e8357..29986ff60 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -1,19 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestLaunch_h
#define cmCTestLaunch_h
-#include "cmStandardIncludes.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmsys/RegularExpression.hxx"
+#include <set>
+#include <string>
+#include <vector>
+
+class cmXMLWriter;
/** \class cmCTestLaunch
* \brief Launcher for make rules to report results for ctest
@@ -25,6 +22,7 @@ class cmCTestLaunch
public:
/** Entry point from ctest executable main(). */
static int Main(int argc, const char* const argv[]);
+
private:
// Initialize the launcher from its command line.
cmCTestLaunch(int argc, const char* const* argv);
@@ -45,6 +43,7 @@ private:
std::string OptionTargetName;
std::string OptionTargetType;
std::string OptionBuildDir;
+ std::string OptionFilterPrefix;
bool ParseArguments(int argc, const char* const* argv);
// The real command line appearing after launcher arguments.
@@ -72,10 +71,9 @@ private:
bool HaveErr;
// Labels associated with the build rule.
- std::set<cmStdString> Labels;
+ std::set<std::string> Labels;
void LoadLabels();
- bool SourceMatches(std::string const& lhs,
- std::string const& rhs);
+ bool SourceMatches(std::string const& lhs, std::string const& rhs);
// Regular expressions to match warnings and their exceptions.
bool ScrapeRulesLoaded;
@@ -87,14 +85,15 @@ private:
bool ScrapeLog(std::string const& fname);
bool Match(std::string const& line,
std::vector<cmsys::RegularExpression>& regexps);
+ bool MatchesFilterPrefix(std::string const& line) const;
// Methods to generate the xml fragment.
void WriteXML();
- void WriteXMLAction(std::ostream& fxml);
- void WriteXMLCommand(std::ostream& fxml);
- void WriteXMLResult(std::ostream& fxml);
- void WriteXMLLabels(std::ostream& fxml);
- void DumpFileToXML(std::ostream& fxml, std::string const& fname);
+ void WriteXMLAction(cmXMLWriter& xml);
+ void WriteXMLCommand(cmXMLWriter& xml);
+ void WriteXMLResult(cmXMLWriter& xml);
+ void WriteXMLLabels(cmXMLWriter& xml);
+ void DumpFileToXML(cmXMLWriter& xml, std::string const& fname);
// Configuration
void LoadConfig();
diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx
index 535c9934f..b9cae3bfe 100644
--- a/Source/CTest/cmCTestMemCheckCommand.cxx
+++ b/Source/CTest/cmCTestMemCheckCommand.cxx
@@ -1,32 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMemCheckCommand.h"
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmCTestMemCheckHandler.h"
+#include "cmMakefile.h"
+cmCTestMemCheckCommand::cmCTestMemCheckCommand()
+{
+ this->Arguments[ctm_DEFECT_COUNT] = "DEFECT_COUNT";
+ this->Arguments[ctm_LAST] = CM_NULLPTR;
+ this->Last = ctm_LAST;
+}
cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
{
- cmCTestGenericHandler* handler
- = this->CTest->GetInitializedHandler("memcheck");
-
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "MemoryCheckCommand", "CTEST_MEMORYCHECK_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "MemoryCheckCommandOptions", "CTEST_MEMORYCHECK_COMMAND_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "MemoryCheckSuppressionFile", "CTEST_MEMORYCHECK_SUPPRESSIONS_FILE");
-
+ cmCTestGenericHandler* handler =
+ this->CTest->GetInitializedHandler("memcheck");
+
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "MemoryCheckType", "CTEST_MEMORYCHECK_TYPE", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "MemoryCheckSanitizerOptions",
+ "CTEST_MEMORYCHECK_SANITIZER_OPTIONS", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "MemoryCheckCommand", "CTEST_MEMORYCHECK_COMMAND",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "MemoryCheckCommandOptions",
+ "CTEST_MEMORYCHECK_COMMAND_OPTIONS", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "MemoryCheckSuppressionFile",
+ "CTEST_MEMORYCHECK_SUPPRESSIONS_FILE", this->Quiet);
+
+ handler->SetQuiet(this->Quiet);
return handler;
}
+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());
+ }
+}
diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h
index 6db47aec8..fa595594a 100644
--- a/Source/CTest/cmCTestMemCheckCommand.h
+++ b/Source/CTest/cmCTestMemCheckCommand.h
@@ -1,20 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestMemCheckCommand_h
#define cmCTestMemCheckCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestTestCommand.h"
class cmCTestGenericHandler;
+class cmCommand;
/** \class cmCTestMemCheck
* \brief Run a ctest script
@@ -24,65 +18,29 @@ class cmCTestGenericHandler;
class cmCTestMemCheckCommand : public cmCTestTestCommand
{
public:
-
- cmCTestMemCheckCommand() {}
+ cmCTestMemCheckCommand();
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestMemCheckCommand* ni = new cmCTestMemCheckCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_memcheck";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Run tests with a dynamic analysis tool.";
- }
+ }
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_memcheck([BUILD build_dir] [RETURN_VALUE res] [APPEND]\n"
- " [START start number] [END end number]\n"
- " [STRIDE stride number] [EXCLUDE exclude regex ]\n"
- " [INCLUDE include regex] \n"
- " [EXCLUDE_LABEL exclude regex] \n"
- " [INCLUDE_LABEL label regex] \n"
- " [PARALLEL_LEVEL level] )\n"
- "Tests the given build directory and stores results in MemCheck.xml. "
- "The second argument is a variable that will hold value. Optionally, "
- "you can specify the starting test number START, the ending test number "
- "END, the number of tests to skip between each test STRIDE, a regular "
- "expression for tests to run INCLUDE, or a regular expression for tests "
- "not to run EXCLUDE. EXCLUDE_LABEL and INCLUDE_LABEL are regular "
- "expressions for tests to be included or excluded by the test "
- "property LABEL. PARALLEL_LEVEL should be set to a positive number "
- "representing the number of tests to be run in parallel."
- "\n"
- CTEST_COMMAND_APPEND_OPTION_DOCS;
- }
+protected:
+ cmCTestGenericHandler* InitializeActualHandler() CM_OVERRIDE;
- cmTypeMacro(cmCTestMemCheckCommand, cmCTestTestCommand);
+ void ProcessAdditionalValues(cmCTestGenericHandler* handler) CM_OVERRIDE;
-protected:
- cmCTestGenericHandler* InitializeActualHandler();
+ enum
+ {
+ ctm_DEFECT_COUNT = ctt_LAST,
+ ctm_LAST
+ };
};
-
#endif
-
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 3ae2ac6a7..c35f0bc70 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -1,29 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMemCheckHandler.h"
-#include "cmXMLParser.h"
+
#include "cmCTest.h"
-#include "cmake.h"
-#include "cmGeneratedFileStream.h"
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Base64.h>
-#include "cmMakefile.h"
-#include "cmXMLSafe.h"
-
-#include <stdlib.h>
-#include <math.h>
-#include <float.h>
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmXMLWriter.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <iostream>
+#include <sstream>
+#include <string.h>
struct CatToErrorType
{
@@ -31,172 +20,106 @@ struct CatToErrorType
int ErrorCode;
};
-
static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
// Error tags
- {"Write Overrun", cmCTestMemCheckHandler::ABW},
- {"Read Overrun", cmCTestMemCheckHandler::ABR},
- {"Memory Overrun", cmCTestMemCheckHandler::ABW},
- {"Allocation Conflict", cmCTestMemCheckHandler::FMM},
- {"Bad Pointer Use", cmCTestMemCheckHandler::FMW},
- {"Dangling Pointer", cmCTestMemCheckHandler::FMR},
- {0,0}
+ { "Write Overrun", cmCTestMemCheckHandler::ABW },
+ { "Read Overrun", cmCTestMemCheckHandler::ABR },
+ { "Memory Overrun", cmCTestMemCheckHandler::ABW },
+ { "Allocation Conflict", cmCTestMemCheckHandler::FMM },
+ { "Bad Pointer Use", cmCTestMemCheckHandler::FMW },
+ { "Dangling Pointer", cmCTestMemCheckHandler::FMR },
+ { CM_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);
+}
+
// parse the xml file containing the results of last BoundsChecker run
class cmBoundsCheckerParser : public cmXMLParser
{
public:
- cmBoundsCheckerParser(cmCTest* c) { this->CTest = c;}
- void StartElement(const char* name, const char** atts)
- {
- if(strcmp(name, "MemoryLeak") == 0)
- {
- this->Errors.push_back(cmCTestMemCheckHandler::MLK);
- }
- if(strcmp(name, "ResourceLeak") == 0)
- {
- this->Errors.push_back(cmCTestMemCheckHandler::MLK);
- }
- if(strcmp(name, "Error") == 0)
- {
- this->ParseError(atts);
- }
- if(strcmp(name, "Dangling Pointer") == 0)
- {
- this->ParseError(atts);
- }
- // Create the log
- cmOStringStream ostr;
- ostr << name << ":\n";
- int i = 0;
- for(; atts[i] != 0; i+=2)
- {
- ostr << " " << cmXMLSafe(atts[i])
- << " - " << cmXMLSafe(atts[i+1]) << "\n";
- }
- ostr << "\n";
- this->Log += ostr.str();
+ cmBoundsCheckerParser(cmCTest* c)
+ {
+ this->CTest = c;
+ this->SetErrorCallback(xmlReportError, (void*)c);
+ }
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
+ if (name == "MemoryLeak" || name == "ResourceLeak") {
+ this->Errors.push_back(cmCTestMemCheckHandler::MLK);
+ } else if (name == "Error" || name == "Dangling Pointer") {
+ this->ParseError(atts);
}
- void EndElement(const char* )
- {
+ // Create the log
+ std::ostringstream ostr;
+ ostr << name << ":\n";
+ int i = 0;
+ for (; atts[i] != CM_NULLPTR; i += 2) {
+ ostr << " " << atts[i] << " - " << atts[i + 1] << "\n";
}
+ ostr << "\n";
+ this->Log += ostr.str();
+ }
+ void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
const char* GetAttribute(const char* name, const char** atts)
- {
- int i = 0;
- for(; atts[i] != 0; ++i)
- {
- if(strcmp(name, atts[i]) == 0)
- {
- return atts[i+1];
- }
- }
- return 0;
+ {
+ int i = 0;
+ for (; atts[i] != CM_NULLPTR; ++i) {
+ if (strcmp(name, atts[i]) == 0) {
+ return atts[i + 1];
+ }
}
+ return CM_NULLPTR;
+ }
void ParseError(const char** atts)
- {
- CatToErrorType* ptr = cmCTestMemCheckBoundsChecker;
- const char* cat = this->GetAttribute("ErrorCategory", atts);
- if(!cat)
- {
- this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "No Category found in Bounds checker XML\n" );
- return;
- }
- while(ptr->ErrorCategory && cat)
- {
- if(strcmp(ptr->ErrorCategory, cat) == 0)
- {
- this->Errors.push_back(ptr->ErrorCode);
- return; // found it we are done
- }
- ptr++;
- }
- if(ptr->ErrorCategory)
- {
- this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Found unknown Bounds Checker error "
- << ptr->ErrorCategory << std::endl);
- }
+ {
+ CatToErrorType* ptr = cmCTestMemCheckBoundsChecker;
+ const char* cat = this->GetAttribute("ErrorCategory", atts);
+ if (!cat) {
+ this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "No Category found in Bounds checker XML\n");
+ return;
+ }
+ while (ptr->ErrorCategory && cat) {
+ if (strcmp(ptr->ErrorCategory, cat) == 0) {
+ this->Errors.push_back(ptr->ErrorCode);
+ return; // found it we are done
+ }
+ ptr++;
+ }
+ if (ptr->ErrorCategory) {
+ this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Found unknown Bounds Checker error " << ptr->ErrorCategory
+ << std::endl);
}
+ }
cmCTest* CTest;
std::vector<int> Errors;
std::string Log;
};
-#define BOUNDS_CHECKER_MARKER \
-"******######*****Begin BOUNDS CHECKER XML******######******"
-//----------------------------------------------------------------------
-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",
- 0
-};
-
-
-//----------------------------------------------------------------------
-static const char* cmCTestMemCheckResultLongStrings[] = {
- "Threading Problem",
- "ABW",
- "ABWL",
- "COR",
- "EXU",
- "FFM",
- "FIM",
- "Mismatched deallocation",
- "FMR",
- "FMW",
- "FUM",
- "IPR",
- "IPW",
- "MAF",
- "Memory Leak",
- "Potential Memory Leak",
- "NPR",
- "ODS",
- "Invalid syscall param",
- "PLK",
- "Uninitialized Memory Conditional",
- "Uninitialized Memory Read",
- 0
-};
-
+#define BOUNDS_CHECKER_MARKER \
+ "******######*****Begin BOUNDS CHECKER XML******######******"
-//----------------------------------------------------------------------
cmCTestMemCheckHandler::cmCTestMemCheckHandler()
{
this->MemCheck = true;
this->CustomMaximumPassedTestOutputSize = 0;
this->CustomMaximumFailedTestOutputSize = 0;
+ this->LogWithPID = false;
}
-//----------------------------------------------------------------------
void cmCTestMemCheckHandler::Initialize()
{
this->Superclass::Initialize();
+ this->LogWithPID = false;
this->CustomMaximumPassedTestOutputSize = 0;
this->CustomMaximumFailedTestOutputSize = 0;
this->MemoryTester = "";
@@ -204,353 +127,452 @@ void cmCTestMemCheckHandler::Initialize()
this->MemoryTesterOptions.clear();
this->MemoryTesterStyle = UNKNOWN;
this->MemoryTesterOutputFile = "";
- int cc;
- for ( cc = 0; cc < NO_MEMORY_FAULT; cc ++ )
- {
- this->MemoryTesterGlobalResults[cc] = 0;
- }
-
+ this->DefectCount = 0;
}
-//----------------------------------------------------------------------
int cmCTestMemCheckHandler::PreProcessHandler()
{
- if ( !this->InitializeMemoryChecking() )
- {
+ if (!this->InitializeMemoryChecking()) {
return 0;
- }
+ }
- if ( !this->ExecuteCommands(this->CustomPreMemCheck) )
- {
+ if (!this->ExecuteCommands(this->CustomPreMemCheck)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem executing pre-memcheck command(s)." << std::endl);
+ "Problem executing pre-memcheck command(s)." << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCTestMemCheckHandler::PostProcessHandler()
{
- if ( !this->ExecuteCommands(this->CustomPostMemCheck) )
- {
+ if (!this->ExecuteCommands(this->CustomPostMemCheck)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem executing post-memcheck command(s)." << std::endl);
+ "Problem executing post-memcheck command(s)." << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
void cmCTestMemCheckHandler::GenerateTestCommand(
std::vector<std::string>& args, int test)
{
- std::vector<cmStdString>::size_type pp;
- cmStdString index;
- cmOStringStream stream;
- std::string memcheckcommand
- = cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
+ std::vector<std::string>::size_type pp;
+ std::string index;
+ std::ostringstream stream;
+ std::string memcheckcommand =
+ cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
stream << test;
index = stream.str();
- for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ )
- {
- cmStdString arg = this->MemoryTesterDynamicOptions[pp];
- cmStdString::size_type pos = arg.find("??");
- if (pos != cmStdString::npos)
- {
+ for (pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp++) {
+ std::string arg = this->MemoryTesterDynamicOptions[pp];
+ std::string::size_type pos = arg.find("??");
+ if (pos != std::string::npos) {
arg.replace(pos, 2, index);
- }
+ }
args.push_back(arg);
memcheckcommand += " \"";
memcheckcommand += arg;
memcheckcommand += "\"";
+ }
+ // Create a copy of the memory tester environment variable.
+ // This is used for memory testing programs that pass options
+ // via environment varaibles.
+ std::string memTesterEnvironmentVariable =
+ this->MemoryTesterEnvironmentVariable;
+ for (pp = 0; pp < this->MemoryTesterOptions.size(); pp++) {
+ 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];
}
- for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ )
- {
- args.push_back(this->MemoryTesterOptions[pp]);
- memcheckcommand += " \"";
- memcheckcommand += this->MemoryTesterOptions[pp];
- memcheckcommand += "\"";
+ // for regular options just add them to args and memcheckcommand
+ // which is just used for display
+ else {
+ args.push_back(this->MemoryTesterOptions[pp]);
+ memcheckcommand += " \"";
+ memcheckcommand += this->MemoryTesterOptions[pp];
+ memcheckcommand += "\"";
+ }
+ }
+ // if this is an env option type, then add the env string as a single
+ // argument.
+ if (!memTesterEnvironmentVariable.empty()) {
+ std::string::size_type pos = memTesterEnvironmentVariable.find("??");
+ if (pos != std::string::npos) {
+ memTesterEnvironmentVariable.replace(pos, 2, index);
}
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: "
- << memcheckcommand << std::endl);
+ memcheckcommand += " " + memTesterEnvironmentVariable;
+ args.push_back(memTesterEnvironmentVariable);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Memory check command: " << memcheckcommand << std::endl,
+ this->Quiet);
+}
+
+void cmCTestMemCheckHandler::InitializeResultsVectors()
+{
+ // fill these members
+ // cmsys::vector<std::string> ResultStrings;
+ // cmsys::vector<std::string> ResultStringsLong;
+ // cmsys::vector<int> GlobalResults;
+ this->ResultStringsLong.clear();
+ this->ResultStrings.clear();
+ this->GlobalResults.clear();
+ // If we are working with style checkers that dynamically fill
+ // the results strings then return.
+ if (this->MemoryTesterStyle > cmCTestMemCheckHandler::BOUNDS_CHECKER) {
+ return;
+ }
+
+ // 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
+ };
+ static const char* cmCTestMemCheckResultLongStrings[] = {
+ "Threading Problem",
+ "ABW",
+ "ABWL",
+ "COR",
+ "EXU",
+ "FFM",
+ "FIM",
+ "Mismatched deallocation",
+ "FMR",
+ "FMW",
+ "FUM",
+ "IPR",
+ "IPW",
+ "MAF",
+ "Memory Leak",
+ "Potential Memory Leak",
+ "NPR",
+ "ODS",
+ "Invalid syscall param",
+ "PLK",
+ "Uninitialized Memory Conditional",
+ "Uninitialized Memory Read",
+ CM_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]);
+ this->GlobalResults.push_back(0);
+ }
}
-//----------------------------------------------------------------------
-void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
+void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile* mf)
{
this->cmCTestTestHandler::PopulateCustomVectors(mf);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
- this->CustomPreMemCheck);
+ this->CustomPreMemCheck);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
- this->CustomPostMemCheck);
+ this->CustomPostMemCheck);
- this->CTest->PopulateCustomVector(mf,
- "CTEST_CUSTOM_MEMCHECK_IGNORE",
- this->CustomTestsIgnore);
+ this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_MEMCHECK_IGNORE",
+ this->CustomTestsIgnore);
+ std::string cmake = cmSystemTools::GetCMakeCommand();
+ this->CTest->SetCTestConfiguration("CMakeCommand", cmake.c_str(),
+ this->Quiet);
}
-//----------------------------------------------------------------------
-void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
+int cmCTestMemCheckHandler::GetDefectCount()
{
- if ( !this->CTest->GetProduceXML() )
- {
- return;
- }
+ return this->DefectCount;
+}
- this->CTest->StartXML(os, this->AppendXML);
- os << "<DynamicAnalysis Checker=\"";
- switch ( this->MemoryTesterStyle )
- {
+void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
+{
+ if (!this->CTest->GetProduceXML()) {
+ return;
+ }
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("DynamicAnalysis");
+ switch (this->MemoryTesterStyle) {
case cmCTestMemCheckHandler::VALGRIND:
- os << "Valgrind";
+ xml.Attribute("Checker", "Valgrind");
break;
case cmCTestMemCheckHandler::PURIFY:
- os << "Purify";
+ xml.Attribute("Checker", "Purify");
break;
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
- os << "BoundsChecker";
+ xml.Attribute("Checker", "BoundsChecker");
+ break;
+ case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
+ xml.Attribute("Checker", "AddressSanitizer");
+ break;
+ case cmCTestMemCheckHandler::LEAK_SANITIZER:
+ xml.Attribute("Checker", "LeakSanitizer");
+ break;
+ case cmCTestMemCheckHandler::THREAD_SANITIZER:
+ xml.Attribute("Checker", "ThreadSanitizer");
+ break;
+ case cmCTestMemCheckHandler::MEMORY_SANITIZER:
+ xml.Attribute("Checker", "MemorySanitizer");
+ break;
+ case cmCTestMemCheckHandler::UB_SANITIZER:
+ xml.Attribute("Checker", "UndefinedBehaviorSanitizer");
break;
default:
- os << "Unknown";
- }
- os << "\">" << std::endl;
+ xml.Attribute("Checker", "Unknown");
+ }
- os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
- << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
- << "\t<TestList>\n";
+ xml.Element("StartDateTime", this->StartTest);
+ 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];
+ for (cc = 0; cc < this->TestResults.size(); cc++) {
+ cmCTestTestResult* result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name;
- os << "\t\t<Test>" << cmXMLSafe(
- this->CTest->GetShortPathToFile(testPath.c_str()))
- << "</Test>" << std::endl;
- }
- os << "\t</TestList>\n";
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- "-- Processing memory checking output: ");
+ xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
+ }
+ xml.EndElement(); // TestList
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "-- Processing memory checking output:\n", this->Quiet);
size_t total = this->TestResults.size();
- size_t step = total / 10;
- size_t current = 0;
- for ( cc = 0; cc < this->TestResults.size(); cc ++ )
- {
- cmCTestTestResult *result = &this->TestResults[cc];
+ for (cc = 0; cc < this->TestResults.size(); cc++) {
+ cmCTestTestResult* result = &this->TestResults[cc];
std::string memcheckstr;
- int memcheckresults[cmCTestMemCheckHandler::NO_MEMORY_FAULT];
- int kk;
+ std::vector<int> memcheckresults(this->ResultStrings.size(), 0);
bool res = this->ProcessMemCheckOutput(result->Output, memcheckstr,
- memcheckresults);
- if ( res && result->Status == cmCTestMemCheckHandler::COMPLETED )
- {
+ memcheckresults);
+ if (res && result->Status == cmCTestMemCheckHandler::COMPLETED) {
continue;
- }
- this->CleanTestOutput(memcheckstr,
+ }
+ this->CleanTestOutput(
+ memcheckstr,
static_cast<size_t>(this->CustomMaximumFailedTestOutputSize));
- this->WriteTestResultHeader(os, result);
- os << "\t\t<Results>" << std::endl;
- for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ )
- {
- if ( memcheckresults[kk] )
- {
- os << "\t\t\t<Defect type=\"" << cmCTestMemCheckResultLongStrings[kk]
- << "\">"
- << memcheckresults[kk]
- << "</Defect>" << std::endl;
- }
- this->MemoryTesterGlobalResults[kk] += memcheckresults[kk];
+ this->WriteTestResultHeader(xml, result);
+ xml.StartElement("Results");
+ int memoryErrors = 0;
+ for (std::vector<int>::size_type kk = 0; kk < memcheckresults.size();
+ ++kk) {
+ if (memcheckresults[kk]) {
+ xml.StartElement("Defect");
+ xml.Attribute("type", this->ResultStringsLong[kk]);
+ xml.Content(memcheckresults[kk]);
+ memoryErrors += memcheckresults[kk];
+ xml.EndElement(); // Defect
}
-
- std::string logTag;
- if(this->CTest->ShouldCompressMemCheckOutput())
- {
+ this->GlobalResults[kk] += memcheckresults[kk];
+ }
+ xml.EndElement(); // Results
+ if (memoryErrors > 0) {
+ const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
+ 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,
+ this->Quiet);
+ }
+ xml.StartElement("Log");
+ if (this->CTest->ShouldCompressTestOutput()) {
this->CTest->CompressString(memcheckstr);
- logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n";
- }
- else
- {
- logTag = "\t<Log>\n";
- }
-
- os
- << "\t\t</Results>\n"
- << logTag << cmXMLSafe(memcheckstr) << std::endl
- << "\t</Log>\n";
- this->WriteTestResultFooter(os, result);
- if ( current < cc )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush);
- current += step;
- }
+ xml.Attribute("compression", "gzip");
+ xml.Attribute("encoding", "base64");
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
- << std::endl);
- os << "\t<DefectList>" << std::endl;
- for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
- {
- if ( this->MemoryTesterGlobalResults[cc] )
- {
-#ifdef cerr
-# undef cerr
-#endif
+ xml.Content(memcheckstr);
+ xml.EndElement(); // Log
+
+ this->WriteTestResultFooter(xml, result);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "MemCheck log files can be found here: "
+ "( * corresponds to test number)"
+ << std::endl,
+ this->Quiet);
+ std::string output = this->MemoryTesterOutputFile;
+ cmSystemTools::ReplaceString(output, "??", "*");
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, output << std::endl,
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Memory checking results:" << std::endl, this->Quiet);
+ xml.StartElement("DefectList");
+ for (cc = 0; cc < this->GlobalResults.size(); cc++) {
+ if (this->GlobalResults[cc]) {
std::cerr.width(35);
-#define cerr no_cerr
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- cmCTestMemCheckResultLongStrings[cc] << " - "
- << this->MemoryTesterGlobalResults[cc] << std::endl);
- os << "\t\t<Defect Type=\"" << cmCTestMemCheckResultLongStrings[cc]
- << "\"/>" << std::endl;
- }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ this->ResultStringsLong[cc]
+ << " - " << this->GlobalResults[cc] << std::endl,
+ this->Quiet);
+ xml.StartElement("Defect");
+ xml.Attribute("Type", this->ResultStringsLong[cc]);
+ xml.EndElement();
}
- os << "\t</DefectList>" << std::endl;
-
- os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl;
- os << "\t<EndTestTime>" << this->EndTestTime
- << "</EndTestTime>" << std::endl;
- os << "<ElapsedMinutes>"
- << static_cast<int>(this->ElapsedTestingTime/6)/10.0
- << "</ElapsedMinutes>\n";
-
- os << "</DynamicAnalysis>" << std::endl;
- this->CTest->EndXML(os);
+ }
+ xml.EndElement(); // DefectList
+ xml.Element("EndDateTime", this->EndTest);
+ xml.Element("EndTestTime", this->EndTestTime);
+ xml.Element("ElapsedMinutes",
+ static_cast<int>(this->ElapsedTestingTime / 6) / 10.0);
+ xml.EndElement(); // DynamicAnalysis
+ this->CTest->EndXML(xml);
}
-//----------------------------------------------------------------------
bool cmCTestMemCheckHandler::InitializeMemoryChecking()
{
+ this->MemoryTesterEnvironmentVariable = "";
+ this->MemoryTester = "";
// Setup the command
- if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
- "MemoryCheckCommand").c_str()) )
- {
- this->MemoryTester
- = this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str();
-
+ if (cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str())) {
+ this->MemoryTester =
+ this->CTest->GetCTestConfiguration("MemoryCheckCommand");
+ std::string testerName =
+ cmSystemTools::GetFilenameName(this->MemoryTester);
// determine the checker type
- if ( this->MemoryTester.find("valgrind") != std::string::npos )
- {
- this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
- }
- else if ( this->MemoryTester.find("purify") != std::string::npos )
- {
+ if (testerName.find("valgrind") != std::string::npos ||
+ this->CTest->GetCTestConfiguration("MemoryCheckType") == "Valgrind") {
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
+ } else if (testerName.find("purify") != std::string::npos) {
this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
- }
- else if ( this->MemoryTester.find("BC") != std::string::npos )
- {
+ } else if (testerName.find("BC") != std::string::npos) {
this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
- }
- else
- {
+ } else {
this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN;
- }
}
- else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
- "PurifyCommand").c_str()) )
- {
- this->MemoryTester
- = this->CTest->GetCTestConfiguration("PurifyCommand").c_str();
+ } else if (cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("PurifyCommand").c_str())) {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("PurifyCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
- }
- else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
- "ValgrindCommand").c_str()) )
- {
- this->MemoryTester
- = this->CTest->GetCTestConfiguration("ValgrindCommand").c_str();
+ } else if (cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("ValgrindCommand")
+ .c_str())) {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("ValgrindCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
- }
- else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
- "BoundsCheckerCommand").c_str()) )
- {
- this->MemoryTester
- = this->CTest->GetCTestConfiguration("BoundsCheckerCommand").c_str();
+ } else if (cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("BoundsCheckerCommand")
+ .c_str())) {
+ this->MemoryTester =
+ this->CTest->GetCTestConfiguration("BoundsCheckerCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
+ }
+ if (this->CTest->GetCTestConfiguration("MemoryCheckType") ==
+ "AddressSanitizer") {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand");
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::ADDRESS_SANITIZER;
+ this->LogWithPID = true; // even if we give the log file the pid is added
+ }
+ if (this->CTest->GetCTestConfiguration("MemoryCheckType") ==
+ "LeakSanitizer") {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand");
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::LEAK_SANITIZER;
+ this->LogWithPID = true; // even if we give the log file the pid is added
+ }
+ if (this->CTest->GetCTestConfiguration("MemoryCheckType") ==
+ "ThreadSanitizer") {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand");
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER;
+ this->LogWithPID = true; // even if we give the log file the pid is added
+ }
+ if (this->CTest->GetCTestConfiguration("MemoryCheckType") ==
+ "MemorySanitizer") {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand");
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::MEMORY_SANITIZER;
+ this->LogWithPID = true; // even if we give the log file the pid is added
+ }
+ if (this->CTest->GetCTestConfiguration("MemoryCheckType") ==
+ "UndefinedBehaviorSanitizer") {
+ this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand");
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::UB_SANITIZER;
+ this->LogWithPID = true; // even if we give the log file the pid is added
+ }
+ // Check the MemoryCheckType
+ if (this->MemoryTesterStyle == cmCTestMemCheckHandler::UNKNOWN) {
+ std::string checkType =
+ this->CTest->GetCTestConfiguration("MemoryCheckType");
+ if (checkType == "Purify") {
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
+ } else if (checkType == "BoundsChecker") {
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
+ } else if (checkType == "Valgrind") {
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
}
- else
- {
- cmCTestLog(this->CTest, WARNING,
- "Memory checker (MemoryCheckCommand) "
- "not set, or cannot find the specified program."
- << std::endl);
+ }
+ if (this->MemoryTester.empty()) {
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "Memory checker (MemoryCheckCommand) "
+ "not set, or cannot find the specified program."
+ << std::endl,
+ this->Quiet);
return false;
- }
+ }
// Setup the options
std::string memoryTesterOptions;
- if ( this->CTest->GetCTestConfiguration(
- "MemoryCheckCommandOptions").size() )
- {
- memoryTesterOptions = this->CTest->GetCTestConfiguration(
- "MemoryCheckCommandOptions");
- }
- else if ( this->CTest->GetCTestConfiguration(
- "ValgrindCommandOptions").size() )
- {
- memoryTesterOptions = this->CTest->GetCTestConfiguration(
- "ValgrindCommandOptions");
- }
- this->MemoryTesterOptions
- = cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
-
- this->MemoryTesterOutputFile
- = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/MemoryChecker.??.log";
-
- switch ( this->MemoryTesterStyle )
- {
- case cmCTestMemCheckHandler::VALGRIND:
- {
- if ( this->MemoryTesterOptions.empty() )
- {
+ if (!this->CTest->GetCTestConfiguration("MemoryCheckCommandOptions")
+ .empty()) {
+ memoryTesterOptions =
+ this->CTest->GetCTestConfiguration("MemoryCheckCommandOptions");
+ } else if (!this->CTest->GetCTestConfiguration("ValgrindCommandOptions")
+ .empty()) {
+ memoryTesterOptions =
+ this->CTest->GetCTestConfiguration("ValgrindCommandOptions");
+ }
+ this->MemoryTesterOptions =
+ cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
+
+ this->MemoryTesterOutputFile =
+ this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.??.log";
+
+ 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");
- }
- if ( this->CTest->GetCTestConfiguration(
- "MemoryCheckSuppressionFile").size() )
- {
- if ( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
- "MemoryCheckSuppressionFile").c_str()) )
- {
+ }
+ if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
+ .empty()) {
+ if (!cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
+ .c_str())) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find memory checker suppression file: "
- << this->CTest->GetCTestConfiguration(
- "MemoryCheckSuppressionFile").c_str() << std::endl);
+ "Cannot find memory checker suppression file: "
+ << this->CTest->GetCTestConfiguration(
+ "MemoryCheckSuppressionFile")
+ << std::endl);
return false;
- }
- std::string suppressions = "--suppressions="
- + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
- this->MemoryTesterOptions.push_back(suppressions);
}
- std::string outputFile = "--log-file="
- + this->MemoryTesterOutputFile;
+ std::string suppressions = "--suppressions=" +
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
+ this->MemoryTesterOptions.push_back(suppressions);
+ }
+ std::string outputFile = "--log-file=" + this->MemoryTesterOutputFile;
this->MemoryTesterDynamicOptions.push_back(outputFile);
break;
- }
- case cmCTestMemCheckHandler::PURIFY:
- {
+ }
+ case cmCTestMemCheckHandler::PURIFY: {
std::string outputFile;
#ifdef _WIN32
- if( this->CTest->GetCTestConfiguration(
- "MemoryCheckSuppressionFile").size() )
- {
- if( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
- "MemoryCheckSuppressionFile").c_str()) )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find memory checker suppression file: "
- << this->CTest->GetCTestConfiguration(
- "MemoryCheckSuppressionFile").c_str() << std::endl);
+ if (this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
+ .size()) {
+ if (!cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
+ .c_str())) {
+ cmCTestLog(
+ this->CTest, ERROR_MESSAGE,
+ "Cannot find memory checker suppression file: "
+ << this->CTest
+ ->GetCTestConfiguration("MemoryCheckSuppressionFile")
+ .c_str()
+ << std::endl);
return false;
- }
- std::string filterFiles = "/FilterFiles="
- + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
- this->MemoryTesterOptions.push_back(filterFiles);
}
+ std::string filterFiles = "/FilterFiles=" +
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
+ this->MemoryTesterOptions.push_back(filterFiles);
+ }
outputFile = "/SAVETEXTDATA=";
#else
outputFile = "-log-file=";
@@ -558,12 +580,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
outputFile += this->MemoryTesterOutputFile;
this->MemoryTesterDynamicOptions.push_back(outputFile);
break;
- }
- case cmCTestMemCheckHandler::BOUNDS_CHECKER:
- {
+ }
+ case cmCTestMemCheckHandler::BOUNDS_CHECKER: {
this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
- std::string dpbdFile = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/MemoryChecker.??.DPbd";
+ std::string dpbdFile = this->CTest->GetBinaryDir() +
+ "/Testing/Temporary/MemoryChecker.??.DPbd";
this->BoundsCheckerDPBDFile = dpbdFile;
this->MemoryTesterDynamicOptions.push_back("/B");
this->MemoryTesterDynamicOptions.push_back(dpbdFile);
@@ -571,127 +592,223 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
this->MemoryTesterOptions.push_back("/M");
break;
+ }
+ // these are almost the same but the env var used is different
+ case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
+ case cmCTestMemCheckHandler::LEAK_SANITIZER:
+ case cmCTestMemCheckHandler::THREAD_SANITIZER:
+ case cmCTestMemCheckHandler::MEMORY_SANITIZER:
+ case cmCTestMemCheckHandler::UB_SANITIZER: {
+ // To pass arguments to ThreadSanitizer the environment variable
+ // TSAN_OPTIONS is used. This is done with the cmake -E env command.
+ // 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");
+ std::string envVar;
+ std::string extraOptions;
+ std::string suppressionsOption;
+ if (!this->CTest->GetCTestConfiguration("MemoryCheckSanitizerOptions")
+ .empty()) {
+ extraOptions = ":" +
+ this->CTest->GetCTestConfiguration("MemoryCheckSanitizerOptions");
+ }
+ if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
+ .empty()) {
+ suppressionsOption = ":suppressions=" +
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
}
+ if (this->MemoryTesterStyle ==
+ cmCTestMemCheckHandler::ADDRESS_SANITIZER) {
+ envVar = "ASAN_OPTIONS";
+ } else if (this->MemoryTesterStyle ==
+ cmCTestMemCheckHandler::LEAK_SANITIZER) {
+ envVar = "LSAN_OPTIONS";
+ } else if (this->MemoryTesterStyle ==
+ cmCTestMemCheckHandler::THREAD_SANITIZER) {
+ envVar = "TSAN_OPTIONS";
+ } else if (this->MemoryTesterStyle ==
+ cmCTestMemCheckHandler::MEMORY_SANITIZER) {
+ envVar = "MSAN_OPTIONS";
+ } else if (this->MemoryTesterStyle ==
+ cmCTestMemCheckHandler::UB_SANITIZER) {
+ envVar = "UBSAN_OPTIONS";
+ }
+ // Quote log_path with single quotes; see
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=467936
+ std::string outputFile =
+ envVar + "=log_path='" + this->MemoryTesterOutputFile + "'";
+ this->MemoryTesterEnvironmentVariable =
+ outputFile + suppressionsOption + extraOptions;
+ break;
+ }
default:
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Do not understand memory checker: " << this->MemoryTester.c_str()
- << std::endl);
+ "Do not understand memory checker: " << this->MemoryTester
+ << std::endl);
return false;
- }
+ }
- std::vector<cmStdString>::size_type cc;
- for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
- {
- this->MemoryTesterGlobalResults[cc] = 0;
- }
+ this->InitializeResultsVectors();
+ // std::vector<std::string>::size_type cc;
+ // for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
+ // {
+ // this->MemoryTesterGlobalResults[cc] = 0;
+ // }
return true;
}
-//----------------------------------------------------------------------
bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str,
- std::string& log, int* results)
+ std::string& log,
+ std::vector<int>& results)
{
- std::string::size_type cc;
- for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
- {
- results[cc] = 0;
- }
+ switch (this->MemoryTesterStyle) {
+ case cmCTestMemCheckHandler::VALGRIND:
+ return this->ProcessMemCheckValgrindOutput(str, log, results);
+ case cmCTestMemCheckHandler::PURIFY:
+ return this->ProcessMemCheckPurifyOutput(str, log, results);
+ case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
+ case cmCTestMemCheckHandler::LEAK_SANITIZER:
+ case cmCTestMemCheckHandler::THREAD_SANITIZER:
+ case cmCTestMemCheckHandler::MEMORY_SANITIZER:
+ case cmCTestMemCheckHandler::UB_SANITIZER:
+ return this->ProcessMemCheckSanitizerOutput(str, log, results);
+ case cmCTestMemCheckHandler::BOUNDS_CHECKER:
+ return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
+ default:
+ log.append("\nMemory checking style used was: ");
+ log.append("None that I know");
+ log = str;
+ return true;
+ }
+}
- if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND )
- {
- return this->ProcessMemCheckValgrindOutput(str, log, results);
- }
- else if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
- {
- return this->ProcessMemCheckPurifyOutput(str, log, results);
+std::vector<int>::size_type cmCTestMemCheckHandler::FindOrAddWarning(
+ const std::string& warning)
+{
+ for (std::vector<std::string>::size_type i = 0;
+ i < this->ResultStrings.size(); ++i) {
+ if (this->ResultStrings[i] == warning) {
+ return i;
}
- else if ( this->MemoryTesterStyle ==
- cmCTestMemCheckHandler::BOUNDS_CHECKER )
- {
- return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
+ }
+ this->GlobalResults.push_back(0); // this must stay the same size
+ this->ResultStrings.push_back(warning);
+ this->ResultStringsLong.push_back(warning);
+ return this->ResultStrings.size() - 1;
+}
+bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput(
+ const std::string& str, std::string& log, std::vector<int>& result)
+{
+ std::string regex;
+ switch (this->MemoryTesterStyle) {
+ case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
+ regex = "ERROR: AddressSanitizer: (.*) on.*";
+ break;
+ case cmCTestMemCheckHandler::LEAK_SANITIZER:
+ // use leakWarning regex
+ break;
+ case cmCTestMemCheckHandler::THREAD_SANITIZER:
+ regex = "WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)";
+ break;
+ case cmCTestMemCheckHandler::MEMORY_SANITIZER:
+ regex = "WARNING: MemorySanitizer: (.*)";
+ break;
+ case cmCTestMemCheckHandler::UB_SANITIZER:
+ regex = "runtime error: (.*)";
+ break;
+ default:
+ break;
+ }
+ cmsys::RegularExpression sanitizerWarning(regex);
+ cmsys::RegularExpression leakWarning("(Direct|Indirect) leak of .*");
+ int defects = 0;
+ std::vector<std::string> lines;
+ cmSystemTools::Split(str.c_str(), lines);
+ std::ostringstream ostr;
+ log = "";
+ for (std::vector<std::string>::iterator i = lines.begin(); i != lines.end();
+ ++i) {
+ std::string resultFound;
+ if (leakWarning.find(*i)) {
+ resultFound = leakWarning.match(1) + " leak";
+ } else if (sanitizerWarning.find(*i)) {
+ resultFound = sanitizerWarning.match(1);
}
- else
- {
- log.append("\nMemory checking style used was: ");
- log.append("None that I know");
- log = str;
+ if (!resultFound.empty()) {
+ std::vector<int>::size_type idx = this->FindOrAddWarning(resultFound);
+ if (result.empty() || idx > result.size() - 1) {
+ result.push_back(1);
+ } else {
+ result[idx]++;
+ }
+ defects++;
+ ostr << "<b>" << this->ResultStrings[idx] << "</b> ";
}
-
-
- return true;
+ ostr << *i << std::endl;
+ }
+ log = ostr.str();
+ this->DefectCount += defects;
+ return defects == 0;
}
-
-//----------------------------------------------------------------------
bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
- const std::string& str, std::string& log,
- int* results)
+ const std::string& str, std::string& log, std::vector<int>& results)
{
- std::vector<cmStdString> lines;
+ std::vector<std::string> lines;
cmSystemTools::Split(str.c_str(), lines);
- cmOStringStream ostr;
+ std::ostringstream ostr;
log = "";
cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
int defects = 0;
- for( std::vector<cmStdString>::iterator i = lines.begin();
- i != lines.end(); ++i)
- {
- int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
- if ( pfW.find(*i) )
- {
- int cc;
- for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
- {
- if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] )
- {
+ for (std::vector<std::string>::iterator i = lines.begin(); i != lines.end();
+ ++i) {
+ std::vector<int>::size_type failure = this->ResultStrings.size();
+ if (pfW.find(*i)) {
+ std::vector<int>::size_type cc;
+ for (cc = 0; cc < this->ResultStrings.size(); cc++) {
+ if (pfW.match(1) == this->ResultStrings[cc]) {
failure = cc;
break;
- }
}
- if ( cc == cmCTestMemCheckHandler::NO_MEMORY_FAULT )
- {
+ }
+ if (cc == this->ResultStrings.size()) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
- << pfW.match(1) << std::endl);
+ << pfW.match(1) << std::endl);
ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
- << std::endl;
- }
- }
- if ( failure != NO_MEMORY_FAULT )
- {
- ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
- results[failure] ++;
- defects ++;
+ << std::endl;
}
- ostr << cmXMLSafe(*i) << std::endl;
}
+ if (failure != this->ResultStrings.size()) {
+ ostr << "<b>" << this->ResultStrings[failure] << "</b> ";
+ results[failure]++;
+ defects++;
+ }
+ ostr << *i << std::endl;
+ }
log = ostr.str();
- if ( defects )
- {
- return false;
- }
- return true;
+ this->DefectCount += defects;
+ return defects == 0;
}
-//----------------------------------------------------------------------
bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
- const std::string& str, std::string& log,
- int* results)
+ const std::string& str, std::string& log, std::vector<int>& results)
{
- std::vector<cmStdString> lines;
+ std::vector<std::string> lines;
cmSystemTools::Split(str.c_str(), lines);
bool unlimitedOutput = false;
- if(str.find("CTEST_FULL_OUTPUT") != str.npos ||
- this->CustomMaximumFailedTestOutputSize == 0)
- {
+ if (str.find("CTEST_FULL_OUTPUT") != std::string::npos ||
+ this->CustomMaximumFailedTestOutputSize == 0) {
unlimitedOutput = true;
- }
+ }
std::string::size_type cc;
- cmOStringStream ostr;
+ std::ostringstream ostr;
log = "";
int defects = 0;
@@ -704,7 +821,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
"== .*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,]+");
+ " in loss record [0-9,]+ of [0-9,]+");
cmsys::RegularExpression vgMLK2(
"== .*[0-9,]+ \\([0-9,]+ direct, [0-9,]+ indirect\\)"
" bytes in [0-9,]+ blocks are definitely lost"
@@ -723,300 +840,261 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
"== .*Use of uninitialised value of size [0-9,]+");
cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9,]+");
cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address ");
- cmsys::RegularExpression vgUMR4("== .*Syscall param .* contains "
+ cmsys::RegularExpression vgUMR4(
+ "== .*Syscall param .* contains "
"uninitialised or unaddressable byte\\(s\\)");
cmsys::RegularExpression vgUMR5("== .*Syscall param .* uninitialised");
cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9,]+");
cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is "
- "locked by a different thread");
+ "locked by a different thread");
std::vector<std::string::size_type> nonValGrindOutput;
double sttime = cmSystemTools::GetTime();
- cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Start test: " << lines.size() << std::endl, this->Quiet);
std::string::size_type totalOutputSize = 0;
- bool outputFull = false;
- for ( cc = 0; cc < lines.size(); cc ++ )
- {
- cmCTestLog(this->CTest, DEBUG, "test line "
- << lines[cc] << std::endl);
-
- if ( valgrindLine.find(lines[cc]) )
- {
- cmCTestLog(this->CTest, DEBUG, "valgrind line "
- << lines[cc] << std::endl);
+ for (cc = 0; cc < lines.size(); cc++) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "test line " << lines[cc] << std::endl, this->Quiet);
+
+ if (valgrindLine.find(lines[cc])) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "valgrind line " << lines[cc] << std::endl,
+ this->Quiet);
int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
- if ( vgFIM.find(lines[cc]) )
- {
+ if (vgFIM.find(lines[cc])) {
failure = cmCTestMemCheckHandler::FIM;
- }
- else if ( vgFMM.find(lines[cc]) )
- {
+ } else if (vgFMM.find(lines[cc])) {
failure = cmCTestMemCheckHandler::FMM;
- }
- else if ( vgMLK1.find(lines[cc]) )
- {
+ } else if (vgMLK1.find(lines[cc])) {
failure = cmCTestMemCheckHandler::MLK;
- }
- else if ( vgMLK2.find(lines[cc]) )
- {
+ } else if (vgMLK2.find(lines[cc])) {
failure = cmCTestMemCheckHandler::MLK;
- }
- else if ( vgPAR.find(lines[cc]) )
- {
+ } else if (vgPAR.find(lines[cc])) {
failure = cmCTestMemCheckHandler::PAR;
- }
- else if ( vgMPK1.find(lines[cc]) )
- {
+ } else if (vgMPK1.find(lines[cc])) {
failure = cmCTestMemCheckHandler::MPK;
- }
- else if ( vgMPK2.find(lines[cc]) )
- {
+ } else if (vgMPK2.find(lines[cc])) {
failure = cmCTestMemCheckHandler::MPK;
- }
- else if ( vgUMC.find(lines[cc]) )
- {
+ } else if (vgUMC.find(lines[cc])) {
failure = cmCTestMemCheckHandler::UMC;
- }
- else if ( vgUMR1.find(lines[cc]) )
- {
+ } else if (vgUMR1.find(lines[cc])) {
failure = cmCTestMemCheckHandler::UMR;
- }
- else if ( vgUMR2.find(lines[cc]) )
- {
+ } else if (vgUMR2.find(lines[cc])) {
failure = cmCTestMemCheckHandler::UMR;
- }
- else if ( vgUMR3.find(lines[cc]) )
- {
+ } else if (vgUMR3.find(lines[cc])) {
failure = cmCTestMemCheckHandler::UMR;
- }
- else if ( vgUMR4.find(lines[cc]) )
- {
+ } else if (vgUMR4.find(lines[cc])) {
failure = cmCTestMemCheckHandler::UMR;
- }
- else if ( vgUMR5.find(lines[cc]) )
- {
+ } else if (vgUMR5.find(lines[cc])) {
failure = cmCTestMemCheckHandler::UMR;
- }
- else if ( vgIPW.find(lines[cc]) )
- {
+ } else if (vgIPW.find(lines[cc])) {
failure = cmCTestMemCheckHandler::IPW;
- }
- else if ( vgABR.find(lines[cc]) )
- {
+ } else if (vgABR.find(lines[cc])) {
failure = cmCTestMemCheckHandler::ABR;
- }
+ }
- if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT )
- {
- ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
- results[failure] ++;
- defects ++;
- }
- totalOutputSize += lines[cc].size();
- ostr << cmXMLSafe(lines[cc]) << std::endl;
+ if (failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT) {
+ ostr << "<b>" << this->ResultStrings[failure] << "</b> ";
+ results[failure]++;
+ defects++;
}
- else
- {
+ totalOutputSize += lines[cc].size();
+ ostr << lines[cc] << std::endl;
+ } else {
nonValGrindOutput.push_back(cc);
- }
}
+ }
// Now put all all the non valgrind output into the test output
- if(!outputFull)
- {
- for(std::vector<std::string::size_type>::iterator i =
- nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i)
- {
- totalOutputSize += lines[*i].size();
- cmCTestLog(this->CTest, DEBUG, "before xml safe "
- << lines[*i] << std::endl);
- cmCTestLog(this->CTest, DEBUG, "after xml safe "
- << cmXMLSafe(lines[*i]) << std::endl);
-
- ostr << cmXMLSafe(lines[*i]) << std::endl;
- if(!unlimitedOutput && totalOutputSize >
- static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
- {
- outputFull = true;
- ostr << "....\n";
- ostr << "Test Output for this test has been truncated see testing"
- " machine logs for full output,\n";
- ostr << "or put CTEST_FULL_OUTPUT in the output of "
- "this test program.\n";
- }
- }
+ // 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;
+ if (!unlimitedOutput &&
+ totalOutputSize >
+ static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) {
+ ostr << "....\n";
+ ostr << "Test Output for this test has been truncated see testing"
+ " machine logs for full output,\n";
+ ostr << "or put CTEST_FULL_OUTPUT in the output of "
+ "this test program.\n";
+ break; // stop the copy of output if we are full
}
- cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
- << (cmSystemTools::GetTime() - sttime) << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
+ << (cmSystemTools::GetTime() - sttime) << std::endl,
+ this->Quiet);
log = ostr.str();
- if ( defects )
- {
- return false;
- }
- return true;
+ this->DefectCount += defects;
+ return defects == 0;
}
-
-
-//----------------------------------------------------------------------
bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
- const std::string& str, std::string& log,
- int* results)
+ const std::string& str, std::string& log, std::vector<int>& results)
{
log = "";
double sttime = cmSystemTools::GetTime();
- std::vector<cmStdString> lines;
+ std::vector<std::string> lines;
cmSystemTools::Split(str.c_str(), lines);
- cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
- std::vector<cmStdString>::size_type cc;
- for ( cc = 0; cc < lines.size(); cc ++ )
- {
- if(lines[cc] == BOUNDS_CHECKER_MARKER)
- {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Start test: " << lines.size() << std::endl, this->Quiet);
+ std::vector<std::string>::size_type cc;
+ for (cc = 0; cc < lines.size(); cc++) {
+ if (lines[cc] == BOUNDS_CHECKER_MARKER) {
break;
- }
}
+ }
cmBoundsCheckerParser parser(this->CTest);
parser.InitializeParser();
- if(cc < lines.size())
- {
- for(cc++; cc < lines.size(); ++cc)
- {
+ if (cc < lines.size()) {
+ for (cc++; cc < lines.size(); ++cc) {
std::string& theLine = lines[cc];
// check for command line arguments that are not escaped
// correctly by BC
- if(theLine.find("TargetArgs=") != theLine.npos)
- {
+ if (theLine.find("TargetArgs=") != std::string::npos) {
// skip this because BC gets it wrong and we can't parse it
- }
- else if(!parser.ParseChunk(theLine.c_str(), theLine.size()))
- {
+ } else if (!parser.ParseChunk(theLine.c_str(), theLine.size())) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error in ParseChunk: " << theLine.c_str()
- << std::endl);
- }
+ "Error in ParseChunk: " << theLine << std::endl);
}
}
+ }
int defects = 0;
- for(cc =0; cc < parser.Errors.size(); ++cc)
- {
+ for (cc = 0; cc < parser.Errors.size(); ++cc) {
results[parser.Errors[cc]]++;
defects++;
- }
- cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
- << (cmSystemTools::GetTime() - sttime) << std::endl);
- if(defects)
- {
+ }
+ cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
+ << (cmSystemTools::GetTime() - sttime) << std::endl,
+ this->Quiet);
+ if (defects) {
// only put the output of Bounds Checker if there were
// errors or leaks detected
log = parser.Log;
- return false;
+ }
+ this->DefectCount += defects;
+ return defects == 0;
+}
+
+// PostProcessTest memcheck results
+void cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, int test)
+{
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "PostProcessTest memcheck results for : " << res.Name
+ << std::endl,
+ this->Quiet);
+ if (this->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER) {
+ this->PostProcessBoundsCheckerTest(res, 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);
}
- return true;
+ }
}
// This method puts the bounds checker output file into the output
// for the test
-void
-cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res,
- int test)
+void cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(
+ cmCTestTestResult& res, int test)
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "PostProcessBoundsCheckerTest for : "
- << res.Name.c_str() << std::endl);
- cmStdString ofile = testOutputFileName(test);
- if ( ofile.empty() )
- {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "PostProcessBoundsCheckerTest for : " << res.Name
+ << std::endl,
+ this->Quiet);
+ std::vector<std::string> files;
+ this->TestOutputFileNames(test, files);
+ if (files.empty()) {
return;
- }
+ }
+ std::string ofile = files[0];
+ if (ofile.empty()) {
+ return;
+ }
// put a scope around this to close ifs so the file can be removed
{
- std::ifstream ifs(ofile.c_str());
- if ( !ifs )
- {
- std::string log = "Cannot read memory tester output file: " + ofile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
- return;
+ cmsys::ifstream ifs(ofile.c_str());
+ if (!ifs) {
+ std::string log = "Cannot read memory tester output file: " + ofile;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
+ return;
}
- res.Output += BOUNDS_CHECKER_MARKER;
- res.Output += "\n";
- std::string line;
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
- res.Output += line;
+ res.Output += BOUNDS_CHECKER_MARKER;
res.Output += "\n";
+ std::string line;
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
+ res.Output += line;
+ res.Output += "\n";
}
}
cmSystemTools::Delay(1000);
- cmSystemTools::RemoveFile(this->BoundsCheckerDPBDFile.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
- << this->BoundsCheckerDPBDFile.c_str() << std::endl);
- cmSystemTools::RemoveFile(this->BoundsCheckerXMLFile.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
- << this->BoundsCheckerXMLFile.c_str() << std::endl);
+ cmSystemTools::RemoveFile(this->BoundsCheckerDPBDFile);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Remove: " << this->BoundsCheckerDPBDFile << std::endl,
+ this->Quiet);
+ cmSystemTools::RemoveFile(this->BoundsCheckerXMLFile);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Remove: " << this->BoundsCheckerXMLFile << std::endl,
+ this->Quiet);
}
-void
-cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res,
- int test)
+void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res,
+ std::string const& ofile)
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "PostProcessPurifyTest for : "
- << res.Name.c_str() << std::endl);
- appendMemTesterOutput(res, test);
-}
-
-void
-cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res,
- int test)
-{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "PostProcessValgrindTest for : "
- << res.Name.c_str() << std::endl);
- appendMemTesterOutput(res, test);
-}
-
-void
-cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res,
- int test)
-{
- cmStdString ofile = testOutputFileName(test);
-
- if ( ofile.empty() )
- {
- return;
- }
- std::ifstream ifs(ofile.c_str());
- if ( !ifs )
- {
- std::string log = "Cannot read memory tester output file: " + ofile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
+ if (ofile.empty()) {
return;
+ }
+ // put ifs in scope so file can be deleted if needed
+ {
+ cmsys::ifstream ifs(ofile.c_str());
+ if (!ifs) {
+ std::string log = "Cannot read memory tester output file: " + ofile;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
+ return;
}
- std::string line;
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
- res.Output += line;
- res.Output += "\n";
+ std::string line;
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
+ res.Output += line;
+ res.Output += "\n";
}
+ }
+ if (this->LogWithPID) {
+ cmSystemTools::RemoveFile(ofile);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Remove: " << ofile << "\n", this->Quiet);
+ }
}
-cmStdString
-cmCTestMemCheckHandler::testOutputFileName(int test)
+void cmCTestMemCheckHandler::TestOutputFileNames(
+ int test, std::vector<std::string>& files)
{
- cmStdString index;
- cmOStringStream stream;
+ std::string index;
+ std::ostringstream stream;
stream << test;
index = stream.str();
- cmStdString ofile = this->MemoryTesterOutputFile;
- cmStdString::size_type pos = ofile.find("??");
+ std::string ofile = this->MemoryTesterOutputFile;
+ std::string::size_type pos = ofile.find("??");
ofile.replace(pos, 2, index);
-
- if ( !cmSystemTools::FileExists(ofile.c_str()) )
- {
- std::string log = "Cannot find memory tester output file: "
- + ofile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
- ofile = "";
+ if (this->LogWithPID) {
+ ofile += ".*";
+ cmsys::Glob g;
+ 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 = "";
+ } else {
+ files = g.GetFiles();
+ return;
}
-
- return ofile;
+ } else if (!cmSystemTools::FileExists(ofile.c_str())) {
+ std::string log = "Cannot find memory tester output file: " + ofile;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
+ ofile = "";
+ }
+ files.push_back(ofile);
}
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 040d2e092..333c2e2dd 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -1,23 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestMemCheckHandler_h
#define cmCTestMemCheckHandler_h
+#include "cmConfigure.h"
#include "cmCTestTestHandler.h"
-#include "cmListFileCache.h"
+
+#include <string>
+#include <vector>
class cmMakefile;
+class cmXMLWriter;
/** \class cmCTestMemCheckHandler
* \brief A class that handles ctest -S invocations
@@ -26,29 +20,42 @@ class cmMakefile;
class cmCTestMemCheckHandler : public cmCTestTestHandler
{
friend class cmCTestRunTest;
+
public:
- cmTypeMacro(cmCTestMemCheckHandler, cmCTestTestHandler);
+ typedef cmCTestTestHandler Superclass;
- void PopulateCustomVectors(cmMakefile *mf);
+ void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
cmCTestMemCheckHandler();
- void Initialize();
+ void Initialize() CM_OVERRIDE;
+
+ int GetDefectCount();
+
protected:
- virtual int PreProcessHandler();
- virtual int PostProcessHandler();
- virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
+ int PreProcessHandler() CM_OVERRIDE;
+ int PostProcessHandler() CM_OVERRIDE;
+ void GenerateTestCommand(std::vector<std::string>& args,
+ int test) CM_OVERRIDE;
private:
-
- enum { // Memory checkers
+ enum
+ { // Memory checkers
UNKNOWN = 0,
VALGRIND,
PURIFY,
- BOUNDS_CHECKER
+ BOUNDS_CHECKER,
+ // checkers after here do not use the standard error list
+ ADDRESS_SANITIZER,
+ LEAK_SANITIZER,
+ THREAD_SANITIZER,
+ MEMORY_SANITIZER,
+ UB_SANITIZER
};
+
public:
- enum { // Memory faults
+ enum
+ { // Memory faults
ABR = 0,
ABW,
ABWL,
@@ -73,8 +80,10 @@ public:
UMR,
NO_MEMORY_FAULT
};
+
private:
- enum { // Program statuses
+ enum
+ { // Program statuses
NOT_RUN = 0,
TIMEOUT,
SEGFAULT,
@@ -86,14 +95,25 @@ private:
BAD_COMMAND,
COMPLETED
};
- std::string BoundsCheckerDPBDFile;
- std::string BoundsCheckerXMLFile;
- std::string MemoryTester;
- std::vector<cmStdString> MemoryTesterDynamicOptions;
- std::vector<cmStdString> MemoryTesterOptions;
- int MemoryTesterStyle;
- std::string MemoryTesterOutputFile;
- int MemoryTesterGlobalResults[NO_MEMORY_FAULT];
+ std::string BoundsCheckerDPBDFile;
+ std::string BoundsCheckerXMLFile;
+ std::string MemoryTester;
+ std::vector<std::string> MemoryTesterDynamicOptions;
+ std::vector<std::string> MemoryTesterOptions;
+ int MemoryTesterStyle;
+ std::string MemoryTesterOutputFile;
+ std::string MemoryTesterEnvironmentVariable;
+ // these are used to store the types of errors that can show up
+ std::vector<std::string> ResultStrings;
+ std::vector<std::string> ResultStringsLong;
+ std::vector<int> GlobalResults;
+ bool LogWithPID; // does log file add pid
+ int DefectCount;
+
+ std::vector<int>::size_type FindOrAddWarning(const std::string& warning);
+ // initialize the ResultStrings and ResultStringsLong for
+ // this type of checker
+ void InitializeResultsVectors();
///! Initialize memory checking subsystem.
bool InitializeMemoryChecking();
@@ -101,34 +121,35 @@ private:
/**
* Generate the Dart compatible output
*/
- void GenerateDartOutput(std::ostream& os);
+ void GenerateDartOutput(cmXMLWriter& xml) CM_OVERRIDE;
- std::vector<cmStdString> CustomPreMemCheck;
- std::vector<cmStdString> CustomPostMemCheck;
+ 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.
- bool ProcessMemCheckOutput(const std::string& str,
- std::string& log, int* results);
- bool ProcessMemCheckValgrindOutput(const std::string& str,
- std::string& log, int* results);
- bool ProcessMemCheckPurifyOutput(const std::string& str,
- std::string& log, int* results);
+ // string. After running, log holds the output and results hold the
+ // different memmory errors.
+ bool ProcessMemCheckOutput(const std::string& str, std::string& log,
+ std::vector<int>& results);
+ bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log,
+ std::vector<int>& results);
+ bool ProcessMemCheckPurifyOutput(const std::string& str, std::string& log,
+ std::vector<int>& results);
+ bool ProcessMemCheckSanitizerOutput(const std::string& str, std::string& log,
+ std::vector<int>& results);
bool ProcessMemCheckBoundsCheckerOutput(const std::string& str,
- std::string& log, int* results);
+ std::string& log,
+ std::vector<int>& results);
- void PostProcessPurifyTest(cmCTestTestResult& res, int test);
+ void PostProcessTest(cmCTestTestResult& res, int test);
void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test);
- void PostProcessValgrindTest(cmCTestTestResult& res, int test);
///! append MemoryTesterOutputFile to the test log
- void appendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res,
- int test);
+ void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res,
+ std::string const& filename);
///! generate the output filename for the given test index
- cmStdString testOutputFileName(int test);
+ void TestOutputFileNames(int test, std::vector<std::string>& files);
};
#endif
-
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 76ddeea01..2c16a0d1e 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -1,35 +1,41 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMultiProcessHandler.h"
-#include "cmProcess.h"
-#include "cmStandardIncludes.h"
+
#include "cmCTest.h"
+#include "cmCTestRunTest.h"
+#include "cmCTestScriptHandler.h"
+#include "cmCTestTestHandler.h"
#include "cmSystemTools.h"
-#include <stdlib.h>
+#include "cmWorkingDirectory.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/String.hxx"
+#include "cmsys/SystemInformation.hxx"
+#include <algorithm>
+#include <iomanip>
+#include <list>
+#include <math.h>
+#include <sstream>
#include <stack>
-#include <float.h>
+#include <stdlib.h>
+#include <utility>
class TestComparator
{
public:
- TestComparator(cmCTestMultiProcessHandler* handler) : Handler(handler) {}
+ TestComparator(cmCTestMultiProcessHandler* handler)
+ : Handler(handler)
+ {
+ }
~TestComparator() {}
// Sorts tests in descending order of cost
- bool operator() (int index1, int index2) const
- {
+ bool operator()(int index1, int index2) const
+ {
return Handler->Properties[index1]->Cost >
Handler->Properties[index2]->Cost;
- }
+ }
private:
cmCTestMultiProcessHandler* Handler;
@@ -38,136 +44,155 @@ private:
cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
{
this->ParallelLevel = 1;
+ this->TestLoad = 0;
this->Completed = 0;
this->RunningCount = 0;
this->StopTimePassed = false;
+ this->HasCycles = false;
+ this->SerialTestRunning = false;
}
cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler()
{
}
- // Set the tests
-void
-cmCTestMultiProcessHandler::SetTests(TestMap& tests,
- PropertiesMap& properties)
+// Set the tests
+void cmCTestMultiProcessHandler::SetTests(TestMap& tests,
+ PropertiesMap& properties)
{
this->Tests = 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)
- {
+ for (TestMap::iterator i = this->Tests.begin(); i != this->Tests.end();
+ ++i) {
this->TestRunningMap[i->first] = false;
this->TestFinishMap[i->first] = false;
- }
- if(!this->CTest->GetShowOnly())
- {
+ }
+ if (!this->CTest->GetShowOnly()) {
this->ReadCostData();
- this->CreateTestCostList();
+ this->HasCycles = !this->CheckCycles();
+ if (this->HasCycles) {
+ return;
}
+ this->CreateTestCostList();
+ }
}
- // Set the max number of tests that can be run at the same time.
+// Set the max number of tests that can be run at the same time.
void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
{
this->ParallelLevel = level < 1 ? 1 : level;
}
-//---------------------------------------------------------
+void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load)
+{
+ this->TestLoad = load;
+}
+
void cmCTestMultiProcessHandler::RunTests()
{
this->CheckResume();
- if(!this->CheckCycles())
- {
+ if (this->HasCycles) {
return;
- }
+ }
this->TestHandler->SetMaxIndex(this->FindMaxIndex());
this->StartNextTests();
- while(this->Tests.size() != 0)
- {
- if(this->StopTimePassed)
- {
+ while (!this->Tests.empty()) {
+ if (this->StopTimePassed) {
return;
- }
+ }
this->CheckOutput();
this->StartNextTests();
- }
+ }
// let all running tests finish
- while(this->CheckOutput())
- {
- }
+ while (this->CheckOutput()) {
+ }
this->MarkFinished();
this->UpdateCostData();
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::StartTestProcess(int test)
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "test " << test << "\n");
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "test " << test << "\n", this->Quiet);
this->TestRunningMap[test] = true; // mark the test as running
// now remove the test itself
this->EraseTest(test);
this->RunningCount += GetProcessorsUsed(test);
cmCTestRunTest* testRun = new cmCTestRunTest(this->TestHandler);
+ if (this->CTest->GetRepeatUntilFail()) {
+ testRun->SetRunUntilFailOn();
+ testRun->SetNumberOfRuns(this->CTest->GetTestRepeat());
+ }
testRun->SetIndex(test);
testRun->SetTestProperties(this->Properties[test]);
- std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(this->Properties[test]->Directory.c_str());
+ // 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);
+ }
+ }
+
+ cmWorkingDirectory workdir(this->Properties[test]->Directory);
// Lock the resources we'll be using
this->LockResources(test);
- if(testRun->StartTest(this->Total))
- {
+ if (testRun->StartTest(this->Total)) {
this->RunningTests.insert(testRun);
- }
- else if(testRun->IsStopTimePassed())
- {
+ } else if (testRun->IsStopTimePassed()) {
this->StopTimePassed = true;
delete testRun;
return;
+ } else {
+
+ for (TestMap::iterator j = this->Tests.begin(); j != this->Tests.end();
+ ++j) {
+ j->second.erase(test);
}
- else
- {
+
this->UnlockResources(test);
this->Completed++;
this->TestFinishMap[test] = true;
this->TestRunningMap[test] = false;
this->RunningCount -= GetProcessorsUsed(test);
testRun->EndTest(this->Completed, this->Total, false);
- this->Failed->push_back(this->Properties[test]->Name);
- delete testRun;
+ if (!this->Properties[test]->Disabled) {
+ this->Failed->push_back(this->Properties[test]->Name);
}
- cmSystemTools::ChangeDirectory(current_dir.c_str());
+ delete testRun;
+ }
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::LockResources(int index)
{
- for(std::set<std::string>::iterator i =
- this->Properties[index]->LockedResources.begin();
- i != this->Properties[index]->LockedResources.end(); ++i)
- {
- this->LockedResources.insert(*i);
- }
+ this->LockedResources.insert(
+ this->Properties[index]->LockedResources.begin(),
+ this->Properties[index]->LockedResources.end());
+
+ if (this->Properties[index]->RunSerial) {
+ this->SerialTestRunning = true;
+ }
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::UnlockResources(int index)
{
- for(std::set<std::string>::iterator i =
- this->Properties[index]->LockedResources.begin();
- i != this->Properties[index]->LockedResources.end(); ++i)
- {
+ for (std::set<std::string>::iterator i =
+ this->Properties[index]->LockedResources.begin();
+ i != this->Properties[index]->LockedResources.end(); ++i) {
this->LockedResources.erase(*i);
- }
+ }
+ if (this->Properties[index]->RunSerial) {
+ this->SerialTestRunning = false;
+ }
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::EraseTest(int test)
{
this->Tests.erase(test);
@@ -175,157 +200,202 @@ void cmCTestMultiProcessHandler::EraseTest(int test)
std::find(this->SortedTests.begin(), this->SortedTests.end(), test));
}
-//---------------------------------------------------------
inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test)
{
- size_t processors =
- static_cast<int>(this->Properties[test]->Processors);
- //If this is set to run serially, it must run alone.
- //Also, if processors setting is set higher than the -j
- //setting, we default to using all of the process slots.
- if(this->Properties[test]->RunSerial
- || processors > this->ParallelLevel)
- {
+ size_t processors = static_cast<int>(this->Properties[test]->Processors);
+ // If processors setting is set higher than the -j
+ // setting, we default to using all of the process slots.
+ if (processors > this->ParallelLevel) {
processors = this->ParallelLevel;
- }
+ }
return processors;
}
-//---------------------------------------------------------
+std::string cmCTestMultiProcessHandler::GetName(int test)
+{
+ return this->Properties[test]->Name;
+}
+
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())
- {
+ // 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()) {
return false;
- }
}
+ }
- // copy the depend tests locally because when
- // a test is finished it will be removed from the depend list
- // and we don't want to be iterating a list while removing from it
- TestSet depends = this->Tests[test];
- size_t totalDepends = depends.size();
- if(totalDepends)
- {
- for(TestSet::const_iterator i = depends.begin();
- i != depends.end(); ++i)
- {
- // if the test is not already running then start it
- if(!this->TestRunningMap[*i])
- {
- // this test might be finished, but since
- // this is a copy of the depend map we might
- // still have it
- if(!this->TestFinishMap[*i])
- {
- // only start one test in this function
- return this->StartTest(*i);
- }
- else
- {
- // the depend has been and finished
- totalDepends--;
- }
- }
- }
- }
// if there are no depends left then run this test
- if(totalDepends == 0)
- {
+ if (this->Tests[test].empty()) {
this->StartTestProcess(test);
return true;
- }
+ }
// This test was not able to start because it is waiting
// on depends to run
return false;
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::StartNextTests()
{
size_t numToStart = 0;
- if(this->RunningCount < this->ParallelLevel)
- {
+ if (this->RunningCount < this->ParallelLevel) {
numToStart = this->ParallelLevel - this->RunningCount;
- }
+ }
- if(numToStart == 0)
- {
+ if (numToStart == 0) {
+ return;
+ }
+
+ // Don't start any new tests if one with the RUN_SERIAL property
+ // is already running.
+ if (this->SerialTestRunning) {
return;
+ }
+
+ bool allTestsFailedTestLoadCheck = false;
+ bool usedFakeLoadForTesting = false;
+ size_t minProcessorsRequired = this->ParallelLevel;
+ std::string testWithMinProcessors;
+
+ cmsys::SystemInformation info;
+
+ unsigned long systemLoad = 0;
+ size_t spareLoad = 0;
+ if (this->TestLoad > 0) {
+ // Activate possible wait.
+ 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 it's not set, look up the true load average.
+ else {
+ systemLoad = static_cast<unsigned long>(ceil(info.GetLoadAverage()));
}
+ spareLoad =
+ (this->TestLoad > systemLoad ? this->TestLoad - systemLoad : 0);
+
+ // Don't start more tests than the spare load can support.
+ if (numToStart > spareLoad) {
+ numToStart = spareLoad;
+ }
+ }
TestList copy = this->SortedTests;
- for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
- {
- //in case this test has already been started due to dependency
- if(this->TestRunningMap[*test] || this->TestFinishMap[*test])
- {
+ for (TestList::iterator test = copy.begin(); test != copy.end(); ++test) {
+ // 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) {
continue;
- }
+ }
+
size_t processors = GetProcessorsUsed(*test);
- if(processors > numToStart)
- {
- return;
+ 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);
+ allTestsFailedTestLoadCheck = false;
+ } else {
+ testLoadOk = false;
}
- if(this->StartTest(*test))
- {
- if(this->StopTimePassed)
- {
+ }
+
+ if (processors <= minProcessorsRequired) {
+ minProcessorsRequired = processors;
+ testWithMinProcessors = GetName(*test);
+ }
+
+ if (testLoadOk && processors <= numToStart && this->StartTest(*test)) {
+ if (this->StopTimePassed) {
return;
- }
- numToStart -= processors;
}
- if(numToStart == 0)
- {
- return;
- }
- }
+
+ numToStart -= processors;
+ } else if (numToStart == 0) {
+ break;
+ }
+ }
+
+ if (allTestsFailedTestLoadCheck) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, ");
+ if (this->SerialTestRunning) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "Waiting for RUN_SERIAL test to finish.");
+ } else {
+ /* clang-format off */
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "System Load: " << systemLoad << ", "
+ "Max Allowed Load: " << this->TestLoad << ", "
+ "Smallest test " << testWithMinProcessors <<
+ " requires " << minProcessorsRequired);
+ /* clang-format on */
+ }
+ 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);
+ }
+ }
}
-//---------------------------------------------------------
bool cmCTestMultiProcessHandler::CheckOutput()
{
// no more output we are done
- if(this->RunningTests.size() == 0)
- {
+ if (this->RunningTests.empty()) {
return false;
- }
+ }
std::vector<cmCTestRunTest*> finished;
std::string out, err;
- for(std::set<cmCTestRunTest*>::const_iterator i = this->RunningTests.begin();
- i != this->RunningTests.end(); ++i)
- {
+ for (std::set<cmCTestRunTest*>::const_iterator i =
+ this->RunningTests.begin();
+ i != this->RunningTests.end(); ++i) {
cmCTestRunTest* p = *i;
- if(!p->CheckOutput())
- {
+ if (!p->CheckOutput()) {
finished.push_back(p);
- }
}
- for( std::vector<cmCTestRunTest*>::iterator i = finished.begin();
- i != finished.end(); ++i)
- {
+ }
+ for (std::vector<cmCTestRunTest*>::iterator i = finished.begin();
+ i != finished.end(); ++i) {
this->Completed++;
cmCTestRunTest* p = *i;
int test = p->GetIndex();
- if(p->EndTest(this->Completed, this->Total, true))
- {
+ 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
- {
+ } else {
this->Failed->push_back(p->GetTestProperties()->Name);
- }
- for(TestMap::iterator j = this->Tests.begin();
- j != this->Tests.end(); ++j)
- {
+ }
+ 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);
@@ -333,300 +403,385 @@ bool cmCTestMultiProcessHandler::CheckOutput()
this->UnlockResources(test);
this->RunningCount -= GetProcessorsUsed(test);
delete p;
- }
+ }
return true;
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::UpdateCostData()
{
std::string fname = this->CTest->GetCostDataFile();
std::string tmpout = fname + ".tmp";
- std::fstream fout;
- fout.open(tmpout.c_str(), std::ios::out);
+ cmsys::ofstream fout;
+ fout.open(tmpout.c_str());
PropertiesMap temp = this->Properties;
- if(cmSystemTools::FileExists(fname.c_str()))
- {
- std::ifstream fin;
+ if (cmSystemTools::FileExists(fname.c_str())) {
+ cmsys::ifstream fin;
fin.open(fname.c_str());
std::string line;
- while(std::getline(fin, line))
- {
- if(line == "---") break;
- std::vector<cmsys::String> parts =
- cmSystemTools::SplitString(line.c_str(), ' ');
- //Format: <name> <previous_runs> <avg_cost>
- if(parts.size() < 3) break;
+ while (std::getline(fin, line)) {
+ if (line == "---") {
+ break;
+ }
+ std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' ');
+ // Format: <name> <previous_runs> <avg_cost>
+ if (parts.size() < 3) {
+ break;
+ }
std::string name = parts[0];
int prev = atoi(parts[1].c_str());
float cost = static_cast<float>(atof(parts[2].c_str()));
int index = this->SearchByName(name);
- if(index == -1)
- {
+ if (index == -1) {
// This test is not in memory. We just rewrite the entry
fout << name << " " << prev << " " << cost << "\n";
- }
- else
- {
+ } else {
// Update with our new average cost
fout << name << " " << this->Properties[index]->PreviousRuns << " "
- << this->Properties[index]->Cost << "\n";
+ << this->Properties[index]->Cost << "\n";
temp.erase(index);
- }
}
- fin.close();
- cmSystemTools::RemoveFile(fname.c_str());
}
+ fin.close();
+ cmSystemTools::RemoveFile(fname);
+ }
// Add all tests not previously listed in the file
- for(PropertiesMap::iterator i = temp.begin(); i != temp.end(); ++i)
- {
+ for (PropertiesMap::iterator i = temp.begin(); i != temp.end(); ++i) {
fout << i->second->Name << " " << i->second->PreviousRuns << " "
- << i->second->Cost << "\n";
- }
+ << i->second->Cost << "\n";
+ }
// Write list of failed tests
fout << "---\n";
- for(std::vector<cmStdString>::iterator i = this->Failed->begin();
- i != this->Failed->end(); ++i)
- {
- fout << i->c_str() << "\n";
- }
+ for (std::vector<std::string>::iterator i = this->Failed->begin();
+ i != this->Failed->end(); ++i) {
+ fout << *i << "\n";
+ }
fout.close();
cmSystemTools::RenameFile(tmpout.c_str(), fname.c_str());
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::ReadCostData()
{
std::string fname = this->CTest->GetCostDataFile();
- if(cmSystemTools::FileExists(fname.c_str(), true))
- {
- std::ifstream fin;
+ if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ cmsys::ifstream fin;
fin.open(fname.c_str());
std::string line;
- while(std::getline(fin, line))
- {
- if(line == "---") break;
+ while (std::getline(fin, line)) {
+ if (line == "---") {
+ break;
+ }
- std::vector<cmsys::String> parts =
- cmSystemTools::SplitString(line.c_str(), ' ');
+ std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' ');
// Probably an older version of the file, will be fixed next run
- if(parts.size() < 3)
- {
+ if (parts.size() < 3) {
fin.close();
return;
- }
+ }
std::string name = parts[0];
int prev = atoi(parts[1].c_str());
float cost = static_cast<float>(atof(parts[2].c_str()));
int index = this->SearchByName(name);
- if(index == -1) continue;
+ if (index == -1) {
+ continue;
+ }
this->Properties[index]->PreviousRuns = prev;
// When not running in parallel mode, don't use cost data
- if(this->ParallelLevel > 1 &&
- this->Properties[index] &&
- this->Properties[index]->Cost == 0)
- {
+ if (this->ParallelLevel > 1 && this->Properties[index] &&
+ this->Properties[index]->Cost == 0) {
this->Properties[index]->Cost = cost;
- }
}
+ }
// Next part of the file is the failed tests
- while(std::getline(fin, line))
- {
- if(line != "")
- {
+ while (std::getline(fin, line)) {
+ if (line != "") {
this->LastTestsFailed.push_back(line);
- }
}
- fin.close();
}
+ fin.close();
+ }
}
-//---------------------------------------------------------
-int cmCTestMultiProcessHandler::SearchByName(std::string name)
+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)
- {
+ for (PropertiesMap::iterator i = this->Properties.begin();
+ i != this->Properties.end(); ++i) {
+ if (i->second->Name == name) {
index = i->first;
- }
}
+ }
return index;
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::CreateTestCostList()
{
- for(TestMap::iterator i = this->Tests.begin();
- i != this->Tests.end(); ++i)
- {
- SortedTests.push_back(i->first);
-
- //If the test failed last time, it should be run first, so max the cost.
- //Only do this for parallel runs; in non-parallel runs, avoid clobbering
- //the test's explicitly set cost.
- if(this->ParallelLevel > 1 &&
- std::find(this->LastTestsFailed.begin(), this->LastTestsFailed.end(),
- this->Properties[i->first]->Name) != this->LastTestsFailed.end())
- {
- this->Properties[i->first]->Cost = FLT_MAX;
+ if (this->ParallelLevel > 1) {
+ CreateParallelTestCostList();
+ } else {
+ CreateSerialTestCostList();
+ }
+}
+
+void cmCTestMultiProcessHandler::CreateParallelTestCostList()
+{
+ TestSet alreadySortedTests;
+
+ std::list<TestSet> priorityStack;
+ priorityStack.push_back(TestSet());
+ 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()) {
+ // If the test failed last time, it should be run first.
+ this->SortedTests.push_back(i->first);
+ alreadySortedTests.insert(i->first);
+ } else {
+ topLevel.insert(i->first);
+ }
+ }
+
+ // In parallel test runs repeatedly move dependencies of the tests on
+ // the current dependency level to the next level until no
+ // further dependencies exist.
+ while (!priorityStack.back().empty()) {
+ TestSet& previousSet = priorityStack.back();
+ priorityStack.push_back(TestSet());
+ TestSet& currentSet = priorityStack.back();
+
+ for (TestSet::const_iterator i = previousSet.begin();
+ i != previousSet.end(); ++i) {
+ 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);
+ }
+ }
+
+ // Remove the empty dependency level
+ priorityStack.pop_back();
+
+ // 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);
+
+ 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);
}
}
+ }
+}
+
+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);
+ }
+}
+
+void cmCTestMultiProcessHandler::CreateSerialTestCostList()
+{
+ TestList presortedList;
+
+ for (TestMap::iterator i = this->Tests.begin(); i != this->Tests.end();
+ ++i) {
+ presortedList.push_back(i->first);
+ }
TestComparator comp(this);
- std::stable_sort(SortedTests.begin(), SortedTests.end(), comp);
+ std::stable_sort(presortedList.begin(), presortedList.end(), comp);
+
+ TestSet alreadySortedTests;
+
+ for (TestList::const_iterator i = presortedList.begin();
+ i != presortedList.end(); ++i) {
+ int test = *i;
+
+ if (alreadySortedTests.find(test) != alreadySortedTests.end()) {
+ 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()) {
+ alreadySortedTests.insert(testDependency);
+ this->SortedTests.push_back(testDependency);
+ }
+ }
+
+ alreadySortedTests.insert(test);
+ this->SortedTests.push_back(test);
+ }
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::WriteCheckpoint(int index)
{
- std::string fname = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/CTestCheckpoint.txt";
- std::fstream fout;
- fout.open(fname.c_str(), std::ios::app | std::ios::out);
+ std::string fname =
+ this->CTest->GetBinaryDir() + "/Testing/Temporary/CTestCheckpoint.txt";
+ cmsys::ofstream fout;
+ fout.open(fname.c_str(), std::ios::app);
fout << index << "\n";
fout.close();
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::MarkFinished()
{
- std::string fname = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/CTestCheckpoint.txt";
- cmSystemTools::RemoveFile(fname.c_str());
+ std::string fname =
+ this->CTest->GetBinaryDir() + "/Testing/Temporary/CTestCheckpoint.txt";
+ cmSystemTools::RemoveFile(fname);
}
-//---------------------------------------------------------
-//For ShowOnly mode
+// For ShowOnly mode
void cmCTestMultiProcessHandler::PrintTestList()
{
this->TestHandler->SetMaxIndex(this->FindMaxIndex());
int count = 0;
for (PropertiesMap::iterator it = this->Properties.begin();
- it != this->Properties.end(); ++it)
- {
+ it != this->Properties.end(); ++it) {
count++;
cmCTestTestHandler::cmCTestTestProperties& p = *it->second;
- //push working dir
- std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(p.Directory.c_str());
+ cmWorkingDirectory workdir(p.Directory);
cmCTestRunTest testRun(this->TestHandler);
testRun.SetIndex(p.Index);
testRun.SetTestProperties(&p);
- testRun.ComputeArguments(); //logs the command in verbose mode
+ testRun.ComputeArguments(); // logs the command in verbose mode
- if(p.Labels.size()) //print the labels
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Labels:");
- }
- for(std::vector<std::string>::iterator label = p.Labels.begin();
- label != p.Labels.end(); ++label)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " " << *label);
- }
- if(p.Labels.size()) //print the labels
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
- }
+ if (!p.Labels.empty()) // print the labels
+ {
+ 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,
+ this->Quiet);
+ }
+ if (!p.Labels.empty()) // print the labels
+ {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl,
+ this->Quiet);
+ }
- if (this->TestHandler->MemCheck)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Memory Check");
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Test");
- }
- cmOStringStream indexStr;
+ if (this->TestHandler->MemCheck) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Memory Check",
+ this->Quiet);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Test", this->Quiet);
+ }
+ std::ostringstream indexStr;
indexStr << " #" << p.Index << ":";
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
- << indexStr.str().c_str());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, p.Name.c_str() << std::endl);
- //pop working dir
- cmSystemTools::ChangeDirectory(current_dir.c_str());
- }
-
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl << "Total Tests: "
- << this->Total << std::endl);
+ << indexStr.str(),
+ this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " " << p.Name,
+ this->Quiet);
+ if (p.Disabled) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " (Disabled)",
+ this->Quiet);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
+ }
+
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl
+ << "Total Tests: " << this->Total << std::endl,
+ this->Quiet);
}
void cmCTestMultiProcessHandler::PrintLabels()
{
std::set<std::string> allLabels;
for (PropertiesMap::iterator it = this->Properties.begin();
- it != this->Properties.end(); ++it)
- {
+ it != this->Properties.end(); ++it) {
cmCTestTestHandler::cmCTestTestProperties& p = *it->second;
allLabels.insert(p.Labels.begin(), p.Labels.end());
- }
-
- if(allLabels.size())
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "All Labels:" << std::endl);
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "No Labels Exist" << std::endl);
- }
- for(std::set<std::string>::iterator label = allLabels.begin();
- label != allLabels.end(); ++label)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " " << *label << std::endl);
- }
+ }
+
+ if (!allLabels.empty()) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "All Labels:" << std::endl,
+ this->Quiet);
+ } else {
+ 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);
+ }
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::CheckResume()
{
- std::string fname = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/CTestCheckpoint.txt";
- if(this->CTest->GetFailover())
- {
- if(cmSystemTools::FileExists(fname.c_str(), true))
- {
- *this->TestHandler->LogFile << "Resuming previously interrupted test set"
- << std::endl
+ std::string fname =
+ this->CTest->GetBinaryDir() + "/Testing/Temporary/CTestCheckpoint.txt";
+ if (this->CTest->GetFailover()) {
+ if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ *this->TestHandler->LogFile
+ << "Resuming previously interrupted test set" << std::endl
<< "----------------------------------------------------------"
<< std::endl;
- std::ifstream fin;
+ cmsys::ifstream fin;
fin.open(fname.c_str());
std::string line;
- while(std::getline(fin, line))
- {
+ while (std::getline(fin, line)) {
int index = atoi(line.c_str());
this->RemoveTest(index);
- }
- fin.close();
}
+ fin.close();
}
- else if(cmSystemTools::FileExists(fname.c_str(), true))
- {
- cmSystemTools::RemoveFile(fname.c_str());
- }
+ } else if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ cmSystemTools::RemoveFile(fname);
+ }
}
-//---------------------------------------------------------
void cmCTestMultiProcessHandler::RemoveTest(int index)
{
this->EraseTest(index);
@@ -636,61 +791,54 @@ void cmCTestMultiProcessHandler::RemoveTest(int index)
this->Completed++;
}
-//---------------------------------------------------------
int cmCTestMultiProcessHandler::FindMaxIndex()
{
int max = 0;
cmCTestMultiProcessHandler::TestMap::iterator i = this->Tests.begin();
- for(; i != this->Tests.end(); ++i)
- {
- if(i->first > max)
- {
+ for (; i != this->Tests.end(); ++i) {
+ if (i->first > max) {
max = i->first;
- }
}
+ }
return max;
}
-//Returns true if no cycles exist in the dependency graph
+// Returns true if no cycles exist in the dependency graph
bool cmCTestMultiProcessHandler::CheckCycles()
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Checking test dependency graph..." << std::endl);
- for(TestMap::iterator it = this->Tests.begin();
- it != this->Tests.end(); ++it)
- {
- //DFS from each element to itself
+ 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) {
+ // DFS from each element to itself
int root = it->first;
std::set<int> visited;
std::stack<int> s;
s.push(root);
- while(!s.empty())
- {
+ while (!s.empty()) {
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)
- {
- //cycle exists
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: a cycle exists in the test dependency graph "
- "for the test \"" << this->Properties[root]->Name <<
- "\".\nPlease fix the cycle and run ctest again.\n");
+ if (visited.insert(test).second) {
+ for (TestSet::iterator d = this->Tests[test].begin();
+ d != this->Tests[test].end(); ++d) {
+ if (*d == root) {
+ // cycle exists
+ cmCTestLog(
+ this->CTest, ERROR_MESSAGE,
+ "Error: a cycle exists in the test dependency graph "
+ "for the test \""
+ << this->Properties[root]->Name
+ << "\".\nPlease fix the cycle and run ctest again.\n");
return false;
- }
- else
- {
- s.push(*d);
- }
}
+ s.push(*d);
}
}
}
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Checking test dependency graph end" << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Checking test dependency graph end" << std::endl,
+ this->Quiet);
return true;
}
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index cd21d9187..dccc2c896 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -1,20 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestMultiProcessHandler_h
#define cmCTestMultiProcessHandler_h
-#include <cmStandardIncludes.h>
-#include <cmCTestTestHandler.h>
-#include <cmCTestRunTest.h>
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCTestTestHandler.h"
+#include <map>
+#include <set>
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestRunTest;
/** \class cmCTestMultiProcessHandler
* \brief run parallel ctest
@@ -24,12 +23,21 @@
class cmCTestMultiProcessHandler
{
friend class TestComparator;
+
public:
- struct TestSet : public std::set<int> {};
- struct TestMap : public std::map<int, TestSet> {};
- struct TestList : public std::vector<int> {};
- struct PropertiesMap : public
- std::map<int, cmCTestTestHandler::cmCTestTestProperties*> {};
+ struct TestSet : public std::set<int>
+ {
+ };
+ struct TestMap : public std::map<int, TestSet>
+ {
+ };
+ struct TestList : public std::vector<int>
+ {
+ };
+ struct PropertiesMap
+ : public std::map<int, cmCTestTestHandler::cmCTestTestProperties*>
+ {
+ };
cmCTestMultiProcessHandler();
virtual ~cmCTestMultiProcessHandler();
@@ -37,26 +45,32 @@ public:
void SetTests(TestMap& tests, PropertiesMap& properties);
// Set the max number of tests that can be run at the same time.
void SetParallelLevel(size_t);
+ void SetTestLoad(unsigned long load);
virtual void RunTests();
void PrintTestList();
void PrintLabels();
- void SetPassFailVectors(std::vector<cmStdString>* passed,
- std::vector<cmStdString>* failed)
- {
+ void SetPassFailVectors(std::vector<std::string>* passed,
+ std::vector<std::string>* failed)
+ {
this->Passed = passed;
this->Failed = failed;
- }
+ }
void SetTestResults(std::vector<cmCTestTestHandler::cmCTestTestResult>* r)
- { this->TestResults = r; }
+ {
+ this->TestResults = r;
+ }
- void SetCTest(cmCTest* ctest) { this->CTest = ctest;}
+ void SetCTest(cmCTest* ctest) { this->CTest = ctest; }
- void SetTestHandler(cmCTestTestHandler * handler)
- { this->TestHandler = handler; }
+ void SetTestHandler(cmCTestTestHandler* handler)
+ {
+ this->TestHandler = handler;
+ }
- cmCTestTestHandler * GetTestHandler()
- { return this->TestHandler; }
+ cmCTestTestHandler* GetTestHandler() { return this->TestHandler; }
+
+ void SetQuiet(bool b) { this->Quiet = b; }
protected:
// Start the next test or tests as many as are allowed by
// ParallelLevel
@@ -69,9 +83,15 @@ protected:
void UpdateCostData();
void ReadCostData();
// Return index of a test based on its name
- int SearchByName(std::string name);
+ int SearchByName(std::string const& name);
void CreateTestCostList();
+
+ void GetAllTestDependencies(int test, TestList& dependencies);
+ void CreateSerialTestCostList();
+
+ void CreateParallelTestCostList();
+
// Removes the checkpoint file
void MarkFinished();
void EraseTest(int index);
@@ -79,38 +99,43 @@ protected:
// check all running processes for output and exit case
bool CheckOutput();
void RemoveTest(int index);
- //Check if we need to resume an interrupted test set
+ // Check if we need to resume an interrupted test set
void CheckResume();
- //Check if there are any circular dependencies
+ // Check if there are any circular dependencies
bool CheckCycles();
int FindMaxIndex();
inline size_t GetProcessorsUsed(int index);
+ std::string GetName(int index);
void LockResources(int index);
void UnlockResources(int index);
// map from test number to set of depend tests
TestMap Tests;
TestList SortedTests;
- //Total number of tests we'll be running
+ // Total number of tests we'll be running
size_t Total;
- //Number of tests that are complete
+ // Number of tests that are complete
size_t Completed;
size_t RunningCount;
bool StopTimePassed;
- //list of test properties (indices concurrent to the test map)
+ // list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
std::map<int, bool> TestRunningMap;
std::map<int, bool> TestFinishMap;
- std::map<int, cmStdString> TestOutput;
- std::vector<cmStdString>* Passed;
- std::vector<cmStdString>* Failed;
+ std::map<int, std::string> TestOutput;
+ std::vector<std::string>* Passed;
+ std::vector<std::string>* Failed;
std::vector<std::string> LastTestsFailed;
std::set<std::string> LockedResources;
std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
size_t ParallelLevel; // max number of process that can be run at once
- std::set<cmCTestRunTest*> RunningTests; // current running tests
- cmCTestTestHandler * TestHandler;
+ unsigned long TestLoad;
+ std::set<cmCTestRunTest*> RunningTests; // current running tests
+ cmCTestTestHandler* TestHandler;
cmCTest* CTest;
+ bool HasCycles;
+ bool Quiet;
+ bool SerialTestRunning;
};
#endif
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
new file mode 100644
index 000000000..c80221634
--- /dev/null
+++ b/Source/CTest/cmCTestP4.cxx
@@ -0,0 +1,529 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestP4.h"
+
+#include "cmCTest.h"
+#include "cmCTestVC.h"
+#include "cmProcessTools.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()
+{
+}
+
+class cmCTestP4::IdentifyParser : public cmCTestVC::LineParser
+{
+public:
+ IdentifyParser(cmCTestP4* p4, const char* prefix, std::string& rev)
+ : Rev(rev)
+ {
+ this->SetLog(&p4->Log, prefix);
+ this->RegexIdentify.compile("^Change ([0-9]+) on");
+ }
+
+private:
+ std::string& Rev;
+ cmsys::RegularExpression RegexIdentify;
+
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexIdentify.find(this->Line)) {
+ this->Rev = this->RegexIdentify.match(1);
+ return false;
+ }
+ return true;
+ }
+};
+
+class cmCTestP4::ChangesParser : public cmCTestVC::LineParser
+{
+public:
+ ChangesParser(cmCTestP4* p4, const char* prefix)
+ : P4(p4)
+ {
+ this->SetLog(&P4->Log, prefix);
+ this->RegexIdentify.compile("^Change ([0-9]+) on");
+ }
+
+private:
+ cmsys::RegularExpression RegexIdentify;
+ cmCTestP4* P4;
+
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexIdentify.find(this->Line)) {
+ P4->ChangeLists.push_back(this->RegexIdentify.match(1));
+ }
+ return true;
+ }
+};
+
+class cmCTestP4::UserParser : public cmCTestVC::LineParser
+{
+public:
+ UserParser(cmCTestP4* p4, const char* prefix)
+ : P4(p4)
+ {
+ this->SetLog(&P4->Log, prefix);
+ this->RegexUser.compile("^(.+) <(.*)> \\((.*)\\) accessed (.*)$");
+ }
+
+private:
+ cmsys::RegularExpression RegexUser;
+ cmCTestP4* P4;
+
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexUser.find(this->Line)) {
+ User NewUser;
+
+ NewUser.UserName = this->RegexUser.match(1);
+ NewUser.EMail = this->RegexUser.match(2);
+ NewUser.Name = this->RegexUser.match(3);
+ NewUser.AccessTime = this->RegexUser.match(4);
+ P4->Users[this->RegexUser.match(1)] = NewUser;
+
+ return false;
+ }
+ return true;
+ }
+};
+
+/* Diff format:
+==== //depot/file#rev - /absolute/path/to/file ====
+(diff data)
+==== //depot/file2#rev - /absolute/path/to/file2 ====
+(diff data)
+==== //depot/file3#rev - /absolute/path/to/file3 ====
+==== //depot/file4#rev - /absolute/path/to/file4 ====
+(diff data)
+*/
+class cmCTestP4::DiffParser : public cmCTestVC::LineParser
+{
+public:
+ DiffParser(cmCTestP4* p4, const char* prefix)
+ : P4(p4)
+ , AlreadyNotified(false)
+ {
+ this->SetLog(&P4->Log, prefix);
+ this->RegexDiff.compile("^==== (.*)#[0-9]+ - (.*)");
+ }
+
+private:
+ cmCTestP4* P4;
+ bool AlreadyNotified;
+ std::string CurrentPath;
+ cmsys::RegularExpression RegexDiff;
+
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (!this->Line.empty() && this->Line[0] == '=' &&
+ this->RegexDiff.find(this->Line)) {
+ CurrentPath = this->RegexDiff.match(1);
+ AlreadyNotified = false;
+ } else {
+ if (!AlreadyNotified) {
+ P4->DoModification(PathModified, CurrentPath);
+ AlreadyNotified = true;
+ }
+ }
+ return true;
+ }
+};
+
+cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
+{
+ std::map<std::string, cmCTestP4::User>::const_iterator it =
+ Users.find(username);
+
+ if (it == Users.end()) {
+ std::vector<char const*> p4_users;
+ SetP4Options(p4_users);
+ p4_users.push_back("users");
+ p4_users.push_back("-m");
+ p4_users.push_back("1");
+ p4_users.push_back(username.c_str());
+ p4_users.push_back(CM_NULLPTR);
+
+ UserParser out(this, "users-out> ");
+ OutputLogger err(this->Log, "users-err> ");
+ RunChild(&p4_users[0], &out, &err);
+
+ // The user should now be added to the map. Search again.
+ it = Users.find(username);
+ if (it == Users.end()) {
+ return cmCTestP4::User();
+ }
+ }
+
+ return it->second;
+}
+
+/* Commit format:
+
+Change 1111111 by user@client on 2013/09/26 11:50:36
+
+ text
+ text
+
+Affected files ...
+
+... //path/to/file#rev edit
+... //path/to/file#rev add
+... //path/to/file#rev delete
+... //path/to/file#rev integrate
+*/
+class cmCTestP4::DescribeParser : public cmCTestVC::LineParser
+{
+public:
+ DescribeParser(cmCTestP4* p4, const char* prefix)
+ : LineParser('\n', false)
+ , P4(p4)
+ , Section(SectionHeader)
+ {
+ this->SetLog(&P4->Log, prefix);
+ this->RegexHeader.compile("^Change ([0-9]+) by (.+)@(.+) on (.*)$");
+ this->RegexDiff.compile("^\\.\\.\\. (.*)#[0-9]+ ([^ ]+)$");
+ }
+
+private:
+ cmsys::RegularExpression RegexHeader;
+ cmsys::RegularExpression RegexDiff;
+ cmCTestP4* P4;
+
+ typedef cmCTestP4::Revision Revision;
+ typedef cmCTestP4::Change Change;
+ std::vector<Change> Changes;
+ enum SectionType
+ {
+ SectionHeader,
+ SectionBody,
+ SectionDiffHeader,
+ SectionDiff,
+ SectionCount
+ };
+ SectionType Section;
+ Revision Rev;
+
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->Line.empty()) {
+ this->NextSection();
+ } else {
+ switch (this->Section) {
+ case SectionHeader:
+ this->DoHeaderLine();
+ break;
+ case SectionBody:
+ this->DoBodyLine();
+ break;
+ case SectionDiffHeader:
+ break; // nothing to do
+ case SectionDiff:
+ this->DoDiffLine();
+ break;
+ case SectionCount:
+ break; // never happens
+ }
+ }
+ return true;
+ }
+
+ void NextSection()
+ {
+ if (this->Section == SectionDiff) {
+ this->P4->DoRevision(this->Rev, this->Changes);
+ this->Rev = Revision();
+ }
+
+ this->Section = SectionType((this->Section + 1) % SectionCount);
+ }
+
+ void DoHeaderLine()
+ {
+ if (this->RegexHeader.find(this->Line)) {
+ this->Rev.Rev = this->RegexHeader.match(1);
+ this->Rev.Date = this->RegexHeader.match(4);
+
+ cmCTestP4::User user = P4->GetUserData(this->RegexHeader.match(2));
+ this->Rev.Author = user.Name;
+ this->Rev.EMail = user.EMail;
+
+ this->Rev.Committer = this->Rev.Author;
+ this->Rev.CommitterEMail = this->Rev.EMail;
+ this->Rev.CommitDate = this->Rev.Date;
+ }
+ }
+
+ void DoBodyLine()
+ {
+ if (this->Line[0] == '\t') {
+ this->Rev.Log += this->Line.substr(1);
+ }
+ this->Rev.Log += "\n";
+ }
+
+ void DoDiffLine()
+ {
+ if (this->RegexDiff.find(this->Line)) {
+ Change change;
+ std::string Path = this->RegexDiff.match(1);
+ if (Path.length() > 2 && Path[0] == '/' && Path[1] == '/') {
+ size_t found = Path.find('/', 2);
+ if (found != std::string::npos) {
+ Path = Path.substr(found + 1);
+ }
+ }
+
+ change.Path = Path;
+ std::string action = this->RegexDiff.match(2);
+
+ if (action == "add") {
+ change.Action = 'A';
+ } else if (action == "delete") {
+ change.Action = 'D';
+ } else if (action == "edit" || action == "integrate") {
+ change.Action = 'M';
+ }
+
+ Changes.push_back(change);
+ }
+ }
+};
+
+void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions)
+{
+ if (P4Options.empty()) {
+ const char* p4 = this->CommandLineTool.c_str();
+ P4Options.push_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.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");
+
+ // 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());
+ }
+
+ CommandOptions.clear();
+ for (std::vector<std::string>::iterator i = P4Options.begin();
+ i != P4Options.end(); ++i) {
+ CommandOptions.push_back(i->c_str());
+ }
+}
+
+std::string cmCTestP4::GetWorkingRevision()
+{
+ std::vector<char const*> p4_identify;
+ SetP4Options(p4_identify);
+
+ p4_identify.push_back("changes");
+ p4_identify.push_back("-m");
+ p4_identify.push_back("1");
+ p4_identify.push_back("-t");
+
+ std::string source = this->SourceDirectory + "/...#have";
+ p4_identify.push_back(source.c_str());
+ p4_identify.push_back(CM_NULLPTR);
+
+ std::string rev;
+ IdentifyParser out(this, "p4_changes-out> ", rev);
+ OutputLogger err(this->Log, "p4_changes-err> ");
+
+ bool result = RunChild(&p4_identify[0], &out, &err);
+
+ // If there was a problem contacting the server return "<unknown>"
+ if (!result) {
+ return "<unknown>";
+ }
+
+ if (rev.empty()) {
+ return "0";
+ }
+ return rev;
+}
+
+bool cmCTestP4::NoteOldRevision()
+{
+ this->OldRevision = this->GetWorkingRevision();
+
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
+ << this->OldRevision << "\n");
+ this->PriorRev.Rev = this->OldRevision;
+ return true;
+}
+
+bool cmCTestP4::NoteNewRevision()
+{
+ this->NewRevision = this->GetWorkingRevision();
+
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
+ << this->NewRevision << "\n");
+ return true;
+}
+
+bool cmCTestP4::LoadRevisions()
+{
+ std::vector<char const*> p4_changes;
+ SetP4Options(p4_changes);
+
+ // Use 'p4 changes ...@old,new' to get a list of changelists
+ std::string range = this->SourceDirectory + "/...";
+
+ // 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 "
+ << "is unknown. No repository changes will be reported.\n");
+ return false;
+ }
+
+ range.append("@")
+ .append(this->OldRevision)
+ .append(",")
+ .append(this->NewRevision);
+
+ p4_changes.push_back("changes");
+ p4_changes.push_back(range.c_str());
+ p4_changes.push_back(CM_NULLPTR);
+
+ ChangesParser out(this, "p4_changes-out> ");
+ OutputLogger err(this->Log, "p4_changes-err> ");
+
+ ChangeLists.clear();
+ this->RunChild(&p4_changes[0], &out, &err);
+
+ if (ChangeLists.empty()) {
+ return true;
+ }
+
+ // 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) {
+ 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);
+
+ DescribeParser outDescribe(this, "p4_describe-out> ");
+ OutputLogger errDescribe(this->Log, "p4_describe-err> ");
+ this->RunChild(&p4_describe[0], &outDescribe, &errDescribe);
+ }
+ return true;
+}
+
+bool cmCTestP4::LoadModifications()
+{
+ std::vector<char const*> p4_diff;
+ SetP4Options(p4_diff);
+
+ p4_diff.push_back("diff");
+
+ // Ideally we would use -Od but not all clients support it
+ p4_diff.push_back("-dn");
+ std::string source = this->SourceDirectory + "/...";
+ p4_diff.push_back(source.c_str());
+ p4_diff.push_back(CM_NULLPTR);
+
+ DiffParser out(this, "p4_diff-out> ");
+ OutputLogger err(this->Log, "p4_diff-err> ");
+ this->RunChild(&p4_diff[0], &out, &err);
+ return true;
+}
+
+bool cmCTestP4::UpdateCustom(const std::string& custom)
+{
+ std::vector<std::string> p4_custom_command;
+ cmSystemTools::ExpandListArgument(custom, p4_custom_command, 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.push_back(CM_NULLPTR);
+
+ OutputLogger custom_out(this->Log, "p4_customsync-out> ");
+ OutputLogger custom_err(this->Log, "p4_customsync-err> ");
+
+ return this->RunUpdateCommand(&p4_custom[0], &custom_out, &custom_err);
+}
+
+bool cmCTestP4::UpdateImpl()
+{
+ std::string custom = this->CTest->GetCTestConfiguration("P4UpdateCustom");
+ if (!custom.empty()) {
+ return this->UpdateCustom(custom);
+ }
+
+ // If we couldn't get a revision number before updating, abort.
+ if (this->OldRevision == "<unknown>") {
+ this->UpdateCommandLine = "Unknown current revision";
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown current revision\n");
+ return false;
+ }
+
+ std::vector<char const*> p4_sync;
+ SetP4Options(p4_sync);
+
+ p4_sync.push_back("sync");
+
+ // Get user-specified update options.
+ std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
+ 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::string source = this->SourceDirectory + "/...";
+
+ // Specify the start time for nightly testing.
+ if (this->CTest->GetTestModel() == cmCTest::NIGHTLY) {
+ std::string date = this->GetNightlyTime();
+ // CTest reports the date as YYYY-MM-DD, Perforce needs it as YYYY/MM/DD
+ std::replace(date.begin(), date.end(), '-', '/');
+
+ // Revision specification: /...@"YYYY/MM/DD HH:MM:SS"
+ source.append("@\"").append(date).append("\"");
+ }
+
+ p4_sync.push_back(source.c_str());
+ p4_sync.push_back(CM_NULLPTR);
+
+ OutputLogger out(this->Log, "p4_sync-out> ");
+ OutputLogger err(this->Log, "p4_sync-err> ");
+
+ return this->RunUpdateCommand(&p4_sync[0], &out, &err);
+}
diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h
new file mode 100644
index 000000000..e234efbfb
--- /dev/null
+++ b/Source/CTest/cmCTestP4.h
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCTestP4_h
+#define cmCTestP4_h
+
+#include "cmConfigure.h"
+
+#include "cmCTestGlobalVC.h"
+
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCTest;
+
+/** \class cmCTestP4
+ * \brief Interaction with the Perforce command-line tool
+ *
+ */
+class cmCTestP4 : public cmCTestGlobalVC
+{
+public:
+ /** Construct with a CTest instance and update log stream. */
+ cmCTestP4(cmCTest* ctest, std::ostream& log);
+
+ ~cmCTestP4() CM_OVERRIDE;
+
+private:
+ std::vector<std::string> ChangeLists;
+
+ struct User
+ {
+ std::string UserName;
+ std::string Name;
+ std::string EMail;
+ std::string AccessTime;
+
+ User()
+ : UserName()
+ , Name()
+ , EMail()
+ , AccessTime()
+ {
+ }
+ };
+ std::map<std::string, User> Users;
+ std::vector<std::string> P4Options;
+
+ User GetUserData(const std::string& username);
+ void SetP4Options(std::vector<char const*>& options);
+
+ std::string GetWorkingRevision();
+ bool NoteOldRevision() CM_OVERRIDE;
+ bool NoteNewRevision() CM_OVERRIDE;
+ bool UpdateImpl() CM_OVERRIDE;
+ bool UpdateCustom(const std::string& custom);
+
+ bool LoadRevisions() CM_OVERRIDE;
+ bool LoadModifications() CM_OVERRIDE;
+
+ class ChangesParser;
+ class DescribeParser;
+ class DiffParser;
+ // Parsing helper classes.
+ class IdentifyParser;
+ class UserParser;
+
+ friend class IdentifyParser;
+ friend class ChangesParser;
+ friend class UserParser;
+ friend class DescribeParser;
+ friend class DiffParser;
+};
+
+#endif
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.cxx b/Source/CTest/cmCTestReadCustomFilesCommand.cxx
index 5db01f98d..b21be872f 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.cxx
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.cxx
@@ -1,35 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestReadCustomFilesCommand.h"
#include "cmCTest.h"
-bool cmCTestReadCustomFilesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+class cmExecutionStatus;
+
+bool cmCTestReadCustomFilesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus& /*unused*/)
{
- if (args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
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 (dit = args.begin(); dit != args.end(); ++dit) {
+ this->CTest->ReadCustomConfigurationFileTree(dit->c_str(), this->Makefile);
+ }
return true;
}
-
-
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h
index b984c84e9..5989fa0fc 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.h
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestReadCustomFilesCommand_h
#define cmCTestReadCustomFilesCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestCommand.h"
+#include <string>
+#include <vector>
+
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmCTestReadCustomFiles
* \brief Run a ctest script
*
@@ -23,53 +22,24 @@
class cmCTestReadCustomFilesCommand : public cmCTestCommand
{
public:
-
cmCTestReadCustomFilesCommand() {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestReadCustomFilesCommand* ni = new cmCTestReadCustomFilesCommand;
ni->CTest = this->CTest;
return ni;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_read_custom_files";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "read CTestCustom files.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_read_custom_files( directory ... )\n"
- "Read all the CTestCustom.ctest or CTestCustom.cmake files from "
- "the given directory.";
- }
-
- cmTypeMacro(cmCTestReadCustomFilesCommand, cmCTestCommand);
-
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx
index fe429bd9d..238284a3f 100644
--- a/Source/CTest/cmCTestRunScriptCommand.cxx
+++ b/Source/CTest/cmCTestRunScriptCommand.cxx
@@ -1,65 +1,49 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestRunScriptCommand.h"
#include "cmCTestScriptHandler.h"
+#include "cmMakefile.h"
+
+#include <sstream>
-bool cmCTestRunScriptCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+class cmExecutionStatus;
+
+bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->CTestScriptHandler->RunCurrentScript();
return true;
- }
+ }
bool np = false;
unsigned int i = 0;
- if (args[i] == "NEW_PROCESS")
- {
+ if (args[i] == "NEW_PROCESS") {
np = true;
i++;
- }
+ }
int start = i;
// run each script
std::string returnVariable;
- for (i = start; i < args.size(); ++i)
- {
- if(args[i] == "RETURN_VALUE")
- {
+ for (i = start; i < args.size(); ++i) {
+ if (args[i] == "RETURN_VALUE") {
++i;
- if(i < args.size())
- {
+ if (i < args.size()) {
returnVariable = args[i];
- }
}
}
- for (i = start; i < args.size(); ++i)
- {
- if(args[i] == "RETURN_VALUE")
- {
+ }
+ for (i = start; i < args.size(); ++i) {
+ if (args[i] == "RETURN_VALUE") {
++i;
- }
- else
- {
+ } else {
int ret;
- cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str(), !np,
- &ret);
- cmOStringStream str;
+ cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str(), !np, &ret);
+ std::ostringstream str;
str << ret;
- this->Makefile->AddDefinition(returnVariable.c_str(), str.str().c_str());
- }
+ this->Makefile->AddDefinition(returnVariable, str.str().c_str());
}
+ }
return true;
}
-
-
diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h
index 05e78991a..9bd09659d 100644
--- a/Source/CTest/cmCTestRunScriptCommand.h
+++ b/Source/CTest/cmCTestRunScriptCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestRunScriptCommand_h
#define cmCTestRunScriptCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestCommand.h"
+#include <string>
+#include <vector>
+
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmCTestRunScript
* \brief Run a ctest script
*
@@ -23,58 +22,25 @@
class cmCTestRunScriptCommand : public cmCTestCommand
{
public:
-
cmCTestRunScriptCommand() {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestRunScriptCommand* ni = new cmCTestRunScriptCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_run_script";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "runs a ctest -S script";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_run_script([NEW_PROCESS] script_file_name script_file_name1 \n"
- " script_file_name2 ... [RETURN_VALUE var])\n"
- "Runs a script or scripts much like if it was run from ctest -S. "
- "If no argument is provided then the current script is run using "
- "the current settings of the variables. If NEW_PROCESS is specified "
- "then each script will be run in a separate process."
- "If RETURN_VALUE is specified the return value of the last script "
- "run will be put into var.";
- }
-
- cmTypeMacro(cmCTestRunScriptCommand, cmCTestCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 0e2fa41b9..0c4269e3d 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -1,77 +1,96 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestRunTest.h"
-#include "cmCTestMemCheckHandler.h"
+
#include "cmCTest.h"
+#include "cmCTestMemCheckHandler.h"
+#include "cmCTestTestHandler.h"
+#include "cmProcess.h"
#include "cmSystemTools.h"
-#include "cm_curl.h"
+#include "cmWorkingDirectory.h"
-#include <cm_zlib.h>
-#include <cmsys/Base64.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)
{
this->CTest = handler->CTest;
this->TestHandler = handler;
- this->TestProcess = 0;
- this->TestResult.ExecutionTime =0;
+ this->TestProcess = CM_NULLPTR;
+ this->TestResult.ExecutionTime = 0;
this->TestResult.ReturnValue = 0;
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.TestCount = 0;
- this->TestResult.Properties = 0;
+ this->TestResult.Properties = CM_NULLPTR;
this->ProcessOutput = "";
this->CompressedOutput = "";
this->CompressionRatio = 2;
this->StopTimePassed = false;
+ this->NumberOfRunsLeft = 1; // default to 1 run of the test
+ this->RunUntilFail = false; // default to run the test once
+ this->RunAgain = false; // default to not having to run again
}
cmCTestRunTest::~cmCTestRunTest()
{
}
-//----------------------------------------------------------------------------
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))
- {
+ while ((timeout = timeEnd - cmSystemTools::GetTime(), timeout > 0)) {
int p = this->TestProcess->GetNextOutputLine(line, timeout);
- if(p == cmsysProcess_Pipe_None)
- {
+ if (p == cmsysProcess_Pipe_None) {
// Process has terminated and all output read.
return false;
- }
- else if(p == cmsysProcess_Pipe_STDOUT ||
- p == cmsysProcess_Pipe_STDERR)
- {
+ }
+ if (p == cmsysProcess_Pipe_STDOUT) {
// Store this line of output.
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- this->GetIndex() << ": " << line << std::endl);
+ 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;
+ }
+ }
}
- else // if(p == cmsysProcess_Pipe_Timeout)
- {
+ } 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()
@@ -79,10 +98,9 @@ void cmCTestRunTest::CompressOutput()
int ret;
z_stream strm;
- unsigned char* in =
- reinterpret_cast<unsigned char*>(
+ 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
+ // 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];
@@ -90,12 +108,11 @@ void cmCTestRunTest::CompressOutput()
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
- ret = deflateInit(&strm, -1); //default compression level
- if (ret != Z_OK)
- {
+ 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;
@@ -103,134 +120,124 @@ void cmCTestRunTest::CompressOutput()
strm.next_out = out;
ret = deflate(&strm, Z_FINISH);
- if(ret == Z_STREAM_ERROR || ret != Z_STREAM_END)
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error during output "
- "compression. Sending uncompressed output." << std::endl);
+ 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)];
+ unsigned char* encoded_buffer =
+ new unsigned char[static_cast<int>(outSize * 1.5)];
- unsigned long rlen
- = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1);
+ size_t rlen = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1);
- for(unsigned long i = 0; i < rlen; i++)
- {
+ 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);
- }
+ if (strm.total_in) {
+ this->CompressionRatio =
+ static_cast<double>(strm.total_out) / static_cast<double>(strm.total_in);
+ }
- delete [] encoded_buffer;
- delete [] out;
+ delete[] encoded_buffer;
+ delete[] out;
}
-//---------------------------------------------------------
bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
{
if ((!this->TestHandler->MemCheck &&
- this->CTest->ShouldCompressTestOutput()) ||
+ this->CTest->ShouldCompressTestOutput()) ||
(this->TestHandler->MemCheck &&
- this->CTest->ShouldCompressMemCheckOutput()))
- {
+ 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 res =
+ started ? this->TestProcess->GetProcessStatus() : cmsysProcess_State_Error;
int retVal = this->TestProcess->GetExitValue();
- std::vector<std::pair<cmsys::RegularExpression,
- std::string> >::iterator passIt;
+ std::vector<std::pair<cmsys::RegularExpression, std::string> >::iterator
+ passIt;
bool forceFail = false;
+ bool skipped = false;
bool outputTestErrorsToConsole = false;
- if ( this->TestProperties->RequiredRegularExpressions.size() > 0 )
- {
+ 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 (passIt = this->TestProperties->RequiredRegularExpressions.begin();
+ passIt != this->TestProperties->RequiredRegularExpressions.end();
+ ++passIt) {
+ if (passIt->first.find(this->ProcessOutput.c_str())) {
found = true;
reason = "Required regular expression found.";
break;
- }
}
- if ( !found )
- {
+ }
+ if (!found) {
reason = "Required regular expression not found.";
forceFail = true;
- }
- reason += "Regex=[";
- for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
- passIt != this->TestProperties->RequiredRegularExpressions.end();
- ++ passIt )
- {
+ }
+ reason += "Regex=[";
+ for (passIt = this->TestProperties->RequiredRegularExpressions.begin();
+ passIt != this->TestProperties->RequiredRegularExpressions.end();
+ ++passIt) {
reason += passIt->second;
reason += "\n";
- }
- reason += "]";
}
- if ( this->TestProperties->ErrorRegularExpressions.size() > 0 )
- {
- for ( passIt = this->TestProperties->ErrorRegularExpressions.begin();
- passIt != this->TestProperties->ErrorRegularExpressions.end();
- ++ passIt )
- {
- if ( passIt->first.find(this->ProcessOutput.c_str()) )
- {
+ 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 += "]";
forceFail = true;
break;
- }
}
}
- if (res == cmsysProcess_State_Exited)
- {
- bool success =
- !forceFail && (retVal == 0 ||
- this->TestProperties->RequiredRegularExpressions.size());
- if((success && !this->TestProperties->WillFail)
- || (!success && this->TestProperties->WillFail))
- {
+ }
+ if (res == cmsysProcess_State_Exited) {
+ bool success = !forceFail &&
+ (retVal == 0 ||
+ !this->TestProperties->RequiredRegularExpressions.empty());
+ if (this->TestProperties->SkipReturnCode >= 0 &&
+ this->TestProperties->SkipReturnCode == retVal) {
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ std::ostringstream s;
+ 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)) {
this->TestResult.Status = cmCTestTestHandler::COMPLETED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed " );
- }
- else
- {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed ");
+ } else {
this->TestResult.Status = cmCTestTestHandler::FAILED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason );
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason);
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
- }
}
- else if ( res == cmsysProcess_State_Expired )
- {
+ } else if (res == cmsysProcess_State_Expired) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout ");
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
- }
- else if ( res == cmsysProcess_State_Exception )
- {
+ } else if (res == cmsysProcess_State_Exception) {
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
- switch(this->TestProcess->GetExitException())
- {
+ switch (this->TestProcess->GetExitException()) {
case cmsysProcess_Exception_Fault:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
@@ -250,59 +257,52 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
default:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
- }
}
- else //cmsysProcess_State_Error
- {
+ } else if ("Disabled" == this->TestResult.CompletionStatus) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) ");
+ } else // cmsysProcess_State_Error
+ {
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run ");
- }
+ }
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n" );
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n");
- if ( outputTestErrorsToConsole )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, this->ProcessOutput << std::endl );
- }
+ if (outputTestErrorsToConsole) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, this->ProcessOutput << std::endl);
+ }
- if ( this->TestHandler->LogFile )
- {
+ if (this->TestHandler->LogFile) {
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
- }
-
- // Set the working directory to the tests directory
- std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(this->TestProperties->Directory.c_str());
-
- this->DartProcessing();
-
- // restore working directory
- cmSystemTools::ChangeDirectory(oldpath.c_str());
+ }
+ // Set the working directory to the tests directory to process Dart files.
+ {
+ cmWorkingDirectory workdir(this->TestProperties->Directory);
+ 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
- if(!this->TestHandler->MemCheck && started)
- {
- this->TestHandler->CleanTestOutput(this->ProcessOutput,
- static_cast<size_t>
- (this->TestResult.Status == cmCTestTestHandler::COMPLETED ?
- this->TestHandler->CustomMaximumPassedTestOutputSize :
- this->TestHandler->CustomMaximumFailedTestOutputSize));
- }
+ if (!this->TestHandler->MemCheck && started) {
+ this->TestHandler->CleanTestOutput(
+ this->ProcessOutput,
+ static_cast<size_t>(
+ this->TestResult.Status == cmCTestTestHandler::COMPLETED
+ ? this->TestHandler->CustomMaximumPassedTestOutputSize
+ : this->TestHandler->CustomMaximumFailedTestOutputSize));
+ }
this->TestResult.Reason = reason;
- if (this->TestHandler->LogFile)
- {
+ if (this->TestHandler->LogFile) {
bool pass = true;
const char* reasonType = "Test Pass Reason";
- if(this->TestResult.Status != cmCTestTestHandler::COMPLETED &&
- this->TestResult.Status != cmCTestTestHandler::NOT_RUN)
- {
+ if (this->TestResult.Status != cmCTestTestHandler::COMPLETED &&
+ this->TestResult.Status != cmCTestTestHandler::NOT_RUN) {
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;
@@ -312,105 +312,134 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
*this->TestHandler->LogFile
<< "----------------------------------------------------------"
<< std::endl;
- if(this->TestResult.Reason.size())
- {
+ if (!this->TestResult.Reason.empty()) {
*this->TestHandler->LogFile << reasonType << ":\n"
- << this->TestResult.Reason << "\n";
- }
- else
- {
- if(pass)
- {
+ << this->TestResult.Reason << "\n";
+ } else {
+ if (pass) {
*this->TestHandler->LogFile << "Test Passed.\n";
- }
- else
- {
+ } else {
*this->TestHandler->LogFile << "Test Failed.\n";
- }
}
- *this->TestHandler->LogFile << "\"" << this->TestProperties->Name.c_str()
+ }
+ *this->TestHandler->LogFile
+ << "\"" << this->TestProperties->Name
<< "\" end time: " << this->CTest->CurrentTime() << std::endl
- << "\"" << this->TestProperties->Name.c_str() << "\" time elapsed: "
- << buffer << std::endl
+ << "\"" << this->TestProperties->Name << "\" time elapsed: " << buffer
+ << std::endl
<< "----------------------------------------------------------"
- << std::endl << std::endl;
- }
+ << std::endl
+ << std::endl;
+ }
// if the test actually started and ran
// record the results in TestResult
- if(started)
- {
+ if (started) {
bool compress = !this->TestHandler->MemCheck &&
- this->CompressionRatio < 1 &&
- this->CTest->ShouldCompressTestOutput();
- this->TestResult.Output = compress ? this->CompressedOutput
- : this->ProcessOutput;
+ this->CompressionRatio < 1 && this->CTest->ShouldCompressTestOutput();
+ this->TestResult.Output =
+ compress ? this->CompressedOutput : this->ProcessOutput;
this->TestResult.CompressOutput = compress;
this->TestResult.ReturnValue = this->TestProcess->GetExitValue();
- this->TestResult.CompletionStatus = "Completed";
+ if (!skipped) {
+ this->TestResult.CompletionStatus = "Completed";
+ }
this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime();
this->MemCheckPostProcess();
this->ComputeWeightedCost();
- }
- // Always push the current TestResult onto the
+ }
+ // If the test does not need to rerun push the current TestResult onto the
// TestHandler vector
- this->TestHandler->TestResults.push_back(this->TestResult);
+ if (!this->NeedsToRerun()) {
+ this->TestHandler->TestResults.push_back(this->TestResult);
+ }
delete this->TestProcess;
- return passed;
+ return passed || skipped;
}
-//----------------------------------------------------------------------
+bool cmCTestRunTest::StartAgain()
+{
+ if (!this->RunAgain) {
+ return false;
+ }
+ this->RunAgain = false; // reset
+ // change to tests directory
+ cmWorkingDirectory workdir(this->TestProperties->Directory);
+ this->StartTest(this->TotalNumberOfTests);
+ return true;
+}
+
+bool cmCTestRunTest::NeedsToRerun()
+{
+ this->NumberOfRunsLeft--;
+ if (this->NumberOfRunsLeft == 0) {
+ return false;
+ }
+ // if number of runs left is not 0, and we are running until
+ // we find a failed test, then return true so the test can be
+ // restarted
+ if (this->RunUntilFail &&
+ this->TestResult.Status == cmCTestTestHandler::COMPLETED) {
+ this->RunAgain = true;
+ return true;
+ }
+ return false;
+}
void cmCTestRunTest::ComputeWeightedCost()
{
double prev = static_cast<double>(this->TestProperties->PreviousRuns);
double avgcost = static_cast<double>(this->TestProperties->Cost);
double current = this->TestResult.ExecutionTime;
- if(this->TestResult.Status == cmCTestTestHandler::COMPLETED)
- {
+ if (this->TestResult.Status == cmCTestTestHandler::COMPLETED) {
this->TestProperties->Cost =
static_cast<float>(((prev * avgcost) + current) / (prev + 1.0));
this->TestProperties->PreviousRuns++;
- }
+ }
}
-//----------------------------------------------------------------------
void cmCTestRunTest::MemCheckPostProcess()
{
- if(!this->TestHandler->MemCheck)
- {
+ if (!this->TestHandler->MemCheck) {
return;
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": process test output now: "
- << this->TestProperties->Name.c_str() << " "
- << this->TestResult.Name.c_str() << std::endl);
- cmCTestMemCheckHandler * handler = static_cast<cmCTestMemCheckHandler*>
- (this->TestHandler);
- switch ( handler->MemoryTesterStyle )
- {
- case cmCTestMemCheckHandler::VALGRIND:
- handler->PostProcessValgrindTest(this->TestResult, this->Index);
- break;
- case cmCTestMemCheckHandler::PURIFY:
- handler->PostProcessPurifyTest(this->TestResult, this->Index);
- break;
- case cmCTestMemCheckHandler::BOUNDS_CHECKER:
- handler->PostProcessBoundsCheckerTest(this->TestResult, this->Index);
- break;
- default:
- break;
- }
+ }
+ 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);
}
-//----------------------------------------------------------------------
// Starts the execution of a test. Returns once it has started
bool cmCTestRunTest::StartTest(size_t total)
{
- 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);
+ 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);
+ this->ProcessOutput.clear();
+
+ // 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->TestResult.Output = "Disabled";
+ this->TestResult.FullCommandLine = "";
+ return false;
+ }
+
this->ComputeArguments();
std::vector<std::string>& args = this->TestProperties->Args;
this->TestResult.Properties = this->TestProperties;
@@ -421,167 +450,175 @@ bool cmCTestRunTest::StartTest(size_t total)
this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
this->TestResult.TestCount = this->TestProperties->Index;
this->TestResult.Name = this->TestProperties->Name;
- this->TestResult.Path = this->TestProperties->Directory.c_str();
+ this->TestResult.Path = this->TestProperties->Directory;
- if(args.size() >= 2 && args[1] == "NOT_AVAILABLE")
- {
+ if (!this->FailedDependencies.empty()) {
+ this->TestProcess = new cmProcess;
+ std::string msg = "Failed test dependencies:";
+ for (std::set<std::string>::const_iterator it =
+ this->FailedDependencies.begin();
+ it != this->FailedDependencies.end(); ++it) {
+ msg += " " + *it;
+ }
+ *this->TestHandler->LogFile << msg << std::endl;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, msg << std::endl);
+ this->TestResult.Output = msg;
+ this->TestResult.FullCommandLine = "";
+ this->TestResult.CompletionStatus = "Fixture dependency failed";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ return false;
+ }
+
+ if (args.size() >= 2 && args[1] == "NOT_AVAILABLE") {
this->TestProcess = new cmProcess;
std::string msg;
- if(this->CTest->GetConfigType().empty())
- {
+ if (this->CTest->GetConfigType().empty()) {
msg = "Test not available without configuration.";
msg += " (Missing \"-C <config>\"?)";
- }
- else
- {
+ } else {
msg = "Test not available in configuration \"";
msg += this->CTest->GetConfigType();
msg += "\".";
- }
+ }
*this->TestHandler->LogFile << msg << std::endl;
cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl);
this->TestResult.Output = msg;
this->TestResult.FullCommandLine = "";
- this->TestResult.CompletionStatus = "Not Run";
+ 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)
- {
+ 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()))
- {
- //Required file was not found
+ if (!cmSystemTools::FileExists(file.c_str())) {
+ // Required file was not found
this->TestProcess = new cmProcess;
- *this->TestHandler->LogFile << "Unable to find required file: "
- << file.c_str() << std::endl;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to find required file: "
- << file.c_str() << std::endl);
+ *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.CompletionStatus = "Not Run";
+ 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 == "") {
// if the command was not found create a TestResult object
// that has that information
this->TestProcess = new cmProcess;
- *this->TestHandler->LogFile << "Unable to find executable: "
- << args[1].c_str() << std::endl;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to find executable: "
- << args[1].c_str() << std::endl);
+ *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.CompletionStatus = "Not Run";
+ this->TestResult.CompletionStatus = "Unable to find executable";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
- }
+ }
this->StartTime = this->CTest->CurrentTime();
double timeout = this->ResolveTimeout();
- if(this->StopTimePassed)
- {
+ if (this->StopTimePassed) {
return false;
- }
+ }
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
&this->TestProperties->Environment);
}
-//----------------------------------------------------------------------
void cmCTestRunTest::ComputeArguments()
{
+ this->Arguments.clear(); // reset becaue this might be a rerun
std::vector<std::string>::const_iterator j =
this->TestProperties->Args.begin();
++j; // skip test name
-
// find the test executable
- if(this->TestHandler->MemCheck)
- {
- cmCTestMemCheckHandler * handler = static_cast<cmCTestMemCheckHandler*>
- (this->TestHandler);
- this->ActualCommand = handler->MemoryTester.c_str();
+ if (this->TestHandler->MemCheck) {
+ cmCTestMemCheckHandler* handler =
+ static_cast<cmCTestMemCheckHandler*>(this->TestHandler);
+ this->ActualCommand = handler->MemoryTester;
this->TestProperties->Args[1] = this->TestHandler->FindTheExecutable(
this->TestProperties->Args[1].c_str());
- }
- else
- {
- this->ActualCommand =
- this->TestHandler->FindTheExecutable(
+ } else {
+ this->ActualCommand = this->TestHandler->FindTheExecutable(
this->TestProperties->Args[1].c_str());
- ++j; //skip the executable (it will be actualCommand)
- }
- std::string testCommand
- = cmSystemTools::ConvertToOutputPath(this->ActualCommand.c_str());
+ ++j; // skip the executable (it will be actualCommand)
+ }
+ std::string testCommand =
+ cmSystemTools::ConvertToOutputPath(this->ActualCommand.c_str());
- //Prepends memcheck args to our command string
+ // 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::vector<std::string>::iterator i = this->Arguments.begin();
+ i != this->Arguments.end(); ++i) {
testCommand += " \"";
testCommand += *i;
testCommand += "\"";
- }
+ }
- for(;j != this->TestProperties->Args.end(); ++j)
- {
+ for (; j != this->TestProperties->Args.end(); ++j) {
testCommand += " \"";
testCommand += *j;
testCommand += "\"";
this->Arguments.push_back(*j);
- }
+ }
this->TestResult.FullCommandLine = testCommand;
+ // Print the test command in verbose mode
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
- << this->Index << ": "
- << (this->TestHandler->MemCheck?"MemCheck":"Test")
- << " command: " << testCommand
- << 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);
+ }
+ 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);
+ }
}
-//----------------------------------------------------------------------
void cmCTestRunTest::DartProcessing()
{
if (!this->ProcessOutput.empty() &&
- this->ProcessOutput.find("<DartMeasurement") != this->ProcessOutput.npos)
- {
- if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str()))
- {
- std::string dartString = this->TestHandler->DartStuff.match(1);
+ this->ProcessOutput.find("<DartMeasurement") != std::string::npos) {
+ if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str())) {
+ 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.c_str())) {
// replace the exact match for the string
- cmSystemTools::ReplaceString(this->ProcessOutput,
- this->TestHandler->DartStuff1.match(1).c_str(), "");
- }
- this->TestResult.RegressionImages
- = this->TestHandler->GenerateRegressionImages(dartString);
+ cmSystemTools::ReplaceString(
+ this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(),
+ "");
}
}
+ }
}
-//----------------------------------------------------------------------
double cmCTestRunTest::ResolveTimeout()
{
double timeout = this->TestProperties->Timeout;
- if(this->CTest->GetStopTime() == "")
- {
+ if (this->CTest->GetStopTime() == "") {
return timeout;
- }
+ }
struct tm* lctime;
- time_t current_time = time(0);
+ time_t current_time = time(CM_NULLPTR);
lctime = gmtime(&current_time);
int gm_hour = lctime->tm_hour;
time_t gm_time = mktime(lctime);
@@ -589,87 +626,77 @@ double cmCTestRunTest::ResolveTimeout()
int local_hour = lctime->tm_hour;
int tzone_offset = local_hour - gm_hour;
- if(gm_time > current_time && gm_hour < local_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)
- {
+ } 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);
+ 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)
- {
+ 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);
+ }
+
+ // 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)
- {
+ 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);
+ "Stopping all tests."
+ << std::endl);
this->StopTimePassed = true;
return 0;
- }
- return timeout == 0 ? stop_timeout :
- (timeout < stop_timeout ? timeout : stop_timeout);
+ }
+ return timeout == 0 ? stop_timeout
+ : (timeout < stop_timeout ? timeout : stop_timeout);
}
-//----------------------------------------------------------------------
bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment)
+ std::vector<std::string>* environment)
{
this->TestProcess = new cmProcess;
this->TestProcess->SetId(this->Index);
this->TestProcess->SetWorkingDirectory(
- this->TestProperties->Directory.c_str());
+ this->TestProperties->Directory.c_str());
this->TestProcess->SetCommand(this->ActualCommand.c_str());
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)
- {
+ if (this->CTest->GetTimeOut() > 0 && this->CTest->GetTimeOut() < timeout) {
timeout = this->CTest->GetTimeOut();
- }
- if (testTimeOut > 0
- && testTimeOut < this->CTest->GetRemainingTimeAllowed())
- {
+ }
+ if (testTimeOut > 0 &&
+ testTimeOut < this->CTest->GetRemainingTimeAllowed()) {
timeout = testTimeOut;
- }
+ }
// always have at least 1 second if we got to here
- if (timeout <= 0)
- {
+ if (timeout <= 0) {
timeout = 1;
- }
+ }
// handle timeout explicitly set to 0
- if (testTimeOut == 0 && explicitTimeout)
- {
+ if (testTimeOut == 0 && explicitTimeout) {
timeout = 0;
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": "
- << "Test timeout computed to be: " << timeout << "\n");
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
+ << ": "
+ << "Test timeout computed to be: " << timeout << "\n",
+ this->TestHandler->GetQuiet());
this->TestProcess->SetTimeout(timeout);
@@ -677,67 +704,82 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
cmSystemTools::SaveRestoreEnvironment sre;
#endif
- if (environment && environment->size()>0)
- {
+ if (environment && !environment->empty()) {
cmSystemTools::AppendEnv(*environment);
- }
+ }
return this->TestProcess->StartProcess();
}
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << completed << "/");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << total << " ");
-
- if ( this->TestHandler->MemCheck )
- {
+ // if this is the last or only run of this test
+ // 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 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))
+ << " "
+ << " ");
+ }
+
+ if (this->TestHandler->MemCheck) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, "MemCheck");
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Test");
- }
+ }
- cmOStringStream indexStr;
+ std::ostringstream indexStr;
indexStr << " #" << this->Index << ":";
cmCTestLog(this->CTest, HANDLER_OUTPUT,
std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
- << indexStr.str().c_str());
+ << indexStr.str());
cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
std::string outname = this->TestProperties->Name + " ";
outname.resize(maxTestNameWidth + 4, '.');
*this->TestHandler->LogFile << this->TestProperties->Index << "/"
- << this->TestHandler->TotalNumberOfTests << " Testing: "
- << this->TestProperties->Name << std::endl;
+ << this->TestHandler->TotalNumberOfTests
+ << " Testing: " << this->TestProperties->Name
+ << std::endl;
*this->TestHandler->LogFile << this->TestProperties->Index << "/"
- << this->TestHandler->TotalNumberOfTests
- << " Test: " << this->TestProperties->Name.c_str() << std::endl;
+ << this->TestHandler->TotalNumberOfTests
+ << " Test: " << this->TestProperties->Name
+ << 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->c_str() << "\"";
- }
- *this->TestHandler->LogFile << std::endl
+ i != this->Arguments.end(); ++i) {
+ *this->TestHandler->LogFile << " \"" << *i << "\"";
+ }
+ *this->TestHandler->LogFile
+ << std::endl
<< "Directory: " << this->TestProperties->Directory << std::endl
- << "\"" << this->TestProperties->Name.c_str() << "\" start time: "
- << this->StartTime << std::endl;
+ << "\"" << this->TestProperties->Name
+ << "\" start time: " << this->StartTime << std::endl;
*this->TestHandler->LogFile
<< "Output:" << std::endl
<< "----------------------------------------------------------"
<< std::endl;
- *this->TestHandler->LogFile
- << this->ProcessOutput.c_str() << "<end of output>" << std::endl;
+ *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.c_str() << " ... ");
+ cmCTestLog(this->CTest, DEBUG, "Testing " << this->TestProperties->Name
+ << " ... ");
}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 476f3e126..d3bb2296f 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -1,20 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestRunTest_h
#define cmCTestRunTest_h
-#include <cmStandardIncludes.h>
-#include <cmCTestTestHandler.h>
-#include <cmProcess.h>
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <set>
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+#include "cmCTestTestHandler.h"
+
+class cmCTest;
+class cmProcess;
/** \class cmRunTest
* \brief represents a single test to be run
@@ -27,22 +26,35 @@ public:
cmCTestRunTest(cmCTestTestHandler* handler);
~cmCTestRunTest();
- void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties * prop)
- { this->TestProperties = prop; }
+ void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; }
+ void SetRunUntilFailOn() { this->RunUntilFail = true; }
+ void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties* prop)
+ {
+ this->TestProperties = prop;
+ }
- cmCTestTestHandler::cmCTestTestProperties * GetTestProperties()
- { return this->TestProperties; }
+ cmCTestTestHandler::cmCTestTestProperties* GetTestProperties()
+ {
+ return this->TestProperties;
+ }
void SetIndex(int i) { this->Index = i; }
int GetIndex() { return this->Index; }
+ void AddFailedDependency(const std::string& failedTest)
+ {
+ this->FailedDependencies.insert(failedTest);
+ }
+
std::string GetProcessOutput() { return this->ProcessOutput; }
bool IsStopTimePassed() { return this->StopTimePassed; }
cmCTestTestHandler::cmCTestTestResult GetTestResults()
- { return this->TestResult; }
+ {
+ return this->TestResult;
+ }
// Read and store output. Returns true if it must be called again.
bool CheckOutput();
@@ -50,15 +62,19 @@ public:
// Compresses the output, writing to CompressedOutput
void CompressOutput();
- //launch the test process, return whether it started correctly
+ // launch the test process, return whether it started correctly
bool StartTest(size_t total);
- //capture and report the test results
+ // 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
+ // Called by ctest -N to log the command string
void ComputeArguments();
void ComputeWeightedCost();
+
+ bool StartAgain();
+
private:
+ bool NeedsToRerun();
void DartProcessing();
void ExeNotFound(std::string exe);
// Figures out a final timeout which is min(STOP_TIME, NOW+TIMEOUT)
@@ -66,18 +82,18 @@ private:
bool ForkProcess(double testTimeOut, bool explicitTimeout,
std::vector<std::string>* environment);
void WriteLogOutputTop(size_t completed, size_t total);
- //Run post processing of the process output for MemCheck
+ // Run post processing of the process output for MemCheck
void MemCheckPostProcess();
- cmCTestTestHandler::cmCTestTestProperties * TestProperties;
- //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;
+ cmCTestTestHandler::cmCTestTestProperties* TestProperties;
+ // 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;
@@ -85,28 +101,30 @@ private:
std::string ProcessOutput;
std::string CompressedOutput;
double CompressionRatio;
- //The test results
+ // The test results
cmCTestTestHandler::cmCTestTestResult TestResult;
int Index;
+ std::set<std::string> FailedDependencies;
std::string StartTime;
std::string ActualCommand;
std::vector<std::string> Arguments;
bool StopTimePassed;
+ bool RunUntilFail;
+ int NumberOfRunsLeft;
+ bool RunAgain;
+ size_t TotalNumberOfTests;
};
inline int getNumWidth(size_t n)
{
int numWidth = 1;
- if(n >= 10)
- {
+ if (n >= 10) {
numWidth = 2;
- }
- if(n >= 100)
- {
+ }
+ if (n >= 100) {
numWidth = 3;
- }
+ }
return numWidth;
}
#endif
-
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 2668c8eef..f60f78c21 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -1,41 +1,35 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSVN.h"
#include "cmCTest.h"
+#include "cmCTestVC.h"
+#include "cmProcessTools.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <map>
+#include <ostream>
+#include <stdlib.h>
+#include <string.h>
-struct cmCTestSVN::Revision: public cmCTestVC::Revision
+struct cmCTestSVN::Revision : public cmCTestVC::Revision
{
cmCTestSVN::SVNInfo* SVNInfo;
};
-//----------------------------------------------------------------------------
-cmCTestSVN::cmCTestSVN(cmCTest* ct, std::ostream& log):
- cmCTestGlobalVC(ct, log)
+cmCTestSVN::cmCTestSVN(cmCTest* ct, std::ostream& log)
+ : cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
}
-//----------------------------------------------------------------------------
cmCTestSVN::~cmCTestSVN()
{
}
-//----------------------------------------------------------------------------
void cmCTestSVN::CleanupImpl()
{
std::vector<const char*> svn_cleanup;
@@ -45,64 +39,51 @@ void cmCTestSVN::CleanupImpl()
this->RunSVNCommand(svn_cleanup, &out, &err);
}
-//----------------------------------------------------------------------------
-class cmCTestSVN::InfoParser: public cmCTestVC::LineParser
+class cmCTestSVN::InfoParser : public cmCTestVC::LineParser
{
public:
- InfoParser(cmCTestSVN* svn,
- const char* prefix,
- std::string& rev,
- SVNInfo& svninfo):
- Rev(rev), SVNRepo(svninfo)
- {
+ InfoParser(cmCTestSVN* svn, const char* prefix, std::string& rev,
+ SVNInfo& svninfo)
+ : Rev(rev)
+ , SVNRepo(svninfo)
+ {
this->SetLog(&svn->Log, prefix);
this->RegexRev.compile("^Revision: ([0-9]+)");
this->RegexURL.compile("^URL: +([^ ]+) *$");
this->RegexRoot.compile("^Repository Root: +([^ ]+) *$");
- }
+ }
+
private:
std::string& Rev;
cmCTestSVN::SVNInfo& SVNRepo;
cmsys::RegularExpression RegexRev;
cmsys::RegularExpression RegexURL;
cmsys::RegularExpression RegexRoot;
- virtual bool ProcessLine()
- {
- if(this->RegexRev.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexRev.find(this->Line)) {
this->Rev = this->RegexRev.match(1);
- }
- else if(this->RegexURL.find(this->Line))
- {
+ } else if (this->RegexURL.find(this->Line)) {
this->SVNRepo.URL = this->RegexURL.match(1);
- }
- else if(this->RegexRoot.find(this->Line))
- {
+ } else if (this->RegexRoot.find(this->Line)) {
this->SVNRepo.Root = this->RegexRoot.match(1);
- }
- return true;
}
+ return true;
+ }
};
-//----------------------------------------------------------------------------
static bool cmCTestSVNPathStarts(std::string const& p1, std::string const& p2)
{
// Does path p1 start with path p2?
- if(p1.size() == p2.size())
- {
+ if (p1.size() == p2.size()) {
return p1 == p2;
- }
- else if(p1.size() > p2.size() && p1[p2.size()] == '/')
- {
+ }
+ if (p1.size() > p2.size() && p1[p2.size()] == '/') {
return strncmp(p1.c_str(), p2.c_str(), p2.size()) == 0;
- }
- else
- {
- return false;
- }
+ }
+ return false;
}
-//----------------------------------------------------------------------------
std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo)
{
// Run "svn info" to get the repository info from the work tree.
@@ -116,51 +97,46 @@ std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo)
return rev;
}
-//----------------------------------------------------------------------------
-void cmCTestSVN::NoteOldRevision()
+bool cmCTestSVN::NoteOldRevision()
{
- // Info for root repository
- this->Repositories.push_back( SVNInfo("") );
- this->RootInfo = &(this->Repositories.back());
- // Info for the external repositories
- this->LoadExternals();
-
- // Get info for all the repositories
- std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
- std::list<SVNInfo>::iterator itend = this->Repositories.end();
- for( ; itbeg != itend ; itbeg++)
- {
+ if (!this->LoadRepositories()) {
+ 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;
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
this->OldRevision = this->RootInfo->OldRevision;
this->PriorRev.Rev = this->OldRevision;
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestSVN::NoteNewRevision()
+bool cmCTestSVN::NoteNewRevision()
{
- // Get info for the external repositories
- std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
- std::list<SVNInfo>::iterator itend = this->Repositories.end();
- for( ; itbeg != itend ; itbeg++)
- {
+ if (!this->LoadRepositories()) {
+ 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;
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
@@ -170,23 +146,21 @@ void cmCTestSVN::NoteNewRevision()
// Compute the base path the working tree has checked out under
// the repository root.
- if(!svninfo.Root.empty()
- && cmCTestSVNPathStarts(svninfo.URL, svninfo.Root))
- {
- svninfo.Base = cmCTest::DecodeURL(
- svninfo.URL.substr(svninfo.Root.size()));
+ if (!svninfo.Root.empty() &&
+ cmCTestSVNPathStarts(svninfo.URL, svninfo.Root)) {
+ svninfo.Base =
+ cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size()));
svninfo.Base += "/";
- }
+ }
this->Log << "Repository '" << svninfo.LocalPath
<< "' Base = " << svninfo.Base << "\n";
-
}
// Set the global new revision to the one of the root
this->NewRevision = this->RootInfo->NewRevision;
+ return true;
}
-//----------------------------------------------------------------------------
void cmCTestSVN::GuessBase(SVNInfo& svninfo,
std::vector<Change> const& changes)
{
@@ -195,21 +169,18 @@ void cmCTestSVN::GuessBase(SVNInfo& svninfo,
// changes under it.
// Consider each possible URL suffix from longest to shortest.
- for(std::string::size_type slash = svninfo.URL.find('/');
- svninfo.Base.empty() && slash != std::string::npos;
- slash = svninfo.URL.find('/', slash+1))
- {
+ for (std::string::size_type slash = svninfo.URL.find('/');
+ svninfo.Base.empty() && slash != std::string::npos;
+ 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();
- svninfo.Base.empty() && ci != changes.end(); ++ci)
- {
- if(cmCTestSVNPathStarts(ci->Path, base))
- {
+ for (std::vector<Change>::const_iterator ci = changes.begin();
+ svninfo.Base.empty() && ci != changes.end(); ++ci) {
+ if (cmCTestSVNPathStarts(ci->Path, base)) {
svninfo.Base = base;
- }
}
}
+ }
// We always append a slash so that we know paths beginning in the
// base lie under its path. If no base was found then the working
@@ -220,89 +191,88 @@ void cmCTestSVN::GuessBase(SVNInfo& svninfo,
this->Log << "Guessed Base = " << svninfo.Base << "\n";
}
-//----------------------------------------------------------------------------
-class cmCTestSVN::UpdateParser: public cmCTestVC::LineParser
+class cmCTestSVN::UpdateParser : public cmCTestVC::LineParser
{
public:
- UpdateParser(cmCTestSVN* svn, const char* prefix): SVN(svn)
- {
+ UpdateParser(cmCTestSVN* svn, const char* prefix)
+ : SVN(svn)
+ {
this->SetLog(&svn->Log, prefix);
this->RegexUpdate.compile("^([ADUCGE ])([ADUCGE ])[B ] +(.+)$");
- }
+ }
+
private:
cmCTestSVN* SVN;
cmsys::RegularExpression RegexUpdate;
- bool ProcessLine()
- {
- if(this->RegexUpdate.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexUpdate.find(this->Line)) {
this->DoPath(this->RegexUpdate.match(1)[0],
- this->RegexUpdate.match(2)[0],
- this->RegexUpdate.match(3));
- }
- return true;
+ this->RegexUpdate.match(2)[0], this->RegexUpdate.match(3));
}
+ return true;
+ }
void DoPath(char path_status, char prop_status, std::string const& path)
- {
- char status = (path_status != ' ')? path_status : prop_status;
+ {
+ char status = (path_status != ' ') ? path_status : prop_status;
std::string dir = cmSystemTools::GetFilenamePath(path);
std::string name = cmSystemTools::GetFilenameName(path);
// See "svn help update".
- switch(status)
- {
+ switch (status) {
case 'G':
this->SVN->Dirs[dir][name].Status = PathModified;
break;
case 'C':
this->SVN->Dirs[dir][name].Status = PathConflicting;
break;
- case 'A': case 'D': case 'U':
+ case 'A':
+ case 'D':
+ case 'U':
this->SVN->Dirs[dir][name].Status = PathUpdated;
break;
case 'E': // TODO?
- case '?': case ' ': default:
+ case '?':
+ case ' ':
+ default:
break;
- }
}
+ }
};
-//----------------------------------------------------------------------------
bool cmCTestSVN::UpdateImpl()
{
// Get user-specified update options.
std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
- if(opts.empty())
- {
+ if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("SVNUpdateOptions");
- }
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(opts.c_str());
+ }
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
// Specify the start time for nightly testing.
- if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
- {
+ if (this->CTest->GetTestModel() == cmCTest::NIGHTLY) {
args.push_back("-r{" + this->GetNightlyTime() + " +0000}");
- }
+ }
std::vector<char const*> svn_update;
svn_update.push_back("update");
- for(std::vector<cmStdString>::const_iterator ai = args.begin();
- ai != args.end(); ++ai)
- {
+ for (std::vector<std::string>::const_iterator ai = args.begin();
+ ai != args.end(); ++ai) {
svn_update.push_back(ai->c_str());
- }
+ }
UpdateParser out(this, "up-out> ");
OutputLogger err(this->Log, "up-err> ");
return this->RunSVNCommand(svn_update, &out, &err);
}
-//----------------------------------------------------------------------------
bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
- OutputParser* out, OutputParser* err)
+ OutputParser* out, OutputParser* err)
{
- if(parameters.empty()) return false;
+ if (parameters.empty()) {
+ return false;
+ }
std::vector<char const*> args;
args.push_back(this->CommandLineTool.c_str());
@@ -311,38 +281,35 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
args.push_back("--non-interactive");
- std::string userOptions =
- this->CTest->GetCTestConfiguration("SVNOptions");
+ std::string userOptions = this->CTest->GetCTestConfiguration("SVNOptions");
- std::vector<cmStdString> parsedUserOptions =
+ std::vector<std::string> parsedUserOptions =
cmSystemTools::ParseArguments(userOptions.c_str());
- for(std::vector<cmStdString>::iterator i = parsedUserOptions.begin();
- i != parsedUserOptions.end(); ++i)
- {
+ for (std::vector<std::string>::iterator i = parsedUserOptions.begin();
+ i != parsedUserOptions.end(); ++i) {
args.push_back(i->c_str());
- }
+ }
- args.push_back(0);
+ args.push_back(CM_NULLPTR);
- if(strcmp(parameters[0], "update") == 0)
- {
+ if (strcmp(parameters[0], "update") == 0) {
return RunUpdateCommand(&args[0], out, err);
- }
- else
- {
- return RunChild(&args[0], out, err);
- }
+ }
+ 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):
- OutputLogger(svn->Log, prefix), SVN(svn), SVNRepo(svninfo)
- { this->InitializeParser(); }
- ~LogParser() { this->CleanupParser(); }
+ LogParser(cmCTestSVN* svn, const char* prefix, SVNInfo& svninfo)
+ : OutputLogger(svn->Log, prefix)
+ , SVN(svn)
+ , SVNRepo(svninfo)
+ {
+ this->InitializeParser();
+ }
+ ~LogParser() CM_OVERRIDE { this->CleanupParser(); }
private:
cmCTestSVN* SVN;
cmCTestSVN::SVNInfo& SVNRepo;
@@ -354,101 +321,83 @@ private:
Change CurChange;
std::vector<char> CData;
- virtual bool ProcessChunk(const char* data, int length)
- {
+ bool ProcessChunk(const char* data, int length) CM_OVERRIDE
+ {
this->OutputLogger::ProcessChunk(data, length);
this->ParseChunk(data, length);
return true;
- }
+ }
- virtual void StartElement(const char* name, const char** atts)
- {
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
this->CData.clear();
- if(strcmp(name, "logentry") == 0)
- {
+ if (name == "logentry") {
this->Rev = Revision();
this->Rev.SVNInfo = &SVNRepo;
- if(const char* rev = this->FindAttribute(atts, "revision"))
- {
+ if (const char* rev = this->FindAttribute(atts, "revision")) {
this->Rev.Rev = rev;
- }
- this->Changes.clear();
}
- else if(strcmp(name, "path") == 0)
- {
+ this->Changes.clear();
+ } else if (name == "path") {
this->CurChange = Change();
- if(const char* action = this->FindAttribute(atts, "action"))
- {
+ if (const char* action = this->FindAttribute(atts, "action")) {
this->CurChange.Action = action[0];
- }
}
}
+ }
- virtual void CharacterDataHandler(const char* data, int length)
- {
- this->CData.insert(this->CData.end(), data, data+length);
- }
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ this->CData.insert(this->CData.end(), data, data + length);
+ }
- virtual void EndElement(const char* name)
- {
- if(strcmp(name, "logentry") == 0)
- {
+ void EndElement(const std::string& name) CM_OVERRIDE
+ {
+ if (name == "logentry") {
this->SVN->DoRevisionSVN(this->Rev, this->Changes);
- }
- else if(strcmp(name, "path") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "path") {
std::string orig_path(&this->CData[0], this->CData.size());
- std::string new_path = SVNRepo.BuildLocalPath( orig_path );
+ std::string new_path = SVNRepo.BuildLocalPath(orig_path);
this->CurChange.Path.assign(new_path);
this->Changes.push_back(this->CurChange);
- }
- else if(strcmp(name, "author") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "author") {
this->Rev.Author.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "date") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "date") {
this->Rev.Date.assign(&this->CData[0], this->CData.size());
- }
- else if(strcmp(name, "msg") == 0 && !this->CData.empty())
- {
+ } else if (!this->CData.empty() && name == "msg") {
this->Rev.Log.assign(&this->CData[0], this->CData.size());
- }
- this->CData.clear();
}
+ this->CData.clear();
+ }
- virtual void ReportError(int, int, const char* msg)
- {
+ void ReportError(int /*line*/, int /*column*/, const char* msg) CM_OVERRIDE
+ {
this->SVN->Log << "Error parsing svn log xml: " << msg << "\n";
- }
+ }
};
-//----------------------------------------------------------------------------
-void cmCTestSVN::LoadRevisions()
+bool cmCTestSVN::LoadRevisions()
{
+ bool result = true;
// Get revisions for all the external repositories
- std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
- std::list<SVNInfo>::iterator itend = this->Repositories.end();
- for( ; itbeg != itend ; itbeg++)
- {
+ std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
+ std::vector<SVNInfo>::iterator itend = this->Repositories.end();
+ for (; itbeg != itend; itbeg++) {
SVNInfo& svninfo = *itbeg;
- LoadRevisions(svninfo);
- }
+ result = this->LoadRevisions(svninfo) && result;
+ }
+ return result;
}
-//----------------------------------------------------------------------------
-void cmCTestSVN::LoadRevisions(SVNInfo &svninfo)
+bool cmCTestSVN::LoadRevisions(SVNInfo& svninfo)
{
// We are interested in every revision included in the update.
std::string revs;
- if(atoi(svninfo.OldRevision.c_str()) < atoi(svninfo.NewRevision.c_str()))
- {
+ if (atoi(svninfo.OldRevision.c_str()) < atoi(svninfo.NewRevision.c_str())) {
revs = "-r" + svninfo.OldRevision + ":" + svninfo.NewRevision;
- }
- else
- {
+ } else {
revs = "-r" + svninfo.NewRevision;
- }
+ }
// Run "svn log" to get all global revisions of interest.
std::vector<const char*> svn_log;
@@ -459,72 +408,75 @@ void cmCTestSVN::LoadRevisions(SVNInfo &svninfo)
svn_log.push_back(svninfo.LocalPath.c_str());
LogParser out(this, "log-out> ", svninfo);
OutputLogger err(this->Log, "log-err> ");
- this->RunSVNCommand(svn_log, &out, &err);
+ return this->RunSVNCommand(svn_log, &out, &err);
}
-//----------------------------------------------------------------------------
void cmCTestSVN::DoRevisionSVN(Revision const& revision,
std::vector<Change> const& changes)
{
// Guess the base checkout path from the changes if necessary.
- if(this->RootInfo->Base.empty() && !changes.empty())
- {
+ if (this->RootInfo->Base.empty() && !changes.empty()) {
this->GuessBase(*this->RootInfo, changes);
- }
+ }
// Ignore changes in the old revision for external repositories
- if(revision.Rev == revision.SVNInfo->OldRevision
- && revision.SVNInfo->LocalPath != "")
- {
+ if (revision.Rev == revision.SVNInfo->OldRevision &&
+ revision.SVNInfo->LocalPath != "") {
return;
- }
+ }
this->cmCTestGlobalVC::DoRevision(revision, changes);
}
-//----------------------------------------------------------------------------
-class cmCTestSVN::StatusParser: public cmCTestVC::LineParser
+class cmCTestSVN::StatusParser : public cmCTestVC::LineParser
{
public:
- StatusParser(cmCTestSVN* svn, const char* prefix): SVN(svn)
- {
+ StatusParser(cmCTestSVN* svn, const char* prefix)
+ : SVN(svn)
+ {
this->SetLog(&svn->Log, prefix);
this->RegexStatus.compile("^([ACDIMRX?!~ ])([CM ])[ L]... +(.+)$");
- }
+ }
+
private:
cmCTestSVN* SVN;
cmsys::RegularExpression RegexStatus;
- bool ProcessLine()
- {
- if(this->RegexStatus.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexStatus.find(this->Line)) {
this->DoPath(this->RegexStatus.match(1)[0],
- this->RegexStatus.match(2)[0],
- this->RegexStatus.match(3));
- }
- return true;
+ this->RegexStatus.match(2)[0], this->RegexStatus.match(3));
}
+ return true;
+ }
void DoPath(char path_status, char prop_status, std::string const& path)
- {
- char status = (path_status != ' ')? path_status : prop_status;
+ {
+ char status = (path_status != ' ') ? path_status : prop_status;
// See "svn help status".
- switch(status)
- {
- case 'M': case '!': case 'A': case 'D': case 'R':
+ switch (status) {
+ case 'M':
+ case '!':
+ case 'A':
+ case 'D':
+ case 'R':
this->SVN->DoModification(PathModified, path);
break;
- case 'C': case '~':
+ case 'C':
+ case '~':
this->SVN->DoModification(PathConflicting, path);
break;
- case 'X': case 'I': case '?': case ' ': default:
+ case 'X':
+ case 'I':
+ case '?':
+ case ' ':
+ default:
break;
- }
}
+ }
};
-//----------------------------------------------------------------------------
-void cmCTestSVN::LoadModifications()
+bool cmCTestSVN::LoadModifications()
{
// Run "svn status" which reports local modifications.
std::vector<const char*> svn_status;
@@ -532,86 +484,85 @@ void cmCTestSVN::LoadModifications()
StatusParser out(this, "status-out> ");
OutputLogger err(this->Log, "status-err> ");
this->RunSVNCommand(svn_status, &out, &err);
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestSVN::WriteXMLGlobal(std::ostream& xml)
+void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml)
{
this->cmCTestGlobalVC::WriteXMLGlobal(xml);
- xml << "\t<SVNPath>" << this->RootInfo->Base << "</SVNPath>\n";
+ xml.Element("SVNPath", this->RootInfo->Base);
}
-//----------------------------------------------------------------------------
-class cmCTestSVN::ExternalParser: public cmCTestVC::LineParser
+class cmCTestSVN::ExternalParser : public cmCTestVC::LineParser
{
public:
- ExternalParser(cmCTestSVN* svn, const char* prefix): SVN(svn)
- {
+ ExternalParser(cmCTestSVN* svn, const char* prefix)
+ : SVN(svn)
+ {
this->SetLog(&svn->Log, prefix);
this->RegexExternal.compile("^X..... +(.+)$");
- }
+ }
+
private:
cmCTestSVN* SVN;
cmsys::RegularExpression RegexExternal;
- bool ProcessLine()
- {
- if(this->RegexExternal.find(this->Line))
- {
+ bool ProcessLine() CM_OVERRIDE
+ {
+ if (this->RegexExternal.find(this->Line)) {
this->DoPath(this->RegexExternal.match(1));
- }
- return true;
}
+ return true;
+ }
void DoPath(std::string const& path)
- {
+ {
// Get local path relative to the source directory
std::string local_path;
- if(path.size() > this->SVN->SourceDirectory.size() &&
- strncmp(path.c_str(), this->SVN->SourceDirectory.c_str(),
- this->SVN->SourceDirectory.size()) == 0)
- {
+ 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;
- }
- else
- {
+ } else {
local_path = path;
- }
- this->SVN->Repositories.push_back( SVNInfo(local_path.c_str()) );
}
+ this->SVN->Repositories.push_back(SVNInfo(local_path.c_str()));
+ }
};
-//----------------------------------------------------------------------------
-void cmCTestSVN::LoadExternals()
+bool cmCTestSVN::LoadRepositories()
{
+ if (!this->Repositories.empty()) {
+ return true;
+ }
+
+ // Info for root repository
+ this->Repositories.push_back(SVNInfo(""));
+ this->RootInfo = &(this->Repositories.back());
+
// Run "svn status" to get the list of external repositories
std::vector<const char*> svn_status;
svn_status.push_back("status");
ExternalParser out(this, "external-out> ");
OutputLogger err(this->Log, "external-err> ");
- this->RunSVNCommand(svn_status, &out, &err);
+ return this->RunSVNCommand(svn_status, &out, &err);
}
-//----------------------------------------------------------------------------
std::string cmCTestSVN::SVNInfo::BuildLocalPath(std::string const& path) const
{
std::string local_path;
// Add local path prefix if not empty
- if (!this->LocalPath.empty())
- {
+ if (!this->LocalPath.empty()) {
local_path += this->LocalPath;
local_path += "/";
- }
+ }
// Add path with base prefix removed
- if(path.size() > this->Base.size() &&
- strncmp(path.c_str(), this->Base.c_str(), this->Base.size()) == 0)
- {
+ 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());
- }
- else
- {
+ } else {
local_path += path;
}
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index c6548e3fb..46b077835 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -1,45 +1,49 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestSVN_h
#define cmCTestSVN_h
+#include "cmConfigure.h"
+
#include "cmCTestGlobalVC.h"
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmXMLWriter;
+
/** \class cmCTestSVN
* \brief Interaction with subversion command-line tool
*
*/
-class cmCTestSVN: public cmCTestGlobalVC
+class cmCTestSVN : public cmCTestGlobalVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestSVN(cmCTest* ctest, std::ostream& log);
- virtual ~cmCTestSVN();
+ ~cmCTestSVN() CM_OVERRIDE;
private:
// Implement cmCTestVC internal API.
- virtual void CleanupImpl();
- virtual void NoteOldRevision();
- virtual void NoteNewRevision();
- virtual bool UpdateImpl();
+ void CleanupImpl() CM_OVERRIDE;
+ bool NoteOldRevision() CM_OVERRIDE;
+ bool NoteNewRevision() CM_OVERRIDE;
+ bool UpdateImpl() CM_OVERRIDE;
bool RunSVNCommand(std::vector<char const*> const& parameters,
- OutputParser* out, OutputParser* err);
+ OutputParser* out, OutputParser* err);
// Information about an SVN repository (root repository or external)
- struct SVNInfo {
+ struct SVNInfo
+ {
- SVNInfo(const char* path) : LocalPath(path) {}
+ SVNInfo(const char* path)
+ : LocalPath(path)
+ {
+ }
// Remove base from the filename
std::string BuildLocalPath(std::string const& path) const;
@@ -58,38 +62,39 @@ private:
// Old and new repository revisions.
std::string OldRevision;
std::string NewRevision;
-
};
// Extended revision structure to include info about external it refers to.
struct Revision;
+
friend struct Revision;
// Info of all the repositories (root, externals and nested ones).
- std::list<SVNInfo> Repositories;
+ std::vector<SVNInfo> Repositories;
// Pointer to the infos of the root repository.
SVNInfo* RootInfo;
std::string LoadInfo(SVNInfo& svninfo);
- void LoadExternals();
- void LoadModifications();
- void LoadRevisions();
- void LoadRevisions(SVNInfo& svninfo);
+ bool LoadRepositories();
+ bool LoadModifications() CM_OVERRIDE;
+ bool LoadRevisions() CM_OVERRIDE;
+ bool LoadRevisions(SVNInfo& svninfo);
- void GuessBase(SVNInfo &svninfo, std::vector<Change> const& changes);
+ void GuessBase(SVNInfo& svninfo, std::vector<Change> const& changes);
void DoRevisionSVN(Revision const& revision,
std::vector<Change> const& changes);
- void WriteXMLGlobal(std::ostream& xml);
+ void WriteXMLGlobal(cmXMLWriter& xml) CM_OVERRIDE;
+ class ExternalParser;
// Parsing helper classes.
class InfoParser;
class LogParser;
class StatusParser;
class UpdateParser;
- class ExternalParser;
+
friend class InfoParser;
friend class LogParser;
friend class StatusParser;
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 8643cb3f7..1d29dfac2 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -1,44 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestScriptHandler.h"
-#include "cmCTest.h"
-#include "cmake.h"
-#include "cmFunctionBlocker.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-#include "cmGeneratedFileStream.h"
-
-//#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Process.h>
-
-// used for sleep
-#ifdef _WIN32
-#include "windows.h"
-#endif
-
+#include "cmsys/Directory.hxx"
+#include "cmsys/Process.h"
+#include <map>
+#include <sstream>
+#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
-#include <math.h>
-#include <float.h>
-
-// needed for sleep
-#if !defined(_WIN32)
-# include <unistd.h>
-#endif
+#include <string.h>
+#include <utility>
+#include "cmCTest.h"
#include "cmCTestBuildCommand.h"
+#include "cmCTestCommand.h"
#include "cmCTestConfigureCommand.h"
#include "cmCTestCoverageCommand.h"
#include "cmCTestEmptyBinaryDirectoryCommand.h"
@@ -51,6 +26,24 @@
#include "cmCTestTestCommand.h"
#include "cmCTestUpdateCommand.h"
#include "cmCTestUploadCommand.h"
+#include "cmFunctionBlocker.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+class cmExecutionStatus;
+struct cmListFileFunction;
#define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log"
@@ -59,44 +52,40 @@ class cmCTestScriptFunctionBlocker : public cmFunctionBlocker
{
public:
cmCTestScriptFunctionBlocker() {}
- virtual ~cmCTestScriptFunctionBlocker() {}
- virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile &mf,
- cmExecutionStatus &);
- //virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
- //virtual void ScopeEnded(cmMakefile &mf);
+ ~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& , cmMakefile &,
- cmExecutionStatus &)
+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 = 0;
- this->LocalGenerator = 0;
- this->CMake = 0;
- this->GlobalGenerator = 0;
+ this->Makefile = CM_NULLPTR;
+ this->CMake = CM_NULLPTR;
+ this->GlobalGenerator = CM_NULLPTR;
this->ScriptStartTime = 0;
// the *60 is becuase the settings are in minutes but GetTime is seconds
- this->MinimumInterval = 30*60;
+ this->MinimumInterval = 30 * 60;
this->ContinuousDuration = -1;
}
-//----------------------------------------------------------------------
void cmCTestScriptHandler::Initialize()
{
this->Superclass::Initialize();
@@ -118,102 +107,71 @@ void cmCTestScriptHandler::Initialize()
this->CMOutFile = "";
this->ExtraUpdates.clear();
- this->MinimumInterval = 20*60;
+ this->MinimumInterval = 20 * 60;
this->ContinuousDuration = -1;
// what time in seconds did this script start running
this->ScriptStartTime = 0;
- this->Makefile = 0;
- if (this->LocalGenerator)
- {
- delete this->LocalGenerator;
- }
- this->LocalGenerator = 0;
- if (this->GlobalGenerator)
- {
- delete this->GlobalGenerator;
- }
- this->GlobalGenerator = 0;
- if (this->CMake)
- {
- delete this->CMake;
- }
+ delete this->Makefile;
+ this->Makefile = CM_NULLPTR;
+
+ delete this->GlobalGenerator;
+ this->GlobalGenerator = CM_NULLPTR;
+
+ delete this->CMake;
}
-//----------------------------------------------------------------------
cmCTestScriptHandler::~cmCTestScriptHandler()
{
- // local generator owns the makefile
- this->Makefile = 0;
- if (this->LocalGenerator)
- {
- delete this->LocalGenerator;
- }
- this->LocalGenerator = 0;
- if (this->GlobalGenerator)
- {
- delete this->GlobalGenerator;
- }
- this->GlobalGenerator = 0;
- if (this->CMake)
- {
- delete this->CMake;
- }
+ delete this->Makefile;
+ delete this->GlobalGenerator;
+ delete this->CMake;
}
-
-//----------------------------------------------------------------------
// just adds an argument to the vector
-void cmCTestScriptHandler::AddConfigurationScript(const char *script,
+void cmCTestScriptHandler::AddConfigurationScript(const char* script,
bool pscope)
{
this->ConfigurationScripts.push_back(script);
this->ScriptProcessScope.push_back(pscope);
}
-
-//----------------------------------------------------------------------
// the generic entry point for handling scripts, this routine will run all
// the scripts provides a -S arguments
int cmCTestScriptHandler::ProcessHandler()
{
int res = 0;
- for (size_t i=0; i < this->ConfigurationScripts.size(); ++i)
- {
+ for (size_t i = 0; i < this->ConfigurationScripts.size(); ++i) {
// for each script run it
- res += this->RunConfigurationScript
- (cmSystemTools::CollapseFullPath(this->ConfigurationScripts[i].c_str()),
- this->ScriptProcessScope[i]);
- }
- if ( res )
- {
+ res |= this->RunConfigurationScript(
+ cmSystemTools::CollapseFullPath(this->ConfigurationScripts[i]),
+ this->ScriptProcessScope[i]);
+ }
+ if (res) {
return -1;
- }
+ }
return 0;
}
void cmCTestScriptHandler::UpdateElapsedTime()
{
- if (this->LocalGenerator)
- {
+ if (this->Makefile) {
// set the current elapsed time
char timeString[20];
- int itime = static_cast<unsigned int>(cmSystemTools::GetTime()
- - this->ScriptStartTime);
- sprintf(timeString,"%i",itime);
- this->LocalGenerator->GetMakefile()->AddDefinition("CTEST_ELAPSED_TIME",
- timeString);
- }
+ int itime = static_cast<unsigned int>(cmSystemTools::GetTime() -
+ this->ScriptStartTime);
+ sprintf(timeString, "%i", itime);
+ this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString);
+ }
}
-//----------------------------------------------------------------------
-void cmCTestScriptHandler::AddCTestCommand(cmCTestCommand* command)
+void cmCTestScriptHandler::AddCTestCommand(std::string const& name,
+ cmCTestCommand* command)
{
- cmCTestCommand* newCom = command;
- newCom->CTest = this->CTest;
- newCom->CTestScriptHandler = this;
- this->CMake->AddCommand(newCom);
+ command->CTest = this->CTest;
+ command->CTestScriptHandler = this;
+ this->CMake->GetState()->AddBuiltinCommand(name, command);
}
int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
@@ -221,153 +179,134 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
// execute the script passing in the arguments to the script as well as the
// arguments from this invocation of cmake
std::vector<const char*> argv;
- argv.push_back(this->CTest->GetCTestExecutable());
+ argv.push_back(cmSystemTools::GetCTestCommand().c_str());
argv.push_back("-SR");
argv.push_back(total_script_arg.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Executable for CTest is: " <<
- this->CTest->GetCTestExecutable() << "\n");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Executable for CTest is: "
+ << cmSystemTools::GetCTestCommand() << "\n");
// now pass through all the other arguments
- std::vector<cmStdString> &initArgs =
+ std::vector<std::string>& initArgs =
this->CTest->GetInitialCommandLineArguments();
//*** need to make sure this does not have the current script ***
- for(size_t i=1; i < initArgs.size(); ++i)
- {
+ for (size_t i = 1; i < initArgs.size(); ++i) {
argv.push_back(initArgs[i].c_str());
- }
- argv.push_back(0);
+ }
+ argv.push_back(CM_NULLPTR);
// Now create process object
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, &*argv.begin());
- //cmsysProcess_SetWorkingDirectory(cp, dir);
+ // cmsysProcess_SetWorkingDirectory(cp, dir);
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- //cmsysProcess_SetTimeout(cp, timeout);
+ // cmsysProcess_SetTimeout(cp, timeout);
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)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Output: "
- << line << "\n");
- if(pipe == cmsysProcess_Pipe_STDERR)
- {
+ while (pipe != cmsysProcess_Pipe_None) {
+ 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)
- {
+ } 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, 100, out, err);
+ }
// Properly handle output of the build command
- cmsysProcess_WaitForExit(cp, 0);
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
int result = cmsysProcess_GetState(cp);
int retVal = 0;
bool failed = false;
- if(result == cmsysProcess_State_Exited)
- {
+ if (result == cmsysProcess_State_Exited) {
retVal = cmsysProcess_GetExitValue(cp);
- }
- else if(result == cmsysProcess_State_Exception)
- {
+ } else if (result == cmsysProcess_State_Exception) {
retVal = cmsysProcess_GetExitException(cp);
cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
- << cmsysProcess_GetExceptionString(cp) << " " <<
- retVal << std::endl);
+ << cmsysProcess_GetExceptionString(cp) << " " << retVal
+ << std::endl);
failed = true;
- }
- else if(result == cmsysProcess_State_Expired)
- {
+ } else if (result == cmsysProcess_State_Expired) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
- << std::endl);
+ << std::endl);
failed = true;
- }
- else if(result == cmsysProcess_State_Error)
- {
+ } else if (result == cmsysProcess_State_Error) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing ctest: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ << cmsysProcess_GetErrorString(cp) << std::endl);
failed = true;
- }
+ }
cmsysProcess_Delete(cp);
- if(failed)
- {
- cmOStringStream message;
+ if (failed) {
+ 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 (std::vector<const char*>::iterator i = argv.begin(); i != argv.end();
+ ++i) {
+ if (*i) {
+ message << *i << " ";
}
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- message.str() << argv[0] << std::endl);
- return -1;
}
+ 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
- if (this->CMake)
- {
+ if (this->CMake) {
delete this->CMake;
delete this->GlobalGenerator;
- delete this->LocalGenerator;
- }
- this->CMake = new cmake;
+ delete this->Makefile;
+ }
+ this->CMake = new cmake(cmake::RoleScript);
+ this->CMake->SetHomeDirectory("");
+ this->CMake->SetHomeOutputDirectory("");
+ this->CMake->GetCurrentSnapshot().SetDefaultDefinitions();
this->CMake->AddCMakePaths();
- this->GlobalGenerator = new cmGlobalGenerator;
- this->GlobalGenerator->SetCMakeInstance(this->CMake);
-
- this->LocalGenerator = this->GlobalGenerator->CreateLocalGenerator();
- this->Makefile = this->LocalGenerator->GetMakefile();
+ this->GlobalGenerator = new cmGlobalGenerator(this->CMake);
- // Set CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR.
- // Also, some commands need Makefile->GetCurrentDirectory().
+ cmStateSnapshot snapshot = this->CMake->GetCurrentSnapshot();
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- this->Makefile->SetStartDirectory(cwd.c_str());
- this->Makefile->SetStartOutputDirectory(cwd.c_str());
-
- // remove all cmake commands which are not scriptable, since they can't be
- // used in ctest scripts
- this->CMake->RemoveUnscriptableCommands();
-
- // add any ctest specific commands, probably should have common superclass
- // for ctest commands to clean this up. If a couple more commands are
- // created with the same format lets do that - ken
- this->AddCTestCommand(new cmCTestBuildCommand);
- this->AddCTestCommand(new cmCTestConfigureCommand);
- this->AddCTestCommand(new cmCTestCoverageCommand);
- this->AddCTestCommand(new cmCTestEmptyBinaryDirectoryCommand);
- this->AddCTestCommand(new cmCTestMemCheckCommand);
- this->AddCTestCommand(new cmCTestReadCustomFilesCommand);
- this->AddCTestCommand(new cmCTestRunScriptCommand);
- this->AddCTestCommand(new cmCTestSleepCommand);
- this->AddCTestCommand(new cmCTestStartCommand);
- this->AddCTestCommand(new cmCTestSubmitCommand);
- this->AddCTestCommand(new cmCTestTestCommand);
- this->AddCTestCommand(new cmCTestUpdateCommand);
- this->AddCTestCommand(new cmCTestUploadCommand);
-}
-
-void cmCTestScriptHandler::GetCommandDocumentation(
- std::vector<cmDocumentationEntry>& v) const
-{
- this->CMake->GetCommandDocumentation(v);
+ snapshot.GetDirectory().SetCurrentSource(cwd);
+ snapshot.GetDirectory().SetCurrentBinary(cwd);
+ this->Makefile = new cmMakefile(this->GlobalGenerator, snapshot);
+
+ this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest);
+
+ this->AddCTestCommand("ctest_build", new cmCTestBuildCommand);
+ this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand);
+ this->AddCTestCommand("ctest_coverage", new cmCTestCoverageCommand);
+ this->AddCTestCommand("ctest_empty_binary_directory",
+ new cmCTestEmptyBinaryDirectoryCommand);
+ this->AddCTestCommand("ctest_memcheck", new 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);
}
-//----------------------------------------------------------------------
// this sets up some variables for the script to use, creates the required
// cmake instance and generators, and then reads in the script
int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
@@ -380,89 +319,81 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
// passed into the scripts as S_ARG
std::string script = total_script_arg;
std::string script_arg;
- if (total_script_arg.find(",") != std::string::npos)
- {
- script = total_script_arg.substr(0,total_script_arg.find(","));
- script_arg = total_script_arg.substr(total_script_arg.find(",")+1);
- }
+ const std::string::size_type comma_pos = total_script_arg.find(',');
+ if (comma_pos != std::string::npos) {
+ script = total_script_arg.substr(0, comma_pos);
+ script_arg = total_script_arg.substr(comma_pos + 1);
+ }
// make sure the file exists
- if (!cmSystemTools::FileExists(script.c_str()))
- {
+ if (!cmSystemTools::FileExists(script.c_str())) {
cmSystemTools::Error("Cannot find file: ", script.c_str());
return 1;
- }
+ }
// read in the list file to fill the cache
// create a cmake instance to read the configuration script
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).c_str());
+ this->Makefile->AddDefinition(
+ "CTEST_SCRIPT_NAME", cmSystemTools::GetFilenameName(script).c_str());
this->Makefile->AddDefinition("CTEST_EXECUTABLE_NAME",
- this->CTest->GetCTestExecutable());
+ cmSystemTools::GetCTestCommand().c_str());
this->Makefile->AddDefinition("CMAKE_EXECUTABLE_NAME",
- this->CTest->GetCMakeExecutable());
+ cmSystemTools::GetCMakeCommand().c_str());
this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true);
this->UpdateElapsedTime();
// add the script arg if defined
- if (script_arg.size())
- {
+ if (!script_arg.empty()) {
this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg.c_str());
- }
+ }
+
+#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();
+ cmCTestScriptFunctionBlocker* f = new cmCTestScriptFunctionBlocker();
f->CTestScriptHandler = this;
this->Makefile->AddFunctionBlocker(f);
-
/* Execute CTestScriptMode.cmake, which loads CMakeDetermineSystem and
CMakeSystemSpecificInformation, so
that variables like CMAKE_SYSTEM and also the search paths for libraries,
header and executables are set correctly and can be used. Makes new-style
ctest scripting easier. */
std::string systemFile =
- this->Makefile->GetModulesFile("CTestScriptMode.cmake");
- if (!this->Makefile->ReadListFile(0, systemFile.c_str()) ||
- cmSystemTools::GetErrorOccuredFlag())
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read:"
- << systemFile.c_str() << "\n");
+ this->Makefile->GetModulesFile("CTestScriptMode.cmake");
+ if (!this->Makefile->ReadListFile(systemFile.c_str()) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
+ 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 =
+ 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.c_str(), it->second.c_str());
- }
+ it != defs.end(); ++it) {
+ this->Makefile->AddDefinition(it->first, it->second.c_str());
+ }
// finally read in the script
- if (!this->Makefile->ReadListFile(0, script.c_str()) ||
- cmSystemTools::GetErrorOccuredFlag())
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read script: "
- << script.c_str()
- << std::endl);
+ if (!this->Makefile->ReadListFile(script.c_str()) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
// Reset the error flag so that it can run more than
- // one script with an error when you
- // use ctest_run_script
+ // one script with an error when you use ctest_run_script.
cmSystemTools::ResetErrorOccuredFlag();
return 2;
- }
+ }
return 0;
}
-
-//----------------------------------------------------------------------
// extract variabels from the script to set ivars
int cmCTestScriptHandler::ExtractVariables()
{
@@ -470,80 +401,64 @@ int cmCTestScriptHandler::ExtractVariables()
const char* minInterval;
const char* contDuration;
- this->SourceDir
- = this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
- this->BinaryDir
- = this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
+ this->SourceDir =
+ this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
+ this->BinaryDir =
+ this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
// add in translations for src and bin
- cmSystemTools::AddKeepPath(this->SourceDir.c_str());
- cmSystemTools::AddKeepPath(this->BinaryDir.c_str());
-
- this->CTestCmd
- = this->Makefile->GetSafeDefinition("CTEST_COMMAND");
- this->CVSCheckOut
- = this->Makefile->GetSafeDefinition("CTEST_CVS_CHECKOUT");
- this->CTestRoot
- = this->Makefile->GetSafeDefinition("CTEST_DASHBOARD_ROOT");
- this->UpdateCmd
- = this->Makefile->GetSafeDefinition("CTEST_UPDATE_COMMAND");
- if ( this->UpdateCmd.empty() )
- {
- this->UpdateCmd
- = this->Makefile->GetSafeDefinition("CTEST_CVS_COMMAND");
- }
- this->CTestEnv
- = this->Makefile->GetSafeDefinition("CTEST_ENVIRONMENT");
- this->InitialCache
- = this->Makefile->GetSafeDefinition("CTEST_INITIAL_CACHE");
- this->CMakeCmd
- = this->Makefile->GetSafeDefinition("CTEST_CMAKE_COMMAND");
- this->CMOutFile
- = this->Makefile->GetSafeDefinition("CTEST_CMAKE_OUTPUT_FILE_NAME");
-
- this->Backup
- = this->Makefile->IsOn("CTEST_BACKUP_AND_RESTORE");
- this->EmptyBinDir
- = this->Makefile->IsOn("CTEST_START_WITH_EMPTY_BINARY_DIRECTORY");
- this->EmptyBinDirOnce
- = this->Makefile->IsOn("CTEST_START_WITH_EMPTY_BINARY_DIRECTORY_ONCE");
-
- minInterval
- = this->Makefile->GetDefinition("CTEST_CONTINUOUS_MINIMUM_INTERVAL");
- contDuration
- = this->Makefile->GetDefinition("CTEST_CONTINUOUS_DURATION");
+ cmSystemTools::AddKeepPath(this->SourceDir);
+ cmSystemTools::AddKeepPath(this->BinaryDir);
+
+ this->CTestCmd = this->Makefile->GetSafeDefinition("CTEST_COMMAND");
+ this->CVSCheckOut = this->Makefile->GetSafeDefinition("CTEST_CVS_CHECKOUT");
+ this->CTestRoot = this->Makefile->GetSafeDefinition("CTEST_DASHBOARD_ROOT");
+ this->UpdateCmd = this->Makefile->GetSafeDefinition("CTEST_UPDATE_COMMAND");
+ if (this->UpdateCmd.empty()) {
+ this->UpdateCmd = this->Makefile->GetSafeDefinition("CTEST_CVS_COMMAND");
+ }
+ this->CTestEnv = this->Makefile->GetSafeDefinition("CTEST_ENVIRONMENT");
+ this->InitialCache =
+ this->Makefile->GetSafeDefinition("CTEST_INITIAL_CACHE");
+ this->CMakeCmd = this->Makefile->GetSafeDefinition("CTEST_CMAKE_COMMAND");
+ this->CMOutFile =
+ this->Makefile->GetSafeDefinition("CTEST_CMAKE_OUTPUT_FILE_NAME");
+
+ this->Backup = this->Makefile->IsOn("CTEST_BACKUP_AND_RESTORE");
+ this->EmptyBinDir =
+ this->Makefile->IsOn("CTEST_START_WITH_EMPTY_BINARY_DIRECTORY");
+ this->EmptyBinDirOnce =
+ this->Makefile->IsOn("CTEST_START_WITH_EMPTY_BINARY_DIRECTORY_ONCE");
+
+ minInterval =
+ this->Makefile->GetDefinition("CTEST_CONTINUOUS_MINIMUM_INTERVAL");
+ contDuration = this->Makefile->GetDefinition("CTEST_CONTINUOUS_DURATION");
char updateVar[40];
int i;
- for (i = 1; i < 10; ++i)
- {
- sprintf(updateVar,"CTEST_EXTRA_UPDATES_%i",i);
- const char *updateVal = this->Makefile->GetDefinition(updateVar);
- if ( updateVal )
- {
- if ( this->UpdateCmd.empty() )
- {
- cmSystemTools::Error(updateVar,
- " specified without specifying CTEST_CVS_COMMAND.");
+ for (i = 1; i < 10; ++i) {
+ sprintf(updateVar, "CTEST_EXTRA_UPDATES_%i", i);
+ const char* updateVal = this->Makefile->GetDefinition(updateVar);
+ if (updateVal) {
+ if (this->UpdateCmd.empty()) {
+ cmSystemTools::Error(
+ updateVar, " specified without specifying CTEST_CVS_COMMAND.");
return 12;
- }
- this->ExtraUpdates.push_back(updateVal);
}
+ this->ExtraUpdates.push_back(updateVal);
}
+ }
// in order to backup and restore we also must have the cvs root
- if (this->Backup && this->CVSCheckOut.empty())
- {
+ if (this->Backup && this->CVSCheckOut.empty()) {
cmSystemTools::Error(
"Backup was requested without specifying CTEST_CVS_CHECKOUT.");
return 3;
- }
+ }
// make sure the required info is here
- if (this->SourceDir.empty() ||
- this->BinaryDir.empty() ||
- this->CTestCmd.empty())
- {
+ 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 = ";
@@ -554,45 +469,39 @@ int cmCTestScriptHandler::ExtractVariables()
"Some required settings in the configuration file were missing:\n",
msg.c_str());
return 4;
- }
+ }
// if the dashboard root isn't specified then we can compute it from the
// this->SourceDir
- if (this->CTestRoot.empty() )
- {
- this->CTestRoot = cmSystemTools::GetFilenamePath(this->SourceDir).c_str();
- }
+ if (this->CTestRoot.empty()) {
+ this->CTestRoot = cmSystemTools::GetFilenamePath(this->SourceDir);
+ }
// the script may override the minimum continuous interval
- if (minInterval)
- {
+ if (minInterval) {
this->MinimumInterval = 60 * atof(minInterval);
- }
- if (contDuration)
- {
+ }
+ if (contDuration) {
this->ContinuousDuration = 60.0 * atof(contDuration);
- }
-
+ }
this->UpdateElapsedTime();
return 0;
}
-//----------------------------------------------------------------------
void cmCTestScriptHandler::SleepInSeconds(unsigned int secondsToWait)
{
#if defined(_WIN32)
- Sleep(1000*secondsToWait);
+ Sleep(1000 * secondsToWait);
#else
- sleep(secondsToWait);
+ sleep(secondsToWait);
#endif
}
-//----------------------------------------------------------------------
// run a specific script
-int cmCTestScriptHandler::RunConfigurationScript
-(const std::string& total_script_arg, bool pscope)
+int cmCTestScriptHandler::RunConfigurationScript(
+ const std::string& total_script_arg, bool pscope)
{
#ifdef CMAKE_BUILD_WITH_CMAKE
cmSystemTools::SaveRestoreEnvironment sre;
@@ -600,36 +509,29 @@ int cmCTestScriptHandler::RunConfigurationScript
int result;
- this->ScriptStartTime =
- cmSystemTools::GetTime();
+ this->ScriptStartTime = cmSystemTools::GetTime();
// read in the script
- if (pscope)
- {
+ if (pscope) {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Reading Script: " << total_script_arg << std::endl);
+ "Reading Script: " << total_script_arg << std::endl);
result = this->ReadInScript(total_script_arg);
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Executing Script: " << total_script_arg << std::endl);
+ "Executing Script: " << total_script_arg << std::endl);
result = this->ExecuteScript(total_script_arg);
- }
- if (result)
- {
+ }
+ if (result) {
return result;
- }
+ }
// only run the curent script if we should
- if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT"))
- {
+ if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT")) {
return this->RunCurrentScript();
- }
+ }
return result;
}
-//----------------------------------------------------------------------
int cmCTestScriptHandler::RunCurrentScript()
{
int result;
@@ -642,57 +544,47 @@ int cmCTestScriptHandler::RunCurrentScript()
// extract the vars from the cache and store in ivars
result = this->ExtractVariables();
- if (result)
- {
+ if (result) {
return result;
- }
+ }
// set any environment variables
- if (!this->CTestEnv.empty())
- {
+ if (!this->CTestEnv.empty()) {
std::vector<std::string> envArgs;
- cmSystemTools::ExpandListArgument(this->CTestEnv.c_str(),envArgs);
+ cmSystemTools::ExpandListArgument(this->CTestEnv, envArgs);
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?
- if ( this->ContinuousDuration >= 0 )
- {
+ if (this->ContinuousDuration >= 0) {
this->UpdateElapsedTime();
- double ending_time = cmSystemTools::GetTime() + this->ContinuousDuration;
- if (this->EmptyBinDirOnce)
- {
+ double ending_time = cmSystemTools::GetTime() + this->ContinuousDuration;
+ if (this->EmptyBinDirOnce) {
this->EmptyBinDir = true;
- }
- do
- {
+ }
+ do {
double interval = cmSystemTools::GetTime();
result = this->RunConfigurationDashboard();
interval = cmSystemTools::GetTime() - interval;
- if (interval < this->MinimumInterval)
- {
+ if (interval < this->MinimumInterval) {
this->SleepInSeconds(
static_cast<unsigned int>(this->MinimumInterval - interval));
- }
- if (this->EmptyBinDirOnce)
- {
+ }
+ if (this->EmptyBinDirOnce) {
this->EmptyBinDir = false;
- }
}
- while (cmSystemTools::GetTime() < ending_time);
- }
+ } while (cmSystemTools::GetTime() < ending_time);
+ }
// otherwise just run it once
- else
- {
+ else {
result = this->RunConfigurationDashboard();
- }
+ }
return result;
}
-//----------------------------------------------------------------------
int cmCTestScriptHandler::CheckOutSourceDir()
{
std::string command;
@@ -701,26 +593,23 @@ int cmCTestScriptHandler::CheckOutSourceDir()
bool res;
if (!cmSystemTools::FileExists(this->SourceDir.c_str()) &&
- !this->CVSCheckOut.empty())
- {
+ !this->CVSCheckOut.empty()) {
// we must now checkout the src dir
output = "";
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Run cvs: " << this->CVSCheckOut << std::endl);
- res = cmSystemTools::RunSingleCommand(this->CVSCheckOut.c_str(), &output,
- &retVal, this->CTestRoot.c_str(), this->HandlerVerbose,
- 0 /*this->TimeOut*/);
- if (!res || retVal != 0)
- {
+ "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*/);
+ if (!res || retVal != 0) {
cmSystemTools::Error("Unable to perform cvs checkout:\n",
output.c_str());
return 6;
- }
}
+ }
return 0;
}
-//----------------------------------------------------------------------
int cmCTestScriptHandler::BackupDirectories()
{
int retVal;
@@ -732,17 +621,14 @@ int cmCTestScriptHandler::BackupDirectories()
this->BackupBinaryDir += "_CMakeBackup";
// backup the binary and src directories if requested
- if (this->Backup)
- {
+ if (this->Backup) {
// if for some reason those directories exist then first delete them
- if (cmSystemTools::FileExists(this->BackupSourceDir.c_str()))
- {
- cmSystemTools::RemoveADirectory(this->BackupSourceDir.c_str());
- }
- if (cmSystemTools::FileExists(this->BackupBinaryDir.c_str()))
- {
- cmSystemTools::RemoveADirectory(this->BackupBinaryDir.c_str());
- }
+ if (cmSystemTools::FileExists(this->BackupSourceDir.c_str())) {
+ cmSystemTools::RemoveADirectory(this->BackupSourceDir);
+ }
+ if (cmSystemTools::FileExists(this->BackupBinaryDir.c_str())) {
+ cmSystemTools::RemoveADirectory(this->BackupBinaryDir);
+ }
// first rename the src and binary directories
rename(this->SourceDir.c_str(), this->BackupSourceDir.c_str());
@@ -750,18 +636,15 @@ int cmCTestScriptHandler::BackupDirectories()
// we must now checkout the src dir
retVal = this->CheckOutSourceDir();
- if (retVal)
- {
+ if (retVal) {
this->RestoreBackupDirectories();
return retVal;
- }
}
+ }
return 0;
}
-
-//----------------------------------------------------------------------
int cmCTestScriptHandler::PerformExtraUpdates()
{
std::string command;
@@ -771,39 +654,31 @@ int cmCTestScriptHandler::PerformExtraUpdates()
// do an initial cvs update as required
command = this->UpdateCmd;
- std::vector<cmStdString>::iterator it;
- for (it = this->ExtraUpdates.begin();
- it != this->ExtraUpdates.end();
- ++ it )
- {
+ std::vector<std::string>::iterator it;
+ for (it = this->ExtraUpdates.begin(); it != this->ExtraUpdates.end(); ++it) {
std::vector<std::string> cvsArgs;
- cmSystemTools::ExpandListArgument(it->c_str(),cvsArgs);
- if (cvsArgs.size() == 2)
- {
+ cmSystemTools::ExpandListArgument(*it, cvsArgs);
+ if (cvsArgs.size() == 2) {
std::string fullCommand = command;
fullCommand += " update ";
fullCommand += cvsArgs[1];
output = "";
retVal = 0;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run Update: "
- << fullCommand.c_str() << std::endl);
- res = cmSystemTools::RunSingleCommand(fullCommand.c_str(), &output,
- &retVal, cvsArgs[0].c_str(),
+ 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*/);
- if (!res || retVal != 0)
- {
- cmSystemTools::Error("Unable to perform extra updates:\n",
- it->c_str(), "\nWith output:\n",
- output.c_str());
+ if (!res || retVal != 0) {
+ cmSystemTools::Error("Unable to perform extra updates:\n", it->c_str(),
+ "\nWith output:\n", output.c_str());
return 0;
- }
}
}
+ }
return 0;
}
-
-//----------------------------------------------------------------------
// run a single dashboard entry
int cmCTestScriptHandler::RunConfigurationDashboard()
{
@@ -816,198 +691,170 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
// make sure the src directory is there, if it isn't then we might be able
// to check it out from cvs
retVal = this->CheckOutSourceDir();
- if (retVal)
- {
+ if (retVal) {
return retVal;
- }
+ }
// backup the dirs if requested
retVal = this->BackupDirectories();
- if (retVal)
- {
+ if (retVal) {
return retVal;
- }
+ }
// clear the binary directory?
- if (this->EmptyBinDir)
- {
- if ( !cmCTestScriptHandler::EmptyBinaryDirectory(
- this->BinaryDir.c_str()) )
- {
+ if (this->EmptyBinDir) {
+ if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir.c_str())) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem removing the binary directory" << std::endl);
- }
+ "Problem removing the binary directory" << std::endl);
}
+ }
// make sure the binary directory exists if it isn't the srcdir
if (!cmSystemTools::FileExists(this->BinaryDir.c_str()) &&
- this->SourceDir != this->BinaryDir)
- {
- if (!cmSystemTools::MakeDirectory(this->BinaryDir.c_str()))
- {
+ this->SourceDir != this->BinaryDir) {
+ if (!cmSystemTools::MakeDirectory(this->BinaryDir.c_str())) {
cmSystemTools::Error("Unable to create the binary directory:\n",
this->BinaryDir.c_str());
this->RestoreBackupDirectories();
return 7;
- }
}
+ }
// if the binary directory and the source directory are the same,
// and we are starting with an empty binary directory, then that means
// we must check out the source tree
- if (this->EmptyBinDir && this->SourceDir == this->BinaryDir)
- {
+ if (this->EmptyBinDir && this->SourceDir == this->BinaryDir) {
// make sure we have the required info
- if (this->CVSCheckOut.empty())
- {
- cmSystemTools::Error("You have specified the source and binary "
+ if (this->CVSCheckOut.empty()) {
+ cmSystemTools::Error(
+ "You have specified the source and binary "
"directories to be the same (an in source build). You have also "
"specified that the binary directory is to be erased. This means "
"that the source will have to be checked out from CVS. But you have "
"not specified CTEST_CVS_CHECKOUT");
return 8;
- }
+ }
// we must now checkout the src dir
retVal = this->CheckOutSourceDir();
- if (retVal)
- {
+ if (retVal) {
this->RestoreBackupDirectories();
return retVal;
- }
}
+ }
// backup the dirs if requested
retVal = this->PerformExtraUpdates();
- if (retVal)
- {
+ if (retVal) {
return retVal;
- }
+ }
// put the initial cache into the bin dir
- if (!this->InitialCache.empty())
- {
+ if (!this->InitialCache.empty()) {
if (!this->WriteInitialCache(this->BinaryDir.c_str(),
- this->InitialCache.c_str()))
- {
+ this->InitialCache.c_str())) {
this->RestoreBackupDirectories();
return 9;
- }
}
+ }
// do an initial cmake to setup the DartConfig file
int cmakeFailed = 0;
std::string cmakeFailedOuput;
- if (!this->CMakeCmd.empty())
- {
+ if (!this->CMakeCmd.empty()) {
command = this->CMakeCmd;
command += " \"";
command += this->SourceDir;
output = "";
command += "\"";
retVal = 0;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run cmake command: "
- << command.c_str() << std::endl);
- res = cmSystemTools::RunSingleCommand(command.c_str(), &output,
- &retVal, this->BinaryDir.c_str(),
+ 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*/);
- if ( !this->CMOutFile.empty() )
- {
+ if (!this->CMOutFile.empty()) {
std::string cmakeOutputFile = this->CMOutFile;
- if ( !cmSystemTools::FileIsFullPath(cmakeOutputFile.c_str()) )
- {
+ if (!cmSystemTools::FileIsFullPath(cmakeOutputFile.c_str())) {
cmakeOutputFile = this->BinaryDir + "/" + cmakeOutputFile;
- }
+ }
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Write CMake output to file: " << cmakeOutputFile.c_str()
- << std::endl);
+ "Write CMake output to file: " << cmakeOutputFile
+ << std::endl);
cmGeneratedFileStream fout(cmakeOutputFile.c_str());
- if ( fout )
- {
+ if (fout) {
fout << output.c_str();
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot open CMake output file: "
- << cmakeOutputFile.c_str() << " for writing" << std::endl);
- }
+ "Cannot open CMake output file: "
+ << cmakeOutputFile << " for writing" << std::endl);
}
- if (!res || retVal != 0)
- {
+ }
+ if (!res || retVal != 0) {
// even if this fails continue to the next step
cmakeFailed = 1;
cmakeFailedOuput = output;
- }
}
+ }
// run ctest, it may be more than one command in here
std::vector<std::string> ctestCommands;
- cmSystemTools::ExpandListArgument(this->CTestCmd,ctestCommands);
+ cmSystemTools::ExpandListArgument(this->CTestCmd, ctestCommands);
// for each variable/argument do a putenv
- for (unsigned i = 0; i < ctestCommands.size(); ++i)
- {
+ for (unsigned i = 0; i < ctestCommands.size(); ++i) {
command = ctestCommands[i];
output = "";
retVal = 0;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run ctest command: "
- << command.c_str() << std::endl);
- res = cmSystemTools::RunSingleCommand(command.c_str(), &output,
- &retVal, this->BinaryDir.c_str(), this->HandlerVerbose,
- 0 /*this->TimeOut*/);
+ 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*/);
// did something critical fail in ctest
- if (!res || cmakeFailed ||
- retVal & cmCTest::BUILD_ERRORS)
- {
+ if (!res || cmakeFailed || retVal & cmCTest::BUILD_ERRORS) {
this->RestoreBackupDirectories();
- if (cmakeFailed)
- {
+ if (cmakeFailed) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Unable to run cmake:" << std::endl
- << cmakeFailedOuput.c_str() << std::endl);
+ "Unable to run cmake:" << std::endl
+ << cmakeFailedOuput << std::endl);
return 10;
- }
+ }
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Unable to run ctest:" << std::endl
- << "command: " << command.c_str() << std::endl
- << "output: " << output.c_str() << std::endl);
- if (!res)
- {
+ "Unable to run ctest:" << std::endl
+ << "command: " << command << std::endl
+ << "output: " << output << std::endl);
+ if (!res) {
return 11;
- }
- return retVal * 100;
}
+ return retVal * 100;
}
+ }
// if all was succesful, delete the backup dirs to free up disk space
- if (this->Backup)
- {
- cmSystemTools::RemoveADirectory(this->BackupSourceDir.c_str());
- cmSystemTools::RemoveADirectory(this->BackupBinaryDir.c_str());
- }
+ if (this->Backup) {
+ cmSystemTools::RemoveADirectory(this->BackupSourceDir);
+ cmSystemTools::RemoveADirectory(this->BackupBinaryDir);
+ }
return 0;
}
-//-------------------------------------------------------------------------
bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
const char* text)
{
std::string cacheFile = directory;
cacheFile += "/CMakeCache.txt";
cmGeneratedFileStream fout(cacheFile.c_str());
- if(!fout)
- {
+ if (!fout) {
return false;
- }
+ }
- if (text!=0)
- {
+ if (text != CM_NULLPTR) {
fout.write(text, strlen(text));
- }
+ }
// Make sure the operating system has finished writing the file
// before closing it. This will ensure the file is finished before
@@ -1017,77 +864,111 @@ bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
return true;
}
-//-------------------------------------------------------------------------
void cmCTestScriptHandler::RestoreBackupDirectories()
{
// if we backed up the dirs and the build failed, then restore
// the backed up dirs
- if (this->Backup)
- {
+ if (this->Backup) {
// if for some reason those directories exist then first delete them
- if (cmSystemTools::FileExists(this->SourceDir.c_str()))
- {
- cmSystemTools::RemoveADirectory(this->SourceDir.c_str());
- }
- if (cmSystemTools::FileExists(this->BinaryDir.c_str()))
- {
- cmSystemTools::RemoveADirectory(this->BinaryDir.c_str());
- }
+ if (cmSystemTools::FileExists(this->SourceDir.c_str())) {
+ cmSystemTools::RemoveADirectory(this->SourceDir);
+ }
+ if (cmSystemTools::FileExists(this->BinaryDir.c_str())) {
+ cmSystemTools::RemoveADirectory(this->BinaryDir);
+ }
// rename the src and binary directories
rename(this->BackupSourceDir.c_str(), this->SourceDir.c_str());
rename(this->BackupBinaryDir.c_str(), this->BinaryDir.c_str());
- }
+ }
}
-bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char *sname,
+bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char* sname,
bool InProcess, int* returnValue)
{
cmCTestScriptHandler* sh = new cmCTestScriptHandler();
sh->SetCTestInstance(ctest);
- sh->AddConfigurationScript(sname,InProcess);
+ sh->AddConfigurationScript(sname, InProcess);
int res = sh->ProcessHandler();
- if(returnValue)
- {
+ if (returnValue) {
*returnValue = res;
- }
+ }
delete sh;
return true;
}
-bool cmCTestScriptHandler::EmptyBinaryDirectory(const char *sname)
+bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
{
// try to avoid deleting root
- if (!sname || strlen(sname) < 2)
- {
+ if (!sname || strlen(sname) < 2) {
return false;
- }
+ }
+
+ // consider non existing target directory a success
+ if (!cmSystemTools::FileExists(sname)) {
+ return true;
+ }
// try to avoid deleting directories that we shouldn't
std::string check = sname;
check += "/CMakeCache.txt";
- if(cmSystemTools::FileExists(check.c_str()) &&
- !cmSystemTools::RemoveADirectory(sname))
- {
+
+ if (!cmSystemTools::FileExists(check.c_str())) {
return false;
+ }
+
+ for (int i = 0; i < 5; ++i) {
+ if (TryToRemoveBinaryDirectoryOnce(sname)) {
+ return true;
}
- return true;
+ cmSystemTools::Delay(100);
+ }
+
+ return false;
+}
+
+bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce(
+ const std::string& directoryPath)
+{
+ cmsys::Directory directory;
+ directory.Load(directoryPath);
+
+ for (unsigned long i = 0; i < directory.GetNumberOfFiles(); ++i) {
+ std::string path = directory.GetFile(i);
+
+ if (path == "." || path == ".." || path == "CMakeCache.txt") {
+ continue;
+ }
+
+ std::string fullPath = directoryPath + std::string("/") + path;
+
+ bool isDirectory = cmSystemTools::FileIsDirectory(fullPath) &&
+ !cmSystemTools::FileIsSymlink(fullPath);
+
+ if (isDirectory) {
+ if (!cmSystemTools::RemoveADirectory(fullPath)) {
+ return false;
+ }
+ } else {
+ if (!cmSystemTools::RemoveFile(fullPath)) {
+ return false;
+ }
+ }
+ }
+
+ return cmSystemTools::RemoveADirectory(directoryPath);
}
-//-------------------------------------------------------------------------
double cmCTestScriptHandler::GetRemainingTimeAllowed()
{
- if (!this->Makefile)
- {
+ if (!this->Makefile) {
return 1.0e7;
- }
+ }
- const char *timelimitS
- = this->Makefile->GetDefinition("CTEST_TIME_LIMIT");
+ const char* timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT");
- if (!timelimitS)
- {
+ if (!timelimitS) {
return 1.0e7;
- }
+ }
double timelimit = atof(timelimitS);
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 9d852cab6..667870260 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -1,27 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestScriptHandler_h
#define cmCTestScriptHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
-class cmMakefile;
-class cmLocalGenerator;
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestCommand;
class cmGlobalGenerator;
+class cmMakefile;
class cmake;
-class cmCTestCommand;
/** \class cmCTestScriptHandler
* \brief A class that handles ctest -S invocations
@@ -62,29 +55,29 @@ class cmCTestCommand;
class cmCTestScriptHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestScriptHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
/**
* Add a script to run, and if is should run in the current process
*/
- void AddConfigurationScript(const char *, bool pscope);
+ void AddConfigurationScript(const char*, bool pscope);
/**
* Run a dashboard using a specified confiuration script
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
/*
* Run a script
*/
- static bool RunScript(cmCTest* ctest, const char *script, bool InProcess,
- int* returnValue);
+ static bool RunScript(cmCTest* ctest, const char* script, bool InProcess,
+ int* returnValue);
int RunCurrentScript();
/*
* Empty Binary Directory
*/
- static bool EmptyBinaryDirectory(const char *dir);
+ static bool EmptyBinaryDirectory(const char* dir);
/*
* Write an initial CMakeCache.txt from the given contents.
@@ -105,13 +98,12 @@ public:
double GetRemainingTimeAllowed();
cmCTestScriptHandler();
- ~cmCTestScriptHandler();
+ ~cmCTestScriptHandler() CM_OVERRIDE;
- void Initialize();
+ void Initialize() CM_OVERRIDE;
void CreateCMake();
- void GetCommandDocumentation(std::vector<cmDocumentationEntry>& v) const;
- cmake* GetCMake() { return this->CMake;}
+ cmake* GetCMake() { return this->CMake; }
private:
// reads in a script
int ReadInScript(const std::string& total_script_arg);
@@ -134,28 +126,31 @@ private:
int RunConfigurationDashboard();
// Add ctest command
- void AddCTestCommand(cmCTestCommand* command);
+ void AddCTestCommand(std::string const& name, cmCTestCommand* command);
+
+ // Try to remove the binary directory once
+ static bool TryToRemoveBinaryDirectoryOnce(const std::string& directoryPath);
- std::vector<cmStdString> ConfigurationScripts;
+ std::vector<std::string> ConfigurationScripts;
std::vector<bool> ScriptProcessScope;
bool Backup;
bool EmptyBinDir;
bool EmptyBinDirOnce;
- cmStdString SourceDir;
- cmStdString BinaryDir;
- cmStdString BackupSourceDir;
- cmStdString BackupBinaryDir;
- cmStdString CTestRoot;
- cmStdString CVSCheckOut;
- cmStdString CTestCmd;
- cmStdString UpdateCmd;
- cmStdString CTestEnv;
- cmStdString InitialCache;
- cmStdString CMakeCmd;
- cmStdString CMOutFile;
- std::vector<cmStdString> ExtraUpdates;
+ std::string SourceDir;
+ std::string BinaryDir;
+ std::string BackupSourceDir;
+ std::string BackupBinaryDir;
+ std::string CTestRoot;
+ std::string CVSCheckOut;
+ std::string CTestCmd;
+ std::string UpdateCmd;
+ std::string CTestEnv;
+ std::string InitialCache;
+ std::string CMakeCmd;
+ std::string CMOutFile;
+ std::vector<std::string> ExtraUpdates;
double MinimumInterval;
double ContinuousDuration;
@@ -163,10 +158,9 @@ private:
// what time in seconds did this script start running
double ScriptStartTime;
- cmMakefile *Makefile;
- cmLocalGenerator *LocalGenerator;
- cmGlobalGenerator *GlobalGenerator;
- cmake *CMake;
+ cmMakefile* Makefile;
+ cmGlobalGenerator* GlobalGenerator;
+ cmake* CMake;
};
#endif
diff --git a/Source/CTest/cmCTestSleepCommand.cxx b/Source/CTest/cmCTestSleepCommand.cxx
index 7e8755066..2752cd370 100644
--- a/Source/CTest/cmCTestSleepCommand.cxx
+++ b/Source/CTest/cmCTestSleepCommand.cxx
@@ -1,55 +1,43 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSleepCommand.h"
#include "cmCTestScriptHandler.h"
-#include <stdlib.h> // required for atoi
-bool cmCTestSleepCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+#include <stdlib.h>
+
+class cmExecutionStatus;
+
+bool cmCTestSleepCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/)
{
- if (args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// sleep for specified seconds
unsigned int time1 = atoi(args[0].c_str());
- if(args.size() == 1 )
- {
+ if (args.size() == 1) {
cmCTestScriptHandler::SleepInSeconds(time1);
// update the elapsed time since it could have slept for a while
this->CTestScriptHandler->UpdateElapsedTime();
return true;
- }
+ }
// sleep up to a duration
- if(args.size() == 3 )
- {
+ if (args.size() == 3) {
unsigned int duration = atoi(args[1].c_str());
unsigned int time2 = atoi(args[2].c_str());
- if (time1 + duration > time2)
- {
+ if (time1 + duration > time2) {
duration = (time1 + duration - time2);
cmCTestScriptHandler::SleepInSeconds(duration);
// update the elapsed time since it could have slept for a while
this->CTestScriptHandler->UpdateElapsedTime();
- }
- return true;
}
+ return true;
+ }
this->SetError("called with incorrect number of arguments");
return false;
}
-
-
diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h
index 0f51ddfeb..f0b5f1eeb 100644
--- a/Source/CTest/cmCTestSleepCommand.h
+++ b/Source/CTest/cmCTestSleepCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestSleepCommand_h
#define cmCTestSleepCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestCommand.h"
+#include <string>
+#include <vector>
+
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmCTestSleep
* \brief Run a ctest script
*
@@ -23,55 +22,25 @@
class cmCTestSleepCommand : public cmCTestCommand
{
public:
-
cmCTestSleepCommand() {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestSleepCommand* ni = new cmCTestSleepCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_sleep";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "sleeps for some amount of time";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_sleep(<seconds>)\n"
- "Sleep for given number of seconds.\n"
- " ctest_sleep(<time1> <duration> <time2>)\n"
- "Sleep for t=(time1 + duration - time2) seconds if t > 0.";
- }
-
- cmTypeMacro(cmCTestSleepCommand, cmCTestCommand);
-
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 228a17300..01a874b45 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -1,92 +1,84 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestStartCommand.h"
#include "cmCTest.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
#include "cmCTestVC.h"
#include "cmGeneratedFileStream.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <stddef.h>
+
+class cmExecutionStatus;
cmCTestStartCommand::cmCTestStartCommand()
{
this->CreateNewTag = true;
+ this->Quiet = false;
}
-bool cmCTestStartCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/)
{
- if (args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
size_t cnt = 0;
const char* smodel = args[cnt].c_str();
- const char* src_dir = 0;
- const char* bld_dir = 0;
+ const char* src_dir = CM_NULLPTR;
+ const char* bld_dir = CM_NULLPTR;
cnt++;
- this->CTest->SetSpecificTrack(0);
- if ( cnt < args.size() -1 )
- {
- if ( args[cnt] == "TRACK" )
- {
- cnt ++;
+ this->CTest->SetSpecificTrack(CM_NULLPTR);
+ if (cnt < args.size() - 1) {
+ if (args[cnt] == "TRACK") {
+ cnt++;
this->CTest->SetSpecificTrack(args[cnt].c_str());
- cnt ++;
- }
+ cnt++;
}
+ }
- if (cnt < args.size())
- {
- if (args[cnt] == "APPEND")
- {
- cnt ++;
+ if (cnt < args.size()) {
+ if (args[cnt] == "APPEND") {
+ cnt++;
this->CreateNewTag = false;
- }
}
+ }
+ if (cnt < args.size()) {
+ if (args[cnt] == "QUIET") {
+ cnt++;
+ this->Quiet = true;
+ }
+ }
- if ( cnt < args.size() )
- {
+ if (cnt < args.size()) {
src_dir = args[cnt].c_str();
- cnt ++;
- if ( cnt < args.size() )
- {
+ cnt++;
+ if (cnt < args.size()) {
bld_dir = args[cnt].c_str();
- }
}
- if ( !src_dir )
- {
+ }
+ if (!src_dir) {
src_dir = this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
- }
- if ( !bld_dir)
- {
+ }
+ if (!bld_dir) {
bld_dir = this->Makefile->GetDefinition("CTEST_BINARY_DIRECTORY");
- }
- if ( !src_dir )
- {
+ }
+ if (!src_dir) {
this->SetError("source directory not specified. Specify source directory "
- "as an argument or set CTEST_SOURCE_DIRECTORY");
+ "as an argument or set CTEST_SOURCE_DIRECTORY");
return false;
- }
- if ( !bld_dir)
- {
+ }
+ if (!bld_dir) {
this->SetError("binary directory not specified. Specify binary directory "
- "as an argument or set CTEST_BINARY_DIRECTORY");
+ "as an argument or set CTEST_BINARY_DIRECTORY");
return false;
- }
+ }
cmSystemTools::AddKeepPath(src_dir);
cmSystemTools::AddKeepPath(bld_dir);
@@ -95,45 +87,44 @@ bool cmCTestStartCommand
std::string sourceDir = cmSystemTools::CollapseFullPath(src_dir);
std::string binaryDir = cmSystemTools::CollapseFullPath(bld_dir);
- this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir.c_str());
- this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str());
-
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model "
- << smodel << std::endl
- << " Source directory: " << src_dir << std::endl
- << " Build directory: " << bld_dir << std::endl);
+ this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir.c_str(),
+ this->Quiet);
+ 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 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Track: " << track << std::endl);
- }
+ if (track) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Track: " << track << std::endl, this->Quiet);
+ }
// Log startup actions.
std::string startLogFile = binaryDir + "/Testing/Temporary/LastStart.log";
cmGeneratedFileStream ofs(startLogFile.c_str());
- if(!ofs)
- {
+ if (!ofs) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot create log file: LastStart.log" << std::endl);
return false;
- }
+ }
// Make sure the source directory exists.
- if(!this->InitialCheckout(ofs, sourceDir))
- {
+ if (!this->InitialCheckout(ofs, sourceDir)) {
return false;
- }
- if(!cmSystemTools::FileIsDirectory(sourceDir.c_str()))
- {
- cmOStringStream e;
+ }
+ if (!cmSystemTools::FileIsDirectory(sourceDir)) {
+ std::ostringstream e;
e << "given source path\n"
<< " " << sourceDir << "\n"
<< "which is not an existing directory. "
<< "Set CTEST_CHECKOUT_COMMAND to a command line to create it.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", "OFF");
this->CTest->SetSuppressUpdatingCTestConfiguration(true);
@@ -144,27 +135,23 @@ bool cmCTestStartCommand
return this->CTest->InitializeFromCommand(this);
}
-//----------------------------------------------------------------------------
-bool cmCTestStartCommand::InitialCheckout(
- std::ostream& ofs, std::string const& sourceDir)
+bool cmCTestStartCommand::InitialCheckout(std::ostream& ofs,
+ std::string const& sourceDir)
{
// Use the user-provided command to create the source tree.
- const char* initialCheckoutCommand
- = this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND");
- if(!initialCheckoutCommand)
- {
+ const char* initialCheckoutCommand =
+ this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND");
+ if (!initialCheckoutCommand) {
initialCheckoutCommand =
this->Makefile->GetDefinition("CTEST_CVS_CHECKOUT");
- }
- if(initialCheckoutCommand)
- {
+ }
+ if (initialCheckoutCommand) {
// Use a generic VC object to run and log the command.
cmCTestVC vc(this->CTest, ofs);
- vc.SetSourceDirectory(sourceDir.c_str());
- if(!vc.InitialCheckout(initialCheckoutCommand))
- {
+ vc.SetSourceDirectory(sourceDir);
+ if (!vc.InitialCheckout(initialCheckoutCommand)) {
return false;
- }
}
+ }
return true;
}
diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h
index 6be47703e..b4943f92d 100644
--- a/Source/CTest/cmCTestStartCommand.h
+++ b/Source/CTest/cmCTestStartCommand.h
@@ -1,19 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestStartCommand_h
#define cmCTestStartCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestCommand.h"
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmCTestStart
* \brief Run a ctest script
*
@@ -22,71 +22,42 @@
class cmCTestStartCommand : public cmCTestCommand
{
public:
-
cmCTestStartCommand();
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestStartCommand* ni = new cmCTestStartCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
ni->CreateNewTag = this->CreateNewTag;
+ ni->Quiet = this->Quiet;
return ni;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
* Will this invocation of ctest_start create a new TAG file?
*/
- bool ShouldCreateNewTag()
- {
- return this->CreateNewTag;
- }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_start";}
+ bool ShouldCreateNewTag() { return this->CreateNewTag; }
/**
- * Succinct documentation.
+ * Should this invocation of ctest_start output non-error messages?
*/
- virtual const char* GetTerseDocumentation() const
- {
- return "Starts the testing for a given model";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_start(Model [TRACK <track>] [APPEND] [source [binary]])\n"
- "Starts the testing for a given model. The command should be called "
- "after the binary directory is initialized. If the 'source' and "
- "'binary' directory are not specified, it reads the "
- "CTEST_SOURCE_DIRECTORY and CTEST_BINARY_DIRECTORY. If the track is "
- "specified, the submissions will go to the specified track. "
- "If APPEND is used, the existing TAG is used rather than "
- "creating a new one based on the current time stamp.";
- }
-
- cmTypeMacro(cmCTestStartCommand, cmCTestCommand);
+ bool ShouldBeQuiet() { return this->Quiet; }
private:
bool InitialCheckout(std::ostream& ofs, std::string const& sourceDir);
bool CreateNewTag;
+ bool Quiet;
};
-
#endif
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 24974e3bc..409eb51fc 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -1,117 +1,101 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSubmitCommand.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
#include "cmCTestSubmitHandler.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#include <sstream>
+
+class cmExecutionStatus;
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
- 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");
-
- if ( !ctestDropMethod )
- {
+ 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 )
- {
+ if (!ctestDropSite) {
// error: CDash requires CTEST_DROP_SITE definition
// in CTestConfig.cmake
- }
- if ( !ctestDropLocation )
- {
+ }
+ if (!ctestDropLocation) {
// error: CDash requires CTEST_DROP_LOCATION definition
// in CTestConfig.cmake
- }
-
- this->CTest->SetCTestConfiguration("DropMethod", ctestDropMethod);
- this->CTest->SetCTestConfiguration("DropSite", ctestDropSite);
- this->CTest->SetCTestConfiguration("DropLocation", ctestDropLocation);
-
- this->CTest->SetCTestConfiguration("IsCDash",
- ctestDropSiteCDash ? "TRUE" : "FALSE");
+ }
+ 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);
+
+ this->CTest->SetCTestConfiguration(
+ "IsCDash", ctestDropSiteCDash ? "TRUE" : "FALSE", this->Quiet);
// Only propagate TriggerSite for non-CDash projects:
//
- if ( !ctestDropSiteCDash )
- {
- this->CTest->SetCTestConfiguration("TriggerSite", ctestTriggerSite);
- }
-
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "CurlOptions", "CTEST_CURL_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "DropSiteUser", "CTEST_DROP_SITE_USER");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "DropSitePassword", "CTEST_DROP_SITE_PASSWORD");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "ScpCommand", "CTEST_SCP_COMMAND");
-
- const char* notesFilesVariable
- = this->Makefile->GetDefinition("CTEST_NOTES_FILES");
- if (notesFilesVariable)
- {
+ if (!ctestDropSiteCDash) {
+ this->CTest->SetCTestConfiguration("TriggerSite", ctestTriggerSite,
+ 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;
- std::vector<cmStdString> newNotesFiles;
- cmSystemTools::ExpandListArgument(notesFilesVariable,notesFiles);
- std::vector<std::string>::iterator it;
- for ( it = notesFiles.begin();
- it != notesFiles.end();
- ++ it )
- {
- newNotesFiles.push_back(*it);
- }
+ cmCTest::VectorOfStrings newNotesFiles;
+ cmSystemTools::ExpandListArgument(notesFilesVariable, notesFiles);
+ newNotesFiles.insert(newNotesFiles.end(), notesFiles.begin(),
+ notesFiles.end());
this->CTest->GenerateNotesFile(newNotesFiles);
- }
+ }
- const char* extraFilesVariable
- = this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES");
- if (extraFilesVariable)
- {
+ const char* extraFilesVariable =
+ this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES");
+ if (extraFilesVariable) {
std::vector<std::string> extraFiles;
- std::vector<cmStdString> newExtraFiles;
- cmSystemTools::ExpandListArgument(extraFilesVariable,extraFiles);
- std::vector<std::string>::iterator it;
- for ( it = extraFiles.begin();
- it != extraFiles.end();
- ++ it )
- {
- newExtraFiles.push_back(*it);
- }
- if ( !this->CTest->SubmitExtraFiles(newExtraFiles))
- {
+ cmCTest::VectorOfStrings newExtraFiles;
+ cmSystemTools::ExpandListArgument(extraFilesVariable, extraFiles);
+ newExtraFiles.insert(newExtraFiles.end(), extraFiles.begin(),
+ extraFiles.end());
+ if (!this->CTest->SubmitExtraFiles(newExtraFiles)) {
this->SetError("problem submitting extra files.");
- return 0;
- }
+ return CM_NULLPTR;
}
+ }
- cmCTestGenericHandler* handler
- = this->CTest->GetInitializedHandler("submit");
- if ( !handler )
- {
+ cmCTestGenericHandler* handler =
+ this->CTest->GetInitializedHandler("submit");
+ if (!handler) {
this->SetError("internal CTest error. Cannot instantiate submit handler");
- return 0;
- }
+ return CM_NULLPTR;
+ }
// If no FILES or PARTS given, *all* PARTS are submitted by default.
//
@@ -127,8 +111,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If given explicit FILES to submit, pass them to the handler.
//
- if(this->FilesMentioned)
- {
+ if (this->FilesMentioned) {
// Intentionally select *no* PARTS. (Pass an empty set.) If PARTS
// were also explicitly mentioned, they will be selected below...
// But FILES with no PARTS mentioned should just submit the FILES
@@ -138,117 +121,152 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(noParts);
static_cast<cmCTestSubmitHandler*>(handler)->SelectFiles(this->Files);
- }
+ }
// If a PARTS option was given, select only the named parts for submission.
//
- if(this->PartsMentioned)
- {
+ if (this->PartsMentioned) {
static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(this->Parts);
- }
-
- 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");
-
+ }
+
+ // Pass along any HTTPHEADER to the handler if this option was given.
+ if (!this->HttpHeaders.empty()) {
+ static_cast<cmCTestSubmitHandler*>(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->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());
+ }
return handler;
}
+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 cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
{
- // Look for arguments specific to this command.
- if(arg == "PARTS")
- {
- this->ArgumentDoing = ArgumentDoingParts;
- this->PartsMentioned = true;
- return true;
+ if (this->CDashUpload) {
+ // Arguments specific to the CDASH_UPLOAD signature.
+ if (arg == "CDASH_UPLOAD") {
+ this->ArgumentDoing = ArgumentDoingCDashUpload;
+ return true;
}
- if(arg == "FILES")
- {
- this->ArgumentDoing = ArgumentDoingFiles;
- this->FilesMentioned = true;
- return true;
+ if (arg == "CDASH_UPLOAD_TYPE") {
+ this->ArgumentDoing = ArgumentDoingCDashUploadType;
+ return true;
}
+ } 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;
+ }
+ }
+ // Arguments used by both modes.
+ if (arg == "HTTPHEADER") {
+ this->ArgumentDoing = ArgumentDoingHttpHeader;
+ return true;
+ }
- if(arg == "RETRY_COUNT")
- {
+ if (arg == "RETRY_COUNT") {
this->ArgumentDoing = ArgumentDoingRetryCount;
return true;
- }
+ }
- if(arg == "RETRY_DELAY")
- {
+ if (arg == "RETRY_DELAY") {
this->ArgumentDoing = ArgumentDoingRetryDelay;
return true;
- }
+ }
- if(arg == "INTERNAL_TEST_CHECKSUM")
- {
+ if (arg == "INTERNAL_TEST_CHECKSUM") {
this->InternalTest = true;
return true;
- }
+ }
// Look for other arguments.
return this->Superclass::CheckArgumentKeyword(arg);
}
-
-//----------------------------------------------------------------------------
bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
{
// Handle states specific to this command.
- if(this->ArgumentDoing == ArgumentDoingParts)
- {
+ if (this->ArgumentDoing == ArgumentDoingParts) {
cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str());
- if(p != cmCTest::PartCount)
- {
+ if (p != cmCTest::PartCount) {
this->Parts.insert(p);
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "Part name \"" << arg << "\" is invalid.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
this->ArgumentDoing = ArgumentDoingError;
- }
- return true;
}
-
- if(this->ArgumentDoing == ArgumentDoingFiles)
- {
- cmStdString filename(arg);
- if(cmSystemTools::FileExists(filename.c_str()))
- {
- this->Files.insert(filename);
- }
- else
- {
- cmOStringStream e;
- e << "File \"" << filename << "\" does not exist. Cannot submit "
- << "a non-existent file.";
+ return true;
+ }
+
+ if (this->ArgumentDoing == ArgumentDoingFiles) {
+ if (cmSystemTools::FileExists(arg.c_str())) {
+ this->Files.insert(arg);
+ } else {
+ 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 true;
}
+ return true;
+ }
- if(this->ArgumentDoing == ArgumentDoingRetryCount)
- {
+ if (this->ArgumentDoing == ArgumentDoingHttpHeader) {
+ this->HttpHeaders.push_back(arg);
+ return true;
+ }
+
+ if (this->ArgumentDoing == ArgumentDoingRetryCount) {
this->RetryCount = arg;
return true;
- }
+ }
- if(this->ArgumentDoing == ArgumentDoingRetryDelay)
- {
+ 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);
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index 53ee8754e..cf65cdc8d 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -1,19 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestSubmitCommand_h
#define cmCTestSubmitCommand_h
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h"
+
#include "cmCTest.h"
+#include "cmCTestHandlerCommand.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+class cmCTestGenericHandler;
+class cmCommand;
+class cmExecutionStatus;
/** \class cmCTestSubmit
* \brief Run a ctest script
@@ -24,77 +25,42 @@
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.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestSubmitCommand* ni = new cmCTestSubmitCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ctest_submit";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Submit results to a dashboard server.";
- }
-
- /**
- * More documentation.
+ * The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_submit([PARTS ...] [FILES ...] [RETRY_COUNT count] "
- " [RETRY_DELAY delay][RETURN_VALUE res])\n"
- "By default all available parts are submitted if no PARTS or FILES "
- "are specified. "
- "The PARTS option lists a subset of parts to be submitted. "
- "Valid part names are:\n"
- " Start = nothing\n"
- " Update = ctest_update results, in Update.xml\n"
- " Configure = ctest_configure results, in Configure.xml\n"
- " Build = ctest_build results, in Build.xml\n"
- " Test = ctest_test results, in Test.xml\n"
- " Coverage = ctest_coverage results, in Coverage.xml\n"
- " MemCheck = ctest_memcheck results, in DynamicAnalysis.xml\n"
- " Notes = Files listed by CTEST_NOTES_FILES, in Notes.xml\n"
- " ExtraFiles = Files listed by CTEST_EXTRA_SUBMIT_FILES\n"
- " Submit = nothing\n"
- "The FILES option explicitly lists specific files to be submitted. "
- "Each individual file must exist at the time of the call.\n"
- "The RETRY_DELAY option specifies how long in seconds to wait after "
- "a timed-out submission before attempting to re-submit.\n"
- "The RETRY_COUNT option specifies how many times to retry a timed-out "
- "submission.\n";
- }
+ std::string GetName() const CM_OVERRIDE { return "ctest_submit"; }
- cmTypeMacro(cmCTestSubmitCommand, cmCTestHandlerCommand);
+ typedef cmCTestHandlerCommand Superclass;
protected:
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
- virtual bool CheckArgumentKeyword(std::string const& arg);
- virtual bool CheckArgumentValue(std::string const& arg);
+ bool CheckArgumentKeyword(std::string const& arg) CM_OVERRIDE;
+ bool CheckArgumentValue(std::string const& arg) CM_OVERRIDE;
enum
{
@@ -102,6 +68,9 @@ protected:
ArgumentDoingFiles,
ArgumentDoingRetryDelay,
ArgumentDoingRetryCount,
+ ArgumentDoingCDashUpload,
+ ArgumentDoingCDashUploadType,
+ ArgumentDoingHttpHeader,
ArgumentDoingLast2
};
@@ -112,7 +81,10 @@ protected:
cmCTest::SetOfStrings Files;
std::string RetryCount;
std::string RetryDelay;
+ bool CDashUpload;
+ std::string CDashUploadFile;
+ std::string CDashUploadType;
+ std::vector<std::string> HttpHeaders;
};
-
#endif
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 941d34877..8d62fa156 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -1,161 +1,140 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSubmitHandler.h"
-#include "cmSystemTools.h"
-#include "cmVersion.h"
-#include "cmGeneratedFileStream.h"
+#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 "cmCTest.h"
+#include "cmCTestCurl.h"
+#include "cmCTestScriptHandler.h"
+#include "cmCurl.h"
+#include "cmGeneratedFileStream.h"
+#include "cmProcessOutput.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+#include "cmThirdParty.h"
+#include "cmWorkingDirectory.h"
#include "cmXMLParser.h"
+#include "cmake.h"
-#include <cmsys/Process.h>
-#include <cmsys/Base64.h>
-
-// For XML-RPC submission
+#if defined(CTEST_USE_XMLRPC)
+#include "cmVersion.h"
+#include "cm_sys_stat.h"
#include "cm_xmlrpc.h"
-
-// For curl submission
-#include "cm_curl.h"
-
-#include <sys/stat.h>
+#endif
#define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar;
-//----------------------------------------------------------------------------
-class cmCTestSubmitHandler::ResponseParser: public cmXMLParser
+class cmCTestSubmitHandler::ResponseParser : public cmXMLParser
{
public:
ResponseParser() { this->Status = STATUS_OK; }
- ~ResponseParser() {}
+ ~ResponseParser() CM_OVERRIDE {}
public:
-
enum StatusType
- {
+ {
STATUS_OK,
STATUS_WARNING,
STATUS_ERROR
- };
+ };
StatusType Status;
- std::string CDashVersion;
std::string Filename;
std::string MD5;
std::string Message;
private:
-
std::vector<char> CurrentValue;
std::string GetCurrentValue()
- {
+ {
std::string val;
- if(this->CurrentValue.size())
- {
+ if (!this->CurrentValue.empty()) {
val.assign(&this->CurrentValue[0], this->CurrentValue.size());
- }
- return val;
}
+ return val;
+ }
- virtual void StartElement(const char* name, const char** atts)
- {
+ void StartElement(const std::string& /*name*/,
+ const char** /*atts*/) CM_OVERRIDE
+ {
this->CurrentValue.clear();
- if(strcmp(name, "cdash") == 0)
- {
- this->CDashVersion = this->FindAttribute(atts, "version");
- }
- }
+ }
- virtual void CharacterDataHandler(const char* data, int length)
- {
- this->CurrentValue.insert(this->CurrentValue.end(), data, data+length);
- }
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ this->CurrentValue.insert(this->CurrentValue.end(), data, data + length);
+ }
- virtual void EndElement(const char* name)
- {
- if(strcmp(name, "status") == 0)
- {
+ void EndElement(const std::string& name) CM_OVERRIDE
+ {
+ if (name == "status") {
std::string status = cmSystemTools::UpperCase(this->GetCurrentValue());
- if(status == "OK" || status == "SUCCESS")
- {
+ if (status == "OK" || status == "SUCCESS") {
this->Status = STATUS_OK;
- }
- else if(status == "WARNING")
- {
+ } else if (status == "WARNING") {
this->Status = STATUS_WARNING;
- }
- else
- {
+ } else {
this->Status = STATUS_ERROR;
- }
}
- else if(strcmp(name, "filename") == 0)
- {
+ } else if (name == "filename") {
this->Filename = this->GetCurrentValue();
- }
- else if(strcmp(name, "md5") == 0)
- {
+ } else if (name == "md5") {
this->MD5 = this->GetCurrentValue();
- }
- else if(strcmp(name, "message") == 0)
- {
+ } else if (name == "message") {
this->Message = this->GetCurrentValue();
- }
}
+ }
};
-
-static size_t
-cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
- void *data)
+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);
+ cmCTestSubmitHandlerVectorOfChar* vec =
+ static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
const char* chPtr = static_cast<char*>(ptr);
vec->insert(vec->end(), chPtr, chPtr + realsize);
return realsize;
}
-static size_t
-cmCTestSubmitHandlerCurlDebugCallback(CURL *, curl_infotype, char *chPtr,
- size_t size, void *data)
+static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/,
+ curl_infotype /*unused*/,
+ char* chPtr, size_t size,
+ void* data)
{
- cmCTestSubmitHandlerVectorOfChar *vec
- = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
+ cmCTestSubmitHandlerVectorOfChar* vec =
+ static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
vec->insert(vec->end(), chPtr, chPtr + size);
return size;
}
-//----------------------------------------------------------------------------
-cmCTestSubmitHandler::cmCTestSubmitHandler() : HTTPProxy(), FTPProxy()
+cmCTestSubmitHandler::cmCTestSubmitHandler()
+ : HTTPProxy()
+ , FTPProxy()
{
this->Initialize();
}
-//----------------------------------------------------------------------------
void cmCTestSubmitHandler::Initialize()
{
// We submit all available parts by default.
- for(cmCTest::Part p = cmCTest::PartStart;
- p != cmCTest::PartCount; p = cmCTest::Part(p+1))
- {
+ for (cmCTest::Part p = cmCTest::PartStart; p != cmCTest::PartCount;
+ p = cmCTest::Part(p + 1)) {
this->SubmitPart[p] = true;
- }
+ }
this->CDash = false;
this->HasWarnings = false;
this->HasErrors = false;
@@ -165,17 +144,16 @@ void cmCTestSubmitHandler::Initialize()
this->HTTPProxyAuth = "";
this->FTPProxy = "";
this->FTPProxyType = 0;
- this->LogFile = 0;
+ this->LogFile = CM_NULLPTR;
this->Files.clear();
}
-//----------------------------------------------------------------------------
-bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url)
+bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix,
+ const std::set<std::string>& files,
+ const std::string& remoteprefix,
+ const std::string& url)
{
- CURL *curl;
+ CURL* curl;
CURLcode res;
FILE* ftpfile;
char error_buffer[1024];
@@ -184,28 +162,24 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
::curl_global_init(CURL_GLOBAL_ALL);
cmCTest::SetOfStrings::const_iterator file;
- for ( file = files.begin(); file != files.end(); ++file )
- {
+ for (file = files.begin(); file != files.end(); ++file) {
/* get a curl handle */
curl = curl_easy_init();
- if(curl)
- {
+ if (curl) {
// Using proxy
- if ( this->FTPProxyType > 0 )
- {
+ 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);
- }
+ 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);
@@ -213,193 +187,191 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
// 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);
+ SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
- cmStdString local_file = *file;
- if ( !cmSystemTools::FileExists(local_file.c_str()) )
- {
+ std::string local_file = *file;
+ if (!cmSystemTools::FileExists(local_file.c_str())) {
local_file = localprefix + "/" + *file;
- }
- cmStdString upload_as
- = url + "/" + remoteprefix + cmSystemTools::GetFilenameName(*file);
-
- struct stat st;
- if ( ::stat(local_file.c_str(), &st) )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
- << local_file.c_str() << std::endl);
+ }
+ 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 = ::fopen(local_file.c_str(), "rb");
- *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
- << upload_as.c_str() << std::endl;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
- << local_file.c_str() << " to "
- << upload_as.c_str() << std::endl);
+ 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());
+ ::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>(st.st_size));
+ ::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);
+ cmCTestSubmitHandlerWriteMemoryCallback);
::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
- cmCTestSubmitHandlerCurlDebugCallback);
+ 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);
+ ::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.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
- }
- if ( chunkDebug.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
- << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
- << std::endl);
- }
+ 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 )
- {
+ 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.c_str() << std::endl);
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
- << error_buffer << std::endl);
- *this->LogFile << " Error when uploading file: "
- << local_file.c_str()
+ " Error message was: " << error_buffer << std::endl);
+ *this->LogFile << " Error when uploading file: " << local_file
<< std::endl
- << " Error message was: "
- << error_buffer << std::endl
+ << " Error message was: " << error_buffer << std::endl
<< " Curl output was: ";
// avoid dereference of empty vector
- if(chunk.size())
- {
+ if (!chunk.empty()) {
*this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size());
cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
- }
+ << 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);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
- << std::endl);
- }
+ 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 cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url)
+bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
+ const std::set<std::string>& files,
+ const std::string& remoteprefix,
+ const std::string& url)
{
- CURL *curl;
+ CURL* curl;
CURLcode res;
FILE* ftpfile;
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");
+
+ // 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,
+ this->Quiet);
+ headers = ::curl_slist_append(headers, h->c_str());
+ }
/* In windows, this will init the winsock stuff */
::curl_global_init(CURL_GLOBAL_ALL);
- cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
- cmStdString curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
+ std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
+ std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
std::vector<std::string> args;
- cmSystemTools::ExpandListArgument(curlopt.c_str(), args);
+ cmSystemTools::ExpandListArgument(curlopt, args);
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::vector<std::string>::iterator i = args.begin(); i != args.end();
+ ++i) {
+ if (*i == "CURLOPT_SSL_VERIFYPEER_OFF") {
verifyPeerOff = true;
- }
- if(*i == "CURLOPT_SSL_VERIFYHOST_OFF")
- {
+ }
+ if (*i == "CURLOPT_SSL_VERIFYHOST_OFF") {
verifyHostOff = true;
- }
}
- cmStdString::size_type kk;
+ }
+ std::string::size_type kk;
cmCTest::SetOfStrings::const_iterator file;
- for ( file = files.begin(); file != files.end(); ++file )
- {
+ for (file = files.begin(); file != files.end(); ++file) {
/* get a curl handle */
curl = curl_easy_init();
- if(curl)
- {
- if(verifyPeerOff)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Set CURLOPT_SSL_VERIFYPEER to off\n");
+ if (curl) {
+ cmCurlSetCAInfo(curl);
+ if (verifyPeerOff) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Set CURLOPT_SSL_VERIFYPEER to off\n",
+ this->Quiet);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
- }
- if(verifyHostOff)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Set CURLOPT_SSL_VERIFYHOST to off\n");
+ }
+ if (verifyHostOff) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Set CURLOPT_SSL_VERIFYHOST to off\n",
+ this->Quiet);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
- }
+ }
// Using proxy
- if ( this->HTTPProxyType > 0 )
- {
+ 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.size() > 0)
- {
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
- this->HTTPProxyAuth.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());
}
- }
}
- if(this->CTest->ShouldUseHTTP10())
- {
+ }
+ if (this->CTest->ShouldUseHTTP10()) {
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
- }
+ }
// enable HTTP ERROR parsing
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
/* enable uploading */
@@ -408,165 +380,156 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
// 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);
+ SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
/* HTTP PUT please */
::curl_easy_setopt(curl, CURLOPT_PUT, 1);
::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- cmStdString local_file = *file;
- if ( !cmSystemTools::FileExists(local_file.c_str()) )
- {
+ ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+ std::string local_file = *file;
+ if (!cmSystemTools::FileExists(local_file.c_str())) {
local_file = localprefix + "/" + *file;
- }
- cmStdString remote_file
- = remoteprefix + cmSystemTools::GetFilenameName(*file);
+ }
+ std::string remote_file =
+ remoteprefix + cmSystemTools::GetFilenameName(*file);
- *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
- << remote_file.c_str() << std::endl;
+ *this->LogFile << "\tUpload file: " << local_file << " to "
+ << remote_file << std::endl;
- cmStdString ofile = "";
- for ( kk = 0; kk < remote_file.size(); kk ++ )
- {
+ 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);
- }
+ switch (c) {
+ case '+':
+ case '?':
+ case '/':
+ case '\\':
+ case '&':
+ case ' ':
+ case '=':
+ case '%':
+ sprintf(hexCh, "%%%02X", (int)c);
+ ofile.append(hexCh);
+ break;
+ default:
+ ofile.append(hexCh);
}
- cmStdString upload_as
- = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
- + "FileName=" + ofile;
+ }
+ std::string upload_as = url +
+ ((url.find('?') == std::string::npos) ? '?' : '&') + "FileName=" +
+ ofile;
upload_as += "&MD5=";
- if(cmSystemTools::IsOn(this->GetOption("InternalTest")))
- {
+ if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) {
upload_as += "bad_md5sum";
- }
- else
- {
+ } else {
char md5[33];
- cmSystemTools::ComputeFileMD5(local_file.c_str(), md5);
+ cmSystemTools::ComputeFileMD5(local_file, md5);
md5[32] = 0;
upload_as += md5;
- }
+ }
- struct stat st;
- if ( ::stat(local_file.c_str(), &st) )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
- << local_file.c_str() << std::endl);
+ if (!cmSystemTools::FileExists(local_file.c_str())) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Cannot find file: " << local_file << std::endl);
::curl_easy_cleanup(curl);
+ ::curl_slist_free_all(headers);
::curl_global_cleanup();
return false;
- }
+ }
+ unsigned long filelen = cmSystemTools::FileLength(local_file);
- ftpfile = ::fopen(local_file.c_str(), "rb");
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
- << local_file.c_str() << " to "
- << upload_as.c_str() << " Size: " << st.st_size << std::endl);
+ ftpfile = cmsys::SystemTools::Fopen(local_file, "rb");
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Upload file: " << local_file << " to "
+ << upload_as << " Size: "
+ << filelen << std::endl,
+ this->Quiet);
// specify target
- ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
+ ::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>(st.st_size));
+ ::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);
+ cmCTestSubmitHandlerWriteMemoryCallback);
::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
- cmCTestSubmitHandlerCurlDebugCallback);
+ 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);
+ ::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(cmSystemTools::IsOn(this->GetOption("InternalTest")) &&
- cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
- this->CTest->GetCDashVersion().c_str(), "1.7"))
- {
- // mock failure output for internal test case
- std::string mock_output = "<cdash version=\"1.7.0\">\n"
- " <status>ERROR</status>\n"
- " <message>Checksum failed for file.</message>\n"
- "</cdash>\n";
- chunk.clear();
- chunk.assign(mock_output.begin(), mock_output.end());
- }
-
- if ( chunk.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
+ if (!chunk.empty()) {
+ cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size())
+ << "]" << std::endl,
+ this->Quiet);
this->ParseResponse(chunk);
- }
- if ( chunkDebug.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
- << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
- << std::endl);
- }
+ }
+ if (!chunkDebug.empty()) {
+ cmCTestOptionalLog(
+ this->CTest, DEBUG, "CURL debug output: ["
+ << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
+ << std::endl,
+ this->Quiet);
+ }
// If curl failed for any reason, or checksum fails, wait and retry
//
- if(res != CURLE_OK || this->HasErrors)
- {
- std::string retryDelay = this->GetOption("RetryDelay") == NULL ?
- "" : this->GetOption("RetryDelay");
- std::string retryCount = this->GetOption("RetryCount") == NULL ?
- "" : this->GetOption("RetryCount");
-
- int delay = retryDelay == "" ? atoi(this->CTest->GetCTestConfiguration(
- "CTestSubmitRetryDelay").c_str()) : atoi(retryDelay.c_str());
- int count = retryCount == "" ? atoi(this->CTest->GetCTestConfiguration(
- "CTestSubmitRetryCount").c_str()) : atoi(retryCount.c_str());
-
- for(int i = 0; i < count; i++)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Submit failed, waiting " << delay << " seconds...\n");
+ if (res != CURLE_OK || this->HasErrors) {
+ std::string retryDelay = this->GetOption("RetryDelay") == CM_NULLPTR
+ ? ""
+ : this->GetOption("RetryDelay");
+ std::string retryCount = this->GetOption("RetryCount") == CM_NULLPTR
+ ? ""
+ : this->GetOption("RetryCount");
+
+ int delay = retryDelay == ""
+ ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
+ .c_str())
+ : atoi(retryDelay.c_str());
+ int count = retryCount == ""
+ ? 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
+ << " seconds...\n",
+ this->Quiet);
double stop = cmSystemTools::GetTime() + delay;
- while(cmSystemTools::GetTime() < stop)
- {
+ while (cmSystemTools::GetTime() < stop) {
cmSystemTools::Delay(100);
- }
+ }
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Retry submission: Attempt " << (i + 1) << " of "
- << count << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Retry submission: Attempt "
+ << (i + 1) << " of " << count << std::endl,
+ this->Quiet);
::fclose(ftpfile);
- ftpfile = ::fopen(local_file.c_str(), "rb");
+ ftpfile = cmsys::SystemTools::Fopen(local_file, "rb");
::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
chunk.clear();
@@ -575,134 +538,121 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
res = ::curl_easy_perform(curl);
- if ( chunk.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
+ if (!chunk.empty()) {
+ cmCTestOptionalLog(
+ this->CTest, DEBUG, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl,
+ this->Quiet);
this->ParseResponse(chunk);
- }
+ }
- if(res == CURLE_OK && !this->HasErrors)
- {
+ if (res == CURLE_OK && !this->HasErrors) {
break;
- }
}
}
+ }
fclose(ftpfile);
- if ( res )
- {
+ 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.c_str() << std::endl);
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
- << error_buffer << std::endl);
- *this->LogFile << " Error when uploading file: "
- << local_file.c_str()
+ " Error message was: " << error_buffer << std::endl);
+ *this->LogFile << " Error when uploading file: " << local_file
<< std::endl
<< " Error message was: " << error_buffer
<< std::endl;
// avoid deref of begin for zero size array
- if(chunk.size())
- {
+ 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);
- }
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
::curl_easy_cleanup(curl);
+ ::curl_slist_free_all(headers);
::curl_global_cleanup();
return false;
- }
+ }
// always cleanup
::curl_easy_cleanup(curl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
- << std::endl);
- }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Uploaded: " + local_file << std::endl,
+ this->Quiet);
}
+ }
+ ::curl_slist_free_all(headers);
::curl_global_cleanup();
return true;
}
-//----------------------------------------------------------------------------
-void cmCTestSubmitHandler
-::ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk)
+void cmCTestSubmitHandler::ParseResponse(
+ cmCTestSubmitHandlerVectorOfChar chunk)
{
- std::string output = "";
+ std::string output;
output.append(chunk.begin(), chunk.end());
- if(output.find("<cdash") != output.npos)
- {
+ if (output.find("<cdash") != std::string::npos) {
ResponseParser parser;
parser.Parse(output.c_str());
- if(parser.Status != ResponseParser::STATUS_OK)
- {
+ if (parser.Status != ResponseParser::STATUS_OK) {
this->HasErrors = true;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission failed: " <<
- parser.Message << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Submission failed: " << parser.Message << std::endl);
return;
- }
}
+ }
output = cmSystemTools::UpperCase(output);
- if(output.find("WARNING") != std::string::npos)
- {
+ if (output.find("WARNING") != std::string::npos) {
this->HasWarnings = true;
- }
- if(output.find("ERROR") != std::string::npos)
- {
+ }
+ if (output.find("ERROR") != std::string::npos) {
this->HasErrors = true;
- }
+ }
- if(this->HasWarnings || this->HasErrors)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n" <<
- cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
- }
+ if (this->HasWarnings || this->HasErrors) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n"
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
+ }
}
-//----------------------------------------------------------------------------
-bool cmCTestSubmitHandler::TriggerUsingHTTP(
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url)
+bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files,
+ const std::string& remoteprefix,
+ const std::string& url)
{
- CURL *curl;
+ 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 )
- {
+ for (file = files.begin(); file != files.end(); ++file) {
/* get a curl handle */
curl = curl_easy_init();
- if(curl)
- {
+ if (curl) {
// Using proxy
- if ( this->HTTPProxyType > 0 )
- {
+ 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.size() > 0)
- {
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
- this->HTTPProxyAuth.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);
@@ -711,126 +661,120 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(
// specify handler for output
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
- cmCTestSubmitHandlerWriteMemoryCallback);
+ cmCTestSubmitHandlerWriteMemoryCallback);
::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
- cmCTestSubmitHandlerCurlDebugCallback);
+ 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);
-
- cmStdString rfile
- = remoteprefix + cmSystemTools::GetFilenameName(*file);
- cmStdString ofile = "";
- cmStdString::iterator kk;
- for ( kk = rfile.begin(); kk < rfile.end(); ++ kk)
- {
+ ::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);
- }
+ switch (c) {
+ case '+':
+ case '?':
+ case '/':
+ case '\\':
+ case '&':
+ case ' ':
+ case '=':
+ case '%':
+ sprintf(hexCh, "%%%02X", (int)c);
+ ofile.append(hexCh);
+ break;
+ default:
+ ofile.append(hexCh);
}
- cmStdString turl
- = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
- + "xmlfile=" + ofile;
- *this->LogFile << "Trigger url: " << turl.c_str() << std::endl;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Trigger url: "
- << turl.c_str() << std::endl);
+ }
+ 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.c_str() << std::endl);
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
- << error_buffer << std::endl);
+ 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.size())
- {
- *this->LogFile
- << " Curl output was: "
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << 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);
- }
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
::curl_easy_cleanup(curl);
::curl_global_cleanup();
return false;
- }
+ }
- if ( chunk.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
- }
- if ( chunkDebug.size() > 0 )
- {
- cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
- << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size())
- << "]" << std::endl);
- }
+ 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);
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
- }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl,
+ this->Quiet);
}
+ }
::curl_global_cleanup();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Dart server triggered..."
- << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Dart server triggered..." << std::endl, this->Quiet);
return true;
}
-//----------------------------------------------------------------------------
-bool cmCTestSubmitHandler::SubmitUsingSCP(
- const cmStdString& scp_command,
- const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url)
+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.size() || !localprefix.size() ||
- !files.size() || !remoteprefix.size() || !url.size() )
- {
- return 0;
- }
+ 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(0);
+ argv.push_back(CM_NULLPTR);
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- //cmsysProcess_SetTimeout(cp, timeout);
+ // cmsysProcess_SetTimeout(cp, timeout);
int problems = 0;
cmCTest::SetOfStrings::const_iterator file;
- for ( file = files.begin(); file != files.end(); ++file )
- {
+ for (file = files.begin(); file != files.end(); ++file) {
int retVal;
std::string lfname = localprefix;
@@ -840,124 +784,114 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(
argv[1] = lfname.c_str();
std::string rfname = url + "/" + remoteprefix + *file;
argv[2] = rfname.c_str();
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \"" << argv[0]
- << "\" \"" << argv[1] << "\" \""
- << argv[2] << "\"" << std::endl);
+ 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;
+ << 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);
+ }
- while(cmsysProcess_WaitForData(cp, &data, &length, 0))
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(data, length));
- }
-
- cmsysProcess_WaitForExit(cp, 0);
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
int result = cmsysProcess_GetState(cp);
- if(result == cmsysProcess_State_Exited)
- {
+ if (result == cmsysProcess_State_Exited) {
retVal = cmsysProcess_GetExitValue(cp);
- if ( retVal != 0 )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "\tSCP returned: "
- << retVal << std::endl);
+ if (retVal != 0) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "\tSCP returned: " << retVal << std::endl,
+ this->Quiet);
*this->LogFile << "\tSCP returned: " << retVal << std::endl;
- problems ++;
- }
+ problems++;
}
- else if(result == cmsysProcess_State_Exception)
- {
+ } else if (result == cmsysProcess_State_Exception) {
retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
- << retVal << std::endl);
+ 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)
- {
+ problems++;
+ } else if (result == cmsysProcess_State_Expired) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
- << std::endl);
+ << std::endl);
*this->LogFile << "\tThere was a timeout" << std::endl;
- problems ++;
- }
- else if(result == cmsysProcess_State_Error)
- {
+ problems++;
+ } else if (result == cmsysProcess_State_Error) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ << cmsysProcess_GetErrorString(cp) << std::endl);
*this->LogFile << "\tError executing SCP: "
- << cmsysProcess_GetErrorString(cp) << std::endl;
- problems ++;
- }
+ << cmsysProcess_GetErrorString(cp) << std::endl;
+ problems++;
}
+ }
cmsysProcess_Delete(cp);
- if ( problems )
- {
- return false;
- }
- return true;
+ return problems == 0;
}
-//----------------------------------------------------------------------------
-bool cmCTestSubmitHandler::SubmitUsingCP(
- const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& destination)
+bool cmCTestSubmitHandler::SubmitUsingCP(const std::string& localprefix,
+ const std::set<std::string>& files,
+ const std::string& remoteprefix,
+ const std::string& destination)
{
- if ( !localprefix.size() ||
- !files.size() || !remoteprefix.size() || !destination.size() )
- {
+ 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);
- return 0;
- }
+ /* clang-format on */
+ return false;
+ }
+
cmCTest::SetOfStrings::const_iterator file;
- bool problems = false;
- for ( file = files.begin(); file != files.end(); ++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.c_str(), rfname.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Copy file: "
- << lfname.c_str() << " to "
- << rfname.c_str() << std::endl);
- }
+ 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.c_str(), true);
- if ( problems )
- {
- return false;
- }
+ cmSystemTools::Touch(tagDoneFile, true);
return true;
}
-
-//----------------------------------------------------------------------------
#if defined(CTEST_USE_XMLRPC)
-bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url)
+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());
- cmStdString realURL = url + "/" + remoteprefix + "/Command/";
+ std::string realURL = url + "/" + remoteprefix + "/Command/";
/* Start up our XML-RPC client library. */
xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, ctestString, ctestVersion);
@@ -966,76 +900,72 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
xmlrpc_env_init(&env);
/* Call the famous server at UserLand. */
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submitting to: "
- << realURL.c_str() << " (" << remoteprefix.c_str() << ")" << std::endl);
+ 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;
+ for (file = files.begin(); file != files.end(); ++file) {
+ xmlrpc_value* result;
- cmStdString local_file = *file;
- if ( !cmSystemTools::FileExists(local_file.c_str()) )
- {
+ std::string local_file = *file;
+ if (!cmSystemTools::FileExists(local_file.c_str())) {
local_file = localprefix + "/" + *file;
- }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submit file: "
- << local_file.c_str() << std::endl);
+ }
+ 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.c_str() << std::endl);
+ 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.c_str() << std::endl);
+ 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 = fopen(local_file.c_str(), "rb");
- if ( !fp )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot open file: "
- << local_file.c_str() << std::endl);
+ 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;
+ 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.c_str() << std::endl);
+ 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 );
+ result = xmlrpc_client_call(&env, pRealURL, remoteCommand, "(6)",
+ fileBuffer, (xmlrpc_int32)fileSize);
- delete [] fileBuffer;
+ delete[] fileBuffer;
- if ( env.fault_occurred )
- {
+ if (env.fault_occurred) {
cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: "
- << env.fault_string << " (" << env.fault_code << ")" << std::endl);
+ << 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);
@@ -1045,126 +975,335 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
return true;
}
#else
-bool cmCTestSubmitHandler::SubmitUsingXMLRPC(cmStdString const&,
- std::set<cmStdString> const&,
- cmStdString const&,
- cmStdString const&)
+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)
+{
+ if (file.empty()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Upload file not specified\n");
+ return -1;
+ }
+ if (!cmSystemTools::FileExists(file)) {
+ 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);
+ 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")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Only http and https are supported for CDASH_UPLOAD\n");
+ return -1;
+ }
+ bool internalTest = cmSystemTools::IsOn(this->GetOption("InternalTest"));
+
+ // Get RETRY_COUNT and RETRY_DELAY values if they were set.
+ std::string retryDelayString = this->GetOption("RetryDelay") == CM_NULLPTR
+ ? ""
+ : this->GetOption("RetryDelay");
+ std::string retryCountString = this->GetOption("RetryCount") == CM_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);
+ }
+ }
+ 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);
+ }
+ }
+
+ char md5sum[33];
+ md5sum[32] = 0;
+ cmSystemTools::ComputeFileMD5(file, md5sum);
+ // 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"));
+ 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) << "&";
+ }
+ str << "stamp=" << curl.Escape(this->CTest->GetCurrentTag()) << "-"
+ << curl.Escape(this->CTest->GetTestModelString()) << "&"
+ << "model=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
+ << "build="
+ << curl.Escape(this->CTest->GetCTestConfiguration("BuildName")) << "&"
+ << "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site"))
+ << "&"
+ << "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
+ << "starttime=" << (int)cmSystemTools::GetTime() << "&"
+ << "endtime=" << (int)cmSystemTools::GetTime() << "&"
+ << "datafilesmd5[0]=" << md5sum << "&"
+ << "type=" << curl.Escape(typeString);
+ std::string fields = str.str();
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "fields: " << fields << "\nurl:" << url
+ << "\nfile: " << file << "\n",
+ this->Quiet);
+ std::string response;
+
+ bool requestSucceeded = curl.HttpRequest(url, fields, response);
+ if (!internalTest && !requestSucceeded) {
+ // If request failed, wait and retry.
+ for (unsigned long i = 0; i < retryCount; i++) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Request failed, waiting " << retryDelay
+ << " seconds...\n",
+ this->Quiet);
+
+ double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay);
+ while (cmSystemTools::GetTime() < stop) {
+ cmSystemTools::Delay(100);
+ }
+
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Retry request: Attempt "
+ << (i + 1) << " of " << retryCount << std::endl,
+ this->Quiet);
+
+ requestSucceeded = curl.HttpRequest(url, fields, response);
+ if (requestSucceeded) {
+ break;
+ }
+ }
+ }
+ if (!internalTest && !requestSucceeded) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in HttpRequest\n"
+ << response);
+ return -1;
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Request upload response: [" << response << "]\n",
+ this->Quiet);
+ Json::Value json;
+ Json::Reader reader;
+ if (!internalTest && !reader.parse(response, json)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string ["
+ << response << "]\n"
+ << reader.getFormattedErrorMessages() << "\n");
+ return -1;
+ }
+ if (!internalTest && json["status"].asInt() != 0) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Bad status returned from CDash: " << json["status"].asInt());
+ return -1;
+ }
+ if (!internalTest) {
+ if (json["datafilesmd5"].isArray()) {
+ int datares = json["datafilesmd5"][0].asInt();
+ if (datares == 1) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "File already exists on CDash, skip upload "
+ << file << "\n",
+ this->Quiet);
+ return 0;
+ }
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "bad datafilesmd5 value in response " << response << "\n");
+ return -1;
+ }
+ }
+
+ std::string upload_as = cmSystemTools::GetFilenameName(file);
+ std::ostringstream fstr;
+ fstr << "type=" << curl.Escape(typeString) << "&"
+ << "md5=" << md5sum << "&"
+ << "filename=" << curl.Escape(upload_as) << "&"
+ << "buildid=" << json["buildid"].asString();
+
+ bool uploadSucceeded = false;
+ if (!internalTest) {
+ uploadSucceeded = curl.UploadFile(file, url, fstr.str(), response);
+ }
+
+ if (!uploadSucceeded) {
+ // If upload failed, wait and retry.
+ for (unsigned long i = 0; i < retryCount; i++) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Upload failed, waiting " << retryDelay
+ << " seconds...\n",
+ this->Quiet);
+
+ double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay);
+ while (cmSystemTools::GetTime() < stop) {
+ cmSystemTools::Delay(100);
+ }
+
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Retry upload: Attempt "
+ << (i + 1) << " of " << retryCount << std::endl,
+ this->Quiet);
+
+ if (!internalTest) {
+ uploadSucceeded = curl.UploadFile(file, url, fstr.str(), response);
+ }
+ if (uploadSucceeded) {
+ break;
+ }
+ }
+ }
+
+ if (!uploadSucceeded) {
+ 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 ["
+ << response << "]\n"
+ << reader.getFormattedErrorMessages() << "\n");
+ return -1;
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Upload file response: [" << response << "]\n",
+ this->Quiet);
+ return 0;
+}
+
int cmCTestSubmitHandler::ProcessHandler()
{
+ const char* cdashUploadFile = this->GetOption("CDashUploadFile");
+ const char* cdashUploadType = this->GetOption("CDashUploadType");
+ 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.size())
- {
+ if (!iscdash.empty()) {
this->CDash = true;
- }
+ }
- const std::string &buildDirectory
- = this->CTest->GetCTestConfiguration("BuildDirectory");
- if ( buildDirectory.size() == 0 )
- {
+ const std::string& buildDirectory =
+ this->CTest->GetCTestConfiguration("BuildDirectory");
+ if (buildDirectory.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find BuildDirectory key in the DartConfiguration.tcl"
- << std::endl);
+ "Cannot find BuildDirectory key in the DartConfiguration.tcl"
+ << std::endl);
return -1;
- }
+ }
- if ( getenv("HTTP_PROXY") )
- {
+ if (getenv("HTTP_PROXY")) {
this->HTTPProxyType = 1;
this->HTTPProxy = getenv("HTTP_PROXY");
- if ( getenv("HTTP_PROXY_PORT") )
- {
+ if (getenv("HTTP_PROXY_PORT")) {
this->HTTPProxy += ":";
this->HTTPProxy += getenv("HTTP_PROXY_PORT");
- }
- if ( getenv("HTTP_PROXY_TYPE") )
- {
- cmStdString type = getenv("HTTP_PROXY_TYPE");
+ }
+ if (getenv("HTTP_PROXY_TYPE")) {
+ std::string type = getenv("HTTP_PROXY_TYPE");
// HTTP/SOCKS4/SOCKS5
- if ( type == "HTTP" )
- {
+ if (type == "HTTP") {
this->HTTPProxyType = 1;
- }
- else if ( type == "SOCKS4" )
- {
+ } else if (type == "SOCKS4") {
this->HTTPProxyType = 2;
- }
- else if ( type == "SOCKS5" )
- {
+ } else if (type == "SOCKS5") {
this->HTTPProxyType = 3;
- }
}
- if ( getenv("HTTP_PROXY_USER") )
- {
+ }
+ if (getenv("HTTP_PROXY_USER")) {
this->HTTPProxyAuth = getenv("HTTP_PROXY_USER");
- }
- if ( getenv("HTTP_PROXY_PASSWD") )
- {
+ }
+ if (getenv("HTTP_PROXY_PASSWD")) {
this->HTTPProxyAuth += ":";
this->HTTPProxyAuth += getenv("HTTP_PROXY_PASSWD");
- }
}
+ }
- if ( getenv("FTP_PROXY") )
- {
+ if (getenv("FTP_PROXY")) {
this->FTPProxyType = 1;
this->FTPProxy = getenv("FTP_PROXY");
- if ( getenv("FTP_PROXY_PORT") )
- {
+ if (getenv("FTP_PROXY_PORT")) {
this->FTPProxy += ":";
this->FTPProxy += getenv("FTP_PROXY_PORT");
- }
- if ( getenv("FTP_PROXY_TYPE") )
- {
- cmStdString type = getenv("FTP_PROXY_TYPE");
+ }
+ if (getenv("FTP_PROXY_TYPE")) {
+ std::string type = getenv("FTP_PROXY_TYPE");
// HTTP/SOCKS4/SOCKS5
- if ( type == "HTTP" )
- {
+ if (type == "HTTP") {
this->FTPProxyType = 1;
- }
- else if ( type == "SOCKS4" )
- {
+ } else if (type == "SOCKS4") {
this->FTPProxyType = 2;
- }
- else if ( type == "SOCKS5" )
- {
+ } else if (type == "SOCKS5") {
this->FTPProxyType = 3;
- }
}
}
-
- if ( this->HTTPProxy.size() > 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use HTTP Proxy: "
- << this->HTTPProxy << std::endl);
- }
- if ( this->FTPProxy.size() > 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use FTP Proxy: "
- << this->FTPProxy << std::endl);
- }
+ }
+
+ 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::string prefix = this->GetSubmitResultsPrefix();
- if (!this->Files.empty())
- {
+ if (!this->Files.empty()) {
// Submit the explicitly selected files:
//
- cmCTest::SetOfStrings::const_iterator it;
- for (it = this->Files.begin(); it != this->Files.end(); ++it)
- {
- files.insert(*it);
- }
- }
+ files.insert(this->Files.begin(), this->Files.end());
+ }
// Add to the list of files to submit from any selected, existing parts:
//
@@ -1176,333 +1315,292 @@ int cmCTestSubmitHandler::ProcessHandler()
this->CTest->AddIfExists(cmCTest::PartConfigure, "Configure.xml");
this->CTest->AddIfExists(cmCTest::PartBuild, "Build.xml");
this->CTest->AddIfExists(cmCTest::PartTest, "Test.xml");
- if(this->CTest->AddIfExists(cmCTest::PartCoverage, "Coverage.xml"))
- {
- cmCTest::VectorOfStrings gfiles;
- std::string gpath
- = buildDirectory + "/Testing/" + this->CTest->GetCurrentTag();
+ if (this->CTest->AddIfExists(cmCTest::PartCoverage, "Coverage.xml")) {
+ std::vector<std::string> gfiles;
+ std::string gpath =
+ buildDirectory + "/Testing/" + this->CTest->GetCurrentTag();
std::string::size_type glen = gpath.size() + 1;
gpath = gpath + "/CoverageLog*";
- cmCTestLog(this->CTest, DEBUG, "Globbing for: " << gpath.c_str()
- << std::endl);
- if ( cmSystemTools::SimpleGlob(gpath, gfiles, 1) )
- {
+ 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 ++ )
- {
+ for (cc = 0; cc < gfiles.size(); cc++) {
gfiles[cc] = gfiles[cc].substr(glen);
- cmCTestLog(this->CTest, DEBUG, "Glob file: " << gfiles[cc].c_str()
- << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Glob file: " << gfiles[cc] << std::endl,
+ this->Quiet);
this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfiles[cc].c_str());
- }
}
- else
- {
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl);
- }
}
+ }
this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml");
this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml");
this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml");
this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml");
// Query parts for files to submit.
- for(cmCTest::Part p = cmCTest::PartStart;
- p != cmCTest::PartCount; p = cmCTest::Part(p+1))
- {
+ for (cmCTest::Part p = cmCTest::PartStart; p != cmCTest::PartCount;
+ p = cmCTest::Part(p + 1)) {
// Skip parts we are not submitting.
- if(!this->SubmitPart[p])
- {
+ if (!this->SubmitPart[p]) {
continue;
- }
+ }
// Submit files from this part.
std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
- for(std::vector<std::string>::const_iterator pi = pfiles.begin();
- pi != pfiles.end(); ++pi)
- {
- files.insert(*pi);
- }
- }
+ files.insert(pfiles.begin(), pfiles.end());
+ }
- if ( ofs )
- {
+ 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->c_str() << std::endl;
- cnt ++;
- }
+ for (it = files.begin(); it != files.end(); ++it) {
+ ofs << cnt << "\t" << *it << std::endl;
+ cnt++;
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
- << this->CTest->GetCTestConfiguration("DropMethod") << ")"
- << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
+ << this->CTest->GetCTestConfiguration("DropMethod")
+ << ")" << std::endl,
+ this->Quiet);
const char* specificTrack = this->CTest->GetSpecificTrack();
- if ( specificTrack )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Send to track: "
- << specificTrack << std::endl);
- }
+ if (specificTrack) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Send to track: " << specificTrack << std::endl,
+ this->Quiet);
+ }
this->SetLogFile(&ofs);
- cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
+ std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
- if ( dropMethod == "" || dropMethod == "ftp" )
- {
+ if (dropMethod == "" || dropMethod == "ftp") {
ofs << "Using drop method: FTP" << std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using FTP submit method"
- << std::endl
- << " Drop site: ftp://");
+ 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").size() > 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration(
- "DropSiteUser").c_str());
- if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
- }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
+ 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);
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSite")
- << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
- if ( !this->SubmitUsingFTP(buildDirectory + "/Testing/"
- + this->CTest->GetCurrentTag(),
- files, prefix, url) )
- {
+ 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);
+ " Problems when submitting via FTP" << std::endl);
ofs << " Problems when submitting via FTP" << std::endl;
return -1;
- }
- if(!this->CDash)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
- << std::endl
- << " Trigger site: "
- << this->CTest->GetCTestConfiguration("TriggerSite")
- << std::endl);
- if ( !this->
- TriggerUsingHTTP(files, prefix,
- this->CTest->GetCTestConfiguration("TriggerSite")))
- {
+ }
+ 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;
- }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
- << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Submission successful" << std::endl, this->Quiet);
ofs << " Submission successful" << std::endl;
return 0;
- }
}
- else if ( dropMethod == "http" || dropMethod == "https" )
- {
+ } else if (dropMethod == "http" || dropMethod == "https") {
std::string url = dropMethod;
url += "://";
ofs << "Using drop method: " << dropMethod << std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP submit method"
- << std::endl
- << " Drop site:" << url);
- if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
- {
+ 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");
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSiteUser").c_str());
- if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
- {
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetCTestConfiguration("DropSiteUser").c_str(),
+ this->Quiet);
+ if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) {
url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
- }
- url += "@";
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******",
+ this->Quiet);
}
+ url += "@";
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "@", this->Quiet);
+ }
url += this->CTest->GetCTestConfiguration("DropSite") +
this->CTest->GetCTestConfiguration("DropLocation");
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSite")
- << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
- if ( !this->SubmitUsingHTTP(buildDirectory + "/Testing/" +
- this->CTest->GetCurrentTag(), files, prefix, url) )
- {
+ 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);
+ " Problems when submitting via HTTP" << std::endl);
ofs << " Problems when submitting via HTTP" << std::endl;
return -1;
- }
- if(!this->CDash)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
- << std::endl
- << " Trigger site: "
- << this->CTest->GetCTestConfiguration("TriggerSite")
- << std::endl);
- if ( !this->
- TriggerUsingHTTP(files, prefix,
- this->CTest->GetCTestConfiguration("TriggerSite")))
- {
+ }
+ 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)
- {
+ }
+ if (this->HasErrors) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during "
- "submission." << std::endl);
+ "submission."
+ << std::endl);
ofs << " Errors occurred during submission. " << std::endl;
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful" <<
- (this->HasWarnings ? ", with warnings." : "") << std::endl);
- ofs << " Submission successful" <<
- (this->HasWarnings ? ", with warnings." : "") << 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" )
- {
+ } else if (dropMethod == "xmlrpc") {
#if defined(CTEST_USE_XMLRPC)
ofs << "Using drop method: XML-RPC" << std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using XML-RPC submit method"
- << 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) )
- {
+ if (!this->SubmitUsingXMLRPC(buildDirectory + "/Testing/" +
+ this->CTest->GetCurrentTag(),
+ files, prefix, url)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when submitting via XML-RPC" << std::endl);
+ " Problems when submitting via XML-RPC" << std::endl);
ofs << " Problems when submitting via XML-RPC" << std::endl;
return -1;
- }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
- << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Submission successful" << std::endl, this->Quiet);
ofs << " Submission successful" << std::endl;
return 0;
#else
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Submission method \"xmlrpc\" not compiled into CTest!"
- << std::endl);
+ << std::endl);
return -1;
#endif
- }
- else if ( dropMethod == "scp" )
- {
+ } else if (dropMethod == "scp") {
std::string url;
- std::string oldWorkingDirectory;
- if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
- {
+ 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
- oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(buildDirectory.c_str());
-
- if ( !this->SubmitUsingSCP(
- this->CTest->GetCTestConfiguration("ScpCommand"),
- "Testing/"+this->CTest->GetCurrentTag(), files, prefix, url) )
- {
- cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
+ 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);
+ " Problems when submitting via SCP" << std::endl);
ofs << " Problems when submitting via SCP" << std::endl;
return -1;
- }
- cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
- << std::endl);
+ }
+ 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");
-
+ } 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
- std::string
- oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(buildDirectory.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Change directory: "
- << buildDirectory.c_str() << std::endl);
-
- if ( !this->SubmitUsingCP(
- "Testing/"+this->CTest->GetCurrentTag(),
- files,
- prefix,
- location) )
- {
- cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
+ cmWorkingDirectory workdir(buildDirectory);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Change directory: " << buildDirectory << 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);
+ " Problems when submitting via CP" << std::endl);
ofs << " Problems when submitting via cp" << std::endl;
return -1;
- }
- cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
- << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Submission successful" << std::endl, this->Quiet);
ofs << " Submission successful" << std::endl;
return 0;
- }
+ }
cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \""
- << dropMethod << "\"" << std::endl);
+ << dropMethod << "\"" << std::endl);
return -1;
}
-//----------------------------------------------------------------------------
std::string cmCTestSubmitHandler::GetSubmitResultsPrefix()
{
- std::string name = this->CTest->GetCTestConfiguration("Site") +
- "___" + this->CTest->GetCTestConfiguration("BuildName") +
- "___" + this->CTest->GetCurrentTag() + "-" +
+ std::string buildname =
+ cmCTest::SafeBuildIdField(this->CTest->GetCTestConfiguration("BuildName"));
+ std::string name = this->CTest->GetCTestConfiguration("Site") + "___" +
+ buildname + "___" + this->CTest->GetCurrentTag() + "-" +
this->CTest->GetTestModelString() + "___XML___";
return name;
}
-//----------------------------------------------------------------------------
void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)
{
// Check whether each part is selected.
- for(cmCTest::Part p = cmCTest::PartStart;
- p != cmCTest::PartCount; p = cmCTest::Part(p+1))
- {
+ for (cmCTest::Part p = cmCTest::PartStart; p != cmCTest::PartCount;
+ p = cmCTest::Part(p + 1)) {
this->SubmitPart[p] =
(std::set<cmCTest::Part>::const_iterator(parts.find(p)) != parts.end());
- }
+ }
}
-//----------------------------------------------------------------------------
void cmCTestSubmitHandler::SelectFiles(cmCTest::SetOfStrings const& files)
{
- cmCTest::SetOfStrings::const_iterator it;
- for (it = files.begin(); it != files.end(); ++it)
- {
- this->Files.insert(*it);
- }
+ this->Files.insert(files.begin(), files.end());
}
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index 14eac80b5..2923f4f3d 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestSubmitHandler_h
#define cmCTestSubmitHandler_h
+#include "cmConfigure.h"
+
+#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
+
/** \class cmCTestSubmitHandler
* \brief Helper class for CTest
*
@@ -23,17 +22,17 @@
class cmCTestSubmitHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestSubmitHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
cmCTestSubmitHandler();
- ~cmCTestSubmitHandler() { this->LogFile = 0; }
+ ~cmCTestSubmitHandler() CM_OVERRIDE { this->LogFile = CM_NULLPTR; }
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
- void Initialize();
+ void Initialize() CM_OVERRIDE;
/** Specify a set of parts (by name) to submit. */
void SelectParts(std::set<cmCTest::Part> const& parts);
@@ -41,39 +40,46 @@ public:
/** Specify a set of files to submit. */
void SelectFiles(cmCTest::SetOfStrings const& files);
+ // handle the cdash file upload protocol
+ int HandleCDashUploadFile(std::string const& file, std::string const& type);
+
+ void SetHttpHeaders(std::vector<std::string> const& v)
+ {
+ 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 cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url);
- bool SubmitUsingHTTP(const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url);
- bool SubmitUsingSCP(const cmStdString& scp_command,
- const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url);
-
- bool SubmitUsingCP( const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url);
-
- bool TriggerUsingHTTP(const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url);
-
- bool SubmitUsingXMLRPC(const cmStdString& localprefix,
- const std::set<cmStdString>& files,
- const cmStdString& remoteprefix,
- const cmStdString& url);
+ 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::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;
@@ -81,18 +87,20 @@ private:
std::string GetSubmitResultsPrefix();
- class ResponseParser;
- cmStdString HTTPProxy;
- int HTTPProxyType;
- cmStdString HTTPProxyAuth;
- cmStdString FTPProxy;
- int FTPProxyType;
+ class ResponseParser;
+
+ 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::vector<std::string> HttpHeaders;
};
#endif
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 231f035fb..075b1403a 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -1,18 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestTestCommand.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <stdlib.h>
+#include <vector>
cmCTestTestCommand::cmCTestTestCommand()
{
@@ -23,10 +20,14 @@ cmCTestTestCommand::cmCTestTestCommand()
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_LAST] = 0;
+ this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD";
+ this->Arguments[ctt_LAST] = CM_NULLPTR;
this->Last = ctt_LAST;
}
@@ -35,74 +36,95 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
const char* ctestTimeout =
this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
- double timeout = this->CTest->GetTimeOut();
- if ( ctestTimeout )
- {
+ double timeout;
+ if (ctestTimeout) {
timeout = atof(ctestTimeout);
- }
- else
- {
- if ( timeout <= 0 )
- {
+ } else {
+ timeout = this->CTest->GetTimeOut();
+ if (timeout <= 0) {
// By default use timeout of 10 minutes
timeout = 600;
- }
}
+ }
this->CTest->SetTimeOut(timeout);
cmCTestGenericHandler* handler = this->InitializeActualHandler();
- if ( this->Values[ctt_START] || this->Values[ctt_END] ||
- this->Values[ctt_STRIDE] )
- {
- cmOStringStream testsToRunString;
- if ( this->Values[ctt_START] )
- {
+ 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] )
- {
+ if (this->Values[ctt_END]) {
testsToRunString << this->Values[ctt_END];
- }
+ }
testsToRunString << ",";
- if ( this->Values[ctt_STRIDE] )
- {
+ if (this->Values[ctt_STRIDE]) {
testsToRunString << this->Values[ctt_STRIDE];
- }
- handler->SetOption("TestsToRunInformation",
- testsToRunString.str().c_str());
}
- if(this->Values[ctt_EXCLUDE])
- {
+ handler->SetOption("TestsToRunInformation",
+ testsToRunString.str().c_str());
+ }
+ if (this->Values[ctt_EXCLUDE]) {
handler->SetOption("ExcludeRegularExpression", this->Values[ctt_EXCLUDE]);
- }
- if(this->Values[ctt_INCLUDE])
- {
+ }
+ if (this->Values[ctt_INCLUDE]) {
handler->SetOption("IncludeRegularExpression", this->Values[ctt_INCLUDE]);
- }
- if(this->Values[ctt_EXCLUDE_LABEL])
- {
+ }
+ if (this->Values[ctt_EXCLUDE_LABEL]) {
handler->SetOption("ExcludeLabelRegularExpression",
this->Values[ctt_EXCLUDE_LABEL]);
- }
- if(this->Values[ctt_INCLUDE_LABEL])
- {
+ }
+ if (this->Values[ctt_INCLUDE_LABEL]) {
handler->SetOption("LabelRegularExpression",
this->Values[ctt_INCLUDE_LABEL]);
- }
- if(this->Values[ctt_PARALLEL_LEVEL])
- {
- handler->SetOption("ParallelLevel",
- this->Values[ctt_PARALLEL_LEVEL]);
- }
- if(this->Values[ctt_SCHEDULE_RANDOM])
- {
- handler->SetOption("ScheduleRandom",
- this->Values[ctt_SCHEDULE_RANDOM]);
- }
- if(this->Values[ctt_STOP_TIME])
- {
+ }
+ if (this->Values[ctt_EXCLUDE_FIXTURE]) {
+ handler->SetOption("ExcludeFixtureRegularExpression",
+ this->Values[ctt_EXCLUDE_FIXTURE]);
+ }
+ if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) {
+ handler->SetOption("ExcludeFixtureSetupRegularExpression",
+ this->Values[ctt_EXCLUDE_FIXTURE_SETUP]);
+ }
+ if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) {
+ handler->SetOption("ExcludeFixtureCleanupRegularExpression",
+ this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]);
+ }
+ if (this->Values[ctt_PARALLEL_LEVEL]) {
+ handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]);
+ }
+ if (this->Values[ctt_SCHEDULE_RANDOM]) {
+ handler->SetOption("ScheduleRandom", this->Values[ctt_SCHEDULE_RANDOM]);
+ }
+ if (this->Values[ctt_STOP_TIME]) {
this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]);
+ }
+
+ // Test load is determined by: TEST_LOAD argument,
+ // or CTEST_TEST_LOAD script variable, or ctest --test-load
+ // 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)) {
+ testLoad = 0;
+ cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : "
+ << this->Values[ctt_TEST_LOAD] << std::endl);
}
+ } else if (ctestTestLoad && *ctestTestLoad) {
+ if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) {
+ testLoad = 0;
+ cmCTestLog(this->CTest, WARNING, "Invalid value for 'CTEST_TEST_LOAD' : "
+ << ctestTestLoad << std::endl);
+ }
+ } else {
+ testLoad = this->CTest->GetTestLoad();
+ }
+ handler->SetTestLoad(testLoad);
+
+ handler->SetQuiet(this->Quiet);
return handler;
}
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 130cb6973..be7e7831f 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestTestCommand_h
#define cmCTestTestCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestHandlerCommand.h"
+#include <string>
+
+class cmCTestGenericHandler;
+class cmCommand;
+
/** \class cmCTestTest
* \brief Run a ctest script
*
@@ -22,71 +20,30 @@
class cmCTestTestCommand : public cmCTestHandlerCommand
{
public:
-
cmCTestTestCommand();
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestTestCommand* ni = new cmCTestTestCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "ctest_test";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Run tests in the project build tree.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_test([BUILD build_dir] [APPEND]\n"
- " [START start number] [END end number]\n"
- " [STRIDE stride number] [EXCLUDE exclude regex ]\n"
- " [INCLUDE include regex] [RETURN_VALUE res] \n"
- " [EXCLUDE_LABEL exclude regex] \n"
- " [INCLUDE_LABEL label regex] \n"
- " [PARALLEL_LEVEL level] \n"
- " [SCHEDULE_RANDOM on] \n"
- " [STOP_TIME time of day]) \n"
- "Tests the given build directory and stores results in Test.xml. The "
- "second argument is a variable that will hold value. Optionally, "
- "you can specify the starting test number START, the ending test number "
- "END, the number of tests to skip between each test STRIDE, a regular "
- "expression for tests to run INCLUDE, or a regular expression for tests "
- "to not run EXCLUDE. EXCLUDE_LABEL and INCLUDE_LABEL are regular "
- "expression for test to be included or excluded by the test "
- "property LABEL. PARALLEL_LEVEL should be set to a positive number "
- "representing the number of tests to be run in parallel. "
- "SCHEDULE_RANDOM will launch tests in a random order, and is "
- "typically used to detect implicit test dependencies. STOP_TIME is the "
- "time of day at which the tests should all stop running."
- "\n"
- CTEST_COMMAND_APPEND_OPTION_DOCS;
- }
-
- cmTypeMacro(cmCTestTestCommand, cmCTestHandlerCommand);
+ std::string GetName() const CM_OVERRIDE { return "ctest_test"; }
protected:
virtual cmCTestGenericHandler* InitializeActualHandler();
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
- enum {
+ enum
+ {
ctt_BUILD = ct_LAST,
ctt_RETURN_VALUE,
ctt_START,
@@ -96,12 +53,15 @@ protected:
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
};
};
-
#endif
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 497774d1b..674be6052 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1,424 +1,319 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestTestHandler.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "cmsys/Base64.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <functional>
+#include <iomanip>
+#include <iterator>
+#include <set>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
-#include "cmCTestTestHandler.h"
-#include "cmCTestMultiProcessHandler.h"
-#include "cmCTestBatchTestHandler.h"
+#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmCTestRunTest.h"
-#include "cmake.h"
+#include "cmCTestBatchTestHandler.h"
+#include "cmCTestMultiProcessHandler.h"
+#include "cmCommand.h"
#include "cmGeneratedFileStream.h"
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Base64.h>
-#include "cmMakefile.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmCommand.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmWorkingDirectory.h"
+#include "cmXMLWriter.h"
+#include "cm_auto_ptr.hxx"
#include "cm_utf8.h"
+#include "cmake.h"
-#include <stdlib.h>
-#include <math.h>
-#include <float.h>
-
-#include <set>
+class cmExecutionStatus;
-//----------------------------------------------------------------------
class cmCTestSubdirCommand : public cmCommand
{
public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestSubdirCommand* c = new cmCTestSubdirCommand;
c->TestHandler = this->TestHandler;
return c;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "subdirs";}
-
- // Unused methods
- virtual const char* GetTerseDocumentation() const { return ""; }
- virtual const char* GetFullDocumentation() const { return ""; }
-
- cmTypeMacro(cmCTestSubdirCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/) CM_OVERRIDE;
cmCTestTestHandler* TestHandler;
};
-//----------------------------------------------------------------------
-bool cmCTestSubdirCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->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 (it = args.begin(); it != args.end(); ++it) {
std::string fname;
- if(cmSystemTools::FileIsFullPath(it->c_str()))
- {
+ if (cmSystemTools::FileIsFullPath(it->c_str())) {
fname = *it;
- }
- else
- {
+ } else {
fname = cwd;
fname += "/";
fname += *it;
- }
+ }
- if ( !cmSystemTools::FileIsDirectory(fname.c_str()) )
- {
+ if (!cmSystemTools::FileIsDirectory(fname)) {
// No subdirectory? So what...
continue;
+ }
+ bool readit = false;
+ {
+ cmWorkingDirectory workdir(fname);
+ const char* testFilename;
+ if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
+ // does the CTestTestfile.cmake exist ?
+ testFilename = "CTestTestfile.cmake";
+ } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
+ // does the DartTestfile.txt exist ?
+ testFilename = "DartTestfile.txt";
+ } else {
+ // No CTestTestfile? Who cares...
+ continue;
}
- cmSystemTools::ChangeDirectory(fname.c_str());
- const char* testFilename;
- if( cmSystemTools::FileExists("CTestTestfile.cmake") )
- {
- // does the CTestTestfile.cmake exist ?
- testFilename = "CTestTestfile.cmake";
- }
- else if( cmSystemTools::FileExists("DartTestfile.txt") )
- {
- // does the DartTestfile.txt exist ?
- testFilename = "DartTestfile.txt";
- }
- else
- {
- // No CTestTestfile? Who cares...
- continue;
- }
- fname += "/";
- fname += testFilename;
- bool readit =
- this->Makefile->ReadListFile(this->Makefile->GetCurrentListFile(),
- fname.c_str());
- cmSystemTools::ChangeDirectory(cwd.c_str());
- if(!readit)
- {
+ fname += "/";
+ fname += testFilename;
+ readit = this->Makefile->ReadDependentFile(fname.c_str());
+ }
+ if (!readit) {
std::string m = "Could not find include file: ";
m += fname;
- this->SetError(m.c_str());
+ this->SetError(m);
return false;
- }
}
- cmSystemTools::ChangeDirectory(cwd.c_str());
+ }
return true;
}
-//----------------------------------------------------------------------
class cmCTestAddSubdirectoryCommand : public cmCommand
{
public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ 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.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "add_subdirectory";}
-
- // Unused methods
- virtual const char* GetTerseDocumentation() const { return ""; }
- virtual const char* GetFullDocumentation() const { return ""; }
-
- cmTypeMacro(cmCTestAddSubdirectoryCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/) CM_OVERRIDE;
cmCTestTestHandler* TestHandler;
};
-//----------------------------------------------------------------------
-bool cmCTestAddSubdirectoryCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCTestAddSubdirectoryCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus& /*unused*/)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(cwd.c_str());
- std::string fname = cwd;
+ std::string fname = cmSystemTools::GetCurrentWorkingDirectory();
fname += "/";
- fname += args[1];
+ fname += args[0];
- if ( !cmSystemTools::FileExists(fname.c_str()) )
- {
+ if (!cmSystemTools::FileExists(fname.c_str())) {
// No subdirectory? So what...
return true;
+ }
+ bool readit = false;
+ {
+ const char* testFilename;
+ if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
+ // does the CTestTestfile.cmake exist ?
+ testFilename = "CTestTestfile.cmake";
+ } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
+ // does the DartTestfile.txt exist ?
+ testFilename = "DartTestfile.txt";
+ } else {
+ // No CTestTestfile? Who cares...
+ return true;
}
- cmSystemTools::ChangeDirectory(fname.c_str());
- const char* testFilename;
- if( cmSystemTools::FileExists("CTestTestfile.cmake") )
- {
- // does the CTestTestfile.cmake exist ?
- testFilename = "CTestTestfile.cmake";
- }
- else if( cmSystemTools::FileExists("DartTestfile.txt") )
- {
- // does the DartTestfile.txt exist ?
- testFilename = "DartTestfile.txt";
- }
- else
- {
- // No CTestTestfile? Who cares...
- cmSystemTools::ChangeDirectory(cwd.c_str());
- return true;
- }
- fname += "/";
- fname += testFilename;
- bool readit =
- this->Makefile->ReadListFile(this->Makefile->GetCurrentListFile(),
- fname.c_str());
- cmSystemTools::ChangeDirectory(cwd.c_str());
- if(!readit)
- {
+ fname += "/";
+ fname += testFilename;
+ readit = this->Makefile->ReadDependentFile(fname.c_str());
+ }
+ if (!readit) {
std::string m = "Could not find include file: ";
m += fname;
- this->SetError(m.c_str());
+ this->SetError(m);
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------
class cmCTestAddTestCommand : public cmCommand
{
public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestAddTestCommand* c = new cmCTestAddTestCommand;
c->TestHandler = this->TestHandler;
return c;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "ADD_TEST";}
-
- // Unused methods
- virtual const char* GetTerseDocumentation() const { return ""; }
- virtual const char* GetFullDocumentation() const { return ""; }
-
- cmTypeMacro(cmCTestAddTestCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& /*args*/,
+ cmExecutionStatus& /*unused*/) CM_OVERRIDE;
cmCTestTestHandler* TestHandler;
};
-//----------------------------------------------------------------------
-bool cmCTestAddTestCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCTestAddTestCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& /*unused*/)
{
- if ( args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
return this->TestHandler->AddTest(args);
}
-//----------------------------------------------------------------------
class cmCTestSetTestsPropertiesCommand : public cmCommand
{
public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- cmCTestSetTestsPropertiesCommand* c
- = new cmCTestSetTestsPropertiesCommand;
+ cmCommand* Clone() CM_OVERRIDE
+ {
+ cmCTestSetTestsPropertiesCommand* c = new cmCTestSetTestsPropertiesCommand;
c->TestHandler = this->TestHandler;
return c;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &);
-
- /**
- * The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "SET_TESTS_PROPERTIES";}
-
- // Unused methods
- virtual const char* GetTerseDocumentation() const { return ""; }
- virtual const char* GetFullDocumentation() const { return ""; }
-
- cmTypeMacro(cmCTestSetTestsPropertiesCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& /*args*/,
+ cmExecutionStatus& /*unused*/) CM_OVERRIDE;
cmCTestTestHandler* TestHandler;
};
-//----------------------------------------------------------------------
-bool cmCTestSetTestsPropertiesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCTestSetTestsPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus& /*unused*/)
{
return this->TestHandler->SetTestsProperties(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.
// -1 is returned at the end of the list.
-inline int GetNextNumber(std::string const& in,
- int& val,
+inline int GetNextNumber(std::string const& in, int& val,
std::string::size_type& pos,
std::string::size_type& pos2)
{
pos2 = in.find(',', pos);
- if(pos2 != in.npos)
- {
- if(pos2-pos == 0)
- {
+ if (pos2 != std::string::npos) {
+ if (pos2 - pos == 0) {
val = -1;
- }
- else
- {
- val = atoi(in.substr(pos, pos2-pos).c_str());
- }
- pos = pos2+1;
- return 1;
- }
- else
- {
- if(in.size()-pos == 0)
- {
- val = -1;
- }
- else
- {
- val = atoi(in.substr(pos, in.size()-pos).c_str());
- }
- return 0;
+ } else {
+ val = atoi(in.substr(pos, pos2 - pos).c_str());
}
+ pos = pos2 + 1;
+ return 1;
+ }
+ if (in.size() - pos == 0) {
+ val = -1;
+ } else {
+ val = atoi(in.substr(pos, in.size() - pos).c_str());
+ }
+ return 0;
}
-//----------------------------------------------------------------------
// 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.
// -1 is returned at the end of the list.
-inline int GetNextRealNumber(std::string const& in,
- double& val,
+inline int GetNextRealNumber(std::string const& in, double& val,
std::string::size_type& pos,
std::string::size_type& pos2)
{
pos2 = in.find(',', pos);
- if(pos2 != in.npos)
- {
- if(pos2-pos == 0)
- {
+ if (pos2 != std::string::npos) {
+ if (pos2 - pos == 0) {
val = -1;
- }
- else
- {
- val = atof(in.substr(pos, pos2-pos).c_str());
- }
- pos = pos2+1;
- return 1;
- }
- else
- {
- if(in.size()-pos == 0)
- {
- val = -1;
- }
- else
- {
- val = atof(in.substr(pos, in.size()-pos).c_str());
- }
- return 0;
+ } else {
+ val = atof(in.substr(pos, pos2 - pos).c_str());
}
+ pos = pos2 + 1;
+ return 1;
+ }
+ if (in.size() - pos == 0) {
+ val = -1;
+ } else {
+ val = atof(in.substr(pos, in.size() - pos).c_str());
+ }
+ return 0;
}
-
-//----------------------------------------------------------------------
cmCTestTestHandler::cmCTestTestHandler()
{
this->UseUnion = false;
- this->UseIncludeLabelRegExpFlag = false;
- this->UseExcludeLabelRegExpFlag = false;
- this->UseIncludeRegExpFlag = false;
- this->UseExcludeRegExpFlag = false;
- this->UseExcludeRegExpFirst = false;
+ this->UseIncludeLabelRegExpFlag = false;
+ this->UseExcludeLabelRegExpFlag = false;
+ this->UseIncludeRegExpFlag = false;
+ this->UseExcludeRegExpFlag = false;
+ this->UseExcludeRegExpFirst = false;
this->CustomMaximumPassedTestOutputSize = 1 * 1024;
this->CustomMaximumFailedTestOutputSize = 300 * 1024;
this->MemCheck = false;
- this->LogFile = 0;
+ this->LogFile = CM_NULLPTR;
// regex to detect <DartMeasurement>...</DartMeasurement>
- this->DartStuff.compile(
- "(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
+ this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
// regex to detect each individual <DartMeasurement>...</DartMeasurement>
this->DartStuff1.compile(
"(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::Initialize()
{
this->Superclass::Initialize();
@@ -447,117 +342,120 @@ void cmCTestTestHandler::Initialize()
this->ExcludeLabelRegularExpression = "";
this->IncludeRegExp = "";
this->ExcludeRegExp = "";
+ this->ExcludeFixtureRegExp.clear();
+ this->ExcludeFixtureSetupRegExp.clear();
+ this->ExcludeFixtureCleanupRegExp.clear();
TestsToRunString = "";
this->UseUnion = false;
this->TestList.clear();
}
-//----------------------------------------------------------------------
-void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf)
+void cmCTestTestHandler::PopulateCustomVectors(cmMakefile* mf)
{
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_TEST",
- this->CustomPreTest);
+ this->CustomPreTest);
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST",
- this->CustomPostTest);
- this->CTest->PopulateCustomVector(mf,
- "CTEST_CUSTOM_TESTS_IGNORE",
- this->CustomTestsIgnore);
- this->CTest->PopulateCustomInteger(mf,
- "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
- this->CustomMaximumPassedTestOutputSize);
- this->CTest->PopulateCustomInteger(mf,
- "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
- this->CustomMaximumFailedTestOutputSize);
+ this->CustomPostTest);
+ this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_TESTS_IGNORE",
+ this->CustomTestsIgnore);
+ this->CTest->PopulateCustomInteger(
+ mf, "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
+ this->CustomMaximumPassedTestOutputSize);
+ this->CTest->PopulateCustomInteger(
+ mf, "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
+ this->CustomMaximumFailedTestOutputSize);
}
-//----------------------------------------------------------------------
int cmCTestTestHandler::PreProcessHandler()
{
- if ( !this->ExecuteCommands(this->CustomPreTest) )
- {
+ if (!this->ExecuteCommands(this->CustomPreTest)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem executing pre-test command(s)." << std::endl);
+ "Problem executing pre-test command(s)." << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
int cmCTestTestHandler::PostProcessHandler()
{
- if ( !this->ExecuteCommands(this->CustomPostTest) )
- {
+ if (!this->ExecuteCommands(this->CustomPostTest)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem executing post-test command(s)." << std::endl);
+ "Problem executing post-test command(s)." << std::endl);
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------
-//clearly it would be nice if this were broken up into a few smaller
-//functions and commented...
+// clearly it would be nice if this were broken up into a few smaller
+// functions and commented...
int cmCTestTestHandler::ProcessHandler()
{
// 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")))
- {
+ if (cmSystemTools::IsOn(this->GetOption("ScheduleRandom"))) {
this->CTest->SetScheduleType("Random");
- }
- if(this->GetOption("ParallelLevel"))
- {
+ }
+ if (this->GetOption("ParallelLevel")) {
this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));
- }
+ }
const char* val;
val = this->GetOption("LabelRegularExpression");
- if ( val )
- {
+ if (val) {
this->UseIncludeLabelRegExpFlag = true;
this->IncludeLabelRegExp = val;
- }
+ }
val = this->GetOption("ExcludeLabelRegularExpression");
- if ( val )
- {
+ if (val) {
this->UseExcludeLabelRegExpFlag = true;
- this->ExcludeLabelRegularExpression = val;
- }
+ this->ExcludeLabelRegExp = val;
+ }
val = this->GetOption("IncludeRegularExpression");
- if ( val )
- {
+ if (val) {
this->UseIncludeRegExp();
this->SetIncludeRegExp(val);
- }
+ }
val = this->GetOption("ExcludeRegularExpression");
- if ( val )
- {
+ if (val) {
this->UseExcludeRegExp();
this->SetExcludeRegExp(val);
- }
+ }
+ val = this->GetOption("ExcludeFixtureRegularExpression");
+ if (val) {
+ this->ExcludeFixtureRegExp = val;
+ }
+ val = this->GetOption("ExcludeFixtureSetupRegularExpression");
+ if (val) {
+ this->ExcludeFixtureSetupRegExp = val;
+ }
+ val = this->GetOption("ExcludeFixtureCleanupRegularExpression");
+ if (val) {
+ this->ExcludeFixtureCleanupRegExp = val;
+ }
+ this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed")));
this->TestResults.clear();
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- (this->MemCheck ? "Memory check" : "Test")
- << " project " << cmSystemTools::GetCurrentWorkingDirectory()
- << std::endl);
- if ( ! this->PreProcessHandler() )
- {
+ 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<cmStdString> passed;
- std::vector<cmStdString> failed;
+ std::vector<std::string> passed;
+ std::vector<std::string> failed;
int total;
- //start the real time clock
+ // start the real time clock
double clock_start, clock_finish;
clock_start = cmSystemTools::GetTime();
@@ -567,473 +465,748 @@ int cmCTestTestHandler::ProcessHandler()
total = int(passed.size()) + int(failed.size());
- if (total == 0)
- {
- if ( !this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels() )
- {
+ if (total == 0) {
+ if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!"
- << std::endl);
+ << 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::vector<std::string>::iterator j = passed.begin();
+ j != passed.end(); ++j) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "\t" << *j << std::endl, this->Quiet);
}
}
- else
- {
- if (this->HandlerVerbose && passed.size() &&
- (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag))
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
- << "The following tests passed:" << std::endl);
- for(std::vector<cmStdString>::iterator j = passed.begin();
- j != passed.end(); ++j)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "\t" << *j
- << std::endl);
- }
+
+ typedef std::set<cmCTestTestHandler::cmCTestTestResult,
+ cmCTestTestResultLess>
+ SetOfTests;
+ SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
+ std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests;
+
+ for (SetOfTests::iterator ftit = resultsSet.begin();
+ ftit != resultsSet.end(); ++ftit) {
+ if (cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") ||
+ ftit->CompletionStatus == "Disabled") {
+ disabledTests.push_back(*ftit);
}
+ }
float percent = float(passed.size()) * 100.0f / float(total);
- if ( failed.size() > 0 && percent > 99)
- {
+ if (!failed.empty() && percent > 99) {
percent = 99;
- }
+ }
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
- << static_cast<int>(percent + .5) << "% tests passed, "
- << failed.size() << " tests failed out of "
- << total << std::endl);
- if(this->CTest->GetLabelSummary())
- {
+ << 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));
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (real) = "
- << realBuf << "\n" );
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\nTotal Test time (real) = " << realBuf << "\n",
+ this->Quiet);
- if (failed.size())
- {
+ if (!disabledTests.empty()) {
cmGeneratedFileStream ofs;
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
- << "The following tests FAILED:" << std::endl);
- this->StartLogFile("TestsFailed", ofs);
+ << "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);
+ }
+ }
- typedef std::set<cmCTestTestHandler::cmCTestTestResult,
- cmCTestTestResultLess> SetOfTests;
- SetOfTests resultsSet(this->TestResults.begin(),
- this->TestResults.end());
+ 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 )
- {
+ 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.c_str() << " ("
- << this->GetTestStatus(ftit->Status) << ")"
- << std::endl);
- }
+ cmCTestLog(
+ this->CTest, HANDLER_OUTPUT, "\t"
+ << std::setw(3) << ftit->TestCount << " - " << ftit->Name << " ("
+ << this->GetTestStatus(ftit->Status) << ")" << std::endl);
}
}
}
+ }
- if ( this->CTest->GetProduceXML() )
- {
+ if (this->CTest->GetProduceXML()) {
cmGeneratedFileStream xmlfile;
- if( !this->StartResultingXML(
+ if (!this->StartResultingXML(
(this->MemCheck ? cmCTest::PartMemCheck : cmCTest::PartTest),
- (this->MemCheck ? "DynamicAnalysis" : "Test"), xmlfile) )
- {
+ (this->MemCheck ? "DynamicAnalysis" : "Test"), xmlfile)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create "
- << (this->MemCheck ? "memory check" : "testing")
- << " XML file" << std::endl);
- this->LogFile = 0;
+ << (this->MemCheck ? "memory check" : "testing")
+ << " XML file" << std::endl);
+ this->LogFile = CM_NULLPTR;
return 1;
- }
- this->GenerateDartOutput(xmlfile);
}
+ cmXMLWriter xml(xmlfile);
+ this->GenerateDartOutput(xml);
+ }
- if ( ! this->PostProcessHandler() )
- {
- this->LogFile = 0;
+ if (!this->PostProcessHandler()) {
+ this->LogFile = CM_NULLPTR;
return -1;
- }
+ }
- if ( !failed.empty() )
- {
- this->LogFile = 0;
+ if (!failed.empty()) {
+ this->LogFile = CM_NULLPTR;
return -1;
- }
- this->LogFile = 0;
+ }
+ this->LogFile = CM_NULLPTR;
return 0;
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::PrintLabelSummary()
{
cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
- cmCTestTestHandler::TestResultsVector::iterator ri =
- this->TestResults.begin();
- std::map<cmStdString, double> labelTimes;
- std::set<cmStdString> labels;
+ 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)
- {
+ for (; it != this->TestList.end(); ++it) {
cmCTestTestProperties& p = *it;
- if(p.Labels.size() != 0)
- {
- for(std::vector<std::string>::iterator l = p.Labels.begin();
- l != p.Labels.end(); ++l)
- {
- if((*l).size() > maxlen)
- {
+ 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();
- }
+ }
labels.insert(*l);
labelTimes[*l] = 0;
- }
+ labelCounts[*l] = 0;
}
}
- ri = this->TestResults.begin();
+ }
+ cmCTestTestHandler::TestResultsVector::iterator ri =
+ this->TestResults.begin();
// fill maps
- for(; ri != this->TestResults.end(); ++ri)
- {
- cmCTestTestResult &result = *ri;
+ for (; ri != this->TestResults.end(); ++ri) {
+ cmCTestTestResult& result = *ri;
cmCTestTestProperties& p = *result.Properties;
- if(p.Labels.size() != 0)
- {
- for(std::vector<std::string>::iterator l = p.Labels.begin();
- l != p.Labels.end(); ++l)
- {
+ 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];
}
}
+ }
// now print times
- if(labels.size())
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:");
- }
- for(std::set<cmStdString>::const_iterator i = labels.begin();
- i != labels.end(); ++i)
- {
+ if (!labels.empty()) {
+ 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;
- label.resize(maxlen +3, ' ');
+ label.resize(maxlen + 3, ' ');
+
char buf[1024];
sprintf(buf, "%6.2f sec", labelTimes[*i]);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\n"
- << label << " = " << buf );
- if ( this->LogFile )
- {
- *this->LogFile << "\n" << *i << " = "
- << buf << "\n";
- }
+
+ std::ostringstream labelCountStr;
+ labelCountStr << "(" << labelCounts[*i] << " test";
+ if (labelCounts[*i] > 1) {
+ labelCountStr << "s";
}
- if(labels.size())
- {
- if(this->LogFile)
- {
+ labelCountStr << ")";
+
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"
+ << label << " = " << buf << " "
+ << labelCountStr.str(),
+ this->Quiet);
+ if (this->LogFile) {
+ *this->LogFile << "\n" << *i << " = " << buf << "\n";
+ }
+ }
+ if (!labels.empty()) {
+ if (this->LogFile) {
*this->LogFile << "\n";
- }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\n");
}
-
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
+ }
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
- if (!this->UseIncludeLabelRegExpFlag )
- {
+ if (!this->UseIncludeLabelRegExpFlag) {
return;
- }
+ }
// if there are no labels and we are filtering by labels
// then exclude the test as it does not have the label
- if(it.Labels.size() == 0 )
- {
+ if (it.Labels.empty()) {
it.IsInBasedOnREOptions = false;
return;
- }
+ }
// check to see if the label regular expression matches
- bool found = false; // assume it does not match
+ 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::vector<std::string>::iterator l = it.Labels.begin();
+ l != it.Labels.end(); ++l) {
+ if (this->IncludeLabelRegularExpression.find(*l)) {
found = true;
- }
}
+ }
// if no match was found, exclude the test
- if(!found)
- {
+ if (!found) {
it.IsInBasedOnREOptions = false;
- }
+ }
}
-
-//----------------------------------------------------------------------
void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
- if (!this->UseExcludeLabelRegExpFlag )
- {
+ if (!this->UseExcludeLabelRegExpFlag) {
return;
- }
+ }
// if there are no labels and we are excluding by labels
// then do nothing as a no label can not be a match
- if(it.Labels.size() == 0 )
- {
+ if (it.Labels.empty()) {
return;
- }
+ }
// check to see if the label regular expression matches
- bool found = false; // assume it does not match
+ 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::vector<std::string>::iterator l = it.Labels.begin();
+ l != it.Labels.end(); ++l) {
+ if (this->ExcludeLabelRegularExpression.find(*l)) {
found = true;
- }
}
+ }
// if match was found, exclude the test
- if(found)
- {
+ if (found) {
it.IsInBasedOnREOptions = false;
- }
+ }
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::CheckLabelFilter(cmCTestTestProperties& it)
{
this->CheckLabelFilterInclude(it);
this->CheckLabelFilterExclude(it);
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::ComputeTestList()
{
this->TestList.clear(); // clear list of test
this->GetListOfTests();
+
+ if (this->RerunFailed) {
+ this->ComputeTestListForRerunFailed();
+ return;
+ }
+
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 ++ )
- {
+ for (it = this->TestList.begin(); it != this->TestList.end(); it++) {
this->CheckLabelFilter(*it);
- if (it->IsInBasedOnREOptions)
- {
- inREcnt ++;
- }
+ if (it->IsInBasedOnREOptions) {
+ inREcnt++;
}
+ }
// expand the test list based on the union flag
- if (this->UseUnion)
- {
+ if (this->UseUnion) {
this->ExpandTestsToRunInformation((int)tmsize);
- }
- else
- {
+ } else {
this->ExpandTestsToRunInformation(inREcnt);
- }
+ }
// Now create a final list of tests to run
int cnt = 0;
inREcnt = 0;
- std::string last_directory = "";
+ std::string last_directory;
ListOfTests finalList;
- for ( it = this->TestList.begin(); it != this->TestList.end(); it ++ )
- {
- cnt ++;
- if (it->IsInBasedOnREOptions)
- {
+ for (it = this->TestList.begin(); it != this->TestList.end(); it++) {
+ cnt++;
+ if (it->IsInBasedOnREOptions) {
inREcnt++;
- }
+ }
- if (this->UseUnion)
- {
+ if (this->UseUnion) {
// if it is not in the list and not in the regexp then skip
- if ((this->TestsToRun.size() &&
- std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt)
- == this->TestsToRun.end()) && !it->IsInBasedOnREOptions)
- {
+ if ((!this->TestsToRun.empty() &&
+ std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt) ==
+ this->TestsToRun.end()) &&
+ !it->IsInBasedOnREOptions) {
continue;
- }
}
- else
- {
+ } else {
// is this test in the list of tests to run? If not then skip it
- if ((this->TestsToRun.size() &&
- std::find(this->TestsToRun.begin(),
- this->TestsToRun.end(), inREcnt)
- == this->TestsToRun.end()) || !it->IsInBasedOnREOptions)
- {
+ if ((!this->TestsToRun.empty() &&
+ std::find(this->TestsToRun.begin(), this->TestsToRun.end(),
+ inREcnt) == this->TestsToRun.end()) ||
+ !it->IsInBasedOnREOptions) {
continue;
- }
}
- it->Index = cnt; // save the index into the test list for this test
- finalList.push_back(*it);
}
+ it->Index = cnt; // save the index into the test list for this test
+ finalList.push_back(*it);
+ }
+
+ UpdateForFixtures(finalList);
+
// Save the total number of tests before exclusions
this->TotalNumberOfTests = this->TestList.size();
// Set the TestList to the final list of all test
this->TestList = finalList;
+
+ this->UpdateMaxTestNameWidth();
+}
+
+void cmCTestTestHandler::ComputeTestListForRerunFailed()
+{
+ this->ExpandTestsToRunInformationForRerunFailed();
+
+ cmCTestTestHandler::ListOfTests::iterator it;
+ ListOfTests finalList;
+ int cnt = 0;
+ for (it = this->TestList.begin(); it != this->TestList.end(); it++) {
+ 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())) {
+ continue;
+ }
+
+ it->Index = cnt;
+ finalList.push_back(*it);
+ }
+
+ UpdateForFixtures(finalList);
+
+ // Save the total number of tests before exclusions
+ this->TotalNumberOfTests = this->TestList.size();
+
+ // Set the TestList to the list of failed tests to rerun
+ this->TestList = finalList;
+
+ this->UpdateMaxTestNameWidth();
+}
+
+void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
+{
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Updating test list for fixtures" << std::endl,
+ this->Quiet);
+
+ // Prepare regular expression evaluators
+ std::string setupRegExp(this->ExcludeFixtureRegExp);
+ std::string cleanupRegExp(this->ExcludeFixtureRegExp);
+ if (!this->ExcludeFixtureSetupRegExp.empty()) {
+ if (setupRegExp.empty()) {
+ setupRegExp = this->ExcludeFixtureSetupRegExp;
+ } else {
+ setupRegExp.append("(" + setupRegExp + ")|(" +
+ this->ExcludeFixtureSetupRegExp + ")");
+ }
+ }
+ if (!this->ExcludeFixtureCleanupRegExp.empty()) {
+ if (cleanupRegExp.empty()) {
+ cleanupRegExp = this->ExcludeFixtureCleanupRegExp;
+ } else {
+ cleanupRegExp.append("(" + cleanupRegExp + ")|(" +
+ this->ExcludeFixtureCleanupRegExp + ")");
+ }
+ }
+ cmsys::RegularExpression excludeSetupRegex(setupRegExp);
+ cmsys::RegularExpression excludeCleanupRegex(cleanupRegExp);
+
+ // 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;
+ FixtureDependencies fixtureSetups;
+ FixtureDependencies fixtureCleanups;
+
+ for (ListOfTests::const_iterator 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));
+ }
+
+ 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));
+ }
+ }
+
+ // 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;
+ addedTests.insert(p.Name);
+ }
+
+ // These are lookups of fixture name to a list of indices into the final
+ // 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;
+
+ // Use integer index for iteration because we append to
+ // the tests vector as we go
+ size_t fixtureTestsAdded = 0;
+ std::set<std::string> addedFixtures;
+ for (size_t i = 0; i < tests.size(); ++i) {
+ // Skip disabled tests
+ if (tests[i].Disabled) {
+ continue;
+ }
+
+ // There are two things to do for each test:
+ // 1. For every fixture required by this test, record that fixture as
+ // being required and create dependencies on that fixture's setup
+ // tests.
+ // 2. Record all setup tests in the final test list so we can later make
+ // cleanup tests in the test list depend on their associated setup
+ // tests to enforce correct ordering.
+
+ // 1. Handle fixture requirements
+ //
+ // 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;
+ if (requiredFixtureName.empty()) {
+ continue;
+ }
+
+ fixtureRequirements[requiredFixtureName].push_back(i);
+
+ // Add dependencies to this test for all of the setup tests
+ // associated with the required fixture. If any of those setup
+ // tests fail, this test should not run. We make the fixture's
+ // 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) {
+ 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()) {
+ tests[i].Depends.push_back(setupTestName);
+ }
+ }
+
+ // Append any fixture setup/cleanup tests to our test list if they
+ // are not already in it (they could have been in the original
+ // set of tests passed to us at the outset or have already been
+ // added from a previously checked test). A fixture isn't required
+ // to have setup/cleanup tests.
+ if (!addedFixtures.insert(requiredFixtureName).second) {
+ // Already seen this fixture, no need to check it again
+ continue;
+ }
+
+ // Only add setup tests if this fixture has not been excluded
+ if (setupRegExp.empty() ||
+ !excludeSetupRegex.find(requiredFixtureName)) {
+ std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
+ fixtureSetups.equal_range(requiredFixtureName);
+ for (FixtureDepsIterator it = fixtureRange.first;
+ it != fixtureRange.second; ++it) {
+ ListOfTests::const_iterator lotIt = it->second;
+ const cmCTestTestProperties& p = *lotIt;
+
+ if (!addedTests.insert(p.Name).second) {
+ // Already have p in our test list
+ continue;
+ }
+
+ // This is a test not yet in our list, so add it and
+ // update its index to reflect where it was in the original
+ // full list of all tests (needed to track individual tests
+ // across ctest runs for re-run failed, etc.)
+ tests.push_back(p);
+ tests.back().Index =
+ 1 + static_cast<int>(std::distance(this->TestList.begin(), lotIt));
+ ++fixtureTestsAdded;
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Added setup test "
+ << p.Name << " required by fixture "
+ << requiredFixtureName << std::endl,
+ this->Quiet);
+ }
+ }
+
+ // Only add cleanup tests if this fixture has not been excluded
+ if (cleanupRegExp.empty() ||
+ !excludeCleanupRegex.find(requiredFixtureName)) {
+ std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
+ fixtureCleanups.equal_range(requiredFixtureName);
+ for (FixtureDepsIterator it = fixtureRange.first;
+ it != fixtureRange.second; ++it) {
+ ListOfTests::const_iterator lotIt = it->second;
+ const cmCTestTestProperties& p = *lotIt;
+
+ if (!addedTests.insert(p.Name).second) {
+ // Already have p in our test list
+ continue;
+ }
+
+ // This is a test not yet in our list, so add it and
+ // update its index to reflect where it was in the original
+ // full list of all tests (needed to track individual tests
+ // across ctest runs for re-run failed, etc.)
+ tests.push_back(p);
+ tests.back().Index =
+ 1 + static_cast<int>(std::distance(this->TestList.begin(), lotIt));
+ ++fixtureTestsAdded;
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Added cleanup test "
+ << p.Name << " required by fixture "
+ << requiredFixtureName << std::endl,
+ this->Quiet);
+ }
+ }
+ }
+
+ // 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;
+ if (setupFixtureName.empty()) {
+ continue;
+ }
+
+ setupFixturesAdded[setupFixtureName].push_back(i);
+ }
+ }
+
+ // Now that we have the final list of tests, we can update all cleanup
+ // tests to depend on those tests which require that fixture and on any
+ // 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;
+ 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;
+
+ // 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);
+ 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()) {
+ p.Depends.push_back(reqTestName);
+ }
+ }
+ }
+
+ // Ensure fixture cleanup tests always run after their setup tests, even
+ // if no other test cases require the fixture
+ 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()) {
+ p.Depends.push_back(setupTestName);
+ }
+ }
+ }
+ }
+ }
+
+ 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 (it = this->TestList.begin();
- it != this->TestList.end(); it ++ )
- {
+ for (cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
+ it != this->TestList.end(); it++) {
cmCTestTestProperties& p = *it;
- if(max < p.Name.size())
- {
+ if (max < p.Name.size()) {
max = p.Name.size();
- }
}
- if(static_cast<std::string::size_type>(this->CTest->GetMaxTestNameWidth())
- != max)
- {
+ }
+ if (static_cast<std::string::size_type>(
+ this->CTest->GetMaxTestNameWidth()) != max) {
this->CTest->SetMaxTestNameWidth(static_cast<int>(max));
- }
+ }
}
-bool cmCTestTestHandler::GetValue(const char* tag,
- int& value,
- std::ifstream& fin)
+bool cmCTestTestHandler::GetValue(const char* tag, int& value,
+ std::istream& fin)
{
std::string line;
bool ret = true;
cmSystemTools::GetLineFromStream(fin, line);
- if(line == tag)
- {
+ if (line == tag) {
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);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
+ << tag << " found [" << line << "]" << std::endl);
ret = false;
- }
+ }
return ret;
}
-bool cmCTestTestHandler::GetValue(const char* tag,
- double& value,
- std::ifstream& fin)
+bool cmCTestTestHandler::GetValue(const char* tag, double& value,
+ std::istream& fin)
{
std::string line;
cmSystemTools::GetLineFromStream(fin, line);
bool ret = true;
- if(line == tag)
- {
+ if (line == tag) {
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);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
+ << tag << " found [" << line << "]" << std::endl);
ret = false;
- }
+ }
return ret;
}
-bool cmCTestTestHandler::GetValue(const char* tag,
- bool& value,
- std::ifstream& fin)
+bool cmCTestTestHandler::GetValue(const char* tag, bool& value,
+ std::istream& fin)
{
std::string line;
cmSystemTools::GetLineFromStream(fin, line);
bool ret = true;
- if(line == tag)
- {
+ if (line == tag) {
#ifdef __HAIKU__
int tmp = 0;
fin >> tmp;
value = false;
- if(tmp)
- {
+ if (tmp) {
value = true;
- }
+ }
#else
fin >> 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);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
+ << tag << " found [" << line << "]" << std::endl);
ret = false;
- }
+ }
return ret;
}
-bool cmCTestTestHandler::GetValue(const char* tag,
- size_t& value,
- std::ifstream& fin)
+bool cmCTestTestHandler::GetValue(const char* tag, size_t& value,
+ std::istream& fin)
{
std::string line;
cmSystemTools::GetLineFromStream(fin, line);
bool ret = true;
- if(line == tag)
- {
+ if (line == tag) {
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
- }
- else
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "parse error: missing tag: "
- << tag << " found [" << line.c_str() << "]" << std::endl);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
+ << tag << " found [" << line << "]" << std::endl);
ret = false;
- }
+ }
return ret;
}
-bool cmCTestTestHandler::GetValue(const char* tag,
- std::string& value,
- std::ifstream& fin)
+bool cmCTestTestHandler::GetValue(const char* tag, std::string& value,
+ std::istream& fin)
{
std::string line;
cmSystemTools::GetLineFromStream(fin, line);
bool ret = true;
- if(line == tag)
- {
- ret = cmSystemTools::GetLineFromStream(fin, value);
- }
- else
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ if (line == tag) {
+ ret = cmSystemTools::GetLineFromStream(fin, value);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
+ << tag << " found [" << line << "]" << std::endl);
ret = false;
- }
+ }
return ret;
}
-//---------------------------------------------------------------------
-void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
- std::vector<cmStdString> &failed)
+void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
+ std::vector<std::string>& failed)
{
this->ComputeTestList();
this->StartTest = this->CTest->CurrentTime();
this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
double elapsed_time_start = cmSystemTools::GetTime();
- cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs() ?
- new cmCTestBatchTestHandler : new cmCTestMultiProcessHandler;
+ cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs()
+ ? new cmCTestBatchTestHandler
+ : new cmCTestMultiProcessHandler;
parallel->SetCTest(this->CTest);
parallel->SetParallelLevel(this->CTest->GetParallelLevel());
parallel->SetTestHandler(this);
-
- *this->LogFile << "Start testing: "
- << this->CTest->CurrentTime() << std::endl
+ parallel->SetQuiet(this->Quiet);
+ if (this->TestLoad > 0) {
+ parallel->SetTestLoad(this->TestLoad);
+ } else {
+ parallel->SetTestLoad(this->CTest->GetTestLoad());
+ }
+
+ *this->LogFile
+ << "Start testing: " << this->CTest->CurrentTime() << std::endl
<< "----------------------------------------------------------"
<< std::endl;
@@ -1041,320 +1214,271 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
cmCTestMultiProcessHandler::PropertiesMap properties;
bool randomSchedule = this->CTest->GetScheduleType() == "Random";
- if(randomSchedule)
- {
- srand((unsigned)time(0));
- }
+ if (randomSchedule) {
+ srand((unsigned)time(CM_NULLPTR));
+ }
for (ListOfTests::iterator it = this->TestList.begin();
- it != this->TestList.end(); ++it)
- {
+ it != this->TestList.end(); ++it) {
cmCTestTestProperties& p = *it;
cmCTestMultiProcessHandler::TestSet depends;
- if(randomSchedule)
- {
+ if (randomSchedule) {
p.Cost = static_cast<float>(rand());
- }
+ }
- if(p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0)
- {
+ if (p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0) {
p.Timeout = this->CTest->GetGlobalTimeout();
- }
+ }
- if(p.Depends.size())
- {
- 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)
- {
+ 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);
break; // break out of test loop as name can only match 1
- }
}
}
}
+ }
tests[it->Index] = depends;
properties[it->Index] = &*it;
- }
+ }
parallel->SetTests(tests, properties);
parallel->SetPassFailVectors(&passed, &failed);
this->TestResults.clear();
parallel->SetTestResults(&this->TestResults);
- if(this->CTest->ShouldPrintLabels())
- {
+ if (this->CTest->ShouldPrintLabels()) {
parallel->PrintLabels();
- }
- else if(this->CTest->GetShowOnly())
- {
+ } else if (this->CTest->GetShowOnly()) {
parallel->PrintTestList();
- }
- else
- {
+ } else {
parallel->RunTests();
- }
+ }
delete parallel;
this->EndTest = this->CTest->CurrentTime();
this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
this->ElapsedTestingTime = cmSystemTools::GetTime() - elapsed_time_start;
- *this->LogFile << "End testing: "
- << this->CTest->CurrentTime() << std::endl;
+ *this->LogFile << "End testing: " << this->CTest->CurrentTime() << std::endl;
}
-//----------------------------------------------------------------------
-void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int)
+void cmCTestTestHandler::GenerateTestCommand(
+ std::vector<std::string>& /*unused*/, int /*unused*/)
{
}
-//----------------------------------------------------------------------
-void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
+void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
{
- if ( !this->CTest->GetProduceXML() )
- {
+ if (!this->CTest->GetProduceXML()) {
return;
- }
+ }
- this->CTest->StartXML(os, this->AppendXML);
- os << "<Testing>\n"
- << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
- << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
- << "\t<TestList>\n";
+ this->CTest->StartXML(xml, this->AppendXML);
+ 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];
+ for (cc = 0; cc < this->TestResults.size(); cc++) {
+ cmCTestTestResult* result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name;
- os << "\t\t<Test>" << cmXMLSafe(
- this->CTest->GetShortPathToFile(testPath.c_str()))
- << "</Test>" << std::endl;
- }
- os << "\t</TestList>\n";
- for ( cc = 0; cc < this->TestResults.size(); cc ++ )
- {
- cmCTestTestResult *result = &this->TestResults[cc];
- this->WriteTestResultHeader(os, result);
- os << "\t\t<Results>" << std::endl;
- if ( result->Status != cmCTestTestHandler::NOT_RUN )
- {
- if ( result->Status != cmCTestTestHandler::COMPLETED ||
- result->ReturnValue )
- {
- os << "\t\t\t<NamedMeasurement type=\"text/string\" "
- "name=\"Exit Code\"><Value>"
- << cmXMLSafe(this->GetTestStatus(result->Status))
- << "</Value>"
- "</NamedMeasurement>\n"
- << "\t\t\t<NamedMeasurement type=\"text/string\" "
- "name=\"Exit Value\"><Value>"
- << result->ReturnValue
- << "</Value></NamedMeasurement>"
- << std::endl;
- }
- os << result->RegressionImages;
- os << "\t\t\t<NamedMeasurement type=\"numeric/double\" "
- << "name=\"Execution Time\"><Value>"
- << result->ExecutionTime
- << "</Value></NamedMeasurement>\n";
- if(result->Reason.size())
- {
+ 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];
+ this->WriteTestResultHeader(xml, result);
+ xml.StartElement("Results");
+
+ 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.EndElement(); // NamedMeasurement
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Exit Value");
+ xml.Element("Value", result->ReturnValue);
+ xml.EndElement(); // NamedMeasurement
+ }
+ this->GenerateRegressionImages(xml, result->DartString);
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "numeric/double");
+ xml.Attribute("name", "Execution Time");
+ xml.Element("Value", result->ExecutionTime);
+ xml.EndElement(); // NamedMeasurement
+ if (!result->Reason.empty()) {
const char* reasonType = "Pass Reason";
- if(result->Status != cmCTestTestHandler::COMPLETED &&
- result->Status != cmCTestTestHandler::NOT_RUN)
- {
+ if (result->Status != cmCTestTestHandler::COMPLETED) {
reasonType = "Fail Reason";
- }
- os << "\t\t\t<NamedMeasurement type=\"text/string\" "
- << "name=\"" << reasonType << "\"><Value>"
- << cmXMLSafe(result->Reason)
- << "</Value></NamedMeasurement>\n";
}
- os
- << "\t\t\t<NamedMeasurement type=\"text/string\" "
- << "name=\"Completion Status\"><Value>"
- << cmXMLSafe(result->CompletionStatus)
- << "</Value></NamedMeasurement>\n";
- }
- os
- << "\t\t\t<NamedMeasurement type=\"text/string\" "
- << "name=\"Command Line\"><Value>"
- << cmXMLSafe(result->FullCommandLine)
- << "</Value></NamedMeasurement>\n";
- std::map<cmStdString,cmStdString>::iterator measureIt;
- for ( measureIt = result->Properties->Measurements.begin();
- measureIt != result->Properties->Measurements.end();
- ++ measureIt )
- {
- os
- << "\t\t\t<NamedMeasurement type=\"text/string\" "
- << "name=\"" << measureIt->first.c_str() << "\"><Value>"
- << cmXMLSafe(measureIt->second)
- << "</Value></NamedMeasurement>\n";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", reasonType);
+ xml.Element("Value", result->Reason);
+ xml.EndElement(); // NamedMeasurement
}
- os
- << "\t\t\t<Measurement>\n"
- << "\t\t\t\t<Value"
- << (result->CompressOutput ?
- " encoding=\"base64\" compression=\"gzip\">"
- : ">");
- os << cmXMLSafe(result->Output);
- os
- << "</Value>\n"
- << "\t\t\t</Measurement>\n"
- << "\t\t</Results>\n";
-
- this->AttachFiles(os, result);
- this->WriteTestResultFooter(os, result);
- }
-
- os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>\n"
- << "\t<EndTestTime>" << this->EndTestTime << "</EndTestTime>\n"
- << "<ElapsedMinutes>"
- << static_cast<int>(this->ElapsedTestingTime/6)/10.0
- << "</ElapsedMinutes>"
- << "</Testing>" << std::endl;
- this->CTest->EndXML(os);
+ }
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Completion Status");
+ 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.EndElement(); // NamedMeasurement
+ std::map<std::string, std::string>::iterator measureIt;
+ for (measureIt = result->Properties->Measurements.begin();
+ measureIt != result->Properties->Measurements.end(); ++measureIt) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", measureIt->first);
+ xml.Element("Value", measureIt->second);
+ xml.EndElement(); // NamedMeasurement
+ }
+ xml.StartElement("Measurement");
+ xml.StartElement("Value");
+ if (result->CompressOutput) {
+ xml.Attribute("encoding", "base64");
+ xml.Attribute("compression", "gzip");
+ }
+ xml.Content(result->Output);
+ xml.EndElement(); // Value
+ xml.EndElement(); // Measurement
+ xml.EndElement(); // Results
+
+ this->AttachFiles(xml, result);
+ this->WriteTestResultFooter(xml, result);
+ }
+
+ xml.Element("EndDateTime", this->EndTest);
+ xml.Element("EndTestTime", this->EndTestTime);
+ xml.Element("ElapsedMinutes",
+ static_cast<int>(this->ElapsedTestingTime / 6) / 10.0);
+ xml.EndElement(); // Testing
+ this->CTest->EndXML(xml);
}
-//----------------------------------------------------------------------------
-void cmCTestTestHandler::WriteTestResultHeader(std::ostream& os,
+void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,
cmCTestTestResult* result)
{
- os << "\t<Test Status=\"";
- if ( result->Status == cmCTestTestHandler::COMPLETED )
- {
- os << "passed";
- }
- else if ( result->Status == cmCTestTestHandler::NOT_RUN )
- {
- os << "notrun";
- }
- else
- {
- os << "failed";
- }
+ xml.StartElement("Test");
+ if (result->Status == cmCTestTestHandler::COMPLETED) {
+ xml.Attribute("Status", "passed");
+ } else if (result->Status == cmCTestTestHandler::NOT_RUN) {
+ xml.Attribute("Status", "notrun");
+ } else {
+ xml.Attribute("Status", "failed");
+ }
std::string testPath = result->Path + "/" + result->Name;
- os << "\">\n"
- << "\t\t<Name>" << cmXMLSafe(result->Name) << "</Name>\n"
- << "\t\t<Path>" << cmXMLSafe(
- this->CTest->GetShortPathToFile(result->Path.c_str())) << "</Path>\n"
- << "\t\t<FullName>" << cmXMLSafe(
- this->CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
- << "\t\t<FullCommandLine>"
- << cmXMLSafe(result->FullCommandLine)
- << "</FullCommandLine>\n";
+ 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);
}
-//----------------------------------------------------------------------------
-void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os,
+void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,
cmCTestTestResult* result)
{
- if(!result->Properties->Labels.empty())
- {
- os << "\t\t<Labels>\n";
+ 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)
- {
- os << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n";
- }
- os << "\t\t</Labels>\n";
+ for (std::vector<std::string>::const_iterator li = labels.begin();
+ li != labels.end(); ++li) {
+ xml.Element("Label", *li);
}
+ xml.EndElement(); // Labels
+ }
- os
- << "\t</Test>" << std::endl;
+ xml.EndElement(); // Test
}
-//----------------------------------------------------------------------
-void cmCTestTestHandler::AttachFiles(std::ostream& os,
+void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
cmCTestTestResult* result)
{
- if(result->Status != cmCTestTestHandler::COMPLETED
- && result->Properties->AttachOnFail.size())
- {
+ 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)
- {
- std::string base64 = this->CTest->Base64GzipEncodeFile(*file);
+ }
+ 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);
- os << "\t\t<NamedMeasurement name=\"Attached File\" encoding=\"base64\" "
- "compression=\"tar/gzip\" filename=\"" << fname << "\" type=\"file\">"
- "\n\t\t\t<Value>\n\t\t\t"
- << base64
- << "\n\t\t\t</Value>\n\t\t</NamedMeasurement>\n";
- }
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("name", "Attached File");
+ xml.Attribute("encoding", "base64");
+ xml.Attribute("compression", "tar/gzip");
+ xml.Attribute("filename", fname);
+ xml.Attribute("type", "file");
+ xml.Element("Value", base64);
+ xml.EndElement(); // NamedMeasurement
+ }
}
-//----------------------------------------------------------------------
-int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
+int cmCTestTestHandler::ExecuteCommands(std::vector<std::string>& vec)
{
- std::vector<cmStdString>::iterator it;
- for ( it = vec.begin(); it != vec.end(); ++it )
- {
+ std::vector<std::string>::iterator it;
+ for (it = vec.begin(); it != vec.end(); ++it) {
int retVal = 0;
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << *it
- << std::endl);
- if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0,
- cmSystemTools::OUTPUT_MERGE
- /*this->Verbose*/) || retVal != 0 )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem running command: "
- << *it << std::endl);
+ 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
+ /*this->Verbose*/) ||
+ retVal != 0) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Problem running command: " << *it << std::endl);
return 0;
- }
}
+ }
return 1;
}
-
-//----------------------------------------------------------------------
// Find the appropriate executable to run for a test
-std::string cmCTestTestHandler::FindTheExecutable(const char *exe)
+std::string cmCTestTestHandler::FindTheExecutable(const char* exe)
{
std::string resConfig;
std::vector<std::string> extraPaths;
std::vector<std::string> failedPaths;
- if(strcmp(exe, "NOT_AVAILABLE") == 0)
- {
+ if (strcmp(exe, "NOT_AVAILABLE") == 0) {
return exe;
- }
- return cmCTestTestHandler::FindExecutable(this->CTest,
- exe, resConfig,
- extraPaths,
- failedPaths);
+ }
+ return cmCTestTestHandler::FindExecutable(this->CTest, exe, resConfig,
+ extraPaths, failedPaths);
}
// add additional configurations to the search path
-void cmCTestTestHandler
-::AddConfigurations(cmCTest *ctest,
- std::vector<std::string> &attempted,
- std::vector<std::string> &attemptedConfigs,
- std::string filepath,
- std::string &filename)
+void cmCTestTestHandler::AddConfigurations(
+ cmCTest* ctest, std::vector<std::string>& attempted,
+ std::vector<std::string>& attemptedConfigs, std::string filepath,
+ std::string& filename)
{
std::string tempPath;
- if (filepath.size() &&
- filepath[filepath.size()-1] != '/')
- {
+ if (!filepath.empty() && filepath[filepath.size() - 1] != '/') {
filepath += "/";
- }
+ }
tempPath = filepath + filename;
attempted.push_back(tempPath);
attemptedConfigs.push_back("");
- if(ctest->GetConfigType().size())
- {
+ if (!ctest->GetConfigType().empty()) {
tempPath = filepath;
tempPath += ctest->GetConfigType();
tempPath += "/";
@@ -1369,9 +1493,7 @@ void cmCTestTestHandler
tempPath += filename;
attempted.push_back(tempPath);
attemptedConfigs.push_back(ctest->GetConfigType());
- }
- else
- {
+ } else {
// no config specified - try some options...
tempPath = filepath;
tempPath += "Release/";
@@ -1403,247 +1525,193 @@ void cmCTestTestHandler
tempPath += filename;
attempted.push_back(tempPath);
attemptedConfigs.push_back("Deployment");
- }
+ }
}
-
-//----------------------------------------------------------------------
// Find the appropriate executable to run for a test
-std::string cmCTestTestHandler
-::FindExecutable(cmCTest *ctest,
- const char *testCommand,
- std::string &resultingConfig,
- std::vector<std::string> &extraPaths,
- std::vector<std::string> &failed)
+std::string cmCTestTestHandler::FindExecutable(
+ cmCTest* ctest, const char* testCommand, std::string& resultingConfig,
+ std::vector<std::string>& extraPaths, std::vector<std::string>& failed)
{
// now run the compiled test if we can find it
std::vector<std::string> attempted;
std::vector<std::string> attemptedConfigs;
std::string tempPath;
- std::string filepath =
- cmSystemTools::GetFilenamePath(testCommand);
- std::string filename =
- cmSystemTools::GetFilenameName(testCommand);
+ std::string filepath = cmSystemTools::GetFilenamePath(testCommand);
+ std::string filename = cmSystemTools::GetFilenameName(testCommand);
- cmCTestTestHandler::AddConfigurations(ctest, attempted,
- attemptedConfigs,
- filepath,filename);
+ cmCTestTestHandler::AddConfigurations(ctest, attempted, attemptedConfigs,
+ filepath, filename);
// even if a fullpath was specified also try it relative to the current
// directory
- if (filepath.size() && filepath[0] == '/')
- {
- std::string localfilepath = filepath.substr(1,filepath.size()-1);
- cmCTestTestHandler::AddConfigurations(ctest, attempted,
- attemptedConfigs,
- localfilepath,filename);
- }
-
+ if (!filepath.empty() && filepath[0] == '/') {
+ std::string localfilepath = filepath.substr(1, filepath.size() - 1);
+ cmCTestTestHandler::AddConfigurations(ctest, attempted, attemptedConfigs,
+ localfilepath, filename);
+ }
// if extraPaths are provided and we were not passed a full path, try them,
// try any extra paths
- if (filepath.size() == 0)
- {
- for (unsigned int i = 0; i < extraPaths.size(); ++i)
- {
+ 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]);
- cmCTestTestHandler::AddConfigurations(ctest,attempted,
- attemptedConfigs,
- filepathExtra,
- filenameExtra);
- }
+ cmCTestTestHandler::AddConfigurations(ctest, attempted, attemptedConfigs,
+ filepathExtra, filenameExtra);
}
+ }
// store the final location in fullPath
std::string fullPath;
// now look in the paths we specified above
- for(unsigned int ai=0;
- ai < attempted.size() && fullPath.size() == 0; ++ai)
- {
+ for (unsigned int ai = 0; ai < attempted.size() && fullPath.empty(); ++ai) {
// first check without exe extension
- if(cmSystemTools::FileExists(attempted[ai].c_str())
- && !cmSystemTools::FileIsDirectory(attempted[ai].c_str()))
- {
- fullPath = cmSystemTools::CollapseFullPath(attempted[ai].c_str());
+ if (cmSystemTools::FileExists(attempted[ai].c_str()) &&
+ !cmSystemTools::FileIsDirectory(attempted[ai])) {
+ fullPath = cmSystemTools::CollapseFullPath(attempted[ai]);
resultingConfig = attemptedConfigs[ai];
- }
+ }
// then try with the exe extension
- else
- {
- failed.push_back(attempted[ai].c_str());
+ else {
+ failed.push_back(attempted[ai]);
tempPath = attempted[ai];
tempPath += cmSystemTools::GetExecutableExtension();
- if(cmSystemTools::FileExists(tempPath.c_str())
- && !cmSystemTools::FileIsDirectory(tempPath.c_str()))
- {
- fullPath = cmSystemTools::CollapseFullPath(tempPath.c_str());
+ if (cmSystemTools::FileExists(tempPath.c_str()) &&
+ !cmSystemTools::FileIsDirectory(tempPath)) {
+ fullPath = cmSystemTools::CollapseFullPath(tempPath);
resultingConfig = attemptedConfigs[ai];
- }
- else
- {
- failed.push_back(tempPath.c_str());
- }
+ } else {
+ failed.push_back(tempPath);
}
}
+ }
// if everything else failed, check the users path, but only if a full path
// wasn't specified
- if (fullPath.size() == 0 && filepath.size() == 0)
- {
+ if (fullPath.empty() && filepath.empty()) {
std::string path = cmSystemTools::FindProgram(filename.c_str());
- if (path != "")
- {
+ if (path != "") {
resultingConfig = "";
return path;
- }
}
- if(fullPath.size() == 0)
- {
- 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->c_str() << "\n");
- }
+ }
+ if (fullPath.empty()) {
+ 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");
}
+ }
return fullPath;
}
-
-//----------------------------------------------------------------------
void cmCTestTestHandler::GetListOfTests()
{
- if ( !this->IncludeLabelRegExp.empty() )
- {
- this->IncludeLabelRegularExpression.
- compile(this->IncludeLabelRegExp.c_str());
- }
- if ( !this->IncludeLabelRegExp.empty() )
- {
- this->ExcludeLabelRegularExpression.
- compile(this->ExcludeLabelRegExp.c_str());
- }
- if ( !this->IncludeRegExp.empty() )
- {
+ if (!this->IncludeLabelRegExp.empty()) {
+ this->IncludeLabelRegularExpression.compile(
+ this->IncludeLabelRegExp.c_str());
+ }
+ if (!this->ExcludeLabelRegExp.empty()) {
+ this->ExcludeLabelRegularExpression.compile(
+ this->ExcludeLabelRegExp.c_str());
+ }
+ if (!this->IncludeRegExp.empty()) {
this->IncludeTestsRegularExpression.compile(this->IncludeRegExp.c_str());
- }
- if ( !this->ExcludeRegExp.empty() )
- {
+ }
+ if (!this->ExcludeRegExp.empty()) {
this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp.c_str());
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Constructing a list of tests" << std::endl);
- cmake cm;
- cmGlobalGenerator gg;
- gg.SetCMakeInstance(&cm);
- cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
- cmMakefile *mf = lg->GetMakefile();
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Constructing a list of tests" << std::endl, this->Quiet);
+ cmake cm(cmake::RoleScript);
+ 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());
+ this->CTest->GetConfigType().c_str());
// Add handler for ADD_TEST
cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand;
newCom1->TestHandler = this;
- cm.AddCommand(newCom1);
+ cm.GetState()->AddBuiltinCommand("add_test", newCom1);
// Add handler for SUBDIRS
- cmCTestSubdirCommand* newCom2 =
- new cmCTestSubdirCommand;
+ cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand;
newCom2->TestHandler = this;
- cm.AddCommand(newCom2);
+ cm.GetState()->AddBuiltinCommand("subdirs", newCom2);
// Add handler for ADD_SUBDIRECTORY
- cmCTestAddSubdirectoryCommand* newCom3 =
- new cmCTestAddSubdirectoryCommand;
+ cmCTestAddSubdirectoryCommand* newCom3 = new cmCTestAddSubdirectoryCommand;
newCom3->TestHandler = this;
- cm.AddCommand(newCom3);
+ cm.GetState()->AddBuiltinCommand("add_subdirectory", newCom3);
- // Add handler for SET_SOURCE_FILES_PROPERTIES
- cmCTestSetTestsPropertiesCommand* newCom4
- = new cmCTestSetTestsPropertiesCommand;
+ // Add handler for SET_TESTS_PROPERTIES
+ cmCTestSetTestsPropertiesCommand* newCom4 =
+ new cmCTestSetTestsPropertiesCommand;
newCom4->TestHandler = this;
- cm.AddCommand(newCom4);
+ cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4);
const char* testFilename;
- if( cmSystemTools::FileExists("CTestTestfile.cmake") )
- {
+ if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
// does the CTestTestfile.cmake exist ?
testFilename = "CTestTestfile.cmake";
- }
- else if( cmSystemTools::FileExists("DartTestfile.txt") )
- {
+ } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
// does the DartTestfile.txt exist ?
testFilename = "DartTestfile.txt";
- }
- else
- {
+ } else {
return;
- }
+ }
- if ( !mf->ReadListFile(0, testFilename) )
- {
+ if (!mf->ReadListFile(testFilename)) {
return;
- }
- if ( cmSystemTools::GetErrorOccuredFlag() )
- {
+ }
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return;
- }
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Done constructing a list of tests" << std::endl);
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Done constructing a list of tests" << std::endl,
+ this->Quiet);
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::UseIncludeRegExp()
{
this->UseIncludeRegExpFlag = true;
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::UseExcludeRegExp()
{
this->UseExcludeRegExpFlag = true;
- this->UseExcludeRegExpFirst = this->UseIncludeRegExpFlag ? false : true;
+ this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag;
}
-//----------------------------------------------------------------------
const char* cmCTestTestHandler::GetTestStatus(int status)
{
- static const char statuses[][100] = {
- "Not Run",
- "Timeout",
- "SEGFAULT",
- "ILLEGAL",
- "INTERRUPT",
- "NUMERICAL",
- "OTHER_FAULT",
- "Failed",
- "BAD_COMMAND",
- "Completed"
- };
-
- if ( status < cmCTestTestHandler::NOT_RUN ||
- status > cmCTestTestHandler::COMPLETED )
- {
+ static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT",
+ "ILLEGAL", "INTERRUPT", "NUMERICAL",
+ "OTHER_FAULT", "Failed", "BAD_COMMAND",
+ "Completed" };
+
+ if (status < cmCTestTestHandler::NOT_RUN ||
+ status > cmCTestTestHandler::COMPLETED) {
return "No Status";
- }
+ }
return statuses[status];
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::ExpandTestsToRunInformation(size_t numTests)
{
- if (this->TestsToRunString.empty())
- {
+ if (this->TestsToRunString.empty()) {
return;
- }
+ }
int start;
int end = -1;
@@ -1651,311 +1719,317 @@ void cmCTestTestHandler::ExpandTestsToRunInformation(size_t numTests)
std::string::size_type pos = 0;
std::string::size_type pos2;
// read start
- if(GetNextNumber(this->TestsToRunString, start, pos, pos2))
- {
+ if (GetNextNumber(this->TestsToRunString, start, pos, pos2)) {
// read end
- if(GetNextNumber(this->TestsToRunString, end, pos, pos2))
- {
+ if (GetNextNumber(this->TestsToRunString, end, pos, pos2)) {
// read stride
- if(GetNextRealNumber(this->TestsToRunString, stride, pos, pos2))
- {
- int val =0;
+ if (GetNextRealNumber(this->TestsToRunString, stride, pos, pos2)) {
+ int val = 0;
// now read specific numbers
- while(GetNextNumber(this->TestsToRunString, val, pos, pos2))
- {
+ while (GetNextNumber(this->TestsToRunString, val, pos, pos2)) {
this->TestsToRun.push_back(val);
- }
- this->TestsToRun.push_back(val);
}
+ this->TestsToRun.push_back(val);
}
}
+ }
// if start is not specified then we assume we start at 1
- if(start == -1)
- {
+ if (start == -1) {
start = 1;
- }
+ }
// if end isnot specified then we assume we end with the last test
- if(end == -1)
- {
+ if (end == -1) {
end = static_cast<int>(numTests);
- }
+ }
// if the stride wasn't specified then it defaults to 1
- if(stride == -1)
- {
+ if (stride == -1) {
stride = 1;
- }
+ }
// if we have a range then add it
- if(end != -1 && start != -1 && stride > 0)
- {
+ if (end != -1 && start != -1 && stride > 0) {
int i = 0;
- while (i*stride + start <= end)
- {
- this->TestsToRun.push_back(static_cast<int>(i*stride+start));
+ while (i * stride + start <= end) {
+ this->TestsToRun.push_back(static_cast<int>(i * stride + start));
++i;
- }
}
+ }
// sort the array
std::sort(this->TestsToRun.begin(), this->TestsToRun.end(),
- std::less<int>());
+ std::less<int>());
// remove duplicates
std::vector<int>::iterator new_end =
std::unique(this->TestsToRun.begin(), this->TestsToRun.end());
this->TestsToRun.erase(new_end, this->TestsToRun.end());
}
-//----------------------------------------------------------------------
+void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
+{
+
+ std::string dirName = this->CTest->GetBinaryDir() + "/Testing/Temporary";
+
+ cmsys::Directory directory;
+ if (directory.Load(dirName) == 0) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of "
+ << dirName << std::endl);
+ return;
+ }
+
+ int numFiles =
+ static_cast<int>(cmsys::Directory::GetNumberOfFilesInDirectory(dirName));
+ std::string pattern = "LastTestsFailed";
+ std::string logName;
+
+ for (int i = 0; i < numFiles; ++i) {
+ std::string fileName = directory.GetFile(i);
+ // bcc crashes if we attempt a normal substring comparison,
+ // hence the following workaround
+ std::string fileNameSubstring = fileName.substr(0, pattern.length());
+ if (fileNameSubstring != pattern) {
+ continue;
+ }
+ if (logName == "") {
+ logName = fileName;
+ } else {
+ // if multiple matching logs were found we use the most recently
+ // modified one.
+ int res;
+ cmSystemTools::FileTimeCompare(logName, fileName, &res);
+ if (res == -1) {
+ logName = fileName;
+ }
+ }
+ }
+
+ std::string lastTestsFailedLog =
+ this->CTest->GetBinaryDir() + "/Testing/Temporary/" + logName;
+
+ if (!cmSystemTools::FileExists(lastTestsFailedLog.c_str())) {
+ if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, lastTestsFailedLog
+ << " does not exist!" << std::endl);
+ }
+ return;
+ }
+
+ // parse the list of tests to rerun from LastTestsFailed.log
+ cmsys::ifstream ifs(lastTestsFailedLog.c_str());
+ if (ifs) {
+ std::string line;
+ std::string::size_type pos;
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
+ pos = line.find(':', 0);
+ if (pos == std::string::npos) {
+ continue;
+ }
+
+ int val = atoi(line.substr(0, pos).c_str());
+ this->TestsToRun.push_back(val);
+ }
+ ifs.close();
+ } else if (!this->CTest->GetShowOnly() &&
+ !this->CTest->ShouldPrintLabels()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem reading file: "
+ << lastTestsFailedLog
+ << " while generating list of previously failed tests."
+ << std::endl);
+ }
+}
+
// Just for convenience
#define SPACE_REGEX "[ \t\r\n]"
-//----------------------------------------------------------------------
-std::string cmCTestTestHandler::GenerateRegressionImages(
- const std::string& xml)
+void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
+ const std::string& dart)
{
cmsys::RegularExpression twoattributes(
- "<DartMeasurement"
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*>([^<]*)</DartMeasurement>");
+ "<DartMeasurement" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*>([^<]*)</DartMeasurement>");
cmsys::RegularExpression threeattributes(
- "<DartMeasurement"
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*>([^<]*)</DartMeasurement>");
+ "<DartMeasurement" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*>([^<]*)</DartMeasurement>");
cmsys::RegularExpression fourattributes(
- "<DartMeasurement"
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*>([^<]*)</DartMeasurement>");
+ "<DartMeasurement" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*>([^<]*)</DartMeasurement>");
cmsys::RegularExpression cdatastart(
- "<DartMeasurement"
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*>"
- SPACE_REGEX "*<!\\[CDATA\\[");
- cmsys::RegularExpression cdataend(
- "]]>"
- SPACE_REGEX "*</DartMeasurement>");
+ "<DartMeasurement" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*>" SPACE_REGEX "*<!\\[CDATA\\[");
+ cmsys::RegularExpression cdataend("]]>" SPACE_REGEX "*</DartMeasurement>");
cmsys::RegularExpression measurementfile(
- "<DartMeasurementFile"
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\""
- SPACE_REGEX "*>([^<]*)</DartMeasurementFile>");
+ "<DartMeasurementFile" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
+ "*>([^<]*)</DartMeasurementFile>");
- cmOStringStream ostr;
bool done = false;
- std::string cxml = xml;
- while ( ! done )
- {
- if ( twoattributes.find(cxml) )
- {
- ostr
- << "\t\t\t<NamedMeasurement"
- << " " << twoattributes.match(1) << "=\""
- << twoattributes.match(2) << "\""
- << " " << twoattributes.match(3) << "=\""
- << twoattributes.match(4) << "\""
- << "><Value>" << twoattributes.match(5)
- << "</Value></NamedMeasurement>"
- << std::endl;
+ std::string cxml = dart;
+ while (!done) {
+ if (twoattributes.find(cxml)) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(twoattributes.match(1).c_str(), twoattributes.match(2));
+ xml.Attribute(twoattributes.match(3).c_str(), twoattributes.match(4));
+ xml.Element("Value", twoattributes.match(5));
+ xml.EndElement();
cxml.erase(twoattributes.start(),
- twoattributes.end() - twoattributes.start());
- }
- else if ( threeattributes.find(cxml) )
- {
- ostr
- << "\t\t\t<NamedMeasurement"
- << " " << threeattributes.match(1) << "=\""
- << threeattributes.match(2) << "\""
- << " " << threeattributes.match(3) << "=\""
- << threeattributes.match(4) << "\""
- << " " << threeattributes.match(5) << "=\""
- << threeattributes.match(6) << "\""
- << "><Value>" << threeattributes.match(7)
- << "</Value></NamedMeasurement>"
- << std::endl;
+ twoattributes.end() - twoattributes.start());
+ } else if (threeattributes.find(cxml)) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(threeattributes.match(1).c_str(),
+ threeattributes.match(2));
+ xml.Attribute(threeattributes.match(3).c_str(),
+ threeattributes.match(4));
+ xml.Attribute(threeattributes.match(5).c_str(),
+ threeattributes.match(6));
+ xml.Element("Value", twoattributes.match(7));
+ xml.EndElement();
cxml.erase(threeattributes.start(),
- threeattributes.end() - threeattributes.start());
- }
- else if ( fourattributes.find(cxml) )
- {
- ostr
- << "\t\t\t<NamedMeasurement"
- << " " << fourattributes.match(1) << "=\""
- << fourattributes.match(2) << "\""
- << " " << fourattributes.match(3) << "=\""
- << fourattributes.match(4) << "\""
- << " " << fourattributes.match(5) << "=\""
- << fourattributes.match(6) << "\""
- << " " << fourattributes.match(7) << "=\""
- << fourattributes.match(8) << "\""
- << "><Value>" << fourattributes.match(9)
- << "</Value></NamedMeasurement>"
- << std::endl;
+ threeattributes.end() - threeattributes.start());
+ } else if (fourattributes.find(cxml)) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(fourattributes.match(1).c_str(), fourattributes.match(2));
+ xml.Attribute(fourattributes.match(3).c_str(), fourattributes.match(4));
+ xml.Attribute(fourattributes.match(5).c_str(), fourattributes.match(6));
+ xml.Attribute(fourattributes.match(7).c_str(), fourattributes.match(8));
+ xml.Element("Value", twoattributes.match(9));
+ xml.EndElement();
cxml.erase(fourattributes.start(),
- fourattributes.end() - fourattributes.start());
- }
- else if ( cdatastart.find(cxml) && cdataend.find(cxml) )
- {
- ostr
- << "\t\t\t<NamedMeasurement"
- << " " << cdatastart.match(1) << "=\""
- << cdatastart.match(2) << "\""
- << " " << cdatastart.match(3) << "=\""
- << cdatastart.match(4) << "\""
- << "><Value><![CDATA["
- << cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end())
- << "]]></Value></NamedMeasurement>"
- << std::endl;
- cxml.erase(cdatastart.start(),
- cdataend.end() - cdatastart.start());
- }
- else if ( measurementfile.find(cxml) )
- {
+ fourattributes.end() - fourattributes.start());
+ } else if (cdatastart.find(cxml) && cdataend.find(cxml)) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2));
+ xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4));
+ xml.StartElement("Value");
+ xml.CData(
+ cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()));
+ xml.EndElement(); // Value
+ xml.EndElement(); // NamedMeasurement
+ cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start());
+ } else if (measurementfile.find(cxml)) {
const std::string& filename =
cmCTest::CleanString(measurementfile.match(5));
- if ( cmSystemTools::FileExists(filename.c_str()) )
- {
- long len = cmSystemTools::FileLength(filename.c_str());
- if ( len == 0 )
- {
+ if (cmSystemTools::FileExists(filename.c_str())) {
+ long len = cmSystemTools::FileLength(filename);
+ if (len == 0) {
std::string k1 = measurementfile.match(1);
std::string v1 = measurementfile.match(2);
std::string k2 = measurementfile.match(3);
std::string v2 = measurementfile.match(4);
- if ( cmSystemTools::LowerCase(k1) == "type" )
- {
+ if (cmSystemTools::LowerCase(k1) == "type") {
v1 = "text/string";
- }
- if ( cmSystemTools::LowerCase(k2) == "type" )
- {
+ }
+ if (cmSystemTools::LowerCase(k2) == "type") {
v2 = "text/string";
- }
-
- ostr
- << "\t\t\t<NamedMeasurement"
- << " " << k1 << "=\"" << v1 << "\""
- << " " << k2 << "=\"" << v2 << "\""
- << " encoding=\"none\""
- << "><Value>Image " << filename.c_str()
- << " is empty</Value></NamedMeasurement>";
}
- else
- {
- std::ifstream ifs(filename.c_str(), std::ios::in
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(k1.c_str(), v1);
+ xml.Attribute(k2.c_str(), v2);
+ xml.Attribute("encoding", "none");
+ xml.Element("Value", "Image " + filename + " is empty");
+ xml.EndElement();
+ } else {
+ cmsys::ifstream ifs(filename.c_str(), std::ios::in
#ifdef _WIN32
- | std::ios::binary
+ | std::ios::binary
#endif
- );
- unsigned char *file_buffer = new unsigned char [ len + 1 ];
+ );
+ 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>(
- static_cast<double>(len) * 1.5 + 5.0) ];
-
- unsigned long rlen
- = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
- unsigned long cc;
-
- ostr
- << "\t\t\t<NamedMeasurement"
- << " " << measurementfile.match(1) << "=\""
- << measurementfile.match(2) << "\""
- << " " << measurementfile.match(3) << "=\""
- << measurementfile.match(4) << "\""
- << " encoding=\"base64\""
- << ">" << std::endl << "\t\t\t\t<Value>";
- for ( cc = 0; cc < rlen; cc ++ )
- {
+ unsigned char* encoded_buffer = new unsigned char[static_cast<int>(
+ static_cast<double>(len) * 1.5 + 5.0)];
+
+ size_t rlen =
+ cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(measurementfile.match(1).c_str(),
+ measurementfile.match(2));
+ xml.Attribute(measurementfile.match(3).c_str(),
+ measurementfile.match(4));
+ xml.Attribute("encoding", "base64");
+ std::ostringstream ostr;
+ for (size_t cc = 0; cc < rlen; cc++) {
ostr << encoded_buffer[cc];
- if ( cc % 60 == 0 && cc )
- {
+ if (cc % 60 == 0 && cc) {
ostr << std::endl;
- }
}
- ostr
- << "</Value>" << std::endl << "\t\t\t</NamedMeasurement>"
- << std::endl;
- delete [] file_buffer;
- delete [] encoded_buffer;
}
+ xml.Element("Value", ostr.str());
+ xml.EndElement(); // NamedMeasurement
+ delete[] file_buffer;
+ delete[] encoded_buffer;
}
- else
- {
+ } else {
int idx = 4;
- if ( measurementfile.match(1) == "name" )
- {
+ if (measurementfile.match(1) == "name") {
idx = 2;
- }
- ostr
- << "\t\t\t<NamedMeasurement"
- << " name=\"" << measurementfile.match(idx) << "\""
- << " text=\"text/string\""
- << "><Value>File " << filename.c_str()
- << " not found</Value></NamedMeasurement>"
- << std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "File \"" << filename.c_str()
- << "\" not found." << std::endl);
}
- cxml.erase(measurementfile.start(),
- measurementfile.end() - measurementfile.start());
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("name", measurementfile.match(idx));
+ 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);
}
- else
- {
+ cxml.erase(measurementfile.start(),
+ measurementfile.end() - measurementfile.start());
+ } else {
done = true;
- }
}
- return ostr.str();
+ }
}
-//----------------------------------------------------------------------
-void cmCTestTestHandler::SetIncludeRegExp(const char *arg)
+void cmCTestTestHandler::SetIncludeRegExp(const char* arg)
{
this->IncludeRegExp = arg;
}
-//----------------------------------------------------------------------
-void cmCTestTestHandler::SetExcludeRegExp(const char *arg)
+void cmCTestTestHandler::SetExcludeRegExp(const char* arg)
{
this->ExcludeRegExp = arg;
}
-//----------------------------------------------------------------------
void cmCTestTestHandler::SetTestsToRunInformation(const char* in)
{
- if ( !in )
- {
+ if (!in) {
return;
- }
+ }
this->TestsToRunString = in;
// if the argument is a file, then read it and use the contents as the
// string
- if(cmSystemTools::FileExists(in))
- {
- std::ifstream fin(in);
+ if (cmSystemTools::FileExists(in)) {
+ cmsys::ifstream fin(in);
unsigned long filelen = cmSystemTools::FileLength(in);
- char* buff = new char[filelen+1];
+ char* buff = new char[filelen + 1];
fin.getline(buff, filelen);
buff[fin.gcount()] = 0;
this->TestsToRunString = buff;
- delete [] buff;
- }
+ delete[] buff;
+ }
}
-//----------------------------------------------------------------------------
bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length)
{
- if(!length || length >= output.size() ||
- output.find("CTEST_FULL_OUTPUT") != output.npos)
- {
+ if (!length || length >= output.size() ||
+ output.find("CTEST_FULL_OUTPUT") != std::string::npos) {
return true;
- }
+ }
// Truncate at given length but do not break in the middle of a multi-byte
// UTF-8 encoding.
@@ -1963,303 +2037,260 @@ bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length)
char const* const end = begin + output.size();
char const* const truncate = begin + length;
char const* current = begin;
- while(current < truncate)
- {
+ while (current < truncate) {
unsigned int ch;
- if(const char* next = cm_utf8_decode_character(current, end, &ch))
- {
- if(next > truncate)
- {
+ if (const char* next = cm_utf8_decode_character(current, end, &ch)) {
+ if (next > truncate) {
break;
- }
- current = next;
}
- else // Bad byte will be handled by cmXMLSafe.
- {
+ current = next;
+ } else // Bad byte will be handled by cmXMLWriter.
+ {
++current;
- }
}
+ }
output = output.substr(0, current - begin);
// Append truncation message.
- cmOStringStream msg;
+ std::ostringstream msg;
msg << "...\n"
- "The rest of the test output was removed since it exceeds the threshold "
- "of " << length << " bytes.\n";
+ "The rest of the test output was removed since it exceeds the "
+ "threshold "
+ "of "
+ << length << " bytes.\n";
output += msg.str();
return true;
}
-//----------------------------------------------------------------------
bool cmCTestTestHandler::SetTestsProperties(
const std::vector<std::string>& args)
{
std::vector<std::string>::const_iterator it;
- std::vector<cmStdString> tests;
+ std::vector<std::string> tests;
bool found = false;
- for ( it = args.begin(); it != args.end(); ++ it )
- {
- if ( *it == "PROPERTIES" )
- {
+ for (it = args.begin(); it != args.end(); ++it) {
+ if (*it == "PROPERTIES") {
found = true;
break;
- }
- tests.push_back(*it);
}
- if ( !found )
- {
+ tests.push_back(*it);
+ }
+ if (!found) {
return false;
- }
- ++ it; // skip PROPERTIES
- for ( ; it != args.end(); ++ it )
- {
+ }
+ ++it; // skip PROPERTIES
+ for (; it != args.end(); ++it) {
std::string key = *it;
- ++ it;
- if ( it == args.end() )
- {
+ ++it;
+ if (it == args.end()) {
break;
- }
+ }
std::string val = *it;
- std::vector<cmStdString>::const_iterator tit;
- for ( tit = tests.begin(); tit != tests.end(); ++ tit )
- {
+ 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 )
- {
- if ( key == "WILL_FAIL" )
- {
+ for (rtit = this->TestList.begin(); rtit != this->TestList.end();
+ ++rtit) {
+ if (*tit == rtit->Name) {
+ if (key == "WILL_FAIL") {
rtit->WillFail = cmSystemTools::IsOn(val.c_str());
- }
- if ( key == "ATTACHED_FILES" )
- {
+ }
+ if (key == "DISABLED") {
+ rtit->Disabled = cmSystemTools::IsOn(val.c_str());
+ }
+ if (key == "ATTACHED_FILES") {
+ cmSystemTools::ExpandListArgument(val, rtit->AttachedFiles);
+ }
+ if (key == "ATTACHED_FILES_ON_FAIL") {
+ cmSystemTools::ExpandListArgument(val, rtit->AttachOnFail);
+ }
+ if (key == "RESOURCE_LOCK") {
std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
+ cmSystemTools::ExpandListArgument(val, lval);
- for(std::vector<std::string>::iterator f = lval.begin();
- f != lval.end(); ++f)
- {
- rtit->AttachedFiles.push_back(*f);
- }
- }
- if ( key == "ATTACHED_FILES_ON_FAIL" )
- {
+ rtit->LockedResources.insert(lval.begin(), lval.end());
+ }
+ if (key == "FIXTURES_SETUP") {
std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
+ cmSystemTools::ExpandListArgument(val, lval);
- for(std::vector<std::string>::iterator f = lval.begin();
- f != lval.end(); ++f)
- {
- rtit->AttachOnFail.push_back(*f);
- }
- }
- if ( key == "RESOURCE_LOCK" )
- {
+ rtit->FixturesSetup.insert(lval.begin(), lval.end());
+ }
+ if (key == "FIXTURES_CLEANUP") {
std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
+ cmSystemTools::ExpandListArgument(val, lval);
- for(std::vector<std::string>::iterator f = lval.begin();
- f != lval.end(); ++f)
- {
- rtit->LockedResources.insert(*f);
- }
- }
- if ( key == "TIMEOUT" )
- {
+ rtit->FixturesCleanup.insert(lval.begin(), lval.end());
+ }
+ if (key == "FIXTURES_REQUIRED") {
+ std::vector<std::string> lval;
+ cmSystemTools::ExpandListArgument(val, lval);
+
+ rtit->FixturesRequired.insert(lval.begin(), lval.end());
+ }
+ if (key == "TIMEOUT") {
rtit->Timeout = atof(val.c_str());
rtit->ExplicitTimeout = true;
- }
- if ( key == "COST" )
- {
+ }
+ if (key == "COST") {
rtit->Cost = static_cast<float>(atof(val.c_str()));
- }
- if ( key == "REQUIRED_FILES" )
- {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
-
- for(std::vector<std::string>::iterator f = lval.begin();
- f != lval.end(); ++f)
- {
- rtit->RequiredFiles.push_back(*f);
- }
- }
- if ( key == "RUN_SERIAL" )
- {
+ }
+ if (key == "REQUIRED_FILES") {
+ cmSystemTools::ExpandListArgument(val, rtit->RequiredFiles);
+ }
+ if (key == "RUN_SERIAL") {
rtit->RunSerial = cmSystemTools::IsOn(val.c_str());
- }
- if ( key == "FAIL_REGULAR_EXPRESSION" )
- {
+ }
+ if (key == "FAIL_REGULAR_EXPRESSION") {
std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
+ cmSystemTools::ExpandListArgument(val, lval);
std::vector<std::string>::iterator crit;
- for ( crit = lval.begin(); crit != lval.end(); ++ 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->c_str())));
- }
+ std::string(*crit)));
}
- if ( key == "PROCESSORS" )
- {
+ }
+ if (key == "PROCESSORS") {
rtit->Processors = atoi(val.c_str());
- if(rtit->Processors < 1)
- {
+ if (rtit->Processors < 1) {
rtit->Processors = 1;
- }
- }
- if ( key == "DEPENDS" )
- {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
- std::vector<std::string>::iterator crit;
- for ( crit = lval.begin(); crit != lval.end(); ++ crit )
- {
- rtit->Depends.push_back(*crit);
- }
}
- if ( key == "ENVIRONMENT" )
- {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
- std::vector<std::string>::iterator crit;
- for ( crit = lval.begin(); crit != lval.end(); ++ crit )
- {
- rtit->Environment.push_back(*crit);
- }
- }
- if ( key == "LABELS" )
- {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
- std::vector<std::string>::iterator crit;
- for ( crit = lval.begin(); crit != lval.end(); ++ crit )
- {
- rtit->Labels.push_back(*crit);
- }
+ }
+ if (key == "SKIP_RETURN_CODE") {
+ rtit->SkipReturnCode = atoi(val.c_str());
+ if (rtit->SkipReturnCode < 0 || rtit->SkipReturnCode > 255) {
+ rtit->SkipReturnCode = -1;
}
- if ( key == "MEASUREMENT" )
- {
- size_t pos = val.find_first_of("=");
- if ( pos != val.npos )
- {
+ }
+ if (key == "DEPENDS") {
+ cmSystemTools::ExpandListArgument(val, rtit->Depends);
+ }
+ if (key == "ENVIRONMENT") {
+ cmSystemTools::ExpandListArgument(val, rtit->Environment);
+ }
+ if (key == "LABELS") {
+ cmSystemTools::ExpandListArgument(val, rtit->Labels);
+ }
+ 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;
- }
- else
- {
+ } else {
rtit->Measurements[val] = "1";
- }
}
- if ( key == "PASS_REGULAR_EXPRESSION" )
- {
+ }
+ if (key == "PASS_REGULAR_EXPRESSION") {
std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val.c_str(), lval);
+ cmSystemTools::ExpandListArgument(val, lval);
std::vector<std::string>::iterator crit;
- for ( crit = lval.begin(); crit != lval.end(); ++ 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->c_str())));
- }
+ std::string(*crit)));
}
- if ( key == "WORKING_DIRECTORY" )
- {
+ }
+ if (key == "WORKING_DIRECTORY") {
rtit->Directory = val;
+ }
+ if (key == "TIMEOUT_AFTER_MATCH") {
+ std::vector<std::string> propArgs;
+ cmSystemTools::ExpandListArgument(val, propArgs);
+ 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)));
+ }
}
}
}
}
}
+ }
return true;
}
-//----------------------------------------------------------------------
bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
{
const std::string& testname = args[0];
- cmCTestLog(this->CTest, DEBUG, "Add test: " << args[0] << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, "Add test: " << args[0] << std::endl,
+ this->Quiet);
- if (this->UseExcludeRegExpFlag &&
- this->UseExcludeRegExpFirst &&
- this->ExcludeTestsRegularExpression.find(testname.c_str()))
- {
+ if (this->UseExcludeRegExpFlag && this->UseExcludeRegExpFirst &&
+ this->ExcludeTestsRegularExpression.find(testname.c_str())) {
return true;
- }
- if ( this->MemCheck )
- {
- std::vector<cmStdString>::iterator it;
+ }
+ if (this->MemCheck) {
+ std::vector<std::string>::iterator it;
bool found = false;
- for ( it = this->CustomTestsIgnore.begin();
- it != this->CustomTestsIgnore.end(); ++ it )
- {
- if ( *it == testname )
- {
+ for (it = this->CustomTestsIgnore.begin();
+ it != this->CustomTestsIgnore.end(); ++it) {
+ if (*it == testname) {
found = true;
break;
- }
}
- if ( found )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Ignore memcheck: "
- << *it << std::endl);
+ }
+ if (found) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Ignore memcheck: " << *it << std::endl, this->Quiet);
return true;
- }
}
- else
- {
- std::vector<cmStdString>::iterator it;
+ } else {
+ std::vector<std::string>::iterator it;
bool found = false;
- for ( it = this->CustomTestsIgnore.begin();
- it != this->CustomTestsIgnore.end(); ++ it )
- {
- if ( *it == testname )
- {
+ for (it = this->CustomTestsIgnore.begin();
+ it != this->CustomTestsIgnore.end(); ++it) {
+ if (*it == testname) {
found = true;
break;
- }
}
- if ( found )
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Ignore test: "
- << *it << std::endl);
+ }
+ if (found) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Ignore test: " << *it << std::endl, this->Quiet);
return true;
- }
}
+ }
cmCTestTestProperties test;
test.Name = testname;
test.Args = args;
test.Directory = cmSystemTools::GetCurrentWorkingDirectory();
- cmCTestLog(this->CTest, DEBUG, "Set test directory: "
- << test.Directory << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Set test directory: " << test.Directory << std::endl,
+ this->Quiet);
test.IsInBasedOnREOptions = true;
test.WillFail = false;
+ test.Disabled = false;
test.RunSerial = false;
test.Timeout = 0;
test.ExplicitTimeout = false;
test.Cost = 0;
test.Processors = 1;
+ test.SkipReturnCode = -1;
test.PreviousRuns = 0;
if (this->UseIncludeRegExpFlag &&
- !this->IncludeTestsRegularExpression.find(testname.c_str()))
- {
+ !this->IncludeTestsRegularExpression.find(testname.c_str())) {
test.IsInBasedOnREOptions = false;
- }
- else if (this->UseExcludeRegExpFlag &&
- !this->UseExcludeRegExpFirst &&
- this->ExcludeTestsRegularExpression.find(testname.c_str()))
- {
+ } else if (this->UseExcludeRegExpFlag && !this->UseExcludeRegExpFirst &&
+ this->ExcludeTestsRegularExpression.find(testname.c_str())) {
test.IsInBasedOnREOptions = false;
- }
+ }
this->TestList.push_back(test);
return true;
}
-
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 93b793b20..0edcb143a 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -1,23 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestTestHandler_h
#define cmCTestTestHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <stddef.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+class cmCTest;
class cmMakefile;
+class cmXMLWriter;
/** \class cmCTestTestHandler
* \brief A class that handles ctest -S invocations
@@ -28,13 +29,14 @@ class cmCTestTestHandler : public cmCTestGenericHandler
friend class cmCTestRunTest;
friend class cmCTestMultiProcessHandler;
friend class cmCTestBatchTestHandler;
+
public:
- cmTypeMacro(cmCTestTestHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
/**
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
/**
* When both -R and -I are used should te resulting test list be the
@@ -44,19 +46,34 @@ public:
void SetUseUnion(bool val) { this->UseUnion = val; }
/**
+ * Set whether or not CTest should only execute the tests that failed
+ * on the previous run. By default this is false.
+ */
+ void SetRerunFailed(bool val) { this->RerunFailed = val; }
+
+ /**
* This method is called when reading CTest custom file
*/
- void PopulateCustomVectors(cmMakefile *mf);
+ void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
///! Control the use of the regular expresisons, call these methods to turn
- ///them on
+ /// them on
void UseIncludeRegExp();
void UseExcludeRegExp();
- void SetIncludeRegExp(const char *);
- void SetExcludeRegExp(const char *);
+ void SetIncludeRegExp(const char*);
+ void SetExcludeRegExp(const char*);
- void SetMaxIndex(int n) {this->MaxIndex = n;}
- int GetMaxIndex() {return this->MaxIndex;}
+ void SetMaxIndex(int n) { this->MaxIndex = n; }
+ int GetMaxIndex() { return this->MaxIndex; }
+
+ void SetTestOutputSizePassed(int n)
+ {
+ this->CustomMaximumPassedTestOutputSize = n;
+ }
+ void SetTestOutputSizeFailed(int n)
+ {
+ this->CustomMaximumFailedTestOutputSize = n;
+ }
///! pass the -I argument down
void SetTestsToRunInformation(const char*);
@@ -73,7 +90,7 @@ public:
*/
bool SetTestsProperties(const std::vector<std::string>& args);
- void Initialize();
+ void Initialize() CM_OVERRIDE;
// NOTE: This struct is Saved/Restored
// in cmCTestTestHandler, if you add to this class
@@ -81,31 +98,41 @@ public:
// ctest -j N will break for that feature
struct cmCTestTestProperties
{
- cmStdString Name;
- cmStdString Directory;
+ std::string Name;
+ std::string Directory;
std::vector<std::string> Args;
std::vector<std::string> RequiredFiles;
std::vector<std::string> Depends;
std::vector<std::string> AttachedFiles;
std::vector<std::string> AttachOnFail;
- std::vector<std::pair<cmsys::RegularExpression,
- std::string> > ErrorRegularExpressions;
- std::vector<std::pair<cmsys::RegularExpression,
- std::string> > RequiredRegularExpressions;
- std::map<cmStdString, cmStdString> Measurements;
+ std::vector<std::pair<cmsys::RegularExpression, std::string> >
+ ErrorRegularExpressions;
+ std::vector<std::pair<cmsys::RegularExpression, std::string> >
+ RequiredRegularExpressions;
+ std::vector<std::pair<cmsys::RegularExpression, std::string> >
+ TimeoutRegularExpressions;
+ std::map<std::string, std::string> Measurements;
bool IsInBasedOnREOptions;
bool WillFail;
+ bool Disabled;
float Cost;
int PreviousRuns;
bool RunSerial;
double Timeout;
bool ExplicitTimeout;
+ double AlternateTimeout;
int Index;
- //Requested number of process slots
+ // Requested number of process slots
int Processors;
+ // return code of test which will mark test as "not run"
+ int SkipReturnCode;
std::vector<std::string> Environment;
std::vector<std::string> Labels;
std::set<std::string> LockedResources;
+ std::set<std::string> FixturesSetup;
+ std::set<std::string> FixturesCleanup;
+ std::set<std::string> FixturesRequired;
+ std::set<std::string> RequireSuccessDepends;
};
struct cmCTestTestResult
@@ -114,72 +141,73 @@ public:
std::string Path;
std::string Reason;
std::string FullCommandLine;
- double ExecutionTime;
- int ReturnValue;
- int Status;
- bool CompressOutput;
+ double ExecutionTime;
+ int ReturnValue;
+ int Status;
+ bool CompressOutput;
std::string CompletionStatus;
std::string Output;
- std::string RegressionImages;
- int TestCount;
+ std::string DartString;
+ int TestCount;
cmCTestTestProperties* Properties;
};
struct cmCTestTestResultLess
{
- bool operator() (const cmCTestTestResult &lhs,
- const cmCTestTestResult &rhs) const
+ bool operator()(const cmCTestTestResult& lhs,
+ const cmCTestTestResult& rhs) const
{
- return lhs.TestCount < rhs.TestCount;
+ return lhs.TestCount < rhs.TestCount;
}
};
// add configurations to a search path for an executable
- static void AddConfigurations(cmCTest *ctest,
- std::vector<std::string> &attempted,
- std::vector<std::string> &attemptedConfigs,
- std::string filepath,
- std::string &filename);
+ static void AddConfigurations(cmCTest* ctest,
+ std::vector<std::string>& attempted,
+ std::vector<std::string>& attemptedConfigs,
+ std::string filepath, std::string& filename);
// full signature static method to find an executable
- static std::string FindExecutable(cmCTest *ctest,
- const char *testCommand,
- std::string &resultingConfig,
- std::vector<std::string> &extraPaths,
- std::vector<std::string> &failed);
+ static std::string FindExecutable(cmCTest* ctest, const char* testCommand,
+ std::string& resultingConfig,
+ std::vector<std::string>& extraPaths,
+ std::vector<std::string>& failed);
typedef std::vector<cmCTestTestProperties> ListOfTests;
+
protected:
// 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<cmStdString>& vec);
+ int ExecuteCommands(std::vector<std::string>& vec);
- void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
- void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result);
+ void WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult* result);
+ void WriteTestResultFooter(cmXMLWriter& xml, cmCTestTestResult* result);
// Write attached test files into the xml
- void AttachFiles(std::ostream& os, cmCTestTestResult* result);
+ void AttachFiles(cmXMLWriter& xml, cmCTestTestResult* result);
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
- double ElapsedTestingTime;
+ double ElapsedTestingTime;
typedef std::vector<cmCTestTestResult> TestResultsVector;
- TestResultsVector TestResults;
+ TestResultsVector TestResults;
- std::vector<cmStdString> CustomTestsIgnore;
- std::string StartTest;
- std::string EndTest;
- unsigned int StartTestTime;
- unsigned int EndTestTime;
+ std::vector<std::string> CustomTestsIgnore;
+ std::string StartTest;
+ std::string EndTest;
+ unsigned int StartTestTime;
+ unsigned int EndTestTime;
bool MemCheck;
int CustomMaximumPassedTestOutputSize;
int CustomMaximumFailedTestOutputSize;
int MaxIndex;
+
public:
- enum { // Program statuses
+ enum
+ { // Program statuses
NOT_RUN = 0,
TIMEOUT,
SEGFAULT,
@@ -196,14 +224,14 @@ private:
/**
* Generate the Dart compatible output
*/
- virtual void GenerateDartOutput(std::ostream& os);
+ virtual void GenerateDartOutput(cmXMLWriter& xml);
void PrintLabelSummary();
/**
* Run the tests for a directory and any subdirectories
*/
- void ProcessDirectory(std::vector<cmStdString> &passed,
- std::vector<cmStdString> &failed);
+ void ProcessDirectory(std::vector<std::string>& passed,
+ std::vector<std::string>& failed);
/**
* Get the list of tests in directory and subdirectories.
@@ -213,33 +241,35 @@ private:
// based on union regex and -I stuff
void ComputeTestList();
- bool GetValue(const char* tag,
- std::string& value,
- std::ifstream& fin);
- bool GetValue(const char* tag,
- int& value,
- std::ifstream& fin);
- bool GetValue(const char* tag,
- size_t& value,
- std::ifstream& fin);
- bool GetValue(const char* tag,
- bool& value,
- std::ifstream& fin);
- bool GetValue(const char* tag,
- double& value,
- std::ifstream& fin);
+ // compute the lists of tests that will actually run
+ // based on LastTestFailed.log
+ void ComputeTestListForRerunFailed();
+
+ // add required setup/cleanup tests not already in the
+ // list of tests to be run and update dependencies between
+ // tests to account for fixture setup/cleanup
+ void UpdateForFixtures(ListOfTests& tests) const;
+
+ void UpdateMaxTestNameWidth();
+
+ bool GetValue(const char* tag, std::string& value, std::istream& fin);
+ bool GetValue(const char* tag, int& value, std::istream& fin);
+ bool GetValue(const char* tag, size_t& value, std::istream& fin);
+ bool GetValue(const char* tag, bool& value, std::istream& fin);
+ bool GetValue(const char* tag, double& value, std::istream& fin);
/**
* Find the executable for a test
*/
- std::string FindTheExecutable(const char *exe);
+ std::string FindTheExecutable(const char* exe);
const char* GetTestStatus(int status);
void ExpandTestsToRunInformation(size_t numPossibleTests);
+ void ExpandTestsToRunInformationForRerunFailed();
- std::vector<cmStdString> CustomPreTest;
- std::vector<cmStdString> CustomPostTest;
+ std::vector<std::string> CustomPreTest;
+ std::vector<std::string> CustomPostTest;
- std::vector<int> TestsToRun;
+ std::vector<int> TestsToRun;
bool UseIncludeLabelRegExpFlag;
bool UseExcludeLabelRegExpFlag;
@@ -250,12 +280,15 @@ private:
std::string ExcludeLabelRegExp;
std::string IncludeRegExp;
std::string ExcludeRegExp;
+ std::string ExcludeFixtureRegExp;
+ std::string ExcludeFixtureSetupRegExp;
+ std::string ExcludeFixtureCleanupRegExp;
cmsys::RegularExpression IncludeLabelRegularExpression;
cmsys::RegularExpression ExcludeLabelRegularExpression;
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
- std::string GenerateRegressionImages(const std::string& xml);
+ void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
cmsys::RegularExpression DartStuff1;
void CheckLabelFilter(cmCTestTestProperties& it);
void CheckLabelFilterExclude(cmCTestTestProperties& it);
@@ -268,6 +301,8 @@ private:
cmsys::RegularExpression DartStuff;
std::ostream* LogFile;
+
+ bool RerunFailed;
};
#endif
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 2ca9f6c86..8c037545f 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -1,80 +1,91 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUpdateCommand.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include <vector>
cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
{
- if ( this->Values[ct_SOURCE] )
- {
- this->CTest->SetCTestConfiguration("SourceDirectory",
+ if (this->Values[ct_SOURCE]) {
+ this->CTest->SetCTestConfiguration(
+ "SourceDirectory",
+ cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
+ this->Quiet);
+ } else {
+ this->CTest->SetCTestConfiguration(
+ "SourceDirectory",
cmSystemTools::CollapseFullPath(
- this->Values[ct_SOURCE]).c_str());
- }
- else
- {
- this->CTest->SetCTestConfiguration("SourceDirectory",
- cmSystemTools::CollapseFullPath(
- this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY")).c_str());
- }
- std::string source_dir
- = this->CTest->GetCTestConfiguration("SourceDirectory");
+ this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"))
+ .c_str(),
+ this->Quiet);
+ }
+ std::string source_dir =
+ this->CTest->GetCTestConfiguration("SourceDirectory");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "UpdateCommand", "CTEST_UPDATE_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "UpdateOptions", "CTEST_UPDATE_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "CVSCommand", "CTEST_CVS_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "CVSUpdateOptions", "CTEST_CVS_UPDATE_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "SVNCommand", "CTEST_SVN_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "SVNUpdateOptions", "CTEST_SVN_UPDATE_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "SVNOptions", "CTEST_SVN_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "BZRCommand", "CTEST_BZR_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "BZRUpdateOptions", "CTEST_BZR_UPDATE_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "GITCommand", "CTEST_GIT_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "GITUpdateOptions", "CTEST_GIT_UPDATE_OPTIONS");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "GITUpdateCustom", "CTEST_GIT_UPDATE_CUSTOM");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "HGCommand", "CTEST_HG_COMMAND");
- this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
- "HGUpdateOptions", "CTEST_HG_UPDATE_OPTIONS");
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "UpdateCommand", "CTEST_UPDATE_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "UpdateOptions", "CTEST_UPDATE_OPTIONS", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "CVSCommand", "CTEST_CVS_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "CVSUpdateOptions", "CTEST_CVS_UPDATE_OPTIONS",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "SVNCommand", "CTEST_SVN_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "SVNUpdateOptions", "CTEST_SVN_UPDATE_OPTIONS",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "SVNOptions", "CTEST_SVN_OPTIONS", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "BZRCommand", "CTEST_BZR_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "BZRUpdateOptions", "CTEST_BZR_UPDATE_OPTIONS",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "GITCommand", "CTEST_GIT_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "GITUpdateOptions", "CTEST_GIT_UPDATE_OPTIONS",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "GITInitSubmodules", "CTEST_GIT_INIT_SUBMODULES",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "GITUpdateCustom", "CTEST_GIT_UPDATE_CUSTOM", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "UpdateVersionOnly", "CTEST_UPDATE_VERSION_ONLY",
+ 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);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "P4Command", "CTEST_P4_COMMAND", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "P4UpdateOptions", "CTEST_P4_UPDATE_OPTIONS", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "P4Client", "CTEST_P4_CLIENT", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "P4Options", "CTEST_P4_OPTIONS", this->Quiet);
- cmCTestGenericHandler* handler
- = this->CTest->GetInitializedHandler("update");
- if ( !handler )
- {
+ cmCTestGenericHandler* handler =
+ this->CTest->GetInitializedHandler("update");
+ if (!handler) {
this->SetError("internal CTest error. Cannot instantiate update handler");
- return 0;
- }
+ return CM_NULLPTR;
+ }
handler->SetCommand(this);
- if ( source_dir.empty() )
- {
+ if (source_dir.empty()) {
this->SetError("source directory not specified. Please use SOURCE tag");
- return 0;
- }
+ return CM_NULLPTR;
+ }
handler->SetOption("SourceDirectory", source_dir.c_str());
+ handler->SetQuiet(this->Quiet);
return handler;
}
-
-
diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h
index c578fff6f..3b8f0a641 100644
--- a/Source/CTest/cmCTestUpdateCommand.h
+++ b/Source/CTest/cmCTestUpdateCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestUpdateCommand_h
#define cmCTestUpdateCommand_h
+#include "cmConfigure.h"
+
#include "cmCTestHandlerCommand.h"
+#include <string>
+
+class cmCTestGenericHandler;
+class cmCommand;
+
/** \class cmCTestUpdate
* \brief Run a ctest script
*
@@ -22,52 +20,26 @@
class cmCTestUpdateCommand : public cmCTestHandlerCommand
{
public:
-
cmCTestUpdateCommand() {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestUpdateCommand* ni = new cmCTestUpdateCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "ctest_update";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Update the work tree from version control.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_update([SOURCE source] [RETURN_VALUE res])\n"
- "Updates the given source directory and stores results in Update.xml. "
- "If no SOURCE is given, the CTEST_SOURCE_DIRECTORY variable is used. "
- "The RETURN_VALUE option specifies a variable in which to store the "
- "result, which is the number of files updated or -1 on error."
- ;
- }
-
- cmTypeMacro(cmCTestUpdateCommand, cmCTestHandlerCommand);
+ std::string GetName() const CM_OVERRIDE { return "ctest_update"; }
protected:
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
};
-
#endif
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 9eae3f3ac..e08a9b7bd 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -1,115 +1,41 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUpdateHandler.h"
+#include "cmCLocaleEnvironmentScope.h"
#include "cmCTest.h"
-#include "cmake.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-#include "cmVersion.h"
-#include "cmGeneratedFileStream.h"
-#include "cmXMLParser.h"
-#include "cmXMLSafe.h"
-
-#include "cmCTestVC.h"
-#include "cmCTestCVS.h"
-#include "cmCTestSVN.h"
#include "cmCTestBZR.h"
+#include "cmCTestCVS.h"
#include "cmCTestGIT.h"
#include "cmCTestHG.h"
+#include "cmCTestP4.h"
+#include "cmCTestSVN.h"
+#include "cmCTestVC.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+#include "cmXMLWriter.h"
-#include <cmsys/auto_ptr.hxx>
-
-//#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Process.h>
-
-// used for sleep
-#ifdef _WIN32
-#include "windows.h"
-#endif
-
-#include <stdlib.h>
-#include <math.h>
-#include <float.h>
+#include "cm_auto_ptr.hxx"
+#include <sstream>
-//----------------------------------------------------------------------
-static const char* cmCTestUpdateHandlerUpdateStrings[] =
-{
- "Unknown",
- "CVS",
- "SVN",
- "BZR",
- "GIT",
- "HG"
+static const char* cmCTestUpdateHandlerUpdateStrings[] = {
+ "Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4"
};
static const char* cmCTestUpdateHandlerUpdateToString(int type)
{
- if ( type < cmCTestUpdateHandler::e_UNKNOWN ||
- type >= cmCTestUpdateHandler::e_LAST )
- {
+ if (type < cmCTestUpdateHandler::e_UNKNOWN ||
+ type >= cmCTestUpdateHandler::e_LAST) {
return cmCTestUpdateHandlerUpdateStrings[cmCTestUpdateHandler::e_UNKNOWN];
- }
+ }
return cmCTestUpdateHandlerUpdateStrings[type];
}
-class cmCTestUpdateHandlerLocale
-{
-public:
- cmCTestUpdateHandlerLocale();
- ~cmCTestUpdateHandlerLocale();
-private:
- std::string saveLCMessages;
-};
-
-cmCTestUpdateHandlerLocale::cmCTestUpdateHandlerLocale()
-{
- const char* lcmess = cmSystemTools::GetEnv("LC_MESSAGES");
- if(lcmess)
- {
- saveLCMessages = lcmess;
- }
- // if LC_MESSAGES is not set to C, then
- // set it, so that svn/cvs info will be in english ascii
- if(! (lcmess && strcmp(lcmess, "C") == 0))
- {
- cmSystemTools::PutEnv("LC_MESSAGES=C");
- }
-}
-
-cmCTestUpdateHandlerLocale::~cmCTestUpdateHandlerLocale()
-{
- // restore the value of LC_MESSAGES after running the version control
- // commands
- if(saveLCMessages.size())
- {
- std::string put = "LC_MESSAGES=";
- put += saveLCMessages;
- cmSystemTools::PutEnv(put.c_str());
- }
- else
- {
- cmSystemTools::UnsetEnv("LC_MESSAGES");
- }
-}
-
-//----------------------------------------------------------------------
cmCTestUpdateHandler::cmCTestUpdateHandler()
{
}
-//----------------------------------------------------------------------
void cmCTestUpdateHandler::Initialize()
{
this->Superclass::Initialize();
@@ -117,114 +43,121 @@ void cmCTestUpdateHandler::Initialize()
this->UpdateType = e_CVS;
}
-//----------------------------------------------------------------------
int cmCTestUpdateHandler::DetermineType(const char* cmd, const char* type)
{
- cmCTestLog(this->CTest, DEBUG, "Determine update type from command: " << cmd
- << " and type: " << type << std::endl);
- if ( type && *type )
- {
- cmCTestLog(this->CTest, DEBUG, "Type specified: " << type << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, "Determine update type from command: "
+ << cmd << " and type: " << type << std::endl,
+ this->Quiet);
+ if (type && *type) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Type specified: " << type << std::endl, this->Quiet);
std::string stype = cmSystemTools::LowerCase(type);
- if ( stype.find("cvs") != std::string::npos )
- {
+ if (stype.find("cvs") != std::string::npos) {
return cmCTestUpdateHandler::e_CVS;
- }
- if ( stype.find("svn") != std::string::npos )
- {
+ }
+ if (stype.find("svn") != std::string::npos) {
return cmCTestUpdateHandler::e_SVN;
- }
- if ( stype.find("bzr") != std::string::npos )
- {
+ }
+ if (stype.find("bzr") != std::string::npos) {
return cmCTestUpdateHandler::e_BZR;
- }
- if ( stype.find("git") != std::string::npos )
- {
+ }
+ if (stype.find("git") != std::string::npos) {
return cmCTestUpdateHandler::e_GIT;
- }
- if ( stype.find("hg") != std::string::npos )
- {
+ }
+ if (stype.find("hg") != std::string::npos) {
return cmCTestUpdateHandler::e_HG;
- }
}
- else
- {
- cmCTestLog(this->CTest, DEBUG, "Type not specified, check command: "
- << cmd << std::endl);
+ if (stype.find("p4") != std::string::npos) {
+ return cmCTestUpdateHandler::e_P4;
+ }
+ } else {
+ cmCTestOptionalLog(
+ this->CTest, DEBUG,
+ "Type not specified, check command: " << cmd << std::endl, this->Quiet);
std::string stype = cmSystemTools::LowerCase(cmd);
- if ( stype.find("cvs") != std::string::npos )
- {
+ if (stype.find("cvs") != std::string::npos) {
return cmCTestUpdateHandler::e_CVS;
- }
- if ( stype.find("svn") != std::string::npos )
- {
+ }
+ if (stype.find("svn") != std::string::npos) {
return cmCTestUpdateHandler::e_SVN;
- }
- if ( stype.find("bzr") != std::string::npos )
- {
+ }
+ if (stype.find("bzr") != std::string::npos) {
return cmCTestUpdateHandler::e_BZR;
- }
- if ( stype.find("git") != std::string::npos )
- {
+ }
+ if (stype.find("git") != std::string::npos) {
return cmCTestUpdateHandler::e_GIT;
- }
- if ( stype.find("hg") != std::string::npos )
- {
+ }
+ if (stype.find("hg") != std::string::npos) {
return cmCTestUpdateHandler::e_HG;
- }
}
+ if (stype.find("p4") != std::string::npos) {
+ return cmCTestUpdateHandler::e_P4;
+ }
+ }
return cmCTestUpdateHandler::e_UNKNOWN;
}
-//----------------------------------------------------------------------
-//clearly it would be nice if this were broken up into a few smaller
-//functions and commented...
+// clearly it would be nice if this were broken up into a few smaller
+// functions and commented...
int cmCTestUpdateHandler::ProcessHandler()
{
// Make sure VCS tool messages are in English so we can parse them.
- cmCTestUpdateHandlerLocale fixLocale;
+ cmCLocaleEnvironmentScope fixLocale;
static_cast<void>(fixLocale);
// Get source dir
const char* sourceDirectory = this->GetOption("SourceDirectory");
- if ( !sourceDirectory )
- {
+ if (!sourceDirectory) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot find SourceDirectory key in the DartConfiguration.tcl"
- << std::endl);
+ "Cannot find SourceDirectory key in the DartConfiguration.tcl"
+ << std::endl);
return -1;
- }
+ }
cmGeneratedFileStream ofs;
- if ( !this->CTest->GetShowOnly() )
- {
+ if (!this->CTest->GetShowOnly()) {
this->StartLogFile("Update", ofs);
- }
+ }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Updating the repository: "
- << sourceDirectory << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Updating the repository: " << sourceDirectory
+ << std::endl,
+ this->Quiet);
- if(!this->SelectVCS())
- {
+ if (!this->SelectVCS()) {
return -1;
- }
+ }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use "
- << cmCTestUpdateHandlerUpdateToString(this->UpdateType)
- << " repository type"
- << std::endl;);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Use "
+ << cmCTestUpdateHandlerUpdateToString(this->UpdateType)
+ << " repository type" << std::endl;
+ , this->Quiet);
// Create an object to interact with the VCS tool.
- cmsys::auto_ptr<cmCTestVC> vc;
- switch (this->UpdateType)
- {
- case e_CVS: vc.reset(new cmCTestCVS(this->CTest, ofs)); break;
- case e_SVN: vc.reset(new cmCTestSVN(this->CTest, ofs)); break;
- case e_BZR: vc.reset(new cmCTestBZR(this->CTest, ofs)); break;
- case e_GIT: vc.reset(new cmCTestGIT(this->CTest, ofs)); break;
- case e_HG: vc.reset(new cmCTestHG(this->CTest, ofs)); break;
- default: vc.reset(new cmCTestVC(this->CTest, ofs)); break;
- }
+ CM_AUTO_PTR<cmCTestVC> vc;
+ switch (this->UpdateType) {
+ case e_CVS:
+ vc.reset(new cmCTestCVS(this->CTest, ofs));
+ break;
+ case e_SVN:
+ vc.reset(new cmCTestSVN(this->CTest, ofs));
+ break;
+ case e_BZR:
+ vc.reset(new cmCTestBZR(this->CTest, ofs));
+ break;
+ case e_GIT:
+ vc.reset(new cmCTestGIT(this->CTest, ofs));
+ break;
+ case e_HG:
+ vc.reset(new cmCTestHG(this->CTest, ofs));
+ break;
+ case e_P4:
+ vc.reset(new cmCTestP4(this->CTest, ofs));
+ break;
+ default:
+ vc.reset(new cmCTestVC(this->CTest, ofs));
+ break;
+ }
vc->SetCommandLineTool(this->UpdateCommand);
vc->SetSourceDirectory(sourceDirectory);
@@ -235,125 +168,130 @@ int cmCTestUpdateHandler::ProcessHandler()
// Now update repository and remember what files were updated
//
cmGeneratedFileStream os;
- if(!this->StartResultingXML(cmCTest::PartUpdate, "Update", os))
- {
+ if (!this->StartResultingXML(cmCTest::PartUpdate, "Update", os)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open log file"
- << std::endl);
+ << 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();
bool updated = vc->Update();
-
- os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- << "<Update mode=\"Client\" Generator=\"ctest-"
- << cmVersion::GetCMakeVersion() << "\">\n"
- << "\t<Site>" << this->CTest->GetCTestConfiguration("Site") << "</Site>\n"
- << "\t<BuildName>" << this->CTest->GetCTestConfiguration("BuildName")
- << "</BuildName>\n"
- << "\t<BuildStamp>" << this->CTest->GetCurrentTag() << "-"
- << this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
- os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
- << "\t<StartTime>" << start_time_time << "</StartTime>\n"
- << "\t<UpdateCommand>"
- << cmXMLSafe(vc->GetUpdateCommandLine()).Quotes(false)
- << "</UpdateCommand>\n"
- << "\t<UpdateType>" << cmXMLSafe(
- cmCTestUpdateHandlerUpdateToString(this->UpdateType))
- << "</UpdateType>\n";
-
- vc->WriteXML(os);
+ std::string buildname =
+ cmCTest::SafeBuildIdField(this->CTest->GetCTestConfiguration("BuildName"));
+
+ cmXMLWriter xml(os);
+ xml.StartDocument();
+ xml.StartElement("Update");
+ xml.Attribute("mode", "Client");
+ xml.Attribute("Generator",
+ std::string("ctest-") + cmVersion::GetCMakeVersion());
+ xml.Element("Site", this->CTest->GetCTestConfiguration("Site"));
+ xml.Element("BuildName", buildname);
+ 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));
+
+ bool loadedMods = vc->WriteXML(xml);
int localModifications = 0;
int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated);
- if(numUpdated)
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Found " << numUpdated << " updated files\n");
- }
- if(int numModified = vc->GetPathCount(cmCTestVC::PathModified))
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Found " << numModified << " locally modified files\n");
+ if (numUpdated) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Found " << numUpdated << " updated files\n",
+ this->Quiet);
+ }
+ if (int numModified = vc->GetPathCount(cmCTestVC::PathModified)) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Found "
+ << numModified << " locally modified files\n",
+ this->Quiet);
localModifications += numModified;
- }
- if(int numConflicting = vc->GetPathCount(cmCTestVC::PathConflicting))
- {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- " Found " << numConflicting << " conflicting files\n");
+ }
+ if (int numConflicting = vc->GetPathCount(cmCTestVC::PathConflicting)) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Found " << numConflicting << " conflicting files\n",
+ this->Quiet);
localModifications += numConflicting;
- }
+ }
- cmCTestLog(this->CTest, DEBUG, "End" << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
std::string end_time = this->CTest->CurrentTime();
- os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
- << "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime())
- << "</EndTime>\n"
- << "<ElapsedMinutes>" <<
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << "</ElapsedMinutes>\n"
- << "\t<UpdateReturnStatus>";
- if(localModifications)
- {
- os << "Update error: There are modified or conflicting files in the "
- "repository";
+ 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.StartElement("UpdateReturnStatus");
+ if (localModifications) {
+ xml.Content("Update error: "
+ "There are modified or conflicting files in the repository");
cmCTestLog(this->CTest, ERROR_MESSAGE,
- " There are modified or conflicting files in the repository"
- << std::endl);
- }
- if(!updated)
- {
- os << "Update command failed:\n" << vc->GetUpdateCommandLine();
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: "
- << vc->GetUpdateCommandLine() << "\n");
- }
- os << "</UpdateReturnStatus>" << std::endl;
- os << "</Update>" << std::endl;
- return numUpdated;
+ " There are modified or conflicting files in the repository"
+ << std::endl);
+ }
+ if (!updated) {
+ xml.Content("Update command failed:\n");
+ xml.Content(vc->GetUpdateCommandLine());
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Update command failed: "
+ << vc->GetUpdateCommandLine() << "\n");
+ }
+ xml.EndElement(); // UpdateReturnStatus
+ xml.EndElement(); // Update
+ xml.EndDocument();
+ return updated && loadedMods ? numUpdated : -1;
}
-//----------------------------------------------------------------------
int cmCTestUpdateHandler::DetectVCS(const char* dir)
{
std::string sourceDirectory = dir;
- cmCTestLog(this->CTest, DEBUG, "Check directory: "
- << sourceDirectory.c_str() << std::endl);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Check directory: " << sourceDirectory << std::endl,
+ this->Quiet);
sourceDirectory += "/.svn";
- if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
- {
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
return cmCTestUpdateHandler::e_SVN;
- }
+ }
sourceDirectory = dir;
sourceDirectory += "/CVS";
- if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
- {
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
return cmCTestUpdateHandler::e_CVS;
- }
+ }
sourceDirectory = dir;
sourceDirectory += "/.bzr";
- if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
- {
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
return cmCTestUpdateHandler::e_BZR;
- }
+ }
sourceDirectory = dir;
sourceDirectory += "/.git";
- if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
- {
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
return cmCTestUpdateHandler::e_GIT;
- }
+ }
sourceDirectory = dir;
sourceDirectory += "/.hg";
- if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
- {
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
return cmCTestUpdateHandler::e_HG;
- }
+ }
+ sourceDirectory = dir;
+ sourceDirectory += "/.p4";
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ return cmCTestUpdateHandler::e_P4;
+ }
+ sourceDirectory = dir;
+ sourceDirectory += "/.p4config";
+ if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ return cmCTestUpdateHandler::e_P4;
+ }
return cmCTestUpdateHandler::e_UNKNOWN;
}
-//----------------------------------------------------------------------
bool cmCTestUpdateHandler::SelectVCS()
{
// Get update command
@@ -361,44 +299,53 @@ bool cmCTestUpdateHandler::SelectVCS()
// Detect the VCS managing the source tree.
this->UpdateType = this->DetectVCS(this->GetOption("SourceDirectory"));
- if (this->UpdateType == e_UNKNOWN)
- {
+ if (this->UpdateType == e_UNKNOWN) {
// The source tree does not have a recognized VCS. Check the
// configuration value or command name.
- this->UpdateType = this->DetermineType(this->UpdateCommand.c_str(),
+ this->UpdateType = this->DetermineType(
+ this->UpdateCommand.c_str(),
this->CTest->GetCTestConfiguration("UpdateType").c_str());
- }
+ }
// If no update command was specified, lookup one for this VCS tool.
- if (this->UpdateCommand.empty())
- {
- const char* key = 0;
- switch (this->UpdateType)
- {
- case e_CVS: key = "CVSCommand"; break;
- case e_SVN: key = "SVNCommand"; break;
- case e_BZR: key = "BZRCommand"; break;
- case e_GIT: key = "GITCommand"; break;
- case e_HG: key = "HGCommand"; break;
- default: break;
- }
- if (key)
- {
+ if (this->UpdateCommand.empty()) {
+ const char* key = CM_NULLPTR;
+ switch (this->UpdateType) {
+ case e_CVS:
+ key = "CVSCommand";
+ break;
+ case e_SVN:
+ key = "SVNCommand";
+ break;
+ case e_BZR:
+ key = "BZRCommand";
+ break;
+ case e_GIT:
+ key = "GITCommand";
+ break;
+ case e_HG:
+ key = "HGCommand";
+ break;
+ case e_P4:
+ key = "P4Command";
+ break;
+ default:
+ break;
+ }
+ if (key) {
this->UpdateCommand = this->CTest->GetCTestConfiguration(key);
- }
- if (this->UpdateCommand.empty())
- {
- cmOStringStream e;
+ }
+ if (this->UpdateCommand.empty()) {
+ std::ostringstream e;
e << "Cannot find UpdateCommand ";
- if (key)
- {
+ if (key) {
e << "or " << key;
- }
+ }
e << " configuration key.";
cmCTestLog(this->CTest, ERROR_MESSAGE, e.str() << std::endl);
return false;
- }
}
+ }
return true;
}
diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h
index 55ec974dc..0cd284421 100644
--- a/Source/CTest/cmCTestUpdateHandler.h
+++ b/Source/CTest/cmCTestUpdateHandler.h
@@ -1,25 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestUpdateHandler_h
#define cmCTestUpdateHandler_h
+#include "cmConfigure.h"
#include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma set woff 1375 /* base class destructor not virtual */
-#endif
+#include <string>
+#include <utility>
+#include <vector>
/** \class cmCTestUpdateHandler
* \brief A class that handles ctest -S invocations
@@ -28,35 +18,40 @@
class cmCTestUpdateHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestUpdateHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
cmCTestUpdateHandler();
- enum {
+ enum
+ {
e_UNKNOWN = 0,
e_CVS,
e_SVN,
e_BZR,
e_GIT,
e_HG,
+ e_P4,
e_LAST
};
/**
* Initialize handler
*/
- virtual void Initialize();
+ void Initialize() CM_OVERRIDE;
private:
// Some structures needed for update
- struct StringPair :
- public std::pair<std::string, std::string>{};
- struct UpdateFiles : public std::vector<StringPair>{};
+ struct StringPair : public std::pair<std::string, std::string>
+ {
+ };
+ struct UpdateFiles : public std::vector<StringPair>
+ {
+ };
// Determine the type of version control
int DetermineType(const char* cmd, const char* type);
@@ -69,8 +64,4 @@ private:
bool SelectVCS();
};
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma reset woff 1375 /* base class destructor not virtual */
-#endif
-
#endif
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index 731c1c7a3..717117a5f 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -1,68 +1,67 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUploadCommand.h"
+#include <sstream>
+#include <vector>
+
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
#include "cmCTestUploadHandler.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
{
- cmCTestGenericHandler* handler
- = this->CTest->GetInitializedHandler("upload");
- if ( !handler )
- {
+ cmCTestGenericHandler* handler =
+ this->CTest->GetInitializedHandler("upload");
+ if (!handler) {
this->SetError("internal CTest error. Cannot instantiate upload handler");
- return 0;
- }
+ return CM_NULLPTR;
+ }
static_cast<cmCTestUploadHandler*>(handler)->SetFiles(this->Files);
+ handler->SetQuiet(this->Quiet);
return handler;
}
-
-//----------------------------------------------------------------------------
bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg)
{
- if(arg == "FILES")
- {
+ 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 == ArgumentDoingFiles)
- {
- cmStdString filename(arg);
- if(cmSystemTools::FileExists(filename.c_str()))
- {
- this->Files.insert(filename);
+ 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);
return true;
- }
- else
- {
- cmOStringStream e;
- e << "File \"" << filename << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
- return false;
- }
}
+ 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);
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index 62f379f6d..6e721796a 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestUploadCommand_h
#define cmCTestUploadCommand_h
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h"
+
#include "cmCTest.h"
+#include "cmCTestHandlerCommand.h"
+
+#include <string>
+
+class cmCTestGenericHandler;
+class cmCommand;
/** \class cmCTestUpload
* \brief Run a ctest script
@@ -24,62 +22,40 @@
class cmCTestUploadCommand : public cmCTestHandlerCommand
{
public:
-
- cmCTestUploadCommand()
- {
- }
+ cmCTestUploadCommand() {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
cmCTestUploadCommand* ni = new cmCTestUploadCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
- }
+ }
/**
* The name of the command as specified in CMakeList.txt.
*/
- virtual const char* GetName() const { return "ctest_upload";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Upload files to a dashboard server.";
- }
+ std::string GetName() const CM_OVERRIDE { return "ctest_upload"; }
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " ctest_upload(FILES ...)\n"
- "Pass a list of files to be sent along with the build results to "
- "the dashboard server.\n";
- }
-
- cmTypeMacro(cmCTestUploadCommand, cmCTestHandlerCommand);
+ typedef cmCTestHandlerCommand Superclass;
protected:
- cmCTestGenericHandler* InitializeHandler();
+ cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
- virtual bool CheckArgumentKeyword(std::string const& arg);
- virtual bool CheckArgumentValue(std::string const& arg);
+ bool CheckArgumentKeyword(std::string const& arg) CM_OVERRIDE;
+ bool CheckArgumentValue(std::string const& arg) CM_OVERRIDE;
enum
{
ArgumentDoingFiles = Superclass::ArgumentDoingLast1,
+ ArgumentDoingCaptureCMakeError,
ArgumentDoingLast2
};
cmCTest::SetOfStrings Files;
};
-
#endif
diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx
index caf2e5370..05a39840d 100644
--- a/Source/CTest/cmCTestUploadHandler.cxx
+++ b/Source/CTest/cmCTestUploadHandler.cxx
@@ -1,27 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUploadHandler.h"
#include "cmGeneratedFileStream.h"
#include "cmVersion.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
+
+#include <ostream>
+#include <set>
+#include <string>
-//----------------------------------------------------------------------------
cmCTestUploadHandler::cmCTestUploadHandler()
{
this->Initialize();
}
-//----------------------------------------------------------------------------
void cmCTestUploadHandler::Initialize()
{
this->Superclass::Initialize();
@@ -33,45 +26,48 @@ void cmCTestUploadHandler::SetFiles(const cmCTest::SetOfStrings& files)
this->Files = files;
}
-//----------------------------------------------------------------------------
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);
+ if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), "Upload.xml",
+ ofs)) {
+ 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;
- ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- << "<?xml-stylesheet type=\"text/xsl\" "
- "href=\"Dart/Source/Server/XSL/Build.xsl "
- "<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n"
- << "<Site BuildName=\""
- << this->CTest->GetCTestConfiguration("BuildName")
- << "\" BuildStamp=\""
- << this->CTest->GetCurrentTag() << "-"
- << this->CTest->GetTestModelString() << "\" Name=\""
- << this->CTest->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
- << cmVersion::GetCMakeVersion()
- << "\">\n";
- this->CTest->AddSiteProperties(ofs);
- ofs << "<Upload>\n";
- for ( it = this->Files.begin(); it != this->Files.end(); it ++ )
- {
- cmCTestLog(this->CTest, OUTPUT,
- "\tUpload file: " << it->c_str() << std::endl);
- ofs << "<File filename=\"" << cmXMLSafe(*it) << "\">\n"
- << "<Content encoding=\"base64\">\n";
- ofs << this->CTest->Base64EncodeFile(*it);
- ofs << "\n</Content>\n"
- << "</File>\n";
- }
- ofs << "</Upload>\n"
- << "</Site>\n";
+ cmXMLWriter xml(ofs);
+ xml.StartDocument();
+ xml.ProcessingInstruction("xml-stylesheet",
+ "type=\"text/xsl\" "
+ "href=\"Dart/Source/Server/XSL/Build.xsl "
+ "<file:///Dart/Source/Server/XSL/Build.xsl> \"");
+ xml.StartElement("Site");
+ xml.Attribute("BuildName", buildname);
+ xml.Attribute("BuildStamp", this->CTest->GetCurrentTag() + "-" +
+ this->CTest->GetTestModelString());
+ xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site"));
+ xml.Attribute("Generator",
+ std::string("ctest") + cmVersion::GetCMakeVersion());
+ this->CTest->AddSiteProperties(xml);
+ xml.StartElement("Upload");
+
+ for (it = this->Files.begin(); it != this->Files.end(); it++) {
+ cmCTestOptionalLog(this->CTest, OUTPUT,
+ "\tUpload file: " << *it << std::endl, this->Quiet);
+ xml.StartElement("File");
+ xml.Attribute("filename", *it);
+ xml.StartElement("Content");
+ xml.Attribute("encoding", "base64");
+ xml.Content(this->CTest->Base64EncodeFile(*it));
+ xml.EndElement(); // Content
+ xml.EndElement(); // File
+ }
+ xml.EndElement(); // Upload
+ xml.EndElement(); // Site
+ xml.EndDocument();
return 0;
}
diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h
index 23ed35a25..1e8d3c801 100644
--- a/Source/CTest/cmCTestUploadHandler.h
+++ b/Source/CTest/cmCTestUploadHandler.h
@@ -1,17 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestUploadHandler_h
#define cmCTestUploadHandler_h
+#include "cmConfigure.h"
+
+#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
/** \class cmCTestUploadHandler
@@ -23,17 +17,17 @@
class cmCTestUploadHandler : public cmCTestGenericHandler
{
public:
- cmTypeMacro(cmCTestUploadHandler, cmCTestGenericHandler);
+ typedef cmCTestGenericHandler Superclass;
cmCTestUploadHandler();
- ~cmCTestUploadHandler() {}
+ ~cmCTestUploadHandler() CM_OVERRIDE {}
/*
* The main entry point for this class
*/
- int ProcessHandler();
+ int ProcessHandler() CM_OVERRIDE;
- void Initialize();
+ void Initialize() CM_OVERRIDE;
/** Specify a set of files to submit. */
void SetFiles(cmCTest::SetOfStrings const& files);
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index fbee2272e..fb2742e08 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -1,24 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestVC.h"
#include "cmCTest.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
-#include <cmsys/Process.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)
+cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log)
+ : CTest(ct)
+ , Log(log)
{
this->PathCount[PathUpdated] = 0;
this->PathCount[PathModified] = 0;
@@ -28,24 +24,20 @@ cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log): CTest(ct), Log(log)
this->Unknown.Rev = "Unknown";
}
-//----------------------------------------------------------------------------
cmCTestVC::~cmCTestVC()
{
}
-//----------------------------------------------------------------------------
void cmCTestVC::SetCommandLineTool(std::string const& tool)
{
this->CommandLineTool = tool;
}
-//----------------------------------------------------------------------------
void cmCTestVC::SetSourceDirectory(std::string const& dir)
{
this->SourceDirectory = dir;
}
-//----------------------------------------------------------------------------
bool cmCTestVC::InitialCheckout(const char* command)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
@@ -55,22 +47,20 @@ 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.c_str())) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot create directory: " << parent << std::endl);
return false;
- }
+ }
// Construct the initial checkout command line.
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
+ std::vector<std::string> args = cmSystemTools::ParseArguments(command);
std::vector<char const*> vc_co;
- for(std::vector<cmStdString>::const_iterator ai = args.begin();
- ai != args.end(); ++ai)
- {
+ for (std::vector<std::string>::const_iterator ai = args.begin();
+ ai != args.end(); ++ai) {
vc_co.push_back(ai->c_str());
- }
- vc_co.push_back(0);
+ }
+ vc_co.push_back(CM_NULLPTR);
// Run the initial checkout command and log its output.
this->Log << "--- Begin Initial Checkout ---\n";
@@ -78,60 +68,54 @@ bool cmCTestVC::InitialCheckout(const char* command)
OutputLogger err(this->Log, "co-err> ");
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);
- }
+ if (!result) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Initial checkout failed!"
+ << std::endl);
+ }
return result;
}
-//----------------------------------------------------------------------------
bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out,
- OutputParser* err, const char* workDir)
+ OutputParser* err, const char* workDir,
+ Encoding encoding)
{
this->Log << this->ComputeCommandLine(cmd) << "\n";
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, cmd);
- workDir = workDir? workDir : this->SourceDirectory.c_str();
+ workDir = workDir ? workDir : this->SourceDirectory.c_str();
cmsysProcess_SetWorkingDirectory(cp, workDir);
- this->RunProcess(cp, out, err);
+ this->RunProcess(cp, out, err, encoding);
int result = cmsysProcess_GetExitValue(cp);
cmsysProcess_Delete(cp);
return result == 0;
}
-//----------------------------------------------------------------------------
std::string cmCTestVC::ComputeCommandLine(char const* const* cmd)
{
- cmOStringStream line;
+ std::ostringstream line;
const char* sep = "";
- for(const char* const* arg = cmd; *arg; ++arg)
- {
+ for (const char* const* arg = cmd; *arg; ++arg) {
line << sep << "\"" << *arg << "\"";
sep = " ";
- }
+ }
return line.str();
}
-//----------------------------------------------------------------------------
-bool cmCTestVC::RunUpdateCommand(char const* const* cmd,
- OutputParser* out, OutputParser* err)
+bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out,
+ OutputParser* err, Encoding encoding)
{
// Report the command line.
this->UpdateCommandLine = this->ComputeCommandLine(cmd);
- if(this->CTest->GetShowOnly())
- {
+ if (this->CTest->GetShowOnly()) {
this->Log << this->UpdateCommandLine << "\n";
return true;
- }
+ }
// Run the command.
- return this->RunChild(cmd, out, err);
+ return this->RunChild(cmd, out, err, CM_NULLPTR, encoding);
}
-//----------------------------------------------------------------------------
std::string cmCTestVC::GetNightlyTime()
{
// Get the nightly start time corresponding to the current dau.
@@ -139,17 +123,11 @@ std::string cmCTestVC::GetNightlyTime()
this->CTest->GetCTestConfiguration("NightlyStartTime"),
this->CTest->GetTomorrowTag());
char current_time[1024];
- sprintf(current_time, "%04d-%02d-%02d %02d:%02d:%02d",
- t->tm_year + 1900,
- t->tm_mon + 1,
- t->tm_mday,
- t->tm_hour,
- t->tm_min,
- t->tm_sec);
+ sprintf(current_time, "%04d-%02d-%02d %02d:%02d:%02d", t->tm_year + 1900,
+ t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
return std::string(current_time);
}
-//----------------------------------------------------------------------------
void cmCTestVC::Cleanup()
{
this->Log << "--- Begin Cleanup ---\n";
@@ -157,36 +135,39 @@ void cmCTestVC::Cleanup()
this->Log << "--- End Cleanup ---\n";
}
-//----------------------------------------------------------------------------
void cmCTestVC::CleanupImpl()
{
// We do no cleanup by default.
}
-//----------------------------------------------------------------------------
bool cmCTestVC::Update()
{
- this->NoteOldRevision();
- this->Log << "--- Begin Update ---\n";
- bool result = this->UpdateImpl();
- this->Log << "--- End Update ---\n";
- this->NoteNewRevision();
+ bool result = 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())) {
+ result = this->NoteOldRevision() && result;
+ this->Log << "--- Begin Update ---\n";
+ result = this->UpdateImpl() && result;
+ this->Log << "--- End Update ---\n";
+ }
+ result = this->NoteNewRevision() && result;
return result;
}
-//----------------------------------------------------------------------------
-void cmCTestVC::NoteOldRevision()
+bool cmCTestVC::NoteOldRevision()
{
// We do nothing by default.
+ return true;
}
-//----------------------------------------------------------------------------
-void cmCTestVC::NoteNewRevision()
+bool cmCTestVC::NoteNewRevision()
{
// We do nothing by default.
+ return true;
}
-//----------------------------------------------------------------------------
bool cmCTestVC::UpdateImpl()
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -194,8 +175,7 @@ bool cmCTestVC::UpdateImpl()
return true;
}
-//----------------------------------------------------------------------------
-bool cmCTestVC::WriteXML(std::ostream& xml)
+bool cmCTestVC::WriteXML(cmXMLWriter& xml)
{
this->Log << "--- Begin Revisions ---\n";
bool result = this->WriteXMLUpdates(xml);
@@ -203,39 +183,33 @@ bool cmCTestVC::WriteXML(std::ostream& xml)
return result;
}
-//----------------------------------------------------------------------------
-bool cmCTestVC::WriteXMLUpdates(std::ostream&)
+bool cmCTestVC::WriteXMLUpdates(cmXMLWriter& /*unused*/)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"* CTest cannot extract updates for this VCS tool.\n");
return true;
}
-//----------------------------------------------------------------------------
-void cmCTestVC::WriteXMLEntry(std::ostream& xml,
- std::string const& path,
- std::string const& name,
- std::string const& full,
+void cmCTestVC::WriteXMLEntry(cmXMLWriter& xml, std::string const& path,
+ std::string const& name, std::string const& full,
File const& f)
{
- static const char* desc[3] = { "Updated", "Modified", "Conflicting"};
- Revision const& rev = f.Rev? *f.Rev : this->Unknown;
- std::string prior = f.PriorRev? f.PriorRev->Rev : std::string("Unknown");
- xml << "\t\t<" << desc[f.Status] << ">\n"
- << "\t\t\t<File>" << cmXMLSafe(name) << "</File>\n"
- << "\t\t\t<Directory>" << cmXMLSafe(path) << "</Directory>\n"
- << "\t\t\t<FullName>" << cmXMLSafe(full) << "</FullName>\n"
- << "\t\t\t<CheckinDate>" << cmXMLSafe(rev.Date) << "</CheckinDate>\n"
- << "\t\t\t<Author>" << cmXMLSafe(rev.Author) << "</Author>\n"
- << "\t\t\t<Email>" << cmXMLSafe(rev.EMail) << "</Email>\n"
- << "\t\t\t<Committer>" << cmXMLSafe(rev.Committer) << "</Committer>\n"
- << "\t\t\t<CommitterEmail>" << cmXMLSafe(rev.CommitterEMail)
- << "</CommitterEmail>\n"
- << "\t\t\t<CommitDate>" << cmXMLSafe(rev.CommitDate)
- << "</CommitDate>\n"
- << "\t\t\t<Log>" << cmXMLSafe(rev.Log) << "</Log>\n"
- << "\t\t\t<Revision>" << cmXMLSafe(rev.Rev) << "</Revision>\n"
- << "\t\t\t<PriorRevision>" << cmXMLSafe(prior) << "</PriorRevision>\n"
- << "\t\t</" << desc[f.Status] << ">\n";
+ static const char* desc[3] = { "Updated", "Modified", "Conflicting" };
+ Revision const& rev = f.Rev ? *f.Rev : this->Unknown;
+ std::string prior = f.PriorRev ? f.PriorRev->Rev : std::string("Unknown");
+ xml.StartElement(desc[f.Status]);
+ xml.Element("File", name);
+ xml.Element("Directory", path);
+ xml.Element("FullName", full);
+ xml.Element("CheckinDate", rev.Date);
+ xml.Element("Author", rev.Author);
+ xml.Element("Email", rev.EMail);
+ xml.Element("Committer", rev.Committer);
+ xml.Element("CommitterEmail", rev.CommitterEMail);
+ xml.Element("CommitDate", rev.CommitDate);
+ xml.Element("Log", rev.Log);
+ xml.Element("Revision", rev.Rev);
+ xml.Element("PriorRevision", prior);
+ xml.EndElement();
++this->PathCount[f.Status];
}
diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h
index 9dd06515d..6400bcda3 100644
--- a/Source/CTest/cmCTestVC.h
+++ b/Source/CTest/cmCTestVC.h
@@ -1,26 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTestVC_h
#define cmCTestVC_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+
+#include "cmProcessOutput.h"
#include "cmProcessTools.h"
class cmCTest;
+class cmXMLWriter;
/** \class cmCTestVC
* \brief Base class for version control system handlers
*
*/
-class cmCTestVC: public cmProcessTools
+class cmCTestVC : public cmProcessTools
{
public:
/** Construct with a CTest instance and update log stream. */
@@ -48,13 +46,20 @@ public:
/** Get the command line used by the Update method. */
std::string const& GetUpdateCommandLine() const
- { return this->UpdateCommandLine; }
+ {
+ return this->UpdateCommandLine;
+ }
/** Write Update.xml entries for the updates found. */
- bool WriteXML(std::ostream& xml);
+ bool WriteXML(cmXMLWriter& xml);
/** Enumerate non-trivial working tree states during update. */
- enum PathStatus { PathUpdated, PathModified, PathConflicting };
+ enum PathStatus
+ {
+ PathUpdated,
+ PathModified,
+ PathConflicting
+ };
/** Get the number of working tree paths in each state after update. */
int GetPathCount(PathStatus s) const { return this->PathCount[s]; }
@@ -62,13 +67,14 @@ public:
protected:
// Internal API to be implemented by subclasses.
virtual void CleanupImpl();
- virtual void NoteOldRevision();
+ virtual bool NoteOldRevision();
virtual bool UpdateImpl();
- virtual void NoteNewRevision();
- virtual bool WriteXMLUpdates(std::ostream& xml);
+ virtual bool NoteNewRevision();
+ virtual bool WriteXMLUpdates(cmXMLWriter& xml);
#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510
-public: // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this
+ // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this
+public:
#endif
/** Basic information about one revision of a tree or file. */
struct Revision
@@ -84,7 +90,6 @@ public: // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this
};
protected:
- struct File;
friend struct File;
/** Represent change to one file. */
@@ -93,24 +98,35 @@ protected:
PathStatus Status;
Revision const* Rev;
Revision const* PriorRev;
- File(): Status(PathUpdated), Rev(0), PriorRev(0) {}
- File(PathStatus status, Revision const* rev, Revision const* priorRev):
- Status(status), Rev(rev), PriorRev(priorRev) {}
+ File()
+ : Status(PathUpdated)
+ , Rev(CM_NULLPTR)
+ , PriorRev(CM_NULLPTR)
+ {
+ }
+ File(PathStatus status, Revision const* rev, Revision const* priorRev)
+ : Status(status)
+ , Rev(rev)
+ , PriorRev(priorRev)
+ {
+ }
};
/** Convert a list of arguments to a human-readable command line. */
static std::string ComputeCommandLine(char const* const* cmd);
/** Run a command line and send output to given parsers. */
- bool RunChild(char const* const* cmd, OutputParser* out,
- OutputParser* err, const char* workDir = 0);
+ bool RunChild(char const* const* cmd, OutputParser* out, OutputParser* err,
+ const char* workDir = CM_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 = 0);
+ bool RunUpdateCommand(char const* const* cmd, OutputParser* out,
+ OutputParser* err = CM_NULLPTR,
+ Encoding encoding = cmProcessOutput::Auto);
/** Write xml element for one file. */
- void WriteXMLEntry(std::ostream& xml, std::string const& path,
+ void WriteXMLEntry(cmXMLWriter& xml, std::string const& path,
std::string const& name, std::string const& full,
File const& f);
diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx
new file mode 100644
index 000000000..83a7b75eb
--- /dev/null
+++ b/Source/CTest/cmParseBlanketJSCoverage.cxx
@@ -0,0 +1,139 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmParseBlanketJSCoverage.h"
+
+#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;
+ JSONParser(cmCTestCoverageHandlerContainer& cont)
+ : Coverage(cont)
+ {
+ }
+
+ virtual ~JSONParser() {}
+
+ std::string getValue(std::string const& line, int type)
+ {
+ size_t begIndex;
+ size_t endIndex;
+ endIndex = line.rfind(',');
+ begIndex = line.find_first_of(':');
+ if (type == 0) {
+ // A unique substring to remove the extra characters
+ // around the files name in the JSON (extra " and ,)
+ std::string foundFileName =
+ line.substr(begIndex + 3, endIndex - (begIndex + 4));
+ return foundFileName;
+ }
+ return line.substr(begIndex);
+ }
+ bool ParseFile(std::string const& file)
+ {
+ FileLinesType localCoverageVector;
+ std::string filename;
+ bool foundFile = false;
+ bool inSource = false;
+ std::string covResult;
+ std::string line;
+
+ cmsys::ifstream in(file.c_str());
+ if (!in) {
+ return false;
+ }
+ while (cmSystemTools::GetLineFromStream(in, line)) {
+ if (line.find("filename") != std::string::npos) {
+ if (foundFile) {
+ /*
+ * Upon finding a second file name, generate a
+ * vector within the total coverage to capture the
+ * information in the local vector
+ */
+ FileLinesType& CoverageVector =
+ this->Coverage.TotalCoverage[filename];
+ CoverageVector = localCoverageVector;
+ localCoverageVector.clear();
+ }
+ foundFile = true;
+ inSource = false;
+ filename = getValue(line, 0);
+ } else if ((line.find("coverage") != std::string::npos) && foundFile &&
+ inSource) {
+ /*
+ * two types of "coverage" in the JSON structure
+ *
+ * The coverage result over the file or set of files
+ * and the coverage for each individual line
+ *
+ * FoundFile and foundSource ensure that
+ * only the value of the line coverage is captured
+ */
+ std::string result = getValue(line, 1);
+ result = result.substr(2);
+ if (result == "\"\"") {
+ // Empty quotation marks indicate that the
+ // line is not executable
+ localCoverageVector.push_back(-1);
+ } else {
+ // Else, it contains the number of time executed
+ localCoverageVector.push_back(atoi(result.c_str()));
+ }
+ } else if (line.find("source") != std::string::npos) {
+ inSource = true;
+ }
+ }
+
+ // On exit, capture end of last file covered.
+ FileLinesType& CoverageVector = this->Coverage.TotalCoverage[filename];
+ CoverageVector = localCoverageVector;
+ localCoverageVector.clear();
+ return true;
+ }
+
+private:
+ cmCTestCoverageHandlerContainer& Coverage;
+};
+
+cmParseBlanketJSCoverage::cmParseBlanketJSCoverage(
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ : Coverage(cont)
+ , CTest(ctest)
+{
+}
+
+bool cmParseBlanketJSCoverage::LoadCoverageData(std::vector<std::string> 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++) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Reading JSON File " << files[i] << std::endl,
+ this->Coverage.Quiet);
+
+ if (!this->ReadJSONFile(files[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmParseBlanketJSCoverage::ReadJSONFile(std::string const& file)
+{
+ cmParseBlanketJSCoverage::JSONParser parser(this->Coverage);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Parsing " << file << std::endl, this->Coverage.Quiet);
+ parser.ParseFile(file);
+ return true;
+}
diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h
new file mode 100644
index 000000000..696121f21
--- /dev/null
+++ b/Source/CTest/cmParseBlanketJSCoverage.h
@@ -0,0 +1,42 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmParseBlanketJSCoverage_h
+#define cmParseBlanketJSCoverage_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
+
+/** \class cmParseBlanketJSCoverage
+ * \brief Parse BlanketJS coverage information
+ *
+ * This class is used to parse BlanketJS(Pascal) coverage information
+ * generated by the Blanket.js library when used in conjunction with the
+ * test runner mocha.js, which is used to write out the JSON format.
+ *
+ * Blanket.js:
+ * http://blanketjs.org/
+ *
+ * Mocha.js
+ * http://visionmedia.github.io/mocha/
+ */
+class cmParseBlanketJSCoverage
+{
+public:
+ cmParseBlanketJSCoverage(cmCTestCoverageHandlerContainer& cont,
+ cmCTest* ctest);
+ bool LoadCoverageData(std::vector<std::string> files);
+ // Read the JSON output
+ bool ReadJSONFile(std::string const& file);
+
+protected:
+ class JSONParser;
+
+ cmCTestCoverageHandlerContainer& Coverage;
+ cmCTest* CTest;
+};
+#endif
diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx
index 137f344df..629010cf1 100644
--- a/Source/CTest/cmParseCacheCoverage.cxx
+++ b/Source/CTest/cmParseCacheCoverage.cxx
@@ -1,49 +1,45 @@
-#include "cmStandardIncludes.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "cmSystemTools.h"
#include "cmParseCacheCoverage.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmSystemTools.h"
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include <map>
+#include <stdio.h>
+#include <stdlib.h>
+#include <utility>
cmParseCacheCoverage::cmParseCacheCoverage(
- cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest)
- :cmParseMumpsCoverage(cont, ctest)
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ : cmParseMumpsCoverage(cont, ctest)
{
}
-
bool cmParseCacheCoverage::LoadCoverageData(const char* d)
{
// load all the .mcov files in the specified directory
cmsys::Directory dir;
- if(!dir.Load(d))
- {
+ if (!dir.Load(d)) {
return false;
- }
+ }
size_t numf;
unsigned int i;
numf = dir.GetNumberOfFiles();
- for (i = 0; i < numf; i++)
- {
+ for (i = 0; i < numf; i++) {
std::string file = dir.GetFile(i);
- if(file != "." && file != ".."
- && !cmSystemTools::FileIsDirectory(file.c_str()))
- {
+ if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
std::string path = d;
path += "/";
path += file;
- if(cmSystemTools::GetFilenameLastExtension(path) == ".cmcov")
- {
- if(!this->ReadCMCovFile(path.c_str()))
- {
+ if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") {
+ if (!this->ReadCMCovFile(path.c_str())) {
return false;
- }
}
}
}
+ }
return true;
}
@@ -54,32 +50,26 @@ void cmParseCacheCoverage::RemoveUnCoveredFiles()
// that only have -1 or 0 for the lines.
cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator ci =
this->Coverage.TotalCoverage.begin();
- while(ci != this->Coverage.TotalCoverage.end())
- {
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector& v =
- ci->second;
+ 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 (cmCTestCoverageHandlerContainer::SingleFileCoverageVector::iterator
+ i = v.begin();
+ i != v.end(); ++i) {
+ if (*i > 0) {
nothing = false;
break;
- }
}
- if(nothing)
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "No coverage found in: " << ci->first
- << std::endl);
+ }
+ if (nothing) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "No coverage found in: " << ci->first << std::endl,
+ this->Coverage.Quiet);
this->Coverage.TotalCoverage.erase(ci++);
- }
- else
- {
+ } else {
++ci;
- }
}
+ }
}
bool cmParseCacheCoverage::SplitString(std::vector<std::string>& args,
@@ -87,18 +77,16 @@ bool cmParseCacheCoverage::SplitString(std::vector<std::string>& args,
{
std::string::size_type pos1 = 0;
std::string::size_type pos2 = line.find(',', 0);
- if(pos2 == std::string::npos)
- {
+ if (pos2 == std::string::npos) {
return false;
- }
+ }
std::string arg;
- while(pos2 != std::string::npos)
- {
- arg = line.substr(pos1, pos2-pos1);
+ while (pos2 != std::string::npos) {
+ arg = line.substr(pos1, pos2 - pos1);
args.push_back(arg);
- pos1 = pos2+1;
- pos2 = line.find(',',pos1);
- }
+ pos1 = pos2 + 1;
+ pos2 = line.find(',', pos1);
+ }
arg = line.substr(pos1);
args.push_back(arg);
return true;
@@ -106,115 +94,107 @@ bool cmParseCacheCoverage::SplitString(std::vector<std::string>& args,
bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
{
- std::ifstream in(file);
- if(!in)
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Can not open : "
- << file << "\n");
+ cmsys::ifstream in(file);
+ if (!in) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not open : " << file << "\n");
return false;
- }
+ }
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");
+ if (!cmSystemTools::GetLineFromStream(in, line)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Empty file : "
+ << file << " referenced in this line of cmcov data:\n"
+ "["
+ << line << "]\n");
return false;
- }
+ }
separateLine.clear();
this->SplitString(separateLine, line);
- if(separateLine.size() !=4 || separateLine[0] != "Routine"
- || separateLine[1] != "Line" || separateLine[2] != "RtnLine"
- || separateLine[3] != "Code")
- {
+ if (separateLine.size() != 4 || separateLine[0] != "Routine" ||
+ separateLine[1] != "Line" || separateLine[2] != "RtnLine" ||
+ separateLine[3] != "Code") {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Bad first line of cmcov file : "
- << file << " line:\n"
- "[" << line << "]\n");
- }
+ "Bad first line of cmcov file : " << file << " line:\n"
+ "["
+ << line << "]\n");
+ }
std::string routine;
std::string filepath;
- while(cmSystemTools::GetLineFromStream(in, line))
- {
+ while (cmSystemTools::GetLineFromStream(in, line)) {
// clear out line argument vector
separateLine.clear();
// parse the comma separated line
this->SplitString(separateLine, line);
// might have more because code could have a quoted , in it
// but we only care about the first 3 args anyway
- if(separateLine.size() < 4)
- {
+ if (separateLine.size() < 4) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Bad line of cmcov file expected at least 4 found: "
- << 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] << " ");
- }
+ << 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] << " ");
+ }
cmCTestLog(this->CTest, ERROR_MESSAGE, "\n");
return false;
- }
+ }
// if we do not have a routine yet, then it should be
// the first argument in the vector
- if(routine.size() == 0)
- {
+ if (routine.empty()) {
routine = separateLine[0];
// Find the full path to the file
- if(!this->FindMumpsFile(routine, filepath))
- {
+ if (!this->FindMumpsFile(routine, filepath)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Could not find mumps file for routine: "
- << routine << "\n");
+ "Could not find mumps file for routine: " << routine
+ << "\n");
filepath = "";
continue; // move to next line
- }
}
+ }
// if we have a routine name, check for end of routine
- else
- {
+ else {
// Totals in arg 0 marks the end of a routine
- if(separateLine[0].substr(0, 6) == "Totals")
- {
+ if (separateLine[0].substr(0, 6) == "Totals") {
routine = ""; // at the end of this routine
filepath = "";
continue; // move to next line
- }
}
+ }
// if the file path was not found for the routine
// move to next line. We should have already warned
// after the call to FindMumpsFile that we did not find
// it, so don't report again to cut down on output
- if(filepath.size() == 0)
- {
+ if (filepath.empty()) {
continue;
- }
+ }
// now we are ready to set the coverage from the line of data
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector&
- coverageVector = this->Coverage.TotalCoverage[filepath];
- std::string::size_type linenumber = atoi(separateLine[1].c_str()) -1;
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector =
+ this->Coverage.TotalCoverage[filepath];
+ std::string::size_type linenumber = atoi(separateLine[1].c_str()) - 1;
int count = atoi(separateLine[2].c_str());
- if(linenumber > coverageVector.size())
- {
+ if (linenumber > coverageVector.size()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Parse error line is greater than number of lines in file: "
- << linenumber << " " << filepath << "\n");
+ << linenumber << " " << filepath << "\n");
continue; // skip setting count to avoid crash
- }
+ }
// now add to count for linenumber
// for some reason the cache coverage adds extra lines to the
// end of the file in some cases. Since they do not exist, we will
// mark them as non executable
- while(linenumber >= coverageVector.size())
- {
+ while (linenumber >= coverageVector.size()) {
coverageVector.push_back(-1);
- }
- coverageVector[linenumber] += count;
}
+ // 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 addition to the count found.
+ if (coverageVector[linenumber] == -1 && count > 0) {
+ coverageVector[linenumber] += count + 1;
+ } else {
+ coverageVector[linenumber] += count;
+ }
+ }
return true;
}
diff --git a/Source/CTest/cmParseCacheCoverage.h b/Source/CTest/cmParseCacheCoverage.h
index 114eb92d3..005d27258 100644
--- a/Source/CTest/cmParseCacheCoverage.h
+++ b/Source/CTest/cmParseCacheCoverage.h
@@ -1,20 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmParseCacheCoverage_h
#define cmParseCacheCoverage_h
+#include "cmConfigure.h"
+
#include "cmParseMumpsCoverage.h"
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
+
/** \class cmParseCacheCoverage
* \brief Parse Cache coverage information
*
@@ -24,19 +22,17 @@
class cmParseCacheCoverage : public cmParseMumpsCoverage
{
public:
- cmParseCacheCoverage(cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest);
+ cmParseCacheCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest);
+
protected:
// implement virtual from parent
- bool LoadCoverageData(const char* dir);
+ bool LoadCoverageData(const char* dir) CM_OVERRIDE;
// remove files with no coverage
void RemoveUnCoveredFiles();
// Read a single mcov file
bool ReadCMCovFile(const char* f);
// split a string based on ,
- bool SplitString(std::vector<std::string>& args,
- std::string const& line);
+ bool SplitString(std::vector<std::string>& args, std::string const& line);
};
-
#endif
diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx
new file mode 100644
index 000000000..ba55cd7b2
--- /dev/null
+++ b/Source/CTest/cmParseCoberturaCoverage.cxx
@@ -0,0 +1,171 @@
+#include "cmParseCoberturaCoverage.h"
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.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)
+ , 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
+ {
+ if (name == "source") {
+ this->InSource = false;
+ } else if (name == "sources") {
+ this->InSources = false;
+ } else if (name == "class") {
+ this->SkipThisClass = false;
+ }
+ }
+
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ std::string tmp;
+ tmp.insert(0, data, length);
+ if (this->InSources && this->InSource) {
+ this->FilePaths.push_back(tmp);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Adding Source: " << tmp << std::endl,
+ this->Coverage.Quiet);
+ }
+ }
+
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
+ std::string FoundSource;
+ std::string finalpath;
+ if (name == "source") {
+ this->InSource = true;
+ } else if (name == "sources") {
+ this->InSources = true;
+ } else if (name == "class") {
+ int tagCount = 0;
+ while (true) {
+ if (strcmp(atts[tagCount], "filename") == 0) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Reading file: " << atts[tagCount + 1]
+ << std::endl,
+ this->Coverage.Quiet);
+ std::string filename = atts[tagCount + 1];
+ this->CurFileName = "";
+
+ // 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) {
+ this->CurFileName = filename;
+ break;
+ }
+ }
+
+ if (this->CurFileName == "") {
+ // 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())) {
+ this->CurFileName = finalpath;
+ break;
+ }
+ }
+ }
+
+ cmsys::ifstream fin(this->CurFileName.c_str());
+ if (this->CurFileName == "" || !fin) {
+ this->CurFileName =
+ this->Coverage.BinaryDir + "/" + atts[tagCount + 1];
+ fin.open(this->CurFileName.c_str());
+ if (!fin) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Skipping system file " << filename
+ << std::endl,
+ this->Coverage.Quiet);
+
+ this->SkipThisClass = true;
+ break;
+ }
+ }
+ std::string line;
+ FileLinesType& curFileLines =
+ this->Coverage.TotalCoverage[this->CurFileName];
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ curFileLines.push_back(-1);
+ }
+
+ break;
+ }
+ ++tagCount;
+ }
+ } else if (name == "line") {
+ int tagCount = 0;
+ int curNumber = -1;
+ int curHits = -1;
+ while (true) {
+ if (this->SkipThisClass) {
+ break;
+ }
+ if (strcmp(atts[tagCount], "hits") == 0) {
+ curHits = atoi(atts[tagCount + 1]);
+ } else if (strcmp(atts[tagCount], "number") == 0) {
+ curNumber = atoi(atts[tagCount + 1]);
+ }
+
+ if (curHits > -1 && curNumber > 0) {
+ FileLinesType& curFileLines =
+ this->Coverage.TotalCoverage[this->CurFileName];
+ {
+ curFileLines[curNumber - 1] = curHits;
+ }
+ break;
+ }
+ ++tagCount;
+ }
+ }
+ }
+
+private:
+ bool InSources;
+ bool InSource;
+ bool SkipThisClass;
+ std::vector<std::string> FilePaths;
+ typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
+ FileLinesType;
+ cmCTest* CTest;
+ cmCTestCoverageHandlerContainer& Coverage;
+ std::string CurFileName;
+};
+
+cmParseCoberturaCoverage::cmParseCoberturaCoverage(
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ : Coverage(cont)
+ , CTest(ctest)
+{
+}
+
+bool cmParseCoberturaCoverage::ReadCoverageXML(const char* xmlFile)
+{
+ cmParseCoberturaCoverage::XMLParser parser(this->CTest, this->Coverage);
+ parser.ParseFile(xmlFile);
+ return true;
+}
diff --git a/Source/CTest/cmParseCoberturaCoverage.h b/Source/CTest/cmParseCoberturaCoverage.h
new file mode 100644
index 000000000..cb6d0976b
--- /dev/null
+++ b/Source/CTest/cmParseCoberturaCoverage.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 cmParseCoberturaCoverage_h
+#define cmParseCoberturaCoverage_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
+
+/** \class cmParsePythonCoverage
+ * \brief Parse coverage.py Python coverage information
+ *
+ * This class is used to parse the output of the coverage.py tool that
+ * is currently maintained by Ned Batchelder. That tool has a command
+ * that produces xml output in the format typically output by the common
+ * Java-based Cobertura coverage application. This helper class parses
+ * that XML file to fill the coverage-handler container.
+ */
+class cmParseCoberturaCoverage
+{
+public:
+ //! Create the coverage parser by passing in the coverage handler
+ //! container and the cmCTest object
+ cmParseCoberturaCoverage(cmCTestCoverageHandlerContainer& cont,
+ cmCTest* ctest);
+
+ bool inSources;
+ bool inSource;
+ std::vector<std::string> filepaths;
+ //! Read the XML produced by running `coverage xml`
+ bool ReadCoverageXML(const char* xmlFile);
+
+private:
+ class XMLParser;
+
+ cmCTestCoverageHandlerContainer& Coverage;
+ cmCTest* CTest;
+ std::string CurFileName;
+};
+
+#endif
diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx
new file mode 100644
index 000000000..4b781a6db
--- /dev/null
+++ b/Source/CTest/cmParseDelphiCoverage.cxx
@@ -0,0 +1,229 @@
+#include "cmParseDelphiCoverage.h"
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmSystemTools.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include <stdio.h>
+#include <stdlib.h>
+
+class cmParseDelphiCoverage::HTMLParser
+{
+public:
+ typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
+ FileLinesType;
+ HTMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
+ : CTest(ctest)
+ , Coverage(cont)
+ {
+ }
+
+ virtual ~HTMLParser() {}
+
+ bool initializeDelphiFile(
+ std::string const& filename,
+ cmParseDelphiCoverage::HTMLParser::FileLinesType& coverageVector)
+ {
+ std::string line;
+ size_t comPos;
+ size_t semiPos;
+ bool blockComFlag = false;
+ bool lineComFlag = false;
+ std::vector<std::string> beginSet;
+ cmsys::ifstream in(filename.c_str());
+ if (!in) {
+ return false;
+ }
+ while (cmSystemTools::GetLineFromStream(in, line)) {
+ lineComFlag = false;
+ // Unique cases found in lines.
+ size_t beginPos = line.find("begin");
+
+ // 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");
+ coverageVector.push_back(-1);
+ continue;
+ }
+ if (line.find('{') != std::string::npos) {
+ blockComFlag = true;
+ } else if (line.find('}') != std::string::npos) {
+ blockComFlag = false;
+ coverageVector.push_back(-1);
+ continue;
+ } else if ((line.find("end;") != std::string::npos) &&
+ !beginSet.empty()) {
+ beginSet.pop_back();
+ coverageVector.push_back(-1);
+ continue;
+ }
+
+ // This checks for comments after lines of code, finding the
+ // comment symbol after the ending semicolon.
+ comPos = line.find("//");
+ if (comPos != std::string::npos) {
+ semiPos = line.find(';');
+ if (comPos < semiPos) {
+ lineComFlag = true;
+ }
+ }
+ // Based up what was found, add a line to the coverageVector
+ if (!beginSet.empty() && line != "" && !blockComFlag && !lineComFlag) {
+ coverageVector.push_back(0);
+ } else {
+ coverageVector.push_back(-1);
+ }
+ }
+ return true;
+ }
+ bool ParseFile(const char* file)
+ {
+ std::string line = file;
+ std::string lineresult;
+ std::string lastroutine;
+ std::string filename;
+ std::string filelineoffset;
+ size_t afterLineNum = 0;
+ size_t lastoffset = 0;
+ size_t endcovpos = 0;
+ size_t endnamepos = 0;
+ size_t pos = 0;
+
+ /*
+ * This first 'while' section goes through the found HTML
+ * file name and attempts to capture the source file name
+ * which is set as part of the HTML file name: the name of
+ * the file is found in parenthesis '()'
+ *
+ * See test HTML file name: UTCovTest(UTCovTest.pas).html.
+ *
+ * Find the text inside each pair of parenthesis and check
+ * to see if it ends in '.pas'. If it can't be found,
+ * exit the function.
+ */
+ while (true) {
+ lastoffset = line.find('(', pos);
+ if (lastoffset == std::string::npos) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, endnamepos
+ << "File not found " << lastoffset << std::endl,
+ this->Coverage.Quiet);
+ return false;
+ }
+ endnamepos = line.find(')', lastoffset);
+ filename = line.substr(lastoffset + 1, (endnamepos - 1) - lastoffset);
+ if (filename.find(".pas") != std::string::npos) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Coverage found for file: " << filename
+ << std::endl,
+ this->Coverage.Quiet);
+ break;
+ }
+ pos = lastoffset + 1;
+ }
+ /*
+ * Glob through the source directory for the
+ * file found above
+ */
+ cmsys::Glob gl;
+ gl.RecurseOn();
+ gl.RecurseThroughSymlinksOff();
+ std::string glob = Coverage.SourceDir + "*/" + filename;
+ gl.FindFiles(glob);
+ std::vector<std::string> const& files = gl.GetFiles();
+ if (files.empty()) {
+ /*
+ * If that doesn't find any matching files
+ * return a failure.
+ */
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Unable to find file matching" << glob << std::endl,
+ this->Coverage.Quiet);
+ return false;
+ }
+ FileLinesType& coverageVector = this->Coverage.TotalCoverage[files[0]];
+
+ /*
+ * Initialize the file to have all code between 'begin' and
+ * 'end' tags marked as executable
+ */
+
+ this->initializeDelphiFile(files[0], coverageVector);
+
+ cmsys::ifstream in(file);
+ if (!in) {
+ return false;
+ }
+
+ /*
+ * Now read the HTML file, looking for the lines that have an
+ * "inline" in it. Then parse out the "class" value of that
+ * line to determine if the line is executed or not.
+ *
+ * Sample HTML line:
+ *
+ * <tr class="covered"><td>47</td><td><pre style="display:inline;">
+ * &nbsp;CheckEquals(1,2-1);</pre></td></tr>
+ *
+ */
+
+ while (cmSystemTools::GetLineFromStream(in, line)) {
+ if (line.find("inline") == std::string::npos) {
+ continue;
+ }
+
+ lastoffset = line.find("class=");
+ endcovpos = line.find('>', lastoffset);
+ lineresult = line.substr(lastoffset + 7, (endcovpos - 8) - lastoffset);
+
+ if (lineresult == "covered") {
+ afterLineNum = line.find('<', endcovpos + 5);
+ filelineoffset =
+ line.substr(endcovpos + 5, afterLineNum - (endcovpos + 5));
+ coverageVector[atoi(filelineoffset.c_str()) - 1] = 1;
+ }
+ }
+ return true;
+ }
+
+private:
+ cmCTest* CTest;
+ cmCTestCoverageHandlerContainer& Coverage;
+};
+
+cmParseDelphiCoverage::cmParseDelphiCoverage(
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ : Coverage(cont)
+ , CTest(ctest)
+{
+}
+
+bool cmParseDelphiCoverage::LoadCoverageData(
+ std::vector<std::string> const& files)
+{
+ size_t i;
+ std::string path;
+ size_t numf = files.size();
+ for (i = 0; i < numf; i++) {
+ path = files[i];
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Reading HTML File " << path << std::endl,
+ this->Coverage.Quiet);
+ if (cmSystemTools::GetFilenameLastExtension(path) == ".html") {
+ if (!this->ReadDelphiHTML(path.c_str())) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool cmParseDelphiCoverage::ReadDelphiHTML(const char* file)
+{
+ cmParseDelphiCoverage::HTMLParser parser(this->CTest, this->Coverage);
+ parser.ParseFile(file);
+ return true;
+}
diff --git a/Source/CTest/cmParseDelphiCoverage.h b/Source/CTest/cmParseDelphiCoverage.h
new file mode 100644
index 000000000..1b374050a
--- /dev/null
+++ b/Source/CTest/cmParseDelphiCoverage.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmParseDelphiCoverage_h
+#define cmParseDelphiCoverage_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
+
+/** \class cmParseDelphiCoverage
+ * \brief Parse Delphi coverage information
+ *
+ * This class is used to parse Delphi(Pascal) coverage information
+ * generated by the Delphi-Code-Coverage tool
+ *
+ * https://code.google.com/p/delphi-code-coverage/
+ */
+
+class cmParseDelphiCoverage
+{
+public:
+ cmParseDelphiCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest);
+ bool LoadCoverageData(std::vector<std::string> const& files);
+ bool ReadDelphiHTML(const char* file);
+ // Read a single HTML file from output
+ bool ReadHTMLFile(const char* f);
+
+protected:
+ class HTMLParser;
+
+ cmCTestCoverageHandlerContainer& Coverage;
+ cmCTest* CTest;
+};
+#endif
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 6b4adb4bd..e4ee699c4 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -1,70 +1,64 @@
-#include "cmStandardIncludes.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "cmSystemTools.h"
#include "cmParseGTMCoverage.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmSystemTools.h"
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include <map>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
cmParseGTMCoverage::cmParseGTMCoverage(cmCTestCoverageHandlerContainer& cont,
cmCTest* ctest)
- :cmParseMumpsCoverage(cont, ctest)
+ : cmParseMumpsCoverage(cont, ctest)
{
}
-
bool cmParseGTMCoverage::LoadCoverageData(const char* d)
{
// load all the .mcov files in the specified directory
cmsys::Directory dir;
- if(!dir.Load(d))
- {
+ if (!dir.Load(d)) {
return false;
- }
+ }
size_t numf;
unsigned int i;
numf = dir.GetNumberOfFiles();
- for (i = 0; i < numf; i++)
- {
+ for (i = 0; i < numf; i++) {
std::string file = dir.GetFile(i);
- if(file != "." && file != ".."
- && !cmSystemTools::FileIsDirectory(file.c_str()))
- {
+ if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
std::string path = d;
path += "/";
path += file;
- if(cmSystemTools::GetFilenameLastExtension(path) == ".mcov")
- {
- if(!this->ReadMCovFile(path.c_str()))
- {
+ if (cmSystemTools::GetFilenameLastExtension(path) == ".mcov") {
+ if (!this->ReadMCovFile(path.c_str())) {
return false;
- }
}
}
}
+ }
return true;
}
bool cmParseGTMCoverage::ReadMCovFile(const char* file)
{
- std::ifstream in(file);
- if(!in)
- {
+ cmsys::ifstream in(file);
+ if (!in) {
return false;
- }
+ }
std::string line;
std::string lastfunction;
std::string lastroutine;
std::string lastpath;
int lastoffset = 0;
- while( cmSystemTools::GetLineFromStream(in, line))
- {
+ while (cmSystemTools::GetLineFromStream(in, line)) {
// only look at lines that have coverage data
- if(line.find("^ZZCOVERAGE") == line.npos)
- {
+ if (line.find("^ZZCOVERAGE") == std::string::npos) {
continue;
- }
+ }
std::string filepath;
std::string function;
std::string routine;
@@ -72,54 +66,51 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
int count = 0;
this->ParseMCOVLine(line, routine, function, linenumber, count);
// skip this one
- if(routine == "RSEL")
- {
+ if (routine == "RSEL") {
continue;
- }
+ }
// no need to search the file if we just did it
- if(function == lastfunction && lastroutine == routine)
- {
- if(lastpath.size())
- {
- this->Coverage.TotalCoverage[lastpath][lastoffset + linenumber]
- += count;
- }
- else
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Can not find mumps file : "
- << lastroutine <<
- " referenced in this line of mcov data:\n"
- "[" << line << "]\n");
- }
- continue;
+ if (function == lastfunction && lastroutine == routine) {
+ if (!lastpath.empty()) {
+ this->Coverage.TotalCoverage[lastpath][lastoffset + linenumber] +=
+ count;
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : "
+ << lastroutine
+ << " referenced in this line of mcov data:\n"
+ "["
+ << line << "]\n");
}
+ continue;
+ }
// Find the full path to the file
bool found = this->FindMumpsFile(routine, filepath);
- if(found)
- {
+ if (found) {
int lineoffset = 0;
- if(this->FindFunctionInMumpsFile(filepath,
- function,
- lineoffset))
- {
+ if (this->FindFunctionInMumpsFile(filepath, function, lineoffset)) {
cmCTestCoverageHandlerContainer::SingleFileCoverageVector&
coverageVector = this->Coverage.TotalCoverage[filepath];
- coverageVector[lineoffset + linenumber] += count;
- lastoffset = lineoffset;
+ // 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.
+ if (coverageVector[lineoffset + linenumber] == -1 && count > 0) {
+ coverageVector[lineoffset + linenumber] += count + 1;
+ } else {
+ coverageVector[lineoffset + linenumber] += count;
}
+ lastoffset = lineoffset;
}
- else
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Can not find mumps file : "
- << routine << " referenced in this line of mcov data:\n"
- "[" << line << "]\n");
- }
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : "
+ << routine << " referenced in this line of mcov data:\n"
+ "["
+ << line << "]\n");
+ }
lastfunction = function;
lastroutine = routine;
lastpath = filepath;
- }
+ }
return true;
}
@@ -127,48 +118,40 @@ bool cmParseGTMCoverage::FindFunctionInMumpsFile(std::string const& filepath,
std::string const& function,
int& lineoffset)
{
- std::ifstream in(filepath.c_str());
- if(!in)
- {
+ cmsys::ifstream in(filepath.c_str());
+ if (!in) {
return false;
- }
+ }
std::string line;
int linenum = 0;
- while( cmSystemTools::GetLineFromStream(in, line))
- {
- std::string::size_type pos = line.find(function.c_str());
- if(pos == 0)
- {
+ while (cmSystemTools::GetLineFromStream(in, line)) {
+ std::string::size_type pos = line.find(function);
+ if (pos == 0) {
char nextchar = line[function.size()];
- if(nextchar == ' ' || nextchar == '(')
- {
+ if (nextchar == ' ' || nextchar == '(' || nextchar == '\t') {
lineoffset = linenum;
return true;
- }
}
- if(pos == 1)
- {
+ }
+ if (pos == 1) {
char prevchar = line[0];
- char nextchar = line[function.size()+1];
- if(prevchar == '%' && (nextchar == ' ' || nextchar == '('))
- {
+ char nextchar = line[function.size() + 1];
+ if (prevchar == '%' && (nextchar == ' ' || nextchar == '(')) {
lineoffset = linenum;
return true;
- }
}
- linenum++; // move to next line count
}
+ 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;
}
bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
std::string& routine,
- std::string& function,
- int& linenumber,
+ std::string& function, int& linenumber,
int& count)
{
// this method parses lines from the .mcov file
@@ -181,63 +164,52 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
// ( file , entry ) = "number_executed:timing_info"
// ^COVERAGE("%RSEL","init",8,"FOR_LOOP",1)=1
// ( file , entry, line, IGNORE ) =number_executed
- std::vector<cmStdString> args;
+ std::vector<std::string> args;
std::string::size_type pos = line.find('(', 0);
// if no ( is found, then return line has no coverage
- if(pos == std::string::npos)
- {
+ if (pos == std::string::npos) {
return false;
- }
+ }
std::string arg;
bool done = false;
// separate out all of the comma separated arguments found
// in the COVERAGE(...) line
- while(line[pos] && !done)
- {
+ while (line[pos] && !done) {
// save the char we are looking at
char cur = line[pos];
// , or ) means end of argument
- if(cur == ',' || cur == ')')
- {
+ if (cur == ',' || cur == ')') {
// save the argument into the argument vector
args.push_back(arg);
// start on a new argument
arg = "";
// if we are at the end of the ), then finish while loop
- if(cur == ')')
- {
+ if (cur == ')') {
done = true;
- }
}
- else
- {
+ } else {
// all chars except ", (, and % get stored in the arg string
- if(cur != '\"' && cur != '(' && cur != '%')
- {
+ if (cur != '\"' && cur != '(' && cur != '%') {
arg.append(1, line[pos]);
- }
}
+ }
// move to next char
pos++;
- }
+ }
// now parse the right hand side of the =
pos = line.find('=');
// no = found, this is an error
- if(pos == line.npos)
- {
+ if (pos == std::string::npos) {
return false;
- }
+ }
pos++; // move past =
// if the next positing is not a ", then this is a
// COVERAGE(..)=count line and turn the rest of the string
// past the = into an integer and set it to count
- if(line[pos] != '\"')
- {
+ if (line[pos] != '\"') {
count = atoi(line.substr(pos).c_str());
- }
- else
- {
+ } else {
// this means line[pos] is a ", and we have a
// COVERAGE(...)="1:0:0:0" type of line
pos++; // move past "
@@ -245,28 +217,28 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
std::string::size_type pos2 = line.find(':', pos);
// turn the string between the " and the first : into an integer
// and set it to count
- count = atoi(line.substr(pos, pos2-pos).c_str());
- }
+ count = atoi(line.substr(pos, pos2 - pos).c_str());
+ }
// less then two arguments is an error
- if(args.size() < 2)
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error parsing mcov line: [" << line << "]\n");
+ if (args.size() < 2) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing mcov line: ["
+ << line << "]\n");
return false;
- }
- routine = args[0]; // the routine is the first argument
+ }
+ routine = args[0]; // the routine is the first argument
function = args[1]; // the function in the routine is the second
// in the two argument only format
// ^COVERAGE("%RSEL","SRC"), the line offset is 0
- if(args.size() == 2)
- {
- linenumber = 0;
- }
- else
- {
+ if (args.size() == 2) {
+ // 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 = "";
+ } else {
// this is the format for this line
// ^COVERAGE("%RSEL","SRC",count)
linenumber = atoi(args[2].c_str());
- }
+ }
return true;
}
diff --git a/Source/CTest/cmParseGTMCoverage.h b/Source/CTest/cmParseGTMCoverage.h
index c6d7ef919..c4949d416 100644
--- a/Source/CTest/cmParseGTMCoverage.h
+++ b/Source/CTest/cmParseGTMCoverage.h
@@ -1,20 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmParseGTMCoverage_h
#define cmParseGTMCoverage_h
+#include "cmConfigure.h"
+
#include "cmParseMumpsCoverage.h"
+#include <string>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
+
/** \class cmParseGTMCoverage
* \brief Parse GTM coverage information
*
@@ -24,26 +21,21 @@
class cmParseGTMCoverage : public cmParseMumpsCoverage
{
public:
- cmParseGTMCoverage(cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest);
+ cmParseGTMCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest);
+
protected:
// implement virtual from parent
- bool LoadCoverageData(const char* dir);
+ bool LoadCoverageData(const char* dir) CM_OVERRIDE;
// Read a single mcov file
bool ReadMCovFile(const char* f);
// find out what line in a mumps file (filepath) the given entry point
// or function is. lineoffset is set by this method.
bool FindFunctionInMumpsFile(std::string const& filepath,
- std::string const& function,
- int& lineoffset);
+ std::string const& function, int& lineoffset);
// parse a line from a .mcov file, and fill in the
// routine, function, linenumber and coverage count
- bool ParseMCOVLine(std::string const& line,
- std::string& routine,
- std::string& function,
- int& linenumber,
- int& count);
+ bool ParseMCOVLine(std::string const& line, std::string& routine,
+ std::string& function, int& linenumber, int& count);
};
-
#endif
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
new file mode 100644
index 000000000..d15864a79
--- /dev/null
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -0,0 +1,184 @@
+#include "cmParseJacocoCoverage.h"
+
+#include "cmConfigure.h"
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.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:
+ XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
+ : CTest(ctest)
+ , Coverage(cont)
+ {
+ this->FilePath = "";
+ this->PackagePath = "";
+ this->PackageName = "";
+ }
+
+ ~XMLParser() CM_OVERRIDE {}
+
+protected:
+ void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
+
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
+ if (name == "package") {
+ this->PackageName = atts[1];
+ this->PackagePath = "";
+ } else if (name == "sourcefile") {
+ std::string fileName = atts[1];
+
+ if (this->PackagePath == "") {
+ if (!this->FindPackagePath(fileName)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: "
+ << this->PackageName << "/" << fileName << std::endl);
+ this->Coverage.Error++;
+ return;
+ }
+ }
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Reading file: " << fileName << std::endl,
+ this->Coverage.Quiet);
+
+ this->FilePath = this->PackagePath + "/" + fileName;
+ cmsys::ifstream fin(this->FilePath.c_str());
+ if (!fin) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Jacoco Coverage: Error opening " << this->FilePath
+ << std::endl);
+ }
+ std::string line;
+ FileLinesType& curFileLines =
+ this->Coverage.TotalCoverage[this->FilePath];
+ if (fin) {
+ curFileLines.push_back(-1);
+ }
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ curFileLines.push_back(-1);
+ }
+ } else if (name == "line") {
+ int tagCount = 0;
+ int nr = -1;
+ int ci = -1;
+ while (true) {
+ if (strcmp(atts[tagCount], "ci") == 0) {
+ ci = atoi(atts[tagCount + 1]);
+ } else if (strcmp(atts[tagCount], "nr") == 0) {
+ nr = atoi(atts[tagCount + 1]);
+ }
+ if (ci > -1 && nr > 0) {
+ FileLinesType& curFileLines =
+ this->Coverage.TotalCoverage[this->FilePath];
+ if (!curFileLines.empty()) {
+ curFileLines[nr - 1] = ci;
+ }
+ break;
+ }
+ ++tagCount;
+ }
+ }
+ }
+
+ virtual bool FindPackagePath(std::string const& fileName)
+ {
+ // Search for the source file in the source directory.
+ if (this->PackagePathFound(fileName, this->Coverage.SourceDir)) {
+ return true;
+ }
+
+ // If not found there, check the binary directory.
+ if (this->PackagePathFound(fileName, this->Coverage.BinaryDir)) {
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool PackagePathFound(std::string const& fileName,
+ std::string const& baseDir)
+ {
+ // Search for the file in the baseDir and its subdirectories.
+ std::string packageGlob = baseDir;
+ packageGlob += "/";
+ packageGlob += fileName;
+ cmsys::Glob gl;
+ gl.RecurseOn();
+ gl.RecurseThroughSymlinksOn();
+ gl.FindFiles(packageGlob);
+ std::vector<std::string> const& files = gl.GetFiles();
+ if (files.empty()) {
+ return false;
+ }
+
+ // 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())) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Found package directory for " << fileName << ": "
+ << dir << std::endl,
+ this->Coverage.Quiet);
+ this->PackagePath = dir;
+ return true;
+ }
+ }
+ return false;
+ }
+
+private:
+ std::string FilePath;
+ std::string PackagePath;
+ std::string PackageName;
+ typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
+ FileLinesType;
+ cmCTest* CTest;
+ cmCTestCoverageHandlerContainer& Coverage;
+};
+
+cmParseJacocoCoverage::cmParseJacocoCoverage(
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ : Coverage(cont)
+ , CTest(ctest)
+{
+}
+
+bool cmParseJacocoCoverage::LoadCoverageData(
+ std::vector<std::string> const& files)
+{
+ // load all the jacoco.xml files in the source directory
+ cmsys::Directory dir;
+ size_t i;
+ std::string path;
+ size_t numf = files.size();
+ for (i = 0; i < numf; i++) {
+ path = files[i];
+
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Reading XML File " << path << std::endl,
+ this->Coverage.Quiet);
+ if (cmSystemTools::GetFilenameLastExtension(path) == ".xml") {
+ if (!this->ReadJacocoXML(path.c_str())) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool cmParseJacocoCoverage::ReadJacocoXML(const char* file)
+{
+ cmParseJacocoCoverage::XMLParser parser(this->CTest, this->Coverage);
+ parser.ParseFile(file);
+ return true;
+}
diff --git a/Source/CTest/cmParseJacocoCoverage.h b/Source/CTest/cmParseJacocoCoverage.h
new file mode 100644
index 000000000..f2aec6db9
--- /dev/null
+++ b/Source/CTest/cmParseJacocoCoverage.h
@@ -0,0 +1,53 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmParseJacocoCoverage_h
+#define cmParseJacocoCoverage_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
+
+/** \class cmParseJacocoCoverage
+ * \brief Parse JaCoCO coverage information
+ *
+ * This class is used to parse coverage information for
+ * java using the JaCoCo tool:
+ *
+ * http://www.eclemma.org/jacoco/trunk/index.html
+ */
+class cmParseJacocoCoverage
+{
+public:
+ cmParseJacocoCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest);
+ bool LoadCoverageData(std::vector<std::string> const& files);
+
+ std::string PackageName;
+ std::string FileName;
+ std::string ModuleName;
+ std::string CurFileName;
+
+private:
+ // implement virtual from parent
+ // remove files with no coverage
+ void RemoveUnCoveredFiles();
+ // Read a single mcov file
+ bool ReadJacocoXML(const char* f);
+ // split a string based on ,
+ bool SplitString(std::vector<std::string>& args, std::string const& line);
+ bool FindJavaFile(std::string const& routine, std::string& filepath);
+ void InitializeJavaFile(std::string& file);
+ bool LoadSource(std::string d);
+
+ class XMLParser;
+
+ std::map<std::string, std::string> RoutineToDirectory;
+ cmCTestCoverageHandlerContainer& Coverage;
+ cmCTest* CTest;
+};
+
+#endif
diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx
index 37e8bd082..eb29f55c0 100644
--- a/Source/CTest/cmParseMumpsCoverage.cxx
+++ b/Source/CTest/cmParseMumpsCoverage.cxx
@@ -1,16 +1,21 @@
-#include "cmStandardIncludes.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include "cmParseMumpsCoverage.h"
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
#include "cmSystemTools.h"
-#include "cmParseGTMCoverage.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
cmParseMumpsCoverage::cmParseMumpsCoverage(
- cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest)
- :Coverage(cont), CTest(ctest)
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ : Coverage(cont)
+ , CTest(ctest)
{
}
@@ -23,96 +28,82 @@ bool cmParseMumpsCoverage::ReadCoverageFile(const char* file)
// Read the gtm_coverage.mcov file, that has two lines of data:
// packages:/full/path/to/Vista/Packages
// coverage_dir:/full/path/to/dir/with/*.mcov
- std::ifstream in(file);
- if(!in)
- {
+ cmsys::ifstream in(file);
+ if (!in) {
return false;
- }
+ }
std::string line;
- while(cmSystemTools::GetLineFromStream(in, line))
- {
+ while (cmSystemTools::GetLineFromStream(in, line)) {
std::string::size_type pos = line.find(':', 0);
std::string packages;
- if(pos != std::string::npos)
- {
+ if (pos != std::string::npos) {
std::string type = line.substr(0, pos);
- std::string path = line.substr(pos+1);
- if(type == "packages")
- {
+ std::string path = line.substr(pos + 1);
+ if (type == "packages") {
this->LoadPackages(path.c_str());
- }
- else if(type == "coverage_dir")
- {
+ } else if (type == "coverage_dir") {
this->LoadCoverageData(path.c_str());
- }
- else
- {
+ } else {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Parse Error in Mumps coverage file :\n"
- << file <<
- "\ntype: [" << type << "]\npath:[" << path << "]\n"
- "input line: [" << line << "]\n");
- }
+ << file << "\ntype: [" << type << "]\npath:[" << path
+ << "]\n"
+ "input line: ["
+ << line << "]\n");
}
}
+ }
return true;
}
void cmParseMumpsCoverage::InitializeMumpsFile(std::string& file)
{
// initialize the coverage information for a given mumps file
- std::ifstream in(file.c_str());
- if(!in)
- {
+ cmsys::ifstream in(file.c_str());
+ if (!in) {
return;
- }
+ }
std::string line;
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector&
- coverageVector = this->Coverage.TotalCoverage[file];
- if(!cmSystemTools::GetLineFromStream(in, line))
- {
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector =
+ this->Coverage.TotalCoverage[file];
+ if (!cmSystemTools::GetLineFromStream(in, line)) {
return;
- }
+ }
// first line of a .m file can never be run
coverageVector.push_back(-1);
- while( cmSystemTools::GetLineFromStream(in, line) )
- {
+ while (cmSystemTools::GetLineFromStream(in, line)) {
// putting in a 0 for a line means it is executable code
// putting in a -1 for a line means it is not executable code
int val = -1; // assume line is not executable
bool found = false;
std::string::size_type i = 0;
// (1) Search for the first whitespace or semicolon character on a line.
- //This will skip over labels if the line starts with one, or will simply
- //be the first character on the line for non-label lines.
- for(; i < line.size(); ++i)
- {
- if(line[i] == ' ' || line[i] == '\t' || line[i] == ';')
- {
+ // This will skip over labels if the line starts with one, or will simply
+ // be the first character on the line for non-label lines.
+ for (; i < line.size(); ++i) {
+ if (line[i] == ' ' || line[i] == '\t' || line[i] == ';') {
found = true;
break;
- }
}
- if(found)
- {
- // (2) If the first character found above is whitespace then continue the
- // search for the first following non-whitespace character.
- if(line[i] == ' ' || line[i] == '\t')
- {
- while(i < line.size() && (line[i] == ' ' || line[i] == '\t'))
- {
+ }
+ if (found) {
+ // (2) If the first character found above is whitespace or a period
+ // then continue the search for the first following non-whitespace
+ // character.
+ if (line[i] == ' ' || line[i] == '\t') {
+ while (i < line.size() &&
+ (line[i] == ' ' || line[i] == '\t' || line[i] == '.')) {
i++;
- }
}
+ }
// (3) If the character found is not a semicolon then the line counts for
// coverage.
- if(i < line.size() && line[i] != ';')
- {
+ if (i < line.size() && line[i] != ';') {
val = 0;
- }
}
- coverageVector.push_back(val);
}
+ coverageVector.push_back(val);
+ }
}
bool cmParseMumpsCoverage::LoadPackages(const char* d)
@@ -121,45 +112,37 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
glob.RecurseOn();
std::string pat = d;
pat += "/*.m";
- glob.FindFiles(pat.c_str());
+ glob.FindFiles(pat);
std::vector<std::string>& files = glob.GetFiles();
std::vector<std::string>::iterator fileIt;
- for ( fileIt = files.begin(); fileIt != files.end();
- ++ fileIt )
- {
+ for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
std::string name = cmSystemTools::GetFilenameName(*fileIt);
- this->RoutineToDirectory[name.substr(0, name.size()-2)] = *fileIt;
+ this->RoutineToDirectory[name.substr(0, name.size() - 2)] = *fileIt;
// initialze each file, this is left out until CDash is fixed
// to handle large numbers of files
this->InitializeMumpsFile(*fileIt);
- }
+ }
return true;
}
bool cmParseMumpsCoverage::FindMumpsFile(std::string const& routine,
std::string& filepath)
{
- std::map<cmStdString, cmStdString>::iterator i =
+ std::map<std::string, std::string>::iterator i =
this->RoutineToDirectory.find(routine);
- if(i != this->RoutineToDirectory.end())
- {
+ 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++) {
+ std::string routine2 = routine + tryname[k];
+ i = this->RoutineToDirectory.find(routine2);
+ if (i != this->RoutineToDirectory.end()) {
+ filepath = i->second;
+ return true;
}
- else
- {
- // try some alternate names
- const char* tryname[] = {"GUX", "GTM", "ONT", 0};
- for(int k=0; tryname[k] != 0; k++)
- {
- std::string routine2 = routine + tryname[k];
- i = this->RoutineToDirectory.find(routine2);
- if(i != this->RoutineToDirectory.end())
- {
- filepath = i->second;
- return true;
- }
- }
- }
+ }
return false;
}
diff --git a/Source/CTest/cmParseMumpsCoverage.h b/Source/CTest/cmParseMumpsCoverage.h
index c1effa79b..2c544954b 100644
--- a/Source/CTest/cmParseMumpsCoverage.h
+++ b/Source/CTest/cmParseMumpsCoverage.h
@@ -1,20 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmParseMumpsCoverage_h
#define cmParseMumpsCoverage_h
-#include "cmStandardIncludes.h"
-#include "cmCTestCoverageHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
/** \class cmParseMumpsCoverage
* \brief Parse Mumps coverage information
@@ -25,12 +20,12 @@
class cmParseMumpsCoverage
{
public:
- cmParseMumpsCoverage(cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest);
+ cmParseMumpsCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest);
virtual ~cmParseMumpsCoverage();
// This is the toplevel coverage file locating the coverage files
// and the mumps source code package tree.
bool ReadCoverageFile(const char* file);
+
protected:
// sub classes will use this to
// load all coverage files found in the given directory
@@ -41,10 +36,10 @@ protected:
// initialize the coverage information for a single mumps file
void InitializeMumpsFile(std::string& file);
// Find mumps file for routine
- bool FindMumpsFile(std::string const& routine,
- std::string& filepath);
+ bool FindMumpsFile(std::string const& routine, std::string& filepath);
+
protected:
- std::map<cmStdString, cmStdString> RoutineToDirectory;
+ std::map<std::string, std::string> RoutineToDirectory;
cmCTestCoverageHandlerContainer& Coverage;
cmCTest* CTest;
};
diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx
index 593b2d1a8..761ebec65 100644
--- a/Source/CTest/cmParsePHPCoverage.cxx
+++ b/Source/CTest/cmParsePHPCoverage.cxx
@@ -1,7 +1,13 @@
-#include "cmStandardIncludes.h"
-#include "cmSystemTools.h"
#include "cmParsePHPCoverage.h"
-#include <cmsys/Directory.hxx>
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmSystemTools.h"
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include <stdlib.h>
+#include <string.h>
/*
To setup coverage for php.
@@ -15,55 +21,45 @@
*/
cmParsePHPCoverage::cmParsePHPCoverage(cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest)
- :Coverage(cont), CTest(ctest)
+ cmCTest* ctest)
+ : Coverage(cont)
+ , CTest(ctest)
{
}
-bool cmParsePHPCoverage::ReadUntil(std::ifstream& in, char until)
+bool cmParsePHPCoverage::ReadUntil(std::istream& in, char until)
{
char c = 0;
- while(in.get(c) && c != until)
- {
- }
- if(c != until)
- {
- return false;
- }
- return true;
+ while (in.get(c) && c != until) {
+ }
+ return c == until;
}
-bool cmParsePHPCoverage::ReadCoverageArray(std::ifstream& in,
- cmStdString const& fileName)
+bool cmParsePHPCoverage::ReadCoverageArray(std::istream& in,
+ std::string const& fileName)
{
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector
- = this->Coverage.TotalCoverage[fileName];
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector =
+ this->Coverage.TotalCoverage[fileName];
char c;
char buf[4];
in.read(buf, 3);
buf[3] = 0;
- if(strcmp(buf, ";a:") != 0)
- {
+ if (strcmp(buf, ";a:") != 0) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read start of coverage array, found : "
- << buf << "\n");
+ "failed to read start of coverage array, found : " << buf
+ << "\n");
return false;
- }
+ }
int size = 0;
- if(!this->ReadInt(in, size))
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read size ");
+ if (!this->ReadInt(in, size)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read size ");
return false;
- }
- if(!in.get(c) && c == '{')
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read open {\n");
+ }
+ if (!in.get(c) && c == '{') {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read open {\n");
return false;
- }
- for(int i =0; i < size; i++)
- {
+ }
+ for (int i = 0; i < size; i++) {
this->ReadUntil(in, ':');
int line = 0;
this->ReadInt(in, line);
@@ -71,19 +67,17 @@ bool cmParsePHPCoverage::ReadCoverageArray(std::ifstream& in,
// it seems to be 1 based but often times
// seems to have a 0'th line.
line--;
- if(line < 0)
- {
+ if (line < 0) {
line = 0;
- }
+ }
this->ReadUntil(in, ':');
int value = 0;
this->ReadInt(in, value);
// make sure the vector is the right size and is
// initialized with -1 for each line
- while(coverageVector.size() <= static_cast<size_t>(line) )
- {
+ while (coverageVector.size() <= static_cast<size_t>(line)) {
coverageVector.push_back(-1);
- }
+ }
// if value is less than 0, set it to zero
// TODO figure out the difference between
// -1 and -2 in xdebug coverage?? For now
@@ -91,163 +85,137 @@ bool cmParsePHPCoverage::ReadCoverageArray(std::ifstream& in,
// CDash expects -1 for non executable code (like comments)
// and 0 for uncovered code, and a positive value
// for number of times a line was executed
- if(value < 0)
- {
+ if (value < 0) {
value = 0;
- }
+ }
// if unset then set it to value
- if(coverageVector[line] == -1)
- {
+ if (coverageVector[line] == -1) {
coverageVector[line] = value;
- }
+ }
// otherwise increment by value
- else
- {
+ else {
coverageVector[line] += value;
- }
}
+ }
return true;
}
-bool cmParsePHPCoverage::ReadInt(std::ifstream& in, int& v)
+bool cmParsePHPCoverage::ReadInt(std::istream& in, int& v)
{
std::string s;
char c = 0;
- while(in.get(c) && c != ':' && c != ';')
- {
+ while (in.get(c) && c != ':' && c != ';') {
s += c;
- }
+ }
v = atoi(s.c_str());
return true;
}
-bool cmParsePHPCoverage::ReadArraySize(std::ifstream& in, int& size)
+bool cmParsePHPCoverage::ReadArraySize(std::istream& in, int& size)
{
char c = 0;
in.get(c);
- if(c != 'a')
- {
+ if (c != 'a') {
return false;
- }
- if(in.get(c) && c == ':')
- {
- if(this->ReadInt(in, size))
- {
+ }
+ if (in.get(c) && c == ':') {
+ if (this->ReadInt(in, size)) {
return true;
- }
}
+ }
return false;
}
-bool cmParsePHPCoverage::ReadFileInformation(std::ifstream& in)
+bool cmParsePHPCoverage::ReadFileInformation(std::istream& in)
{
char buf[4];
in.read(buf, 2);
buf[2] = 0;
- if(strcmp(buf, "s:") != 0)
- {
+ if (strcmp(buf, "s:") != 0) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"failed to read start of file info found: [" << buf << "]\n");
return false;
- }
+ }
char c;
int size = 0;
- if(this->ReadInt(in, size))
- {
+ if (this->ReadInt(in, size)) {
size++; // add one for null termination
- char* s = new char[size+1];
+ char* s = new char[size + 1];
// read open quote
- if(in.get(c) && c != '"')
- {
+ if (in.get(c) && c != '"') {
delete[] s;
return false;
- }
+ }
// read the string data
- in.read(s, size-1);
- s[size-1] = 0;
- cmStdString fileName = s;
- delete [] s;
+ in.read(s, size - 1);
+ s[size - 1] = 0;
+ std::string fileName = s;
+ delete[] s;
// read close quote
- if(in.get(c) && c != '"')
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read close quote\n"
- << "read [" << c << "]\n");
+ if (in.get(c) && c != '"') {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read close quote\n"
+ << "read [" << c << "]\n");
return false;
- }
- if(!this->ReadCoverageArray(in, fileName) )
- {
+ }
+ if (!this->ReadCoverageArray(in, fileName)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read coverage array for file: "
- << fileName << "\n");
+ "failed to read coverage array for file: " << fileName
+ << "\n");
return false;
- }
- return true;
}
+ return true;
+ }
return false;
}
-
bool cmParsePHPCoverage::ReadPHPData(const char* file)
{
- std::ifstream in(file);
- if(!in)
- {
+ cmsys::ifstream in(file);
+ if (!in) {
return false;
- }
+ }
int size = 0;
this->ReadArraySize(in, size);
char c = 0;
in.get(c);
- if(c != '{')
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read open array\n");
+ if (c != '{') {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read open array\n");
return false;
- }
- for(int i =0; i < size; i++)
- {
- if(!this->ReadFileInformation(in))
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Failed to read file #" << i << "\n");
+ }
+ for (int i = 0; i < size; i++) {
+ if (!this->ReadFileInformation(in)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Failed to read file #" << i
+ << "\n");
return false;
- }
+ }
in.get(c);
- if(c != '}')
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "failed to read close array\n");
+ if (c != '}') {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read close array\n");
return false;
- }
}
+ }
return true;
}
bool cmParsePHPCoverage::ReadPHPCoverageDirectory(const char* d)
{
cmsys::Directory dir;
- if(!dir.Load(d))
- {
+ if (!dir.Load(d)) {
return false;
- }
+ }
size_t numf;
unsigned int i;
numf = dir.GetNumberOfFiles();
- for (i = 0; i < numf; i++)
- {
+ for (i = 0; i < numf; i++) {
std::string file = dir.GetFile(i);
- if(file != "." && file != ".."
- && !cmSystemTools::FileIsDirectory(file.c_str()))
- {
+ if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
std::string path = d;
path += "/";
path += file;
- if(!this->ReadPHPData(path.c_str()))
- {
+ if (!this->ReadPHPData(path.c_str())) {
return false;
- }
}
}
+ }
return true;
}
diff --git a/Source/CTest/cmParsePHPCoverage.h b/Source/CTest/cmParsePHPCoverage.h
index d50a83c58..ff0e6366d 100644
--- a/Source/CTest/cmParsePHPCoverage.h
+++ b/Source/CTest/cmParsePHPCoverage.h
@@ -1,20 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc.
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmParsePHPCoverage_h
#define cmParsePHPCoverage_h
-#include "cmStandardIncludes.h"
-#include "cmCTestCoverageHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <string>
+
+class cmCTest;
+class cmCTestCoverageHandlerContainer;
/** \class cmParsePHPCoverage
* \brief Parse xdebug PHP coverage information
@@ -26,20 +21,19 @@
class cmParsePHPCoverage
{
public:
- cmParsePHPCoverage(cmCTestCoverageHandlerContainer& cont,
- cmCTest* ctest);
+ cmParsePHPCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest);
bool ReadPHPCoverageDirectory(const char* dir);
void PrintCoverage();
+
private:
bool ReadPHPData(const char* file);
- bool ReadArraySize(std::ifstream& in, int& size);
- bool ReadFileInformation(std::ifstream& in);
- bool ReadInt(std::ifstream& in, int& v);
- bool ReadCoverageArray(std::ifstream& in, cmStdString const&);
- bool ReadUntil(std::ifstream& in, char until);
+ bool ReadArraySize(std::istream& in, int& size);
+ bool ReadFileInformation(std::istream& in);
+ bool ReadInt(std::istream& in, int& v);
+ bool ReadCoverageArray(std::istream& in, std::string const&);
+ bool ReadUntil(std::istream& in, char until);
cmCTestCoverageHandlerContainer& Coverage;
cmCTest* CTest;
};
-
#endif
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 167b992c9..f4ec6da29 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -1,21 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmProcess.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-#include <cmProcess.h>
-#include <cmSystemTools.h>
+#include "cmConfigure.h"
+#include "cmProcessOutput.h"
+#include "cmSystemTools.h"
+#include <iostream>
cmProcess::cmProcess()
{
- this->Process = 0;
+ this->Process = CM_NULLPTR;
this->Timeout = 0;
this->TotalTime = 0;
this->ExitValue = 0;
@@ -39,49 +33,43 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
bool cmProcess::StartProcess()
{
- if(this->Command.size() == 0)
- {
+ if (this->Command.empty()) {
return false;
- }
+ }
this->StartTime = cmSystemTools::GetTime();
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)
- {
+ for (std::vector<std::string>::iterator i = this->Arguments.begin();
+ i != this->Arguments.end(); ++i) {
this->ProcessArgs.push_back(i->c_str());
- }
- this->ProcessArgs.push_back(0); // null terminate the list
+ }
+ this->ProcessArgs.push_back(CM_NULLPTR); // null terminate the list
this->Process = cmsysProcess_New();
cmsysProcess_SetCommand(this->Process, &*this->ProcessArgs.begin());
- if(this->WorkingDirectory.size())
- {
+ if (!this->WorkingDirectory.empty()) {
cmsysProcess_SetWorkingDirectory(this->Process,
this->WorkingDirectory.c_str());
- }
+ }
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);
+ return (cmsysProcess_GetState(this->Process) ==
+ cmsysProcess_State_Executing);
}
-//----------------------------------------------------------------------------
bool cmProcess::Buffer::GetLine(std::string& line)
{
// Scan for the next newline.
- for(size_type sz = this->size(); this->Last != sz; ++this->Last)
- {
- if((*this)[this->Last] == '\n' || (*this)[this->Last] == '\0')
- {
+ 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;
size_type length = this->Last - this->First;
- while(length && text[length-1] == '\r')
- {
- length --;
- }
+ while (length && text[length - 1] == '\r') {
+ length--;
+ }
line.assign(text, length);
// Start a new range for the next line.
@@ -90,87 +78,70 @@ bool cmProcess::Buffer::GetLine(std::string& line)
// Return the line extracted.
return true;
- }
}
+ }
// Available data have been exhausted without a newline.
- if(this->First != 0)
- {
+ if (this->First != 0) {
// Move the partial line to the beginning of the buffer.
this->erase(this->begin(), this->begin() + this->First);
this->First = 0;
this->Last = this->size();
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmProcess::Buffer::GetLast(std::string& line)
{
// Return the partial last line, if any.
- if(!this->empty())
- {
+ if (!this->empty()) {
line.assign(&*this->begin(), this->size());
this->First = this->Last = 0;
this->clear();
return true;
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
int cmProcess::GetNextOutputLine(std::string& line, double timeout)
{
- for(;;)
- {
+ cmProcessOutput processOutput(cmProcessOutput::UTF8);
+ std::string strdata;
+ for (;;) {
// Look for lines already buffered.
- if(this->StdOut.GetLine(line))
- {
+ if (this->Output.GetLine(line)) {
return cmsysProcess_Pipe_STDOUT;
- }
- else if(this->StdErr.GetLine(line))
- {
- return cmsysProcess_Pipe_STDERR;
- }
+ }
// 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)
- {
+ if (p == cmsysProcess_Pipe_Timeout) {
return cmsysProcess_Pipe_Timeout;
- }
- else if(p == cmsysProcess_Pipe_STDOUT)
- {
- this->StdOut.insert(this->StdOut.end(), data, data+length);
- }
- else if(p == cmsysProcess_Pipe_STDERR)
- {
- this->StdErr.insert(this->StdErr.end(), data, data+length);
- }
- else // p == cmsysProcess_Pipe_None
- {
+ }
+ 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;
- }
}
+ }
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ this->Output.insert(this->Output.end(), strdata.begin(), strdata.end());
+ }
// Look for partial last lines.
- if(this->StdOut.GetLast(line))
- {
+ if (this->Output.GetLast(line)) {
return cmsysProcess_Pipe_STDOUT;
- }
- else if(this->StdErr.GetLast(line))
- {
- return cmsysProcess_Pipe_STDERR;
- }
+ }
// No more data. Wait for process exit.
- if(!cmsysProcess_WaitForExit(this->Process, &timeout))
- {
+ if (!cmsysProcess_WaitForExit(this->Process, &timeout)) {
return cmsysProcess_Pipe_Timeout;
- }
+ }
// Record exit information.
this->ExitValue = cmsysProcess_GetExitValue(this->Process);
@@ -179,10 +150,9 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout)
// 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)
- {
+ if (this->TotalTime <= 0.0) {
this->TotalTime = 0.0;
- }
+ }
// std::cerr << "Time to run: " << this->TotalTime << "\n";
return cmsysProcess_Pipe_None;
}
@@ -190,89 +160,81 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout)
// return the process status
int cmProcess::GetProcessStatus()
{
- if(!this->Process)
- {
+ 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:
- {
+ 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)
+ << " process: " << cmsysProcess_GetErrorString(this->Process)
<< "\n";
- } break;
- case cmsysProcess_State_Exception:
- {
+ } break;
+ case cmsysProcess_State_Exception: {
std::cerr << "cmProcess: " << this->Command
- << " process exited with an exception: ";
- switch(cmsysProcess_GetExitException(this->Process))
- {
- case cmsysProcess_Exception_None:
- {
+ << " process exited with an exception: ";
+ switch (cmsysProcess_GetExitException(this->Process)) {
+ case cmsysProcess_Exception_None: {
std::cerr << "None";
- } break;
- case cmsysProcess_Exception_Fault:
- {
+ } break;
+ case cmsysProcess_Exception_Fault: {
std::cerr << "Segmentation fault";
- } break;
- case cmsysProcess_Exception_Illegal:
- {
+ } break;
+ case cmsysProcess_Exception_Illegal: {
std::cerr << "Illegal instruction";
- } break;
- case cmsysProcess_Exception_Interrupt:
- {
+ } break;
+ case cmsysProcess_Exception_Interrupt: {
std::cerr << "Interrupted by user";
- } break;
- case cmsysProcess_Exception_Numerical:
- {
+ } break;
+ case cmsysProcess_Exception_Numerical: {
std::cerr << "Numerical exception";
- } break;
- case cmsysProcess_Exception_Other:
- {
+ } break;
+ case cmsysProcess_Exception_Other: {
std::cerr << "Unknown";
- } break;
- }
+ } break;
+ }
std::cerr << "\n";
- } break;
- case cmsysProcess_State_Executing:
- {
- std::cerr << "cmProcess: Never terminated " <<
- this->Command << " process.\n";
- } break;
- case cmsysProcess_State_Exited:
- {
+ } 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:
- {
+ << " 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:
- {
+ } break;
+ case cmsysProcess_State_Killed: {
std::cerr << "cmProcess: killed " << this->Command << " process.\n";
- } break;
- }
+ } break;
+ }
return result;
+}
+void cmProcess::ChangeTimeout(double t)
+{
+ this->Timeout = t;
+ cmsysProcess_SetTimeout(this->Process, this->Timeout);
}
+void cmProcess::ResetStartTime()
+{
+ cmsysProcess_ResetStartTime(this->Process);
+ this->StartTime = cmSystemTools::GetTime();
+}
int cmProcess::GetExitException()
{
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 1479df05f..86e905aca 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -1,21 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmProcess_h
#define cmProcess_h
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmStandardIncludes.h"
-#include <cmsys/Process.h>
-
+#include "cmsys/Process.h"
+#include <string>
+#include <vector>
/** \class cmProcess
* \brief run a process with c++
@@ -27,11 +19,13 @@ class cmProcess
public:
cmProcess();
~cmProcess();
- const char* GetCommand() { return this->Command.c_str();}
+ const char* GetCommand() { return this->Command.c_str(); }
void SetCommand(const char* command);
void SetCommandArguments(std::vector<std::string> const& arg);
- void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir;}
- void SetTimeout(double t) { this->Timeout = t;}
+ void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
+ void SetTimeout(double t) { this->Timeout = t; }
+ void ChangeTimeout(double t);
+ void ResetStartTime();
// Return true if the process starts
bool StartProcess();
@@ -40,41 +34,44 @@ public:
// Report the status of the program
int ReportStatus();
int GetId() { return this->Id; }
- void SetId(int id) { this->Id = id;}
- int GetExitValue() { return this->ExitValue;}
- double GetTotalTime() { return this->TotalTime;}
+ 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
- * cmsysProcess_Pipe_STDOUT = Line came from stderr
+ * cmsysProcess_Pipe_STDOUT = Line came from stdout or stderr
* cmsysProcess_Pipe_Timeout = Timeout expired while waiting
*/
int GetNextOutputLine(std::string& line, double timeout);
+
private:
double Timeout;
double StartTime;
double TotalTime;
cmsysProcess* Process;
- class Buffer: public std::vector<char>
+ class Buffer : public std::vector<char>
{
// Half-open index range of partial line already scanned.
size_type First;
size_type Last;
+
public:
- Buffer(): First(0), Last(0) {}
+ Buffer()
+ : First(0)
+ , Last(0)
+ {
+ }
bool GetLine(std::string& line);
bool GetLast(std::string& line);
};
- Buffer StdErr;
- Buffer StdOut;
+ Buffer Output;
std::string Command;
std::string WorkingDirectory;
std::vector<std::string> Arguments;
std::vector<const char*> ProcessArgs;
- std::string Output;
int Id;
int ExitValue;
};
diff --git a/Source/Checks/cm_c11_thread_local.c b/Source/Checks/cm_c11_thread_local.c
new file mode 100644
index 000000000..bdf91aa90
--- /dev/null
+++ b/Source/Checks/cm_c11_thread_local.c
@@ -0,0 +1,5 @@
+_Thread_local int i = 42;
+int main(void)
+{
+ return 0;
+}
diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake
new file mode 100644
index 000000000..6b8d10b2b
--- /dev/null
+++ b/Source/Checks/cm_c11_thread_local.cmake
@@ -0,0 +1,33 @@
+set(CMake_C11_THREAD_LOCAL_BROKEN 0)
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION)
+ if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS)
+ message(STATUS "Checking if compiler supports C11 _Thread_local")
+ try_compile(CMake_C11_THREAD_LOCAL_WORKS
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/cm_c11_thread_local.c
+ CMAKE_FLAGS -DCMAKE_C_STANDARD=11
+ OUTPUT_VARIABLE OUTPUT
+ )
+ if(CMake_C11_THREAD_LOCAL_WORKS AND "${OUTPUT}" MATCHES "error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'")
+ set_property(CACHE CMake_C11_THREAD_LOCAL_WORKS PROPERTY VALUE 0)
+ endif()
+ if(CMake_C11_THREAD_LOCAL_WORKS)
+ message(STATUS "Checking if compiler supports C11 _Thread_local - yes")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if compiler supports C11 _Thread_local passed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ else()
+ message(STATUS "Checking if compiler supports C11 _Thread_local - no")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if compiler supports C11 _Thread_local failed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ endif()
+ endif()
+ if(NOT CMake_C11_THREAD_LOCAL_WORKS)
+ set(CMake_C11_THREAD_LOCAL_BROKEN 1)
+ endif()
+endif()
diff --git a/Source/Checks/cm_cxx14_cstdio.cmake b/Source/Checks/cm_cxx14_cstdio.cmake
new file mode 100644
index 000000000..73f7e2ed5
--- /dev/null
+++ b/Source/Checks/cm_cxx14_cstdio.cmake
@@ -0,0 +1,33 @@
+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
new file mode 100644
index 000000000..f5806a9c6
--- /dev/null
+++ b/Source/Checks/cm_cxx14_cstdio.cpp
@@ -0,0 +1,5 @@
+#include <cstdio>
+int main()
+{
+ return 0;
+}
diff --git a/Source/Checks/cm_cxx_attribute_fallthrough.cxx b/Source/Checks/cm_cxx_attribute_fallthrough.cxx
new file mode 100644
index 000000000..df43625a4
--- /dev/null
+++ b/Source/Checks/cm_cxx_attribute_fallthrough.cxx
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 000000000..d3100fdc8
--- /dev/null
+++ b/Source/Checks/cm_cxx_auto_ptr.cxx
@@ -0,0 +1,18 @@
+#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
new file mode 100644
index 000000000..809e4cfcf
--- /dev/null
+++ b/Source/Checks/cm_cxx_eq_delete.cxx
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 000000000..7b35a5f29
--- /dev/null
+++ b/Source/Checks/cm_cxx_fallthrough.cxx
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 000000000..3b0802579
--- /dev/null
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -0,0 +1,58 @@
+
+function(cm_check_cxx_feature name)
+ string(TOUPPER ${name} FEATURE)
+ if(NOT DEFINED CMake_HAVE_CXX_${FEATURE})
+ message(STATUS "Checking if compiler supports C++ ${name}")
+ if(CMAKE_CXX_STANDARD)
+ set(maybe_cxx_standard -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD})
+ else()
+ set(maybe_cxx_standard "")
+ endif()
+ try_compile(CMake_HAVE_CXX_${FEATURE}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/cm_cxx_${name}.cxx
+ CMAKE_FLAGS ${maybe_cxx_standard}
+ OUTPUT_VARIABLE OUTPUT
+ )
+ # Filter out MSBuild output that looks like a warning.
+ string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${OUTPUT}")
+ # If using the feature causes warnings, treat it as broken/unavailable.
+ if(check_output MATCHES "[Ww]arning")
+ set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
+ endif()
+ if(CMake_HAVE_CXX_${FEATURE})
+ message(STATUS "Checking if compiler supports C++ ${name} - yes")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if compiler supports C++ ${name} passed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ else()
+ message(STATUS "Checking if compiler supports C++ ${name} - no")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if compiler supports C++ ${name} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ endif()
+ 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
new file mode 100644
index 000000000..602109405
--- /dev/null
+++ b/Source/Checks/cm_cxx_gnu_fallthrough.cxx
@@ -0,0 +1,11 @@
+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_make_unique.cxx b/Source/Checks/cm_cxx_make_unique.cxx
new file mode 100644
index 000000000..a3ff68f9b
--- /dev/null
+++ b/Source/Checks/cm_cxx_make_unique.cxx
@@ -0,0 +1,6 @@
+#include <memory>
+int main()
+{
+ std::unique_ptr<int> u = std::make_unique<int>(0);
+ return *u;
+}
diff --git a/Source/Checks/cm_cxx_nullptr.cxx b/Source/Checks/cm_cxx_nullptr.cxx
new file mode 100644
index 000000000..500684aee
--- /dev/null
+++ b/Source/Checks/cm_cxx_nullptr.cxx
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 000000000..5a33fbb78
--- /dev/null
+++ b/Source/Checks/cm_cxx_override.cxx
@@ -0,0 +1,24 @@
+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_unique_ptr.cxx b/Source/Checks/cm_cxx_unique_ptr.cxx
new file mode 100644
index 000000000..a9d4ce5d1
--- /dev/null
+++ b/Source/Checks/cm_cxx_unique_ptr.cxx
@@ -0,0 +1,6 @@
+#include <memory>
+int main()
+{
+ std::unique_ptr<int> u(new int(0));
+ return *u;
+}
diff --git a/Source/Checks/cm_cxx_unordered_map.cxx b/Source/Checks/cm_cxx_unordered_map.cxx
new file mode 100644
index 000000000..be3de252b
--- /dev/null
+++ b/Source/Checks/cm_cxx_unordered_map.cxx
@@ -0,0 +1,7 @@
+#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
new file mode 100644
index 000000000..de4bb7765
--- /dev/null
+++ b/Source/Checks/cm_cxx_unordered_set.cxx
@@ -0,0 +1,7 @@
+#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 5efc2fb1a..c5ac1f1a6 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -1,16 +1,8 @@
-#=============================================================================
-# CMake - Cross Platform Makefile Generator
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# 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
@@ -25,13 +17,26 @@ set( CURSES_SRCS
CursesDialog/ccmake
)
-include_directories(${CMake_SOURCE_DIR}/Source/CursesDialog/form
- ${CMake_BINARY_DIR}/Source/CursesDialog/form)
+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} )
target_link_libraries(ccmake CMakeLib)
-target_link_libraries(ccmake cmForm)
+if(CMAKE_USE_SYSTEM_FORM)
+ target_link_libraries(ccmake
+ ${CURSES_FORM_LIBRARY}
+ ${CURSES_LIBRARY}
+ )
+ if(CURSES_EXTRA_LIBRARY)
+ target_link_libraries(ccmake ${CURSES_EXTRA_LIBRARY})
+ endif()
+else()
+ target_link_libraries(ccmake cmForm)
+endif()
-install(TARGETS ccmake DESTINATION bin)
+CMake_OPTIONAL_COMPONENT(ccmake)
+install(TARGETS ccmake DESTINATION ${CMAKE_BIN_DIR} ${COMPONENT})
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 623d7d3a5..28a0e95b9 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -1,217 +1,177 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "../cmCacheManager.h"
-#include "../cmSystemTools.h"
-#include "../cmake.h"
-#include "../cmDocumentation.h"
-
-#include <signal.h>
-#include <sys/ioctl.h>
+/* 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 "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
+#include "cmDocumentation.h"
+#include "cmDocumentationEntry.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include <form.h>
+#include "cmsys/Encoding.hxx"
+#include <iostream>
+#include <signal.h>
+#include <string.h>
+#include <string>
+#include <vector>
-//----------------------------------------------------------------------------
-static const char * cmDocumentationName[][3] =
-{
- {0,
- " ccmake - Curses Interface for CMake.", 0},
- {0,0,0}
+static const char* cmDocumentationName[][2] = {
+ { CM_NULLPTR, " ccmake - Curses Interface for CMake." },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationUsage[][3] =
-{
- {0,
- " ccmake <path-to-source>\n"
- " ccmake <path-to-existing-build>", 0},
- {0,0,0}
+static const char* cmDocumentationUsage[][2] = {
+ { CM_NULLPTR, " ccmake <path-to-source>\n"
+ " ccmake <path-to-existing-build>" },
+ { CM_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 }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationDescription[][3] =
-{
- {0,
- "The \"ccmake\" executable is the CMake curses interface. Project "
- "configuration settings may be specified interactively through "
- "this GUI. Brief instructions are provided at the bottom of the "
- "terminal when the program is running.", 0},
- CMAKE_STANDARD_INTRODUCTION,
- {0,0,0}
+static const char* cmDocumentationUsageNote[][2] = {
+ { CM_NULLPTR, "Run 'ccmake --help' for more information." },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationOptions[][3] =
-{
- CMAKE_STANDARD_OPTIONS_TABLE,
- {0,0,0}
-};
+static const char* cmDocumentationOptions[]
+ [2] = { CMAKE_STANDARD_OPTIONS_TABLE,
+ { CM_NULLPTR, CM_NULLPTR } };
-//----------------------------------------------------------------------------
-static const char * cmDocumentationSeeAlso[][3] =
-{
- {0, "cmake", 0},
- {0, "ctest", 0},
- {0, 0, 0}
-};
+cmCursesForm* cmCursesForm::CurrentForm = CM_NULLPTR;
-cmCursesForm* cmCursesForm::CurrentForm=0;
+extern "C" {
-extern "C"
+void onsig(int /*unused*/)
{
-
-void onsig(int)
-{
- if (cmCursesForm::CurrentForm)
- {
+ if (cmCursesForm::CurrentForm) {
endwin();
- initscr(); /* Initialization */
- noecho(); /* Echo off */
- cbreak(); /* nl- or cr not needed */
- keypad(stdscr,TRUE); /* Use key symbols as
- KEY_DOWN*/
+ initscr(); /* Initialization */
+ noecho(); /* Echo off */
+ cbreak(); /* nl- or cr not needed */
+ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
refresh();
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
- cmCursesForm::CurrentForm->Render(1,1,x,y);
+ cmCursesForm::CurrentForm->Render(1, 1, x, y);
cmCursesForm::CurrentForm->UpdateStatusBar();
- }
+ }
signal(SIGWINCH, onsig);
}
-
}
-void CMakeErrorHandler(const char* message, const char* title, bool&, void* clientData)
+void CMakeMessageHandler(const char* message, const char* title,
+ bool& /*unused*/, void* clientData)
{
- cmCursesForm* self = static_cast<cmCursesForm*>( clientData );
+ cmCursesForm* self = static_cast<cmCursesForm*>(clientData);
self->AddError(message, title);
}
-int main(int argc, char** argv)
+int main(int argc, char const* const* argv)
{
- cmSystemTools::FindExecutableDirectory(argv[0]);
+ cmsys::Encoding::CommandLineArguments encoding_args =
+ cmsys::Encoding::CommandLineArguments::Main(argc, argv);
+ argc = encoding_args.argc();
+ argv = encoding_args.argv();
+
+ cmSystemTools::FindCMakeResources(argv[0]);
cmDocumentation doc;
doc.addCMakeStandardDocSections();
- if(doc.CheckOptions(argc, argv))
- {
- cmake hcm;
- std::vector<cmDocumentationEntry> commands;
- std::vector<cmDocumentationEntry> compatCommands;
+ if (doc.CheckOptions(argc, argv)) {
+ cmake hcm(cmake::RoleInternal);
+ hcm.SetHomeDirectory("");
+ hcm.SetHomeOutputDirectory("");
+ hcm.AddCMakePaths();
std::vector<cmDocumentationEntry> generators;
- hcm.GetCommandDocumentation(commands, true, false);
- hcm.GetCommandDocumentation(compatCommands, false, true);
hcm.GetGeneratorDocumentation(generators);
doc.SetName("ccmake");
- doc.SetSection("Name",cmDocumentationName);
- doc.SetSection("Usage",cmDocumentationUsage);
- doc.SetSection("Description",cmDocumentationDescription);
- doc.SetSection("Generators",generators);
- doc.PrependSection("Options",cmDocumentationOptions);
- doc.SetSection("Command",commands);
- doc.SetSection("Compatibility Commands",compatCommands);
- doc.SetSeeAlsoList(cmDocumentationSeeAlso);
- return doc.PrintRequestedDocumentation(std::cout)? 0:1;
+ doc.SetSection("Name", cmDocumentationName);
+ doc.SetSection("Usage", cmDocumentationUsage);
+ if (argc == 1) {
+ doc.AppendSection("Usage", cmDocumentationUsageNote);
}
+ doc.SetSection("Generators", generators);
+ doc.PrependSection("Options", cmDocumentationOptions);
+ return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
+ }
bool debug = false;
unsigned int i;
int j;
std::vector<std::string> args;
- for(j =0; j < argc; ++j)
- {
- if(strcmp(argv[j], "-debug") == 0)
- {
+ for (j = 0; j < argc; ++j) {
+ if (strcmp(argv[j], "-debug") == 0) {
debug = true;
- }
- else
- {
+ } else {
args.push_back(argv[j]);
- }
}
+ }
std::string cacheDir = cmSystemTools::GetCurrentWorkingDirectory();
- for(i=1; i < args.size(); ++i)
- {
+ for (i = 1; i < args.size(); ++i) {
std::string arg = args[i];
- if(arg.find("-B",0) == 0)
- {
+ if (arg.find("-B", 0) == 0) {
cacheDir = arg.substr(2);
- }
}
+ }
cmSystemTools::DisableRunCommandOutput();
- if (debug)
- {
+ if (debug) {
cmCursesForm::DebugStart();
- }
+ }
- initscr(); /* Initialization */
- noecho(); /* Echo off */
- cbreak(); /* nl- or cr not needed */
- keypad(stdscr,TRUE); /* Use key symbols as
- KEY_DOWN*/
+ initscr(); /* Initialization */
+ noecho(); /* Echo off */
+ cbreak(); /* nl- or cr not needed */
+ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
signal(SIGWINCH, onsig);
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
endwin();
std::cerr << "Window is too small. A size of at least "
<< cmCursesMainForm::MIN_WIDTH << " x "
- << cmCursesMainForm::MIN_HEIGHT
- << " is required to run ccmake." << std::endl;
+ << cmCursesMainForm::MIN_HEIGHT << " is required to run ccmake."
+ << std::endl;
return 1;
- }
-
+ }
cmCursesMainForm* myform;
myform = new cmCursesMainForm(args, x);
- if(myform->LoadCache(cacheDir.c_str()))
- {
+ if (myform->LoadCache(cacheDir.c_str())) {
curses_clear();
touchwin(stdscr);
endwin();
delete myform;
std::cerr << "Error running cmake::LoadCache(). Aborting.\n";
return 1;
- }
+ }
- cmSystemTools::SetErrorCallback(CMakeErrorHandler, myform);
+ cmSystemTools::SetMessageCallback(CMakeMessageHandler, myform);
cmCursesForm::CurrentForm = myform;
myform->InitializeUI();
- if ( myform->Configure(1) == 0 )
- {
+ if (myform->Configure(1) == 0) {
myform->Render(1, 1, x, y);
myform->HandleInput();
- }
+ }
// Need to clean-up better
curses_clear();
touchwin(stdscr);
endwin();
delete cmCursesForm::CurrentForm;
- cmCursesForm::CurrentForm = 0;
+ cmCursesForm::CurrentForm = CM_NULLPTR;
std::cout << std::endl << std::endl;
return 0;
-
}
diff --git a/Source/CursesDialog/cmCursesBoolWidget.cxx b/Source/CursesDialog/cmCursesBoolWidget.cxx
index fd15b9944..80a5b5b9c 100644
--- a/Source/CursesDialog/cmCursesBoolWidget.cxx
+++ b/Source/CursesDialog/cmCursesBoolWidget.cxx
@@ -1,74 +1,53 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCursesBoolWidget.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmCursesWidget.h"
+#include "cmStateTypes.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCursesBoolWidget.h"
-#include "cmCursesMainForm.h"
+#include <string>
-cmCursesBoolWidget::cmCursesBoolWidget(int width, int height,
- int left, int top) :
- cmCursesWidget(width, height, left, top)
+cmCursesBoolWidget::cmCursesBoolWidget(int width, int height, int left,
+ int top)
+ : cmCursesWidget(width, height, left, top)
{
- this->Type = cmCacheManager::BOOL;
- set_field_fore(this->Field, A_NORMAL);
- set_field_back(this->Field, A_STANDOUT);
- field_opts_off(this->Field, O_STATIC);
+ this->Type = cmStateEnums::BOOL;
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ field_opts_off(this->Field, O_STATIC);
this->SetValueAsBool(false);
}
-bool cmCursesBoolWidget::HandleInput(int& key, cmCursesMainForm*, WINDOW* w)
+bool cmCursesBoolWidget::HandleInput(int& key, cmCursesMainForm* /*fm*/,
+ WINDOW* w)
{
+ // toggle boolean values with enter or space
// 10 == enter
- if (key == 10 || key == KEY_ENTER)
- {
- if (this->GetValueAsBool())
- {
+ if (key == 10 || key == KEY_ENTER || key == ' ') {
+ if (this->GetValueAsBool()) {
this->SetValueAsBool(false);
- }
- else
- {
+ } else {
this->SetValueAsBool(true);
- }
+ }
touchwin(w);
wrefresh(w);
return true;
- }
- else
- {
- return false;
- }
-
+ }
+ return false;
}
void cmCursesBoolWidget::SetValueAsBool(bool value)
{
- if (value)
- {
+ if (value) {
this->SetValue("ON");
- }
- else
- {
+ } else {
this->SetValue("OFF");
- }
+ }
}
bool cmCursesBoolWidget::GetValueAsBool()
{
- if (this->Value == "ON")
- {
- return true;
- }
- else
- {
- return false;
- }
+ return this->Value == "ON";
}
diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h
index d2a25ca12..90bcc2209 100644
--- a/Source/CursesDialog/cmCursesBoolWidget.h
+++ b/Source/CursesDialog/cmCursesBoolWidget.h
@@ -1,22 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesBoolWidget_h
+#define cmCursesBoolWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesBoolWidget_h
-#define __cmCursesBoolWidget_h
+#include "cmConfigure.h"
+#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
+
class cmCursesMainForm;
class cmCursesBoolWidget : public cmCursesWidget
{
+ CM_DISABLE_COPY(cmCursesBoolWidget)
+
public:
cmCursesBoolWidget(int width, int height, int left, int top);
@@ -24,17 +21,12 @@ public:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled.
- virtual bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w);
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
// Description:
// Set/Get the value (on/off).
void SetValueAsBool(bool value);
bool GetValueAsBool();
-
-protected:
- cmCursesBoolWidget(const cmCursesBoolWidget& from);
- void operator=(const cmCursesBoolWidget&);
-
};
-#endif // __cmCursesBoolWidget_h
+#endif // cmCursesBoolWidget_h
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index c58d037f0..d071c9178 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -1,86 +1,95 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesCacheEntryComposite.h"
-#include "cmCursesStringWidget.h"
-#include "cmCursesLabelWidget.h"
+
#include "cmCursesBoolWidget.h"
-#include "cmCursesPathWidget.h"
#include "cmCursesFilePathWidget.h"
-#include "cmCursesDummyWidget.h"
-#include "../cmSystemTools.h"
+#include "cmCursesLabelWidget.h"
+#include "cmCursesOptionsWidget.h"
+#include "cmCursesPathWidget.h"
+#include "cmCursesStringWidget.h"
+#include "cmCursesWidget.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(const char* key,
- int labelwidth,
- int entrywidth) :
- Key(key), LabelWidth(labelwidth), EntryWidth(entrywidth)
+#include <assert.h>
+#include <vector>
+
+cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
+ const std::string& key, int labelwidth, int entrywidth)
+ : Key(key)
+ , LabelWidth(labelwidth)
+ , EntryWidth(entrywidth)
{
this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
- this->Entry = 0;
+ this->Entry = CM_NULLPTR;
this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
}
cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
- const char* key, const cmCacheManager::CacheIterator& it, bool isNew,
- int labelwidth, int entrywidth)
- : Key(key), LabelWidth(labelwidth), EntryWidth(entrywidth)
+ const std::string& key, cmake* cm, bool isNew, int labelwidth,
+ int entrywidth)
+ : Key(key)
+ , LabelWidth(labelwidth)
+ , EntryWidth(entrywidth)
{
this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
- if (isNew)
- {
+ if (isNew) {
this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, "*");
- }
- else
- {
+ } else {
this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
- }
+ }
- this->Entry = 0;
- switch ( it.GetType() )
- {
- case cmCacheManager::BOOL:
+ this->Entry = CM_NULLPTR;
+ const char* value = cm->GetState()->GetCacheEntryValue(key);
+ assert(value);
+ switch (cm->GetState()->GetCacheEntryType(key)) {
+ case cmStateEnums::BOOL:
this->Entry = new cmCursesBoolWidget(this->EntryWidth, 1, 1, 1);
- if (cmSystemTools::IsOn(it.GetValue()))
- {
+ if (cmSystemTools::IsOn(value)) {
static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(true);
- }
- else
- {
+ } else {
static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(false);
- }
+ }
break;
- case cmCacheManager::PATH:
+ case cmStateEnums::PATH:
this->Entry = new cmCursesPathWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesPathWidget*>(this->Entry)->SetString(
- it.GetValue());
+ static_cast<cmCursesPathWidget*>(this->Entry)->SetString(value);
break;
- case cmCacheManager::FILEPATH:
+ case cmStateEnums::FILEPATH:
this->Entry = new cmCursesFilePathWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesFilePathWidget*>(this->Entry)->SetString(
- it.GetValue());
+ static_cast<cmCursesFilePathWidget*>(this->Entry)->SetString(value);
break;
- case cmCacheManager::STRING:
- this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesStringWidget*>(this->Entry)->SetString(
- it.GetValue());
+ case cmStateEnums::STRING: {
+ const char* stringsProp =
+ cm->GetState()->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);
+ }
+ ow->SetOption(value);
+ } else {
+ this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
+ static_cast<cmCursesStringWidget*>(this->Entry)->SetString(value);
+ }
break;
- case cmCacheManager::UNINITIALIZED:
- cmSystemTools::Error("Found an undefined variable: ", it.GetName());
+ }
+ case cmStateEnums::UNINITIALIZED:
+ cmSystemTools::Error("Found an undefined variable: ", key.c_str());
break;
default:
// TODO : put warning message here
break;
- }
-
+ }
}
cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite()
@@ -92,12 +101,8 @@ cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite()
const char* cmCursesCacheEntryComposite::GetValue()
{
- if (this->Label)
- {
+ if (this->Label) {
return this->Label->GetValue();
- }
- else
- {
- return 0;
- }
+ }
+ return CM_NULLPTR;
}
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index 1357a02ec..3c500785d 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -1,36 +1,31 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesCacheEntryComposite_h
+#define cmCursesCacheEntryComposite_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesCacheEntryComposite_h
-#define __cmCursesCacheEntryComposite_h
+#include <string>
-#include "../cmCacheManager.h"
-#include "cmCursesLabelWidget.h"
+class cmCursesLabelWidget;
+class cmCursesWidget;
+class cmake;
class cmCursesCacheEntryComposite
{
+ CM_DISABLE_COPY(cmCursesCacheEntryComposite)
+
public:
- cmCursesCacheEntryComposite(const char* key, int labelwidth, int entrywidth);
- cmCursesCacheEntryComposite(const char* key,
- const cmCacheManager::CacheIterator& it,
- bool isNew, int labelwidth, int entrywidth);
+ cmCursesCacheEntryComposite(const std::string& key, int labelwidth,
+ int entrywidth);
+ cmCursesCacheEntryComposite(const std::string& key, cmake* cm, bool isNew,
+ int labelwidth, int entrywidth);
~cmCursesCacheEntryComposite();
const char* GetValue();
friend class cmCursesMainForm;
protected:
- cmCursesCacheEntryComposite(const cmCursesCacheEntryComposite& from);
- void operator=(const cmCursesCacheEntryComposite&);
-
cmCursesLabelWidget* Label;
cmCursesLabelWidget* IsNewLabel;
cmCursesWidget* Entry;
@@ -39,4 +34,4 @@ protected:
int EntryWidth;
};
-#endif // __cmCursesCacheEntryComposite_h
+#endif // cmCursesCacheEntryComposite_h
diff --git a/Source/CursesDialog/cmCursesDummyWidget.cxx b/Source/CursesDialog/cmCursesDummyWidget.cxx
index 60086a51b..da0478a26 100644
--- a/Source/CursesDialog/cmCursesDummyWidget.cxx
+++ b/Source/CursesDialog/cmCursesDummyWidget.cxx
@@ -1,26 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesDummyWidget.h"
-cmCursesDummyWidget::cmCursesDummyWidget(int width, int height,
- int left, int top) :
- cmCursesWidget(width, height, left, top)
+#include "cmCursesWidget.h"
+#include "cmStateTypes.h"
+
+cmCursesDummyWidget::cmCursesDummyWidget(int width, int height, int left,
+ int top)
+ : cmCursesWidget(width, height, left, top)
{
- this->Type = cmCacheManager::INTERNAL;
+ this->Type = cmStateEnums::INTERNAL;
}
-
-bool cmCursesDummyWidget::HandleInput(int&, cmCursesMainForm*, WINDOW* )
+bool cmCursesDummyWidget::HandleInput(int& /*key*/, cmCursesMainForm* /*fm*/,
+ WINDOW* /*w*/)
{
return false;
}
-
diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h
index 9ac13652d..d9bb6babc 100644
--- a/Source/CursesDialog/cmCursesDummyWidget.h
+++ b/Source/CursesDialog/cmCursesDummyWidget.h
@@ -1,23 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesDummyWidget_h
+#define cmCursesDummyWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesDummyWidget_h
-#define __cmCursesDummyWidget_h
+#include "cmConfigure.h"
+#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
class cmCursesMainForm;
class cmCursesDummyWidget : public cmCursesWidget
{
+ CM_DISABLE_COPY(cmCursesDummyWidget)
+
public:
cmCursesDummyWidget(int width, int height, int left, int top);
@@ -25,12 +21,7 @@ public:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled.
- virtual bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w);
-
-protected:
- cmCursesDummyWidget(const cmCursesDummyWidget& from);
- void operator=(const cmCursesDummyWidget&);
-
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
};
-#endif // __cmCursesDummyWidget_h
+#endif // cmCursesDummyWidget_h
diff --git a/Source/CursesDialog/cmCursesFilePathWidget.cxx b/Source/CursesDialog/cmCursesFilePathWidget.cxx
index 01db014bb..518da4f08 100644
--- a/Source/CursesDialog/cmCursesFilePathWidget.cxx
+++ b/Source/CursesDialog/cmCursesFilePathWidget.cxx
@@ -1,20 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesFilePathWidget.h"
-cmCursesFilePathWidget::cmCursesFilePathWidget(int width, int height,
- int left, int top) :
- cmCursesPathWidget(width, height, left, top)
+#include "cmCursesPathWidget.h"
+#include "cmStateTypes.h"
+
+cmCursesFilePathWidget::cmCursesFilePathWidget(int width, int height, int left,
+ int top)
+ : cmCursesPathWidget(width, height, left, top)
{
- this->Type = cmCacheManager::FILEPATH;
+ this->Type = cmStateEnums::FILEPATH;
}
-
diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h
index 9d2972ee7..6ad535b99 100644
--- a/Source/CursesDialog/cmCursesFilePathWidget.h
+++ b/Source/CursesDialog/cmCursesFilePathWidget.h
@@ -1,28 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesFilePathWidget_h
+#define cmCursesFilePathWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesFilePathWidget_h
-#define __cmCursesFilePathWidget_h
+#include "cmConfigure.h"
#include "cmCursesPathWidget.h"
class cmCursesFilePathWidget : public cmCursesPathWidget
{
+ CM_DISABLE_COPY(cmCursesFilePathWidget)
+
public:
cmCursesFilePathWidget(int width, int height, int left, int top);
-
-protected:
- cmCursesFilePathWidget(const cmCursesFilePathWidget& from);
- void operator=(const cmCursesFilePathWidget&);
-
};
-#endif // __cmCursesFilePathWidget_h
+#endif // cmCursesFilePathWidget_h
diff --git a/Source/CursesDialog/cmCursesForm.cxx b/Source/CursesDialog/cmCursesForm.cxx
index 72ae5eef7..06c1e9c70 100644
--- a/Source/CursesDialog/cmCursesForm.cxx
+++ b/Source/CursesDialog/cmCursesForm.cxx
@@ -1,32 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesForm.h"
-std::ofstream cmCursesForm::DebugFile;
+cmsys::ofstream cmCursesForm::DebugFile;
bool cmCursesForm::Debug = false;
cmCursesForm::cmCursesForm()
{
- this->Form = 0;
+ this->Form = CM_NULLPTR;
}
cmCursesForm::~cmCursesForm()
{
- if (this->Form)
- {
+ if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = 0;
- }
+ this->Form = CM_NULLPTR;
+ }
}
void cmCursesForm::DebugStart()
@@ -37,10 +27,9 @@ void cmCursesForm::DebugStart()
void cmCursesForm::DebugEnd()
{
- if (!cmCursesForm::Debug)
- {
+ if (!cmCursesForm::Debug) {
return;
- }
+ }
cmCursesForm::Debug = false;
cmCursesForm::DebugFile.close();
@@ -48,10 +37,9 @@ void cmCursesForm::DebugEnd()
void cmCursesForm::LogMessage(const char* msg)
{
- if (!cmCursesForm::Debug)
- {
+ if (!cmCursesForm::Debug) {
return;
- }
+ }
cmCursesForm::DebugFile << msg << std::endl;
}
diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h
index 3cba856ab..553105c76 100644
--- a/Source/CursesDialog/cmCursesForm.h
+++ b/Source/CursesDialog/cmCursesForm.h
@@ -1,22 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesForm_h
+#define cmCursesForm_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesForm_h
-#define __cmCursesForm_h
-
-#include "../cmStandardIncludes.h"
#include "cmCursesStandardIncludes.h"
+#include "cmsys/FStream.hxx"
+
class cmCursesForm
{
+ CM_DISABLE_COPY(cmCursesForm)
+
public:
cmCursesForm();
virtual ~cmCursesForm();
@@ -53,23 +49,15 @@ public:
// Description:
// Return the FORM. Should be only used by low-level methods.
- FORM* GetForm()
- {
- return this->Form;
- }
+ FORM* GetForm() { return this->Form; }
static cmCursesForm* CurrentForm;
-
protected:
-
- static std::ofstream DebugFile;
+ static cmsys::ofstream DebugFile;
static bool Debug;
- cmCursesForm(const cmCursesForm& form);
- void operator=(const cmCursesForm&);
-
FORM* Form;
};
-#endif // __cmCursesForm_h
+#endif // cmCursesForm_h
diff --git a/Source/CursesDialog/cmCursesLabelWidget.cxx b/Source/CursesDialog/cmCursesLabelWidget.cxx
index b5ed3128c..1dfd4ce47 100644
--- a/Source/CursesDialog/cmCursesLabelWidget.cxx
+++ b/Source/CursesDialog/cmCursesLabelWidget.cxx
@@ -1,32 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesLabelWidget.h"
-cmCursesLabelWidget::cmCursesLabelWidget(int width, int height,
- int left, int top,
- const std::string& name) :
- cmCursesWidget(width, height, left, top)
+#include "cmCursesWidget.h"
+
+cmCursesLabelWidget::cmCursesLabelWidget(int width, int height, int left,
+ int top, const std::string& name)
+ : cmCursesWidget(width, height, left, top)
{
- field_opts_off(this->Field, O_EDIT);
- field_opts_off(this->Field, O_ACTIVE);
- field_opts_off(this->Field, O_STATIC);
- this->SetValue(name.c_str());
+ field_opts_off(this->Field, O_EDIT);
+ field_opts_off(this->Field, O_ACTIVE);
+ field_opts_off(this->Field, O_STATIC);
+ this->SetValue(name);
}
cmCursesLabelWidget::~cmCursesLabelWidget()
{
}
-bool cmCursesLabelWidget::HandleInput(int&, cmCursesMainForm*, WINDOW* )
+bool cmCursesLabelWidget::HandleInput(int& /*key*/, cmCursesMainForm* /*fm*/,
+ WINDOW* /*w*/)
{
// Static text. No input is handled here.
return false;
diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h
index cc32d11ea..267de7c8c 100644
--- a/Source/CursesDialog/cmCursesLabelWidget.h
+++ b/Source/CursesDialog/cmCursesLabelWidget.h
@@ -1,38 +1,31 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesLabelWidget_h
+#define cmCursesLabelWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesLabelWidget_h
-#define __cmCursesLabelWidget_h
-
-#include "cmCursesWidget.h"
#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);
- virtual ~cmCursesLabelWidget();
+ ~cmCursesLabelWidget() CM_OVERRIDE;
// Description:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled
- virtual bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w);
-
-protected:
- cmCursesLabelWidget(const cmCursesLabelWidget& from);
- void operator=(const cmCursesLabelWidget&);
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
};
-#endif // __cmCursesLabelWidget_h
+#endif // cmCursesLabelWidget_h
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index 057f8f3d8..7fb065d30 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -1,207 +1,178 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "../cmCacheManager.h"
-#include "../cmSystemTools.h"
-#include "../cmake.h"
-#include "../cmVersion.h"
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesLongMessageForm.h"
+
+#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);
+ return (z & 037);
}
-cmCursesLongMessageForm::cmCursesLongMessageForm(std::vector<std::string>
- const& messages, const char*
- title)
+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++)
- {
+ for (it = messages.begin(); it != messages.end(); it++) {
this->Messages += (*it);
// Add one blank line after each message
this->Messages += "\n\n";
- }
+ }
this->Title = title;
- this->Fields[0] = 0;
- this->Fields[1] = 0;
+ this->Fields[0] = CM_NULLPTR;
+ this->Fields[1] = CM_NULLPTR;
}
cmCursesLongMessageForm::~cmCursesLongMessageForm()
{
- if (this->Fields[0])
- {
+ if (this->Fields[0]) {
free_field(this->Fields[0]);
- }
+ }
}
-
void cmCursesLongMessageForm::UpdateStatusBar()
{
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
char bar[cmCursesMainForm::MAX_WIDTH];
size_t size = strlen(this->Title.c_str());
- if ( size >= cmCursesMainForm::MAX_WIDTH )
- {
- size = cmCursesMainForm::MAX_WIDTH-1;
- }
+ if (size >= cmCursesMainForm::MAX_WIDTH) {
+ size = cmCursesMainForm::MAX_WIDTH - 1;
+ }
strncpy(bar, this->Title.c_str(), size);
- for(size_t i=size-1; i<cmCursesMainForm::MAX_WIDTH; i++) bar[i] = ' ';
-
+ for (size_t i = size - 1; i < cmCursesMainForm::MAX_WIDTH; i++) {
+ bar[i] = ' ';
+ }
int width;
- if (x < cmCursesMainForm::MAX_WIDTH )
- {
+ if (x < cmCursesMainForm::MAX_WIDTH) {
width = x;
- }
- else
- {
- width = cmCursesMainForm::MAX_WIDTH-1;
- }
+ } else {
+ width = cmCursesMainForm::MAX_WIDTH - 1;
+ }
bar[width] = '\0';
char version[cmCursesMainForm::MAX_WIDTH];
char vertmp[128];
- sprintf(vertmp,"CMake Version %s", cmVersion::GetCMakeVersion());
- size_t sideSpace = (width-strlen(vertmp));
- for(size_t i=0; i<sideSpace; i++) { version[i] = ' '; }
- sprintf(version+sideSpace, "%s", vertmp);
+ sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion());
+ size_t sideSpace = (width - strlen(vertmp));
+ for (size_t i = 0; i < sideSpace; i++) {
+ version[i] = ' ';
+ }
+ sprintf(version + sideSpace, "%s", vertmp);
version[width] = '\0';
- curses_move(y-4,0);
+ char fmt_s[] = "%s";
+ curses_move(y - 4, 0);
attron(A_STANDOUT);
- printw(bar);
+ printw(fmt_s, bar);
attroff(A_STANDOUT);
- curses_move(y-3,0);
- printw(version);
+ curses_move(y - 3, 0);
+ printw(fmt_s, version);
pos_form_cursor(this->Form);
}
void cmCursesLongMessageForm::PrintKeys()
{
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
return;
- }
+ }
char firstLine[512];
- sprintf(firstLine, "Press [e] to exit help");
+ sprintf(firstLine, "Press [e] to exit help");
- curses_move(y-2,0);
- printw(firstLine);
+ char fmt_s[] = "%s";
+ curses_move(y - 2, 0);
+ printw(fmt_s, firstLine);
pos_form_cursor(this->Form);
-
}
-void cmCursesLongMessageForm::Render(int, int, int, int)
+void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
+ int /*height*/)
{
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
- if (this->Form)
- {
+ if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = 0;
- }
+ this->Form = CM_NULLPTR;
+ }
const char* msg = this->Messages.c_str();
curses_clear();
- if (this->Fields[0])
- {
+ if (this->Fields[0]) {
free_field(this->Fields[0]);
- this->Fields[0] = 0;
- }
+ this->Fields[0] = CM_NULLPTR;
+ }
- this->Fields[0] = new_field(y-6, x-2, 1, 1, 0, 0);
+ this->Fields[0] = new_field(y - 6, x - 2, 1, 1, 0, 0);
- field_opts_off(this->Fields[0], O_STATIC);
+ field_opts_off(this->Fields[0], O_STATIC);
this->Form = new_form(this->Fields);
post_form(this->Form);
- int i=0;
+ int i = 0;
form_driver(this->Form, REQ_BEG_FIELD);
- while(msg[i] != '\0' && i < 60000)
- {
- if (msg[i] == '\n' && msg[i+1] != '\0')
- {
+ while (msg[i] != '\0' && i < 60000) {
+ if (msg[i] == '\n' && msg[i + 1] != '\0') {
form_driver(this->Form, REQ_NEW_LINE);
- }
- else
- {
+ } else {
form_driver(this->Form, msg[i]);
- }
- i++;
}
+ i++;
+ }
form_driver(this->Form, REQ_BEG_FIELD);
this->UpdateStatusBar();
this->PrintKeys();
touchwin(stdscr);
refresh();
-
}
void cmCursesLongMessageForm::HandleInput()
{
- if (!this->Form)
- {
+ if (!this->Form) {
return;
- }
+ }
char debugMessage[128];
- for(;;)
- {
+ for (;;) {
int key = getch();
sprintf(debugMessage, "Message widget handling input, key: %d", key);
cmCursesForm::LogMessage(debugMessage);
// quit
- if ( key == 'o' || key == 'e' )
- {
+ if (key == 'o' || key == 'e') {
break;
- }
- else if ( key == KEY_DOWN || key == ctrl('n') )
- {
+ }
+ if (key == KEY_DOWN || key == ctrl('n')) {
form_driver(this->Form, REQ_SCR_FLINE);
- }
- else if ( key == KEY_UP || key == ctrl('p') )
- {
+ } else if (key == KEY_UP || key == ctrl('p')) {
form_driver(this->Form, REQ_SCR_BLINE);
- }
- else if ( key == KEY_NPAGE || key == ctrl('d') )
- {
+ } else if (key == KEY_NPAGE || key == ctrl('d')) {
form_driver(this->Form, REQ_SCR_FPAGE);
- }
- else if ( key == KEY_PPAGE || key == ctrl('u') )
- {
+ } else if (key == KEY_PPAGE || key == ctrl('u')) {
form_driver(this->Form, REQ_SCR_BPAGE);
- }
+ }
this->UpdateStatusBar();
this->PrintKeys();
touchwin(stdscr);
wrefresh(stdscr);
- }
-
+ }
}
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h
index 1e86974f2..cd8e0953a 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.h
+++ b/Source/CursesDialog/cmCursesLongMessageForm.h
@@ -1,38 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesLongMessageForm_h
+#define cmCursesLongMessageForm_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesLongMessageForm_h
-#define __cmCursesLongMessageForm_h
-
-#include "../cmStandardIncludes.h"
#include "cmCursesForm.h"
#include "cmCursesStandardIncludes.h"
-class cmCursesCacheEntryComposite;
+#include <string>
+#include <vector>
class cmCursesLongMessageForm : public cmCursesForm
{
+ CM_DISABLE_COPY(cmCursesLongMessageForm)
+
public:
cmCursesLongMessageForm(std::vector<std::string> const& messages,
const char* title);
- virtual ~cmCursesLongMessageForm();
+ ~cmCursesLongMessageForm() CM_OVERRIDE;
// Description:
// Handle user input.
- virtual void HandleInput();
+ void HandleInput() CM_OVERRIDE;
// Description:
// Display form. Use a window of size width x height, starting
// at top, left.
- virtual void Render(int left, int top, int width, int height);
+ void Render(int left, int top, int width, int height) CM_OVERRIDE;
// Description:
// This method should normally called only by the form.
@@ -42,17 +37,13 @@ public:
// Description:
// This method should normally called only by the form.
// The only exception is during a resize.
- virtual void UpdateStatusBar();
+ void UpdateStatusBar() CM_OVERRIDE;
protected:
- cmCursesLongMessageForm(const cmCursesLongMessageForm& from);
- void operator=(const cmCursesLongMessageForm&);
-
std::string Messages;
std::string Title;
FIELD* Fields[2];
-
};
-#endif // __cmCursesLongMessageForm_h
+#endif // cmCursesLongMessageForm_h
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 4fee0bbd3..026320a1f 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -1,56 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "../cmCacheManager.h"
-#include "../cmSystemTools.h"
-#include "../cmVersion.h"
-#include "../cmake.h"
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesMainForm.h"
-#include "cmCursesStringWidget.h"
-#include "cmCursesLabelWidget.h"
-#include "cmCursesBoolWidget.h"
-#include "cmCursesPathWidget.h"
-#include "cmCursesFilePathWidget.h"
-#include "cmCursesDummyWidget.h"
+
+#include "cmAlgorithms.h"
#include "cmCursesCacheEntryComposite.h"
+#include "cmCursesDummyWidget.h"
+#include "cmCursesForm.h"
+#include "cmCursesLabelWidget.h"
#include "cmCursesLongMessageForm.h"
+#include "cmCursesStandardIncludes.h"
+#include "cmCursesStringWidget.h"
+#include "cmCursesWidget.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+#include "cmake.h"
+#include <stdio.h>
+#include <string.h>
inline int ctrl(int z)
{
- return (z&037);
+ return (z & 037);
}
cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args,
- int initWidth) :
- Args(args), InitialWidth(initWidth)
+ int initWidth)
+ : Args(args)
+ , InitialWidth(initWidth)
{
this->NumberOfPages = 0;
- this->Fields = 0;
- this->Entries = 0;
+ this->Fields = CM_NULLPTR;
+ this->Entries = CM_NULLPTR;
this->AdvancedMode = false;
this->NumberOfVisibleEntries = 0;
this->OkToGenerate = false;
- this->HelpMessage.push_back("Welcome to ccmake, curses based user interface for CMake.");
+ this->HelpMessage.push_back(
+ "Welcome to ccmake, curses based user interface for CMake.");
this->HelpMessage.push_back("");
this->HelpMessage.push_back(s_ConstHelpMessage);
- this->CMakeInstance = new cmake;
- this->CMakeInstance->SetCMakeEditCommand("ccmake");
+ this->CMakeInstance = new cmake(cmake::RoleProject);
+ this->CMakeInstance->SetCMakeEditCommand(
+ cmSystemTools::GetCMakeCursesCommand());
// create the arguments for the cmake object
- std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0].c_str());
+ std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0]);
whereCMake += "/cmake";
this->Args[0] = whereCMake;
this->CMakeInstance->SetArgs(this->Args);
- this->CMakeInstance->SetCMakeCommand(whereCMake.c_str());
this->SearchString = "";
this->OldSearchString = "";
this->SearchMode = false;
@@ -58,47 +56,37 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args,
cmCursesMainForm::~cmCursesMainForm()
{
- if (this->Form)
- {
+ if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = 0;
- }
+ this->Form = CM_NULLPTR;
+ }
delete[] this->Fields;
// Clean-up composites
- if (this->Entries)
- {
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
- delete *it;
- }
- }
+ if (this->Entries) {
+ cmDeleteAll(*this->Entries);
+ }
delete this->Entries;
- if (this->CMakeInstance)
- {
+ if (this->CMakeInstance) {
delete this->CMakeInstance;
- this->CMakeInstance = 0;
- }
+ this->CMakeInstance = CM_NULLPTR;
+ }
}
// See if a cache entry is in the list of entries in the ui.
-bool cmCursesMainForm::LookForCacheEntry(const char* key)
+bool cmCursesMainForm::LookForCacheEntry(const std::string& key)
{
- if (!key || !this->Entries)
- {
+ if (!this->Entries) {
return false;
- }
+ }
std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
- if (!strcmp(key, (*it)->Key.c_str()))
- {
+ for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ if (key == (*it)->Key) {
return true;
- }
}
+ }
return false;
}
@@ -110,91 +98,75 @@ void cmCursesMainForm::InitializeUI()
// which contain labels, entries and new entry markers
std::vector<cmCursesCacheEntryComposite*>* newEntries =
new std::vector<cmCursesCacheEntryComposite*>;
- newEntries->reserve(this->CMakeInstance->GetCacheManager()->GetSize());
+ std::vector<std::string> cacheKeys =
+ this->CMakeInstance->GetState()->GetCacheEntryKeys();
+ newEntries->reserve(cacheKeys.size());
// Count non-internal and non-static entries
- int count=0;
- for(cmCacheManager::CacheIterator i =
- this->CMakeInstance->GetCacheManager()->NewIterator();
- !i.IsAtEnd(); i.Next())
- {
- if ( i.GetType() != cmCacheManager::INTERNAL &&
- i.GetType() != cmCacheManager::STATIC &&
- i.GetType() != cmCacheManager::UNINITIALIZED)
- {
+ int count = 0;
+
+ for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
+ it != cacheKeys.end(); ++it) {
+ cmStateEnums::CacheEntryType t =
+ this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+ if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC &&
+ t != cmStateEnums::UNINITIALIZED) {
++count;
- }
}
+ }
int entrywidth = this->InitialWidth - 35;
cmCursesCacheEntryComposite* comp;
- if ( count == 0 )
- {
+ 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);
- }
- else
- {
+ } else {
// Create the composites.
// First add entries which are new
- for(cmCacheManager::CacheIterator i =
- this->CMakeInstance->GetCacheManager()->NewIterator();
- !i.IsAtEnd(); i.Next())
- {
- const char* key = i.GetName();
- if ( i.GetType() == cmCacheManager::INTERNAL ||
- i.GetType() == cmCacheManager::STATIC ||
- i.GetType() == cmCacheManager::UNINITIALIZED )
- {
+ for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
+ it != cacheKeys.end(); ++it) {
+ std::string key = *it;
+ cmStateEnums::CacheEntryType t =
+ this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+ if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
+ t == cmStateEnums::UNINITIALIZED) {
continue;
- }
+ }
- if (!this->LookForCacheEntry(key))
- {
- newEntries->push_back(new cmCursesCacheEntryComposite(key, i,
- true, 30,
- entrywidth));
+ if (!this->LookForCacheEntry(key)) {
+ newEntries->push_back(new cmCursesCacheEntryComposite(
+ key, this->CMakeInstance, true, 30, entrywidth));
this->OkToGenerate = false;
- }
}
+ }
// then add entries which are old
- for(cmCacheManager::CacheIterator i =
- this->CMakeInstance->GetCacheManager()->NewIterator();
- !i.IsAtEnd(); i.Next())
- {
- const char* key = i.GetName();
- if ( i.GetType() == cmCacheManager::INTERNAL ||
- i.GetType() == cmCacheManager::STATIC ||
- i.GetType() == cmCacheManager::UNINITIALIZED )
- {
+ for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
+ it != cacheKeys.end(); ++it) {
+ std::string key = *it;
+ cmStateEnums::CacheEntryType t =
+ this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+ if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
+ t == cmStateEnums::UNINITIALIZED) {
continue;
- }
+ }
- if (this->LookForCacheEntry(key))
- {
- newEntries->push_back(new cmCursesCacheEntryComposite(key, i,
- false, 30,
- entrywidth));
- }
+ if (this->LookForCacheEntry(key)) {
+ newEntries->push_back(new cmCursesCacheEntryComposite(
+ key, this->CMakeInstance, false, 30, entrywidth));
}
}
+ }
// Clean old entries
- if (this->Entries)
- {
- // Have to call delete on each pointer
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
- delete *it;
- }
- }
+ if (this->Entries) {
+ cmDeleteAll(*this->Entries);
+ }
delete this->Entries;
this->Entries = newEntries;
@@ -202,168 +174,151 @@ void cmCursesMainForm::InitializeUI()
this->RePost();
}
-
void cmCursesMainForm::RePost()
{
// Create the fields to be passed to the form.
- if (this->Form)
- {
+ if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = 0;
- }
+ this->Form = CM_NULLPTR;
+ }
delete[] this->Fields;
- if (this->AdvancedMode)
- {
+ if (this->AdvancedMode) {
this->NumberOfVisibleEntries = this->Entries->size();
- }
- else
- {
+ } 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)
- {
- cmCacheManager::CacheIterator mit =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
- if (mit.IsAtEnd() ||
- (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
- {
+ for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ const char* existingValue =
+ this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ bool advanced =
+ this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
+ (*it)->GetValue(), "ADVANCED");
+ if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
- }
- this->NumberOfVisibleEntries++;
}
+ this->NumberOfVisibleEntries++;
}
+ }
// there is always one even if it is the dummy one
- if(this->NumberOfVisibleEntries == 0)
- {
+ if (this->NumberOfVisibleEntries == 0) {
this->NumberOfVisibleEntries = 1;
- }
+ }
// Assign the fields: 3 for each entry: label, new entry marker
// ('*' or ' ') and entry widget
- this->Fields = new FIELD*[3*this->NumberOfVisibleEntries+1];
+ this->Fields = new FIELD*[3 * this->NumberOfVisibleEntries + 1];
size_t cc;
- for ( cc = 0; cc < 3 * this->NumberOfVisibleEntries+1; cc ++ )
- {
- this->Fields[cc] = 0;
- }
+ for (cc = 0; cc < 3 * this->NumberOfVisibleEntries + 1; cc++) {
+ this->Fields[cc] = CM_NULLPTR;
+ }
// Assign fields
- int j=0;
+ int j = 0;
std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
- cmCacheManager::CacheIterator mit =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
- if (mit.IsAtEnd() ||
- (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
- {
+ for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ const char* existingValue =
+ this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ bool advanced =
+ this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
+ (*it)->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[3 * j] = (*it)->Label->Field;
+ this->Fields[3 * j + 1] = (*it)->IsNewLabel->Field;
+ this->Fields[3 * j + 2] = (*it)->Entry->Field;
+ j++;
+ }
// if no cache entries there should still be one dummy field
- if(j == 0)
- {
+ 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;
+ this->Fields[0] = (*it)->Label->Field;
+ this->Fields[1] = (*it)->IsNewLabel->Field;
+ this->Fields[2] = (*it)->Entry->Field;
this->NumberOfVisibleEntries = 1;
- }
+ }
// Has to be null terminated.
- this->Fields[3*this->NumberOfVisibleEntries] = 0;
+ this->Fields[3 * this->NumberOfVisibleEntries] = CM_NULLPTR;
}
void cmCursesMainForm::Render(int left, int top, int width, int height)
{
- if (this->Form)
- {
+ if (this->Form) {
FIELD* currentField = current_field(this->Form);
- cmCursesWidget* cw = reinterpret_cast<cmCursesWidget*>
- (field_userptr(currentField));
+ cmCursesWidget* cw =
+ reinterpret_cast<cmCursesWidget*>(field_userptr(currentField));
// If in edit mode, get out of it
- if ( cw->GetType() == cmCacheManager::STRING ||
- cw->GetType() == cmCacheManager::PATH ||
- cw->GetType() == cmCacheManager::FILEPATH )
- {
+ if (cw->GetType() == cmStateEnums::STRING ||
+ cw->GetType() == cmStateEnums::PATH ||
+ cw->GetType() == cmStateEnums::FILEPATH) {
cmCursesStringWidget* sw = static_cast<cmCursesStringWidget*>(cw);
sw->SetInEdit(false);
- }
+ }
// Delete the previous form
unpost_form(this->Form);
free_form(this->Form);
- this->Form = 0;
- }
+ this->Form = CM_NULLPTR;
+ }
// Wrong window size
- if ( width < cmCursesMainForm::MIN_WIDTH ||
- width < this->InitialWidth ||
- height < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (width < cmCursesMainForm::MIN_WIDTH || width < this->InitialWidth ||
+ height < cmCursesMainForm::MIN_HEIGHT) {
return;
- }
+ }
// Leave room for toolbar
height -= 7;
- if (this->AdvancedMode)
- {
+ if (this->AdvancedMode) {
this->NumberOfVisibleEntries = this->Entries->size();
- }
- else
- {
+ } 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)
- {
- cmCacheManager::CacheIterator mit =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
- if (mit.IsAtEnd() ||
- (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
- {
+ for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ const char* existingValue =
+ this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ bool advanced =
+ this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
+ (*it)->GetValue(), "ADVANCED");
+ if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
- }
- this->NumberOfVisibleEntries++;
}
+ this->NumberOfVisibleEntries++;
}
+ }
// Re-adjust the fields according to their place
this->NumberOfPages = 1;
- if (height > 0)
- {
+ if (height > 0) {
bool isNewPage;
- int i=0;
+ int i = 0;
std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
- cmCacheManager::CacheIterator mit =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
- if (mit.IsAtEnd() ||
- (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
- {
+ for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ const char* existingValue =
+ this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ bool advanced =
+ this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
+ (*it)->GetValue(), "ADVANCED");
+ if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
- }
+ }
int row = (i % height) + 1;
int page = (i / height) + 1;
- isNewPage = ( page > 1 ) && ( row == 1 );
+ isNewPage = (page > 1) && (row == 1);
- if (isNewPage)
- {
+ 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)->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);
i++;
- }
}
+ }
// Post the form
this->Form = new_form(this->Fields);
@@ -378,151 +333,125 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
void cmCursesMainForm::PrintKeys(int process /* = 0 */)
{
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- x < this->InitialWidth ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || x < this->InitialWidth ||
+ y < cmCursesMainForm::MIN_HEIGHT) {
return;
- }
+ }
// Give the current widget (if it exists), a chance to print keys
- cmCursesWidget* cw = 0;
- if (this->Form)
- {
+ cmCursesWidget* cw = CM_NULLPTR;
+ if (this->Form) {
FIELD* currentField = current_field(this->Form);
cw = reinterpret_cast<cmCursesWidget*>(field_userptr(currentField));
- }
-
- if (cw)
- {
- cw->PrintKeys();
- }
-
-// {
-// }
-// else
-// {
- char firstLine[512]="";
- char secondLine[512]="";
- char thirdLine[512]="";
- if (process)
- {
- const char* clearLine =
- " ";
- strcpy(firstLine, clearLine);
- strcpy(secondLine, clearLine);
- strcpy(thirdLine, clearLine);
- }
- else
- {
- if (this->OkToGenerate)
- {
- sprintf(firstLine,
- "Press [c] to configure Press [g] to generate and exit");
+ }
+
+ char fmt_s[] = "%s";
+ if (cw == CM_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);
+ } else {
+ if (this->OkToGenerate) {
+ sprintf(firstLine,
+ "Press [c] to configure Press [g] to generate and exit");
+ } else {
+ sprintf(firstLine,
+ "Press [c] to configure ");
}
- else
{
- sprintf(firstLine, "Press [c] to configure ");
+ const char* toggleKeyInstruction =
+ "Press [t] to toggle advanced mode (Currently %s)";
+ sprintf(thirdLine, toggleKeyInstruction,
+ this->AdvancedMode ? "On" : "Off");
}
- {
- const char* toggleKeyInstruction =
- "Press [t] to toggle advanced mode (Currently %s)";
- 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";
- if ( process )
- {
- strcpy(fmt, " ");
- }
- printw(fmt);
- curses_move(y-3,0);
- printw(firstLine);
- curses_move(y-2,0);
- printw(secondLine);
- curses_move(y-1,0);
- printw(thirdLine);
-
- if (cw)
- {
- sprintf(firstLine, "Page %d of %d", cw->GetPage(), this->NumberOfPages);
- curses_move(0,65-static_cast<unsigned int>(strlen(firstLine))-1);
- printw(firstLine);
+ curses_move(y - 4, 0);
+ char fmt[512] =
+ "Press [enter] to edit option Press [d] to delete an entry";
+ if (process) {
+ strcpy(fmt, " ");
}
-// }
+ printw(fmt_s, fmt);
+ curses_move(y - 3, 0);
+ printw(fmt_s, firstLine);
+ curses_move(y - 2, 0);
+ printw(fmt_s, secondLine);
+ curses_move(y - 1, 0);
+ printw(fmt_s, thirdLine);
+ }
+
+ if (cw) {
+ char pageLine[512] = "";
+ sprintf(pageLine, "Page %d of %d", cw->GetPage(), this->NumberOfPages);
+ curses_move(0, 65 - static_cast<unsigned int>(strlen(pageLine)) - 1);
+ printw(fmt_s, pageLine);
+ }
pos_form_cursor(this->Form);
-
}
// Print the key of the current entry and the CMake version
// on the status bar. Designed for a width of 80 chars.
void cmCursesMainForm::UpdateStatusBar(const char* message)
{
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
// If window size is too small, display error and return
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- x < this->InitialWidth ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || x < this->InitialWidth ||
+ y < cmCursesMainForm::MIN_HEIGHT) {
curses_clear();
- curses_move(0,0);
+ 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);
return;
- }
+ }
// Get the key of the current entry
FIELD* cur = current_field(this->Form);
int findex = field_index(cur);
- cmCursesWidget* lbl = 0;
- if ( findex >= 0 )
- {
- lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(this->Fields[findex-2]));
- }
+ cmCursesWidget* lbl = CM_NULLPTR;
+ if (findex >= 0) {
+ lbl = reinterpret_cast<cmCursesWidget*>(
+ field_userptr(this->Fields[findex - 2]));
+ }
char help[128] = "";
const char* curField = "";
- if ( lbl )
- {
+ if (lbl) {
curField = lbl->GetValue();
// Get the help string of the current entry
// and add it to the help string
- cmCacheManager::CacheIterator it =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator(curField);
- if (!it.IsAtEnd())
- {
- const char* hs = it.GetProperty("HELPSTRING");
- if ( hs )
- {
+ const char* existingValue =
+ this->CMakeInstance->GetState()->GetCacheEntryValue(curField);
+ if (existingValue) {
+ const char* hs = this->CMakeInstance->GetState()->GetCacheEntryProperty(
+ curField, "HELPSTRING");
+ if (hs) {
strncpy(help, hs, 127);
help[127] = '\0';
- }
- else
- {
+ } else {
help[0] = 0;
- }
- }
- else
- {
- sprintf(help," ");
}
+ } else {
+ sprintf(help, " ");
}
+ }
// Join the key, help string and pad with spaces
// (or truncate) as necessary
@@ -531,125 +460,104 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
size_t helpLen = strlen(help);
size_t width;
- if (x < cmCursesMainForm::MAX_WIDTH )
- {
+ if (x < cmCursesMainForm::MAX_WIDTH) {
width = x;
- }
- else
- {
+ } else {
width = cmCursesMainForm::MAX_WIDTH;
- }
+ }
- if ( message )
- {
+ if (message) {
curField = message;
curFieldLen = strlen(message);
- if ( curFieldLen < width )
- {
+ if (curFieldLen < width) {
strcpy(bar, curField);
- for(i=curFieldLen; i < width; ++i)
- {
+ for (i = curFieldLen; i < width; ++i) {
bar[i] = ' ';
- }
}
- else
- {
+ } else {
strncpy(bar, curField, width);
- }
- }
- else
- {
- if (curFieldLen >= width)
- {
+ }
+ } else {
+ if (curFieldLen >= width) {
strncpy(bar, curField, width);
- }
- else
- {
+ } else {
strcpy(bar, curField);
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[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] = ' ';
- }
}
}
}
-
+ }
bar[width] = '\0';
-
// Display CMake version info on the next line
// We want to display this on the right
char version[cmCursesMainForm::MAX_WIDTH];
char vertmp[128];
- sprintf(vertmp,"CMake Version %s", cmVersion::GetCMakeVersion());
- size_t sideSpace = (width-strlen(vertmp));
- for(i=0; i<sideSpace; i++) { version[i] = ' '; }
- sprintf(version+sideSpace, "%s", vertmp);
+ sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion());
+ size_t sideSpace = (width - strlen(vertmp));
+ for (i = 0; i < sideSpace; i++) {
+ version[i] = ' ';
+ }
+ sprintf(version + sideSpace, "%s", vertmp);
version[width] = '\0';
// Now print both lines
- curses_move(y-5,0);
+ char fmt_s[] = "%s";
+ curses_move(y - 5, 0);
attron(A_STANDOUT);
- char format[] = "%s";
- printw(format, bar);
+ printw(fmt_s, bar);
attroff(A_STANDOUT);
- curses_move(y-4,0);
- printw(version);
+ curses_move(y - 4, 0);
+ printw(fmt_s, version);
pos_form_cursor(this->Form);
}
-void cmCursesMainForm::UpdateProgress(const char *msg, float prog, void* vp)
+void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp)
{
cmCursesMainForm* cm = static_cast<cmCursesMainForm*>(vp);
- if ( !cm )
- {
+ if (!cm) {
return;
- }
+ }
char tmp[1024];
- const char *cmsg = tmp;
- if ( prog >= 0 )
- {
- sprintf(tmp, "%s %i%%",msg,(int)(100*prog));
- }
- else
- {
+ const char* cmsg = tmp;
+ if (prog >= 0) {
+ sprintf(tmp, "%s %i%%", msg, (int)(100 * prog));
+ } else {
cmsg = msg;
- }
+ }
cm->UpdateStatusBar(cmsg);
cm->PrintKeys(1);
- curses_move(1,1);
+ curses_move(1, 1);
touchwin(stdscr);
refresh();
}
int cmCursesMainForm::Configure(int noconfigure)
{
- int xi,yi;
+ int xi, yi;
getmaxyx(stdscr, yi, xi);
- curses_move(1,1);
+ curses_move(1, 1);
this->UpdateStatusBar("Configuring, please wait...");
this->PrintKeys(1);
touchwin(stdscr);
refresh();
- this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, this);
+ this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress,
+ this);
// always save the current gui values to disk
this->FillCacheManagerFromUI();
- this->CMakeInstance->GetCacheManager()->SaveCache(
+ this->CMakeInstance->SaveCache(
this->CMakeInstance->GetHomeOutputDirectory());
- this->LoadCache(0);
+ this->LoadCache(CM_NULLPTR);
// Get rid of previous errors
this->Errors = std::vector<std::string>();
@@ -657,52 +565,43 @@ int cmCursesMainForm::Configure(int noconfigure)
// run the generate process
this->OkToGenerate = true;
int retVal;
- if ( noconfigure )
- {
+ if (noconfigure) {
retVal = this->CMakeInstance->DoPreConfigureChecks();
this->OkToGenerate = false;
- if ( retVal > 0 )
- {
+ if (retVal > 0) {
retVal = 0;
- }
}
- else
- {
+ } else {
retVal = this->CMakeInstance->Configure();
- }
- this->CMakeInstance->SetProgressCallback(0, 0);
+ }
+ this->CMakeInstance->SetProgressCallback(CM_NULLPTR, CM_NULLPTR);
- keypad(stdscr,TRUE); /* Use key symbols as
- KEY_DOWN*/
+ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
- if( retVal != 0 || !this->Errors.empty())
- {
+ if (retVal != 0 || !this->Errors.empty()) {
// see if there was an error
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
this->OkToGenerate = false;
- }
- int xx,yy;
+ }
+ int xx, yy;
getmaxyx(stdscr, yy, xx);
cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(
- this->Errors,
- cmSystemTools::GetErrorOccuredFlag()
- ? "Errors occurred during the last pass." :
- "CMake produced the following output.");
+ this->Errors, cmSystemTools::GetErrorOccuredFlag()
+ ? "Errors occurred during the last pass."
+ : "CMake produced the following output.");
// reset error condition
cmSystemTools::ResetErrorOccuredFlag();
CurrentForm = msgs;
- msgs->Render(1,1,xx,yy);
+ msgs->Render(1, 1, xx, yy);
msgs->HandleInput();
// If they typed the wrong source directory, we report
// an error and exit
- if ( retVal == -2 )
- {
+ if (retVal == -2) {
return retVal;
- }
- CurrentForm = this;
- this->Render(1,1,xx,yy);
}
+ CurrentForm = this;
+ this->Render(1, 1, xx, yy);
+ }
this->InitializeUI();
this->Render(1, 1, xi, yi);
@@ -712,15 +611,16 @@ int cmCursesMainForm::Configure(int noconfigure)
int cmCursesMainForm::Generate()
{
- int xi,yi;
+ int xi, yi;
getmaxyx(stdscr, yi, xi);
- curses_move(1,1);
+ curses_move(1, 1);
this->UpdateStatusBar("Generating, please wait...");
this->PrintKeys(1);
touchwin(stdscr);
refresh();
- this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, this);
+ this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress,
+ this);
// Get rid of previous errors
this->Errors = std::vector<std::string>();
@@ -728,40 +628,35 @@ int cmCursesMainForm::Generate()
// run the generate process
int retVal = this->CMakeInstance->Generate();
- this->CMakeInstance->SetProgressCallback(0, 0);
- keypad(stdscr,TRUE); /* Use key symbols as
- KEY_DOWN*/
+ this->CMakeInstance->SetProgressCallback(CM_NULLPTR, CM_NULLPTR);
+ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
- if( retVal != 0 || !this->Errors.empty())
- {
+ if (retVal != 0 || !this->Errors.empty()) {
// see if there was an error
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
this->OkToGenerate = false;
- }
+ }
// reset error condition
cmSystemTools::ResetErrorOccuredFlag();
- int xx,yy;
+ int xx, yy;
getmaxyx(stdscr, yy, xx);
const char* title = "Messages during last pass.";
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
title = "Errors occurred during the last pass.";
- }
- cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->Errors,
- title);
+ }
+ cmCursesLongMessageForm* msgs =
+ new cmCursesLongMessageForm(this->Errors, title);
CurrentForm = msgs;
- msgs->Render(1,1,xx,yy);
+ msgs->Render(1, 1, xx, yy);
msgs->HandleInput();
// If they typed the wrong source directory, we report
// an error and exit
- if ( retVal == -2 )
- {
+ if (retVal == -2) {
return retVal;
- }
- CurrentForm = this;
- this->Render(1,1,xx,yy);
}
+ CurrentForm = this;
+ this->Render(1, 1, xx, yy);
+ }
this->InitializeUI();
this->Render(1, 1, xi, yi);
@@ -769,345 +664,293 @@ int cmCursesMainForm::Generate()
return 0;
}
-void cmCursesMainForm::AddError(const char* message, const char*)
+void cmCursesMainForm::AddError(const char* message, const char* /*unused*/)
{
this->Errors.push_back(message);
}
void cmCursesMainForm::RemoveEntry(const char* value)
{
- if (!value)
- {
+ if (!value) {
return;
- }
+ }
std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
+ for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
const char* val = (*it)->GetValue();
- if ( val && !strcmp(value, val) )
- {
+ if (val && !strcmp(value, val)) {
this->CMakeInstance->UnwatchUnusedCli(value);
this->Entries->erase(it);
break;
- }
}
+ }
}
// 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++)
- {
- cmCacheManager::CacheIterator it =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator(
- (*this->Entries)[i]->Key.c_str());
- if (!it.IsAtEnd())
- {
- std::string oldValue = it.GetValue();
+ for (size_t i = 0; i < size; i++) {
+ std::string cacheKey = (*this->Entries)[i]->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 fixedOldValue;
std::string fixedNewValue;
- this->FixValue(it.GetType(), oldValue, fixedOldValue);
- this->FixValue(it.GetType(), newValue, fixedNewValue);
+ cmStateEnums::CacheEntryType t =
+ this->CMakeInstance->GetState()->GetCacheEntryType(cacheKey);
+ this->FixValue(t, oldValue, fixedOldValue);
+ this->FixValue(t, newValue, fixedNewValue);
- if(!(fixedOldValue == fixedNewValue))
- {
+ if (!(fixedOldValue == fixedNewValue)) {
// The user has changed the value. Mark it as modified.
- it.SetProperty("MODIFIED", true);
- it.SetValue(fixedNewValue.c_str());
- }
+ this->CMakeInstance->GetState()->SetCacheEntryBoolProperty(
+ cacheKey, "MODIFIED", true);
+ this->CMakeInstance->GetState()->SetCacheEntryValue(cacheKey,
+ fixedNewValue);
}
}
+ }
}
-void cmCursesMainForm::FixValue(cmCacheManager::CacheEntryType type,
+void cmCursesMainForm::FixValue(cmStateEnums::CacheEntryType type,
const std::string& in, std::string& out) const
{
- out = in.substr(0,in.find_last_not_of(" ")+1);
- if(type == cmCacheManager::PATH || type == cmCacheManager::FILEPATH)
- {
+ out = in.substr(0, in.find_last_not_of(' ') + 1);
+ if (type == cmStateEnums::PATH || type == cmStateEnums::FILEPATH) {
cmSystemTools::ConvertToUnixSlashes(out);
- }
- if(type == cmCacheManager::BOOL)
- {
- if(cmSystemTools::IsOff(out.c_str()))
- {
+ }
+ if (type == cmStateEnums::BOOL) {
+ if (cmSystemTools::IsOff(out.c_str())) {
out = "OFF";
- }
- else
- {
+ } else {
out = "ON";
- }
}
+ }
}
-#include <unistd.h>
-
void cmCursesMainForm::HandleInput()
{
- int x=0,y=0;
+ int x = 0, y = 0;
- if (!this->Form)
- {
+ if (!this->Form) {
return;
- }
+ }
FIELD* currentField;
cmCursesWidget* currentWidget;
char debugMessage[128];
- for(;;)
- {
+ for (;;) {
this->UpdateStatusBar();
this->PrintKeys();
- if ( this->SearchMode )
- {
+ if (this->SearchMode) {
std::string searchstr = "Search: " + this->SearchString;
- this->UpdateStatusBar( searchstr.c_str() );
+ this->UpdateStatusBar(searchstr.c_str());
this->PrintKeys(1);
- curses_move(y-5,static_cast<unsigned int>(searchstr.size()));
- //curses_move(1,1);
+ curses_move(y - 5, static_cast<unsigned int>(searchstr.size()));
+ // curses_move(1,1);
touchwin(stdscr);
refresh();
- }
+ }
int key = getch();
getmaxyx(stdscr, y, x);
// If window too small, handle 'q' only
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
// quit
- if ( key == 'q' )
- {
+ if (key == 'q') {
break;
- }
- else
- {
- continue;
- }
}
+ continue;
+ }
currentField = current_field(this->Form);
- currentWidget = reinterpret_cast<cmCursesWidget*>(field_userptr(
- currentField));
+ currentWidget =
+ reinterpret_cast<cmCursesWidget*>(field_userptr(currentField));
- bool widgetHandled=false;
+ bool widgetHandled = false;
- if ( this->SearchMode )
- {
- if ( key == 10 || key == KEY_ENTER )
- {
+ if (this->SearchMode) {
+ if (key == 10 || key == KEY_ENTER) {
this->SearchMode = false;
- if ( this->SearchString.size() > 0 )
- {
+ if (!this->SearchString.empty()) {
this->JumpToCacheEntry(this->SearchString.c_str());
this->OldSearchString = this->SearchString;
- }
- this->SearchString = "";
}
+ this->SearchString = "";
+ }
/*
else if ( key == KEY_ESCAPE )
{
this->SearchMode = false;
}
*/
- else if ((key >= 'a' && key <= 'z') ||
- (key >= 'A' && key <= 'Z') ||
- (key >= '0' && key <= '9') ||
- (key == '_' ))
- {
- if ( this->SearchString.size() < static_cast<std::string::size_type>(x-10) )
- {
+ else if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') ||
+ (key >= '0' && key <= '9') || (key == '_')) {
+ if (this->SearchString.size() <
+ static_cast<std::string::size_type>(x - 10)) {
this->SearchString += static_cast<char>(key);
- }
}
- else if ( key == ctrl('h') || key == KEY_BACKSPACE || key == KEY_DC )
- {
- if ( this->SearchString.size() > 0 )
- {
- this->SearchString.resize(this->SearchString.size()-1);
- }
+ } else if (key == ctrl('h') || key == KEY_BACKSPACE || key == KEY_DC) {
+ if (!this->SearchString.empty()) {
+ this->SearchString.resize(this->SearchString.size() - 1);
}
}
- else if (currentWidget && !this->SearchMode)
- {
+ } else if (currentWidget && !this->SearchMode) {
// Ask the current widget if it wants to handle input
widgetHandled = currentWidget->HandleInput(key, this, stdscr);
- if (widgetHandled)
- {
+ if (widgetHandled) {
this->OkToGenerate = false;
this->UpdateStatusBar();
this->PrintKeys();
- }
}
- if ((!currentWidget || !widgetHandled) && !this->SearchMode)
- {
+ }
+ if ((!currentWidget || !widgetHandled) && !this->SearchMode) {
// If the current widget does not want to handle input,
// we handle it.
sprintf(debugMessage, "Main form handling input, key: %d", key);
cmCursesForm::LogMessage(debugMessage);
// quit
- if ( key == 'q' )
- {
+ if (key == 'q') {
break;
- }
+ }
// if not end of page, next field otherwise next page
// each entry consists of fields: label, isnew, value
// therefore, the label field for the prev. entry is index-5
// and the label field for the next entry is index+1
// (index always corresponds to the value field)
- else if ( key == KEY_DOWN || key == ctrl('n') )
- {
+ // scroll down with arrow down, ctrl+n (emacs binding), or j (vim
+ // binding)
+ if (key == KEY_DOWN || key == ctrl('n') || key == 'j') {
FIELD* cur = current_field(this->Form);
size_t findex = field_index(cur);
- if ( findex == 3*this->NumberOfVisibleEntries-1 )
- {
+ if (findex == 3 * this->NumberOfVisibleEntries - 1) {
continue;
- }
- if (new_page(this->Fields[findex+1]))
- {
+ }
+ if (new_page(this->Fields[findex + 1])) {
form_driver(this->Form, REQ_NEXT_PAGE);
- }
- else
- {
+ } else {
form_driver(this->Form, REQ_NEXT_FIELD);
- }
}
+ }
// if not beginning of page, previous field, otherwise previous page
// each entry consists of fields: label, isnew, value
// therefore, the label field for the prev. entry is index-5
// and the label field for the next entry is index+1
// (index always corresponds to the value field)
- else if ( key == KEY_UP || key == ctrl('p') )
- {
+ // scroll down with arrow up, ctrl+p (emacs binding), or k (vim binding)
+ else if (key == KEY_UP || key == ctrl('p') || key == 'k') {
FIELD* cur = current_field(this->Form);
int findex = field_index(cur);
- if ( findex == 2 )
- {
+ if (findex == 2) {
continue;
- }
- if ( new_page(this->Fields[findex-2]) )
- {
+ }
+ if (new_page(this->Fields[findex - 2])) {
form_driver(this->Form, REQ_PREV_PAGE);
- set_current_field(this->Form, this->Fields[findex-3]);
- }
- else
- {
+ set_current_field(this->Form, this->Fields[findex - 3]);
+ } else {
form_driver(this->Form, REQ_PREV_FIELD);
- }
}
+ }
// pg down
- else if ( key == KEY_NPAGE || key == ctrl('d') )
- {
+ else if (key == KEY_NPAGE || key == ctrl('d')) {
form_driver(this->Form, REQ_NEXT_PAGE);
- }
+ }
// pg up
- else if ( key == KEY_PPAGE || key == ctrl('u') )
- {
+ else if (key == KEY_PPAGE || key == ctrl('u')) {
form_driver(this->Form, REQ_PREV_PAGE);
- }
+ }
// configure
- else if ( key == 'c' )
- {
+ else if (key == 'c') {
this->Configure();
- }
+ }
// display help
- else if ( key == 'h' )
- {
+ else if (key == 'h') {
getmaxyx(stdscr, y, x);
FIELD* cur = current_field(this->Form);
int findex = field_index(cur);
- cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(
- this->Fields[findex-2]));
+ cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(
+ field_userptr(this->Fields[findex - 2]));
const char* curField = lbl->GetValue();
- const char* helpString=0;
- cmCacheManager::CacheIterator it =
- this->CMakeInstance->GetCacheManager()->GetCacheIterator(curField);
- if (!it.IsAtEnd())
- {
- helpString = it.GetProperty("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);
+ const char* helpString = CM_NULLPTR;
+
+ const char* existingValue =
+ this->CMakeInstance->GetState()->GetCacheEntryValue(curField);
+ if (existingValue) {
+ helpString = this->CMakeInstance->GetState()->GetCacheEntryProperty(
+ 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;
- }
- else
- {
+ } else {
this->HelpMessage[1] = "";
- }
+ }
- cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->HelpMessage,
- "Help.");
+ cmCursesLongMessageForm* msgs =
+ new cmCursesLongMessageForm(this->HelpMessage, "Help.");
CurrentForm = msgs;
- msgs->Render(1,1,x,y);
+ msgs->Render(1, 1, x, y);
msgs->HandleInput();
CurrentForm = this;
- this->Render(1,1,x,y);
+ this->Render(1, 1, x, y);
set_current_field(this->Form, cur);
- }
+ }
// display last errors
- else if ( key == 'l' )
- {
+ else if (key == 'l') {
getmaxyx(stdscr, y, x);
- cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->Errors,
- "Errors occurred during the last pass.");
+ cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(
+ this->Errors, "Errors occurred during the last pass.");
CurrentForm = msgs;
- msgs->Render(1,1,x,y);
+ msgs->Render(1, 1, x, y);
msgs->HandleInput();
CurrentForm = this;
- this->Render(1,1,x,y);
- }
- else if ( key == '/' )
- {
+ this->Render(1, 1, x, y);
+ } else if (key == '/') {
this->SearchMode = true;
this->UpdateStatusBar("Search");
this->PrintKeys(1);
touchwin(stdscr);
refresh();
- }
- else if ( key == 'n' )
- {
- if ( this->OldSearchString.size() > 0 )
- {
+ } else if (key == 'n') {
+ if (!this->OldSearchString.empty()) {
this->JumpToCacheEntry(this->OldSearchString.c_str());
- }
}
+ }
// switch advanced on/off
- else if ( key == 't' )
- {
- if (this->AdvancedMode)
- {
+ else if (key == 't') {
+ if (this->AdvancedMode) {
this->AdvancedMode = false;
- }
- else
- {
+ } else {
this->AdvancedMode = true;
- }
+ }
getmaxyx(stdscr, y, x);
this->RePost();
this->Render(1, 1, x, y);
- }
+ }
// generate and exit
- else if ( key == 'g' )
- {
- if ( this->OkToGenerate )
- {
+ else if (key == 'g') {
+ if (this->OkToGenerate) {
this->Generate();
break;
- }
}
+ }
// delete cache entry
- else if ( key == 'd' && this->NumberOfVisibleEntries )
- {
+ else if (key == 'd' && this->NumberOfVisibleEntries) {
this->OkToGenerate = false;
FIELD* cur = current_field(this->Form);
size_t findex = field_index(cur);
@@ -1118,76 +961,66 @@ void cmCursesMainForm::HandleInput()
// and the label field for the next entry is findex+1
// (findex always corresponds to the value field)
FIELD* nextCur;
- if ( findex == 2 )
- {
- nextCur=0;
- }
- else if ( findex == 3*this->NumberOfVisibleEntries-1 )
- {
- nextCur = this->Fields[findex-5];
- }
- else
- {
- nextCur = this->Fields[findex+1];
- }
+ if (findex == 2) {
+ nextCur = CM_NULLPTR;
+ } else if (findex == 3 * this->NumberOfVisibleEntries - 1) {
+ nextCur = this->Fields[findex - 5];
+ } else {
+ nextCur = this->Fields[findex + 1];
+ }
// Get the label widget
// each entry consists of fields: label, isnew, value
// therefore, the label field for the is findex-2
// (findex always corresponds to the value field)
- cmCursesWidget* lbl
- = reinterpret_cast<cmCursesWidget*>(
- field_userptr(this->Fields[findex-2]));
- if ( lbl )
- {
- this->CMakeInstance->GetCacheManager()->RemoveCacheEntry(lbl->GetValue());
+ cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(
+ field_userptr(this->Fields[findex - 2]));
+ if (lbl) {
+ this->CMakeInstance->GetState()->RemoveCacheEntry(lbl->GetValue());
std::string nextVal;
- if (nextCur)
- {
- nextVal = (reinterpret_cast<cmCursesWidget*>(field_userptr(nextCur))->GetValue());
- }
+ if (nextCur) {
+ nextVal =
+ (reinterpret_cast<cmCursesWidget*>(field_userptr(nextCur))
+ ->GetValue());
+ }
getmaxyx(stdscr, y, x);
this->RemoveEntry(lbl->GetValue());
this->RePost();
this->Render(1, 1, x, y);
- if (nextCur)
- {
+ if (nextCur) {
// make the next or prev. current field after deletion
- nextCur = 0;
+ nextCur = CM_NULLPTR;
std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
- {
- if (nextVal == (*it)->Key)
- {
+ for (it = this->Entries->begin(); it != this->Entries->end();
+ ++it) {
+ if (nextVal == (*it)->Key) {
nextCur = (*it)->Entry->Field;
- }
}
+ }
- if (nextCur)
- {
+ if (nextCur) {
set_current_field(this->Form, nextCur);
- }
}
}
}
}
+ }
touchwin(stdscr);
wrefresh(stdscr);
- }
+ }
}
-int cmCursesMainForm::LoadCache(const char *)
+int cmCursesMainForm::LoadCache(const char* /*unused*/)
{
int r = this->CMakeInstance->LoadCache();
- if(r < 0)
- {
+ if (r < 0) {
return r;
- }
+ }
this->CMakeInstance->SetCacheArgs(this->Args);
this->CMakeInstance->PreLoadCMakeFiles();
return r;
@@ -1196,55 +1029,44 @@ int cmCursesMainForm::LoadCache(const char *)
void cmCursesMainForm::JumpToCacheEntry(const char* astr)
{
std::string str;
- if ( astr )
- {
+ if (astr) {
str = cmSystemTools::LowerCase(astr);
- }
+ }
- if(str.empty())
- {
+ if (str.empty()) {
return;
- }
+ }
FIELD* cur = current_field(this->Form);
int start_index = field_index(cur);
int findex = start_index;
- for(;;)
- {
- if ( str.size() > 0 )
- {
- cmCursesWidget* lbl = 0;
- if ( findex >= 0 )
- {
- lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(this->Fields[findex-2]));
- }
- if ( lbl )
- {
+ for (;;) {
+ if (!str.empty()) {
+ cmCursesWidget* lbl = CM_NULLPTR;
+ if (findex >= 0) {
+ lbl = reinterpret_cast<cmCursesWidget*>(
+ field_userptr(this->Fields[findex - 2]));
+ }
+ if (lbl) {
const char* curField = lbl->GetValue();
- if ( curField )
- {
+ if (curField) {
std::string cfld = cmSystemTools::LowerCase(curField);
- if ( cfld.find(str) != cfld.npos && findex != start_index )
- {
+ if (cfld.find(str) != std::string::npos && findex != start_index) {
break;
- }
}
}
}
- if ( size_t(findex) >= 3* this->NumberOfVisibleEntries-1 )
- {
+ }
+ if (size_t(findex) >= 3 * this->NumberOfVisibleEntries - 1) {
set_current_field(this->Form, this->Fields[2]);
- }
- else if (new_page(this->Fields[findex+1]))
- {
+ } else if (new_page(this->Fields[findex + 1])) {
form_driver(this->Form, REQ_NEXT_PAGE);
- }
- else
- {
+ } else {
form_driver(this->Form, REQ_NEXT_FIELD);
- }
+ }
/*
char buffer[1024];
- sprintf(buffer, "Line: %d != %d / %d\n", findex, idx, this->NumberOfVisibleEntries);
+ sprintf(buffer, "Line: %d != %d / %d\n", findex, idx,
+ this->NumberOfVisibleEntries);
touchwin(stdscr);
refresh();
this->UpdateStatusBar( buffer );
@@ -1252,52 +1074,71 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr)
*/
cur = current_field(this->Form);
findex = field_index(cur);
- if ( findex == start_index )
- {
+ if (findex == start_index) {
break;
- }
}
+ }
}
-
const char* cmCursesMainForm::s_ConstHelpMessage =
-"CMake is used to configure and generate build files for software projects. "
-"The basic steps for configuring a project with ccmake are as follows:\n\n"
-"1. Run ccmake in the directory where you want the object and executable files to be placed (build directory). If the source directory is not the same as this build directory, you have to specify it as an argument on the command line.\n\n"
-"2. When ccmake is run, it will read the configuration files and display the current build options. "
-"If you have run CMake before and have updated the configuration files since then, any new entries will be displayed on top and will be marked with a *. "
-"On the other hand, the first time you run ccmake, all build options will be new and will be marked as such. "
-"At this point, you can modify any options (see keys below) you want to change. "
-"When you are satisfied with your changes, press 'c' to have CMake process the configuration files. "
-"Please note that changing some options may cause new ones to appear. These will be shown on top and will be marked with *. "
-"Repeat this procedure until you are satisfied with all the options and there are no new entries. "
-"At this point, a new command will appear: G)enerate and Exit. You can now hit 'g' to have CMake generate all the build files (i.e. makefiles or project files) and exit. "
-"At any point during the process, you can exit ccmake with 'q'. However, this will not generate/change any build files.\n\n"
-"ccmake KEYS:\n\n"
-"Navigation: "
-"You can use the arrow keys and page up, down to navigate the options. Alternatively, you can use the following keys: \n"
-" C-n : next option\n"
-" C-p : previous options\n"
-" C-d : down one page\n"
-" C-u : up one page\n\n"
-"Editing options: "
-"To change an option press enter or return. If the current options is a boolean, this will toggle it's value. "
-"Otherwise, ccmake will enter edit mode. In this mode you can edit an option using arrow keys and backspace. Alternatively, you can use the following keys:\n"
-" C-b : back one character\n"
-" C-f : forward one character\n"
-" C-a : go to the beginning of the field\n"
-" C-e : go to the end of the field\n"
-" C-d : delete previous character\n"
-" C-k : kill the rest of the field\n"
-" Esc : Restore field (discard last changes)\n"
-" Enter : Leave edit mode\n"
-"You can also delete an option by pressing 'd'\n\n"
-"Commands:\n"
-" q : quit ccmake without generating build files\n"
-" h : help, shows this screen\n"
-" c : process the configuration files with the current options\n"
-" g : generate build files and exit, only available when there are no "
-"new options and no errors have been detected during last configuration.\n"
-" l : shows last errors\n"
-" t : toggles advanced mode. In normal mode, only the most important options are shown. In advanced mode, all options are shown. We recommend using normal mode unless you are an expert.\n"
-" / : search for a variable name.\n";
+ "CMake is used to configure and generate build files for software projects. "
+ "The basic steps for configuring a project with ccmake are as follows:\n\n"
+ "1. Run ccmake in the directory where you want the object and executable "
+ "files to be placed (build directory). If the source directory is not the "
+ "same as this build directory, you have to specify it as an argument on the "
+ "command line.\n\n"
+ "2. When ccmake is run, it will read the configuration files and display "
+ "the current build options. "
+ "If you have run CMake before and have updated the configuration files "
+ "since then, any new entries will be displayed on top and will be marked "
+ "with a *. "
+ "On the other hand, the first time you run ccmake, all build options will "
+ "be new and will be marked as such. "
+ "At this point, you can modify any options (see keys below) you want to "
+ "change. "
+ "When you are satisfied with your changes, press 'c' to have CMake process "
+ "the configuration files. "
+ "Please note that changing some options may cause new ones to appear. These "
+ "will be shown on top and will be marked with *. "
+ "Repeat this procedure until you are satisfied with all the options and "
+ "there are no new entries. "
+ "At this point, a new command will appear: G)enerate and Exit. You can now "
+ "hit 'g' to have CMake generate all the build files (i.e. makefiles or "
+ "project files) and exit. "
+ "At any point during the process, you can exit ccmake with 'q'. However, "
+ "this will not generate/change any build files.\n\n"
+ "ccmake KEYS:\n\n"
+ "Navigation: "
+ "You can use the arrow keys and page up, down to navigate the options. "
+ "Alternatively, you can use the following keys: \n"
+ " C-n or j : next option\n"
+ " C-p or k : previous options\n"
+ " C-d : down one page\n"
+ " C-u : up one page\n\n"
+ "Editing options: "
+ "To change an option press enter or return. If the current options is a "
+ "boolean, this will toggle its value. "
+ "Otherwise, ccmake will enter edit mode. Alternatively, you can toggle "
+ "a bool variable by pressing space, and enter edit mode with i."
+ "In this mode you can edit an option using arrow keys and backspace. "
+ "Alternatively, you can use the following keys:\n"
+ " C-b : back one character\n"
+ " C-f : forward one character\n"
+ " C-a : go to the beginning of the field\n"
+ " C-e : go to the end of the field\n"
+ " C-d : delete previous character\n"
+ " C-k : kill the rest of the field\n"
+ " Esc : Restore field (discard last changes)\n"
+ " Enter : Leave edit mode\n"
+ "Commands:\n"
+ " q : quit ccmake without generating build files\n"
+ " h : help, shows this screen\n"
+ " c : process the configuration files with the current options\n"
+ " g : generate build files and exit, only available when there are no "
+ "new options and no errors have been detected during last configuration.\n"
+ " l : shows last errors\n"
+ " d : delete an option\n"
+ " t : toggles advanced mode. In normal mode, only the most important "
+ "options are shown. In advanced mode, all options are shown. We recommend "
+ "using normal mode unless you are an expert.\n"
+ " / : search for a variable name.\n";
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index 883a2b3d6..e35cf3ed7 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -1,23 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesMainForm_h
+#define cmCursesMainForm_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesMainForm_h
-#define __cmCursesMainForm_h
-
-#include "../cmStandardIncludes.h"
#include "cmCursesForm.h"
#include "cmCursesStandardIncludes.h"
+#include "cmStateTypes.h"
+
+#include <stddef.h>
+#include <string>
+#include <vector>
class cmCursesCacheEntryComposite;
-class cmCursesWidget;
class cmake;
/** \class cmCursesMainForm
@@ -27,9 +23,11 @@ class cmake;
*/
class cmCursesMainForm : public cmCursesForm
{
+ CM_DISABLE_COPY(cmCursesMainForm)
+
public:
cmCursesMainForm(std::vector<std::string> const& args, int initwidth);
- virtual ~cmCursesMainForm();
+ ~cmCursesMainForm() CM_OVERRIDE;
/**
* Set the widgets which represent the cache entries.
@@ -39,21 +37,22 @@ public:
/**
* Handle user input.
*/
- virtual void HandleInput();
+ void HandleInput() CM_OVERRIDE;
/**
* Display form. Use a window of size width x height, starting
* at top, left.
*/
- virtual void Render(int left, int top, int width, int height);
+ void Render(int left, int top, int width, int height) CM_OVERRIDE;
/**
* Returns true if an entry with the given key is in the
* list of current composites.
*/
- bool LookForCacheEntry(const char* key);
+ bool LookForCacheEntry(const std::string& key);
- enum {
+ enum
+ {
MIN_WIDTH = 65,
MIN_HEIGHT = 6,
IDEAL_WIDTH = 80,
@@ -65,7 +64,7 @@ public:
* exception is during a resize. The optional argument specifies the
* string to be displayed in the status bar.
*/
- virtual void UpdateStatusBar() { this->UpdateStatusBar(0); }
+ void UpdateStatusBar() CM_OVERRIDE { this->UpdateStatusBar(CM_NULLPTR); }
virtual void UpdateStatusBar(const char* message);
/**
@@ -81,13 +80,13 @@ public:
* During a CMake run, an error handle should add errors
* to be displayed afterwards.
*/
- virtual void AddError(const char* message, const char* title);
+ void AddError(const char* message, const char* title) CM_OVERRIDE;
/**
* Used to do a configure. If argument is specified, it does only the check
* and not configure.
*/
- int Configure(int noconfigure=0);
+ int Configure(int noconfigure = 0);
/**
* Used to generate
@@ -97,24 +96,21 @@ public:
/**
* Used by main program
*/
- int LoadCache(const char *dir);
+ int LoadCache(const char* dir);
/**
* Progress callback
*/
- static void UpdateProgressOld(const char *msg, float prog, void*);
- static void UpdateProgress(const char *msg, float prog, void*);
+ static void UpdateProgressOld(const char* msg, float prog, void*);
+ static void UpdateProgress(const char* msg, float prog, void*);
protected:
- cmCursesMainForm(const cmCursesMainForm& from);
- void operator=(const cmCursesMainForm&);
-
// Copy the cache values from the user interface to the actual
// cache.
void FillCacheManagerFromUI();
// Fix formatting of values to a consistent form.
- void FixValue(cmCacheManager::CacheEntryType type,
- const std::string& in, std::string& out) const;
+ void FixValue(cmStateEnums::CacheEntryType type, const std::string& in,
+ std::string& out) const;
// Re-post the existing fields. Used to toggle between
// normal and advanced modes. Render() should be called
// afterwards.
@@ -154,11 +150,11 @@ protected:
int NumberOfPages;
int InitialWidth;
- cmake *CMakeInstance;
+ cmake* CMakeInstance;
std::string SearchString;
std::string OldSearchString;
bool SearchMode;
};
-#endif // __cmCursesMainForm_h
+#endif // cmCursesMainForm_h
diff --git a/Source/CursesDialog/cmCursesOptionsWidget.cxx b/Source/CursesDialog/cmCursesOptionsWidget.cxx
new file mode 100644
index 000000000..d26a98f86
--- /dev/null
+++ b/Source/CursesDialog/cmCursesOptionsWidget.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 "cmCursesOptionsWidget.h"
+
+#include "cmCursesWidget.h"
+#include "cmStateTypes.h"
+
+#define ctrl(z) ((z)&037)
+
+cmCursesOptionsWidget::cmCursesOptionsWidget(int width, int height, int left,
+ int top)
+ : cmCursesWidget(width, height, left, top)
+{
+ this->Type = cmStateEnums::BOOL; // this is a bit of a hack
+ // there is no option type, and string type causes ccmake to cast
+ // the widget into a string widget at some point. BOOL is safe for
+ // now.
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ field_opts_off(this->Field, O_STATIC);
+}
+
+bool cmCursesOptionsWidget::HandleInput(int& key, cmCursesMainForm* /*fm*/,
+ WINDOW* w)
+{
+ switch (key) {
+ case 10: // 10 == enter
+ case KEY_ENTER:
+ this->NextOption();
+ touchwin(w);
+ wrefresh(w);
+ return true;
+ case KEY_LEFT:
+ case ctrl('b'):
+ touchwin(w);
+ wrefresh(w);
+ this->PreviousOption();
+ return true;
+ case KEY_RIGHT:
+ case ctrl('f'):
+ this->NextOption();
+ touchwin(w);
+ wrefresh(w);
+ return true;
+ default:
+ return false;
+ }
+}
+
+void cmCursesOptionsWidget::AddOption(std::string const& option)
+{
+ this->Options.push_back(option);
+}
+
+void cmCursesOptionsWidget::NextOption()
+{
+ this->CurrentOption++;
+ if (this->CurrentOption > this->Options.size() - 1) {
+ this->CurrentOption = 0;
+ }
+ this->SetValue(this->Options[this->CurrentOption]);
+}
+void cmCursesOptionsWidget::PreviousOption()
+{
+ if (this->CurrentOption == 0) {
+ this->CurrentOption = this->Options.size() - 1;
+ } else {
+ this->CurrentOption--;
+ }
+ this->SetValue(this->Options[this->CurrentOption]);
+}
+
+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) {
+ this->CurrentOption = index;
+ }
+ index++;
+ }
+}
diff --git a/Source/CursesDialog/cmCursesOptionsWidget.h b/Source/CursesDialog/cmCursesOptionsWidget.h
new file mode 100644
index 000000000..7f4416f95
--- /dev/null
+++ b/Source/CursesDialog/cmCursesOptionsWidget.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesOptionsWidget_h
+#define cmCursesOptionsWidget_h
+
+#include "cmConfigure.h"
+
+#include "cmCursesStandardIncludes.h"
+#include "cmCursesWidget.h"
+
+#include <string>
+#include <vector>
+
+class cmCursesMainForm;
+
+class cmCursesOptionsWidget : public cmCursesWidget
+{
+ CM_DISABLE_COPY(cmCursesOptionsWidget)
+
+public:
+ cmCursesOptionsWidget(int width, int height, int left, int top);
+
+ // 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;
+ void SetOption(const std::string&);
+ void AddOption(std::string const&);
+ void NextOption();
+ void PreviousOption();
+
+protected:
+ std::vector<std::string> Options;
+ std::vector<std::string>::size_type CurrentOption;
+};
+
+#endif // cmCursesOptionsWidget_h
diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx
index 14c325bcb..05c3279c3 100644
--- a/Source/CursesDialog/cmCursesPathWidget.cxx
+++ b/Source/CursesDialog/cmCursesPathWidget.cxx
@@ -1,24 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesPathWidget.h"
#include "cmCursesMainForm.h"
+#include "cmCursesStringWidget.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-cmCursesPathWidget::cmCursesPathWidget(int width, int height,
- int left, int top) :
- cmCursesStringWidget(width, height, left, top)
+#include <vector>
+
+cmCursesPathWidget::cmCursesPathWidget(int width, int height, int left,
+ int top)
+ : cmCursesStringWidget(width, height, left, top)
{
- this->Type = cmCacheManager::PATH;
+ this->Type = cmStateEnums::PATH;
this->Cycle = false;
this->CurrentIndex = 0;
}
@@ -33,59 +28,51 @@ void cmCursesPathWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW* w)
void cmCursesPathWidget::OnTab(cmCursesMainForm* fm, WINDOW* w)
{
- if ( !this->GetString() )
- {
+ if (!this->GetString()) {
return;
- }
+ }
FORM* form = fm->GetForm();
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
std::string cstr = this->GetString();
- cstr = cstr.substr(0, cstr.find_last_not_of(" \t\n\r")+1);
- if ( this->LastString != cstr )
- {
+ cstr = cstr.substr(0, cstr.find_last_not_of(" \t\n\r") + 1);
+ if (this->LastString != cstr) {
this->Cycle = false;
this->CurrentIndex = 0;
this->LastGlob = "";
- }
+ }
std::string glob;
- if ( this->Cycle )
- {
+ if (this->Cycle) {
glob = this->LastGlob;
- }
- else
- {
+ } else {
glob = cstr + "*";
- }
- std::vector<cmStdString> dirs;
+ }
+ std::vector<std::string> dirs;
- cmSystemTools::SimpleGlob(glob.c_str(), dirs, (this->Type == cmCacheManager::PATH?-1:0));
- if ( this->CurrentIndex < dirs.size() )
- {
+ cmSystemTools::SimpleGlob(glob, dirs,
+ (this->Type == cmStateEnums::PATH ? -1 : 0));
+ if (this->CurrentIndex < dirs.size()) {
cstr = dirs[this->CurrentIndex];
- }
- if ( cstr[cstr.size()-1] == '*' )
- {
- cstr = cstr.substr(0, cstr.size()-1);
- }
+ }
+ if (cstr[cstr.size() - 1] == '*') {
+ cstr = cstr.substr(0, cstr.size() - 1);
+ }
- if ( cmSystemTools::FileIsDirectory(cstr.c_str()) )
- {
+ if (cmSystemTools::FileIsDirectory(cstr)) {
cstr += "/";
- }
+ }
- this->SetString(cstr.c_str());
+ this->SetString(cstr);
touchwin(w);
wrefresh(w);
form_driver(form, REQ_END_FIELD);
this->LastGlob = glob;
this->LastString = cstr;
this->Cycle = true;
- this->CurrentIndex ++;
- if ( this->CurrentIndex >= dirs.size() )
- {
+ this->CurrentIndex++;
+ if (this->CurrentIndex >= dirs.size()) {
this->CurrentIndex = 0;
- }
+ }
}
void cmCursesPathWidget::OnReturn(cmCursesMainForm* fm, WINDOW* w)
diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h
index 45c22a392..ae6c16d02 100644
--- a/Source/CursesDialog/cmCursesPathWidget.h
+++ b/Source/CursesDialog/cmCursesPathWidget.h
@@ -1,21 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesPathWidget_h
+#define cmCursesPathWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesPathWidget_h
-#define __cmCursesPathWidget_h
+#include "cmConfigure.h"
+#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);
@@ -23,18 +23,15 @@ public:
* This method is called when different keys are pressed. The
* subclass can have a special implementation handler for this.
*/
- virtual void OnTab(cmCursesMainForm* fm, WINDOW* w);
- virtual void OnReturn(cmCursesMainForm* fm, WINDOW* w);
- virtual void OnType(int& key, cmCursesMainForm* fm, WINDOW* w);
+ 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;
protected:
- cmCursesPathWidget(const cmCursesPathWidget& from);
- void operator=(const cmCursesPathWidget&);
-
std::string LastString;
std::string LastGlob;
bool Cycle;
std::string::size_type CurrentIndex;
};
-#endif // __cmCursesPathWidget_h
+#endif // cmCursesPathWidget_h
diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h
index b157a289b..5c5950483 100644
--- a/Source/CursesDialog/cmCursesStandardIncludes.h
+++ b/Source/CursesDialog/cmCursesStandardIncludes.h
@@ -1,72 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCursesStandardIncludes_h
#define cmCursesStandardIncludes_h
-#if defined(__sun__) && defined(__GNUC__)
- #define _MSE_INT_H
-#endif
-#include <cmFormConfigure.h>
+#include "cmConfigure.h"
#if defined(__hpux)
-# define _BOOL_DEFINED
-# include <sys/time.h>
-# define _XOPEN_SOURCE_EXTENDED
-# include <curses.h>
-# include <form.h>
-# undef _XOPEN_SOURCE_EXTENDED
-#else
-/* figure out which curses.h to include */
-# 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
-
-# include <form.h>
-#endif
-
-// This is a hack to prevent warnings about these functions being
-// declared but not referenced.
-#if defined(__sgi) && !defined(__GNUC__)
-class cmCursesStandardIncludesHack
-{
-public:
- enum
- {
- Ref1 = sizeof(cfgetospeed(0)),
- Ref2 = sizeof(cfgetispeed(0)),
- Ref3 = sizeof(tcgetattr(0, 0)),
- Ref4 = sizeof(tcsetattr(0, 0, 0)),
- Ref5 = sizeof(cfsetospeed(0,0)),
- Ref6 = sizeof(cfsetispeed(0,0))
- };
-};
-#endif
-
-#ifndef getmaxyx
- #define getmaxyx(w,y,x) ((y) = getmaxy(w), (x) = getmaxx(w))
+#define _BOOL_DEFINED
+#include <sys/time.h>
#endif
+#include <form.h>
// on some machines move erase and clear conflict with stl
// so remove them from the namespace
inline void curses_move(unsigned int x, unsigned int y)
{
- move(x,y);
+ move(x, y);
}
inline void curses_clear()
@@ -79,5 +29,4 @@ inline void curses_clear()
#undef erase
#undef clear
-
#endif // cmCursesStandardIncludes_h
diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index bd1ff71c6..ff189f01e 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -1,43 +1,42 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesStringWidget.h"
+
+#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);
+ return (z & 037);
}
-cmCursesStringWidget::cmCursesStringWidget(int width, int height,
- int left, int top) :
- cmCursesWidget(width, height, left, top)
+cmCursesStringWidget::cmCursesStringWidget(int width, int height, int left,
+ int top)
+ : cmCursesWidget(width, height, left, top)
{
this->InEdit = false;
- this->Type = cmCacheManager::STRING;
- set_field_fore(this->Field, A_NORMAL);
- set_field_back(this->Field, A_STANDOUT);
- field_opts_off(this->Field, O_STATIC);
+ this->Type = cmStateEnums::STRING;
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ field_opts_off(this->Field, O_STATIC);
}
-void cmCursesStringWidget::OnTab(cmCursesMainForm*, WINDOW*)
+void cmCursesStringWidget::OnTab(cmCursesMainForm* /*unused*/,
+ WINDOW* /*unused*/)
{
- //FORM* form = fm->GetForm();
+ // FORM* form = fm->GetForm();
}
-void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW*)
+void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
{
FORM* form = fm->GetForm();
- if (this->InEdit)
- {
+ if (this->InEdit) {
cmCursesForm::LogMessage("String widget leaving edit.");
this->InEdit = false;
fm->PrintKeys();
@@ -46,19 +45,18 @@ void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW*)
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
this->Done = true;
- }
- else
- {
+ } else {
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];
+ this->OriginalString = new char[strlen(buf) + 1];
strcpy(this->OriginalString, buf);
- }
+ }
}
-void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW*)
+void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm,
+ WINDOW* /*unused*/)
{
form_driver(fm->GetForm(), key);
}
@@ -66,23 +64,23 @@ void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW*)
bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
WINDOW* w)
{
- int x,y;
+ int x, y;
FORM* form = fm->GetForm();
+ // when not in edit mode, edit mode is entered by pressing enter or i (vim
+ // binding)
// 10 == enter
- if (!this->InEdit && ( key != 10 && key != KEY_ENTER ) )
- {
+ if (!this->InEdit && (key != 10 && key != KEY_ENTER && key != 'i')) {
return false;
- }
+ }
- this->OriginalString=0;
+ this->OriginalString = CM_NULLPTR;
this->Done = false;
char debugMessage[128];
// <Enter> is used to change edit mode (like <Esc> in vi).
- while(!this->Done)
- {
+ while (!this->Done) {
sprintf(debugMessage, "String widget handling input, key: %d", key);
cmCursesForm::LogMessage(debugMessage);
@@ -90,48 +88,39 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
getmaxyx(stdscr, y, x);
// If window too small, handle 'q' only
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
// quit
- if ( key == 'q' )
- {
+ if (key == 'q') {
return false;
- }
- else
- {
- key=getch();
- continue;
- }
}
+ key = getch();
+ continue;
+ }
- // If resize occured during edit, move out of edit mode
- if (!this->InEdit && ( key != 10 && key != KEY_ENTER ) )
- {
+ // If resize occurred during edit, move out of edit mode
+ if (!this->InEdit && (key != 10 && key != KEY_ENTER && key != 'i')) {
return false;
- }
- // 10 == enter
- if (key == 10 || key == KEY_ENTER)
- {
+ }
+ // enter edit with return and i (vim binding)
+ if (!this->InEdit && (key == 10 || key == KEY_ENTER || key == 'i')) {
this->OnReturn(fm, w);
- }
- else if ( key == KEY_DOWN || key == ctrl('n') ||
- key == KEY_UP || key == ctrl('p') ||
- key == KEY_NPAGE || key == ctrl('d') ||
- key == KEY_PPAGE || key == ctrl('u'))
- {
+ }
+ // leave edit with return (but not i -- not a toggle)
+ else if (this->InEdit && (key == 10 || key == KEY_ENTER)) {
+ this->OnReturn(fm, w);
+ } else if (key == KEY_DOWN || key == ctrl('n') || key == KEY_UP ||
+ key == ctrl('p') || key == KEY_NPAGE || key == ctrl('d') ||
+ key == KEY_PPAGE || key == ctrl('u')) {
this->InEdit = false;
delete[] this->OriginalString;
// trick to force forms to update the field buffer
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
return false;
- }
+ }
// esc
- else if (key == 27)
- {
- if (this->InEdit)
- {
+ else if (key == 27) {
+ if (this->InEdit) {
this->InEdit = false;
fm->PrintKeys();
this->SetString(this->OriginalString);
@@ -139,63 +128,41 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
touchwin(w);
wrefresh(w);
return true;
- }
}
- else if ( key == 9 )
- {
+ } else if (key == 9) {
this->OnTab(fm, w);
- }
- else if ( key == KEY_LEFT || key == ctrl('b') )
- {
+ } else if (key == KEY_LEFT || key == ctrl('b')) {
form_driver(form, REQ_PREV_CHAR);
- }
- else if ( key == KEY_RIGHT || key == ctrl('f') )
- {
+ } else if (key == KEY_RIGHT || key == ctrl('f')) {
form_driver(form, REQ_NEXT_CHAR);
- }
- else if ( key == ctrl('k') )
- {
+ } else if (key == ctrl('k')) {
form_driver(form, REQ_CLR_EOL);
- }
- else if ( key == ctrl('a') || key == KEY_HOME )
- {
+ } else if (key == ctrl('a') || key == KEY_HOME) {
form_driver(form, REQ_BEG_FIELD);
- }
- else if ( key == ctrl('e') || key == KEY_END )
- {
+ } else if (key == ctrl('e') || key == KEY_END) {
form_driver(form, REQ_END_FIELD);
- }
- else if ( key == 127 ||
- key == KEY_BACKSPACE )
- {
- if ( form->curcol > 0 )
- {
- form_driver(form, REQ_DEL_PREV);
- }
- }
- else if ( key == ctrl('d') ||key == KEY_DC )
- {
- if ( form->curcol >= 0 )
- {
- form_driver(form, REQ_DEL_CHAR);
- }
- }
- else
- {
+ } else if (key == 127 || key == KEY_BACKSPACE) {
+ FIELD* cur = current_field(form);
+ form_driver(form, REQ_DEL_PREV);
+ if (current_field(form) != cur) {
+ set_current_field(form, cur);
+ }
+ } else if (key == ctrl('d') || key == KEY_DC) {
+ form_driver(form, REQ_DEL_CHAR);
+ } else {
this->OnType(key, fm, w);
- }
- if ( !this->Done )
- {
+ }
+ if (!this->Done) {
touchwin(w);
wrefresh(w);
- key=getch();
- }
+ key = getch();
}
+ }
return true;
}
-void cmCursesStringWidget::SetString(const char* value)
+void cmCursesStringWidget::SetString(const std::string& value)
{
this->SetValue(value);
}
@@ -212,38 +179,33 @@ const char* cmCursesStringWidget::GetValue()
bool cmCursesStringWidget::PrintKeys()
{
- int x,y;
+ int x, y;
getmaxyx(stdscr, y, x);
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
+ if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
return false;
- }
- if (this->InEdit)
- {
+ }
+ if (this->InEdit) {
+ char fmt_s[] = "%s";
char firstLine[512];
// Clean the toolbar
- for(int i=0; i<512; i++)
- {
+ for (int i = 0; i < 512; i++) {
firstLine[i] = ' ';
- }
+ }
firstLine[511] = '\0';
- curses_move(y-4,0);
- printw(firstLine);
- curses_move(y-3,0);
- printw(firstLine);
- curses_move(y-2,0);
- printw(firstLine);
- curses_move(y-1,0);
- printw(firstLine);
-
- sprintf(firstLine, "Editing option, press [enter] to leave edit.");
- curses_move(y-3,0);
- printw(firstLine);
+ 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);
+
+ curses_move(y - 3, 0);
+ printw(fmt_s, "Editing option, press [enter] to confirm");
+ curses_move(y - 2, 0);
+ printw(fmt_s, " press [esc] to cancel");
return true;
- }
- else
- {
- return false;
- }
+ }
+ return false;
}
diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h
index e939049df..5eb33666d 100644
--- a/Source/CursesDialog/cmCursesStringWidget.h
+++ b/Source/CursesDialog/cmCursesStringWidget.h
@@ -1,19 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesStringWidget_h
+#define cmCursesStringWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesStringWidget_h
-#define __cmCursesStringWidget_h
+#include "cmConfigure.h"
+#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
+#include <string>
+
class cmCursesMainForm;
/** \class cmCursesStringWidget
@@ -24,6 +20,8 @@ class cmCursesMainForm;
class cmCursesStringWidget : public cmCursesWidget
{
+ CM_DISABLE_COPY(cmCursesStringWidget)
+
public:
cmCursesStringWidget(int width, int height, int left, int top);
@@ -32,14 +30,14 @@ public:
* when this widget has focus. Returns true if the input was
* handled.
*/
- virtual bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w);
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
/**
* Set/Get the string.
*/
- void SetString(const char* value);
+ void SetString(const std::string& value);
const char* GetString();
- virtual const char* GetValue();
+ const char* GetValue() CM_OVERRIDE;
/**
* Set/Get InEdit flag. Can be used to tell the widget to leave
@@ -61,16 +59,13 @@ public:
* in the toolbar and return true. Otherwise, return false
* and the parent widget will print.
*/
- virtual bool PrintKeys();
+ bool PrintKeys() CM_OVERRIDE;
protected:
- cmCursesStringWidget(const cmCursesStringWidget& from);
- void operator=(const cmCursesStringWidget&);
-
// true if the widget is in edit mode
bool InEdit;
char* OriginalString;
bool Done;
};
-#endif // __cmCursesStringWidget_h
+#endif // cmCursesStringWidget_h
diff --git a/Source/CursesDialog/cmCursesWidget.cxx b/Source/CursesDialog/cmCursesWidget.cxx
index 5dffcaa5c..054f27e29 100644
--- a/Source/CursesDialog/cmCursesWidget.cxx
+++ b/Source/CursesDialog/cmCursesWidget.cxx
@@ -1,55 +1,41 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesWidget.h"
cmCursesWidget::cmCursesWidget(int width, int height, int left, int top)
{
this->Field = new_field(height, width, top, left, 0, 0);
set_field_userptr(this->Field, reinterpret_cast<char*>(this));
- field_opts_off(this->Field, O_AUTOSKIP);
+ field_opts_off(this->Field, O_AUTOSKIP);
this->Page = 0;
}
cmCursesWidget::~cmCursesWidget()
{
- if (this->Field)
- {
+ if (this->Field) {
free_field(this->Field);
- this->Field = 0;
- }
+ this->Field = CM_NULLPTR;
+ }
}
void cmCursesWidget::Move(int x, int y, bool isNewPage)
{
- if (!this->Field)
- {
+ if (!this->Field) {
return;
- }
+ }
move_field(this->Field, y, x);
- if (isNewPage)
- {
- set_new_page(this->Field, TRUE);
- }
- else
- {
- set_new_page(this->Field, FALSE);
- }
+ if (isNewPage) {
+ set_new_page(this->Field, true);
+ } else {
+ set_new_page(this->Field, false);
+ }
}
-void cmCursesWidget::SetValue(const char* value)
+void cmCursesWidget::SetValue(const std::string& value)
{
this->Value = value;
- set_field_buffer(this->Field, 0, value);
+ set_field_buffer(this->Field, 0, const_cast<char*>(value.c_str()));
}
const char* cmCursesWidget::GetValue()
diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h
index 952c67a86..3470d7096 100644
--- a/Source/CursesDialog/cmCursesWidget.h
+++ b/Source/CursesDialog/cmCursesWidget.h
@@ -1,24 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesWidget_h
+#define cmCursesWidget_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef __cmCursesWidget_h
-#define __cmCursesWidget_h
-
-#include "../cmCacheManager.h"
#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();
@@ -40,48 +37,35 @@ public:
* Set/Get the value (setting the value also changes the contents
* of the field buffer).
*/
- virtual void SetValue(const char* value);
+ virtual void SetValue(const std::string& value);
virtual const char* GetValue();
/**
* Get the type of the widget (STRING, PATH etc...)
*/
- cmCacheManager::CacheEntryType GetType()
- { return this->Type; }
+ cmStateEnums::CacheEntryType GetType() { return this->Type; }
/**
* If there are any, print the widget specific commands
* in the toolbar and return true. Otherwise, return false
* and the parent widget will print.
*/
- virtual bool PrintKeys()
- {
- return false;
- }
+ virtual bool PrintKeys() { return false; }
/**
* Set/Get the page this widget is in.
*/
- void SetPage(int page)
- {
- this->Page = page;
- }
- int GetPage()
- {
- return this->Page;
- }
+ void SetPage(int page) { this->Page = page; }
+ int GetPage() { return this->Page; }
friend class cmCursesMainForm;
protected:
- cmCursesWidget(const cmCursesWidget& from);
- void operator=(const cmCursesWidget&);
-
- cmCacheManager::CacheEntryType Type;
+ cmStateEnums::CacheEntryType Type;
std::string Value;
FIELD* Field;
// The page in the main form this widget is in
int Page;
};
-#endif // __cmCursesWidget_h
+#endif // cmCursesWidget_h
diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes
new file mode 100644
index 000000000..62d728cf6
--- /dev/null
+++ b/Source/CursesDialog/form/.gitattributes
@@ -0,0 +1 @@
+* -format.clang-format
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index 4e07fa0ff..0677043a9 100644
--- a/Source/CursesDialog/form/CMakeLists.txt
+++ b/Source/CursesDialog/form/CMakeLists.txt
@@ -1,14 +1,6 @@
-#=============================================================================
-# CMake - Cross Platform Makefile Generator
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
project(CMAKE_FORM)
include_regular_expression("^.*$")
diff --git a/Source/CursesDialog/form/cmFormConfigure.h.in b/Source/CursesDialog/form/cmFormConfigure.h.in
index a43169d03..511c52516 100644
--- a/Source/CursesDialog/form/cmFormConfigure.h.in
+++ b/Source/CursesDialog/form/cmFormConfigure.h.in
@@ -1,15 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef CMFORMCONFIGURE_H
#define CMFORMCONFIGURE_H
diff --git a/Source/CursesDialog/form/fld_attr.c b/Source/CursesDialog/form/fld_attr.c
index 86195882b..35ea9033c 100644
--- a/Source/CursesDialog/form/fld_attr.c
+++ b/Source/CursesDialog/form/fld_attr.c
@@ -29,13 +29,7 @@
/****************************************************************************
* Author: Juergen Pfeifer <juergen.pfeifer@gmx.net> 1995,1997 *
****************************************************************************/
-#if defined(__hpux)
- #define _XOPEN_SOURCE_EXTENDED
-#endif
- #include "form.priv.h"
-#if defined(__hpux)
- #undef _XOPEN_SOURCE_EXTENDED
-#endif
+#include "form.priv.h"
MODULE_ID("$Id$")
/*----------------------------------------------------------------------------
diff --git a/Source/CursesDialog/form/fld_def.c b/Source/CursesDialog/form/fld_def.c
index 4a49a2558..00da3b4ef 100644
--- a/Source/CursesDialog/form/fld_def.c
+++ b/Source/CursesDialog/form/fld_def.c
@@ -73,7 +73,7 @@ FIELD *_nc_Default_Field = &default_field;
| int *err )
|
| Description : Create an argument structure for the specified type.
-| Use the type-dependant argument list to construct
+| Use the type-dependent argument list to construct
| it.
|
| Return Values : Pointer to argument structure. Maybe NULL.
@@ -193,7 +193,7 @@ _nc_Free_Argument(const FIELDTYPE * typ, TypeArgument * argp)
| Description : Copy argument structure of field src to field dst
|
| Return Values : TRUE - copy worked
-| FALSE - error occured
+| FALSE - error occurred
+--------------------------------------------------------------------------*/
bool
_nc_Copy_Type(FIELD *dst, FIELD const *src)
diff --git a/Source/CursesDialog/form/fld_ftlink.c b/Source/CursesDialog/form/fld_ftlink.c
index 1cb80d118..e98a4ca71 100644
--- a/Source/CursesDialog/form/fld_ftlink.c
+++ b/Source/CursesDialog/form/fld_ftlink.c
@@ -46,7 +46,7 @@ MODULE_ID("$Id$")
| E_BAD_ARGUMENT - invalid arguments
| E_SYSTEM_ERROR - system error (no memory)
|
-| Return Values : Fieldtype pointer or NULL if error occured.
+| Return Values : Fieldtype pointer or NULL if error occurred.
+--------------------------------------------------------------------------*/
FIELDTYPE *link_fieldtype(FIELDTYPE * type1, FIELDTYPE * type2)
{
diff --git a/Source/CursesDialog/form/fld_newftyp.c b/Source/CursesDialog/form/fld_newftyp.c
index b45ebd879..b839f1976 100644
--- a/Source/CursesDialog/form/fld_newftyp.c
+++ b/Source/CursesDialog/form/fld_newftyp.c
@@ -63,7 +63,7 @@ const FIELDTYPE* _nc_Default_FieldType = &default_fieldtype;
| E_BAD_ARGUMENT - invalid arguments
| E_SYSTEM_ERROR - system error (no memory)
|
-| Return Values : Fieldtype pointer or NULL if error occured
+| Return Values : Fieldtype pointer or NULL if error occurred
+--------------------------------------------------------------------------*/
FIELDTYPE *new_fieldtype(
bool (* const field_check)(FIELD *,const void *),
diff --git a/Source/CursesDialog/form/form.h b/Source/CursesDialog/form/form.h
index 94f05af8a..39ed75a7c 100644
--- a/Source/CursesDialog/form/form.h
+++ b/Source/CursesDialog/form/form.h
@@ -33,11 +33,7 @@
#ifndef FORM_H
#define FORM_H
-#if defined(__sun__) && defined(__GNUC__)
- #define _MSE_INT_H
-#endif
-
-#include <cmFormConfigure.h>
+#include "cmFormConfigure.h"
/* figure out which curses.h to include */
# if defined(CURSES_HAVE_NCURSES_H)
@@ -47,7 +43,17 @@
# elif defined(CURSES_HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
# else
+# if defined(__hpux)
+# if defined(_XOPEN_SOURCE_EXTENDED)
+# define HAVE__XOPEN_SOURCE_EXTENDED
+# else
+# define _XOPEN_SOURCE_EXTENDED
+# endif
+# endif
# include <curses.h>
+# if defined(__hpux) && !defined(HAVE__XOPEN_SOURCE_EXTENDED)
+# undef _XOPEN_SOURCE_EXTENDED
+# endif
# endif
#include <eti.h>
diff --git a/Source/CursesDialog/form/form.priv.h b/Source/CursesDialog/form/form.priv.h
index 3691f2fd0..6e00af6f3 100644
--- a/Source/CursesDialog/form/form.priv.h
+++ b/Source/CursesDialog/form/form.priv.h
@@ -33,12 +33,6 @@
#include "mf_common.h"
#include "form.h"
-/* get around odd bug on aCC and itanium */
-#if defined(__hpux) && defined(__ia64)
-#define getmaxx __getmaxx
-#define getmaxy __getmaxy
-#endif
-
/* form status values */
#define _OVLMODE (0x04) /* Form is in overlay mode */
#define _WINDOW_MODIFIED (0x10) /* Current field window has been modified */
@@ -46,7 +40,7 @@
/* field status values */
#define _CHANGED (0x01) /* Field has been changed */
-#define _NEWTOP (0x02) /* Vertical scrolling occured */
+#define _NEWTOP (0x02) /* Vertical scrolling occurred */
#define _NEWPAGE (0x04) /* field begins new page of form */
#define _MAY_GROW (0x08) /* dynamic field may still grow */
diff --git a/Source/CursesDialog/form/frm_def.c b/Source/CursesDialog/form/frm_def.c
index 0b28f5f0e..645b3baa8 100644
--- a/Source/CursesDialog/form/frm_def.c
+++ b/Source/CursesDialog/form/frm_def.c
@@ -240,7 +240,7 @@ static int Connect_Fields(FORM * form, FIELD ** fields)
| If there are fields, position to first active field.
|
| Return Values : E_OK - success
-| any other - error occured
+| any other - error occurred
+--------------------------------------------------------------------------*/
INLINE static int Associate_Fields(FORM *form, FIELD **fields)
{
@@ -267,7 +267,7 @@ INLINE static int Associate_Fields(FORM *form, FIELD **fields)
|
| Description : Create new form with given array of fields.
|
-| Return Values : Pointer to form. NULL if error occured.
+| Return Values : Pointer to form. NULL if error occurred.
+--------------------------------------------------------------------------*/
FORM *new_form(FIELD ** fields)
{
diff --git a/Source/CursesDialog/form/frm_driver.c b/Source/CursesDialog/form/frm_driver.c
index b9611bf10..e4e72aa9c 100644
--- a/Source/CursesDialog/form/frm_driver.c
+++ b/Source/CursesDialog/form/frm_driver.c
@@ -29,13 +29,7 @@
/****************************************************************************
* Author: Juergen Pfeifer <juergen.pfeifer@gmx.net> 1995,1997 *
****************************************************************************/
-#if defined(__hpux)
- #define _XOPEN_SOURCE_EXTENDED
-#endif
#include "form.priv.h"
-#if defined(__hpux)
- #undef _XOPEN_SOURCE_EXTENDED
-#endif
/* AIX seems to define this */
#undef lines
@@ -357,12 +351,7 @@ static void Buffer_To_Window(const FIELD * field, WINDOW * win)
assert(win && field);
-#if defined(__LSB_VERSION__)
getmaxyx(win, height, width);
-#else
- width = getmaxx(win);
- height = getmaxy(win);
-#endif
for(row=0, pBuffer=field->buf;
row < height;
@@ -394,17 +383,13 @@ static void Window_To_Buffer(WINDOW * win, FIELD * field)
int pad;
int len = 0;
char *p;
- int row, height;
+ int row, height, width;
assert(win && field && field->buf );
pad = field->pad;
p = field->buf;
-#if defined(__LSB_VERSION__)
- { int width; getmaxyx(win, height, width); }
-#else
- height = getmaxy(win);
-#endif
+ getmaxyx(win, height, width);
for(row=0; (row < height) && (row < field->drows); row++ )
{
@@ -1691,7 +1676,7 @@ static int VSC_Generic(FORM *form, int lines)
|
| Description : Performs the generic vertical scrolling routines.
| This has to check for a multi-line field and to set
-| the _NEWTOP flag if scrolling really occured.
+| the _NEWTOP flag if scrolling really occurred.
|
| Return Values : Propagated error code from low-level driver calls
+--------------------------------------------------------------------------*/
@@ -2174,7 +2159,7 @@ static int Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM * form)
|
| Description : Generic routine for field editing requests. The driver
| routines are only called for editable fields, the
-| _WINDOW_MODIFIED flag is set if editing occured.
+| _WINDOW_MODIFIED flag is set if editing occurred.
| This is somewhat special due to the overload semantics
| of the NEW_LINE and DEL_PREV requests.
|
diff --git a/Source/CursesDialog/form/frm_post.c b/Source/CursesDialog/form/frm_post.c
index 3c63de70e..924fe6a9e 100644
--- a/Source/CursesDialog/form/frm_post.c
+++ b/Source/CursesDialog/form/frm_post.c
@@ -63,12 +63,7 @@ int post_form(FORM * form)
RETURN(E_NOT_CONNECTED);
formwin = Get_Form_Window(form);
-#if defined(__LSB_VERSION__)
getmaxyx(formwin, height, width);
-#else
- width = getmaxx(formwin);
- height = getmaxy(formwin);
-#endif
if ((form->cols > width) || (form->rows > height))
RETURN(E_NO_ROOM);
diff --git a/Source/CursesDialog/form/frm_req_name.c b/Source/CursesDialog/form/frm_req_name.c
index b108dabe4..6fb9183b3 100644
--- a/Source/CursesDialog/form/frm_req_name.c
+++ b/Source/CursesDialog/form/frm_req_name.c
@@ -35,13 +35,7 @@
* Routines to handle external names of menu requests *
***************************************************************************/
-#if defined(__hpux)
- #define _XOPEN_SOURCE_EXTENDED
-#endif
#include "form.priv.h"
-#if defined(__hpux)
- #undef _XOPEN_SOURCE_EXTENDED
-#endif
MODULE_ID("$Id$")
diff --git a/Source/LexerParser/.clang-tidy b/Source/LexerParser/.clang-tidy
new file mode 100644
index 000000000..52b11bf91
--- /dev/null
+++ b/Source/LexerParser/.clang-tidy
@@ -0,0 +1,6 @@
+---
+# We want to disable all checks for generated code. However, clang-tidy will
+# assume we did not configure it correctly. Just add one check that will never
+# be found.
+Checks: '-*,llvm-twine-local'
+...
diff --git a/Source/LexerParser/.gitattributes b/Source/LexerParser/.gitattributes
new file mode 100644
index 000000000..47eedfb4b
--- /dev/null
+++ b/Source/LexerParser/.gitattributes
@@ -0,0 +1,17 @@
+/cmCommandArgumentLexer.cxx generated
+/cmCommandArgumentLexer.h generated
+/cmCommandArgumentParser.cxx generated
+/cmCommandArgumentParserTokens.h generated
+/cmDependsJavaLexer.cxx generated
+/cmDependsJavaLexer.h generated
+/cmDependsJavaParser.cxx generated
+/cmDependsJavaParserTokens.h generated
+/cmExprLexer.cxx generated
+/cmExprLexer.h generated
+/cmExprParser.cxx generated
+/cmExprParserTokens.h generated
+/cmFortranLexer.cxx generated
+/cmFortranLexer.h generated
+/cmFortranParser.cxx generated
+/cmFortranParserTokens.h generated
+/cmListFileLexer.c generated
diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
new file mode 100644
index 000000000..12dce3758
--- /dev/null
+++ b/Source/LexerParser/cmCommandArgumentLexer.cxx
@@ -0,0 +1,2072 @@
+#include "cmStandardLexer.h"
+#line 2 "cmCommandArgumentLexer.cxx"
+
+#line 4 "cmCommandArgumentLexer.cxx"
+
+#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 1
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#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
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* 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 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.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmCommandArgument_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 cmCommandArgument_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 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 );
+
+#define YY_FLUSH_BUFFER cmCommandArgument_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 );
+
+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
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ cmCommandArgument_yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmCommandArgument_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); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmCommandArgument_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 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 );
+
+/* 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 14
+#define YY_END_OF_BUFFER 15
+/* 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 yyconst 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] =
+ { 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, 3, 1, 1, 1, 1,
+ 1, 1, 4, 1, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 1, 1, 1,
+ 1, 1, 1, 5, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 4, 7, 4, 4,
+ 4, 4, 4, 4, 4, 8, 4, 4, 4, 4,
+ 1, 9, 1, 1, 4, 1, 4, 4, 4, 4,
+
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 10, 1, 11, 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 yyconst 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] =
+ { 0,
+ 0, 0, 31, 30, 29, 28, 36, 0, 6, 16,
+ 0, 41, 41, 41, 0, 41, 0, 22, 22, 41,
+ 18, 18, 41, 41, 7, 41, 4, 41, 41, 20,
+ 21, 26, 9, 30
+ } ;
+
+static yyconst 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,
+ 32, 33, 29, 29, 18, 29, 18, 29, 0, 29,
+ 29, 29, 29, 29
+ } ;
+
+static yyconst flex_uint16_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,
+ 17, 17, 26, 17, 18, 18, 21, 21, 25, 21,
+ 23, 24, 23, 23, 23, 29, 16, 16, 15, 15,
+ 7, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29
+ } ;
+
+static yyconst 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,
+ 30, 30, 22, 30, 31, 31, 32, 32, 19, 32,
+ 34, 18, 34, 34, 34, 7, 6, 5, 4, 3,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29
+ } ;
+
+/* 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
+#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. */
+/*
+
+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
+
+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
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#include "cmCommandArgumentParserHelper.h"
+
+/* Replace the lexer input function. */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ { result = yyextra->LexInput(buf, max_size); }
+
+/* Include the set of tokens from the parser. */
+#include "cmCommandArgumentParserTokens.h"
+
+/*--------------------------------------------------------------------------*/
+
+
+#line 484 "cmCommandArgumentLexer.cxx"
+
+#define INITIAL 0
+#define ESCAPES 1
+#define NOESCAPES 2
+
+#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 cmCommandArgument_yylex_init (yyscan_t* scanner);
+
+int cmCommandArgument_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 cmCommandArgument_yyget_debug (yyscan_t yyscanner );
+
+void cmCommandArgument_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE cmCommandArgument_yyget_extra (yyscan_t yyscanner );
+
+void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner );
+
+void cmCommandArgument_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+
+FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner );
+
+void cmCommandArgument_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+
+ int cmCommandArgument_yyget_leng (yyscan_t yyscanner );
+
+char *cmCommandArgument_yyget_text (yyscan_t yyscanner );
+
+int cmCommandArgument_yyget_lineno (yyscan_t yyscanner );
+
+void cmCommandArgument_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmCommandArgument_yyget_column (yyscan_t yyscanner );
+
+void cmCommandArgument_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 cmCommandArgument_yywrap (yyscan_t yyscanner );
+#else
+extern int cmCommandArgument_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst 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 = '*'; \
+ size_t 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, 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 cmCommandArgument_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int cmCommandArgument_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 ) {
+ cmCommandArgument_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmCommandArgument_yy_load_buffer_state(yyscanner );
+ }
+
+ {
+#line 42 "cmCommandArgumentLexer.in.l"
+
+
+#line 740 "cmCommandArgumentLexer.cxx"
+
+ 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 >= 30 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 41 );
+
+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
+#line 44 "cmCommandArgumentLexer.in.l"
+{
+ //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
+ yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
+ return cal_ENVCURLY;
+}
+ 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);
+ return cal_NCURLY;
+}
+ 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);
+ return cal_ATNAME;
+}
+ 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;
+ 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;
+ 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;
+ 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));
+ return cal_NAME;
+}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 89 "cmCommandArgumentLexer.in.l"
+{
+ if ( !yyextra->HandleEscapeSymbol(yylvalp, *(yytext+1)) )
+ {
+ return cal_ERROR;
+ }
+ return cal_SYMBOL;
+}
+ YY_BREAK
+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));
+ return cal_SYMBOL;
+}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 103 "cmCommandArgumentLexer.in.l"
+{
+ //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
+ yylvalp->str = yyextra->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;
+ 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;
+ 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;
+ 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):
+ yyterminate();
+
+ 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
+ * cmCommandArgument_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 ( cmCommandArgument_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 cmCommandArgument_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;
+ yy_size_t 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 = (yy_size_t) (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. */
+ cmCommandArgument_yyrealloc((void *) b->yy_ch_buf,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;
+ cmCommandArgument_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 ((int) (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 );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ 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 >= 30 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) 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 >= 30 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 29);
+
+ (void)yyg;
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+#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 = 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. */
+ cmCommandArgument_yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( cmCommandArgument_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 cmCommandArgument_yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ cmCommandArgument_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmCommandArgument_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ cmCommandArgument_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)
+{
+ 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);
+ */
+ cmCommandArgument_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;
+ cmCommandArgument_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
+ * 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)
+{
+ 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 cmCommandArgument_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 );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_create_buffer()" );
+
+ b->yy_buf_size = (yy_size_t)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 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ cmCommandArgument_yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with cmCommandArgument_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void cmCommandArgument_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 )
+ cmCommandArgument_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ cmCommandArgument_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.
+ */
+ static void cmCommandArgument_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);
+
+ 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.
+ * 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 cmCommandArgument_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 )
+ cmCommandArgument_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 cmCommandArgument_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);
+
+ /* This block is copied from cmCommandArgument_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 cmCommandArgument_yy_switch_to_buffer. */
+ cmCommandArgument_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 cmCommandArgument_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_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 );
+ 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 cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int 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**)cmCommandArgument_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()" );
+
+ 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**)cmCommandArgument_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()" );
+
+ /* 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 cmCommandArgument_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) cmCommandArgument_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_scan_buffer()" );
+
+ b->yy_buf_size = 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;
+
+ cmCommandArgument_yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to cmCommandArgument_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_BUFFER_STATE cmCommandArgument_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return cmCommandArgument_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
+ * 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 b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t 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 );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_scan_bytes()" );
+
+ for ( i = 0; i < (size_t)_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);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in cmCommandArgument_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 (yyconst char* msg , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) 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 cmCommandArgument_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 cmCommandArgument_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 cmCommandArgument_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 *cmCommandArgument_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 *cmCommandArgument_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 cmCommandArgument_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 *cmCommandArgument_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 cmCommandArgument_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 cmCommandArgument_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" );
+
+ yylineno = _line_number;
+}
+
+/** Set the current column.
+ * @param _column_no column number
+ * @param yyscanner The scanner object.
+ */
+void cmCommandArgument_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" );
+
+ 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 cmCommandArgument_yy_switch_to_buffer
+ */
+void cmCommandArgument_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = _out_str ;
+}
+
+int cmCommandArgument_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = _bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* cmCommandArgument_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)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmCommandArgument_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 );
+}
+
+/* cmCommandArgument_yylex_init_extra has the same functionality as cmCommandArgument_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 yyextra field.
+ */
+
+int cmCommandArgument_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);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmCommandArgument_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));
+
+ cmCommandArgument_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 cmCommandArgument_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
+ * cmCommandArgument_yylex_init()
+ */
+ return 0;
+}
+
+/* cmCommandArgument_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int cmCommandArgument_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_CURRENT_BUFFER_LVALUE = NULL;
+ cmCommandArgument_yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ cmCommandArgument_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ cmCommandArgument_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. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ cmCommandArgument_yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst 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 (yyconst char * s , yyscan_t yyscanner)
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *cmCommandArgument_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)
+{
+ 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 cmCommandArgument_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 */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 127 "cmCommandArgumentLexer.in.l"
+
+
+
+/*--------------------------------------------------------------------------*/
+void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes)
+{
+ /* Hack into the internal flex-generated scanner to set the state. */
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if(noEscapes) {
+ BEGIN(NOESCAPES);
+ } else {
+ BEGIN(ESCAPES);
+ }
+}
diff --git a/Source/cmCommandArgumentLexer.h b/Source/LexerParser/cmCommandArgumentLexer.h
index 2ea3fa29f..82e87b557 100644
--- a/Source/cmCommandArgumentLexer.h
+++ b/Source/LexerParser/cmCommandArgumentLexer.h
@@ -1,26 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
#ifndef cmCommandArgument_yyHEADER_H
#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
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -99,25 +93,13 @@ typedef unsigned int flex_uint32_t;
#endif /* ! FLEXINT_H */
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* An opaque pointer. */
@@ -139,7 +121,15 @@ typedef void* yyscan_t;
/* 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
@@ -155,52 +145,52 @@ typedef size_t yy_size_t;
#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.
- */
- yy_size_t 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;
+ {
+ 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;
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
- int yy_buffer_status;
+ int yy_buffer_status;
- };
+ };
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
void cmCommandArgument_yyrestart (FILE *input_file ,yyscan_t yyscanner );
@@ -221,7 +211,7 @@ void cmCommandArgument_yyfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
-#define cmCommandArgument_yywrap(n) 1
+#define cmCommandArgument_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
@@ -256,19 +246,23 @@ void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscann
FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner );
-void cmCommandArgument_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+void cmCommandArgument_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner );
-void cmCommandArgument_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+void cmCommandArgument_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
-int cmCommandArgument_yyget_leng (yyscan_t yyscanner );
+ int cmCommandArgument_yyget_leng (yyscan_t yyscanner );
char *cmCommandArgument_yyget_text (yyscan_t yyscanner );
int cmCommandArgument_yyget_lineno (yyscan_t yyscanner );
-void cmCommandArgument_yyset_lineno (int line_number ,yyscan_t yyscanner );
+void cmCommandArgument_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmCommandArgument_yyget_column (yyscan_t yyscanner );
+
+void cmCommandArgument_yyset_column (int _column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -296,7 +290,12 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
/* 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. */
@@ -329,5 +328,9 @@ extern int cmCommandArgument_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
+#line 127 "cmCommandArgumentLexer.in.l"
+
+
+#line 335 "cmCommandArgumentLexer.h"
#undef cmCommandArgument_yyIN_HEADER
#endif /* cmCommandArgument_yyHEADER_H */
diff --git a/Source/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
index 24a0eec85..e3a80948c 100644
--- a/Source/cmCommandArgumentLexer.in.l
+++ b/Source/LexerParser/cmCommandArgumentLexer.in.l
@@ -1,43 +1,23 @@
%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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.
+This file must be translated to C++ and modified to build everywhere.
-Run flex like this:
+Run flex >= 2.6 like this:
- flex --prefix=cmCommandArgument_yy --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
+ flex --nounistd -DFLEXINT_H --prefix=cmCommandArgument_yy --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
Modify cmCommandArgumentLexer.cxx:
- - add #include "cmStandardIncludes.h" to top of file
- - put header block at top of file
- - remove TABs
- - remove use of the 'register' storage class specifier
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmCommandArgument_yyalloc, cmCommandArgument_yyrealloc, cmCommandArgument_yyfree
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
- - add "return 0;" to end of cmCommandArgument_yylex
-
-Modify cmCommandArgumentLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
+ - 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
*/
-#include "cmStandardLexer.h"
+/* IWYU pragma: no_forward_declare yyguts_t */
#include "cmCommandArgumentParserHelper.h"
@@ -151,12 +131,9 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes)
{
/* Hack into the internal flex-generated scanner to set the state. */
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if(noEscapes)
- {
+ if(noEscapes) {
BEGIN(NOESCAPES);
- }
- else
- {
+ } else {
BEGIN(ESCAPES);
- }
+ }
}
diff --git a/Source/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
index c5146c5d7..aed0826c0 100644
--- a/Source/cmCommandArgumentParser.cxx
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -1,25 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* A Bison parser, made by GNU Bison 3.0.4. */
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Bison implementation for Yacc-like parsers in C
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/* A Bison parser, made by GNU Bison 2.3. */
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+ 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,9 +15,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -58,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "3.0.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -66,70 +52,26 @@
/* Pure parsers. */
#define YYPURE 1
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-/* Substitute the variable and function names. */
-#define yyparse cmCommandArgument_yyparse
-#define yylex cmCommandArgument_yylex
-#define yyerror cmCommandArgument_yyerror
-#define yylval cmCommandArgument_yylval
-#define yychar cmCommandArgument_yychar
-#define yydebug cmCommandArgument_yydebug
-#define yynerrs cmCommandArgument_yynerrs
-
+/* Push parsers. */
+#define YYPUSH 0
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- cal_ENVCURLY = 258,
- cal_NCURLY = 259,
- cal_DCURLY = 260,
- cal_DOLLAR = 261,
- cal_LCURLY = 262,
- cal_RCURLY = 263,
- cal_NAME = 264,
- cal_BSLASH = 265,
- cal_SYMBOL = 266,
- cal_AT = 267,
- cal_ERROR = 268,
- cal_ATNAME = 269
- };
-#endif
-/* Tokens. */
-#define cal_ENVCURLY 258
-#define cal_NCURLY 259
-#define cal_DCURLY 260
-#define cal_DOLLAR 261
-#define cal_LCURLY 262
-#define cal_RCURLY 263
-#define cal_NAME 264
-#define cal_BSLASH 265
-#define cal_SYMBOL 266
-#define cal_AT 267
-#define cal_ERROR 268
-#define cal_ATNAME 269
+/* Pull parsers. */
+#define YYPULL 1
+/* Substitute the variable and function names. */
+#define yyparse cmCommandArgument_yyparse
+#define yylex cmCommandArgument_yylex
+#define yyerror cmCommandArgument_yyerror
+#define yydebug cmCommandArgument_yydebug
+#define yynerrs cmCommandArgument_yynerrs
/* Copy the first part of user declarations. */
-#line 1 "cmCommandArgumentParser.y"
-
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#line 1 "cmCommandArgumentParser.y" /* yacc.c:339 */
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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.
@@ -139,19 +81,14 @@ Run bison like this:
bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
Modify cmCommandArgumentParser.cxx:
- - remove TABs
- - put header block at top of file
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
*/
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string.h>
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmCommandArgument_yyerror(x) \
- cmCommandArgumentError(yyscanner, x)
#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
/* Make sure malloc and free are available on QNX. */
@@ -174,21 +111,14 @@ Modify cmCommandArgumentParser.cxx:
/* Forward declare the lexer entry point. */
YY_DECL;
-/* Internal utility functions. */
-static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
+/* Helper function to forward error callback from parser. */
+static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
-#define YYDEBUG 1
/* Configure the parser to support large input. */
#define YYMAXDEPTH 100000
#define YYINITDEPTH 10000
/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
#ifdef _MSC_VER
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no
@@ -197,39 +127,80 @@ static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4702) /* unreachable code */
#endif
+#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339 */
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
-# define YYERROR_VERBOSE 0
+# define YYERROR_VERBOSE 1
#endif
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* In a future release of Bison, this section will be replaced
+ by #include "cmCommandArgumentParserTokens.h". */
+#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmCommandArgument_yydebug;
#endif
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ cal_ENVCURLY = 258,
+ cal_NCURLY = 259,
+ cal_DCURLY = 260,
+ cal_DOLLAR = 261,
+ cal_LCURLY = 262,
+ cal_RCURLY = 263,
+ cal_NAME = 264,
+ cal_BSLASH = 265,
+ cal_SYMBOL = 266,
+ cal_AT = 267,
+ cal_ERROR = 268,
+ cal_ATNAME = 269
+ };
#endif
+/* Tokens. */
+#define cal_ENVCURLY 258
+#define cal_NCURLY 259
+#define cal_DCURLY 260
+#define cal_DOLLAR 261
+#define cal_LCURLY 262
+#define cal_RCURLY 263
+#define cal_NAME 264
+#define cal_BSLASH 265
+#define cal_SYMBOL 266
+#define cal_AT 267
+#define cal_ERROR 268
+#define cal_ATNAME 269
+/* Value type. */
-/* Copy the second part of user declarations. */
+int cmCommandArgument_yyparse (yyscan_t yyscanner);
-/* Line 216 of yacc.c. */
-#line 227 "cmCommandArgumentParser.cxx"
+#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
@@ -243,11 +214,8 @@ typedef unsigned char yytype_uint8;
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
#else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
#endif
#ifdef YYTYPE_UINT16
@@ -267,8 +235,7 @@ typedef short int yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -282,38 +249,67 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
# endif
# endif
# ifndef YY_
-# define YY_(msgid) msgid
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# 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))
+# define YYUSE(E) ((void) (E))
#else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
#endif
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
- int i;
+# define YY_INITIAL_VALUE(Value) Value
#endif
-{
- return i;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
#if ! defined yyoverflow || YYERROR_VERBOSE
@@ -332,11 +328,11 @@ YYID (i)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
# endif
# endif
# endif
@@ -344,8 +340,8 @@ YYID (i)
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
@@ -359,25 +355,23 @@ YYID (i)
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
-# if (defined __cplusplus && ! defined _STDLIB_H \
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined malloc && ! defined EXIT_SUCCESS
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined free && ! defined EXIT_SUCCESS
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
@@ -392,9 +386,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- };
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
/* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -405,42 +399,46 @@ union yyalloc
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
+# define YYCOPY_NEEDED 1
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack) \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
- while (YYID (0))
+ while (0)
#endif
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 25
/* YYLAST -- Last index in YYTABLE. */
@@ -452,17 +450,19 @@ union yyalloc
#define YYNNTS 10
/* YYNRULES -- Number of rules. */
#define YYNRULES 24
-/* YYNRULES -- Number of states. */
+/* YYNSTATES -- Number of states. */
#define YYNSTATES 33
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 269
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -495,36 +495,16 @@ static const yytype_uint8 yytranslate[] =
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 5, 7, 10, 11, 14, 16, 18,
- 20, 22, 24, 26, 28, 30, 34, 38, 42, 44,
- 46, 49, 50, 53, 55
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 16, 0, -1, 17, -1, 18, -1, 18, 10, -1,
- -1, 19, 18, -1, 20, -1, 21, -1, 9, -1,
- 12, -1, 6, -1, 7, -1, 8, -1, 11, -1,
- 3, 22, 8, -1, 4, 23, 8, -1, 5, 23,
- 8, -1, 14, -1, 23, -1, 11, 22, -1, -1,
- 24, 23, -1, 9, -1, 21, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 116, 116, 123, 128, 134, 138, 144, 149, 155,
- 160, 165, 170, 175, 180, 186, 192, 198, 204, 210,
- 215, 221, 225, 231, 236
+ 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
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 1
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -533,13 +513,13 @@ static const char *const yytname[] =
"cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
"cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
"GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
- "EnvVarName", "MultipleIds", "ID", 0
+ "EnvVarName", "MultipleIds", "ID", YY_NULLPTR
};
#endif
# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
@@ -547,25 +527,29 @@ static const yytype_uint16 yytoknum[] =
};
# endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 15, 16, 17, 17, 18, 18, 19, 19, 20,
- 20, 20, 20, 20, 20, 21, 21, 21, 21, 22,
- 22, 23, 23, 24, 24
-};
+#define YYPACT_NINF -3
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-3)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int8 yypact[] =
{
- 0, 2, 1, 1, 2, 0, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 3, 3, 3, 1, 1,
- 2, 0, 2, 1, 1
+ 0, 14, 26, 26, -3, -3, -3, -3, -3, -3,
+ -3, 10, -3, 3, 0, -3, -3, -3, 14, -3,
+ 7, -3, 26, 13, 16, -3, -3, -3, -3, -3,
+ -3, -3, -3
};
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
static const yytype_uint8 yydefact[] =
{
5, 21, 21, 21, 11, 12, 13, 9, 14, 10,
@@ -574,34 +558,21 @@ static const yytype_uint8 yydefact[] =
22, 16, 17
};
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
-{
- -1, 11, 12, 13, 14, 15, 19, 20, 21, 22
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -3
-static const yytype_int8 yypact[] =
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
{
- 0, 14, 26, 26, -3, -3, -3, -3, -3, -3,
- -3, 10, -3, 3, 0, -3, -3, -3, 14, -3,
- 7, -3, 26, 13, 16, -3, -3, -3, -3, -3,
- -3, -3, -3
+ -3, -3, -3, 8, -3, -3, 2, 9, -2, -3
};
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
{
- -3, -3, -3, 8, -3, -3, 2, 9, -2, -3
+ -1, 11, 12, 13, 14, 15, 19, 20, 21, 22
};
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
23, 24, 16, 1, 2, 3, 4, 5, 6, 7,
@@ -620,8 +591,8 @@ static const yytype_int8 yycheck[] =
14
};
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
0, 3, 4, 5, 6, 7, 8, 9, 11, 12,
@@ -630,6 +601,23 @@ static const yytype_uint8 yystos[] =
23, 8, 8
};
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 15, 16, 17, 17, 18, 18, 19, 19, 20,
+ 20, 20, 20, 20, 20, 21, 21, 21, 21, 22,
+ 22, 23, 23, 24, 24
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 2, 0, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 3, 3, 1, 1,
+ 2, 0, 2, 1, 1
+};
+
+
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY (-2)
@@ -640,85 +628,30 @@ static const yytype_uint8 yystos[] =
#define YYERROR goto yyerrorlab
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
#define YYRECOVERING() (!!yyerrstatus)
#define YYBACKUP(Token, Value) \
do \
- if (yychar == YYEMPTY && yylen == 1) \
+ if (yychar == YYEMPTY) \
{ \
yychar = (Token); \
yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK (1); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
goto yybackup; \
} \
else \
{ \
- yyerror (YY_("syntax error: cannot back up")); \
+ yyerror (yyscanner, YY_("syntax error: cannot back up")); \
YYERROR; \
} \
-while (YYID (0))
-
+while (0)
+/* Error token number */
#define YYTERROR 1
#define YYERRCODE 256
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
/* Enable debugging if requested. */
#if YYDEBUG
@@ -732,7 +665,13 @@ while (YYID (0))
do { \
if (yydebug) \
YYFPRINTF Args; \
-} while (YYID (0))
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
do { \
@@ -740,42 +679,29 @@ do { \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
- Type, Value); \
+ Type, Value, yyscanner); \
YYFPRINTF (stderr, "\n"); \
} \
-} while (YYID (0))
+} while (0)
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
# endif
- switch (yytype)
- {
- default:
- break;
- }
+ YYUSE (yytype);
}
@@ -783,24 +709,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
- yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
YYFPRINTF (yyoutput, ")");
}
@@ -809,20 +724,15 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
| TOP (included). |
`------------------------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
-#endif
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
{
YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
YYFPRINTF (stderr, "\n");
}
@@ -830,45 +740,38 @@ yy_stack_print (bottom, top)
do { \
if (yydebug) \
yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
+} while (0)
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
- YYSTYPE *yyvsp;
- int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
+ unsigned long int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
- fprintf (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
&(yyvsp[(yyi + 1) - (yynrhs)])
- );
- fprintf (stderr, "\n");
+ , yyscanner);
+ YYFPRINTF (stderr, "\n");
}
}
# define YY_REDUCE_PRINT(Rule) \
do { \
if (yydebug) \
- yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+ yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
@@ -897,7 +800,6 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
-
#if YYERROR_VERBOSE
@@ -906,15 +808,8 @@ int yydebug;
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
{
YYSIZE_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
@@ -930,16 +825,8 @@ yystrlen (yystr)
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
{
char *yyd = yydest;
const char *yys = yysrc;
@@ -1000,165 +887,159 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
- return 0;
- else
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
{
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
{
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
}
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
- if (yyresult)
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
}
- return yysize;
- }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
}
#endif /* YYERROR_VERBOSE */
-
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
YYUSE (yyvaluep);
-
+ YYUSE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
- switch (yytype)
- {
-
- default:
- break;
- }
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
@@ -1167,99 +1048,76 @@ int yyparse ();
| yyparse. |
`----------*/
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
+yyparse (yyscan_t yyscanner)
{
- /* The look-ahead symbol. */
+/* The lookahead symbol. */
int yychar;
-/* The semantic value of the look-ahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
+ /* Number of syntax errors so far. */
+ int yynerrs;
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
- YYSIZE_T yystacksize = YYINITDEPTH;
+ YYSIZE_T yystacksize;
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
int yylen = 0;
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
-
+ yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
/*------------------------------------------------------------.
@@ -1286,7 +1144,6 @@ int yynerrs;
YYSTYPE *yyvs1 = yyvs;
yytype_int16 *yyss1 = yyss;
-
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
@@ -1294,7 +1151,6 @@ int yynerrs;
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
-
&yystacksize);
yyss = yyss1;
@@ -1317,9 +1173,8 @@ int yynerrs;
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
@@ -1330,7 +1185,6 @@ int yynerrs;
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
-
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long int) yystacksize));
@@ -1340,6 +1194,9 @@ int yynerrs;
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
goto yybackup;
/*-----------.
@@ -1348,20 +1205,20 @@ int yynerrs;
yybackup:
/* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
+ lookahead token if we need one and don't already have one. */
- /* First try to decide what to do without reference to look-ahead token. */
+ /* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
+ if (yypact_value_is_default (yyn))
goto yydefault;
- /* Not known => get a look-ahead token if don't already have one. */
+ /* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
+ yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
@@ -1383,29 +1240,27 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
- if (yyn == 0 || yyn == YYTABLE_NINF)
+ if (yytable_value_is_error (yyn))
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
- /* Shift the look-ahead token. */
+ /* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -1428,7 +1283,7 @@ yyreduce:
yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ '$$ = $1'.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
@@ -1442,175 +1297,205 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 117 "cmCommandArgumentParser.y"
+#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = 0;
- yyGetParser->SetResult((yyvsp[(1) - (1)].str));
-}
+ (yyval.str) = 0;
+ yyGetParser->SetResult((yyvsp[0].str));
+ }
+#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 3:
-#line 124 "cmCommandArgumentParser.y"
+#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 4:
-#line 129 "cmCommandArgumentParser.y"
+#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
+ (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+ }
+#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 5:
-#line 134 "cmCommandArgumentParser.y"
+#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = 0;
-}
+ (yyval.str) = 0;
+ }
+#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 6:
-#line 139 "cmCommandArgumentParser.y"
+#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
+ (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+ }
+#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 7:
-#line 145 "cmCommandArgumentParser.y"
+#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 8:
-#line 150 "cmCommandArgumentParser.y"
+#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 9:
-#line 156 "cmCommandArgumentParser.y"
+#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 10:
-#line 161 "cmCommandArgumentParser.y"
+#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 11:
-#line 166 "cmCommandArgumentParser.y"
+#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 12:
-#line 171 "cmCommandArgumentParser.y"
+#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 13:
-#line 176 "cmCommandArgumentParser.y"
+#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 14:
-#line 181 "cmCommandArgumentParser.y"
+#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 15:
-#line 187 "cmCommandArgumentParser.y"
+#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str));
- //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
+ (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
+ }
+#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 16:
-#line 193 "cmCommandArgumentParser.y"
+#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str));
- //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
+ (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
+ }
+#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 17:
-#line 199 "cmCommandArgumentParser.y"
+#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->ExpandVariable((yyvsp[(2) - (3)].str));
- //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
+ (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
+ }
+#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 18:
-#line 205 "cmCommandArgumentParser.y"
+#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[(1) - (1)].str));
-}
+ (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
+ }
+#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 19:
-#line 211 "cmCommandArgumentParser.y"
+#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 20:
-#line 216 "cmCommandArgumentParser.y"
+#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (2)].str);
-}
+ (yyval.str) = (yyvsp[-1].str);
+ }
+#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 21:
-#line 221 "cmCommandArgumentParser.y"
+#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = 0;
-}
+ (yyval.str) = 0;
+ }
+#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 22:
-#line 226 "cmCommandArgumentParser.y"
+#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
+ (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+ }
+#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 23:
-#line 232 "cmCommandArgumentParser.y"
+#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 24:
-#line 237 "cmCommandArgumentParser.y"
+#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
- (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+ (yyval.str) = (yyvsp[0].str);
+ }
+#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
-/* Line 1267 of yacc.c. */
-#line 1606 "cmCommandArgumentParser.cxx"
+#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
default: break;
}
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
YYPOPSTACK (yylen);
@@ -1619,8 +1504,7 @@ yyreduce:
*++yyvsp = yyval;
-
- /* Now `shift' the result of the reduction. Determine what state
+ /* 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. */
@@ -1635,48 +1519,51 @@ yyreduce:
goto yynewstate;
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
#if ! YYERROR_VERBOSE
- yyerror (YY_("syntax error"));
+ yyerror (yyscanner, YY_("syntax error"));
#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
{
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
{
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
{
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
}
}
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (yymsg);
- }
- else
- {
- yyerror (YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
+ yyerror (yyscanner, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
}
+# undef YYSYNTAX_ERROR
#endif
}
@@ -1684,7 +1571,7 @@ yyerrlab:
if (yyerrstatus == 3)
{
- /* If just tried and failed to reuse look-ahead token after an
+ /* If just tried and failed to reuse lookahead token after an
error, discard it. */
if (yychar <= YYEOF)
@@ -1696,12 +1583,13 @@ yyerrlab:
else
{
yydestruct ("Error: discarding",
- yytoken, &yylval);
+ yytoken, &yylval, yyscanner);
yychar = YYEMPTY;
}
}
- /* Else will try to reuse look-ahead token after shifting the error
+#if 0
+ /* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -1717,7 +1605,7 @@ yyerrorlab:
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
@@ -1730,12 +1618,13 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
+#endif
yyerrstatus = 3; /* Each real token shifted decrements this. */
for (;;)
{
yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
+ if (!yypact_value_is_default (yyn))
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -1752,16 +1641,15 @@ yyerrlab1:
yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
+ yystos[yystate], yyvsp, yyscanner);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -1785,28 +1673,33 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#ifndef yyoverflow
+#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
+ yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- /* Do not reclaim the symbols of the rule which action triggered
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, yyscanner);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp);
+ yystos[*yyssp], yyvsp, yyscanner);
YYPOPSTACK (1);
}
#ifndef yyoverflow
@@ -1817,19 +1710,14 @@ yyreturn:
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
+ return yyresult;
}
-
-
-#line 242 "cmCommandArgumentParser.y"
+#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906 */
/* End of grammar */
/*--------------------------------------------------------------------------*/
-void cmCommandArgumentError(yyscan_t yyscanner, const char* message)
+void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message)
{
yyGetParser->Error(message);
}
-
-
diff --git a/Source/LexerParser/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y
new file mode 100644
index 000000000..55a88dffa
--- /dev/null
+++ b/Source/LexerParser/cmCommandArgumentParser.y
@@ -0,0 +1,191 @@
+%{
+/* 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 bison like this:
+
+ bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
+
+Modify cmCommandArgumentParser.cxx:
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string.h>
+
+#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
+
+/* Make sure malloc and free are available on QNX. */
+#ifdef __QNX__
+# include <malloc.h>
+#endif
+
+/* Make sure the parser uses standard memory allocation. The default
+ generated parser malloc/free declarations do not work on all
+ platforms. */
+#include <stdlib.h>
+#define YYMALLOC malloc
+#define YYFREE free
+
+/*-------------------------------------------------------------------------*/
+#include "cmCommandArgumentParserHelper.h" /* Interface to parser object. */
+#include "cmCommandArgumentLexer.h" /* Interface to lexer object. */
+#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+
+/* Forward declare the lexer entry point. */
+YY_DECL;
+
+/* Helper function to forward error callback from parser. */
+static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Configure the parser to support large input. */
+#define YYMAXDEPTH 100000
+#define YYINITDEPTH 10000
+
+/* Disable some warnings in the generated code. */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label. */
+# pragma warning (disable: 4065) /* Switch statement contains default but no
+ case. */
+# pragma warning (disable: 4244) /* loss of precision */
+# pragma warning (disable: 4702) /* unreachable code */
+#endif
+%}
+
+/* Generate a reentrant parser object. */
+%define api.pure
+
+/* Configure the parser to use a lexer object. */
+%lex-param {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+/*
+%union {
+ char* string;
+}
+*/
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token cal_ENVCURLY
+%token cal_NCURLY
+%token cal_DCURLY
+%token cal_DOLLAR "$"
+%token cal_LCURLY "{"
+%token cal_RCURLY "}"
+%token cal_NAME
+%token cal_BSLASH "\\"
+%token cal_SYMBOL
+%token cal_AT "@"
+%token cal_ERROR
+%token cal_ATNAME
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+
+Start:
+ GoalWithOptionalBackSlash {
+ $<str>$ = 0;
+ yyGetParser->SetResult($<str>1);
+ }
+
+GoalWithOptionalBackSlash:
+ Goal {
+ $<str>$ = $<str>1;
+ }
+| Goal cal_BSLASH {
+ $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+ }
+
+Goal:
+ {
+ $<str>$ = 0;
+ }
+| String Goal {
+ $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+ }
+
+String:
+ OuterText {
+ $<str>$ = $<str>1;
+ }
+| Variable {
+ $<str>$ = $<str>1;
+ }
+
+OuterText:
+ cal_NAME {
+ $<str>$ = $<str>1;
+ }
+| cal_AT {
+ $<str>$ = $<str>1;
+ }
+| cal_DOLLAR {
+ $<str>$ = $<str>1;
+ }
+| cal_LCURLY {
+ $<str>$ = $<str>1;
+ }
+| cal_RCURLY {
+ $<str>$ = $<str>1;
+ }
+| cal_SYMBOL {
+ $<str>$ = $<str>1;
+ }
+
+Variable:
+ cal_ENVCURLY EnvVarName cal_RCURLY {
+ $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1, $<str>2);
+ }
+| cal_NCURLY MultipleIds cal_RCURLY {
+ $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1, $<str>2);
+ }
+| cal_DCURLY MultipleIds cal_RCURLY {
+ $<str>$ = yyGetParser->ExpandVariable($<str>2);
+ }
+| cal_ATNAME {
+ $<str>$ = yyGetParser->ExpandVariableForAt($<str>1);
+ }
+
+EnvVarName:
+ MultipleIds {
+ $<str>$ = $<str>1;
+ }
+| cal_SYMBOL EnvVarName {
+ $<str>$ = $<str>1;
+ }
+
+MultipleIds:
+ {
+ $<str>$ = 0;
+ }
+| ID MultipleIds {
+ $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+ }
+
+ID:
+ cal_NAME {
+ $<str>$ = $<str>1;
+ }
+| Variable {
+ $<str>$ = $<str>1;
+ }
+;
+
+%%
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message)
+{
+ yyGetParser->Error(message);
+}
diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h
new file mode 100644
index 000000000..3172182d7
--- /dev/null
+++ b/Source/LexerParser/cmCommandArgumentParserTokens.h
@@ -0,0 +1,82 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmCommandArgument_yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ cal_ENVCURLY = 258,
+ cal_NCURLY = 259,
+ cal_DCURLY = 260,
+ cal_DOLLAR = 261,
+ cal_LCURLY = 262,
+ cal_RCURLY = 263,
+ cal_NAME = 264,
+ cal_BSLASH = 265,
+ cal_SYMBOL = 266,
+ cal_AT = 267,
+ cal_ERROR = 268,
+ cal_ATNAME = 269
+ };
+#endif
+/* Tokens. */
+#define cal_ENVCURLY 258
+#define cal_NCURLY 259
+#define cal_DCURLY 260
+#define cal_DOLLAR 261
+#define cal_LCURLY 262
+#define cal_RCURLY 263
+#define cal_NAME 264
+#define cal_BSLASH 265
+#define cal_SYMBOL 266
+#define cal_AT 267
+#define cal_ERROR 268
+#define cal_ATNAME 269
+
+/* Value type. */
+
+
+
+int cmCommandArgument_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */
diff --git a/Source/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx
index 0af44b02e..8159f47bb 100644
--- a/Source/cmDependsJavaLexer.cxx
+++ b/Source/LexerParser/cmDependsJavaLexer.cxx
@@ -1,16 +1,17 @@
-#include "cmStandardIncludes.h"
+#include "cmStandardLexer.h"
#line 2 "cmDependsJavaLexer.cxx"
#line 4 "cmDependsJavaLexer.cxx"
+#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 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -23,10 +24,6 @@
#include <errno.h>
#include <stdlib.h>
-#if defined(__BEOS__) || defined (__HAIKU__)
-#include <unistd.h> /* prevents a conflict with a #define later on... */
-#endif
-
/* end standard C headers. */
/* flex integer type definitions */
@@ -36,7 +33,15 @@
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#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;
@@ -51,7 +56,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -82,26 +86,17 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_CONST
+#endif /* ! C99 */
-#endif /* __STDC__ */
-#endif /* ! __cplusplus */
+#endif /* ! FLEXINT_H */
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* Returned upon end-of-file. */
@@ -131,8 +126,6 @@ typedef void* yyscan_t;
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
-int cmDependsJava_yylex_init (yyscan_t* scanner);
-
/* 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.
@@ -156,107 +149,117 @@ int cmDependsJava_yylex_init (yyscan_t* scanner);
/* 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. */ \
+ 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 )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
+ *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 )
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
-#endif
+#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.
- */
- yy_size_t 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;
+ {
+ 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;
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
- int yy_buffer_status;
+ 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 cmDependsJava_yyrestart()), so that the user can continue scanning by
- * just pointing yyin at a new input file.
- */
+ /* 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 cmDependsJava_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
@@ -299,30 +302,30 @@ void cmDependsJava_yyfree (void * ,yyscan_t yyscanner );
#define yy_new_buffer cmDependsJava_yy_create_buffer
#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
cmDependsJava_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
+ YY_CURRENT_BUFFER_LVALUE = \
cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
- }
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
#define yy_set_bol(at_bol) \
- { \
- if ( ! YY_CURRENT_BUFFER ){\
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
cmDependsJava_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
+ YY_CURRENT_BUFFER_LVALUE = \
cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
- }
+ } \
+ 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(n) 1
+#define cmDependsJava_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR;
@@ -334,27 +337,27 @@ typedef int yy_state_type;
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 yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error (yyconst 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 = (size_t) (yy_cp - yy_bp); \
- yyg->yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yyg->yy_c_buf_p = yy_cp;
+ 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 111
#define YY_END_OF_BUFFER 112
/* 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;
- };
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
static yyconst flex_int16_t yy_accept[327] =
{ 0,
0, 0, 0, 0, 0, 0, 112, 110, 109, 109,
@@ -395,7 +398,7 @@ static yyconst flex_int16_t yy_accept[327] =
27, 29, 107, 107, 45, 0
} ;
-static yyconst flex_int32_t yy_ec[256] =
+static yyconst 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,
@@ -427,7 +430,7 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[65] =
+static yyconst 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,
@@ -438,7 +441,7 @@ static yyconst flex_int32_t yy_meta[65] =
1, 1, 1, 1
} ;
-static yyconst flex_int16_t yy_base[334] =
+static yyconst flex_uint16_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,
@@ -520,7 +523,7 @@ static yyconst flex_int16_t yy_def[334] =
326, 326, 326
} ;
-static yyconst flex_int16_t yy_nxt[479] =
+static yyconst flex_uint16_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,
@@ -641,41 +644,27 @@ static yyconst flex_int16_t yy_chk[479] =
#define YY_RESTORE_YY_MORE_OFFSET
#line 1 "cmDependsJavaLexer.in.l"
#line 2 "cmDependsJavaLexer.in.l"
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 like this:
+This file must be translated to C++ and modified to build everywhere.
- flex --prefix=cmDependsJava_yy --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
+Run flex >= 2.6 like this:
-Modify cmDependsJavaLexer.c:
- - remove TABs
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmDependsJava_yyalloc, cmDependsJava_yyrealloc, cmDependsJava_yyfree
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
+ flex --nounistd -DFLEXINT_H --prefix=cmDependsJava_yy --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
-Modify cmDependsJavaLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
+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
*/
-#include "cmStandardLexer.h"
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#include <iostream>
#include "cmDependsJavaParserHelper.h"
@@ -694,20 +683,12 @@ Modify cmDependsJavaLexer.h:
/*--------------------------------------------------------------------------*/
-#line 721 "cmDependsJavaLexer.cxx"
+#line 686 "cmDependsJavaLexer.cxx"
#define INITIAL 0
#define comment 1
#define string 2
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endif
@@ -746,6 +727,12 @@ struct yyguts_t
}; /* end struct yyguts_t */
+static int yy_init_globals (yyscan_t yyscanner );
+
+int cmDependsJava_yylex_init (yyscan_t* scanner);
+
+int cmDependsJava_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. */
@@ -761,19 +748,23 @@ void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner )
FILE *cmDependsJava_yyget_in (yyscan_t yyscanner );
-void cmDependsJava_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+void cmDependsJava_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *cmDependsJava_yyget_out (yyscan_t yyscanner );
-void cmDependsJava_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+void cmDependsJava_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
-int cmDependsJava_yyget_leng (yyscan_t yyscanner );
+ int cmDependsJava_yyget_leng (yyscan_t yyscanner );
char *cmDependsJava_yyget_text (yyscan_t yyscanner );
int cmDependsJava_yyget_lineno (yyscan_t yyscanner );
-void cmDependsJava_yyset_lineno (int line_number ,yyscan_t yyscanner );
+void cmDependsJava_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmDependsJava_yyget_column (yyscan_t yyscanner );
+
+void cmDependsJava_yyset_column (int _column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -787,6 +778,12 @@ extern int cmDependsJava_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 *,yyconst char *,int ,yyscan_t yyscanner);
#endif
@@ -807,7 +804,12 @@ static int input (yyscan_t yyscanner );
/* 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. */
@@ -815,7 +817,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#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,
@@ -823,33 +825,33 @@ static int input (yyscan_t yyscanner );
*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
- if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
- { \
- int c = '*'; \
- size_t 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 = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
- { \
- if( errno != EINTR) \
- { \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- break; \
- } \
- errno=0; \
- clearerr(yyin); \
- } \
- }\
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t 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, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
\
#endif
@@ -894,897 +896,1052 @@ extern int cmDependsJava_yylex (yyscan_t yyscanner);
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
-#define YY_BREAK break;
+#define YY_BREAK /*LINTED*/break;
#endif
#define YY_RULE_SETUP \
- YY_USER_ACTION
+ 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;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 88 "cmDependsJavaLexer.in.l"
-
-#line 940 "cmDependsJavaLexer.cxx"
-
- if ( yyg->yy_init )
- {
- yyg->yy_init = 0;
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
#ifdef YY_USER_INIT
- YY_USER_INIT;
+ YY_USER_INIT;
#endif
- if ( ! yyg->yy_start )
- yyg->yy_start = 1; /* first start state */
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
- if ( ! yyin )
- yyin = stdin;
+ if ( ! yyin )
+ yyin = stdin;
- if ( ! yyout )
- yyout = stdout;
+ if ( ! yyout )
+ yyout = stdout;
- if ( ! YY_CURRENT_BUFFER ) {
- cmDependsJava_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
+ if ( ! YY_CURRENT_BUFFER ) {
+ cmDependsJava_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
- cmDependsJava_yy_load_buffer_state(yyscanner );
- }
+ cmDependsJava_yy_load_buffer_state(yyscanner );
+ }
- for(;;) /* loops until end-of-file is reached */
- {
- yy_cp = yyg->yy_c_buf_p;
+ {
+#line 48 "cmDependsJavaLexer.in.l"
- /* Support of yytext. */
- *yy_cp = yyg->yy_hold_char;
+#line 943 "cmDependsJavaLexer.cxx"
- /* yy_bp points to the position in yy_ch_buf of the start of
- * the current run.
- */
- yy_bp = yy_cp;
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
- yy_current_state = yyg->yy_start;
+ /* 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 >= 327 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 414 );
+ 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 >= 327 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 414 );
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;
+ 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
-#line 89 "cmDependsJavaLexer.in.l"
+#line 49 "cmDependsJavaLexer.in.l"
{ BEGIN(comment); }
- YY_BREAK
+ YY_BREAK
case 2:
YY_RULE_SETUP
-#line 90 "cmDependsJavaLexer.in.l"
+#line 50 "cmDependsJavaLexer.in.l"
{ BEGIN(INITIAL); }
- YY_BREAK
+ YY_BREAK
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
-#line 91 "cmDependsJavaLexer.in.l"
+#line 51 "cmDependsJavaLexer.in.l"
{}
- YY_BREAK
+ YY_BREAK
case 4:
YY_RULE_SETUP
-#line 93 "cmDependsJavaLexer.in.l"
+#line 53 "cmDependsJavaLexer.in.l"
{ BEGIN(string); }
- YY_BREAK
+ YY_BREAK
case 5:
YY_RULE_SETUP
-#line 94 "cmDependsJavaLexer.in.l"
+#line 54 "cmDependsJavaLexer.in.l"
{ BEGIN(INITIAL); return jp_STRINGLITERAL; }
+ YY_BREAK
case 6:
YY_RULE_SETUP
-#line 95 "cmDependsJavaLexer.in.l"
+#line 55 "cmDependsJavaLexer.in.l"
{}
- YY_BREAK
+ YY_BREAK
case 7:
YY_RULE_SETUP
-#line 97 "cmDependsJavaLexer.in.l"
+#line 57 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_ABSTRACT; }
+ YY_BREAK
case 8:
YY_RULE_SETUP
-#line 98 "cmDependsJavaLexer.in.l"
+#line 58 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_ASSERT; }
+ YY_BREAK
case 9:
YY_RULE_SETUP
-#line 99 "cmDependsJavaLexer.in.l"
+#line 59 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_BOOLEAN_TYPE; }
+ YY_BREAK
case 10:
YY_RULE_SETUP
-#line 100 "cmDependsJavaLexer.in.l"
+#line 60 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_BREAK; }
+ YY_BREAK
case 11:
YY_RULE_SETUP
-#line 101 "cmDependsJavaLexer.in.l"
+#line 61 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_BYTE_TYPE; }
+ YY_BREAK
case 12:
YY_RULE_SETUP
-#line 102 "cmDependsJavaLexer.in.l"
+#line 62 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CASE; }
+ YY_BREAK
case 13:
YY_RULE_SETUP
-#line 103 "cmDependsJavaLexer.in.l"
+#line 63 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CATCH; }
+ YY_BREAK
case 14:
YY_RULE_SETUP
-#line 104 "cmDependsJavaLexer.in.l"
+#line 64 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CHAR_TYPE; }
+ YY_BREAK
case 15:
YY_RULE_SETUP
-#line 105 "cmDependsJavaLexer.in.l"
+#line 65 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CLASS; }
+ YY_BREAK
case 16:
YY_RULE_SETUP
-#line 106 "cmDependsJavaLexer.in.l"
+#line 66 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CONTINUE; }
+ YY_BREAK
case 17:
YY_RULE_SETUP
-#line 107 "cmDependsJavaLexer.in.l"
+#line 67 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_DEFAULT; }
+ YY_BREAK
case 18:
YY_RULE_SETUP
-#line 108 "cmDependsJavaLexer.in.l"
+#line 68 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_DO; }
+ YY_BREAK
case 19:
YY_RULE_SETUP
-#line 109 "cmDependsJavaLexer.in.l"
+#line 69 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_DOUBLE_TYPE; }
+ YY_BREAK
case 20:
YY_RULE_SETUP
-#line 110 "cmDependsJavaLexer.in.l"
+#line 70 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_ELSE; }
+ YY_BREAK
case 21:
YY_RULE_SETUP
-#line 111 "cmDependsJavaLexer.in.l"
+#line 71 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_EXTENDS; }
+ YY_BREAK
case 22:
YY_RULE_SETUP
-#line 112 "cmDependsJavaLexer.in.l"
+#line 72 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FINAL; }
+ YY_BREAK
case 23:
YY_RULE_SETUP
-#line 113 "cmDependsJavaLexer.in.l"
+#line 73 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FINALLY; }
+ YY_BREAK
case 24:
YY_RULE_SETUP
-#line 114 "cmDependsJavaLexer.in.l"
+#line 74 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FLOAT_TYPE; }
+ YY_BREAK
case 25:
YY_RULE_SETUP
-#line 115 "cmDependsJavaLexer.in.l"
+#line 75 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FOR; }
+ YY_BREAK
case 26:
YY_RULE_SETUP
-#line 116 "cmDependsJavaLexer.in.l"
+#line 76 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_IF; }
+ YY_BREAK
case 27:
YY_RULE_SETUP
-#line 117 "cmDependsJavaLexer.in.l"
+#line 77 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_IMPLEMENTS; }
+ YY_BREAK
case 28:
YY_RULE_SETUP
-#line 118 "cmDependsJavaLexer.in.l"
+#line 78 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_IMPORT; }
+ YY_BREAK
case 29:
YY_RULE_SETUP
-#line 119 "cmDependsJavaLexer.in.l"
+#line 79 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_INSTANCEOF; }
+ YY_BREAK
case 30:
YY_RULE_SETUP
-#line 120 "cmDependsJavaLexer.in.l"
+#line 80 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_INT_TYPE; }
+ YY_BREAK
case 31:
YY_RULE_SETUP
-#line 121 "cmDependsJavaLexer.in.l"
+#line 81 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_INTERFACE; }
+ YY_BREAK
case 32:
YY_RULE_SETUP
-#line 122 "cmDependsJavaLexer.in.l"
+#line 82 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_LONG_TYPE; }
+ YY_BREAK
case 33:
YY_RULE_SETUP
-#line 123 "cmDependsJavaLexer.in.l"
+#line 83 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_NATIVE; }
+ YY_BREAK
case 34:
YY_RULE_SETUP
-#line 124 "cmDependsJavaLexer.in.l"
+#line 84 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_NEW; }
+ YY_BREAK
case 35:
YY_RULE_SETUP
-#line 125 "cmDependsJavaLexer.in.l"
+#line 85 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PACKAGE; }
+ YY_BREAK
case 36:
YY_RULE_SETUP
-#line 126 "cmDependsJavaLexer.in.l"
+#line 86 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PRIVATE; }
+ YY_BREAK
case 37:
YY_RULE_SETUP
-#line 127 "cmDependsJavaLexer.in.l"
+#line 87 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PROTECTED; }
+ YY_BREAK
case 38:
YY_RULE_SETUP
-#line 128 "cmDependsJavaLexer.in.l"
+#line 88 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PUBLIC; }
+ YY_BREAK
case 39:
YY_RULE_SETUP
-#line 129 "cmDependsJavaLexer.in.l"
+#line 89 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_RETURN; }
+ YY_BREAK
case 40:
YY_RULE_SETUP
-#line 130 "cmDependsJavaLexer.in.l"
+#line 90 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SHORT_TYPE; }
+ YY_BREAK
case 41:
YY_RULE_SETUP
-#line 131 "cmDependsJavaLexer.in.l"
+#line 91 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_STATIC; }
+ YY_BREAK
case 42:
YY_RULE_SETUP
-#line 132 "cmDependsJavaLexer.in.l"
+#line 92 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_STRICTFP; }
+ YY_BREAK
case 43:
YY_RULE_SETUP
-#line 133 "cmDependsJavaLexer.in.l"
+#line 93 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SUPER; }
+ YY_BREAK
case 44:
YY_RULE_SETUP
-#line 134 "cmDependsJavaLexer.in.l"
+#line 94 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SWITCH; }
+ YY_BREAK
case 45:
YY_RULE_SETUP
-#line 135 "cmDependsJavaLexer.in.l"
+#line 95 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SYNCHRONIZED; }
+ YY_BREAK
case 46:
YY_RULE_SETUP
-#line 136 "cmDependsJavaLexer.in.l"
+#line 96 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_THIS; }
+ YY_BREAK
case 47:
YY_RULE_SETUP
-#line 137 "cmDependsJavaLexer.in.l"
+#line 97 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_THROW; }
+ YY_BREAK
case 48:
YY_RULE_SETUP
-#line 138 "cmDependsJavaLexer.in.l"
+#line 98 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_THROWS; }
+ YY_BREAK
case 49:
YY_RULE_SETUP
-#line 139 "cmDependsJavaLexer.in.l"
+#line 99 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_TRANSIENT; }
+ YY_BREAK
case 50:
YY_RULE_SETUP
-#line 140 "cmDependsJavaLexer.in.l"
+#line 100 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_TRY; }
+ YY_BREAK
case 51:
YY_RULE_SETUP
-#line 141 "cmDependsJavaLexer.in.l"
+#line 101 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_VOID; }
+ YY_BREAK
case 52:
YY_RULE_SETUP
-#line 142 "cmDependsJavaLexer.in.l"
+#line 102 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_VOLATILE; }
+ YY_BREAK
case 53:
YY_RULE_SETUP
-#line 143 "cmDependsJavaLexer.in.l"
+#line 103 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_WHILE; }
+ YY_BREAK
case 54:
YY_RULE_SETUP
-#line 145 "cmDependsJavaLexer.in.l"
+#line 105 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_BOOLEANLITERAL; }
+ YY_BREAK
case 55:
/* rule 55 can match eol */
YY_RULE_SETUP
-#line 146 "cmDependsJavaLexer.in.l"
+#line 106 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_CHARACTERLITERAL; }
+ YY_BREAK
case 56:
YY_RULE_SETUP
-#line 147 "cmDependsJavaLexer.in.l"
+#line 107 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_DECIMALINTEGERLITERAL; }
+ YY_BREAK
case 57:
YY_RULE_SETUP
-#line 148 "cmDependsJavaLexer.in.l"
+#line 108 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_FLOATINGPOINTLITERAL; }
+ YY_BREAK
case 58:
YY_RULE_SETUP
-#line 149 "cmDependsJavaLexer.in.l"
+#line 109 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_HEXINTEGERLITERAL; }
+ YY_BREAK
case 59:
YY_RULE_SETUP
-#line 150 "cmDependsJavaLexer.in.l"
+#line 110 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_NULLLITERAL; }
+ YY_BREAK
case 60:
YY_RULE_SETUP
-#line 152 "cmDependsJavaLexer.in.l"
+#line 112 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_AND; }
+ YY_BREAK
case 61:
YY_RULE_SETUP
-#line 153 "cmDependsJavaLexer.in.l"
+#line 113 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_ANDAND; }
+ YY_BREAK
case 62:
YY_RULE_SETUP
-#line 154 "cmDependsJavaLexer.in.l"
+#line 114 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_ANDEQUALS; }
+ YY_BREAK
case 63:
YY_RULE_SETUP
-#line 155 "cmDependsJavaLexer.in.l"
+#line 115 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_BRACKETEND; }
+ YY_BREAK
case 64:
YY_RULE_SETUP
-#line 156 "cmDependsJavaLexer.in.l"
+#line 116 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_BRACKETSTART; }
+ YY_BREAK
case 65:
YY_RULE_SETUP
-#line 157 "cmDependsJavaLexer.in.l"
+#line 117 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CARROT; }
+ YY_BREAK
case 66:
YY_RULE_SETUP
-#line 158 "cmDependsJavaLexer.in.l"
+#line 118 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CARROTEQUALS; }
+ YY_BREAK
case 67:
YY_RULE_SETUP
-#line 159 "cmDependsJavaLexer.in.l"
+#line 119 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_COLON; }
+ YY_BREAK
case 68:
YY_RULE_SETUP
-#line 160 "cmDependsJavaLexer.in.l"
+#line 120 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_COMMA; }
+ YY_BREAK
case 69:
YY_RULE_SETUP
-#line 161 "cmDependsJavaLexer.in.l"
+#line 121 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CURLYEND; }
+ YY_BREAK
case 70:
YY_RULE_SETUP
-#line 162 "cmDependsJavaLexer.in.l"
+#line 122 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CURLYSTART; }
+ YY_BREAK
case 71:
YY_RULE_SETUP
-#line 163 "cmDependsJavaLexer.in.l"
+#line 123 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DIVIDE; }
+ YY_BREAK
case 72:
YY_RULE_SETUP
-#line 164 "cmDependsJavaLexer.in.l"
+#line 124 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DIVIDEEQUALS; }
+ YY_BREAK
case 73:
YY_RULE_SETUP
-#line 165 "cmDependsJavaLexer.in.l"
+#line 125 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DOLLAR; }
+ YY_BREAK
case 74:
YY_RULE_SETUP
-#line 166 "cmDependsJavaLexer.in.l"
+#line 126 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DOT; }
+ YY_BREAK
case 75:
YY_RULE_SETUP
-#line 167 "cmDependsJavaLexer.in.l"
+#line 127 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EQUALS; }
+ YY_BREAK
case 76:
YY_RULE_SETUP
-#line 168 "cmDependsJavaLexer.in.l"
+#line 128 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EQUALSEQUALS; }
+ YY_BREAK
case 77:
YY_RULE_SETUP
-#line 169 "cmDependsJavaLexer.in.l"
+#line 129 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EXCLAMATION; }
+ YY_BREAK
case 78:
YY_RULE_SETUP
-#line 170 "cmDependsJavaLexer.in.l"
+#line 130 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EXCLAMATIONEQUALS; }
+ YY_BREAK
case 79:
YY_RULE_SETUP
-#line 171 "cmDependsJavaLexer.in.l"
+#line 131 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GREATER; }
+ YY_BREAK
case 80:
YY_RULE_SETUP
-#line 172 "cmDependsJavaLexer.in.l"
+#line 132 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTEQUALS; }
+ YY_BREAK
case 81:
YY_RULE_SETUP
-#line 173 "cmDependsJavaLexer.in.l"
+#line 133 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGT; }
+ YY_BREAK
case 82:
YY_RULE_SETUP
-#line 174 "cmDependsJavaLexer.in.l"
+#line 134 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGTEQUALS; }
+ YY_BREAK
case 83:
YY_RULE_SETUP
-#line 175 "cmDependsJavaLexer.in.l"
+#line 135 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGTGT; }
+ YY_BREAK
case 84:
YY_RULE_SETUP
-#line 176 "cmDependsJavaLexer.in.l"
+#line 136 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGTGTEQUALS; }
+ YY_BREAK
case 85:
YY_RULE_SETUP
-#line 177 "cmDependsJavaLexer.in.l"
+#line 137 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LESLESEQUALS; }
+ YY_BREAK
case 86:
YY_RULE_SETUP
-#line 178 "cmDependsJavaLexer.in.l"
+#line 138 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LESSTHAN; }
+ YY_BREAK
case 87:
YY_RULE_SETUP
-#line 179 "cmDependsJavaLexer.in.l"
+#line 139 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LTEQUALS; }
+ YY_BREAK
case 88:
YY_RULE_SETUP
-#line 180 "cmDependsJavaLexer.in.l"
+#line 140 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LTLT; }
+ YY_BREAK
case 89:
YY_RULE_SETUP
-#line 181 "cmDependsJavaLexer.in.l"
+#line 141 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_MINUS; }
+ YY_BREAK
case 90:
YY_RULE_SETUP
-#line 182 "cmDependsJavaLexer.in.l"
+#line 142 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_MINUSEQUALS; }
+ YY_BREAK
case 91:
YY_RULE_SETUP
-#line 183 "cmDependsJavaLexer.in.l"
+#line 143 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_MINUSMINUS; }
+ YY_BREAK
case 92:
YY_RULE_SETUP
-#line 184 "cmDependsJavaLexer.in.l"
+#line 144 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PAREEND; }
+ YY_BREAK
case 93:
YY_RULE_SETUP
-#line 185 "cmDependsJavaLexer.in.l"
+#line 145 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PARESTART; }
+ YY_BREAK
case 94:
YY_RULE_SETUP
-#line 186 "cmDependsJavaLexer.in.l"
+#line 146 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PERCENT; }
+ YY_BREAK
case 95:
YY_RULE_SETUP
-#line 187 "cmDependsJavaLexer.in.l"
+#line 147 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PERCENTEQUALS; }
+ YY_BREAK
case 96:
YY_RULE_SETUP
-#line 188 "cmDependsJavaLexer.in.l"
+#line 148 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PIPE; }
+ YY_BREAK
case 97:
YY_RULE_SETUP
-#line 189 "cmDependsJavaLexer.in.l"
+#line 149 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PIPEEQUALS; }
+ YY_BREAK
case 98:
YY_RULE_SETUP
-#line 190 "cmDependsJavaLexer.in.l"
+#line 150 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PIPEPIPE; }
+ YY_BREAK
case 99:
YY_RULE_SETUP
-#line 191 "cmDependsJavaLexer.in.l"
+#line 151 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PLUS; }
+ YY_BREAK
case 100:
YY_RULE_SETUP
-#line 192 "cmDependsJavaLexer.in.l"
+#line 152 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PLUSEQUALS; }
+ YY_BREAK
case 101:
YY_RULE_SETUP
-#line 193 "cmDependsJavaLexer.in.l"
+#line 153 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PLUSPLUS; }
+ YY_BREAK
case 102:
YY_RULE_SETUP
-#line 194 "cmDependsJavaLexer.in.l"
+#line 154 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_QUESTION; }
+ YY_BREAK
case 103:
YY_RULE_SETUP
-#line 195 "cmDependsJavaLexer.in.l"
+#line 155 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_SEMICOL; }
+ YY_BREAK
case 104:
YY_RULE_SETUP
-#line 196 "cmDependsJavaLexer.in.l"
+#line 156 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_TILDE; }
+ YY_BREAK
case 105:
YY_RULE_SETUP
-#line 197 "cmDependsJavaLexer.in.l"
+#line 157 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_TIMES; }
+ YY_BREAK
case 106:
YY_RULE_SETUP
-#line 198 "cmDependsJavaLexer.in.l"
+#line 158 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_TIMESEQUALS; }
+ YY_BREAK
case 107:
YY_RULE_SETUP
-#line 200 "cmDependsJavaLexer.in.l"
+#line 160 "cmDependsJavaLexer.in.l"
{
yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
return jp_NAME;
}
+ YY_BREAK
case 108:
/* rule 108 can match eol */
YY_RULE_SETUP
-#line 205 "cmDependsJavaLexer.in.l"
+#line 165 "cmDependsJavaLexer.in.l"
{ }
- YY_BREAK
+ YY_BREAK
case 109:
/* rule 109 can match eol */
YY_RULE_SETUP
-#line 206 "cmDependsJavaLexer.in.l"
+#line 166 "cmDependsJavaLexer.in.l"
{ }
- YY_BREAK
+ YY_BREAK
case 110:
YY_RULE_SETUP
-#line 207 "cmDependsJavaLexer.in.l"
+#line 167 "cmDependsJavaLexer.in.l"
{
std::cerr << "Unknown character: " << yytext[0]
<< " (" << (int)yytext[0] << ")" << std::endl;
yyextra->Error("Unknown character");
return jp_ERROR;
}
+ YY_BREAK
case 111:
YY_RULE_SETUP
-#line 214 "cmDependsJavaLexer.in.l"
+#line 174 "cmDependsJavaLexer.in.l"
ECHO;
- YY_BREAK
-#line 1590 "cmDependsJavaLexer.cxx"
+ YY_BREAK
+#line 1567 "cmDependsJavaLexer.cxx"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(comment):
case YY_STATE_EOF(string):
- yyterminate();
-
- 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
- * cmDependsJava_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 ( cmDependsJava_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 */
-return 0; /* this should not happen but it silences a warning*/
+ yyterminate();
+
+ 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
+ * cmDependsJava_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 ( cmDependsJava_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 cmDependsJava_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
+ * 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
- {
- size_t nuto_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
- while ( nuto_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;
-
- 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. */
- cmDependsJava_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- 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];
-
- nuto_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
-
- }
-
- if ( nuto_read > YY_READ_BUF_SIZE )
- nuto_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, nuto_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;
- cmDependsJava_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;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ yy_size_t 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 = (yy_size_t) (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. */
+ cmDependsJava_yyrealloc((void *) b->yy_ch_buf,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;
+ cmDependsJava_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 ((int) (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 );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ 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];
- 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;
+ 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;
+ 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 >= 327 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- }
-
- return yy_current_state;
+ 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 >= 327 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) 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 );
+ * 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;
+ 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 >= 327 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 326);
+
+ (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;
- 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 >= 327 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 326);
+ 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" );
+ }
- return yy_is_jam ? 0 : yy_current_state;
+ *--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)
@@ -1793,72 +1950,72 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
#endif
{
- int c;
+ 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 = 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. */
- cmDependsJava_yyrestart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( cmDependsJava_yywrap(yyscanner ) )
- return EOF;
-
- if ( ! yyg->yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
+ *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 = 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. */
+ cmDependsJava_yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( cmDependsJava_yywrap(yyscanner ) )
+ return 0;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
#ifdef __cplusplus
- return yyinput(yyscanner);
+ return yyinput(yyscanner);
#else
- return input(yyscanner);
+ return input(yyscanner);
#endif
- }
+ }
- case EOB_ACT_CONTINUE_SCAN:
- yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
- break;
- }
- }
- }
+ 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;
+ 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;
+ return c;
}
-#endif /* ifndef YY_NO_INPUT */
+#endif /* ifndef YY_NO_INPUT */
/** Immediately switch to a different input stream.
* @param input_file A readable stream.
@@ -1869,14 +2026,14 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if ( ! YY_CURRENT_BUFFER ){
+ if ( ! YY_CURRENT_BUFFER ){
cmDependsJava_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
+ YY_CURRENT_BUFFER_LVALUE =
cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
+ }
- cmDependsJava_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ cmDependsJava_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ cmDependsJava_yy_load_buffer_state(yyscanner );
}
/** Switch to a different input buffer.
@@ -1887,41 +2044,41 @@ static int yy_get_next_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);
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * cmDependsJava_yypop_buffer_state();
+ * cmDependsJava_yypush_buffer_state(new_buffer);
*/
- cmDependsJava_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;
- cmDependsJava_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
- * to go ahead and always set it.
- */
- yyg->yy_did_buffer_switch_on_eof = 1;
+ cmDependsJava_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;
+ cmDependsJava_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
+ * 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)
{
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;
+ 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.
@@ -1932,26 +2089,26 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
*/
YY_BUFFER_STATE cmDependsJava_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
- YY_BUFFER_STATE b;
+ YY_BUFFER_STATE b;
- b = (YY_BUFFER_STATE) cmDependsJava_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_create_buffer()" );
+ b = (YY_BUFFER_STATE) cmDependsJava_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_create_buffer()" );
- b->yy_buf_size = size;
+ b->yy_buf_size = (yy_size_t)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 );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_create_buffer()" );
+ /* 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 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_create_buffer()" );
- b->yy_is_our_buffer = 1;
+ b->yy_is_our_buffer = 1;
- cmDependsJava_yy_init_buffer(b,file ,yyscanner);
+ cmDependsJava_yy_init_buffer(b,file ,yyscanner);
- return b;
+ return b;
}
/** Destroy the buffer.
@@ -1962,22 +2119,18 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if ( ! b )
- return;
+ 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_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
- if ( b->yy_is_our_buffer )
- cmDependsJava_yyfree((void *) b->yy_ch_buf ,yyscanner );
+ if ( b->yy_is_our_buffer )
+ cmDependsJava_yyfree((void *) b->yy_ch_buf ,yyscanner );
- cmDependsJava_yyfree((void *) b ,yyscanner );
+ cmDependsJava_yyfree((void *) b ,yyscanner );
}
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-
/* 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.
@@ -1985,13 +2138,13 @@ extern int isatty (int );
static void cmDependsJava_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
{
- int oerrno = errno;
+ int oerrno = errno;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- cmDependsJava_yy_flush_buffer(b ,yyscanner);
+ cmDependsJava_yy_flush_buffer(b ,yyscanner);
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
+ 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.
@@ -2004,7 +2157,7 @@ extern int isatty (int );
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
- errno = oerrno;
+ errno = oerrno;
}
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
@@ -2014,25 +2167,25 @@ extern int isatty (int );
void cmDependsJava_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if ( ! b )
- return;
+ if ( ! b )
+ return;
- b->yy_n_chars = 0;
+ 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;
+ /* 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_buf_pos = &b->yy_ch_buf[0];
- b->yy_at_bol = 1;
- b->yy_buffer_status = YY_BUFFER_NEW;
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
- if ( b == YY_CURRENT_BUFFER )
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ if ( b == YY_CURRENT_BUFFER )
+ cmDependsJava_yy_load_buffer_state(yyscanner );
}
/** Pushes the new state onto the stack. The new state becomes
@@ -2044,28 +2197,28 @@ extern int isatty (int );
void cmDependsJava_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);
-
- /* This block is copied from cmDependsJava_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 cmDependsJava_yy_switch_to_buffer. */
- cmDependsJava_yy_load_buffer_state(yyscanner );
- yyg->yy_did_buffer_switch_on_eof = 1;
+ if (new_buffer == NULL)
+ return;
+
+ cmDependsJava_yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from cmDependsJava_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 cmDependsJava_yy_switch_to_buffer. */
+ cmDependsJava_yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
}
/** Removes and deletes the top of the stack, if present.
@@ -2075,18 +2228,18 @@ void cmDependsJava_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yy
void cmDependsJava_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_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 );
- yyg->yy_did_buffer_switch_on_eof = 1;
- }
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ cmDependsJava_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 );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
}
/* Allocates the stack if it does not exist.
@@ -2094,42 +2247,46 @@ void cmDependsJava_yypop_buffer_state (yyscan_t yyscanner)
*/
static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner)
{
- int nuto_alloc;
+ int num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (!yyg->yy_buffer_stack) {
+ 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.
+ /* 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.
*/
- nuto_alloc = 1;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsJava_yyalloc
- (nuto_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
-
- memset(yyg->yy_buffer_stack, 0, nuto_alloc * sizeof(struct yy_buffer_state*));
-
- yyg->yy_buffer_stack_max = nuto_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. */
- int grow_size = 8 /* arbitrary grow size */;
-
- nuto_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsJava_yyrealloc
- (yyg->yy_buffer_stack,
- nuto_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
-
- /* 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 = nuto_alloc;
- }
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsJava_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()" );
+
+ 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**)cmDependsJava_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()" );
+
+ /* 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.
@@ -2140,110 +2297,112 @@ static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner)
*/
YY_BUFFER_STATE cmDependsJava_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 0;
-
- b = (YY_BUFFER_STATE) cmDependsJava_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_scan_buffer()" );
-
- b->yy_buf_size = 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 = 0;
- 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;
-
- cmDependsJava_yy_switch_to_buffer(b ,yyscanner );
-
- return b;
+ 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) cmDependsJava_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_scan_buffer()" );
+
+ b->yy_buf_size = 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;
+
+ cmDependsJava_yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
}
/** Setup the input buffer state to scan a string. The next call to cmDependsJava_yylex() will
- * scan from a @e copy of @a yy_str.
- * @param yy_str a NUL-terminated string to scan
+ * 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_BUFFER_STATE cmDependsJava_yy_scan_string (yyconst char * yy_str , yyscan_t yyscanner)
+YY_BUFFER_STATE cmDependsJava_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{
- return cmDependsJava_yy_scan_bytes(yy_str,strlen(yy_str) ,yyscanner);
+ return cmDependsJava_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
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @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 * bytes, int len , yyscan_t yyscanner)
+YY_BUFFER_STATE cmDependsJava_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
- YY_BUFFER_STATE b;
- char *buf;
- yy_size_t n;
- int i;
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t i;
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
- buf = (char *) cmDependsJava_yyalloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_scan_bytes()" );
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = (yy_size_t) _yybytes_len + 2;
+ buf = (char *) cmDependsJava_yyalloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_scan_bytes()" );
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
+ for ( i = 0; i < (size_t)_yybytes_len; ++i )
+ buf[i] = yybytes[i];
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = cmDependsJava_yy_scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmDependsJava_yy_scan_bytes()" );
+ b = cmDependsJava_yy_scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in cmDependsJava_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;
+ /* 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;
+ return b;
}
#ifndef YY_EXIT_FAILURE
#define YY_EXIT_FAILURE 2
#endif
-static void yy_fatal_error (yyconst char* msg , yyscan_t)
+static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
{
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) 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. */ \
+ 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 )
+ 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. */
@@ -2330,51 +2489,51 @@ void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner
}
/** Set the current line number.
- * @param line_number
+ * @param _line_number line number
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yyset_lineno (int line_number , yyscan_t yyscanner)
+void cmDependsJava_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" , yyscanner);
+ YY_FATAL_ERROR( "cmDependsJava_yyset_lineno called with no buffer" );
- yylineno = line_number;
+ yylineno = _line_number;
}
/** Set the current column.
- * @param column_no
+ * @param _column_no column number
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yyset_column (int column_no , yyscan_t yyscanner)
+void cmDependsJava_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" , yyscanner);
+ YY_FATAL_ERROR( "cmDependsJava_yyset_column called with no buffer" );
- yycolumn = column_no;
+ yycolumn = _column_no;
}
/** Set the input stream. This does not discard the current
* input buffer.
- * @param in_str A readable stream.
+ * @param _in_str A readable stream.
* @param yyscanner The scanner object.
* @see cmDependsJava_yy_switch_to_buffer
*/
-void cmDependsJava_yyset_in (FILE * in_str , yyscan_t yyscanner)
+void cmDependsJava_yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = in_str ;
+ yyin = _in_str ;
}
-void cmDependsJava_yyset_out (FILE * out_str , yyscan_t yyscanner)
+void cmDependsJava_yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
+ yyout = _out_str ;
}
int cmDependsJava_yyget_debug (yyscan_t yyscanner)
@@ -2383,45 +2542,14 @@ int cmDependsJava_yyget_debug (yyscan_t yyscanner)
return yy_flex_debug;
}
-void cmDependsJava_yyset_debug (int bdebug , yyscan_t yyscanner)
+void cmDependsJava_yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
+ yy_flex_debug = _bdebug ;
}
/* Accessor methods for yylval and yylloc */
-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 once per scanner lifetime. */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- yyg->yy_init = 1;
- yyg->yy_start = 0;
- yyg->yy_start_stack_ptr = 0;
- yyg->yy_start_stack_depth = 0;
- yyg->yy_start_stack = (int *) 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
- yyin = stdin;
- yyout = stdout;
-#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * cmDependsJava_yylex_init()
- */
- return 0;
-}
-
/* User-visible API */
/* cmDependsJava_yylex_init is special because it creates the scanner itself, so it is
@@ -2444,33 +2572,108 @@ int cmDependsJava_yylex_init(yyscan_t* ptr_yy_globals)
return 1;
}
- memset(*ptr_yy_globals,0,sizeof(struct yyguts_t));
+ /* 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 );
}
+/* cmDependsJava_yylex_init_extra has the same functionality as cmDependsJava_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 yyextra field.
+ */
+
+int cmDependsJava_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);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmDependsJava_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));
+
+ cmDependsJava_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 cmDependsJava_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
+ * cmDependsJava_yylex_init()
+ */
+ return 0;
+}
+
/* cmDependsJava_yylex_destroy is for both reentrant and non-reentrant scanners. */
int cmDependsJava_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_CURRENT_BUFFER_LVALUE = NULL;
- cmDependsJava_yypop_buffer_state(yyscanner);
- }
+ while(YY_CURRENT_BUFFER){
+ cmDependsJava_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ cmDependsJava_yypop_buffer_state(yyscanner);
+ }
- /* Destroy the stack itself. */
- cmDependsJava_yyfree(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
+ /* Destroy the stack itself. */
+ cmDependsJava_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
/* Destroy the start condition stack. */
cmDependsJava_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. */
+ yy_init_globals( yyscanner);
+
/* Destroy the main struct (reentrant only). */
cmDependsJava_yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
return 0;
}
@@ -2481,62 +2684,55 @@ 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)
{
- int i;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
+ 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 (yyconst char * s , yyscan_t yyscanner)
{
- int n;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- for ( n = 0; s[n]; ++n )
- ;
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
- return n;
+ return n;
}
#endif
-void *cmDependsJava_yyalloc (yy_size_t size , yyscan_t)
+void *cmDependsJava_yyalloc (yy_size_t size , yyscan_t yyscanner)
{
- return (void *) malloc( size );
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ return malloc(size);
}
-void *cmDependsJava_yyrealloc (void * ptr, yy_size_t size , yyscan_t)
+void *cmDependsJava_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
- /* 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 (void *) realloc( (char *) ptr, size );
+ 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 cmDependsJava_yyfree (void * ptr , yyscan_t)
+void cmDependsJava_yyfree (void * ptr , yyscan_t yyscanner)
{
- free( (char *) ptr ); /* see cmDependsJava_yyrealloc() for (char *) cast */
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ free( (char *) ptr ); /* see cmDependsJava_yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-#line 214 "cmDependsJavaLexer.in.l"
-
-
-
+#line 174 "cmDependsJavaLexer.in.l"
diff --git a/Source/cmDependsJavaLexer.h b/Source/LexerParser/cmDependsJavaLexer.h
index 61aa66de2..ccadd70b9 100644
--- a/Source/cmDependsJavaLexer.h
+++ b/Source/LexerParser/cmDependsJavaLexer.h
@@ -1,26 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
#ifndef cmDependsJava_yyHEADER_H
#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
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -33,10 +27,6 @@
#include <errno.h>
#include <stdlib.h>
-#if defined(__BEOS__) || defined(__HAIKU__)
-#include <unistd.h> /* prevents a conflict with a #define later on... */
-#endif
-
/* end standard C headers. */
/* flex integer type definitions */
@@ -46,7 +36,15 @@
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#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;
@@ -61,7 +59,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -92,26 +89,17 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_CONST
+#endif /* ! C99 */
-#endif /* __STDC__ */
-#endif /* ! __cplusplus */
+#endif /* ! FLEXINT_H */
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* An opaque pointer. */
@@ -131,91 +119,91 @@ typedef void* yyscan_t;
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
-int cmDependsJava_yylex_init (yyscan_t* scanner);
+/* 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
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int 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.
- */
- yy_size_t 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;
+ {
+ 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;
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
- int yy_buffer_status;
+ int yy_buffer_status;
- };
+ };
#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_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_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
void cmDependsJava_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 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 );
void *cmDependsJava_yyalloc (yy_size_t ,yyscan_t yyscanner );
void *cmDependsJava_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
@@ -223,7 +211,7 @@ void cmDependsJava_yyfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
-#define cmDependsJava_yywrap(n) 1
+#define cmDependsJava_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
@@ -239,6 +227,10 @@ void cmDependsJava_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
+int cmDependsJava_yylex_init (yyscan_t* scanner);
+
+int cmDependsJava_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. */
@@ -250,24 +242,27 @@ void cmDependsJava_yyset_debug (int debug_flag ,yyscan_t yyscanner );
YY_EXTRA_TYPE cmDependsJava_yyget_extra (yyscan_t yyscanner );
-void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined ,
- yyscan_t yyscanner );
+void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *cmDependsJava_yyget_in (yyscan_t yyscanner );
-void cmDependsJava_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+void cmDependsJava_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *cmDependsJava_yyget_out (yyscan_t yyscanner );
-void cmDependsJava_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+void cmDependsJava_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
-int cmDependsJava_yyget_leng (yyscan_t yyscanner );
+ int cmDependsJava_yyget_leng (yyscan_t yyscanner );
char *cmDependsJava_yyget_text (yyscan_t yyscanner );
int cmDependsJava_yyget_lineno (yyscan_t yyscanner );
-void cmDependsJava_yyset_lineno (int line_number ,yyscan_t yyscanner );
+void cmDependsJava_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmDependsJava_yyget_column (yyscan_t yyscanner );
+
+void cmDependsJava_yyset_column (int _column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -295,7 +290,12 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
/* 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. */
@@ -314,15 +314,13 @@ extern int cmDependsJava_yylex (yyscan_t yyscanner);
#define YY_DECL int cmDependsJava_yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
-/* yy_get_previous_state - get the state just before the
- EOB char was reached */
+/* 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 yytext_ptr
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
@@ -330,5 +328,9 @@ extern int cmDependsJava_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
+#line 174 "cmDependsJavaLexer.in.l"
+
+
+#line 335 "cmDependsJavaLexer.h"
#undef cmDependsJava_yyIN_HEADER
#endif /* cmDependsJava_yyHEADER_H */
diff --git a/Source/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l
index aa2f8a587..8cb42b17a 100644
--- a/Source/cmDependsJavaLexer.in.l
+++ b/Source/LexerParser/cmDependsJavaLexer.in.l
@@ -1,40 +1,25 @@
%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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.
+This file must be translated to C++ and modified to build everywhere.
-Run flex like this:
+Run flex >= 2.6 like this:
- flex --prefix=cmDependsJava_yy --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
+ flex --nounistd -DFLEXINT_H --prefix=cmDependsJava_yy --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
-Modify cmDependsJavaLexer.c:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmDependsJava_yyalloc, cmDependsJava_yyrealloc, cmDependsJava_yyfree
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
-
-Modify cmDependsJavaLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
+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
*/
-#include "cmStandardLexer.h"
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#include <iostream>
#include "cmDependsJavaParserHelper.h"
@@ -179,7 +164,7 @@ null { PRIMITIVE; return jp_NULLLITERAL; }
\/\/.*\n { }
[ \f\t\n\r] { }
-. {
+. {
std::cerr << "Unknown character: " << yytext[0]
<< " (" << (int)yytext[0] << ")" << std::endl;
yyextra->Error("Unknown character");
diff --git a/Source/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx
index 586c0debe..bc45d45e1 100644
--- a/Source/cmDependsJavaParser.cxx
+++ b/Source/LexerParser/cmDependsJavaParser.cxx
@@ -1,12 +1,13 @@
-/* A Bison parser, made by GNU Bison 1.875d. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
- 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Bison implementation for Yacc-like parsers in C
- This program is free software; you can redistribute it and/or modify
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,17 +15,23 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
-/* Written by Richard Stallman by simplifying the original so called
- ``semantic'' parser. */
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
@@ -33,145 +40,223 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
-/* turn off some warning as this is generated code */
-#if defined(_MSC_VER)
-# pragma warning ( disable : 4702 ) /* unreachable code */
-#endif
-
/* Identify Bison output. */
#define YYBISON 1
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
/* Pure parsers. */
#define YYPURE 1
-/* Using locations. */
-#define YYLSP_NEEDED 0
+/* Push parsers. */
+#define YYPUSH 0
-/* If NAME_PREFIX is specified substitute the variables and functions
- names. */
-#define yyparse cmDependsJava_yyparse
-#define yylex cmDependsJava_yylex
-#define yyerror cmDependsJava_yyerror
-#define yylval cmDependsJava_yylval
-#define yychar cmDependsJava_yychar
-#define yydebug cmDependsJava_yydebug
-#define yynerrs cmDependsJava_yynerrs
+/* Pull parsers. */
+#define YYPULL 1
-/* Tokens. */
+/* Substitute the variable and function names. */
+#define yyparse cmDependsJava_yyparse
+#define yylex cmDependsJava_yylex
+#define yyerror cmDependsJava_yyerror
+#define yydebug cmDependsJava_yydebug
+#define yynerrs cmDependsJava_yynerrs
+
+
+/* Copy the first part of user declarations. */
+#line 1 "cmDependsJavaParser.y" /* yacc.c:339 */
+
+/* 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 bison like this:
+
+ bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
+
+Modify cmDependsJavaParser.cxx:
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
+
+/*-------------------------------------------------------------------------*/
+#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */
+#include "cmDependsJavaLexer.h" /* Interface to lexer object. */
+#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+
+/* Forward declare the lexer entry point. */
+YY_DECL;
+
+/* Helper function to forward error callback from parser. */
+static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
+
+#define YYMAXDEPTH 1000000
+
+
+#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. */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label. */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+
+#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "cmDependsJavaParserTokens.h". */
+#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmDependsJava_yydebug;
+#endif
+
+/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- jp_ABSTRACT = 258,
- jp_ASSERT = 259,
- jp_BOOLEAN_TYPE = 260,
- jp_BREAK = 261,
- jp_BYTE_TYPE = 262,
- jp_CASE = 263,
- jp_CATCH = 264,
- jp_CHAR_TYPE = 265,
- jp_CLASS = 266,
- jp_CONTINUE = 267,
- jp_DEFAULT = 268,
- jp_DO = 269,
- jp_DOUBLE_TYPE = 270,
- jp_ELSE = 271,
- jp_EXTENDS = 272,
- jp_FINAL = 273,
- jp_FINALLY = 274,
- jp_FLOAT_TYPE = 275,
- jp_FOR = 276,
- jp_IF = 277,
- jp_IMPLEMENTS = 278,
- jp_IMPORT = 279,
- jp_INSTANCEOF = 280,
- jp_INT_TYPE = 281,
- jp_INTERFACE = 282,
- jp_LONG_TYPE = 283,
- jp_NATIVE = 284,
- jp_NEW = 285,
- jp_PACKAGE = 286,
- jp_PRIVATE = 287,
- jp_PROTECTED = 288,
- jp_PUBLIC = 289,
- jp_RETURN = 290,
- jp_SHORT_TYPE = 291,
- jp_STATIC = 292,
- jp_STRICTFP = 293,
- jp_SUPER = 294,
- jp_SWITCH = 295,
- jp_SYNCHRONIZED = 296,
- jp_THIS = 297,
- jp_THROW = 298,
- jp_THROWS = 299,
- jp_TRANSIENT = 300,
- jp_TRY = 301,
- jp_VOID = 302,
- jp_VOLATILE = 303,
- jp_WHILE = 304,
- jp_BOOLEANLITERAL = 305,
- jp_CHARACTERLITERAL = 306,
- jp_DECIMALINTEGERLITERAL = 307,
- jp_FLOATINGPOINTLITERAL = 308,
- jp_HEXINTEGERLITERAL = 309,
- jp_NULLLITERAL = 310,
- jp_STRINGLITERAL = 311,
- jp_NAME = 312,
- jp_AND = 313,
- jp_ANDAND = 314,
- jp_ANDEQUALS = 315,
- jp_BRACKETEND = 316,
- jp_BRACKETSTART = 317,
- jp_CARROT = 318,
- jp_CARROTEQUALS = 319,
- jp_COLON = 320,
- jp_COMMA = 321,
- jp_CURLYEND = 322,
- jp_CURLYSTART = 323,
- jp_DIVIDE = 324,
- jp_DIVIDEEQUALS = 325,
- jp_DOLLAR = 326,
- jp_DOT = 327,
- jp_EQUALS = 328,
- jp_EQUALSEQUALS = 329,
- jp_EXCLAMATION = 330,
- jp_EXCLAMATIONEQUALS = 331,
- jp_GREATER = 332,
- jp_GTEQUALS = 333,
- jp_GTGT = 334,
- jp_GTGTEQUALS = 335,
- jp_GTGTGT = 336,
- jp_GTGTGTEQUALS = 337,
- jp_LESLESEQUALS = 338,
- jp_LESSTHAN = 339,
- jp_LTEQUALS = 340,
- jp_LTLT = 341,
- jp_MINUS = 342,
- jp_MINUSEQUALS = 343,
- jp_MINUSMINUS = 344,
- jp_PAREEND = 345,
- jp_PARESTART = 346,
- jp_PERCENT = 347,
- jp_PERCENTEQUALS = 348,
- jp_PIPE = 349,
- jp_PIPEEQUALS = 350,
- jp_PIPEPIPE = 351,
- jp_PLUS = 352,
- jp_PLUSEQUALS = 353,
- jp_PLUSPLUS = 354,
- jp_QUESTION = 355,
- jp_SEMICOL = 356,
- jp_TILDE = 357,
- jp_TIMES = 358,
- jp_TIMESEQUALS = 359,
- jp_ERROR = 360
- };
+ enum yytokentype
+ {
+ jp_ABSTRACT = 258,
+ jp_ASSERT = 259,
+ jp_BOOLEAN_TYPE = 260,
+ jp_BREAK = 261,
+ jp_BYTE_TYPE = 262,
+ jp_CASE = 263,
+ jp_CATCH = 264,
+ jp_CHAR_TYPE = 265,
+ jp_CLASS = 266,
+ jp_CONTINUE = 267,
+ jp_DEFAULT = 268,
+ jp_DO = 269,
+ jp_DOUBLE_TYPE = 270,
+ jp_ELSE = 271,
+ jp_EXTENDS = 272,
+ jp_FINAL = 273,
+ jp_FINALLY = 274,
+ jp_FLOAT_TYPE = 275,
+ jp_FOR = 276,
+ jp_IF = 277,
+ jp_IMPLEMENTS = 278,
+ jp_IMPORT = 279,
+ jp_INSTANCEOF = 280,
+ jp_INT_TYPE = 281,
+ jp_INTERFACE = 282,
+ jp_LONG_TYPE = 283,
+ jp_NATIVE = 284,
+ jp_NEW = 285,
+ jp_PACKAGE = 286,
+ jp_PRIVATE = 287,
+ jp_PROTECTED = 288,
+ jp_PUBLIC = 289,
+ jp_RETURN = 290,
+ jp_SHORT_TYPE = 291,
+ jp_STATIC = 292,
+ jp_STRICTFP = 293,
+ jp_SUPER = 294,
+ jp_SWITCH = 295,
+ jp_SYNCHRONIZED = 296,
+ jp_THIS = 297,
+ jp_THROW = 298,
+ jp_THROWS = 299,
+ jp_TRANSIENT = 300,
+ jp_TRY = 301,
+ jp_VOID = 302,
+ jp_VOLATILE = 303,
+ jp_WHILE = 304,
+ jp_BOOLEANLITERAL = 305,
+ jp_CHARACTERLITERAL = 306,
+ jp_DECIMALINTEGERLITERAL = 307,
+ jp_FLOATINGPOINTLITERAL = 308,
+ jp_HEXINTEGERLITERAL = 309,
+ jp_NULLLITERAL = 310,
+ jp_STRINGLITERAL = 311,
+ jp_NAME = 312,
+ jp_AND = 313,
+ jp_ANDAND = 314,
+ jp_ANDEQUALS = 315,
+ jp_BRACKETEND = 316,
+ jp_BRACKETSTART = 317,
+ jp_CARROT = 318,
+ jp_CARROTEQUALS = 319,
+ jp_COLON = 320,
+ jp_COMMA = 321,
+ jp_CURLYEND = 322,
+ jp_CURLYSTART = 323,
+ jp_DIVIDE = 324,
+ jp_DIVIDEEQUALS = 325,
+ jp_DOLLAR = 326,
+ jp_DOT = 327,
+ jp_EQUALS = 328,
+ jp_EQUALSEQUALS = 329,
+ jp_EXCLAMATION = 330,
+ jp_EXCLAMATIONEQUALS = 331,
+ jp_GREATER = 332,
+ jp_GTEQUALS = 333,
+ jp_GTGT = 334,
+ jp_GTGTEQUALS = 335,
+ jp_GTGTGT = 336,
+ jp_GTGTGTEQUALS = 337,
+ jp_LESLESEQUALS = 338,
+ jp_LESSTHAN = 339,
+ jp_LTEQUALS = 340,
+ jp_LTLT = 341,
+ jp_MINUS = 342,
+ jp_MINUSEQUALS = 343,
+ jp_MINUSMINUS = 344,
+ jp_PAREEND = 345,
+ jp_PARESTART = 346,
+ jp_PERCENT = 347,
+ jp_PERCENTEQUALS = 348,
+ jp_PIPE = 349,
+ jp_PIPEEQUALS = 350,
+ jp_PIPEPIPE = 351,
+ jp_PLUS = 352,
+ jp_PLUSEQUALS = 353,
+ jp_PLUSPLUS = 354,
+ jp_QUESTION = 355,
+ jp_SEMICOL = 356,
+ jp_TILDE = 357,
+ jp_TIMES = 358,
+ jp_TIMESEQUALS = 359,
+ jp_ERROR = 360
+ };
#endif
+/* Tokens. */
#define jp_ABSTRACT 258
#define jp_ASSERT 259
#define jp_BOOLEAN_TYPE 260
@@ -276,156 +361,205 @@
#define jp_TIMESEQUALS 359
#define jp_ERROR 360
+/* Value type. */
-/* Copy the first part of user declarations. */
-#line 1 "cmDependsJavaParser.y"
-
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+int cmDependsJava_yyparse (yyscan_t yyscanner);
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
+#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */
-Run bison like this:
+/* Copy the second part of user declarations. */
- bison --yacc --name-prefix=cmDependsJava_yy
- --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx
- cmDependsJavaParser.y
+#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358 */
-Modify cmDependsJavaParser.c:
- - remove TABs
+#ifdef short
+# undef short
+#endif
-*/
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmDependsJava_yyerror(x) \
- cmDependsJavaError(yyscanner, x)
-#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
-/*-------------------------------------------------------------------------*/
-#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */
-#include "cmDependsJavaLexer.h" /* Interface to lexer object. */
-#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
-/* Forward declare the lexer entry point. */
-YY_DECL;
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
-/* Internal utility functions. */
-static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
-#define YYDEBUG 1
-#define YYMAXDEPTH 1000000
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
-#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. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
#endif
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label. */
-# pragma warning (disable: 4065) /* Switch statement contains default but
- no case. */
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
#endif
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
+#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
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
#else
-# define YYERROR_VERBOSE 0
+# define YYUSE(E) /* empty */
#endif
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 214 of yacc.c. */
-#line 372 "cmDependsJavaParser.cxx"
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-# define YYFREE free
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# endif
+#if ! defined yyoverflow || YYERROR_VERBOSE
/* The parser invokes alloca or malloc; define the necessary symbols. */
# ifdef YYSTACK_USE_ALLOCA
# if YYSTACK_USE_ALLOCA
-# define YYSTACK_ALLOC alloca
-# endif
-# else
-# if defined (alloca) || defined (_ALLOCA_H)
-# define YYSTACK_ALLOC alloca
-# else
# ifdef __GNUC__
# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
# endif
# endif
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
+ /* Pacify GCC's 'empty if-body' warning. */
# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
# endif
+# else
# define YYSTACK_ALLOC YYMALLOC
# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-#if (! defined (yyoverflow) \
- && (! defined (__cplusplus) \
- || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- short int yyss;
- YYSTYPE yyvs;
- };
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
/* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -433,74 +567,74 @@ union yyalloc
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined (__GNUC__) && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (0)
-# endif
-# endif
+# define YYCOPY_NEEDED 1
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
while (0)
#endif
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short int yysigned_char;
-#endif
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
-/* YYFINAL -- State number of the termination state. */
+/* YYFINAL -- State number of the termination state. */
#define YYFINAL 23
/* YYLAST -- Last index in YYTABLE. */
#define YYLAST 2215
-/* YYNTOKENS -- Number of terminals. */
+/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 106
-/* YYNNTS -- Number of nonterminals. */
+/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 158
-/* YYNRULES -- Number of rules. */
+/* YYNRULES -- Number of rules. */
#define YYNRULES 351
-/* YYNRULES -- Number of states. */
+/* YYNSTATES -- Number of states. */
#define YYNSTATES 575
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 360
-#define YYTRANSLATE(YYX) \
+#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char yytranslate[] =
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -542,201 +676,51 @@ static const unsigned char yytranslate[] =
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const unsigned short int yyprhs[] =
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
{
- 0, 0, 3, 5, 7, 9, 11, 13, 15, 17,
- 19, 21, 23, 25, 27, 29, 31, 33, 35, 37,
- 39, 41, 43, 45, 47, 49, 51, 54, 57, 59,
- 61, 63, 65, 68, 72, 76, 80, 84, 86, 88,
- 92, 93, 95, 96, 99, 100, 103, 107, 109, 111,
- 115, 121, 123, 125, 127, 129, 132, 134, 136, 138,
- 140, 142, 144, 146, 148, 150, 152, 154, 158, 161,
- 165, 169, 174, 175, 177, 180, 183, 185, 189, 193,
- 194, 197, 199, 201, 203, 205, 207, 209, 214, 216,
- 220, 222, 226, 228, 232, 234, 236, 239, 242, 246,
- 251, 256, 257, 259, 264, 268, 269, 271, 273, 277,
- 281, 284, 286, 290, 292, 295, 300, 306, 311, 316,
- 317, 320, 326, 332, 336, 340, 341, 343, 346, 350,
- 354, 355, 358, 360, 362, 364, 367, 369, 372, 374,
- 377, 379, 382, 386, 387, 389, 392, 394, 398, 402,
- 403, 405, 407, 410, 412, 414, 416, 419, 423, 426,
- 428, 430, 432, 434, 436, 438, 440, 442, 444, 446,
- 448, 450, 452, 454, 456, 458, 460, 462, 464, 466,
- 468, 470, 472, 474, 478, 482, 485, 487, 489, 491,
- 493, 495, 497, 499, 505, 513, 521, 527, 532, 533,
- 535, 536, 539, 542, 544, 547, 551, 554, 560, 566,
- 574, 584, 585, 587, 588, 590, 600, 601, 603, 605,
- 607, 609, 611, 615, 619, 625, 629, 630, 632, 636,
- 640, 644, 650, 654, 659, 660, 662, 664, 667, 673,
- 676, 678, 680, 682, 684, 688, 690, 692, 694, 696,
- 703, 704, 706, 707, 709, 711, 715, 720, 725, 730,
- 735, 736, 738, 740, 743, 747, 750, 754, 758, 762,
- 766, 770, 775, 782, 789, 796, 801, 806, 808, 810,
- 814, 816, 818, 821, 824, 826, 828, 831, 834, 836,
- 839, 842, 844, 847, 850, 852, 858, 863, 869, 871,
- 875, 879, 883, 885, 889, 893, 895, 899, 903, 907,
- 909, 913, 917, 921, 925, 929, 931, 935, 939, 941,
- 945, 947, 951, 953, 957, 959, 963, 965, 969, 971,
- 977, 979, 981, 985, 987, 989, 991, 993, 995, 997,
- 999, 1001, 1003, 1005, 1007, 1009, 1011, 1013, 1015, 1017,
- 1019, 1021
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const short int yyrhs[] =
-{
- 107, 0, -1, 122, -1, 109, -1, 53, -1, 50,
- -1, 51, -1, 56, -1, 55, -1, 52, -1, 54,
- -1, 111, -1, 112, -1, 7, -1, 36, -1, 26,
- -1, 28, -1, 10, -1, 20, -1, 15, -1, 5,
- -1, 113, -1, 116, -1, 117, -1, 113, -1, 113,
- -1, 111, 234, -1, 117, 234, -1, 118, -1, 120,
- -1, 119, -1, 57, -1, 71, 57, -1, 117, 72,
- 119, -1, 117, 72, 11, -1, 117, 72, 42, -1,
- 121, 72, 11, -1, 111, -1, 47, -1, 123, 124,
- 125, -1, -1, 126, -1, -1, 124, 127, -1, -1,
- 125, 130, -1, 31, 117, 101, -1, 128, -1, 129,
- -1, 24, 117, 101, -1, 24, 117, 72, 103, 101,
- -1, 134, -1, 165, -1, 101, -1, 132, -1, 131,
- 132, -1, 34, -1, 33, -1, 32, -1, 37, -1,
- 3, -1, 18, -1, 29, -1, 41, -1, 45, -1,
- 48, -1, 38, -1, 135, 11, 119, -1, 133, 139,
- -1, 133, 137, 139, -1, 133, 136, 139, -1, 133,
- 136, 137, 139, -1, -1, 131, -1, 17, 114, -1,
- 23, 138, -1, 115, -1, 138, 66, 115, -1, 68,
- 140, 67, -1, -1, 140, 141, -1, 142, -1, 158,
- -1, 159, -1, 130, -1, 143, -1, 148, -1, 135,
- 110, 144, 101, -1, 145, -1, 144, 66, 145, -1,
- 146, -1, 146, 73, 147, -1, 119, -1, 146, 62,
- 61, -1, 261, -1, 174, -1, 149, 101, -1, 149,
- 157, -1, 149, 157, 101, -1, 135, 110, 151, 150,
- -1, 135, 47, 151, 150, -1, -1, 155, -1, 119,
- 91, 152, 90, -1, 151, 62, 61, -1, -1, 153,
- -1, 154, -1, 153, 66, 154, -1, 135, 110, 146,
- -1, 44, 156, -1, 114, -1, 156, 66, 114, -1,
- 177, -1, 37, 177, -1, 135, 160, 150, 161, -1,
- 135, 160, 150, 161, 101, -1, 118, 91, 152, 90,
- -1, 68, 162, 178, 67, -1, -1, 162, 163, -1,
- 42, 91, 228, 90, 101, -1, 39, 91, 228, 90,
- 101, -1, 135, 27, 119, -1, 164, 166, 168, -1,
- -1, 167, -1, 17, 115, -1, 167, 66, 115, -1,
- 68, 169, 67, -1, -1, 169, 170, -1, 171, -1,
- 172, -1, 134, -1, 134, 101, -1, 165, -1, 165,
- 101, -1, 143, -1, 149, 173, -1, 101, -1, 173,
- 101, -1, 68, 175, 67, -1, -1, 176, -1, 176,
- 66, -1, 147, -1, 176, 66, 147, -1, 68, 178,
- 67, -1, -1, 179, -1, 180, -1, 179, 180, -1,
- 181, -1, 183, -1, 134, -1, 182, 101, -1, 131,
- 110, 144, -1, 110, 144, -1, 185, -1, 187, -1,
- 191, -1, 192, -1, 201, -1, 204, -1, 185, -1,
- 188, -1, 193, -1, 202, -1, 207, -1, 177, -1,
- 186, -1, 189, -1, 194, -1, 203, -1, 213, -1,
- 215, -1, 216, -1, 218, -1, 217, -1, 219, -1,
- 212, -1, 101, -1, 119, 65, 183, -1, 119, 65,
- 184, -1, 190, 101, -1, 258, -1, 242, -1, 243,
- -1, 239, -1, 240, -1, 236, -1, 226, -1, 22,
- 91, 261, 90, 183, -1, 22, 91, 261, 90, 184,
- 16, 183, -1, 22, 91, 261, 90, 184, 16, 184,
- -1, 40, 91, 261, 90, 195, -1, 68, 197, 196,
- 67, -1, -1, 199, -1, -1, 197, 198, -1, 199,
- 179, -1, 200, -1, 199, 200, -1, 8, 262, 65,
- -1, 13, 65, -1, 49, 91, 261, 90, 183, -1,
- 49, 91, 261, 90, 184, -1, 14, 183, 49, 91,
- 261, 90, 101, -1, 21, 91, 206, 101, 208, 101,
- 205, 90, 183, -1, -1, 210, -1, -1, 209, -1,
- 21, 91, 206, 101, 208, 101, 205, 90, 184, -1,
- -1, 261, -1, 211, -1, 182, -1, 211, -1, 190,
- -1, 211, 66, 190, -1, 4, 261, 101, -1, 4,
- 261, 65, 261, 101, -1, 6, 214, 101, -1, -1,
- 119, -1, 12, 214, 101, -1, 35, 208, 101, -1,
- 43, 261, 101, -1, 41, 91, 261, 90, 177, -1,
- 46, 177, 221, -1, 46, 177, 220, 223, -1, -1,
- 221, -1, 222, -1, 221, 222, -1, 9, 91, 154,
- 90, 177, -1, 19, 177, -1, 225, -1, 230, -1,
- 108, -1, 42, -1, 91, 261, 90, -1, 226, -1,
- 235, -1, 236, -1, 237, -1, 263, 114, 91, 228,
- 90, 227, -1, -1, 139, -1, -1, 229, -1, 261,
- -1, 229, 66, 261, -1, 263, 111, 232, 231, -1,
- 263, 113, 232, 231, -1, 263, 111, 234, 174, -1,
- 263, 113, 234, 174, -1, -1, 234, -1, 233, -1,
- 232, 233, -1, 62, 261, 61, -1, 62, 61, -1,
- 234, 62, 61, -1, 224, 72, 119, -1, 39, 72,
- 119, -1, 42, 72, 119, -1, 224, 72, 42, -1,
- 117, 91, 228, 90, -1, 224, 72, 119, 91, 228,
- 90, -1, 39, 72, 119, 91, 228, 90, -1, 42,
- 72, 119, 91, 228, 90, -1, 117, 62, 261, 61,
- -1, 225, 62, 261, 61, -1, 224, -1, 117, -1,
- 116, 72, 11, -1, 239, -1, 240, -1, 238, 99,
- -1, 238, 89, -1, 242, -1, 243, -1, 97, 241,
- -1, 87, 241, -1, 244, -1, 99, 241, -1, 89,
- 241, -1, 238, -1, 102, 241, -1, 75, 241, -1,
- 245, -1, 91, 111, 231, 90, 241, -1, 91, 261,
- 90, 244, -1, 91, 117, 234, 90, 244, -1, 241,
- -1, 246, 103, 241, -1, 246, 69, 241, -1, 246,
- 92, 241, -1, 246, -1, 247, 97, 246, -1, 247,
- 87, 246, -1, 247, -1, 248, 86, 247, -1, 248,
- 79, 247, -1, 248, 81, 247, -1, 248, -1, 249,
- 84, 248, -1, 249, 77, 248, -1, 249, 85, 248,
- -1, 249, 78, 248, -1, 249, 25, 112, -1, 249,
- -1, 250, 74, 249, -1, 250, 76, 249, -1, 250,
- -1, 251, 58, 250, -1, 251, -1, 252, 63, 251,
- -1, 252, -1, 253, 94, 252, -1, 253, -1, 254,
- 59, 253, -1, 254, -1, 255, 96, 254, -1, 255,
- -1, 255, 100, 261, 65, 256, -1, 256, -1, 258,
- -1, 259, 260, 257, -1, 117, -1, 235, -1, 237,
- -1, 73, -1, 104, -1, 70, -1, 93, -1, 98,
- -1, 88, -1, 83, -1, 80, -1, 82, -1, 60,
- -1, 64, -1, 95, -1, 257, -1, 261, -1, 30,
- -1, 117, 72, 30, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short int yyrline[] =
-{
- 0, 191, 191, 200, 208, 216, 224, 232, 240, 249,
- 257, 266, 274, 283, 288, 293, 298, 303, 308, 313,
- 318, 324, 332, 341, 351, 360, 369, 377, 387, 393,
- 400, 407, 413, 420, 429, 439, 449, 458, 466, 475,
- 484, 490, 499, 505, 514, 520, 529, 541, 549, 558,
- 570, 583, 591, 599, 608, 616, 625, 625, 625, 626,
- 627, 627, 627, 627, 627, 627, 628, 631, 641, 650,
- 659, 668, 678, 684, 693, 702, 711, 719, 728, 737,
- 743, 752, 760, 768, 776, 785, 793, 802, 808, 816,
- 825, 833, 842, 851, 860, 868, 877, 885, 893, 902,
- 911, 921, 928, 938, 948, 955, 962, 965, 971, 981,
- 991, 1001, 1007, 1017, 1027, 1037, 1046, 1056, 1067, 1077,
- 1084, 1094, 1103, 1113, 1122, 1132, 1138, 1148, 1157, 1167,
- 1177, 1184, 1193, 1202, 1211, 1220, 1228, 1237, 1246, 1256,
- 1266, 1275, 1285, 1295, 1302, 1311, 1321, 1330, 1340, 1349,
- 1356, 1366, 1375, 1385, 1394, 1403, 1413, 1423, 1432, 1442,
- 1451, 1460, 1469, 1478, 1487, 1497, 1506, 1515, 1524, 1533,
- 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615, 1624,
- 1633, 1642, 1652, 1662, 1673, 1683, 1693, 1702, 1711, 1720,
- 1729, 1738, 1747, 1757, 1767, 1777, 1787, 1794, 1801, 1808,
- 1818, 1825, 1835, 1845, 1854, 1864, 1873, 1883, 1890, 1897,
- 1904, 1912, 1919, 1929, 1936, 1946, 1956, 1963, 1973, 1982,
- 1992, 2002, 2011, 2021, 2030, 2040, 2051, 2058, 2065, 2076,
- 2086, 2096, 2106, 2115, 2125, 2132, 2142, 2151, 2161, 2168,
- 2178, 2187, 2197, 2206, 2212, 2221, 2230, 2239, 2248, 2258,
- 2268, 2275, 2285, 2292, 2302, 2311, 2321, 2330, 2339, 2348,
- 2358, 2365, 2375, 2384, 2394, 2404, 2410, 2417, 2427, 2437,
- 2447, 2458, 2468, 2479, 2489, 2500, 2510, 2520, 2529, 2538,
- 2547, 2556, 2566, 2576, 2586, 2595, 2604, 2613, 2622, 2632,
- 2642, 2652, 2661, 2670, 2679, 2689, 2698, 2707, 2714, 2723,
- 2732, 2741, 2751, 2760, 2769, 2779, 2788, 2797, 2806, 2816,
- 2825, 2834, 2843, 2852, 2861, 2871, 2880, 2889, 2899, 2908,
- 2918, 2927, 2937, 2946, 2956, 2965, 2975, 2984, 2994, 3003,
- 3013, 3022, 3032, 3042, 3052, 3061, 3071, 3080, 3089, 3098,
- 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3170, 3180, 3190,
- 3200, 3209
+ 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
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "jp_ABSTRACT", "jp_ASSERT",
@@ -813,14 +797,14 @@ static const char *const yytname[] =
"ConditionalAndExpression", "ConditionalOrExpression",
"ConditionalExpression", "AssignmentExpression", "Assignment",
"LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression",
- "New", 0
+ "New", YY_NULLPTR
};
#endif
# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const unsigned short int yytoknum[] =
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
@@ -836,178 +820,19 @@ static const unsigned short int yytoknum[] =
};
# endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned short int yyr1[] =
-{
- 0, 106, 107, 108, 108, 108, 108, 108, 108, 109,
- 109, 110, 110, 111, 111, 111, 111, 111, 111, 111,
- 111, 112, 112, 113, 114, 115, 116, 116, 117, 117,
- 118, 119, 119, 120, 120, 120, 120, 121, 121, 122,
- 123, 123, 124, 124, 125, 125, 126, 127, 127, 128,
- 129, 130, 130, 130, 131, 131, 132, 132, 132, 132,
- 132, 132, 132, 132, 132, 132, 132, 133, 134, 134,
- 134, 134, 135, 135, 136, 137, 138, 138, 139, 140,
- 140, 141, 141, 141, 141, 142, 142, 143, 144, 144,
- 145, 145, 146, 146, 147, 147, 148, 148, 148, 149,
- 149, 150, 150, 151, 151, 152, 152, 153, 153, 154,
- 155, 156, 156, 157, 158, 159, 159, 160, 161, 162,
- 162, 163, 163, 164, 165, 166, 166, 167, 167, 168,
- 169, 169, 170, 170, 170, 170, 170, 170, 171, 172,
- 173, 173, 174, 175, 175, 175, 176, 176, 177, 178,
- 178, 179, 179, 180, 180, 180, 181, 182, 182, 183,
- 183, 183, 183, 183, 183, 184, 184, 184, 184, 184,
- 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
- 185, 185, 186, 187, 188, 189, 190, 190, 190, 190,
- 190, 190, 190, 191, 192, 193, 194, 195, 196, 196,
- 197, 197, 198, 199, 199, 200, 200, 201, 202, 203,
- 204, 205, 205, 206, 206, 207, 208, 208, 209, 209,
- 210, 211, 211, 212, 212, 213, 214, 214, 215, 216,
- 217, 218, 219, 219, 220, 220, 221, 221, 222, 223,
- 224, 224, 225, 225, 225, 225, 225, 225, 225, 226,
- 227, 227, 228, 228, 229, 229, 230, 230, 230, 230,
- 231, 231, 232, 232, 233, 234, 234, 235, 235, 235,
- 235, 236, 236, 236, 236, 237, 237, 238, 238, 238,
- 238, 238, 239, 240, 241, 241, 241, 241, 241, 242,
- 243, 244, 244, 244, 244, 245, 245, 245, 246, 246,
- 246, 246, 247, 247, 247, 248, 248, 248, 248, 249,
- 249, 249, 249, 249, 249, 250, 250, 250, 251, 251,
- 252, 252, 253, 253, 254, 254, 255, 255, 256, 256,
- 257, 257, 258, 259, 259, 259, 260, 260, 260, 260,
- 260, 260, 260, 260, 260, 260, 260, 260, 261, 262,
- 263, 263
-};
+#define YYPACT_NINF -503
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
-{
- 0, 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, 2, 2, 1, 1,
- 1, 1, 2, 3, 3, 3, 3, 1, 1, 3,
- 0, 1, 0, 2, 0, 2, 3, 1, 1, 3,
- 5, 1, 1, 1, 1, 2, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 3, 2, 3,
- 3, 4, 0, 1, 2, 2, 1, 3, 3, 0,
- 2, 1, 1, 1, 1, 1, 1, 4, 1, 3,
- 1, 3, 1, 3, 1, 1, 2, 2, 3, 4,
- 4, 0, 1, 4, 3, 0, 1, 1, 3, 3,
- 2, 1, 3, 1, 2, 4, 5, 4, 4, 0,
- 2, 5, 5, 3, 3, 0, 1, 2, 3, 3,
- 0, 2, 1, 1, 1, 2, 1, 2, 1, 2,
- 1, 2, 3, 0, 1, 2, 1, 3, 3, 0,
- 1, 1, 2, 1, 1, 1, 2, 3, 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, 3, 3, 2, 1, 1, 1, 1,
- 1, 1, 1, 5, 7, 7, 5, 4, 0, 1,
- 0, 2, 2, 1, 2, 3, 2, 5, 5, 7,
- 9, 0, 1, 0, 1, 9, 0, 1, 1, 1,
- 1, 1, 3, 3, 5, 3, 0, 1, 3, 3,
- 3, 5, 3, 4, 0, 1, 1, 2, 5, 2,
- 1, 1, 1, 1, 3, 1, 1, 1, 1, 6,
- 0, 1, 0, 1, 1, 3, 4, 4, 4, 4,
- 0, 1, 1, 2, 3, 2, 3, 3, 3, 3,
- 3, 4, 6, 6, 6, 4, 4, 1, 1, 3,
- 1, 1, 2, 2, 1, 1, 2, 2, 1, 2,
- 2, 1, 2, 2, 1, 5, 4, 5, 1, 3,
- 3, 3, 1, 3, 3, 1, 3, 3, 3, 1,
- 3, 3, 3, 3, 3, 1, 3, 3, 1, 3,
- 1, 3, 1, 3, 1, 3, 1, 3, 1, 5,
- 1, 1, 3, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 3
-};
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-503)))
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const unsigned short int yydefact[] =
-{
- 40, 0, 0, 2, 42, 41, 20, 13, 17, 19,
- 18, 15, 16, 14, 38, 31, 0, 37, 0, 28,
- 30, 29, 0, 1, 44, 32, 0, 46, 0, 0,
- 72, 43, 47, 48, 34, 35, 33, 36, 0, 60,
- 61, 62, 58, 57, 56, 59, 66, 63, 64, 65,
- 53, 45, 73, 54, 0, 51, 0, 125, 52, 0,
- 49, 55, 0, 0, 79, 0, 0, 68, 0, 0,
- 0, 0, 126, 0, 24, 74, 23, 25, 76, 75,
- 72, 0, 70, 69, 67, 123, 127, 130, 124, 0,
- 50, 0, 59, 78, 84, 0, 80, 81, 85, 86,
- 0, 82, 83, 71, 72, 128, 77, 72, 114, 38,
- 0, 11, 12, 21, 22, 23, 28, 101, 96, 97,
- 113, 129, 134, 0, 138, 0, 136, 131, 132, 133,
- 0, 226, 226, 0, 0, 0, 350, 216, 0, 0,
- 63, 243, 0, 0, 0, 5, 6, 9, 4, 10,
- 8, 7, 0, 0, 0, 182, 242, 3, 0, 22,
- 333, 30, 73, 155, 0, 170, 0, 72, 151, 153,
- 0, 154, 159, 171, 160, 172, 0, 161, 162, 173,
- 163, 174, 164, 181, 175, 176, 177, 179, 178, 180,
- 277, 240, 245, 241, 246, 247, 248, 0, 189, 190,
- 187, 188, 186, 0, 0, 0, 101, 92, 0, 88,
- 90, 101, 0, 26, 27, 72, 0, 0, 102, 98,
- 135, 140, 139, 137, 0, 0, 0, 0, 0, 37,
- 0, 278, 245, 247, 291, 280, 281, 298, 284, 285,
- 288, 294, 302, 305, 309, 315, 318, 320, 322, 324,
- 326, 328, 330, 348, 331, 0, 227, 0, 0, 0,
- 0, 213, 0, 0, 217, 0, 0, 0, 0, 0,
- 234, 0, 278, 246, 248, 290, 0, 289, 92, 158,
- 0, 0, 0, 252, 0, 0, 148, 152, 156, 185,
- 0, 0, 283, 282, 345, 346, 338, 336, 343, 344,
- 342, 341, 339, 347, 340, 337, 0, 37, 24, 0,
- 72, 0, 100, 0, 87, 0, 0, 99, 265, 0,
- 0, 0, 106, 107, 111, 110, 119, 115, 141, 293,
- 287, 37, 278, 0, 286, 292, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 223, 225,
- 228, 0, 0, 219, 221, 0, 214, 218, 0, 229,
- 268, 0, 0, 269, 230, 0, 0, 232, 236, 0,
- 244, 279, 0, 351, 0, 253, 254, 183, 157, 270,
- 267, 0, 332, 0, 260, 262, 0, 260, 0, 252,
- 0, 104, 89, 93, 143, 91, 95, 94, 266, 0,
- 117, 72, 0, 72, 116, 0, 26, 27, 244, 300,
- 301, 299, 304, 303, 307, 308, 306, 314, 311, 313,
- 310, 312, 316, 317, 319, 321, 323, 325, 327, 0,
- 0, 0, 216, 0, 0, 252, 0, 0, 252, 72,
- 0, 233, 237, 0, 275, 271, 0, 252, 276, 0,
- 256, 263, 261, 258, 257, 259, 0, 103, 146, 0,
- 144, 109, 108, 112, 0, 243, 120, 0, 0, 0,
- 296, 0, 224, 0, 0, 222, 0, 0, 0, 30,
- 193, 0, 159, 166, 167, 168, 169, 0, 200, 196,
- 231, 0, 0, 239, 207, 255, 0, 264, 250, 142,
- 145, 252, 252, 118, 295, 297, 329, 0, 211, 213,
- 0, 0, 0, 0, 273, 198, 274, 0, 272, 251,
- 249, 147, 0, 0, 209, 0, 212, 220, 0, 0,
- 0, 184, 194, 0, 0, 0, 201, 72, 203, 238,
- 0, 0, 0, 216, 0, 0, 349, 0, 206, 197,
- 202, 204, 122, 121, 210, 0, 0, 208, 205, 211,
- 0, 0, 195, 0, 215
-};
+#define YYTABLE_NINF -336
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short int yydefgoto[] =
-{
- -1, 2, 156, 157, 158, 229, 112, 113, 75, 78,
- 230, 231, 19, 20, 21, 22, 3, 4, 24, 30,
- 5, 31, 32, 33, 51, 52, 53, 54, 163, 164,
- 65, 66, 79, 67, 80, 96, 97, 98, 208, 209,
- 210, 405, 99, 100, 217, 206, 321, 322, 323, 218,
- 325, 119, 101, 102, 117, 327, 413, 476, 57, 58,
- 71, 72, 88, 104, 127, 128, 129, 222, 406, 469,
- 470, 165, 166, 167, 168, 169, 170, 171, 491, 172,
- 173, 174, 493, 175, 176, 177, 178, 494, 179, 499,
- 545, 525, 546, 547, 548, 180, 495, 181, 182, 535,
- 365, 496, 263, 366, 536, 367, 183, 184, 257, 185,
- 186, 187, 188, 189, 376, 377, 378, 451, 190, 191,
- 232, 530, 384, 385, 193, 415, 394, 395, 214, 194,
- 233, 196, 234, 235, 236, 237, 238, 239, 240, 241,
- 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
- 252, 253, 254, 203, 306, 386, 557, 204
-};
+#define yytable_value_is_error(Yytable_value) \
+ 0
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -503
-static const short int yypact[] =
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
{
159, 1039, 236, -503, -503, -503, -503, -503, -503, -503,
-503, -503, -503, -503, -503, -503, 186, -503, 56, -503,
@@ -1069,8 +894,73 @@ static const short int yypact[] =
1699, 432, -503, 1699, -503
};
-/* YYPGOTO[NTERM-NUM]. */
-static const short int yypgoto[] =
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 40, 0, 0, 2, 42, 41, 20, 13, 17, 19,
+ 18, 15, 16, 14, 38, 31, 0, 37, 0, 28,
+ 30, 29, 0, 1, 44, 32, 0, 46, 0, 0,
+ 72, 43, 47, 48, 34, 35, 33, 36, 0, 60,
+ 61, 62, 58, 57, 56, 59, 66, 63, 64, 65,
+ 53, 45, 73, 54, 0, 51, 0, 125, 52, 0,
+ 49, 55, 0, 0, 79, 0, 0, 68, 0, 0,
+ 0, 0, 126, 0, 24, 74, 23, 25, 76, 75,
+ 72, 0, 70, 69, 67, 123, 127, 130, 124, 0,
+ 50, 0, 59, 78, 84, 0, 80, 81, 85, 86,
+ 0, 82, 83, 71, 72, 128, 77, 72, 114, 38,
+ 0, 11, 12, 21, 22, 23, 28, 101, 96, 97,
+ 113, 129, 134, 0, 138, 0, 136, 131, 132, 133,
+ 0, 226, 226, 0, 0, 0, 350, 216, 0, 0,
+ 63, 243, 0, 0, 0, 5, 6, 9, 4, 10,
+ 8, 7, 0, 0, 0, 182, 242, 3, 0, 22,
+ 333, 30, 73, 155, 0, 170, 0, 72, 151, 153,
+ 0, 154, 159, 171, 160, 172, 0, 161, 162, 173,
+ 163, 174, 164, 181, 175, 176, 177, 179, 178, 180,
+ 277, 240, 245, 241, 246, 247, 248, 0, 189, 190,
+ 187, 188, 186, 0, 0, 0, 101, 92, 0, 88,
+ 90, 101, 0, 26, 27, 72, 0, 0, 102, 98,
+ 135, 140, 139, 137, 0, 0, 0, 0, 0, 37,
+ 0, 278, 245, 247, 291, 280, 281, 298, 284, 285,
+ 288, 294, 302, 305, 309, 315, 318, 320, 322, 324,
+ 326, 328, 330, 348, 331, 0, 227, 0, 0, 0,
+ 0, 213, 0, 0, 217, 0, 0, 0, 0, 0,
+ 234, 0, 278, 246, 248, 290, 0, 289, 92, 158,
+ 0, 0, 0, 252, 0, 0, 148, 152, 156, 185,
+ 0, 0, 283, 282, 345, 346, 338, 336, 343, 344,
+ 342, 341, 339, 347, 340, 337, 0, 37, 24, 0,
+ 72, 0, 100, 0, 87, 0, 0, 99, 265, 0,
+ 0, 0, 106, 107, 111, 110, 119, 115, 141, 293,
+ 287, 37, 278, 0, 286, 292, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 223, 225,
+ 228, 0, 0, 219, 221, 0, 214, 218, 0, 229,
+ 268, 0, 0, 269, 230, 0, 0, 232, 236, 0,
+ 244, 279, 0, 351, 0, 253, 254, 183, 157, 270,
+ 267, 0, 332, 0, 260, 262, 0, 260, 0, 252,
+ 0, 104, 89, 93, 143, 91, 95, 94, 266, 0,
+ 117, 72, 0, 72, 116, 0, 26, 27, 244, 300,
+ 301, 299, 304, 303, 307, 308, 306, 314, 311, 313,
+ 310, 312, 316, 317, 319, 321, 323, 325, 327, 0,
+ 0, 0, 216, 0, 0, 252, 0, 0, 252, 72,
+ 0, 233, 237, 0, 275, 271, 0, 252, 276, 0,
+ 256, 263, 261, 258, 257, 259, 0, 103, 146, 0,
+ 144, 109, 108, 112, 0, 243, 120, 0, 0, 0,
+ 296, 0, 224, 0, 0, 222, 0, 0, 0, 30,
+ 193, 0, 159, 166, 167, 168, 169, 0, 200, 196,
+ 231, 0, 0, 239, 207, 255, 0, 264, 250, 142,
+ 145, 252, 252, 118, 295, 297, 329, 0, 211, 213,
+ 0, 0, 0, 0, 273, 198, 274, 0, 272, 251,
+ 249, 147, 0, 0, 209, 0, 212, 220, 0, 0,
+ 0, 184, 194, 0, 0, 0, 201, 72, 203, 238,
+ 0, 0, 0, 216, 0, 0, 349, 0, 206, 197,
+ 202, 204, 122, 121, 210, 0, 0, 208, 205, 211,
+ 0, 0, 195, 0, 215
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
{
-503, -503, -503, -503, -85, 2, 181, -41, -198, -45,
-87, -1, 431, 14, -503, -503, -503, -503, -503, -503,
@@ -1090,12 +980,31 @@ static const short int yypgoto[] =
95, 274, 350, -503, -503, 660, -503, -503
};
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -336
-static const short int yytable[] =
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 2, 156, 157, 158, 229, 112, 113, 75, 78,
+ 230, 231, 19, 20, 21, 22, 3, 4, 24, 30,
+ 5, 31, 32, 33, 51, 52, 53, 54, 163, 164,
+ 65, 66, 79, 67, 80, 96, 97, 98, 208, 209,
+ 210, 405, 99, 100, 217, 206, 321, 322, 323, 218,
+ 325, 119, 101, 102, 117, 327, 413, 476, 57, 58,
+ 71, 72, 88, 104, 127, 128, 129, 222, 406, 469,
+ 470, 165, 166, 167, 168, 169, 170, 171, 491, 172,
+ 173, 174, 493, 175, 176, 177, 178, 494, 179, 499,
+ 545, 525, 546, 547, 548, 180, 495, 181, 182, 535,
+ 365, 496, 263, 366, 536, 367, 183, 184, 257, 185,
+ 186, 187, 188, 189, 376, 377, 378, 451, 190, 191,
+ 232, 530, 384, 385, 193, 415, 394, 395, 214, 194,
+ 233, 196, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 203, 306, 386, 557, 204
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
{
18, 82, 83, 17, 287, 61, 309, 56, 114, 364,
110, 363, 279, 468, 34, 108, 537, 103, 324, 107,
@@ -1321,7 +1230,7 @@ static const short int yytable[] =
0, 0, 0, 0, 0, 305
};
-static const short int yycheck[] =
+static const yytype_int16 yycheck[] =
{
1, 65, 66, 1, 167, 52, 204, 30, 95, 261,
95, 261, 158, 404, 11, 92, 518, 81, 216, 68,
@@ -1547,9 +1456,9 @@ static const short int yycheck[] =
-1, -1, -1, -1, -1, 104
};
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const unsigned short int yystos[] =
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint16 yystos[] =
{
0, 31, 107, 122, 123, 126, 5, 7, 10, 15,
20, 26, 28, 36, 47, 57, 71, 111, 117, 118,
@@ -1611,78 +1520,123 @@ static const unsigned short int yystos[] =
16, 205, 184, 90, 184
};
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint16 yyr1[] =
+{
+ 0, 106, 107, 108, 108, 108, 108, 108, 108, 109,
+ 109, 110, 110, 111, 111, 111, 111, 111, 111, 111,
+ 111, 112, 112, 113, 114, 115, 116, 116, 117, 117,
+ 118, 119, 119, 120, 120, 120, 120, 121, 121, 122,
+ 123, 123, 124, 124, 125, 125, 126, 127, 127, 128,
+ 129, 130, 130, 130, 131, 131, 132, 132, 132, 132,
+ 132, 132, 132, 132, 132, 132, 132, 133, 134, 134,
+ 134, 134, 135, 135, 136, 137, 138, 138, 139, 140,
+ 140, 141, 141, 141, 141, 142, 142, 143, 144, 144,
+ 145, 145, 146, 146, 147, 147, 148, 148, 148, 149,
+ 149, 150, 150, 151, 151, 152, 152, 153, 153, 154,
+ 155, 156, 156, 157, 158, 159, 159, 160, 161, 162,
+ 162, 163, 163, 164, 165, 166, 166, 167, 167, 168,
+ 169, 169, 170, 170, 170, 170, 170, 170, 171, 172,
+ 173, 173, 174, 175, 175, 175, 176, 176, 177, 178,
+ 178, 179, 179, 180, 180, 180, 181, 182, 182, 183,
+ 183, 183, 183, 183, 183, 184, 184, 184, 184, 184,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 186, 187, 188, 189, 190, 190, 190, 190,
+ 190, 190, 190, 191, 192, 193, 194, 195, 196, 196,
+ 197, 197, 198, 199, 199, 200, 200, 201, 202, 203,
+ 204, 205, 205, 206, 206, 207, 208, 208, 209, 209,
+ 210, 211, 211, 212, 212, 213, 214, 214, 215, 216,
+ 217, 218, 219, 219, 220, 220, 221, 221, 222, 223,
+ 224, 224, 225, 225, 225, 225, 225, 225, 225, 226,
+ 227, 227, 228, 228, 229, 229, 230, 230, 230, 230,
+ 231, 231, 232, 232, 233, 234, 234, 235, 235, 235,
+ 235, 236, 236, 236, 236, 237, 237, 238, 238, 238,
+ 238, 238, 239, 240, 241, 241, 241, 241, 241, 242,
+ 243, 244, 244, 244, 244, 245, 245, 245, 246, 246,
+ 246, 246, 247, 247, 247, 248, 248, 248, 248, 249,
+ 249, 249, 249, 249, 249, 250, 250, 250, 251, 251,
+ 252, 252, 253, 253, 254, 254, 255, 255, 256, 256,
+ 257, 257, 258, 259, 259, 259, 260, 260, 260, 260,
+ 260, 260, 260, 260, 260, 260, 260, 260, 261, 262,
+ 263, 263
+};
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 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, 2, 2, 1, 1,
+ 1, 1, 2, 3, 3, 3, 3, 1, 1, 3,
+ 0, 1, 0, 2, 0, 2, 3, 1, 1, 3,
+ 5, 1, 1, 1, 1, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3, 2, 3,
+ 3, 4, 0, 1, 2, 2, 1, 3, 3, 0,
+ 2, 1, 1, 1, 1, 1, 1, 4, 1, 3,
+ 1, 3, 1, 3, 1, 1, 2, 2, 3, 4,
+ 4, 0, 1, 4, 3, 0, 1, 1, 3, 3,
+ 2, 1, 3, 1, 2, 4, 5, 4, 4, 0,
+ 2, 5, 5, 3, 3, 0, 1, 2, 3, 3,
+ 0, 2, 1, 1, 1, 2, 1, 2, 1, 2,
+ 1, 2, 3, 0, 1, 2, 1, 3, 3, 0,
+ 1, 1, 2, 1, 1, 1, 2, 3, 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, 3, 3, 2, 1, 1, 1, 1,
+ 1, 1, 1, 5, 7, 7, 5, 4, 0, 1,
+ 0, 2, 2, 1, 2, 3, 2, 5, 5, 7,
+ 9, 0, 1, 0, 1, 9, 0, 1, 1, 1,
+ 1, 1, 3, 3, 5, 3, 0, 1, 3, 3,
+ 3, 5, 3, 4, 0, 1, 1, 2, 5, 2,
+ 1, 1, 1, 1, 3, 1, 1, 1, 1, 6,
+ 0, 1, 0, 1, 1, 3, 4, 4, 4, 4,
+ 0, 1, 1, 2, 3, 2, 3, 3, 3, 3,
+ 3, 4, 6, 6, 6, 4, 4, 1, 1, 3,
+ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2,
+ 2, 1, 2, 2, 1, 5, 4, 5, 1, 3,
+ 3, 3, 1, 3, 3, 1, 3, 3, 3, 1,
+ 3, 3, 3, 3, 3, 1, 3, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 1, 3, 1, 5,
+ 1, 1, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 3
+};
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
-#define YYFAIL goto yyerrlab
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror ("syntax error: cannot back up");\
- YYERROR; \
- } \
+#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 YYTERROR 1
-#define YYERRCODE 256
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
- are run). */
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- ((Current).first_line = (Rhs)[1].first_line, \
- (Current).first_column = (Rhs)[1].first_column, \
- (Current).last_line = (Rhs)[N].last_line, \
- (Current).last_column = (Rhs)[N].last_column)
-#endif
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
/* Enable debugging if requested. */
#if YYDEBUG
@@ -1692,54 +1646,85 @@ while (0)
# define YYFPRINTF fprintf
# endif
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
} while (0)
-# define YYDSYMPRINT(Args) \
-do { \
- if (yydebug) \
- yysymprint Args; \
-} while (0)
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
-# define YYDSYMPRINTF(Title, Token, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Token, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, yyscanner); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
} while (0)
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (yyscanner);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
+ YYFPRINTF (yyoutput, ")");
+}
+
/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included). |
`------------------------------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
static void
-yy_stack_print (short int *bottom, short int *top)
-#else
-static void
-yy_stack_print (bottom, top)
- short int *bottom;
- short int *top;
-#endif
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
{
YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
YYFPRINTF (stderr, "\n");
}
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
} while (0)
@@ -1747,29 +1732,30 @@ do { \
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
static void
-yy_reduce_print (yyrule)
- int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
int yyi;
- unsigned int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
yyrule - 1, yylno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , yyscanner);
+ YYFPRINTF (stderr, "\n");
+ }
}
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (Rule); \
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
} while (0)
/* Nonzero means print parse trace. It is left uninitialized so that
@@ -1777,15 +1763,14 @@ do { \
int yydebug;
#else /* !YYDEBUG */
# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
+#ifndef YYINITDEPTH
# define YYINITDEPTH 200
#endif
@@ -1793,58 +1778,40 @@ int yydebug;
if the built-in stack extension method is used).
Do not make this value too large; the results are undefined if
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
evaluated with infinite-precision integer arithmetic. */
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif
-
#if YYERROR_VERBOSE
# ifndef yystrlen
-# if defined (__GLIBC__) && defined (_STRING_H)
+# if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
yystrlen (const char *yystr)
-# else
-yystrlen (yystr)
- const char *yystr;
-# endif
{
- const char *yys = yystr;
-
- while (*yys++ != '\0')
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
continue;
-
- return yys - yystr - 1;
+ return yylen;
}
# endif
# endif
# ifndef yystpcpy
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
# define yystpcpy stpcpy
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
static char *
-# if defined (__STDC__) || defined (__cplusplus)
yystpcpy (char *yydest, const char *yysrc)
-# else
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
{
char *yyd = yydest;
const char *yys = yysrc;
@@ -1857,91 +1824,207 @@ yystpcpy (yydest, yysrc)
# endif
# endif
-#endif /* !YYERROR_VERBOSE */
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
-
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+ if (! yyres)
+ return yystrlen (yystr);
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
- if (yytype < YYNTOKENS)
- {
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
}
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
- switch (yytype)
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
{
- default:
- break;
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
}
- YYFPRINTF (yyoutput, ")");
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
}
+#endif /* YYERROR_VERBOSE */
-#endif /* ! YYDEBUG */
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ YYUSE (yyvaluep);
+ YYUSE (yyscanner);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
- switch (yytype)
- {
-
- default:
- break;
- }
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM);
-# else
-int yyparse ();
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
@@ -1950,90 +2033,76 @@ int yyparse ();
| yyparse. |
`----------*/
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
+yyparse (yyscan_t yyscanner)
{
- /* The lookahead symbol. */
+/* The lookahead symbol. */
int yychar;
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-/* Number of syntax errors so far. */
-int yynerrs;
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
+ /* Number of syntax errors so far. */
+ int yynerrs;
- /* The state stack. */
- short int yyssa[YYINITDEPTH];
- short int *yyss = yyssa;
- short int *yyssp;
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
-#define YYPOPSTACK (yyvsp--, yyssp--)
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
- YYSIZE_T yystacksize = YYINITDEPTH;
+ YYSIZE_T yystacksize;
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
-
-
+ yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
/*------------------------------------------------------------.
@@ -2041,8 +2110,7 @@ int yynerrs;
`------------------------------------------------------------*/
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.
- */
+ have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
yysetstate:
@@ -2055,49 +2123,46 @@ int yynerrs;
#ifdef yyoverflow
{
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- short int *yyss1 = yyss;
-
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow ("parser stack overflow",
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
-
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
- goto yyoverflowlab;
+ goto yyexhaustedlab;
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyoverflowlab;
+ goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
+ yystacksize = YYMAXDEPTH;
{
- short int *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyoverflowlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
}
# endif
#endif /* no yyoverflow */
@@ -2105,16 +2170,18 @@ int yynerrs;
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
-
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long int) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
+ YYABORT;
}
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
goto yybackup;
/*-----------.
@@ -2122,14 +2189,12 @@ int yynerrs;
`-----------*/
yybackup:
-/* Do appropriate processing given the current state. */
-/* Read a lookahead token if we need one and don't already have one. */
-/* yyresume: */
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
/* First try to decide what to do without reference to lookahead token. */
-
yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
+ if (yypact_value_is_default (yyn))
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
@@ -2138,7 +2203,7 @@ yybackup:
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
+ yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
@@ -2149,7 +2214,7 @@ yybackup:
else
{
yytoken = YYTRANSLATE (yychar);
- YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
}
/* If the proper action on seeing token YYTOKEN is to reduce or to
@@ -2160,31 +2225,28 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Shift the lookahead token. */
- YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-
-
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
goto yynewstate;
@@ -2206,7 +2268,7 @@ yyreduce:
yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ '$$ = $1'.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
@@ -2220,3581 +2282,3927 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 192 "cmDependsJavaParser.y"
+#line 180 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 3:
-#line 201 "cmDependsJavaParser.y"
+#line 189 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 4:
-#line 209 "cmDependsJavaParser.y"
+#line 197 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 5:
-#line 217 "cmDependsJavaParser.y"
+#line 205 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 6:
-#line 225 "cmDependsJavaParser.y"
+#line 213 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 7:
-#line 233 "cmDependsJavaParser.y"
+#line 221 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 8:
-#line 241 "cmDependsJavaParser.y"
+#line 229 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 9:
-#line 250 "cmDependsJavaParser.y"
+#line 238 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 10:
-#line 258 "cmDependsJavaParser.y"
+#line 246 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 11:
-#line 267 "cmDependsJavaParser.y"
+#line 255 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 12:
-#line 275 "cmDependsJavaParser.y"
+#line 263 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 13:
-#line 284 "cmDependsJavaParser.y"
+#line 272 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 14:
-#line 289 "cmDependsJavaParser.y"
+#line 277 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 15:
-#line 294 "cmDependsJavaParser.y"
+#line 282 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 16:
-#line 299 "cmDependsJavaParser.y"
+#line 287 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 17:
-#line 304 "cmDependsJavaParser.y"
+#line 292 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 18:
-#line 309 "cmDependsJavaParser.y"
+#line 297 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 19:
-#line 314 "cmDependsJavaParser.y"
+#line 302 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 20:
-#line 319 "cmDependsJavaParser.y"
+#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
+#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 21:
-#line 325 "cmDependsJavaParser.y"
+#line 313 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 22:
-#line 333 "cmDependsJavaParser.y"
+#line 321 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 23:
-#line 342 "cmDependsJavaParser.y"
+#line 330 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- jpStoreClass(yyvsp[0].str);
+ jpStoreClass((yyvsp[0].str));
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 24:
-#line 352 "cmDependsJavaParser.y"
+#line 340 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 25:
-#line 361 "cmDependsJavaParser.y"
+#line 349 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 26:
-#line 370 "cmDependsJavaParser.y"
+#line 358 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 27:
-#line 378 "cmDependsJavaParser.y"
+#line 366 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
- jpStoreClass(yyvsp[-1].str);
+ jpStoreClass((yyvsp[-1].str));
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 28:
-#line 388 "cmDependsJavaParser.y"
+#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = yyvsp[0].str;
+ (yyval.str) = (yyvsp[0].str);
}
+#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 29:
-#line 394 "cmDependsJavaParser.y"
+#line 382 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = yyvsp[0].str;
+ (yyval.str) = (yyvsp[0].str);
}
+#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 30:
-#line 401 "cmDependsJavaParser.y"
+#line 389 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = yyvsp[0].str;
+ (yyval.str) = (yyvsp[0].str);
}
+#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 31:
-#line 408 "cmDependsJavaParser.y"
+#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = yyvsp[0].str;
+ (yyval.str) = (yyvsp[0].str);
}
+#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 32:
-#line 414 "cmDependsJavaParser.y"
+#line 402 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
- yyval.str = yyvsp[0].str;
+ (yyval.str) = (yyvsp[0].str);
}
+#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 33:
-#line 421 "cmDependsJavaParser.y"
+#line 409 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->AddClassFound(yyvsp[-2].str);
- yyGetParser->UpdateCombine(yyvsp[-2].str, yyvsp[0].str);
- yyGetParser->DeallocateParserType(&(yyvsp[-2].str));
- yyval.str = const_cast<char*>(yyGetParser->GetCurrentCombine());
+ yyGetParser->AddClassFound((yyvsp[-2].str));
+ yyGetParser->UpdateCombine((yyvsp[-2].str), (yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
+ (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
}
+#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 34:
-#line 430 "cmDependsJavaParser.y"
+#line 418 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- jpStoreClass(yyvsp[-2].str);
+ jpStoreClass((yyvsp[-2].str));
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 35:
-#line 440 "cmDependsJavaParser.y"
+#line 428 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- jpStoreClass(yyvsp[-2].str);
+ jpStoreClass((yyvsp[-2].str));
yyGetParser->SetCurrentCombine("");
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 36:
-#line 450 "cmDependsJavaParser.y"
+#line 438 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 37:
-#line 459 "cmDependsJavaParser.y"
+#line 447 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 38:
-#line 467 "cmDependsJavaParser.y"
+#line 455 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 39:
-#line 476 "cmDependsJavaParser.y"
+#line 464 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 40:
-#line 484 "cmDependsJavaParser.y"
+#line 472 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 41:
-#line 491 "cmDependsJavaParser.y"
+#line 479 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 42:
-#line 499 "cmDependsJavaParser.y"
+#line 487 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 43:
-#line 506 "cmDependsJavaParser.y"
+#line 494 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 44:
-#line 514 "cmDependsJavaParser.y"
+#line 502 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 45:
-#line 521 "cmDependsJavaParser.y"
+#line 509 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 46:
-#line 530 "cmDependsJavaParser.y"
+#line 518 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->SetCurrentPackage(yyvsp[-1].str);
- yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+ yyGetParser->SetCurrentPackage((yyvsp[-1].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
yyGetParser->SetCurrentCombine("");
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 47:
-#line 542 "cmDependsJavaParser.y"
+#line 530 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 48:
-#line 550 "cmDependsJavaParser.y"
+#line 538 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 49:
-#line 559 "cmDependsJavaParser.y"
+#line 547 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->AddPackagesImport(yyvsp[-1].str);
- yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+ yyGetParser->AddPackagesImport((yyvsp[-1].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
yyGetParser->SetCurrentCombine("");
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 50:
-#line 571 "cmDependsJavaParser.y"
+#line 559 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
- std::string str = yyvsp[-3].str;
+ std::string str = (yyvsp[-3].str);
str += ".*";
yyGetParser->AddPackagesImport(str.c_str());
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 51:
-#line 584 "cmDependsJavaParser.y"
+#line 572 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 52:
-#line 592 "cmDependsJavaParser.y"
+#line 580 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 53:
-#line 600 "cmDependsJavaParser.y"
+#line 588 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 54:
-#line 609 "cmDependsJavaParser.y"
+#line 597 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 55:
-#line 617 "cmDependsJavaParser.y"
+#line 605 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 67:
-#line 632 "cmDependsJavaParser.y"
+#line 620 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
- yyGetParser->StartClass(yyvsp[0].str);
+ yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
+#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 68:
-#line 642 "cmDependsJavaParser.y"
+#line 630 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
+#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 69:
-#line 651 "cmDependsJavaParser.y"
+#line 639 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
+#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 70:
-#line 660 "cmDependsJavaParser.y"
+#line 648 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
+#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 71:
-#line 669 "cmDependsJavaParser.y"
+#line 657 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
+#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 72:
-#line 678 "cmDependsJavaParser.y"
+#line 666 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 73:
-#line 685 "cmDependsJavaParser.y"
+#line 673 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 74:
-#line 694 "cmDependsJavaParser.y"
+#line 682 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 75:
-#line 703 "cmDependsJavaParser.y"
+#line 691 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 76:
-#line 712 "cmDependsJavaParser.y"
+#line 700 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 77:
-#line 720 "cmDependsJavaParser.y"
+#line 708 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 78:
-#line 729 "cmDependsJavaParser.y"
+#line 717 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 79:
-#line 737 "cmDependsJavaParser.y"
+#line 725 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 80:
-#line 744 "cmDependsJavaParser.y"
+#line 732 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 81:
-#line 753 "cmDependsJavaParser.y"
+#line 741 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 82:
-#line 761 "cmDependsJavaParser.y"
+#line 749 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 83:
-#line 769 "cmDependsJavaParser.y"
+#line 757 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 84:
-#line 777 "cmDependsJavaParser.y"
+#line 765 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 85:
-#line 786 "cmDependsJavaParser.y"
+#line 774 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 86:
-#line 794 "cmDependsJavaParser.y"
+#line 782 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 87:
-#line 803 "cmDependsJavaParser.y"
+#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
}
+#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 88:
-#line 809 "cmDependsJavaParser.y"
+#line 797 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 89:
-#line 817 "cmDependsJavaParser.y"
+#line 805 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 90:
-#line 826 "cmDependsJavaParser.y"
+#line 814 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 91:
-#line 834 "cmDependsJavaParser.y"
+#line 822 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 92:
-#line 843 "cmDependsJavaParser.y"
+#line 831 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 93:
-#line 852 "cmDependsJavaParser.y"
+#line 840 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 94:
-#line 861 "cmDependsJavaParser.y"
+#line 849 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 95:
-#line 869 "cmDependsJavaParser.y"
+#line 857 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 96:
-#line 878 "cmDependsJavaParser.y"
+#line 866 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 97:
-#line 886 "cmDependsJavaParser.y"
+#line 874 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 98:
-#line 894 "cmDependsJavaParser.y"
+#line 882 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 99:
-#line 903 "cmDependsJavaParser.y"
+#line 891 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 100:
-#line 912 "cmDependsJavaParser.y"
+#line 900 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 101:
-#line 921 "cmDependsJavaParser.y"
+#line 909 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 102:
-#line 929 "cmDependsJavaParser.y"
+#line 917 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 103:
-#line 939 "cmDependsJavaParser.y"
+#line 927 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 104:
-#line 949 "cmDependsJavaParser.y"
+#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
}
+#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 105:
-#line 955 "cmDependsJavaParser.y"
+#line 943 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 107:
-#line 966 "cmDependsJavaParser.y"
+#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
+#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 108:
-#line 972 "cmDependsJavaParser.y"
+#line 960 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 109:
-#line 982 "cmDependsJavaParser.y"
+#line 970 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 110:
-#line 992 "cmDependsJavaParser.y"
+#line 980 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 111:
-#line 1002 "cmDependsJavaParser.y"
+#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
+#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 112:
-#line 1008 "cmDependsJavaParser.y"
+#line 996 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 113:
-#line 1018 "cmDependsJavaParser.y"
+#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 114:
-#line 1028 "cmDependsJavaParser.y"
+#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 115:
-#line 1038 "cmDependsJavaParser.y"
+#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 116:
-#line 1047 "cmDependsJavaParser.y"
+#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 117:
-#line 1057 "cmDependsJavaParser.y"
+#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 118:
-#line 1068 "cmDependsJavaParser.y"
+#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 119:
-#line 1077 "cmDependsJavaParser.y"
+#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 120:
-#line 1085 "cmDependsJavaParser.y"
+#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 121:
-#line 1095 "cmDependsJavaParser.y"
+#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 122:
-#line 1104 "cmDependsJavaParser.y"
+#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 123:
-#line 1114 "cmDependsJavaParser.y"
+#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
- yyGetParser->StartClass(yyvsp[0].str);
+ yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
+#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 124:
-#line 1123 "cmDependsJavaParser.y"
+#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
+#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 125:
-#line 1132 "cmDependsJavaParser.y"
+#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 126:
-#line 1139 "cmDependsJavaParser.y"
+#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 127:
-#line 1149 "cmDependsJavaParser.y"
+#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 128:
-#line 1158 "cmDependsJavaParser.y"
+#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 129:
-#line 1168 "cmDependsJavaParser.y"
+#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 130:
-#line 1177 "cmDependsJavaParser.y"
+#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 131:
-#line 1185 "cmDependsJavaParser.y"
+#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 132:
-#line 1194 "cmDependsJavaParser.y"
+#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 133:
-#line 1203 "cmDependsJavaParser.y"
+#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 134:
-#line 1212 "cmDependsJavaParser.y"
+#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 135:
-#line 1221 "cmDependsJavaParser.y"
+#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 136:
-#line 1229 "cmDependsJavaParser.y"
+#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 137:
-#line 1238 "cmDependsJavaParser.y"
+#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 138:
-#line 1247 "cmDependsJavaParser.y"
+#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 139:
-#line 1257 "cmDependsJavaParser.y"
+#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 140:
-#line 1267 "cmDependsJavaParser.y"
+#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 141:
-#line 1276 "cmDependsJavaParser.y"
+#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 142:
-#line 1286 "cmDependsJavaParser.y"
+#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 143:
-#line 1295 "cmDependsJavaParser.y"
+#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 144:
-#line 1303 "cmDependsJavaParser.y"
+#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 145:
-#line 1312 "cmDependsJavaParser.y"
+#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 146:
-#line 1322 "cmDependsJavaParser.y"
+#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 147:
-#line 1331 "cmDependsJavaParser.y"
+#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 148:
-#line 1341 "cmDependsJavaParser.y"
+#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 149:
-#line 1349 "cmDependsJavaParser.y"
+#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 150:
-#line 1357 "cmDependsJavaParser.y"
+#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 151:
-#line 1367 "cmDependsJavaParser.y"
+#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 152:
-#line 1376 "cmDependsJavaParser.y"
+#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 153:
-#line 1386 "cmDependsJavaParser.y"
+#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 154:
-#line 1395 "cmDependsJavaParser.y"
+#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 155:
-#line 1404 "cmDependsJavaParser.y"
+#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 156:
-#line 1414 "cmDependsJavaParser.y"
+#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 157:
-#line 1424 "cmDependsJavaParser.y"
+#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 158:
-#line 1433 "cmDependsJavaParser.y"
+#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 159:
-#line 1443 "cmDependsJavaParser.y"
+#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 160:
-#line 1452 "cmDependsJavaParser.y"
+#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 161:
-#line 1461 "cmDependsJavaParser.y"
+#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 162:
-#line 1470 "cmDependsJavaParser.y"
+#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 163:
-#line 1479 "cmDependsJavaParser.y"
+#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 164:
-#line 1488 "cmDependsJavaParser.y"
+#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 165:
-#line 1498 "cmDependsJavaParser.y"
+#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 166:
-#line 1507 "cmDependsJavaParser.y"
+#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 167:
-#line 1516 "cmDependsJavaParser.y"
+#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 168:
-#line 1525 "cmDependsJavaParser.y"
+#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 169:
-#line 1534 "cmDependsJavaParser.y"
+#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 170:
-#line 1544 "cmDependsJavaParser.y"
+#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 171:
-#line 1553 "cmDependsJavaParser.y"
+#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 172:
-#line 1562 "cmDependsJavaParser.y"
+#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 173:
-#line 1571 "cmDependsJavaParser.y"
+#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 174:
-#line 1580 "cmDependsJavaParser.y"
+#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 175:
-#line 1589 "cmDependsJavaParser.y"
+#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 176:
-#line 1598 "cmDependsJavaParser.y"
+#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 177:
-#line 1607 "cmDependsJavaParser.y"
+#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 178:
-#line 1616 "cmDependsJavaParser.y"
+#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 179:
-#line 1625 "cmDependsJavaParser.y"
+#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 180:
-#line 1634 "cmDependsJavaParser.y"
+#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 181:
-#line 1643 "cmDependsJavaParser.y"
+#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 182:
-#line 1653 "cmDependsJavaParser.y"
+#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 183:
-#line 1663 "cmDependsJavaParser.y"
+#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[-2].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 184:
-#line 1674 "cmDependsJavaParser.y"
+#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 185:
-#line 1684 "cmDependsJavaParser.y"
+#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 186:
-#line 1694 "cmDependsJavaParser.y"
+#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 187:
-#line 1703 "cmDependsJavaParser.y"
+#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 188:
-#line 1712 "cmDependsJavaParser.y"
+#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 189:
-#line 1721 "cmDependsJavaParser.y"
+#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 190:
-#line 1730 "cmDependsJavaParser.y"
+#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 191:
-#line 1739 "cmDependsJavaParser.y"
+#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 192:
-#line 1748 "cmDependsJavaParser.y"
+#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 193:
-#line 1758 "cmDependsJavaParser.y"
+#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 194:
-#line 1768 "cmDependsJavaParser.y"
+#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(7);
jpCheckEmpty(7);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 195:
-#line 1778 "cmDependsJavaParser.y"
+#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(7);
jpCheckEmpty(7);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 196:
-#line 1788 "cmDependsJavaParser.y"
+#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
+#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 197:
-#line 1795 "cmDependsJavaParser.y"
+#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
}
+#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 198:
-#line 1801 "cmDependsJavaParser.y"
+#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 199:
-#line 1809 "cmDependsJavaParser.y"
+#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 200:
-#line 1818 "cmDependsJavaParser.y"
+#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 201:
-#line 1826 "cmDependsJavaParser.y"
+#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 202:
-#line 1836 "cmDependsJavaParser.y"
+#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 203:
-#line 1846 "cmDependsJavaParser.y"
+#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 204:
-#line 1855 "cmDependsJavaParser.y"
+#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 205:
-#line 1865 "cmDependsJavaParser.y"
+#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 206:
-#line 1874 "cmDependsJavaParser.y"
+#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 207:
-#line 1884 "cmDependsJavaParser.y"
+#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
+#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 208:
-#line 1891 "cmDependsJavaParser.y"
+#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
+#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 209:
-#line 1898 "cmDependsJavaParser.y"
+#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(7);
}
+#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 210:
-#line 1906 "cmDependsJavaParser.y"
+#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(9);
}
+#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 211:
-#line 1912 "cmDependsJavaParser.y"
+#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 212:
-#line 1920 "cmDependsJavaParser.y"
+#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 213:
-#line 1929 "cmDependsJavaParser.y"
+#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 214:
-#line 1937 "cmDependsJavaParser.y"
+#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 215:
-#line 1948 "cmDependsJavaParser.y"
+#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(9);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 216:
-#line 1956 "cmDependsJavaParser.y"
+#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 217:
-#line 1964 "cmDependsJavaParser.y"
+#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 218:
-#line 1974 "cmDependsJavaParser.y"
+#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 219:
-#line 1983 "cmDependsJavaParser.y"
+#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 220:
-#line 1993 "cmDependsJavaParser.y"
+#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 221:
-#line 2003 "cmDependsJavaParser.y"
+#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 222:
-#line 2012 "cmDependsJavaParser.y"
+#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 223:
-#line 2022 "cmDependsJavaParser.y"
+#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 224:
-#line 2031 "cmDependsJavaParser.y"
+#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 225:
-#line 2041 "cmDependsJavaParser.y"
+#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 226:
-#line 2051 "cmDependsJavaParser.y"
+#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 227:
-#line 2059 "cmDependsJavaParser.y"
+#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
+#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 228:
-#line 2066 "cmDependsJavaParser.y"
+#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 229:
-#line 2077 "cmDependsJavaParser.y"
+#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 230:
-#line 2087 "cmDependsJavaParser.y"
+#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 231:
-#line 2097 "cmDependsJavaParser.y"
+#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 232:
-#line 2107 "cmDependsJavaParser.y"
+#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 233:
-#line 2116 "cmDependsJavaParser.y"
+#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 234:
-#line 2125 "cmDependsJavaParser.y"
+#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 235:
-#line 2133 "cmDependsJavaParser.y"
+#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 236:
-#line 2143 "cmDependsJavaParser.y"
+#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 237:
-#line 2152 "cmDependsJavaParser.y"
+#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 238:
-#line 2162 "cmDependsJavaParser.y"
+#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
+#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 239:
-#line 2169 "cmDependsJavaParser.y"
+#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 240:
-#line 2179 "cmDependsJavaParser.y"
+#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 241:
-#line 2188 "cmDependsJavaParser.y"
+#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 242:
-#line 2198 "cmDependsJavaParser.y"
+#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 243:
-#line 2207 "cmDependsJavaParser.y"
+#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
+#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 244:
-#line 2213 "cmDependsJavaParser.y"
+#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 245:
-#line 2222 "cmDependsJavaParser.y"
+#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 246:
-#line 2231 "cmDependsJavaParser.y"
+#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 247:
-#line 2240 "cmDependsJavaParser.y"
+#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 248:
-#line 2249 "cmDependsJavaParser.y"
+#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 249:
-#line 2259 "cmDependsJavaParser.y"
+#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
jpCheckEmpty(6);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 250:
-#line 2268 "cmDependsJavaParser.y"
+#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 251:
-#line 2276 "cmDependsJavaParser.y"
+#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 252:
-#line 2285 "cmDependsJavaParser.y"
+#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 253:
-#line 2293 "cmDependsJavaParser.y"
+#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 254:
-#line 2303 "cmDependsJavaParser.y"
+#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 255:
-#line 2312 "cmDependsJavaParser.y"
+#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 256:
-#line 2322 "cmDependsJavaParser.y"
+#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 257:
-#line 2331 "cmDependsJavaParser.y"
+#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 258:
-#line 2340 "cmDependsJavaParser.y"
+#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 259:
-#line 2349 "cmDependsJavaParser.y"
+#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 260:
-#line 2358 "cmDependsJavaParser.y"
+#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 261:
-#line 2366 "cmDependsJavaParser.y"
+#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 262:
-#line 2376 "cmDependsJavaParser.y"
+#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 263:
-#line 2385 "cmDependsJavaParser.y"
+#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 264:
-#line 2395 "cmDependsJavaParser.y"
+#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 265:
-#line 2405 "cmDependsJavaParser.y"
+#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
}
+#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 266:
-#line 2411 "cmDependsJavaParser.y"
+#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
}
+#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 267:
-#line 2418 "cmDependsJavaParser.y"
+#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 268:
-#line 2428 "cmDependsJavaParser.y"
+#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 269:
-#line 2438 "cmDependsJavaParser.y"
+#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 270:
-#line 2448 "cmDependsJavaParser.y"
+#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 271:
-#line 2459 "cmDependsJavaParser.y"
+#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 272:
-#line 2469 "cmDependsJavaParser.y"
+#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
- yyGetParser->DeallocateParserType(&(yyvsp[-5].str));
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(6);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 273:
-#line 2480 "cmDependsJavaParser.y"
+#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(6);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 274:
-#line 2490 "cmDependsJavaParser.y"
+#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(6);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 275:
-#line 2501 "cmDependsJavaParser.y"
+#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
- yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 276:
-#line 2511 "cmDependsJavaParser.y"
+#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 277:
-#line 2521 "cmDependsJavaParser.y"
+#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 278:
-#line 2530 "cmDependsJavaParser.y"
+#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
- yyval.str = 0;
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 279:
-#line 2539 "cmDependsJavaParser.y"
+#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 280:
-#line 2548 "cmDependsJavaParser.y"
+#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 281:
-#line 2557 "cmDependsJavaParser.y"
+#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 282:
-#line 2567 "cmDependsJavaParser.y"
+#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 283:
-#line 2577 "cmDependsJavaParser.y"
+#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 284:
-#line 2587 "cmDependsJavaParser.y"
+#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 285:
-#line 2596 "cmDependsJavaParser.y"
+#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 286:
-#line 2605 "cmDependsJavaParser.y"
+#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 287:
-#line 2614 "cmDependsJavaParser.y"
+#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 288:
-#line 2623 "cmDependsJavaParser.y"
+#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 289:
-#line 2633 "cmDependsJavaParser.y"
+#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 290:
-#line 2643 "cmDependsJavaParser.y"
+#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 291:
-#line 2653 "cmDependsJavaParser.y"
+#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 292:
-#line 2662 "cmDependsJavaParser.y"
+#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 293:
-#line 2671 "cmDependsJavaParser.y"
+#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 294:
-#line 2680 "cmDependsJavaParser.y"
+#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 295:
-#line 2690 "cmDependsJavaParser.y"
+#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 296:
-#line 2699 "cmDependsJavaParser.y"
+#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 297:
-#line 2708 "cmDependsJavaParser.y"
+#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
+#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 298:
-#line 2715 "cmDependsJavaParser.y"
+#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 299:
-#line 2724 "cmDependsJavaParser.y"
+#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 300:
-#line 2733 "cmDependsJavaParser.y"
+#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 301:
-#line 2742 "cmDependsJavaParser.y"
+#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 302:
-#line 2752 "cmDependsJavaParser.y"
+#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 303:
-#line 2761 "cmDependsJavaParser.y"
+#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 304:
-#line 2770 "cmDependsJavaParser.y"
+#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 305:
-#line 2780 "cmDependsJavaParser.y"
+#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 306:
-#line 2789 "cmDependsJavaParser.y"
+#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 307:
-#line 2798 "cmDependsJavaParser.y"
+#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 308:
-#line 2807 "cmDependsJavaParser.y"
+#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 309:
-#line 2817 "cmDependsJavaParser.y"
+#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 310:
-#line 2826 "cmDependsJavaParser.y"
+#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 311:
-#line 2835 "cmDependsJavaParser.y"
+#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 312:
-#line 2844 "cmDependsJavaParser.y"
+#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 313:
-#line 2853 "cmDependsJavaParser.y"
+#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 314:
-#line 2862 "cmDependsJavaParser.y"
+#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 315:
-#line 2872 "cmDependsJavaParser.y"
+#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 316:
-#line 2881 "cmDependsJavaParser.y"
+#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 317:
-#line 2890 "cmDependsJavaParser.y"
+#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 318:
-#line 2900 "cmDependsJavaParser.y"
+#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 319:
-#line 2909 "cmDependsJavaParser.y"
+#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 320:
-#line 2919 "cmDependsJavaParser.y"
+#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 321:
-#line 2928 "cmDependsJavaParser.y"
+#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 322:
-#line 2938 "cmDependsJavaParser.y"
+#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 323:
-#line 2947 "cmDependsJavaParser.y"
+#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 324:
-#line 2957 "cmDependsJavaParser.y"
+#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 325:
-#line 2966 "cmDependsJavaParser.y"
+#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 326:
-#line 2976 "cmDependsJavaParser.y"
+#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 327:
-#line 2985 "cmDependsJavaParser.y"
+#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 328:
-#line 2995 "cmDependsJavaParser.y"
+#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 329:
-#line 3004 "cmDependsJavaParser.y"
+#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 330:
-#line 3014 "cmDependsJavaParser.y"
+#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 331:
-#line 3023 "cmDependsJavaParser.y"
+#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 332:
-#line 3033 "cmDependsJavaParser.y"
+#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 333:
-#line 3043 "cmDependsJavaParser.y"
+#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
- yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+ yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 334:
-#line 3053 "cmDependsJavaParser.y"
+#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 335:
-#line 3062 "cmDependsJavaParser.y"
+#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 336:
-#line 3072 "cmDependsJavaParser.y"
+#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 337:
-#line 3081 "cmDependsJavaParser.y"
+#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 338:
-#line 3090 "cmDependsJavaParser.y"
+#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 339:
-#line 3099 "cmDependsJavaParser.y"
+#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 340:
-#line 3108 "cmDependsJavaParser.y"
+#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 341:
-#line 3117 "cmDependsJavaParser.y"
+#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 342:
-#line 3126 "cmDependsJavaParser.y"
+#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 343:
-#line 3135 "cmDependsJavaParser.y"
+#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 344:
-#line 3144 "cmDependsJavaParser.y"
+#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 345:
-#line 3153 "cmDependsJavaParser.y"
+#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 346:
-#line 3162 "cmDependsJavaParser.y"
+#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 347:
-#line 3171 "cmDependsJavaParser.y"
+#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 348:
-#line 3181 "cmDependsJavaParser.y"
+#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 349:
-#line 3191 "cmDependsJavaParser.y"
+#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 350:
-#line 3201 "cmDependsJavaParser.y"
+#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 351:
-#line 3210 "cmDependsJavaParser.y"
+#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
- jpStoreClass(yyvsp[-2].str);
+ jpStoreClass((yyvsp[-2].str));
jpCheckEmpty(3);
- yyval.str = 0;
+ (yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
+#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
+#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+ default: break;
}
-
-/* Line 1010 of yacc.c. */
-#line 5780 "cmDependsJavaParser.cxx"
-
- yyvsp -= yylen;
- yyssp -= yylen;
-
-
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
-
- /* Now `shift' the result of the reduction. Determine what state
+ /* 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. */
@@ -5809,74 +6217,52 @@ yyreduce:
goto yynewstate;
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
-#if YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- YYSIZE_T yysize = 0;
- int yytype = YYTRANSLATE (yychar);
- const char* yyprefix;
- char *yymsg;
- int yyx;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 0;
-
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
- yycount += 1;
- if (yycount == 5)
- {
- yysize = 0;
- break;
- }
- }
- yysize += (sizeof ("syntax error, unexpected ")
- + yystrlen (yytname[yytype]));
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg != 0)
+#if ! YYERROR_VERBOSE
+ yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
{
- char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
- yyp = yystpcpy (yyp, yytname[yytype]);
-
- if (yycount < 5)
- {
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
{
- yyp = yystpcpy (yyp, yyprefix);
- yyp = yystpcpy (yyp, yytname[yyx]);
- yyprefix = " or ";
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
}
- }
- yyerror (yymsg);
- YYSTACK_FREE (yymsg);
+ yyerror (yyscanner, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
}
- else
- yyerror ("syntax error; also virtual memory exhausted");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror ("syntax error");
+# undef YYSYNTAX_ERROR
+#endif
}
@@ -5884,31 +6270,23 @@ yyerrlab:
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
- error, discard it. */
+ error, discard it. */
if (yychar <= YYEOF)
{
- /* If at end of input, pop the error token,
- then the rest of the stack, then return failure. */
- if (yychar == YYEOF)
- for (;;)
- {
- YYPOPSTACK;
- if (yyssp == yyss)
- YYABORT;
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[*yyssp], yyvsp);
- }
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
}
else
- {
- YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
- yydestruct (yytoken, &yylval);
- yychar = YYEMPTY;
-
- }
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, yyscanner);
+ yychar = YYEMPTY;
+ }
}
+#if 0
/* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -5919,15 +6297,17 @@ yyerrlab:
`---------------------------------------------------*/
yyerrorlab:
-#if defined(__GNUC__) || defined(__HP_aCC)
- /* Pacify GCC when the user code never invokes YYERROR and the label
- yyerrorlab therefore never appears in user code. */
- if (0)
+ /* 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;
-#endif
- yyvsp -= yylen;
- yyssp -= yylen;
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
goto yyerrlab1;
@@ -5936,40 +6316,42 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
+#endif
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
for (;;)
{
yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
- YYABORT;
+ YYABORT;
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[yystate], yyvsp);
- YYPOPSTACK;
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yyscanner);
+ YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
- YYDPRINTF ((stderr, "Shifting error token, "));
-
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
yystate = yyn;
goto yynewstate;
@@ -5989,33 +6371,51 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here. |
-`----------------------------------------------*/
-yyoverflowlab:
- yyerror ("parser stack overflow");
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, yyscanner);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yyscanner);
+ YYPOPSTACK (1);
+ }
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
return yyresult;
}
-
-
-#line 3219 "cmDependsJavaParser.y"
+#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906 */
/* End of grammar */
/*--------------------------------------------------------------------------*/
-void cmDependsJavaError(yyscan_t yyscanner, const char* message)
+void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message)
{
yyGetParser->Error(message);
}
-
-
diff --git a/Source/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y
index 944d4b5ce..f7eb22818 100644
--- a/Source/cmDependsJavaParser.y
+++ b/Source/LexerParser/cmDependsJavaParser.y
@@ -1,15 +1,6 @@
%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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.
@@ -19,18 +10,16 @@ Run bison like this:
bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
Modify cmDependsJavaParser.cxx:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - add __HP_aCC to the #if test for yyerrorlab warning suppression
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
*/
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmDependsJava_yyerror(x) \
- cmDependsJavaError(yyscanner, x)
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
/*-------------------------------------------------------------------------*/
@@ -41,10 +30,9 @@ Modify cmDependsJavaParser.cxx:
/* Forward declare the lexer entry point. */
YY_DECL;
-/* Internal utility functions. */
-static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
+/* Helper function to forward error callback from parser. */
+static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
-#define YYDEBUG 1
#define YYMAXDEPTH 1000000
@@ -52,12 +40,6 @@ static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
#ifdef _MSC_VER
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
@@ -65,7 +47,13 @@ static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
%}
/* Generate a reentrant parser object. */
-%pure_parser
+%define api.pure
+
+/* Configure the parser to use a lexer object. */
+%lex-param {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
/*
%union {
@@ -254,7 +242,7 @@ jp_DECIMALINTEGERLITERAL
yyGetParser->SetCurrentCombine("");
}
|
-jp_HEXINTEGERLITERAL
+jp_HEXINTEGERLITERAL
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3220,8 +3208,7 @@ Name jp_DOT jp_NEW
/* End of grammar */
/*--------------------------------------------------------------------------*/
-void cmDependsJavaError(yyscan_t yyscanner, const char* message)
+void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message)
{
yyGetParser->Error(message);
}
-
diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h
new file mode 100644
index 000000000..7f18f1dd8
--- /dev/null
+++ b/Source/LexerParser/cmDependsJavaParserTokens.h
@@ -0,0 +1,264 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmDependsJava_yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ jp_ABSTRACT = 258,
+ jp_ASSERT = 259,
+ jp_BOOLEAN_TYPE = 260,
+ jp_BREAK = 261,
+ jp_BYTE_TYPE = 262,
+ jp_CASE = 263,
+ jp_CATCH = 264,
+ jp_CHAR_TYPE = 265,
+ jp_CLASS = 266,
+ jp_CONTINUE = 267,
+ jp_DEFAULT = 268,
+ jp_DO = 269,
+ jp_DOUBLE_TYPE = 270,
+ jp_ELSE = 271,
+ jp_EXTENDS = 272,
+ jp_FINAL = 273,
+ jp_FINALLY = 274,
+ jp_FLOAT_TYPE = 275,
+ jp_FOR = 276,
+ jp_IF = 277,
+ jp_IMPLEMENTS = 278,
+ jp_IMPORT = 279,
+ jp_INSTANCEOF = 280,
+ jp_INT_TYPE = 281,
+ jp_INTERFACE = 282,
+ jp_LONG_TYPE = 283,
+ jp_NATIVE = 284,
+ jp_NEW = 285,
+ jp_PACKAGE = 286,
+ jp_PRIVATE = 287,
+ jp_PROTECTED = 288,
+ jp_PUBLIC = 289,
+ jp_RETURN = 290,
+ jp_SHORT_TYPE = 291,
+ jp_STATIC = 292,
+ jp_STRICTFP = 293,
+ jp_SUPER = 294,
+ jp_SWITCH = 295,
+ jp_SYNCHRONIZED = 296,
+ jp_THIS = 297,
+ jp_THROW = 298,
+ jp_THROWS = 299,
+ jp_TRANSIENT = 300,
+ jp_TRY = 301,
+ jp_VOID = 302,
+ jp_VOLATILE = 303,
+ jp_WHILE = 304,
+ jp_BOOLEANLITERAL = 305,
+ jp_CHARACTERLITERAL = 306,
+ jp_DECIMALINTEGERLITERAL = 307,
+ jp_FLOATINGPOINTLITERAL = 308,
+ jp_HEXINTEGERLITERAL = 309,
+ jp_NULLLITERAL = 310,
+ jp_STRINGLITERAL = 311,
+ jp_NAME = 312,
+ jp_AND = 313,
+ jp_ANDAND = 314,
+ jp_ANDEQUALS = 315,
+ jp_BRACKETEND = 316,
+ jp_BRACKETSTART = 317,
+ jp_CARROT = 318,
+ jp_CARROTEQUALS = 319,
+ jp_COLON = 320,
+ jp_COMMA = 321,
+ jp_CURLYEND = 322,
+ jp_CURLYSTART = 323,
+ jp_DIVIDE = 324,
+ jp_DIVIDEEQUALS = 325,
+ jp_DOLLAR = 326,
+ jp_DOT = 327,
+ jp_EQUALS = 328,
+ jp_EQUALSEQUALS = 329,
+ jp_EXCLAMATION = 330,
+ jp_EXCLAMATIONEQUALS = 331,
+ jp_GREATER = 332,
+ jp_GTEQUALS = 333,
+ jp_GTGT = 334,
+ jp_GTGTEQUALS = 335,
+ jp_GTGTGT = 336,
+ jp_GTGTGTEQUALS = 337,
+ jp_LESLESEQUALS = 338,
+ jp_LESSTHAN = 339,
+ jp_LTEQUALS = 340,
+ jp_LTLT = 341,
+ jp_MINUS = 342,
+ jp_MINUSEQUALS = 343,
+ jp_MINUSMINUS = 344,
+ jp_PAREEND = 345,
+ jp_PARESTART = 346,
+ jp_PERCENT = 347,
+ jp_PERCENTEQUALS = 348,
+ jp_PIPE = 349,
+ jp_PIPEEQUALS = 350,
+ jp_PIPEPIPE = 351,
+ jp_PLUS = 352,
+ jp_PLUSEQUALS = 353,
+ jp_PLUSPLUS = 354,
+ jp_QUESTION = 355,
+ jp_SEMICOL = 356,
+ jp_TILDE = 357,
+ jp_TIMES = 358,
+ jp_TIMESEQUALS = 359,
+ jp_ERROR = 360
+ };
+#endif
+/* Tokens. */
+#define jp_ABSTRACT 258
+#define jp_ASSERT 259
+#define jp_BOOLEAN_TYPE 260
+#define jp_BREAK 261
+#define jp_BYTE_TYPE 262
+#define jp_CASE 263
+#define jp_CATCH 264
+#define jp_CHAR_TYPE 265
+#define jp_CLASS 266
+#define jp_CONTINUE 267
+#define jp_DEFAULT 268
+#define jp_DO 269
+#define jp_DOUBLE_TYPE 270
+#define jp_ELSE 271
+#define jp_EXTENDS 272
+#define jp_FINAL 273
+#define jp_FINALLY 274
+#define jp_FLOAT_TYPE 275
+#define jp_FOR 276
+#define jp_IF 277
+#define jp_IMPLEMENTS 278
+#define jp_IMPORT 279
+#define jp_INSTANCEOF 280
+#define jp_INT_TYPE 281
+#define jp_INTERFACE 282
+#define jp_LONG_TYPE 283
+#define jp_NATIVE 284
+#define jp_NEW 285
+#define jp_PACKAGE 286
+#define jp_PRIVATE 287
+#define jp_PROTECTED 288
+#define jp_PUBLIC 289
+#define jp_RETURN 290
+#define jp_SHORT_TYPE 291
+#define jp_STATIC 292
+#define jp_STRICTFP 293
+#define jp_SUPER 294
+#define jp_SWITCH 295
+#define jp_SYNCHRONIZED 296
+#define jp_THIS 297
+#define jp_THROW 298
+#define jp_THROWS 299
+#define jp_TRANSIENT 300
+#define jp_TRY 301
+#define jp_VOID 302
+#define jp_VOLATILE 303
+#define jp_WHILE 304
+#define jp_BOOLEANLITERAL 305
+#define jp_CHARACTERLITERAL 306
+#define jp_DECIMALINTEGERLITERAL 307
+#define jp_FLOATINGPOINTLITERAL 308
+#define jp_HEXINTEGERLITERAL 309
+#define jp_NULLLITERAL 310
+#define jp_STRINGLITERAL 311
+#define jp_NAME 312
+#define jp_AND 313
+#define jp_ANDAND 314
+#define jp_ANDEQUALS 315
+#define jp_BRACKETEND 316
+#define jp_BRACKETSTART 317
+#define jp_CARROT 318
+#define jp_CARROTEQUALS 319
+#define jp_COLON 320
+#define jp_COMMA 321
+#define jp_CURLYEND 322
+#define jp_CURLYSTART 323
+#define jp_DIVIDE 324
+#define jp_DIVIDEEQUALS 325
+#define jp_DOLLAR 326
+#define jp_DOT 327
+#define jp_EQUALS 328
+#define jp_EQUALSEQUALS 329
+#define jp_EXCLAMATION 330
+#define jp_EXCLAMATIONEQUALS 331
+#define jp_GREATER 332
+#define jp_GTEQUALS 333
+#define jp_GTGT 334
+#define jp_GTGTEQUALS 335
+#define jp_GTGTGT 336
+#define jp_GTGTGTEQUALS 337
+#define jp_LESLESEQUALS 338
+#define jp_LESSTHAN 339
+#define jp_LTEQUALS 340
+#define jp_LTLT 341
+#define jp_MINUS 342
+#define jp_MINUSEQUALS 343
+#define jp_MINUSMINUS 344
+#define jp_PAREEND 345
+#define jp_PARESTART 346
+#define jp_PERCENT 347
+#define jp_PERCENTEQUALS 348
+#define jp_PIPE 349
+#define jp_PIPEEQUALS 350
+#define jp_PIPEPIPE 351
+#define jp_PLUS 352
+#define jp_PLUSEQUALS 353
+#define jp_PLUSPLUS 354
+#define jp_QUESTION 355
+#define jp_SEMICOL 356
+#define jp_TILDE 357
+#define jp_TIMES 358
+#define jp_TIMESEQUALS 359
+#define jp_ERROR 360
+
+/* Value type. */
+
+
+
+int cmDependsJava_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */
diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx
new file mode 100644
index 000000000..fb6f0db98
--- /dev/null
+++ b/Source/LexerParser/cmExprLexer.cxx
@@ -0,0 +1,2033 @@
+#include "cmStandardLexer.h"
+#line 2 "cmExprLexer.cxx"
+
+#line 4 "cmExprLexer.cxx"
+
+#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 1
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#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
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* 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 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.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmExpr_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 cmExpr_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 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)
+
+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 );
+
+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 );
+
+#define yy_new_buffer cmExpr_yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ cmExpr_yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmExpr_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); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmExpr_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 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 );
+
+/* 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 15
+#define YY_END_OF_BUFFER 16
+/* 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 yyconst flex_int16_t yy_accept[23] =
+ { 0,
+ 0, 0, 16, 15, 6, 8, 13, 14, 4, 2,
+ 3, 5, 1, 15, 15, 9, 7, 10, 1, 11,
+ 12, 0
+ } ;
+
+static yyconst YY_CHAR yy_ec[256] =
+ { 0,
+ 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, 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, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 14, 1, 15, 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 yyconst YY_CHAR yy_meta[16] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_uint16_t yy_base[23] =
+ { 0,
+ 0, 0, 20, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 9, 7, 5, 21, 21, 21, 6, 21,
+ 21, 21
+ } ;
+
+static yyconst flex_int16_t yy_def[23] =
+ { 0,
+ 22, 1, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 0
+ } ;
+
+static yyconst flex_uint16_t yy_nxt[37] =
+ { 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
+ } ;
+
+static yyconst flex_int16_t yy_chk[37] =
+ { 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
+ } ;
+
+/* 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
+#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. */
+/*
+
+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
+
+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
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#include "cmExprParserHelper.h"
+
+/* Replace the lexer input function. */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ { result = yyextra->LexInput(buf, max_size); }
+
+/* Include the set of tokens from the parser. */
+#include "cmExprParserTokens.h"
+
+/*--------------------------------------------------------------------------*/
+#line 476 "cmExprLexer.cxx"
+
+#define INITIAL 0
+
+#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 cmExpr_yylex_init (yyscan_t* scanner);
+
+int cmExpr_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 cmExpr_yyget_debug (yyscan_t yyscanner );
+
+void cmExpr_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE cmExpr_yyget_extra (yyscan_t yyscanner );
+
+void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *cmExpr_yyget_in (yyscan_t yyscanner );
+
+void cmExpr_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+
+FILE *cmExpr_yyget_out (yyscan_t yyscanner );
+
+void cmExpr_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+
+ int cmExpr_yyget_leng (yyscan_t yyscanner );
+
+char *cmExpr_yyget_text (yyscan_t yyscanner );
+
+int cmExpr_yyget_lineno (yyscan_t yyscanner );
+
+void cmExpr_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmExpr_yyget_column (yyscan_t yyscanner );
+
+void cmExpr_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 cmExpr_yywrap (yyscan_t yyscanner );
+#else
+extern int cmExpr_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 *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst 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 = '*'; \
+ size_t 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, 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 cmExpr_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int cmExpr_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 ) {
+ cmExpr_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmExpr_yy_load_buffer_state(yyscanner );
+ }
+
+ {
+#line 39 "cmExprLexer.in.l"
+
+
+#line 732 "cmExprLexer.cxx"
+
+ 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 >= 23 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 21 );
+
+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
+#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; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 44 "cmExprLexer.in.l"
+{ return exp_MINUS; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 45 "cmExprLexer.in.l"
+{ return exp_TIMES; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 46 "cmExprLexer.in.l"
+{ return exp_DIVIDE; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 47 "cmExprLexer.in.l"
+{ return exp_MOD; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 48 "cmExprLexer.in.l"
+{ return exp_OR; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 49 "cmExprLexer.in.l"
+{ return exp_AND; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 50 "cmExprLexer.in.l"
+{ return exp_XOR; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 51 "cmExprLexer.in.l"
+{ return exp_NOT; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 52 "cmExprLexer.in.l"
+{ return exp_SHIFTLEFT; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 53 "cmExprLexer.in.l"
+{ return exp_SHIFTRIGHT; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 54 "cmExprLexer.in.l"
+{ return exp_OPENPARENT; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 55 "cmExprLexer.in.l"
+{ return exp_CLOSEPARENT; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 57 "cmExprLexer.in.l"
+ECHO;
+ YY_BREAK
+#line 864 "cmExprLexer.cxx"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ 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
+ * cmExpr_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 ( cmExpr_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 cmExpr_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;
+ yy_size_t 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 = (yy_size_t) (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. */
+ cmExpr_yyrealloc((void *) b->yy_ch_buf,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;
+ cmExpr_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 ((int) (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 );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ 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 >= 23 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) 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 >= 23 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 22);
+
+ (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 = 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. */
+ cmExpr_yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( cmExpr_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 cmExpr_yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ cmExpr_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmExpr_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ cmExpr_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)
+{
+ 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);
+ */
+ cmExpr_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;
+ cmExpr_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
+ * 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)
+{
+ 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 cmExpr_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 );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_create_buffer()" );
+
+ b->yy_buf_size = (yy_size_t)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 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ cmExpr_yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with cmExpr_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void cmExpr_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 )
+ cmExpr_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ cmExpr_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.
+ */
+ static void cmExpr_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);
+
+ 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.
+ * 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 cmExpr_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 )
+ cmExpr_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 cmExpr_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);
+
+ /* This block is copied from cmExpr_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 cmExpr_yy_switch_to_buffer. */
+ cmExpr_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 cmExpr_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_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 );
+ 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 cmExpr_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int 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**)cmExpr_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()" );
+
+ 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**)cmExpr_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()" );
+
+ /* 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 cmExpr_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) cmExpr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_scan_buffer()" );
+
+ b->yy_buf_size = 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;
+
+ cmExpr_yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to cmExpr_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_BUFFER_STATE cmExpr_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return cmExpr_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
+ * 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 b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t 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 );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_scan_bytes()" );
+
+ for ( i = 0; i < (size_t)_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);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in cmExpr_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 (yyconst char* msg , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) 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 cmExpr_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 cmExpr_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 cmExpr_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 *cmExpr_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 *cmExpr_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 cmExpr_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 *cmExpr_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 cmExpr_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 cmExpr_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" );
+
+ yylineno = _line_number;
+}
+
+/** Set the current column.
+ * @param _column_no column number
+ * @param yyscanner The scanner object.
+ */
+void cmExpr_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" );
+
+ 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 cmExpr_yy_switch_to_buffer
+ */
+void cmExpr_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = _out_str ;
+}
+
+int cmExpr_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = _bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* cmExpr_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)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmExpr_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 );
+}
+
+/* cmExpr_yylex_init_extra has the same functionality as cmExpr_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 yyextra field.
+ */
+
+int cmExpr_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);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmExpr_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));
+
+ cmExpr_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 cmExpr_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
+ * cmExpr_yylex_init()
+ */
+ return 0;
+}
+
+/* cmExpr_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int cmExpr_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_CURRENT_BUFFER_LVALUE = NULL;
+ cmExpr_yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ cmExpr_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ cmExpr_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. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ cmExpr_yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst 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 (yyconst char * s , yyscan_t yyscanner)
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *cmExpr_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)
+{
+ 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 cmExpr_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 */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 57 "cmExprLexer.in.l"
diff --git a/Source/cmExprLexer.h b/Source/LexerParser/cmExprLexer.h
index 03b36cec5..835a7a36a 100644
--- a/Source/cmExprLexer.h
+++ b/Source/LexerParser/cmExprLexer.h
@@ -1,30 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
#ifndef cmExpr_yyHEADER_H
#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
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -46,7 +36,15 @@
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#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;
@@ -61,7 +59,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -92,26 +89,17 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_CONST
+#endif /* ! C99 */
-#endif /* __STDC__ */
-#endif /* ! __cplusplus */
+#endif /* ! FLEXINT_H */
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* An opaque pointer. */
@@ -131,91 +119,91 @@ typedef void* yyscan_t;
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
-int cmExpr_yylex_init (yyscan_t* scanner);
+/* 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
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int 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.
- */
- yy_size_t 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;
+ {
+ 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;
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
- int yy_buffer_status;
+ int yy_buffer_status;
- };
+ };
#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_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_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
void cmExpr_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 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 );
void *cmExpr_yyalloc (yy_size_t ,yyscan_t yyscanner );
void *cmExpr_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
@@ -223,7 +211,7 @@ void cmExpr_yyfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
-#define cmExpr_yywrap(n) 1
+#define cmExpr_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
@@ -237,6 +225,10 @@ void cmExpr_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
+int cmExpr_yylex_init (yyscan_t* scanner);
+
+int cmExpr_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. */
@@ -252,19 +244,23 @@ void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *cmExpr_yyget_in (yyscan_t yyscanner );
-void cmExpr_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+void cmExpr_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *cmExpr_yyget_out (yyscan_t yyscanner );
-void cmExpr_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+void cmExpr_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
-int cmExpr_yyget_leng (yyscan_t yyscanner );
+ int cmExpr_yyget_leng (yyscan_t yyscanner );
char *cmExpr_yyget_text (yyscan_t yyscanner );
int cmExpr_yyget_lineno (yyscan_t yyscanner );
-void cmExpr_yyset_lineno (int line_number ,yyscan_t yyscanner );
+void cmExpr_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmExpr_yyget_column (yyscan_t yyscanner );
+
+void cmExpr_yyset_column (int _column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -292,7 +288,12 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
/* 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. */
@@ -311,15 +312,13 @@ extern int cmExpr_yylex (yyscan_t yyscanner);
#define YY_DECL int cmExpr_yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
-/* yy_get_previous_state - get the state just before the EOB char was
- reached */
+/* 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 yytext_ptr
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
@@ -327,8 +326,9 @@ extern int cmExpr_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
+#line 57 "cmExprLexer.in.l"
-
+#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
new file mode 100644
index 000000000..25ddba460
--- /dev/null
+++ b/Source/LexerParser/cmExprLexer.in.l
@@ -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. */
+/*
+
+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
+
+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
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#include "cmExprParserHelper.h"
+
+/* Replace the lexer input function. */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ { result = yyextra->LexInput(buf, max_size); }
+
+/* Include the set of tokens from the parser. */
+#include "cmExprParserTokens.h"
+
+/*--------------------------------------------------------------------------*/
+%}
+
+%option reentrant
+%option noyywrap
+%pointer
+
+%%
+
+[0-9][0-9]* { yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+
+"+" { return exp_PLUS; }
+"-" { return exp_MINUS; }
+"*" { return exp_TIMES; }
+"/" { return exp_DIVIDE; }
+"%" { return exp_MOD; }
+"\|" { return exp_OR; }
+"&" { return exp_AND; }
+"^" { return exp_XOR; }
+"~" { return exp_NOT; }
+"<<" { return exp_SHIFTLEFT; }
+">>" { return exp_SHIFTRIGHT; }
+"(" { return exp_OPENPARENT; }
+")" { return exp_CLOSEPARENT; }
+
+%%
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
new file mode 100644
index 000000000..67664a5f5
--- /dev/null
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -0,0 +1,1698 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names. */
+#define yyparse cmExpr_yyparse
+#define yylex cmExpr_yylex
+#define yyerror cmExpr_yyerror
+#define yydebug cmExpr_yydebug
+#define yynerrs cmExpr_yynerrs
+
+
+/* Copy the first part of user declarations. */
+#line 1 "cmExprParser.y" /* yacc.c:339 */
+
+/* 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 bison like this:
+
+ bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
+
+Modify cmExprParser.cxx:
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define YYDEBUG 1
+#include "cmExprParserHelper.h" /* Interface to parser object. */
+#include "cmExprLexer.h" /* Interface to lexer object. */
+#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+
+/* Forward declare the lexer entry point. */
+YY_DECL;
+
+/* Helper function to forward error callback from parser. */
+static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Disable some warnings in the generated code. */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label. */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+
+#line 112 "cmExprParser.cxx" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "cmExprParserTokens.h". */
+#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
+# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmExpr_yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ exp_PLUS = 258,
+ exp_MINUS = 259,
+ exp_TIMES = 260,
+ exp_DIVIDE = 261,
+ exp_MOD = 262,
+ exp_SHIFTLEFT = 263,
+ exp_SHIFTRIGHT = 264,
+ exp_OPENPARENT = 265,
+ exp_CLOSEPARENT = 266,
+ exp_OR = 267,
+ exp_AND = 268,
+ exp_XOR = 269,
+ exp_NOT = 270,
+ exp_NUMBER = 271
+ };
+#endif
+/* Tokens. */
+#define exp_PLUS 258
+#define exp_MINUS 259
+#define exp_TIMES 260
+#define exp_DIVIDE 261
+#define exp_MOD 262
+#define exp_SHIFTLEFT 263
+#define exp_SHIFTRIGHT 264
+#define exp_OPENPARENT 265
+#define exp_CLOSEPARENT 266
+#define exp_OR 267
+#define exp_AND 268
+#define exp_XOR 269
+#define exp_NOT 270
+#define exp_NUMBER 271
+
+/* Value type. */
+
+
+
+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
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# 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))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 17
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 30
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 17
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 10
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 23
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 39
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 271
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16
+};
+
+#if YYDEBUG
+ /* 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
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "exp_PLUS", "exp_MINUS", "exp_TIMES",
+ "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT", "exp_SHIFTRIGHT",
+ "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR", "exp_AND", "exp_XOR",
+ "exp_NOT", "exp_NUMBER", "$accept", "start", "exp", "bitwiseor",
+ "bitwisexor", "bitwiseand", "shift", "term", "unary", "factor", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271
+};
+# endif
+
+#define YYPACT_NINF -8
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-8)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ 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
+};
+
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ 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
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -8, -8, 12, 5, 11, 9, -2, 4, -1, -8
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 5, 6, 7, 8, 9, 10, 11, 12, 13
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ 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
+};
+
+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
+};
+
+ /* 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
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+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
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+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
+};
+
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+#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)
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, yyscanner); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (yyscanner);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , yyscanner);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+{
+ YYUSE (yyvaluep);
+ YYUSE (yyscanner);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (yyscan_t yyscanner)
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ 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;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# 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));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ 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. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = yylex (&yylval, yyscanner);
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 73 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
+ }
+#line 1289 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 3:
+#line 78 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1297 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 4:
+#line 81 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
+ }
+#line 1305 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 5:
+#line 86 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1313 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 89 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
+ }
+#line 1321 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 94 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1329 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 97 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
+ }
+#line 1337 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 9:
+#line 102 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1345 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 10:
+#line 105 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
+ }
+#line 1353 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 11:
+#line 108 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
+ }
+#line 1361 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 113 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1369 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 13:
+#line 116 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
+ }
+#line 1377 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 14:
+#line 119 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
+ }
+#line 1385 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 124 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1393 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 16:
+#line 127 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
+ }
+#line 1401 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 17:
+#line 130 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
+ }
+#line 1409 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 18:
+#line 133 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
+ }
+#line 1417 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 19:
+#line 138 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1425 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 20:
+#line 141 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = + (yyvsp[0].Number);
+ }
+#line 1433 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 21:
+#line 144 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = - (yyvsp[0].Number);
+ }
+#line 1441 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 22:
+#line 149 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1449 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 23:
+#line 152 "cmExprParser.y" /* yacc.c:1646 */
+ {
+ (yyval.Number) = (yyvsp[-1].Number);
+ }
+#line 1457 "cmExprParser.cxx" /* yacc.c:1646 */
+ break;
+
+
+#line 1461 "cmExprParser.cxx" /* yacc.c:1646 */
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* 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];
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (yyscanner, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, yyscanner);
+ yychar = YYEMPTY;
+ }
+ }
+
+#if 0
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| 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;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+#endif
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yyscanner);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (yyscanner, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, yyscanner);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yyscanner);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ return yyresult;
+}
+#line 157 "cmExprParser.y" /* yacc.c:1906 */
+
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
+{
+ cmExpr_yyget_extra(yyscanner)->Error(message);
+}
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
new file mode 100644
index 000000000..d1c3a97a7
--- /dev/null
+++ b/Source/LexerParser/cmExprParser.y
@@ -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. */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+ bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
+
+Modify cmExprParser.cxx:
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define YYDEBUG 1
+#include "cmExprParserHelper.h" /* Interface to parser object. */
+#include "cmExprLexer.h" /* Interface to lexer object. */
+#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+
+/* Forward declare the lexer entry point. */
+YY_DECL;
+
+/* Helper function to forward error callback from parser. */
+static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Disable some warnings in the generated code. */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label. */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+%}
+
+/* Generate a reentrant parser object. */
+%define api.pure
+
+/* Configure the parser to use a lexer object. */
+%lex-param {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token exp_PLUS
+%token exp_MINUS
+%token exp_TIMES
+%token exp_DIVIDE
+%token exp_MOD
+%token exp_SHIFTLEFT
+%token exp_SHIFTRIGHT
+%token exp_OPENPARENT
+%token exp_CLOSEPARENT
+%token exp_OR;
+%token exp_AND;
+%token exp_XOR;
+%token exp_NOT;
+%token exp_NUMBER;
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+
+start:
+ exp {
+ cmExpr_yyget_extra(yyscanner)->SetResult($<Number>1);
+ }
+
+exp:
+ bitwiseor {
+ $<Number>$ = $<Number>1;
+ }
+| exp exp_OR bitwiseor {
+ $<Number>$ = $<Number>1 | $<Number>3;
+ }
+
+bitwiseor:
+ bitwisexor {
+ $<Number>$ = $<Number>1;
+ }
+| bitwiseor exp_XOR bitwisexor {
+ $<Number>$ = $<Number>1 ^ $<Number>3;
+ }
+
+bitwisexor:
+ bitwiseand {
+ $<Number>$ = $<Number>1;
+ }
+| bitwisexor exp_AND bitwiseand {
+ $<Number>$ = $<Number>1 & $<Number>3;
+ }
+
+bitwiseand:
+ shift {
+ $<Number>$ = $<Number>1;
+ }
+| bitwiseand exp_SHIFTLEFT shift {
+ $<Number>$ = $<Number>1 << $<Number>3;
+ }
+| bitwiseand exp_SHIFTRIGHT shift {
+ $<Number>$ = $<Number>1 >> $<Number>3;
+ }
+
+shift:
+ term {
+ $<Number>$ = $<Number>1;
+ }
+| shift exp_PLUS term {
+ $<Number>$ = $<Number>1 + $<Number>3;
+ }
+| shift exp_MINUS term {
+ $<Number>$ = $<Number>1 - $<Number>3;
+ }
+
+term:
+ unary {
+ $<Number>$ = $<Number>1;
+ }
+| term exp_TIMES unary {
+ $<Number>$ = $<Number>1 * $<Number>3;
+ }
+| term exp_DIVIDE unary {
+ $<Number>$ = $<Number>1 / $<Number>3;
+ }
+| term exp_MOD unary {
+ $<Number>$ = $<Number>1 % $<Number>3;
+ }
+
+unary:
+ factor {
+ $<Number>$ = $<Number>1;
+ }
+| exp_PLUS unary {
+ $<Number>$ = + $<Number>2;
+ }
+| exp_MINUS unary {
+ $<Number>$ = - $<Number>2;
+ }
+
+factor:
+ exp_NUMBER {
+ $<Number>$ = $<Number>1;
+ }
+| exp_OPENPARENT exp exp_CLOSEPARENT {
+ $<Number>$ = $<Number>2;
+ }
+;
+
+%%
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
+{
+ cmExpr_yyget_extra(yyscanner)->Error(message);
+}
diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h
new file mode 100644
index 000000000..84b2bbdcd
--- /dev/null
+++ b/Source/LexerParser/cmExprParserTokens.h
@@ -0,0 +1,86 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
+# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmExpr_yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ exp_PLUS = 258,
+ exp_MINUS = 259,
+ exp_TIMES = 260,
+ exp_DIVIDE = 261,
+ exp_MOD = 262,
+ exp_SHIFTLEFT = 263,
+ exp_SHIFTRIGHT = 264,
+ exp_OPENPARENT = 265,
+ exp_CLOSEPARENT = 266,
+ exp_OR = 267,
+ exp_AND = 268,
+ exp_XOR = 269,
+ exp_NOT = 270,
+ exp_NUMBER = 271
+ };
+#endif
+/* Tokens. */
+#define exp_PLUS 258
+#define exp_MINUS 259
+#define exp_TIMES 260
+#define exp_DIVIDE 261
+#define exp_MOD 262
+#define exp_SHIFTLEFT 263
+#define exp_SHIFTRIGHT 264
+#define exp_OPENPARENT 265
+#define exp_CLOSEPARENT 266
+#define exp_OR 267
+#define exp_AND 268
+#define exp_XOR 269
+#define exp_NOT 270
+#define exp_NUMBER 271
+
+/* Value type. */
+
+
+
+int cmExpr_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED */
diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx
new file mode 100644
index 000000000..01c09acb7
--- /dev/null
+++ b/Source/LexerParser/cmFortranLexer.cxx
@@ -0,0 +1,2511 @@
+#include "cmStandardLexer.h"
+#line 2 "cmFortranLexer.cxx"
+
+#line 4 "cmFortranLexer.cxx"
+
+#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 1
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#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
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* 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 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.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmFortran_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 cmFortran_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 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)
+
+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 );
+
+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 );
+
+#define yy_new_buffer cmFortran_yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ cmFortran_yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmFortran_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); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmFortran_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 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 );
+
+/* 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 54
+#define YY_END_OF_BUFFER 55
+/* 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 yyconst 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,
+ 48, 35, 37, 50, 39, 49, 46, 46, 46, 46,
+ 46, 46, 49, 46, 51, 49, 50, 49, 46, 9,
+ 8, 9, 4, 3, 49, 0, 10, 0, 0, 0,
+ 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,
+ 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,
+ 46, 46, 0, 24, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32, 27, 0, 0, 20, 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,
+
+ 14, 16, 42, 44, 0, 0, 0, 13, 0
+ } ;
+
+static yyconst 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,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 5, 6, 7, 8, 9, 1, 10, 11, 12,
+ 13, 14, 1, 15, 1, 1, 1, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 17, 18, 19,
+ 20, 21, 22, 1, 23, 24, 25, 26, 27, 28,
+ 29, 29, 30, 29, 29, 31, 32, 33, 34, 29,
+ 29, 35, 36, 37, 38, 29, 29, 29, 29, 29,
+ 1, 39, 1, 1, 40, 1, 23, 24, 41, 42,
+
+ 43, 44, 29, 29, 45, 29, 29, 46, 32, 47,
+ 34, 29, 29, 35, 48, 37, 49, 29, 29, 29,
+ 29, 29, 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 yyconst 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,
+ 6, 1, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 1, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7
+ } ;
+
+static yyconst flex_uint16_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
+ } ;
+
+static yyconst 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,
+ 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,
+ 211, 209, 209, 209, 209, 209, 209, 214, 214, 209,
+ 39, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 215, 215, 215, 215, 209, 209, 213, 213, 213, 213,
+
+ 213, 213, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 209, 213, 213, 213, 213, 209, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209, 213, 213,
+ 213, 213, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 213, 213, 213, 213, 209, 209, 209, 209, 209, 209,
+ 209, 216, 217, 209, 209, 209, 209, 213, 213, 213,
+ 209, 209, 209, 209, 209, 209, 209, 209, 213, 213,
+
+ 209, 209, 213, 213, 209, 218, 218, 209, 0, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209
+ } ;
+
+static yyconst flex_uint16_t yy_nxt[633] =
+ { 0,
+ 12, 13, 14, 13, 13, 15, 16, 12, 17, 18,
+ 19, 20, 21, 12, 22, 12, 23, 24, 12, 25,
+ 12, 26, 27, 27, 27, 27, 28, 27, 27, 29,
+ 27, 30, 27, 27, 27, 31, 27, 32, 33, 34,
+ 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,
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+ 81, 79, 79, 79, 79, 79, 79, 81, 81, 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,
+ 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,
+ 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] =
+ { 0,
+ 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, 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,
+ 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,
+ 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,
+ 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
+ * 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
+#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. */
+/*-------------------------------------------------------------------------
+ Portions of this source have been derived from makedepf90 version 2.8.8,
+
+ Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann@iki.fi>
+
+ The code was originally distributed under the GPL but permission
+ from the copyright holder has been obtained to distribute this
+ derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+
+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
+
+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
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#undef YY_NO_UNPUT
+
+#define cmFortranLexer_cxx
+#include "cmFortranParser.h" /* Interface to parser object. */
+
+/* Replace the lexer input function. */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ { result = cmFortranParser_Input(yyextra, buf, max_size); }
+
+/* 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
+#define str_sq 3
+#define str_dq 4
+
+#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 cmFortran_yylex_init (yyscan_t* scanner);
+
+int cmFortran_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 cmFortran_yyget_debug (yyscan_t yyscanner );
+
+void cmFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner );
+
+void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *cmFortran_yyget_in (yyscan_t yyscanner );
+
+void cmFortran_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+
+FILE *cmFortran_yyget_out (yyscan_t yyscanner );
+
+void cmFortran_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+
+ int cmFortran_yyget_leng (yyscan_t yyscanner );
+
+char *cmFortran_yyget_text (yyscan_t yyscanner );
+
+int cmFortran_yyget_lineno (yyscan_t yyscanner );
+
+void cmFortran_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmFortran_yyget_column (yyscan_t yyscanner );
+
+void cmFortran_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 cmFortran_yywrap (yyscan_t yyscanner );
+#else
+extern int cmFortran_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 *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst 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 = '*'; \
+ size_t 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, 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 cmFortran_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int cmFortran_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 \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ 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 ) {
+ cmFortran_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmFortran_yy_load_buffer_state(yyscanner );
+ }
+
+ {
+#line 56 "cmFortranLexer.in.l"
+
+
+#line 951 "cmFortranLexer.cxx"
+
+ 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_current_state += YY_AT_BOL();
+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 >= 210 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 583 );
+
+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
+#line 58 "cmFortranLexer.in.l"
+{
+ cmFortranParser_StringStart(yyextra);
+ cmFortranParser_SetOldStartcond(yyextra, YY_START);
+ BEGIN(str_dq);
+}
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 64 "cmFortranLexer.in.l"
+{
+ cmFortranParser_StringStart(yyextra);
+ cmFortranParser_SetOldStartcond(yyextra, YY_START);
+ BEGIN(str_sq);
+}
+ 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));
+ return STRING;
+}
+ 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) */
+ else
+ {
+ unput(yytext[strlen(yytext)-1]);
+ }
+}
+ YY_BREAK
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+#line 90 "cmFortranLexer.in.l"
+{
+ unput ('\n');
+ BEGIN(INITIAL);
+ return UNTERMINATED_STRING;
+}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 96 "cmFortranLexer.in.l"
+{
+ cmFortranParser_StringAppend(yyextra, yytext[0]);
+}
+ YY_BREAK
+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);
+ return CPP_INCLUDE_ANGLE;
+}
+ 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;
+}
+ 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):
+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) )
+ {
+ return YY_NULL;
+ }
+}
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 178 "cmFortranLexer.in.l"
+ECHO;
+ YY_BREAK
+#line 1331 "cmFortranLexer.cxx"
+
+ 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
+ * cmFortran_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 ( cmFortran_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 cmFortran_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;
+ yy_size_t 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 = (yy_size_t) (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. */
+ cmFortran_yyrealloc((void *) b->yy_ch_buf,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;
+ cmFortran_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 ((int) (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 );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ 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;
+ yy_current_state += YY_AT_BOL();
+
+ 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 >= 210 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) 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 >= 210 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 209);
+
+ (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 = 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. */
+ cmFortran_yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( cmFortran_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;
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ 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 cmFortran_yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ cmFortran_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmFortran_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ cmFortran_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)
+{
+ 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);
+ */
+ cmFortran_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;
+ cmFortran_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
+ * 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)
+{
+ 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 cmFortran_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 );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_create_buffer()" );
+
+ b->yy_buf_size = (yy_size_t)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 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ cmFortran_yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with cmFortran_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void cmFortran_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 )
+ cmFortran_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ cmFortran_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.
+ */
+ static void cmFortran_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);
+
+ 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.
+ * 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 cmFortran_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 )
+ cmFortran_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 cmFortran_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);
+
+ /* This block is copied from cmFortran_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 cmFortran_yy_switch_to_buffer. */
+ cmFortran_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 cmFortran_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_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 );
+ 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 cmFortran_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int 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**)cmFortran_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()" );
+
+ 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**)cmFortran_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()" );
+
+ /* 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 cmFortran_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) cmFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_scan_buffer()" );
+
+ b->yy_buf_size = 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;
+
+ cmFortran_yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to cmFortran_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_BUFFER_STATE cmFortran_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return cmFortran_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
+ * 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 b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t 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 );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_scan_bytes()" );
+
+ for ( i = 0; i < (size_t)_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);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in cmFortran_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 (yyconst char* msg , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) 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 cmFortran_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 cmFortran_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 cmFortran_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 *cmFortran_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 *cmFortran_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 cmFortran_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 *cmFortran_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 cmFortran_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 cmFortran_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" );
+
+ yylineno = _line_number;
+}
+
+/** Set the current column.
+ * @param _column_no column number
+ * @param yyscanner The scanner object.
+ */
+void cmFortran_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" );
+
+ 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 cmFortran_yy_switch_to_buffer
+ */
+void cmFortran_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = _out_str ;
+}
+
+int cmFortran_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = _bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* cmFortran_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)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmFortran_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 );
+}
+
+/* cmFortran_yylex_init_extra has the same functionality as cmFortran_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 yyextra field.
+ */
+
+int cmFortran_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);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmFortran_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));
+
+ cmFortran_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 cmFortran_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
+ * cmFortran_yylex_init()
+ */
+ return 0;
+}
+
+/* cmFortran_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int cmFortran_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_CURRENT_BUFFER_LVALUE = NULL;
+ cmFortran_yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ cmFortran_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ cmFortran_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. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ cmFortran_yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst 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 (yyconst char * s , yyscan_t yyscanner)
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *cmFortran_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)
+{
+ 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 cmFortran_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 */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 178 "cmFortranLexer.in.l"
+
+
+
+/*--------------------------------------------------------------------------*/
+YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
+{
+ /* Hack into the internal flex-generated scanner to get the buffer. */
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return YY_CURRENT_BUFFER;
+}
diff --git a/Source/cmDependsFortranLexer.h b/Source/LexerParser/cmFortranLexer.h
index 8e24cfd80..ddda91965 100644
--- a/Source/cmDependsFortranLexer.h
+++ b/Source/LexerParser/cmFortranLexer.h
@@ -1,26 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+#ifndef cmFortran_yyHEADER_H
+#define cmFortran_yyHEADER_H 1
+#define cmFortran_yyIN_HEADER 1
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#line 6 "cmFortranLexer.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDependsFortran_yyHEADER_H
-#define cmDependsFortran_yyHEADER_H 1
-#define cmDependsFortran_yyIN_HEADER 1
+#line 8 "cmFortranLexer.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 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -99,25 +93,13 @@ typedef unsigned int flex_uint32_t;
#endif /* ! FLEXINT_H */
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* An opaque pointer. */
@@ -163,73 +145,73 @@ typedef size_t yy_size_t;
#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.
- */
- yy_size_t 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;
+ {
+ 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;
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
- int yy_buffer_status;
+ int yy_buffer_status;
- };
+ };
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-void cmDependsFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmDependsFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmDependsFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner );
+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 );
-YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsFortran_yy_scan_bytes (yyconst char *bytes,int len ,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 );
-void *cmDependsFortran_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmDependsFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmDependsFortran_yyfree (void * ,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 );
/* Begin user sect3 */
-#define cmDependsFortran_yywrap(n) 1
+#define cmFortran_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
@@ -247,38 +229,42 @@ void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
-int cmDependsFortran_yylex_init (yyscan_t* scanner);
+int cmFortran_yylex_init (yyscan_t* scanner);
-int cmDependsFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int cmFortran_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 cmDependsFortran_yylex_destroy (yyscan_t yyscanner );
+int cmFortran_yylex_destroy (yyscan_t yyscanner );
+
+int cmFortran_yyget_debug (yyscan_t yyscanner );
-int cmDependsFortran_yyget_debug (yyscan_t yyscanner );
+void cmFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-void cmDependsFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner );
-YY_EXTRA_TYPE cmDependsFortran_yyget_extra (yyscan_t yyscanner );
+void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-void cmDependsFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+FILE *cmFortran_yyget_in (yyscan_t yyscanner );
-FILE *cmDependsFortran_yyget_in (yyscan_t yyscanner );
+void cmFortran_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
-void cmDependsFortran_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+FILE *cmFortran_yyget_out (yyscan_t yyscanner );
-FILE *cmDependsFortran_yyget_out (yyscan_t yyscanner );
+void cmFortran_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
-void cmDependsFortran_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+ int cmFortran_yyget_leng (yyscan_t yyscanner );
-int cmDependsFortran_yyget_leng (yyscan_t yyscanner );
+char *cmFortran_yyget_text (yyscan_t yyscanner );
-char *cmDependsFortran_yyget_text (yyscan_t yyscanner );
+int cmFortran_yyget_lineno (yyscan_t yyscanner );
-int cmDependsFortran_yyget_lineno (yyscan_t yyscanner );
+void cmFortran_yyset_lineno (int _line_number ,yyscan_t yyscanner );
-void cmDependsFortran_yyset_lineno (int line_number ,yyscan_t yyscanner );
+int cmFortran_yyget_column (yyscan_t yyscanner );
+
+void cmFortran_yyset_column (int _column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -286,9 +272,9 @@ void cmDependsFortran_yyset_lineno (int line_number ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmDependsFortran_yywrap (yyscan_t yyscanner );
+extern "C" int cmFortran_yywrap (yyscan_t yyscanner );
#else
-extern int cmDependsFortran_yywrap (yyscan_t yyscanner );
+extern int cmFortran_yywrap (yyscan_t yyscanner );
#endif
#endif
@@ -325,9 +311,9 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmDependsFortran_yylex (yyscan_t yyscanner);
+extern int cmFortran_yylex (yyscan_t yyscanner);
-#define YY_DECL int cmDependsFortran_yylex (yyscan_t yyscanner)
+#define YY_DECL int cmFortran_yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
@@ -344,5 +330,9 @@ extern int cmDependsFortran_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#undef cmDependsFortran_yyIN_HEADER
-#endif /* cmDependsFortran_yyHEADER_H */
+#line 178 "cmFortranLexer.in.l"
+
+
+#line 337 "cmFortranLexer.h"
+#undef cmFortran_yyIN_HEADER
+#endif /* cmFortran_yyHEADER_H */
diff --git a/Source/cmDependsFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l
index 01488024e..112121037 100644
--- a/Source/cmDependsFortranLexer.in.l
+++ b/Source/LexerParser/cmFortranLexer.in.l
@@ -1,15 +1,6 @@
%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
/*-------------------------------------------------------------------------
Portions of this source have been derived from makedepf90 version 2.8.8,
@@ -22,41 +13,34 @@
/*
-This file must be translated to C and modified to build everywhere.
-
-Run flex like this:
+This file must be translated to C++ and modified to build everywhere.
- flex -i --prefix=cmDependsFortran_yy --header-file=cmDependsFortranLexer.h -ocmDependsFortranLexer.cxx cmDependsFortranLexer.in.l
+Run flex >= 2.6 like this:
-Modify cmDependsFortranLexer.cxx:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmDependsFortran_yyalloc, cmDependsFortran_yyrealloc, cmDependsFortran_yyfree
- - remove "yyscanner = NULL" from end of cmDependsFortran_yylex_destroy
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
+ flex -i --nounistd -DFLEXINT_H --prefix=cmFortran_yy --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l
-Modify cmDependsFortranLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
+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
*/
-#include "cmStandardLexer.h"
+/* IWYU pragma: no_forward_declare yyguts_t */
-#define cmDependsFortranLexer_cxx
-#include "cmDependsFortranParser.h" /* Interface to parser object. */
+#undef YY_NO_UNPUT
+
+#define cmFortranLexer_cxx
+#include "cmFortranParser.h" /* Interface to parser object. */
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = cmDependsFortranParser_Input(yyextra, buf, max_size); }
+ { result = cmFortranParser_Input(yyextra, buf, max_size); }
/* Include the set of tokens from the parser. */
-#include "cmDependsFortranParserTokens.h"
+#include "cmFortranParserTokens.h"
/*--------------------------------------------------------------------------*/
%}
@@ -72,21 +56,21 @@ Modify cmDependsFortranLexer.h:
%%
\" {
- cmDependsFortranParser_StringStart(yyextra);
- cmDependsFortranParser_SetOldStartcond(yyextra, YY_START);
+ cmFortranParser_StringStart(yyextra);
+ cmFortranParser_SetOldStartcond(yyextra, YY_START);
BEGIN(str_dq);
}
' {
- cmDependsFortranParser_StringStart(yyextra);
- cmDependsFortranParser_SetOldStartcond(yyextra, YY_START);
+ cmFortranParser_StringStart(yyextra);
+ cmFortranParser_SetOldStartcond(yyextra, YY_START);
BEGIN(str_sq);
}
<str_dq>\" |
<str_sq>' {
- BEGIN(cmDependsFortranParser_GetOldStartcond(yyextra) );
- yylvalp->string = strdup(cmDependsFortranParser_StringEnd(yyextra));
+ BEGIN(cmFortranParser_GetOldStartcond(yyextra) );
+ yylvalp->string = strdup(cmFortranParser_StringEnd(yyextra));
return STRING;
}
@@ -94,7 +78,7 @@ Modify cmDependsFortranLexer.h:
<str_dq,str_sq>&[ \t]*\n[ \t]*& /* Ignore (continued strings, free fmt) */
<fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] {
- if (cmDependsFortranParser_GetOldStartcond(yyextra) == fixed_fmt)
+ if (cmFortranParser_GetOldStartcond(yyextra) == fixed_fmt)
; /* Ignore (cont. strings, fixed fmt) */
else
{
@@ -110,12 +94,13 @@ Modify cmDependsFortranLexer.h:
}
<str_sq,str_dq>. {
- cmDependsFortranParser_StringAppend(yyextra, yytext[0]);
+ cmFortranParser_StringAppend(yyextra, yytext[0]);
}
!.*\n { return EOSTMT; } /* Treat comments like */
<fixed_fmt>^[cC*dD].*\n { return EOSTMT; } /* empty lines */
+^[ \t]*#([ \t]*line)?[ \t]*[0-9]+[ \t]* { return CPP_LINE_DIRECTIVE; }
^[ \t]*#[ \t]*include[ \t]*<[^>]+> {
yytext[yyleng-1] = 0;
yylvalp->string = strdup(strchr(yytext, '<')+1);
@@ -152,28 +137,39 @@ $[ \t]*endif { return F90PPR_ENDIF; }
, { return COMMA; }
:: { return DCOLON; }
+: { return COLON; }
<fixed_fmt>\n[ ]{5}[^ ] { return GARBAGE; }
=|=> { return ASSIGNMENT_OP; }
+[Ee][Nn][Dd] { return END; }
+[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; }
+[Uu][Ss][Ee] { return USE; }
+
[a-zA-Z_][a-zA-Z_0-9]* {
yylvalp->string = strdup(yytext);
return WORD;
}
-[^ \t\n\r;,!'"a-zA-Z=&]+ { return GARBAGE; }
+\( { return LPAREN; }
+\) { return RPAREN; }
+
+[^ \t\n\r:;,!'"a-zA-Z=&()]+ { return GARBAGE; }
;|\n { return EOSTMT; }
[ \t\r,] /* Ignore */
-\\[ \t]*\n /* Ignore line-endings preceeded by \ */
+\\[ \t]*\n /* Ignore line-endings preceded by \ */
. { return *yytext; }
<<EOF>> {
- if(!cmDependsFortranParser_FilePop(yyextra) )
+ if(!cmFortranParser_FilePop(yyextra) )
{
return YY_NULL;
}
@@ -182,7 +178,7 @@ $[ \t]*endif { return F90PPR_ENDIF; }
%%
/*--------------------------------------------------------------------------*/
-YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
+YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
{
/* Hack into the internal flex-generated scanner to get the buffer. */
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
diff --git a/Source/cmDependsFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 7b49a9c5c..2b3452f2e 100644
--- a/Source/cmDependsFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.5. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.5"
+#define YYBISON_VERSION "3.0.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,35 +58,20 @@
/* Pull parsers. */
#define YYPULL 1
-/* Using locations. */
-#define YYLSP_NEEDED 0
/* Substitute the variable and function names. */
-#define yyparse cmDependsFortran_yyparse
-#define yylex cmDependsFortran_yylex
-#define yyerror cmDependsFortran_yyerror
-#define yylval cmDependsFortran_yylval
-#define yychar cmDependsFortran_yychar
-#define yydebug cmDependsFortran_yydebug
-#define yynerrs cmDependsFortran_yynerrs
+#define yyparse cmFortran_yyparse
+#define yylex cmFortran_yylex
+#define yyerror cmFortran_yyerror
+#define yydebug cmFortran_yydebug
+#define yynerrs cmFortran_yynerrs
/* Copy the first part of user declarations. */
+#line 1 "cmFortranParser.y" /* yacc.c:339 */
-/* Line 268 of yacc.c */
-#line 1 "cmDependsFortranParser.y"
-
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
/*-------------------------------------------------------------------------
Portions of this source have been derived from makedepf90 version 2.8.8,
@@ -103,53 +88,37 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmDependsFortran_yy
- --defines=cmDependsFortranParserTokens.h
- -ocmDependsFortranParser.cxx
- cmDependsFortranParser.y
+ bison --yacc --name-prefix=cmFortran_yy
+ --defines=cmFortranParserTokens.h
+ -ocmFortranParser.cxx
+ cmFortranParser.y
-Modify cmDependsFortranParser.cxx:
- - remove TABs
- - Remove the yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+Modify cmFortranParser.cxx:
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
*/
-/*-------------------------------------------------------------------------*/
-#define cmDependsFortranParser_cxx
-#include "cmDependsFortranParser.h" /* Interface to parser object. */
-#include "cmDependsFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <cmsys/String.h>
+#include "cmsys/String.h"
+#include <stdlib.h>
+#include <string.h>
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmDependsFortran_yyerror(x) \
- cmDependsFortranError(yyscanner, x)
+/*-------------------------------------------------------------------------*/
+#define cmFortranParser_cxx
+#include "cmFortranParser.h" /* Interface to parser object. */
+#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
-/* Helper function to forward error callback. */
-static void cmDependsFortranError(yyscan_t yyscanner, const char* message)
+/* Helper function to forward error callback from parser. */
+static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_Error(parser, message);
-}
-
-static bool cmDependsFortranParserIsKeyword(const char* word,
- const char* keyword)
-{
- return cmsysString_strcasecmp(word, keyword) == 0;
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_Error(parser, message);
}
/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
#ifdef _MSC_VER
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch contains default but no case. */
@@ -159,125 +128,147 @@ static bool cmDependsFortranParserIsKeyword(const char* word,
# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
#endif
+#line 132 "cmFortranParser.cxx" /* yacc.c:339 */
-/* Line 268 of yacc.c */
-#line 165 "cmDependsFortranParser.cxx"
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
-# define YYERROR_VERBOSE 0
+# define YYERROR_VERBOSE 1
#endif
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* In a future release of Bison, this section will be replaced
+ by #include "cmFortranParserTokens.h". */
+#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmFortran_yydebug;
#endif
-
-/* Tokens. */
+/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- EOSTMT = 258,
- ASSIGNMENT_OP = 259,
- GARBAGE = 260,
- CPP_INCLUDE = 261,
- F90PPR_INCLUDE = 262,
- COCO_INCLUDE = 263,
- F90PPR_DEFINE = 264,
- CPP_DEFINE = 265,
- F90PPR_UNDEF = 266,
- CPP_UNDEF = 267,
- CPP_IFDEF = 268,
- CPP_IFNDEF = 269,
- CPP_IF = 270,
- CPP_ELSE = 271,
- CPP_ELIF = 272,
- CPP_ENDIF = 273,
- F90PPR_IFDEF = 274,
- F90PPR_IFNDEF = 275,
- F90PPR_IF = 276,
- F90PPR_ELSE = 277,
- F90PPR_ELIF = 278,
- F90PPR_ENDIF = 279,
- COMMA = 280,
- DCOLON = 281,
- CPP_TOENDL = 282,
- UNTERMINATED_STRING = 283,
- STRING = 284,
- WORD = 285,
- CPP_INCLUDE_ANGLE = 286
- };
+ enum yytokentype
+ {
+ EOSTMT = 258,
+ ASSIGNMENT_OP = 259,
+ GARBAGE = 260,
+ CPP_LINE_DIRECTIVE = 261,
+ CPP_INCLUDE = 262,
+ F90PPR_INCLUDE = 263,
+ COCO_INCLUDE = 264,
+ F90PPR_DEFINE = 265,
+ CPP_DEFINE = 266,
+ F90PPR_UNDEF = 267,
+ CPP_UNDEF = 268,
+ CPP_IFDEF = 269,
+ CPP_IFNDEF = 270,
+ CPP_IF = 271,
+ CPP_ELSE = 272,
+ CPP_ELIF = 273,
+ CPP_ENDIF = 274,
+ F90PPR_IFDEF = 275,
+ F90PPR_IFNDEF = 276,
+ F90PPR_IF = 277,
+ F90PPR_ELSE = 278,
+ F90PPR_ELIF = 279,
+ F90PPR_ENDIF = 280,
+ COMMA = 281,
+ COLON = 282,
+ DCOLON = 283,
+ LPAREN = 284,
+ RPAREN = 285,
+ UNTERMINATED_STRING = 286,
+ STRING = 287,
+ WORD = 288,
+ CPP_INCLUDE_ANGLE = 289,
+ END = 290,
+ INCLUDE = 291,
+ INTERFACE = 292,
+ MODULE = 293,
+ SUBMODULE = 294,
+ USE = 295
+ };
#endif
/* Tokens. */
#define EOSTMT 258
#define ASSIGNMENT_OP 259
#define GARBAGE 260
-#define CPP_INCLUDE 261
-#define F90PPR_INCLUDE 262
-#define COCO_INCLUDE 263
-#define F90PPR_DEFINE 264
-#define CPP_DEFINE 265
-#define F90PPR_UNDEF 266
-#define CPP_UNDEF 267
-#define CPP_IFDEF 268
-#define CPP_IFNDEF 269
-#define CPP_IF 270
-#define CPP_ELSE 271
-#define CPP_ELIF 272
-#define CPP_ENDIF 273
-#define F90PPR_IFDEF 274
-#define F90PPR_IFNDEF 275
-#define F90PPR_IF 276
-#define F90PPR_ELSE 277
-#define F90PPR_ELIF 278
-#define F90PPR_ENDIF 279
-#define COMMA 280
-#define DCOLON 281
-#define CPP_TOENDL 282
-#define UNTERMINATED_STRING 283
-#define STRING 284
-#define WORD 285
-#define CPP_INCLUDE_ANGLE 286
-
-
-
-
+#define CPP_LINE_DIRECTIVE 261
+#define CPP_INCLUDE 262
+#define F90PPR_INCLUDE 263
+#define COCO_INCLUDE 264
+#define F90PPR_DEFINE 265
+#define CPP_DEFINE 266
+#define F90PPR_UNDEF 267
+#define CPP_UNDEF 268
+#define CPP_IFDEF 269
+#define CPP_IFNDEF 270
+#define CPP_IF 271
+#define CPP_ELSE 272
+#define CPP_ELIF 273
+#define CPP_ENDIF 274
+#define F90PPR_IFDEF 275
+#define F90PPR_IFNDEF 276
+#define F90PPR_IF 277
+#define F90PPR_ELSE 278
+#define F90PPR_ELIF 279
+#define F90PPR_ENDIF 280
+#define COMMA 281
+#define COLON 282
+#define DCOLON 283
+#define LPAREN 284
+#define RPAREN 285
+#define UNTERMINATED_STRING 286
+#define STRING 287
+#define WORD 288
+#define CPP_INCLUDE_ANGLE 289
+#define END 290
+#define INCLUDE 291
+#define INTERFACE 292
+#define MODULE 293
+#define SUBMODULE 294
+#define USE 295
+
+/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-/* Line 293 of yacc.c */
-#line 89 "cmDependsFortranParser.y"
+union YYSTYPE
+{
+#line 70 "cmFortranParser.y" /* yacc.c:355 */
char* string;
+#line 256 "cmFortranParser.cxx" /* yacc.c:355 */
+};
-
-/* Line 293 of yacc.c */
-#line 269 "cmDependsFortranParser.cxx"
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
-/* Copy the second part of user declarations. */
+int cmFortran_yyparse (yyscan_t yyscanner);
-/* Line 343 of yacc.c */
-#line 281 "cmDependsFortranParser.cxx"
+#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
@@ -291,11 +282,8 @@ typedef unsigned char yytype_uint8;
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
#else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
#endif
#ifdef YYTYPE_UINT16
@@ -315,8 +303,7 @@ typedef short int yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -330,39 +317,68 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
# endif
# endif
# ifndef YY_
-# define YY_(msgid) msgid
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# 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))
+# define YYUSE(E) ((void) (E))
#else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
#endif
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
- int yyi;
+# define YY_INITIAL_VALUE(Value) Value
#endif
-{
- return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
+
#if ! defined yyoverflow || YYERROR_VERBOSE
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -380,9 +396,9 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
@@ -392,8 +408,8 @@ YYID (yyi)
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
@@ -417,15 +433,13 @@ YYID (yyi)
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined malloc && ! defined EXIT_SUCCESS
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined free && ! defined EXIT_SUCCESS
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
@@ -469,26 +483,26 @@ union yyalloc
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
- while (YYID (0))
+ while (0)
#endif
#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from FROM to TO. The source and destination do
+/* Copy COUNT objects from SRC to DST. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
# else
-# define YYCOPY(To, From, Count) \
+# define YYCOPY(Dst, Src, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
+ (Dst)[yyi] = (Src)[yyi]; \
} \
- while (YYID (0))
+ while (0)
# endif
# endif
#endif /* !YYCOPY_NEEDED */
@@ -496,25 +510,27 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 276
+#define YYLAST 593
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 32
+#define YYNTOKENS 41
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 16
+#define YYNNTS 14
/* YYNRULES -- Number of rules. */
-#define YYNRULES 53
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 97
+#define YYNRULES 63
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 126
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 286
+#define YYMAXUTOK 295
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -545,244 +561,293 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 4, 7, 9, 11, 16, 19, 24,
- 30, 38, 43, 47, 52, 57, 62, 67, 72, 76,
- 80, 84, 88, 93, 97, 99, 101, 103, 105, 107,
- 109, 111, 113, 115, 117, 119, 121, 123, 125, 127,
- 129, 131, 133, 135, 137, 139, 140, 143, 145, 147,
- 149, 151, 153, 155
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 33, 0, -1, -1, 33, 34, -1, 36, -1, 35,
- -1, 30, 4, 46, 3, -1, 30, 3, -1, 30,
- 30, 46, 3, -1, 30, 26, 30, 46, 3, -1,
- 30, 25, 30, 26, 30, 46, 3, -1, 30, 29,
- 46, 3, -1, 31, 46, 3, -1, 37, 29, 46,
- 3, -1, 38, 30, 46, 3, -1, 39, 30, 46,
- 3, -1, 40, 30, 46, 3, -1, 41, 30, 46,
- 3, -1, 42, 46, 3, -1, 43, 46, 3, -1,
- 44, 46, 3, -1, 45, 46, 3, -1, 30, 5,
- 46, 3, -1, 5, 46, 3, -1, 3, -1, 1,
- -1, 6, -1, 7, -1, 8, -1, 10, -1, 9,
- -1, 12, -1, 11, -1, 13, -1, 19, -1, 14,
- -1, 20, -1, 15, -1, 21, -1, 17, -1, 23,
- -1, 16, -1, 22, -1, 18, -1, 24, -1, -1,
- 46, 47, -1, 30, -1, 29, -1, 5, -1, 4,
- -1, 26, -1, 25, -1, 28, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint8 yyrline[] =
{
- 0, 111, 111, 111, 113, 113, 115, 121, 131, 161,
- 172, 185, 196, 203, 210, 216, 222, 228, 234, 239,
- 244, 249, 254, 258, 259, 260, 265, 265, 265, 266,
- 266, 267, 267, 268, 268, 269, 269, 270, 270, 271,
- 271, 272, 272, 273, 273, 274, 274, 277, 278, 279,
- 280, 281, 282, 283
+ 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
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 1
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "EOSTMT", "ASSIGNMENT_OP", "GARBAGE",
- "CPP_INCLUDE", "F90PPR_INCLUDE", "COCO_INCLUDE", "F90PPR_DEFINE",
- "CPP_DEFINE", "F90PPR_UNDEF", "CPP_UNDEF", "CPP_IFDEF", "CPP_IFNDEF",
- "CPP_IF", "CPP_ELSE", "CPP_ELIF", "CPP_ENDIF", "F90PPR_IFDEF",
- "F90PPR_IFNDEF", "F90PPR_IF", "F90PPR_ELSE", "F90PPR_ELIF",
- "F90PPR_ENDIF", "COMMA", "DCOLON", "CPP_TOENDL", "UNTERMINATED_STRING",
- "STRING", "WORD", "CPP_INCLUDE_ANGLE", "$accept", "code", "stmt",
- "assignment_stmt", "keyword_stmt", "include", "define", "undef", "ifdef",
- "ifndef", "if", "elif", "else", "endif", "other", "misc_code", 0
+ "CPP_LINE_DIRECTIVE", "CPP_INCLUDE", "F90PPR_INCLUDE", "COCO_INCLUDE",
+ "F90PPR_DEFINE", "CPP_DEFINE", "F90PPR_UNDEF", "CPP_UNDEF", "CPP_IFDEF",
+ "CPP_IFNDEF", "CPP_IF", "CPP_ELSE", "CPP_ELIF", "CPP_ENDIF",
+ "F90PPR_IFDEF", "F90PPR_IFNDEF", "F90PPR_IF", "F90PPR_ELSE",
+ "F90PPR_ELIF", "F90PPR_ENDIF", "COMMA", "COLON", "DCOLON", "LPAREN",
+ "RPAREN", "UNTERMINATED_STRING", "STRING", "WORD", "CPP_INCLUDE_ANGLE",
+ "END", "INCLUDE", "INTERFACE", "MODULE", "SUBMODULE", "USE", "$accept",
+ "code", "stmt", "include", "define", "undef", "ifdef", "ifndef", "if",
+ "elif", "else", "endif", "other", "misc_code", YY_NULLPTR
};
#endif
# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295
};
# endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 32, 33, 33, 34, 34, 35, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 37, 37, 37, 38,
- 38, 39, 39, 40, 40, 41, 41, 42, 42, 43,
- 43, 44, 44, 45, 45, 46, 46, 47, 47, 47,
- 47, 47, 47, 47
-};
+#define YYPACT_NINF -39
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 0, 2, 1, 1, 4, 2, 4, 5,
- 7, 4, 3, 4, 4, 4, 4, 4, 3, 3,
- 3, 3, 4, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 0, 2, 1, 1, 1,
- 1, 1, 1, 1
-};
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-39)))
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
{
- 2, 0, 1, 25, 24, 45, 26, 27, 28, 30,
- 29, 32, 31, 33, 35, 37, 41, 39, 43, 34,
- 36, 38, 42, 40, 44, 0, 45, 3, 5, 4,
- 0, 0, 0, 0, 0, 45, 45, 45, 45, 0,
- 7, 45, 45, 0, 0, 45, 45, 0, 45, 45,
- 45, 45, 45, 0, 0, 0, 0, 23, 50, 49,
- 52, 51, 53, 48, 47, 46, 0, 0, 0, 45,
- 0, 0, 12, 0, 0, 0, 0, 0, 18, 19,
- 20, 21, 6, 22, 0, 0, 11, 8, 13, 14,
- 15, 16, 17, 45, 9, 0, 10
+ -39, 21, -39, 1, -39, -20, -39, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, -24, -18, 20, -8,
+ -3, 39, -39, 15, 16, 18, 19, 33, -39, -39,
+ -39, -39, -39, -39, 59, -39, -39, -39, -39, -39,
+ 35, 36, 37, -39, -39, -39, -39, -39, -39, 76,
+ 114, 129, 167, 182, -39, -39, -39, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
+ -39, -39, 220, 235, 273, 288, -21, 26, -39, 326,
+ 341, 379, 394, 432, 447, -39, -39, -39, -39, -39,
+ -39, -39, -39, -39, 38, 40, 41, 485, -39, -39,
+ -39, -39, -39, -39, 45, -39, -39, -39, 43, 500,
+ 538, -39, -39, -39, 553, -39
};
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
{
- -1, 1, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 65
+ 2, 0, 1, 0, 25, 0, 27, 28, 29, 31,
+ 30, 33, 32, 34, 36, 38, 42, 40, 44, 35,
+ 37, 39, 43, 41, 45, 46, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 46, 46,
+ 46, 46, 26, 46, 0, 46, 46, 4, 46, 46,
+ 0, 0, 0, 46, 46, 46, 46, 46, 46, 0,
+ 0, 0, 0, 0, 15, 57, 56, 62, 58, 59,
+ 60, 61, 63, 55, 48, 49, 50, 51, 52, 53,
+ 54, 47, 0, 0, 0, 0, 0, 0, 46, 0,
+ 0, 0, 0, 0, 0, 21, 22, 23, 24, 14,
+ 10, 13, 9, 6, 0, 0, 0, 0, 5, 16,
+ 17, 18, 19, 20, 0, 46, 46, 11, 0, 0,
+ 0, 46, 7, 12, 0, 8
};
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -29
-static const yytype_int16 yypact[] =
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
{
- -29, 39, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, 246, -29, -29, -29, -29,
- -28, -27, -22, -17, -16, -29, -29, -29, -29, 2,
- -29, -29, -29, -13, -12, -29, -29, 61, -29, -29,
- -29, -29, -29, 68, 74, 80, 108, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, 114, 120, -24, -29,
- 126, 154, -29, 160, 166, 172, 200, 206, -29, -29,
- -29, -29, -29, -29, -9, 212, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, 218, -29
+ -39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
+ -39, -39, -38, -39
};
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
{
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -26, -29
+ -1, 1, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 44, 81
};
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
- 47, 48, 84, 49, 0, 57, 58, 59, 50, 53,
- 54, 55, 56, 51, 52, 66, 67, 68, 69, 70,
- 71, 93, 73, 74, 75, 76, 77, 60, 61, 0,
- 62, 63, 64, 0, 0, 0, 0, 0, 0, 2,
- 3, 0, 4, 85, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 72, 58, 59, 95, 0, 25,
- 26, 78, 58, 59, 0, 0, 0, 79, 58, 59,
- 0, 0, 0, 80, 58, 59, 60, 61, 0, 62,
- 63, 64, 0, 60, 61, 0, 62, 63, 64, 60,
- 61, 0, 62, 63, 64, 60, 61, 0, 62, 63,
- 64, 81, 58, 59, 0, 0, 0, 82, 58, 59,
- 0, 0, 0, 83, 58, 59, 0, 0, 0, 86,
- 58, 59, 0, 60, 61, 0, 62, 63, 64, 60,
- 61, 0, 62, 63, 64, 60, 61, 0, 62, 63,
- 64, 60, 61, 0, 62, 63, 64, 87, 58, 59,
- 0, 0, 0, 88, 58, 59, 0, 0, 0, 89,
- 58, 59, 0, 0, 0, 90, 58, 59, 0, 60,
- 61, 0, 62, 63, 64, 60, 61, 0, 62, 63,
- 64, 60, 61, 0, 62, 63, 64, 60, 61, 0,
- 62, 63, 64, 91, 58, 59, 0, 0, 0, 92,
- 58, 59, 0, 0, 0, 94, 58, 59, 0, 0,
- 0, 96, 58, 59, 0, 60, 61, 0, 62, 63,
- 64, 60, 61, 0, 62, 63, 64, 60, 61, 0,
- 62, 63, 64, 60, 61, 0, 62, 63, 64, 40,
- 41, 42, 0, 0, 0, 0, 0, 0, 0, 0,
+ 59, 60, 61, 62, 42, 63, 104, 82, 83, 105,
+ 84, 85, 43, 45, 46, 89, 90, 91, 92, 93,
+ 94, 2, 3, 47, 4, 49, 50, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 54, 0, 55,
+ 107, 56, 57, 48, 106, 25, 26, 27, 28, 29,
+ 30, 31, 64, 65, 66, 51, 58, 52, 86, 87,
+ 88, 114, 53, 115, 116, 118, 121, 119, 120, 95,
+ 65, 66, 0, 124, 0, 67, 68, 69, 70, 71,
+ 72, 73, 74, 0, 75, 76, 77, 78, 79, 80,
+ 0, 0, 67, 68, 69, 70, 71, 72, 73, 74,
+ 0, 75, 76, 77, 78, 79, 80, 96, 65, 66,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 97, 65, 66, 0, 0, 0, 0, 0,
+ 67, 68, 69, 70, 71, 72, 73, 74, 0, 75,
+ 76, 77, 78, 79, 80, 67, 68, 69, 70, 71,
+ 72, 73, 74, 0, 75, 76, 77, 78, 79, 80,
+ 98, 65, 66, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 99, 65, 66, 0, 0,
+ 0, 0, 0, 67, 68, 69, 70, 71, 72, 73,
+ 74, 0, 75, 76, 77, 78, 79, 80, 67, 68,
+ 69, 70, 71, 72, 73, 74, 0, 75, 76, 77,
+ 78, 79, 80, 100, 65, 66, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 101, 65,
+ 66, 0, 0, 0, 0, 0, 67, 68, 69, 70,
+ 71, 72, 73, 74, 0, 75, 76, 77, 78, 79,
+ 80, 67, 68, 69, 70, 71, 72, 73, 74, 0,
+ 75, 76, 77, 78, 79, 80, 102, 65, 66, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 43, 44, 0, 0, 45, 46
+ 0, 103, 65, 66, 0, 0, 0, 0, 0, 67,
+ 68, 69, 70, 71, 72, 73, 74, 0, 75, 76,
+ 77, 78, 79, 80, 67, 68, 69, 70, 71, 72,
+ 73, 74, 0, 75, 76, 77, 78, 79, 80, 108,
+ 65, 66, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 109, 65, 66, 0, 0, 0,
+ 0, 0, 67, 68, 69, 70, 71, 72, 73, 74,
+ 0, 75, 76, 77, 78, 79, 80, 67, 68, 69,
+ 70, 71, 72, 73, 74, 0, 75, 76, 77, 78,
+ 79, 80, 110, 65, 66, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 111, 65, 66,
+ 0, 0, 0, 0, 0, 67, 68, 69, 70, 71,
+ 72, 73, 74, 0, 75, 76, 77, 78, 79, 80,
+ 67, 68, 69, 70, 71, 72, 73, 74, 0, 75,
+ 76, 77, 78, 79, 80, 112, 65, 66, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 113, 65, 66, 0, 0, 0, 0, 0, 67, 68,
+ 69, 70, 71, 72, 73, 74, 0, 75, 76, 77,
+ 78, 79, 80, 67, 68, 69, 70, 71, 72, 73,
+ 74, 0, 75, 76, 77, 78, 79, 80, 117, 65,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 122, 65, 66, 0, 0, 0, 0,
+ 0, 67, 68, 69, 70, 71, 72, 73, 74, 0,
+ 75, 76, 77, 78, 79, 80, 67, 68, 69, 70,
+ 71, 72, 73, 74, 0, 75, 76, 77, 78, 79,
+ 80, 123, 65, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 125, 65, 66, 0,
+ 0, 0, 0, 0, 67, 68, 69, 70, 71, 72,
+ 73, 74, 0, 75, 76, 77, 78, 79, 80, 67,
+ 68, 69, 70, 71, 72, 73, 74, 0, 75, 76,
+ 77, 78, 79, 80
};
-#define yypact_value_is_default(yystate) \
- ((yystate) == (-29))
-
-#define yytable_value_is_error(yytable_value) \
- YYID (0)
-
static const yytype_int8 yycheck[] =
{
- 26, 29, 26, 30, -1, 3, 4, 5, 30, 35,
- 36, 37, 38, 30, 30, 41, 42, 30, 30, 45,
- 46, 30, 48, 49, 50, 51, 52, 25, 26, -1,
- 28, 29, 30, -1, -1, -1, -1, -1, -1, 0,
- 1, -1, 3, 69, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 3, 4, 5, 93, -1, 30,
- 31, 3, 4, 5, -1, -1, -1, 3, 4, 5,
- -1, -1, -1, 3, 4, 5, 25, 26, -1, 28,
- 29, 30, -1, 25, 26, -1, 28, 29, 30, 25,
- 26, -1, 28, 29, 30, 25, 26, -1, 28, 29,
- 30, 3, 4, 5, -1, -1, -1, 3, 4, 5,
- -1, -1, -1, 3, 4, 5, -1, -1, -1, 3,
- 4, 5, -1, 25, 26, -1, 28, 29, 30, 25,
- 26, -1, 28, 29, 30, 25, 26, -1, 28, 29,
- 30, 25, 26, -1, 28, 29, 30, 3, 4, 5,
- -1, -1, -1, 3, 4, 5, -1, -1, -1, 3,
- 4, 5, -1, -1, -1, 3, 4, 5, -1, 25,
- 26, -1, 28, 29, 30, 25, 26, -1, 28, 29,
- 30, 25, 26, -1, 28, 29, 30, 25, 26, -1,
- 28, 29, 30, 3, 4, 5, -1, -1, -1, 3,
- 4, 5, -1, -1, -1, 3, 4, 5, -1, -1,
- -1, 3, 4, 5, -1, 25, 26, -1, 28, 29,
- 30, 25, 26, -1, 28, 29, 30, 25, 26, -1,
- 28, 29, 30, 25, 26, -1, 28, 29, 30, 3,
+ 38, 39, 40, 41, 3, 43, 27, 45, 46, 30,
+ 48, 49, 32, 37, 32, 53, 54, 55, 56, 57,
+ 58, 0, 1, 3, 3, 33, 29, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 32, -1, 33,
+ 88, 33, 33, 33, 28, 34, 35, 36, 37, 38,
+ 39, 40, 3, 4, 5, 26, 33, 28, 33, 33,
+ 33, 33, 33, 33, 33, 30, 33, 115, 116, 3,
+ 4, 5, -1, 121, -1, 26, 27, 28, 29, 30,
+ 31, 32, 33, -1, 35, 36, 37, 38, 39, 40,
+ -1, -1, 26, 27, 28, 29, 30, 31, 32, 33,
+ -1, 35, 36, 37, 38, 39, 40, 3, 4, 5,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3, 4, 5, -1, -1, -1, -1, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, -1, 35,
+ 36, 37, 38, 39, 40, 26, 27, 28, 29, 30,
+ 31, 32, 33, -1, 35, 36, 37, 38, 39, 40,
+ 3, 4, 5, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3, 4, 5, -1, -1,
+ -1, -1, -1, 26, 27, 28, 29, 30, 31, 32,
+ 33, -1, 35, 36, 37, 38, 39, 40, 26, 27,
+ 28, 29, 30, 31, 32, 33, -1, 35, 36, 37,
+ 38, 39, 40, 3, 4, 5, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 3, 4,
+ 5, -1, -1, -1, -1, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, -1, 35, 36, 37, 38, 39,
+ 40, 26, 27, 28, 29, 30, 31, 32, 33, -1,
+ 35, 36, 37, 38, 39, 40, 3, 4, 5, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3, 4, 5, -1, -1, -1, -1, -1, 26,
+ 27, 28, 29, 30, 31, 32, 33, -1, 35, 36,
+ 37, 38, 39, 40, 26, 27, 28, 29, 30, 31,
+ 32, 33, -1, 35, 36, 37, 38, 39, 40, 3,
4, 5, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3, 4, 5, -1, -1, -1,
+ -1, -1, 26, 27, 28, 29, 30, 31, 32, 33,
+ -1, 35, 36, 37, 38, 39, 40, 26, 27, 28,
+ 29, 30, 31, 32, 33, -1, 35, 36, 37, 38,
+ 39, 40, 3, 4, 5, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3, 4, 5,
+ -1, -1, -1, -1, -1, 26, 27, 28, 29, 30,
+ 31, 32, 33, -1, 35, 36, 37, 38, 39, 40,
+ 26, 27, 28, 29, 30, 31, 32, 33, -1, 35,
+ 36, 37, 38, 39, 40, 3, 4, 5, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 25, 26, -1, -1, 29, 30
+ 3, 4, 5, -1, -1, -1, -1, -1, 26, 27,
+ 28, 29, 30, 31, 32, 33, -1, 35, 36, 37,
+ 38, 39, 40, 26, 27, 28, 29, 30, 31, 32,
+ 33, -1, 35, 36, 37, 38, 39, 40, 3, 4,
+ 5, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3, 4, 5, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, -1,
+ 35, 36, 37, 38, 39, 40, 26, 27, 28, 29,
+ 30, 31, 32, 33, -1, 35, 36, 37, 38, 39,
+ 40, 3, 4, 5, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3, 4, 5, -1,
+ -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, -1, 35, 36, 37, 38, 39, 40, 26,
+ 27, 28, 29, 30, 31, 32, 33, -1, 35, 36,
+ 37, 38, 39, 40
};
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 33, 0, 1, 3, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 30, 31, 34, 35, 36,
- 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
- 3, 4, 5, 25, 26, 29, 30, 46, 29, 30,
- 30, 30, 30, 46, 46, 46, 46, 3, 4, 5,
- 25, 26, 28, 29, 30, 47, 46, 46, 30, 30,
- 46, 46, 3, 46, 46, 46, 46, 46, 3, 3,
- 3, 3, 3, 3, 26, 46, 3, 3, 3, 3,
- 3, 3, 3, 30, 3, 46, 3
+ 0, 42, 0, 1, 3, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 34, 35, 36, 37, 38,
+ 39, 40, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 3, 32, 53, 37, 32, 3, 33, 33,
+ 29, 26, 28, 33, 32, 33, 33, 33, 33, 53,
+ 53, 53, 53, 53, 3, 4, 5, 26, 27, 28,
+ 29, 30, 31, 32, 33, 35, 36, 37, 38, 39,
+ 40, 54, 53, 53, 53, 53, 33, 33, 33, 53,
+ 53, 53, 53, 53, 53, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 27, 30, 28, 53, 3, 3,
+ 3, 3, 3, 3, 33, 33, 33, 3, 30, 53,
+ 53, 33, 3, 3, 53, 3
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 41, 42, 42, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 44, 44, 44,
+ 45, 45, 46, 46, 47, 47, 48, 48, 49, 49,
+ 50, 50, 51, 51, 52, 52, 53, 53, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 2, 4, 4, 7, 9, 4,
+ 4, 5, 7, 4, 4, 3, 4, 4, 4, 4,
+ 4, 3, 3, 3, 3, 1, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1
};
+
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY (-2)
@@ -793,84 +858,30 @@ static const yytype_uint8 yystos[] =
#define YYERROR goto yyerrorlab
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
-
-#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
-
#define YYRECOVERING() (!!yyerrstatus)
#define YYBACKUP(Token, Value) \
do \
- if (yychar == YYEMPTY && yylen == 1) \
+ if (yychar == YYEMPTY) \
{ \
yychar = (Token); \
yylval = (Value); \
- YYPOPSTACK (1); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
goto yybackup; \
} \
else \
{ \
- yyerror (YY_("syntax error: cannot back up")); \
+ yyerror (yyscanner, YY_("syntax error: cannot back up")); \
YYERROR; \
} \
-while (YYID (0))
-
+while (0)
+/* Error token number */
#define YYTERROR 1
#define YYERRCODE 256
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* This macro is provided for backward compatibility. */
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
/* Enable debugging if requested. */
#if YYDEBUG
@@ -884,7 +895,13 @@ while (YYID (0))
do { \
if (yydebug) \
YYFPRINTF Args; \
-} while (YYID (0))
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
do { \
@@ -892,42 +909,29 @@ do { \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
- Type, Value); \
+ Type, Value, yyscanner); \
YYFPRINTF (stderr, "\n"); \
} \
-} while (YYID (0))
+} while (0)
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
# endif
- switch (yytype)
- {
- default:
- break;
- }
+ YYUSE (yytype);
}
@@ -935,24 +939,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
- yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
YYFPRINTF (yyoutput, ")");
}
@@ -961,16 +954,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
| TOP (included). |
`------------------------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
- yytype_int16 *yybottom;
- yytype_int16 *yytop;
-#endif
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -985,36 +970,29 @@ yy_stack_print (yybottom, yytop)
do { \
if (yydebug) \
yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
+} while (0)
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
static void
-yy_reduce_print (yyvsp, yyrule)
- YYSTYPE *yyvsp;
- int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
+ unsigned long int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
&(yyvsp[(yyi + 1) - (yynrhs)])
- );
+ , yyscanner);
YYFPRINTF (stderr, "\n");
}
}
@@ -1022,8 +1000,8 @@ yy_reduce_print (yyvsp, yyrule)
# define YY_REDUCE_PRINT(Rule) \
do { \
if (yydebug) \
- yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+ yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
@@ -1060,15 +1038,8 @@ int yydebug;
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
{
YYSIZE_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
@@ -1084,16 +1055,8 @@ yystrlen (yystr)
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
{
char *yyd = yydest;
const char *yys = yysrc;
@@ -1166,12 +1129,11 @@ static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yytype_int16 *yyssp, int yytoken)
{
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
- const char *yyformat = 0;
+ const char *yyformat = YY_NULLPTR;
/* Arguments of yyformat. */
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
/* Number of reported tokens (one for the "unexpected", one per
@@ -1179,10 +1141,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
int yycount = 0;
/* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
is an error action. In that case, don't check for expected
@@ -1231,11 +1189,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
break;
}
yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
}
}
}
@@ -1255,10 +1215,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
# undef YYCASE_
}
- yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
if (*yymsg_alloc < yysize)
{
@@ -1295,81 +1257,39 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
static void
-yydestruct (yymsg, yytype, yyvaluep)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
YYUSE (yyvaluep);
-
+ YYUSE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
- switch (yytype)
- {
-
- default:
- break;
- }
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
}
-/* Prevent warnings from -Wmissing-prototypes. */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
/*----------.
| yyparse. |
`----------*/
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
+yyparse (yyscan_t yyscanner)
{
/* The lookahead symbol. */
int yychar;
+
/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
/* Number of syntax errors so far. */
int yynerrs;
@@ -1379,10 +1299,10 @@ YYSTYPE yylval;
int yyerrstatus;
/* The stacks and their tools:
- `yyss': related to states.
- `yyvs': related to semantic values.
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
- Refer to the stacks thru separate pointers, to allow yyoverflow
+ Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
@@ -1400,7 +1320,7 @@ YYSTYPE yylval;
int yyn;
int yyresult;
/* Lookahead token as an internal (translated) token number. */
- int yytoken;
+ int yytoken = 0;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
@@ -1418,9 +1338,8 @@ YYSTYPE yylval;
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yytoken = 0;
- yyss = yyssa;
- yyvs = yyvsa;
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1429,14 +1348,6 @@ YYSTYPE yylval;
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
- yyssp = yyss;
- yyvsp = yyvs;
-
goto yysetstate;
/*------------------------------------------------------------.
@@ -1537,7 +1448,7 @@ yybackup:
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
+ yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
@@ -1577,7 +1488,9 @@ yybackup:
yychar = YYEMPTY;
yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -1600,7 +1513,7 @@ yyreduce:
yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ '$$ = $1'.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
@@ -1613,250 +1526,234 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 6:
+ case 4:
+#line 101 "cmFortranParser.y" /* yacc.c:1646 */
+ {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_SetInInterface(parser, true);
+ }
+#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */
+ break;
+
+ case 5:
+#line 105 "cmFortranParser.y" /* yacc.c:1646 */
+ {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */
+ break;
-/* Line 1806 of yacc.c */
-#line 116 "cmDependsFortranParser.y"
+ case 6:
+#line 110 "cmFortranParser.y" /* yacc.c:1646 */
{
- free((yyvsp[(1) - (4)].string));
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
+ cmsysString_strcasecmp((yyvsp[-2].string), "procedure") != 0 &&
+ cmsysString_strcasecmp((yyvsp[-2].string), "subroutine") != 0) {
+ cmFortranParser_RuleModule(parser, (yyvsp[-2].string));
}
+ free((yyvsp[-2].string));
+ }
+#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 7:
-
-/* Line 1806 of yacc.c */
-#line 122 "cmDependsFortranParser.y"
+#line 119 "cmFortranParser.y" /* yacc.c:1646 */
{
- if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (2)].string), "interface"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_SetInInterface(parser, true);
- }
- free((yyvsp[(1) - (2)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, (yyvsp[-4].string));
+ free((yyvsp[-4].string));
+ free((yyvsp[-2].string));
+ }
+#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 8:
-
-/* Line 1806 of yacc.c */
-#line 132 "cmDependsFortranParser.y"
+#line 125 "cmFortranParser.y" /* yacc.c:1646 */
{
- if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "use"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, (yyvsp[(2) - (4)].string));
- }
- else if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "module"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleModule(parser, (yyvsp[(2) - (4)].string));
- }
- else if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "interface"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_SetInInterface(parser, true);
- }
- else if (cmDependsFortranParserIsKeyword((yyvsp[(2) - (4)].string), "interface") &&
- cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "end"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_SetInInterface(parser, false);
- }
- free((yyvsp[(1) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
+ free((yyvsp[-6].string));
+ free((yyvsp[-4].string));
+ free((yyvsp[-2].string));
+ }
+#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 9:
-
-/* Line 1806 of yacc.c */
-#line 162 "cmDependsFortranParser.y"
+#line 132 "cmFortranParser.y" /* yacc.c:1646 */
{
- if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (5)].string), "use"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, (yyvsp[(3) - (5)].string));
- }
- free((yyvsp[(1) - (5)].string));
- free((yyvsp[(3) - (5)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_SetInInterface(parser, true);
+ free((yyvsp[-2].string));
+ }
+#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 10:
-
-/* Line 1806 of yacc.c */
-#line 173 "cmDependsFortranParser.y"
+#line 137 "cmFortranParser.y" /* yacc.c:1646 */
{
- if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (7)].string), "use") &&
- cmDependsFortranParserIsKeyword((yyvsp[(3) - (7)].string), "non_intrinsic") )
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, (yyvsp[(5) - (7)].string));
- }
- free((yyvsp[(1) - (7)].string));
- free((yyvsp[(3) - (7)].string));
- free((yyvsp[(5) - (7)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_SetInInterface(parser, false);
+ }
+#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 11:
-
-/* Line 1806 of yacc.c */
-#line 186 "cmDependsFortranParser.y"
+#line 141 "cmFortranParser.y" /* yacc.c:1646 */
{
- if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "include"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, (yyvsp[(2) - (4)].string));
- }
- free((yyvsp[(1) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 12:
-
-/* Line 1806 of yacc.c */
-#line 197 "cmDependsFortranParser.y"
+#line 146 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, (yyvsp[(1) - (3)].string));
- free((yyvsp[(1) - (3)].string));
+ if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
}
+ free((yyvsp[-4].string));
+ free((yyvsp[-2].string));
+ }
+#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 13:
-
-/* Line 1806 of yacc.c */
-#line 204 "cmDependsFortranParser.y"
+#line 154 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, (yyvsp[(2) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 14:
-
-/* Line 1806 of yacc.c */
-#line 211 "cmDependsFortranParser.y"
+#line 159 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleDefine(parser, (yyvsp[(2) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 15:
-
-/* Line 1806 of yacc.c */
-#line 217 "cmDependsFortranParser.y"
+#line 164 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUndef(parser, (yyvsp[(2) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 16:
-
-/* Line 1806 of yacc.c */
-#line 223 "cmDependsFortranParser.y"
+#line 169 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleIfdef(parser, (yyvsp[(2) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 17:
-
-/* Line 1806 of yacc.c */
-#line 229 "cmDependsFortranParser.y"
+#line 174 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleIfndef(parser, (yyvsp[(2) - (4)].string));
- free((yyvsp[(2) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 18:
-
-/* Line 1806 of yacc.c */
-#line 235 "cmDependsFortranParser.y"
+#line 179 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleIf(parser);
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 19:
-
-/* Line 1806 of yacc.c */
-#line 240 "cmDependsFortranParser.y"
+#line 184 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleElif(parser);
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 20:
-
-/* Line 1806 of yacc.c */
-#line 245 "cmDependsFortranParser.y"
+#line 189 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleElse(parser);
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
+ free((yyvsp[-2].string));
+ }
+#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 21:
-
-/* Line 1806 of yacc.c */
-#line 250 "cmDependsFortranParser.y"
+#line 194 "cmFortranParser.y" /* yacc.c:1646 */
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleEndif(parser);
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleIf(parser);
+ }
+#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 22:
-
-/* Line 1806 of yacc.c */
-#line 255 "cmDependsFortranParser.y"
+#line 198 "cmFortranParser.y" /* yacc.c:1646 */
{
- free((yyvsp[(1) - (4)].string));
- }
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleElif(parser);
+ }
+#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
- case 47:
+ case 23:
+#line 202 "cmFortranParser.y" /* yacc.c:1646 */
+ {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleElse(parser);
+ }
+#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */
+ break;
-/* Line 1806 of yacc.c */
-#line 277 "cmDependsFortranParser.y"
- { free ((yyvsp[(1) - (1)].string)); }
+ case 24:
+#line 206 "cmFortranParser.y" /* yacc.c:1646 */
+ {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleEndif(parser);
+ }
+#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 48:
-
-/* Line 1806 of yacc.c */
-#line 278 "cmDependsFortranParser.y"
- { free ((yyvsp[(1) - (1)].string)); }
+#line 228 "cmFortranParser.y" /* yacc.c:1646 */
+ { free ((yyvsp[0].string)); }
+#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
+ case 55:
+#line 235 "cmFortranParser.y" /* yacc.c:1646 */
+ { free ((yyvsp[0].string)); }
+#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */
+ break;
-/* Line 1806 of yacc.c */
-#line 1860 "cmDependsFortranParser.cxx"
+#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1878,7 +1775,7 @@ yyreduce:
*++yyvsp = yyval;
- /* Now `shift' the result of the reduction. Determine what state
+ /* 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. */
@@ -1893,9 +1790,9 @@ yyreduce:
goto yynewstate;
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
@@ -1906,7 +1803,7 @@ yyerrlab:
{
++yynerrs;
#if ! YYERROR_VERBOSE
- yyerror (YY_("syntax error"));
+ yyerror (yyscanner, YY_("syntax error"));
#else
# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
yyssp, yytoken)
@@ -1933,7 +1830,7 @@ yyerrlab:
yymsgp = yymsg;
}
}
- yyerror (yymsgp);
+ yyerror (yyscanner, yymsgp);
if (yysyntax_error_status == 2)
goto yyexhaustedlab;
}
@@ -1957,7 +1854,7 @@ yyerrlab:
else
{
yydestruct ("Error: discarding",
- yytoken, &yylval);
+ yytoken, &yylval, yyscanner);
yychar = YYEMPTY;
}
}
@@ -1979,7 +1876,7 @@ yyerrorlab:
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
@@ -2015,13 +1912,15 @@ yyerrlab1:
yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
+ yystos[yystate], yyvsp, yyscanner);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -2045,12 +1944,12 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
+ yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
@@ -2062,16 +1961,16 @@ yyreturn:
user semantic actions for why this is necessary. */
yytoken = YYTRANSLATE (yychar);
yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
+ yytoken, &yylval, yyscanner);
}
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp);
+ yystos[*yyssp], yyvsp, yyscanner);
YYPOPSTACK (1);
}
#ifndef yyoverflow
@@ -2082,13 +1981,8 @@ yyreturn:
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
+ return yyresult;
}
-
-
-
-/* Line 2067 of yacc.c */
-#line 286 "cmDependsFortranParser.y"
+#line 246 "cmFortranParser.y" /* yacc.c:1906 */
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
new file mode 100644
index 000000000..acfb40ad8
--- /dev/null
+++ b/Source/LexerParser/cmFortranParser.y
@@ -0,0 +1,247 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+/*-------------------------------------------------------------------------
+ Portions of this source have been derived from makedepf90 version 2.8.8,
+
+ Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann@iki.fi>
+
+ The code was originally distributed under the GPL but permission
+ from the copyright holder has been obtained to distribute this
+ derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+ bison --yacc --name-prefix=cmFortran_yy
+ --defines=cmFortranParserTokens.h
+ -ocmFortranParser.cxx
+ cmFortranParser.y
+
+Modify cmFortranParser.cxx:
+ - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmsys/String.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define cmFortranParser_cxx
+#include "cmFortranParser.h" /* Interface to parser object. */
+#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */
+
+/* Forward declare the lexer entry point. */
+YY_DECL;
+
+/* Helper function to forward error callback from parser. */
+static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
+{
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_Error(parser, message);
+}
+
+/* Disable some warnings in the generated code. */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label. */
+# pragma warning (disable: 4065) /* Switch contains default but no case. */
+# pragma warning (disable: 4701) /* Local variable may not be initialized. */
+# pragma warning (disable: 4702) /* Unreachable code. */
+# pragma warning (disable: 4127) /* Conditional expression is constant. */
+# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
+#endif
+%}
+
+/* Generate a reentrant parser object. */
+%define api.pure
+
+/* Configure the parser to use a lexer object. */
+%lex-param {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+%union {
+ char* string;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token EOSTMT ASSIGNMENT_OP GARBAGE
+%token CPP_LINE_DIRECTIVE
+%token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
+%token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
+%token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
+%token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF
+%token F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
+%token COMMA COLON DCOLON LPAREN RPAREN
+%token <number> UNTERMINATED_STRING
+%token <string> STRING WORD
+%token <string> CPP_INCLUDE_ANGLE
+%token END
+%token INCLUDE
+%token INTERFACE
+%token MODULE
+%token SUBMODULE
+%token USE
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+code: /* empty */ | code stmt;
+
+stmt:
+ INTERFACE EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_SetInInterface(parser, true);
+ }
+| USE WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, $2);
+ free($2);
+ }
+| MODULE WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ if (cmsysString_strcasecmp($2, "function") != 0 &&
+ cmsysString_strcasecmp($2, "procedure") != 0 &&
+ cmsysString_strcasecmp($2, "subroutine") != 0) {
+ cmFortranParser_RuleModule(parser, $2);
+ }
+ free($2);
+ }
+| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, $3);
+ free($3);
+ free($5);
+ }
+| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, $3);
+ free($3);
+ free($5);
+ free($7);
+ }
+| INTERFACE WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_SetInInterface(parser, true);
+ free($2);
+ }
+| END INTERFACE other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_SetInInterface(parser, false);
+ }
+| USE DCOLON WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, $3);
+ free($3);
+ }
+| USE COMMA WORD DCOLON WORD other EOSTMT {
+ if (cmsysString_strcasecmp($3, "non_intrinsic") == 0) {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUse(parser, $5);
+ }
+ free($3);
+ free($5);
+ }
+| INCLUDE STRING other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleInclude(parser, $2);
+ free($2);
+ }
+| CPP_LINE_DIRECTIVE STRING other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleLineDirective(parser, $2);
+ free($2);
+ }
+| CPP_INCLUDE_ANGLE other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleInclude(parser, $1);
+ free($1);
+ }
+| include STRING other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleInclude(parser, $2);
+ free($2);
+ }
+| define WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleDefine(parser, $2);
+ free($2);
+ }
+| undef WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUndef(parser, $2);
+ free($2);
+ }
+| ifdef WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleIfdef(parser, $2);
+ free($2);
+ }
+| ifndef WORD other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleIfndef(parser, $2);
+ free($2);
+ }
+| if other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleIf(parser);
+ }
+| elif other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleElif(parser);
+ }
+| else other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleElse(parser);
+ }
+| endif other EOSTMT {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleEndif(parser);
+ }
+| EOSTMT
+| error EOSTMT /* tolerate unknown statements until their end */
+;
+
+
+
+include: CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
+define: CPP_DEFINE | F90PPR_DEFINE;
+undef: CPP_UNDEF | F90PPR_UNDEF ;
+ifdef: CPP_IFDEF | F90PPR_IFDEF ;
+ifndef: CPP_IFNDEF | F90PPR_IFNDEF ;
+if: CPP_IF | F90PPR_IF ;
+elif: CPP_ELIF | F90PPR_ELIF ;
+else: CPP_ELSE | F90PPR_ELSE ;
+endif: CPP_ENDIF | F90PPR_ENDIF ;
+other: /* empty */ | other misc_code ;
+
+misc_code:
+ WORD { free ($1); }
+| END
+| INCLUDE
+| INTERFACE
+| MODULE
+| SUBMODULE
+| USE
+| STRING { free ($1); }
+| GARBAGE
+| ASSIGNMENT_OP
+| COLON
+| DCOLON
+| LPAREN
+| RPAREN
+| COMMA
+| UNTERMINATED_STRING
+;
+
+%%
+/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h
new file mode 100644
index 000000000..8d6a5fe5a
--- /dev/null
+++ b/Source/LexerParser/cmFortranParserTokens.h
@@ -0,0 +1,149 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmFortran_yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ EOSTMT = 258,
+ ASSIGNMENT_OP = 259,
+ GARBAGE = 260,
+ CPP_LINE_DIRECTIVE = 261,
+ CPP_INCLUDE = 262,
+ F90PPR_INCLUDE = 263,
+ COCO_INCLUDE = 264,
+ F90PPR_DEFINE = 265,
+ CPP_DEFINE = 266,
+ F90PPR_UNDEF = 267,
+ CPP_UNDEF = 268,
+ CPP_IFDEF = 269,
+ CPP_IFNDEF = 270,
+ CPP_IF = 271,
+ CPP_ELSE = 272,
+ CPP_ELIF = 273,
+ CPP_ENDIF = 274,
+ F90PPR_IFDEF = 275,
+ F90PPR_IFNDEF = 276,
+ F90PPR_IF = 277,
+ F90PPR_ELSE = 278,
+ F90PPR_ELIF = 279,
+ F90PPR_ENDIF = 280,
+ COMMA = 281,
+ COLON = 282,
+ DCOLON = 283,
+ LPAREN = 284,
+ RPAREN = 285,
+ UNTERMINATED_STRING = 286,
+ STRING = 287,
+ WORD = 288,
+ CPP_INCLUDE_ANGLE = 289,
+ END = 290,
+ INCLUDE = 291,
+ INTERFACE = 292,
+ MODULE = 293,
+ SUBMODULE = 294,
+ USE = 295
+ };
+#endif
+/* Tokens. */
+#define EOSTMT 258
+#define ASSIGNMENT_OP 259
+#define GARBAGE 260
+#define CPP_LINE_DIRECTIVE 261
+#define CPP_INCLUDE 262
+#define F90PPR_INCLUDE 263
+#define COCO_INCLUDE 264
+#define F90PPR_DEFINE 265
+#define CPP_DEFINE 266
+#define F90PPR_UNDEF 267
+#define CPP_UNDEF 268
+#define CPP_IFDEF 269
+#define CPP_IFNDEF 270
+#define CPP_IF 271
+#define CPP_ELSE 272
+#define CPP_ELIF 273
+#define CPP_ENDIF 274
+#define F90PPR_IFDEF 275
+#define F90PPR_IFNDEF 276
+#define F90PPR_IF 277
+#define F90PPR_ELSE 278
+#define F90PPR_ELIF 279
+#define F90PPR_ENDIF 280
+#define COMMA 281
+#define COLON 282
+#define DCOLON 283
+#define LPAREN 284
+#define RPAREN 285
+#define UNTERMINATED_STRING 286
+#define STRING 287
+#define WORD 288
+#define CPP_INCLUDE_ANGLE 289
+#define END 290
+#define INCLUDE 291
+#define INTERFACE 292
+#define MODULE 293
+#define SUBMODULE 294
+#define USE 295
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 70 "cmFortranParser.y" /* yacc.c:1909 */
+
+ char* string;
+
+#line 138 "cmFortranParserTokens.h" /* yacc.c:1909 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int cmFortran_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */
diff --git a/Source/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c
new file mode 100644
index 000000000..3dd3b85b9
--- /dev/null
+++ b/Source/LexerParser/cmListFileLexer.c
@@ -0,0 +1,2688 @@
+#include "cmStandardLexer.h"
+#line 2 "cmListFileLexer.c"
+
+#line 4 "cmListFileLexer.c"
+
+#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 1
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#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
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* 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 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.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmListFileLexer_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
+
+ /* 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.
+ * 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.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+ #define YY_LINENO_REWIND_TO(dst) \
+ do {\
+ const char *p;\
+ for ( p = yy_cp-1; p >= (dst); --p)\
+ if ( *p == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* 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 cmListFileLexer_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 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 );
+
+#define YY_FLUSH_BUFFER cmListFileLexer_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 );
+
+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
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ cmListFileLexer_yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmListFileLexer_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); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cmListFileLexer_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 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 );
+
+/* 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 24
+#define YY_END_OF_BUFFER 25
+/* 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 yyconst flex_int16_t yy_accept[77] =
+ { 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
+ } ;
+
+static yyconst 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,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 5, 6, 7, 1, 1, 1, 8,
+ 9, 1, 1, 1, 1, 1, 1, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 1, 1, 1,
+ 11, 1, 1, 1, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 14, 15, 1, 12, 1, 12, 12, 12, 12,
+
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 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, 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 yyconst YY_CHAR yy_meta[16] =
+ { 0,
+ 1, 1, 2, 3, 4, 3, 1, 3, 5, 6,
+ 1, 6, 1, 1, 7
+ } ;
+
+static yyconst flex_uint16_t yy_base[95] =
+ { 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
+
+ } ;
+
+static yyconst flex_int16_t yy_def[95] =
+ { 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
+
+ } ;
+
+static yyconst flex_uint16_t yy_nxt[253] =
+ { 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
+ } ;
+
+static yyconst flex_int16_t yy_chk[253] =
+ { 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
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst 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, };
+
+/* 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
+#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. */
+/*
+
+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
+
+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
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#ifdef WIN32
+#include "cmsys/Encoding.h"
+#endif
+
+/* Setup the proper cmListFileLexer_yylex declaration. */
+#define YY_EXTRA_TYPE cmListFileLexer*
+#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
+
+#include "cmListFileLexer.h"
+
+/*--------------------------------------------------------------------------*/
+struct cmListFileLexer_s
+{
+ cmListFileLexer_Token token;
+ int bracket;
+ int comment;
+ int line;
+ int column;
+ int size;
+ FILE* file;
+ size_t cr;
+ char* string_buffer;
+ char* string_position;
+ int string_left;
+ yyscan_t scanner;
+};
+
+static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
+ int length);
+static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
+ int length);
+static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
+ size_t bufferSize);
+static void cmListFileLexerInit(cmListFileLexer* lexer);
+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); }
+
+/*--------------------------------------------------------------------------*/
+
+
+
+
+#line 606 "cmListFileLexer.c"
+
+#define INITIAL 0
+#define STRING 1
+#define BRACKET 2
+#define BRACKETEND 3
+#define COMMENT 4
+
+#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 cmListFileLexer_yylex_init (yyscan_t* scanner);
+
+int cmListFileLexer_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 cmListFileLexer_yyget_debug (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+
+FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+
+ int cmListFileLexer_yyget_leng (yyscan_t yyscanner );
+
+char *cmListFileLexer_yyget_text (yyscan_t yyscanner );
+
+int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmListFileLexer_yyget_column (yyscan_t yyscanner );
+
+void cmListFileLexer_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 cmListFileLexer_yywrap (yyscan_t yyscanner );
+#else
+extern int cmListFileLexer_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 *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst 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 = '*'; \
+ size_t 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, 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 cmListFileLexer_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int cmListFileLexer_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 ) {
+ cmListFileLexer_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmListFileLexer_yy_load_buffer_state(yyscanner );
+ }
+
+ {
+#line 80 "cmListFileLexer.in.l"
+
+
+#line 866 "cmListFileLexer.c"
+
+ 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 >= 77 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 237 );
+
+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;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+ }
+
+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:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 82 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_Newline;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+ BEGIN(INITIAL);
+ return 1;
+}
+ YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 91 "cmListFileLexer.in.l"
+{
+ const char* bracket = yytext;
+ lexer->comment = yytext[0] == '#';
+ if (lexer->comment) {
+ lexer->token.type = cmListFileLexer_Token_CommentBracket;
+ bracket += 1;
+ } else {
+ lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
+ }
+ cmListFileLexerSetToken(lexer, "", 0);
+ lexer->bracket = strchr(bracket+1, '[') - bracket;
+ if (yytext[yyleng-1] == '\n') {
+ ++lexer->line;
+ lexer->column = 1;
+ } else {
+ lexer->column += yyleng;
+ }
+ BEGIN(BRACKET);
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 111 "cmListFileLexer.in.l"
+{
+ lexer->column += yyleng;
+ BEGIN(COMMENT);
+}
+ 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);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 127 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ParenRight;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 134 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_Identifier;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 141 "cmListFileLexer.in.l"
+{
+ /* Handle ]]====]=======]*/
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ if (yyleng == lexer->bracket) {
+ BEGIN(BRACKETEND);
+ }
+}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 150 "cmListFileLexer.in.l"
+{
+ lexer->column += yyleng;
+ /* Erase the partial bracket from the token. */
+ lexer->token.length -= lexer->bracket;
+ lexer->token.text[lexer->token.length] = 0;
+ BEGIN(INITIAL);
+ return 1;
+}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 159 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+}
+ YY_BREAK
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 164 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+ BEGIN(BRACKET);
+}
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 171 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ BEGIN(BRACKET);
+}
+ 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);
+ return 1;
+}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 183 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 190 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 197 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 204 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
+ cmListFileLexerSetToken(lexer, "", 0);
+ lexer->column += yyleng;
+ BEGIN(STRING);
+}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 211 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+}
+ YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 216 "cmListFileLexer.in.l"
+{
+ /* Continuation: text is not part of string */
+ ++lexer->line;
+ lexer->column = 1;
+}
+ YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 222 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+}
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 228 "cmListFileLexer.in.l"
+{
+ lexer->column += yyleng;
+ BEGIN(INITIAL);
+ return 1;
+}
+ 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);
+ return 1;
+}
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 245 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_Space;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 252 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_BadCharacter;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+ 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);
+ return 0;
+}
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 265 "cmListFileLexer.in.l"
+ECHO;
+ YY_BREAK
+#line 1205 "cmListFileLexer.c"
+
+ 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
+ * cmListFileLexer_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 ( cmListFileLexer_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 cmListFileLexer_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;
+ yy_size_t 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 = (yy_size_t) (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. */
+ cmListFileLexer_yyrealloc((void *) b->yy_ch_buf,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;
+ cmListFileLexer_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 ((int) (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 );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ 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 >= 77 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) 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 >= 77 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 76);
+
+ (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;
+
+ if ( c == '\n' ){
+ --yylineno;
+ }
+
+ 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 = 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. */
+ cmListFileLexer_yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( cmListFileLexer_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;
+
+ if ( c == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+
+ 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 cmListFileLexer_yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ cmListFileLexer_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cmListFileLexer_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ cmListFileLexer_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)
+{
+ 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);
+ */
+ cmListFileLexer_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;
+ cmListFileLexer_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
+ * 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)
+{
+ 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 cmListFileLexer_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 );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
+
+ b->yy_buf_size = (yy_size_t)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 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ cmListFileLexer_yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with cmListFileLexer_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void cmListFileLexer_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 )
+ cmListFileLexer_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ cmListFileLexer_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.
+ */
+ static void cmListFileLexer_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);
+
+ 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.
+ * 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 cmListFileLexer_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 )
+ cmListFileLexer_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 cmListFileLexer_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);
+
+ /* This block is copied from cmListFileLexer_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 cmListFileLexer_yy_switch_to_buffer. */
+ cmListFileLexer_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 cmListFileLexer_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_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 );
+ 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 cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int 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**)cmListFileLexer_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()" );
+
+ 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**)cmListFileLexer_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()" );
+
+ /* 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 cmListFileLexer_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) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_buffer()" );
+
+ b->yy_buf_size = 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;
+
+ cmListFileLexer_yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_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_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return cmListFileLexer_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
+ * 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 b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t 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 );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" );
+
+ for ( i = 0; i < (size_t)_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);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in cmListFileLexer_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 (yyconst char* msg , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) 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 cmListFileLexer_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 cmListFileLexer_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 cmListFileLexer_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 *cmListFileLexer_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 *cmListFileLexer_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 cmListFileLexer_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 *cmListFileLexer_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 cmListFileLexer_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 cmListFileLexer_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" );
+
+ yylineno = _line_number;
+}
+
+/** Set the current column.
+ * @param _column_no column number
+ * @param yyscanner The scanner object.
+ */
+void cmListFileLexer_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" );
+
+ 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 cmListFileLexer_yy_switch_to_buffer
+ */
+void cmListFileLexer_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = _out_str ;
+}
+
+int cmListFileLexer_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)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = _bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* cmListFileLexer_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)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmListFileLexer_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 );
+}
+
+/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_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 yyextra field.
+ */
+
+int cmListFileLexer_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);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmListFileLexer_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));
+
+ cmListFileLexer_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 cmListFileLexer_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
+ * cmListFileLexer_yylex_init()
+ */
+ return 0;
+}
+
+/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int cmListFileLexer_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_CURRENT_BUFFER_LVALUE = NULL;
+ cmListFileLexer_yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ cmListFileLexer_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ cmListFileLexer_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. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ cmListFileLexer_yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst 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 (yyconst char * s , yyscan_t yyscanner)
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *cmListFileLexer_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)
+{
+ 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 cmListFileLexer_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 */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 265 "cmListFileLexer.in.l"
+
+
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
+ int length)
+{
+ /* Set the token line and column number. */
+ lexer->token.line = lexer->line;
+ lexer->token.column = lexer->column;
+
+ /* Use the same buffer if possible. */
+ if (lexer->token.text) {
+ if (text && length < lexer->size) {
+ strcpy(lexer->token.text, text);
+ lexer->token.length = length;
+ return;
+ }
+ free(lexer->token.text);
+ lexer->token.text = 0;
+ lexer->size = 0;
+ }
+
+ /* Need to extend the buffer. */
+ if (text) {
+ lexer->token.text = strdup(text);
+ lexer->token.length = length;
+ lexer->size = length + 1;
+ } else {
+ lexer->token.length = 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
+ int length)
+{
+ char* temp;
+ int newSize;
+
+ /* If the appended text will fit in the buffer, do not reallocate. */
+ newSize = lexer->token.length + length + 1;
+ if (lexer->token.text && newSize <= lexer->size) {
+ strcpy(lexer->token.text + lexer->token.length, text);
+ lexer->token.length += length;
+ return;
+ }
+
+ /* We need to extend the buffer. */
+ temp = malloc(newSize);
+ if (lexer->token.text) {
+ memcpy(temp, lexer->token.text, lexer->token.length);
+ free(lexer->token.text);
+ }
+ memcpy(temp + lexer->token.length, text, length);
+ temp[lexer->token.length + length] = 0;
+ lexer->token.text = temp;
+ lexer->token.length += length;
+ lexer->size = newSize;
+}
+
+/*--------------------------------------------------------------------------*/
+static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
+ size_t bufferSize)
+{
+ if (lexer) {
+ if (lexer->file) {
+ /* Convert CRLF -> LF explicitly. The C FILE "t"ext mode
+ does not convert newlines on all platforms. Move any
+ trailing CR to the start of the buffer for the next read. */
+ size_t cr = lexer->cr;
+ size_t n;
+ buffer[0] = '\r';
+ n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
+ if (n) {
+ char* o = buffer;
+ const char* i = buffer;
+ const char* e;
+ n += cr;
+ cr = (buffer[n - 1] == '\r') ? 1 : 0;
+ e = buffer + n - cr;
+ while (i != e) {
+ if (i[0] == '\r' && i[1] == '\n') {
+ ++i;
+ }
+ *o++ = *i++;
+ }
+ n = o - buffer;
+ } else {
+ n = cr;
+ cr = 0;
+ }
+ lexer->cr = cr;
+ return n;
+ } else if (lexer->string_left) {
+ int length = lexer->string_left;
+ if ((int)bufferSize < length) {
+ length = (int)bufferSize;
+ }
+ memcpy(buffer, lexer->string_position, length);
+ lexer->string_position += length;
+ lexer->string_left -= length;
+ return length;
+ }
+ }
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerInit(cmListFileLexer* lexer)
+{
+ if (lexer->file || lexer->string_buffer) {
+ cmListFileLexer_yylex_init(&lexer->scanner);
+ cmListFileLexer_yyset_extra(lexer, lexer->scanner);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerDestroy(cmListFileLexer* lexer)
+{
+ cmListFileLexerSetToken(lexer, 0, 0);
+ if (lexer->file || lexer->string_buffer) {
+ cmListFileLexer_yylex_destroy(lexer->scanner);
+ if (lexer->file) {
+ fclose(lexer->file);
+ lexer->file = 0;
+ }
+ if (lexer->string_buffer) {
+ free(lexer->string_buffer);
+ lexer->string_buffer = 0;
+ lexer->string_left = 0;
+ lexer->string_position = 0;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+cmListFileLexer* cmListFileLexer_New(void)
+{
+ cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
+ if (!lexer) {
+ return 0;
+ }
+ memset(lexer, 0, sizeof(*lexer));
+ lexer->line = 1;
+ lexer->column = 1;
+ return lexer;
+}
+
+/*--------------------------------------------------------------------------*/
+void cmListFileLexer_Delete(cmListFileLexer* lexer)
+{
+ cmListFileLexer_SetFileName(lexer, 0, 0);
+ free(lexer);
+}
+
+/*--------------------------------------------------------------------------*/
+static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
+{
+ unsigned char b[2];
+ if (fread(b, 1, 2, f) == 2) {
+ if (b[0] == 0xEF && b[1] == 0xBB) {
+ if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
+ return cmListFileLexer_BOM_UTF8;
+ }
+ } else if (b[0] == 0xFE && b[1] == 0xFF) {
+ /* UTF-16 BE */
+ return cmListFileLexer_BOM_UTF16BE;
+ } else if (b[0] == 0 && b[1] == 0) {
+ if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
+ return cmListFileLexer_BOM_UTF32BE;
+ }
+ } else if (b[0] == 0xFF && b[1] == 0xFE) {
+ fpos_t p;
+ fgetpos(f, &p);
+ if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
+ return cmListFileLexer_BOM_UTF32LE;
+ }
+ if (fsetpos(f, &p) != 0) {
+ return cmListFileLexer_BOM_Broken;
+ }
+ return cmListFileLexer_BOM_UTF16LE;
+ }
+ }
+ if (fseek(f, 0, SEEK_SET) != 0) {
+ return cmListFileLexer_BOM_Broken;
+ }
+ return cmListFileLexer_BOM_None;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
+ cmListFileLexer_BOM* bom)
+{
+ int result = 1;
+ cmListFileLexerDestroy(lexer);
+ if (name) {
+#ifdef _WIN32
+ wchar_t* wname = cmsysEncoding_DupToWide(name);
+ lexer->file = _wfopen(wname, L"rb");
+ free(wname);
+#else
+ lexer->file = fopen(name, "rb");
+#endif
+ if (lexer->file) {
+ if (bom) {
+ *bom = cmListFileLexer_ReadBOM(lexer->file);
+ }
+ } else {
+ result = 0;
+ }
+ }
+ cmListFileLexerInit(lexer);
+ return result;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
+{
+ int result = 1;
+ cmListFileLexerDestroy(lexer);
+ if (text) {
+ int length = (int)strlen(text);
+ lexer->string_buffer = (char*)malloc(length + 1);
+ if (lexer->string_buffer) {
+ strcpy(lexer->string_buffer, text);
+ lexer->string_position = lexer->string_buffer;
+ lexer->string_left = length;
+ } else {
+ result = 0;
+ }
+ }
+ cmListFileLexerInit(lexer);
+ return result;
+}
+
+/*--------------------------------------------------------------------------*/
+cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
+{
+ if (!lexer->file) {
+ return 0;
+ }
+ if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
+ return &lexer->token;
+ } else {
+ cmListFileLexer_SetFileName(lexer, 0, 0);
+ return 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
+{
+ if (lexer->file) {
+ return lexer->line;
+ } else {
+ return 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
+{
+ if (lexer->file) {
+ return lexer->column;
+ } else {
+ return 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
+ cmListFileLexer_Type type)
+{
+ (void)lexer;
+ switch (type) {
+ case cmListFileLexer_Token_None:
+ return "nothing";
+ case cmListFileLexer_Token_Space:
+ return "space";
+ case cmListFileLexer_Token_Newline:
+ return "newline";
+ case cmListFileLexer_Token_Identifier:
+ return "identifier";
+ case cmListFileLexer_Token_ParenLeft:
+ return "left paren";
+ case cmListFileLexer_Token_ParenRight:
+ return "right paren";
+ case cmListFileLexer_Token_ArgumentUnquoted:
+ return "unquoted argument";
+ case cmListFileLexer_Token_ArgumentQuoted:
+ return "quoted argument";
+ case cmListFileLexer_Token_ArgumentBracket:
+ return "bracket argument";
+ case cmListFileLexer_Token_CommentBracket:
+ return "bracket comment";
+ case cmListFileLexer_Token_BadCharacter:
+ return "bad character";
+ case cmListFileLexer_Token_BadBracket:
+ return "unterminated bracket";
+ case cmListFileLexer_Token_BadString:
+ return "unterminated string";
+ }
+ return "unknown token";
+}
diff --git a/Source/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l
index 12b53eef6..5152dbf08 100644
--- a/Source/cmListFileLexer.in.l
+++ b/Source/LexerParser/cmListFileLexer.in.l
@@ -1,36 +1,28 @@
%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 like this:
+Run flex >= 2.6 like this:
- flex --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
+ flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
Modify cmListFileLexer.c:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - remove the yyunput function
- - add a statement "(void)yyscanner;" to the top of these methods:
- yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree
- - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy
- - remove all YY_BREAK lines occurring right after return statements
- - remove the isatty forward declaration
+ - 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
*/
-#include "cmStandardLexer.h"
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#ifdef WIN32
+#include "cmsys/Encoding.h"
+#endif
/* Setup the proper cmListFileLexer_yylex declaration. */
#define YY_EXTRA_TYPE cmListFileLexer*
@@ -42,10 +34,13 @@ Modify cmListFileLexer.c:
struct cmListFileLexer_s
{
cmListFileLexer_Token token;
+ int bracket;
+ int comment;
int line;
int column;
int size;
FILE* file;
+ size_t cr;
char* string_buffer;
char* string_position;
int string_left;
@@ -74,22 +69,51 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
%option noyywrap
%pointer
%x STRING
+%x BRACKET
+%x BRACKETEND
+%x COMMENT
MAKEVAR \$\([A-Za-z0-9_]*\)
-UNQUOTED ([^ \t\r\n\(\)#\\\"]|\\.)
-LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t])*\"
+UNQUOTED ([^ \t\r\n\(\)#\\\"[=]|\\.)
+LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
%%
-\n {
+<INITIAL,COMMENT>\n {
lexer->token.type = cmListFileLexer_Token_Newline;
cmListFileLexerSetToken(lexer, yytext, yyleng);
++lexer->line;
lexer->column = 1;
+ BEGIN(INITIAL);
return 1;
}
-#.* {
+#?\[=*\[\n? {
+ const char* bracket = yytext;
+ lexer->comment = yytext[0] == '#';
+ if (lexer->comment) {
+ lexer->token.type = cmListFileLexer_Token_CommentBracket;
+ bracket += 1;
+ } else {
+ lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
+ }
+ cmListFileLexerSetToken(lexer, "", 0);
+ lexer->bracket = strchr(bracket+1, '[') - bracket;
+ if (yytext[yyleng-1] == '\n') {
+ ++lexer->line;
+ lexer->column = 1;
+ } else {
+ lexer->column += yyleng;
+ }
+ BEGIN(BRACKET);
+}
+
+# {
+ lexer->column += yyleng;
+ BEGIN(COMMENT);
+}
+
+<COMMENT>.* {
lexer->column += yyleng;
}
@@ -107,21 +131,70 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t])*\"
return 1;
}
-[A-Za-z_][A-Za-z0-9_]+ {
+[A-Za-z_][A-Za-z0-9_]* {
lexer->token.type = cmListFileLexer_Token_Identifier;
cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
return 1;
}
-({UNQUOTED})({UNQUOTED})* {
+<BRACKET>\]=* {
+ /* Handle ]]====]=======]*/
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ if (yyleng == lexer->bracket) {
+ BEGIN(BRACKETEND);
+ }
+}
+
+<BRACKETEND>\] {
+ lexer->column += yyleng;
+ /* Erase the partial bracket from the token. */
+ lexer->token.length -= lexer->bracket;
+ lexer->token.text[lexer->token.length] = 0;
+ BEGIN(INITIAL);
+ return 1;
+}
+
+<BRACKET>([^]\n])+ {
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+}
+
+<BRACKET,BRACKETEND>\n {
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+ BEGIN(BRACKET);
+}
+
+<BRACKET,BRACKETEND>. {
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ BEGIN(BRACKET);
+}
+
+<BRACKET,BRACKETEND><<EOF>> {
+ lexer->token.type = cmListFileLexer_Token_BadBracket;
+ BEGIN(INITIAL);
+ return 1;
+}
+
+({UNQUOTED}|=|\[=*{UNQUOTED})({UNQUOTED}|[[=])* {
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+
+({MAKEVAR}|{UNQUOTED}|=|\[=*{LEGACY})({LEGACY}|[[=])* {
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
return 1;
}
-({MAKEVAR}|{UNQUOTED})({LEGACY})* {
+\[ {
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
@@ -141,7 +214,7 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t])*\"
}
<STRING>\\\n {
- cmListFileLexerAppend(lexer, yytext, yyleng);
+ /* Continuation: text is not part of string */
++lexer->line;
lexer->column = 1;
}
@@ -200,30 +273,25 @@ static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
lexer->token.column = lexer->column;
/* Use the same buffer if possible. */
- if(lexer->token.text)
- {
- if(text && length < lexer->size)
- {
+ if (lexer->token.text) {
+ if (text && length < lexer->size) {
strcpy(lexer->token.text, text);
lexer->token.length = length;
return;
- }
+ }
free(lexer->token.text);
lexer->token.text = 0;
lexer->size = 0;
- }
+ }
/* Need to extend the buffer. */
- if(text)
- {
+ if (text) {
lexer->token.text = strdup(text);
lexer->token.length = length;
- lexer->size = length+1;
- }
- else
- {
+ lexer->size = length + 1;
+ } else {
lexer->token.length = 0;
- }
+ }
}
/*--------------------------------------------------------------------------*/
@@ -235,22 +303,20 @@ static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
/* If the appended text will fit in the buffer, do not reallocate. */
newSize = lexer->token.length + length + 1;
- if(lexer->token.text && newSize <= lexer->size)
- {
- strcpy(lexer->token.text+lexer->token.length, text);
+ if (lexer->token.text && newSize <= lexer->size) {
+ strcpy(lexer->token.text + lexer->token.length, text);
lexer->token.length += length;
return;
- }
+ }
/* We need to extend the buffer. */
temp = malloc(newSize);
- if(lexer->token.text)
- {
+ if (lexer->token.text) {
memcpy(temp, lexer->token.text, lexer->token.length);
free(lexer->token.text);
- }
- memcpy(temp+lexer->token.length, text, length);
- temp[lexer->token.length+length] = 0;
+ }
+ memcpy(temp + lexer->token.length, text, length);
+ temp[lexer->token.length + length] = 0;
lexer->token.text = temp;
lexer->token.length += length;
lexer->size = newSize;
@@ -260,64 +326,84 @@ static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
size_t bufferSize)
{
- if(lexer)
- {
- if(lexer->file)
- {
- return (int)fread(buffer, 1, bufferSize, lexer->file);
+ if (lexer) {
+ if (lexer->file) {
+ /* Convert CRLF -> LF explicitly. The C FILE "t"ext mode
+ does not convert newlines on all platforms. Move any
+ trailing CR to the start of the buffer for the next read. */
+ size_t cr = lexer->cr;
+ size_t n;
+ buffer[0] = '\r';
+ n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
+ if (n) {
+ char* o = buffer;
+ const char* i = buffer;
+ const char* e;
+ n += cr;
+ cr = (buffer[n - 1] == '\r') ? 1 : 0;
+ e = buffer + n - cr;
+ while (i != e) {
+ if (i[0] == '\r' && i[1] == '\n') {
+ ++i;
+ }
+ *o++ = *i++;
+ }
+ n = o - buffer;
+ } else {
+ n = cr;
+ cr = 0;
}
- else if(lexer->string_left)
- {
+ lexer->cr = cr;
+ return n;
+ } else if (lexer->string_left) {
int length = lexer->string_left;
- if((int)bufferSize < length) { length = (int)bufferSize; }
+ if ((int)bufferSize < length) {
+ length = (int)bufferSize;
+ }
memcpy(buffer, lexer->string_position, length);
lexer->string_position += length;
lexer->string_left -= length;
return length;
- }
}
+ }
return 0;
}
/*--------------------------------------------------------------------------*/
static void cmListFileLexerInit(cmListFileLexer* lexer)
{
- if(lexer->file || lexer->string_buffer)
- {
+ if (lexer->file || lexer->string_buffer) {
cmListFileLexer_yylex_init(&lexer->scanner);
cmListFileLexer_yyset_extra(lexer, lexer->scanner);
- }
+ }
}
/*--------------------------------------------------------------------------*/
static void cmListFileLexerDestroy(cmListFileLexer* lexer)
{
- if(lexer->file || lexer->string_buffer)
- {
+ cmListFileLexerSetToken(lexer, 0, 0);
+ if (lexer->file || lexer->string_buffer) {
cmListFileLexer_yylex_destroy(lexer->scanner);
- if(lexer->file)
- {
+ if (lexer->file) {
fclose(lexer->file);
lexer->file = 0;
- }
- if(lexer->string_buffer)
- {
+ }
+ if (lexer->string_buffer) {
free(lexer->string_buffer);
lexer->string_buffer = 0;
lexer->string_left = 0;
lexer->string_position = 0;
- }
}
+ }
}
/*--------------------------------------------------------------------------*/
-cmListFileLexer* cmListFileLexer_New()
+cmListFileLexer* cmListFileLexer_New(void)
{
cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
- if(!lexer)
- {
+ if (!lexer) {
return 0;
- }
+ }
memset(lexer, 0, sizeof(*lexer));
lexer->line = 1;
lexer->column = 1;
@@ -327,23 +413,62 @@ cmListFileLexer* cmListFileLexer_New()
/*--------------------------------------------------------------------------*/
void cmListFileLexer_Delete(cmListFileLexer* lexer)
{
- cmListFileLexer_SetFileName(lexer, 0);
+ cmListFileLexer_SetFileName(lexer, 0, 0);
free(lexer);
}
/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name)
+static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
+{
+ unsigned char b[2];
+ if (fread(b, 1, 2, f) == 2) {
+ if (b[0] == 0xEF && b[1] == 0xBB) {
+ if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
+ return cmListFileLexer_BOM_UTF8;
+ }
+ } else if (b[0] == 0xFE && b[1] == 0xFF) {
+ /* UTF-16 BE */
+ return cmListFileLexer_BOM_UTF16BE;
+ } else if (b[0] == 0 && b[1] == 0) {
+ if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
+ return cmListFileLexer_BOM_UTF32BE;
+ }
+ } else if (b[0] == 0xFF && b[1] == 0xFE) {
+ fpos_t p;
+ fgetpos(f, &p);
+ if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
+ return cmListFileLexer_BOM_UTF32LE;
+ }
+ fsetpos(f, &p);
+ return cmListFileLexer_BOM_UTF16LE;
+ }
+ }
+ rewind(f);
+ return cmListFileLexer_BOM_None;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
+ cmListFileLexer_BOM* bom)
{
int result = 1;
cmListFileLexerDestroy(lexer);
- if(name)
- {
- lexer->file = fopen(name, "r");
- if(!lexer->file)
- {
- result = 0;
+ if (name) {
+#ifdef _WIN32
+ wchar_t* wname = cmsysEncoding_DupToWide(name);
+ lexer->file = _wfopen(wname, L"rb");
+ free(wname);
+#else
+ lexer->file = fopen(name, "rb");
+#endif
+ if (lexer->file) {
+ if (bom) {
+ *bom = cmListFileLexer_ReadBOM(lexer->file);
}
+ } else {
+ result = 0;
}
+ }
cmListFileLexerInit(lexer);
return result;
}
@@ -353,21 +478,17 @@ int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
{
int result = 1;
cmListFileLexerDestroy(lexer);
- if(text)
- {
+ if (text) {
int length = (int)strlen(text);
- lexer->string_buffer = (char*)malloc(length+1);
- if(lexer->string_buffer)
- {
+ lexer->string_buffer = (char*)malloc(length + 1);
+ if (lexer->string_buffer) {
strcpy(lexer->string_buffer, text);
lexer->string_position = lexer->string_buffer;
lexer->string_left = length;
- }
- else
- {
+ } else {
result = 0;
- }
}
+ }
cmListFileLexerInit(lexer);
return result;
}
@@ -375,45 +496,35 @@ int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
/*--------------------------------------------------------------------------*/
cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
{
- if(!lexer->file)
- {
+ if (!lexer->file) {
return 0;
- }
- if(cmListFileLexer_yylex(lexer->scanner, lexer))
- {
+ }
+ if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
return &lexer->token;
- }
- else
- {
- cmListFileLexer_SetFileName(lexer, 0);
+ } else {
+ cmListFileLexer_SetFileName(lexer, 0, 0);
return 0;
- }
+ }
}
/*--------------------------------------------------------------------------*/
long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
{
- if(lexer->file)
- {
+ if (lexer->file) {
return lexer->line;
- }
- else
- {
+ } else {
return 0;
- }
+ }
}
/*--------------------------------------------------------------------------*/
long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
{
- if(lexer->file)
- {
+ if (lexer->file) {
return lexer->column;
- }
- else
- {
+ } else {
return 0;
- }
+ }
}
/*--------------------------------------------------------------------------*/
@@ -421,18 +532,33 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
cmListFileLexer_Type type)
{
(void)lexer;
- switch(type)
- {
- case cmListFileLexer_Token_None: return "nothing";
- case cmListFileLexer_Token_Space: return "space";
- case cmListFileLexer_Token_Newline: return "newline";
- case cmListFileLexer_Token_Identifier: return "identifier";
- case cmListFileLexer_Token_ParenLeft: return "left paren";
- case cmListFileLexer_Token_ParenRight: return "right paren";
- case cmListFileLexer_Token_ArgumentUnquoted: return "unquoted argument";
- case cmListFileLexer_Token_ArgumentQuoted: return "quoted argument";
- case cmListFileLexer_Token_BadCharacter: return "bad character";
- case cmListFileLexer_Token_BadString: return "unterminated string";
- }
+ switch (type) {
+ case cmListFileLexer_Token_None:
+ return "nothing";
+ case cmListFileLexer_Token_Space:
+ return "space";
+ case cmListFileLexer_Token_Newline:
+ return "newline";
+ case cmListFileLexer_Token_Identifier:
+ return "identifier";
+ case cmListFileLexer_Token_ParenLeft:
+ return "left paren";
+ case cmListFileLexer_Token_ParenRight:
+ return "right paren";
+ case cmListFileLexer_Token_ArgumentUnquoted:
+ return "unquoted argument";
+ case cmListFileLexer_Token_ArgumentQuoted:
+ return "quoted argument";
+ case cmListFileLexer_Token_ArgumentBracket:
+ return "bracket argument";
+ case cmListFileLexer_Token_CommentBracket:
+ return "bracket comment";
+ case cmListFileLexer_Token_BadCharacter:
+ return "bad character";
+ case cmListFileLexer_Token_BadBracket:
+ return "unterminated bracket";
+ case cmListFileLexer_Token_BadString:
+ return "unterminated string";
+ }
return "unknown token";
}
diff --git a/Source/Modules/FindJsonCpp.cmake b/Source/Modules/FindJsonCpp.cmake
new file mode 100644
index 000000000..1951b6154
--- /dev/null
+++ b/Source/Modules/FindJsonCpp.cmake
@@ -0,0 +1,107 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindJsonCpp
+-----------
+
+Find JsonCpp includes and library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+An :ref:`imported target <Imported targets>` named
+``JsonCpp::JsonCpp`` is provided if JsonCpp has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``JsonCpp_FOUND``
+ True if JsonCpp was found, false otherwise.
+``JsonCpp_INCLUDE_DIRS``
+ Include directories needed to include JsonCpp headers.
+``JsonCpp_LIBRARIES``
+ Libraries needed to link to JsonCpp.
+``JsonCpp_VERSION_STRING``
+ The version of JsonCpp found.
+ May not be set for JsonCpp versions prior to 1.0.
+``JsonCpp_VERSION_MAJOR``
+ The major version of JsonCpp.
+``JsonCpp_VERSION_MINOR``
+ The minor version of JsonCpp.
+``JsonCpp_VERSION_PATCH``
+ The patch version of JsonCpp.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+This module uses the following cache variables:
+
+``JsonCpp_LIBRARY``
+ The location of the JsonCpp library file.
+``JsonCpp_INCLUDE_DIR``
+ The location of the JsonCpp include directory containing ``json/json.h``.
+
+The cache variables should not be used by project code.
+They may be set by end users to point at JsonCpp components.
+#]=======================================================================]
+
+#-----------------------------------------------------------------------------
+find_library(JsonCpp_LIBRARY
+ NAMES jsoncpp
+ )
+mark_as_advanced(JsonCpp_LIBRARY)
+
+find_path(JsonCpp_INCLUDE_DIR
+ NAMES json/json.h
+ PATH_SUFFIXES jsoncpp
+ )
+mark_as_advanced(JsonCpp_INCLUDE_DIR)
+
+#-----------------------------------------------------------------------------
+# Extract version number if possible.
+set(_JsonCpp_H_REGEX "^#[ \t]*define[ \t]+JSONCPP_VERSION_STRING[ \t]+\"(([0-9]+)\\.([0-9]+)\\.([0-9]+)[^\"]*)\".*$")
+if(JsonCpp_INCLUDE_DIR AND EXISTS "${JsonCpp_INCLUDE_DIR}/json/version.h")
+ file(STRINGS "${JsonCpp_INCLUDE_DIR}/json/version.h" _JsonCpp_H REGEX "${_JsonCpp_H_REGEX}")
+else()
+ set(_JsonCpp_H "")
+endif()
+if(_JsonCpp_H MATCHES "${_JsonCpp_H_REGEX}")
+ set(JsonCpp_VERSION_STRING "${CMAKE_MATCH_1}")
+ set(JsonCpp_VERSION_MAJOR "${CMAKE_MATCH_2}")
+ set(JsonCpp_VERSION_MINOR "${CMAKE_MATCH_3}")
+ set(JsonCpp_VERSION_PATCH "${CMAKE_MATCH_4}")
+else()
+ set(JsonCpp_VERSION_STRING "")
+ set(JsonCpp_VERSION_MAJOR "")
+ set(JsonCpp_VERSION_MINOR "")
+ set(JsonCpp_VERSION_PATCH "")
+endif()
+unset(_JsonCpp_H_REGEX)
+unset(_JsonCpp_H)
+
+#-----------------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(JsonCpp
+ FOUND_VAR JsonCpp_FOUND
+ REQUIRED_VARS JsonCpp_LIBRARY JsonCpp_INCLUDE_DIR
+ VERSION_VAR JsonCpp_VERSION_STRING
+ )
+set(JSONCPP_FOUND ${JsonCpp_FOUND})
+
+#-----------------------------------------------------------------------------
+# Provide documented result variables and targets.
+if(JsonCpp_FOUND)
+ set(JsonCpp_INCLUDE_DIRS ${JsonCpp_INCLUDE_DIR})
+ set(JsonCpp_LIBRARIES ${JsonCpp_LIBRARY})
+ if(NOT TARGET JsonCpp::JsonCpp)
+ add_library(JsonCpp::JsonCpp UNKNOWN IMPORTED)
+ set_target_properties(JsonCpp::JsonCpp PROPERTIES
+ IMPORTED_LOCATION "${JsonCpp_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${JsonCpp_INCLUDE_DIRS}"
+ IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
+ )
+ endif()
+endif()
diff --git a/Source/Modules/FindLibRHash.cmake b/Source/Modules/FindLibRHash.cmake
new file mode 100644
index 000000000..86c6189f3
--- /dev/null
+++ b/Source/Modules/FindLibRHash.cmake
@@ -0,0 +1,73 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindLibRHash
+------------
+
+Find LibRHash include directory and library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+An :ref:`imported target <Imported targets>` named
+``LibRHash::LibRHash`` is provided if LibRHash has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``LibRHash_FOUND``
+ True if LibRHash was found, false otherwise.
+``LibRHash_INCLUDE_DIRS``
+ Include directories needed to include LibRHash headers.
+``LibRHash_LIBRARIES``
+ Libraries needed to link to LibRHash.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+This module uses the following cache variables:
+
+``LibRHash_LIBRARY``
+ The location of the LibRHash library file.
+``LibRHash_INCLUDE_DIR``
+ The location of the LibRHash include directory containing ``rhash.h``.
+
+The cache variables should not be used by project code.
+They may be set by end users to point at LibRHash components.
+#]=======================================================================]
+
+#-----------------------------------------------------------------------------
+find_library(LibRHash_LIBRARY
+ NAMES rhash
+ )
+mark_as_advanced(LibRHash_LIBRARY)
+
+find_path(LibRHash_INCLUDE_DIR
+ NAMES rhash.h
+ )
+mark_as_advanced(LibRHash_INCLUDE_DIR)
+
+#-----------------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibRHash
+ FOUND_VAR LibRHash_FOUND
+ REQUIRED_VARS LibRHash_LIBRARY LibRHash_INCLUDE_DIR
+ )
+set(LIBRHASH_FOUND ${LibRHash_FOUND})
+
+#-----------------------------------------------------------------------------
+# Provide documented result variables and targets.
+if(LibRHash_FOUND)
+ set(LibRHash_INCLUDE_DIRS ${LibRHash_INCLUDE_DIR})
+ set(LibRHash_LIBRARIES ${LibRHash_LIBRARY})
+ if(NOT TARGET LibRHash::LibRHash)
+ add_library(LibRHash::LibRHash UNKNOWN IMPORTED)
+ set_target_properties(LibRHash::LibRHash PROPERTIES
+ IMPORTED_LOCATION "${LibRHash_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LibRHash_INCLUDE_DIRS}"
+ )
+ endif()
+endif()
diff --git a/Source/Modules/FindLibUV.cmake b/Source/Modules/FindLibUV.cmake
new file mode 100644
index 000000000..ba13d75f8
--- /dev/null
+++ b/Source/Modules/FindLibUV.cmake
@@ -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.
+
+#[=======================================================================[.rst:
+FindLibUV
+---------
+
+Find libuv includes and library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+An :ref:`imported target <Imported targets>` named
+``LibUV::LibUV`` is provided if libuv has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``LibUV_FOUND``
+ True if libuv was found, false otherwise.
+``LibUV_INCLUDE_DIRS``
+ Include directories needed to include libuv headers.
+``LibUV_LIBRARIES``
+ Libraries needed to link to libuv.
+``LibUV_VERSION``
+ The version of libuv found.
+``LibUV_VERSION_MAJOR``
+ The major version of libuv.
+``LibUV_VERSION_MINOR``
+ The minor version of libuv.
+``LibUV_VERSION_PATCH``
+ The patch version of libuv.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+This module uses the following cache variables:
+
+``LibUV_LIBRARY``
+ The location of the libuv library file.
+``LibUV_INCLUDE_DIR``
+ The location of the libuv include directory containing ``uv.h``.
+
+The cache variables should not be used by project code.
+They may be set by end users to point at libuv components.
+#]=======================================================================]
+
+#-----------------------------------------------------------------------------
+find_library(LibUV_LIBRARY
+ NAMES uv libuv
+ )
+mark_as_advanced(LibUV_LIBRARY)
+
+find_path(LibUV_INCLUDE_DIR
+ NAMES uv.h
+ )
+mark_as_advanced(LibUV_INCLUDE_DIR)
+
+#-----------------------------------------------------------------------------
+# Extract version number if possible.
+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.h")
+ file(STRINGS "${LibUV_INCLUDE_DIR}/uv.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
+else()
+ set(_LibUV_H "")
+endif()
+foreach(c MAJOR MINOR PATCH)
+ if(_LibUV_H MATCHES "#[ \t]*define[ \t]+UV_VERSION_${c}[ \t]+([0-9]+)")
+ set(_LibUV_VERSION_${c} "${CMAKE_MATCH_1}")
+ else()
+ unset(_LibUV_VERSION_${c})
+ endif()
+endforeach()
+if(DEFINED _LibUV_VERSION_MAJOR AND DEFINED _LibUV_VERSION_MINOR)
+ set(LibUV_VERSION_MAJOR "${_LibUV_VERSION_MAJOR}")
+ set(LibUV_VERSION_MINOR "${_LibUV_VERSION_MINOR}")
+ set(LibUV_VERSION "${LibUV_VERSION_MAJOR}.${LibUV_VERSION_MINOR}")
+ if(DEFINED _LibUV_VERSION_PATCH)
+ set(LibUV_VERSION_PATCH "${_LibUV_VERSION_PATCH}")
+ set(LibUV_VERSION "${LibUV_VERSION}.${LibUV_VERSION_PATCH}")
+ else()
+ unset(LibUV_VERSION_PATCH)
+ endif()
+else()
+ set(LibUV_VERSION_MAJOR "")
+ set(LibUV_VERSION_MINOR "")
+ set(LibUV_VERSION_PATCH "")
+ set(LibUV_VERSION "")
+endif()
+unset(_LibUV_VERSION_MAJOR)
+unset(_LibUV_VERSION_MINOR)
+unset(_LibUV_VERSION_PATCH)
+unset(_LibUV_H_REGEX)
+unset(_LibUV_H)
+
+#-----------------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUV
+ FOUND_VAR LibUV_FOUND
+ REQUIRED_VARS LibUV_LIBRARY LibUV_INCLUDE_DIR
+ VERSION_VAR LibUV_VERSION
+ )
+set(LIBUV_FOUND ${LibUV_FOUND})
+
+#-----------------------------------------------------------------------------
+# Provide documented result variables and targets.
+if(LibUV_FOUND)
+ set(LibUV_INCLUDE_DIRS ${LibUV_INCLUDE_DIR})
+ set(LibUV_LIBRARIES ${LibUV_LIBRARY})
+ if(NOT TARGET LibUV::LibUV)
+ add_library(LibUV::LibUV UNKNOWN IMPORTED)
+ set_target_properties(LibUV::LibUV PROPERTIES
+ IMPORTED_LOCATION "${LibUV_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LibUV_INCLUDE_DIRS}"
+ )
+ endif()
+endif()
diff --git a/Source/QtDialog/AddCacheEntry.cxx b/Source/QtDialog/AddCacheEntry.cxx
index e7fedc5c5..6284ac946 100644
--- a/Source/QtDialog/AddCacheEntry.cxx
+++ b/Source/QtDialog/AddCacheEntry.cxx
@@ -1,34 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "AddCacheEntry.h"
-#include <QMetaProperty>
+
#include <QCompleter>
+#include <QMetaProperty>
static const int NumTypes = 4;
-static const QByteArray TypeStrings[NumTypes] =
- { "BOOL", "PATH", "FILEPATH", "STRING" };
-static const QCMakeProperty::PropertyType Types[NumTypes] =
- { QCMakeProperty::BOOL, QCMakeProperty::PATH,
- QCMakeProperty::FILEPATH, QCMakeProperty::STRING};
+static const int DefaultTypeIndex = 0;
+static const QByteArray TypeStrings[NumTypes] = { "BOOL", "PATH", "FILEPATH",
+ "STRING" };
+static const QCMakeProperty::PropertyType Types[NumTypes] = {
+ QCMakeProperty::BOOL, QCMakeProperty::PATH, QCMakeProperty::FILEPATH,
+ QCMakeProperty::STRING
+};
-AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& completions)
+AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& varNames,
+ const QStringList& varTypes)
: QWidget(p)
+ , VarNames(varNames)
+ , VarTypes(varTypes)
{
this->setupUi(this);
- for(int i=0; i<NumTypes; i++)
- {
+ for (int i = 0; i < NumTypes; i++) {
this->Type->addItem(TypeStrings[i]);
- }
+ }
QWidget* cb = new QCheckBox();
QWidget* path = new QCMakePathEditor();
QWidget* filepath = new QCMakeFilePathEditor();
@@ -43,25 +38,26 @@ AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& completions)
this->setTabOrder(path, filepath);
this->setTabOrder(filepath, string);
this->setTabOrder(string, this->Description);
- this->Name->setCompleter(new QCompleter(completions, this));
+ QCompleter* completer = new QCompleter(this->VarNames, this);
+ this->Name->setCompleter(completer);
+ connect(completer, SIGNAL(activated(const QString&)), this,
+ SLOT(onCompletionActivated(const QString&)));
}
QString AddCacheEntry::name() const
{
- return this->Name->text();
+ return this->Name->text().trimmed();
}
QVariant AddCacheEntry::value() const
{
QWidget* w = this->StackedWidget->currentWidget();
- if(qobject_cast<QLineEdit*>(w))
- {
+ if (qobject_cast<QLineEdit*>(w)) {
return static_cast<QLineEdit*>(w)->text();
- }
- else if(qobject_cast<QCheckBox*>(w))
- {
+ }
+ if (qobject_cast<QCheckBox*>(w)) {
return static_cast<QCheckBox*>(w)->isChecked();
- }
+ }
return QVariant();
}
@@ -73,11 +69,31 @@ QString AddCacheEntry::description() const
QCMakeProperty::PropertyType AddCacheEntry::type() const
{
int idx = this->Type->currentIndex();
- if(idx >= 0 && idx < NumTypes)
- {
+ if (idx >= 0 && idx < NumTypes) {
return Types[idx];
- }
- return QCMakeProperty::BOOL;
+ }
+ return Types[DefaultTypeIndex];
}
+QString AddCacheEntry::typeString() const
+{
+ int idx = this->Type->currentIndex();
+ if (idx >= 0 && idx < NumTypes) {
+ return TypeStrings[idx];
+ }
+ return TypeStrings[DefaultTypeIndex];
+}
+void AddCacheEntry::onCompletionActivated(const QString& text)
+{
+ int idx = this->VarNames.indexOf(text);
+ if (idx != -1) {
+ QString vartype = this->VarTypes[idx];
+ for (int i = 0; i < NumTypes; i++) {
+ if (TypeStrings[i] == vartype) {
+ this->Type->setCurrentIndex(i);
+ break;
+ }
+ }
+ }
+}
diff --git a/Source/QtDialog/AddCacheEntry.h b/Source/QtDialog/AddCacheEntry.h
index e219d4ee7..cc710f558 100644
--- a/Source/QtDialog/AddCacheEntry.h
+++ b/Source/QtDialog/AddCacheEntry.h
@@ -1,36 +1,35 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef AddCacheEntry_h
#define AddCacheEntry_h
-#include <QWidget>
+#include "QCMake.h"
+
#include <QCheckBox>
#include <QStringList>
+#include <QWidget>
-#include "QCMake.h"
#include "ui_AddCacheEntry.h"
class AddCacheEntry : public QWidget, public Ui::AddCacheEntry
{
Q_OBJECT
public:
- AddCacheEntry(QWidget* p, const QStringList& completions);
+ AddCacheEntry(QWidget* p, const QStringList& varNames,
+ const QStringList& varTypes);
QString name() const;
QVariant value() const;
QString description() const;
QCMakeProperty::PropertyType type() const;
+ QString typeString() const;
+
+private slots:
+ void onCompletionActivated(const QString& text);
+
+private:
+ const QStringList& VarNames;
+ const QStringList& VarTypes;
};
#endif
-
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index ef252944e..9e9df781e 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -1,19 +1,11 @@
-#=============================================================================
-# CMake - Cross Platform Makefile Generator
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# 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)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
@@ -27,15 +19,68 @@ if (Qt5Widgets_FOUND)
macro(qt4_add_resources)
qt5_add_resources(${ARGN})
endmacro()
- set(QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
+ set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
+ set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_LIBRARIES})
+
# Remove this when the minimum version of Qt is 4.6.
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
- if(WIN32 AND TARGET Qt5::Core)
+ if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES)
+ list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES})
+ set_property(SOURCE CMakeSetup.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin)
+ 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
+ # Qt5 support is missing there.
+ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
+ macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var)
+ get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
+ if(EXISTS "${_qt_plugin_path}")
+ get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME)
+ get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
+ get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME)
+ if(APPLE)
+ set(_qt_plugin_dir "PlugIns")
+ elseif(WIN32)
+ set(_qt_plugin_dir "plugins")
+ endif()
+ set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}")
+ install(FILES "${_qt_plugin_path}"
+ DESTINATION "${_qt_plugin_dest}"
+ ${COMPONENT})
+ set(${_qt_plugins_var}
+ "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}")
+ else()
+ message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
+ endif()
+ endmacro()
+ if(APPLE)
+ install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ "[Paths]\nPlugins = ${_qt_plugin_dir}\n")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
+ ${COMPONENT})
+ elseif(WIN32)
+ install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ "[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ DESTINATION bin
+ ${COMPONENT})
+ endif()
+ endif()
+
+ if(TARGET Qt5::Core)
get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
+ if(APPLE)
+ get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH)
+ endif()
endif()
else()
set(QT_MIN_VERSION "4.4.0")
@@ -47,12 +92,8 @@ else()
include(${QT_USE_FILE})
- if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}")
- get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH)
- if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll")
- set(Qt_BIN_DIR ${_Qt_BIN_DIR})
- endif()
- endif()
+ set(CMake_QT_LIBRARIES ${QT_LIBRARIES})
+
endif()
set(SRCS
@@ -69,15 +110,18 @@ set(SRCS
QCMakeCacheView.h
QCMakeWidgets.cxx
QCMakeWidgets.h
- QMacInstallDialog.cxx
- QMacInstallDialog.h
+ RegexExplorer.cxx
+ RegexExplorer.h
+ WarningMessagesDialog.cxx
+ WarningMessagesDialog.h
)
QT4_WRAP_UI(UI_SRCS
CMakeSetupDialog.ui
Compilers.ui
CrossCompiler.ui
AddCacheEntry.ui
- MacInstallDialog.ui
+ RegexExplorer.ui
+ WarningMessagesDialog.ui
)
QT4_WRAP_CPP(MOC_SRCS
AddCacheEntry.h
@@ -87,7 +131,8 @@ QT4_WRAP_CPP(MOC_SRCS
QCMake.h
QCMakeCacheView.h
QCMakeWidgets.h
- QMacInstallDialog.h
+ RegexExplorer.h
+ WarningMessagesDialog.h
)
QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
@@ -102,56 +147,103 @@ if(APPLE)
MACOSX_PACKAGE_LOCATION Resources)
endif()
+if(USE_LGPL)
+ install(FILES ${CMake_SOURCE_DIR}/Licenses/LGPLv${USE_LGPL}.txt
+ DESTINATION ${CMAKE_DATA_DIR}/Licenses
+ ${COMPONENT})
+ set_property(SOURCE CMakeSetupDialog.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_LGPL="${USE_LGPL}")
+endif()
+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
-add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS})
-target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
-if(Qt_BIN_DIR)
- set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR})
-endif()
+add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE})
+target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES})
+
+# cmake-gui has not been updated for `include-what-you-use`.
+# Block the tool until this is done.
+set_target_properties(cmake-gui PROPERTIES
+ CXX_INCLUDE_WHAT_YOU_USE ""
+ )
+
+# Files generated by MOC, RCC, and UIC may produce clang-tidy warnings.
+# We generate a dummy .clang-tidy file in the binary directory that disables
+# all clang-tidy checks except one that will never match. This one check is
+# necessary; clang-tidy reports an error when no checks are enabled.
+# Since the Qt code generators will generate source files in the binary tree,
+# clang-tidy will load the configuration from this dummy file when the sources
+# are built.
+file(WRITE "${QtDialog_BINARY_DIR}/.clang-tidy" "
+---
+Checks: '-*,llvm-twine-local'
+...
+")
if(APPLE)
+ file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line
+ LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware")
+
set_target_properties(cmake-gui PROPERTIES
- OUTPUT_NAME ${CMAKE_BUNDLE_NAME})
+ OUTPUT_NAME CMake
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_BUNDLE_VERSION}"
+ # TBD: MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_BUNDLE_VERSION}"
+ MACOSX_BUNDLE_COPYRIGHT "${copyright_line}"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "org.cmake.cmake"
+ )
+
+ # Create a symlink in the build tree to provide a "cmake-gui" next
+ # to the "cmake" executable that refers to the application bundle.
+ add_custom_command(TARGET cmake-gui POST_BUILD
+ COMMAND ln -sf CMake.app/Contents/MacOS/CMake
+ $<TARGET_FILE_DIR:cmake>/cmake-gui
+ )
endif()
set(CMAKE_INSTALL_DESTINATION_ARGS
- BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}")
+ BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT})
-install(TARGETS cmake-gui RUNTIME DESTINATION bin ${CMAKE_INSTALL_DESTINATION_ARGS})
+install(TARGETS cmake-gui
+ RUNTIME DESTINATION bin ${COMPONENT}
+ ${CMAKE_INSTALL_DESTINATION_ARGS})
+
+if(UNIX AND NOT APPLE)
+ foreach (size IN ITEMS 32 128)
+ install(
+ FILES "${CMAKE_CURRENT_SOURCE_DIR}/CMakeSetup${size}.png"
+ DESTINATION "${CMAKE_XDGDATA_DIR}/icons/hicolor/${size}x${size}/apps"
+ ${COMPONENT}
+ RENAME "CMakeSetup.png")
+ endforeach ()
-if(UNIX)
# install a desktop file so CMake appears in the application start menu
# with an icon
- install(FILES CMake.desktop DESTINATION share/applications )
- install(FILES CMakeSetup32.png DESTINATION share/pixmaps )
- install(FILES cmakecache.xml DESTINATION share/mime/packages )
+ install(FILES cmake-gui.desktop
+ DESTINATION "${CMAKE_XDGDATA_DIR}/applications"
+ ${COMPONENT})
+ install(FILES cmakecache.xml
+ DESTINATION "${CMAKE_XDGDATA_DIR}/mime/packages"
+ ${COMPONENT})
endif()
if(APPLE)
- set(CMAKE_POSTFLIGHT_SCRIPT
- "${CMake_BINARY_DIR}/Source/QtDialog/postflight.sh")
- set(CMAKE_POSTUPGRADE_SCRIPT
- "${CMake_BINARY_DIR}/Source/QtDialog/postupgrade.sh")
- configure_file("${CMake_SOURCE_DIR}/Source/QtDialog/postflight.sh.in"
- "${CMake_BINARY_DIR}/Source/QtDialog/postflight.sh")
- configure_file("${CMake_SOURCE_DIR}/Source/QtDialog/postupgrade.sh.in"
- "${CMake_BINARY_DIR}/Source/QtDialog/postupgrade.sh")
- install(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" cmake-gui
- WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)")
+ install(CODE "
+ execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui
+ WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)
+ " ${COMPONENT})
endif()
-if(APPLE OR WIN32)
+if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
# install rules for including 3rd party libs such as Qt
# if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation
set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}")
if(APPLE)
- set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
+ set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/CMake")
endif()
install(CODE "
include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
- fixup_bundle(\"${fixup_exe}\" \"\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\")
- ")
+ fixup_bundle(\"${fixup_exe}\" \"${QT_PLUGINS}\" \"${Qt_BIN_DIR};${QT_LIBRARY_DIR};${QT_BINARY_DIR}\")
+ " ${COMPONENT})
endif()
set(CMAKE_PACKAGE_QTGUI TRUE)
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 01893f589..7fa2ac661 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -1,122 +1,113 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "QCMake.h" // include to disable MS warnings
-#include <QApplication>
-#include <QDir>
-#include <QTranslator>
-#include <QLocale>
-#include "QMacInstallDialog.h"
+/* 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 "CMakeSetupDialog.h"
+#include "cmAlgorithms.h"
#include "cmDocumentation.h"
-#include "cmake.h"
+#include "cmDocumentationEntry.h"
#include "cmVersion.h"
-#include <cmsys/CommandLineArguments.hxx>
-#include <cmsys/SystemTools.hxx>
+#include "cmake.h"
+#include "cmsys/CommandLineArguments.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/SystemTools.hxx"
+#include <QApplication>
+#include <QDir>
+#include <QLocale>
+#include <QString>
+#include <QTextCodec>
+#include <QTranslator>
+#include <QtPlugin>
+#include <iostream>
-//----------------------------------------------------------------------------
-static const char * cmDocumentationName[][3] =
-{
- {0,
- " cmake-gui - CMake GUI.", 0},
- {0,0,0}
-};
+#include "cmSystemTools.h" // IWYU pragma: keep
-//----------------------------------------------------------------------------
-static const char * cmDocumentationUsage[][3] =
-{
- {0,
- " cmake-gui [options]\n"
- " cmake-gui [options] <path-to-source>\n"
- " cmake-gui [options] <path-to-existing-build>", 0},
- {0,0,0}
-};
+static const char* cmDocumentationName[][2] = { { CM_NULLPTR,
+ " cmake-gui - CMake GUI." },
+ { CM_NULLPTR, CM_NULLPTR } };
-//----------------------------------------------------------------------------
-static const char * cmDocumentationDescription[][3] =
-{
- {0,
- "The \"cmake-gui\" executable is the CMake GUI. Project "
- "configuration settings may be specified interactively. "
- "Brief instructions are provided at the bottom of the "
- "window when the program is running.", 0},
- CMAKE_STANDARD_INTRODUCTION,
- {0,0,0}
+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 }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationOptions[][3] =
-{
- {0,0,0}
-};
+static const char* cmDocumentationOptions[]
+ [2] = { { CM_NULLPTR, CM_NULLPTR } };
+
+#if defined(Q_OS_MAC)
+static int cmOSXInstall(std::string dir);
+static void cmAddPluginPath();
+#endif
+
+#if defined(USE_QXcbIntegrationPlugin)
+Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
+#endif
int main(int argc, char** argv)
{
- cmSystemTools::FindExecutableDirectory(argv[0]);
+ cmsys::Encoding::CommandLineArguments encoding_args =
+ cmsys::Encoding::CommandLineArguments::Main(argc, argv);
+ int argc2 = encoding_args.argc();
+ char const* const* argv2 = encoding_args.argv();
+
+ cmSystemTools::FindCMakeResources(argv2[0]);
// check docs first so that X is not need to get docs
// do docs, if args were given
cmDocumentation doc;
doc.addCMakeStandardDocSections();
- if(argc >1 && doc.CheckOptions(argc, argv))
- {
+ if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) {
// Construct and print requested documentation.
- cmake hcm;
+ cmake hcm(cmake::RoleInternal);
+ hcm.SetHomeDirectory("");
+ hcm.SetHomeOutputDirectory("");
hcm.AddCMakePaths();
- // just incase the install is bad avoid a seg fault
- const char* root = hcm.GetCacheDefinition("CMAKE_ROOT");
- if(root)
- {
- doc.SetCMakeRoot(root);
- }
- std::vector<cmDocumentationEntry> commands;
- std::vector<cmDocumentationEntry> compatCommands;
- std::map<std::string,cmDocumentationSection *> propDocs;
std::vector<cmDocumentationEntry> generators;
- hcm.GetCommandDocumentation(commands, true, false);
- hcm.GetCommandDocumentation(compatCommands, false, true);
hcm.GetGeneratorDocumentation(generators);
- hcm.GetPropertiesDocumentation(propDocs);
doc.SetName("cmake");
- doc.SetSection("Name",cmDocumentationName);
- doc.SetSection("Usage",cmDocumentationUsage);
- doc.SetSection("Description",cmDocumentationDescription);
- doc.AppendSection("Generators",generators);
- doc.PrependSection("Options",cmDocumentationOptions);
- doc.SetSection("Commands",commands);
- doc.SetSection("Compatilbility Commands", compatCommands);
- doc.SetSections(propDocs);
-
- return (doc.PrintRequestedDocumentation(std::cout)? 0:1);
- }
+ doc.SetSection("Name", cmDocumentationName);
+ doc.SetSection("Usage", cmDocumentationUsage);
+ doc.AppendSection("Generators", generators);
+ doc.PrependSection("Options", cmDocumentationOptions);
+
+ return (doc.PrintRequestedDocumentation(std::cout) ? 0 : 1);
+ }
+
+#if defined(Q_OS_MAC)
+ if (argc2 == 2 && strcmp(argv2[1], "--install") == 0) {
+ return cmOSXInstall("/usr/local/bin");
+ }
+ if (argc2 == 2 && cmHasLiteralPrefix(argv2[1], "--install=")) {
+ return cmOSXInstall(argv2[1] + 10);
+ }
+#endif
+
+// When we are on OSX and we are launching cmake-gui from a symlink, the
+// application will fail to launch as it can't find the qt.conf file which
+// tells it what the name of the plugin folder is. We need to add this path
+// BEFORE the application is constructed as that is what triggers the
+// searching for the platform plugins
+#if defined(Q_OS_MAC)
+ cmAddPluginPath();
+#endif
QApplication app(argc, argv);
+ setlocale(LC_NUMERIC, "C");
+
+ QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8");
+ QTextCodec::setCodecForLocale(utf8_codec);
+
+#if QT_VERSION < 0x050000
// clean out standard Qt paths for plugins, which we don't use anyway
// when creating Mac bundles, it potentially causes problems
- foreach(QString p, QApplication::libraryPaths())
- {
+ foreach (QString p, QApplication::libraryPaths()) {
QApplication::removeLibraryPath(p);
- }
+ }
+#endif
- // if arg for install
- for(int i =0; i < argc; i++)
- {
- if(strcmp(argv[i], "--mac-install") == 0)
- {
- QMacInstallDialog setupdialog(0);
- setupdialog.exec();
- return 0;
- }
- }
// tell the cmake library where cmake is
QDir cmExecDir(QApplication::applicationDirPath());
#if defined(Q_OS_MAC)
@@ -144,62 +135,119 @@ int main(int argc, char** argv)
dialog.show();
cmsys::CommandLineArguments arg;
- arg.Initialize(argc, argv);
+ arg.Initialize(argc2, argv2);
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");
+ 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();
- if(!sourceDirectory.empty() && !binaryDirectory.empty())
- {
+ if (!sourceDirectory.empty() && !binaryDirectory.empty()) {
dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str()));
dialog.setBinaryDirectory(QString::fromLocal8Bit(binaryDirectory.c_str()));
- }
- else
- {
+ } else {
QStringList args = app.arguments();
- if(args.count() == 2)
- {
- cmsys_stl::string filePath = cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data());
+ if (args.count() == 2) {
+ std::string filePath =
+ cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data());
// check if argument is a directory containing CMakeCache.txt
- cmsys_stl::string buildFilePath =
+ std::string buildFilePath =
cmSystemTools::CollapseFullPath("CMakeCache.txt", filePath.c_str());
// check if argument is a CMakeCache.txt file
- if(cmSystemTools::GetFilenameName(filePath) == "CMakeCache.txt" &&
- cmSystemTools::FileExists(filePath.c_str()))
- {
+ if (cmSystemTools::GetFilenameName(filePath) == "CMakeCache.txt" &&
+ cmSystemTools::FileExists(filePath.c_str())) {
buildFilePath = filePath;
- }
+ }
// check if argument is a directory containing CMakeLists.txt
- cmsys_stl::string srcFilePath =
+ std::string srcFilePath =
cmSystemTools::CollapseFullPath("CMakeLists.txt", filePath.c_str());
- if(cmSystemTools::FileExists(buildFilePath.c_str()))
- {
- dialog.setBinaryDirectory(
- QString::fromLocal8Bit(
- cmSystemTools::GetFilenamePath(buildFilePath).c_str()
- )
- );
- }
- else if(cmSystemTools::FileExists(srcFilePath.c_str()))
- {
+ if (cmSystemTools::FileExists(buildFilePath.c_str())) {
+ dialog.setBinaryDirectory(QString::fromLocal8Bit(
+ cmSystemTools::GetFilenamePath(buildFilePath).c_str()));
+ } else if (cmSystemTools::FileExists(srcFilePath.c_str())) {
dialog.setSourceDirectory(QString::fromLocal8Bit(filePath.c_str()));
- dialog.setBinaryDirectory(
- QString::fromLocal8Bit(cmSystemTools::CollapseFullPath(".").c_str())
- );
- }
+ dialog.setBinaryDirectory(QString::fromLocal8Bit(
+ cmSystemTools::CollapseFullPath(".").c_str()));
}
}
+ }
return app.exec();
}
+#if defined(Q_OS_MAC)
+#include "cm_sys_stat.h"
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+static bool cmOSXInstall(std::string const& dir, std::string const& tool)
+{
+ if (tool.empty()) {
+ return true;
+ }
+ std::string link = dir + cmSystemTools::GetFilenameName(tool);
+ struct stat st;
+ if (lstat(link.c_str(), &st) == 0 && S_ISLNK(st.st_mode)) {
+ char buf[4096];
+ ssize_t s = readlink(link.c_str(), buf, sizeof(buf) - 1);
+ if (s >= 0 && std::string(buf, s) == tool) {
+ std::cerr << "Exists: '" << link << "' -> '" << tool << "'\n";
+ return true;
+ }
+ }
+ cmSystemTools::MakeDirectory(dir);
+ 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;
+ }
+}
+static int cmOSXInstall(std::string dir)
+{
+ if (!cmHasLiteralSuffix(dir, "/")) {
+ dir += "/";
+ }
+ return (cmOSXInstall(dir, cmSystemTools::GetCMakeCommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCTestCommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCPackCommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCMakeGUICommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCMakeCursesCommand()))
+ ? 0
+ : 1;
+}
+
+// Locate the PlugIns directory and add it to the QApplication library paths.
+// We need to resolve all symlinks so we have a known relative path between
+// MacOS/CMake and the PlugIns directory.
+//
+// Note we are using cmSystemTools since Qt can't provide the path to the
+// executable before the QApplication is created, and that is when plugin
+// searching occurs.
+static void cmAddPluginPath()
+{
+ std::string const& path = cmSystemTools::GetCMakeGUICommand();
+ if (path.empty()) {
+ return;
+ }
+ std::string const& realPath = cmSystemTools::GetRealPath(path);
+ QFileInfo appPath(QString::fromLocal8Bit(realPath.c_str()));
+ QDir pluginDir = appPath.dir();
+ bool const foundPluginDir = pluginDir.cd("../PlugIns");
+ if (foundPluginDir) {
+ QApplication::addLibraryPath(pluginDir.path());
+ }
+}
+
+#endif
diff --git a/Source/QtDialog/CMakeSetup64.png b/Source/QtDialog/CMakeSetup64.png
new file mode 100644
index 000000000..43a8cc6af
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup64.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 4d62f7263..57f8e107e 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -1,43 +1,38 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "CMakeSetupDialog.h"
-#include <QFileDialog>
-#include <QProgressBar>
-#include <QMessageBox>
-#include <QStatusBar>
-#include <QToolButton>
-#include <QDialogButtonBox>
+
#include <QCloseEvent>
#include <QCoreApplication>
-#include <QSettings>
+#include <QDesktopServices>
+#include <QDialogButtonBox>
+#include <QDragEnterEvent>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QKeySequence>
#include <QMenu>
#include <QMenuBar>
-#include <QDragEnterEvent>
+#include <QMessageBox>
#include <QMimeData>
-#include <QUrl>
+#include <QProgressBar>
+#include <QSettings>
#include <QShortcut>
-#include <QKeySequence>
-#include <QMacInstallDialog.h>
-#include <QInputDialog>
+#include <QStatusBar>
+#include <QToolButton>
+#include <QUrl>
-#include "QCMake.h"
-#include "QCMakeCacheView.h"
#include "AddCacheEntry.h"
#include "FirstConfigure.h"
+#include "QCMake.h"
+#include "QCMakeCacheView.h"
+#include "RegexExplorer.h"
+#include "WarningMessagesDialog.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
QCMakeThread::QCMakeThread(QObject* p)
- : QThread(p), CMakeInstance(NULL)
+ : QThread(p)
+ , CMakeInstance(CM_NULLPTR)
{
}
@@ -53,11 +48,14 @@ void QCMakeThread::run()
emit this->cmakeInitialized();
this->exec();
delete this->CMakeInstance;
- this->CMakeInstance = NULL;
+ this->CMakeInstance = CM_NULLPTR;
}
CMakeSetupDialog::CMakeSetupDialog()
- : ExitAfterGenerate(true), CacheModified(false), ConfigureNeeded(true), CurrentState(Interrupting)
+ : ExitAfterGenerate(true)
+ , CacheModified(false)
+ , ConfigureNeeded(true)
+ , CurrentState(Interrupting)
{
QString title = QString(tr("CMake %1"));
title = title.arg(cmVersion::GetCMakeVersion());
@@ -66,12 +64,14 @@ CMakeSetupDialog::CMakeSetupDialog()
// create the GUI
QSettings settings;
settings.beginGroup("Settings/StartPath");
- int h = settings.value("Height", 500).toInt();
- int w = settings.value("Width", 700).toInt();
- this->resize(w, h);
+ restoreGeometry(settings.value("geometry").toByteArray());
+ restoreState(settings.value("windowState").toByteArray());
- this->AddVariableCompletions = settings.value("AddVariableCompletionEntries",
- QStringList("CMAKE_INSTALL_PREFIX")).toStringList();
+ this->AddVariableNames =
+ settings.value("AddVariableNames", QStringList("CMAKE_INSTALL_PREFIX"))
+ .toStringList();
+ this->AddVariableTypes =
+ settings.value("AddVariableTypes", QStringList("PATH")).toStringList();
QWidget* cont = new QWidget(this);
this->setupUi(cont);
@@ -91,58 +91,57 @@ CMakeSetupDialog::CMakeSetupDialog()
bool advancedView = settings.value("AdvancedView", false).toBool();
this->setAdvancedView(advancedView);
- this->advancedCheck->setCheckState(advancedView?Qt::Checked : Qt::Unchecked);
+ this->advancedCheck->setCheckState(advancedView ? Qt::Checked
+ : Qt::Unchecked);
QMenu* FileMenu = this->menuBar()->addMenu(tr("&File"));
this->ReloadCacheAction = FileMenu->addAction(tr("&Reload Cache"));
- QObject::connect(this->ReloadCacheAction, SIGNAL(triggered(bool)),
- this, SLOT(doReloadCache()));
+ QObject::connect(this->ReloadCacheAction, SIGNAL(triggered(bool)), this,
+ SLOT(doReloadCache()));
this->DeleteCacheAction = FileMenu->addAction(tr("&Delete Cache"));
- QObject::connect(this->DeleteCacheAction, SIGNAL(triggered(bool)),
- this, SLOT(doDeleteCache()));
+ QObject::connect(this->DeleteCacheAction, SIGNAL(triggered(bool)), this,
+ SLOT(doDeleteCache()));
this->ExitAction = FileMenu->addAction(tr("E&xit"));
this->ExitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
- QObject::connect(this->ExitAction, SIGNAL(triggered(bool)),
- this, SLOT(close()));
+ QObject::connect(this->ExitAction, SIGNAL(triggered(bool)), this,
+ SLOT(close()));
QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools"));
this->ConfigureAction = ToolsMenu->addAction(tr("&Configure"));
// prevent merging with Preferences menu item on Mac OS X
this->ConfigureAction->setMenuRole(QAction::NoRole);
- QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)),
- this, SLOT(doConfigure()));
+ QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)), this,
+ SLOT(doConfigure()));
this->GenerateAction = ToolsMenu->addAction(tr("&Generate"));
- QObject::connect(this->GenerateAction, SIGNAL(triggered(bool)),
- this, SLOT(doGenerate()));
+ QObject::connect(this->GenerateAction, SIGNAL(triggered(bool)), this,
+ SLOT(doGenerate()));
QAction* showChangesAction = ToolsMenu->addAction(tr("&Show My Changes"));
- QObject::connect(showChangesAction, SIGNAL(triggered(bool)),
- this, SLOT(showUserChanges()));
-#if defined(Q_WS_MAC)
- this->InstallForCommandLineAction
- = ToolsMenu->addAction(tr("&Install For Command Line Use"));
+ QObject::connect(showChangesAction, SIGNAL(triggered(bool)), this,
+ SLOT(showUserChanges()));
+#if defined(Q_WS_MAC) || defined(Q_OS_MAC)
+ this->InstallForCommandLineAction =
+ ToolsMenu->addAction(tr("&How to Install For Command Line Use"));
QObject::connect(this->InstallForCommandLineAction, SIGNAL(triggered(bool)),
this, SLOT(doInstallForCommandLine()));
#endif
ToolsMenu->addSeparator();
- ToolsMenu->addAction(tr("&Find in Output..."),
- this, SLOT(doOutputFindDialog()),
- QKeySequence::Find);
- ToolsMenu->addAction(tr("Find Next"),
- this, SLOT(doOutputFindNext()),
+ ToolsMenu->addAction(tr("Regular Expression Explorer..."), this,
+ SLOT(doRegexExplorerDialog()));
+ ToolsMenu->addSeparator();
+ ToolsMenu->addAction(tr("&Find in Output..."), this,
+ SLOT(doOutputFindDialog()), QKeySequence::Find);
+ ToolsMenu->addAction(tr("Find Next"), this, SLOT(doOutputFindNext()),
QKeySequence::FindNext);
- ToolsMenu->addAction(tr("Find Previous"),
- this, SLOT(doOutputFindPrev()),
+ ToolsMenu->addAction(tr("Find Previous"), this, SLOT(doOutputFindPrev()),
QKeySequence::FindPrevious);
- ToolsMenu->addAction(tr("Goto Next Error"),
- this, SLOT(doOutputErrorNext()),
- QKeySequence(Qt::Key_F8)); // in Visual Studio
- new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Period),
- this, SLOT(doOutputErrorNext())); // in Eclipse
+ ToolsMenu->addAction(tr("Goto Next Error"), this, SLOT(doOutputErrorNext()),
+ QKeySequence(Qt::Key_F8)); // in Visual Studio
+ new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Period), this,
+ SLOT(doOutputErrorNext())); // in Eclipse
QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options"));
- this->SuppressDevWarningsAction =
- OptionsMenu->addAction(tr("&Suppress dev Warnings (-Wno-dev)"));
- this->SuppressDevWarningsAction->setCheckable(true);
+ OptionsMenu->addAction(tr("Warning Messages..."), this,
+ SLOT(doWarningMessagesDialog()));
this->WarnUninitializedAction =
OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
this->WarnUninitializedAction->setCheckable(true);
@@ -152,24 +151,24 @@ CMakeSetupDialog::CMakeSetupDialog()
QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
debugAction->setCheckable(true);
- QObject::connect(debugAction, SIGNAL(toggled(bool)),
- this, SLOT(setDebugOutput(bool)));
+ QObject::connect(debugAction, SIGNAL(toggled(bool)), this,
+ SLOT(setDebugOutput(bool)));
OptionsMenu->addSeparator();
- QAction* expandAction = OptionsMenu->addAction(tr("&Expand Grouped Entries"));
- QObject::connect(expandAction, SIGNAL(triggered(bool)),
- this->CacheValues, SLOT(expandAll()));
- QAction* collapseAction = OptionsMenu->addAction(tr("&Collapse Grouped Entries"));
- QObject::connect(collapseAction, SIGNAL(triggered(bool)),
- this->CacheValues, SLOT(collapseAll()));
+ QAction* expandAction =
+ OptionsMenu->addAction(tr("&Expand Grouped Entries"));
+ QObject::connect(expandAction, SIGNAL(triggered(bool)), this->CacheValues,
+ SLOT(expandAll()));
+ QAction* collapseAction =
+ OptionsMenu->addAction(tr("&Collapse Grouped Entries"));
+ QObject::connect(collapseAction, SIGNAL(triggered(bool)), this->CacheValues,
+ SLOT(collapseAll()));
QMenu* HelpMenu = this->menuBar()->addMenu(tr("&Help"));
QAction* a = HelpMenu->addAction(tr("About"));
- QObject::connect(a, SIGNAL(triggered(bool)),
- this, SLOT(doAbout()));
+ QObject::connect(a, SIGNAL(triggered(bool)), this, SLOT(doAbout()));
a = HelpMenu->addAction(tr("Help"));
- QObject::connect(a, SIGNAL(triggered(bool)),
- this, SLOT(doHelp()));
+ QObject::connect(a, SIGNAL(triggered(bool)), this, SLOT(doHelp()));
this->setAcceptDrops(true);
@@ -187,12 +186,12 @@ CMakeSetupDialog::CMakeSetupDialog()
this->Output->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)),
- this, SLOT(doOutputContextMenu(const QPoint &)));
+ this, SLOT(doOutputContextMenu(const QPoint&)));
// start the cmake worker thread
this->CMakeThread = new QCMakeThread(this);
- QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()),
- this, SLOT(initialize()), Qt::QueuedConnection);
+ QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()), this,
+ SLOT(initialize()), Qt::QueuedConnection);
this->CMakeThread->start();
this->enterState(ReadyConfigure);
@@ -205,20 +204,22 @@ void CMakeSetupDialog::initialize()
{
// now the cmake worker thread is running, lets make our connections to it
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(propertiesChanged(const QCMakePropertyList&)),
- this->CacheValues->cacheModel(),
- SLOT(setProperties(const QCMakePropertyList&)));
+ SIGNAL(propertiesChanged(const QCMakePropertyList&)),
+ this->CacheValues->cacheModel(),
+ SLOT(setProperties(const QCMakePropertyList&)));
- QObject::connect(this->ConfigureButton, SIGNAL(clicked(bool)),
- this, SLOT(doConfigure()));
+ QObject::connect(this->ConfigureButton, SIGNAL(clicked(bool)), this,
+ SLOT(doConfigure()));
- QObject::connect(this->CMakeThread->cmakeInstance(), SIGNAL(configureDone(int)),
- this, SLOT(exitLoop(int)));
- QObject::connect(this->CMakeThread->cmakeInstance(), SIGNAL(generateDone(int)),
- this, SLOT(exitLoop(int)));
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(configureDone(int)), this, SLOT(exitLoop(int)));
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(generateDone(int)), this, SLOT(exitLoop(int)));
- QObject::connect(this->GenerateButton, SIGNAL(clicked(bool)),
- this, SLOT(doGenerate()));
+ QObject::connect(this->GenerateButton, SIGNAL(clicked(bool)), this,
+ SLOT(doGenerate()));
+ QObject::connect(this->OpenProjectButton, SIGNAL(clicked(bool)), this,
+ SLOT(doOpenProject()));
QObject::connect(this->BrowseSourceDirectoryButton, SIGNAL(clicked(bool)),
this, SLOT(doSourceBrowse()));
@@ -227,54 +228,50 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->BinaryDirectory, SIGNAL(editTextChanged(QString)),
this, SLOT(onBinaryDirectoryChanged(QString)));
- QObject::connect(this->SourceDirectory, SIGNAL(textChanged(QString)),
- this, SLOT(onSourceDirectoryChanged(QString)));
+ QObject::connect(this->SourceDirectory, SIGNAL(textChanged(QString)), this,
+ SLOT(onSourceDirectoryChanged(QString)));
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(sourceDirChanged(QString)),
- this, SLOT(updateSourceDirectory(QString)));
+ SIGNAL(sourceDirChanged(QString)), this,
+ SLOT(updateSourceDirectory(QString)));
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(binaryDirChanged(QString)),
- this, SLOT(updateBinaryDirectory(QString)));
+ SIGNAL(binaryDirChanged(QString)), this,
+ SLOT(updateBinaryDirectory(QString)));
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(progressChanged(QString, float)),
- this, SLOT(showProgress(QString,float)));
+ SIGNAL(progressChanged(QString, float)), this,
+ SLOT(showProgress(QString, float)));
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(errorMessage(QString)),
- this, SLOT(error(QString)));
+ SIGNAL(errorMessage(QString)), this, SLOT(error(QString)));
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(outputMessage(QString)),
- this, SLOT(message(QString)));
+ SIGNAL(outputMessage(QString)), this,
+ SLOT(message(QString)));
- QObject::connect(this->groupedCheck, SIGNAL(toggled(bool)),
- this, SLOT(setGroupedView(bool)));
- QObject::connect(this->advancedCheck, SIGNAL(toggled(bool)),
- this, SLOT(setAdvancedView(bool)));
- QObject::connect(this->Search, SIGNAL(textChanged(QString)),
- this, SLOT(setSearchFilter(QString)));
+ QObject::connect(this->groupedCheck, SIGNAL(toggled(bool)), this,
+ SLOT(setGroupedView(bool)));
+ QObject::connect(this->advancedCheck, SIGNAL(toggled(bool)), this,
+ SLOT(setAdvancedView(bool)));
+ QObject::connect(this->Search, SIGNAL(textChanged(QString)), this,
+ SLOT(setSearchFilter(QString)));
QObject::connect(this->CMakeThread->cmakeInstance(),
- SIGNAL(generatorChanged(QString)),
- this, SLOT(updateGeneratorLabel(QString)));
+ SIGNAL(generatorChanged(QString)), this,
+ SLOT(updateGeneratorLabel(QString)));
this->updateGeneratorLabel(QString());
QObject::connect(this->CacheValues->cacheModel(),
- SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(setCacheModified()));
+ SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(setCacheModified()));
QObject::connect(this->CacheValues->selectionModel(),
- SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
this, SLOT(selectionChanged()));
- QObject::connect(this->RemoveEntry, SIGNAL(clicked(bool)),
- this, SLOT(removeSelectedCacheEntries()));
- QObject::connect(this->AddEntry, SIGNAL(clicked(bool)),
- this, SLOT(addCacheEntry()));
-
- QObject::connect(this->SuppressDevWarningsAction, SIGNAL(triggered(bool)),
- this->CMakeThread->cmakeInstance(), SLOT(setSuppressDevWarnings(bool)));
+ QObject::connect(this->RemoveEntry, SIGNAL(clicked(bool)), this,
+ SLOT(removeSelectedCacheEntries()));
+ QObject::connect(this->AddEntry, SIGNAL(clicked(bool)), this,
+ SLOT(addCacheEntry()));
QObject::connect(this->WarnUninitializedAction, SIGNAL(triggered(bool)),
this->CMakeThread->cmakeInstance(),
@@ -283,24 +280,21 @@ void CMakeSetupDialog::initialize()
this->CMakeThread->cmakeInstance(),
SLOT(setWarnUnusedMode(bool)));
- if(!this->SourceDirectory->text().isEmpty() ||
- !this->BinaryDirectory->lineEdit()->text().isEmpty())
- {
+ if (!this->SourceDirectory->text().isEmpty() ||
+ !this->BinaryDirectory->lineEdit()->text().isEmpty()) {
this->onSourceDirectoryChanged(this->SourceDirectory->text());
this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
- }
- else
- {
+ } else {
this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
- }
+ }
}
CMakeSetupDialog::~CMakeSetupDialog()
{
QSettings settings;
settings.beginGroup("Settings/StartPath");
- settings.setValue("Height", this->height());
- settings.setValue("Width", this->width());
+ settings.setValue("windowState", QVariant(saveState()));
+ settings.setValue("geometry", QVariant(saveGeometry()));
settings.setValue("SplitterSizes", this->Splitter->saveState());
// wait for thread to stop
@@ -313,38 +307,34 @@ bool CMakeSetupDialog::prepareConfigure()
// make sure build directory exists
QString bindir = this->CMakeThread->cmakeInstance()->binaryDirectory();
QDir dir(bindir);
- if(!dir.exists())
- {
+ if (!dir.exists()) {
QString msg = tr("Build directory does not exist, "
- "should I create it?\n\n"
- "Directory: ");
+ "should I create it?\n\n"
+ "Directory: ");
msg += bindir;
QString title = tr("Create Directory");
QMessageBox::StandardButton btn;
btn = QMessageBox::information(this, title, msg,
QMessageBox::Yes | QMessageBox::No);
- if(btn == QMessageBox::No)
- {
+ if (btn == QMessageBox::No) {
return false;
- }
- if(!dir.mkpath("."))
- {
- QMessageBox::information(this, tr("Create Directory Failed"),
+ }
+ if (!dir.mkpath(".")) {
+ QMessageBox::information(
+ this, tr("Create Directory Failed"),
QString(tr("Failed to create directory %1")).arg(dir.path()),
QMessageBox::Ok);
return false;
- }
}
+ }
// if no generator, prompt for it and other setup stuff
- if(this->CMakeThread->cmakeInstance()->generator().isEmpty())
- {
- if(!this->setupFirstConfigure())
- {
+ if (this->CMakeThread->cmakeInstance()->generator().isEmpty()) {
+ if (!this->setupFirstConfigure()) {
return false;
- }
}
+ }
// remember path
this->addBinaryPath(dir.absolutePath());
@@ -359,36 +349,30 @@ void CMakeSetupDialog::exitLoop(int err)
void CMakeSetupDialog::doConfigure()
{
- if(this->CurrentState == Configuring)
- {
+ if (this->CurrentState == Configuring) {
// stop configure
doInterrupt();
return;
- }
+ }
- if(!prepareConfigure())
- {
+ if (!prepareConfigure()) {
return;
- }
+ }
this->enterState(Configuring);
bool ret = doConfigureInternal();
- if(ret)
- {
+ if (ret) {
this->ConfigureNeeded = false;
- }
+ }
- if(ret && !this->CacheValues->cacheModel()->newPropertyCount())
- {
+ if (ret && !this->CacheValues->cacheModel()->newPropertyCount()) {
this->enterState(ReadyGenerate);
- }
- else
- {
+ } else {
this->enterState(ReadyConfigure);
this->CacheValues->scrollToTop();
- }
+ }
this->ProgressBar->reset();
}
@@ -397,84 +381,106 @@ bool CMakeSetupDialog::doConfigureInternal()
this->Output->clear();
this->CacheValues->selectionModel()->clear();
- QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "setProperties", Qt::QueuedConnection,
- Q_ARG(QCMakePropertyList,
- this->CacheValues->cacheModel()->properties()));
- QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "configure", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(
+ this->CMakeThread->cmakeInstance(), "setProperties", Qt::QueuedConnection,
+ Q_ARG(QCMakePropertyList, this->CacheValues->cacheModel()->properties()));
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "configure",
+ Qt::QueuedConnection);
int err = this->LocalLoop.exec();
- if(err != 0)
- {
- QMessageBox::critical(this, tr("Error"),
+ if (err != 0) {
+ QMessageBox::critical(
+ this, tr("Error"),
tr("Error in configuration process, project files may be invalid"),
QMessageBox::Ok);
- }
+ }
return 0 == err;
}
void CMakeSetupDialog::doInstallForCommandLine()
{
- QMacInstallDialog setupdialog(0);
- setupdialog.exec();
+ QString title = tr("How to Install For Command Line Use");
+ QString msg = tr("One may add CMake to the PATH:\n"
+ "\n"
+ " PATH=\"%1\":\"$PATH\"\n"
+ "\n"
+ "Or, to install symlinks to '/usr/local/bin', run:\n"
+ "\n"
+ " sudo \"%2\" --install\n"
+ "\n"
+ "Or, to install symlinks to another directory, run:\n"
+ "\n"
+ " sudo \"%3\" --install=/path/to/bin\n");
+ msg = msg.arg(
+ cmSystemTools::GetFilenamePath(cmSystemTools::GetCMakeCommand()).c_str());
+ msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str());
+ msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str());
+
+ QDialog dialog;
+ dialog.setWindowTitle(title);
+ QVBoxLayout* l = new QVBoxLayout(&dialog);
+ QLabel* lab = new QLabel(&dialog);
+ l->addWidget(lab);
+ lab->setText(msg);
+ lab->setWordWrap(false);
+ lab->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
+ QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
+ l->addWidget(btns);
+ dialog.exec();
}
bool CMakeSetupDialog::doGenerateInternal()
{
- QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "generate", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "generate",
+ Qt::QueuedConnection);
int err = this->LocalLoop.exec();
- if(err != 0)
- {
- QMessageBox::critical(this, tr("Error"),
+ if (err != 0) {
+ QMessageBox::critical(
+ this, tr("Error"),
tr("Error in generation process, project files may be invalid"),
QMessageBox::Ok);
- }
+ }
return 0 == err;
}
void CMakeSetupDialog::doGenerate()
{
- if(this->CurrentState == Generating)
- {
+ if (this->CurrentState == Generating) {
// stop generate
doInterrupt();
return;
- }
+ }
// see if we need to configure
// we'll need to configure if:
// the configure step hasn't been done yet
// generate was the last step done
- if(this->ConfigureNeeded)
- {
- if(!prepareConfigure())
- {
+ if (this->ConfigureNeeded) {
+ if (!prepareConfigure()) {
return;
- }
}
+ }
this->enterState(Generating);
bool config_passed = true;
- if(this->ConfigureNeeded)
- {
+ if (this->ConfigureNeeded) {
this->CacheValues->cacheModel()->setShowNewProperties(false);
this->ProgressFactor = 0.5;
config_passed = doConfigureInternal();
this->ProgressOffset = 0.5;
- }
+ }
- if(config_passed)
- {
+ if (config_passed) {
doGenerateInternal();
- }
+ }
this->ProgressOffset = 0.0;
this->ProgressFactor = 1.0;
@@ -486,81 +492,106 @@ void CMakeSetupDialog::doGenerate()
this->ConfigureNeeded = true;
}
+QString CMakeSetupDialog::getProjectFilename()
+{
+ QStringList nameFilter;
+ nameFilter << "*.sln"
+ << "*.xcodeproj";
+ QDir directory(this->BinaryDirectory->currentText());
+ QStringList nlnFile = directory.entryList(nameFilter);
+
+ if (nlnFile.count() == 1) {
+ return this->BinaryDirectory->currentText() + "/" + nlnFile.at(0);
+ }
+
+ return QString();
+}
+
+void CMakeSetupDialog::doOpenProject()
+{
+ QDesktopServices::openUrl(QUrl::fromLocalFile(this->getProjectFilename()));
+}
+
void CMakeSetupDialog::closeEvent(QCloseEvent* e)
{
// prompt for close if there are unsaved changes, and we're not busy
- if(this->CacheModified)
- {
+ if (this->CacheModified) {
QString msg = tr("You have changed options but not rebuilt, "
- "are you sure you want to exit?");
+ "are you sure you want to exit?");
QString title = tr("Confirm Exit");
QMessageBox::StandardButton btn;
btn = QMessageBox::critical(this, title, msg,
QMessageBox::Yes | QMessageBox::No);
- if(btn == QMessageBox::No)
- {
+ if (btn == QMessageBox::No) {
e->ignore();
- }
}
+ }
// don't close if we're busy, unless the user really wants to
- if(this->CurrentState == Configuring)
- {
- QString msg = tr("You are in the middle of a Configure.\n"
- "If you Exit now the configure information will be lost.\n"
- "Are you sure you want to Exit?");
+ if (this->CurrentState == Configuring) {
+ QString msg =
+ tr("You are in the middle of a Configure.\n"
+ "If you Exit now the configure information will be lost.\n"
+ "Are you sure you want to Exit?");
QString title = tr("Confirm Exit");
QMessageBox::StandardButton btn;
btn = QMessageBox::critical(this, title, msg,
QMessageBox::Yes | QMessageBox::No);
- if(btn == QMessageBox::No)
- {
+ if (btn == QMessageBox::No) {
e->ignore();
- }
- else
- {
+ } else {
this->doInterrupt();
- }
}
+ }
// let the generate finish
- if(this->CurrentState == Generating)
- {
+ if (this->CurrentState == Generating) {
e->ignore();
- }
+ }
}
void CMakeSetupDialog::doHelp()
{
- QString msg = tr("CMake is used to configure and generate build files for "
+ QString msg = tr(
+ "CMake is used to configure and generate build files for "
"software projects. The basic steps for configuring a project are as "
- "follows:\r\n\r\n1. Select the source directory for the project. This should "
- "contain the CMakeLists.txt files for the project.\r\n\r\n2. Select the build "
- "directory for the project. This is the directory where the project will be "
+ "follows:\r\n\r\n1. Select the source directory for the project. This "
+ "should "
+ "contain the CMakeLists.txt files for the project.\r\n\r\n2. Select the "
+ "build "
+ "directory for the project. This is the directory where the project "
+ "will be "
"built. It can be the same or a different directory than the source "
- "directory. For easy clean up, a separate build directory is recommended. "
+ "directory. For easy clean up, a separate build directory is "
+ "recommended. "
"CMake will create the directory if it does not exist.\r\n\r\n3. Once the "
"source and binary directories are selected, it is time to press the "
- "Configure button. This will cause CMake to read all of the input files and "
- "discover all the variables used by the project. The first time a variable "
- "is displayed it will be in Red. Users should inspect red variables making "
- "sure the values are correct. For some projects the Configure process can "
- "be iterative, so continue to press the Configure button until there are no "
+ "Configure button. This will cause CMake to read all of the input files "
+ "and "
+ "discover all the variables used by the project. The first time a "
+ "variable "
+ "is displayed it will be in Red. Users should inspect red variables "
+ "making "
+ "sure the values are correct. For some projects the Configure process "
+ "can "
+ "be iterative, so continue to press the Configure button until there are "
+ "no "
"longer red entries.\r\n\r\n4. Once there are no longer red entries, you "
- "should click the Generate button. This will write the build files to the build "
+ "should click the Generate button. This will write the build files to "
+ "the build "
"directory.");
QDialog dialog;
QFontMetrics met(this->font());
int msgWidth = met.width(msg);
- dialog.setMinimumSize(msgWidth/15,20);
+ dialog.setMinimumSize(msgWidth / 15, 20);
dialog.setWindowTitle(tr("Help"));
QVBoxLayout* l = new QVBoxLayout(&dialog);
QLabel* lab = new QLabel(&dialog);
lab->setText(msg);
lab->setWordWrap(true);
- QDialogButtonBox* btns = new QDialogButtonBox(QDialogButtonBox::Ok,
- Qt::Horizontal, &dialog);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
l->addWidget(lab);
l->addWidget(btns);
@@ -575,42 +606,45 @@ void CMakeSetupDialog::doInterrupt()
void CMakeSetupDialog::doSourceBrowse()
{
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Enter Path to Source"), this->SourceDirectory->text());
- if(!dir.isEmpty())
- {
+ QString dir = QFileDialog::getExistingDirectory(
+ this, tr("Enter Path to Source"), this->SourceDirectory->text(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ if (!dir.isEmpty()) {
this->setSourceDirectory(dir);
- }
+ }
}
void CMakeSetupDialog::updateSourceDirectory(const QString& dir)
{
- if(this->SourceDirectory->text() != dir)
- {
+ if (this->SourceDirectory->text() != dir) {
this->SourceDirectory->blockSignals(true);
this->SourceDirectory->setText(dir);
this->SourceDirectory->blockSignals(false);
- }
+ }
}
void CMakeSetupDialog::updateBinaryDirectory(const QString& dir)
{
- if(this->BinaryDirectory->currentText() != dir)
- {
+ if (this->BinaryDirectory->currentText() != dir) {
this->BinaryDirectory->blockSignals(true);
this->BinaryDirectory->setEditText(dir);
this->BinaryDirectory->blockSignals(false);
- }
+ }
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ } else {
+ this->OpenProjectButton->setEnabled(false);
+ }
}
void CMakeSetupDialog::doBinaryBrowse()
{
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Enter Path to Build"), this->BinaryDirectory->currentText());
- if(!dir.isEmpty() && dir != this->BinaryDirectory->currentText())
- {
+ QString dir = QFileDialog::getExistingDirectory(
+ this, tr("Enter Path to Build"), this->BinaryDirectory->currentText(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ if (!dir.isEmpty() && dir != this->BinaryDirectory->currentText()) {
this->setBinaryDirectory(dir);
- }
+ }
}
void CMakeSetupDialog::setBinaryDirectory(const QString& dir)
@@ -622,7 +656,8 @@ void CMakeSetupDialog::onSourceDirectoryChanged(const QString& dir)
{
this->Output->clear();
QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "setSourceDirectory", Qt::QueuedConnection, Q_ARG(QString, dir));
+ "setSourceDirectory", Qt::QueuedConnection,
+ Q_ARG(QString, dir));
}
void CMakeSetupDialog::onBinaryDirectoryChanged(const QString& dir)
@@ -634,10 +669,12 @@ void CMakeSetupDialog::onBinaryDirectoryChanged(const QString& dir)
this->CacheModified = false;
this->CacheValues->cacheModel()->clear();
- qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())->clearChanges();
+ qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())
+ ->clearChanges();
this->Output->clear();
QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "setBinaryDirectory", Qt::QueuedConnection, Q_ARG(QString, dir));
+ "setBinaryDirectory", Qt::QueuedConnection,
+ Q_ARG(QString, dir));
}
void CMakeSetupDialog::setSourceDirectory(const QString& dir)
@@ -654,13 +691,14 @@ void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent)
void CMakeSetupDialog::error(const QString& msg)
{
this->Output->setCurrentCharFormat(this->ErrorFormat);
- //QTextEdit will terminate the msg with a ParagraphSeparator, but it also replaces
- //all newlines with ParagraphSeparators. By replacing the newlines by ourself, one
- //error msg will be one paragraph.
+ // QTextEdit will terminate the msg with a ParagraphSeparator, but it also
+ // replaces
+ // all newlines with ParagraphSeparators. By replacing the newlines by
+ // ourself, one
+ // error msg will be one paragraph.
QString paragraph(msg);
paragraph.replace(QLatin1Char('\n'), QChar::LineSeparator);
this->Output->append(paragraph);
-
}
void CMakeSetupDialog::message(const QString& msg)
@@ -682,7 +720,7 @@ void CMakeSetupDialog::setEnabledState(bool enabled)
this->ExitAction->setEnabled(enabled);
this->ConfigureAction->setEnabled(enabled);
this->AddEntry->setEnabled(enabled);
- this->RemoveEntry->setEnabled(false); // let selection re-enable it
+ this->RemoveEntry->setEnabled(false); // let selection re-enable it
}
bool CMakeSetupDialog::setupFirstConfigure()
@@ -692,57 +730,54 @@ bool CMakeSetupDialog::setupFirstConfigure()
// initialize dialog and restore saved settings
// add generators
- dialog.setGenerators(this->CMakeThread->cmakeInstance()->availableGenerators());
+ dialog.setGenerators(
+ this->CMakeThread->cmakeInstance()->availableGenerators());
// restore from settings
dialog.loadFromSettings();
- if(dialog.exec() == QDialog::Accepted)
- {
+ if (dialog.exec() == QDialog::Accepted) {
dialog.saveToSettings();
this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator());
+ this->CMakeThread->cmakeInstance()->setToolset(dialog.getToolset());
QCMakeCacheModel* m = this->CacheValues->cacheModel();
- if(dialog.compilerSetup())
- {
+ if (dialog.compilerSetup()) {
QString fortranCompiler = dialog.getFortranCompiler();
- if(!fortranCompiler.isEmpty())
- {
+ if (!fortranCompiler.isEmpty()) {
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
"Fortran compiler.", fortranCompiler, false);
- }
+ }
QString cxxCompiler = dialog.getCXXCompiler();
- if(!cxxCompiler.isEmpty())
- {
+ if (!cxxCompiler.isEmpty()) {
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
"CXX compiler.", cxxCompiler, false);
- }
+ }
QString cCompiler = dialog.getCCompiler();
- if(!cCompiler.isEmpty())
- {
+ if (!cCompiler.isEmpty()) {
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
"C compiler.", cCompiler, false);
- }
}
- else if(dialog.crossCompilerSetup())
- {
+ } else if (dialog.crossCompilerSetup()) {
QString fortranCompiler = dialog.getFortranCompiler();
- if(!fortranCompiler.isEmpty())
- {
+ if (!fortranCompiler.isEmpty()) {
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
"Fortran compiler.", fortranCompiler, false);
- }
+ }
QString mode = dialog.getCrossIncludeMode();
- m->insertProperty(QCMakeProperty::STRING, "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE",
+ m->insertProperty(QCMakeProperty::STRING,
+ "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE",
tr("CMake Find Include Mode"), mode, false);
mode = dialog.getCrossLibraryMode();
- m->insertProperty(QCMakeProperty::STRING, "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
+ m->insertProperty(QCMakeProperty::STRING,
+ "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
tr("CMake Find Library Mode"), mode, false);
mode = dialog.getCrossProgramMode();
- m->insertProperty(QCMakeProperty::STRING, "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
+ m->insertProperty(QCMakeProperty::STRING,
+ "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
tr("CMake Find Program Mode"), mode, false);
QString rootPath = dialog.getCrossRoot();
@@ -752,21 +787,23 @@ bool CMakeSetupDialog::setupFirstConfigure()
QString systemName = dialog.getSystemName();
m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_NAME",
tr("CMake System Name"), systemName, false);
+ QString systemVersion = dialog.getSystemVersion();
+ m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_VERSION",
+ tr("CMake System Version"), systemVersion, false);
QString cxxCompiler = dialog.getCXXCompiler();
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
tr("CXX compiler."), cxxCompiler, false);
QString cCompiler = dialog.getCCompiler();
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
tr("C compiler."), cCompiler, false);
- }
- else if(dialog.crossCompilerToolChainFile())
- {
+ } else if (dialog.crossCompilerToolChainFile()) {
QString toolchainFile = dialog.getCrossCompilerToolChainFile();
m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_TOOLCHAIN_FILE",
- tr("Cross Compile ToolChain File"), toolchainFile, false);
- }
- return true;
+ tr("Cross Compile ToolChain File"), toolchainFile,
+ false);
}
+ return true;
+ }
return false;
}
@@ -774,21 +811,18 @@ bool CMakeSetupDialog::setupFirstConfigure()
void CMakeSetupDialog::updateGeneratorLabel(const QString& gen)
{
QString str = tr("Current Generator: ");
- if(gen.isEmpty())
- {
+ if (gen.isEmpty()) {
str += tr("None");
- }
- else
- {
+ } else {
str += gen;
- }
+ }
this->Generator->setText(str);
}
void CMakeSetupDialog::doReloadCache()
{
- QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "reloadCache", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "reloadCache",
+ Qt::QueuedConnection);
}
void CMakeSetupDialog::doDeleteCache()
@@ -798,22 +832,36 @@ void CMakeSetupDialog::doDeleteCache()
QMessageBox::StandardButton btn;
btn = QMessageBox::information(this, title, msg,
QMessageBox::Yes | QMessageBox::No);
- if(btn == QMessageBox::No)
- {
+ if (btn == QMessageBox::No) {
return;
- }
- QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "deleteCache", Qt::QueuedConnection);
+ }
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "deleteCache",
+ Qt::QueuedConnection);
}
void CMakeSetupDialog::doAbout()
{
- QString msg = tr("CMake %1\n"
- "Using Qt %2\n"
- "www.cmake.org");
-
+ QString msg = tr(
+ "CMake %1 (cmake.org).\n"
+ "CMake suite maintained and supported by Kitware (kitware.com/cmake).\n"
+ "Distributed under terms of the BSD 3-Clause License.\n"
+ "\n"
+ "CMake GUI maintained by csimsoft,\n"
+ "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"
+ "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
+ std::string lgpl =
+ cmSystemTools::GetCMakeRoot() + "/Licenses/LGPLv" USE_LGPL ".txt";
+ msg = msg.arg(lgpl.c_str());
+#endif
QDialog dialog;
dialog.setWindowTitle(tr("About"));
@@ -822,8 +870,8 @@ void CMakeSetupDialog::doAbout()
l->addWidget(lab);
lab->setText(msg);
lab->setWordWrap(true);
- QDialogButtonBox* btns = new QDialogButtonBox(QDialogButtonBox::Ok,
- Qt::Horizontal, &dialog);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
l->addWidget(btns);
dialog.exec();
@@ -841,10 +889,9 @@ void CMakeSetupDialog::addBinaryPath(const QString& path)
// update UI
this->BinaryDirectory->blockSignals(true);
int idx = this->BinaryDirectory->findText(cleanpath);
- if(idx != -1)
- {
+ if (idx != -1) {
this->BinaryDirectory->removeItem(idx);
- }
+ }
this->BinaryDirectory->insertItem(0, cleanpath);
this->BinaryDirectory->setCurrentIndex(0);
this->BinaryDirectory->blockSignals(false);
@@ -858,56 +905,48 @@ void CMakeSetupDialog::addBinaryPath(const QString& path)
void CMakeSetupDialog::dragEnterEvent(QDragEnterEvent* e)
{
- if(!(this->CurrentState == ReadyConfigure ||
- this->CurrentState == ReadyGenerate))
- {
+ if (!(this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
e->ignore();
return;
- }
+ }
const QMimeData* dat = e->mimeData();
QList<QUrl> urls = dat->urls();
QString file = urls.count() ? urls[0].toLocalFile() : QString();
- if(!file.isEmpty() &&
- (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive) ||
- file.endsWith("CMakeLists.txt", Qt::CaseInsensitive) ) )
- {
+ if (!file.isEmpty() &&
+ (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive) ||
+ file.endsWith("CMakeLists.txt", Qt::CaseInsensitive))) {
e->accept();
- }
- else
- {
+ } else {
e->ignore();
- }
+ }
}
void CMakeSetupDialog::dropEvent(QDropEvent* e)
{
- if(!(this->CurrentState == ReadyConfigure ||
- this->CurrentState == ReadyGenerate))
- {
+ if (!(this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
return;
- }
+ }
const QMimeData* dat = e->mimeData();
QList<QUrl> urls = dat->urls();
QString file = urls.count() ? urls[0].toLocalFile() : QString();
- if(file.endsWith("CMakeCache.txt", Qt::CaseInsensitive))
- {
+ if (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive)) {
QFileInfo info(file);
- if(this->CMakeThread->cmakeInstance()->binaryDirectory() != info.absolutePath())
- {
+ if (this->CMakeThread->cmakeInstance()->binaryDirectory() !=
+ info.absolutePath()) {
this->setBinaryDirectory(info.absolutePath());
- }
}
- else if(file.endsWith("CMakeLists.txt", Qt::CaseInsensitive))
- {
+ } else if (file.endsWith("CMakeLists.txt", Qt::CaseInsensitive)) {
QFileInfo info(file);
- if(this->CMakeThread->cmakeInstance()->binaryDirectory() != info.absolutePath())
- {
+ if (this->CMakeThread->cmakeInstance()->binaryDirectory() !=
+ info.absolutePath()) {
this->setSourceDirectory(info.absolutePath());
this->setBinaryDirectory(info.absolutePath());
- }
}
+ }
}
QStringList CMakeSetupDialog::loadBuildPaths()
@@ -916,14 +955,12 @@ QStringList CMakeSetupDialog::loadBuildPaths()
settings.beginGroup("Settings/StartPath");
QStringList buildPaths;
- for(int i=0; i<10; i++)
- {
- QString p = settings.value(QString("WhereBuild%1").arg(i)).toString();
- if(!p.isEmpty())
- {
- buildPaths.append(p);
- }
+ for (int i = 0; i < 10; i++) {
+ QString p = settings.value(QString("WhereBuild%1").arg(i)).toString();
+ if (!p.isEmpty()) {
+ buildPaths.append(p);
}
+ }
return buildPaths;
}
@@ -933,20 +970,19 @@ void CMakeSetupDialog::saveBuildPaths(const QStringList& paths)
settings.beginGroup("Settings/StartPath");
int num = paths.count();
- if(num > 10)
- {
+ if (num > 10) {
num = 10;
- }
+ }
- for(int i=0; i<num; i++)
- {
+ for (int i = 0; i < num; i++) {
settings.setValue(QString("WhereBuild%1").arg(i), paths[i]);
- }
+ }
}
void CMakeSetupDialog::setCacheModified()
{
this->CacheModified = true;
+ this->ConfigureNeeded = true;
this->enterState(ReadyConfigure);
}
@@ -954,78 +990,71 @@ void CMakeSetupDialog::removeSelectedCacheEntries()
{
QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
QList<QPersistentModelIndex> pidxs;
- foreach(QModelIndex i, idxs)
- {
+ foreach (QModelIndex const& i, idxs) {
pidxs.append(i);
- }
- foreach(QPersistentModelIndex pi, pidxs)
- {
+ }
+ foreach (QPersistentModelIndex const& pi, pidxs) {
this->CacheValues->model()->removeRow(pi.row(), pi.parent());
- }
+ }
}
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
- {
+ } else {
this->RemoveEntry->setEnabled(false);
- }
+ }
}
void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
{
- if(s == this->CurrentState)
- {
+ if (s == this->CurrentState) {
return;
- }
+ }
this->CurrentState = s;
- if(s == Interrupting)
- {
+ if (s == Interrupting) {
this->ConfigureButton->setEnabled(false);
this->GenerateButton->setEnabled(false);
- }
- else if(s == Configuring)
- {
+ this->OpenProjectButton->setEnabled(false);
+ } else if (s == Configuring) {
this->setEnabledState(false);
this->GenerateButton->setEnabled(false);
this->GenerateAction->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
this->ConfigureButton->setText(tr("&Stop"));
- }
- else if(s == Generating)
- {
+ } else if (s == Generating) {
this->CacheModified = false;
this->setEnabledState(false);
this->ConfigureButton->setEnabled(false);
this->GenerateAction->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
this->GenerateButton->setText(tr("&Stop"));
- }
- else if(s == ReadyConfigure)
- {
+ } else if (s == ReadyConfigure) {
this->setEnabledState(true);
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)
- {
+ } else if (s == ReadyGenerate) {
this->setEnabledState(true);
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"));
- }
+ }
}
void CMakeSetupDialog::addCacheEntry()
@@ -1034,40 +1063,40 @@ void CMakeSetupDialog::addCacheEntry()
dialog.resize(400, 200);
dialog.setWindowTitle(tr("Add Cache Entry"));
QVBoxLayout* l = new QVBoxLayout(&dialog);
- AddCacheEntry* w = new AddCacheEntry(&dialog, this->AddVariableCompletions);
+ AddCacheEntry* w =
+ new AddCacheEntry(&dialog, this->AddVariableNames, this->AddVariableTypes);
QDialogButtonBox* btns = new QDialogButtonBox(
- QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
- Qt::Horizontal, &dialog);
+ QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
QObject::connect(btns, SIGNAL(rejected()), &dialog, SLOT(reject()));
l->addWidget(w);
l->addStretch();
l->addWidget(btns);
- if(QDialog::Accepted == dialog.exec())
- {
+ if (QDialog::Accepted == dialog.exec()) {
QCMakeCacheModel* m = this->CacheValues->cacheModel();
- m->insertProperty(w->type(), w->name(), w->description(), w->value(), false);
+ m->insertProperty(w->type(), w->name(), w->description(), w->value(),
+ false);
// only add variable names to the completion which are new
- if (!this->AddVariableCompletions.contains(w->name()))
- {
- this->AddVariableCompletions << w->name();
+ if (!this->AddVariableNames.contains(w->name())) {
+ this->AddVariableNames << w->name();
+ this->AddVariableTypes << w->typeString();
// limit to at most 100 completion items
- if (this->AddVariableCompletions.size() > 100)
- {
- this->AddVariableCompletions.removeFirst();
- }
+ if (this->AddVariableNames.size() > 100) {
+ this->AddVariableNames.removeFirst();
+ this->AddVariableTypes.removeFirst();
+ }
// make sure CMAKE_INSTALL_PREFIX is always there
- if (!this->AddVariableCompletions.contains("CMAKE_INSTALL_PREFIX"))
- {
- this->AddVariableCompletions << QString("CMAKE_INSTALL_PREFIX");
- }
+ if (!this->AddVariableNames.contains("CMAKE_INSTALL_PREFIX")) {
+ this->AddVariableNames << "CMAKE_INSTALL_PREFIX";
+ this->AddVariableTypes << "PATH";
+ }
QSettings settings;
settings.beginGroup("Settings/StartPath");
- settings.setValue("AddVariableCompletionEntries",
- this->AddVariableCompletions);
- }
+ settings.setValue("AddVariableNames", this->AddVariableNames);
+ settings.setValue("AddVariableTypes", this->AddVariableTypes);
}
+ }
}
void CMakeSetupDialog::startSearch()
@@ -1079,18 +1108,19 @@ void CMakeSetupDialog::startSearch()
void CMakeSetupDialog::setDebugOutput(bool flag)
{
QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
- "setDebugOutput", Qt::QueuedConnection, Q_ARG(bool, flag));
+ "setDebugOutput", Qt::QueuedConnection,
+ Q_ARG(bool, flag));
}
void CMakeSetupDialog::setGroupedView(bool v)
{
- this->CacheValues->cacheModel()->setViewType(v ? QCMakeCacheModel::GroupView : QCMakeCacheModel::FlatView);
+ this->CacheValues->cacheModel()->setViewType(v ? QCMakeCacheModel::GroupView
+ : QCMakeCacheModel::FlatView);
this->CacheValues->setRootIsDecorated(v);
QSettings settings;
settings.beginGroup("Settings/StartPath");
settings.setValue("GroupView", v);
-
}
void CMakeSetupDialog::setAdvancedView(bool v)
@@ -1104,7 +1134,8 @@ void CMakeSetupDialog::setAdvancedView(bool v)
void CMakeSetupDialog::showUserChanges()
{
QSet<QCMakeProperty> changes =
- qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())->changes();
+ qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())
+ ->changes();
QDialog dialog(this);
dialog.setWindowTitle(tr("My Changes"));
@@ -1113,19 +1144,17 @@ void CMakeSetupDialog::showUserChanges()
QTextEdit* textedit = new QTextEdit(&dialog);
textedit->setReadOnly(true);
l->addWidget(textedit);
- QDialogButtonBox* btns = new QDialogButtonBox(QDialogButtonBox::Close,
- Qt::Horizontal, &dialog);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, &dialog);
QObject::connect(btns, SIGNAL(rejected()), &dialog, SLOT(accept()));
l->addWidget(btns);
QString command;
QString cache;
- foreach(QCMakeProperty prop, changes)
- {
+ foreach (QCMakeProperty const& prop, changes) {
QString type;
- switch(prop.Type)
- {
+ switch (prop.Type) {
case QCMakeProperty::BOOL:
type = "BOOL";
break;
@@ -1138,25 +1167,19 @@ void CMakeSetupDialog::showUserChanges()
case QCMakeProperty::STRING:
type = "STRING";
break;
- }
+ }
QString value;
- if(prop.Type == QCMakeProperty::BOOL)
- {
+ if (prop.Type == QCMakeProperty::BOOL) {
value = prop.Value.toBool() ? "1" : "0";
- }
- else
- {
+ } else {
value = prop.Value.toString();
- }
-
- QString line("%1:%2=");
- line = line.arg(prop.Key);
- line = line.arg(type);
-
- command += QString("-D%1\"%2\" ").arg(line).arg(value);
- cache += QString("%1%2\n").arg(line).arg(value);
}
+ QString const line = QString("%1:%2=").arg(prop.Key, type);
+ command += QString("-D%1\"%2\" ").arg(line, value);
+ cache += QString("%1%2\n").arg(line, value);
+ }
+
textedit->append(tr("Commandline options:"));
textedit->append(command);
textedit->append("\n");
@@ -1172,20 +1195,20 @@ void CMakeSetupDialog::setSearchFilter(const QString& str)
this->CacheValues->setSearchFilter(str);
}
-void CMakeSetupDialog::doOutputContextMenu(const QPoint &pt)
+void CMakeSetupDialog::doOutputContextMenu(const QPoint& pt)
{
- QMenu *menu = this->Output->createStandardContextMenu();
+ QMenu* menu = this->Output->createStandardContextMenu();
menu->addSeparator();
- menu->addAction(tr("Find..."),
- this, SLOT(doOutputFindDialog()), QKeySequence::Find);
- menu->addAction(tr("Find Next"),
- this, SLOT(doOutputFindNext()), QKeySequence::FindNext);
- menu->addAction(tr("Find Previous"),
- this, SLOT(doOutputFindPrev()), QKeySequence::FindPrevious);
+ menu->addAction(tr("Find..."), this, SLOT(doOutputFindDialog()),
+ QKeySequence::Find);
+ menu->addAction(tr("Find Next"), this, SLOT(doOutputFindNext()),
+ QKeySequence::FindNext);
+ menu->addAction(tr("Find Previous"), this, SLOT(doOutputFindPrev()),
+ QKeySequence::FindPrevious);
menu->addSeparator();
- menu->addAction(tr("Goto Next Error"),
- this, SLOT(doOutputErrorNext()), QKeySequence(Qt::Key_F8));
+ menu->addAction(tr("Goto Next Error"), this, SLOT(doOutputErrorNext()),
+ QKeySequence(Qt::Key_F8));
menu->exec(this->Output->mapToGlobal(pt));
delete menu;
@@ -1196,24 +1219,26 @@ void CMakeSetupDialog::doOutputFindDialog()
QStringList strings(this->FindHistory);
QString selection = this->Output->textCursor().selectedText();
- if (!selection.isEmpty() &&
- !selection.contains(QChar::ParagraphSeparator) &&
- !selection.contains(QChar::LineSeparator))
- {
+ if (!selection.isEmpty() && !selection.contains(QChar::ParagraphSeparator) &&
+ !selection.contains(QChar::LineSeparator)) {
strings.push_front(selection);
- }
+ }
bool ok;
QString search = QInputDialog::getItem(this, tr("Find in Output"),
tr("Find:"), strings, 0, true, &ok);
- if (ok && !search.isEmpty())
- {
- if (!this->FindHistory.contains(search))
- {
+ if (ok && !search.isEmpty()) {
+ if (!this->FindHistory.contains(search)) {
this->FindHistory.push_front(search);
- }
- doOutputFindNext();
}
+ doOutputFindNext();
+ }
+}
+
+void CMakeSetupDialog::doRegexExplorerDialog()
+{
+ RegexExplorer dialog(this);
+ dialog.exec();
}
void CMakeSetupDialog::doOutputFindPrev()
@@ -1223,83 +1248,80 @@ void CMakeSetupDialog::doOutputFindPrev()
void CMakeSetupDialog::doOutputFindNext(bool directionForward)
{
- if (this->FindHistory.isEmpty())
- {
- doOutputFindDialog(); //will re-call this function again
+ if (this->FindHistory.isEmpty()) {
+ doOutputFindDialog(); // will re-call this function again
return;
- }
+ }
QString search = this->FindHistory.front();
- QTextCursor cursor = this->Output->textCursor();
+ QTextCursor textCursor = this->Output->textCursor();
QTextDocument* document = this->Output->document();
QTextDocument::FindFlags flags;
- if (!directionForward)
- {
+ if (!directionForward) {
flags |= QTextDocument::FindBackward;
- }
+ }
- cursor = document->find(search, cursor, flags);
+ textCursor = document->find(search, textCursor, flags);
- if (cursor.isNull())
- {
+ if (textCursor.isNull()) {
// first search found nothing, wrap around and search again
- cursor = this->Output->textCursor();
- cursor.movePosition(directionForward ? QTextCursor::Start
- : QTextCursor::End);
- cursor = document->find(search, cursor, flags);
- }
-
- if (cursor.hasSelection())
- {
- this->Output->setTextCursor(cursor);
- }
+ textCursor = this->Output->textCursor();
+ textCursor.movePosition(directionForward ? QTextCursor::Start
+ : QTextCursor::End);
+ textCursor = document->find(search, textCursor, flags);
+ }
+
+ if (textCursor.hasSelection()) {
+ this->Output->setTextCursor(textCursor);
+ }
}
void CMakeSetupDialog::doOutputErrorNext()
{
- QTextCursor cursor = this->Output->textCursor();
+ QTextCursor textCursor = this->Output->textCursor();
bool atEnd = false;
// move cursor out of current error-block
- if (cursor.blockCharFormat() == this->ErrorFormat)
- {
- atEnd = !cursor.movePosition(QTextCursor::NextBlock);
- }
+ if (textCursor.blockCharFormat() == this->ErrorFormat) {
+ atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
+ }
// move cursor to next error-block
- while (cursor.blockCharFormat() != this->ErrorFormat && !atEnd)
- {
- atEnd = !cursor.movePosition(QTextCursor::NextBlock);
- }
+ while (textCursor.blockCharFormat() != this->ErrorFormat && !atEnd) {
+ atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
+ }
- if (atEnd)
- {
+ if (atEnd) {
// first search found nothing, wrap around and search again
- atEnd = !cursor.movePosition(QTextCursor::Start);
+ atEnd = !textCursor.movePosition(QTextCursor::Start);
// move cursor to next error-block
- while (cursor.blockCharFormat() != this->ErrorFormat && !atEnd)
- {
- atEnd = !cursor.movePosition(QTextCursor::NextBlock);
- }
+ while (textCursor.blockCharFormat() != this->ErrorFormat && !atEnd) {
+ atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
}
+ }
- if (!atEnd)
- {
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+ if (!atEnd) {
+ textCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
QTextCharFormat selectionFormat;
selectionFormat.setBackground(Qt::yellow);
- QTextEdit::ExtraSelection extraSelection = {cursor, selectionFormat};
+ QTextEdit::ExtraSelection extraSelection = { textCursor, selectionFormat };
this->Output->setExtraSelections(QList<QTextEdit::ExtraSelection>()
<< extraSelection);
// make the whole error-block visible
- this->Output->setTextCursor(cursor);
+ this->Output->setTextCursor(textCursor);
// remove the selection to see the extraSelection
- cursor.setPosition(cursor.anchor());
- this->Output->setTextCursor(cursor);
- }
+ textCursor.setPosition(textCursor.anchor());
+ this->Output->setTextCursor(textCursor);
+ }
+}
+
+void CMakeSetupDialog::doWarningMessagesDialog()
+{
+ WarningMessagesDialog dialog(this, this->CMakeThread->cmakeInstance());
+ dialog.exec();
}
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 963c7d12e..1abdb462d 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -1,23 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef CMakeSetupDialog_h
#define CMakeSetupDialog_h
#include "QCMake.h"
+
+#include "ui_CMakeSetupDialog.h"
+#include <QEventLoop>
#include <QMainWindow>
#include <QThread>
-#include <QEventLoop>
-#include "ui_CMakeSetupDialog.h"
class QCMakeThread;
class CMakeCacheModel;
@@ -40,6 +31,8 @@ protected slots:
void initialize();
void doConfigure();
void doGenerate();
+ QString getProjectFilename();
+ void doOpenProject();
void doInstallForCommandLine();
void doHelp();
void doAbout();
@@ -77,15 +70,24 @@ protected slots:
bool doConfigureInternal();
bool doGenerateInternal();
void exitLoop(int);
- void doOutputContextMenu(const QPoint &);
+ void doOutputContextMenu(const QPoint&);
void doOutputFindDialog();
void doOutputFindNext(bool directionForward = true);
void doOutputFindPrev();
void doOutputErrorNext();
+ void doRegexExplorerDialog();
+ /// display the modal warning messages dialog window
+ void doWarningMessagesDialog();
protected:
-
- enum State { Interrupting, ReadyConfigure, ReadyGenerate, Configuring, Generating };
+ enum State
+ {
+ Interrupting,
+ ReadyConfigure,
+ ReadyGenerate,
+ Configuring,
+ Generating
+ };
void enterState(State s);
void closeEvent(QCloseEvent*);
@@ -101,7 +103,6 @@ protected:
QAction* ExitAction;
QAction* ConfigureAction;
QAction* GenerateAction;
- QAction* SuppressDevWarningsAction;
QAction* WarnUninitializedAction;
QAction* WarnUnusedAction;
QAction* InstallForCommandLineAction;
@@ -110,7 +111,8 @@ protected:
QTextCharFormat ErrorFormat;
QTextCharFormat MessageFormat;
- QStringList AddVariableCompletions;
+ QStringList AddVariableNames;
+ QStringList AddVariableTypes;
QStringList FindHistory;
QEventLoop LocalLoop;
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
index 98da249d5..8d8e0cdc2 100644
--- a/Source/QtDialog/CMakeSetupDialog.ui
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -134,7 +134,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
+ <width>12</width>
<height>23</height>
</size>
</property>
@@ -238,6 +238,13 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QPushButton" name="OpenProjectButton">
+ <property name="text">
+ <string>Open &amp;Project</string>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QLabel" name="Generator">
<property name="text">
diff --git a/Source/QtDialog/Compilers.h b/Source/QtDialog/Compilers.h
index 3f7b83411..6c8c8f52a 100644
--- a/Source/QtDialog/Compilers.h
+++ b/Source/QtDialog/Compilers.h
@@ -3,19 +3,21 @@
#ifndef COMPILERS_HPP
#define COMPILERS_HPP
+#include "cmConfigure.h"
+
#include <QWidget>
+
#include <ui_Compilers.h>
class Compilers : public QWidget, public Ui::Compilers
{
Q_OBJECT
public:
- Compilers(QWidget* p=NULL) :
- QWidget(p)
+ Compilers(QWidget* p = CM_NULLPTR)
+ : QWidget(p)
{
this->setupUi(this);
}
};
#endif
-
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index 6de9f00cc..b193a2782 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -1,13 +1,13 @@
#include "FirstConfigure.h"
+
#include "Compilers.h"
-#include <QSettings>
-#include <QRadioButton>
#include <QComboBox>
+#include <QRadioButton>
+#include <QSettings>
#include <QVBoxLayout>
-
StartCompilerSetup::StartCompilerSetup(QWidget* p)
: QWizardPage(p)
{
@@ -15,12 +15,21 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p)
l->addWidget(new QLabel(tr("Specify the generator for this project")));
this->GeneratorOptions = new QComboBox(this);
l->addWidget(this->GeneratorOptions);
+
+ // Add the ability to specify toolset (-T parameter)
+ ToolsetFrame = CreateToolsetWidgets();
+ l->addWidget(ToolsetFrame);
+
l->addSpacing(6);
- this->CompilerSetupOptions[0] = new QRadioButton(tr("Use default native compilers"), this);
- this->CompilerSetupOptions[1] = new QRadioButton(tr("Specify native compilers"), this);
- this->CompilerSetupOptions[2] = new QRadioButton(tr("Specify toolchain file for cross-compiling"), this);
- this->CompilerSetupOptions[3] = new QRadioButton(tr("Specify options for cross-compiling"), this);
+ this->CompilerSetupOptions[0] =
+ new QRadioButton(tr("Use default native compilers"), this);
+ this->CompilerSetupOptions[1] =
+ new QRadioButton(tr("Specify native compilers"), this);
+ this->CompilerSetupOptions[2] =
+ new QRadioButton(tr("Specify toolchain file for cross-compiling"), this);
+ this->CompilerSetupOptions[3] =
+ new QRadioButton(tr("Specify options for cross-compiling"), this);
l->addWidget(this->CompilerSetupOptions[0]);
l->addWidget(this->CompilerSetupOptions[1]);
l->addWidget(this->CompilerSetupOptions[2]);
@@ -28,31 +37,62 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p)
this->CompilerSetupOptions[0]->setChecked(true);
- QObject::connect(this->CompilerSetupOptions[0], SIGNAL(toggled(bool)),
- this, SLOT(onSelectionChanged(bool)));
- QObject::connect(this->CompilerSetupOptions[1], SIGNAL(toggled(bool)),
- this, SLOT(onSelectionChanged(bool)));
- QObject::connect(this->CompilerSetupOptions[2], SIGNAL(toggled(bool)),
- this, SLOT(onSelectionChanged(bool)));
- QObject::connect(this->CompilerSetupOptions[3], SIGNAL(toggled(bool)),
- this, SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[0], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[1], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[2], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[3], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(GeneratorOptions,
+ SIGNAL(currentIndexChanged(QString const&)), this,
+ SLOT(onGeneratorChanged(QString const&)));
+}
+
+QFrame* StartCompilerSetup::CreateToolsetWidgets()
+{
+ QFrame* frame = new QFrame(this);
+ QVBoxLayout* l = new QVBoxLayout(frame);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ ToolsetLabel = new QLabel(tr("Optional toolset to use (argument to -T)"));
+ l->addWidget(ToolsetLabel);
+
+ Toolset = new QLineEdit(frame);
+ l->addWidget(Toolset);
+
+ return frame;
}
StartCompilerSetup::~StartCompilerSetup()
{
}
-void StartCompilerSetup::setGenerators(const QStringList& gens)
+void StartCompilerSetup::setGenerators(
+ std::vector<cmake::GeneratorInfo> const& gens)
{
this->GeneratorOptions->clear();
- this->GeneratorOptions->addItems(gens);
-};
+
+ 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()));
+
+ if (it->supportsToolset) {
+ this->GeneratorsSupportingToolset.append(
+ QString::fromLocal8Bit(it->name.c_str()));
+ }
+ }
+
+ this->GeneratorOptions->addItems(generator_list);
+}
void StartCompilerSetup::setCurrentGenerator(const QString& gen)
{
int idx = this->GeneratorOptions->findText(gen);
- if(idx != -1)
- {
+ if (idx != -1) {
this->GeneratorOptions->setCurrentIndex(idx);
}
}
@@ -62,6 +102,11 @@ QString StartCompilerSetup::getGenerator() const
return this->GeneratorOptions->currentText();
};
+QString StartCompilerSetup::getToolset() const
+{
+ return this->Toolset->text();
+};
+
bool StartCompilerSetup::defaultSetup() const
{
return this->CompilerSetupOptions[0]->isChecked();
@@ -84,18 +129,31 @@ bool StartCompilerSetup::crossCompilerSetup() const
void StartCompilerSetup::onSelectionChanged(bool on)
{
- if(on)
- selectionChanged();
+ if (on) {
+ emit selectionChanged();
+ }
+}
+
+void StartCompilerSetup::onGeneratorChanged(QString const& name)
+{
+ if (GeneratorsSupportingToolset.contains(name)) {
+ ToolsetFrame->show();
+ } else {
+ ToolsetFrame->hide();
+ }
}
int StartCompilerSetup::nextId() const
{
- if(compilerSetup())
+ if (compilerSetup()) {
return NativeSetup;
- if(crossCompilerSetup())
+ }
+ if (crossCompilerSetup()) {
return CrossSetup;
- if(crossCompilerToolChainFile())
+ }
+ if (crossCompilerToolChainFile()) {
return ToolchainSetup;
+ }
return -1;
}
@@ -142,7 +200,6 @@ void NativeCompilerSetup::setFortranCompiler(const QString& s)
this->FortranCompiler->setText(s);
}
-
CrossCompilerSetup::CrossCompilerSetup(QWidget* p)
: QWizardPage(p)
{
@@ -151,7 +208,8 @@ CrossCompilerSetup::CrossCompilerSetup(QWidget* p)
QWidget::setTabOrder(systemVersion, systemProcessor);
QWidget::setTabOrder(systemProcessor, CrossCompilers->CCompiler);
QWidget::setTabOrder(CrossCompilers->CCompiler, CrossCompilers->CXXCompiler);
- QWidget::setTabOrder(CrossCompilers->CXXCompiler, CrossCompilers->FortranCompiler);
+ QWidget::setTabOrder(CrossCompilers->CXXCompiler,
+ CrossCompilers->FortranCompiler);
QWidget::setTabOrder(CrossCompilers->FortranCompiler, crossFindRoot);
QWidget::setTabOrder(crossFindRoot, crossProgramMode);
QWidget::setTabOrder(crossProgramMode, crossLibraryMode);
@@ -216,7 +274,6 @@ void CrossCompilerSetup::setSystem(const QString& t)
this->systemName->setText(t);
}
-
QString CrossCompilerSetup::getVersion() const
{
return this->systemVersion->text();
@@ -227,7 +284,6 @@ void CrossCompilerSetup::setVersion(const QString& t)
this->systemVersion->setText(t);
}
-
QString CrossCompilerSetup::getProcessor() const
{
return this->systemProcessor->text();
@@ -301,11 +357,9 @@ void ToolchainCompilerSetup::setToolchainFile(const QString& t)
this->ToolchainFile->setText(t);
}
-
-
FirstConfigure::FirstConfigure()
{
- //this->setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
+ // this->setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
this->mStartCompilerSetupPage = new StartCompilerSetup(this);
this->setPage(Start, this->mStartCompilerSetupPage);
QObject::connect(this->mStartCompilerSetupPage, SIGNAL(selectionChanged()),
@@ -325,7 +379,8 @@ FirstConfigure::~FirstConfigure()
{
}
-void FirstConfigure::setGenerators(const QStringList& gens)
+void FirstConfigure::setGenerators(
+ std::vector<cmake::GeneratorInfo> const& gens)
{
this->mStartCompilerSetupPage->setGenerators(gens);
}
@@ -335,6 +390,11 @@ QString FirstConfigure::getGenerator() const
return this->mStartCompilerSetupPage->getGenerator();
}
+QString FirstConfigure::getToolset() const
+{
+ return this->mStartCompilerSetupPage->getToolset();
+}
+
void FirstConfigure::loadFromSettings()
{
QSettings settings;
@@ -346,24 +406,38 @@ void FirstConfigure::loadFromSettings()
// restore compiler setup
settings.beginGroup("Settings/Compiler");
- this->mNativeCompilerSetupPage->setCCompiler(settings.value("CCompiler").toString());
- this->mNativeCompilerSetupPage->setCXXCompiler(settings.value("CXXCompiler").toString());
- this->mNativeCompilerSetupPage->setFortranCompiler(settings.value("FortranCompiler").toString());
+ this->mNativeCompilerSetupPage->setCCompiler(
+ settings.value("CCompiler").toString());
+ this->mNativeCompilerSetupPage->setCXXCompiler(
+ settings.value("CXXCompiler").toString());
+ this->mNativeCompilerSetupPage->setFortranCompiler(
+ settings.value("FortranCompiler").toString());
settings.endGroup();
// restore cross compiler setup
settings.beginGroup("Settings/CrossCompiler");
- this->mCrossCompilerSetupPage->setCCompiler(settings.value("CCompiler").toString());
- this->mCrossCompilerSetupPage->setCXXCompiler(settings.value("CXXCompiler").toString());
- this->mCrossCompilerSetupPage->setFortranCompiler(settings.value("FortranCompiler").toString());
- this->mToolchainCompilerSetupPage->setToolchainFile(settings.value("ToolChainFile").toString());
- this->mCrossCompilerSetupPage->setSystem(settings.value("SystemName").toString());
- this->mCrossCompilerSetupPage->setVersion(settings.value("SystemVersion").toString());
- this->mCrossCompilerSetupPage->setProcessor(settings.value("SystemProcessor").toString());
- this->mCrossCompilerSetupPage->setFindRoot(settings.value("FindRoot").toString());
- this->mCrossCompilerSetupPage->setProgramMode(settings.value("ProgramMode", 0).toInt());
- this->mCrossCompilerSetupPage->setLibraryMode(settings.value("LibraryMode", 0).toInt());
- this->mCrossCompilerSetupPage->setIncludeMode(settings.value("IncludeMode", 0).toInt());
+ this->mCrossCompilerSetupPage->setCCompiler(
+ settings.value("CCompiler").toString());
+ this->mCrossCompilerSetupPage->setCXXCompiler(
+ settings.value("CXXCompiler").toString());
+ this->mCrossCompilerSetupPage->setFortranCompiler(
+ settings.value("FortranCompiler").toString());
+ this->mToolchainCompilerSetupPage->setToolchainFile(
+ settings.value("ToolChainFile").toString());
+ this->mCrossCompilerSetupPage->setSystem(
+ settings.value("SystemName").toString());
+ this->mCrossCompilerSetupPage->setVersion(
+ settings.value("SystemVersion").toString());
+ this->mCrossCompilerSetupPage->setProcessor(
+ settings.value("SystemProcessor").toString());
+ this->mCrossCompilerSetupPage->setFindRoot(
+ settings.value("FindRoot").toString());
+ this->mCrossCompilerSetupPage->setProgramMode(
+ settings.value("ProgramMode", 0).toInt());
+ this->mCrossCompilerSetupPage->setLibraryMode(
+ settings.value("LibraryMode", 0).toInt());
+ this->mCrossCompilerSetupPage->setIncludeMode(
+ settings.value("IncludeMode", 0).toInt());
settings.endGroup();
}
@@ -379,24 +453,35 @@ void FirstConfigure::saveToSettings()
// save compiler setup
settings.beginGroup("Settings/Compiler");
- settings.setValue("CCompiler", this->mNativeCompilerSetupPage->getCCompiler());
- settings.setValue("CXXCompiler", this->mNativeCompilerSetupPage->getCXXCompiler());
- settings.setValue("FortranCompiler", this->mNativeCompilerSetupPage->getFortranCompiler());
+ settings.setValue("CCompiler",
+ this->mNativeCompilerSetupPage->getCCompiler());
+ settings.setValue("CXXCompiler",
+ this->mNativeCompilerSetupPage->getCXXCompiler());
+ settings.setValue("FortranCompiler",
+ this->mNativeCompilerSetupPage->getFortranCompiler());
settings.endGroup();
// save cross compiler setup
settings.beginGroup("Settings/CrossCompiler");
- settings.setValue("CCompiler", this->mCrossCompilerSetupPage->getCCompiler());
- settings.setValue("CXXCompiler", this->mCrossCompilerSetupPage->getCXXCompiler());
- settings.setValue("FortranCompiler", this->mCrossCompilerSetupPage->getFortranCompiler());
+ settings.setValue("CCompiler",
+ this->mCrossCompilerSetupPage->getCCompiler());
+ settings.setValue("CXXCompiler",
+ this->mCrossCompilerSetupPage->getCXXCompiler());
+ settings.setValue("FortranCompiler",
+ this->mCrossCompilerSetupPage->getFortranCompiler());
settings.setValue("ToolChainFile", this->getCrossCompilerToolChainFile());
settings.setValue("SystemName", this->mCrossCompilerSetupPage->getSystem());
- settings.setValue("SystemVersion", this->mCrossCompilerSetupPage->getVersion());
- settings.setValue("SystemProcessor", this->mCrossCompilerSetupPage->getProcessor());
+ settings.setValue("SystemVersion",
+ this->mCrossCompilerSetupPage->getVersion());
+ settings.setValue("SystemProcessor",
+ this->mCrossCompilerSetupPage->getProcessor());
settings.setValue("FindRoot", this->mCrossCompilerSetupPage->getFindRoot());
- settings.setValue("ProgramMode", this->mCrossCompilerSetupPage->getProgramMode());
- settings.setValue("LibraryMode", this->mCrossCompilerSetupPage->getLibraryMode());
- settings.setValue("IncludeMode", this->mCrossCompilerSetupPage->getIncludeMode());
+ settings.setValue("ProgramMode",
+ this->mCrossCompilerSetupPage->getProgramMode());
+ settings.setValue("LibraryMode",
+ this->mCrossCompilerSetupPage->getLibraryMode());
+ settings.setValue("IncludeMode",
+ this->mCrossCompilerSetupPage->getIncludeMode());
settings.endGroup();
}
@@ -432,44 +517,37 @@ QString FirstConfigure::getSystemName() const
QString FirstConfigure::getCCompiler() const
{
- if(this->compilerSetup())
- {
+ if (this->compilerSetup()) {
return this->mNativeCompilerSetupPage->getCCompiler();
- }
- else if(this->crossCompilerSetup())
- {
+ }
+ if (this->crossCompilerSetup()) {
return this->mCrossCompilerSetupPage->getCCompiler();
- }
+ }
return QString();
}
QString FirstConfigure::getCXXCompiler() const
{
- if(this->compilerSetup())
- {
+ if (this->compilerSetup()) {
return this->mNativeCompilerSetupPage->getCXXCompiler();
- }
- else if(this->crossCompilerSetup())
- {
+ }
+ if (this->crossCompilerSetup()) {
return this->mCrossCompilerSetupPage->getCXXCompiler();
- }
+ }
return QString();
}
QString FirstConfigure::getFortranCompiler() const
{
- if(this->compilerSetup())
- {
+ if (this->compilerSetup()) {
return this->mNativeCompilerSetupPage->getFortranCompiler();
- }
- else if(this->crossCompilerSetup())
- {
+ }
+ if (this->crossCompilerSetup()) {
return this->mCrossCompilerSetupPage->getFortranCompiler();
- }
+ }
return QString();
}
-
QString FirstConfigure::getSystemVersion() const
{
return this->mCrossCompilerSetupPage->getVersion();
@@ -485,12 +563,7 @@ QString FirstConfigure::getCrossRoot() const
return this->mCrossCompilerSetupPage->getFindRoot();
}
-const QString CrossModes[] =
-{
- "BOTH",
- "ONLY",
- "NEVER"
-};
+const QString CrossModes[] = { "BOTH", "ONLY", "NEVER" };
QString FirstConfigure::getCrossProgramMode() const
{
@@ -506,4 +579,3 @@ QString FirstConfigure::getCrossIncludeMode() const
{
return CrossModes[this->mCrossCompilerSetupPage->getIncludeMode()];
}
-
diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h
index be390b0fd..c467ddb19 100644
--- a/Source/QtDialog/FirstConfigure.h
+++ b/Source/QtDialog/FirstConfigure.h
@@ -4,6 +4,9 @@
#include <QWizard>
#include <QWizardPage>
+
+#include "cmake.h"
+
#include "ui_Compilers.h"
#include "ui_CrossCompiler.h"
@@ -20,116 +23,126 @@ enum FirstConfigurePages
Done
};
-//! the first page that gives basic options for what compilers setup to choose from
+//! the first page that gives basic options for what compilers setup to choose
+//! from
class StartCompilerSetup : public QWizardPage
{
Q_OBJECT
- public:
- StartCompilerSetup(QWidget* p);
- ~StartCompilerSetup();
- void setGenerators(const QStringList& gens);
- void setCurrentGenerator(const QString& gen);
- QString getGenerator() const;
+public:
+ StartCompilerSetup(QWidget* p);
+ ~StartCompilerSetup();
+ void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
+ void setCurrentGenerator(const QString& gen);
+ QString getGenerator() const;
+ QString getToolset() const;
- bool defaultSetup() const;
- bool compilerSetup() const;
- bool crossCompilerSetup() const;
- bool crossCompilerToolChainFile() const;
+ bool defaultSetup() const;
+ bool compilerSetup() const;
+ bool crossCompilerSetup() const;
+ bool crossCompilerToolChainFile() const;
- int nextId() const;
+ int nextId() const;
- signals:
- void selectionChanged();
+signals:
+ void selectionChanged();
- protected slots:
- void onSelectionChanged(bool);
+protected slots:
+ void onSelectionChanged(bool);
+ void onGeneratorChanged(QString const& name);
- protected:
- QComboBox* GeneratorOptions;
- QRadioButton* CompilerSetupOptions[4];
+protected:
+ QComboBox* GeneratorOptions;
+ QRadioButton* CompilerSetupOptions[4];
+ QFrame* ToolsetFrame;
+ QLineEdit* Toolset;
+ QLabel* ToolsetLabel;
+ QStringList GeneratorsSupportingToolset;
+
+private:
+ QFrame* CreateToolsetWidgets();
};
//! the page that gives basic options for native compilers
class NativeCompilerSetup : public QWizardPage, protected Ui::Compilers
{
Q_OBJECT
- public:
- NativeCompilerSetup(QWidget* p);
- ~NativeCompilerSetup();
+public:
+ NativeCompilerSetup(QWidget* p);
+ ~NativeCompilerSetup();
- QString getCCompiler() const;
- void setCCompiler(const QString&);
+ QString getCCompiler() const;
+ void setCCompiler(const QString&);
- QString getCXXCompiler() const;
- void setCXXCompiler(const QString&);
+ QString getCXXCompiler() const;
+ void setCXXCompiler(const QString&);
- QString getFortranCompiler() const;
- void setFortranCompiler(const QString&);
+ QString getFortranCompiler() const;
+ void setFortranCompiler(const QString&);
- int nextId() const { return -1; }
+ int nextId() const { return -1; }
};
//! the page that gives options for cross compilers
class CrossCompilerSetup : public QWizardPage, protected Ui::CrossCompiler
{
Q_OBJECT
- public:
- CrossCompilerSetup(QWidget* p);
- ~CrossCompilerSetup();
-
- QString getSystem() const;
- void setSystem(const QString&);
-
- QString getVersion() const;
- void setVersion(const QString&);
-
- QString getProcessor() const;
- void setProcessor(const QString&);
-
- QString getCCompiler() const;
- void setCCompiler(const QString&);
+public:
+ CrossCompilerSetup(QWidget* p);
+ ~CrossCompilerSetup();
- QString getCXXCompiler() const;
- void setCXXCompiler(const QString&);
+ QString getSystem() const;
+ void setSystem(const QString&);
- QString getFortranCompiler() const;
- void setFortranCompiler(const QString&);
+ QString getVersion() const;
+ void setVersion(const QString&);
- QString getFindRoot() const;
- void setFindRoot(const QString&);
+ QString getProcessor() const;
+ void setProcessor(const QString&);
- enum CrossMode
- {
- BOTH,
- ONLY,
- NEVER
- };
+ QString getCCompiler() const;
+ void setCCompiler(const QString&);
- int getProgramMode() const;
- void setProgramMode(int);
- int getLibraryMode() const;
- void setLibraryMode(int);
- int getIncludeMode() const;
- void setIncludeMode(int);
+ QString getCXXCompiler() const;
+ void setCXXCompiler(const QString&);
- int nextId() const { return -1; }
+ QString getFortranCompiler() const;
+ void setFortranCompiler(const QString&);
+
+ QString getFindRoot() const;
+ void setFindRoot(const QString&);
+
+ enum CrossMode
+ {
+ BOTH,
+ ONLY,
+ NEVER
+ };
+
+ int getProgramMode() const;
+ void setProgramMode(int);
+ int getLibraryMode() const;
+ void setLibraryMode(int);
+ int getIncludeMode() const;
+ void setIncludeMode(int);
+
+ int nextId() const { return -1; }
};
//! the page that gives options for a toolchain file
class ToolchainCompilerSetup : public QWizardPage
{
Q_OBJECT
- public:
- ToolchainCompilerSetup(QWidget* p);
- ~ToolchainCompilerSetup();
+public:
+ ToolchainCompilerSetup(QWidget* p);
+ ~ToolchainCompilerSetup();
- QString toolchainFile() const;
- void setToolchainFile(const QString&);
+ QString toolchainFile() const;
+ void setToolchainFile(const QString&);
- int nextId() const { return -1; }
+ int nextId() const { return -1; }
- protected:
- QCMakeFilePathEditor* ToolchainFile;
+protected:
+ QCMakeFilePathEditor* ToolchainFile;
};
//! the wizard with the pages
@@ -140,8 +153,9 @@ public:
FirstConfigure();
~FirstConfigure();
- void setGenerators(const QStringList& gens);
+ void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
QString getGenerator() const;
+ QString getToolset() const;
bool defaultSetup() const;
bool compilerSetup() const;
@@ -170,8 +184,6 @@ protected:
NativeCompilerSetup* mNativeCompilerSetupPage;
CrossCompilerSetup* mCrossCompilerSetupPage;
ToolchainCompilerSetup* mToolchainCompilerSetupPage;
-
};
#endif // FirstConfigure_h
-
diff --git a/Source/QtDialog/Info.plist.in b/Source/QtDialog/Info.plist.in
new file mode 100644
index 000000000..00a27c39c
--- /dev/null
+++ b/Source/QtDialog/Info.plist.in
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>LSApplicationCategoryType</key>
+ <string>public.app-category.developer-tools</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+</dict>
+</plist>
diff --git a/Source/QtDialog/MacInstallDialog.ui b/Source/QtDialog/MacInstallDialog.ui
deleted file mode 100644
index c7e31dbbe..000000000
--- a/Source/QtDialog/MacInstallDialog.ui
+++ /dev/null
@@ -1,103 +0,0 @@
-<ui version="4.0" >
- <class>Dialog</class>
- <widget class="QDialog" name="Dialog" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>470</width>
- <height>159</height>
- </rect>
- </property>
- <property name="windowTitle" >
- <string>Install Command Line Tools</string>
- </property>
- <layout class="QGridLayout" >
- <property name="margin" >
- <number>9</number>
- </property>
- <property name="spacing" >
- <number>6</number>
- </property>
- <item row="3" column="1" >
- <spacer>
- <property name="orientation" >
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0" colspan="3" >
- <layout class="QHBoxLayout" >
- <property name="margin" >
- <number>0</number>
- </property>
- <property name="spacing" >
- <number>6</number>
- </property>
- <item>
- <spacer>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="skipInstallButton" >
- <property name="text" >
- <string>Skip Install Command Line </string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="doInstallButton" >
- <property name="text" >
- <string>Install Command Line Links</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="0" column="2" >
- <widget class="QPushButton" name="choosePathButton" >
- <property name="text" >
- <string>Choose...</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0" >
- <widget class="QLabel" name="label" >
- <property name="text" >
- <string>Install Folder:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1" >
- <widget class="QLineEdit" name="InstallPrefix" />
- </item>
- <item row="1" column="0" colspan="3" >
- <widget class="QLabel" name="label_2" >
- <property name="text" >
- <string>This will create symbolic links to the command line tools of cmake into the specified install folder.</string>
- </property>
- <property name="wordWrap" >
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index 0d0118164..d473d9b8f 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -1,92 +1,61 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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 <QDir>
#include <QCoreApplication>
+#include <QDir>
-#include "cmake.h"
-#include "cmCacheManager.h"
-#include "cmSystemTools.h"
#include "cmExternalMakefileProjectGenerator.h"
+#include "cmState.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)
: QObject(p)
{
- this->SuppressDevWarnings = false;
this->WarnUninitializedMode = false;
this->WarnUnusedMode = false;
qRegisterMetaType<QCMakeProperty>();
qRegisterMetaType<QCMakePropertyList>();
- QDir execDir(QCoreApplication::applicationDirPath());
-
-#if defined(Q_OS_MAC)
- if(execDir.exists("../bin/cmake"))
- {
- execDir.cd("../bin");
- }
- else
- {
- execDir.cd("../../../"); // path to cmake in build directory (need to fix for deployment)
- }
-#endif
-
- QString cmakeCommand = QString("cmake")+QString::fromLocal8Bit(cmSystemTools::GetExecutableExtension());
- cmakeCommand = execDir.filePath(cmakeCommand);
-
cmSystemTools::DisableRunCommandOutput();
cmSystemTools::SetRunCommandHideConsole(true);
- cmSystemTools::SetErrorCallback(QCMake::errorCallback, this);
- cmSystemTools::FindExecutableDirectory(cmakeCommand.toLocal8Bit().data());
+ cmSystemTools::SetMessageCallback(QCMake::messageCallback, this);
+ cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this);
+ cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this);
- this->CMakeInstance = new cmake;
- this->CMakeInstance->SetCMakeCommand(cmakeCommand.toLocal8Bit().data());
-#if defined(Q_OS_MAC)
- this->CMakeInstance->SetCMakeEditCommand("cmake-gui.app/Contents/MacOS/cmake-gui");
-#else
- this->CMakeInstance->SetCMakeEditCommand("cmake-gui");
-#endif
+ this->CMakeInstance = new cmake(cmake::RoleProject);
+ this->CMakeInstance->SetCMakeEditCommand(
+ cmSystemTools::GetCMakeGUICommand());
this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this);
cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this);
- std::vector<std::string> generators;
+ std::vector<cmake::GeneratorInfo> generators;
this->CMakeInstance->GetRegisteredGenerators(generators);
- std::vector<std::string>::iterator iter;
- for(iter = generators.begin(); iter != generators.end(); ++iter)
- {
+
+ 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 (*iter == "KDevelop3")
- {
+ if (it->name == "KDevelop3") {
continue;
- }
- this->AvailableGenerators.append(QString::fromLocal8Bit(iter->c_str()));
}
+
+ this->AvailableGenerators.push_back(*it);
+ }
}
QCMake::~QCMake()
{
delete this->CMakeInstance;
- //cmDynamicLoader::FlushCache();
+ // cmDynamicLoader::FlushCache();
}
void QCMake::loadCache(const QString& dir)
@@ -96,62 +65,73 @@ void QCMake::loadCache(const QString& dir)
void QCMake::setSourceDirectory(const QString& _dir)
{
- QString dir =
- QString::fromLocal8Bit(cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
- if(this->SourceDirectory != dir)
- {
+ QString dir = QString::fromLocal8Bit(
+ cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
+ if (this->SourceDirectory != dir) {
this->SourceDirectory = QDir::fromNativeSeparators(dir);
emit this->sourceDirChanged(this->SourceDirectory);
- }
+ }
}
void QCMake::setBinaryDirectory(const QString& _dir)
{
- QString dir =
- QString::fromLocal8Bit(cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
- if(this->BinaryDirectory != dir)
- {
+ QString dir = QString::fromLocal8Bit(
+ cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
+ if (this->BinaryDirectory != dir) {
this->BinaryDirectory = QDir::fromNativeSeparators(dir);
emit this->binaryDirChanged(this->BinaryDirectory);
- cmCacheManager *cachem = this->CMakeInstance->GetCacheManager();
+ cmState* state = this->CMakeInstance->GetState();
this->setGenerator(QString());
- if(!this->CMakeInstance->GetCacheManager()->LoadCache(
- this->BinaryDirectory.toLocal8Bit().data()))
- {
+ this->setToolset(QString());
+ if (!this->CMakeInstance->LoadCache(
+ this->BinaryDirectory.toLocal8Bit().data())) {
QDir testDir(this->BinaryDirectory);
- if(testDir.exists("CMakeCache.txt"))
- {
- 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 permissions of the directory you are trying to run CMake on.");
- }
+ if (testDir.exists("CMakeCache.txt")) {
+ 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 permissions of the directory you are trying to "
+ "run CMake on.");
}
+ }
QCMakePropertyList props = this->properties();
emit this->propertiesChanged(props);
- cmCacheManager::CacheIterator itm = cachem->NewIterator();
- if ( itm.Find("CMAKE_HOME_DIRECTORY"))
- {
- setSourceDirectory(QString::fromLocal8Bit(itm.GetValue()));
- }
- if ( itm.Find("CMAKE_GENERATOR"))
- {
- const char* extraGen = cachem->GetCacheValue("CMAKE_EXTRA_GENERATOR");
- std::string curGen = cmExternalMakefileProjectGenerator::
- CreateFullGeneratorName(itm.GetValue(), extraGen);
+ const char* homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
+ if (homeDir) {
+ setSourceDirectory(QString::fromLocal8Bit(homeDir));
+ }
+ const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
+ if (gen) {
+ const char* extraGen =
+ state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
+ std::string curGen =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ gen, extraGen ? extraGen : "");
this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
- }
}
-}
+ const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
+ if (toolset) {
+ this->setToolset(QString::fromLocal8Bit(toolset));
+ }
+ }
+}
void QCMake::setGenerator(const QString& gen)
{
- if(this->Generator != gen)
- {
+ if (this->Generator != gen) {
this->Generator = gen;
emit this->generatorChanged(this->Generator);
- }
+ }
+}
+
+void QCMake::setToolset(const QString& toolset)
+{
+ if (this->Toolset != toolset) {
+ this->Toolset = toolset;
+ emit this->toolsetChanged(this->Toolset);
+ }
}
void QCMake::configure()
@@ -160,14 +140,16 @@ void QCMake::configure()
UINT lastErrorMode = SetErrorMode(0);
#endif
- this->CMakeInstance->SetHomeDirectory(this->SourceDirectory.toLocal8Bit().data());
- this->CMakeInstance->SetStartDirectory(this->SourceDirectory.toLocal8Bit().data());
- this->CMakeInstance->SetHomeOutputDirectory(this->BinaryDirectory.toLocal8Bit().data());
- this->CMakeInstance->SetStartOutputDirectory(this->BinaryDirectory.toLocal8Bit().data());
+ this->CMakeInstance->SetHomeDirectory(
+ this->SourceDirectory.toLocal8Bit().data());
+ this->CMakeInstance->SetHomeOutputDirectory(
+ this->BinaryDirectory.toLocal8Bit().data());
this->CMakeInstance->SetGlobalGenerator(
- this->CMakeInstance->CreateGlobalGenerator(this->Generator.toLocal8Bit().data()));
+ this->CMakeInstance->CreateGlobalGenerator(
+ this->Generator.toLocal8Bit().data()));
+ this->CMakeInstance->SetGeneratorPlatform("");
+ this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data());
this->CMakeInstance->LoadCache();
- this->CMakeInstance->SetSuppressDevWarnings(this->SuppressDevWarnings);
this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode);
this->CMakeInstance->PreLoadCMakeFiles();
@@ -210,132 +192,105 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)
QStringList toremove;
// set the value of properties
- cmCacheManager *cachem = this->CMakeInstance->GetCacheManager();
- for(cmCacheManager::CacheIterator i = cachem->NewIterator();
- !i.IsAtEnd(); i.Next())
- {
-
- if(i.GetType() == cmCacheManager::INTERNAL ||
- i.GetType() == cmCacheManager::STATIC)
- {
+ 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);
+ if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC) {
continue;
- }
+ }
QCMakeProperty prop;
- prop.Key = QString::fromLocal8Bit(i.GetName());
+ prop.Key = QString::fromLocal8Bit(it->c_str());
int idx = props.indexOf(prop);
- if(idx == -1)
- {
- toremove.append(QString::fromLocal8Bit(i.GetName()));
- }
- else
- {
+ if (idx == -1) {
+ toremove.append(QString::fromLocal8Bit(it->c_str()));
+ } else {
prop = props[idx];
- if(prop.Value.type() == QVariant::Bool)
- {
- i.SetValue(prop.Value.toBool() ? "ON" : "OFF");
- }
- else
- {
- i.SetValue(prop.Value.toString().toLocal8Bit().data());
- }
- props.removeAt(idx);
+ if (prop.Value.type() == QVariant::Bool) {
+ state->SetCacheEntryValue(*it, prop.Value.toBool() ? "ON" : "OFF");
+ } else {
+ state->SetCacheEntryValue(*it,
+ prop.Value.toString().toLocal8Bit().data());
}
-
+ props.removeAt(idx);
}
+ }
// remove some properites
- foreach(QString s, toremove)
- {
+ foreach (QString const& s, toremove) {
this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
- cachem->RemoveCacheEntry(s.toLocal8Bit().data());
- }
+ state->RemoveCacheEntry(s.toLocal8Bit().data());
+ }
// add some new properites
- foreach(QCMakeProperty s, props)
- {
+ foreach (QCMakeProperty const& s, props) {
this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
- if(s.Type == QCMakeProperty::BOOL)
- {
- this->CMakeInstance->AddCacheEntry(s.Key.toLocal8Bit().data(),
- s.Value.toBool() ? "ON" : "OFF",
- s.Help.toLocal8Bit().data(),
- cmCacheManager::BOOL);
- }
- else if(s.Type == QCMakeProperty::STRING)
- {
- this->CMakeInstance->AddCacheEntry(s.Key.toLocal8Bit().data(),
- s.Value.toString().toLocal8Bit().data(),
- s.Help.toLocal8Bit().data(),
- cmCacheManager::STRING);
- }
- else if(s.Type == QCMakeProperty::PATH)
- {
- this->CMakeInstance->AddCacheEntry(s.Key.toLocal8Bit().data(),
- s.Value.toString().toLocal8Bit().data(),
- s.Help.toLocal8Bit().data(),
- cmCacheManager::PATH);
- }
- else if(s.Type == QCMakeProperty::FILEPATH)
- {
- this->CMakeInstance->AddCacheEntry(s.Key.toLocal8Bit().data(),
- s.Value.toString().toLocal8Bit().data(),
- s.Help.toLocal8Bit().data(),
- cmCacheManager::FILEPATH);
- }
+ if (s.Type == QCMakeProperty::BOOL) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toBool() ? "ON" : "OFF",
+ s.Help.toLocal8Bit().data(), cmStateEnums::BOOL);
+ } else if (s.Type == QCMakeProperty::STRING) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
+ s.Help.toLocal8Bit().data(), cmStateEnums::STRING);
+ } else if (s.Type == QCMakeProperty::PATH) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
+ s.Help.toLocal8Bit().data(), cmStateEnums::PATH);
+ } else if (s.Type == QCMakeProperty::FILEPATH) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
+ s.Help.toLocal8Bit().data(), cmStateEnums::FILEPATH);
}
+ }
- cachem->SaveCache(this->BinaryDirectory.toLocal8Bit().data());
+ this->CMakeInstance->SaveCache(this->BinaryDirectory.toLocal8Bit().data());
}
QCMakePropertyList QCMake::properties() const
{
QCMakePropertyList ret;
- cmCacheManager *cachem = this->CMakeInstance->GetCacheManager();
- for(cmCacheManager::CacheIterator i = cachem->NewIterator();
- !i.IsAtEnd(); i.Next())
- {
-
- if(i.GetType() == cmCacheManager::INTERNAL ||
- i.GetType() == cmCacheManager::STATIC ||
- i.GetType() == cmCacheManager::UNINITIALIZED)
- {
+ 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);
+ if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
+ t == cmStateEnums::UNINITIALIZED) {
continue;
- }
+ }
- QCMakeProperty prop;
- prop.Key = QString::fromLocal8Bit(i.GetName());
- prop.Help = QString::fromLocal8Bit(i.GetProperty("HELPSTRING"));
- prop.Value = QString::fromLocal8Bit(i.GetValue());
- prop.Advanced = i.GetPropertyAsBool("ADVANCED");
+ const char* cachedValue = state->GetCacheEntryValue(*i);
- if(i.GetType() == cmCacheManager::BOOL)
- {
+ QCMakeProperty prop;
+ prop.Key = QString::fromLocal8Bit(i->c_str());
+ prop.Help =
+ QString::fromLocal8Bit(state->GetCacheEntryProperty(*i, "HELPSTRING"));
+ prop.Value = QString::fromLocal8Bit(cachedValue);
+ prop.Advanced = state->GetCacheEntryPropertyAsBool(*i, "ADVANCED");
+ if (t == cmStateEnums::BOOL) {
prop.Type = QCMakeProperty::BOOL;
- prop.Value = cmSystemTools::IsOn(i.GetValue());
- }
- else if(i.GetType() == cmCacheManager::PATH)
- {
+ prop.Value = cmSystemTools::IsOn(cachedValue);
+ } else if (t == cmStateEnums::PATH) {
prop.Type = QCMakeProperty::PATH;
- }
- else if(i.GetType() == cmCacheManager::FILEPATH)
- {
+ } else if (t == cmStateEnums::FILEPATH) {
prop.Type = QCMakeProperty::FILEPATH;
- }
- else if(i.GetType() == cmCacheManager::STRING)
- {
+ } else if (t == cmStateEnums::STRING) {
prop.Type = QCMakeProperty::STRING;
- if (i.PropertyExists("STRINGS"))
- {
- prop.Strings = QString::fromLocal8Bit(i.GetProperty("STRINGS")).split(";");
- }
+ const char* stringsProperty =
+ state->GetCacheEntryProperty(*i, "STRINGS");
+ if (stringsProperty) {
+ prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";");
}
+ }
ret.append(prop);
- }
+ }
return ret;
}
@@ -358,25 +313,36 @@ bool QCMake::interruptCallback(void* cd)
void QCMake::progressCallback(const char* msg, float percent, void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
- if(percent >= 0)
- {
+ if (percent >= 0) {
emit self->progressChanged(QString::fromLocal8Bit(msg), percent);
- }
- else
- {
+ } else {
emit self->outputMessage(QString::fromLocal8Bit(msg));
- }
+ }
QCoreApplication::processEvents();
}
-void QCMake::errorCallback(const char* msg, const char* /*title*/,
- bool& /*stop*/, void* cd)
+void QCMake::messageCallback(const char* msg, const char* /*title*/,
+ bool& /*stop*/, void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
emit self->errorMessage(QString::fromLocal8Bit(msg));
QCoreApplication::processEvents();
}
+void QCMake::stdoutCallback(const char* msg, size_t len, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
+ QCoreApplication::processEvents();
+}
+
+void QCMake::stderrCallback(const char* msg, size_t len, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
+ QCoreApplication::processEvents();
+}
+
QString QCMake::binaryDirectory() const
{
return this->BinaryDirectory;
@@ -392,19 +358,20 @@ QString QCMake::generator() const
return this->Generator;
}
-QStringList QCMake::availableGenerators() const
+std::vector<cmake::GeneratorInfo> const& QCMake::availableGenerators() const
{
- return this->AvailableGenerators;
+ return AvailableGenerators;
}
void QCMake::deleteCache()
{
// delete cache
- this->CMakeInstance->GetCacheManager()->DeleteCache(this->BinaryDirectory.toLocal8Bit().data());
+ this->CMakeInstance->DeleteCache(this->BinaryDirectory.toLocal8Bit().data());
// reload to make our cache empty
- this->CMakeInstance->GetCacheManager()->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
+ this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
// emit no generator and no properties
this->setGenerator(QString());
+ this->setToolset(QString());
QCMakePropertyList props = this->properties();
emit this->propertiesChanged(props);
}
@@ -415,7 +382,7 @@ void QCMake::reloadCache()
QCMakePropertyList props;
emit this->propertiesChanged(props);
// reload
- this->CMakeInstance->GetCacheManager()->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
+ this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
// emit new cache properties
props = this->properties();
emit this->propertiesChanged(props);
@@ -423,11 +390,10 @@ void QCMake::reloadCache()
void QCMake::setDebugOutput(bool flag)
{
- if(flag != this->CMakeInstance->GetDebugOutput())
- {
+ if (flag != this->CMakeInstance->GetDebugOutput()) {
this->CMakeInstance->SetDebugOutputOn(flag);
emit this->debugOutputChanged(flag);
- }
+ }
}
bool QCMake::getDebugOutput() const
@@ -435,10 +401,44 @@ bool QCMake::getDebugOutput() const
return this->CMakeInstance->GetDebugOutput();
}
+bool QCMake::getSuppressDevWarnings()
+{
+ return this->CMakeInstance->GetSuppressDevWarnings();
+}
void QCMake::setSuppressDevWarnings(bool value)
{
- this->SuppressDevWarnings = value;
+ this->CMakeInstance->SetSuppressDevWarnings(value);
+}
+
+bool QCMake::getSuppressDeprecatedWarnings()
+{
+ return this->CMakeInstance->GetSuppressDeprecatedWarnings();
+}
+
+void QCMake::setSuppressDeprecatedWarnings(bool value)
+{
+ this->CMakeInstance->SetSuppressDeprecatedWarnings(value);
+}
+
+bool QCMake::getDevWarningsAsErrors()
+{
+ return this->CMakeInstance->GetDevWarningsAsErrors();
+}
+
+void QCMake::setDevWarningsAsErrors(bool value)
+{
+ this->CMakeInstance->SetDevWarningsAsErrors(value);
+}
+
+bool QCMake::getDeprecatedWarningsAsErrors()
+{
+ return this->CMakeInstance->GetDeprecatedWarningsAsErrors();
+}
+
+void QCMake::setDeprecatedWarningsAsErrors(bool value)
+{
+ this->CMakeInstance->SetDeprecatedWarningsAsErrors(value);
}
void QCMake::setWarnUninitializedMode(bool value)
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index 93ac8ab00..e14cdf2c9 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -1,37 +1,38 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef QCMake_h
+#define QCMake_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "cmake.h"
-#ifndef __QCMake_h
-#define __QCMake_h
#ifdef _MSC_VER
-#pragma warning ( disable : 4127 )
-#pragma warning ( disable : 4512 )
+#pragma warning(disable : 4127)
+#pragma warning(disable : 4512)
#endif
+#include <vector>
+
+#include <QAtomicInt>
+#include <QList>
+#include <QMetaType>
#include <QObject>
#include <QString>
-#include <QVariant>
-#include <QList>
#include <QStringList>
-#include <QMetaType>
-#include <QAtomicInt>
-
-class cmake;
+#include <QVariant>
/// struct to represent cmake properties in Qt
/// Value is of type String or Bool
struct QCMakeProperty
{
- enum PropertyType { BOOL, PATH, FILEPATH, STRING };
+ enum PropertyType
+ {
+ BOOL,
+ PATH,
+ FILEPATH,
+ STRING
+ };
QString Key;
QVariant Value;
QStringList Strings;
@@ -39,13 +40,13 @@ struct QCMakeProperty
PropertyType Type;
bool Advanced;
bool operator==(const QCMakeProperty& other) const
- {
+ {
return this->Key == other.Key;
- }
+ }
bool operator<(const QCMakeProperty& other) const
- {
+ {
return this->Key < other.Key;
- }
+ }
};
// list of properties
@@ -62,7 +63,7 @@ class QCMake : public QObject
{
Q_OBJECT
public:
- QCMake(QObject* p=0);
+ QCMake(QObject* p = CM_NULLPTR);
~QCMake();
public slots:
/// load the cache file in a directory
@@ -73,13 +74,16 @@ public slots:
void setBinaryDirectory(const QString& dir);
/// set the desired generator to use
void setGenerator(const QString& generator);
+ /// set the desired generator to use
+ void setToolset(const QString& toolset);
/// do the configure step
void configure();
/// generate the files
void generate();
/// set the property values
void setProperties(const QCMakePropertyList&);
- /// interrupt the configure or generate process (if connecting, make a direct connection)
+ /// interrupt the configure or generate process (if connecting, make a direct
+ /// connection)
void interrupt();
/// delete the cache in binary directory
void deleteCache();
@@ -87,8 +91,22 @@ public slots:
void reloadCache();
/// set whether to do debug output
void setDebugOutput(bool);
+ /// get whether to do suppress dev warnings
+ bool getSuppressDevWarnings();
/// set whether to do suppress dev warnings
void setSuppressDevWarnings(bool value);
+ /// get whether to do suppress deprecated warnings
+ bool getSuppressDeprecatedWarnings();
+ /// set whether to do suppress deprecated warnings
+ void setSuppressDeprecatedWarnings(bool value);
+ /// get whether to treat developer (author) warnings as errors
+ bool getDevWarningsAsErrors();
+ /// set whether to treat developer (author) warnings as errors
+ void setDevWarningsAsErrors(bool value);
+ /// get whether to treat deprecated warnings as errors
+ bool getDeprecatedWarningsAsErrors();
+ /// set whether to treat deprecated warnings as errors
+ void setDeprecatedWarningsAsErrors(bool value);
/// set whether to run cmake with warnings about uninitialized variables
void setWarnUninitializedMode(bool value);
/// set whether to run cmake with warnings about unused variables
@@ -104,12 +122,13 @@ public:
/// get the current generator
QString generator() const;
/// get the available generators
- QStringList availableGenerators() const;
+ std::vector<cmake::GeneratorInfo> const& availableGenerators() const;
/// get whether to do debug output
bool getDebugOutput() const;
signals:
- /// signal when properties change (during read from disk or configure process)
+ /// signal when properties change (during read from disk or configure
+ /// process)
void propertiesChanged(const QCMakePropertyList& vars);
/// signal when the generator changes
void generatorChanged(const QString& gen);
@@ -130,25 +149,28 @@ signals:
void errorMessage(const QString& msg);
/// signal when debug output changes
void debugOutputChanged(bool);
+ /// signal when the toolset changes
+ void toolsetChanged(const QString& toolset);
protected:
cmake* CMakeInstance;
static bool interruptCallback(void*);
static void progressCallback(const char* msg, float percent, void* cd);
- static void errorCallback(const char* msg, const char* title,
- bool&, void* cd);
- bool SuppressDevWarnings;
+ 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 WarnUninitializedMode;
bool WarnUnusedMode;
bool WarnUnusedAllMode;
QString SourceDirectory;
QString BinaryDirectory;
QString Generator;
- QStringList AvailableGenerators;
+ QString Toolset;
+ std::vector<cmake::GeneratorInfo> AvailableGenerators;
QString CMakeExecutable;
QAtomicInt InterruptFlag;
};
-#endif // __QCMake_h
-
+#endif // QCMake_h
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index bae6a30a7..08c2d58d5 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -1,25 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "QCMakeCacheView.h"
+#include <QApplication>
+#include <QEvent>
#include <QHBoxLayout>
#include <QHeaderView>
-#include <QEvent>
-#include <QStyle>
#include <QKeyEvent>
-#include <QSortFilterProxyModel>
#include <QMetaProperty>
-#include <QApplication>
+#include <QSortFilterProxyModel>
+#include <QStyle>
#include "QCMakeWidgets.h"
@@ -27,46 +17,44 @@
class QCMakeSearchFilter : public QSortFilterProxyModel
{
public:
- QCMakeSearchFilter(QObject* o) : QSortFilterProxyModel(o) {}
+ QCMakeSearchFilter(QObject* o)
+ : QSortFilterProxyModel(o)
+ {
+ }
+
protected:
- bool filterAcceptsRow(int row, const QModelIndex& p) const
- {
+ bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
+ {
QStringList strs;
const QAbstractItemModel* m = this->sourceModel();
QModelIndex idx = m->index(row, 0, p);
// if there are no children, get strings for column 0 and 1
- if(!m->hasChildren(idx))
- {
+ if (!m->hasChildren(idx)) {
strs.append(m->data(idx).toString());
idx = m->index(row, 1, p);
strs.append(m->data(idx).toString());
- }
- else
- {
+ } else {
// get strings for children entries to compare with
// instead of comparing with the parent
int num = m->rowCount(idx);
- for(int i=0; i<num; i++)
- {
+ for (int i = 0; i < num; i++) {
QModelIndex tmpidx = m->index(i, 0, idx);
strs.append(m->data(tmpidx).toString());
tmpidx = m->index(i, 1, idx);
strs.append(m->data(tmpidx).toString());
- }
}
+ }
// check all strings for a match
- foreach(QString str, strs)
- {
- if(str.contains(this->filterRegExp()))
- {
+ foreach (QString const& str, strs) {
+ if (str.contains(this->filterRegExp())) {
return true;
- }
}
+ }
return false;
- }
+ }
};
// filter for searches
@@ -74,7 +62,10 @@ class QCMakeAdvancedFilter : public QSortFilterProxyModel
{
public:
QCMakeAdvancedFilter(QObject* o)
- : QSortFilterProxyModel(o), ShowAdvanced(false) {}
+ : QSortFilterProxyModel(o)
+ , ShowAdvanced(false)
+ {
+ }
void setShowAdvanced(bool f)
{
@@ -84,37 +75,29 @@ public:
bool showAdvanced() const { return this->ShowAdvanced; }
protected:
-
bool ShowAdvanced;
- bool filterAcceptsRow(int row, const QModelIndex& p) const
- {
+ bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
+ {
const QAbstractItemModel* m = this->sourceModel();
QModelIndex idx = m->index(row, 0, p);
// if there are no children
- if(!m->hasChildren(idx))
- {
+ if (!m->hasChildren(idx)) {
bool adv = m->data(idx, QCMakeCacheModel::AdvancedRole).toBool();
- if(!adv || (adv && this->ShowAdvanced))
- {
- return true;
- }
- return false;
- }
+ return !adv || this->ShowAdvanced;
+ }
// check children
int num = m->rowCount(idx);
- for(int i=0; i<num; i++)
- {
+ for (int i = 0; i < num; i++) {
bool accept = this->filterAcceptsRow(i, idx);
- if(accept)
- {
+ if (accept) {
return true;
- }
}
- return false;
}
+ return false;
+ }
};
QCMakeCacheView::QCMakeCacheView(QWidget* p)
@@ -147,10 +130,9 @@ QCMakeCacheView::QCMakeCacheView(QWidget* p)
bool QCMakeCacheView::event(QEvent* e)
{
- if(e->type() == QEvent::Show)
- {
- this->header()->setDefaultSectionSize(this->viewport()->width()/2);
- }
+ if (e->type() == QEvent::Show) {
+ this->header()->setDefaultSectionSize(this->viewport()->width() / 2);
+ }
return QTreeView::event(e);
}
@@ -160,17 +142,15 @@ QCMakeCacheModel* QCMakeCacheView::cacheModel() const
}
QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
- Qt::KeyboardModifiers mod)
+ Qt::KeyboardModifiers mod)
{
// want home/end to go to begin/end of rows, not columns
- if(act == MoveHome)
- {
+ if (act == MoveHome) {
return this->model()->index(0, 1);
- }
- else if(act == MoveEnd)
- {
- return this->model()->index(this->model()->rowCount()-1, 1);
- }
+ }
+ if (act == MoveEnd) {
+ return this->model()->index(this->model()->rowCount() - 1, 1);
+ }
return QTreeView::moveCursor(act, mod);
}
@@ -195,10 +175,10 @@ void QCMakeCacheView::setSearchFilter(const QString& s)
}
QCMakeCacheModel::QCMakeCacheModel(QObject* p)
- : QStandardItemModel(p),
- EditEnabled(true),
- NewPropertyCount(0),
- View(FlatView)
+ : QStandardItemModel(p)
+ , EditEnabled(true)
+ , NewPropertyCount(0)
+ , View(FlatView)
{
this->ShowNewProperties = true;
QStringList labels;
@@ -234,47 +214,39 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
{
QSet<QCMakeProperty> newProps, newProps2;
- if(this->ShowNewProperties)
- {
+ if (this->ShowNewProperties) {
newProps = props.toSet();
newProps2 = newProps;
QSet<QCMakeProperty> oldProps = this->properties().toSet();
oldProps.intersect(newProps);
newProps.subtract(oldProps);
newProps2.subtract(newProps);
- }
- else
- {
+ } else {
newProps2 = props.toSet();
- }
+ }
bool b = this->blockSignals(true);
this->clear();
this->NewPropertyCount = newProps.size();
- if(View == FlatView)
- {
+ if (View == FlatView) {
QCMakePropertyList newP = newProps.toList();
QCMakePropertyList newP2 = newProps2.toList();
qSort(newP);
qSort(newP2);
int row_count = 0;
- foreach(QCMakeProperty p, newP)
- {
+ foreach (QCMakeProperty const& p, newP) {
this->insertRow(row_count);
this->setPropertyData(this->index(row_count, 0), p, true);
row_count++;
}
- foreach(QCMakeProperty p, newP2)
- {
+ foreach (QCMakeProperty const& p, newP2) {
this->insertRow(row_count);
this->setPropertyData(this->index(row_count, 0), p, false);
row_count++;
}
- }
- else if(this->View == GroupView)
- {
+ } else if (this->View == GroupView) {
QMap<QString, QCMakePropertyList> newPropsTree;
this->breakProperties(newProps, newPropsTree);
QMap<QString, QCMakePropertyList> newPropsTree2;
@@ -282,36 +254,40 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
QStandardItem* root = this->invisibleRootItem();
- foreach(QString key, newPropsTree.keys())
- {
- QCMakePropertyList props2 = newPropsTree[key];
+ for (QMap<QString, QCMakePropertyList>::const_iterator iter =
+ newPropsTree.begin();
+ iter != newPropsTree.end(); ++iter) {
+ QString const& key = iter.key();
+ QCMakePropertyList const& props2 = iter.value();
QList<QStandardItem*> parentItems;
parentItems.append(
- new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key)
- );
+ new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key));
parentItems.append(new QStandardItem());
- parentItems[0]->setData(QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
- parentItems[1]->setData(QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
+ parentItems[0]->setData(QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
+ parentItems[1]->setData(QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
parentItems[0]->setData(1, GroupRole);
parentItems[1]->setData(1, GroupRole);
root->appendRow(parentItems);
int num = props2.size();
- for(int i=0; i<num; i++)
- {
+ for (int i = 0; i < num; i++) {
QCMakeProperty prop = props2[i];
QList<QStandardItem*> items;
items.append(new QStandardItem());
items.append(new QStandardItem());
parentItems[0]->appendRow(items);
this->setPropertyData(this->indexFromItem(items[0]), prop, true);
- }
}
+ }
- foreach(QString key, newPropsTree2.keys())
- {
- QCMakePropertyList props2 = newPropsTree2[key];
+ for (QMap<QString, QCMakePropertyList>::const_iterator iter =
+ newPropsTree2.begin();
+ iter != newPropsTree2.end(); ++iter) {
+ QString const& key = iter.key();
+ QCMakePropertyList const& props2 = iter.value();
QStandardItem* parentItem =
new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key);
@@ -319,16 +295,15 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
parentItem->setData(1, GroupRole);
int num = props2.size();
- for(int i=0; i<num; i++)
- {
+ for (int i = 0; i < num; i++) {
QCMakeProperty prop = props2[i];
QList<QStandardItem*> items;
items.append(new QStandardItem());
items.append(new QStandardItem());
parentItem->appendRow(items);
this->setPropertyData(this->indexFromItem(items[0]), prop, false);
- }
}
+ }
}
this->blockSignals(b);
@@ -348,8 +323,7 @@ void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
QCMakePropertyList oldProps;
int numNew = this->NewPropertyCount;
int numTotal = props.count();
- for(int i=numNew; i<numTotal; i++)
- {
+ for (int i = numNew; i < numTotal; i++) {
oldProps.append(props[i]);
}
@@ -362,7 +336,7 @@ void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
}
void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1,
- const QCMakeProperty& prop, bool isNew)
+ const QCMakeProperty& prop, bool isNew)
{
QModelIndex idx2 = idx1.sibling(idx1.row(), 1);
@@ -371,46 +345,42 @@ void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1,
this->setData(idx1, prop.Type, QCMakeCacheModel::TypeRole);
this->setData(idx1, prop.Advanced, QCMakeCacheModel::AdvancedRole);
- if(prop.Type == QCMakeProperty::BOOL)
- {
+ if (prop.Type == QCMakeProperty::BOOL) {
int check = prop.Value.toBool() ? Qt::Checked : Qt::Unchecked;
this->setData(idx2, check, Qt::CheckStateRole);
- }
- else
- {
+ } else {
this->setData(idx2, prop.Value, Qt::DisplayRole);
}
this->setData(idx2, prop.Help, QCMakeCacheModel::HelpRole);
- if (!prop.Strings.isEmpty())
- {
+ if (!prop.Strings.isEmpty()) {
this->setData(idx1, prop.Strings, QCMakeCacheModel::StringsRole);
}
- if(isNew)
- {
- this->setData(idx1, QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
- this->setData(idx2, QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
+ if (isNew) {
+ this->setData(idx1, QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
+ this->setData(idx2, QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
}
}
void QCMakeCacheModel::getPropertyData(const QModelIndex& idx1,
- QCMakeProperty& prop) const
+ QCMakeProperty& prop) const
{
QModelIndex idx2 = idx1.sibling(idx1.row(), 1);
prop.Key = this->data(idx1, Qt::DisplayRole).toString();
prop.Help = this->data(idx1, HelpRole).toString();
- prop.Type = static_cast<QCMakeProperty::PropertyType>(this->data(idx1, TypeRole).toInt());
+ prop.Type = static_cast<QCMakeProperty::PropertyType>(
+ this->data(idx1, TypeRole).toInt());
prop.Advanced = this->data(idx1, AdvancedRole).toBool();
- prop.Strings = this->data(idx1, QCMakeCacheModel::StringsRole).toStringList();
- if(prop.Type == QCMakeProperty::BOOL)
- {
+ prop.Strings =
+ this->data(idx1, QCMakeCacheModel::StringsRole).toStringList();
+ if (prop.Type == QCMakeProperty::BOOL) {
int check = this->data(idx2, Qt::CheckStateRole).toInt();
prop.Value = check == Qt::Checked;
- }
- else
- {
+ } else {
prop.Value = this->data(idx2, Qt::DisplayRole).toString();
}
}
@@ -418,43 +388,36 @@ void QCMakeCacheModel::getPropertyData(const QModelIndex& idx1,
QString QCMakeCacheModel::prefix(const QString& s)
{
QString prefix = s.section('_', 0, 0);
- if(prefix == s)
- {
+ if (prefix == s) {
prefix = QString();
- }
+ }
return prefix;
}
-void QCMakeCacheModel::breakProperties(const QSet<QCMakeProperty>& props,
- QMap<QString, QCMakePropertyList>& result)
+void QCMakeCacheModel::breakProperties(
+ const QSet<QCMakeProperty>& props, QMap<QString, QCMakePropertyList>& result)
{
QMap<QString, QCMakePropertyList> tmp;
// return a map of properties grouped by prefixes, and sorted
- foreach(QCMakeProperty p, props)
- {
+ foreach (QCMakeProperty const& p, props) {
QString prefix = QCMakeCacheModel::prefix(p.Key);
tmp[prefix].append(p);
- }
+ }
// sort it and re-org any properties with only one sub item
QCMakePropertyList reorgProps;
QMap<QString, QCMakePropertyList>::iterator iter;
- for(iter = tmp.begin(); iter != tmp.end();)
- {
- if(iter->count() == 1)
- {
+ for (iter = tmp.begin(); iter != tmp.end();) {
+ if (iter->count() == 1) {
reorgProps.append((*iter)[0]);
iter = tmp.erase(iter);
- }
- else
- {
+ } else {
qSort(*iter);
++iter;
- }
}
- if(reorgProps.count())
- {
+ }
+ if (reorgProps.count()) {
tmp[QString()] += reorgProps;
- }
+ }
result = tmp;
}
@@ -462,27 +425,21 @@ QCMakePropertyList QCMakeCacheModel::properties() const
{
QCMakePropertyList props;
- if(!this->rowCount())
- {
+ if (!this->rowCount()) {
return props;
- }
+ }
- QList<QModelIndex> idxs;
- idxs.append(this->index(0,0));
+ QVector<QModelIndex> idxs;
+ idxs.append(this->index(0, 0));
// walk the entire model for property entries
// this works regardless of a flat view or a tree view
- while(!idxs.isEmpty())
- {
+ while (!idxs.isEmpty()) {
QModelIndex idx = idxs.last();
- if(this->hasChildren(idx) && this->rowCount(idx))
- {
- idxs.append(this->index(0,0, idx));
- }
- else
- {
- if(!data(idx, GroupRole).toInt())
- {
+ if (this->hasChildren(idx) && this->rowCount(idx)) {
+ idxs.append(this->index(0, 0, idx));
+ } else {
+ if (!data(idx, GroupRole).toInt()) {
// get data
QCMakeProperty prop;
this->getPropertyData(idx, prop);
@@ -490,17 +447,17 @@ QCMakePropertyList QCMakeCacheModel::properties() const
}
// go to the next in the tree
- while(!idxs.isEmpty() && (
-#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
- (idxs.last().row()+1) >= rowCount(idxs.last().parent()) ||
+ while (!idxs.isEmpty() &&
+ (
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && \
+ QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+ (idxs.last().row() + 1) >= rowCount(idxs.last().parent()) ||
#endif
- !idxs.last().sibling(idxs.last().row()+1, 0).isValid()))
- {
- idxs.removeLast();
+ !idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) {
+ idxs.remove(idxs.size() - 1);
}
- if(!idxs.isEmpty())
- {
- idxs.last() = idxs.last().sibling(idxs.last().row()+1, 0);
+ if (!idxs.isEmpty()) {
+ idxs.last() = idxs.last().sibling(idxs.last().row() + 1, 0);
}
}
}
@@ -509,8 +466,9 @@ QCMakePropertyList QCMakeCacheModel::properties() const
}
bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
- const QString& name, const QString& description,
- const QVariant& value, bool advanced)
+ const QString& name,
+ const QString& description,
+ const QVariant& value, bool advanced)
{
QCMakeProperty prop;
prop.Key = name;
@@ -519,9 +477,9 @@ bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
prop.Type = t;
prop.Advanced = advanced;
- //insert at beginning
+ // insert at beginning
this->insertRow(0);
- this->setPropertyData(this->index(0,0), prop, true);
+ this->setPropertyData(this->index(0, 0), prop, true);
this->NewPropertyCount++;
return true;
}
@@ -541,33 +499,31 @@ int QCMakeCacheModel::newPropertyCount() const
return this->NewPropertyCount;
}
-Qt::ItemFlags QCMakeCacheModel::flags (const QModelIndex& idx) const
+Qt::ItemFlags QCMakeCacheModel::flags(const QModelIndex& idx) const
{
Qt::ItemFlags f = QStandardItemModel::flags(idx);
- if(!this->EditEnabled)
- {
+ if (!this->EditEnabled) {
f &= ~Qt::ItemIsEditable;
return f;
- }
- if(QCMakeProperty::BOOL == this->data(idx, TypeRole).toInt())
- {
+ }
+ if (QCMakeProperty::BOOL == this->data(idx, TypeRole).toInt()) {
f |= Qt::ItemIsUserCheckable;
- }
+ }
return f;
}
QModelIndex QCMakeCacheModel::buddy(const QModelIndex& idx) const
{
- if(!this->hasChildren(idx) &&
- this->data(idx, TypeRole).toInt() != QCMakeProperty::BOOL)
- {
+ if (!this->hasChildren(idx) &&
+ this->data(idx, TypeRole).toInt() != QCMakeProperty::BOOL) {
return this->index(idx.row(), 1, idx.parent());
}
return idx;
}
QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
- : QItemDelegate(p), FileDialogFlag(false)
+ : QItemDelegate(p)
+ , FileDialogFlag(false)
{
}
@@ -576,92 +532,81 @@ void QCMakeCacheModelDelegate::setFileDialogFlag(bool f)
this->FileDialogFlag = f;
}
-QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* p,
- const QStyleOptionViewItem&, const QModelIndex& idx) const
+QWidget* QCMakeCacheModelDelegate::createEditor(
+ QWidget* p, const QStyleOptionViewItem& /*option*/,
+ const QModelIndex& idx) const
{
QModelIndex var = idx.sibling(idx.row(), 0);
int type = var.data(QCMakeCacheModel::TypeRole).toInt();
- if(type == QCMakeProperty::BOOL)
- {
- return NULL;
- }
- else if(type == QCMakeProperty::PATH)
- {
+ if (type == QCMakeProperty::BOOL) {
+ return CM_NULLPTR;
+ }
+ if (type == QCMakeProperty::PATH) {
QCMakePathEditor* editor =
- new QCMakePathEditor(p,
- var.data(Qt::DisplayRole).toString());
+ new QCMakePathEditor(p, var.data(Qt::DisplayRole).toString());
QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
- SLOT(setFileDialogFlag(bool)));
+ SLOT(setFileDialogFlag(bool)));
return editor;
- }
- else if(type == QCMakeProperty::FILEPATH)
- {
+ }
+ if (type == QCMakeProperty::FILEPATH) {
QCMakeFilePathEditor* editor =
- new QCMakeFilePathEditor(p,
- var.data(Qt::DisplayRole).toString());
+ new QCMakeFilePathEditor(p, var.data(Qt::DisplayRole).toString());
QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
- SLOT(setFileDialogFlag(bool)));
+ SLOT(setFileDialogFlag(bool)));
return editor;
- }
- else if(type == QCMakeProperty::STRING &&
- var.data(QCMakeCacheModel::StringsRole).isValid())
- {
- QCMakeComboBox* editor =
- new QCMakeComboBox(p, var.data(QCMakeCacheModel::StringsRole).toStringList());
+ }
+ if (type == QCMakeProperty::STRING &&
+ var.data(QCMakeCacheModel::StringsRole).isValid()) {
+ QCMakeComboBox* editor = new QCMakeComboBox(
+ p, var.data(QCMakeCacheModel::StringsRole).toStringList());
editor->setFrame(false);
return editor;
- }
+ }
QLineEdit* editor = new QLineEdit(p);
editor->setFrame(false);
return editor;
}
-bool QCMakeCacheModelDelegate::editorEvent(QEvent* e, QAbstractItemModel* model,
- const QStyleOptionViewItem& option, const QModelIndex& index)
+bool QCMakeCacheModelDelegate::editorEvent(QEvent* e,
+ QAbstractItemModel* model,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index)
{
Qt::ItemFlags flags = model->flags(index);
- if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
- || !(flags & Qt::ItemIsEnabled))
- {
+ if (!(flags & Qt::ItemIsUserCheckable) ||
+ !(option.state & QStyle::State_Enabled) ||
+ !(flags & Qt::ItemIsEnabled)) {
return false;
- }
+ }
QVariant value = index.data(Qt::CheckStateRole);
- if (!value.isValid())
- {
+ if (!value.isValid()) {
return false;
- }
+ }
- if ((e->type() == QEvent::MouseButtonRelease)
- || (e->type() == QEvent::MouseButtonDblClick))
- {
+ if ((e->type() == QEvent::MouseButtonRelease) ||
+ (e->type() == QEvent::MouseButtonDblClick)) {
// eat the double click events inside the check rect
- if (e->type() == QEvent::MouseButtonDblClick)
- {
+ if (e->type() == QEvent::MouseButtonDblClick) {
return true;
- }
}
- else if (e->type() == QEvent::KeyPress)
- {
- if(static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
- static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select)
- {
+ } else if (e->type() == QEvent::KeyPress) {
+ if (static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
+ static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select) {
return false;
- }
}
- else
- {
+ } else {
return false;
- }
+ }
- Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
- ? Qt::Unchecked : Qt::Checked);
+ Qt::CheckState state =
+ (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked
+ : Qt::Checked);
bool success = model->setData(index, state, Qt::CheckStateRole);
- if(success)
- {
+ if (success) {
this->recordChange(model, index);
- }
+ }
return success;
}
@@ -673,29 +618,32 @@ bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
// 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
- if(evt->type() == QEvent::FocusOut && this->FileDialogFlag)
- {
+ if (evt->type() == QEvent::FocusOut && this->FileDialogFlag) {
return false;
- }
+ }
return QItemDelegate::eventFilter(object, evt);
}
void QCMakeCacheModelDelegate::setModelData(QWidget* editor,
- QAbstractItemModel* model, const QModelIndex& index ) const
+ QAbstractItemModel* model,
+ const QModelIndex& index) const
{
QItemDelegate::setModelData(editor, model, index);
const_cast<QCMakeCacheModelDelegate*>(this)->recordChange(model, index);
}
-QSize QCMakeCacheModelDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
+QSize QCMakeCacheModelDelegate::sizeHint(const QStyleOptionViewItem& option,
+ const QModelIndex& index) const
{
QSize sz = QItemDelegate::sizeHint(option, index);
- QStyle *style = QApplication::style();
+ QStyle* style = QApplication::style();
// increase to checkbox size
QStyleOptionButton opt;
opt.QStyleOption::operator=(option);
- sz = sz.expandedTo(style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, NULL).size());
+ sz = sz.expandedTo(
+ style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, CM_NULLPTR)
+ .size());
return sz;
}
@@ -710,30 +658,27 @@ void QCMakeCacheModelDelegate::clearChanges()
mChanges.clear();
}
-void QCMakeCacheModelDelegate::recordChange(QAbstractItemModel* model, const QModelIndex& index)
+void QCMakeCacheModelDelegate::recordChange(QAbstractItemModel* model,
+ const QModelIndex& index)
{
QModelIndex idx = index;
QAbstractItemModel* mymodel = model;
- while(qobject_cast<QAbstractProxyModel*>(mymodel))
- {
+ while (qobject_cast<QAbstractProxyModel*>(mymodel)) {
idx = static_cast<QAbstractProxyModel*>(mymodel)->mapToSource(idx);
mymodel = static_cast<QAbstractProxyModel*>(mymodel)->sourceModel();
- }
+ }
QCMakeCacheModel* cache_model = qobject_cast<QCMakeCacheModel*>(mymodel);
- if(cache_model && idx.isValid())
- {
+ if (cache_model && idx.isValid()) {
QCMakeProperty prop;
idx = idx.sibling(idx.row(), 0);
cache_model->getPropertyData(idx, prop);
// clean out an old one
QSet<QCMakeProperty>::iterator iter = mChanges.find(prop);
- if(iter != mChanges.end())
- {
+ if (iter != mChanges.end()) {
mChanges.erase(iter);
- }
+ }
// now add the new item
mChanges.insert(prop);
- }
+ }
}
-
diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h
index 41f0bd87c..c1debf590 100644
--- a/Source/QtDialog/QCMakeCacheView.h
+++ b/Source/QtDialog/QCMakeCacheView.h
@@ -1,23 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef QCMakeCacheView_h
#define QCMakeCacheView_h
#include "QCMake.h"
-#include <QTreeView>
+
+#include <QItemDelegate>
#include <QSet>
#include <QStandardItemModel>
-#include <QItemDelegate>
+#include <QTreeView>
class QSortFilterProxyModel;
class QCMakeCacheModel;
@@ -37,7 +28,7 @@ public:
// get whether to show advanced entries
bool showAdvanced() const;
- QSize sizeHint() const { return QSize(200,200); }
+ QSize sizeHint() const { return QSize(200, 200); }
public slots:
// set whether to show advanced entries
@@ -64,14 +55,20 @@ public:
// roles used to retrieve extra data such has help strings, types of
// properties, and the advanced flag
- enum { HelpRole = Qt::ToolTipRole,
- TypeRole = Qt::UserRole,
- AdvancedRole,
- StringsRole,
- GroupRole
- };
-
- enum ViewType { FlatView, GroupView };
+ enum
+ {
+ HelpRole = Qt::ToolTipRole,
+ TypeRole = Qt::UserRole,
+ AdvancedRole,
+ StringsRole,
+ GroupRole
+ };
+
+ enum ViewType
+ {
+ FlatView,
+ GroupView
+ };
public slots:
// set a list of properties. This list will be sorted and grouped according
@@ -91,9 +88,9 @@ public slots:
// insert a new property at a row specifying all the information about the
// property
- bool insertProperty(QCMakeProperty::PropertyType t,
- const QString& name, const QString& description,
- const QVariant& value, bool advanced);
+ bool insertProperty(QCMakeProperty::PropertyType t, const QString& name,
+ const QString& description, const QVariant& value,
+ bool advanced);
// set the view type
void setViewType(ViewType t);
@@ -110,12 +107,11 @@ public:
int newPropertyCount() const;
// return flags (overloaded to modify flag based on EditEnabled flag)
- Qt::ItemFlags flags (const QModelIndex& index) const;
+ Qt::ItemFlags flags(const QModelIndex& index) const;
QModelIndex buddy(const QModelIndex& idx) const;
// get the data in the model for this property
- void getPropertyData(const QModelIndex& idx1,
- QCMakeProperty& prop) const;
+ void getPropertyData(const QModelIndex& idx1, QCMakeProperty& prop) const;
protected:
bool EditEnabled;
@@ -124,17 +120,16 @@ protected:
ViewType View;
// set the data in the model for this property
- void setPropertyData(const QModelIndex& idx1,
- const QCMakeProperty& p, bool isNew);
+ void setPropertyData(const QModelIndex& idx1, const QCMakeProperty& p,
+ bool isNew);
// breaks up he property list into groups
// where each group has the same prefix up to the first underscore
static void breakProperties(const QSet<QCMakeProperty>& props,
- QMap<QString, QCMakePropertyList>& result);
+ QMap<QString, QCMakePropertyList>& result);
// gets the prefix of a string up to the first _
static QString prefix(const QString& s);
-
};
/// Qt delegate class for interaction (or other customization)
@@ -146,18 +141,22 @@ public:
QCMakeCacheModelDelegate(QObject* p);
/// create our own editors for cache properties
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,
- const QModelIndex& index ) const;
- bool editorEvent (QEvent* event, QAbstractItemModel* model,
- const QStyleOptionViewItem& option, const QModelIndex& index);
+ const QModelIndex& index) const;
+ bool editorEvent(QEvent* event, QAbstractItemModel* model,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index);
bool eventFilter(QObject* object, QEvent* event);
- void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const;
- QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
+ void setModelData(QWidget* editor, QAbstractItemModel* model,
+ const QModelIndex& index) const;
+ QSize sizeHint(const QStyleOptionViewItem& option,
+ const QModelIndex& index) const;
QSet<QCMakeProperty> changes() const;
void clearChanges();
protected slots:
void setFileDialogFlag(bool);
+
protected:
bool FileDialogFlag;
// record a change to an item in the model.
@@ -169,4 +168,3 @@ protected:
};
#endif
-
diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx
index a0c5e17fe..7f0cafa37 100644
--- a/Source/QtDialog/QCMakeWidgets.cxx
+++ b/Source/QtDialog/QCMakeWidgets.cxx
@@ -1,41 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "QCMakeWidgets.h"
#include <QDirModel>
-#include <QFileInfo>
#include <QFileDialog>
-#include <QToolButton>
+#include <QFileInfo>
#include <QResizeEvent>
+#include <QToolButton>
QCMakeFileEditor::QCMakeFileEditor(QWidget* p, const QString& var)
- : QLineEdit(p), Variable(var)
+ : QLineEdit(p)
+ , Variable(var)
{
this->ToolButton = new QToolButton(this);
this->ToolButton->setText("...");
this->ToolButton->setCursor(QCursor(Qt::ArrowCursor));
- QObject::connect(this->ToolButton, SIGNAL(clicked(bool)),
- this, SLOT(chooseFile()));
+ QObject::connect(this->ToolButton, SIGNAL(clicked(bool)), this,
+ SLOT(chooseFile()));
}
QCMakeFilePathEditor::QCMakeFilePathEditor(QWidget* p, const QString& var)
- : QCMakeFileEditor(p, var)
+ : QCMakeFileEditor(p, var)
{
this->setCompleter(new QCMakeFileCompleter(this, false));
}
QCMakePathEditor::QCMakePathEditor(QWidget* p, const QString& var)
- : QCMakeFileEditor(p, var)
+ : QCMakeFileEditor(p, var)
{
this->setCompleter(new QCMakeFileCompleter(this, true));
}
@@ -57,23 +48,21 @@ void QCMakeFilePathEditor::chooseFile()
QString path;
QFileInfo info(this->text());
QString title;
- if(this->Variable.isEmpty())
- {
+ if (this->Variable.isEmpty()) {
title = tr("Select File");
- }
- else
- {
+ } else {
title = tr("Select File for %1");
title = title.arg(this->Variable);
- }
- this->fileDialogExists(true);
- path = QFileDialog::getOpenFileName(this, title, info.absolutePath());
- this->fileDialogExists(false);
+ }
+ emit this->fileDialogExists(true);
+ path =
+ QFileDialog::getOpenFileName(this, title, info.absolutePath(), QString(),
+ CM_NULLPTR, QFileDialog::DontResolveSymlinks);
+ emit this->fileDialogExists(false);
- if(!path.isEmpty())
- {
+ if (!path.isEmpty()) {
this->setText(QDir::fromNativeSeparators(path));
- }
+ }
}
void QCMakePathEditor::chooseFile()
@@ -81,42 +70,38 @@ void QCMakePathEditor::chooseFile()
// choose a file and set it
QString path;
QString title;
- if(this->Variable.isEmpty())
- {
+ if (this->Variable.isEmpty()) {
title = tr("Select Path");
- }
- else
- {
+ } else {
title = tr("Select Path for %1");
title = title.arg(this->Variable);
- }
- this->fileDialogExists(true);
- path = QFileDialog::getExistingDirectory(this, title, this->text());
- this->fileDialogExists(false);
- if(!path.isEmpty())
- {
+ }
+ emit this->fileDialogExists(true);
+ path = QFileDialog::getExistingDirectory(this, title, this->text(),
+ QFileDialog::ShowDirsOnly |
+ QFileDialog::DontResolveSymlinks);
+ emit this->fileDialogExists(false);
+ if (!path.isEmpty()) {
this->setText(QDir::fromNativeSeparators(path));
- }
+ }
}
// use same QDirModel for all completers
static QDirModel* fileDirModel()
{
- static QDirModel* m = NULL;
- if(!m)
- {
+ static QDirModel* m = CM_NULLPTR;
+ if (!m) {
m = new QDirModel();
- }
+ }
return m;
}
static QDirModel* pathDirModel()
{
- static QDirModel* m = NULL;
- if(!m)
- {
+ static QDirModel* m = CM_NULLPTR;
+ if (!m) {
m = new QDirModel();
m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
- }
+ }
return m;
}
@@ -131,4 +116,3 @@ QString QCMakeFileCompleter::pathFromIndex(const QModelIndex& idx) const
{
return QDir::fromNativeSeparators(QCompleter::pathFromIndex(idx));
}
-
diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h
index 8f58df2bb..1ec666ff6 100644
--- a/Source/QtDialog/QCMakeWidgets.h
+++ b/Source/QtDialog/QCMakeWidgets.h
@@ -1,21 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef QCMakeWidgets_h
#define QCMakeWidgets_h
-#include <QLineEdit>
+#include "cmConfigure.h"
+
#include <QComboBox>
#include <QCompleter>
+#include <QLineEdit>
+
class QToolButton;
// common widgets for Qt based CMake
@@ -30,6 +23,7 @@ protected slots:
virtual void chooseFile() = 0;
signals:
void fileDialogExists(bool);
+
protected:
void resizeEvent(QResizeEvent* e);
QToolButton* ToolButton;
@@ -41,7 +35,7 @@ class QCMakePathEditor : public QCMakeFileEditor
{
Q_OBJECT
public:
- QCMakePathEditor(QWidget* p = NULL, const QString& var = QString());
+ QCMakePathEditor(QWidget* p = CM_NULLPTR, const QString& var = QString());
void chooseFile();
};
@@ -50,7 +44,8 @@ class QCMakeFilePathEditor : public QCMakeFileEditor
{
Q_OBJECT
public:
- QCMakeFilePathEditor(QWidget* p = NULL, const QString& var = QString());
+ QCMakeFilePathEditor(QWidget* p = CM_NULLPTR,
+ const QString& var = QString());
void chooseFile();
};
@@ -68,20 +63,20 @@ class QCMakeComboBox : public QComboBox
{
Q_OBJECT
Q_PROPERTY(QString value READ currentText WRITE setValue USER true);
+
public:
- QCMakeComboBox(QWidget* p, QStringList strings) : QComboBox(p)
+ QCMakeComboBox(QWidget* p, QStringList strings)
+ : QComboBox(p)
{
this->addItems(strings);
}
void setValue(const QString& v)
{
int i = this->findText(v);
- if(i != -1)
- {
+ if (i != -1) {
this->setCurrentIndex(i);
}
}
};
#endif
-
diff --git a/Source/QtDialog/QMacInstallDialog.cxx b/Source/QtDialog/QMacInstallDialog.cxx
deleted file mode 100644
index 8b8c5319f..000000000
--- a/Source/QtDialog/QMacInstallDialog.cxx
+++ /dev/null
@@ -1,121 +0,0 @@
-#include "QMacInstallDialog.h"
-#include <QMessageBox>
-#include "cmSystemTools.h"
-#include <iostream>
-#include <QFileDialog>
-#include "ui_MacInstallDialog.h"
-
-class QMacInstallDialog::QMacInstallDialogInternals : public Ui::Dialog
-{
-public:
-};
-
-QMacInstallDialog::QMacInstallDialog(QWidget*w)
- :QDialog(w)
-{
- this->Internals = new QMacInstallDialogInternals;
- this->Internals->setupUi(this);
- QObject::connect(this->Internals->choosePathButton, SIGNAL(pressed()),
- this, SLOT(ShowBrowser()));
- QObject::connect(this->Internals->skipInstallButton, SIGNAL(pressed()),
- this, SLOT(SkipInstall()));
- QObject::connect(this->Internals->doInstallButton, SIGNAL(pressed()),
- this, SLOT(DoInstall()));
- this->Internals->InstallPrefix->setText("/usr/bin/");
-
-}
-
-QMacInstallDialog::~QMacInstallDialog()
-{
- delete this->Internals;
-}
-
-void QMacInstallDialog::DoInstall()
-{
- QDir installDir(this->Internals->InstallPrefix->text());
- QString installTo = installDir.path();
- if(!cmSystemTools::FileExists(installTo.toLocal8Bit().data()))
- {
- QString message = tr("Build install does not exist, "
- "should I create it?\n\n"
- "Directory: ");
- message += installDir.path();
- QString title = tr("Create Directory");
- QMessageBox::StandardButton btn;
- btn = QMessageBox::information(this, title, message,
- QMessageBox::Yes | QMessageBox::No);
- if(btn == QMessageBox::Yes)
- {
- cmSystemTools::MakeDirectory(installTo.toLocal8Bit().data());
- }
- }
- QDir cmExecDir(QApplication::applicationDirPath());
- cmExecDir.cd("../bin");
- QFileInfoList list = cmExecDir.entryInfoList();
- for (int i = 0; i < list.size(); ++i)
- {
- QFileInfo fileInfo = list.at(i);
- QString filename = fileInfo.fileName();
- if(filename.size() && filename[0] == '.')
- {
- continue;
- }
- QString file = fileInfo.absoluteFilePath();
- QString newName = installTo;
- newName += "/";
- newName += filename;
- // Remove the old files
- if(cmSystemTools::FileExists(newName.toLocal8Bit().data()))
- {
- std::cout << "rm [" << newName.toLocal8Bit().data() << "]\n";
- if(!cmSystemTools::RemoveFile(newName.toLocal8Bit().data()))
- {
- QString message = tr("Failed to remove file "
- "installation may be incomplete: ");
- message += newName;
- QString title = tr("Error Removing file");
- QMessageBox::StandardButton btn =
- QMessageBox::critical(this, title, message,
- QMessageBox::Ok|QMessageBox::Abort);
- if(btn == QMessageBox::Abort)
- {
- return;
- }
- }
- }
- std::cout << "ln -s [" << file.toLocal8Bit().data() << "] [";
- std::cout << newName.toLocal8Bit().data() << "]\n";
- if(!cmSystemTools::CreateSymlink(file.toLocal8Bit().data(),
- newName.toLocal8Bit().data()))
- {
- QString message = tr("Failed create symlink "
- "installation may be incomplete: ");
- message += newName;
- QString title = tr("Error Creating Symlink");
- QMessageBox::StandardButton btn =
- QMessageBox::critical(this, title, message,
- QMessageBox::Ok|QMessageBox::Abort);
- if(btn == QMessageBox::Abort)
- {
- return;
- }
- }
- }
- this->done(0);
-}
-
-void QMacInstallDialog::SkipInstall()
-{
- this->done(0);
-}
-
-
-void QMacInstallDialog::ShowBrowser()
-{
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Enter Install Prefix"), this->Internals->InstallPrefix->text());
- if(!dir.isEmpty())
- {
- this->Internals->InstallPrefix->setText(dir);
- }
-}
diff --git a/Source/QtDialog/QMacInstallDialog.h b/Source/QtDialog/QMacInstallDialog.h
deleted file mode 100644
index efe67dfaf..000000000
--- a/Source/QtDialog/QMacInstallDialog.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef QMacInstallDialog_h
-#define QMacInstallDialog_h
-#include <QDialog>
-
-class QMacInstallDialog : public QDialog
-{
- Q_OBJECT;
-public:
- QMacInstallDialog(QWidget*w);
- ~QMacInstallDialog();
-private slots:
- void ShowBrowser();
- void SkipInstall();
- void DoInstall();
-private:
- class QMacInstallDialogInternals;
- QMacInstallDialogInternals* Internals;
-};
-
-#endif
diff --git a/Source/QtDialog/QtDialogCPack.cmake.in b/Source/QtDialog/QtDialogCPack.cmake.in
index 3196471d7..7ae860548 100644
--- a/Source/QtDialog/QtDialogCPack.cmake.in
+++ b/Source/QtDialog/QtDialogCPack.cmake.in
@@ -9,9 +9,6 @@ if(CMAKE_PACKAGE_QTGUI)
# / and then install
# cmake into the bundle for cmake-gui and must use DESTDIR
set(CPACK_SET_DESTDIR TRUE)
- # we also want to run post install stuff to setup command line
- set(CPACK_POSTFLIGHT_SCRIPT "@CMAKE_POSTFLIGHT_SCRIPT@")
- set(CPACK_POSTUPGRADE_SCRIPT "@CMAKE_POSTUPGRADE_SCRIPT@")
endif()
endif()
diff --git a/Source/QtDialog/RegexExplorer.cxx b/Source/QtDialog/RegexExplorer.cxx
new file mode 100644
index 000000000..abed70e90
--- /dev/null
+++ b/Source/QtDialog/RegexExplorer.cxx
@@ -0,0 +1,166 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "RegexExplorer.h"
+
+RegexExplorer::RegexExplorer(QWidget* p)
+ : QDialog(p)
+ , m_matched(false)
+{
+ this->setupUi(this);
+
+ for (int i = 1; i < cmsys::RegularExpression::NSUBEXP; ++i) {
+ matchNumber->addItem(QString("Match %1").arg(QString::number(i)),
+ QVariant(i));
+ }
+ matchNumber->setCurrentIndex(0);
+}
+
+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);
+ widget->setPalette(palette);
+}
+
+void RegexExplorer::on_regularExpression_textChanged(const QString& text)
+{
+#ifdef QT_NO_STL
+ m_regex = text.toAscii().constData();
+#else
+ m_regex = text.toStdString();
+#endif
+
+ bool validExpression =
+ stripEscapes(m_regex) && m_regexParser.compile(m_regex);
+ if (!validExpression) {
+ m_regexParser.set_invalid();
+ }
+
+ setStatusColor(labelRegexValid, validExpression);
+
+ on_inputText_textChanged();
+}
+
+void RegexExplorer::on_inputText_textChanged()
+{
+ if (m_regexParser.is_valid()) {
+ QString plainText = inputText->toPlainText();
+#ifdef QT_NO_STL
+ m_text = plainText.toAscii().constData();
+#else
+ m_text = plainText.toStdString();
+#endif
+ m_matched = m_regexParser.find(m_text);
+ } else {
+ m_matched = false;
+ }
+
+ setStatusColor(labelRegexMatch, m_matched);
+
+ if (!m_matched) {
+ clearMatch();
+ return;
+ }
+
+ std::string matchingText;
+
+ if (matchAll->isChecked()) {
+ const char* p = m_text.c_str();
+ while (m_regexParser.find(p)) {
+ std::string::size_type l = m_regexParser.start();
+ std::string::size_type r = m_regexParser.end();
+ if (r - l == 0) {
+ // matched empty string
+ clearMatch();
+ return;
+ }
+ if (!matchingText.empty()) {
+ matchingText += ";";
+ }
+ matchingText += std::string(p + l, r - l);
+ p += r;
+ }
+ } else {
+ matchingText = m_regexParser.match(0);
+ }
+
+#ifdef QT_NO_STL
+ QString matchText = matchingText.c_str();
+#else
+ QString matchText = QString::fromStdString(matchingText);
+#endif
+ match0->setPlainText(matchText);
+
+ on_matchNumber_currentIndexChanged(matchNumber->currentIndex());
+}
+
+void RegexExplorer::on_matchNumber_currentIndexChanged(int index)
+{
+ if (!m_matched) {
+ return;
+ }
+
+ QVariant itemData = matchNumber->itemData(index);
+ int idx = itemData.toInt();
+
+ if (idx < 1 || idx >= cmsys::RegularExpression::NSUBEXP) {
+ return;
+ }
+
+#ifdef QT_NO_STL
+ QString match = m_regexParser.match(idx).c_str();
+#else
+ QString match = QString::fromStdString(m_regexParser.match(idx));
+#endif
+ matchN->setPlainText(match);
+}
+
+void RegexExplorer::on_matchAll_toggled(bool checked)
+{
+ Q_UNUSED(checked);
+
+ on_inputText_textChanged();
+}
+
+void RegexExplorer::clearMatch()
+{
+ m_matched = false;
+ match0->clear();
+ matchN->clear();
+}
+
+bool RegexExplorer::stripEscapes(std::string& source)
+{
+ const char* in = source.c_str();
+
+ std::string result;
+ result.reserve(source.size());
+
+ for (char inc = *in; inc != '\0'; inc = *++in) {
+ if (inc == '\\') {
+ char nextc = in[1];
+ if (nextc == 't') {
+ result.append(1, '\t');
+ in++;
+ } else if (nextc == 'n') {
+ result.append(1, '\n');
+ in++;
+ } else if (nextc == 't') {
+ result.append(1, '\t');
+ in++;
+ } else if (isalnum(nextc) || nextc == '\0') {
+ return false;
+ } else {
+ result.append(1, nextc);
+ in++;
+ }
+ } else {
+ result.append(1, inc);
+ }
+ }
+
+ source = result;
+ return true;
+}
diff --git a/Source/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h
new file mode 100644
index 000000000..867989279
--- /dev/null
+++ b/Source/QtDialog/RegexExplorer.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 RegexExplorer_h
+#define RegexExplorer_h
+
+#include "cmsys/RegularExpression.hxx"
+#include <QDialog>
+#include <string>
+
+#include "ui_RegexExplorer.h"
+
+class QString;
+class QWidget;
+
+class RegexExplorer : public QDialog, public Ui::RegexExplorer
+{
+ Q_OBJECT
+public:
+ RegexExplorer(QWidget* p);
+
+private slots:
+ void on_regularExpression_textChanged(const QString& text);
+ void on_inputText_textChanged();
+ void on_matchNumber_currentIndexChanged(int index);
+ void on_matchAll_toggled(bool checked);
+
+private:
+ static void setStatusColor(QWidget* widget, bool successful);
+ static bool stripEscapes(std::string& regex);
+
+ void clearMatch();
+
+ cmsys::RegularExpression m_regexParser;
+ std::string m_text;
+ std::string m_regex;
+ bool m_matched;
+};
+
+#endif
diff --git a/Source/QtDialog/RegexExplorer.ui b/Source/QtDialog/RegexExplorer.ui
new file mode 100644
index 000000000..0af69999c
--- /dev/null
+++ b/Source/QtDialog/RegexExplorer.ui
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RegexExplorer</class>
+ <widget class="QDialog" name="RegexExplorer">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>639</width>
+ <height>555</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Regular Expression Explorer</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Input Text</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="inputText"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Regular Expression</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelRegexValid">
+ <property name="text">
+ <string>Valid</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelRegexMatch">
+ <property name="text">
+ <string>Match</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="regularExpression"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Complete Match</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="matchAll">
+ <property name="text">
+ <string>Match All</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="match0">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="matchNumber">
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="matchN">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Source/QtDialog/WarningMessagesDialog.cxx b/Source/QtDialog/WarningMessagesDialog.cxx
new file mode 100644
index 000000000..f608a84f9
--- /dev/null
+++ b/Source/QtDialog/WarningMessagesDialog.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 "WarningMessagesDialog.h"
+
+WarningMessagesDialog::WarningMessagesDialog(QWidget* prnt, QCMake* instance)
+ : QDialog(prnt)
+ , cmakeInstance(instance)
+{
+ this->setupUi(this);
+ this->setInitialValues();
+ this->setupSignals();
+}
+
+void WarningMessagesDialog::setInitialValues()
+{
+ this->suppressDeveloperWarnings->setChecked(
+ this->cmakeInstance->getSuppressDevWarnings());
+ this->suppressDeprecatedWarnings->setChecked(
+ this->cmakeInstance->getSuppressDeprecatedWarnings());
+
+ this->developerWarningsAsErrors->setChecked(
+ this->cmakeInstance->getDevWarningsAsErrors());
+ this->deprecatedWarningsAsErrors->setChecked(
+ this->cmakeInstance->getDeprecatedWarningsAsErrors());
+}
+
+void WarningMessagesDialog::setupSignals()
+{
+ QObject::connect(this->buttonBox, SIGNAL(accepted()), this,
+ SLOT(doAccept()));
+
+ QObject::connect(this->suppressDeveloperWarnings, SIGNAL(stateChanged(int)),
+ this, SLOT(doSuppressDeveloperWarningsChanged(int)));
+ QObject::connect(this->suppressDeprecatedWarnings, SIGNAL(stateChanged(int)),
+ this, SLOT(doSuppressDeprecatedWarningsChanged(int)));
+
+ QObject::connect(this->developerWarningsAsErrors, SIGNAL(stateChanged(int)),
+ this, SLOT(doDeveloperWarningsAsErrorsChanged(int)));
+ QObject::connect(this->deprecatedWarningsAsErrors, SIGNAL(stateChanged(int)),
+ this, SLOT(doDeprecatedWarningsAsErrorsChanged(int)));
+}
+
+void WarningMessagesDialog::doAccept()
+{
+ this->cmakeInstance->setSuppressDevWarnings(
+ this->suppressDeveloperWarnings->isChecked());
+ this->cmakeInstance->setSuppressDeprecatedWarnings(
+ this->suppressDeprecatedWarnings->isChecked());
+
+ this->cmakeInstance->setDevWarningsAsErrors(
+ this->developerWarningsAsErrors->isChecked());
+ this->cmakeInstance->setDeprecatedWarningsAsErrors(
+ this->deprecatedWarningsAsErrors->isChecked());
+}
+
+void WarningMessagesDialog::doSuppressDeveloperWarningsChanged(int state)
+{
+ // no warnings implies no errors either
+ if (state) {
+ this->developerWarningsAsErrors->setChecked(false);
+ }
+}
+
+void WarningMessagesDialog::doSuppressDeprecatedWarningsChanged(int state)
+{
+ // no warnings implies no errors either
+ if (state) {
+ this->deprecatedWarningsAsErrors->setChecked(false);
+ }
+}
+
+void WarningMessagesDialog::doDeveloperWarningsAsErrorsChanged(int state)
+{
+ // warnings as errors implies warnings are not suppressed
+ if (state) {
+ this->suppressDeveloperWarnings->setChecked(false);
+ }
+}
+
+void WarningMessagesDialog::doDeprecatedWarningsAsErrorsChanged(int state)
+{
+ // warnings as errors implies warnings are not suppressed
+ if (state) {
+ this->suppressDeprecatedWarnings->setChecked(false);
+ }
+}
diff --git a/Source/QtDialog/WarningMessagesDialog.h b/Source/QtDialog/WarningMessagesDialog.h
new file mode 100644
index 000000000..acb830d85
--- /dev/null
+++ b/Source/QtDialog/WarningMessagesDialog.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 WarningMessagesDialog_h
+#define WarningMessagesDialog_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
+{
+ Q_OBJECT
+
+public:
+ WarningMessagesDialog(QWidget* prnt, QCMake* instance);
+
+private slots:
+ /**
+ * Handler for the accept event of the ok/cancel button box.
+ */
+ void doAccept();
+
+ /**
+ * Handler for checked state changed event of the suppress developer warnings
+ * checkbox.
+ */
+ void doSuppressDeveloperWarningsChanged(int state);
+ /**
+ * Handler for checked state changed event of the suppress deprecated
+ * warnings checkbox.
+ */
+ void doSuppressDeprecatedWarningsChanged(int state);
+
+ /**
+ * Handler for checked state changed event of the developer warnings as
+ * errors checkbox.
+ */
+ void doDeveloperWarningsAsErrorsChanged(int state);
+ /**
+ * Handler for checked state changed event of the deprecated warnings as
+ * errors checkbox.
+ */
+ void doDeprecatedWarningsAsErrorsChanged(int state);
+
+private:
+ QCMake* cmakeInstance;
+
+ /**
+ * Set the initial values of the widgets on this dialog window, using the
+ * current state of the cache.
+ */
+ void setInitialValues();
+
+ /**
+ * Setup the signals for the widgets on this dialog window.
+ */
+ void setupSignals();
+};
+
+#endif /* MessageDialog_h */
diff --git a/Source/QtDialog/WarningMessagesDialog.ui b/Source/QtDialog/WarningMessagesDialog.ui
new file mode 100644
index 000000000..3b35cbc67
--- /dev/null
+++ b/Source/QtDialog/WarningMessagesDialog.ui
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MessagesDialog</class>
+ <widget class="QDialog" name="MessagesDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Warning Messages</string>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Suppress Warnings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="suppressDeveloperWarnings">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Suppress developer (author) warnings.</string>
+ </property>
+ <property name="text">
+ <string>Developer Warnings</string>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="suppressDeprecatedWarnings">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Suppress deprecated warnings.</string>
+ </property>
+ <property name="text">
+ <string>Deprecated Warnings</string>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Warnings as Errors</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="developerWarningsAsErrors">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Treat developer (author) warnings as errors.</string>
+ </property>
+ <property name="text">
+ <string>Developer Warnings as Errors</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="deprecatedWarningsAsErrors">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Treat deprecated warnings as errors.</string>
+ </property>
+ <property name="text">
+ <string>Deprecated Warnings as Errors</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>MessagesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>MessagesDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/Source/QtDialog/CMake.desktop b/Source/QtDialog/cmake-gui.desktop
index 645eb76e9..842091f5b 100644
--- a/Source/QtDialog/CMake.desktop
+++ b/Source/QtDialog/cmake-gui.desktop
@@ -3,7 +3,7 @@ Version=1.0
Name=CMake
Comment=Cross-platform buildsystem
Exec=cmake-gui %f
-Icon=CMakeSetup32.png
+Icon=CMakeSetup
Terminal=false
X-MultipleArgs=false
Type=Application
diff --git a/Source/QtDialog/postflight.sh.in b/Source/QtDialog/postflight.sh.in
deleted file mode 100755
index 33be35206..000000000
--- a/Source/QtDialog/postflight.sh.in
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-"$2@CMAKE_INSTALL_SUBDIR@/@CMAKE_BUNDLE_NAME@.app/Contents/MacOS/@CMAKE_BUNDLE_NAME@" --mac-install
-exit 0
diff --git a/Source/QtDialog/postupgrade.sh.in b/Source/QtDialog/postupgrade.sh.in
deleted file mode 100755
index 06bd98656..000000000
--- a/Source/QtDialog/postupgrade.sh.in
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-exit 0
diff --git a/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in b/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in
new file mode 100644
index 000000000..8cc583542
--- /dev/null
+++ b/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in
@@ -0,0 +1,21 @@
+// Component: CMake.Reference.DoxygenHTML
+
+function Component()
+{
+ // Default constructor
+}
+
+Component.prototype.createOperations = function()
+{
+ // Create shortcut
+ if (installer.value("os") === "win") {
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/%CMAKE_DOC_DIR%/developer-reference/html/index.html",
+ "@StartMenuDir@/CMake Developer Reference.lnk");
+
+ }
+
+ // Call default implementation
+ component.createOperations();
+}
diff --git a/Source/QtIFW/CMake.Dialogs.QtGUI.qs.in b/Source/QtIFW/CMake.Dialogs.QtGUI.qs.in
new file mode 100644
index 000000000..71f395ac0
--- /dev/null
+++ b/Source/QtIFW/CMake.Dialogs.QtGUI.qs.in
@@ -0,0 +1,21 @@
+// Component: CMake.Dialogs.QtGUI
+
+function Component()
+{
+ // Default constructor
+}
+
+Component.prototype.createOperations = function()
+{
+ // Create shortcut
+ if (installer.value("os") === "win") {
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/%CMAKE_BIN_DIR%/cmake-gui.exe",
+ "@StartMenuDir@/CMake (cmake-gui).lnk");
+
+ }
+
+ // Call default implementation
+ component.createOperations();
+}
diff --git a/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in b/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in
new file mode 100644
index 000000000..54bc14ae9
--- /dev/null
+++ b/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in
@@ -0,0 +1,21 @@
+// Component: CMake.Documentation.SphinxHTML
+
+function Component()
+{
+ // Default constructor
+}
+
+Component.prototype.createOperations = function()
+{
+ // Create shortcut
+ if (installer.value("os") === "win") {
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/%CMAKE_DOC_DIR%/html/index.html",
+ "@StartMenuDir@/CMake Documentation.lnk");
+
+ }
+
+ // Call default implementation
+ component.createOperations();
+}
diff --git a/Source/QtIFW/CMake.qs.in b/Source/QtIFW/CMake.qs.in
new file mode 100644
index 000000000..1f3166ebb
--- /dev/null
+++ b/Source/QtIFW/CMake.qs.in
@@ -0,0 +1,24 @@
+// Component: CMake
+
+function Component()
+{
+ // Default constructor
+}
+
+Component.prototype.createOperations = function()
+{
+ // Create shortcut
+ if (installer.value("os") === "win") {
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/%CMAKE_DOC_DIR%/cmake.org.html",
+ "@StartMenuDir@/CMake Web Site.lnk");
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/cmake-maintenance.exe",
+ "@StartMenuDir@/CMake Maintenance Tool.lnk");
+ }
+
+ // Call default implementation
+ component.createOperations();
+}
diff --git a/Source/QtIFW/cmake.org.html b/Source/QtIFW/cmake.org.html
new file mode 100644
index 000000000..001d6342b
--- /dev/null
+++ b/Source/QtIFW/cmake.org.html
@@ -0,0 +1,7 @@
+<html>
+<head>
+<meta http-equiv="Refresh" content="0; url=https://cmake.org/" />
+</head>
+<body>
+</body>
+</html>
diff --git a/Source/QtIFW/controlscript.qs b/Source/QtIFW/controlscript.qs
new file mode 100644
index 000000000..d1a9b102a
--- /dev/null
+++ b/Source/QtIFW/controlscript.qs
@@ -0,0 +1,6 @@
+// controlscript.qs - CMake installation control script
+
+function Controller()
+{
+ // do nothing now
+}
diff --git a/Source/QtIFW/installscript.qs.in b/Source/QtIFW/installscript.qs.in
new file mode 100644
index 000000000..72d49e84c
--- /dev/null
+++ b/Source/QtIFW/installscript.qs.in
@@ -0,0 +1,27 @@
+// Component: CMake
+
+function Component()
+{
+ // Do not show component selection page
+ installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
+}
+
+Component.prototype.createOperations = function()
+{
+ // Create shortcut
+ if (installer.value("os") === "win") {
+
+%_CPACK_IFW_SHORTCUT_OPTIONAL%
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/%CMAKE_DOC_DIR%/cmake.org.html",
+ "@StartMenuDir@/CMake Web Site.lnk");
+
+ component.addOperation("CreateShortcut",
+ "@TargetDir@/cmake-maintenance.exe",
+ "@StartMenuDir@/CMake Maintenance Tool.lnk");
+ }
+
+ // Call default implementation
+ component.createOperations();
+}
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
new file mode 100644
index 000000000..e96226a4b
--- /dev/null
+++ b/Source/bindexplib.cxx
@@ -0,0 +1,405 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+/*-------------------------------------------------------------------------
+ Portions of this source have been derived from the 'bindexplib' tool
+ provided by the CERN ROOT Data Analysis Framework project (root.cern.ch).
+ Permission has been granted by Pere Mato <pere.mato@cern.ch> to distribute
+ this derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+*----------------------------------------------------------------------
+* 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,
+ * 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)
+*----------------------------------------------------------------------
+*/
+#include "bindexplib.h"
+
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include <iostream>
+#include <windows.h>
+
+#ifndef IMAGE_FILE_MACHINE_ARMNT
+#define IMAGE_FILE_MACHINE_ARMNT 0x01c4
+#endif
+
+typedef struct cmANON_OBJECT_HEADER_BIGOBJ
+{
+ /* same as ANON_OBJECT_HEADER_V2 */
+ WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
+ WORD Sig2; // Must be 0xffff
+ WORD Version; // >= 2 (implies the Flags field is present)
+ WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx
+ DWORD TimeDateStamp;
+ CLSID ClassID; // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}
+ DWORD SizeOfData; // Size of data that follows the header
+ DWORD Flags; // 0x1 -> contains metadata
+ DWORD MetaDataSize; // Size of CLR metadata
+ DWORD MetaDataOffset; // Offset of CLR metadata
+
+ /* bigobj specifics */
+ DWORD NumberOfSections; // extended from WORD
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+} cmANON_OBJECT_HEADER_BIGOBJ;
+
+typedef struct _cmIMAGE_SYMBOL_EX
+{
+ union
+ {
+ BYTE ShortName[8];
+ struct
+ {
+ DWORD Short; // if 0, use LongName
+ DWORD Long; // offset into string table
+ } Name;
+ DWORD LongName[2]; // PBYTE [2]
+ } N;
+ DWORD Value;
+ LONG SectionNumber;
+ WORD Type;
+ BYTE StorageClass;
+ BYTE NumberOfAuxSymbols;
+} cmIMAGE_SYMBOL_EX;
+typedef cmIMAGE_SYMBOL_EX UNALIGNED* cmPIMAGE_SYMBOL_EX;
+
+PIMAGE_SECTION_HEADER GetSectionHeaderOffset(
+ PIMAGE_FILE_HEADER pImageFileHeader)
+{
+ return (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageFileHeader +
+ IMAGE_SIZEOF_FILE_HEADER +
+ pImageFileHeader->SizeOfOptionalHeader);
+}
+
+PIMAGE_SECTION_HEADER GetSectionHeaderOffset(
+ cmANON_OBJECT_HEADER_BIGOBJ* pImageFileHeader)
+{
+ return (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageFileHeader +
+ sizeof(cmANON_OBJECT_HEADER_BIGOBJ));
+}
+
+/*
++ * Utility func, strstr with size
++ */
+const char* StrNStr(const char* start, const char* find, size_t& size)
+{
+ size_t len;
+ const char* hint;
+
+ if (!start || !find || !size) {
+ size = 0;
+ return 0;
+ }
+ len = strlen(find);
+
+ while ((hint = (const char*)memchr(start, find[0], size - len + 1))) {
+ size -= (hint - start);
+ if (!strncmp(hint, find, len))
+ return hint;
+ start = hint + 1;
+ }
+
+ size = 0;
+ return 0;
+}
+
+template <
+ // cmANON_OBJECT_HEADER_BIGOBJ or IMAGE_FILE_HEADER
+ class ObjectHeaderType,
+ // cmPIMAGE_SYMBOL_EX or PIMAGE_SYMBOL
+ class SymbolTableType>
+class DumpSymbols
+{
+public:
+ /*
+ *----------------------------------------------------------------------
+ * Constructor --
+ *
+ * Initialize variables from pointer to object header.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ DumpSymbols(ObjectHeaderType* ih, std::set<std::string>& symbols,
+ std::set<std::string>& dataSymbols, bool isI386)
+ : Symbols(symbols)
+ , DataSymbols(dataSymbols)
+ {
+ this->ObjectImageHeader = ih;
+ this->SymbolTable =
+ (SymbolTableType*)((DWORD_PTR) this->ObjectImageHeader +
+ this->ObjectImageHeader->PointerToSymbolTable);
+ this->SectionHeaders = GetSectionHeaderOffset(this->ObjectImageHeader);
+ this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
+ this->IsI386 = isI386;
+ }
+
+ /*
+ *----------------------------------------------------------------------
+ * DumpObjFile --
+ *
+ * Dump an object file's exported symbols.
+ *----------------------------------------------------------------------
+ */
+ void DumpObjFile() { this->DumpExternalsObjects(); }
+
+ /*
+ *----------------------------------------------------------------------
+ * DumpExternalsObjects --
+ *
+ * Dumps a COFF symbol table from an OBJ.
+ *----------------------------------------------------------------------
+ */
+ void DumpExternalsObjects()
+ {
+ unsigned i;
+ PSTR stringTable;
+ std::string symbol;
+ DWORD SectChar;
+ /*
+ * The string table apparently starts right after the symbol table
+ */
+ stringTable = (PSTR) & this->SymbolTable[this->SymbolCount];
+ SymbolTableType* pSymbolTable = this->SymbolTable;
+ for (i = 0; i < this->SymbolCount; i++) {
+ if (pSymbolTable->SectionNumber > 0 &&
+ (pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
+ if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
+ /*
+ * The name of the Function entry points
+ */
+ if (pSymbolTable->N.Name.Short != 0) {
+ symbol = "";
+ symbol.insert(0, (const char*)pSymbolTable->N.ShortName, 8);
+ } else {
+ symbol = stringTable + pSymbolTable->N.Name.Long;
+ }
+
+ // clear out any leading spaces
+ while (isspace(symbol[0]))
+ symbol.erase(0, 1);
+ // if it starts with _ and has an @ then it is a __cdecl
+ // so remove the @ stuff for the export
+ if (symbol[0] == '_') {
+ std::string::size_type posAt = symbol.find('@');
+ if (posAt != std::string::npos) {
+ symbol.erase(posAt);
+ }
+ }
+ // For i386 builds we need to remove _
+ if (this->IsI386 && symbol[0] == '_') {
+ symbol.erase(0, 1);
+ }
+
+ // Check whether it is "Scalar deleting destructor" and "Vector
+ // deleting destructor"
+ // if scalarPrefix and vectorPrefix are not found then print
+ // the symbol
+ const char* scalarPrefix = "??_G";
+ const char* vectorPrefix = "??_E";
+ // The original code had a check for
+ // symbol.find("real@") == std::string::npos)
+ // but this disallows member functions with the name "real".
+ if (symbol.compare(0, 4, scalarPrefix) &&
+ symbol.compare(0, 4, vectorPrefix)) {
+ SectChar = this->SectionHeaders[pSymbolTable->SectionNumber - 1]
+ .Characteristics;
+ // skip symbols containing a dot
+ if (symbol.find('.') == std::string::npos) {
+ if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) {
+ // Read only (i.e. constants) must be excluded
+ this->DataSymbols.insert(symbol);
+ } else {
+ if (pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ) ||
+ (SectChar & IMAGE_SCN_MEM_EXECUTE)) {
+ this->Symbols.insert(symbol);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Take into account any aux symbols
+ */
+ i += pSymbolTable->NumberOfAuxSymbols;
+ pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
+ pSymbolTable++;
+ }
+ }
+
+private:
+ std::set<std::string>& Symbols;
+ std::set<std::string>& DataSymbols;
+ DWORD_PTR SymbolCount;
+ PIMAGE_SECTION_HEADER SectionHeaders;
+ ObjectHeaderType* ObjectImageHeader;
+ SymbolTableType* SymbolTable;
+ bool IsI386;
+};
+
+bool DumpFile(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,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename);
+ return false;
+ }
+
+ hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (hFileMapping == 0) {
+ CloseHandle(hFile);
+ fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
+ return false;
+ }
+
+ lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
+ if (lpFileBase == 0) {
+ CloseHandle(hFileMapping);
+ CloseHandle(hFile);
+ fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
+ return false;
+ }
+
+ 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));
+ symbolDumper.DumpObjFile();
+ } else {
+ printf("unrecognized file format in '%s'\n", filename);
+ return false;
+ }
+ }
+ UnmapViewOfFile(lpFileBase);
+ CloseHandle(hFileMapping);
+ CloseHandle(hFile);
+ return true;
+}
+
+bool bindexplib::AddObjectFile(const char* filename)
+{
+ return DumpFile(filename, this->Symbols, this->DataSymbols);
+}
+
+bool bindexplib::AddDefinitionFile(const char* filename)
+{
+ cmsys::ifstream infile(filename);
+ if (!infile) {
+ fprintf(stderr, "Couldn't open definition file '%s'\n", filename);
+ return false;
+ }
+ std::string str;
+ while (std::getline(infile, str)) {
+ // skip the LIBRAY and EXPORTS lines (if any)
+ if ((str.compare(0, 7, "LIBRARY") == 0) ||
+ (str.compare(0, 7, "EXPORTS") == 0)) {
+ continue;
+ }
+ // remove leading tabs & spaces
+ str.erase(0, str.find_first_not_of(" \t"));
+ std::size_t found = str.find(" \t DATA");
+ if (found != std::string::npos) {
+ str.erase(found, std::string::npos);
+ this->DataSymbols.insert(str);
+ } else {
+ this->Symbols.insert(str);
+ }
+ }
+ infile.close();
+ return true;
+}
+
+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::set<std::string>::const_iterator i = this->Symbols.begin();
+ i != this->Symbols.end(); ++i) {
+ fprintf(file, "\t%s\n", i->c_str());
+ }
+}
diff --git a/Source/bindexplib.h b/Source/bindexplib.h
new file mode 100644
index 000000000..bc904e9f8
--- /dev/null
+++ b/Source/bindexplib.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 bindexplib_h
+#define bindexplib_h
+
+#include "cmConfigure.h"
+
+#include <set>
+#include <stdio.h>
+#include <string>
+
+class bindexplib
+{
+public:
+ bindexplib() {}
+ bool AddDefinitionFile(const char* filename);
+ bool AddObjectFile(const char* filename);
+ void WriteFile(FILE* file);
+
+private:
+ std::set<std::string> Symbols;
+ std::set<std::string> DataSymbols;
+};
+#endif
diff --git a/Source/cmAddCompileOptionsCommand.cxx b/Source/cmAddCompileOptionsCommand.cxx
index a6c3c005c..21a8012d8 100644
--- a/Source/cmAddCompileOptionsCommand.cxx
+++ b/Source/cmAddCompileOptionsCommand.cxx
@@ -1,28 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddCompileOptionsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAddCompileOptionsCommand.h"
+class cmExecutionStatus;
-bool cmAddCompileOptionsCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddCompileOptionsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
- for(std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
this->Makefile->AddCompileOption(i->c_str());
- }
+ }
return true;
}
diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h
index e9bbf2816..297f901db 100644
--- a/Source/cmAddCompileOptionsCommand.h
+++ b/Source/cmAddCompileOptionsCommand.h
@@ -1,19 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAddCompileOptionsCommand_h
#define cmAddCompileOptionsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmDocumentGeneratorExpressions.h"
+
+class cmExecutionStatus;
class cmAddCompileOptionsCommand : public cmCommand
{
@@ -21,51 +18,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddCompileOptionsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddCompileOptionsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "add_compile_options";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Adds options to the compilation of source files.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_compile_options(<option> ...)\n"
- "Adds options to the compiler command line for sources in the "
- "current directory and below. This command can be used to add any "
- "options, but alternative commands exist to add preprocessor "
- "definitions or include directories. "
- "See documentation of the directory and target COMPILE_OPTIONS "
- "properties for details. "
- "Arguments to add_compile_options may use \"generator "
- "expressions\" with the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- ;
- }
-
- cmTypeMacro(cmAddCompileOptionsCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
#endif
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 56348494d..b5e7c9ea9 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -1,40 +1,42 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddCustomCommandCommand.h"
-#include "cmTarget.h"
+#include <sstream>
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmSourceFile.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::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
/* 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.");
- return false;
- }
+ if (args.size() < 4) {
+ this->SetError("called with wrong number of arguments.");
+ return false;
+ }
- std::string source, target, main_dependency, working;
+ std::string source, target, main_dependency, working, depfile;
std::string comment_buffer;
- const char* comment = 0;
- std::vector<std::string> depends, outputs, output;
+ const char* comment = CM_NULLPTR;
+ std::vector<std::string> depends, outputs, output, 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;
@@ -46,7 +48,8 @@ bool cmAddCustomCommandCommand
cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
- enum tdoing {
+ enum tdoing
+ {
doing_source,
doing_command,
doing_target,
@@ -56,97 +59,76 @@ bool cmAddCustomCommandCommand
doing_main_dependency,
doing_output,
doing_outputs,
+ doing_byproducts,
doing_comment,
doing_working_directory,
+ doing_depfile,
doing_nothing
};
tdoing doing = doing_nothing;
- for (unsigned int j = 0; j < args.size(); ++j)
- {
+ for (unsigned int j = 0; j < args.size(); ++j) {
std::string const& copy = args[j];
- if(copy == "SOURCE")
- {
+ if (copy == "SOURCE") {
doing = doing_source;
- }
- else if(copy == "COMMAND")
- {
+ } else if (copy == "COMMAND") {
doing = doing_command;
// Save the current command before starting the next command.
- if(!currentLine.empty())
- {
+ if (!currentLine.empty()) {
commandLines.push_back(currentLine);
currentLine.clear();
- }
}
- else if(copy == "PRE_BUILD")
- {
+ } else if (copy == "PRE_BUILD") {
cctype = cmTarget::PRE_BUILD;
- }
- else if(copy == "PRE_LINK")
- {
+ } else if (copy == "PRE_LINK") {
cctype = cmTarget::PRE_LINK;
- }
- else if(copy == "POST_BUILD")
- {
+ } else if (copy == "POST_BUILD") {
cctype = cmTarget::POST_BUILD;
- }
- else if(copy == "VERBATIM")
- {
+ } else if (copy == "VERBATIM") {
verbatim = true;
- }
- else if(copy == "APPEND")
- {
+ } else if (copy == "APPEND") {
append = true;
- }
- else if(copy == "TARGET")
- {
+ } 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")
- {
+ } else if (copy == "ARGS") {
// Ignore this old keyword.
- }
- else if (copy == "DEPENDS")
- {
+ } else if (copy == "DEPENDS") {
doing = doing_depends;
- }
- else if (copy == "OUTPUTS")
- {
+ } else if (copy == "OUTPUTS") {
doing = doing_outputs;
- }
- else if (copy == "OUTPUT")
- {
+ } else if (copy == "OUTPUT") {
doing = doing_output;
- }
- else if (copy == "WORKING_DIRECTORY")
- {
+ } else if (copy == "BYPRODUCTS") {
+ doing = doing_byproducts;
+ } else if (copy == "WORKING_DIRECTORY") {
doing = doing_working_directory;
- }
- else if (copy == "MAIN_DEPENDENCY")
- {
+ } else if (copy == "MAIN_DEPENDENCY") {
doing = doing_main_dependency;
- }
- else if (copy == "IMPLICIT_DEPENDS")
- {
+ } else if (copy == "IMPLICIT_DEPENDS") {
doing = doing_implicit_depends_lang;
- }
- else if (copy == "COMMENT")
- {
+ } 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;
}
- else
- {
+ } else {
std::string filename;
- switch (doing)
- {
+ switch (doing) {
case doing_output:
case doing_outputs:
- if (!cmSystemTools::FileIsFullPath(copy.c_str()))
- {
+ case doing_byproducts:
+ if (!cmSystemTools::FileIsFullPath(copy.c_str())) {
// 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
@@ -157,231 +139,243 @@ bool cmAddCustomCommandCommand
// and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt".
// This is fairly obscure so we can wait for someone to
// complain.
- filename = this->Makefile->GetCurrentOutputDirectory();
+ filename = this->Makefile->GetCurrentBinaryDirectory();
filename += "/";
- }
+ }
filename += copy;
cmSystemTools::ConvertToUnixSlashes(filename);
break;
case doing_source:
- // We do not want to convert the argument to SOURCE because
- // that option is only available for backward compatibility.
- // Old-style use of this command may use the SOURCE==TARGET
- // trick which we must preserve. If we convert the source
- // to a full path then it will no longer equal the target.
+ // We do not want to convert the argument to SOURCE because
+ // that option is only available for backward compatibility.
+ // Old-style use of this command may use the SOURCE==TARGET
+ // trick which we must preserve. If we convert the source
+ // to a full path then it will no longer equal the target.
default:
break;
- }
+ }
- switch (doing)
- {
- case doing_working_directory:
- working = copy;
- break;
- case doing_source:
- source = copy;
- break;
- case doing_output:
- output.push_back(filename);
- break;
- case doing_main_dependency:
- main_dependency = copy;
- break;
- case doing_implicit_depends_lang:
- implicit_depends_lang = copy;
- doing = doing_implicit_depends_file;
- break;
- case doing_implicit_depends_file:
- {
- // An implicit dependency starting point is also an
- // explicit dependency.
- std::string dep = copy;
- cmSystemTools::ConvertToUnixSlashes(dep);
- depends.push_back(dep);
+ if (cmSystemTools::FileIsFullPath(filename.c_str())) {
+ filename = cmSystemTools::CollapseFullPath(filename);
+ }
+ switch (doing) {
+ case doing_depfile:
+ depfile = copy;
+ break;
+ case doing_working_directory:
+ working = copy;
+ break;
+ case doing_source:
+ source = copy;
+ break;
+ case doing_output:
+ output.push_back(filename);
+ break;
+ case doing_main_dependency:
+ main_dependency = copy;
+ break;
+ case doing_implicit_depends_lang:
+ implicit_depends_lang = copy;
+ doing = doing_implicit_depends_file;
+ break;
+ case doing_implicit_depends_file: {
+ // An implicit dependency starting point is also an
+ // explicit dependency.
+ std::string dep = copy;
+ 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);
+ // Add the implicit dependency language and file.
+ cmCustomCommand::ImplicitDependsPair entry(implicit_depends_lang,
+ dep);
+ implicit_depends.push_back(entry);
- // Switch back to looking for a language.
- doing = doing_implicit_depends_lang;
- }
- break;
- case doing_command:
- currentLine.push_back(copy);
- break;
- case doing_target:
- target = copy;
- break;
- case doing_depends:
- {
- std::string dep = copy;
- cmSystemTools::ConvertToUnixSlashes(dep);
- depends.push_back(dep);
- }
- break;
- case doing_outputs:
- outputs.push_back(filename);
- break;
- case doing_comment:
- comment_buffer = copy;
- comment = comment_buffer.c_str();
- break;
- default:
- this->SetError("Wrong syntax. Unknown type of argument.");
- return false;
- }
+ // Switch back to looking for a language.
+ doing = doing_implicit_depends_lang;
+ } break;
+ case doing_command:
+ currentLine.push_back(copy);
+ break;
+ case doing_target:
+ target = copy;
+ break;
+ case doing_depends: {
+ std::string dep = copy;
+ cmSystemTools::ConvertToUnixSlashes(dep);
+ depends.push_back(dep);
+ } break;
+ case doing_outputs:
+ outputs.push_back(filename);
+ break;
+ case doing_byproducts:
+ byproducts.push_back(filename);
+ break;
+ case doing_comment:
+ comment_buffer = copy;
+ comment = comment_buffer.c_str();
+ break;
+ default:
+ this->SetError("Wrong syntax. Unknown type of argument.");
+ return false;
}
}
+ }
// Store the last command line finished.
- if(!currentLine.empty())
- {
+ if (!currentLine.empty()) {
commandLines.push_back(currentLine);
currentLine.clear();
- }
+ }
// 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())
- {
+ if (output.empty() && target.empty()) {
this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
return false;
- }
+ }
- if(source.empty() && !target.empty() && !output.empty())
- {
+ if (source.empty() && !target.empty() && !output.empty()) {
this->SetError(
"Wrong syntax. A TARGET and OUTPUT can not both be specified.");
return false;
- }
- if(append && output.empty())
- {
+ }
+ if (append && output.empty()) {
this->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))
- {
+ if (!this->CheckOutputs(output) || !this->CheckOutputs(outputs) ||
+ !this->CheckOutputs(byproducts)) {
return false;
- }
+ }
// Check for an append request.
- if(append)
- {
+ if (append) {
// Lookup an existing command.
- if(cmSourceFile* sf =
- this->Makefile->GetSourceFileWithOutput(output[0].c_str()))
- {
- if(cmCustomCommand* cc = sf->GetCustomCommand())
- {
+ 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;
- }
}
+ }
// No command for this output exists.
- cmOStringStream e;
- e << "given APPEND option with output \"" << output[0].c_str()
- << "\" which is not already a custom command output.";
- this->SetError(e.str().c_str());
+ std::ostringstream e;
+ e << "given APPEND option with output\n\"" << output[0]
+ << "\"\nwhich is not already a custom command output.";
+ this->SetError(e.str());
return false;
- }
+ }
// Convert working directory to a full path.
- if(!working.empty())
- {
- const char* build_dir = this->Makefile->GetCurrentOutputDirectory();
- working = cmSystemTools::CollapseFullPath(working.c_str(), build_dir);
- }
+ if (!working.empty()) {
+ const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
+ working = cmSystemTools::CollapseFullPath(working, build_dir);
+ }
// Choose which mode of the command to use.
bool escapeOldStyle = !verbatim;
- if(source.empty() && output.empty())
- {
+ if (source.empty() && output.empty()) {
// Source is empty, use the target.
std::vector<std::string> no_depends;
- this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
- commandLines, cctype,
- comment, working.c_str(),
- escapeOldStyle);
- }
- else if(target.empty())
- {
+ this->Makefile->AddCustomCommandToTarget(
+ target, byproducts, no_depends, commandLines, cctype, comment,
+ working.c_str(), escapeOldStyle, uses_terminal, depfile,
+ command_expand_lists);
+ } else if (target.empty()) {
// Target is empty, use the output.
- this->Makefile->AddCustomCommandToOutput(output, depends,
- main_dependency.c_str(),
- commandLines, comment,
- working.c_str(), false,
- escapeOldStyle);
+ 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())
- {
+ if (!implicit_depends.empty()) {
bool okay = false;
- if(cmSourceFile* sf =
- this->Makefile->GetSourceFileWithOutput(output[0].c_str()))
- {
- if(cmCustomCommand* cc = sf->GetCustomCommand())
- {
+ if (cmSourceFile* sf =
+ this->Makefile->GetSourceFileWithOutput(output[0])) {
+ if (cmCustomCommand* cc = sf->GetCustomCommand()) {
okay = true;
cc->SetImplicitDepends(implicit_depends);
- }
}
- if(!okay)
- {
- cmOStringStream e;
+ }
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
}
}
- else
- {
- // Use the old-style mode for backward compatibility.
- this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
- source.c_str(), commandLines,
- comment);
+ } else if (!byproducts.empty()) {
+ this->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");
+ return false;
+ } else {
+ bool issueMessage = true;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0050)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0050) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ messageType = cmake::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) {
+ return false;
+ }
+ }
+
+ // Use the old-style mode for backward compatibility.
+ this->Makefile->AddCustomCommandOldStyle(target, outputs, depends, source,
+ commandLines, comment);
+ }
+
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmAddCustomCommandCommand
-::CheckOutputs(const std::vector<std::string>& outputs)
+bool cmAddCustomCommandCommand::CheckOutputs(
+ const std::vector<std::string>& outputs)
{
- for(std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o)
- {
+ 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()))
- {
+ 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.c_str());
+ 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 != o->npos)
- {
- cmOStringStream msg;
+ 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().c_str());
+ this->SetError(msg.str());
return false;
- }
}
+ }
return true;
}
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index 1cc1e3a75..c3a91b2a3 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -1,24 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAddCustomCommandCommand_h
#define cmAddCustomCommandCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmDocumentGeneratorExpressions.h"
+
+class cmExecutionStatus;
/** \class cmAddCustomCommandCommand
- * \brief
- *
- * cmAddCustomCommandCommand defines a new command (rule) that can
+ * \brief cmAddCustomCommandCommand defines a new command (rule) that can
* be executed within the build process
*
*/
@@ -29,162 +24,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddCustomCommandCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddCustomCommandCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "add_custom_command";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add a custom build rule to the generated build system.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "There are two main signatures for add_custom_command "
- "The first signature is for adding a custom command "
- "to produce an output.\n"
- " add_custom_command(OUTPUT output1 [output2 ...]\n"
- " COMMAND command1 [ARGS] [args1...]\n"
- " [COMMAND command2 [ARGS] [args2...] ...]\n"
- " [MAIN_DEPENDENCY depend]\n"
- " [DEPENDS [depends...]]\n"
- " [IMPLICIT_DEPENDS <lang1> depend1\n"
- " [<lang2> depend2] ...]\n"
- " [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM] [APPEND])\n"
- "This defines a command to generate specified OUTPUT file(s). "
- "A target created in the same directory (CMakeLists.txt file) that "
- "specifies any output of the custom command as a source file is given "
- "a rule to generate the file using the command at build time. "
- "Do not list the output in more than one independent target that may "
- "build in parallel or the two instances of the rule may conflict "
- "(instead use add_custom_target to drive the command and make the "
- "other targets depend on that one). "
- "If an output name is a relative path it will be interpreted "
- "relative to the build tree directory corresponding to the current "
- "source directory. "
- "Note that MAIN_DEPENDENCY is completely optional and is "
- "used as a suggestion to visual studio about where to hang the "
- "custom command. In makefile terms this creates a new target in the "
- "following form:\n"
- " OUTPUT: MAIN_DEPENDENCY DEPENDS\n"
- " COMMAND\n"
- "If more than one command is specified they will be executed in order. "
- "The optional ARGS argument is for backward compatibility and will be "
- "ignored.\n"
- "The second signature adds a custom command to a target "
- "such as a library or executable. This is useful for "
- "performing an operation before or after building the target. "
- "The command becomes part of the target and will only execute "
- "when the target itself is built. If the target is already built,"
- " the command will not execute.\n"
- " add_custom_command(TARGET target\n"
- " PRE_BUILD | PRE_LINK | POST_BUILD\n"
- " COMMAND command1 [ARGS] [args1...]\n"
- " [COMMAND command2 [ARGS] [args2...] ...]\n"
- " [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM])\n"
- "This defines a new command that will be associated with "
- "building the specified target. When the command will "
- "happen is determined by which of the following is specified:\n"
- " PRE_BUILD - run before all other dependencies\n"
- " PRE_LINK - run after other dependencies\n"
- " POST_BUILD - run after the target has been built\n"
- "Note that the PRE_BUILD option is only supported on Visual "
- "Studio 7 or later. For all other generators PRE_BUILD "
- "will be treated as PRE_LINK.\n"
- "If WORKING_DIRECTORY is specified the command will be executed "
- "in the directory given. "
- "If it is a relative path it will be interpreted relative to the "
- "build tree directory corresponding to the current source directory. "
- "If COMMENT is set, the value will be displayed as a "
- "message before the commands are executed at build time. "
- "If APPEND is specified the COMMAND and DEPENDS option values "
- "are appended to the custom command for the first output specified. "
- "There must have already been a previous call to this command with "
- "the same output. The COMMENT, WORKING_DIRECTORY, and MAIN_DEPENDENCY "
- "options are currently ignored when APPEND is given, "
- "but may be used in the future."
- "\n"
- "If VERBATIM is given then all arguments to the commands will be "
- "escaped properly for the build tool so that the invoked command "
- "receives each argument unchanged. "
- "Note that one level of escapes is still used by the CMake language "
- "processor before add_custom_command even sees the arguments. "
- "Use of VERBATIM is recommended as it enables correct behavior. "
- "When VERBATIM is not given the behavior is platform specific because "
- "there is no protection of tool-specific special characters."
- "\n"
- "If the output of the custom command is not actually "
- "created as a file on disk it should be marked as SYMBOLIC with "
- "SET_SOURCE_FILES_PROPERTIES.\n"
-
- "The IMPLICIT_DEPENDS option requests scanning of implicit "
- "dependencies of an input file. The language given specifies the "
- "programming language whose corresponding dependency scanner should "
- "be used. Currently only C and CXX language scanners are supported. "
- "The language has to be specified for every file in the "
- "IMPLICIT_DEPENDS list. "
- "Dependencies discovered from the scanning are added to those of "
- "the custom command at build time. Note that the IMPLICIT_DEPENDS "
- "option is currently supported only for Makefile generators and "
- "will be ignored by other generators."
- "\n"
- "If COMMAND specifies an executable target (created by "
- "ADD_EXECUTABLE) it will automatically be replaced by the location "
- "of the executable created at build time. Additionally a "
- "target-level dependency will be added so that the executable target "
- "will be built before any target using this custom command. However "
- "this does NOT add a file-level dependency that would cause the "
- "custom command to re-run whenever the executable is recompiled."
- "\n"
- "Arguments to COMMAND may use \"generator expressions\" with the "
- "syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- "References to target names in generator expressions imply "
- "target-level dependencies, but NOT file-level dependencies. "
- "List target names with the DEPENDS option to add file dependencies."
- "\n"
- "The DEPENDS option specifies files on which the command depends. "
- "If any dependency is an OUTPUT of another custom command in the "
- "same directory (CMakeLists.txt file) CMake automatically brings the "
- "other custom command into the target in which this command is built. "
- "If DEPENDS is not specified the command will run whenever the OUTPUT "
- "is missing; if the command does not actually create the OUTPUT then "
- "the rule will always run. "
- "If DEPENDS specifies any target (created by an ADD_* command) "
- "a target-level dependency is created to make sure the target is "
- "built before any target using this custom command. Additionally, "
- "if the target is an executable or library a file-level dependency "
- "is created to cause the custom command to re-run whenever the target "
- "is recompiled.\n"
- ;
- }
-
- cmTypeMacro(cmAddCustomCommandCommand, cmCommand);
protected:
bool CheckOutputs(const std::vector<std::string>& outputs);
};
-
#endif
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 4eba88636..87e114780 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -1,42 +1,40 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddCustomTargetCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAddCustomTargetCommand.h"
+#include "cmCustomCommandLines.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.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::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
+
+ std::string const& targetName = args[0];
// Check the target name.
- if(args[0].find_first_of("/\\") != args[0].npos)
- {
- if(!this->Makefile->NeedBackwardsCompatibility(2,2))
- {
- cmOStringStream e;
- e << "called with invalid target name \"" << args[0]
- << "\". Target names may not contain a slash. "
- << "Use ADD_CUSTOM_COMMAND to generate files. "
- << "Set CMAKE_BACKWARDS_COMPATIBILITY to 2.2 "
- << "or lower to skip this check.";
- this->SetError(e.str().c_str());
- return false;
- }
- }
+ 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());
+ return false;
+ }
// Accumulate one command line at a time.
cmCustomCommandLine currentLine;
@@ -45,145 +43,201 @@ bool cmAddCustomTargetCommand
cmCustomCommandLines commandLines;
// Accumulate dependencies.
- std::vector<std::string> depends;
+ std::vector<std::string> depends, byproducts;
std::string working_directory;
bool verbatim = false;
+ bool uses_terminal = false;
+ bool command_expand_lists = false;
std::string comment_buffer;
- const char* comment = 0;
+ const char* comment = CM_NULLPTR;
std::vector<std::string> sources;
// Keep track of parser state.
- enum tdoing {
+ enum tdoing
+ {
doing_command,
doing_depends,
+ doing_byproducts,
doing_working_directory,
doing_comment,
doing_source,
- doing_verbatim
+ doing_nothing
};
tdoing doing = doing_command;
// Look for the ALL option.
bool excludeFromAll = true;
unsigned int start = 1;
- if(args.size() > 1)
- {
- if(args[1] == "ALL")
- {
+ if (args.size() > 1) {
+ if (args[1] == "ALL") {
excludeFromAll = false;
start = 2;
- }
}
+ }
// Parse the rest of the arguments.
- for(unsigned int j = start; j < args.size(); ++j)
- {
+ for (unsigned int j = start; j < args.size(); ++j) {
std::string const& copy = args[j];
- if(copy == "DEPENDS")
- {
+ if (copy == "DEPENDS") {
doing = doing_depends;
- }
- else if(copy == "WORKING_DIRECTORY")
- {
+ } else if (copy == "BYPRODUCTS") {
+ doing = doing_byproducts;
+ } else if (copy == "WORKING_DIRECTORY") {
doing = doing_working_directory;
- }
- else if(copy == "VERBATIM")
- {
- doing = doing_verbatim;
+ } else if (copy == "VERBATIM") {
+ doing = doing_nothing;
verbatim = true;
- }
- else if (copy == "COMMENT")
- {
+ } else if (copy == "USES_TERMINAL") {
+ doing = doing_nothing;
+ uses_terminal = true;
+ } else if (copy == "COMMAND_EXPAND_LISTS") {
+ doing = doing_nothing;
+ command_expand_lists = true;
+ } else if (copy == "COMMENT") {
doing = doing_comment;
- }
- else if(copy == "COMMAND")
- {
+ } else if (copy == "COMMAND") {
doing = doing_command;
// Save the current command before starting the next command.
- if(!currentLine.empty())
- {
+ if (!currentLine.empty()) {
commandLines.push_back(currentLine);
currentLine.clear();
- }
}
- else if(copy == "SOURCES")
- {
+ } else if (copy == "SOURCES") {
doing = doing_source;
- }
- else
- {
- switch (doing)
- {
+ } else {
+ switch (doing) {
case doing_working_directory:
working_directory = copy;
break;
case doing_command:
currentLine.push_back(copy);
break;
- case doing_depends:
- {
+ case doing_byproducts: {
+ std::string filename;
+ if (!cmSystemTools::FileIsFullPath(copy.c_str())) {
+ filename = this->Makefile->GetCurrentBinaryDirectory();
+ filename += "/";
+ }
+ filename += copy;
+ cmSystemTools::ConvertToUnixSlashes(filename);
+ byproducts.push_back(filename);
+ } break;
+ case doing_depends: {
std::string dep = copy;
cmSystemTools::ConvertToUnixSlashes(dep);
depends.push_back(dep);
- }
+ } break;
+ case doing_comment:
+ comment_buffer = copy;
+ comment = comment_buffer.c_str();
break;
- case doing_comment:
- comment_buffer = copy;
- comment = comment_buffer.c_str();
- break;
case doing_source:
sources.push_back(copy);
break;
default:
this->SetError("Wrong syntax. Unknown type of argument.");
return false;
- }
}
}
+ }
- std::string::size_type pos = args[0].find_first_of("#<>");
- if(pos != args[0].npos)
- {
- cmOStringStream msg;
- msg << "called with target name containing a \"" << args[0][pos]
+ 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().c_str());
+ this->SetError(msg.str());
return false;
+ }
+
+ // Some requirements on custom target names already exist
+ // and have been checked at this point.
+ // The following restrictions overlap but depend on policy CMP0037.
+ bool nameOk = cmGeneratorExpression::IsValidTargetName(targetName) &&
+ !cmGlobalGenerator::IsReservedTarget(targetName);
+ 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;
+ }
}
+ }
// Store the last command line finished.
- if(!currentLine.empty())
- {
+ if (!currentLine.empty()) {
commandLines.push_back(currentLine);
currentLine.clear();
- }
+ }
// Enforce name uniqueness.
{
- std::string msg;
- if(!this->Makefile->EnforceUniqueName(args[0], msg, true))
- {
- this->SetError(msg.c_str());
- return false;
+ std::string msg;
+ if (!this->Makefile->EnforceUniqueName(targetName, msg, true)) {
+ this->SetError(msg);
+ return false;
}
}
// Convert working directory to a full path.
- if(!working_directory.empty())
- {
- const char* build_dir = this->Makefile->GetCurrentOutputDirectory();
+ if (!working_directory.empty()) {
+ const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
working_directory =
- cmSystemTools::CollapseFullPath(working_directory.c_str(), build_dir);
- }
+ 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");
+ return true;
+ }
+ if (commandLines.empty() && uses_terminal) {
+ this->Makefile->IssueMessage(
+ cmake::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,
+ "COMMAND_EXPAND_LISTS may not be specified without any COMMAND");
+ return true;
+ }
// Add the utility target to the makefile.
bool escapeOldStyle = !verbatim;
- cmTarget* target =
- this->Makefile->AddUtilityCommand(args[0].c_str(), excludeFromAll,
- working_directory.c_str(), depends,
- commandLines, escapeOldStyle, comment);
+ cmTarget* target = this->Makefile->AddUtilityCommand(
+ targetName, excludeFromAll, working_directory.c_str(), byproducts, depends,
+ commandLines, escapeOldStyle, comment, uses_terminal,
+ command_expand_lists);
// Add additional user-specified source files to the target.
target->AddSources(sources);
diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h
index d4ed450f0..7229c2779 100644
--- a/Source/cmAddCustomTargetCommand.h
+++ b/Source/cmAddCustomTargetCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAddCustomTargetCommand_h
#define cmAddCustomTargetCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmAddCustomTargetCommand
* \brief Command that adds a target to the build system.
*
@@ -27,82 +25,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddCustomTargetCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddCustomTargetCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const
- {return "add_custom_target";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add a target with no output so it will always be built.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_custom_target(Name [ALL] [command1 [args1...]]\n"
- " [COMMAND command2 [args2...] ...]\n"
- " [DEPENDS depend depend depend ... ]\n"
- " [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM]\n"
- " [SOURCES src1 [src2...]])\n"
- "Adds a target with the given name that executes the given commands. "
- "The target has no output file and is ALWAYS CONSIDERED OUT OF DATE "
- "even if the commands try to create a file with the name of the "
- "target. Use ADD_CUSTOM_COMMAND to generate a file with dependencies. "
- "By default nothing depends on the custom target. Use "
- "ADD_DEPENDENCIES to add dependencies to or from other targets. "
- "If the ALL option is specified "
- "it indicates that this target should be added to the default build "
- "target so that it will be run every time "
- "(the command cannot be called ALL). "
- "The command and arguments are optional and if not specified an "
- "empty target will be created. "
- "If WORKING_DIRECTORY is set, then the command will be run in that "
- "directory. "
- "If it is a relative path it will be interpreted relative to the "
- "build tree directory corresponding to the current source directory. "
- "If COMMENT is set, the value will be displayed as a "
- "message before the commands are executed at build time. "
- "Dependencies listed with the DEPENDS argument may reference files "
- "and outputs of custom commands created with add_custom_command() in "
- "the same directory (CMakeLists.txt file).\n"
- "If VERBATIM is given then all arguments to the commands will be "
- "escaped properly for the build tool so that the invoked command "
- "receives each argument unchanged. "
- "Note that one level of escapes is still used by the CMake language "
- "processor before add_custom_target even sees the arguments. "
- "Use of VERBATIM is recommended as it enables correct behavior. "
- "When VERBATIM is not given the behavior is platform specific because "
- "there is no protection of tool-specific special characters."
- "\n"
- "The SOURCES option specifies additional source files to be included "
- "in the custom target. "
- "Specified source files will be added to IDE project files for "
- "convenience in editing even if they have not build rules."
- ;
- }
-
- cmTypeMacro(cmAddCustomTargetCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
#endif
diff --git a/Source/cmAddDefinitionsCommand.cxx b/Source/cmAddDefinitionsCommand.cxx
index b813e3eb0..9e0607c60 100644
--- a/Source/cmAddDefinitionsCommand.cxx
+++ b/Source/cmAddDefinitionsCommand.cxx
@@ -1,31 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddDefinitionsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAddDefinitionsCommand.h"
+class cmExecutionStatus;
// cmAddDefinitionsCommand
-bool cmAddDefinitionsCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddDefinitionsCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
// it is OK to have no arguments
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
- for(std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
this->Makefile->AddDefineFlag(i->c_str());
- }
+ }
return true;
}
-
diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h
index ff2c4a038..abf5a5964 100644
--- a/Source/cmAddDefinitionsCommand.h
+++ b/Source/cmAddDefinitionsCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAddDefinitionsCommand_h
#define cmAddDefinitionsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmAddDefinitionsCommand
* \brief Specify a list of compiler defines
*
@@ -26,55 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddDefinitionsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddDefinitionsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "add_definitions";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Adds -D define flags to the compilation of source files.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_definitions(-DFOO -DBAR ...)\n"
- "Adds flags to the compiler command line for sources in the current "
- "directory and below. This command can be used to add any flags, "
- "but it was originally intended to add preprocessor definitions. "
- "Flags beginning in -D or /D that look like preprocessor definitions "
- "are automatically added to the COMPILE_DEFINITIONS property for "
- "the current directory. Definitions with non-trivial values may be "
- "left in the set of flags instead of being converted for reasons of "
- "backwards compatibility. See documentation of the directory, "
- "target, and source file COMPILE_DEFINITIONS properties for details "
- "on adding preprocessor definitions to specific scopes and "
- "configurations."
- ;
- }
-
- cmTypeMacro(cmAddDefinitionsCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index e4d7f7f1e..a73b57e82 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -1,48 +1,39 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddDependenciesCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAddDependenciesCommand.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
// cmDependenciesCommand
-bool cmAddDependenciesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddDependenciesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- std::string target_name = args[0];
- if(this->Makefile->IsAlias(target_name.c_str()))
- {
- cmOStringStream e;
+ 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(cmTarget* target = this->Makefile->FindTargetToUse(target_name.c_str()))
- {
+ }
+ 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->c_str());
- }
+ for (; s != args.end(); ++s) {
+ target->AddUtility(*s, this->Makefile);
}
- else
- {
- cmOStringStream e;
+ } 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 "
@@ -50,8 +41,7 @@ bool cmAddDependenciesCommand
<< "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());
- }
+ }
return true;
}
-
diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h
index ed8006765..c7328d63e 100644
--- a/Source/cmAddDependenciesCommand.h
+++ b/Source/cmAddDependenciesCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDependenciessCommand_h
#define cmDependenciessCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmAddDependenciesCommand
* \brief Add a dependency to a target
*
@@ -25,54 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddDependenciesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddDependenciesCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "add_dependencies";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add a dependency between top-level targets.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_dependencies(target-name depend-target1\n"
- " depend-target2 ...)\n"
- "Make a top-level target depend on other top-level targets. A "
- "top-level target is one created by ADD_EXECUTABLE, ADD_LIBRARY, "
- "or ADD_CUSTOM_TARGET. Adding dependencies with this command "
- "can be used to make sure one target is built before another target. "
- "Dependencies added to an IMPORTED target are followed transitively "
- "in its place since the target itself does not build. "
- "See the DEPENDS option of ADD_CUSTOM_TARGET "
- "and ADD_CUSTOM_COMMAND for adding file-level dependencies in custom "
- "rules. See the OBJECT_DEPENDS option in "
- "SET_SOURCE_FILES_PROPERTIES to add file-level dependencies to object "
- "files.";
- }
-
- cmTypeMacro(cmAddDependenciesCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 578525969..1d0376fe0 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -1,28 +1,30 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddExecutableCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAddExecutableCommand.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
// cmExecutableCommand
-bool cmAddExecutableCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::vector<std::string>::const_iterator s = args.begin();
- std::string exename = *s;
+ std::string const& exename = *s;
++s;
bool use_win32 = false;
@@ -31,178 +33,179 @@ bool cmAddExecutableCommand
bool importTarget = false;
bool importGlobal = false;
bool isAlias = false;
- while ( s != args.end() )
- {
- if (*s == "WIN32")
- {
+ while (s != args.end()) {
+ if (*s == "WIN32") {
++s;
use_win32 = true;
- }
- else if ( *s == "MACOSX_BUNDLE" )
- {
+ } else if (*s == "MACOSX_BUNDLE") {
++s;
use_macbundle = true;
- }
- else if(*s == "EXCLUDE_FROM_ALL")
- {
+ } else if (*s == "EXCLUDE_FROM_ALL") {
++s;
excludeFromAll = true;
- }
- else if(*s == "IMPORTED")
- {
- ++s;
- importTarget = true;
- }
- else if(importTarget && *s == "GLOBAL")
- {
+ } else if (*s == "IMPORTED") {
+ ++s;
+ importTarget = true;
+ } else if (importTarget && *s == "GLOBAL") {
++s;
importGlobal = true;
- }
- else if(*s == "ALIAS")
- {
+ } else if (*s == "ALIAS") {
++s;
isAlias = true;
- }
- else
- {
+ } else {
break;
+ }
+ }
+
+ bool nameOk = cmGeneratorExpression::IsValidTargetName(exename) &&
+ !cmGlobalGenerator::IsReservedTarget(exename);
+
+ 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;
}
}
+ }
// Special modifiers are not allowed with IMPORTED signature.
- if(importTarget
- && (use_win32 || use_macbundle || excludeFromAll))
- {
- if(use_win32)
- {
+ if (importTarget && (use_win32 || use_macbundle || excludeFromAll)) {
+ if (use_win32) {
this->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.");
- }
- else // if(excludeFromAll)
- {
+ } else if (use_macbundle) {
+ this->SetError("may not be given MACOSX_BUNDLE for an IMPORTED target.");
+ } else // if(excludeFromAll)
+ {
this->SetError(
"may not be given EXCLUDE_FROM_ALL for an IMPORTED target.");
- }
- return false;
}
- if (isAlias)
- {
- if(!cmGeneratorExpression::IsValidTargetName(exename.c_str()))
- {
- this->SetError(("Invalid name for ALIAS: " + exename).c_str());
+ return false;
+ }
+ if (isAlias) {
+ if (!cmGeneratorExpression::IsValidTargetName(exename)) {
+ this->SetError("Invalid name for ALIAS: " + exename);
return false;
- }
- if(excludeFromAll)
- {
+ }
+ if (excludeFromAll) {
this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
return false;
- }
- if(importTarget || importGlobal)
- {
+ }
+ if (importTarget || importGlobal) {
this->SetError("IMPORTED with ALIAS is not allowed.");
return false;
- }
- if(args.size() != 3)
- {
- cmOStringStream e;
+ }
+ if (args.size() != 3) {
+ std::ostringstream e;
e << "ALIAS requires exactly one target argument.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- const char *aliasedName = s->c_str();
- if(this->Makefile->IsAlias(aliasedName))
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << exename
- << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
- cmTarget *aliasedTarget =
- this->Makefile->FindTargetToUse(aliasedName, true);
- if(!aliasedTarget)
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << exename
- << "\" because target \"" << aliasedName << "\" does not already "
- "exist.";
- this->SetError(e.str().c_str());
+ }
+ cmTarget* aliasedTarget =
+ this->Makefile->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());
return false;
- }
- cmTarget::TargetType type = aliasedTarget->GetType();
- if(type != cmTarget::EXECUTABLE)
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << exename
- << "\" because target \"" << aliasedName << "\" is not an "
- "executable.";
- this->SetError(e.str().c_str());
+ }
+ 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());
return false;
- }
- if(aliasedTarget->IsImported())
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << exename
- << "\" because target \"" << aliasedName << "\" is IMPORTED.";
- this->SetError(e.str().c_str());
+ }
+ if (aliasedTarget->IsImported()) {
+ std::ostringstream e;
+ e << "cannot create ALIAS target \"" << exename << "\" because target \""
+ << aliasedName << "\" is IMPORTED.";
+ this->SetError(e.str());
return false;
- }
- this->Makefile->AddAlias(exename.c_str(), aliasedTarget);
- return true;
}
+ this->Makefile->AddAlias(exename, aliasedName);
+ return true;
+ }
// Handle imported target creation.
- if(importTarget)
- {
+ if (importTarget) {
// Make sure the target does not already exist.
- if(this->Makefile->FindTargetToUse(exename.c_str()))
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Create the imported target.
- this->Makefile->AddImportedTarget(exename.c_str(), cmTarget::EXECUTABLE,
+ this->Makefile->AddImportedTarget(exename, cmStateEnums::EXECUTABLE,
importGlobal);
return true;
- }
+ }
// Enforce name uniqueness.
{
- std::string msg;
- if(!this->Makefile->EnforceUniqueName(exename, msg))
- {
- this->SetError(msg.c_str());
- return false;
+ std::string msg;
+ if (!this->Makefile->EnforceUniqueName(exename, msg)) {
+ this->SetError(msg);
+ return false;
}
}
- if (s == args.end())
- {
- this->SetError
- ("called with incorrect number of arguments, no sources provided");
+ 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);
- if ( use_win32 )
- {
+ cmTarget* tgt =
+ this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll);
+ if (use_win32) {
tgt->SetProperty("WIN32_EXECUTABLE", "ON");
- }
- if ( use_macbundle)
- {
+ }
+ if (use_macbundle) {
tgt->SetProperty("MACOSX_BUNDLE", "ON");
- }
+ }
return true;
}
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index 2774ce841..8100da185 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExecutablesCommand_h
#define cmExecutablesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmExecutablesCommand
* \brief Defines a list of executables to build.
*
@@ -26,105 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddExecutableCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddExecutableCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "add_executable";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Add an executable to the project using the specified source files.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_executable(<name> [WIN32] [MACOSX_BUNDLE]\n"
- " [EXCLUDE_FROM_ALL]\n"
- " source1 source2 ... sourceN)\n"
- "Adds an executable target called <name> to be built from the "
- "source files listed in the command invocation. "
- "The <name> corresponds to the logical target name and must be "
- "globally unique within a project. "
- "The actual file name of the executable built is constructed based on "
- "conventions of the native platform "
- "(such as <name>.exe or just <name>). "
- "\n"
- "By default the executable file will be created in the build tree "
- "directory corresponding to the source tree directory in which "
- "the command was invoked. "
- "See documentation of the RUNTIME_OUTPUT_DIRECTORY "
- "target property to change this location. "
- "See documentation of the OUTPUT_NAME target property to change "
- "the <name> part of the final file name. "
- "\n"
- "If WIN32 is given the property WIN32_EXECUTABLE will be set on the "
- "target created. "
- "See documentation of that target property for details."
- "\n"
- "If MACOSX_BUNDLE is given the corresponding property will be "
- "set on the created target. "
- "See documentation of the MACOSX_BUNDLE target property for details."
- "\n"
- "If EXCLUDE_FROM_ALL is given the corresponding property will be "
- "set on the created target. "
- "See documentation of the EXCLUDE_FROM_ALL target property for "
- "details."
- "\n"
- "The add_executable command can also create IMPORTED executable "
- "targets using this signature:\n"
- " add_executable(<name> IMPORTED [GLOBAL])\n"
- "An IMPORTED executable target references an executable file located "
- "outside the project. "
- "No rules are generated to build it. "
- "The target name has scope in the directory in which it is created "
- "and below, but the GLOBAL option extends visibility. "
- "It may be referenced like any target built within the project. "
- "IMPORTED executables are useful for convenient reference from "
- "commands like add_custom_command. "
- "Details about the imported executable are specified by setting "
- "properties whose names begin in \"IMPORTED_\". "
- "The most important such property is IMPORTED_LOCATION "
- "(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
- "which specifies the location of the main executable file on disk. "
- "See documentation of the IMPORTED_* properties for more information."
- "\n"
- "The signature\n"
- " add_executable(<name> ALIAS <target>)\n"
- "creates an alias, such that <name> can be used to refer to <target> "
- "in subsequent commands. The <name> does not appear in the generated "
- "buildsystem as a make target. The <target> may not be an IMPORTED "
- "target or an ALIAS. Alias targets can be used as linkable targets, "
- "targets to read properties from, executables for custom commands and "
- "custom targets. They can also be tested for existance with the "
- "regular if(TARGET) subcommand. The <name> may not be used to modify "
- "properties of <target>, that is, it may not be used as the operand of "
- "set_property, set_target_properties, target_link_libraries etc. An "
- "ALIAS target may not be installed of exported."
- ;
- }
-
- cmTypeMacro(cmAddExecutableCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index cbc6ed1e9..ebf17632a 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -1,41 +1,43 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddLibraryCommand.h"
+#include <sstream>
+
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmake.h"
+class cmExecutionStatus;
+
// cmLibraryCommand
-bool cmAddLibraryCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
// otherwise it defaults to static library.
- cmTarget::TargetType type = cmTarget::SHARED_LIBRARY;
- if (cmSystemTools::IsOff(this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
- {
- type = cmTarget::STATIC_LIBRARY;
- }
+ cmStateEnums::TargetType type = cmStateEnums::SHARED_LIBRARY;
+ if (cmSystemTools::IsOff(
+ this->Makefile->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();
- std::string libName = *s;
+ std::string const& libName = *s;
++s;
@@ -44,230 +46,333 @@ bool cmAddLibraryCommand
// source list name. There may be two keyword arguments, check for them
bool haveSpecifiedType = false;
bool isAlias = false;
- while ( s != args.end() )
- {
+ while (s != args.end()) {
std::string libType = *s;
- if(libType == "STATIC")
- {
+ if (libType == "STATIC") {
+ if (type == cmStateEnums::INTERFACE_LIBRARY) {
+ std::ostringstream e;
+ e << "INTERFACE library specified with conflicting STATIC type.";
+ this->SetError(e.str());
+ return false;
+ }
++s;
- type = cmTarget::STATIC_LIBRARY;
+ type = cmStateEnums::STATIC_LIBRARY;
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());
+ return false;
}
- else if(libType == "SHARED")
- {
++s;
- type = cmTarget::SHARED_LIBRARY;
+ type = cmStateEnums::SHARED_LIBRARY;
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());
+ return false;
}
- else if(libType == "MODULE")
- {
++s;
- type = cmTarget::MODULE_LIBRARY;
+ type = cmStateEnums::MODULE_LIBRARY;
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());
+ return false;
}
- else if(libType == "OBJECT")
- {
++s;
- type = cmTarget::OBJECT_LIBRARY;
+ type = cmStateEnums::OBJECT_LIBRARY;
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());
+ return false;
}
- else if(libType == "UNKNOWN")
- {
++s;
- type = cmTarget::UNKNOWN_LIBRARY;
+ type = cmStateEnums::UNKNOWN_LIBRARY;
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());
+ return false;
}
- else if(libType == "ALIAS")
- {
++s;
isAlias = true;
+ } else if (libType == "INTERFACE") {
+ if (haveSpecifiedType) {
+ std::ostringstream e;
+ e << "INTERFACE library specified with conflicting/multiple types.";
+ this->SetError(e.str());
+ return false;
+ }
+ if (isAlias) {
+ std::ostringstream e;
+ e << "INTERFACE library specified with conflicting ALIAS type.";
+ this->SetError(e.str());
+ return false;
+ }
+ if (excludeFromAll) {
+ std::ostringstream e;
+ e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
+ this->SetError(e.str());
+ return false;
}
- else if(*s == "EXCLUDE_FROM_ALL")
- {
++s;
- excludeFromAll = true;
+ type = cmStateEnums::INTERFACE_LIBRARY;
+ 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());
+ return false;
}
- else if(*s == "IMPORTED")
- {
+ ++s;
+ excludeFromAll = true;
+ } else if (*s == "IMPORTED") {
++s;
importTarget = true;
- }
- else if(importTarget && *s == "GLOBAL")
- {
+ } else if (importTarget && *s == "GLOBAL") {
++s;
importGlobal = true;
- }
- else
- {
+ } 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());
+ return false;
+ } else {
break;
- }
}
- if (isAlias)
- {
- if(!cmGeneratorExpression::IsValidTargetName(libName.c_str()))
- {
- this->SetError(("Invalid name for ALIAS: " + libName).c_str());
+ }
+
+ if (type == cmStateEnums::INTERFACE_LIBRARY) {
+ if (s != args.end()) {
+ std::ostringstream e;
+ e << "INTERFACE library requires no source arguments.";
+ this->SetError(e.str());
+ return false;
+ }
+ if (importGlobal && !importTarget) {
+ std::ostringstream e;
+ e << "INTERFACE library specified as GLOBAL, but not as IMPORTED.";
+ this->SetError(e.str());
return false;
+ }
+ }
+
+ bool nameOk = cmGeneratorExpression::IsValidTargetName(libName) &&
+ !cmGlobalGenerator::IsReservedTarget(libName);
+
+ 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(excludeFromAll)
- {
+ }
+ }
+
+ if (isAlias) {
+ if (!cmGeneratorExpression::IsValidTargetName(libName)) {
+ this->SetError("Invalid name for ALIAS: " + libName);
+ return false;
+ }
+ if (excludeFromAll) {
this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
return false;
- }
- if(importTarget || importGlobal)
- {
+ }
+ if (importTarget || importGlobal) {
this->SetError("IMPORTED with ALIAS is not allowed.");
return false;
- }
- if(args.size() != 3)
- {
- cmOStringStream e;
+ }
+ if (args.size() != 3) {
+ std::ostringstream e;
e << "ALIAS requires exactly one target argument.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- const char *aliasedName = s->c_str();
- if(this->Makefile->IsAlias(aliasedName))
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << libName
- << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
- cmTarget *aliasedTarget =
- this->Makefile->FindTargetToUse(aliasedName, true);
- if(!aliasedTarget)
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << libName
- << "\" because target \"" << aliasedName << "\" does not already "
- "exist.";
- this->SetError(e.str().c_str());
+ }
+ cmTarget* aliasedTarget =
+ this->Makefile->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());
return false;
- }
- cmTarget::TargetType aliasedType = aliasedTarget->GetType();
- if(aliasedType != cmTarget::SHARED_LIBRARY
- && aliasedType != cmTarget::STATIC_LIBRARY
- && aliasedType != cmTarget::MODULE_LIBRARY
- && aliasedType != cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << libName
- << "\" because target \"" << aliasedName << "\" is not a library.";
- this->SetError(e.str().c_str());
+ }
+ cmStateEnums::TargetType aliasedType = aliasedTarget->GetType();
+ if (aliasedType != cmStateEnums::SHARED_LIBRARY &&
+ 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());
return false;
- }
- if(aliasedTarget->IsImported())
- {
- cmOStringStream e;
- e << "cannot create ALIAS target \"" << libName
- << "\" because target \"" << aliasedName << "\" is IMPORTED.";
- this->SetError(e.str().c_str());
+ }
+ if (aliasedTarget->IsImported()) {
+ std::ostringstream e;
+ e << "cannot create ALIAS target \"" << libName << "\" because target \""
+ << aliasedName << "\" is IMPORTED.";
+ this->SetError(e.str());
return false;
- }
- this->Makefile->AddAlias(libName.c_str(), aliasedTarget);
- return true;
}
+ this->Makefile->AddAlias(libName, aliasedName);
+ return true;
+ }
- if(importTarget && excludeFromAll)
- {
+ if (importTarget && excludeFromAll) {
this->SetError("excludeFromAll with IMPORTED target makes no sense.");
return false;
- }
+ }
/* ideally we should check whether for the linker language of the target
CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
STATIC. But at this point we know only the name of the target, but not
yet its linker language. */
- if ((type != cmTarget::STATIC_LIBRARY) &&
- (type != cmTarget::OBJECT_LIBRARY) &&
- (this->Makefile->GetCMakeInstance()->GetPropertyAsBool(
- "TARGET_SUPPORTS_SHARED_LIBS") == false))
- {
- cmOStringStream w;
- w <<
- "ADD_LIBRARY called with " <<
- (type==cmTarget::SHARED_LIBRARY ? "SHARED" : "MODULE") <<
- " option but the target platform does not support dynamic linking. "
- "Building a STATIC library instead. This may lead to problems.";
+ 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());
- type = cmTarget::STATIC_LIBRARY;
- }
+ type = cmStateEnums::STATIC_LIBRARY;
+ }
// Handle imported target creation.
- if(importTarget)
- {
+ if (importTarget) {
// The IMPORTED signature requires a type to be specified explicitly.
- if (!haveSpecifiedType)
- {
+ if (!haveSpecifiedType) {
this->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,
+ "The OBJECT library type may not be used for IMPORTED libraries" +
+ reason + ".");
+ return true;
}
- if(type == cmTarget::OBJECT_LIBRARY)
- {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "The OBJECT library type may not be used for IMPORTED libraries."
- );
- return true;
+ }
+ 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());
+ return false;
}
+ }
// Make sure the target does not already exist.
- if(this->Makefile->FindTargetToUse(libName.c_str()))
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Create the imported target.
- this->Makefile->AddImportedTarget(libName.c_str(), type, importGlobal);
+ this->Makefile->AddImportedTarget(libName, type, importGlobal);
return true;
- }
+ }
// A non-imported target may not have UNKNOWN type.
- if(type == cmTarget::UNKNOWN_LIBRARY)
- {
+ if (type == cmStateEnums::UNKNOWN_LIBRARY) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "The UNKNOWN library type may be used only for IMPORTED libraries."
- );
+ "The UNKNOWN library type may be used only for IMPORTED libraries.");
return true;
- }
+ }
// Enforce name uniqueness.
{
- std::string msg;
- if(!this->Makefile->EnforceUniqueName(libName, msg))
- {
- this->SetError(msg.c_str());
- return false;
+ std::string msg;
+ if (!this->Makefile->EnforceUniqueName(libName, msg)) {
+ this->SetError(msg);
+ return false;
+ }
+ }
+
+ std::vector<std::string> srclists;
+
+ 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());
+ return false;
}
+
+ this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
+ return true;
}
- if (s == args.end())
- {
+ 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");
- }
+ cmSystemTools::Message(msg.c_str(), "Warning");
+ }
- std::vector<std::string> srclists;
- while (s != args.end())
- {
- srclists.push_back(*s);
- ++s;
- }
+ srclists.insert(srclists.end(), s, args.end());
- this->Makefile->AddLibrary(libName.c_str(), type, srclists, excludeFromAll);
+ this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
return true;
}
-
-
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index 59354b0f5..df49fae93 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLibrarysCommand_h
#define cmLibrarysCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmLibrarysCommand
* \brief Defines a list of executables to build.
*
@@ -26,136 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddLibraryCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddLibraryCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "add_library";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add a library to the project using the specified source files.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_library(<name> [STATIC | SHARED | MODULE]\n"
- " [EXCLUDE_FROM_ALL]\n"
- " source1 source2 ... sourceN)\n"
- "Adds a library target called <name> to be built from the "
- "source files listed in the command invocation. "
- "The <name> corresponds to the logical target name and must be "
- "globally unique within a project. "
- "The actual file name of the library built is constructed based on "
- "conventions of the native platform "
- "(such as lib<name>.a or <name>.lib)."
- "\n"
- "STATIC, SHARED, or MODULE may be given to specify the type of library "
- "to be created. "
- "STATIC libraries are archives of object files for use when linking "
- "other targets. "
- "SHARED libraries are linked dynamically and loaded at runtime. "
- "MODULE libraries are plugins that are not linked into other targets "
- "but may be loaded dynamically at runtime using dlopen-like "
- "functionality. "
- "If no type is given explicitly the type is STATIC or SHARED based "
- "on whether the current value of the variable BUILD_SHARED_LIBS is "
- "true. "
- "For SHARED and MODULE libraries the POSITION_INDEPENDENT_CODE "
- "target property is set to TRUE automatically."
- "\n"
- "By default the library file will be created in the build tree "
- "directory corresponding to the source tree directory in which "
- "the command was invoked. "
- "See documentation of the ARCHIVE_OUTPUT_DIRECTORY, "
- "LIBRARY_OUTPUT_DIRECTORY, and RUNTIME_OUTPUT_DIRECTORY "
- "target properties to change this location. "
- "See documentation of the OUTPUT_NAME target property to change "
- "the <name> part of the final file name. "
- "\n"
- "If EXCLUDE_FROM_ALL is given the corresponding property will be "
- "set on the created target. "
- "See documentation of the EXCLUDE_FROM_ALL target property for "
- "details."
- "\n"
- "The add_library command can also create IMPORTED library "
- "targets using this signature:\n"
- " add_library(<name> <SHARED|STATIC|MODULE|UNKNOWN> IMPORTED\n"
- " [GLOBAL])\n"
- "An IMPORTED library target references a library file located "
- "outside the project. "
- "No rules are generated to build it. "
- "The target name has scope in the directory in which it is created "
- "and below, but the GLOBAL option extends visibility. "
- "It may be referenced like any target built within the project. "
- "IMPORTED libraries are useful for convenient reference from "
- "commands like target_link_libraries. "
- "Details about the imported library are specified by setting "
- "properties whose names begin in \"IMPORTED_\". "
- "The most important such property is IMPORTED_LOCATION "
- "(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
- "which specifies the location of the main library file on disk. "
- "See documentation of the IMPORTED_* properties for more information."
- "\n"
- "The signature\n"
- " add_library(<name> OBJECT <src>...)\n"
- "creates a special \"object library\" target. "
- "An object library compiles source files but does not archive or link "
- "their object files into a library. "
- "Instead other targets created by add_library or add_executable may "
- "reference the objects using an expression of the form "
- "$<TARGET_OBJECTS:objlib> as a source, where \"objlib\" is the "
- "object library name. "
- "For example:\n"
- " add_library(... $<TARGET_OBJECTS:objlib> ...)\n"
- " add_executable(... $<TARGET_OBJECTS:objlib> ...)\n"
- "will include objlib's object files in a library and an executable "
- "along with those compiled from their own sources. "
- "Object libraries may contain only sources (and headers) that compile "
- "to object files. "
- "They may contain custom commands generating such sources, but not "
- "PRE_BUILD, PRE_LINK, or POST_BUILD commands. "
- "Object libraries cannot be imported, exported, installed, or linked."
- " "
- "Some native build systems may not like targets that have only "
- "object files, so consider adding at least one real source file "
- "to any target that references $<TARGET_OBJECTS:objlib>."
- "\n"
- "The signature\n"
- " add_library(<name> ALIAS <target>)\n"
- "creates an alias, such that <name> can be used to refer to <target> "
- "in subsequent commands. The <name> does not appear in the generated "
- "buildsystem as a make target. The <target> may not be an IMPORTED "
- "target or an ALIAS. Alias targets can be used as linkable targets, "
- "targets to read properties from. They can also be tested for "
- "existance with the "
- "regular if(TARGET) subcommand. The <name> may not be used to modify "
- "properties of <target>, that is, it may not be used as the operand of "
- "set_property, set_target_properties, target_link_libraries etc. An "
- "ALIAS target may not be installed of exported."
- ;
- }
-
- cmTypeMacro(cmAddLibraryCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 5b1c9c668..1727ca56f 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -1,28 +1,26 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddSubDirectoryCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAddSubDirectoryCommand.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmAddSubDirectoryCommand
-bool cmAddSubDirectoryCommand::InitialPass
-(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddSubDirectoryCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// store the binpath
- std::string srcArg = args[0];
+ std::string const& srcArg = args[0];
std::string binArg;
bool excludeFromAll = false;
@@ -30,99 +28,84 @@ bool cmAddSubDirectoryCommand::InitialPass
// 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 (; i != args.end(); ++i) {
+ if (*i == "EXCLUDE_FROM_ALL") {
excludeFromAll = true;
continue;
- }
- else if (!binArg.size())
- {
+ }
+ if (binArg.empty()) {
binArg = *i;
- }
- else
- {
+ } else {
this->SetError("called with incorrect number of arguments");
return false;
- }
}
+ }
// 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.c_str())) {
srcPath = srcArg;
- }
- else
- {
- srcPath = this->Makefile->GetCurrentDirectory();
+ } else {
+ srcPath = this->Makefile->GetCurrentSourceDirectory();
srcPath += "/";
srcPath += srcArg;
- }
- if(!cmSystemTools::FileIsDirectory(srcPath.c_str()))
- {
+ }
+ if (!cmSystemTools::FileIsDirectory(srcPath)) {
std::string error = "given source \"";
error += srcArg;
error += "\" which is not an existing directory.";
- this->SetError(error.c_str());
+ this->SetError(error);
return false;
- }
- srcPath = cmSystemTools::CollapseFullPath(srcPath.c_str());
+ }
+ srcPath = cmSystemTools::CollapseFullPath(srcPath);
// Compute the full path to the binary directory.
std::string binPath;
- if(binArg.empty())
- {
+ if (binArg.empty()) {
// 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.c_str(),
- this->Makefile->GetCurrentDirectory()))
- {
- cmOStringStream e;
+ 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->GetCurrentDirectory() << "\". "
+ << this->Makefile->GetCurrentSourceDirectory() << "\". "
<< "When specifying an out-of-tree source a binary directory "
<< "must be explicitly specified.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Remove the CurrentDirectory from the srcPath and replace it
// with the CurrentOutputDirectory.
- const char* src = this->Makefile->GetCurrentDirectory();
- const char* bin = this->Makefile->GetCurrentOutputDirectory();
+ 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] == '/')
- { --srcLen; }
- if(binLen > 0 && bin[binLen-1] == '/')
- { --binLen; }
- binPath = std::string(bin, binLen) + srcPath.substr(srcLen);
+ if (srcLen > 0 && src[srcLen - 1] == '/') {
+ --srcLen;
+ }
+ if (binLen > 0 && bin[binLen - 1] == '/') {
+ --binLen;
}
- else
- {
+ binPath = std::string(bin, 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.c_str())) {
binPath = binArg;
- }
- else
- {
- binPath = this->Makefile->GetCurrentOutputDirectory();
+ } else {
+ binPath = this->Makefile->GetCurrentBinaryDirectory();
binPath += "/";
binPath += binArg;
- }
}
- binPath = cmSystemTools::CollapseFullPath(binPath.c_str());
+ }
+ binPath = cmSystemTools::CollapseFullPath(binPath);
// Add the subdirectory using the computed full paths.
- this->Makefile->AddSubDirectory(srcPath.c_str(), binPath.c_str(),
- excludeFromAll, false, true);
+ this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, true);
return true;
}
diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h
index e7f907c3f..0e71ffd85 100644
--- a/Source/cmAddSubDirectoryCommand.h
+++ b/Source/cmAddSubDirectoryCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAddSubDirectoryCommand_h
#define cmAddSubDirectoryCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmAddSubDirectoryCommand
* \brief Specify a subdirectory to build
*
@@ -27,73 +25,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddSubDirectoryCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddSubDirectoryCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "add_subdirectory";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add a subdirectory to the build.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_subdirectory(source_dir [binary_dir] \n"
- " [EXCLUDE_FROM_ALL])\n"
- "Add a subdirectory to the build. The source_dir specifies the "
- "directory in which the source CMakeLists.txt and code files are "
- "located. If it is a relative "
- "path it will be evaluated with respect to the current "
- "directory (the typical usage), but it may also be an absolute path. "
- "The binary_dir specifies the directory in which to place the output "
- "files. If it is a relative path it will be evaluated with respect "
- "to the current output directory, but it may also be an absolute "
- "path. If binary_dir is not specified, the value of source_dir, "
- "before expanding any relative path, will be used (the typical usage). "
- "The CMakeLists.txt file in the specified source directory will "
- "be processed immediately by CMake before processing in the current "
- "input file continues beyond this command.\n"
-
- "If the EXCLUDE_FROM_ALL argument is provided then targets in the "
- "subdirectory will not be included in the ALL target of the parent "
- "directory by default, and will be excluded from IDE project files. "
- "Users must explicitly build targets in the subdirectory. "
- "This is meant for use when the subdirectory contains a separate part "
- "of the project that is useful but not necessary, such as a set of "
- "examples. "
- "Typically the subdirectory should contain its own project() command "
- "invocation so that a full build system will be generated in the "
- "subdirectory (such as a VS IDE solution file). "
- "Note that inter-target dependencies supercede this exclusion. "
- "If a target built by the parent project depends on a target in the "
- "subdirectory, the dependee target will be included in the parent "
- "project build system to satisfy the dependency."
- ;
- }
-
- cmTypeMacro(cmAddSubDirectoryCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index a9165f5b1..3a3afdb05 100644
--- a/Source/cmAddTestCommand.cxx
+++ b/Source/cmAddTestCommand.cxx
@@ -1,75 +1,58 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddTestCommand.h"
-#include "cmTestGenerator.h"
+#include <sstream>
+#include "cmMakefile.h"
#include "cmTest.h"
+#include "cmTestGenerator.h"
+class cmExecutionStatus;
// cmExecutableCommand
-bool cmAddTestCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(!args.empty() && args[0] == "NAME")
- {
+ if (!args.empty() && args[0] == "NAME") {
return this->HandleNameMode(args);
- }
+ }
// 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 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Collect the command with arguments.
std::vector<std::string> command;
- for(std::vector<std::string>::const_iterator it = args.begin() + 1;
- it != args.end(); ++it)
- {
- command.push_back(*it);
- }
+ command.insert(command.end(), 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].c_str());
- if(test)
- {
+ cmTest* test = this->Makefile->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())
- {
- cmOStringStream e;
+ if (!test->GetOldStyle()) {
+ std::ostringstream e;
e << " given test name \"" << args[0]
<< "\" which already exists in this directory.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- else
- {
- test = this->Makefile->CreateTest(args[0].c_str());
+ } else {
+ test = this->Makefile->CreateTest(args[0]);
test->SetOldStyle(true);
this->Makefile->AddTestGenerator(new cmTestGenerator(test));
- }
+ }
test->SetCommand(command);
return true;
}
-//----------------------------------------------------------------------------
bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args)
{
std::string name;
@@ -78,7 +61,8 @@ bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args)
std::vector<std::string> command;
// Read the arguments.
- enum Doing {
+ enum Doing
+ {
DoingName,
DoingCommand,
DoingConfigs,
@@ -86,94 +70,71 @@ bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args)
DoingNone
};
Doing doing = DoingName;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "COMMAND")
- {
- if(!command.empty())
- {
+ 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.");
return false;
- }
- doing = DoingCommand;
}
- else if(args[i] == "CONFIGURATIONS")
- {
- if(!configurations.empty())
- {
+ doing = DoingCommand;
+ } else if (args[i] == "CONFIGURATIONS") {
+ if (!configurations.empty()) {
this->SetError(" may be given at most one set of CONFIGURATIONS.");
return false;
- }
- doing = DoingConfigs;
}
- else if(args[i] == "WORKING_DIRECTORY")
- {
- if(!working_directory.empty())
- {
+ doing = DoingConfigs;
+ } else if (args[i] == "WORKING_DIRECTORY") {
+ if (!working_directory.empty()) {
this->SetError(" may be given at most one WORKING_DIRECTORY.");
return false;
- }
- doing = DoingWorkingDirectory;
}
- else if(doing == DoingName)
- {
+ doing = DoingWorkingDirectory;
+ } else if (doing == DoingName) {
name = args[i];
doing = DoingNone;
- }
- else if(doing == DoingCommand)
- {
+ } else if (doing == DoingCommand) {
command.push_back(args[i]);
- }
- else if(doing == DoingConfigs)
- {
+ } else if (doing == DoingConfigs) {
configurations.push_back(args[i]);
- }
- else if(doing == DoingWorkingDirectory)
- {
+ } else if (doing == DoingWorkingDirectory) {
working_directory = args[i];
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << " given unknown argument:\n " << args[i] << "\n";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Require a test name.
- if(name.empty())
- {
+ if (name.empty()) {
this->SetError(" must be given non-empty NAME.");
return false;
- }
+ }
// Require a command.
- if(command.empty())
- {
+ if (command.empty()) {
this->SetError(" must be given non-empty COMMAND.");
return false;
- }
+ }
// Require a unique test name within the directory.
- if(this->Makefile->GetTest(name.c_str()))
- {
- cmOStringStream e;
+ if (this->Makefile->GetTest(name)) {
+ std::ostringstream e;
e << " given test NAME \"" << name
<< "\" which already exists in this directory.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Add the test.
- cmTest* test = this->Makefile->CreateTest(name.c_str());
+ cmTest* test = this->Makefile->CreateTest(name);
test->SetOldStyle(false);
test->SetCommand(command);
- if(!working_directory.empty())
- {
+ if (!working_directory.empty()) {
test->SetProperty("WORKING_DIRECTORY", working_directory.c_str());
- }
+ }
this->Makefile->AddTestGenerator(new cmTestGenerator(test, configurations));
return true;
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index ec7fda3f3..a098a03f1 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -1,19 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAddTestCommand_h
#define cmAddTestCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmDocumentGeneratorExpressions.h"
+
+class cmExecutionStatus;
/** \class cmAddTestCommand
* \brief Add a test to the lists of tests to run.
@@ -26,79 +23,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAddTestCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAddTestCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "add_test";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add a test to the project with the specified arguments.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " add_test(testname Exename arg1 arg2 ... )\n"
- "If the ENABLE_TESTING command has been run, this command adds a "
- "test target to the current directory. If ENABLE_TESTING has not "
- "been run, this command does nothing. "
- "The tests are run by the testing subsystem by executing Exename "
- "with the specified arguments. Exename can be either an executable "
- "built by this project or an arbitrary executable on the "
- "system (like tclsh). The test will be run with the current working "
- "directory set to the CMakeList.txt files corresponding directory "
- "in the binary tree.\n"
- "\n"
- " add_test(NAME <name> [CONFIGURATIONS [Debug|Release|...]]\n"
- " [WORKING_DIRECTORY dir]\n"
- " COMMAND <command> [arg1 [arg2 ...]])\n"
- "Add a test called <name>. "
- "The test name may not contain spaces, quotes, or other characters "
- "special in CMake syntax. "
- "If COMMAND specifies an executable target (created by "
- "add_executable) it will automatically be replaced by the location "
- "of the executable created at build time. "
- "If a CONFIGURATIONS option is given then the test will be executed "
- "only when testing under one of the named configurations. "
- "If a WORKING_DIRECTORY option is given then the test will be executed "
- "in the given directory."
- "\n"
- "Arguments after COMMAND may use \"generator expressions\" with the "
- "syntax \"$<...>\". "
- CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS
- "Example usage:\n"
- " add_test(NAME mytest\n"
- " COMMAND testDriver --config $<CONFIGURATION>\n"
- " --exe $<TARGET_FILE:myexe>)\n"
- "This creates a test \"mytest\" whose command runs a testDriver "
- "tool passing the configuration name and the full path to the "
- "executable file produced by target \"myexe\"."
- ;
- }
-
- cmTypeMacro(cmAddTestCommand, cmCommand);
private:
bool HandleNameMode(std::vector<std::string> const& args);
};
-
#endif
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
new file mode 100644
index 000000000..4adfe2328
--- /dev/null
+++ b/Source/cmAlgorithms.h
@@ -0,0 +1,405 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmAlgorithms_h
+#define cmAlgorithms_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_kwiml.h"
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <sstream>
+#include <string.h>
+#include <string>
+#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;
+}
+
+template <typename T, size_t N>
+bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N])
+{
+ return cmHasLiteralPrefixImpl(str1, str2, N - 1);
+}
+
+template <typename T, size_t N>
+bool cmHasLiteralSuffix(const T& str1, const char (&str2)[N])
+{
+ return cmHasLiteralSuffixImpl(str1, str2, N - 1);
+}
+
+struct cmStrCmp
+{
+ 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>
+FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
+{
+ const typename std::iterator_traits<FwdIt>::difference_type dist =
+ std::distance(middle, last);
+ std::rotate(first, middle, last);
+ std::advance(first, dist);
+ return first;
+}
+
+template <typename Container, typename Predicate>
+void cmEraseIf(Container& cont, Predicate pred)
+{
+ cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
+}
+
+namespace ContainerAlgorithms {
+
+template <typename T>
+struct cmIsPair
+{
+ enum
+ {
+ value = false
+ };
+};
+
+template <typename K, typename V>
+struct cmIsPair<std::pair<K, V> >
+{
+ enum
+ {
+ value = true
+ };
+};
+
+template <typename Range,
+ bool valueTypeIsPair = cmIsPair<typename Range::value_type>::value>
+struct DefaultDeleter
+{
+ void operator()(typename Range::value_type value) const { delete value; }
+};
+
+template <typename Range>
+struct DefaultDeleter<Range, /* valueTypeIsPair = */ true>
+{
+ void operator()(typename Range::value_type value) const
+ {
+ delete value.second;
+ }
+};
+
+template <typename FwdIt>
+FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n)
+{
+ FwdIt m = i1;
+ std::advance(m, n);
+ return cmRotate(i1, m, i2);
+}
+
+template <typename Range>
+struct BinarySearcher
+{
+ typedef typename Range::value_type argument_type;
+ BinarySearcher(Range const& r)
+ : m_range(r)
+ {
+ }
+
+ bool operator()(argument_type const& item) const
+ {
+ return std::binary_search(m_range.begin(), m_range.end(), item);
+ }
+
+private:
+ Range const& m_range;
+};
+}
+
+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());
+}
+
+template <typename Range>
+void cmDeleteAll(Range const& r)
+{
+ std::for_each(r.begin(), r.end(),
+ ContainerAlgorithms::DefaultDeleter<Range>());
+}
+
+template <typename Range>
+std::string cmJoin(Range const& r, const char* delimiter)
+{
+ 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();
+}
+
+template <typename Range>
+std::string cmJoin(Range const& r, std::string const& delimiter)
+{
+ return cmJoin(r, delimiter.c_str());
+}
+
+template <typename Range>
+typename Range::const_iterator cmRemoveN(Range& r, size_t n)
+{
+ return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n);
+}
+
+template <typename Range, typename InputRange>
+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();
+ if (remIt == remEnd) {
+ return rangeEnd;
+ }
+
+ typename Range::iterator writer = r.begin();
+ std::advance(writer, *remIt);
+ typename Range::iterator pivot = writer;
+ typename InputRange::value_type prevRem = *remIt;
+ ++remIt;
+ size_t count = 1;
+ for (; writer != rangeEnd && remIt != remEnd; ++count, ++remIt) {
+ std::advance(pivot, *remIt - prevRem);
+ prevRem = *remIt;
+ writer = ContainerAlgorithms::RemoveN(writer, pivot, count);
+ }
+ return ContainerAlgorithms::RemoveN(writer, rangeEnd, count);
+}
+
+template <typename Range, typename MatchRange>
+typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
+{
+ return std::remove_if(r.begin(), r.end(),
+ ContainerAlgorithms::BinarySearcher<MatchRange>(m));
+}
+
+namespace ContainerAlgorithms {
+
+template <typename Range, typename T = typename Range::value_type>
+struct RemoveDuplicatesAPI
+{
+ 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)
+ {
+ return **it != *it2;
+ }
+};
+
+template <typename Range, typename T>
+struct RemoveDuplicatesAPI<Range, T*>
+{
+ typedef typename Range::const_iterator const_iterator;
+ typedef T* 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)
+ {
+ 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);
+ }
+ }
+ 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;
+}
+
+template <typename Range>
+std::string cmWrap(char prefix, Range const& r, char suffix,
+ std::string const& sep)
+{
+ return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep);
+}
+
+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());
+ }
+}
+
+#endif
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index b410e440e..0f13b114f 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -1,308 +1,335 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmArchiveWrite.h"
+#include "cmLocale.h"
#include "cmSystemTools.h"
-#include <cmsys/ios/iostream>
-#include <cmsys/Directory.hxx>
-#include <cm_libarchive.h>
+#include "cm_get_date.h"
+#include "cm_libarchive.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include <iostream>
+#include <string.h>
+#include <time.h>
+
+#ifndef __LA_SSIZE_T
+#define __LA_SSIZE_T la_ssize_t
+#endif
+
+static std::string cm_archive_error_string(struct archive* a)
+{
+ const char* e = archive_error_string(a);
+ return e ? e : "unknown error";
+}
+
+static void cm_archive_entry_copy_pathname(struct archive_entry* e,
+ const std::string& dest)
+{
+#if cmsys_STL_HAS_WSTRING
+ archive_entry_copy_pathname_w(e, cmsys::Encoding::ToWide(dest).c_str());
+#else
+ archive_entry_copy_pathname(e, dest.c_str());
+#endif
+}
+
+static void cm_archive_entry_copy_sourcepath(struct archive_entry* e,
+ const std::string& file)
+{
+#if cmsys_STL_HAS_WSTRING
+ archive_entry_copy_sourcepath_w(e, cmsys::Encoding::ToWide(file).c_str());
+#else
+ archive_entry_copy_sourcepath(e, file.c_str());
+#endif
+}
-//----------------------------------------------------------------------------
class cmArchiveWrite::Entry
{
struct archive_entry* Object;
+
public:
- Entry(): Object(archive_entry_new()) {}
+ Entry()
+ : Object(archive_entry_new())
+ {
+ }
~Entry() { archive_entry_free(this->Object); }
operator struct archive_entry*() { return this->Object; }
};
-//----------------------------------------------------------------------------
struct cmArchiveWrite::Callback
{
// archive_write_callback
- static __LA_SSIZE_T Write(struct archive*, void *cd,
- const void *b, size_t n)
- {
+ static __LA_SSIZE_T Write(struct archive* /*unused*/, void* cd,
+ const void* b, size_t n)
+ {
cmArchiveWrite* self = static_cast<cmArchiveWrite*>(cd);
- if(self->Stream.write(static_cast<const char*>(b),
- static_cast<cmsys_ios::streamsize>(n)))
- {
+ if (self->Stream.write(static_cast<const char*>(b),
+ static_cast<std::streamsize>(n))) {
return static_cast<__LA_SSIZE_T>(n);
- }
- else
- {
- return static_cast<__LA_SSIZE_T>(-1);
- }
}
+ return static_cast<__LA_SSIZE_T>(-1);
+ }
};
-//----------------------------------------------------------------------------
-cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, Type t):
- Stream(os),
- Archive(archive_write_new()),
- Disk(archive_read_disk_new()),
- Verbose(false)
+cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
+ std::string const& format)
+ : Stream(os)
+ , Archive(archive_write_new())
+ , Disk(archive_read_disk_new())
+ , Verbose(false)
+ , Format(format)
{
- switch (c)
- {
+ switch (c) {
case CompressNone:
- if(archive_write_set_compression_none(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_compression_none: ";
- this->Error += archive_error_string(this->Archive);
+ 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);
return;
- }
+ }
break;
case CompressCompress:
- if(archive_write_set_compression_compress(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_compression_compress: ";
- this->Error += archive_error_string(this->Archive);
+ 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);
return;
- }
+ }
break;
case CompressGZip:
- if(archive_write_set_compression_gzip(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_compression_gzip: ";
- this->Error += archive_error_string(this->Archive);
+ 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);
return;
- }
+ }
break;
case CompressBZip2:
- if(archive_write_set_compression_bzip2(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_compression_bzip2: ";
- this->Error += archive_error_string(this->Archive);
+ 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);
return;
- }
+ }
break;
case CompressLZMA:
- if(archive_write_set_compression_lzma(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_compression_lzma: ";
- this->Error += archive_error_string(this->Archive);
+ 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);
return;
- }
+ }
break;
case CompressXZ:
- if(archive_write_set_compression_xz(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_compression_xz: ";
- this->Error += archive_error_string(this->Archive);
+ 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);
return;
- }
+ }
break;
- };
+ };
#if !defined(_WIN32) || defined(__CYGWIN__)
- if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK)
- {
+ if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) {
this->Error = "archive_read_disk_set_standard_lookup: ";
- this->Error += archive_error_string(this->Archive);
- return;;
- }
+ this->Error += cm_archive_error_string(this->Archive);
+ return;
+ }
#endif
- switch (t)
- {
- case TypeZIP:
- if(archive_write_set_format_zip(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_format_zip: ";
- this->Error += archive_error_string(this->Archive);
- return;
- }
- break;
- case TypeTAR:
- if(archive_write_set_format_pax_restricted(this->Archive) != ARCHIVE_OK)
- {
- this->Error = "archive_write_set_format_pax_restricted: ";
- this->Error += archive_error_string(this->Archive);
- return;
- }
- break;
- }
+
+ 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);
+ return;
+ }
// do not pad the last block!!
- if (archive_write_set_bytes_in_last_block(this->Archive, 1))
- {
+ if (archive_write_set_bytes_in_last_block(this->Archive, 1)) {
this->Error = "archive_write_set_bytes_in_last_block: ";
- this->Error += archive_error_string(this->Archive);
+ this->Error += cm_archive_error_string(this->Archive);
return;
- }
+ }
- if(archive_write_open(
- this->Archive, this, 0,
- reinterpret_cast<archive_write_callback*>(&Callback::Write),
- 0) != ARCHIVE_OK)
- {
+ if (archive_write_open(
+ this->Archive, this, CM_NULLPTR,
+ reinterpret_cast<archive_write_callback*>(&Callback::Write),
+ CM_NULLPTR) != ARCHIVE_OK) {
this->Error = "archive_write_open: ";
- this->Error += archive_error_string(this->Archive);
+ this->Error += cm_archive_error_string(this->Archive);
return;
- }
+ }
}
-//----------------------------------------------------------------------------
cmArchiveWrite::~cmArchiveWrite()
{
- archive_read_finish(this->Disk);
- archive_write_finish(this->Archive);
+ archive_read_free(this->Disk);
+ archive_write_free(this->Archive);
}
-//----------------------------------------------------------------------------
-bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix)
+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);
+ if (this->Okay()) {
+ if (!path.empty() && path[path.size() - 1] == '/') {
+ path.erase(path.size() - 1);
}
+ this->AddPath(path.c_str(), skip, prefix, recursive);
+ }
return this->Okay();
}
-//----------------------------------------------------------------------------
-bool cmArchiveWrite::AddPath(const char* path,
- size_t skip, const char* prefix)
+bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
+ bool recursive)
{
- if(!this->AddFile(path, skip, prefix))
- {
+ if (!this->AddFile(path, skip, prefix)) {
return false;
- }
- if(!cmSystemTools::FileIsDirectory(path) ||
- cmSystemTools::FileIsSymlink(path))
- {
+ }
+ if ((!cmSystemTools::FileIsDirectory(path) || !recursive) ||
+ cmSystemTools::FileIsSymlink(path)) {
return true;
- }
+ }
cmsys::Directory d;
- if(d.Load(path))
- {
+ if (d.Load(path)) {
std::string next = path;
next += "/";
std::string::size_type end = next.size();
unsigned long n = d.GetNumberOfFiles();
- for(unsigned long i = 0; i < n; ++i)
- {
+ for (unsigned long i = 0; i < n; ++i) {
const char* file = d.GetFile(i);
- if(strcmp(file, ".") != 0 && strcmp(file, "..") != 0)
- {
+ if (strcmp(file, ".") != 0 && strcmp(file, "..") != 0) {
next.erase(end);
next += file;
- if(!this->AddPath(next.c_str(), skip, prefix))
- {
+ if (!this->AddPath(next.c_str(), skip, prefix)) {
return false;
- }
}
}
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmArchiveWrite::AddFile(const char* file,
- size_t skip, const char* prefix)
+bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
{
// 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))
- {
+ if (skip >= strlen(file)) {
return true;
- }
+ }
const char* out = file + skip;
+ cmLocaleRAII localeRAII;
+ static_cast<void>(localeRAII);
+
// Meta-data.
- std::string dest = prefix? prefix : "";
+ std::string dest = prefix ? prefix : "";
dest += out;
- if(this->Verbose)
- {
+ if (this->Verbose) {
std::cout << dest << "\n";
- }
+ }
Entry e;
- archive_entry_copy_sourcepath(e, file);
- archive_entry_set_pathname(e, dest.c_str());
- if(archive_read_disk_entry_from_file(this->Disk, e, -1, 0) != ARCHIVE_OK)
- {
- this->Error = "archive_read_disk_entry_from_file: ";
- this->Error += archive_error_string(this->Disk);
+ 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) !=
+ ARCHIVE_OK) {
+ this->Error = "archive_read_disk_entry_from_file '";
+ this->Error += file;
+ this->Error += "': ";
+ this->Error += cm_archive_error_string(this->Disk);
return false;
+ }
+ if (!this->MTime.empty()) {
+ time_t now;
+ 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 += "'";
+ return false;
}
+ archive_entry_set_mtime(e, t, 0);
+ }
+
+ // manages the uid/guid of the entry (if any)
+ if (this->Uid.IsSet() && this->Gid.IsSet()) {
+ archive_entry_set_uid(e, this->Uid.Get());
+ archive_entry_set_gid(e, this->Gid.Get());
+ }
+
+ if (!this->Uname.empty() && !this->Gname.empty()) {
+ archive_entry_set_uname(e, this->Uname.c_str());
+ archive_entry_set_gname(e, this->Gname.c_str());
+ }
+
+ // manages the permissions
+ if (this->Permissions.IsSet()) {
+ archive_entry_set_perm(e, this->Permissions.Get());
+ }
+
+ if (this->PermissionsMask.IsSet()) {
+ int perm = archive_entry_perm(e);
+ archive_entry_set_perm(e, perm & this->PermissionsMask.Get());
+ }
+
// Clear acl and xattr fields not useful for distribution.
archive_entry_acl_clear(e);
archive_entry_xattr_clear(e);
archive_entry_set_fflags(e, 0, 0);
- if(archive_write_header(this->Archive, e) != ARCHIVE_OK)
- {
+
+ if (this->Format == "pax" || this->Format == "paxr") {
+ // Sparse files are a GNU tar extension.
+ // Do not use them in standard tar files.
+ archive_entry_sparse_clear(e);
+ }
+
+ if (archive_write_header(this->Archive, e) != ARCHIVE_OK) {
this->Error = "archive_write_header: ";
- this->Error += archive_error_string(this->Archive);
+ this->Error += cm_archive_error_string(this->Archive);
return false;
- }
+ }
// do not copy content of symlink
- if (!archive_entry_symlink(e))
- {
+ if (!archive_entry_symlink(e)) {
// Content.
- if(size_t size = static_cast<size_t>(archive_entry_size(e)))
- {
+ if (size_t size = static_cast<size_t>(archive_entry_size(e))) {
return this->AddData(file, size);
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmArchiveWrite::AddData(const char* file, size_t size)
{
- std::ifstream fin(file, std::ios::in | cmsys_ios_binary);
- if(!fin)
- {
+ 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();
return false;
- }
+ }
char buffer[16384];
size_t nleft = size;
- while(nleft > 0)
- {
- typedef cmsys_ios::streamsize ssize_type;
- size_t const nnext = nleft > sizeof(buffer)? sizeof(buffer) : nleft;
+ while (nleft > 0) {
+ typedef std::streamsize ssize_type;
+ 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);
// Some stream libraries (older HPUX) return failure at end of
// file on the last read even if some data were read. Check
// gcount instead of trusting the stream error status.
- if(static_cast<size_t>(fin.gcount()) != nnext)
- {
+ if (static_cast<size_t>(fin.gcount()) != nnext) {
break;
- }
- if(archive_write_data(this->Archive, buffer, nnext) != nnext_s)
- {
+ }
+ if (archive_write_data(this->Archive, buffer, nnext) != nnext_s) {
this->Error = "archive_write_data: ";
- this->Error += archive_error_string(this->Archive);
+ this->Error += cm_archive_error_string(this->Archive);
return false;
- }
- nleft -= nnext;
}
- if(nleft > 0)
- {
+ nleft -= nnext;
+ }
+ if (nleft > 0) {
this->Error = "Error reading \"";
this->Error += file;
this->Error += "\": ";
this->Error += cmSystemTools::GetLastSystemError();
return false;
- }
+ }
return true;
}
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index 3e3b2f0ca..4c85c0d16 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -1,30 +1,45 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmArchiveWrite_h
#define cmArchiveWrite_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <stddef.h>
+#include <string>
#if !defined(CMAKE_BUILD_WITH_CMAKE)
-# error "cmArchiveWrite not allowed during bootstrap build!"
+#error "cmArchiveWrite not allowed during bootstrap build!"
#endif
+template <typename T>
+class cmArchiveWriteOptional
+{
+public:
+ cmArchiveWriteOptional() { this->Clear(); }
+ explicit cmArchiveWriteOptional(T val) { this->Set(val); }
+
+ void Set(T val)
+ {
+ this->IsValueSet = true;
+ this->Value = val;
+ }
+ void Clear() { this->IsValueSet = false; }
+ bool IsSet() const { return this->IsValueSet; }
+ T Get() const { return Value; }
+private:
+ T Value;
+ bool IsValueSet;
+};
+
/** \class cmArchiveWrite
* \brief Wrapper around libarchive for writing.
*
*/
class cmArchiveWrite
{
- typedef void (cmArchiveWrite::* safe_bool)();
+ typedef void (cmArchiveWrite::*safe_bool)();
void safe_bool_true() {}
public:
/** Compression type. */
@@ -38,15 +53,10 @@ public:
CompressXZ
};
- /** Archive Type */
- enum Type
- {
- TypeTAR,
- TypeZIP
- };
-
/** Construct with output stream to which to write archive. */
- cmArchiveWrite(std::ostream& os, Compress c = CompressNone, Type = TypeTAR);
+ cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
+ std::string const& format = "paxr");
+
~cmArchiveWrite();
/**
@@ -57,11 +67,14 @@ 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 = 0);
+ bool Add(std::string path, size_t skip = 0, const char* prefix = CM_NULLPTR,
+ bool recursive = true);
/** Returns true if there has been no error. */
operator safe_bool() const
- { return this->Okay()? &cmArchiveWrite::safe_bool_true : 0; }
+ {
+ return this->Okay() ? &cmArchiveWrite::safe_bool_true : CM_NULLPTR;
+ }
/** Returns true if there has been an error. */
bool operator!() const { return !this->Okay(); }
@@ -73,9 +86,63 @@ public:
// std::cout.
void SetVerbose(bool v) { this->Verbose = v; }
+ void SetMTime(std::string const& t) { this->MTime = t; }
+
+ //! Sets the permissions of the added files/folders
+ void SetPermissions(int permissions_)
+ {
+ this->Permissions.Set(permissions_);
+ }
+
+ //! Clears permissions - default is used instead
+ void ClearPermissions() { this->Permissions.Clear(); }
+
+ //! Sets the permissions mask of files/folders
+ //!
+ //! The permissions will be copied from the existing file
+ //! or folder. The mask will then be applied to unset
+ //! some of them
+ void SetPermissionsMask(int permissionsMask_)
+ {
+ this->PermissionsMask.Set(permissionsMask_);
+ }
+
+ //! Clears permissions mask - default is used instead
+ void ClearPermissionsMask() { this->PermissionsMask.Clear(); }
+
+ //! Sets UID and GID to be used in the tar file
+ void SetUIDAndGID(int uid_, int gid_)
+ {
+ this->Uid.Set(uid_);
+ this->Gid.Set(gid_);
+ }
+
+ //! Clears UID and GID to be used in the tar file - default is used instead
+ void ClearUIDAndGID()
+ {
+ this->Uid.Clear();
+ this->Gid.Clear();
+ }
+
+ //! Sets UNAME and GNAME to be used in the tar file
+ void SetUNAMEAndGNAME(const std::string& uname_, const std::string& gname_)
+ {
+ this->Uname = uname_;
+ this->Gname = gname_;
+ }
+
+ //! Clears UNAME and GNAME to be used in the tar file
+ //! default is used instead
+ void ClearUNAMEAndGNAME()
+ {
+ this->Uname = "";
+ this->Gname = "";
+ }
+
private:
bool Okay() const { return this->Error.empty(); }
- bool AddPath(const char* path, size_t skip, const char* prefix);
+ bool AddPath(const char* path, size_t skip, const char* prefix,
+ bool recursive = true);
bool AddFile(const char* file, size_t skip, const char* prefix);
bool AddData(const char* file, size_t size);
@@ -88,7 +155,25 @@ private:
struct archive* Archive;
struct archive* Disk;
bool Verbose;
+ std::string Format;
std::string Error;
+ std::string MTime;
+
+ //! UID of the user in the tar file
+ cmArchiveWriteOptional<int> Uid;
+
+ //! GUID of the user in the tar file
+ cmArchiveWriteOptional<int> Gid;
+
+ //! UNAME/GNAME of the user (does not override UID/GID)
+ //!@{
+ std::string Uname;
+ std::string Gname;
+ //!@}
+
+ //! Permissions on files/folders
+ cmArchiveWriteOptional<int> Permissions;
+ cmArchiveWriteOptional<int> PermissionsMask;
};
#endif
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 01f64b730..847a41660 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -1,89 +1,80 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAuxSourceDirectoryCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/Directory.hxx"
+#include <algorithm>
+#include <stddef.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmAuxSourceDirectoryCommand.h"
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include <cmsys/Directory.hxx>
+class cmExecutionStatus;
// cmAuxSourceDirectoryCommand
-bool cmAuxSourceDirectoryCommand::InitialPass
-(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmAuxSourceDirectoryCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2 || args.size() > 2)
- {
+ if (args.size() != 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::string sourceListValue;
- std::string templateDirectory = args[0];
- this->Makefile->AddExtraDirectory(templateDirectory.c_str());
+ std::string const& templateDirectory = args[0];
std::string tdir;
- if(!cmSystemTools::FileIsFullPath(templateDirectory.c_str()))
- {
- tdir = this->Makefile->GetCurrentDirectory();
+ if (!cmSystemTools::FileIsFullPath(templateDirectory.c_str())) {
+ tdir = this->Makefile->GetCurrentSourceDirectory();
tdir += "/";
tdir += templateDirectory;
- }
- else
- {
+ } else {
tdir = templateDirectory;
- }
+ }
// was the list already populated
- const char *def = this->Makefile->GetDefinition(args[1].c_str());
- if (def)
- {
+ const char* def = this->Makefile->GetDefinition(args[1]);
+ if (def) {
sourceListValue = def;
- }
+ }
+
+ std::vector<std::string> files;
// Load all the files in the directory
cmsys::Directory dir;
- if(dir.Load(tdir.c_str()))
- {
+ if (dir.Load(tdir)) {
size_t numfiles = dir.GetNumberOfFiles();
- for(size_t i =0; i < numfiles; ++i)
- {
+ for (size_t i = 0; i < numfiles; ++i) {
std::string file = dir.GetFile(static_cast<unsigned long>(i));
// Split the filename into base and extension
- std::string::size_type dotpos = file.rfind(".");
- if( dotpos != std::string::npos )
- {
- std::string ext = file.substr(dotpos+1);
+ std::string::size_type dotpos = file.rfind('.');
+ if (dotpos != std::string::npos) {
+ std::string ext = file.substr(dotpos + 1);
std::string base = file.substr(0, dotpos);
// Process only source files
- if( base.size() != 0
- && std::find( this->Makefile->GetSourceExtensions().begin(),
- this->Makefile->GetSourceExtensions().end(), ext )
- != this->Makefile->GetSourceExtensions().end() )
- {
+ 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;
// add the file as a class file so
// depends can be done
- cmSourceFile* sf =
- this->Makefile->GetOrCreateSource(fullname.c_str());
- sf->SetProperty("ABSTRACT","0");
- if(!sourceListValue.empty())
- {
- sourceListValue += ";";
- }
- sourceListValue += fullname;
- }
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(fullname);
+ sf->SetProperty("ABSTRACT", "0");
+ files.push_back(fullname);
}
}
}
- this->Makefile->AddDefinition(args[1].c_str(), sourceListValue.c_str());
+ }
+ std::sort(files.begin(), files.end());
+ if (!sourceListValue.empty()) {
+ sourceListValue += ";";
+ }
+ sourceListValue += cmJoin(files, ";");
+ this->Makefile->AddDefinition(args[1], sourceListValue.c_str());
return true;
}
-
diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h
index 8a70f19cb..e49e86117 100644
--- a/Source/cmAuxSourceDirectoryCommand.h
+++ b/Source/cmAuxSourceDirectoryCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAuxSourceDirectoryCommand_h
#define cmAuxSourceDirectoryCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmAuxSourceDirectoryCommand
* \brief Specify auxiliary source code directories.
*
@@ -29,58 +27,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmAuxSourceDirectoryCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmAuxSourceDirectoryCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "aux_source_directory";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Find all source files in a directory.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " aux_source_directory(<dir> <variable>)\n"
- "Collects the names of all the source files in the specified "
- "directory and stores the list in the <variable> provided. This "
- "command is intended to be used by projects that use explicit "
- "template instantiation. Template instantiation files can be "
- "stored in a \"Templates\" subdirectory and collected automatically "
- "using this command to avoid manually listing all instantiations.\n"
- "It is tempting to use this command to avoid writing the list of "
- "source files for a library or executable target. While this seems "
- "to work, there is no way for CMake to generate a build system that "
- "knows when a new source file has been added. Normally the "
- "generated build system knows when it needs to rerun CMake because "
- "the CMakeLists.txt file is modified to add a new source. When the "
- "source is just added to the directory without modifying this file, "
- "one would have to manually rerun CMake to generate a build system "
- "incorporating the new file.";
- }
-
- cmTypeMacro(cmAuxSourceDirectoryCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx
new file mode 100644
index 000000000..1dac212c2
--- /dev/null
+++ b/Source/cmBase32.cxx
@@ -0,0 +1,99 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmBase32.h"
+
+// -- Static functions
+
+static const unsigned char Base32EncodeTable[33] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+
+inline unsigned char Base32EncodeChar(int schar)
+{
+ return Base32EncodeTable[schar];
+}
+
+void Base32Encode5(const unsigned char src[5], char dst[8])
+{
+ // [0]:5 bits
+ dst[0] = Base32EncodeChar((src[0] >> 3) & 0x1F);
+ // [0]:3 bits + [1]:2 bits
+ dst[1] = Base32EncodeChar(((src[0] << 2) & 0x1C) + ((src[1] >> 6) & 0x03));
+ // [1]:5 bits
+ dst[2] = Base32EncodeChar((src[1] >> 1) & 0x1F);
+ // [1]:1 bit + [2]:4 bits
+ dst[3] = Base32EncodeChar(((src[1] << 4) & 0x10) + ((src[2] >> 4) & 0x0F));
+ // [2]:4 bits + [3]:1 bit
+ dst[4] = Base32EncodeChar(((src[2] << 1) & 0x1E) + ((src[3] >> 7) & 0x01));
+ // [3]:5 bits
+ dst[5] = Base32EncodeChar((src[3] >> 2) & 0x1F);
+ // [3]:2 bits + [4]:3 bit
+ dst[6] = Base32EncodeChar(((src[3] << 3) & 0x18) + ((src[4] >> 5) & 0x07));
+ // [4]:5 bits
+ dst[7] = Base32EncodeChar((src[4] << 0) & 0x1F);
+}
+
+// -- Class methods
+
+cmBase32Encoder::cmBase32Encoder()
+{
+}
+
+cmBase32Encoder::~cmBase32Encoder()
+{
+}
+
+std::string cmBase32Encoder::encodeString(const unsigned char* input,
+ size_t len, bool padding)
+{
+ std::string res;
+
+ static const size_t blockSize = 5;
+ static const size_t bufferSize = 8;
+ char buffer[bufferSize];
+
+ const unsigned char* end = input + len;
+ while ((input + blockSize) <= end) {
+ Base32Encode5(input, buffer);
+ res.append(buffer, bufferSize);
+ input += blockSize;
+ }
+
+ size_t remain = static_cast<size_t>(end - input);
+ if (remain != 0) {
+ // Temporary source buffer filled up with 0s
+ unsigned char extended[blockSize];
+ for (size_t ii = 0; ii != remain; ++ii) {
+ extended[ii] = input[ii];
+ }
+ for (size_t ii = remain; ii != blockSize; ++ii) {
+ extended[ii] = 0;
+ }
+
+ Base32Encode5(extended, buffer);
+ size_t numPad(0);
+ switch (remain) {
+ case 1:
+ numPad = 6;
+ break;
+ case 2:
+ numPad = 4;
+ break;
+ case 3:
+ numPad = 3;
+ break;
+ case 4:
+ numPad = 1;
+ break;
+ default:
+ break;
+ }
+ res.append(buffer, bufferSize - numPad);
+ if (padding) {
+ for (size_t ii = 0; ii != numPad; ++ii) {
+ res.push_back(paddingChar);
+ }
+ }
+ }
+
+ return res;
+}
diff --git a/Source/cmBase32.h b/Source/cmBase32.h
new file mode 100644
index 000000000..c6758d4f3
--- /dev/null
+++ b/Source/cmBase32.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 cmBase32_h
+#define cmBase32_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stddef.h>
+#include <string>
+
+/** \class cmBase32Encoder
+ * \brief Encodes a byte sequence to a Base32 byte sequence according to
+ * RFC4648
+ *
+ */
+class cmBase32Encoder
+{
+public:
+ static const char paddingChar = '=';
+
+public:
+ cmBase32Encoder();
+ ~cmBase32Encoder();
+
+ // Encodes the given input byte sequence into a string
+ // @arg input Input data pointer
+ // @arg len Input data size
+ // @arg padding Flag to append "=" on demand
+ std::string encodeString(const unsigned char* input, size_t len,
+ bool padding = true);
+};
+
+#endif
diff --git a/Source/cmBootstrapCommands1.cxx b/Source/cmBootstrapCommands1.cxx
deleted file mode 100644
index 9093579dc..000000000
--- a/Source/cmBootstrapCommands1.cxx
+++ /dev/null
@@ -1,91 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-// This file is used to compile all the commands
-// that CMake knows about at compile time.
-// This is sort of a boot strapping approach since you would
-// like to have CMake to build CMake.
-#include "cmCommands.h"
-#include "cmAddCustomCommandCommand.cxx"
-#include "cmAddCustomTargetCommand.cxx"
-#include "cmAddDefinitionsCommand.cxx"
-#include "cmAddDependenciesCommand.cxx"
-#include "cmAddExecutableCommand.cxx"
-#include "cmAddLibraryCommand.cxx"
-#include "cmAddSubDirectoryCommand.cxx"
-#include "cmAddTestCommand.cxx"
-#include "cmBreakCommand.cxx"
-#include "cmBuildCommand.cxx"
-#include "cmCMakeMinimumRequired.cxx"
-#include "cmCMakePolicyCommand.cxx"
-#include "cmCommandArgumentsHelper.cxx"
-#include "cmConfigureFileCommand.cxx"
-#include "cmCoreTryCompile.cxx"
-#include "cmCreateTestSourceList.cxx"
-#include "cmDefinePropertyCommand.cxx"
-#include "cmElseCommand.cxx"
-#include "cmEnableLanguageCommand.cxx"
-#include "cmEnableTestingCommand.cxx"
-#include "cmEndForEachCommand.cxx"
-#include "cmEndFunctionCommand.cxx"
-#include "cmEndIfCommand.cxx"
-#include "cmEndMacroCommand.cxx"
-#include "cmEndWhileCommand.cxx"
-#include "cmExecProgramCommand.cxx"
-#include "cmExecuteProcessCommand.cxx"
-#include "cmExternalMakefileProjectGenerator.cxx"
-#include "cmFindBase.cxx"
-#include "cmFindCommon.cxx"
-#include "cmFileCommand.cxx"
-#include "cmFindFileCommand.cxx"
-#include "cmFindLibraryCommand.cxx"
-#include "cmFindPackageCommand.cxx"
-#include "cmFindPathCommand.cxx"
-#include "cmFindProgramCommand.cxx"
-#include "cmForEachCommand.cxx"
-#include "cmFunctionCommand.cxx"
-
-void GetBootstrapCommands1(std::list<cmCommand*>& commands)
-{
- commands.push_back(new cmAddCustomCommandCommand);
- commands.push_back(new cmAddCustomTargetCommand);
- commands.push_back(new cmAddDefinitionsCommand);
- commands.push_back(new cmAddDependenciesCommand);
- commands.push_back(new cmAddExecutableCommand);
- commands.push_back(new cmAddLibraryCommand);
- commands.push_back(new cmAddSubDirectoryCommand);
- commands.push_back(new cmAddTestCommand);
- commands.push_back(new cmBreakCommand);
- commands.push_back(new cmBuildCommand);
- commands.push_back(new cmCMakeMinimumRequired);
- commands.push_back(new cmCMakePolicyCommand);
- commands.push_back(new cmConfigureFileCommand);
- commands.push_back(new cmCreateTestSourceList);
- commands.push_back(new cmDefinePropertyCommand);
- commands.push_back(new cmElseCommand);
- commands.push_back(new cmEnableLanguageCommand);
- commands.push_back(new cmEnableTestingCommand);
- commands.push_back(new cmEndForEachCommand);
- commands.push_back(new cmEndFunctionCommand);
- commands.push_back(new cmEndIfCommand);
- commands.push_back(new cmEndMacroCommand);
- commands.push_back(new cmEndWhileCommand);
- commands.push_back(new cmExecProgramCommand);
- commands.push_back(new cmExecuteProcessCommand);
- commands.push_back(new cmFileCommand);
- commands.push_back(new cmFindFileCommand);
- commands.push_back(new cmFindLibraryCommand);
- commands.push_back(new cmFindPackageCommand);
- commands.push_back(new cmFindPathCommand);
- commands.push_back(new cmFindProgramCommand);
- commands.push_back(new cmForEachCommand);
- commands.push_back(new cmFunctionCommand);
-}
diff --git a/Source/cmBootstrapCommands2.cxx b/Source/cmBootstrapCommands2.cxx
deleted file mode 100644
index be72526ba..000000000
--- a/Source/cmBootstrapCommands2.cxx
+++ /dev/null
@@ -1,102 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-// This file is used to compile all the commands
-// that CMake knows about at compile time.
-// This is sort of a boot strapping approach since you would
-// like to have CMake to build CMake.
-#include "cmCommands.h"
-#include "cmGeneratorExpressionEvaluationFile.cxx"
-#include "cmGetCMakePropertyCommand.cxx"
-#include "cmGetDirectoryPropertyCommand.cxx"
-#include "cmGetFilenameComponentCommand.cxx"
-#include "cmGetPropertyCommand.cxx"
-#include "cmGetSourceFilePropertyCommand.cxx"
-#include "cmGetTargetPropertyCommand.cxx"
-#include "cmHexFileConverter.cxx"
-#include "cmIfCommand.cxx"
-#include "cmIncludeCommand.cxx"
-#include "cmIncludeDirectoryCommand.cxx"
-#include "cmIncludeRegularExpressionCommand.cxx"
-#include "cmInstallFilesCommand.cxx"
-#include "cmInstallCommandArguments.cxx"
-#include "cmInstallCommand.cxx"
-#include "cmInstallTargetsCommand.cxx"
-#include "cmLinkDirectoriesCommand.cxx"
-#include "cmListCommand.cxx"
-#include "cmMacroCommand.cxx"
-#include "cmMakeDirectoryCommand.cxx"
-#include "cmMarkAsAdvancedCommand.cxx"
-#include "cmMathCommand.cxx"
-#include "cmMessageCommand.cxx"
-#include "cmOptionCommand.cxx"
-#include "cmProjectCommand.cxx"
-#include "cmReturnCommand.cxx"
-#include "cmSeparateArgumentsCommand.cxx"
-#include "cmSetCommand.cxx"
-#include "cmSetDirectoryPropertiesCommand.cxx"
-#include "cmSetPropertyCommand.cxx"
-#include "cmSetSourceFilesPropertiesCommand.cxx"
-#include "cmSetTargetPropertiesCommand.cxx"
-#include "cmSetTestsPropertiesCommand.cxx"
-#include "cmGetTestPropertyCommand.cxx"
-#include "cmSiteNameCommand.cxx"
-#include "cmStringCommand.cxx"
-#include "cmSubdirCommand.cxx"
-#include "cmTargetLinkLibrariesCommand.cxx"
-#include "cmTimestamp.cxx"
-#include "cmTryCompileCommand.cxx"
-#include "cmTryRunCommand.cxx"
-#include "cmUnsetCommand.cxx"
-#include "cmWhileCommand.cxx"
-
-void GetBootstrapCommands2(std::list<cmCommand*>& commands)
-{
- commands.push_back(new cmGetCMakePropertyCommand);
- commands.push_back(new cmGetDirectoryPropertyCommand);
- commands.push_back(new cmGetFilenameComponentCommand);
- commands.push_back(new cmGetPropertyCommand);
- commands.push_back(new cmGetSourceFilePropertyCommand);
- commands.push_back(new cmGetTargetPropertyCommand);
- commands.push_back(new cmIfCommand);
- commands.push_back(new cmIncludeCommand);
- commands.push_back(new cmIncludeDirectoryCommand);
- commands.push_back(new cmIncludeRegularExpressionCommand);
- commands.push_back(new cmInstallCommand);
- commands.push_back(new cmInstallFilesCommand);
- commands.push_back(new cmInstallTargetsCommand);
- commands.push_back(new cmLinkDirectoriesCommand);
- commands.push_back(new cmListCommand);
- commands.push_back(new cmMacroCommand);
- commands.push_back(new cmMakeDirectoryCommand);
- commands.push_back(new cmMarkAsAdvancedCommand);
- commands.push_back(new cmMathCommand);
- commands.push_back(new cmMessageCommand);
- commands.push_back(new cmOptionCommand);
- commands.push_back(new cmProjectCommand);
- commands.push_back(new cmReturnCommand);
- commands.push_back(new cmSeparateArgumentsCommand);
- commands.push_back(new cmSetCommand);
- commands.push_back(new cmSetDirectoryPropertiesCommand);
- commands.push_back(new cmSetPropertyCommand);
- commands.push_back(new cmSetSourceFilesPropertiesCommand);
- commands.push_back(new cmSetTargetPropertiesCommand);
- commands.push_back(new cmGetTestPropertyCommand);
- commands.push_back(new cmSetTestsPropertiesCommand);
- commands.push_back(new cmSiteNameCommand);
- commands.push_back(new cmStringCommand);
- commands.push_back(new cmSubdirCommand);
- commands.push_back(new cmTargetLinkLibrariesCommand);
- commands.push_back(new cmTryCompileCommand);
- commands.push_back(new cmTryRunCommand);
- commands.push_back(new cmUnsetCommand);
- commands.push_back(new cmWhileCommand);
-}
diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx
index b70e40088..3772c6fb6 100644
--- a/Source/cmBreakCommand.cxx
+++ b/Source/cmBreakCommand.cxx
@@ -1,21 +1,74 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmBreakCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmBreakCommand.h"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmake.h"
// cmBreakCommand
-bool cmBreakCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &status)
+bool cmBreakCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- status.SetBreakInvoked(true);
+ if (!this->Makefile->IsLoopBlock()) {
+ bool issueMessage = true;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ messageType = cmake::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) {
+ return false;
+ }
+ }
+ }
+
+ status.SetBreakInvoked();
+
+ if (!args.empty()) {
+ bool issueMessage = true;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ messageType = cmake::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) {
+ return false;
+ }
+ }
+ }
+
return true;
}
-
diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h
index 17f57cfa1..fcca45c31 100644
--- a/Source/cmBreakCommand.h
+++ b/Source/cmBreakCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmBreakCommand_h
#define cmBreakCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmBreakCommand
* \brief Break from an enclosing foreach or while loop
*
@@ -25,49 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmBreakCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmBreakCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "break";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Break from an enclosing foreach or while loop.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " break()\n"
- "Breaks from an enclosing foreach loop or while loop";
- }
-
- cmTypeMacro(cmBreakCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index b6e2569a5..fd876004b 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -1,169 +1,128 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmBuildCommand.h"
-#include "cmLocalGenerator.h"
+#include <sstream>
+
#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-//----------------------------------------------------------------------
-bool cmBuildCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+class cmExecutionStatus;
+
+bool cmBuildCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
// Support the legacy signature of the command:
//
- if(2 == args.size())
- {
+ if (2 == args.size()) {
return this->TwoArgsSignature(args);
- }
+ }
return this->MainSignature(args);
}
-//----------------------------------------------------------------------
-bool cmBuildCommand
-::MainSignature(std::vector<std::string> const& args)
+bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("requires at least one argument naming a CMake variable");
return false;
- }
+ }
// The cmake variable in which to store the result.
- const char* variable = args[0].c_str();
+ std::string const& variable = args[0];
// Parse remaining arguments.
- const char* configuration = 0;
- const char* project_name = 0;
- const char* target = 0;
- enum Doing { DoingNone, DoingConfiguration, DoingProjectName, DoingTarget };
+ std::string configuration;
+ std::string project_name;
+ std::string target;
+ enum Doing
+ {
+ DoingNone,
+ DoingConfiguration,
+ DoingProjectName,
+ DoingTarget
+ };
Doing doing = DoingNone;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "CONFIGURATION")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "CONFIGURATION") {
doing = DoingConfiguration;
- }
- else if(args[i] == "PROJECT_NAME")
- {
+ } else if (args[i] == "PROJECT_NAME") {
doing = DoingProjectName;
- }
- else if(args[i] == "TARGET")
- {
+ } else if (args[i] == "TARGET") {
doing = DoingTarget;
- }
- else if(doing == DoingConfiguration)
- {
+ } else if (doing == DoingConfiguration) {
doing = DoingNone;
- configuration = args[i].c_str();
- }
- else if(doing == DoingProjectName)
- {
+ configuration = args[i];
+ } else if (doing == DoingProjectName) {
doing = DoingNone;
- project_name = args[i].c_str();
- }
- else if(doing == DoingTarget)
- {
+ project_name = args[i];
+ } else if (doing == DoingTarget) {
doing = DoingNone;
- target = args[i].c_str();
- }
- else
- {
- cmOStringStream e;
+ target = args[i];
+ } else {
+ std::ostringstream e;
e << "unknown argument \"" << args[i] << "\"";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
- }
-
- const char* makeprogram
- = this->Makefile->GetDefinition("CMAKE_MAKE_PROGRAM");
- if(!makeprogram)
- {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "build_command() requires CMAKE_MAKE_PROGRAM to be defined. "
- "Call project() or enable_language() first.");
- return true;
}
+ }
- // If null/empty CONFIGURATION argument, GenerateBuildCommand uses 'Debug'
+ // If null/empty CONFIGURATION argument, cmake --build uses 'Debug'
// in the currently implemented multi-configuration global generators...
// so we put this code here to end up with the same default configuration
// as the original 2-arg build_command signature:
//
- if(!configuration || !*configuration)
- {
- configuration = getenv("CMAKE_CONFIG_TYPE");
- }
- if(!configuration || !*configuration)
- {
+ if (configuration.empty()) {
+ cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configuration);
+ }
+ if (configuration.empty()) {
configuration = "Release";
- }
+ }
- // If null/empty PROJECT_NAME argument, use the Makefile's project name:
- //
- if(!project_name || !*project_name)
- {
- project_name = this->Makefile->GetProjectName();
- }
+ if (!project_name.empty()) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ "Ignoring PROJECT_NAME option because it has no effect.");
+ }
- // If null/empty TARGET argument, GenerateBuildCommand omits any mention
- // of a target name on the build command line...
- //
- std::string makecommand = this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->GenerateBuildCommand
- (makeprogram, project_name, 0, 0, target, configuration, true, false);
+ std::string makecommand =
+ this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
+ target, configuration, "", this->Makefile->IgnoreErrorsCMP0061());
this->Makefile->AddDefinition(variable, makecommand.c_str());
return true;
}
-//----------------------------------------------------------------------
-bool cmBuildCommand
-::TwoArgsSignature(std::vector<std::string> const& args)
+bool cmBuildCommand::TwoArgsSignature(std::vector<std::string> const& args)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with less than two arguments");
return false;
- }
+ }
- const char* define = args[0].c_str();
- const char* cacheValue
- = this->Makefile->GetDefinition(define);
- std::string makeprogram = args[1];
+ std::string const& define = args[0];
+ const char* cacheValue = this->Makefile->GetDefinition(define);
- std::string configType = "Release";
- const char* cfg = getenv("CMAKE_CONFIG_TYPE");
- if ( cfg )
- {
- configType = cfg;
- }
+ std::string configType;
+ if (!cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType) ||
+ configType.empty()) {
+ configType = "Release";
+ }
- std::string makecommand = this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->GenerateBuildCommand
- (makeprogram.c_str(), this->Makefile->GetProjectName(), 0, 0,
- 0, configType.c_str(), true, false);
+ std::string makecommand =
+ this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
+ "", configType, "", this->Makefile->IgnoreErrorsCMP0061());
- if(cacheValue)
- {
+ if (cacheValue) {
return true;
- }
- this->Makefile->AddCacheDefinition(define,
- makecommand.c_str(),
- "Command used to build entire project "
- "from the command line.",
- cmCacheManager::STRING);
+ }
+ this->Makefile->AddCacheDefinition(define, makecommand.c_str(),
+ "Command used to build entire project "
+ "from the command line.",
+ cmStateEnums::STRING);
return true;
}
diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h
index 1bab4536e..1f357a980 100644
--- a/Source/cmBuildCommand.h
+++ b/Source/cmBuildCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmBuildCommand_h
#define cmBuildCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmBuildCommand
* \brief build_command command
*
@@ -25,17 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmBuildCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmBuildCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
* The primary command signature with optional, KEYWORD-based args.
@@ -47,51 +42,8 @@ public:
*/
virtual bool TwoArgsSignature(std::vector<std::string> const& args);
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "build_command";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get the command line to build this project.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " build_command(<variable>\n"
- " [CONFIGURATION <config>]\n"
- " [PROJECT_NAME <projname>]\n"
- " [TARGET <target>])\n"
- "Sets the given <variable> to a string containing the command line "
- "for building one configuration of a target in a project using the "
- "build tool appropriate for the current CMAKE_GENERATOR.\n"
- "If CONFIGURATION is omitted, CMake chooses a reasonable default "
- "value for multi-configuration generators. CONFIGURATION is "
- "ignored for single-configuration generators.\n"
- "If PROJECT_NAME is omitted, the resulting command line will build "
- "the top level PROJECT in the current build tree.\n"
- "If TARGET is omitted, the resulting command line will build "
- "everything, effectively using build target 'all' or 'ALL_BUILD'.\n"
- " build_command(<cachevariable> <makecommand>)\n"
- "This second signature is deprecated, but still available for "
- "backwards compatibility. Use the first signature instead.\n"
- "Sets the given <cachevariable> to a string containing the command "
- "to build this project from the root of the build tree using "
- "the build tool given by <makecommand>. <makecommand> should be "
- "the full path to msdev, devenv, nmake, make or one of the end "
- "user build tools."
- ;
- }
-
- cmTypeMacro(cmBuildCommand, cmCommand);
+private:
+ bool IgnoreErrors() const;
};
#endif
diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx
index f95a79eda..9d2c0c642 100644
--- a/Source/cmBuildNameCommand.cxx
+++ b/Source/cmBuildNameCommand.cxx
@@ -1,77 +1,60 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmBuildNameCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmBuildNameCommand.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
-#include <cmsys/RegularExpression.hxx>
+class cmExecutionStatus;
// cmBuildNameCommand
-bool cmBuildNameCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- const char* cacheValue = this->Makefile->GetDefinition(args[0].c_str());
- if(cacheValue)
- {
+ }
+ const char* cacheValue = this->Makefile->GetDefinition(args[0]);
+ if (cacheValue) {
// do we need to correct the value?
cmsys::RegularExpression reg("[()/]");
- if (reg.find(cacheValue))
- {
+ if (reg.find(cacheValue)) {
std::string cv = cacheValue;
- cmSystemTools::ReplaceString(cv,"/", "_");
- cmSystemTools::ReplaceString(cv,"(", "_");
- cmSystemTools::ReplaceString(cv,")", "_");
- this->Makefile->AddCacheDefinition(args[0].c_str(),
- cv.c_str(),
- "Name of build.",
- cmCacheManager::STRING);
- }
- return true;
+ 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);
}
-
+ return true;
+ }
std::string buildname = "WinNT";
- if(this->Makefile->GetDefinition("UNIX"))
- {
+ if (this->Makefile->GetDefinition("UNIX")) {
buildname = "";
- cmSystemTools::RunSingleCommand("uname -a", &buildname);
- if(buildname.length())
- {
+ 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.c_str());
+ if (reg.find(buildname.c_str())) {
buildname = reg.match(1) + "-" + reg.match(2);
- }
}
}
+ }
std::string compiler = "${CMAKE_CXX_COMPILER}";
- this->Makefile->ExpandVariablesInString ( compiler );
+ this->Makefile->ExpandVariablesInString(compiler);
buildname += "-";
buildname += cmSystemTools::GetFilenameName(compiler);
- cmSystemTools::ReplaceString(buildname,
- "/", "_");
- cmSystemTools::ReplaceString(buildname,
- "(", "_");
- cmSystemTools::ReplaceString(buildname,
- ")", "_");
+ std::replace(buildname.begin(), buildname.end(), '/', '_');
+ std::replace(buildname.begin(), buildname.end(), '(', '_');
+ std::replace(buildname.begin(), buildname.end(), ')', '_');
- this->Makefile->AddCacheDefinition(args[0].c_str(),
- buildname.c_str(),
- "Name of build.",
- cmCacheManager::STRING);
+ this->Makefile->AddCacheDefinition(args[0], buildname.c_str(),
+ "Name of build.", cmStateEnums::STRING);
return true;
}
-
diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h
index 26505a260..ff26c559c 100644
--- a/Source/cmBuildNameCommand.h
+++ b/Source/cmBuildNameCommand.h
@@ -1,82 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmBuildNameCommand_h
#define cmBuildNameCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-/** \class cmBuildNameCommand
- * \brief build_name command
- *
- * cmBuildNameCommand implements the build_name CMake command
- */
+class cmExecutionStatus;
+
class cmBuildNameCommand : public cmCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmBuildNameCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "build_name";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Deprecated. Use ${CMAKE_SYSTEM} and ${CMAKE_CXX_COMPILER} instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " build_name(variable)\n"
- "Sets the specified variable to a string representing the platform "
- "and compiler settings. These values are now available through the "
- "CMAKE_SYSTEM and CMAKE_CXX_COMPILER variables.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmBuildNameCommand, cmCommand);
+ cmCommand* Clone() CM_OVERRIDE { return new cmBuildNameCommand; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmCLocaleEnvironmentScope.cxx b/Source/cmCLocaleEnvironmentScope.cxx
new file mode 100644
index 000000000..28e8f2efc
--- /dev/null
+++ b/Source/cmCLocaleEnvironmentScope.cxx
@@ -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. */
+#include "cmCLocaleEnvironmentScope.h"
+
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <utility>
+
+cmCLocaleEnvironmentScope::cmCLocaleEnvironmentScope()
+{
+ this->SetEnv("LANGUAGE", "");
+ this->SetEnv("LC_MESSAGES", "C");
+
+ std::string lcAll = this->GetEnv("LC_ALL");
+
+ if (!lcAll.empty()) {
+ this->SetEnv("LC_ALL", "");
+ this->SetEnv("LC_CTYPE", lcAll);
+ }
+}
+
+std::string cmCLocaleEnvironmentScope::GetEnv(std::string const& key)
+{
+ std::string value;
+ cmSystemTools::GetEnv(key, value);
+ return value;
+}
+
+void cmCLocaleEnvironmentScope::SetEnv(std::string const& key,
+ std::string const& value)
+{
+ std::string oldValue = this->GetEnv(key);
+
+ this->EnvironmentBackup.insert(std::make_pair(key, oldValue));
+
+ if (value.empty()) {
+ cmSystemTools::UnsetEnv(key.c_str());
+ } else {
+ std::ostringstream tmp;
+ tmp << key << "=" << value;
+ cmSystemTools::PutEnv(tmp.str());
+ }
+}
+
+cmCLocaleEnvironmentScope::~cmCLocaleEnvironmentScope()
+{
+ for (backup_map_t::const_iterator i = this->EnvironmentBackup.begin();
+ i != this->EnvironmentBackup.end(); ++i) {
+ std::ostringstream tmp;
+ tmp << i->first << "=" << i->second;
+ cmSystemTools::PutEnv(tmp.str());
+ }
+}
diff --git a/Source/cmCLocaleEnvironmentScope.h b/Source/cmCLocaleEnvironmentScope.h
new file mode 100644
index 000000000..e956cb24d
--- /dev/null
+++ b/Source/cmCLocaleEnvironmentScope.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 cmCLocaleEnvironmentScope_h
+#define cmCLocaleEnvironmentScope_h
+
+#include "cmConfigure.h"
+
+#include <map>
+#include <string>
+
+class cmCLocaleEnvironmentScope
+{
+ CM_DISABLE_COPY(cmCLocaleEnvironmentScope)
+
+public:
+ cmCLocaleEnvironmentScope();
+ ~cmCLocaleEnvironmentScope();
+
+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;
+ backup_map_t EnvironmentBackup;
+};
+
+#endif
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 62f238369..4475c5a52 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -1,38 +1,38 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCMakeHostSystemInformationCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCMakeHostSystemInformationCommand.h"
+#include "cmMakefile.h"
+#include "cmsys/SystemInformation.hxx"
+
+#if defined(_WIN32)
+#include "cmSystemTools.h"
+#include "cmVSSetupHelper.h"
+#define HAVE_VS_SETUP_HELPER
+#endif
-#include <cmsys/ios/sstream>
+class cmExecutionStatus;
// cmCMakeHostSystemInformation
-bool cmCMakeHostSystemInformationCommand
-::InitialPass(std::vector<std::string> const &args, cmExecutionStatus &)
+bool cmCMakeHostSystemInformationCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
size_t current_index = 0;
- if(args.size() < (current_index + 2) || args[current_index] != "RESULT")
- {
+ if (args.size() < (current_index + 2) || args[current_index] != "RESULT") {
this->SetError("missing RESULT specification.");
return false;
- }
+ }
- std::string variable = args[current_index + 1];
+ std::string const& variable = args[current_index + 1];
current_index += 2;
- if(args.size() < (current_index + 2) || args[current_index] != "QUERY")
- {
+ if (args.size() < (current_index + 2) || args[current_index] != "QUERY") {
this->SetError("missing QUERY specification");
return false;
- }
+ }
cmsys::SystemInformation info;
info.RunCPUCheck();
@@ -40,87 +40,75 @@ bool cmCMakeHostSystemInformationCommand
info.RunMemoryCheck();
std::string result_list;
- for(size_t i = current_index + 1; i < args.size(); ++i)
- {
- std::string key = args[i];
- if(i != current_index + 1)
- {
+ for (size_t i = current_index + 1; i < args.size(); ++i) {
+ std::string const& key = args[i];
+ if (i != current_index + 1) {
result_list += ";";
- }
+ }
std::string value;
- if(!this->GetValue(info, key, value)) return false;
-
- result_list += value;
+ if (!this->GetValue(info, key, value)) {
+ return false;
}
+ result_list += value;
+ }
- this->Makefile->AddDefinition(variable.c_str(), result_list.c_str());
+ this->Makefile->AddDefinition(variable, result_list.c_str());
return true;
}
-bool cmCMakeHostSystemInformationCommand
-::GetValue(cmsys::SystemInformation &info,
- std::string const& key, std::string &value)
+bool cmCMakeHostSystemInformationCommand::GetValue(
+ cmsys::SystemInformation& info, std::string const& key, std::string& value)
{
- if(key == "NUMBER_OF_LOGICAL_CORES")
- {
+ if (key == "NUMBER_OF_LOGICAL_CORES") {
value = this->ValueToString(info.GetNumberOfLogicalCPU());
- }
- else if(key == "NUMBER_OF_PHYSICAL_CORES")
- {
+ } else if (key == "NUMBER_OF_PHYSICAL_CORES") {
value = this->ValueToString(info.GetNumberOfPhysicalCPU());
- }
- else if(key == "HOSTNAME")
- {
+ } else if (key == "HOSTNAME") {
value = this->ValueToString(info.GetHostname());
- }
- else if(key == "FQDN")
- {
+ } else if (key == "FQDN") {
value = this->ValueToString(info.GetFullyQualifiedDomainName());
- }
- else if(key == "TOTAL_VIRTUAL_MEMORY")
- {
+ } else if (key == "TOTAL_VIRTUAL_MEMORY") {
value = this->ValueToString(info.GetTotalVirtualMemory());
- }
- else if(key == "AVAILABLE_VIRTUAL_MEMORY")
- {
+ } else if (key == "AVAILABLE_VIRTUAL_MEMORY") {
value = this->ValueToString(info.GetAvailableVirtualMemory());
- }
- else if(key == "TOTAL_PHYSICAL_MEMORY")
- {
+ } else if (key == "TOTAL_PHYSICAL_MEMORY") {
value = this->ValueToString(info.GetTotalPhysicalMemory());
- }
- else if(key == "AVAILABLE_PHYSICAL_MEMORY")
- {
+ } else if (key == "AVAILABLE_PHYSICAL_MEMORY") {
value = this->ValueToString(info.GetAvailablePhysicalMemory());
+#ifdef HAVE_VS_SETUP_HELPER
+ } else if (key == "VS_15_DIR") {
+ cmVSSetupAPIHelper vsSetupAPIHelper;
+ if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
+ cmSystemTools::ConvertToUnixSlashes(value);
}
- else
- {
+#endif
+ } else {
std::string e = "does not recognize <key> " + key;
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
- }
+ }
return true;
}
-std::string cmCMakeHostSystemInformationCommand
-::ValueToString(size_t value) const
+std::string cmCMakeHostSystemInformationCommand::ValueToString(
+ size_t value) const
{
- cmsys_ios::stringstream tmp;
+ std::ostringstream tmp;
tmp << value;
return tmp.str();
}
-std::string cmCMakeHostSystemInformationCommand
-::ValueToString(const char *value) const
+std::string cmCMakeHostSystemInformationCommand::ValueToString(
+ const char* value) const
{
std::string safe_string = value ? value : "";
return safe_string;
}
-std::string cmCMakeHostSystemInformationCommand
-::ValueToString(std::string const& value) const
+std::string cmCMakeHostSystemInformationCommand::ValueToString(
+ std::string const& value) const
{
return value;
}
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
index d1b8700ff..ef6ca3730 100644
--- a/Source/cmCMakeHostSystemInformationCommand.h
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -1,20 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCMakeHostSystemInformationCommand_h
#define cmCMakeHostSystemInformationCommand_h
+#include "cmConfigure.h"
+
+#include <stddef.h>
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include <cmsys/SystemInformation.hxx>
+class cmExecutionStatus;
+namespace cmsys {
+class SystemInformation;
+} // namespace cmsys
/** \class cmCMakeHostSystemInformationCommand
* \brief Query host system specific information
@@ -28,74 +28,24 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
return new cmCMakeHostSystemInformationCommand;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const
- {
- return "cmake_host_system_information";
- }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Query host system specific information.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " cmake_host_system_information(RESULT <variable> QUERY <key> ...)\n"
- "Queries system information of the host system on which cmake runs. "
- "One or more <key> can be provided to "
- "select the information to be queried. "
- "The list of queried values is stored in <variable>.\n"
- "<key> can be one of the following values:\n"
- " NUMBER_OF_LOGICAL_CORES = Number of logical cores.\n"
- " NUMBER_OF_PHYSICAL_CORES = Number of physical cores.\n"
- " HOSTNAME = Hostname.\n"
- " FQDN = Fully qualified domain name.\n"
- " TOTAL_VIRTUAL_MEMORY = "
- "Total virtual memory in megabytes.\n"
- " AVAILABLE_VIRTUAL_MEMORY = "
- "Available virtual memory in megabytes.\n"
- " TOTAL_PHYSICAL_MEMORY = "
- "Total physical memory in megabytes.\n"
- " AVAILABLE_PHYSICAL_MEMORY = "
- "Available physical memory in megabytes.\n"
- ;
- }
-
- cmTypeMacro(cmCMakeHostSystemInformationCommand, cmCommand);
+ 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);
+ 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(const char* value) const;
std::string ValueToString(std::string const& value) const;
};
diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx
index 49c585fba..942688cee 100644
--- a/Source/cmCMakeMinimumRequired.cxx
+++ b/Source/cmCMakeMinimumRequired.cxx
@@ -1,139 +1,116 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeMinimumRequired.h"
+#include <sstream>
+#include <stdio.h>
+
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
// cmCMakeMinimumRequired
-bool cmCMakeMinimumRequired
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
// Process arguments.
std::string version_string;
bool doing_version = false;
- for(unsigned int i=0; i < args.size(); ++i)
- {
- if(args[i] == "VERSION")
- {
+ for (unsigned int i = 0; i < args.size(); ++i) {
+ if (args[i] == "VERSION") {
doing_version = true;
- }
- else if(args[i] == "FATAL_ERROR")
- {
- if(doing_version)
- {
+ } else if (args[i] == "FATAL_ERROR") {
+ if (doing_version) {
this->SetError("called with no value for VERSION.");
return false;
- }
- doing_version = false;
}
- else if(doing_version)
- {
+ doing_version = false;
+ } else if (doing_version) {
doing_version = false;
version_string = args[i];
- }
- else
- {
+ } else {
this->UnknownArguments.push_back(args[i]);
- }
}
- if(doing_version)
- {
+ }
+ if (doing_version) {
this->SetError("called with no value for VERSION.");
return false;
- }
+ }
// Make sure there was a version to check.
- if(version_string.empty())
- {
+ if (version_string.empty()) {
return this->EnforceUnknownArguments();
- }
+ }
// Save the required version string.
this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
version_string.c_str());
-
// Get the current version number.
- int current_major = cmVersion::GetMajorVersion();
- int current_minor = cmVersion::GetMinorVersion();
- int current_patch = cmVersion::GetPatchVersion();
- int current_tweak = cmVersion::GetTweakVersion();
+ unsigned int current_major = cmVersion::GetMajorVersion();
+ unsigned int current_minor = cmVersion::GetMinorVersion();
+ unsigned int current_patch = cmVersion::GetPatchVersion();
+ unsigned int current_tweak = cmVersion::GetTweakVersion();
// Parse at least two components of the version number.
// Use zero for those not specified.
- int required_major = 0;
- int required_minor = 0;
- int required_patch = 0;
- int required_tweak = 0;
- if(sscanf(version_string.c_str(), "%u.%u.%u.%u",
- &required_major, &required_minor,
- &required_patch, &required_tweak) < 2)
- {
- cmOStringStream e;
- e << "could not parse VERSION \"" << version_string.c_str() << "\".";
- this->SetError(e.str().c_str());
+ unsigned int required_major = 0;
+ 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,
+ &required_minor, &required_patch, &required_tweak) < 2) {
+ std::ostringstream e;
+ e << "could not parse VERSION \"" << version_string << "\".";
+ this->SetError(e.str());
return false;
- }
+ }
// Compare the version numbers.
- if((current_major < required_major) ||
- (current_major == required_major &&
- current_minor < required_minor) ||
- (current_major == required_major &&
- current_minor == required_minor &&
- current_patch < required_patch) ||
- (current_major == required_major &&
- current_minor == required_minor &&
- current_patch == required_patch &&
- current_tweak < required_tweak))
- {
+ if ((current_major < required_major) ||
+ (current_major == required_major && current_minor < required_minor) ||
+ (current_major == required_major && current_minor == required_minor &&
+ current_patch < required_patch) ||
+ (current_major == required_major && current_minor == required_minor &&
+ current_patch == required_patch && current_tweak < required_tweak)) {
// The current version is too low.
- cmOStringStream e;
- e << "CMake " << version_string.c_str()
+ std::ostringstream e;
+ e << "CMake " << version_string
<< " or higher is required. You are running version "
<< cmVersion::GetCMakeVersion();
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
return true;
- }
+ }
// The version is not from the future, so enforce unknown arguments.
- if(!this->EnforceUnknownArguments())
- {
+ if (!this->EnforceUnknownArguments()) {
return false;
- }
+ }
- if (required_major < 2 || (required_major == 2 && required_minor < 4))
- {
+ if (required_major < 2 || (required_major == 2 && required_minor < 4)) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
this->Makefile->SetPolicyVersion("2.4");
- }
- else
- {
+ } else {
this->Makefile->SetPolicyVersion(version_string.c_str());
}
return true;
}
-//----------------------------------------------------------------------------
bool cmCMakeMinimumRequired::EnforceUnknownArguments()
{
- if(!this->UnknownArguments.empty())
- {
- cmOStringStream e;
- e << "called with unknown argument \""
- << this->UnknownArguments[0] << "\".";
- this->SetError(e.str().c_str());
+ if (!this->UnknownArguments.empty()) {
+ std::ostringstream e;
+ e << "called with unknown argument \"" << this->UnknownArguments[0]
+ << "\".";
+ this->SetError(e.str());
return false;
- }
+ }
return true;
}
diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h
index acf28298b..45b6b7885 100644
--- a/Source/cmCMakeMinimumRequired.h
+++ b/Source/cmCMakeMinimumRequired.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCMakeMinimumRequired_h
#define cmCMakeMinimumRequired_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmCMakeMinimumRequired
* \brief cmake_minimum_required command
*
@@ -25,66 +23,18 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmCMakeMinimumRequired;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmCMakeMinimumRequired; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "cmake_minimum_required";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set the minimum required version of cmake for a project.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " cmake_minimum_required(VERSION major[.minor[.patch[.tweak]]]\n"
- " [FATAL_ERROR])\n"
- "If the current version of CMake is lower than that required "
- "it will stop processing the project and report an error. "
- "When a version higher than 2.4 is specified the command implicitly "
- "invokes\n"
- " cmake_policy(VERSION major[.minor[.patch[.tweak]]])\n"
- "which sets the cmake policy version level to the version specified. "
- "When version 2.4 or lower is given the command implicitly invokes\n"
- " cmake_policy(VERSION 2.4)\n"
- "which enables compatibility features for CMake 2.4 and lower.\n"
- "The FATAL_ERROR option is accepted but ignored by CMake 2.6 "
- "and higher. "
- "It should be specified so CMake versions 2.4 and lower fail with an "
- "error instead of just a warning.";
- }
-
- cmTypeMacro(cmCMakeMinimumRequired, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
std::vector<std::string> UnknownArguments;
bool EnforceUnknownArguments();
};
-
-
#endif
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index f4be55930..3ccc815e6 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -1,109 +1,104 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCMakePolicyCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCMakePolicyCommand.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmake.h"
-#include "cmVersion.h"
+class cmExecutionStatus;
// cmCMakePolicyCommand
-bool cmCMakePolicyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCMakePolicyCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("requires at least one argument.");
return false;
- }
+ }
- if(args[0] == "SET")
- {
+ if (args[0] == "SET") {
return this->HandleSetMode(args);
- }
- else if(args[0] == "GET")
- {
+ }
+ if (args[0] == "GET") {
return this->HandleGetMode(args);
- }
- else if(args[0] == "PUSH")
- {
- if(args.size() > 1)
- {
+ }
+ if (args[0] == "PUSH") {
+ if (args.size() > 1) {
this->SetError("PUSH may not be given additional arguments.");
return false;
- }
+ }
this->Makefile->PushPolicy();
return true;
- }
- else if(args[0] == "POP")
- {
- if(args.size() > 1)
- {
+ }
+ if (args[0] == "POP") {
+ if (args.size() > 1) {
this->SetError("POP may not be given additional arguments.");
return false;
- }
+ }
this->Makefile->PopPolicy();
return true;
- }
- else if(args[0] == "VERSION")
- {
+ }
+ if (args[0] == "VERSION") {
return this->HandleVersionMode(args);
- }
+ }
- cmOStringStream e;
+ std::ostringstream e;
e << "given unknown first argument \"" << args[0] << "\"";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
}
-//----------------------------------------------------------------------------
bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
this->SetError("SET must be given exactly 2 additional arguments.");
return false;
- }
+ }
cmPolicies::PolicyStatus status;
- if(args[2] == "OLD")
- {
+ if (args[2] == "OLD") {
status = cmPolicies::OLD;
- }
- else if(args[2] == "NEW")
- {
+ } else if (args[2] == "NEW") {
status = cmPolicies::NEW;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "SET given unrecognized policy status \"" << args[2] << "\"";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- if(!this->Makefile->SetPolicy(args[1].c_str(), status))
- {
+ if (!this->Makefile->SetPolicy(args[1].c_str(), status)) {
this->SetError("SET failed to set policy.");
return false;
- }
+ }
+ if (args[1] == "CMP0001" &&
+ (status == cmPolicies::WARN || status == cmPolicies::OLD)) {
+ if (!(this->Makefile->GetState()->GetInitializedCacheValue(
+ "CMAKE_BACKWARDS_COMPATIBILITY"))) {
+ // Set it to 2.4 because that is the last version where the
+ // variable had meaning.
+ this->Makefile->AddCacheDefinition(
+ "CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
+ "For backwards compatibility, what version of CMake "
+ "commands and "
+ "syntax should this version of CMake try to support.",
+ cmStateEnums::STRING);
+ }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
this->SetError("GET must be given exactly 2 additional arguments.");
return false;
- }
+ }
// Get arguments.
std::string const& id = args[1];
@@ -111,62 +106,56 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args)
// Lookup the policy number.
cmPolicies::PolicyID pid;
- if(!this->Makefile->GetPolicies()->GetPolicyID(id.c_str(), pid))
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Lookup the policy setting.
cmPolicies::PolicyStatus status = this->Makefile->GetPolicyStatus(pid);
- switch (status)
- {
+ switch (status) {
case cmPolicies::OLD:
// Report that the policy is set to OLD.
- this->Makefile->AddDefinition(var.c_str(), "OLD");
+ this->Makefile->AddDefinition(var, "OLD");
break;
case cmPolicies::WARN:
// Report that the policy is not set.
- this->Makefile->AddDefinition(var.c_str(), "");
+ this->Makefile->AddDefinition(var, "");
break;
case cmPolicies::NEW:
// Report that the policy is set to NEW.
- this->Makefile->AddDefinition(var.c_str(), "NEW");
+ this->Makefile->AddDefinition(var, "NEW");
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
// The policy is required to be set before anything needs it.
{
- cmOStringStream e;
- e << this->Makefile->GetPolicies()->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());
+ 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());
}
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmCMakePolicyCommand::HandleVersionMode(std::vector<std::string> const& args)
+bool cmCMakePolicyCommand::HandleVersionMode(
+ std::vector<std::string> const& args)
{
- if(args.size() <= 1)
- {
+ if (args.size() <= 1) {
this->SetError("VERSION not given an argument");
return false;
- }
- else if(args.size() >= 3)
- {
+ }
+ if (args.size() >= 3) {
this->SetError("VERSION given too many arguments");
return false;
- }
+ }
this->Makefile->SetPolicyVersion(args[1].c_str());
return true;
}
diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h
index 4f9faa168..0e88243f5 100644
--- a/Source/cmCMakePolicyCommand.h
+++ b/Source/cmCMakePolicyCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCMakePolicyCommand_h
#define cmCMakePolicyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmCMakePolicyCommand
* \brief Set how CMake should handle policies
*
@@ -26,117 +24,19 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmCMakePolicyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmCMakePolicyCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "cmake_policy";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Manage CMake Policy settings.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "As CMake evolves it is sometimes necessary to change existing "
- "behavior in order to fix bugs or improve implementations of "
- "existing features. "
- "The CMake Policy mechanism is designed to help keep existing projects "
- "building as new versions of CMake introduce changes in behavior. "
- "Each new policy (behavioral change) is given an identifier of "
- "the form \"CMP<NNNN>\" where \"<NNNN>\" is an integer index. "
- "Documentation associated with each policy describes the OLD and NEW "
- "behavior and the reason the policy was introduced. "
- "Projects may set each policy to select the desired behavior. "
- "When CMake needs to know which behavior to use it checks for "
- "a setting specified by the project. "
- "If no setting is available the OLD behavior is assumed and a warning "
- "is produced requesting that the policy be set.\n"
- "The cmake_policy command is used to set policies to OLD or NEW "
- "behavior. "
- "While setting policies individually is supported, we encourage "
- "projects to set policies based on CMake versions.\n"
- " cmake_policy(VERSION major.minor[.patch[.tweak]])\n"
- "Specify that the current CMake list file is written for the "
- "given version of CMake. "
- "All policies introduced in the specified version or earlier "
- "will be set to use NEW behavior. "
- "All policies introduced after the specified version will be unset "
- "(unless variable CMAKE_POLICY_DEFAULT_CMP<NNNN> sets a default). "
- "This effectively requests behavior preferred as of a given CMake "
- "version and tells newer CMake versions to warn about their new "
- "policies. "
- "The policy version specified must be at least 2.4 or the command "
- "will report an error. "
- "In order to get compatibility features supporting versions earlier "
- "than 2.4 see documentation of policy CMP0001."
- "\n"
- " cmake_policy(SET CMP<NNNN> NEW)\n"
- " cmake_policy(SET CMP<NNNN> OLD)\n"
- "Tell CMake to use the OLD or NEW behavior for a given policy. "
- "Projects depending on the old behavior of a given policy may "
- "silence a policy warning by setting the policy state to OLD. "
- "Alternatively one may fix the project to work with the new behavior "
- "and set the policy state to NEW."
- "\n"
- " cmake_policy(GET CMP<NNNN> <variable>)\n"
- "Check whether a given policy is set to OLD or NEW behavior. "
- "The output variable value will be \"OLD\" or \"NEW\" if the "
- "policy is set, and empty otherwise."
- "\n"
- "CMake keeps policy settings on a stack, so changes made by the "
- "cmake_policy command affect only the top of the stack. "
- "A new entry on the policy stack is managed automatically for each "
- "subdirectory to protect its parents and siblings. "
- "CMake also manages a new entry for scripts loaded by include() and "
- "find_package() commands except when invoked with the NO_POLICY_SCOPE "
- "option (see also policy CMP0011). "
- "The cmake_policy command provides an interface to manage custom "
- "entries on the policy stack:\n"
- " cmake_policy(PUSH)\n"
- " cmake_policy(POP)\n"
- "Each PUSH must have a matching POP to erase any changes. "
- "This is useful to make temporary changes to policy settings."
- "\n"
- "Functions and macros record policy settings when they are created "
- "and use the pre-record policies when they are invoked. "
- "If the function or macro implementation sets policies, the changes "
- "automatically propagate up through callers until they reach the "
- "closest nested policy stack entry."
- ;
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- cmTypeMacro(cmCMakePolicyCommand, cmCommand);
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);
};
-
-
#endif
diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx
new file mode 100644
index 000000000..57a8b383c
--- /dev/null
+++ b/Source/cmCPackPropertiesGenerator.cxx
@@ -0,0 +1,48 @@
+#include "cmCPackPropertiesGenerator.h"
+
+#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)
+ : cmScriptGenerator("CPACK_BUILD_CONFIG", configurations)
+ , LG(lg)
+ , InstalledFile(installedFile)
+{
+ this->ActionsPerConfig = true;
+}
+
+void cmCPackPropertiesGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ std::string const& expandedFileName =
+ this->InstalledFile.GetNameExpression().Evaluate(this->LG, config);
+
+ 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;
+
+ 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);
+ os << " " << cmOutputConverter::EscapeForCMake(value);
+ }
+
+ os << ")\n";
+ }
+}
diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h
new file mode 100644
index 000000000..48f4c10f4
--- /dev/null
+++ b/Source/cmCPackPropertiesGenerator.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackPropertiesGenerator_h
+#define cmCPackPropertiesGenerator_h
+
+#include "cmConfigure.h"
+
+#include "cmScriptGenerator.h"
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmInstalledFile;
+class cmLocalGenerator;
+
+/** \class cmCPackPropertiesGenerator
+ * \brief Support class for generating CPackProperties.cmake.
+ *
+ */
+class cmCPackPropertiesGenerator : public cmScriptGenerator
+{
+ CM_DISABLE_COPY(cmCPackPropertiesGenerator)
+
+public:
+ cmCPackPropertiesGenerator(cmLocalGenerator* lg,
+ cmInstalledFile const& installedFile,
+ std::vector<std::string> const& configurations);
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) CM_OVERRIDE;
+
+ cmLocalGenerator* LG;
+ cmInstalledFile const& InstalledFile;
+};
+
+#endif
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index cb62f21e6..e78f5fe04 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -1,209 +1,198 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
/*
this file contains the implementation of the C API to CMake. Generally
these routines just manipulate arguments and then call the associated
methods on the CMake classes. */
-#include "cmMakefile.h"
#include "cmCPluginAPI.h"
-#include "cmVersion.h"
+#include "cmExecutionStatus.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
+#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"
-{
+extern "C" {
-void CCONV *cmGetClientData(void *info)
+void CCONV* cmGetClientData(void* info)
{
- return ((cmLoadedCommandInfo *)info)->ClientData;
+ return ((cmLoadedCommandInfo*)info)->ClientData;
}
-void CCONV cmSetClientData(void *info, void *cd)
+void CCONV cmSetClientData(void* info, void* cd)
{
- ((cmLoadedCommandInfo *)info)->ClientData = cd;
+ ((cmLoadedCommandInfo*)info)->ClientData = cd;
}
-void CCONV cmSetError(void *info, const char *err)
+void CCONV cmSetError(void* info, const char* err)
{
- if (((cmLoadedCommandInfo *)info)->Error)
- {
- free(((cmLoadedCommandInfo *)info)->Error);
- }
- ((cmLoadedCommandInfo *)info)->Error = strdup(err);
+ if (((cmLoadedCommandInfo*)info)->Error) {
+ free(((cmLoadedCommandInfo*)info)->Error);
+ }
+ ((cmLoadedCommandInfo*)info)->Error = strdup(err);
}
-unsigned int CCONV cmGetCacheMajorVersion(void *arg)
+unsigned int CCONV cmGetCacheMajorVersion(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetCacheMajorVersion();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ cmState* state = mf->GetState();
+ return state->GetCacheMajorVersion();
}
-unsigned int CCONV cmGetCacheMinorVersion(void *arg)
+unsigned int CCONV cmGetCacheMinorVersion(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetCacheMinorVersion();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ cmState* state = mf->GetState();
+ return state->GetCacheMinorVersion();
}
-unsigned int CCONV cmGetMajorVersion(void *)
+unsigned int CCONV cmGetMajorVersion(void*)
{
return cmVersion::GetMajorVersion();
}
-unsigned int CCONV cmGetMinorVersion(void *)
+unsigned int CCONV cmGetMinorVersion(void*)
{
return cmVersion::GetMinorVersion();
}
-void CCONV cmAddDefinition(void *arg, const char* name, const char* value)
+void CCONV cmAddDefinition(void* arg, const char* name, const char* value)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- mf->AddDefinition(name,value);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ mf->AddDefinition(name, value);
}
/* Add a definition to this makefile and the global cmake cache. */
-void CCONV cmAddCacheDefinition(void *arg, const char* name,
- const char* value, const char* doc, int type)
+void CCONV cmAddCacheDefinition(void* arg, const char* name, const char* value,
+ const char* doc, int type)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
- switch (type)
- {
+ switch (type) {
case CM_CACHE_BOOL:
- mf->AddCacheDefinition(name,value,doc,
- cmCacheManager::BOOL);
+ mf->AddCacheDefinition(name, value, doc, cmStateEnums::BOOL);
break;
case CM_CACHE_PATH:
- mf->AddCacheDefinition(name,value,doc,
- cmCacheManager::PATH);
+ mf->AddCacheDefinition(name, value, doc, cmStateEnums::PATH);
break;
case CM_CACHE_FILEPATH:
- mf->AddCacheDefinition(name,value,doc,
- cmCacheManager::FILEPATH);
+ mf->AddCacheDefinition(name, value, doc, cmStateEnums::FILEPATH);
break;
case CM_CACHE_STRING:
- mf->AddCacheDefinition(name,value,doc,
- cmCacheManager::STRING);
+ mf->AddCacheDefinition(name, value, doc, cmStateEnums::STRING);
break;
case CM_CACHE_INTERNAL:
- mf->AddCacheDefinition(name,value,doc,
- cmCacheManager::INTERNAL);
+ mf->AddCacheDefinition(name, value, doc, cmStateEnums::INTERNAL);
break;
case CM_CACHE_STATIC:
- mf->AddCacheDefinition(name,value,doc,
- cmCacheManager::STATIC);
+ mf->AddCacheDefinition(name, value, doc, cmStateEnums::STATIC);
break;
- }
+ }
}
-const char* CCONV cmGetProjectName(void *arg)
+const char* CCONV cmGetProjectName(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetProjectName();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ static std::string name;
+ name = mf->GetStateSnapshot().GetProjectName();
+ return name.c_str();
}
-const char* CCONV cmGetHomeDirectory(void *arg)
+const char* CCONV cmGetHomeDirectory(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetHomeDirectory();
}
-const char* CCONV cmGetHomeOutputDirectory(void *arg)
+const char* CCONV cmGetHomeOutputDirectory(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetHomeOutputDirectory();
}
-const char* CCONV cmGetStartDirectory(void *arg)
+const char* CCONV cmGetStartDirectory(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetStartDirectory();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ return mf->GetCurrentSourceDirectory();
}
-const char* CCONV cmGetStartOutputDirectory(void *arg)
+const char* CCONV cmGetStartOutputDirectory(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetStartOutputDirectory();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ return mf->GetCurrentBinaryDirectory();
}
-const char* CCONV cmGetCurrentDirectory(void *arg)
+const char* CCONV cmGetCurrentDirectory(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetCurrentDirectory();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ return mf->GetCurrentSourceDirectory();
}
-const char* CCONV cmGetCurrentOutputDirectory(void *arg)
+const char* CCONV cmGetCurrentOutputDirectory(void* arg)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return mf->GetCurrentOutputDirectory();
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ return mf->GetCurrentBinaryDirectory();
}
-const char* CCONV cmGetDefinition(void *arg,const char*def)
+const char* CCONV cmGetDefinition(void* arg, const char* def)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetDefinition(def);
}
-int CCONV cmIsOn(void *arg, const char* name)
+int CCONV cmIsOn(void* arg, const char* name)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
return static_cast<int>(mf->IsOn(name));
}
/** Check if a command exists. */
-int CCONV cmCommandExists(void *arg, const char* name)
+int CCONV cmCommandExists(void* arg, const char* name)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- return static_cast<int>(mf->CommandExists(name));
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ return static_cast<int>(mf->GetState()->GetCommand(name) ? 1 : 0);
}
-void CCONV cmAddDefineFlag(void *arg, const char* definition)
+void CCONV cmAddDefineFlag(void* arg, const char* definition)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
mf->AddDefineFlag(definition);
}
-void CCONV cmAddLinkDirectoryForTarget(void *arg, const char *tgt,
- const char* d)
+void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
+ const char* d)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- mf->AddLinkDirectoryForTarget(tgt,d);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ cmTarget* t = mf->FindLocalNonAliasTarget(tgt);
+ if (!t) {
+ cmSystemTools::Error(
+ "Attempt to add link directories to non-existent target: ", tgt,
+ " for directory ", d);
+ return;
+ }
+ t->AddLinkDirectory(d);
}
-
-void CCONV cmAddExecutable(void *arg, const char *exename,
- int numSrcs, const char **srcs, int win32)
+void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
+ const char** srcs, int win32)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::vector<std::string> srcs2;
int i;
- for (i = 0; i < numSrcs; ++i)
- {
+ for (i = 0; i < numSrcs; ++i) {
srcs2.push_back(srcs[i]);
- }
- cmTarget* tg = mf->AddExecutable(exename, srcs2);
- if ( win32 )
- {
- tg->SetProperty("WIN32_EXECUTABLE", "ON");
- }
-}
-
-void CCONV cmAddUtilityCommand(void *arg, const char* utilityName,
- const char* command,
- const char* arguments,
- int all,
- int numDepends,
- const char **depends,
- int,
- const char **)
+ }
+ cmTarget* tg = mf->AddExecutable(exename, srcs2);
+ if (win32) {
+ tg->SetProperty("WIN32_EXECUTABLE", "ON");
+ }
+}
+
+void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
+ const char* command, const char* arguments,
+ int all, int numDepends, const char** depends,
+ int, const char**)
{
// Get the makefile instance. Perform an extra variable expansion
// now because the API caller expects it.
@@ -213,33 +202,30 @@ void CCONV cmAddUtilityCommand(void *arg, const char* utilityName,
cmCustomCommandLine commandLine;
std::string expand = command;
commandLine.push_back(mf->ExpandVariablesInString(expand));
- if(arguments && arguments[0])
- {
+ if (arguments && arguments[0]) {
// TODO: Parse arguments!
expand = arguments;
commandLine.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
// Accumulate the list of dependencies.
std::vector<std::string> depends2;
- for(int i = 0; i < numDepends; ++i)
- {
+ for (int i = 0; i < numDepends; ++i) {
expand = depends[i];
depends2.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
// Pass the call to the makefile instance.
- mf->AddUtilityCommand(utilityName, (all ? false : true),
- 0, depends2, commandLines);
+ mf->AddUtilityCommand(utilityName, (all ? false : true), CM_NULLPTR,
+ depends2, commandLines);
}
-void CCONV cmAddCustomCommand(void *arg, const char* source,
- const char* command,
- int numArgs, const char **args,
- int numDepends, const char **depends,
- int numOutputs, const char **outputs,
- const char *target)
+void CCONV cmAddCustomCommand(void* arg, const char* source,
+ const char* command, int numArgs,
+ const char** args, int numDepends,
+ const char** depends, int numOutputs,
+ const char** outputs, const char* target)
{
// Get the makefile instance. Perform an extra variable expansion
// now because the API caller expects it.
@@ -249,41 +235,38 @@ void CCONV cmAddCustomCommand(void *arg, const char* source,
cmCustomCommandLine commandLine;
std::string expand = command;
commandLine.push_back(mf->ExpandVariablesInString(expand));
- for(int i=0; i < numArgs; ++i)
- {
+ for (int i = 0; i < numArgs; ++i) {
expand = args[i];
commandLine.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
// Accumulate the list of dependencies.
std::vector<std::string> depends2;
- for(int i = 0; i < numDepends; ++i)
- {
+ for (int i = 0; i < numDepends; ++i) {
expand = depends[i];
depends2.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
// Accumulate the list of outputs.
std::vector<std::string> outputs2;
- for(int i = 0; i < numOutputs; ++i)
- {
+ for (int i = 0; i < numOutputs; ++i) {
expand = outputs[i];
outputs2.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
// Pass the call to the makefile instance.
- const char* no_comment = 0;
+ const char* no_comment = CM_NULLPTR;
mf->AddCustomCommandOldStyle(target, outputs2, depends2, source,
commandLines, no_comment);
}
-void CCONV cmAddCustomCommandToOutput(void *arg, const char* output,
- const char* command,
- int numArgs, const char **args,
- const char* main_dependency,
- int numDepends, const char **depends)
+void CCONV cmAddCustomCommandToOutput(void* arg, const char* output,
+ const char* command, int numArgs,
+ const char** args,
+ const char* main_dependency,
+ int numDepends, const char** depends)
{
// Get the makefile instance. Perform an extra variable expansion
// now because the API caller expects it.
@@ -293,33 +276,30 @@ void CCONV cmAddCustomCommandToOutput(void *arg, const char* output,
cmCustomCommandLine commandLine;
std::string expand = command;
commandLine.push_back(mf->ExpandVariablesInString(expand));
- for(int i=0; i < numArgs; ++i)
- {
+ for (int i = 0; i < numArgs; ++i) {
expand = args[i];
commandLine.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
// Accumulate the list of dependencies.
std::vector<std::string> depends2;
- for(int i = 0; i < numDepends; ++i)
- {
+ for (int i = 0; i < numDepends; ++i) {
expand = depends[i];
depends2.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
// Pass the call to the makefile instance.
- const char* no_comment = 0;
- const char* no_working_dir = 0;
- mf->AddCustomCommandToOutput(output, depends2, main_dependency,
- commandLines, no_comment, no_working_dir);
+ const char* no_comment = CM_NULLPTR;
+ const char* no_working_dir = CM_NULLPTR;
+ mf->AddCustomCommandToOutput(output, depends2, main_dependency, commandLines,
+ no_comment, no_working_dir);
}
-void CCONV cmAddCustomCommandToTarget(void *arg, const char* target,
- const char* command,
- int numArgs, const char **args,
- int commandType)
+void CCONV cmAddCustomCommandToTarget(void* arg, const char* target,
+ const char* command, int numArgs,
+ const char** args, int commandType)
{
// Get the makefile instance.
cmMakefile* mf = static_cast<cmMakefile*>(arg);
@@ -329,18 +309,16 @@ void CCONV cmAddCustomCommandToTarget(void *arg, const char* target,
cmCustomCommandLine commandLine;
std::string expand = command;
commandLine.push_back(mf->ExpandVariablesInString(expand));
- for(int i=0; i < numArgs; ++i)
- {
+ for (int i = 0; i < numArgs; ++i) {
expand = args[i];
commandLine.push_back(mf->ExpandVariablesInString(expand));
- }
+ }
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
// Select the command type.
cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
- switch (commandType)
- {
+ switch (commandType) {
case CM_PRE_BUILD:
cctype = cmTarget::PRE_BUILD;
break;
@@ -350,140 +328,152 @@ void CCONV cmAddCustomCommandToTarget(void *arg, const char* target,
case CM_POST_BUILD:
cctype = cmTarget::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 = 0;
- const char* no_working_dir = 0;
- mf->AddCustomCommandToTarget(target, no_depends, commandLines,
+ const char* no_comment = CM_NULLPTR;
+ const char* no_working_dir = CM_NULLPTR;
+ mf->AddCustomCommandToTarget(target, no_byproducts, no_depends, commandLines,
cctype, no_comment, no_working_dir);
}
-void CCONV cmAddLinkLibraryForTarget(void *arg, const char *tgt,
- const char*value, int libtype)
+static void addLinkLibrary(cmMakefile* mf, std::string const& target,
+ std::string const& lib, cmTargetLinkLibraryType llt)
+{
+ cmTarget* t = mf->FindLocalNonAliasTarget(target);
+ if (!t) {
+ 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());
+ return;
+ }
+
+ cmTarget* tgt = mf->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.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ }
+
+ t->AddLinkLibrary(*mf, lib, llt);
+}
+
+void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt,
+ const char* value, int libtype)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
- switch (libtype)
- {
+ switch (libtype) {
case CM_LIBRARY_GENERAL:
- mf->AddLinkLibraryForTarget(tgt,value, cmTarget::GENERAL);
+ addLinkLibrary(mf, tgt, value, GENERAL_LibraryType);
break;
case CM_LIBRARY_DEBUG:
- mf->AddLinkLibraryForTarget(tgt,value, cmTarget::DEBUG);
+ addLinkLibrary(mf, tgt, value, DEBUG_LibraryType);
break;
case CM_LIBRARY_OPTIMIZED:
- mf->AddLinkLibraryForTarget(tgt,value, cmTarget::OPTIMIZED);
+ addLinkLibrary(mf, tgt, value, OPTIMIZED_LibraryType);
break;
- }
+ }
}
-void CCONV cmAddLibrary(void *arg, const char *libname, int shared,
- int numSrcs, const char **srcs)
+void CCONV cmAddLibrary(void* arg, const char* libname, int shared,
+ int numSrcs, const char** srcs)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::vector<std::string> srcs2;
int i;
- for (i = 0; i < numSrcs; ++i)
- {
+ for (i = 0; i < numSrcs; ++i) {
srcs2.push_back(srcs[i]);
- }
- mf->AddLibrary(libname,
- (shared? cmTarget::SHARED_LIBRARY : cmTarget::STATIC_LIBRARY),
- srcs2);
+ }
+ mf->AddLibrary(libname, (shared ? cmStateEnums::SHARED_LIBRARY
+ : cmStateEnums::STATIC_LIBRARY),
+ srcs2);
}
-char CCONV *cmExpandVariablesInString(void *arg, const char *source,
- int escapeQuotes, int atOnly)
+char CCONV* cmExpandVariablesInString(void* arg, const char* source,
+ int escapeQuotes, int atOnly)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ 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.size())
- {
- strcpy(res,result.c_str());
- }
+ 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;
}
-
-int CCONV cmExecuteCommand(void *arg, const char *name,
- int numArgs, const char **args)
+int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
+ const char** args)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmListFileFunction lff;
lff.Name = name;
- for(int i = 0; i < numArgs; ++i)
- {
+ for (int i = 0; i < numArgs; ++i) {
// Assume all arguments are quoted.
lff.Arguments.push_back(
- cmListFileArgument(args[i], cmListFileArgument::Quoted,
- "[CMake-Plugin]", 0));
- }
+ cmListFileArgument(args[i], cmListFileArgument::Quoted, 0));
+ }
cmExecutionStatus status;
- return mf->ExecuteCommand(lff,status);
+ return mf->ExecuteCommand(lff, status);
}
-void CCONV cmExpandSourceListArguments(void *arg,
- int numArgs,
- const char **args,
- int *resArgc,
- char ***resArgv,
- unsigned int startArgumentIndex)
+void CCONV cmExpandSourceListArguments(void* arg, int numArgs,
+ const char** args, int* resArgc,
+ char*** resArgv,
+ unsigned int startArgumentIndex)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ (void)arg;
+ (void)startArgumentIndex;
std::vector<std::string> result;
- std::vector<std::string> args2;
int i;
- for (i = 0; i < numArgs; ++i)
- {
- args2.push_back(args[i]);
- }
- mf->ExpandSourceListArguments(args2, result, startArgumentIndex);
+ for (i = 0; i < numArgs; ++i) {
+ result.push_back(args[i]);
+ }
int resargc = static_cast<int>(result.size());
- char **resargv = 0;
- if (resargc)
- {
- resargv = (char **)malloc(resargc*sizeof(char *));
- }
- for (i = 0; i < resargc; ++i)
- {
+ char** resargv = CM_NULLPTR;
+ if (resargc) {
+ resargv = (char**)malloc(resargc * sizeof(char*));
+ }
+ for (i = 0; i < resargc; ++i) {
resargv[i] = strdup(result[i].c_str());
- }
+ }
*resArgc = resargc;
*resArgv = resargv;
}
-void CCONV cmFreeArguments(int argc, char **argv)
+void CCONV cmFreeArguments(int argc, char** argv)
{
int i;
- for (i = 0; i < argc; ++i)
- {
+ for (i = 0; i < argc; ++i) {
free(argv[i]);
- }
- if (argv)
- {
+ }
+ if (argv) {
free(argv);
- }
+ }
}
-int CCONV cmGetTotalArgumentSize(int argc, char **argv)
+int CCONV cmGetTotalArgumentSize(int argc, char** argv)
{
int i;
int result = 0;
- for (i = 0; i < argc; ++i)
- {
- if (argv[i])
- {
+ for (i = 0; i < argc; ++i) {
+ if (argv[i]) {
result = result + static_cast<int>(strlen(argv[i]));
- }
}
+ }
return result;
}
@@ -491,7 +481,10 @@ int CCONV cmGetTotalArgumentSize(int argc, char **argv)
// API for source files.
struct cmCPluginAPISourceFile
{
- cmCPluginAPISourceFile(): RealSourceFile(0) {}
+ cmCPluginAPISourceFile()
+ : RealSourceFile(CM_NULLPTR)
+ {
+ }
cmSourceFile* RealSourceFile;
std::string SourceName;
std::string SourceExtension;
@@ -502,94 +495,83 @@ struct cmCPluginAPISourceFile
// Keep a map from real cmSourceFile instances stored in a makefile to
// the CPluginAPI proxy source file.
-class cmCPluginAPISourceFileMap:
- public std::map<cmSourceFile*, cmCPluginAPISourceFile*>
+class cmCPluginAPISourceFileMap
+ : public std::map<cmSourceFile*, cmCPluginAPISourceFile*>
{
public:
typedef std::map<cmSourceFile*, cmCPluginAPISourceFile*> derived;
typedef derived::iterator iterator;
typedef derived::value_type value_type;
~cmCPluginAPISourceFileMap()
- {
- for(iterator i=this->begin(); i != this->end(); ++i)
- {
+ {
+ for (iterator i = this->begin(); i != this->end(); ++i) {
delete i->second;
- }
}
+ }
};
cmCPluginAPISourceFileMap cmCPluginAPISourceFiles;
-void * CCONV cmCreateSourceFile(void)
+void* CCONV cmCreateSourceFile(void)
{
return (void*)new cmCPluginAPISourceFile;
}
-void * CCONV cmCreateNewSourceFile(void *arg)
+void* CCONV cmCreateNewSourceFile(void*)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- cmCPluginAPISourceFile *sf = new cmCPluginAPISourceFile;
- sf->Properties.SetCMakeInstance(mf->GetCMakeInstance());
+ cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
return (void*)sf;
}
-void CCONV cmDestroySourceFile(void *arg)
+void CCONV cmDestroySourceFile(void* arg)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
// Only delete if it was created by cmCreateSourceFile or
// cmCreateNewSourceFile and is therefore not in the map.
- if(!sf->RealSourceFile)
- {
+ if (!sf->RealSourceFile) {
delete sf;
- }
+ }
}
-void CCONV *cmGetSource(void *arg, const char *name)
+void CCONV* cmGetSource(void* arg, const char* name)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- if(cmSourceFile* rsf = mf->GetSource(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);
- if(i == cmCPluginAPISourceFiles.end())
- {
+ 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->SourceName =
- cmSystemTools::GetFilenameWithoutLastExtension(sf->FullPath.c_str());
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->FullPath);
sf->SourceExtension =
- cmSystemTools::GetFilenameLastExtension(sf->FullPath.c_str());
+ cmSystemTools::GetFilenameLastExtension(sf->FullPath);
// Store the proxy in the map so it can be re-used and deleted later.
cmCPluginAPISourceFileMap::value_type entry(rsf, sf);
i = cmCPluginAPISourceFiles.insert(entry).first;
- }
- return (void *)i->second;
- }
- else
- {
- return 0;
}
+ return (void*)i->second;
+ }
+ return CM_NULLPTR;
}
-void * CCONV cmAddSource(void *arg, void *arg2)
+void* CCONV cmAddSource(void* arg, void* arg2)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmCPluginAPISourceFile* osf = static_cast<cmCPluginAPISourceFile*>(arg2);
- if(osf->FullPath.empty())
- {
- return 0;
- }
+ if (osf->FullPath.empty()) {
+ return CM_NULLPTR;
+ }
// Create the real cmSourceFile instance and copy over saved information.
- cmSourceFile* rsf = mf->GetOrCreateSource(osf->FullPath.c_str());
+ 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->c_str());
- }
+ for (std::vector<std::string>::iterator i = osf->Depends.begin();
+ i != osf->Depends.end(); ++i) {
+ rsf->AddDepend(*i);
+ }
// Create the proxy for the real source file.
cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
@@ -600,107 +582,87 @@ 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 (void*)sf;
}
-const char * CCONV cmSourceFileGetSourceName(void *arg)
+const char* CCONV cmSourceFileGetSourceName(void* arg)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
return sf->SourceName.c_str();
}
-const char * CCONV cmSourceFileGetFullPath(void *arg)
+const char* CCONV cmSourceFileGetFullPath(void* arg)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
return sf->FullPath.c_str();
}
-const char * CCONV cmSourceFileGetProperty(void *arg,const char *prop)
+const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
- if(cmSourceFile* rsf = sf->RealSourceFile)
- {
+ if (cmSourceFile* rsf = sf->RealSourceFile) {
return rsf->GetProperty(prop);
- }
- else
- {
- if(!strcmp(prop,"LOCATION"))
- {
- return sf->FullPath.c_str();
- }
- bool chain = false;
- // Ignore chain because old code will not expect it and it is a
- // pain to implement here anyway.
- return sf->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE,
- chain);
- }
+ }
+ if (!strcmp(prop, "LOCATION")) {
+ return sf->FullPath.c_str();
+ }
+ return sf->Properties.GetPropertyValue(prop);
}
-int CCONV cmSourceFileGetPropertyAsBool(void *arg,const char *prop)
+int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
- if(cmSourceFile* rsf = sf->RealSourceFile)
- {
- return rsf->GetPropertyAsBool(prop) ? 1:0;
- }
- else
- {
- return cmSystemTools::IsOn(cmSourceFileGetProperty(arg, prop))? 1:0;
- }
+ if (cmSourceFile* rsf = sf->RealSourceFile) {
+ return rsf->GetPropertyAsBool(prop) ? 1 : 0;
+ }
+ return cmSystemTools::IsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0;
}
-void CCONV cmSourceFileSetProperty(void *arg,const char *prop,
- const char *value)
+void CCONV cmSourceFileSetProperty(void* arg, const char* prop,
+ const char* value)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
- if(cmSourceFile* rsf = sf->RealSourceFile)
- {
+ if (cmSourceFile* rsf = sf->RealSourceFile) {
rsf->SetProperty(prop, value);
+ } else if (prop) {
+ if (!value) {
+ value = "NOTFOUND";
}
- else if(prop)
- {
- if(!value) { value = "NOTFOUND"; }
- sf->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE);
- }
+ sf->Properties.SetProperty(prop, value);
+ }
}
-void CCONV cmSourceFileAddDepend(void *arg, const char *depend)
+void CCONV cmSourceFileAddDepend(void* arg, const char* depend)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
- if(cmSourceFile* rsf = sf->RealSourceFile)
- {
+ if (cmSourceFile* rsf = sf->RealSourceFile) {
rsf->AddDepend(depend);
- }
- else
- {
+ } else {
sf->Depends.push_back(depend);
- }
+ }
}
-void CCONV cmSourceFileSetName(void *arg, const char* name, const char* dir,
+void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
int numSourceExtensions,
- const char **sourceExtensions,
+ const char** sourceExtensions,
int numHeaderExtensions,
- const char **headerExtensions)
+ const char** headerExtensions)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
- if(sf->RealSourceFile)
- {
+ if (sf->RealSourceFile) {
// SetName is allowed only on temporary source files created by
// the command for building and passing to AddSource.
return;
- }
+ }
std::vector<std::string> sourceExts;
std::vector<std::string> headerExts;
int i;
- for (i = 0; i < numSourceExtensions; ++i)
- {
+ for (i = 0; i < numSourceExtensions; ++i) {
sourceExts.push_back(sourceExtensions[i]);
- }
- for (i = 0; i < numHeaderExtensions; ++i)
- {
+ }
+ for (i = 0; i < numHeaderExtensions; ++i) {
headerExts.push_back(headerExtensions[i]);
- }
+ }
// Save the original name given.
sf->SourceName = name;
@@ -712,168 +674,149 @@ 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.c_str())) {
sf->SourceName = cmSystemTools::GetFilenamePath(name);
- if ( sf->SourceName.size() > 0 )
- {
+ if (!sf->SourceName.empty()) {
sf->SourceName += "/";
- }
+ }
sf->SourceName += cmSystemTools::GetFilenameWithoutLastExtension(name);
std::string::size_type pos = hname.rfind('.');
- if(pos != std::string::npos)
- {
- sf->SourceExtension = hname.substr(pos+1, hname.size()-pos);
- if ( cmSystemTools::FileIsFullPath(name) )
- {
+ if (pos != std::string::npos) {
+ sf->SourceExtension = hname.substr(pos + 1, hname.size() - pos);
+ if (cmSystemTools::FileIsFullPath(name)) {
std::string::size_type pos2 = hname.rfind('/');
- if(pos2 != std::string::npos)
- {
- sf->SourceName = hname.substr(pos2+1, pos - pos2-1);
- }
+ if (pos2 != std::string::npos) {
+ sf->SourceName = hname.substr(pos2 + 1, pos - pos2 - 1);
}
}
+ }
sf->FullPath = hname;
return;
- }
+ }
// Next, try the various source extensions
- for( std::vector<std::string>::const_iterator ext = sourceExts.begin();
- ext != sourceExts.end(); ++ext )
- {
+ 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()))
- {
+ if (cmSystemTools::FileExists(hname.c_str())) {
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 )
- {
+ 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()))
- {
+ if (cmSystemTools::FileExists(hname.c_str())) {
sf->SourceExtension = *ext;
sf->FullPath = hname;
return;
- }
}
+ }
- cmOStringStream e;
+ 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 )
- {
+ for (std::vector<std::string>::const_iterator ext = sourceExts.begin();
+ ext != sourceExts.end(); ++ext) {
e << " ." << *ext;
- }
- for( std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext )
- {
+ }
+ for (std::vector<std::string>::const_iterator ext = headerExts.begin();
+ ext != headerExts.end(); ++ext) {
e << " ." << *ext;
- }
+ }
cmSystemTools::Error(e.str().c_str());
- return;
}
-void CCONV cmSourceFileSetName2(void *arg, const char* name, const char* dir,
- const char *ext, int headerFileOnly)
+void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir,
+ const char* ext, int headerFileOnly)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
- if(sf->RealSourceFile)
- {
+ if (sf->RealSourceFile) {
// SetName is allowed only on temporary source files created by
// the command for building and passing to AddSource.
return;
- }
+ }
// Implement the old SetName method code here.
- if(headerFileOnly)
- {
- sf->Properties.SetProperty("HEADER_FILE_ONLY", "1",
- cmProperty::SOURCE_FILE);
- }
+ if (headerFileOnly) {
+ sf->Properties.SetProperty("HEADER_FILE_ONLY", "1");
+ }
sf->SourceName = name;
std::string fname = sf->SourceName;
- if(ext && strlen(ext))
- {
+ if (ext && strlen(ext)) {
fname += ".";
fname += ext;
- }
- sf->FullPath = cmSystemTools::CollapseFullPath(fname.c_str(), dir);
+ }
+ sf->FullPath = cmSystemTools::CollapseFullPath(fname, dir);
cmSystemTools::ConvertToUnixSlashes(sf->FullPath);
sf->SourceExtension = ext;
}
-char * CCONV cmGetFilenameWithoutExtension(const char *name)
+char* CCONV cmGetFilenameWithoutExtension(const char* name)
{
std::string sres = cmSystemTools::GetFilenameWithoutExtension(name);
- char *result = (char *)malloc(sres.size()+1);
- strcpy(result,sres.c_str());
+ char* result = (char*)malloc(sres.size() + 1);
+ strcpy(result, sres.c_str());
return result;
}
-char * CCONV cmGetFilenamePath(const char *name)
+char* CCONV cmGetFilenamePath(const char* name)
{
std::string sres = cmSystemTools::GetFilenamePath(name);
- char *result = (char *)malloc(sres.size()+1);
- strcpy(result,sres.c_str());
+ char* result = (char*)malloc(sres.size() + 1);
+ strcpy(result, sres.c_str());
return result;
}
-char * CCONV cmCapitalized(const char *name)
+char* CCONV cmCapitalized(const char* name)
{
std::string sres = cmSystemTools::Capitalized(name);
- char *result = (char *)malloc(sres.size()+1);
- strcpy(result,sres.c_str());
+ char* result = (char*)malloc(sres.size() + 1);
+ strcpy(result, sres.c_str());
return result;
}
-void CCONV cmCopyFileIfDifferent(const char *name1, const char *name2)
+void CCONV cmCopyFileIfDifferent(const char* name1, const char* name2)
{
- cmSystemTools::CopyFileIfDifferent(name1,name2);
+ cmSystemTools::CopyFileIfDifferent(name1, name2);
}
-void CCONV cmRemoveFile(const char *name)
+void CCONV cmRemoveFile(const char* name)
{
cmSystemTools::RemoveFile(name);
}
-void CCONV cmDisplayStatus(void *arg, const char* message)
+void CCONV cmDisplayStatus(void* arg, const char* message)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
mf->DisplayStatus(message, -1);
}
-void CCONV cmFree(void *data)
+void CCONV cmFree(void* data)
{
free(data);
}
-void CCONV DefineSourceFileProperty (void *arg, const char *name,
- const char *briefDocs,
- const char *longDocs,
- int chained)
+void CCONV DefineSourceFileProperty(void* arg, const char* name,
+ const char* briefDocs,
+ const char* longDocs, int chained)
{
- cmMakefile *mf = static_cast<cmMakefile *>(arg);
- mf->GetCMakeInstance()->DefineProperty(name,cmProperty::SOURCE_FILE,
- briefDocs, longDocs,
- chained != 0);
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE, briefDocs,
+ longDocs, chained != 0);
}
} // close the extern "C" scope
-cmCAPI cmStaticCAPI =
-{
+cmCAPI cmStaticCAPI = {
cmGetClientData,
cmGetTotalArgumentSize,
cmFreeArguments,
@@ -932,4 +875,3 @@ cmCAPI cmStaticCAPI =
cmCreateNewSourceFile,
DefineSourceFileProperty,
};
-
diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h
index 5c832c30e..88b81c6c1 100644
--- a/Source/cmCPluginAPI.h
+++ b/Source/cmCPluginAPI.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
/* This header file defines the API that loadable commands can use. In many
of these commands C++ instances of cmMakefile of cmSourceFile are passed
in as arguments or returned. In these cases they are passed as a void *
@@ -23,7 +14,7 @@
#define CMAKE_VERSION_MAJOR 2
#define CMAKE_VERSION_MINOR 5
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
@@ -46,141 +37,131 @@ typedef struct
/* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how
information is passed from the InitialPass to FInalPass for commands
that need a FinalPass and need information from the InitialPass */
- void *(CCONV *GetClientData) (void *info);
+ void*(CCONV* GetClientData)(void* info);
/* return the summed size in characters of all the arguments */
- int (CCONV *GetTotalArgumentSize) (int argc, char **argv);
+ int(CCONV* GetTotalArgumentSize)(int argc, char** argv);
/* free all the memory associated with an argc, argv pair */
- void (CCONV *FreeArguments) (int argc, char **argv);
+ void(CCONV* FreeArguments)(int argc, char** argv);
/* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how
information is passed from the InitialPass to FInalPass for commands
that need a FinalPass and need information from the InitialPass */
- void (CCONV *SetClientData) (void *info, void *cd);
+ void(CCONV* SetClientData)(void* info, void* cd);
/* when an error occurs, call this function to set the error string */
- void (CCONV *SetError) (void *info, const char *err);
+ void(CCONV* SetError)(void* info, const char* err);
/*=========================================================================
The following functions all directly map to methods in the cmMakefile
class. See cmMakefile.h for descriptions of what each method does. All of
these methods take the void * makefile pointer as their first argument.
=========================================================================*/
- void (CCONV *AddCacheDefinition) (void *mf, const char* name,
- const char* value,
- const char* doc, int cachetype);
- void (CCONV *AddCustomCommand) (void *mf, const char* source,
- const char* command,
- int numArgs, const char **args,
- int numDepends, const char **depends,
- int numOutputs, const char **outputs,
- const char *target);
- void (CCONV *AddDefineFlag) (void *mf, const char* definition);
- void (CCONV *AddDefinition) (void *mf, const char* name,
- const char* value);
- void (CCONV *AddExecutable) (void *mf, const char *exename,
- int numSrcs, const char **srcs, int win32);
- void (CCONV *AddLibrary) (void *mf, const char *libname,
- int shared, int numSrcs, const char **srcs);
- void (CCONV *AddLinkDirectoryForTarget) (void *mf, const char *tgt,
- const char* d);
- void (CCONV *AddLinkLibraryForTarget) (void *mf, const char *tgt,
- const char *libname, int libtype);
- void (CCONV *AddUtilityCommand) (void *mf, const char* utilityName,
- const char *command, const char *arguments,
- int all, int numDepends, const char **depends,
- int numOutputs, const char **outputs);
- int (CCONV *CommandExists) (void *mf, const char* name);
- int (CCONV *ExecuteCommand) (void *mf, const char *name,
- int numArgs, const char **args);
- void (CCONV *ExpandSourceListArguments) (void *mf,int argc,
- const char **argv,
- int *resArgc, char ***resArgv,
- unsigned int startArgumentIndex);
- char *(CCONV *ExpandVariablesInString) (void *mf, const char *source,
- int escapeQuotes, int atOnly);
- unsigned int (CCONV *GetCacheMajorVersion) (void *mf);
- unsigned int (CCONV *GetCacheMinorVersion) (void *mf);
- const char* (CCONV *GetCurrentDirectory) (void *mf);
- const char* (CCONV *GetCurrentOutputDirectory) (void *mf);
- const char* (CCONV *GetDefinition) (void *mf, const char *def);
- const char* (CCONV *GetHomeDirectory) (void *mf);
- const char* (CCONV *GetHomeOutputDirectory) (void *mf);
- unsigned int (CCONV *GetMajorVersion) (void *mf);
- unsigned int (CCONV *GetMinorVersion) (void *mf);
- const char* (CCONV *GetProjectName) (void *mf);
- const char* (CCONV *GetStartDirectory) (void *mf);
- const char* (CCONV *GetStartOutputDirectory) (void *mf);
- int (CCONV *IsOn) (void *mf, const char* name);
-
+ void(CCONV* AddCacheDefinition)(void* mf, const char* name,
+ const char* value, const char* doc,
+ int cachetype);
+ void(CCONV* AddCustomCommand)(void* mf, const char* source,
+ const char* command, int numArgs,
+ const char** args, int numDepends,
+ const char** depends, int numOutputs,
+ const char** outputs, const char* target);
+ void(CCONV* AddDefineFlag)(void* mf, const char* definition);
+ void(CCONV* AddDefinition)(void* mf, const char* name, const char* value);
+ void(CCONV* AddExecutable)(void* mf, const char* exename, int numSrcs,
+ const char** srcs, int win32);
+ void(CCONV* AddLibrary)(void* mf, const char* libname, int shared,
+ int numSrcs, const char** srcs);
+ void(CCONV* AddLinkDirectoryForTarget)(void* mf, const char* tgt,
+ const char* d);
+ void(CCONV* AddLinkLibraryForTarget)(void* mf, const char* tgt,
+ const char* libname, int libtype);
+ void(CCONV* AddUtilityCommand)(void* mf, const char* utilityName,
+ const char* command, const char* arguments,
+ int all, int numDepends, const char** depends,
+ int numOutputs, const char** outputs);
+ int(CCONV* CommandExists)(void* mf, const char* name);
+ int(CCONV* ExecuteCommand)(void* mf, const char* name, int numArgs,
+ const char** args);
+ void(CCONV* ExpandSourceListArguments)(void* mf, int argc, const char** argv,
+ int* resArgc, char*** resArgv,
+ unsigned int startArgumentIndex);
+ char*(CCONV* ExpandVariablesInString)(void* mf, const char* source,
+ int escapeQuotes, int atOnly);
+ unsigned int(CCONV* GetCacheMajorVersion)(void* mf);
+ unsigned int(CCONV* GetCacheMinorVersion)(void* mf);
+ const char*(CCONV* GetCurrentDirectory)(void* mf);
+ const char*(CCONV* GetCurrentOutputDirectory)(void* mf);
+ const char*(CCONV* GetDefinition)(void* mf, const char* def);
+ const char*(CCONV* GetHomeDirectory)(void* mf);
+ const char*(CCONV* GetHomeOutputDirectory)(void* mf);
+ unsigned int(CCONV* GetMajorVersion)(void* mf);
+ unsigned int(CCONV* GetMinorVersion)(void* mf);
+ const char*(CCONV* GetProjectName)(void* mf);
+ const char*(CCONV* GetStartDirectory)(void* mf);
+ const char*(CCONV* GetStartOutputDirectory)(void* mf);
+ int(CCONV* IsOn)(void* mf, const char* name);
/*=========================================================================
The following functions are designed to operate or manipulate
cmSourceFiles. Please see cmSourceFile.h for additional information on many
of these methods. Some of these methods are in cmMakefile.h.
=========================================================================*/
- void *(CCONV *AddSource) (void *mf, void *sf);
- void *(CCONV *CreateSourceFile) ();
- void (CCONV *DestroySourceFile) (void *sf);
- void *(CCONV *GetSource) (void *mf, const char* sourceName);
- void (CCONV *SourceFileAddDepend) (void *sf, const char *depend);
- const char *(CCONV *SourceFileGetProperty) (void *sf, const char *prop);
- int (CCONV *SourceFileGetPropertyAsBool) (void *sf, const char *prop);
- const char *(CCONV *SourceFileGetSourceName) (void *sf);
- const char *(CCONV *SourceFileGetFullPath) (void *sf);
- void (CCONV *SourceFileSetName) (void *sf, const char* name,
- const char* dir,
- int numSourceExtensions,
- const char **sourceExtensions,
- int numHeaderExtensions,
- const char **headerExtensions);
- void (CCONV *SourceFileSetName2) (void *sf, const char* name,
- const char* dir,
- const char *ext, int headerFileOnly);
- void (CCONV *SourceFileSetProperty) (void *sf, const char *prop,
- const char *value);
-
+ void*(CCONV* AddSource)(void* mf, void* sf);
+ void*(CCONV* CreateSourceFile)();
+ void(CCONV* DestroySourceFile)(void* sf);
+ void*(CCONV* GetSource)(void* mf, const char* sourceName);
+ void(CCONV* SourceFileAddDepend)(void* sf, const char* depend);
+ const char*(CCONV* SourceFileGetProperty)(void* sf, const char* prop);
+ int(CCONV* SourceFileGetPropertyAsBool)(void* sf, const char* prop);
+ const char*(CCONV* SourceFileGetSourceName)(void* sf);
+ const char*(CCONV* SourceFileGetFullPath)(void* sf);
+ void(CCONV* SourceFileSetName)(void* sf, const char* name, const char* dir,
+ int numSourceExtensions,
+ const char** sourceExtensions,
+ int numHeaderExtensions,
+ const char** headerExtensions);
+ void(CCONV* SourceFileSetName2)(void* sf, const char* name, const char* dir,
+ const char* ext, int headerFileOnly);
+ void(CCONV* SourceFileSetProperty)(void* sf, const char* prop,
+ const char* value);
/*=========================================================================
The following methods are from cmSystemTools.h see that file for specific
documentation on each method.
=========================================================================*/
- char *(CCONV *Capitalized)(const char *);
- void (CCONV *CopyFileIfDifferent)(const char *f1, const char *f2);
- char *(CCONV *GetFilenameWithoutExtension)(const char *);
- char *(CCONV *GetFilenamePath)(const char *);
- void (CCONV *RemoveFile)(const char *f1);
- void (CCONV *Free)(void *);
+ char*(CCONV* Capitalized)(const char*);
+ void(CCONV* CopyFileIfDifferent)(const char* f1, const char* f2);
+ char*(CCONV* GetFilenameWithoutExtension)(const char*);
+ char*(CCONV* GetFilenamePath)(const char*);
+ void(CCONV* RemoveFile)(const char* f1);
+ void(CCONV* Free)(void*);
/*=========================================================================
The following are new functions added after 1.6
=========================================================================*/
- void (CCONV *AddCustomCommandToOutput) (void *mf, const char* output,
- const char* command,
- int numArgs, const char **args,
- const char* main_dependency,
- int numDepends, const char **depends);
- void (CCONV *AddCustomCommandToTarget) (void *mf, const char* target,
- const char* command,
- int numArgs, const char **args,
- int commandType);
+ void(CCONV* AddCustomCommandToOutput)(void* mf, const char* output,
+ const char* command, int numArgs,
+ const char** args,
+ const char* main_dependency,
+ int numDepends, const char** depends);
+ void(CCONV* AddCustomCommandToTarget)(void* mf, const char* target,
+ const char* command, int numArgs,
+ const char** args, int commandType);
/* display status information */
- void (CCONV *DisplaySatus) (void *info, const char *message);
+ void(CCONV* DisplaySatus)(void* info, const char* message);
/* new functions added after 2.4 */
- void *(CCONV *CreateNewSourceFile) (void *mf);
- void (CCONV *DefineSourceFileProperty) (void *mf, const char *name,
- const char *briefDocs,
- const char *longDocs,
- int chained);
+ void*(CCONV* CreateNewSourceFile)(void* mf);
+ void(CCONV* DefineSourceFileProperty)(void* mf, const char* name,
+ const char* briefDocs,
+ const char* longDocs, int chained);
/* this is the end of the C function stub API structure */
} cmCAPI;
-
/*=========================================================================
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
#endif
@@ -206,37 +187,38 @@ define the different types of compiles a library may be
/*=========================================================================
define the different types of custom commands for a target
=========================================================================*/
-#define CM_PRE_BUILD 0
-#define CM_PRE_LINK 1
+#define CM_PRE_BUILD 0
+#define CM_PRE_LINK 1
#define CM_POST_BUILD 2
/*=========================================================================
Finally we define the key data structures and function prototypes
=========================================================================*/
- typedef const char* (CCONV *CM_DOC_FUNCTION)();
- typedef int (CCONV *CM_INITIAL_PASS_FUNCTION)(void *info, void *mf,
- int argc, char *[]);
- typedef void (CCONV *CM_FINAL_PASS_FUNCTION)(void *info, void *mf);
- typedef void (CCONV *CM_DESTRUCTOR_FUNCTION)(void *info);
-
- typedef struct {
- unsigned long reserved1; /* Reserved for future use. DO NOT USE. */
- unsigned long reserved2; /* Reserved for future use. DO NOT USE. */
- cmCAPI *CAPI;
- int m_Inherited; /* this ivar is no longer used in CMake 2.2 or later */
- CM_INITIAL_PASS_FUNCTION InitialPass;
- CM_FINAL_PASS_FUNCTION FinalPass;
- CM_DESTRUCTOR_FUNCTION Destructor;
- CM_DOC_FUNCTION GetTerseDocumentation;
- CM_DOC_FUNCTION GetFullDocumentation;
- const char *Name;
- char *Error;
- void *ClientData;
- } cmLoadedCommandInfo;
-
- typedef void (CCONV *CM_INIT_FUNCTION)(cmLoadedCommandInfo *);
-
-#ifdef __cplusplus
+typedef const char*(CCONV* CM_DOC_FUNCTION)();
+typedef int(CCONV* CM_INITIAL_PASS_FUNCTION)(void* info, void* mf, int argc,
+ char* []);
+typedef void(CCONV* CM_FINAL_PASS_FUNCTION)(void* info, void* mf);
+typedef void(CCONV* CM_DESTRUCTOR_FUNCTION)(void* info);
+
+typedef struct
+{
+ unsigned long reserved1; /* Reserved for future use. DO NOT USE. */
+ unsigned long reserved2; /* Reserved for future use. DO NOT USE. */
+ cmCAPI* CAPI;
+ int m_Inherited; /* this ivar is no longer used in CMake 2.2 or later */
+ CM_INITIAL_PASS_FUNCTION InitialPass;
+ CM_FINAL_PASS_FUNCTION FinalPass;
+ CM_DESTRUCTOR_FUNCTION Destructor;
+ CM_DOC_FUNCTION GetTerseDocumentation;
+ CM_DOC_FUNCTION GetFullDocumentation;
+ const char* Name;
+ char* Error;
+ void* ClientData;
+} cmLoadedCommandInfo;
+
+typedef void(CCONV* CM_INIT_FUNCTION)(cmLoadedCommandInfo*);
+
+#ifdef __cplusplus
}
#endif
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 14e1f5014..e2605561a 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -1,102 +1,95 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTest.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
#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 <iostream>
+#include <map>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <time.h>
+#include <utility>
+#include <vector>
-#include "cmCTest.h"
-#include "cmake.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-#include <cmsys/Base64.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/SystemInformation.hxx>
-#include "cmDynamicLoader.h"
-#include "cmGeneratedFileStream.h"
-#include "cmXMLSafe.h"
-#include "cmVersionMacros.h"
-#include "cmCTestCommand.h"
-#include "cmCTestStartCommand.h"
-
-#include "cmCTestBuildHandler.h"
+#include "cmAlgorithms.h"
#include "cmCTestBuildAndTestHandler.h"
+#include "cmCTestBuildHandler.h"
#include "cmCTestConfigureHandler.h"
#include "cmCTestCoverageHandler.h"
+#include "cmCTestGenericHandler.h"
#include "cmCTestMemCheckHandler.h"
#include "cmCTestScriptHandler.h"
+#include "cmCTestStartCommand.h"
#include "cmCTestSubmitHandler.h"
#include "cmCTestTestHandler.h"
#include "cmCTestUpdateHandler.h"
#include "cmCTestUploadHandler.h"
-
+#include "cmCurl.h"
+#include "cmDynamicLoader.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmProcessOutput.h"
+#include "cmState.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
+#include "cmVersionConfig.h"
+#include "cmXMLWriter.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/Glob.hxx>
-
-#include <stdlib.h>
-#include <math.h>
-#include <float.h>
-#include <ctype.h>
-
-#include <cmsys/auto_ptr.hxx>
-
-#include <cm_zlib.h>
-#include <cmsys/Base64.h>
-
-#if defined(__BEOS__)
-#include <be/kernel/OS.h> /* disable_debugger() API. */
-#endif
-
-#if defined(__HAIKU__)
-#include <os/kernel/OS.h> /* disable_debugger() API. */
+#if defined(__BEOS__) || defined(__HAIKU__)
+#include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
+#define DEBUGOUT \
+ std::cout << __LINE__ << " "; \
+ std::cout
+#define DEBUGERR \
+ std::cerr << __LINE__ << " "; \
+ std::cerr
-#define DEBUGOUT std::cout << __LINE__ << " "; std::cout
-#define DEBUGERR std::cerr << __LINE__ << " "; std::cerr
-
-//----------------------------------------------------------------------
-struct tm* cmCTest::GetNightlyTime(std::string str,
- bool tomorrowtag)
+struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
{
struct tm* lctime;
- time_t tctime = time(0);
+ time_t tctime = time(CM_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.c_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
- //is the time at which the nightly dashboard was opened or
- //will be opened on the date of the current client machine.
- //As such, this time may be in the past or in the future.
+ 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);
+ // 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
+ // is the time at which the nightly dashboard was opened or
+ // will be opened on the date of the current client machine.
+ // 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(0);
+ tctime = time(CM_NULLPTR);
cmCTestLog(this, DEBUG, " Get the current time: " << tctime << std::endl);
const int dayLength = 24 * 60 * 60;
cmCTestLog(this, DEBUG, "Seconds: " << tctime << std::endl);
- while ( ntime > tctime )
- {
+ while (ntime > tctime) {
// If nightlySeconds is in the past, this is the current
// open dashboard, then return nightlySeconds. If
// nightlySeconds is in the future, this is the next
@@ -105,132 +98,113 @@ struct tm* cmCTest::GetNightlyTime(std::string str,
ntime -= dayLength;
cmCTestLog(this, DEBUG, "Pick yesterday" << std::endl);
cmCTestLog(this, DEBUG, " Future time, subtract day: " << ntime
- << std::endl);
- }
- while ( tctime > (ntime + dayLength) )
- {
+ << 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);
- if ( tomorrowtag )
- {
+ 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;
- }
+ }
lctime = gmtime(&ntime);
return lctime;
}
-//----------------------------------------------------------------------
std::string cmCTest::CleanString(const std::string& str)
{
std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v");
std::string::size_type epos = str.find_last_not_of(" \n\t\r\f\v");
- if ( spos == str.npos )
- {
+ if (spos == std::string::npos) {
return std::string();
- }
- if ( epos != str.npos )
- {
+ }
+ if (epos != std::string::npos) {
epos = epos - spos + 1;
- }
+ }
return str.substr(spos, epos);
}
-//----------------------------------------------------------------------
std::string cmCTest::CurrentTime()
{
- time_t currenttime = time(0);
+ time_t currenttime = time(CM_NULLPTR);
struct tm* t = localtime(&currenttime);
- //return ::CleanString(ctime(&currenttime));
+ // return ::CleanString(ctime(&currenttime));
char current_time[1024];
- if ( this->ShortDateFormat )
- {
+ if (this->ShortDateFormat) {
strftime(current_time, 1000, "%b %d %H:%M %Z", t);
- }
- else
- {
+ } else {
strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t);
- }
+ }
cmCTestLog(this, DEBUG, " Current_Time: " << current_time << std::endl);
- return cmXMLSafe(cmCTest::CleanString(current_time)).str();
+ return cmCTest::CleanString(current_time);
}
-//----------------------------------------------------------------------
std::string cmCTest::GetCostDataFile()
{
std::string fname = this->GetCTestConfiguration("CostDataFile");
- if(fname == "")
- {
- fname= this->GetBinaryDir() + "/Testing/Temporary/CTestCostData.txt";
- }
+ if (fname == "") {
+ 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)
+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);
+ 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 fields,
- std::string putFile, int timeout)
+ 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)
- {
+ // 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()))
- {
+ 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 = ::fopen(putFile.c_str(), "rb");
+ file = cmsys::SystemTools::Fopen(putFile, "rb");
::curl_easy_setopt(curl, CURLOPT_INFILE, file);
- //fall through to append GET fields
+ // fall through to append GET fields
case cmCTest::HTTP_GET:
- if(fields.size())
- {
+ if (!fields.empty()) {
url += "?" + fields;
- }
- break;
- default:
+ }
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
+ // set response options
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPResponseCallback);
- ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&response);
+ ::curl_easy_setopt(curl, CURLOPT_FILE, (void*)&response);
::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
CURLcode res = ::curl_easy_perform(curl);
@@ -242,100 +216,86 @@ int cmCTest::HTTPRequest(std::string url, HTTPMethod method,
}
#endif
-//----------------------------------------------------------------------
std::string cmCTest::MakeURLSafe(const std::string& str)
{
- cmOStringStream ost;
+ std::ostringstream ost;
char buffer[10];
- for ( std::string::size_type pos = 0; pos < str.size(); pos ++ )
- {
+ 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 )
- {
+ if ((ch > 126 || ch < 32 || ch == '&' || ch == '%' || ch == '+' ||
+ ch == '=' || ch == '@') &&
+ ch != 9) {
sprintf(buffer, "%02x;", (unsigned int)ch);
ost << buffer;
- }
- else
- {
+ } 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, 0, 16)));
+ 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)));
c += 2;
- }
- else
- {
+ } else {
out.append(1, *c);
- }
}
+ }
return out;
}
-//----------------------------------------------------------------------
cmCTest::cmCTest()
{
- this->LabelSummary = true;
- this->ParallelLevel = 1;
- this->ParallelLevelSetInCli = false;
- 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->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->CompressMemCheckOutput = 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 = 0;
- this->OutputLogFileLastTag = -1;
+ 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->DartVersion = 1;
+ this->DropSiteCDash = false;
this->OutputTestOutputOnTestFailure = false;
- this->ComputedCompressTestOutput = false;
- this->ComputedCompressMemCheckOutput = false;
- if(cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE"))
- {
- this->OutputTestOutputOnTestFailure = true;
- }
+ 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");
@@ -351,46 +311,37 @@ cmCTest::cmCTest()
this->Parts[PartUpload].SetName("Upload");
// Fill the part name-to-id map.
- for(Part p = PartStart; p != PartCount; p = Part(p+1))
- {
+ for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
this->PartMap[cmSystemTools::LowerCase(this->Parts[p].GetName())] = p;
- }
+ }
- this->ShortDateFormat = true;
+ this->ShortDateFormat = true;
- this->TestingHandlers["build"] = new cmCTestBuildHandler;
+ 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["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;
+ 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 )
- {
+ for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
+ ++it) {
it->second->SetCTestInstance(this);
- }
+ }
// Make sure we can capture the build tool output.
cmSystemTools::EnableVSConsoleOutput();
}
-//----------------------------------------------------------------------
cmCTest::~cmCTest()
{
- cmCTest::t_TestingHandlers::iterator it;
- for ( it = this->TestingHandlers.begin();
- it != this->TestingHandlers.end(); ++ it )
- {
- delete it->second;
- it->second = 0;
- }
- this->SetOutputLogFileName(0);
+ cmDeleteAll(this->TestingHandlers);
+ this->SetOutputLogFileName(CM_NULLPTR);
}
void cmCTest::SetParallelLevel(int level)
@@ -398,268 +349,206 @@ void cmCTest::SetParallelLevel(int level)
this->ParallelLevel = level < 1 ? 1 : level;
}
-//----------------------------------------------------------------------------
-bool cmCTest::ShouldCompressTestOutput()
+void cmCTest::SetTestLoad(unsigned long load)
{
- if(!this->ComputedCompressTestOutput)
- {
- std::string cdashVersion = this->GetCDashVersion();
- //version >= 1.6?
- bool cdashSupportsGzip = cmSystemTools::VersionCompare(
- cmSystemTools::OP_GREATER, cdashVersion.c_str(), "1.6") ||
- cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- cdashVersion.c_str(), "1.6");
- this->CompressTestOutput &= cdashSupportsGzip;
- this->ComputedCompressTestOutput = true;
- }
- return this->CompressTestOutput;
+ this->TestLoad = load;
}
-//----------------------------------------------------------------------------
-bool cmCTest::ShouldCompressMemCheckOutput()
-{
- if(!this->ComputedCompressMemCheckOutput)
- {
- std::string cdashVersion = this->GetCDashVersion();
-
- bool compressionSupported = cmSystemTools::VersionCompare(
- cmSystemTools::OP_GREATER, cdashVersion.c_str(), "1.9.0");
- this->CompressMemCheckOutput &= compressionSupported;
- this->ComputedCompressMemCheckOutput = true;
- }
- return this->CompressMemCheckOutput;
-}
-
-//----------------------------------------------------------------------------
-std::string cmCTest::GetCDashVersion()
+bool cmCTest::ShouldCompressTestOutput()
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
- //First query the server. If that fails, fall back to the local setting
- std::string response;
- std::string url = "http://";
- url += this->GetCTestConfiguration("DropSite");
-
- std::string cdashUri = this->GetCTestConfiguration("DropLocation");
- cdashUri = cdashUri.substr(0, cdashUri.find("/submit.php"));
-
- int res = 1;
- if ( ! cdashUri.empty() )
- {
- url += cdashUri + "/api/getversion.php";
- res = cmCTest::HTTPRequest(url, cmCTest::HTTP_GET, response, "", "", 3);
- }
-
- return res ? this->GetCTestConfiguration("CDashVersion") : response;
-#else
- return this->GetCTestConfiguration("CDashVersion");
-#endif
+ return this->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())
- {
+ if (i != this->PartMap.end()) {
return i->second;
- }
+ }
// The string does not name a valid part.
return PartCount;
}
-//----------------------------------------------------------------------
int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
{
- cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
- if(!this->InteractiveDebugMode)
- {
+ bool quiet = false;
+ if (command && command->ShouldBeQuiet()) {
+ quiet = true;
+ }
+
+ cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
+ if (!this->InteractiveDebugMode) {
this->BlockTestErrorDiagnostics();
- }
- else
- {
+ } else {
cmSystemTools::PutEnv("CTEST_INTERACTIVE_DEBUG_MODE=1");
- }
+ }
this->BinaryDir = binary_dir;
cmSystemTools::ConvertToUnixSlashes(this->BinaryDir);
this->UpdateCTestConfiguration();
- cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
- if ( this->ProduceXML )
- {
- cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
- cmCTestLog(this, OUTPUT,
- " Site: " << this->GetCTestConfiguration("Site") << std::endl
- << " Build name: " << this->GetCTestConfiguration("BuildName")
- << std::endl);
- cmCTestLog(this, DEBUG, "Produce XML is on" << std::endl);
- if ( this->TestModel == cmCTest::NIGHTLY &&
- this->GetCTestConfiguration("NightlyStartTime").empty() )
- {
- cmCTestLog(this, WARNING,
- "WARNING: No nightly start time found please set in"
- " CTestConfig.cmake or DartConfig.cmake" << std::endl);
- cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl);
+ cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
+ if (this->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, DEBUG, "Produce XML is on" << std::endl, quiet);
+ if (this->TestModel == cmCTest::NIGHTLY &&
+ this->GetCTestConfiguration("NightlyStartTime").empty()) {
+ cmCTestOptionalLog(
+ this, WARNING,
+ "WARNING: No nightly start time found please set in CTestConfig.cmake"
+ " or DartConfig.cmake"
+ << std::endl,
+ quiet);
+ cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl,
+ quiet);
return 0;
- }
}
+ }
- cmake cm;
- cmGlobalGenerator gg;
- gg.SetCMakeInstance(&cm);
- cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
- cmMakefile *mf = lg->GetMakefile();
- if ( !this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), mf) )
- {
- cmCTestLog(this, DEBUG, "Cannot find custom configuration file tree"
- << std::endl);
+ cmake cm(cmake::RoleScript);
+ 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())) {
+ cmCTestOptionalLog(
+ this, DEBUG, "Cannot find custom configuration file tree" << std::endl,
+ quiet);
return 0;
- }
+ }
- if ( this->ProduceXML )
- {
+ if (this->ProduceXML) {
// Verify "Testing" directory exists:
//
std::string testingDir = this->BinaryDir + "/Testing";
- if ( cmSystemTools::FileExists(testingDir.c_str()) )
- {
- if ( !cmSystemTools::FileIsDirectory(testingDir.c_str()) )
- {
- cmCTestLog(this, ERROR_MESSAGE, "File " << testingDir
- << " is in the place of the testing directory" << std::endl);
+ if (cmSystemTools::FileExists(testingDir.c_str())) {
+ if (!cmSystemTools::FileIsDirectory(testingDir)) {
+ 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()) )
- {
+ } else {
+ if (!cmSystemTools::MakeDirectory(testingDir.c_str())) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory "
- << testingDir << std::endl);
+ << testingDir << std::endl);
return 0;
- }
}
+ }
// Create new "TAG" file or read existing one:
//
bool createNewTag = true;
- if (command)
- {
+ if (command) {
createNewTag = command->ShouldCreateNewTag();
- }
+ }
std::string tagfile = testingDir + "/TAG";
- std::ifstream tfin(tagfile.c_str());
+ cmsys::ifstream tfin(tagfile.c_str());
std::string tag;
- if (createNewTag)
- {
- time_t tctime = time(0);
- if ( this->TomorrowTag )
- {
- tctime += ( 24 * 60 * 60 );
- }
- struct tm *lctime = gmtime(&tctime);
- if ( tfin && cmSystemTools::GetLineFromStream(tfin, tag) )
- {
+ if (createNewTag) {
+ time_t tctime = time(CM_NULLPTR);
+ if (this->TomorrowTag) {
+ tctime += (24 * 60 * 60);
+ }
+ struct tm* lctime = gmtime(&tctime);
+ if (tfin && cmSystemTools::GetLineFromStream(tfin, tag)) {
int year = 0;
int mon = 0;
int day = 0;
int hour = 0;
int min = 0;
- sscanf(tag.c_str(), "%04d%02d%02d-%02d%02d",
- &year, &mon, &day, &hour, &min);
- if ( year != lctime->tm_year + 1900 ||
- mon != lctime->tm_mon+1 ||
- day != lctime->tm_mday )
- {
+ sscanf(tag.c_str(), "%04d%02d%02d-%02d%02d", &year, &mon, &day, &hour,
+ &min);
+ if (year != lctime->tm_year + 1900 || mon != lctime->tm_mon + 1 ||
+ day != lctime->tm_mday) {
tag = "";
- }
+ }
std::string tagmode;
- if ( cmSystemTools::GetLineFromStream(tfin, tagmode) )
- {
- if (tagmode.size() > 4 && !this->Parts[PartStart])
- {
+ if (cmSystemTools::GetLineFromStream(tfin, tagmode)) {
+ if (tagmode.size() > 4 && !this->Parts[PartStart]) {
this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str());
- }
}
- tfin.close();
}
- if (tag.size() == 0 || (0 != command) || this->Parts[PartStart])
- {
- cmCTestLog(this, DEBUG, "TestModel: " << this->GetTestModelString()
- << std::endl);
- cmCTestLog(this, DEBUG, "TestModel: " << this->TestModel << std::endl);
- if ( this->TestModel == cmCTest::NIGHTLY )
- {
+ tfin.close();
+ }
+ if (tag.empty() || (CM_NULLPTR != command) || this->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) {
lctime = this->GetNightlyTime(
this->GetCTestConfiguration("NightlyStartTime"),
this->TomorrowTag);
- }
+ }
char datestring[100];
- sprintf(datestring, "%04d%02d%02d-%02d%02d",
- lctime->tm_year + 1900,
- lctime->tm_mon+1,
- lctime->tm_mday,
- lctime->tm_hour,
+ sprintf(datestring, "%04d%02d%02d-%02d%02d", lctime->tm_year + 1900,
+ lctime->tm_mon + 1, lctime->tm_mday, lctime->tm_hour,
lctime->tm_min);
tag = datestring;
- std::ofstream ofs(tagfile.c_str());
- if ( ofs )
- {
+ cmsys::ofstream ofs(tagfile.c_str());
+ if (ofs) {
ofs << tag << std::endl;
ofs << this->GetTestModelString() << std::endl;
- }
+ }
ofs.close();
- if ( 0 == command )
- {
- cmCTestLog(this, OUTPUT, "Create new tag: " << tag << " - "
- << this->GetTestModelString() << std::endl);
- }
+ if (CM_NULLPTR == command) {
+ cmCTestOptionalLog(this, OUTPUT, "Create new tag: "
+ << tag << " - " << this->GetTestModelString()
+ << std::endl,
+ quiet);
}
}
- else
- {
- if ( tfin )
- {
+ } else {
+ if (tfin) {
cmSystemTools::GetLineFromStream(tfin, tag);
tfin.close();
- }
+ }
- if ( tag.empty() )
- {
- cmCTestLog(this, ERROR_MESSAGE,
- "Cannot read existing TAG file in " << testingDir
- << std::endl);
+ if (tag.empty()) {
+ cmCTestLog(this, ERROR_MESSAGE, "Cannot read existing TAG file in "
+ << testingDir << std::endl);
return 0;
- }
-
- cmCTestLog(this, OUTPUT, " Use existing tag: " << tag << " - "
- << this->GetTestModelString() << std::endl);
}
- this->CurrentTag = tag;
+ cmCTestOptionalLog(this, OUTPUT, " Use existing tag: "
+ << tag << " - " << this->GetTestModelString()
+ << std::endl,
+ quiet);
}
+ this->CurrentTag = tag;
+ }
+
return 1;
}
-//----------------------------------------------------------------------
bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
{
- std::string src_dir
- = this->GetCTestConfiguration("SourceDirectory").c_str();
- std::string bld_dir = this->GetCTestConfiguration("BuildDirectory").c_str();
+ std::string src_dir = this->GetCTestConfiguration("SourceDirectory");
+ std::string bld_dir = this->GetCTestConfiguration("BuildDirectory");
this->DartVersion = 1;
this->DropSiteCDash = false;
- for(Part p = PartStart; p != PartCount; p = Part(p+1))
- {
+ for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
this->Parts[p].SubmitFiles.clear();
- }
+ }
cmMakefile* mf = command->GetMakefile();
std::string fname;
@@ -672,158 +561,145 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
bld_dir_fname += "/CTestConfig.cmake";
cmSystemTools::ConvertToUnixSlashes(bld_dir_fname);
- if ( cmSystemTools::FileExists(bld_dir_fname.c_str()) )
- {
+ if (cmSystemTools::FileExists(bld_dir_fname.c_str())) {
fname = bld_dir_fname;
- }
- else if ( cmSystemTools::FileExists(src_dir_fname.c_str()) )
- {
+ } else if (cmSystemTools::FileExists(src_dir_fname.c_str())) {
fname = src_dir_fname;
- }
+ }
- if ( !fname.empty() )
- {
- cmCTestLog(this, OUTPUT, " Reading ctest configuration file: "
- << fname.c_str() << std::endl);
- bool readit = mf->ReadListFile(mf->GetCurrentListFile(),
- fname.c_str() );
- if(!readit)
- {
+ if (!fname.empty()) {
+ cmCTestOptionalLog(this, OUTPUT, " Reading ctest configuration file: "
+ << fname << std::endl,
+ command->ShouldBeQuiet());
+ bool readit = mf->ReadDependentFile(fname.c_str());
+ if (!readit) {
std::string m = "Could not find include file: ";
m += fname;
- command->SetError(m.c_str());
+ command->SetError(m);
return false;
- }
- }
- else
- {
- cmCTestLog(this, WARNING,
- "Cannot locate CTest configuration: in BuildDirectory: "
- << bld_dir_fname.c_str() << std::endl);
- cmCTestLog(this, WARNING,
- "Cannot locate CTest configuration: in SourceDirectory: "
- << src_dir_fname.c_str() << std::endl);
}
+ } 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",
- "CTEST_NIGHTLY_START_TIME");
- this->SetCTestConfigurationFromCMakeVariable(mf, "Site", "CTEST_SITE");
- this->SetCTestConfigurationFromCMakeVariable(mf, "BuildName",
- "CTEST_BUILD_NAME");
+ "CTEST_NIGHTLY_START_TIME",
+ command->ShouldBeQuiet());
+ this->SetCTestConfigurationFromCMakeVariable(mf, "Site", "CTEST_SITE",
+ command->ShouldBeQuiet());
+ this->SetCTestConfigurationFromCMakeVariable(
+ mf, "BuildName", "CTEST_BUILD_NAME", command->ShouldBeQuiet());
const char* dartVersion = mf->GetDefinition("CTEST_DART_SERVER_VERSION");
- if ( dartVersion )
- {
+ if (dartVersion) {
this->DartVersion = atoi(dartVersion);
- if ( this->DartVersion < 0 )
- {
+ if (this->DartVersion < 0) {
cmCTestLog(this, ERROR_MESSAGE, "Invalid Dart server version: "
- << dartVersion << ". Please specify the version number."
- << std::endl);
+ << 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) )
- {
+ if (!this->Initialize(bld_dir.c_str(), command)) {
return false;
- }
- cmCTestLog(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->SuppressUpdatingCTestConfiguration) {
return true;
- }
+ }
std::string fileName = this->CTestConfigFile;
- if ( fileName.empty() )
- {
+ if (fileName.empty()) {
fileName = this->BinaryDir + "/CTestConfiguration.ini";
- if ( !cmSystemTools::FileExists(fileName.c_str()) )
- {
+ if (!cmSystemTools::FileExists(fileName.c_str())) {
fileName = this->BinaryDir + "/DartConfiguration.tcl";
- }
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "UpdateCTestConfiguration from :"
- << fileName.c_str() << "\n");
- if ( !cmSystemTools::FileExists(fileName.c_str()) )
- {
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "UpdateCTestConfiguration from :" << fileName << "\n");
+ if (!cmSystemTools::FileExists(fileName.c_str())) {
// No need to exit if we are not producing XML
- if ( this->ProduceXML )
- {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot find file: " << fileName.c_str()
- << std::endl);
+ if (this->ProduceXML) {
+ cmCTestLog(this, ERROR_MESSAGE, "Cannot find file: " << fileName
+ << std::endl);
return false;
- }
}
- else
- {
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Parse Config file:"
- << fileName.c_str() << "\n");
+ } else {
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Parse Config file:" << fileName
+ << "\n");
// parse the dart test file
- std::ifstream fin(fileName.c_str());
+ cmsys::ifstream fin(fileName.c_str());
- if(!fin)
- {
+ if (!fin) {
return false;
- }
+ }
char buffer[1024];
- while ( fin )
- {
+ while (fin) {
buffer[0] = 0;
fin.getline(buffer, 1023);
buffer[1023] = 0;
std::string line = cmCTest::CleanString(buffer);
- if(line.size() == 0)
- {
+ if (line.empty()) {
continue;
- }
- while ( fin && (line[line.size()-1] == '\\') )
- {
- line = line.substr(0, line.size()-1);
+ }
+ while (fin && (line[line.size() - 1] == '\\')) {
+ line = line.substr(0, line.size() - 1);
buffer[0] = 0;
fin.getline(buffer, 1023);
buffer[1023] = 0;
line += cmCTest::CleanString(buffer);
- }
- if ( line[0] == '#' )
- {
+ }
+ if (line[0] == '#') {
continue;
- }
- std::string::size_type cpos = line.find_first_of(":");
- if ( cpos == line.npos )
- {
+ }
+ std::string::size_type cpos = line.find_first_of(':');
+ if (cpos == std::string::npos) {
continue;
- }
+ }
std::string key = line.substr(0, cpos);
- std::string value
- = cmCTest::CleanString(line.substr(cpos+1, line.npos));
+ std::string value = cmCTest::CleanString(line.substr(cpos + 1));
this->CTestConfiguration[key] = value;
- }
- fin.close();
}
- if ( !this->GetCTestConfiguration("BuildDirectory").empty() )
- {
+ fin.close();
+ }
+ if (!this->GetCTestConfiguration("BuildDirectory").empty()) {
this->BinaryDir = this->GetCTestConfiguration("BuildDirectory");
- cmSystemTools::ChangeDirectory(this->BinaryDir.c_str());
- }
+ cmSystemTools::ChangeDirectory(this->BinaryDir);
+ }
this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
- if ( this->ProduceXML )
- {
+ std::string const& testLoad = this->GetCTestConfiguration("TestLoad");
+ if (!testLoad.empty()) {
+ unsigned long load;
+ if (cmSystemTools::StringToULong(testLoad.c_str(), &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());
- }
+ }
return true;
}
-//----------------------------------------------------------------------
void cmCTest::BlockTestErrorDiagnostics()
{
cmSystemTools::PutEnv("DART_TEST_FROM_DART=1");
@@ -835,314 +711,245 @@ void cmCTest::BlockTestErrorDiagnostics()
#endif
}
-//----------------------------------------------------------------------
void cmCTest::SetTestModel(int mode)
{
this->InteractiveDebugMode = false;
this->TestModel = mode;
}
-//----------------------------------------------------------------------
bool cmCTest::SetTest(const char* ttype, bool report)
{
- if ( cmSystemTools::LowerCase(ttype) == "all" )
- {
- for(Part p = PartStart; p != PartCount; p = Part(p+1))
- {
+ if (cmSystemTools::LowerCase(ttype) == "all") {
+ for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
this->Parts[p].Enable();
- }
- return true;
}
+ return true;
+ }
Part p = this->GetPartFromName(ttype);
- if(p != PartCount)
- {
+ if (p != PartCount) {
this->Parts[p].Enable();
return true;
- }
- else
- {
- if ( report )
- {
- cmCTestLog(this, ERROR_MESSAGE, "Don't know about test \"" << ttype
- << "\" yet..." << std::endl);
- }
- return false;
- }
+ }
+ if (report) {
+ cmCTestLog(this, ERROR_MESSAGE, "Don't know about test \""
+ << ttype << "\" yet..." << std::endl);
+ }
+ return false;
}
-//----------------------------------------------------------------------
void cmCTest::Finalize()
{
}
-//----------------------------------------------------------------------
-bool cmCTest::OpenOutputFile(const std::string& path,
- const std::string& name, cmGeneratedFileStream& stream,
- bool compress)
+bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name,
+ cmGeneratedFileStream& stream, bool compress)
{
std::string testingDir = this->BinaryDir + "/Testing";
- if ( path.size() > 0 )
- {
+ if (!path.empty()) {
testingDir += "/" + path;
- }
- if ( cmSystemTools::FileExists(testingDir.c_str()) )
- {
- if ( !cmSystemTools::FileIsDirectory(testingDir.c_str()) )
- {
- cmCTestLog(this, ERROR_MESSAGE, "File " << testingDir
- << " is in the place of the testing directory"
- << std::endl);
+ }
+ if (cmSystemTools::FileExists(testingDir.c_str())) {
+ if (!cmSystemTools::FileIsDirectory(testingDir)) {
+ 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()) )
- {
+ } else {
+ if (!cmSystemTools::MakeDirectory(testingDir.c_str())) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory " << testingDir
- << std::endl);
+ << std::endl);
return false;
- }
}
+ }
std::string filename = testingDir + "/" + name;
stream.Open(filename.c_str());
- if( !stream )
- {
+ if (!stream) {
cmCTestLog(this, ERROR_MESSAGE, "Problem opening file: " << filename
- << std::endl);
+ << std::endl);
return false;
- }
- if ( compress )
- {
- if ( this->CompressXMLFiles )
- {
+ }
+ if (compress) {
+ if (this->CompressXMLFiles) {
stream.SetCompression(true);
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------
bool cmCTest::AddIfExists(Part part, const char* file)
{
- if ( this->CTestFileExists(file) )
- {
+ if (this->CTestFileExists(file)) {
this->AddSubmitFile(part, file);
- }
- else
- {
+ } else {
std::string name = file;
name += ".gz";
- if ( this->CTestFileExists(name.c_str()) )
- {
+ if (this->CTestFileExists(name)) {
this->AddSubmitFile(part, file);
- }
- else
- {
+ } else {
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------
bool cmCTest::CTestFileExists(const std::string& filename)
{
- std::string testingDir = this->BinaryDir + "/Testing/" +
- this->CurrentTag + "/" + filename;
+ std::string testingDir =
+ this->BinaryDir + "/Testing/" + this->CurrentTag + "/" + filename;
return cmSystemTools::FileExists(testingDir.c_str());
}
-//----------------------------------------------------------------------
cmCTestGenericHandler* cmCTest::GetInitializedHandler(const char* handler)
{
cmCTest::t_TestingHandlers::iterator it =
this->TestingHandlers.find(handler);
- if ( it == this->TestingHandlers.end() )
- {
- return 0;
- }
+ if (it == this->TestingHandlers.end()) {
+ return CM_NULLPTR;
+ }
it->second->Initialize();
return it->second;
}
-//----------------------------------------------------------------------
cmCTestGenericHandler* cmCTest::GetHandler(const char* handler)
{
cmCTest::t_TestingHandlers::iterator it =
this->TestingHandlers.find(handler);
- if ( it == this->TestingHandlers.end() )
- {
- return 0;
- }
+ if (it == this->TestingHandlers.end()) {
+ return CM_NULLPTR;
+ }
return it->second;
}
-//----------------------------------------------------------------------
int cmCTest::ExecuteHandler(const char* shandler)
{
cmCTestGenericHandler* handler = this->GetHandler(shandler);
- if ( !handler )
- {
+ if (!handler) {
return -1;
- }
+ }
handler->Initialize();
return handler->ProcessHandler();
}
-//----------------------------------------------------------------------
-int cmCTest::ProcessTests()
+int cmCTest::ProcessSteps()
{
int res = 0;
bool notest = true;
int update_count = 0;
- for(Part p = PartStart; notest && p != PartCount; p = Part(p+1))
- {
+ for (Part p = PartStart; notest && p != PartCount; p = Part(p + 1)) {
notest = !this->Parts[p];
- }
- if (this->Parts[PartUpdate] &&
- (this->GetRemainingTimeAllowed() - 120 > 0))
- {
+ }
+ if (this->Parts[PartUpdate] && (this->GetRemainingTimeAllowed() - 120 > 0)) {
cmCTestGenericHandler* uphandler = this->GetHandler("update");
- uphandler->SetPersistentOption("SourceDirectory",
+ uphandler->SetPersistentOption(
+ "SourceDirectory",
this->GetCTestConfiguration("SourceDirectory").c_str());
update_count = uphandler->ProcessHandler();
- if ( update_count < 0 )
- {
+ if (update_count < 0) {
res |= cmCTest::UPDATE_ERRORS;
- }
}
- if ( this->TestModel == cmCTest::CONTINUOUS && !update_count )
- {
+ }
+ if (this->TestModel == cmCTest::CONTINUOUS && !update_count) {
return 0;
- }
+ }
if (this->Parts[PartConfigure] &&
- (this->GetRemainingTimeAllowed() - 120 > 0))
- {
- if (this->GetHandler("configure")->ProcessHandler() < 0)
- {
+ (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if (this->GetHandler("configure")->ProcessHandler() < 0) {
res |= cmCTest::CONFIGURE_ERRORS;
- }
}
- if (this->Parts[PartBuild] &&
- (this->GetRemainingTimeAllowed() - 120 > 0))
- {
+ }
+ if (this->Parts[PartBuild] && (this->GetRemainingTimeAllowed() - 120 > 0)) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("build")->ProcessHandler() < 0)
- {
+ if (this->GetHandler("build")->ProcessHandler() < 0) {
res |= cmCTest::BUILD_ERRORS;
- }
}
+ }
if ((this->Parts[PartTest] || notest) &&
- (this->GetRemainingTimeAllowed() - 120 > 0))
- {
+ (this->GetRemainingTimeAllowed() - 120 > 0)) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("test")->ProcessHandler() < 0)
- {
+ if (this->GetHandler("test")->ProcessHandler() < 0) {
res |= cmCTest::TEST_ERRORS;
- }
}
+ }
if (this->Parts[PartCoverage] &&
- (this->GetRemainingTimeAllowed() - 120 > 0))
- {
+ (this->GetRemainingTimeAllowed() - 120 > 0)) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("coverage")->ProcessHandler() < 0)
- {
+ if (this->GetHandler("coverage")->ProcessHandler() < 0) {
res |= cmCTest::COVERAGE_ERRORS;
- }
}
+ }
if (this->Parts[PartMemCheck] &&
- (this->GetRemainingTimeAllowed() - 120 > 0))
- {
+ (this->GetRemainingTimeAllowed() - 120 > 0)) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("memcheck")->ProcessHandler() < 0)
- {
+ if (this->GetHandler("memcheck")->ProcessHandler() < 0) {
res |= cmCTest::MEMORY_ERRORS;
- }
}
- if ( !notest )
- {
+ }
+ if (!notest) {
std::string notes_dir = this->BinaryDir + "/Testing/Notes";
- if ( cmSystemTools::FileIsDirectory(notes_dir.c_str()) )
- {
+ if (cmSystemTools::FileIsDirectory(notes_dir)) {
cmsys::Directory d;
- d.Load(notes_dir.c_str());
+ d.Load(notes_dir);
unsigned long kk;
- for ( kk = 0; kk < d.GetNumberOfFiles(); kk ++ )
- {
+ 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()) &&
- !cmSystemTools::FileIsDirectory(fullname.c_str()) )
- {
- if ( this->NotesFiles.size() > 0 )
- {
+ if (cmSystemTools::FileExists(fullname.c_str()) &&
+ !cmSystemTools::FileIsDirectory(fullname)) {
+ if (!this->NotesFiles.empty()) {
this->NotesFiles += ";";
- }
+ }
this->NotesFiles += fullname;
this->Parts[PartNotes].Enable();
- }
}
}
}
- if (this->Parts[PartNotes])
- {
+ }
+ if (this->Parts[PartNotes]) {
this->UpdateCTestConfiguration();
- if ( this->NotesFiles.size() )
- {
+ if (!this->NotesFiles.empty()) {
this->GenerateNotesFile(this->NotesFiles.c_str());
- }
}
- if (this->Parts[PartSubmit])
- {
+ }
+ if (this->Parts[PartSubmit]) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("submit")->ProcessHandler() < 0)
- {
+ if (this->GetHandler("submit")->ProcessHandler() < 0) {
res |= cmCTest::SUBMIT_ERRORS;
- }
- }
- if ( res != 0 )
- {
- cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest"
- << std::endl);
}
+ }
+ if (res != 0) {
+ cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest" << std::endl);
+ }
return res;
}
-//----------------------------------------------------------------------
std::string cmCTest::GetTestModelString()
{
- if ( !this->SpecificTrack.empty() )
- {
+ if (!this->SpecificTrack.empty()) {
return this->SpecificTrack;
- }
- switch ( this->TestModel )
- {
- case cmCTest::NIGHTLY:
- return "Nightly";
- case cmCTest::CONTINUOUS:
- return "Continuous";
- }
+ }
+ switch (this->TestModel) {
+ case cmCTest::NIGHTLY:
+ return "Nightly";
+ case cmCTest::CONTINUOUS:
+ return "Continuous";
+ }
return "Experimental";
}
-//----------------------------------------------------------------------
int cmCTest::GetTestModelFromString(const char* str)
{
- if ( !str )
- {
+ if (!str) {
return cmCTest::EXPERIMENTAL;
- }
+ }
std::string rstr = cmSystemTools::LowerCase(str);
- if ( strncmp(rstr.c_str(), "cont", 4) == 0 )
- {
+ if (cmHasLiteralPrefix(rstr.c_str(), "cont")) {
return cmCTest::CONTINUOUS;
- }
- if ( strncmp(rstr.c_str(), "nigh", 4) == 0 )
- {
+ }
+ if (cmHasLiteralPrefix(rstr.c_str(), "nigh")) {
return cmCTest::NIGHTLY;
- }
+ }
return cmCTest::EXPERIMENTAL;
}
@@ -1151,37 +958,30 @@ int cmCTest::GetTestModelFromString(const char* str)
//######################################################################
//######################################################################
-//----------------------------------------------------------------------
-int cmCTest::RunMakeCommand(const char* command, std::string* output,
- int* retVal, const char* dir, int timeout, std::ofstream& ofs)
+int cmCTest::RunMakeCommand(const char* command, std::string& output,
+ int* retVal, const char* dir, int timeout,
+ std::ostream& ofs, Encoding encoding)
{
// First generate the command and arguments
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
+ std::vector<std::string> args = cmSystemTools::ParseArguments(command);
- if(args.size() < 1)
- {
+ if (args.empty()) {
return false;
- }
+ }
std::vector<const char*> argv;
- for(std::vector<cmStdString>::const_iterator a = args.begin();
- a != args.end(); ++a)
- {
+ for (std::vector<std::string>::const_iterator a = args.begin();
+ a != args.end(); ++a) {
argv.push_back(a->c_str());
- }
- argv.push_back(0);
-
- if ( output )
- {
- *output = "";
- }
+ }
+ argv.push_back(CM_NULLPTR);
+ output = "";
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:");
std::vector<const char*>::iterator ait;
- for ( ait = argv.begin(); ait != argv.end() && *ait; ++ ait )
- {
+ for (ait = argv.begin(); ait != argv.end() && *ait; ++ait) {
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << *ait << "\"");
- }
+ }
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl);
// Now create process object
@@ -1199,71 +999,68 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output,
char* data;
int length;
- cmCTestLog(this, HANDLER_OUTPUT,
- " Each . represents " << tick_len << " bytes of output" << std::endl
- << " " << std::flush);
- while(cmsysProcess_WaitForData(cp, &data, &length, 0))
- {
- if ( output )
- {
- for(int cc =0; cc < length; ++cc)
- {
- if(data[cc] == 0)
- {
- data[cc] = '\n';
- }
- }
-
- output->append(data, length);
- while ( output->size() > (tick * tick_len) )
- {
- tick ++;
- cmCTestLog(this, HANDLER_OUTPUT, "." << std::flush);
- if ( tick % tick_line_len == 0 && tick > 0 )
- {
- cmCTestLog(this, HANDLER_OUTPUT, " Size: "
- << int((double(output->size()) / 1024.0) + 1) << "K" << std::endl
- << " " << std::flush);
- }
- }
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length));
- if ( ofs )
- {
- ofs << cmCTestLogWrite(data, 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)) {
+ processOutput.DecodeText(data, length, strdata);
+ for (size_t cc = 0; cc < strdata.size(); ++cc) {
+ if (strdata[cc] == 0) {
+ strdata[cc] = '\n';
+ }
+ }
+ output.append(strdata);
+ while (output.size() > (tick * tick_len)) {
+ tick++;
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush);
+ 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);
}
}
- cmCTestLog(this, OUTPUT, " Size of output: "
- << int(double(output->size()) / 1024.0) << "K" << std::endl);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (ofs) {
+ ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
+ }
+ }
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ output.append(strdata);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (ofs) {
+ ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
+ }
+ }
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size of output: "
+ << int(double(output.size()) / 1024.0) << "K" << std::endl);
- cmsysProcess_WaitForExit(cp, 0);
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
int result = cmsysProcess_GetState(cp);
- if(result == cmsysProcess_State_Exited)
- {
+ if (result == cmsysProcess_State_Exited) {
*retVal = cmsysProcess_GetExitValue(cp);
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Command exited with the value: "
- << *retVal << std::endl);
- }
- else if(result == cmsysProcess_State_Exception)
- {
+ cmCTestLog(this, HANDLER_VERBOSE_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);
- }
- else if(result == cmsysProcess_State_Expired)
- {
+ << 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.";
+ } 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);
- }
+ << cmsysProcess_GetErrorString(cp) << std::endl);
+ }
cmsysProcess_Delete(cp);
@@ -1275,219 +1072,202 @@ 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,
- std::vector<std::string>* environment)
+int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
+ int* retVal, std::ostream* log, double testTimeOut,
+ std::vector<std::string>* environment, Encoding encoding)
{
- bool modifyEnv = (environment && environment->size()>0);
+ bool modifyEnv = (environment && !environment->empty());
// determine how much time we have
double timeout = this->GetRemainingTimeAllowed() - 120;
- if (this->TimeOut > 0 && this->TimeOut < timeout)
- {
+ if (this->TimeOut > 0 && this->TimeOut < timeout) {
timeout = this->TimeOut;
- }
- if (testTimeOut > 0
- && testTimeOut < this->GetRemainingTimeAllowed())
- {
+ }
+ if (testTimeOut > 0 && testTimeOut < this->GetRemainingTimeAllowed()) {
timeout = testTimeOut;
- }
+ }
// always have at least 1 second if we got to here
- if (timeout <= 0)
- {
+ if (timeout <= 0) {
timeout = 1;
- }
+ }
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
"Test timeout computed to be: " << timeout << "\n");
- if(cmSystemTools::SameFile(argv[0], this->CTestSelf.c_str()) &&
- !this->ForceNewCTestProcess)
- {
+ if (cmSystemTools::SameFile(argv[0], cmSystemTools::GetCTestCommand()) &&
+ !this->ForceNewCTestProcess) {
cmCTest inst;
inst.ConfigType = this->ConfigType;
inst.TimeOut = timeout;
// Capture output of the child ctest.
- cmOStringStream oss;
+ 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 (unsigned int i = 0; i < argv.size(); ++i) {
+ if (argv[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)
- {
+ if (strcmp(argv[i], "--build-generator") == 0 && timeout > 0) {
args.push_back("--test-timeout");
- cmOStringStream msg;
+ std::ostringstream msg;
msg << timeout;
args.push_back(msg.str());
- }
- args.push_back(argv[i]);
}
+ args.push_back(argv[i]);
}
- if ( log )
- {
+ }
+ if (log) {
*log << "* Run internal CTest" << std::endl;
- }
- std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
+ }
- cmsys::auto_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
- if (modifyEnv)
- {
+ CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv;
+ if (modifyEnv) {
saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
cmSystemTools::AppendEnv(*environment);
- }
+ }
*retVal = inst.Run(args, output);
- *output += oss.str();
- if ( log )
- {
- *log << output->c_str();
- }
- cmSystemTools::ChangeDirectory(oldpath.c_str());
-
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- "Internal cmCTest object used to run test." << std::endl
- << *output << std::endl);
+ if (output) {
+ *output += oss.str();
+ }
+ if (log && output) {
+ *log << *output;
+ }
+ if (output) {
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "Internal cmCTest object used to run test." << std::endl
+ << *output
+ << std::endl);
+ }
return cmsysProcess_State_Exited;
- }
+ }
std::vector<char> tempOutput;
- if ( output )
- {
+ if (output) {
*output = "";
- }
+ }
- cmsys::auto_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
- if (modifyEnv)
- {
+ CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv;
+ if (modifyEnv) {
saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
cmSystemTools::AppendEnv(*environment);
- }
+ }
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, &*argv.begin());
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
- if(cmSystemTools::GetRunCommandHideConsole())
- {
+ if (cmSystemTools::GetRunCommandHideConsole()) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- }
+ }
cmsysProcess_SetTimeout(cp, timeout);
cmsysProcess_Execute(cp);
char* data;
int length;
- while(cmsysProcess_WaitForData(cp, &data, &length, 0))
- {
- if ( output )
- {
- tempOutput.insert(tempOutput.end(), data, data+length);
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length));
- if ( log )
- {
- log->write(data, length);
- }
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
+ while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) {
+ processOutput.DecodeText(data, length, strdata);
+ if (output) {
+ tempOutput.insert(tempOutput.end(), data, data + length);
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (log) {
+ log->write(strdata.c_str(), strdata.size());
+ }
+ }
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (log) {
+ log->write(strdata.c_str(), strdata.size());
}
+ }
- cmsysProcess_WaitForExit(cp, 0);
- if(output && tempOutput.begin() != tempOutput.end())
- {
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ processOutput.DecodeText(tempOutput, tempOutput);
+ if (output && tempOutput.begin() != tempOutput.end()) {
output->append(&*tempOutput.begin(), tempOutput.size());
- }
+ }
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "-- Process completed"
- << std::endl);
+ << std::endl);
int result = cmsysProcess_GetState(cp);
- if(result == cmsysProcess_State_Exited)
- {
+ if (result == cmsysProcess_State_Exited) {
*retVal = cmsysProcess_GetExitValue(cp);
- if(*retVal != 0 && this->OutputTestOutputOnTestFailure)
- {
- OutputTestErrors(tempOutput);
- }
+ if (*retVal != 0 && this->OutputTestOutputOnTestFailure) {
+ OutputTestErrors(tempOutput);
+ }
+ } else if (result == cmsysProcess_State_Exception) {
+ if (this->OutputTestOutputOnTestFailure) {
+ OutputTestErrors(tempOutput);
}
- else if(result == cmsysProcess_State_Exception)
- {
- if(this->OutputTestOutputOnTestFailure)
- {
- OutputTestErrors(tempOutput);
- }
*retVal = cmsysProcess_GetExitException(cp);
std::string outerr = "\n*** Exception executing: ";
outerr += cmsysProcess_GetExceptionString(cp);
- *output += outerr;
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr.c_str() << std::endl
- << std::flush);
+ if (output) {
+ *output += outerr;
}
- else if(result == cmsysProcess_State_Error)
- {
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl
+ << std::flush);
+ } else if (result == cmsysProcess_State_Error) {
std::string outerr = "\n*** ERROR executing: ";
outerr += cmsysProcess_GetErrorString(cp);
- *output += outerr;
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr.c_str() << std::endl
- << std::flush);
+ if (output) {
+ *output += outerr;
}
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl
+ << std::flush);
+ }
cmsysProcess_Delete(cp);
return result;
}
-//----------------------------------------------------------------------
std::string cmCTest::SafeBuildIdField(const std::string& value)
{
std::string safevalue(value);
- if (safevalue != "")
- {
+ if (safevalue != "") {
// Disallow non-filename and non-space whitespace characters.
// If they occur, replace them with ""
//
- const char *disallowed = "\\/:*?\"<>|\n\r\t\f\v";
+ const char* disallowed = "\\:*?\"<>|\n\r\t\f\v";
- if (safevalue.find_first_of(disallowed) != value.npos)
- {
+ if (safevalue.find_first_of(disallowed) != std::string::npos) {
std::string::size_type i = 0;
std::string::size_type n = strlen(disallowed);
char replace[2];
replace[1] = 0;
- for (i= 0; i<n; ++i)
- {
+ for (i = 0; i < n; ++i) {
replace[0] = disallowed[i];
cmSystemTools::ReplaceString(safevalue, replace, "");
- }
}
-
- safevalue = cmXMLSafe(safevalue).str();
}
+ }
- if (safevalue == "")
- {
+ if (safevalue == "") {
safevalue = "(empty)";
- }
+ }
return safevalue;
}
-//----------------------------------------------------------------------
-void cmCTest::StartXML(std::ostream& ostr, bool append)
+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." << std::endl);
+ if (this->CurrentTag.empty()) {
+ cmCTestLog(this, ERROR_MESSAGE, "Current Tag empty, this may mean"
+ " NightlStartTime was not set correctly."
+ << std::endl);
cmSystemTools::SetFatalErrorOccured();
- }
+ }
// find out about the system
cmsys::SystemInformation info;
@@ -1495,283 +1275,257 @@ void cmCTest::StartXML(std::ostream& ostr, bool append)
info.RunOSCheck();
info.RunMemoryCheck();
- std::string buildname = cmCTest::SafeBuildIdField(
- this->GetCTestConfiguration("BuildName"));
- std::string stamp = cmCTest::SafeBuildIdField(
- this->CurrentTag + "-" + this->GetTestModelString());
- std::string site = cmCTest::SafeBuildIdField(
- this->GetCTestConfiguration("Site"));
-
- ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- << "<Site BuildName=\"" << buildname << "\"\n"
- << "\tBuildStamp=\"" << stamp << "\"\n"
- << "\tName=\"" << site << "\"\n"
- << "\tGenerator=\"ctest-" << cmVersion::GetCMakeVersion() << "\"\n"
- << (append? "\tAppend=\"true\"\n":"")
- << "\tCompilerName=\"" << this->GetCTestConfiguration("Compiler")
- << "\"\n"
-#ifdef _COMPILER_VERSION
- << "\tCompilerVersion=\"_COMPILER_VERSION\"\n"
-#endif
- << "\tOSName=\"" << info.GetOSName() << "\"\n"
- << "\tHostname=\"" << info.GetHostname() << "\"\n"
- << "\tOSRelease=\"" << info.GetOSRelease() << "\"\n"
- << "\tOSVersion=\"" << info.GetOSVersion() << "\"\n"
- << "\tOSPlatform=\"" << info.GetOSPlatform() << "\"\n"
- << "\tIs64Bits=\"" << info.Is64Bits() << "\"\n"
- << "\tVendorString=\"" << info.GetVendorString() << "\"\n"
- << "\tVendorID=\"" << info.GetVendorID() << "\"\n"
- << "\tFamilyID=\"" << info.GetFamilyID() << "\"\n"
- << "\tModelID=\"" << info.GetModelID() << "\"\n"
- << "\tProcessorCacheSize=\"" << info.GetProcessorCacheSize() << "\"\n"
- << "\tNumberOfLogicalCPU=\"" << info.GetNumberOfLogicalCPU() << "\"\n"
- << "\tNumberOfPhysicalCPU=\""<< info.GetNumberOfPhysicalCPU() << "\"\n"
- << "\tTotalVirtualMemory=\"" << info.GetTotalVirtualMemory() << "\"\n"
- << "\tTotalPhysicalMemory=\""<< info.GetTotalPhysicalMemory() << "\"\n"
- << "\tLogicalProcessorsPerPhysical=\""
- << info.GetLogicalProcessorsPerPhysical() << "\"\n"
- << "\tProcessorClockFrequency=\""
- << info.GetProcessorClockFrequency() << "\"\n"
- << ">" << std::endl;
- this->AddSiteProperties(ostr);
-}
-
-//----------------------------------------------------------------------
-void cmCTest::AddSiteProperties(std::ostream& ostr)
+ std::string buildname =
+ cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName"));
+ std::string stamp = cmCTest::SafeBuildIdField(this->CurrentTag + "-" +
+ this->GetTestModelString());
+ std::string site =
+ cmCTest::SafeBuildIdField(this->GetCTestConfiguration("Site"));
+
+ xml.StartDocument();
+ xml.StartElement("Site");
+ xml.Attribute("BuildName", buildname);
+ xml.BreakAttributes();
+ xml.Attribute("BuildStamp", stamp);
+ xml.Attribute("Name", site);
+ xml.Attribute("Generator",
+ std::string("ctest-") + cmVersion::GetCMakeVersion());
+ if (append) {
+ xml.Attribute("Append", "true");
+ }
+ xml.Attribute("CompilerName", this->GetCTestConfiguration("Compiler"));
+ xml.Attribute("CompilerVersion",
+ this->GetCTestConfiguration("CompilerVersion"));
+ xml.Attribute("OSName", info.GetOSName());
+ xml.Attribute("Hostname", info.GetHostname());
+ xml.Attribute("OSRelease", info.GetOSRelease());
+ xml.Attribute("OSVersion", info.GetOSVersion());
+ xml.Attribute("OSPlatform", info.GetOSPlatform());
+ xml.Attribute("Is64Bits", info.Is64Bits());
+ xml.Attribute("VendorString", info.GetVendorString());
+ xml.Attribute("VendorID", info.GetVendorID());
+ xml.Attribute("FamilyID", info.GetFamilyID());
+ xml.Attribute("ModelID", info.GetModelID());
+ xml.Attribute("ProcessorCacheSize", info.GetProcessorCacheSize());
+ xml.Attribute("NumberOfLogicalCPU", info.GetNumberOfLogicalCPU());
+ xml.Attribute("NumberOfPhysicalCPU", info.GetNumberOfPhysicalCPU());
+ xml.Attribute("TotalVirtualMemory", info.GetTotalVirtualMemory());
+ xml.Attribute("TotalPhysicalMemory", info.GetTotalPhysicalMemory());
+ xml.Attribute("LogicalProcessorsPerPhysical",
+ info.GetLogicalProcessorsPerPhysical());
+ xml.Attribute("ProcessorClockFrequency", info.GetProcessorClockFrequency());
+
+ std::string changeId = this->GetCTestConfiguration("ChangeId");
+ if (!changeId.empty()) {
+ xml.Attribute("ChangeId", changeId);
+ }
+
+ this->AddSiteProperties(xml);
+}
+
+void cmCTest::AddSiteProperties(cmXMLWriter& xml)
{
cmCTestScriptHandler* ch =
static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
- cmake* cm = ch->GetCMake();
+ cmake* cm = ch->GetCMake();
// if no CMake then this is the old style script and props like
// this will not work anyway.
- if(!cm)
- {
+ if (!cm) {
return;
- }
+ }
// This code should go when cdash is changed to use labels only
- const char* subproject = cm->GetProperty("SubProject", cmProperty::GLOBAL);
- if(subproject)
- {
- ostr << "<Subproject name=\"" << subproject << "\">\n";
+ const char* subproject = cm->GetState()->GetGlobalProperty("SubProject");
+ if (subproject) {
+ xml.StartElement("Subproject");
+ xml.Attribute("name", subproject);
const char* labels =
- ch->GetCMake()->GetProperty("SubProjectLabels", cmProperty::GLOBAL);
- if(labels)
- {
- ostr << " <Labels>\n";
+ ch->GetCMake()->GetState()->GetGlobalProperty("SubProjectLabels");
+ 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)
- {
- ostr << " <Label>" << i->c_str() << "</Label>\n";
- }
- ostr << " </Labels>\n";
+ for (std::vector<std::string>::iterator i = args.begin();
+ i != args.end(); ++i) {
+ xml.Element("Label", *i);
}
- ostr << "</Subproject>\n";
+ xml.EndElement();
}
+ xml.EndElement();
+ }
// This code should stay when cdash only does label based sub-projects
- const char* label = cm->GetProperty("Label", cmProperty::GLOBAL);
- if(label)
- {
- ostr << "<Labels>\n";
- ostr << " <Label>" << label << "</Label>\n";
- ostr << "</Labels>\n";
- }
+ const char* label = cm->GetState()->GetGlobalProperty("Label");
+ if (label) {
+ xml.StartElement("Labels");
+ xml.Element("Label", label);
+ xml.EndElement();
+ }
}
-
-//----------------------------------------------------------------------
-void cmCTest::EndXML(std::ostream& ostr)
+void cmCTest::EndXML(cmXMLWriter& xml)
{
- ostr << "</Site>" << std::endl;
+ xml.EndElement(); // Site
+ xml.EndDocument();
}
-//----------------------------------------------------------------------
-int cmCTest::GenerateCTestNotesOutput(std::ostream& os,
- const cmCTest::VectorOfStrings& files)
+int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
+ const cmCTest::VectorOfStrings& files)
{
+ std::string buildname =
+ cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName"));
cmCTest::VectorOfStrings::const_iterator it;
- os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- << "<?xml-stylesheet type=\"text/xsl\" "
- "href=\"Dart/Source/Server/XSL/Build.xsl "
- "<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n"
- << "<Site BuildName=\"" << this->GetCTestConfiguration("BuildName")
- << "\" BuildStamp=\""
- << this->CurrentTag << "-" << this->GetTestModelString() << "\" Name=\""
- << this->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
- << cmVersion::GetCMakeVersion()
- << "\">\n";
- this->AddSiteProperties(os);
- os << "<Notes>" << std::endl;
-
- for ( it = files.begin(); it != files.end(); it ++ )
- {
- cmCTestLog(this, OUTPUT, "\tAdd file: " << it->c_str() << std::endl);
+ xml.StartDocument();
+ xml.ProcessingInstruction("xml-stylesheet",
+ "type=\"text/xsl\" "
+ "href=\"Dart/Source/Server/XSL/Build.xsl "
+ "<file:///Dart/Source/Server/XSL/Build.xsl> \"");
+ xml.StartElement("Site");
+ xml.Attribute("BuildName", buildname);
+ xml.Attribute("BuildStamp",
+ this->CurrentTag + "-" + this->GetTestModelString());
+ xml.Attribute("Name", this->GetCTestConfiguration("Site"));
+ xml.Attribute("Generator",
+ 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);
std::string note_time = this->CurrentTime();
- os << "<Note Name=\"" << cmXMLSafe(*it) << "\">\n"
- << "<Time>" << cmSystemTools::GetTime() << "</Time>\n"
- << "<DateTime>" << note_time << "</DateTime>\n"
- << "<Text>" << std::endl;
- std::ifstream ifs(it->c_str());
- if ( ifs )
- {
+ xml.StartElement("Note");
+ xml.Attribute("Name", *it);
+ xml.Element("Time", cmSystemTools::GetTime());
+ xml.Element("DateTime", note_time);
+ xml.StartElement("Text");
+ cmsys::ifstream ifs(it->c_str());
+ if (ifs) {
std::string line;
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
- os << cmXMLSafe(line) << std::endl;
- }
- ifs.close();
- }
- else
- {
- os << "Problem reading file: " << it->c_str() << std::endl;
- cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: " << it->c_str()
- << " while creating notes" << std::endl);
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
+ xml.Content(line);
+ xml.Content("\n");
}
- os << "</Text>\n"
- << "</Note>" << std::endl;
+ ifs.close();
+ } else {
+ xml.Content("Problem reading file: " + *it + "\n");
+ cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: "
+ << *it << " while creating notes" << std::endl);
}
- os << "</Notes>\n"
- << "</Site>" << std::endl;
+ xml.EndElement(); // Text
+ xml.EndElement(); // Note
+ }
+ xml.EndElement(); // Notes
+ xml.EndElement(); // Site
+ xml.EndDocument();
return 1;
}
-//----------------------------------------------------------------------
-int cmCTest::GenerateNotesFile(const std::vector<cmStdString> &files)
+int cmCTest::GenerateNotesFile(const VectorOfStrings& files)
{
cmGeneratedFileStream ofs;
- if ( !this->OpenOutputFile(this->CurrentTag, "Notes.xml", ofs) )
- {
+ if (!this->OpenOutputFile(this->CurrentTag, "Notes.xml", ofs)) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl);
return 1;
- }
-
- this->GenerateCTestNotesOutput(ofs, files);
+ }
+ cmXMLWriter xml(ofs);
+ this->GenerateCTestNotesOutput(xml, files);
return 0;
}
-//----------------------------------------------------------------------
int cmCTest::GenerateNotesFile(const char* cfiles)
{
- if ( !cfiles )
- {
+ if (!cfiles) {
return 1;
- }
+ }
- std::vector<cmStdString> files;
+ VectorOfStrings files;
cmCTestLog(this, OUTPUT, "Create notes file" << std::endl);
files = cmSystemTools::SplitString(cfiles, ';');
- if ( files.size() == 0 )
- {
+ if (files.empty()) {
return 1;
- }
+ }
return this->GenerateNotesFile(files);
}
-//----------------------------------------------------------------------
-std::string cmCTest::Base64GzipEncodeFile(std::string file)
+std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
{
std::string tarFile = file + "_temp.tar.gz";
- std::vector<cmStdString> files;
+ std::vector<std::string> files;
files.push_back(file);
- if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false))
- {
+ if (!cmSystemTools::CreateTar(tarFile.c_str(), files,
+ cmSystemTools::TarCompressGZip, false)) {
cmCTestLog(this, ERROR_MESSAGE, "Error creating tar while "
- "encoding file: " << file << std::endl);
+ "encoding file: "
+ << file << std::endl);
return "";
- }
+ }
std::string base64 = this->Base64EncodeFile(tarFile);
- cmSystemTools::RemoveFile(tarFile.c_str());
+ cmSystemTools::RemoveFile(tarFile);
return base64;
}
-//----------------------------------------------------------------------
-std::string cmCTest::Base64EncodeFile(std::string file)
+std::string cmCTest::Base64EncodeFile(std::string const& file)
{
- long len = cmSystemTools::FileLength(file.c_str());
- std::ifstream ifs(file.c_str(), std::ios::in
+ size_t const len = cmSystemTools::FileLength(file);
+ cmsys::ifstream ifs(file.c_str(), std::ios::in
#ifdef _WIN32
- | std::ios::binary
+ | std::ios::binary
#endif
- );
- unsigned char *file_buffer = new unsigned char [ len + 1 ];
- ifs.read(reinterpret_cast<char*>(file_buffer), len);
+ );
+ std::vector<char> file_buffer(len + 1);
+ ifs.read(&file_buffer[0], len);
ifs.close();
- unsigned char *encoded_buffer
- = new unsigned char [ static_cast<int>(
- static_cast<double>(len) * 1.5 + 5.0) ];
+ std::vector<char> encoded_buffer((len * 3) / 2 + 5);
- unsigned long rlen
- = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
+ size_t const rlen = cmsysBase64_Encode(
+ reinterpret_cast<unsigned char*>(&file_buffer[0]), len,
+ reinterpret_cast<unsigned char*>(&encoded_buffer[0]), 1);
- std::string base64 = "";
- for(unsigned long i = 0; i < rlen; i++)
- {
- base64 += encoded_buffer[i];
- }
- delete [] file_buffer;
- delete [] encoded_buffer;
-
- return base64;
+ return std::string(&encoded_buffer[0], rlen);
}
-
-//----------------------------------------------------------------------
-bool cmCTest::SubmitExtraFiles(const std::vector<cmStdString> &files)
+bool cmCTest::SubmitExtraFiles(const VectorOfStrings& files)
{
- std::vector<cmStdString>::const_iterator it;
- for ( it = files.begin();
- it != files.end();
- ++ it )
- {
- if ( !cmSystemTools::FileExists(it->c_str()) )
- {
+ 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->c_str() << " to submit."
- << std::endl;);
+ << *it << " to submit." << std::endl;);
return false;
- }
- this->AddSubmitFile(PartExtraFiles, it->c_str());
}
+ this->AddSubmitFile(PartExtraFiles, it->c_str());
+ }
return true;
}
-//----------------------------------------------------------------------
bool cmCTest::SubmitExtraFiles(const char* cfiles)
{
- if ( !cfiles )
- {
- return 1;
- }
+ if (!cfiles) {
+ return true;
+ }
- std::vector<cmStdString> files;
+ VectorOfStrings files;
cmCTestLog(this, OUTPUT, "Submit extra files" << std::endl);
files = cmSystemTools::SplitString(cfiles, ';');
- if ( files.size() == 0 )
- {
- return 1;
- }
+ if (files.empty()) {
+ return true;
+ }
return this->SubmitExtraFiles(files);
}
-
-//-------------------------------------------------------
// for a -D argument convert the next argument into
// the proper list of dashboard steps via SetTest
-bool cmCTest::AddTestsForDashboardType(std::string &targ)
+bool cmCTest::AddTestsForDashboardType(std::string& targ)
{
- if ( targ == "Experimental" )
- {
+ if (targ == "Experimental") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Start");
this->SetTest("Configure");
@@ -1779,50 +1533,31 @@ bool cmCTest::AddTestsForDashboardType(std::string &targ)
this->SetTest("Test");
this->SetTest("Coverage");
this->SetTest("Submit");
- }
- else if ( targ == "ExperimentalStart" )
- {
+ } else if (targ == "ExperimentalStart") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Start");
- }
- else if ( targ == "ExperimentalUpdate" )
- {
+ } else if (targ == "ExperimentalUpdate") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Update");
- }
- else if ( targ == "ExperimentalConfigure" )
- {
+ } else if (targ == "ExperimentalConfigure") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Configure");
- }
- else if ( targ == "ExperimentalBuild" )
- {
+ } else if (targ == "ExperimentalBuild") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Build");
- }
- else if ( targ == "ExperimentalTest" )
- {
+ } else if (targ == "ExperimentalTest") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Test");
- }
- else if ( targ == "ExperimentalMemCheck"
- || targ == "ExperimentalPurify" )
- {
+ } else if (targ == "ExperimentalMemCheck" || targ == "ExperimentalPurify") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("MemCheck");
- }
- else if ( targ == "ExperimentalCoverage" )
- {
+ } else if (targ == "ExperimentalCoverage") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Coverage");
- }
- else if ( targ == "ExperimentalSubmit" )
- {
+ } else if (targ == "ExperimentalSubmit") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Submit");
- }
- else if ( targ == "Continuous" )
- {
+ } else if (targ == "Continuous") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Start");
this->SetTest("Update");
@@ -1831,50 +1566,31 @@ bool cmCTest::AddTestsForDashboardType(std::string &targ)
this->SetTest("Test");
this->SetTest("Coverage");
this->SetTest("Submit");
- }
- else if ( targ == "ContinuousStart" )
- {
+ } else if (targ == "ContinuousStart") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Start");
- }
- else if ( targ == "ContinuousUpdate" )
- {
+ } else if (targ == "ContinuousUpdate") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Update");
- }
- else if ( targ == "ContinuousConfigure" )
- {
+ } else if (targ == "ContinuousConfigure") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Configure");
- }
- else if ( targ == "ContinuousBuild" )
- {
+ } else if (targ == "ContinuousBuild") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Build");
- }
- else if ( targ == "ContinuousTest" )
- {
+ } else if (targ == "ContinuousTest") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Test");
- }
- else if ( targ == "ContinuousMemCheck"
- || targ == "ContinuousPurify" )
- {
+ } else if (targ == "ContinuousMemCheck" || targ == "ContinuousPurify") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("MemCheck");
- }
- else if ( targ == "ContinuousCoverage" )
- {
+ } else if (targ == "ContinuousCoverage") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Coverage");
- }
- else if ( targ == "ContinuousSubmit" )
- {
+ } else if (targ == "ContinuousSubmit") {
this->SetTestModel(cmCTest::CONTINUOUS);
this->SetTest("Submit");
- }
- else if ( targ == "Nightly" )
- {
+ } else if (targ == "Nightly") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Start");
this->SetTest("Update");
@@ -1883,50 +1599,31 @@ bool cmCTest::AddTestsForDashboardType(std::string &targ)
this->SetTest("Test");
this->SetTest("Coverage");
this->SetTest("Submit");
- }
- else if ( targ == "NightlyStart" )
- {
+ } else if (targ == "NightlyStart") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Start");
- }
- else if ( targ == "NightlyUpdate" )
- {
+ } else if (targ == "NightlyUpdate") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Update");
- }
- else if ( targ == "NightlyConfigure" )
- {
+ } else if (targ == "NightlyConfigure") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Configure");
- }
- else if ( targ == "NightlyBuild" )
- {
+ } else if (targ == "NightlyBuild") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Build");
- }
- else if ( targ == "NightlyTest" )
- {
+ } else if (targ == "NightlyTest") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Test");
- }
- else if ( targ == "NightlyMemCheck"
- || targ == "NightlyPurify" )
- {
+ } else if (targ == "NightlyMemCheck" || targ == "NightlyPurify") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("MemCheck");
- }
- else if ( targ == "NightlyCoverage" )
- {
+ } else if (targ == "NightlyCoverage") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Coverage");
- }
- else if ( targ == "NightlySubmit" )
- {
+ } else if (targ == "NightlySubmit") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Submit");
- }
- else if ( targ == "MemoryCheck" )
- {
+ } else if (targ == "MemoryCheck") {
this->SetTestModel(cmCTest::EXPERIMENTAL);
this->SetTest("Start");
this->SetTest("Configure");
@@ -1934,9 +1631,7 @@ bool cmCTest::AddTestsForDashboardType(std::string &targ)
this->SetTest("MemCheck");
this->SetTest("Coverage");
this->SetTest("Submit");
- }
- else if ( targ == "NightlyMemoryCheck" )
- {
+ } else if (targ == "NightlyMemoryCheck") {
this->SetTestModel(cmCTest::NIGHTLY);
this->SetTest("Start");
this->SetTest("Update");
@@ -1945,804 +1640,769 @@ bool cmCTest::AddTestsForDashboardType(std::string &targ)
this->SetTest("MemCheck");
this->SetTest("Coverage");
this->SetTest("Submit");
- }
- else
- {
+ } else {
return false;
- }
+ }
return true;
}
-
-//----------------------------------------------------------------------
-void cmCTest::ErrorMessageUnknownDashDValue(std::string &val)
+void cmCTest::ErrorMessageUnknownDashDValue(std::string& val)
{
cmCTestLog(this, ERROR_MESSAGE,
- "CTest -D called with incorrect option: " << val << std::endl);
+ "CTest -D called with incorrect option: " << val << std::endl);
- cmCTestLog(this, ERROR_MESSAGE,
- "Available options are:" << std::endl
- << " ctest -D Continuous" << std::endl
- << " ctest -D Continuous(Start|Update|Configure|Build)" << std::endl
- << " ctest -D Continuous(Test|Coverage|MemCheck|Submit)" << std::endl
- << " ctest -D Experimental" << std::endl
- << " ctest -D Experimental(Start|Update|Configure|Build)" << std::endl
- << " ctest -D Experimental(Test|Coverage|MemCheck|Submit)" << std::endl
- << " ctest -D Nightly" << std::endl
- << " ctest -D Nightly(Start|Update|Configure|Build)" << std::endl
- << " ctest -D Nightly(Test|Coverage|MemCheck|Submit)" << std::endl
- << " ctest -D NightlyMemoryCheck" << std::endl);
+ cmCTestLog(
+ this, ERROR_MESSAGE, "Available options are:"
+ << std::endl
+ << " ctest -D Continuous" << std::endl
+ << " ctest -D Continuous(Start|Update|Configure|Build)" << std::endl
+ << " ctest -D Continuous(Test|Coverage|MemCheck|Submit)" << std::endl
+ << " ctest -D Experimental" << std::endl
+ << " ctest -D Experimental(Start|Update|Configure|Build)" << std::endl
+ << " ctest -D Experimental(Test|Coverage|MemCheck|Submit)" << std::endl
+ << " ctest -D Nightly" << std::endl
+ << " ctest -D Nightly(Start|Update|Configure|Build)" << std::endl
+ << " ctest -D Nightly(Test|Coverage|MemCheck|Submit)" << std::endl
+ << " ctest -D NightlyMemoryCheck" << std::endl);
}
-
-//----------------------------------------------------------------------
bool cmCTest::CheckArgument(const std::string& arg, const char* varg1,
- const char* varg2)
+ const char* varg2)
{
return (varg1 && arg == varg1) || (varg2 && arg == varg2);
}
-
-//----------------------------------------------------------------------
// Processes one command line argument (and its arguments if any)
// for many simple options and then returns
-void cmCTest::HandleCommandLineArguments(size_t &i,
- std::vector<std::string> &args)
+bool cmCTest::HandleCommandLineArguments(size_t& i,
+ std::vector<std::string>& args,
+ std::string& errormsg)
{
std::string arg = args[i];
-
- if(this->CheckArgument(arg, "-F"))
- {
+ if (this->CheckArgument(arg, "-F")) {
this->Failover = true;
- }
- if(this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1)
- {
+ }
+ if (this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1) {
i++;
int plevel = atoi(args[i].c_str());
this->SetParallelLevel(plevel);
this->ParallelLevelSetInCli = true;
- }
- else if(arg.find("-j") == 0)
- {
+ } else if (arg.find("-j") == 0) {
int plevel = atoi(arg.substr(2).c_str());
this->SetParallelLevel(plevel);
this->ParallelLevelSetInCli = true;
+ }
+ if (this->CheckArgument(arg, "--repeat-until-fail")) {
+ if (i >= args.size() - 1) {
+ errormsg = "'--repeat-until-fail' requires an argument";
+ return false;
+ }
+ i++;
+ long repeat = 1;
+ if (!cmSystemTools::StringToLong(args[i].c_str(), &repeat)) {
+ errormsg =
+ "'--repeat-until-fail' given non-integer value '" + args[i] + "'";
+ return false;
}
+ this->RepeatTests = static_cast<int>(repeat);
+ if (repeat > 1) {
+ this->RepeatUntilFail = true;
+ }
+ }
- if(this->CheckArgument(arg, "--no-compress-output"))
- {
- this->CompressTestOutput = false;
- this->CompressMemCheckOutput = false;
+ if (this->CheckArgument(arg, "--test-load") && i < args.size() - 1) {
+ i++;
+ unsigned long load;
+ if (cmSystemTools::StringToULong(args[i].c_str(), &load)) {
+ this->SetTestLoad(load);
+ } else {
+ cmCTestLog(this, WARNING,
+ "Invalid value for 'Test Load' : " << args[i] << std::endl);
}
+ }
- if(this->CheckArgument(arg, "--print-labels"))
- {
+ if (this->CheckArgument(arg, "--no-compress-output")) {
+ this->CompressTestOutput = false;
+ }
+
+ if (this->CheckArgument(arg, "--print-labels")) {
this->PrintLabels = true;
- }
+ }
- if(this->CheckArgument(arg, "--http1.0"))
- {
+ if (this->CheckArgument(arg, "--http1.0")) {
this->UseHTTP10 = true;
- }
+ }
- if(this->CheckArgument(arg, "--timeout") && i < args.size() - 1)
- {
+ if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) {
i++;
double timeout = (double)atof(args[i].c_str());
this->GlobalTimeout = timeout;
- }
+ }
- if(this->CheckArgument(arg, "--stop-time") && i < args.size() - 1)
- {
+ if (this->CheckArgument(arg, "--stop-time") && i < args.size() - 1) {
i++;
this->SetStopTime(args[i]);
- }
+ }
- if(this->CheckArgument(arg, "-C", "--build-config") &&
- i < args.size() - 1)
- {
+ if (this->CheckArgument(arg, "-C", "--build-config") &&
+ i < args.size() - 1) {
i++;
this->SetConfigType(args[i].c_str());
- }
+ }
- if(this->CheckArgument(arg, "--debug"))
- {
+ if (this->CheckArgument(arg, "--debug")) {
this->Debug = true;
this->ShowLineNumbers = true;
- }
- if(this->CheckArgument(arg, "--track") && i < args.size() - 1)
- {
+ }
+ if (this->CheckArgument(arg, "--track") && i < args.size() - 1) {
i++;
this->SpecificTrack = args[i];
- }
- if(this->CheckArgument(arg, "--show-line-numbers"))
- {
+ }
+ if (this->CheckArgument(arg, "--show-line-numbers")) {
this->ShowLineNumbers = true;
- }
- if(this->CheckArgument(arg, "--no-label-summary"))
- {
+ }
+ if (this->CheckArgument(arg, "--no-label-summary")) {
this->LabelSummary = false;
- }
- if(this->CheckArgument(arg, "-Q", "--quiet"))
- {
+ }
+ if (this->CheckArgument(arg, "-Q", "--quiet")) {
this->Quiet = true;
- }
- if(this->CheckArgument(arg, "-V", "--verbose"))
- {
+ }
+ if (this->CheckArgument(arg, "-V", "--verbose")) {
this->Verbose = true;
- }
- if(this->CheckArgument(arg, "-B"))
- {
+ }
+ if (this->CheckArgument(arg, "-B")) {
this->BatchJobs = true;
- }
- if(this->CheckArgument(arg, "-VV", "--extra-verbose"))
- {
+ }
+ if (this->CheckArgument(arg, "-VV", "--extra-verbose")) {
this->ExtraVerbose = true;
this->Verbose = true;
- }
- if(this->CheckArgument(arg, "--output-on-failure"))
- {
+ }
+ if (this->CheckArgument(arg, "--output-on-failure")) {
this->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));
+ }
+ } else {
+ cmCTestLog(this, WARNING,
+ "Invalid value for '--test-output-size-passed': " << args[i]
+ << "\n");
}
-
- if(this->CheckArgument(arg, "-N", "--show-only"))
- {
- this->ShowOnly = true;
+ }
+ if (this->CheckArgument(arg, "--test-output-size-failed") &&
+ 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));
+ }
+ } else {
+ cmCTestLog(this, WARNING,
+ "Invalid value for '--test-output-size-failed': " << args[i]
+ << "\n");
}
+ }
+ if (this->CheckArgument(arg, "-N", "--show-only")) {
+ this->ShowOnly = true;
+ }
- if(this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1 )
- {
+ if (this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1) {
i++;
this->SetOutputLogFileName(args[i].c_str());
- }
+ }
- if(this->CheckArgument(arg, "--tomorrow-tag"))
- {
+ if (this->CheckArgument(arg, "--tomorrow-tag")) {
this->TomorrowTag = true;
- }
- if(this->CheckArgument(arg, "--force-new-ctest-process"))
- {
+ }
+ if (this->CheckArgument(arg, "--force-new-ctest-process")) {
this->ForceNewCTestProcess = true;
- }
- if(this->CheckArgument(arg, "-W", "--max-width") && i < args.size() - 1)
- {
+ }
+ if (this->CheckArgument(arg, "-W", "--max-width") && i < args.size() - 1) {
i++;
this->MaxTestNameWidth = atoi(args[i].c_str());
- }
- if(this->CheckArgument(arg, "--interactive-debug-mode") &&
- i < args.size() - 1 )
- {
+ }
+ if (this->CheckArgument(arg, "--interactive-debug-mode") &&
+ i < args.size() - 1) {
i++;
this->InteractiveDebugMode = cmSystemTools::IsOn(args[i].c_str());
- }
- if(this->CheckArgument(arg, "--submit-index") && i < args.size() - 1 )
- {
+ }
+ if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) {
i++;
this->SubmitIndex = atoi(args[i].c_str());
- if ( this->SubmitIndex < 0 )
- {
+ if (this->SubmitIndex < 0) {
this->SubmitIndex = 0;
- }
}
+ }
- if(this->CheckArgument(arg, "--overwrite") && i < args.size() - 1)
- {
+ if (this->CheckArgument(arg, "--overwrite") && i < args.size() - 1) {
i++;
- this->AddCTestConfigurationOverwrite(args[i].c_str());
- }
- if(this->CheckArgument(arg, "-A", "--add-notes") && i < args.size() - 1)
- {
+ this->AddCTestConfigurationOverwrite(args[i]);
+ }
+ if (this->CheckArgument(arg, "-A", "--add-notes") && i < args.size() - 1) {
this->ProduceXML = true;
this->SetTest("Notes");
i++;
this->SetNotesFiles(args[i].c_str());
- }
+ }
// options that control what tests are run
- if(this->CheckArgument(arg, "-I", "--tests-information") &&
- i < args.size() - 1)
- {
+ 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());
- }
- if(this->CheckArgument(arg, "-U", "--union"))
- {
+ this->GetHandler("memcheck")
+ ->SetPersistentOption("TestsToRunInformation", args[i].c_str());
+ }
+ if (this->CheckArgument(arg, "-U", "--union")) {
this->GetHandler("test")->SetPersistentOption("UseUnion", "true");
this->GetHandler("memcheck")->SetPersistentOption("UseUnion", "true");
- }
- if(this->CheckArgument(arg, "-R", "--tests-regex") && i < args.size() - 1)
- {
+ }
+ 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());
- }
- if(this->CheckArgument(arg, "-L", "--label-regex") && i < args.size() - 1)
- {
+ this->GetHandler("test")->SetPersistentOption("IncludeRegularExpression",
+ args[i].c_str());
+ this->GetHandler("memcheck")
+ ->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());
- }
- if(this->CheckArgument(arg, "-LE", "--label-exclude") && i < args.size() - 1)
- {
+ this->GetHandler("test")->SetPersistentOption("LabelRegularExpression",
+ args[i].c_str());
+ this->GetHandler("memcheck")
+ ->SetPersistentOption("LabelRegularExpression", args[i].c_str());
+ }
+ if (this->CheckArgument(arg, "-LE", "--label-exclude") &&
+ i < args.size() - 1) {
i++;
- this->GetHandler("test")->
- SetPersistentOption("ExcludeLabelRegularExpression", args[i].c_str());
- this->GetHandler("memcheck")->
- SetPersistentOption("ExcludeLabelRegularExpression", args[i].c_str());
- }
+ this->GetHandler("test")->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)
- {
+ 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->GetHandler("test")->SetPersistentOption("ExcludeRegularExpression",
+ args[i].c_str());
+ this->GetHandler("memcheck")
+ ->SetPersistentOption("ExcludeRegularExpression", args[i].c_str());
+ }
+
+ if (this->CheckArgument(arg, "-FA", "--fixture-exclude-any") &&
+ i < args.size() - 1) {
+ i++;
+ this->GetHandler("test")->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(
+ "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(
+ "ExcludeFixtureCleanupRegularExpression", args[i].c_str());
+ this->GetHandler("memcheck")
+ ->SetPersistentOption("ExcludeFixtureCleanupRegularExpression",
+ args[i].c_str());
+ }
+
+ if (this->CheckArgument(arg, "--rerun-failed")) {
+ this->GetHandler("test")->SetPersistentOption("RerunFailed", "true");
+ this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true");
+ }
+ return true;
}
-//----------------------------------------------------------------------
// handle the -S -SR and -SP arguments
-void cmCTest::HandleScriptArguments(size_t &i,
- std::vector<std::string> &args,
- bool &SRArgumentSpecified)
+void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
+ bool& SRArgumentSpecified)
{
std::string arg = args[i];
- if(this->CheckArgument(arg, "-SP", "--script-new-process") &&
- i < args.size() - 1 )
- {
+ if (this->CheckArgument(arg, "-SP", "--script-new-process") &&
+ i < args.size() - 1) {
this->RunConfigurationScript = true;
i++;
- cmCTestScriptHandler* ch
- = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch =
+ static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
// -SR is an internal argument, -SP should be ignored when it is passed
- if (!SRArgumentSpecified)
- {
- ch->AddConfigurationScript(args[i].c_str(),false);
- }
+ if (!SRArgumentSpecified) {
+ ch->AddConfigurationScript(args[i].c_str(), false);
}
+ }
- if(this->CheckArgument(arg, "-SR", "--script-run") &&
- i < args.size() - 1 )
- {
+ if (this->CheckArgument(arg, "-SR", "--script-run") && i < args.size() - 1) {
SRArgumentSpecified = true;
this->RunConfigurationScript = true;
i++;
- cmCTestScriptHandler* ch
- = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
- ch->AddConfigurationScript(args[i].c_str(),true);
- }
+ cmCTestScriptHandler* ch =
+ static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ ch->AddConfigurationScript(args[i].c_str(), true);
+ }
- if(this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1 )
- {
+ if (this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1) {
this->RunConfigurationScript = true;
i++;
- cmCTestScriptHandler* ch
- = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch =
+ static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
// -SR is an internal argument, -S should be ignored when it is passed
- if (!SRArgumentSpecified)
- {
- ch->AddConfigurationScript(args[i].c_str(),true);
- }
+ if (!SRArgumentSpecified) {
+ ch->AddConfigurationScript(args[i].c_str(), true);
}
+ }
}
-//----------------------------------------------------------------------
-bool cmCTest::AddVariableDefinition(const std::string &arg)
+bool cmCTest::AddVariableDefinition(const std::string& arg)
{
std::string name;
std::string value;
- cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
+ cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
- if (cmCacheManager::ParseEntry(arg.c_str(), name, value, type))
- {
+ if (cmake::ParseCacheEntry(arg, name, value, type)) {
this->Definitions[name] = value;
return true;
- }
+ }
return false;
}
-//----------------------------------------------------------------------
// the main entry point of ctest, called from main
-int cmCTest::Run(std::vector<std::string> &args, std::string* output)
+int cmCTest::Run(std::vector<std::string>& args, std::string* output)
{
- this->FindRunningCMake();
const char* ctestExec = "ctest";
bool cmakeAndTest = false;
bool executeTests = true;
bool SRArgumentSpecified = false;
// copy the command line
- for(size_t i=0; i < args.size(); ++i)
- {
- this->InitialCommandLineArguments.push_back(args[i]);
- }
+ this->InitialCommandLineArguments.insert(
+ this->InitialCommandLineArguments.end(), args.begin(), args.end());
// process the command line arguments
- for(size_t i=1; i < args.size(); ++i)
- {
+ for (size_t i = 1; i < args.size(); ++i) {
// handle the simple commandline arguments
- this->HandleCommandLineArguments(i,args);
+ std::string errormsg;
+ if (!this->HandleCommandLineArguments(i, args, errormsg)) {
+ cmSystemTools::Error(errormsg.c_str());
+ return 1;
+ }
// handle the script arguments -S -SR -SP
- this->HandleScriptArguments(i,args,SRArgumentSpecified);
+ this->HandleScriptArguments(i, args, SRArgumentSpecified);
- // handle a request for a dashboard
+ // --dashboard: handle a request for a dashboard
std::string arg = args[i];
- if(this->CheckArgument(arg, "-D", "--dashboard") && i < args.size() - 1 )
- {
+ if (this->CheckArgument(arg, "-D", "--dashboard") && i < args.size() - 1) {
this->ProduceXML = true;
i++;
std::string targ = args[i];
// AddTestsForDashboard parses the dashboard type and converts it
// into the separate stages
- if (!this->AddTestsForDashboardType(targ))
- {
- if (!this->AddVariableDefinition(targ))
- {
+ if (!this->AddTestsForDashboardType(targ)) {
+ if (!this->AddVariableDefinition(targ)) {
this->ErrorMessageUnknownDashDValue(targ);
executeTests = false;
- }
}
}
+ }
// If it's not exactly -D, but it starts with -D, then try to parse out
// a variable definition from it, same as CMake does. Unsuccessful
// 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" && cmSystemTools::StringStartsWith(arg.c_str(), "-D")) {
std::string input = arg.substr(2);
this->AddVariableDefinition(input);
- }
+ }
- if(this->CheckArgument(arg, "-T", "--test-action") &&
- (i < args.size() -1) )
- {
- this->ProduceXML = true;
- i++;
- if ( !this->SetTest(args[i].c_str(), false) )
- {
- executeTests = false;
- cmCTestLog(this, ERROR_MESSAGE,
- "CTest -T called with incorrect option: "
- << args[i].c_str() << std::endl);
- cmCTestLog(this, ERROR_MESSAGE, "Available options are:" << std::endl
- << " " << ctestExec << " -T all" << std::endl
- << " " << ctestExec << " -T start" << std::endl
- << " " << ctestExec << " -T update" << std::endl
- << " " << ctestExec << " -T configure" << std::endl
- << " " << ctestExec << " -T build" << std::endl
- << " " << ctestExec << " -T test" << std::endl
- << " " << ctestExec << " -T coverage" << std::endl
- << " " << ctestExec << " -T memcheck" << std::endl
- << " " << ctestExec << " -T notes" << std::endl
- << " " << ctestExec << " -T submit" << std::endl);
- }
- }
+ // --test-action: calls SetTest(<stage>, /*report=*/ false) to enable
+ // the corresponding stage
+ if (!this->HandleTestActionArgument(ctestExec, i, args)) {
+ executeTests = false;
+ }
- // what type of test model
- if(this->CheckArgument(arg, "-M", "--test-model") &&
- (i < args.size() -1) )
- {
- i++;
- std::string const& str = args[i];
- if ( cmSystemTools::LowerCase(str) == "nightly" )
- {
- this->SetTestModel(cmCTest::NIGHTLY);
- }
- else if ( cmSystemTools::LowerCase(str) == "continuous" )
- {
- this->SetTestModel(cmCTest::CONTINUOUS);
- }
- else if ( cmSystemTools::LowerCase(str) == "experimental" )
- {
- this->SetTestModel(cmCTest::EXPERIMENTAL);
- }
- else
- {
- executeTests = false;
- cmCTestLog(this, ERROR_MESSAGE,
- "CTest -M called with incorrect option: " << str.c_str()
- << std::endl);
- cmCTestLog(this, ERROR_MESSAGE, "Available options are:" << std::endl
- << " " << ctestExec << " -M Continuous" << std::endl
- << " " << ctestExec << " -M Experimental" << std::endl
- << " " << ctestExec << " -M Nightly" << std::endl);
- }
- }
+ // --test-model: what type of test model
+ if (!this->HandleTestModelArgument(ctestExec, i, args)) {
+ executeTests = false;
+ }
- if(this->CheckArgument(arg, "--extra-submit") && i < args.size() - 1)
- {
+ // --extra-submit
+ if (this->CheckArgument(arg, "--extra-submit") && i < args.size() - 1) {
this->ProduceXML = true;
this->SetTest("Submit");
i++;
- if ( !this->SubmitExtraFiles(args[i].c_str()) )
- {
+ if (!this->SubmitExtraFiles(args[i].c_str())) {
return 0;
- }
}
+ }
// --build-and-test options
- if(this->CheckArgument(arg, "--build-and-test") && i < args.size() - 1)
- {
+ if (this->CheckArgument(arg, "--build-and-test") && i < args.size() - 1) {
cmakeAndTest = true;
- }
+ }
- if(this->CheckArgument(arg, "--schedule-random"))
- {
+ // --schedule-random
+ if (this->CheckArgument(arg, "--schedule-random")) {
this->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 (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
+ ++it) {
+ if (!it->second->ProcessCommandLineArguments(arg, i, args)) {
cmCTestLog(this, ERROR_MESSAGE,
- "Problem parsing command line arguments within a handler");
+ "Problem parsing command line arguments within a handler");
return 0;
- }
}
- } // the close of the for argument loop
+ }
+ } // the close of the for argument loop
- if (!this->ParallelLevelSetInCli)
- {
- if (const char *parallel = cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL"))
- {
- int plevel = atoi(parallel);
+ // handle CTEST_PARALLEL_LEVEL environment variable
+ if (!this->ParallelLevelSetInCli) {
+ std::string parallel;
+ if (cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL", parallel)) {
+ int plevel = atoi(parallel.c_str());
this->SetParallelLevel(plevel);
- }
}
+ }
- // now what sould cmake do? if --build-and-test was specified then
+ // now what should cmake do? if --build-and-test was specified then
// we run the build and test handler and return
- if(cmakeAndTest)
- {
- this->Verbose = true;
- cmCTestBuildAndTestHandler* handler =
- static_cast<cmCTestBuildAndTestHandler*>(this->GetHandler("buildtest"));
- int retv = handler->ProcessHandler();
- *output = handler->GetOutput();
-#ifdef CMAKE_BUILD_WITH_CMAKE
- cmDynamicLoader::FlushCache();
-#endif
- if(retv != 0)
- {
- cmCTestLog(this, DEBUG, "build and test failing returning: " << retv
- << std::endl);
- }
- return retv;
- }
-
- if(executeTests)
- {
- int res;
- // call process directory
- if (this->RunConfigurationScript)
- {
- if ( this->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);
- }
- this->GetHandler("script")->SetVerbose(this->Verbose);
- res = this->GetHandler("script")->ProcessHandler();
- if(res != 0)
- {
- cmCTestLog(this, DEBUG, "running script failing returning: " << res
- << std::endl);
- }
+ if (cmakeAndTest) {
+ return this->RunCMakeAndTest(output);
+ }
- }
- 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);
- }
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- if(!this->Initialize(cwd.c_str(), 0))
- {
- res = 12;
- cmCTestLog(this, ERROR_MESSAGE, "Problem initializing the dashboard."
- << std::endl);
- }
- else
- {
- res = this->ProcessTests();
- }
- this->Finalize();
- }
- if(res != 0)
- {
- cmCTestLog(this, DEBUG, "Running a test(s) failed returning : " << res
- << std::endl);
- }
- return res;
- }
+ if (executeTests) {
+ return this->ExecuteTests();
+ }
return 1;
}
-//----------------------------------------------------------------------
-void cmCTest::FindRunningCMake()
+bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i,
+ const std::vector<std::string>& args)
{
- // Find our own executable.
- this->CTestSelf = cmSystemTools::GetExecutableDirectory();
- this->CTestSelf += "/ctest";
- this->CTestSelf += cmSystemTools::GetExecutableExtension();
- if(!cmSystemTools::FileExists(this->CTestSelf.c_str()))
- {
- cmSystemTools::Error("CTest executable cannot be found at ",
- this->CTestSelf.c_str());
+ bool success = true;
+ std::string arg = args[i];
+ if (this->CheckArgument(arg, "-T", "--test-action") &&
+ (i < args.size() - 1)) {
+ this->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:"
+ << std::endl
+ << " " << ctestExec << " -T all" << std::endl
+ << " " << ctestExec << " -T start" << std::endl
+ << " " << ctestExec << " -T update" << std::endl
+ << " " << ctestExec << " -T configure" << std::endl
+ << " " << ctestExec << " -T build" << std::endl
+ << " " << ctestExec << " -T test" << std::endl
+ << " " << ctestExec << " -T coverage" << std::endl
+ << " " << ctestExec << " -T memcheck" << std::endl
+ << " " << ctestExec << " -T notes" << std::endl
+ << " " << ctestExec << " -T submit" << std::endl);
}
+ }
+ return success;
+}
- this->CMakeSelf = cmSystemTools::GetExecutableDirectory();
- this->CMakeSelf += "/cmake";
- this->CMakeSelf += cmSystemTools::GetExecutableExtension();
- if(!cmSystemTools::FileExists(this->CMakeSelf.c_str()))
- {
- cmSystemTools::Error("CMake executable cannot be found at ",
- this->CMakeSelf.c_str());
+bool cmCTest::HandleTestModelArgument(const char* ctestExec, size_t& i,
+ const std::vector<std::string>& args)
+{
+ bool success = true;
+ std::string arg = args[i];
+ if (this->CheckArgument(arg, "-M", "--test-model") &&
+ (i < args.size() - 1)) {
+ i++;
+ std::string const& str = args[i];
+ if (cmSystemTools::LowerCase(str) == "nightly") {
+ this->SetTestModel(cmCTest::NIGHTLY);
+ } else if (cmSystemTools::LowerCase(str) == "continuous") {
+ this->SetTestModel(cmCTest::CONTINUOUS);
+ } else if (cmSystemTools::LowerCase(str) == "experimental") {
+ 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:"
+ << std::endl
+ << " " << ctestExec << " -M Continuous" << std::endl
+ << " " << ctestExec << " -M Experimental" << std::endl
+ << " " << ctestExec << " -M Nightly" << std::endl);
}
+ }
+ return success;
+}
+
+int cmCTest::ExecuteTests()
+{
+ int res;
+ // call process directory
+ if (this->RunConfigurationScript) {
+ if (this->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);
+ }
+ this->GetHandler("script")->SetVerbose(this->Verbose);
+ res = this->GetHandler("script")->ProcessHandler();
+ if (res != 0) {
+ cmCTestLog(this, DEBUG,
+ "running script failing returning: " << res << std::endl);
+ }
+
+ } 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);
+ }
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ if (!this->Initialize(cwd.c_str(), CM_NULLPTR)) {
+ res = 12;
+ cmCTestLog(this, ERROR_MESSAGE, "Problem initializing the dashboard."
+ << std::endl);
+ } else {
+ res = this->ProcessSteps();
+ }
+ this->Finalize();
+ }
+ if (res != 0) {
+ cmCTestLog(this, DEBUG,
+ "Running a test(s) failed returning : " << res << std::endl);
+ }
+ return res;
+}
+
+int cmCTest::RunCMakeAndTest(std::string* output)
+{
+ this->Verbose = true;
+ cmCTestBuildAndTestHandler* handler =
+ static_cast<cmCTestBuildAndTestHandler*>(this->GetHandler("buildtest"));
+ int retv = handler->ProcessHandler();
+ *output = handler->GetOutput();
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmDynamicLoader::FlushCache();
+#endif
+ if (retv != 0) {
+ cmCTestLog(this, DEBUG, "build and test failing returning: " << retv
+ << std::endl);
+ }
+ return retv;
}
-//----------------------------------------------------------------------
void cmCTest::SetNotesFiles(const char* notes)
{
- if ( !notes )
- {
+ if (!notes) {
return;
- }
+ }
this->NotesFiles = notes;
}
-//----------------------------------------------------------------------
-void cmCTest::SetStopTime(std::string time)
+void cmCTest::SetStopTime(std::string const& time)
{
this->StopTime = time;
this->DetermineNextDayStop();
}
-//----------------------------------------------------------------------
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);
+ << dir << std::endl);
std::string fname = dir;
fname += "/CTestCustom.cmake";
- cmCTestLog(this, DEBUG, "* Check for file: "
- << fname.c_str() << std::endl);
- if ( cmSystemTools::FileExists(fname.c_str()) )
- {
+ cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl);
+ if (cmSystemTools::FileExists(fname.c_str())) {
cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
- << fname.c_str() << std::endl);
+ << fname << std::endl);
bool erroroc = cmSystemTools::GetErrorOccuredFlag();
cmSystemTools::ResetErrorOccuredFlag();
- if ( !mf->ReadListFile(0, fname.c_str()) ||
- cmSystemTools::GetErrorOccuredFlag() )
- {
- cmCTestLog(this, ERROR_MESSAGE,
- "Problem reading custom configuration: "
- << fname.c_str() << std::endl);
- }
+ if (!mf->ReadListFile(fname.c_str()) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
+ cmCTestLog(this, ERROR_MESSAGE, "Problem reading custom configuration: "
+ << fname << std::endl);
+ }
found = true;
- if ( erroroc )
- {
+ if (erroroc) {
cmSystemTools::SetErrorOccured();
- }
}
+ }
std::string rexpr = dir;
rexpr += "/CTestCustom.ctest";
- cmCTestLog(this, DEBUG, "* Check for file: "
- << rexpr.c_str() << std::endl);
- if ( !found && cmSystemTools::FileExists(rexpr.c_str()) )
- {
+ cmCTestLog(this, DEBUG, "* Check for file: " << rexpr << std::endl);
+ if (!found && cmSystemTools::FileExists(rexpr.c_str())) {
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 )
- {
+ for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
- << fileIt->c_str() << std::endl);
- if ( !mf->ReadListFile(0, fileIt->c_str()) ||
- cmSystemTools::GetErrorOccuredFlag() )
- {
+ << *fileIt << std::endl);
+ if (!mf->ReadListFile(fileIt->c_str()) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
cmCTestLog(this, ERROR_MESSAGE,
- "Problem reading custom configuration: "
- << fileIt->c_str() << std::endl);
- }
+ "Problem reading custom configuration: " << *fileIt
+ << std::endl);
}
- found = true;
}
+ found = true;
+ }
- if ( found )
- {
+ if (found) {
cmCTest::t_TestingHandlers::iterator it;
- for ( it = this->TestingHandlers.begin();
- it != this->TestingHandlers.end(); ++ it )
- {
+ for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
+ ++it) {
cmCTestLog(this, DEBUG,
- "* Read custom CTest configuration vectors for handler: "
- << it->first.c_str() << " (" << it->second << ")" << std::endl);
+ "* Read custom CTest configuration vectors for handler: "
+ << it->first << " (" << it->second << ")" << std::endl);
it->second->PopulateCustomVectors(mf);
- }
}
+ }
return 1;
}
-//----------------------------------------------------------------------
-void cmCTest::PopulateCustomVector(cmMakefile* mf, const char* def,
- VectorOfStrings& vec)
+void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def,
+ std::vector<std::string>& vec)
{
- if ( !def)
- {
- return;
- }
const char* dval = mf->GetDefinition(def);
- if ( !dval )
- {
+ if (!dval) {
return;
- }
+ }
cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl);
- std::vector<std::string> slist;
- cmSystemTools::ExpandListArgument(dval, slist);
- std::vector<std::string>::iterator it;
vec.clear();
+ cmSystemTools::ExpandListArgument(dval, vec);
- for ( it = slist.begin(); it != slist.end(); ++it )
- {
- cmCTestLog(this, DEBUG, " -- " << it->c_str() << std::endl);
- vec.push_back(it->c_str());
- }
+ for (std::vector<std::string>::const_iterator it = vec.begin();
+ it != vec.end(); ++it) {
+ cmCTestLog(this, DEBUG, " -- " << *it << std::endl);
+ }
}
-//----------------------------------------------------------------------
-void cmCTest::PopulateCustomInteger(cmMakefile* mf, const char* def, int& val)
+void cmCTest::PopulateCustomInteger(cmMakefile* mf, const std::string& def,
+ int& val)
{
- if ( !def)
- {
- return;
- }
const char* dval = mf->GetDefinition(def);
- if ( !dval )
- {
+ if (!dval) {
return;
- }
+ }
val = atoi(dval);
}
-//----------------------------------------------------------------------
std::string cmCTest::GetShortPathToFile(const char* cfname)
{
- const std::string& sourceDir
- = cmSystemTools::CollapseFullPath(
- this->GetCTestConfiguration("SourceDirectory").c_str());
- const std::string& buildDir
- = cmSystemTools::CollapseFullPath(
- this->GetCTestConfiguration("BuildDirectory").c_str());
+ const std::string& sourceDir = cmSystemTools::CollapseFullPath(
+ this->GetCTestConfiguration("SourceDirectory"));
+ const std::string& buildDir = cmSystemTools::CollapseFullPath(
+ this->GetCTestConfiguration("BuildDirectory"));
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.c_str(), fname.c_str());
+ std::string bldRelpath =
+ cmSystemTools::RelativePath(buildDir.c_str(), fname.c_str());
// If any contains "." it is not parent directory
- bool inSrc = srcRelpath.find("..") == srcRelpath.npos;
- bool inBld = bldRelpath.find("..") == bldRelpath.npos;
+ bool inSrc = srcRelpath.find("..") == std::string::npos;
+ bool inBld = bldRelpath.find("..") == std::string::npos;
// TODO: Handle files with .. in their name
- std::string* res = 0;
+ std::string* res = CM_NULLPTR;
- if ( inSrc && inBld )
- {
+ if (inSrc && inBld) {
// If both have relative path with no dots, pick the shorter one
- if ( srcRelpath.size() < bldRelpath.size() )
- {
+ if (srcRelpath.size() < bldRelpath.size()) {
res = &srcRelpath;
- }
- else
- {
+ } else {
res = &bldRelpath;
- }
}
- else if ( inSrc )
- {
+ } else if (inSrc) {
res = &srcRelpath;
- }
- else if ( inBld )
- {
+ } else if (inBld) {
res = &bldRelpath;
- }
+ }
std::string path;
- if ( !res )
- {
+ if (!res) {
path = fname;
- }
- else
- {
+ } else {
cmSystemTools::ConvertToUnixSlashes(*res);
path = "./" + *res;
- if ( path[path.size()-1] == '/' )
- {
- path = path.substr(0, path.size()-1);
- }
+ if (path[path.size() - 1] == '/') {
+ path = path.substr(0, path.size() - 1);
}
+ }
cmsys::SystemTools::ReplaceString(path, ":", "_");
cmsys::SystemTools::ReplaceString(path, " ", "_");
return path;
}
-//----------------------------------------------------------------------
-std::string cmCTest::GetCTestConfiguration(const char *name)
+std::string cmCTest::GetCTestConfiguration(const std::string& name)
{
- if ( this->CTestConfigurationOverwrites.find(name) !=
- this->CTestConfigurationOverwrites.end() )
- {
+ if (this->CTestConfigurationOverwrites.find(name) !=
+ this->CTestConfigurationOverwrites.end()) {
return this->CTestConfigurationOverwrites[name];
- }
+ }
return this->CTestConfiguration[name];
}
-//----------------------------------------------------------------------
void cmCTest::EmptyCTestConfiguration()
{
this->CTestConfiguration.clear();
}
-//----------------------------------------------------------------------
void cmCTest::DetermineNextDayStop()
{
struct tm* lctime;
- time_t current_time = time(0);
+ time_t current_time = time(CM_NULLPTR);
lctime = gmtime(&current_time);
int gm_hour = lctime->tm_hour;
time_t gm_time = mktime(lctime);
@@ -2750,190 +2410,158 @@ void cmCTest::DetermineNextDayStop()
int local_hour = lctime->tm_hour;
int tzone_offset = local_hour - gm_hour;
- if(gm_time > current_time && gm_hour < local_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)
- {
+ } 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(),
+ 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)
- {
+ if (stop_time < current_time) {
this->NextDayStopTime = true;
- }
+ }
}
-//----------------------------------------------------------------------
-void cmCTest::SetCTestConfiguration(const char *name, const char* value)
+void cmCTest::SetCTestConfiguration(const char* name, const char* value,
+ bool suppress)
{
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "SetCTestConfiguration:"
- << name << ":" << (value ? value : "(null)") << "\n");
+ cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT, "SetCTestConfiguration:"
+ << name << ":" << (value ? value : "(null)") << "\n",
+ suppress);
- if ( !name )
- {
+ if (!name) {
return;
- }
- if ( !value )
- {
+ }
+ if (!value) {
this->CTestConfiguration.erase(name);
return;
- }
+ }
this->CTestConfiguration[name] = value;
}
-
-//----------------------------------------------------------------------
std::string cmCTest::GetCurrentTag()
{
return this->CurrentTag;
}
-//----------------------------------------------------------------------
std::string cmCTest::GetBinaryDir()
{
return this->BinaryDir;
}
-//----------------------------------------------------------------------
std::string const& cmCTest::GetConfigType()
{
return this->ConfigType;
}
-//----------------------------------------------------------------------
bool cmCTest::GetShowOnly()
{
return this->ShowOnly;
}
-//----------------------------------------------------------------------
int cmCTest::GetMaxTestNameWidth() const
{
return this->MaxTestNameWidth;
}
-//----------------------------------------------------------------------
void cmCTest::SetProduceXML(bool v)
{
this->ProduceXML = v;
}
-//----------------------------------------------------------------------
bool cmCTest::GetProduceXML()
{
return this->ProduceXML;
}
-//----------------------------------------------------------------------
const char* cmCTest::GetSpecificTrack()
{
- if ( this->SpecificTrack.empty() )
- {
- return 0;
- }
+ if (this->SpecificTrack.empty()) {
+ return CM_NULLPTR;
+ }
return this->SpecificTrack.c_str();
}
-//----------------------------------------------------------------------
void cmCTest::SetSpecificTrack(const char* track)
{
- if ( !track )
- {
+ if (!track) {
this->SpecificTrack = "";
return;
- }
+ }
this->SpecificTrack = track;
}
-//----------------------------------------------------------------------
void cmCTest::AddSubmitFile(Part part, const char* name)
{
this->Parts[part].SubmitFiles.push_back(name);
}
-//----------------------------------------------------------------------
-void cmCTest::AddCTestConfigurationOverwrite(const char* encstr)
+void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr)
{
- std::string overStr = encstr;
- size_t epos = overStr.find("=");
- if ( epos == overStr.npos )
- {
+ size_t epos = overStr.find('=');
+ if (epos == std::string::npos) {
cmCTestLog(this, ERROR_MESSAGE,
- "CTest configuration overwrite specified in the wrong format."
- << std::endl
- << "Valid format is: --overwrite key=value" << std::endl
- << "The specified was: --overwrite " << overStr.c_str() << std::endl);
+ "CTest configuration overwrite specified in the wrong format."
+ << std::endl
+ << "Valid format is: --overwrite key=value" << std::endl
+ << "The specified was: --overwrite " << overStr << std::endl);
return;
- }
+ }
std::string key = overStr.substr(0, epos);
- std::string value = overStr.substr(epos+1, overStr.npos);
+ std::string value = overStr.substr(epos + 1);
this->CTestConfigurationOverwrites[key] = value;
}
-//----------------------------------------------------------------------
void cmCTest::SetConfigType(const char* ct)
{
- this->ConfigType = ct?ct:"";
+ this->ConfigType = ct ? ct : "";
cmSystemTools::ReplaceString(this->ConfigType, ".\\", "");
- std::string confTypeEnv
- = "CMAKE_CONFIG_TYPE=" + this->ConfigType;
- cmSystemTools::PutEnv(confTypeEnv.c_str());
+ std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->ConfigType;
+ cmSystemTools::PutEnv(confTypeEnv);
}
-//----------------------------------------------------------------------
-bool cmCTest::SetCTestConfigurationFromCMakeVariable(cmMakefile* mf,
- const char* dconfig, const char* cmake_var)
+bool cmCTest::SetCTestConfigurationFromCMakeVariable(
+ cmMakefile* mf, const char* dconfig, const std::string& cmake_var,
+ bool suppress)
{
const char* ctvar;
ctvar = mf->GetDefinition(cmake_var);
- if ( !ctvar )
- {
+ if (!ctvar) {
return false;
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- "SetCTestConfigurationFromCMakeVariable:"
- << dconfig << ":" << cmake_var << std::endl);
- this->SetCTestConfiguration(dconfig, ctvar);
+ }
+ cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT,
+ "SetCTestConfigurationFromCMakeVariable:"
+ << dconfig << ":" << cmake_var << std::endl,
+ suppress);
+ this->SetCTestConfiguration(dconfig, ctvar, suppress);
return true;
}
-bool cmCTest::RunCommand(
- const char* command,
- std::string* stdOut,
- std::string* stdErr,
- int *retVal,
- const char* dir,
- double timeout)
+bool cmCTest::RunCommand(const char* command, std::string* stdOut,
+ std::string* stdErr, int* retVal, const char* dir,
+ double timeout, Encoding encoding)
{
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
+ std::vector<std::string> args = cmSystemTools::ParseArguments(command);
- if(args.size() < 1)
- {
+ if (args.empty()) {
return false;
- }
+ }
std::vector<const char*> argv;
- for(std::vector<cmStdString>::const_iterator a = args.begin();
- a != args.end(); ++a)
- {
+ for (std::vector<std::string>::const_iterator a = args.begin();
+ a != args.end(); ++a) {
argv.push_back(a->c_str());
- }
- argv.push_back(0);
+ }
+ argv.push_back(CM_NULLPTR);
*stdOut = "";
*stdErr = "";
@@ -2941,10 +2569,9 @@ bool cmCTest::RunCommand(
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, &*argv.begin());
cmsysProcess_SetWorkingDirectory(cp, dir);
- if(cmSystemTools::GetRunCommandHideConsole())
- {
+ if (cmSystemTools::GetRunCommandHideConsole()) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- }
+ }
cmsysProcess_SetTimeout(cp, timeout);
cmsysProcess_Execute(cp);
@@ -2952,119 +2579,99 @@ bool cmCTest::RunCommand(
std::vector<char> tempError;
char* data;
int length;
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
int res;
bool done = false;
- while(!done)
- {
- res = cmsysProcess_WaitForData(cp, &data, &length, 0);
- switch ( res )
- {
- case cmsysProcess_Pipe_STDOUT:
- tempOutput.insert(tempOutput.end(), data, data+length);
- break;
- case cmsysProcess_Pipe_STDERR:
- tempError.insert(tempError.end(), data, data+length);
- break;
- default:
- done = true;
- }
- if ( (res == cmsysProcess_Pipe_STDOUT ||
- res == cmsysProcess_Pipe_STDERR) && this->ExtraVerbose )
- {
- cmSystemTools::Stdout(data, length);
- }
+ while (!done) {
+ res = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR);
+ switch (res) {
+ case cmsysProcess_Pipe_STDOUT:
+ tempOutput.insert(tempOutput.end(), data, data + length);
+ break;
+ case cmsysProcess_Pipe_STDERR:
+ tempError.insert(tempError.end(), data, data + length);
+ break;
+ default:
+ done = true;
+ }
+ if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) &&
+ this->ExtraVerbose) {
+ processOutput.DecodeText(data, length, strdata);
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ }
+ }
+ if (this->ExtraVerbose) {
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
}
+ }
- cmsysProcess_WaitForExit(cp, 0);
- if ( tempOutput.size() > 0 )
- {
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ if (!tempOutput.empty()) {
+ processOutput.DecodeText(tempOutput, tempOutput);
stdOut->append(&*tempOutput.begin(), tempOutput.size());
- }
- if ( tempError.size() > 0 )
- {
+ }
+ if (!tempError.empty()) {
+ processOutput.DecodeText(tempError, tempError);
stdErr->append(&*tempError.begin(), tempError.size());
- }
+ }
bool result = true;
- if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
- {
- if ( retVal )
- {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
+ if (retVal) {
*retVal = cmsysProcess_GetExitValue(cp);
- }
- else
- {
- if ( cmsysProcess_GetExitValue(cp) != 0 )
- {
+ } else {
+ if (cmsysProcess_GetExitValue(cp) != 0) {
result = false;
- }
}
}
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) {
const char* exception_str = cmsysProcess_GetExceptionString(cp);
cmCTestLog(this, ERROR_MESSAGE, exception_str << std::endl);
stdErr->append(exception_str, strlen(exception_str));
result = false;
- }
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
const char* error_str = cmsysProcess_GetErrorString(cp);
cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
stdErr->append(error_str, strlen(error_str));
result = false;
- }
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
const char* error_str = "Process terminated due to timeout\n";
cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
stdErr->append(error_str, strlen(error_str));
result = false;
- }
+ }
cmsysProcess_Delete(cp);
return result;
}
-//----------------------------------------------------------------------
void cmCTest::SetOutputLogFileName(const char* name)
{
- if ( this->OutputLogFile)
- {
+ if (this->OutputLogFile) {
delete this->OutputLogFile;
- this->OutputLogFile= 0;
- }
- if ( name )
- {
+ this->OutputLogFile = CM_NULLPTR;
+ }
+ if (name) {
this->OutputLogFile = new cmGeneratedFileStream(name);
- }
+ }
}
-//----------------------------------------------------------------------
-static const char* cmCTestStringLogType[] =
-{
- "DEBUG",
- "OUTPUT",
- "HANDLER_OUTPUT",
- "HANDLER_VERBOSE_OUTPUT",
- "WARNING",
- "ERROR_MESSAGE",
- 0
-};
+static const char* cmCTestStringLogType[] = { "DEBUG",
+ "OUTPUT",
+ "HANDLER_OUTPUT",
+ "HANDLER_PROGRESS_OUTPUT",
+ "HANDLER_VERBOSE_OUTPUT",
+ "WARNING",
+ "ERROR_MESSAGE",
+ CM_NULLPTR };
-//----------------------------------------------------------------------
-#ifdef cerr
-# undef cerr
-#endif
-#ifdef cout
-# undef cout
-#endif
-
-#define cmCTestLogOutputFileLine(stream) \
- if ( this->ShowLineNumbers ) \
- { \
- (stream) << std::endl << file << ":" << line << " "; \
- }
+#define cmCTestLogOutputFileLine(stream) \
+ if (this->ShowLineNumbers) { \
+ (stream) << std::endl << file << ":" << line << " "; \
+ }
void cmCTest::InitStreams()
{
@@ -3073,167 +2680,153 @@ void cmCTest::InitStreams()
this->StreamErr = &std::cerr;
}
-void cmCTest::Log(int logType, const char* file, int line, const char* msg)
+void cmCTest::Log(int logType, const char* file, int line, const char* msg,
+ bool suppress)
{
- if ( !msg || !*msg )
- {
+ if (!msg || !*msg) {
return;
- }
- if ( this->OutputLogFile )
- {
+ }
+ if (suppress && logType != cmCTest::ERROR_MESSAGE) {
+ return;
+ }
+ if (logType == cmCTest::HANDLER_PROGRESS_OUTPUT &&
+ (this->Debug || this->ExtraVerbose)) {
+ return;
+ }
+ if (this->OutputLogFile) {
bool display = true;
- if ( logType == cmCTest::DEBUG && !this->Debug ) { display = false; }
- if ( logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Debug &&
- !this->ExtraVerbose ) { display = false; }
- if ( display )
- {
+ if (logType == cmCTest::DEBUG && !this->Debug) {
+ display = false;
+ }
+ if (logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Debug &&
+ !this->ExtraVerbose) {
+ display = false;
+ }
+ if (display) {
cmCTestLogOutputFileLine(*this->OutputLogFile);
- if ( logType != this->OutputLogFileLastTag )
- {
+ if (logType != this->OutputLogFileLastTag) {
*this->OutputLogFile << "[";
- if ( logType >= OTHER || logType < 0 )
- {
+ if (logType >= OTHER || logType < 0) {
*this->OutputLogFile << "OTHER";
- }
- else
- {
+ } else {
*this->OutputLogFile << cmCTestStringLogType[logType];
- }
- *this->OutputLogFile << "] " << std::endl << std::flush;
}
+ *this->OutputLogFile << "] " << std::endl << std::flush;
+ }
*this->OutputLogFile << msg << std::flush;
- if ( logType != this->OutputLogFileLastTag )
- {
+ if (logType != this->OutputLogFileLastTag) {
*this->OutputLogFile << std::endl << std::flush;
this->OutputLogFileLastTag = logType;
- }
}
}
- if ( !this->Quiet )
- {
+ }
+ if (!this->Quiet) {
std::ostream& out = *this->StreamOut;
std::ostream& err = *this->StreamErr;
- switch ( logType )
- {
- case DEBUG:
- if ( this->Debug )
- {
- cmCTestLogOutputFileLine(out);
- out << msg;
- out.flush();
+ switch (logType) {
+ case DEBUG:
+ if (this->Debug) {
+ cmCTestLogOutputFileLine(out);
+ out << msg;
+ out.flush();
}
- break;
- case OUTPUT: case HANDLER_OUTPUT:
- if ( this->Debug || this->Verbose )
- {
- cmCTestLogOutputFileLine(out);
- out << msg;
- out.flush();
+ break;
+ case OUTPUT:
+ case HANDLER_OUTPUT:
+ if (this->Debug || this->Verbose) {
+ cmCTestLogOutputFileLine(out);
+ out << msg;
+ out.flush();
}
- break;
- case HANDLER_VERBOSE_OUTPUT:
- if ( this->Debug || this->ExtraVerbose )
- {
+ break;
+ case HANDLER_VERBOSE_OUTPUT:
+ if (this->Debug || this->ExtraVerbose) {
+ cmCTestLogOutputFileLine(out);
+ out << msg;
+ out.flush();
+ }
+ break;
+ case WARNING:
+ cmCTestLogOutputFileLine(err);
+ err << msg;
+ err.flush();
+ break;
+ case ERROR_MESSAGE:
+ cmCTestLogOutputFileLine(err);
+ err << msg;
+ err.flush();
+ cmSystemTools::SetErrorOccured();
+ break;
+ default:
cmCTestLogOutputFileLine(out);
out << msg;
out.flush();
- }
- break;
- case WARNING:
- cmCTestLogOutputFileLine(err);
- err << msg;
- err.flush();
- break;
- case ERROR_MESSAGE:
- cmCTestLogOutputFileLine(err);
- err << msg;
- err.flush();
- cmSystemTools::SetErrorOccured();
- break;
- default:
- cmCTestLogOutputFileLine(out);
- out << msg;
- out.flush();
- }
}
+ }
}
-//-------------------------------------------------------------------------
double cmCTest::GetRemainingTimeAllowed()
{
- if (!this->GetHandler("script"))
- {
+ if (!this->GetHandler("script")) {
return 1.0e7;
- }
+ }
- cmCTestScriptHandler* ch
- = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch =
+ static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
return ch->GetRemainingTimeAllowed();
}
-//----------------------------------------------------------------------
-void cmCTest::OutputTestErrors(std::vector<char> const &process_output)
+void cmCTest::OutputTestErrors(std::vector<char> const& process_output)
{
std::string test_outputs("\n*** Test Failed:\n");
- if(process_output.size())
- {
+ if (!process_output.empty()) {
test_outputs.append(&*process_output.begin(), process_output.size());
- }
+ }
cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush);
}
-//----------------------------------------------------------------------
bool cmCTest::CompressString(std::string& str)
{
int ret;
z_stream strm;
- unsigned char* in = reinterpret_cast<unsigned char*>(
- const_cast<char*>(str.c_str()));
- //zlib makes the guarantee that this is the maximum output size
- int outSize = static_cast<int>(
- static_cast<double>(str.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;
+ ret = deflateInit(&strm, -1); // default compression level
+ if (ret != Z_OK) {
return false;
- }
+ }
+
+ unsigned char* in =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(str.c_str()));
+ // zlib makes the guarantee that this is the maximum output size
+ int outSize =
+ static_cast<int>(static_cast<double>(str.size()) * 1.001 + 13.0);
+ std::vector<unsigned char> out(outSize);
strm.avail_in = static_cast<uInt>(str.size());
strm.next_in = in;
strm.avail_out = outSize;
- strm.next_out = out;
+ strm.next_out = &out[0];
ret = deflate(&strm, Z_FINISH);
- if(ret == Z_STREAM_ERROR || ret != Z_STREAM_END)
- {
+ if (ret != Z_STREAM_END) {
cmCTestLog(this, ERROR_MESSAGE, "Error during gzip compression."
- << std::endl);
- delete[] out;
+ << std::endl);
return false;
- }
+ }
(void)deflateEnd(&strm);
// Now base64 encode the resulting binary string
- unsigned char* base64EncodedBuffer
- = new unsigned char[static_cast<int>(outSize * 1.5)];
-
- unsigned long rlen
- = cmsysBase64_Encode(out, strm.total_out, base64EncodedBuffer, 1);
+ std::vector<unsigned char> base64EncodedBuffer((outSize * 3) / 2);
- str = "";
- str.append(reinterpret_cast<char*>(base64EncodedBuffer), rlen);
+ size_t rlen =
+ cmsysBase64_Encode(&out[0], strm.total_out, &base64EncodedBuffer[0], 1);
- delete [] base64EncodedBuffer;
- delete [] out;
+ str.assign(reinterpret_cast<char*>(&base64EncodedBuffer[0]), rlen);
return true;
}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 5dd35ce41..60f3295e7 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -1,53 +1,39 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCTest_h
#define cmCTest_h
-#include "cmStandardIncludes.h"
-#include "cmListFileCache.h"
+#include "cmConfigure.h"
+
+#include "cmProcessOutput.h"
+#include "cmsys/String.hxx"
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
#include <time.h>
+#include <vector>
-class cmake;
-class cmMakefile;
class cmCTestGenericHandler;
-class cmGeneratedFileStream;
-class cmCTestCommand;
-class cmCTestScriptHandler;
class cmCTestStartCommand;
-
-#define cmCTestLog(ctSelf, logType, msg) \
- do { \
- cmOStringStream cmCTestLog_msg; \
- cmCTestLog_msg << msg; \
- (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__,\
- cmCTestLog_msg.str().c_str());\
- } while ( 0 )
-
-#ifdef cerr
-# undef cerr
-#endif
-#define cerr no_cerr_use_cmCTestLog
-
-#ifdef cout
-# undef cout
-#endif
-#define cout no_cout_use_cmCTestLog
-
+class cmGeneratedFileStream;
+class cmMakefile;
+class cmXMLWriter;
+
+/** \class cmCTest
+ * \brief Represents a ctest invocation.
+ *
+ * This class represents a ctest invocation. It is the top level class when
+ * running ctest.
+ *
+ */
class cmCTest
{
friend class cmCTestRunTest;
friend class cmCTestMultiProcessHandler;
+
public:
+ typedef cmProcessOutput::Encoding Encoding;
/** Enumerate parts of the testing and submission process. */
enum Part
{
@@ -68,21 +54,26 @@ public:
/** Representation of one part. */
struct PartInfo
{
- PartInfo(): Enabled(false) {}
+ PartInfo()
+ : Enabled(false)
+ {
+ }
- void SetName(const char* name) { this->Name = name; }
- const char* GetName() const { return this->Name.c_str(); }
+ 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 {
+ enum HTTPMethod
+ {
HTTP_GET,
HTTP_POST,
HTTP_PUT
@@ -92,20 +83,19 @@ public:
* Perform an HTTP request.
*/
static int HTTPRequest(std::string url, HTTPMethod method,
- std::string& response,
- std::string fields = "",
- std::string putFile = "", int timeout = 0);
+ 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<cmStdString> VectorOfStrings;
- typedef std::set<cmStdString> SetOfStrings;
+ 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 = 0);
+ /** Process Command line arguments */
+ int Run(std::vector<std::string>&, std::string* output = CM_NULLPTR);
/**
* Initialize and finalize testing
@@ -114,44 +104,53 @@ public:
void Finalize();
/**
- * Process the tests. This is the main routine. The execution of the
- * tests should look like this:
+ * Process the dashboard client steps.
*
+ * Steps are enabled using SetTest()
+ *
+ * The execution of the steps (or #Part) should look like this:
+ *
+ * /code
* ctest foo;
* foo.Initialize();
* // Set some things on foo
- * foo.ProcessTests();
+ * foo.ProcessSteps();
* foo.Finalize();
+ * /endcode
+ *
+ * \sa Initialize(), Finalize(), Part, PartInfo, SetTest()
*/
- int ProcessTests();
+ int ProcessSteps();
- /*
+ /**
* A utility function that returns the nightly time
*/
- struct tm* GetNightlyTime(std::string str,
- bool tomorrowtag);
+ struct tm* GetNightlyTime(std::string const& str, bool tomorrowtag);
- /*
+ /**
* Is the tomorrow tag set?
*/
- bool GetTomorrowTag() { return this->TomorrowTag; };
+ bool GetTomorrowTag() { return this->TomorrowTag; }
/**
* Try to run tests of the project
*/
int TestDirectory(bool memcheck);
- ///! what is the configuraiton type, e.g. Debug, Release etc.
+ /** what is the configuraiton type, e.g. Debug, Release etc. */
std::string const& GetConfigType();
double GetTimeOut() { return this->TimeOut; }
void SetTimeOut(double t) { this->TimeOut = t; }
double GetGlobalTimeout() { return this->GlobalTimeout; }
- // how many test to run at the same time
+ /** how many test to run at the same time */
int GetParallelLevel() { return this->ParallelLevel; }
void SetParallelLevel(int);
+ unsigned long GetTestLoad() { return this->TestLoad; }
+ void SetTestLoad(unsigned long);
+
/**
* Check if CTest file exists
*/
@@ -167,13 +166,14 @@ public:
* Set the cmake test mode (experimental, nightly, continuous).
*/
void SetTestModel(int mode);
- int GetTestModel() { return this->TestModel; };
+ int GetTestModel() { return this->TestModel; }
std::string GetTestModelString();
static int GetTestModelFromString(const char* str);
static std::string CleanString(const std::string& str);
- std::string GetCTestConfiguration(const char *name);
- void SetCTestConfiguration(const char *name, const char* value);
+ std::string GetCTestConfiguration(const std::string& name);
+ void SetCTestConfiguration(const char* name, const char* value,
+ bool suppress = false);
void EmptyCTestConfiguration();
/**
@@ -182,21 +182,20 @@ public:
cmCTest();
~cmCTest();
- //! Set the notes files to be created.
+ /** Set the notes files to be created. */
void SetNotesFiles(const char* notes);
- void PopulateCustomVector(cmMakefile* mf, const char* definition,
- VectorOfStrings& vec);
- void PopulateCustomInteger(cmMakefile* mf, const char* def,
- int& val);
+ void PopulateCustomVector(cmMakefile* mf, const std::string& definition,
+ std::vector<std::string>& vec);
+ void PopulateCustomInteger(cmMakefile* mf, const std::string& def, int& val);
- ///! Get the current time as string
+ /** Get the current time as string */
std::string CurrentTime();
- //! tar/gzip and then base 64 encode a file
- std::string Base64GzipEncodeFile(std::string file);
- //! base64 encode a file
- std::string Base64EncodeFile(std::string file);
+ /** tar/gzip and then base 64 encode a file */
+ std::string Base64GzipEncodeFile(std::string const& file);
+ /** base64 encode a file */
+ std::string Base64EncodeFile(std::string const& file);
/**
* Return the time remaining that the script is allowed to run in
@@ -205,13 +204,13 @@ public:
*/
double GetRemainingTimeAllowed();
- ///! Open file in the output directory and set the stream
- bool OpenOutputFile(const std::string& path,
- const std::string& name,
- cmGeneratedFileStream& stream,
- bool compress = false);
+ /**
+ * Open file in the output directory and set the stream
+ */
+ bool OpenOutputFile(const std::string& path, const std::string& name,
+ cmGeneratedFileStream& stream, bool compress = false);
- ///! Should we only show what we would do?
+ /** Should we only show what we would do? */
bool GetShowOnly();
bool ShouldUseHTTP10() { return this->UseHTTP10; }
@@ -219,21 +218,18 @@ public:
bool ShouldPrintLabels() { return this->PrintLabels; }
bool ShouldCompressTestOutput();
- bool ShouldCompressMemCheckOutput();
bool CompressString(std::string& str);
- std::string GetCDashVersion();
-
std::string GetStopTime() { return this->StopTime; }
- void SetStopTime(std::string time);
+ void SetStopTime(std::string const& time);
- //Used for parallel ctest job scheduling
+ /** Used for parallel ctest job scheduling */
std::string GetScheduleType() { return this->ScheduleType; }
- void SetScheduleType(std::string type) { this->ScheduleType = type; }
+ void SetScheduleType(std::string const& type) { this->ScheduleType = type; }
- ///! The max output width
+ /** The max output width */
int GetMaxTestNameWidth() const;
- void SetMaxTestNameWidth(int w) { this->MaxTestNameWidth = w;}
+ void SetMaxTestNameWidth(int w) { this->MaxTestNameWidth = w; }
/**
* Run a single executable command and put the stdout and stderr
@@ -255,70 +251,78 @@ public:
* 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 = 0, const char* dir = 0, double timeout = 0.0);
+ bool RunCommand(const char* command, std::string* stdOut,
+ std::string* stdErr, int* retVal = CM_NULLPTR,
+ const char* dir = CM_NULLPTR, double timeout = 0.0,
+ Encoding encoding = cmProcessOutput::Auto);
- //! Clean/make safe for xml the given value such that it may be used as
- // one of the key fields by CDash when computing the buildid.
+ /**
+ * Clean/make safe for xml the given value such that it may be used as
+ * one of the key fields by CDash when computing the buildid.
+ */
static std::string SafeBuildIdField(const std::string& value);
- //! Start CTest XML output file
- void StartXML(std::ostream& ostr, bool append);
-
- //! End CTest XML output file
- void EndXML(std::ostream& ostr);
+ /** Start CTest XML output file */
+ void StartXML(cmXMLWriter& xml, bool append);
- //! 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::ofstream& ofs);
+ /** End CTest XML output file */
+ void EndXML(cmXMLWriter& xml);
- /*
- * return the current tag
+ /**
+ * 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,
+ Encoding encoding = cmProcessOutput::Auto);
+
+ /** Return the current tag */
std::string GetCurrentTag();
- //! Get the path to the build tree
+ /** Get the path to the build tree */
std::string GetBinaryDir();
- //! Get the short path to the file. This means if the file is in binary or
- //source directory, it will become /.../relative/path/to/file
+ /**
+ * Get the short path to the file.
+ *
+ * This means if the file is in binary or
+ * source directory, it will become /.../relative/path/to/file
+ */
std::string GetShortPathToFile(const char* fname);
- //! Get the path to CTest
- const char* GetCTestExecutable() { return this->CTestSelf.c_str(); }
- const char* GetCMakeExecutable() { return this->CMakeSelf.c_str(); }
-
- enum {
+ enum
+ {
EXPERIMENTAL,
NIGHTLY,
CONTINUOUS
};
- // provide some more detailed info on the return code for ctest
- enum {
- UPDATE_ERRORS = 0x01,
+ /** provide some more detailed info on the return code for ctest */
+ enum
+ {
+ UPDATE_ERRORS = 0x01,
CONFIGURE_ERRORS = 0x02,
- BUILD_ERRORS = 0x04,
- TEST_ERRORS = 0x08,
- MEMORY_ERRORS = 0x10,
- COVERAGE_ERRORS = 0x20,
- SUBMIT_ERRORS = 0x40
+ BUILD_ERRORS = 0x04,
+ TEST_ERRORS = 0x08,
+ MEMORY_ERRORS = 0x10,
+ COVERAGE_ERRORS = 0x20,
+ SUBMIT_ERRORS = 0x40
};
- ///! Are we producing XML
+ /** Are we producing XML */
bool GetProduceXML();
void SetProduceXML(bool v);
- //! Run command specialized for tests. Returns process status and retVal is
- // return value or exception. If environment is non-null, it is used to set
- // environment variables prior to running the test. After running the test,
- // 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::vector<std::string>* environment);
+ /**
+ * Run command specialized for tests. Returns process status and retVal is
+ * return value or exception. If environment is non-null, it is used to set
+ * environment variables prior to running the test. After running the test,
+ * 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::vector<std::string>* environment,
+ Encoding encoding = cmProcessOutput::Auto);
/**
* Execute handler and return its result. If the handler fails, it returns
@@ -326,79 +330,95 @@ public:
*/
int ExecuteHandler(const char* handler);
- /*
+ /**
* Get the handler object
*/
cmCTestGenericHandler* GetHandler(const char* handler);
cmCTestGenericHandler* GetInitializedHandler(const char* handler);
- /*
+ /**
* Set the CTest variable from CMake variable
*/
bool SetCTestConfigurationFromCMakeVariable(cmMakefile* mf,
- const char* dconfig, const char* cmake_var);
+ const char* dconfig,
+ const std::string& cmake_var,
+ bool suppress = false);
- //! Make string safe to be send as an URL
+ /** 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&);
- //! Should ctect configuration be updated. When using new style ctest
- // script, this should be true.
+ /**
+ * Should ctect configuration be updated. When using new style ctest
+ * script, this should be true.
+ */
void SetSuppressUpdatingCTestConfiguration(bool val)
- {
+ {
this->SuppressUpdatingCTestConfiguration = val;
- }
+ }
- //! Add overwrite to ctest configuration.
- // The format is key=value
- void AddCTestConfigurationOverwrite(const char* encstr);
+ /**
+ * Add overwrite to ctest configuration.
+ *
+ * The format is key=value
+ */
+ void AddCTestConfigurationOverwrite(const std::string& encstr);
- //! Create XML file that contains all the notes specified
- int GenerateNotesFile(const std::vector<cmStdString> &files);
+ /** Create XML file that contains all the notes specified */
+ int GenerateNotesFile(const VectorOfStrings& files);
- //! Submit extra files to the server
+ /** Submit extra files to the server */
bool SubmitExtraFiles(const char* files);
- bool SubmitExtraFiles(const std::vector<cmStdString> &files);
+ bool SubmitExtraFiles(const VectorOfStrings& files);
- //! Set the output log file name
+ /** Set the output log file name */
void SetOutputLogFileName(const char* name);
- //! Set the visual studio or Xcode config type
+ /** Set the visual studio or Xcode config type */
void SetConfigType(const char* ct);
- //! Various log types
- enum {
+ /** Various log types */
+ enum
+ {
DEBUG = 0,
OUTPUT,
HANDLER_OUTPUT,
+ HANDLER_PROGRESS_OUTPUT,
HANDLER_VERBOSE_OUTPUT,
WARNING,
ERROR_MESSAGE,
OTHER
};
- //! Add log to the output
- void Log(int logType, const char* file, int line, const char* msg);
+ /** Add log to the output */
+ void Log(int logType, const char* file, int line, const char* msg,
+ bool suppress = false);
- //! Get the version of dart server
+ /** Get the version of dart server */
int GetDartVersion() { return this->DartVersion; }
int GetDropSiteCDash() { return this->DropSiteCDash; }
- //! Add file to be submitted
+ /** 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; }
+ {
+ return this->Parts[part].SubmitFiles;
+ }
void ClearSubmitFiles(Part part) { this->Parts[part].SubmitFiles.clear(); }
- //! Read the custom configuration files and apply them to the current ctest
+ /**
+ * Read the custom configuration files and apply them to the current ctest
+ */
int ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf);
- std::vector<cmStdString> &GetInitialCommandLineArguments()
- { return this->InitialCommandLineArguments; };
+ std::vector<std::string>& GetInitialCommandLineArguments()
+ {
+ return this->InitialCommandLineArguments;
+ }
- //! Set the track to submit to
+ /** Set the track to submit to */
void SetSpecificTrack(const char* track);
const char* GetSpecificTrack();
@@ -408,23 +428,34 @@ public:
void SetBatchJobs(bool batch = true) { this->BatchJobs = batch; }
bool GetBatchJobs() { return this->BatchJobs; }
- bool GetVerbose() { return this->Verbose;}
- bool GetExtraVerbose() { return this->ExtraVerbose;}
+ bool GetVerbose() { return this->Verbose; }
+ bool GetExtraVerbose() { return this->ExtraVerbose; }
/** Direct process output to given streams. */
void SetStreams(std::ostream* out, std::ostream* err)
- { this->StreamOut = out; this->StreamErr = err; }
- void AddSiteProperties(std::ostream& );
- bool GetLabelSummary() { return this->LabelSummary;}
+ {
+ this->StreamOut = out;
+ this->StreamErr = err;
+ }
+ void AddSiteProperties(cmXMLWriter& xml);
+ bool GetLabelSummary() { return this->LabelSummary; }
std::string GetCostDataFile();
- const std::map<std::string, std::string> &GetDefinitions()
- {
+ const std::map<std::string, std::string>& GetDefinitions()
+ {
return this->Definitions;
- }
+ }
+
+ /** Return the number of times a test should be run */
+ int GetTestRepeat() { return this->RepeatTests; }
+
+ /** 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;
@@ -442,68 +473,62 @@ private:
bool RunConfigurationScript;
- //flag for lazy getter (optimization)
- bool ComputedCompressTestOutput;
- bool ComputedCompressMemCheckOutput;
-
int GenerateNotesFile(const char* files);
void DetermineNextDayStop();
// these are helper classes
- typedef std::map<cmStdString,cmCTestGenericHandler*> t_TestingHandlers;
+ typedef std::map<std::string, cmCTestGenericHandler*> t_TestingHandlers;
t_TestingHandlers TestingHandlers;
bool ShowOnly;
- //! Map of configuration properties
- typedef std::map<cmStdString, cmStdString> CTestConfigurationMap;
+ /** Map of configuration properties */
+ typedef std::map<std::string, std::string> CTestConfigurationMap;
- std::string CTestConfigFile;
+ 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<cmStdString, Part> PartMapType;
- PartMapType PartMap;
+ PartInfo Parts[PartCount];
+ typedef std::map<std::string, Part> PartMapType;
+ PartMapType PartMap;
- std::string CurrentTag;
- bool TomorrowTag;
+ std::string CurrentTag;
+ bool TomorrowTag;
- int TestModel;
- std::string SpecificTrack;
+ int TestModel;
+ std::string SpecificTrack;
- double TimeOut;
+ double TimeOut;
- double GlobalTimeout;
+ double GlobalTimeout;
- int LastStopTimeout;
+ int LastStopTimeout;
- int MaxTestNameWidth;
+ int MaxTestNameWidth;
- int ParallelLevel;
- bool ParallelLevelSetInCli;
+ int ParallelLevel;
+ bool ParallelLevelSetInCli;
- int CompatibilityMode;
+ unsigned long TestLoad;
- // information for the --build-and-test options
- std::string CMakeSelf;
- std::string CTestSelf;
- std::string BinaryDir;
+ int CompatibilityMode;
- std::string NotesFiles;
+ // information for the --build-and-test options
+ std::string BinaryDir;
+ std::string NotesFiles;
- bool InteractiveDebugMode;
+ bool InteractiveDebugMode;
- bool ShortDateFormat;
+ bool ShortDateFormat;
- bool CompressXMLFiles;
- bool CompressTestOutput;
- bool CompressMemCheckOutput;
+ bool CompressXMLFiles;
+ bool CompressTestOutput;
void InitStreams();
std::ostream* StreamOut;
@@ -521,51 +546,57 @@ private:
*/
int Initialize(const char* binary_dir, cmCTestStartCommand* command);
- //! parse the option after -D and convert it into the appropriate steps
- bool AddTestsForDashboardType(std::string &targ);
+ /** parse the option after -D and convert it into the appropriate steps */
+ bool AddTestsForDashboardType(std::string& targ);
- //! read as "emit an error message for an unknown -D value"
- void ErrorMessageUnknownDashDValue(std::string &val);
+ /** read as "emit an error message for an unknown -D value" */
+ void ErrorMessageUnknownDashDValue(std::string& val);
- //! add a variable definition from a command line -D value
- bool AddVariableDefinition(const std::string &arg);
+ /** add a variable definition from a command line -D value */
+ bool AddVariableDefinition(const std::string& arg);
- //! parse and process most common command line arguments
- void HandleCommandLineArguments(size_t &i,
- std::vector<std::string> &args);
+ /** parse and process most common command line arguments */
+ bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
+ std::string& errormsg);
- //! hande the -S -SP and -SR arguments
- void HandleScriptArguments(size_t &i,
- std::vector<std::string> &args,
- bool &SRArgumentSpecified);
+ /** hande the -S -SP and -SR arguments */
+ void HandleScriptArguments(size_t& i, std::vector<std::string>& args,
+ bool& SRArgumentSpecified);
- //! Reread the configuration file
+ /** Reread the configuration file */
bool UpdateCTestConfiguration();
- //! Create note from files.
- int GenerateCTestNotesOutput(std::ostream& os,
- const VectorOfStrings& files);
-
- ///! Find the running cmake
- void FindRunningCMake();
+ /** Create note from files. */
+ int GenerateCTestNotesOutput(cmXMLWriter& xml, const VectorOfStrings& files);
- //! Check if the argument is the one specified
+ /** Check if the argument is the one specified */
bool CheckArgument(const std::string& arg, const char* varg1,
- const char* varg2 = 0);
+ const char* varg2 = CM_NULLPTR);
+
+ /** Output errors from a test */
+ void OutputTestErrors(std::vector<char> const& process_output);
+
+ /** Handle the --test-action command line argument */
+ bool HandleTestActionArgument(const char* ctestExec, size_t& i,
+ const std::vector<std::string>& args);
+
+ /** Handle the --test-model command line argument */
+ bool HandleTestModelArgument(const char* ctestExec, size_t& i,
+ const std::vector<std::string>& args);
- //! Output errors from a test
- void OutputTestErrors(std::vector<char> const &process_output);
+ int RunCMakeAndTest(std::string* output);
+ int ExecuteTests();
- bool SuppressUpdatingCTestConfiguration;
+ bool SuppressUpdatingCTestConfiguration;
bool Debug;
bool ShowLineNumbers;
bool Quiet;
- int DartVersion;
+ int DartVersion;
bool DropSiteCDash;
- std::vector<cmStdString> InitialCommandLineArguments;
+ std::vector<std::string> InitialCommandLineArguments;
int SubmitIndex;
@@ -581,21 +612,39 @@ class cmCTestLogWrite
{
public:
cmCTestLogWrite(const char* data, size_t length)
- : Data(data), Length(length) {}
+ : Data(data)
+ , Length(length)
+ {
+ }
const char* Data;
size_t Length;
};
-inline std::ostream& operator<< (std::ostream& os, const cmCTestLogWrite& c)
+inline std::ostream& operator<<(std::ostream& os, const cmCTestLogWrite& c)
{
- if (!c.Length)
- {
+ if (!c.Length) {
return os;
- }
+ }
os.write(c.Data, c.Length);
os.flush();
return os;
}
+#define cmCTestLog(ctSelf, logType, msg) \
+ do { \
+ std::ostringstream cmCTestLog_msg; \
+ cmCTestLog_msg << msg; \
+ (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \
+ cmCTestLog_msg.str().c_str()); \
+ } while (false)
+
+#define cmCTestOptionalLog(ctSelf, logType, msg, suppress) \
+ do { \
+ std::ostringstream cmCTestLog_msg; \
+ cmCTestLog_msg << msg; \
+ (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \
+ cmCTestLog_msg.str().c_str(), suppress); \
+ } while (false)
+
#endif
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index ed09545cb..0b025ab6f 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -1,184 +1,27 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCacheManager.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include <algorithm>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
-#include "cmCacheManager.h"
-#include "cmSystemTools.h"
-#include "cmCacheManager.h"
#include "cmGeneratedFileStream.h"
-#include "cmMakefile.h"
-#include "cmake.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
+#include "cmake.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/Glob.hxx>
-
-#include <cmsys/RegularExpression.hxx>
-
-const char* cmCacheManagerTypes[] =
-{ "BOOL",
- "PATH",
- "FILEPATH",
- "STRING",
- "INTERNAL",
- "STATIC",
- "UNINITIALIZED",
- 0
-};
-
-cmCacheManager::cmCacheManager(cmake* cm)
+cmCacheManager::cmCacheManager()
{
this->CacheMajorVersion = 0;
this->CacheMinorVersion = 0;
- this->CMakeInstance = cm;
-}
-
-const char* cmCacheManager::TypeToString(cmCacheManager::CacheEntryType type)
-{
- if ( type > 6 )
- {
- return cmCacheManagerTypes[6];
- }
- return cmCacheManagerTypes[type];
-}
-
-cmCacheManager::CacheEntryType cmCacheManager::StringToType(const char* s)
-{
- int i = 0;
- while(cmCacheManagerTypes[i])
- {
- if(strcmp(s, cmCacheManagerTypes[i]) == 0)
- {
- return static_cast<CacheEntryType>(i);
- }
- ++i;
- }
- return STRING;
-}
-
-bool cmCacheManager::IsType(const char* s)
-{
- for(int i=0; cmCacheManagerTypes[i]; ++i)
- {
- if(strcmp(s, cmCacheManagerTypes[i]) == 0)
- {
- return true;
- }
- }
- return false;
-}
-
-bool cmCacheManager::LoadCache(cmMakefile* mf)
-{
- return this->LoadCache(mf->GetHomeOutputDirectory());
-}
-
-
-bool cmCacheManager::LoadCache(const char* path)
-{
- return this->LoadCache(path,true);
-}
-
-bool cmCacheManager::LoadCache(const char* path,
- bool internal)
-{
- std::set<cmStdString> emptySet;
- return this->LoadCache(path, internal, emptySet, emptySet);
}
-static bool ParseEntryWithoutType(const char* entry,
- std::string& var,
- std::string& value)
-{
- // input line is: key=value
- static cmsys::RegularExpression reg(
- "^([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
- // input line is: "key"=value
- static cmsys::RegularExpression regQuoted(
- "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
- bool flag = false;
- if(regQuoted.find(entry))
- {
- var = regQuoted.match(1);
- value = regQuoted.match(2);
- flag = true;
- }
- else if (reg.find(entry))
- {
- var = reg.match(1);
- value = reg.match(2);
- flag = true;
- }
-
- // 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] == '\'')
- {
- value = value.substr(1,
- value.size() - 2);
- }
-
- return flag;
-}
-
-bool cmCacheManager::ParseEntry(const char* entry,
- std::string& var,
- std::string& value,
- CacheEntryType& type)
-{
- // input line is: key:type=value
- static cmsys::RegularExpression reg(
- "^([^:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
- // input line is: "key":type=value
- static cmsys::RegularExpression regQuoted(
- "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
- bool flag = false;
- if(regQuoted.find(entry))
- {
- var = regQuoted.match(1);
- type = cmCacheManager::StringToType(regQuoted.match(2).c_str());
- value = regQuoted.match(3);
- flag = true;
- }
- else if (reg.find(entry))
- {
- var = reg.match(1);
- type = cmCacheManager::StringToType(reg.match(2).c_str());
- value = reg.match(3);
- flag = true;
- }
-
- // 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] == '\'')
- {
- value = value.substr(1,
- value.size() - 2);
- }
-
- if (!flag)
- {
- return ParseEntryWithoutType(entry, var, value);
- }
-
- return flag;
-}
-
-void cmCacheManager::CleanCMakeFiles(const char* path)
+void cmCacheManager::CleanCMakeFiles(const std::string& path)
{
std::string glob = path;
glob += cmake::GetCMakeFilesDirectory();
@@ -186,226 +29,186 @@ void cmCacheManager::CleanCMakeFiles(const char* path)
cmsys::Glob globIt;
globIt.FindFiles(glob);
std::vector<std::string> files = globIt.GetFiles();
- for(std::vector<std::string>::iterator i = files.begin();
- i != files.end(); ++i)
- {
- cmSystemTools::RemoveFile(i->c_str());
- }
+ std::for_each(files.begin(), files.end(), cmSystemTools::RemoveFile);
}
-bool cmCacheManager::LoadCache(const char* path,
- bool internal,
- std::set<cmStdString>& excludes,
- std::set<cmStdString>& includes)
+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";
// clear the old cache, if we are reading in internal values
- if ( internal )
- {
+ if (internal) {
this->Cache.clear();
- }
- if(!cmSystemTools::FileExists(cacheFile.c_str()))
- {
+ }
+ if (!cmSystemTools::FileExists(cacheFile.c_str())) {
this->CleanCMakeFiles(path);
return false;
- }
+ }
- std::ifstream fin(cacheFile.c_str());
- if(!fin)
- {
+ cmsys::ifstream fin(cacheFile.c_str());
+ if (!fin) {
return false;
- }
- const char *realbuffer;
+ }
+ const char* realbuffer;
std::string buffer;
std::string entryKey;
- while(fin)
- {
+ unsigned int lineno = 0;
+ while (fin) {
// Format is key:type=value
std::string helpString;
CacheEntry e;
- e.Properties.SetCMakeInstance(this->CMakeInstance);
cmSystemTools::GetLineFromStream(fin, buffer);
+ lineno++;
realbuffer = buffer.c_str();
- while(*realbuffer != '0' &&
- (*realbuffer == ' ' ||
- *realbuffer == '\t' ||
- *realbuffer == '\r' ||
- *realbuffer == '\n'))
- {
- realbuffer++;
+ while (*realbuffer != '0' &&
+ (*realbuffer == ' ' || *realbuffer == '\t' || *realbuffer == '\r' ||
+ *realbuffer == '\n')) {
+ if (*realbuffer == '\n') {
+ lineno++;
}
+ realbuffer++;
+ }
// skip blank lines and comment lines
- if(realbuffer[0] == '#' || realbuffer[0] == 0)
- {
+ if (realbuffer[0] == '#' || realbuffer[0] == 0) {
continue;
- }
- while(realbuffer[0] == '/' && realbuffer[1] == '/')
- {
- if ((realbuffer[2] == '\\') && (realbuffer[3]=='n'))
- {
+ }
+ while (realbuffer[0] == '/' && realbuffer[1] == '/') {
+ if ((realbuffer[2] == '\\') && (realbuffer[3] == 'n')) {
helpString += "\n";
helpString += &realbuffer[4];
- }
- else
- {
+ } else {
helpString += &realbuffer[2];
- }
+ }
cmSystemTools::GetLineFromStream(fin, buffer);
+ lineno++;
realbuffer = buffer.c_str();
- if(!fin)
- {
+ if (!fin) {
continue;
- }
}
+ }
e.SetProperty("HELPSTRING", helpString.c_str());
- if(cmCacheManager::ParseEntry(realbuffer, entryKey, e.Value, e.Type))
- {
- if ( excludes.find(entryKey) == excludes.end() )
- {
+ if (cmState::ParseCacheEntry(realbuffer, entryKey, e.Value, e.Type)) {
+ if (excludes.find(entryKey) == excludes.end()) {
// Load internal values if internal is set.
// If the entry is not internal to the cache being loaded
// or if it is in the list of internal entries to be
// imported, load it.
- if ( internal || (e.Type != INTERNAL) ||
- (includes.find(entryKey) != includes.end()) )
- {
+ if (internal || (e.Type != cmStateEnums::INTERNAL) ||
+ (includes.find(entryKey) != includes.end())) {
// If we are loading the cache from another project,
// make all loaded entries internal so that it is
// not visible in the gui
- if (!internal)
- {
- e.Type = INTERNAL;
+ if (!internal) {
+ e.Type = cmStateEnums::INTERNAL;
helpString = "DO NOT EDIT, ";
helpString += entryKey;
helpString += " loaded from external file. "
- "To change this value edit this file: ";
+ "To change this value edit this file: ";
helpString += path;
- helpString += "/CMakeCache.txt" ;
+ helpString += "/CMakeCache.txt";
e.SetProperty("HELPSTRING", helpString.c_str());
- }
- if(!this->ReadPropertyEntry(entryKey, e))
- {
+ }
+ if (!this->ReadPropertyEntry(entryKey, e)) {
e.Initialized = true;
this->Cache[entryKey] = e;
- }
}
}
}
- else
- {
- cmSystemTools::Error("Parse error in cache file ", cacheFile.c_str(),
- ". Offending entry: ", realbuffer);
- }
+ } else {
+ std::ostringstream error;
+ error << "Parse error in cache file " << cacheFile;
+ error << " on line " << lineno << ". Offending entry: " << realbuffer;
+ cmSystemTools::Error(error.str().c_str());
}
+ }
this->CacheMajorVersion = 0;
this->CacheMinorVersion = 0;
- if(const char* cmajor = this->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION"))
- {
- unsigned int v=0;
- if(sscanf(cmajor, "%u", &v) == 1)
- {
+ if (const char* cmajor =
+ this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
+ unsigned int v = 0;
+ if (sscanf(cmajor, "%u", &v) == 1) {
this->CacheMajorVersion = v;
- }
- if(const char* cminor = this->GetCacheValue("CMAKE_CACHE_MINOR_VERSION"))
- {
- if(sscanf(cminor, "%u", &v) == 1)
- {
+ }
+ if (const char* cminor =
+ this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
+ if (sscanf(cminor, "%u", &v) == 1) {
this->CacheMinorVersion = v;
- }
}
}
- else
- {
+ } else {
// CMake version not found in the list file.
// Set as version 0.0
this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0",
"Minor version of cmake used to create the "
- "current loaded cache", cmCacheManager::INTERNAL);
+ "current loaded cache",
+ cmStateEnums::INTERNAL);
this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0",
"Major version of cmake used to create the "
- "current loaded cache", cmCacheManager::INTERNAL);
-
- }
+ "current loaded cache",
+ cmStateEnums::INTERNAL);
+ }
// check to make sure the cache directory has not
// been moved
- if ( internal && this->GetCacheValue("CMAKE_CACHEFILE_DIR") )
- {
+ const char* oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ if (internal && oldDir) {
std::string currentcwd = path;
- std::string oldcwd = this->GetCacheValue("CMAKE_CACHEFILE_DIR");
+ std::string oldcwd = oldDir;
cmSystemTools::ConvertToUnixSlashes(currentcwd);
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
- if(!cmSystemTools::SameFile(oldcwd.c_str(), currentcwd.c_str()))
- {
+ 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->GetCacheValue("CMAKE_CACHEFILE_DIR")) +
+ 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());
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-const char* cmCacheManager::PersistentProperties[] =
-{
- "ADVANCED",
- "MODIFIED",
- "STRINGS",
- 0
-};
+const char* cmCacheManager::PersistentProperties[] = { "ADVANCED", "MODIFIED",
+ "STRINGS", CM_NULLPTR };
-//----------------------------------------------------------------------------
bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
CacheEntry& e)
{
// All property entries are internal.
- if(e.Type != cmCacheManager::INTERNAL)
- {
+ if (e.Type != cmStateEnums::INTERNAL) {
return false;
- }
+ }
const char* end = entryKey.c_str() + entryKey.size();
- for(const char** p = this->PersistentProperties; *p; ++p)
- {
+ for (const char** p = this->PersistentProperties; *p; ++p) {
std::string::size_type plen = strlen(*p) + 1;
- if(entryKey.size() > plen && *(end-plen) == '-' &&
- strcmp(end-plen+1, *p) == 0)
- {
+ if (entryKey.size() > plen && *(end - plen) == '-' &&
+ strcmp(end - plen + 1, *p) == 0) {
std::string key = entryKey.substr(0, entryKey.size() - plen);
cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str());
- if(it.IsAtEnd())
- {
+ if (it.IsAtEnd()) {
// Create an entry and store the property.
CacheEntry& ne = this->Cache[key];
- ne.Properties.SetCMakeInstance(this->CMakeInstance);
- ne.Type = cmCacheManager::UNINITIALIZED;
+ ne.Type = cmStateEnums::UNINITIALIZED;
ne.SetProperty(*p, e.Value.c_str());
- }
- else
- {
+ } else {
// Store this property on its entry.
it.SetProperty(*p, e.Value.c_str());
- }
- return true;
}
+ return true;
}
+ }
return false;
}
-//----------------------------------------------------------------------------
-void cmCacheManager::WritePropertyEntries(std::ostream& os,
- CacheIterator const& i)
+void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i)
{
- for(const char** p = this->PersistentProperties; *p; ++p)
- {
- if(const char* value = i.GetProperty(*p))
- {
+ for (const char** p = this->PersistentProperties; *p; ++p) {
+ if (const char* value = i.GetProperty(*p)) {
std::string helpstring = *p;
helpstring += " property for variable: ";
helpstring += i.GetName();
@@ -418,70 +221,63 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os,
os << ":INTERNAL=";
this->OutputValue(os, value);
os << "\n";
- }
}
+ }
}
-bool cmCacheManager::SaveCache(cmMakefile* mf)
-{
- return this->SaveCache(mf->GetHomeOutputDirectory());
-}
-
-
-bool cmCacheManager::SaveCache(const char* path)
+bool cmCacheManager::SaveCache(const std::string& path)
{
std::string cacheFile = path;
cacheFile += "/CMakeCache.txt";
cmGeneratedFileStream fout(cacheFile.c_str());
fout.SetCopyIfDifferent(true);
- if(!fout)
- {
+ if (!fout) {
cmSystemTools::Error("Unable to open cache file for save. ",
cacheFile.c_str());
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 "
- "current loaded cache", cmCacheManager::INTERNAL);
+ "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 "
- "current loaded cache", cmCacheManager::INTERNAL);
+ "current loaded cache",
+ cmStateEnums::INTERNAL);
sprintf(temp, "%d", cmVersion::GetPatchVersion());
this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp,
"Patch version of cmake used to create the "
- "current loaded cache", cmCacheManager::INTERNAL);
+ "current loaded cache",
+ cmStateEnums::INTERNAL);
// Let us store the current working directory so that if somebody
// Copies it, he will not be surprised
std::string currentcwd = path;
- if ( currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' &&
- currentcwd[1] == ':' )
- {
+ if (currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' && currentcwd[1] == ':') {
// Cast added to avoid compiler warning. Cast is ok because
// value is guaranteed to fit in char by the above if...
currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a');
- }
+ }
cmSystemTools::ConvertToUnixSlashes(currentcwd);
this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(),
"This is the directory where this CMakeCache.txt"
- " was created", cmCacheManager::INTERNAL);
+ " was created",
+ cmStateEnums::INTERNAL);
+ /* clang-format off */
fout << "# This is the CMakeCache file.\n"
- << "# For build in directory: " << currentcwd << "\n";
- cmCacheManager::CacheEntry* cmakeCacheEntry
- = this->GetCacheEntry("CMAKE_COMMAND");
- if ( cmakeCacheEntry )
- {
- fout << "# It was generated by CMake: " <<
- cmakeCacheEntry->Value << std::endl;
- }
+ << "# For build in directory: " << currentcwd << "\n"
+ << "# It was generated by CMake: "
+ << cmSystemTools::GetCMakeCommand() << std::endl;
+ /* clang-format on */
+ /* clang-format off */
fout << "# You can edit this file to change values found and used by cmake."
<< std::endl
<< "# If you do not want to change any of the values, simply exit the "
@@ -494,42 +290,37 @@ bool cmCacheManager::SaveCache(const char* path)
<< "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT "
"TYPE!." << std::endl
<< "# VALUE is the current value for the KEY.\n\n";
+ /* clang-format on */
fout << "########################\n";
fout << "# EXTERNAL cache entries\n";
fout << "########################\n";
fout << "\n";
- for( std::map<cmStdString, CacheEntry>::const_iterator i =
- this->Cache.begin(); i != this->Cache.end(); ++i)
- {
+ for (std::map<std::string, CacheEntry>::const_iterator i =
+ this->Cache.begin();
+ i != this->Cache.end(); ++i) {
const CacheEntry& ce = (*i).second;
- CacheEntryType t = ce.Type;
- if(!ce.Initialized)
- {
+ 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");
*/
- }
- else if(t != INTERNAL)
- {
+ } else if (t != cmStateEnums::INTERNAL) {
// Format is key:type=value
- if(const char* help = ce.GetProperty("HELPSTRING"))
- {
+ if (const char* help = ce.GetProperty("HELPSTRING")) {
cmCacheManager::OutputHelpString(fout, help);
- }
- else
- {
+ } else {
cmCacheManager::OutputHelpString(fout, "Missing description");
- }
+ }
this->OutputKey(fout, i->first);
- fout << ":" << cmCacheManagerTypes[t] << "=";
+ fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
this->OutputValue(fout, ce.Value);
fout << "\n\n";
- }
}
+ }
fout << "\n";
fout << "########################\n";
@@ -537,224 +328,186 @@ bool cmCacheManager::SaveCache(const char* path)
fout << "########################\n";
fout << "\n";
- for( cmCacheManager::CacheIterator i = this->NewIterator();
- !i.IsAtEnd(); i.Next())
- {
- if ( !i.Initialized() )
- {
+ for (cmCacheManager::CacheIterator i = this->NewIterator(); !i.IsAtEnd();
+ i.Next()) {
+ if (!i.Initialized()) {
continue;
- }
+ }
- CacheEntryType t = i.GetType();
+ cmStateEnums::CacheEntryType t = i.GetType();
this->WritePropertyEntries(fout, i);
- if(t == cmCacheManager::INTERNAL)
- {
+ if (t == cmStateEnums::INTERNAL) {
// Format is key:type=value
- if(const char* help = i.GetProperty("HELPSTRING"))
- {
+ if (const char* help = i.GetProperty("HELPSTRING")) {
this->OutputHelpString(fout, help);
- }
+ }
this->OutputKey(fout, i.GetName());
- fout << ":" << cmCacheManagerTypes[t] << "=";
+ fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
this->OutputValue(fout, i.GetValue());
fout << "\n";
- }
}
+ }
fout << "\n";
fout.Close();
std::string checkCacheFile = path;
checkCacheFile += cmake::GetCMakeFilesDirectory();
cmSystemTools::MakeDirectory(checkCacheFile.c_str());
checkCacheFile += "/cmake.check_cache";
- std::ofstream checkCache(checkCacheFile.c_str());
- if(!checkCache)
- {
+ cmsys::ofstream checkCache(checkCacheFile.c_str());
+ if (!checkCache) {
cmSystemTools::Error("Unable to open check cache file for write. ",
checkCacheFile.c_str());
return false;
- }
+ }
checkCache << "# This file is generated by cmake for dependency checking "
- "of the CMakeCache.txt file\n";
+ "of the CMakeCache.txt file\n";
return true;
}
-bool cmCacheManager::DeleteCache(const char* path)
+bool cmCacheManager::DeleteCache(const std::string& path)
{
std::string cacheFile = path;
cmSystemTools::ConvertToUnixSlashes(cacheFile);
std::string cmakeFiles = cacheFile;
cacheFile += "/CMakeCache.txt";
- if(cmSystemTools::FileExists(cacheFile.c_str()))
- {
- cmSystemTools::RemoveFile(cacheFile.c_str());
+ if (cmSystemTools::FileExists(cacheFile.c_str())) {
+ cmSystemTools::RemoveFile(cacheFile);
// now remove the files in the CMakeFiles directory
// this cleans up language cache files
cmakeFiles += cmake::GetCMakeFilesDirectory();
- if(cmSystemTools::FileIsDirectory(cmakeFiles.c_str()))
- {
- cmSystemTools::RemoveADirectory(cmakeFiles.c_str());
- }
+ if (cmSystemTools::FileIsDirectory(cmakeFiles)) {
+ cmSystemTools::RemoveADirectory(cmakeFiles);
}
+ }
return true;
}
void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
{
// support : in key name by double quoting
- const char* q = (key.find(':') != key.npos ||
- key.find("//") == 0)? "\"" : "";
+ const char* q =
+ (key.find(':') != std::string::npos || key.find("//") == 0) ? "\"" : "";
fout << q << key << q;
}
void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
{
// if value has trailing space or tab, enclose it in single quotes
- if (value.size() &&
- (value[value.size() - 1] == ' ' ||
- value[value.size() - 1] == '\t'))
- {
+ if (!value.empty() &&
+ (value[value.size() - 1] == ' ' || value[value.size() - 1] == '\t')) {
fout << '\'' << value << '\'';
- }
- else
- {
+ } else {
fout << value;
- }
+ }
}
void cmCacheManager::OutputHelpString(std::ostream& fout,
const std::string& helpString)
{
std::string::size_type end = helpString.size();
- if(end == 0)
- {
+ if (end == 0) {
return;
- }
+ }
std::string oneLine;
std::string::size_type pos = 0;
- for (std::string::size_type i=0; i<=end; i++)
- {
- if ((i==end)
- || (helpString[i]=='\n')
- || ((i-pos >= 60) && (helpString[i]==' ')))
- {
+ for (std::string::size_type i = 0; i <= end; i++) {
+ if ((i == end) || (helpString[i] == '\n') ||
+ ((i - pos >= 60) && (helpString[i] == ' '))) {
fout << "//";
- if (helpString[pos] == '\n')
- {
+ if (helpString[pos] == '\n') {
pos++;
fout << "\\n";
- }
+ }
oneLine = helpString.substr(pos, i - pos);
- fout << oneLine.c_str() << "\n";
+ fout << oneLine << "\n";
pos = i;
- }
}
+ }
}
-void cmCacheManager::RemoveCacheEntry(const char* key)
+void cmCacheManager::RemoveCacheEntry(const std::string& key)
{
CacheEntryMap::iterator i = this->Cache.find(key);
- if(i != this->Cache.end())
- {
+ if (i != this->Cache.end()) {
this->Cache.erase(i);
- }
+ }
}
-
-cmCacheManager::CacheEntry *cmCacheManager::GetCacheEntry(const char* key)
+cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry(
+ const std::string& key)
{
CacheEntryMap::iterator i = this->Cache.find(key);
- if(i != this->Cache.end())
- {
+ if (i != this->Cache.end()) {
return &i->second;
- }
- return 0;
+ }
+ return CM_NULLPTR;
}
-cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(
- const char *key)
+cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key)
{
return CacheIterator(*this, key);
}
-const char* cmCacheManager::GetCacheValue(const char* key) const
+const char* cmCacheManager::GetInitializedCacheValue(
+ const std::string& key) const
{
CacheEntryMap::const_iterator i = this->Cache.find(key);
- if(i != this->Cache.end() &&
- i->second.Initialized)
- {
+ if (i != this->Cache.end() && i->second.Initialized) {
return i->second.Value.c_str();
- }
- return 0;
+ }
+ return CM_NULLPTR;
}
-
void cmCacheManager::PrintCache(std::ostream& out) const
{
out << "=================================================" << std::endl;
out << "CMakeCache Contents:" << std::endl;
- for(std::map<cmStdString, CacheEntry>::const_iterator i =
- this->Cache.begin(); i != this->Cache.end(); ++i)
- {
- if((*i).second.Type != INTERNAL)
- {
- out << (*i).first.c_str() << " = " << (*i).second.Value.c_str()
- << 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;
}
+ }
out << "\n\n";
- out << "To change values in the CMakeCache, "
- << std::endl << "edit CMakeCache.txt in your output directory.\n";
+ out << "To change values in the CMakeCache, " << std::endl
+ << "edit CMakeCache.txt in your output directory.\n";
out << "=================================================" << std::endl;
}
-
-void cmCacheManager::AddCacheEntry(const char* key,
- const char* value,
+void cmCacheManager::AddCacheEntry(const std::string& key, const char* value,
const char* helpString,
- CacheEntryType type)
+ cmStateEnums::CacheEntryType type)
{
CacheEntry& e = this->Cache[key];
- e.Properties.SetCMakeInstance(this->CMakeInstance);
- if ( value )
- {
+ if (value) {
e.Value = value;
e.Initialized = true;
- }
- else
- {
+ } else {
e.Value = "";
- }
+ }
e.Type = type;
// make sure we only use unix style paths
- if(type == FILEPATH || type == PATH)
- {
- if(e.Value.find(';') != e.Value.npos)
- {
+ if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) {
+ if (e.Value.find(';') != std::string::npos) {
std::vector<std::string> paths;
cmSystemTools::ExpandListArgument(e.Value, paths);
const char* sep = "";
e.Value = "";
- for(std::vector<std::string>::iterator i = paths.begin();
- i != paths.end(); ++i)
- {
+ for (std::vector<std::string>::iterator i = paths.begin();
+ i != paths.end(); ++i) {
cmSystemTools::ConvertToUnixSlashes(*i);
e.Value += sep;
e.Value += *i;
sep = ";";
- }
}
- else
- {
+ } else {
cmSystemTools::ConvertToUnixSlashes(e.Value);
- }
- }
- e.SetProperty("HELPSTRING", helpString? helpString :
- "(This variable does not exist and should not be used)");
- if (this->Cache[key].Value == e.Value)
- {
- this->CMakeInstance->UnwatchUnusedCli(key);
}
- this->Cache[key] = e;
+ }
+ e.SetProperty("HELPSTRING", helpString
+ ? helpString
+ : "(This variable does not exist and should not be used)");
}
bool cmCacheManager::CacheIterator::IsAtEnd() const
@@ -767,7 +520,7 @@ void cmCacheManager::CacheIterator::Begin()
this->Position = this->Container.Cache.begin();
}
-bool cmCacheManager::CacheIterator::Find(const char* key)
+bool cmCacheManager::CacheIterator::Find(const std::string& key)
{
this->Position = this->Container.Cache.find(key);
return !this->IsAtEnd();
@@ -775,225 +528,124 @@ bool cmCacheManager::CacheIterator::Find(const char* key)
void cmCacheManager::CacheIterator::Next()
{
- if (!this->IsAtEnd())
- {
+ if (!this->IsAtEnd()) {
++this->Position;
- }
+ }
+}
+
+std::vector<std::string> cmCacheManager::CacheIterator::GetPropertyList() const
+{
+ return this->GetEntry().GetPropertyList();
}
void cmCacheManager::CacheIterator::SetValue(const char* value)
{
- if (this->IsAtEnd())
- {
+ if (this->IsAtEnd()) {
return;
- }
+ }
CacheEntry* entry = &this->GetEntry();
- if ( value )
- {
+ if (value) {
entry->Value = value;
entry->Initialized = true;
- }
- else
- {
+ } else {
entry->Value = "";
- }
+ }
}
-//----------------------------------------------------------------------------
bool cmCacheManager::CacheIterator::GetValueAsBool() const
{
return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
}
-//----------------------------------------------------------------------------
-const char*
-cmCacheManager::CacheEntry::GetProperty(const char* prop) const
+std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
{
- if(strcmp(prop, "TYPE") == 0)
- {
- return cmCacheManagerTypes[this->Type];
- }
- else if(strcmp(prop, "VALUE") == 0)
- {
+ return this->Properties.GetPropertyList();
+}
+
+const char* cmCacheManager::CacheEntry::GetProperty(
+ const std::string& prop) const
+{
+ if (prop == "TYPE") {
+ return cmState::CacheEntryTypeToString(this->Type);
+ }
+ if (prop == "VALUE") {
return this->Value.c_str();
- }
- bool c = false;
- return
- this->Properties.GetPropertyValue(prop, cmProperty::CACHE, c);
+ }
+ return this->Properties.GetPropertyValue(prop);
}
-//----------------------------------------------------------------------------
-void cmCacheManager::CacheEntry::SetProperty(const char* prop,
+void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
const char* value)
{
- if(strcmp(prop, "TYPE") == 0)
- {
- this->Type = cmCacheManager::StringToType(value? value : "STRING");
- }
- else if(strcmp(prop, "VALUE") == 0)
- {
- this->Value = value? value : "";
- }
- else
- {
- this->Properties.SetProperty(prop, value, cmProperty::CACHE);
- }
+ if (prop == "TYPE") {
+ this->Type = cmState::StringToCacheEntryType(value ? value : "STRING");
+ } else if (prop == "VALUE") {
+ this->Value = value ? value : "";
+ } else {
+ this->Properties.SetProperty(prop, value);
+ }
}
-//----------------------------------------------------------------------------
-void cmCacheManager::CacheEntry::AppendProperty(const char* prop,
+void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop,
const char* value,
bool asString)
{
- if(strcmp(prop, "TYPE") == 0)
- {
- this->Type = cmCacheManager::StringToType(value? value : "STRING");
- }
- else if(strcmp(prop, "VALUE") == 0)
- {
- if(value)
- {
- if(!this->Value.empty() && *value && !asString)
- {
+ if (prop == "TYPE") {
+ this->Type = cmState::StringToCacheEntryType(value ? value : "STRING");
+ } else if (prop == "VALUE") {
+ if (value) {
+ if (!this->Value.empty() && *value && !asString) {
this->Value += ";";
- }
- this->Value += value;
}
+ this->Value += value;
}
- else
- {
- this->Properties.AppendProperty(prop, value, cmProperty::CACHE, asString);
- }
+ } else {
+ this->Properties.AppendProperty(prop, value, asString);
+ }
}
-//----------------------------------------------------------------------------
-const char* cmCacheManager::CacheIterator::GetProperty(const char* prop) const
+const char* cmCacheManager::CacheIterator::GetProperty(
+ const std::string& prop) const
{
- if(!this->IsAtEnd())
- {
+ if (!this->IsAtEnd()) {
return this->GetEntry().GetProperty(prop);
- }
- return 0;
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-void cmCacheManager::CacheIterator::SetProperty(const char* p, const char* v)
+void cmCacheManager::CacheIterator::SetProperty(const std::string& p,
+ const char* v)
{
- if(!this->IsAtEnd())
- {
+ if (!this->IsAtEnd()) {
this->GetEntry().SetProperty(p, v);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmCacheManager::CacheIterator::AppendProperty(const char* p,
+void cmCacheManager::CacheIterator::AppendProperty(const std::string& p,
const char* v,
bool asString)
{
- if(!this->IsAtEnd())
- {
+ if (!this->IsAtEnd()) {
this->GetEntry().AppendProperty(p, v, asString);
- }
+ }
}
-//----------------------------------------------------------------------------
-bool cmCacheManager::CacheIterator::GetPropertyAsBool(const char* prop) const
+bool cmCacheManager::CacheIterator::GetPropertyAsBool(
+ const std::string& prop) const
{
- if(const char* value = this->GetProperty(prop))
- {
+ if (const char* value = this->GetProperty(prop)) {
return cmSystemTools::IsOn(value);
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
-void cmCacheManager::CacheIterator::SetProperty(const char* p, bool v)
+void cmCacheManager::CacheIterator::SetProperty(const std::string& p, bool v)
{
this->SetProperty(p, v ? "ON" : "OFF");
}
-//----------------------------------------------------------------------------
-bool cmCacheManager::CacheIterator::PropertyExists(const char* prop) const
+bool cmCacheManager::CacheIterator::PropertyExists(
+ const std::string& prop) const
{
- return this->GetProperty(prop)? true:false;
-}
-
-//----------------------------------------------------------------------------
-bool cmCacheManager::NeedCacheCompatibility(int major, int minor)
-{
- // Compatibility is not needed if the cache version is zero because
- // the cache was created or modified by the user.
- if(this->CacheMajorVersion == 0)
- {
- return false;
- }
-
- // Compatibility is needed if the cache version is equal to or lower
- // than the given version.
- unsigned int actual_compat =
- CMake_VERSION_ENCODE(this->CacheMajorVersion, this->CacheMinorVersion, 0);
- return (actual_compat &&
- actual_compat <= CMake_VERSION_ENCODE(major, minor, 0));
-}
-
-//----------------------------------------------------------------------------
-void cmCacheManager::DefineProperties(cmake *cm)
-{
- cm->DefineProperty
- ("ADVANCED", cmProperty::CACHE,
- "True if entry should be hidden by default in GUIs.",
- "This is a boolean value indicating whether the entry is considered "
- "interesting only for advanced configuration. "
- "The mark_as_advanced() command modifies this property."
- );
-
- cm->DefineProperty
- ("HELPSTRING", cmProperty::CACHE,
- "Help associated with entry in GUIs.",
- "This string summarizes the purpose of an entry to help users set it "
- "through a CMake GUI."
- );
-
- cm->DefineProperty
- ("TYPE", cmProperty::CACHE,
- "Widget type for entry in GUIs.",
- "Cache entry values are always strings, but CMake GUIs present widgets "
- "to help users set values. "
- "The GUIs use this property as a hint to determine the widget type. "
- "Valid TYPE values are:\n"
- " BOOL = Boolean ON/OFF value.\n"
- " PATH = Path to a directory.\n"
- " FILEPATH = Path to a file.\n"
- " STRING = Generic string value.\n"
- " INTERNAL = Do not present in GUI at all.\n"
- " STATIC = Value managed by CMake, do not change.\n"
- " UNINITIALIZED = Type not yet specified.\n"
- "Generally the TYPE of a cache entry should be set by the command "
- "which creates it (set, option, find_library, etc.)."
- );
-
- cm->DefineProperty
- ("MODIFIED", cmProperty::CACHE,
- "Internal management property. Do not set or get.",
- "This is an internal cache entry property managed by CMake to "
- "track interactive user modification of entries. Ignore it."
- );
-
- cm->DefineProperty
- ("STRINGS", cmProperty::CACHE,
- "Enumerate possible STRING entry values for GUI selection.",
- "For cache entries with type STRING, this enumerates a set of values. "
- "CMake GUIs may use this to provide a selection widget instead of a "
- "generic string entry field. "
- "This is for convenience only. "
- "CMake does not enforce that the value matches one of those listed."
- );
-
- cm->DefineProperty
- ("VALUE", cmProperty::CACHE,
- "Value of a cache entry.",
- "This property maps to the actual value of a cache entry. "
- "Setting this property always sets the value without checking, so "
- "use with care."
- );
+ return this->GetProperty(prop) != CM_NULLPTR;
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index a5e5eeeff..c464311c6 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -1,21 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCacheManager_h
#define cmCacheManager_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
#include "cmPropertyMap.h"
-class cmMakefile;
-class cmMarkAsAdvancedCommand;
+#include "cmStateTypes.h"
+
class cmake;
/** \class cmCacheManager
@@ -27,25 +26,28 @@ class cmake;
class cmCacheManager
{
public:
- cmCacheManager(cmake* cm);
+ cmCacheManager();
class CacheIterator;
friend class cmCacheManager::CacheIterator;
- enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL,STATIC,
- UNINITIALIZED };
private:
struct CacheEntry
{
std::string Value;
- CacheEntryType Type;
+ cmStateEnums::CacheEntryType Type;
cmPropertyMap Properties;
- const char* GetProperty(const char*) const;
- void SetProperty(const char* property, const char* value);
- void AppendProperty(const char* property, const char* value,
- bool asString=false);
+ 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(UNINITIALIZED), Initialized(false)
- {}
+ CacheEntry()
+ : Value("")
+ , Type(cmStateEnums::UNINITIALIZED)
+ , Initialized(false)
+ {
+ }
};
public:
@@ -53,121 +55,172 @@ public:
{
public:
void Begin();
- bool Find(const char*);
+ bool Find(const std::string&);
bool IsAtEnd() const;
void Next();
- const char *GetName() const {
- return this->Position->first.c_str(); }
- const char* GetProperty(const char*) const ;
- bool GetPropertyAsBool(const char*) const ;
- bool PropertyExists(const char*) const;
- void SetProperty(const char* property, const char* value);
- void AppendProperty(const char* property, const char* value,
- bool asString=false);
- void SetProperty(const char* property, bool value);
+ std::string GetName() const { return this->Position->first; }
+ std::vector<std::string> GetPropertyList() const;
+ const char* GetProperty(const std::string&) const;
+ bool GetPropertyAsBool(const std::string&) const;
+ bool PropertyExists(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);
+ void SetProperty(const std::string& property, bool value);
const char* GetValue() const { return this->GetEntry().Value.c_str(); }
bool GetValueAsBool() const;
void SetValue(const char*);
- CacheEntryType GetType() const { return this->GetEntry().Type; }
- void SetType(CacheEntryType ty) { this->GetEntry().Type = ty; }
+ cmStateEnums::CacheEntryType GetType() const
+ {
+ return this->GetEntry().Type;
+ }
+ void SetType(cmStateEnums::CacheEntryType ty)
+ {
+ this->GetEntry().Type = ty;
+ }
bool Initialized() { return this->GetEntry().Initialized; }
- cmCacheManager &Container;
- std::map<cmStdString, CacheEntry>::iterator Position;
- CacheIterator(cmCacheManager &cm) : Container(cm) {
+ cmCacheManager& Container;
+ std::map<std::string, CacheEntry>::iterator Position;
+ CacheIterator(cmCacheManager& cm)
+ : Container(cm)
+ {
this->Begin();
}
- CacheIterator(cmCacheManager &cm, const char* key) : Container(cm)
- {
- if ( key )
- {
+ CacheIterator(cmCacheManager& cm, const char* key)
+ : Container(cm)
+ {
+ if (key) {
this->Find(key);
- }
}
+ }
+
private:
CacheEntry const& GetEntry() const { return this->Position->second; }
CacheEntry& GetEntry() { return this->Position->second; }
};
///! return an iterator to iterate through the cache map
- cmCacheManager::CacheIterator NewIterator()
- {
- return CacheIterator(*this);
- }
+ cmCacheManager::CacheIterator NewIterator() { return CacheIterator(*this); }
- /**
- * Types for the cache entries. These are useful as
- * hints for a cache editor program. Path should bring
- * up a file chooser, BOOL a check box, and STRING a
- * text entry box, FILEPATH is a full path to a file which
- * can be different than just a path input
- */
- static CacheEntryType StringToType(const char*);
- static const char* TypeToString(CacheEntryType);
- static bool IsType(const char*);
-
- ///! Load a cache for given makefile. Loads from ouput home.
- bool LoadCache(cmMakefile*);
///! Load a cache for given makefile. Loads from path/CMakeCache.txt.
- bool LoadCache(const char* path);
- bool LoadCache(const char* path, bool internal);
- bool LoadCache(const char* path, bool internal,
- std::set<cmStdString>& excludes,
- std::set<cmStdString>& includes);
-
- ///! Save cache for given makefile. Saves to ouput home CMakeCache.txt.
- bool SaveCache(cmMakefile*) ;
+ 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 char* path) ;
+ bool SaveCache(const std::string& path);
///! Delete the cache given
- bool DeleteCache(const char* path);
+ bool DeleteCache(const std::string& path);
///! 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=0);
+ cmCacheManager::CacheIterator GetCacheIterator(const char* key = CM_NULLPTR);
///! Remove an entry from the cache
- void RemoveCacheEntry(const char* key);
+ void RemoveCacheEntry(const std::string& key);
///! Get the number of entries in the cache
- int GetSize() {
- return static_cast<int>(this->Cache.size()); }
-
- ///! Break up a line like VAR:type="value" into var, type and value
- static bool ParseEntry(const char* entry,
- std::string& var,
- std::string& value,
- CacheEntryType& type);
+ int GetSize() { return static_cast<int>(this->Cache.size()); }
///! Get a value from the cache given a key
- const char* GetCacheValue(const char* key) const;
+ const char* GetInitializedCacheValue(const std::string& key) const;
- /** Get the version of CMake that wrote the cache. */
- unsigned int GetCacheMajorVersion() { return this->CacheMajorVersion; }
- unsigned int GetCacheMinorVersion() { return this->CacheMinorVersion; }
- bool NeedCacheCompatibility(int major, int minor);
+ const char* GetCacheEntryValue(const std::string& key)
+ {
+ cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str());
+ if (it.IsAtEnd()) {
+ return CM_NULLPTR;
+ }
+ return it.GetValue();
+ }
+
+ const char* GetCacheEntryProperty(std::string const& key,
+ std::string const& propName)
+ {
+ return this->GetCacheIterator(key.c_str()).GetProperty(propName);
+ }
- /** Define and document CACHE entry properties. */
- static void DefineProperties(cmake *cm);
+ cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key)
+ {
+ return this->GetCacheIterator(key.c_str()).GetType();
+ }
+
+ bool GetCacheEntryPropertyAsBool(std::string const& key,
+ std::string const& propName)
+ {
+ return this->GetCacheIterator(key.c_str()).GetPropertyAsBool(propName);
+ }
+
+ void SetCacheEntryProperty(std::string const& key,
+ std::string const& propName,
+ std::string const& value)
+ {
+ this->GetCacheIterator(key.c_str()).SetProperty(propName, value.c_str());
+ }
+
+ void SetCacheEntryBoolProperty(std::string const& key,
+ std::string const& propName, bool value)
+ {
+ this->GetCacheIterator(key.c_str()).SetProperty(propName, value);
+ }
+
+ void SetCacheEntryValue(std::string const& key, std::string const& value)
+ {
+ this->GetCacheIterator(key.c_str()).SetValue(value.c_str());
+ }
+
+ void RemoveCacheEntryProperty(std::string const& key,
+ std::string const& propName)
+ {
+ this->GetCacheIterator(key.c_str())
+ .SetProperty(propName, (void*)CM_NULLPTR);
+ }
+
+ void AppendCacheEntryProperty(std::string const& key,
+ std::string const& propName,
+ std::string const& value,
+ bool asString = false)
+ {
+ this->GetCacheIterator(key.c_str())
+ .AppendProperty(propName, value.c_str(), asString);
+ }
+
+ std::vector<std::string> GetCacheEntryKeys()
+ {
+ std::vector<std::string> definitions;
+ definitions.reserve(this->GetSize());
+ cmCacheManager::CacheIterator cit = this->GetCacheIterator();
+ for (cit.Begin(); !cit.IsAtEnd(); cit.Next()) {
+ definitions.push_back(cit.GetName());
+ }
+ return definitions;
+ }
+
+ /** Get the version of CMake that wrote the cache. */
+ unsigned int GetCacheMajorVersion() const { return this->CacheMajorVersion; }
+ unsigned int GetCacheMinorVersion() const { return this->CacheMinorVersion; }
protected:
///! Add an entry into the cache
- void AddCacheEntry(const char* key, const char* value,
- const char* helpString, CacheEntryType type);
+ void AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString,
+ cmStateEnums::CacheEntryType type);
///! Get a cache entry object for a key
- CacheEntry *GetCacheEntry(const char *key);
+ CacheEntry* GetCacheEntry(const std::string& key);
///! Clean out the CMakeFiles directory if no CMakeCache.txt
- void CleanCMakeFiles(const char* path);
+ void CleanCMakeFiles(const std::string& path);
// Cache version info
unsigned int CacheMajorVersion;
unsigned int CacheMinorVersion;
+
private:
cmake* CMakeInstance;
- typedef std::map<cmStdString, CacheEntry> CacheEntryMap;
+ typedef std::map<std::string, CacheEntry> CacheEntryMap;
static void OutputHelpString(std::ostream& fout,
const std::string& helpString);
static void OutputKey(std::ostream& fout, std::string const& key);
@@ -175,15 +228,13 @@ private:
static const char* PersistentProperties[];
bool ReadPropertyEntry(std::string const& key, CacheEntry& e);
- void WritePropertyEntries(std::ostream& os, CacheIterator const& i);
+ void WritePropertyEntries(std::ostream& os, CacheIterator i);
CacheEntryMap Cache;
- // Only cmake and cmMakefile should be able to add cache values
+ // Only cmake and cmState should be able to add cache values
// the commands should never use the cmCacheManager directly
- friend class cmMakefile; // allow access to add cache values
- friend class cmake; // allow access to add cache values
- friend class cmakewizard; // allow access to add cache values
- friend class cmMarkAsAdvancedCommand; // allow access to add cache values
+ friend class cmState; // allow access to add cache values
+ friend class cmake; // allow access to add cache values
};
#endif
diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx
index 0c154770d..99fe5877e 100644
--- a/Source/cmCallVisualStudioMacro.cxx
+++ b/Source/cmCallVisualStudioMacro.cxx
@@ -1,106 +1,78 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCallVisualStudioMacro.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include <sstream>
-#include "cmCallVisualStudioMacro.h"
#include "cmSystemTools.h"
-
#if defined(_MSC_VER)
#define HAVE_COMDEF_H
#endif
-
// Just for this file:
//
static bool LogErrorsAsMessages;
-
#if defined(HAVE_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.
//
-#if ( _MSC_VER >= 1300 )
-// VS7 and later:
#ifdef _NATIVE_WCHAR_T_DEFINED
-# ifdef _DEBUG
-# pragma comment(lib, "comsuppwd.lib")
-# else
-# pragma comment(lib, "comsuppw.lib")
-# endif
+#ifdef _DEBUG
+#pragma comment(lib, "comsuppwd.lib")
#else
-# ifdef _DEBUG
-# pragma comment(lib, "comsuppd.lib")
-# else
-# pragma comment(lib, "comsupp.lib")
-# endif
+#pragma comment(lib, "comsuppw.lib")
#endif
#else
-// VS6 only had comsupp.lib:
-# pragma comment(lib, "comsupp.lib")
+#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 oss; \
- oss.flags(std::ios::hex); \
- oss << context << " failed HRESULT, hr = 0x" << hr << std::endl; \
- oss.flags(std::ios::dec); \
- oss << __FILE__ << "(" << __LINE__ << ")"; \
- cmSystemTools::Message(oss.str().c_str()); \
- } \
- }
-
+#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()); \
+ } \
+ }
-//----------------------------------------------------------------------------
///! Using the given instance of Visual Studio, call the named macro
-HRESULT InstanceCallMacro(
- IDispatch* vsIDE,
- const std::string& macro,
- const std::string& args)
+HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
+ const std::string& args)
{
HRESULT hr = E_POINTER;
_bstr_t macroName(macro.c_str());
_bstr_t macroArgs(args.c_str());
- if (0 != vsIDE)
- {
- DISPID dispid = (DISPID) -1;
- OLECHAR *name = L"ExecuteCommand";
+ if (0 != vsIDE) {
+ DISPID dispid = (DISPID)-1;
+ OLECHAR* name = L"ExecuteCommand";
- hr = vsIDE->GetIDsOfNames(IID_NULL, &name, 1,
- LOCALE_USER_DEFAULT, &dispid);
+ hr =
+ vsIDE->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
ReportHRESULT(hr, "GetIDsOfNames(ExecuteCommand)");
- if (SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
VARIANTARG vargs[2];
DISPPARAMS params;
VARIANT result;
EXCEPINFO excep;
- UINT arg = (UINT) -1;
+ UINT arg = (UINT)-1;
// No VariantInit or VariantClear calls are necessary for
// these two vargs. They are both local _bstr_t variables
@@ -113,7 +85,7 @@ HRESULT InstanceCallMacro(
params.rgvarg = &vargs[0];
params.rgdispidNamedArgs = 0;
- params.cArgs = sizeof(vargs)/sizeof(vargs[0]);
+ params.cArgs = sizeof(vargs) / sizeof(vargs[0]);
params.cNamedArgs = 0;
VariantInit(&result);
@@ -121,74 +93,64 @@ HRESULT InstanceCallMacro(
memset(&excep, 0, sizeof(excep));
hr = vsIDE->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT,
- DISPATCH_METHOD, &params, &result, &excep, &arg);
+ DISPATCH_METHOD, &params, &result, &excep, &arg);
std::ostringstream oss;
oss << std::endl;
oss << "Invoke(ExecuteCommand)" << std::endl;
- oss << " Macro: " << macro.c_str() << std::endl;
- oss << " Args: " << args.c_str() << std::endl;
+ oss << " Macro: " << macro << std::endl;
+ oss << " Args: " << args << std::endl;
- if (DISP_E_EXCEPTION == hr)
- {
+ if (DISP_E_EXCEPTION == hr) {
oss << "DISP_E_EXCEPTION EXCEPINFO:" << excep.wCode << std::endl;
oss << " wCode: " << excep.wCode << std::endl;
oss << " wReserved: " << excep.wReserved << std::endl;
- if (excep.bstrSource)
- {
- oss << " bstrSource: " <<
- (const char*)(_bstr_t)excep.bstrSource << std::endl;
- }
- if (excep.bstrDescription)
- {
- oss << " bstrDescription: " <<
- (const char*)(_bstr_t)excep.bstrDescription << std::endl;
- }
- if (excep.bstrHelpFile)
- {
- oss << " bstrHelpFile: " <<
- (const char*)(_bstr_t)excep.bstrHelpFile << std::endl;
- }
+ if (excep.bstrSource) {
+ oss << " bstrSource: " << (const char*)(_bstr_t)excep.bstrSource
+ << std::endl;
+ }
+ if (excep.bstrDescription) {
+ oss << " bstrDescription: "
+ << (const char*)(_bstr_t)excep.bstrDescription << std::endl;
+ }
+ if (excep.bstrHelpFile) {
+ oss << " bstrHelpFile: " << (const char*)(_bstr_t)excep.bstrHelpFile
+ << std::endl;
+ }
oss << " dwHelpContext: " << excep.dwHelpContext << std::endl;
oss << " pvReserved: " << excep.pvReserved << std::endl;
oss << " pfnDeferredFillIn: " << excep.pfnDeferredFillIn << std::endl;
oss << " scode: " << excep.scode << std::endl;
- }
+ }
std::string exstr(oss.str());
ReportHRESULT(hr, exstr.c_str());
VariantClear(&result);
- }
}
+ }
return hr;
}
-
-//----------------------------------------------------------------------------
///! Get the Solution object from the IDE object
-HRESULT GetSolutionObject(
- IDispatch* vsIDE,
- IDispatchPtr& vsSolution)
+HRESULT GetSolutionObject(IDispatch* vsIDE, IDispatchPtr& vsSolution)
{
HRESULT hr = E_POINTER;
- if (0 != vsIDE)
- {
- DISPID dispid = (DISPID) -1;
- OLECHAR *name = L"Solution";
+ if (0 != vsIDE) {
+ DISPID dispid = (DISPID)-1;
+ OLECHAR* name = L"Solution";
- hr = vsIDE->GetIDsOfNames(IID_NULL, &name, 1,
- LOCALE_USER_DEFAULT, &dispid);
+ hr =
+ vsIDE->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
ReportHRESULT(hr, "GetIDsOfNames(Solution)");
- if (SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
DISPPARAMS params;
VARIANT result;
EXCEPINFO excep;
- UINT arg = (UINT) -1;
+ UINT arg = (UINT)-1;
params.rgvarg = 0;
params.rgdispidNamedArgs = 0;
@@ -200,45 +162,38 @@ HRESULT GetSolutionObject(
memset(&excep, 0, sizeof(excep));
hr = vsIDE->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT,
- DISPATCH_PROPERTYGET, &params, &result, &excep, &arg);
+ DISPATCH_PROPERTYGET, &params, &result, &excep, &arg);
ReportHRESULT(hr, "Invoke(Solution)");
- if (SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
vsSolution = V_DISPATCH(&result);
- }
+ }
VariantClear(&result);
- }
}
+ }
return hr;
}
-
-//----------------------------------------------------------------------------
///! Get the FullName property from the Solution object
-HRESULT GetSolutionFullName(
- IDispatch* vsSolution,
- std::string& fullName)
+HRESULT GetSolutionFullName(IDispatch* vsSolution, std::string& fullName)
{
HRESULT hr = E_POINTER;
- if (0 != vsSolution)
- {
- DISPID dispid = (DISPID) -1;
- OLECHAR *name = L"FullName";
+ if (0 != vsSolution) {
+ DISPID dispid = (DISPID)-1;
+ OLECHAR* name = L"FullName";
- hr = vsSolution->GetIDsOfNames(IID_NULL, &name, 1,
- LOCALE_USER_DEFAULT, &dispid);
+ hr = vsSolution->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &dispid);
ReportHRESULT(hr, "GetIDsOfNames(FullName)");
- if (SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
DISPPARAMS params;
VARIANT result;
EXCEPINFO excep;
- UINT arg = (UINT) -1;
+ UINT arg = (UINT)-1;
params.rgvarg = 0;
params.rgdispidNamedArgs = 0;
@@ -250,43 +205,36 @@ HRESULT GetSolutionFullName(
memset(&excep, 0, sizeof(excep));
hr = vsSolution->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT,
- DISPATCH_PROPERTYGET, &params, &result, &excep, &arg);
+ DISPATCH_PROPERTYGET, &params, &result, &excep,
+ &arg);
ReportHRESULT(hr, "Invoke(FullName)");
- if (SUCCEEDED(hr))
- {
- fullName = (std::string) (_bstr_t) V_BSTR(&result);
- }
+ if (SUCCEEDED(hr)) {
+ fullName = (std::string)(_bstr_t)V_BSTR(&result);
+ }
VariantClear(&result);
- }
}
+ }
return hr;
}
-
-//----------------------------------------------------------------------------
///! Get the FullName property from the Solution object, given the IDE object
-HRESULT GetIDESolutionFullName(
- IDispatch* vsIDE,
- std::string& fullName)
+HRESULT GetIDESolutionFullName(IDispatch* vsIDE, std::string& fullName)
{
IDispatchPtr vsSolution;
HRESULT hr = GetSolutionObject(vsIDE, vsSolution);
ReportHRESULT(hr, "GetSolutionObject");
- if (SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
GetSolutionFullName(vsSolution, fullName);
ReportHRESULT(hr, "GetSolutionFullName");
- }
+ }
return hr;
}
-
-//----------------------------------------------------------------------------
///! 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)
@@ -301,22 +249,18 @@ HRESULT GetRunningInstances(std::map<std::string, IUnknownPtr>& mrot)
HRESULT hr = GetRunningObjectTable(0, &runningObjectTable);
ReportHRESULT(hr, "GetRunningObjectTable");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
hr = runningObjectTable->EnumRunning(&monikerEnumerator);
ReportHRESULT(hr, "EnumRunning");
- }
+ }
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
hr = monikerEnumerator->Reset();
ReportHRESULT(hr, "Reset");
- }
+ }
- if(SUCCEEDED(hr))
- {
- while (S_OK == monikerEnumerator->Next(1, &moniker, &numFetched))
- {
+ if (SUCCEEDED(hr)) {
+ while (S_OK == monikerEnumerator->Next(1, &moniker, &numFetched)) {
std::string runningObjectName;
IUnknownPtr runningObjectVal;
IBindCtxPtr ctx;
@@ -324,45 +268,37 @@ HRESULT GetRunningInstances(std::map<std::string, IUnknownPtr>& mrot)
hr = CreateBindCtx(0, &ctx);
ReportHRESULT(hr, "CreateBindCtx");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
LPOLESTR displayName = 0;
hr = moniker->GetDisplayName(ctx, 0, &displayName);
ReportHRESULT(hr, "GetDisplayName");
- if (displayName)
- {
- runningObjectName = (std::string) (_bstr_t) displayName;
+ if (displayName) {
+ runningObjectName = (std::string)(_bstr_t)displayName;
CoTaskMemFree(displayName);
- }
+ }
hr = runningObjectTable->GetObject(moniker, &runningObjectVal);
ReportHRESULT(hr, "GetObject");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
mrot.insert(std::make_pair(runningObjectName, runningObjectVal));
- }
}
+ }
numFetched = 0;
moniker = 0;
- }
}
+ }
return hr;
}
-
-//----------------------------------------------------------------------------
///! 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)
+bool FilesSameSolution(const std::string& slnFile, const std::string& slnName)
{
- if (slnFile == "ALL" || slnName == "ALL")
- {
+ if (slnFile == "ALL" || slnName == "ALL") {
return true;
- }
+ }
// Otherwise, make lowercase local copies, convert to Unix slashes, and
// see if the resulting strings are the same:
@@ -374,59 +310,48 @@ bool FilesSameSolution(
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.
-HRESULT FindVisualStudioInstances(
- const std::string& slnFile,
- std::vector<IDispatchPtr>& instances)
+HRESULT FindVisualStudioInstances(const std::string& slnFile,
+ std::vector<IDispatchPtr>& instances)
{
std::map<std::string, IUnknownPtr> mrot;
HRESULT hr = GetRunningInstances(mrot);
ReportHRESULT(hr, "GetRunningInstances");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
std::map<std::string, IUnknownPtr>::iterator it;
- for(it = mrot.begin(); it != mrot.end(); ++it)
- {
+ for (it = mrot.begin(); it != mrot.end(); ++it) {
if (cmSystemTools::StringStartsWith(it->first.c_str(),
- "!VisualStudio.DTE."))
- {
+ "!VisualStudio.DTE.")) {
IDispatchPtr disp(it->second);
- if (disp != (IDispatch*) 0)
- {
+ if (disp != (IDispatch*)0) {
std::string slnName;
hr = GetIDESolutionFullName(disp, slnName);
ReportHRESULT(hr, "GetIDESolutionFullName");
- if (FilesSameSolution(slnFile, slnName))
- {
+ if (FilesSameSolution(slnFile, slnName)) {
instances.push_back(disp);
- //std::cout << "Found Visual Studio instance." << std::endl;
- //std::cout << " ROT entry name: " << it->first << std::endl;
- //std::cout << " ROT entry object: "
+ // std::cout << "Found Visual Studio instance." << std::endl;
+ // std::cout << " ROT entry name: " << it->first << std::endl;
+ // std::cout << " ROT entry object: "
// << (IUnknown*) it->second << std::endl;
- //std::cout << " slnFile: " << slnFile << std::endl;
- //std::cout << " slnName: " << slnName << std::endl;
- }
+ // std::cout << " slnFile: " << slnFile << std::endl;
+ // std::cout << " slnName: " << slnName << std::endl;
}
}
}
}
+ }
return hr;
}
+#endif // defined(HAVE_COMDEF_H)
-#endif //defined(HAVE_COMDEF_H)
-
-
-//----------------------------------------------------------------------------
int cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances(
const std::string& slnFile)
{
@@ -438,22 +363,20 @@ int cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances(
HRESULT hr = CoInitialize(0);
ReportHRESULT(hr, "CoInitialize");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
std::vector<IDispatchPtr> instances;
hr = FindVisualStudioInstances(slnFile, instances);
ReportHRESULT(hr, "FindVisualStudioInstances");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
count = static_cast<int>(instances.size());
- }
+ }
// Force release all COM pointers before CoUninitialize:
instances.clear();
CoUninitialize();
- }
+ }
#else
(void)slnFile;
#endif
@@ -461,15 +384,12 @@ int cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances(
return count;
}
-
-//----------------------------------------------------------------------------
///! 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,
- const bool logErrorsAsMessages)
+int cmCallVisualStudioMacro::CallMacro(const std::string& slnFile,
+ const std::string& macro,
+ const std::string& args,
+ const bool logErrorsAsMessages)
{
int err = 1; // no comdef.h
@@ -481,60 +401,53 @@ int cmCallVisualStudioMacro::CallMacro(
HRESULT hr = CoInitialize(0);
ReportHRESULT(hr, "CoInitialize");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
std::vector<IDispatchPtr> instances;
hr = FindVisualStudioInstances(slnFile, instances);
ReportHRESULT(hr, "FindVisualStudioInstances");
- if(SUCCEEDED(hr))
- {
+ if (SUCCEEDED(hr)) {
err = 0; // no error
std::vector<IDispatchPtr>::iterator it;
- for(it = instances.begin(); it != instances.end(); ++it)
- {
+ for (it = instances.begin(); it != instances.end(); ++it) {
hr = InstanceCallMacro(*it, macro, args);
ReportHRESULT(hr, "InstanceCallMacro");
- if (FAILED(hr))
- {
+ if (FAILED(hr)) {
err = 3; // error attempting to call the macro
- }
}
+ }
- if(0 == instances.size())
- {
+ if (instances.empty()) {
// no instances to call
- //cmSystemTools::Message(
+ // cmSystemTools::Message(
// "cmCallVisualStudioMacro::CallMacro no instances found to call",
// "Warning");
- }
}
+ }
// Force release all COM pointers before CoUninitialize:
instances.clear();
CoUninitialize();
- }
+ }
#else
(void)slnFile;
(void)macro;
(void)args;
- if (LogErrorsAsMessages)
- {
+ if (LogErrorsAsMessages) {
cmSystemTools::Message("cmCallVisualStudioMacro::CallMacro is not "
- "supported on this platform");
- }
+ "supported on this platform");
+ }
#endif
- if (err && LogErrorsAsMessages)
- {
+ if (err && LogErrorsAsMessages) {
std::ostringstream oss;
oss << "cmCallVisualStudioMacro::CallMacro failed, err = " << err;
cmSystemTools::Message(oss.str().c_str());
- }
+ }
return 0;
}
diff --git a/Source/cmCallVisualStudioMacro.h b/Source/cmCallVisualStudioMacro.h
index 09bddfa25..ad35d306a 100644
--- a/Source/cmCallVisualStudioMacro.h
+++ b/Source/cmCallVisualStudioMacro.h
@@ -1,18 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCallVisualStudioMacro_h
#define cmCallVisualStudioMacro_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <string>
/** \class cmCallVisualStudioMacro
* \brief Control class for communicating with CMake's Visual Studio macros
@@ -26,8 +19,7 @@ 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.
- static int CallMacro(const std::string& slnFile,
- const std::string& macro,
+ static int CallMacro(const std::string& slnFile, const std::string& macro,
const std::string& args,
const bool logErrorsAsMessages);
@@ -38,7 +30,6 @@ public:
const std::string& slnFile);
protected:
-
private:
};
diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx
new file mode 100644
index 000000000..d349c9167
--- /dev/null
+++ b/Source/cmCommand.cxx
@@ -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. */
+#include "cmCommand.h"
+
+#include "cmMakefile.h"
+
+class cmExecutionStatus;
+struct cmListFileArgument;
+
+bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus& status)
+{
+ std::vector<std::string> expandedArguments;
+ if (!this->Makefile->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);
+}
+
+const char* cmCommand::GetError()
+{
+ if (this->Error.empty()) {
+ return "unknown error.";
+ }
+ return this->Error.c_str();
+}
+
+void cmCommand::SetError(const std::string& e)
+{
+ this->Error = e;
+}
diff --git a/Source/cmCommand.h b/Source/cmCommand.h
index 49f451b58..ad72fe208 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -1,21 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCommand_h
#define cmCommand_h
-#include "cmObject.h"
-#include "cmListFileCache.h"
-#include "cmMakefile.h"
-#include "cmCommandArgumentsHelper.h"
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+class cmMakefile;
+struct cmListFileArgument;
/** \class cmCommand
* \brief Superclass for all commands in CMake.
@@ -27,16 +22,18 @@
* to support such features as enable/disable, inheritance,
* documentation, and construction.
*/
-class cmCommand : public cmObject
+class cmCommand
{
-public:
- cmTypeMacro(cmCommand, cmObject);
+ CM_DISABLE_COPY(cmCommand)
+public:
/**
- * Construct the command. By default it is enabled with no makefile.
+ * Construct the command. By default it has no makefile.
*/
cmCommand()
- {this->Makefile = 0; this->Enabled = true;}
+ : Makefile(CM_NULLPTR)
+ {
+ }
/**
* Need virtual destructor to destroy real command type.
@@ -46,8 +43,7 @@ public:
/**
* Specify the makefile.
*/
- void SetMakefile(cmMakefile*m)
- {this->Makefile = m; }
+ void SetMakefile(cmMakefile* m) { this->Makefile = m; }
cmMakefile* GetMakefile() { return this->Makefile; }
/**
@@ -56,24 +52,14 @@ public:
* arguments and then invokes the InitialPass.
*/
virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &status)
- {
- std::vector<std::string> expandedArguments;
- if(!this->Makefile->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);
- }
+ cmExecutionStatus& status);
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &) = 0;
+ cmExecutionStatus&) = 0;
/**
* This is called at the end after all the information
@@ -81,7 +67,7 @@ public:
* not implement this method. At this point, reading and
* writing to the cache can be done.
*/
- virtual void FinalPass() {};
+ virtual void FinalPass() {}
/**
* Does this command have a final pass? Query after InitialPass.
@@ -94,101 +80,19 @@ public:
virtual cmCommand* Clone() = 0;
/**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const
- {
- return false;
- }
-
- /**
- * This determines if usage of the method is discouraged or not.
- * This is currently only used for generating the documentation.
- */
- virtual bool IsDiscouraged() const
- {
- return false;
- }
-
- /**
- * This is used to avoid including this command
- * in documentation. This is mainly used by
- * cmMacroHelperCommand and cmFunctionHelperCommand
- * which cannot provide appropriate documentation.
- */
- virtual bool ShouldAppearInDocumentation() const
- {
- return true;
- }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const = 0;
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const = 0;
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const = 0;
-
- /**
- * Enable the command.
- */
- void EnabledOn()
- {this->Enabled = true;}
-
- /**
- * Disable the command.
- */
- void EnabledOff()
- {this->Enabled = false;}
-
- /**
- * Query whether the command is enabled.
- */
- bool GetEnabled() const
- {return this->Enabled;}
-
- /**
- * Disable or enable the command.
- */
- void SetEnabled(bool enabled)
- {this->Enabled = enabled;}
-
- /**
* Return the last error string.
*/
- const char* GetError()
- {
- if(this->Error.length() == 0)
- {
- this->Error = this->GetName();
- this->Error += " unknown error.";
- }
- return this->Error.c_str();
- }
+ const char* GetError();
/**
* Set the error message
*/
- void SetError(const char* e)
- {
- this->Error = this->GetName();
- this->Error += " ";
- this->Error += e;
- }
+ void SetError(const std::string& e);
protected:
cmMakefile* Makefile;
- cmCommandArgumentsHelper Helper;
private:
- bool Enabled;
std::string Error;
};
diff --git a/Source/cmCommandArgumentLexer.cxx b/Source/cmCommandArgumentLexer.cxx
deleted file mode 100644
index e68f6b5fd..000000000
--- a/Source/cmCommandArgumentLexer.cxx
+++ /dev/null
@@ -1,2077 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmStandardIncludes.h"
-
-#line 2 "cmCommandArgumentLexer.cxx"
-
-#line 4 "cmCommandArgumentLexer.cxx"
-
-#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 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#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
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* 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.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmCommandArgument_yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#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
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
- #define YY_LESS_LINENO(n)
-
-/* 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_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.
- */
- yy_size_t 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 cmCommandArgument_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 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 );
-
-#define YY_FLUSH_BUFFER cmCommandArgument_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 );
-
-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
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- cmCommandArgument_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmCommandArgument_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); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmCommandArgument_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(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char 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 yy_fatal_error (yyconst 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 = (size_t) (yy_cp - yy_bp); \
- 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,
- but its presence is necessary. */
-struct yy_trans_info
- {
- flex_int32_t yy_verify;
- flex_int32_t yy_nxt;
- };
-static yyconst 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 flex_int32_t 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, 3, 1, 1, 1, 1,
- 1, 1, 4, 1, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 1, 1, 1,
- 1, 1, 1, 5, 4, 4, 4, 4, 6, 4,
- 4, 4, 4, 4, 4, 4, 4, 7, 4, 4,
- 4, 4, 4, 4, 4, 8, 4, 4, 4, 4,
- 1, 9, 1, 1, 4, 1, 4, 4, 4, 4,
-
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 10, 1, 11, 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 yyconst flex_int32_t yy_meta[12] =
- { 0,
- 1, 2, 3, 4, 3, 4, 4, 4, 3, 5,
- 3
- } ;
-
-static yyconst 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,
- 18, 18, 41, 41, 7, 41, 4, 41, 41, 20,
- 21, 26, 9, 30
- } ;
-
-static yyconst 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,
- 32, 33, 29, 29, 18, 29, 18, 29, 0, 29,
- 29, 29, 29, 29
- } ;
-
-static yyconst 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,
- 17, 17, 26, 17, 18, 18, 21, 21, 25, 21,
- 23, 24, 23, 23, 23, 29, 16, 16, 15, 15,
- 7, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29
- } ;
-
-static yyconst 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,
- 30, 30, 22, 30, 31, 31, 32, 32, 19, 32,
- 34, 18, 34, 34, 34, 7, 6, 5, 4, 3,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29
- } ;
-
-/* 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
-#line 1 "cmCommandArgumentLexer.in.l"
-#line 2 "cmCommandArgumentLexer.in.l"
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex like this:
-
- flex --prefix=cmCommandArgument_yy --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
-
-Modify cmCommandArgumentLexer.cxx:
- - add #include "cmStandardIncludes.h" to top of file
- - put header block at top of file
- - remove TABs
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmCommandArgument_yyalloc, cmCommandArgument_yyrealloc, cmCommandArgument_yyfree
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
- - add "return 0;" to end of cmCommandArgument_yylex
-
-Modify cmCommandArgumentLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
-
-*/
-
-#include "cmStandardLexer.h"
-
-#include "cmCommandArgumentParserHelper.h"
-
-/* Replace the lexer input function. */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
-
-/* Include the set of tokens from the parser. */
-#include "cmCommandArgumentParserTokens.h"
-
-/*--------------------------------------------------------------------------*/
-
-
-#line 508 "cmCommandArgumentLexer.cxx"
-
-#define INITIAL 0
-#define ESCAPES 1
-#define NOESCAPES 2
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#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 cmCommandArgument_yylex_init (yyscan_t* scanner);
-
-int cmCommandArgument_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 cmCommandArgument_yyget_debug (yyscan_t yyscanner );
-
-void cmCommandArgument_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE cmCommandArgument_yyget_extra (yyscan_t yyscanner );
-
-void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner );
-
-void cmCommandArgument_yyset_in (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner );
-
-void cmCommandArgument_yyset_out (FILE * out_str ,yyscan_t yyscanner );
-
-int cmCommandArgument_yyget_leng (yyscan_t yyscanner );
-
-char *cmCommandArgument_yyget_text (yyscan_t yyscanner );
-
-int cmCommandArgument_yyget_lineno (yyscan_t yyscanner );
-
-void cmCommandArgument_yyset_lineno (int line_number ,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 cmCommandArgument_yywrap (yyscan_t yyscanner );
-#else
-extern int cmCommandArgument_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst 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
-#define YY_READ_BUF_SIZE 8192
-#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 fwrite( yytext, yyleng, 1, yyout )
-#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 = '*'; \
- size_t 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 = fread(buf, 1, 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 cmCommandArgument_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int cmCommandArgument_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 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;
-
-#line 64 "cmCommandArgumentLexer.in.l"
-
-
-#line 732 "cmCommandArgumentLexer.cxx"
-
- 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 ) {
- cmCommandArgument_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmCommandArgument_yy_load_buffer_state(yyscanner );
- }
-
- for(;;) /* 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 >= 30 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 41 );
-
-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
-#line 66 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
- return cal_ENVCURLY;
-}
-case 2:
-YY_RULE_SETUP
-#line 72 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
- return cal_NCURLY;
-}
-case 3:
-YY_RULE_SETUP
-#line 78 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
- return cal_ATNAME;
-}
-case 4:
-YY_RULE_SETUP
-#line 84 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DCURLYVariable;
- return cal_DCURLY;
-}
-case 5:
-YY_RULE_SETUP
-#line 91 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->RCURLYVariable;
- return cal_RCURLY;
-}
-case 6:
-YY_RULE_SETUP
-#line 98 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->ATVariable;
- return cal_AT;
-}
-case 7:
-YY_RULE_SETUP
-#line 105 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- return cal_NAME;
-}
-case 8:
-YY_RULE_SETUP
-#line 111 "cmCommandArgumentLexer.in.l"
-{
- if ( !yyextra->HandleEscapeSymbol(yylvalp, *(yytext+1)) )
- {
- return cal_ERROR;
- }
- return cal_SYMBOL;
-}
-case 9:
-/* rule 9 can match eol */
-YY_RULE_SETUP
-#line 119 "cmCommandArgumentLexer.in.l"
-{
- //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
- yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- return cal_SYMBOL;
-}
-case 10:
-YY_RULE_SETUP
-#line 125 "cmCommandArgumentLexer.in.l"
-{
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DOLLARVariable;
- return cal_DOLLAR;
-}
-case 11:
-YY_RULE_SETUP
-#line 131 "cmCommandArgumentLexer.in.l"
-{
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->LCURLYVariable;
- return cal_LCURLY;
-}
-case 12:
-YY_RULE_SETUP
-#line 137 "cmCommandArgumentLexer.in.l"
-{
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
- return cal_BSLASH;
-}
-case 13:
-YY_RULE_SETUP
-#line 143 "cmCommandArgumentLexer.in.l"
-{
- //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
- return cal_SYMBOL;
-}
-case 14:
-YY_RULE_SETUP
-#line 149 "cmCommandArgumentLexer.in.l"
-ECHO;
- YY_BREAK
-#line 943 "cmCommandArgumentLexer.cxx"
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(ESCAPES):
-case YY_STATE_EOF(NOESCAPES):
- yyterminate();
-
- 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
- * cmCommandArgument_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 ( cmCommandArgument_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 */
-return 0; /* this should not happend but it should silence a warning */
-} /* end of cmCommandArgument_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;
-
- 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. */
- cmCommandArgument_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- 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, (size_t) 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;
- cmCommandArgument_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 ((yy_size_t) (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. */
- yy_size_t 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 );
- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
- }
-
- 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 >= 30 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) 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 >= 30 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 29);
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
-#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 = 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. */
- cmCommandArgument_yyrestart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( cmCommandArgument_yywrap(yyscanner ) )
- return EOF;
-
- 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 cmCommandArgument_yyrestart (FILE * input_file , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! YY_CURRENT_BUFFER ){
- cmCommandArgument_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmCommandArgument_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmCommandArgument_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)
-{
- 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);
- */
- cmCommandArgument_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;
- cmCommandArgument_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
- * 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)
-{
- 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 cmCommandArgument_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 );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_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 *) cmCommandArgument_yyalloc(b->yy_buf_size + 2 ,yyscanner );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- cmCommandArgument_yy_init_buffer(b,file ,yyscanner);
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with cmCommandArgument_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
- void cmCommandArgument_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 )
- cmCommandArgument_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
- cmCommandArgument_yyfree((void *) b ,yyscanner );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-
-/* 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.
- */
- static void cmCommandArgument_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);
-
- 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.
- * 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 cmCommandArgument_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 )
- cmCommandArgument_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 cmCommandArgument_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);
-
- /* This block is copied from cmCommandArgument_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 cmCommandArgument_yy_switch_to_buffer. */
- cmCommandArgument_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 cmCommandArgument_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_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 );
- 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 cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner)
-{
- int 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;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmCommandArgument_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()" );
-
- 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. */
- int 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,
- 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()" );
-
- /* 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 cmCommandArgument_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 0;
-
- b = (YY_BUFFER_STATE) cmCommandArgument_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_scan_buffer()" );
-
- b->yy_buf_size = 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 = 0;
- 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;
-
- cmCommandArgument_yy_switch_to_buffer(b ,yyscanner );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to cmCommandArgument_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_BUFFER_STATE cmCommandArgument_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-
- return cmCommandArgument_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to cmCommandArgument_yylex() will
- * scan from a @e copy of @a yybytes.
- * @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 b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
- buf = (char *) cmCommandArgument_yyalloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_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 = cmCommandArgument_yy_scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmCommandArgument_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 yy_fatal_error (yyconst char* msg , yyscan_t)
-{
- (void) 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 cmCommandArgument_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 cmCommandArgument_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 cmCommandArgument_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 *cmCommandArgument_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 *cmCommandArgument_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 cmCommandArgument_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 *cmCommandArgument_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 cmCommandArgument_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
- * @param yyscanner The scanner object.
- */
-void cmCommandArgument_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" , yyscanner);
-
- yylineno = line_number;
-}
-
-/** Set the current column.
- * @param column_no
- * @param yyscanner The scanner object.
- */
-void cmCommandArgument_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" , yyscanner);
-
- 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 cmCommandArgument_yy_switch_to_buffer
- */
-void cmCommandArgument_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)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
-}
-
-int cmCommandArgument_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)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-/* User-visible API */
-
-/* cmCommandArgument_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)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmCommandArgument_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 );
-}
-
-/* cmCommandArgument_yylex_init_extra has the same functionality as cmCommandArgument_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 yyextra field.
- */
-
-int cmCommandArgument_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);
-
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmCommandArgument_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));
-
- cmCommandArgument_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 cmCommandArgument_yylex_destroy(), so don't allocate here.
- */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- 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 = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * cmCommandArgument_yylex_init()
- */
- return 0;
-}
-
-/* cmCommandArgument_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmCommandArgument_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_CURRENT_BUFFER_LVALUE = NULL;
- cmCommandArgument_yypop_buffer_state(yyscanner);
- }
-
- /* Destroy the stack itself. */
- cmCommandArgument_yyfree(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
-
- /* Destroy the start condition stack. */
- cmCommandArgument_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. */
- yy_init_globals( yyscanner);
-
- /* Destroy the main struct (reentrant only). */
- cmCommandArgument_yyfree ( yyscanner , yyscanner );
- yyscanner = NULL;
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
- int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
- int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *cmCommandArgument_yyalloc (yy_size_t size , yyscan_t)
-{
- return (void *) malloc( size );
-}
-
-void *cmCommandArgument_yyrealloc (void * ptr, yy_size_t size , yyscan_t)
-{
- /* 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 (void *) realloc( (char *) ptr, size );
-}
-
-void cmCommandArgument_yyfree (void * ptr , yyscan_t)
-{
- free( (char *) ptr ); /* see cmCommandArgument_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 149 "cmCommandArgumentLexer.in.l"
-
-
-
-/*--------------------------------------------------------------------------*/
-void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes)
-{
- /* Hack into the internal flex-generated scanner to set the state. */
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if(noEscapes)
- {
- BEGIN(NOESCAPES);
- }
- else
- {
- BEGIN(ESCAPES);
- }
-}
-
diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y
deleted file mode 100644
index 48f5c8ecd..000000000
--- a/Source/cmCommandArgumentParser.y
+++ /dev/null
@@ -1,246 +0,0 @@
-%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
- bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
-
-Modify cmCommandArgumentParser.cxx:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - put header block at top of file
-
-*/
-
-#include "cmStandardIncludes.h"
-
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmCommandArgument_yyerror(x) \
- cmCommandArgumentError(yyscanner, x)
-#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
-
-/* Make sure malloc and free are available on QNX. */
-#ifdef __QNX__
-# include <malloc.h>
-#endif
-
-/* Make sure the parser uses standard memory allocation. The default
- generated parser malloc/free declarations do not work on all
- platforms. */
-#include <stdlib.h>
-#define YYMALLOC malloc
-#define YYFREE free
-
-/*-------------------------------------------------------------------------*/
-#include "cmCommandArgumentParserHelper.h" /* Interface to parser object. */
-#include "cmCommandArgumentLexer.h" /* Interface to lexer object. */
-#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL. */
-
-/* Forward declare the lexer entry point. */
-YY_DECL;
-
-/* Internal utility functions. */
-static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-/* Configure the parser to support large input. */
-#define YYMAXDEPTH 100000
-#define YYINITDEPTH 10000
-
-/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label. */
-# pragma warning (disable: 4065) /* Switch statement contains default but no
- case. */
-# pragma warning (disable: 4244) /* loss of precision */
-# pragma warning (disable: 4702) /* unreachable code */
-#endif
-%}
-
-/* Generate a reentrant parser object. */
-%pure_parser
-
-/*
-%union {
- char* string;
-}
-*/
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token cal_ENVCURLY
-%token cal_NCURLY
-%token cal_DCURLY
-%token cal_DOLLAR "$"
-%token cal_LCURLY "{"
-%token cal_RCURLY "}"
-%token cal_NAME
-%token cal_BSLASH "\\"
-%token cal_SYMBOL
-%token cal_AT "@"
-%token cal_ERROR
-%token cal_ATNAME
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-
-Start:
-GoalWithOptionalBackSlash
-{
- $<str>$ = 0;
- yyGetParser->SetResult($<str>1);
-}
-
-GoalWithOptionalBackSlash:
-Goal
-{
- $<str>$ = $<str>1;
-}
-|
-Goal cal_BSLASH
-{
- $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
-
-Goal:
-{
- $<str>$ = 0;
-}
-|
-String Goal
-{
- $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
-
-String:
-OuterText
-{
- $<str>$ = $<str>1;
-}
-|
-Variable
-{
- $<str>$ = $<str>1;
-}
-
-OuterText:
-cal_NAME
-{
- $<str>$ = $<str>1;
-}
-|
-cal_AT
-{
- $<str>$ = $<str>1;
-}
-|
-cal_DOLLAR
-{
- $<str>$ = $<str>1;
-}
-|
-cal_LCURLY
-{
- $<str>$ = $<str>1;
-}
-|
-cal_RCURLY
-{
- $<str>$ = $<str>1;
-}
-|
-cal_SYMBOL
-{
- $<str>$ = $<str>1;
-}
-
-Variable:
-cal_ENVCURLY EnvVarName cal_RCURLY
-{
- $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1,$<str>2);
- //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-|
-cal_NCURLY MultipleIds cal_RCURLY
-{
- $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1,$<str>2);
- //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-|
-cal_DCURLY MultipleIds cal_RCURLY
-{
- $<str>$ = yyGetParser->ExpandVariable($<str>2);
- //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-|
-cal_ATNAME
-{
- $<str>$ = yyGetParser->ExpandVariableForAt($<str>1);
-}
-
-EnvVarName:
-MultipleIds
-{
- $<str>$ = $<str>1;
-}
-|
-cal_SYMBOL EnvVarName
-{
- $<str>$ = $<str>1;
-}
-
-MultipleIds:
-{
- $<str>$ = 0;
-}
-|
-ID MultipleIds
-{
- $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
-
-ID:
-cal_NAME
-{
- $<str>$ = $<str>1;
-}
-|
-Variable
-{
- $<str>$ = $<str>1;
-}
-
-
-%%
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmCommandArgumentError(yyscan_t yyscanner, const char* message)
-{
- yyGetParser->Error(message);
-}
-
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index dbeeb0793..4eb4531f6 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -1,34 +1,30 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCommandArgumentParserHelper.h"
-#include "cmSystemTools.h"
+#include "cmCommandArgumentLexer.h"
#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include "cmCommandArgumentLexer.h"
+#include <iostream>
+#include <sstream>
+#include <string.h>
-int cmCommandArgument_yyparse( yyscan_t yyscanner );
+int cmCommandArgument_yyparse(yyscan_t yyscanner);
//
cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
{
this->WarnUninitialized = false;
this->CheckSystemVars = false;
this->FileLine = -1;
- this->FileName = 0;
+ this->FileName = CM_NULLPTR;
this->RemoveEmpty = true;
this->EmptyVariable[0] = 0;
strcpy(this->DCURLYVariable, "${");
strcpy(this->RCURLYVariable, "}");
- strcpy(this->ATVariable, "@");
+ strcpy(this->ATVariable, "@");
strcpy(this->DOLLARVariable, "$");
strcpy(this->LCURLYVariable, "{");
strcpy(this->BSLASHVariable, "\\");
@@ -37,7 +33,6 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
this->ReplaceAtSyntax = false;
}
-
cmCommandArgumentParserHelper::~cmCommandArgumentParserHelper()
{
this->CleanupParser();
@@ -49,14 +44,13 @@ void cmCommandArgumentParserHelper::SetLineFile(long line, const char* file)
this->FileName = file;
}
-char* cmCommandArgumentParserHelper::AddString(const char* str)
+char* cmCommandArgumentParserHelper::AddString(const std::string& str)
{
- if ( !str || !*str )
- {
+ if (str.empty()) {
return this->EmptyVariable;
- }
- char* stVal = new char[strlen(str)+1];
- strcpy(stVal, str);
+ }
+ char* stVal = new char[str.size() + 1];
+ strcpy(stVal, str.c_str());
this->Variables.push_back(stVal);
return stVal;
}
@@ -64,116 +58,88 @@ char* cmCommandArgumentParserHelper::AddString(const char* str)
char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
const char* var)
{
- if ( !key )
- {
+ if (!key) {
return this->ExpandVariable(var);
- }
- if(!var)
- {
+ }
+ if (!var) {
return this->EmptyVariable;
- }
- if ( strcmp(key, "ENV") == 0 )
- {
- char *ptr = getenv(var);
- if (ptr)
- {
- if (this->EscapeQuotes)
- {
- return this->AddString(cmSystemTools::EscapeQuotes(ptr).c_str());
- }
- else
- {
- return ptr;
- }
+ }
+ if (strcmp(key, "ENV") == 0) {
+ std::string str;
+ if (cmSystemTools::GetEnv(var, str)) {
+ if (this->EscapeQuotes) {
+ return this->AddString(cmSystemTools::EscapeQuotes(str));
}
- return this->EmptyVariable;
+ return this->AddString(str);
}
- if ( strcmp(key, "CACHE") == 0 )
- {
- if(const char* c = this->Makefile->GetCacheManager()->GetCacheValue(var))
- {
- if(this->EscapeQuotes)
- {
- return this->AddString(cmSystemTools::EscapeQuotes(c).c_str());
- }
- else
- {
- return this->AddString(c);
- }
- }
return this->EmptyVariable;
+ }
+ if (strcmp(key, "CACHE") == 0) {
+ if (const char* c =
+ this->Makefile->GetState()->GetInitializedCacheValue(var)) {
+ if (this->EscapeQuotes) {
+ return this->AddString(cmSystemTools::EscapeQuotes(c));
+ }
+ return this->AddString(c);
}
- cmOStringStream e;
+ return this->EmptyVariable;
+ }
+ std::ostringstream e;
e << "Syntax $" << key << "{} is not supported. "
<< "Only ${}, $ENV{}, and $CACHE{} are allowed.";
this->SetError(e.str());
- return 0;
+ return CM_NULLPTR;
}
char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
{
- if(!var)
- {
- return 0;
- }
- if(this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0)
- {
- cmOStringStream ostr;
+ if (!var) {
+ return CM_NULLPTR;
+ }
+ if (this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0) {
+ std::ostringstream ostr;
ostr << this->FileLine;
- return this->AddString(ostr.str().c_str());
- }
+ return this->AddString(ostr.str());
+ }
const char* value = this->Makefile->GetDefinition(var);
- if(!value && !this->RemoveEmpty)
- {
+ 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->WarnUninitialized && !this->Makefile->VariableInitialized(var)) {
if (this->CheckSystemVars ||
cmSystemTools::IsSubDirectory(this->FileName,
this->Makefile->GetHomeDirectory()) ||
- cmSystemTools::IsSubDirectory(this->FileName,
- this->Makefile->GetHomeOutputDirectory()))
- {
- cmOStringStream msg;
- cmListFileBacktrace bt;
- cmListFileContext lfc;
- lfc.FilePath = this->FileName;
- lfc.Line = this->FileLine;
- bt.push_back(lfc);
+ cmSystemTools::IsSubDirectory(
+ this->FileName, this->Makefile->GetHomeOutputDirectory())) {
+ std::ostringstream msg;
msg << "uninitialized variable \'" << var << "\'";
- this->Makefile->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
- msg.str().c_str(), bt);
- }
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
}
- return 0;
}
- if (this->EscapeQuotes && value)
- {
- return this->AddString(cmSystemTools::EscapeQuotes(value).c_str());
- }
- return this->AddString(value);
+ return CM_NULLPTR;
+ }
+ if (this->EscapeQuotes && value) {
+ return this->AddString(cmSystemTools::EscapeQuotes(value));
+ }
+ return this->AddString(value ? value : "");
}
char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
{
- if(this->ReplaceAtSyntax)
- {
+ if (this->ReplaceAtSyntax) {
// try to expand the variable
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)
- {
- return this->AddString(ret);
- }
+ if (!ret && this->RemoveEmpty) {
+ return this->AddString("");
+ }
// if the ret was not 0, then return it
- if(ret)
- {
+ if (ret) {
return ret;
- }
}
+ }
// at this point we want to put it back because of one of these cases:
// - this->ReplaceAtSyntax is false
// - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
@@ -181,84 +147,78 @@ char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
std::string ref = "@";
ref += var;
ref += "@";
- return this->AddString(ref.c_str());
+ return this->AddString(ref);
}
char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
{
- if ( !in1 )
- {
+ if (!in1) {
return in2;
- }
- else if ( !in2 )
- {
+ }
+ if (!in2) {
return in1;
- }
+ }
size_t len = strlen(in1) + strlen(in2) + 1;
- char* out = new char [ len ];
+ char* out = new char[len];
strcpy(out, in1);
strcat(out, in2);
this->Variables.push_back(out);
return out;
}
-void cmCommandArgumentParserHelper::AllocateParserType
-(cmCommandArgumentParserHelper::ParserType* pt,const char* str, int len)
+void cmCommandArgumentParserHelper::AllocateParserType(
+ cmCommandArgumentParserHelper::ParserType* pt, const char* str, int len)
{
- pt->str = 0;
- if ( len == 0 )
- {
+ pt->str = CM_NULLPTR;
+ if (len == 0) {
len = static_cast<int>(strlen(str));
- }
- if ( len == 0 )
- {
+ }
+ if (len == 0) {
return;
- }
- pt->str = new char[ len + 1 ];
+ }
+ pt->str = new char[len + 1];
strncpy(pt->str, str, len);
pt->str[len] = 0;
this->Variables.push_back(pt->str);
}
-bool cmCommandArgumentParserHelper::HandleEscapeSymbol
-(cmCommandArgumentParserHelper::ParserType* pt, char symbol)
+bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
+ cmCommandArgumentParserHelper::ParserType* pt, char symbol)
{
- switch ( symbol )
- {
- case '\\':
- case '"':
- case ' ':
- case '#':
- case '(':
- case ')':
- case '$':
- case '@':
- case '^':
- this->AllocateParserType(pt, &symbol, 1);
- break;
- case ';':
- this->AllocateParserType(pt, "\\;", 2);
- break;
- case 't':
- this->AllocateParserType(pt, "\t", 1);
- break;
- case 'n':
- this->AllocateParserType(pt, "\n", 1);
- break;
- case 'r':
- this->AllocateParserType(pt, "\r", 1);
- break;
- case '0':
- this->AllocateParserType(pt, "\0", 1);
- break;
- default:
- {
- cmOStringStream e;
- e << "Invalid escape sequence \\" << symbol;
- this->SetError(e.str());
- }
- return false;
+ switch (symbol) {
+ case '\\':
+ case '"':
+ case ' ':
+ case '#':
+ case '(':
+ case ')':
+ case '$':
+ case '@':
+ case '^':
+ this->AllocateParserType(pt, &symbol, 1);
+ break;
+ case ';':
+ this->AllocateParserType(pt, "\\;", 2);
+ break;
+ case 't':
+ this->AllocateParserType(pt, "\t", 1);
+ break;
+ case 'n':
+ this->AllocateParserType(pt, "\n", 1);
+ break;
+ case 'r':
+ this->AllocateParserType(pt, "\r", 1);
+ break;
+ case '0':
+ this->AllocateParserType(pt, "\0", 1);
+ break;
+ default: {
+ std::ostringstream e;
+ e << "Invalid escape sequence \\" << symbol;
+ this->SetError(e.str());
}
+ return false;
+ }
return true;
}
@@ -266,10 +226,9 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes);
int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
{
- if ( !str)
- {
+ if (!str) {
return 0;
- }
+ }
this->Verbose = verb;
this->InputBuffer = str;
this->InputBufferPos = 0;
@@ -283,59 +242,48 @@ int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
int res = cmCommandArgument_yyparse(yyscanner);
cmCommandArgument_yylex_destroy(yyscanner);
- if ( res != 0 )
- {
+ if (res != 0) {
return 0;
- }
+ }
this->CleanupParser();
- if ( Verbose )
- {
- std::cerr << "Expanding [" << str << "] produced: ["
- << this->Result.c_str() << "]" << std::endl;
- }
+ if (Verbose) {
+ std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
+ << std::endl;
+ }
return 1;
}
void cmCommandArgumentParserHelper::CleanupParser()
{
std::vector<char*>::iterator sit;
- for ( sit = this->Variables.begin();
- sit != this->Variables.end();
- ++ sit )
- {
- delete [] *sit;
- }
+ for (sit = this->Variables.begin(); sit != this->Variables.end(); ++sit) {
+ delete[] * sit;
+ }
this->Variables.erase(this->Variables.begin(), this->Variables.end());
}
int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen)
{
- if ( maxlen < 1 )
- {
+ if (maxlen < 1) {
return 0;
+ }
+ if (this->InputBufferPos < this->InputBuffer.size()) {
+ buf[0] = this->InputBuffer[this->InputBufferPos++];
+ if (buf[0] == '\n') {
+ this->CurrentLine++;
}
- if ( this->InputBufferPos < this->InputBuffer.size() )
- {
- buf[0] = this->InputBuffer[ this->InputBufferPos++ ];
- if ( buf[0] == '\n' )
- {
- this->CurrentLine ++;
- }
- return(1);
- }
- else
- {
- buf[0] = '\n';
- return( 0 );
- }
+ return (1);
+ }
+ buf[0] = '\n';
+ return (0);
}
void cmCommandArgumentParserHelper::Error(const char* str)
{
unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
- cmOStringStream ostr;
+ std::ostringstream ostr;
ostr << str << " (" << pos << ")";
this->SetError(ostr.str());
}
@@ -349,19 +297,17 @@ void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile* mf)
void cmCommandArgumentParserHelper::SetResult(const char* value)
{
- if ( !value )
- {
+ if (!value) {
this->Result = "";
return;
- }
+ }
this->Result = value;
}
void cmCommandArgumentParserHelper::SetError(std::string const& msg)
{
// Keep only the first error.
- if(this->ErrorString.empty())
- {
+ if (this->ErrorString.empty()) {
this->ErrorString = msg;
- }
+ }
}
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index f8c672fef..465ca9e28 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -1,39 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCommandArgumentParserHelper_h
#define cmCommandArgumentParserHelper_h
-#include "cmStandardIncludes.h"
-
-#define YYSTYPE cmCommandArgumentParserHelper::ParserType
-#define YYSTYPE_IS_DECLARED
-#define YY_EXTRA_TYPE cmCommandArgumentParserHelper*
-#define YY_DECL int cmCommandArgument_yylex(YYSTYPE* yylvalp,\
- yyscan_t yyscanner)
+#include "cmConfigure.h"
-/** \class cmCommandArgumentParserHelper
- * \brief Helper class for parsing java source files
- *
- * Finds dependencies for java file and list of outputs
- */
+#include <string>
+#include <vector>
class cmMakefile;
class cmCommandArgumentParserHelper
{
+ CM_DISABLE_COPY(cmCommandArgumentParserHelper)
+
public:
- typedef struct {
+ struct ParserType
+ {
char* str;
- } ParserType;
+ };
cmCommandArgumentParserHelper();
~cmCommandArgumentParserHelper();
@@ -42,9 +27,9 @@ public:
// For the lexer:
void AllocateParserType(cmCommandArgumentParserHelper::ParserType* pt,
- const char* str, int len = 0);
+ const char* str, int len = 0);
bool HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt,
- char symbol);
+ char symbol);
int LexInput(char* buf, int maxlen);
void Error(const char* str);
@@ -77,16 +62,14 @@ public:
char BSLASHVariable[3];
private:
- cmStdString::size_type InputBufferPos;
- cmStdString InputBuffer;
+ std::string::size_type InputBufferPos;
+ std::string InputBuffer;
std::vector<char> OutputBuffer;
- int CurrentLine;
- int Verbose;
void Print(const char* place, const char* str);
void SafePrintMissing(const char* str, int line, int cnt);
- char* AddString(const char* str);
+ char* AddString(const std::string& str);
void CleanupParser();
void SetError(std::string const& msg);
@@ -94,17 +77,23 @@ private:
std::vector<char*> Variables;
const cmMakefile* Makefile;
std::string Result;
+ std::string ErrorString;
const char* FileName;
+ long FileLine;
+ int CurrentLine;
+ int Verbose;
bool WarnUninitialized;
bool CheckSystemVars;
- long FileLine;
bool EscapeQuotes;
- std::string ErrorString;
bool NoEscapeMode;
bool ReplaceAtSyntax;
bool RemoveEmpty;
};
-#endif
-
+#define YYSTYPE cmCommandArgumentParserHelper::ParserType
+#define YYSTYPE_IS_DECLARED
+#define YY_EXTRA_TYPE cmCommandArgumentParserHelper*
+#define YY_DECL \
+ int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+#endif
diff --git a/Source/cmCommandArgumentParserTokens.h b/Source/cmCommandArgumentParserTokens.h
deleted file mode 100644
index 7fb58e2d9..000000000
--- a/Source/cmCommandArgumentParserTokens.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- cal_ENVCURLY = 258,
- cal_NCURLY = 259,
- cal_DCURLY = 260,
- cal_DOLLAR = 261,
- cal_LCURLY = 262,
- cal_RCURLY = 263,
- cal_NAME = 264,
- cal_BSLASH = 265,
- cal_SYMBOL = 266,
- cal_AT = 267,
- cal_ERROR = 268,
- cal_ATNAME = 269
- };
-#endif
-/* Tokens. */
-#define cal_ENVCURLY 258
-#define cal_NCURLY 259
-#define cal_DCURLY 260
-#define cal_DOLLAR 261
-#define cal_LCURLY 262
-#define cal_RCURLY 263
-#define cal_NAME 264
-#define cal_BSLASH 265
-#define cal_SYMBOL 266
-#define cal_AT 267
-#define cal_ERROR 268
-#define cal_ATNAME 269
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
diff --git a/Source/cmCommandArgumentsHelper.cxx b/Source/cmCommandArgumentsHelper.cxx
index 1d5fc0790..babddbe94 100644
--- a/Source/cmCommandArgumentsHelper.cxx
+++ b/Source/cmCommandArgumentsHelper.cxx
@@ -1,40 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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)
+ : Key(key)
+ , Group(group)
+ , WasActive(false)
+ , ArgumentsBeforeEmpty(true)
+ , CurrentIndex(0)
{
- if (args!=0)
- {
+ if (args != CM_NULLPTR) {
args->AddArgument(this);
- }
+ }
- if (this->Group!=0)
- {
+ if (this->Group != CM_NULLPTR) {
this->Group->ContainedArguments.push_back(this);
- }
+ }
}
void cmCommandArgument::Reset()
{
- this->WasActive =false;
+ this->WasActive = false;
this->CurrentIndex = 0;
this->DoReset();
}
@@ -47,60 +35,40 @@ void cmCommandArgument::Follows(const cmCommandArgument* arg)
void cmCommandArgument::FollowsGroup(const cmCommandArgumentGroup* group)
{
- if (group!=0)
- {
+ if (group != CM_NULLPTR) {
this->ArgumentsBeforeEmpty = false;
- for(std::vector<cmCommandArgument*>::const_iterator
- argIt= group->ContainedArguments.begin();
- argIt != group->ContainedArguments.end();
- ++argIt)
- {
- this->ArgumentsBefore.insert(*argIt);
- }
- }
+ this->ArgumentsBefore.insert(group->ContainedArguments.begin(),
+ group->ContainedArguments.end());
+ }
}
bool cmCommandArgument::MayFollow(const cmCommandArgument* current) const
{
- if (this->ArgumentsBeforeEmpty)
- {
+ if (this->ArgumentsBeforeEmpty) {
return true;
- }
-
- std::set<const cmCommandArgument*>::const_iterator argIt
- = this->ArgumentsBefore.find(current);
- if (argIt != this->ArgumentsBefore.end())
- {
- return true;
- }
-
- return false;
+ }
+ return this->ArgumentsBefore.find(current) != this->ArgumentsBefore.end();
}
bool cmCommandArgument::KeyMatches(const std::string& key) const
{
- if ((this->Key==0) || (this->Key[0]=='\0'))
- {
+ if ((this->Key == CM_NULLPTR) || (this->Key[0] == '\0')) {
return true;
- }
- return (key==this->Key);
+ }
+ return (key == this->Key);
}
void cmCommandArgument::ApplyOwnGroup()
{
- if (this->Group!=0)
- {
- for (std::vector<cmCommandArgument*>::const_iterator
- it = this->Group->ContainedArguments.begin();
- it != this->Group->ContainedArguments.end();
- ++it)
- {
- if(*it != this)
- {
+ 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()
@@ -111,37 +79,31 @@ void cmCommandArgument::Activate()
bool cmCommandArgument::Consume(const std::string& arg)
{
- bool res=this->DoConsume(arg, this->CurrentIndex);
+ 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(0)
+ : cmCommandArgument(args, key, group)
+ , Ignore(CM_NULLPTR)
{
- if ((key==0) || (*key==0))
- {
+ if ((key == CM_NULLPTR) || (*key == 0)) {
this->DataStart = 0;
- }
- else
- {
+ } else {
this->DataStart = 1;
- }
+ }
}
-bool cmCAStringVector::DoConsume(const std::string& arg,unsigned int index)
+bool cmCAStringVector::DoConsume(const std::string& arg, unsigned int index)
{
- if (index >= this->DataStart)
- {
- if ((this->Ignore==0) || (arg != this->Ignore))
- {
+ if (index >= this->DataStart) {
+ if ((this->Ignore == CM_NULLPTR) || (arg != this->Ignore)) {
this->Vector.push_back(arg);
- }
}
+ }
return false;
}
@@ -151,27 +113,22 @@ void cmCAStringVector::DoReset()
this->Vector.clear();
}
-cmCAString::cmCAString(cmCommandArgumentsHelper* args,
- const char* key,
+cmCAString::cmCAString(cmCommandArgumentsHelper* args, const char* key,
cmCommandArgumentGroup* group)
-:cmCommandArgument(args, key, group)
+ : cmCommandArgument(args, key, group)
{
- if ((key==0) || (*key==0))
- {
+ if ((key == CM_NULLPTR) || (*key == 0)) {
this->DataStart = 0;
- }
- else
- {
+ } else {
this->DataStart = 1;
- }
+ }
}
bool cmCAString::DoConsume(const std::string& arg, unsigned int index)
{
- if (index == this->DataStart)
- {
+ if (index == this->DataStart) {
this->String = arg;
- }
+ }
return index >= this->DataStart;
}
@@ -181,19 +138,18 @@ void cmCAString::DoReset()
this->String = "";
}
-cmCAEnabler::cmCAEnabler(cmCommandArgumentsHelper* args,
- const char* key,
+cmCAEnabler::cmCAEnabler(cmCommandArgumentsHelper* args, const char* key,
cmCommandArgumentGroup* group)
-:cmCommandArgument(args, key, group)
-,Enabled(false)
-{}
+ : cmCommandArgument(args, key, group)
+ , Enabled(false)
+{
+}
bool cmCAEnabler::DoConsume(const std::string&, unsigned int index)
{
- if (index==0)
- {
+ if (index == 0) {
this->Enabled = true;
- }
+ }
return true;
}
@@ -202,19 +158,18 @@ void cmCAEnabler::DoReset()
this->Enabled = false;
}
-cmCADisabler::cmCADisabler(cmCommandArgumentsHelper* args,
- const char* key,
+cmCADisabler::cmCADisabler(cmCommandArgumentsHelper* args, const char* key,
cmCommandArgumentGroup* group)
-:cmCommandArgument(args, key, group)
-,Enabled(true)
-{}
+ : cmCommandArgument(args, key, group)
+ , Enabled(true)
+{
+}
bool cmCADisabler::DoConsume(const std::string&, unsigned int index)
{
- if (index==0)
- {
+ if (index == 0) {
this->Enabled = false;
- }
+ }
return true;
}
@@ -225,83 +180,66 @@ void cmCADisabler::DoReset()
void cmCommandArgumentGroup::Follows(const cmCommandArgument* arg)
{
- for(std::vector<cmCommandArgument*>::iterator
- it = this->ContainedArguments.begin();
- it != this->ContainedArguments.end();
- ++it)
- {
+ 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)
- {
+ 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==0)
- {
+ if (args == CM_NULLPTR) {
return;
- }
+ }
- for(std::vector<cmCommandArgument*>::iterator
- argIt = this->Arguments.begin();
- argIt != this->Arguments.end();
- ++argIt)
- {
+ for (std::vector<cmCommandArgument*>::iterator argIt =
+ this->Arguments.begin();
+ argIt != this->Arguments.end(); ++argIt) {
(*argIt)->ApplyOwnGroup();
(*argIt)->Reset();
- }
-
- cmCommandArgument* activeArgument = 0;
- const cmCommandArgument* previousArgument = 0;
- 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)))
- {
+ }
+
+ 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)
- {
+ if (activeArgument) {
bool argDone = activeArgument->Consume(*it);
previousArgument = activeArgument;
- if (argDone)
- {
- activeArgument = 0;
- }
+ if (argDone) {
+ activeArgument = CM_NULLPTR;
}
- else
- {
- if (unconsumedArgs!=0)
- {
+ } 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
index f732f8f1d..44db374d6 100644
--- a/Source/cmCommandArgumentsHelper.h
+++ b/Source/cmCommandArgumentsHelper.h
@@ -1,21 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <set>
+#include <string>
+#include <vector>
-class cmCommandArgumentsHelper;
class cmCommandArgumentGroup;
+class cmCommandArgumentsHelper;
/* cmCommandArgumentsHelper, cmCommandArgumentGroup and cmCommandArgument (i.e.
its derived classes cmCAXXX can be used to simplify the processing of
@@ -41,164 +36,161 @@ For an example see cmExportCommand.cxx.
*/
class cmCommandArgument
{
- public:
- cmCommandArgument(cmCommandArgumentsHelper* args,
- const char* key,
- cmCommandArgumentGroup* group=0);
- 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;
+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=0);
-
- /// 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();
- virtual bool DoConsume(const std::string& arg, unsigned int index);
- virtual void DoReset();
+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=0);
-
- /// 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;
- virtual bool DoConsume(const std::string& arg, unsigned int index);
- virtual void DoReset();
- cmCAString();
+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=0);
-
- /// Has it been enabled ?
- bool IsEnabled() const {return this->Enabled;}
- private:
- bool Enabled;
- virtual bool DoConsume(const std::string& arg, unsigned int index);
- virtual void DoReset();
- cmCAEnabler();
+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=0);
-
- /// Is it still enabled ?
- bool IsEnabled() const {return this->Enabled;}
- private:
- bool Enabled;
- virtual bool DoConsume(const std::string& arg, unsigned int index);
- virtual void DoReset();
- cmCADisabler();
+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);
+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;
+ /// 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;
+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 1e2a85cfb..e1d8ef143 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -1,86 +1,353 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* 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"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmAddCustomCommandCommand.h"
+#include "cmAddCustomTargetCommand.h"
+#include "cmAddDefinitionsCommand.h"
+#include "cmAddDependenciesCommand.h"
+#include "cmAddExecutableCommand.h"
+#include "cmAddLibraryCommand.h"
+#include "cmAddSubDirectoryCommand.h"
+#include "cmAddTestCommand.h"
+#include "cmBreakCommand.h"
+#include "cmBuildCommand.h"
+#include "cmCMakeMinimumRequired.h"
+#include "cmCMakePolicyCommand.h"
+#include "cmConfigureFileCommand.h"
+#include "cmContinueCommand.h"
+#include "cmCreateTestSourceList.h"
+#include "cmDefinePropertyCommand.h"
+#include "cmEnableLanguageCommand.h"
+#include "cmEnableTestingCommand.h"
+#include "cmExecProgramCommand.h"
+#include "cmExecuteProcessCommand.h"
+#include "cmFileCommand.h"
+#include "cmFindFileCommand.h"
+#include "cmFindLibraryCommand.h"
+#include "cmFindPackageCommand.h"
+#include "cmFindPathCommand.h"
+#include "cmFindProgramCommand.h"
+#include "cmForEachCommand.h"
+#include "cmFunctionCommand.h"
+#include "cmGetCMakePropertyCommand.h"
+#include "cmGetDirectoryPropertyCommand.h"
+#include "cmGetFilenameComponentCommand.h"
+#include "cmGetPropertyCommand.h"
+#include "cmGetSourceFilePropertyCommand.h"
+#include "cmGetTargetPropertyCommand.h"
+#include "cmGetTestPropertyCommand.h"
+#include "cmIfCommand.h"
+#include "cmIncludeCommand.h"
+#include "cmIncludeDirectoryCommand.h"
+#include "cmIncludeRegularExpressionCommand.h"
+#include "cmInstallCommand.h"
+#include "cmInstallFilesCommand.h"
+#include "cmInstallTargetsCommand.h"
+#include "cmLinkDirectoriesCommand.h"
+#include "cmListCommand.h"
+#include "cmMacroCommand.h"
+#include "cmMakeDirectoryCommand.h"
+#include "cmMarkAsAdvancedCommand.h"
+#include "cmMathCommand.h"
+#include "cmMessageCommand.h"
+#include "cmOptionCommand.h"
+#include "cmParseArgumentsCommand.h"
+#include "cmProjectCommand.h"
+#include "cmReturnCommand.h"
+#include "cmSeparateArgumentsCommand.h"
+#include "cmSetCommand.h"
+#include "cmSetDirectoryPropertiesCommand.h"
+#include "cmSetPropertyCommand.h"
+#include "cmSetSourceFilesPropertiesCommand.h"
+#include "cmSetTargetPropertiesCommand.h"
+#include "cmSetTestsPropertiesCommand.h"
+#include "cmSiteNameCommand.h"
+#include "cmStringCommand.h"
+#include "cmSubdirCommand.h"
+#include "cmTargetLinkLibrariesCommand.h"
+#include "cmTryCompileCommand.h"
+#include "cmTryRunCommand.h"
+#include "cmUnsetCommand.h"
+#include "cmWhileCommand.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCommands.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmAddCompileOptionsCommand.cxx"
-#include "cmAuxSourceDirectoryCommand.cxx"
-#include "cmBuildNameCommand.cxx"
-#include "cmCMakeHostSystemInformationCommand.cxx"
-#include "cmElseIfCommand.cxx"
-#include "cmExportCommand.cxx"
-#include "cmExportLibraryDependencies.cxx"
-#include "cmFLTKWrapUICommand.cxx"
-#include "cmIncludeExternalMSProjectCommand.cxx"
-#include "cmInstallProgramsCommand.cxx"
-#include "cmLinkLibrariesCommand.cxx"
-#include "cmLoadCacheCommand.cxx"
-#include "cmOutputRequiredFilesCommand.cxx"
-#include "cmQTWrapCPPCommand.cxx"
-#include "cmQTWrapUICommand.cxx"
-#include "cmRemoveCommand.cxx"
-#include "cmRemoveDefinitionsCommand.cxx"
-#include "cmSourceGroupCommand.cxx"
-#include "cmSubdirDependsCommand.cxx"
-#include "cmTargetCompileDefinitionsCommand.cxx"
-#include "cmTargetCompileOptionsCommand.cxx"
-#include "cmTargetIncludeDirectoriesCommand.cxx"
-#include "cmTargetPropCommandBase.cxx"
-#include "cmUseMangledMesaCommand.cxx"
-#include "cmUtilitySourceCommand.cxx"
-#include "cmVariableRequiresCommand.cxx"
-#include "cmVariableWatchCommand.cxx"
+#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"
+#endif
-#include "cmWriteFileCommand.cxx"
+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("get_directory_property",
+ new 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);
+ 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);
-// This one must be last because it includes windows.h and
-// windows.h #defines GetCurrentDirectory which is a member
-// of cmMakefile
-#include "cmLoadCommandCommand.cxx"
-#endif
+ 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.");
+ state->AddUnexpectedCommand(
+ "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.");
+ 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.");
+ 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.");
+ 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.");
+ 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.");
-void GetPredefinedCommands(std::list<cmCommand*>&
#if defined(CMAKE_BUILD_WITH_CMAKE)
- commands
+ 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);
+
+ state->AddDisallowedCommand(
+ "build_name", new cmBuildNameCommand, cmPolicies::CMP0036,
+ "The build_name command should not be called; see CMP0036.");
+ state->AddDisallowedCommand(
+ "use_mangled_mesa", new cmUseMangledMesaCommand, cmPolicies::CMP0030,
+ "The use_mangled_mesa command should not be called; see CMP0030.");
+
#endif
- )
+}
+
+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("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);
+ 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);
+ state->AddBuiltinCommand("set_source_files_properties",
+ new cmSetSourceFilesPropertiesCommand);
+ state->AddBuiltinCommand("set_target_properties",
+ new 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)
- commands.push_back(new cmAddCompileOptionsCommand);
- commands.push_back(new cmAuxSourceDirectoryCommand);
- commands.push_back(new cmBuildNameCommand);
- commands.push_back(new cmCMakeHostSystemInformationCommand);
- commands.push_back(new cmElseIfCommand);
- commands.push_back(new cmExportCommand);
- commands.push_back(new cmExportLibraryDependenciesCommand);
- commands.push_back(new cmFLTKWrapUICommand);
- commands.push_back(new cmIncludeExternalMSProjectCommand);
- commands.push_back(new cmInstallProgramsCommand);
- commands.push_back(new cmLinkLibrariesCommand);
- commands.push_back(new cmLoadCacheCommand);
- commands.push_back(new cmLoadCommandCommand);
- commands.push_back(new cmOutputRequiredFilesCommand);
- commands.push_back(new cmQTWrapCPPCommand);
- commands.push_back(new cmQTWrapUICommand);
- commands.push_back(new cmRemoveCommand);
- commands.push_back(new cmRemoveDefinitionsCommand);
- commands.push_back(new cmSourceGroupCommand);
- commands.push_back(new cmSubdirDependsCommand);
- commands.push_back(new cmTargetIncludeDirectoriesCommand);
- commands.push_back(new cmTargetCompileDefinitionsCommand);
- commands.push_back(new cmTargetCompileOptionsCommand);
- commands.push_back(new cmUseMangledMesaCommand);
- commands.push_back(new cmUtilitySourceCommand);
- commands.push_back(new cmVariableRequiresCommand);
- commands.push_back(new cmVariableWatchCommand);
- commands.push_back(new cmWriteFileCommand);
+ 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);
+ state->AddBuiltinCommand("target_compile_definitions",
+ new cmTargetCompileDefinitionsCommand);
+ state->AddBuiltinCommand("target_compile_features",
+ new cmTargetCompileFeaturesCommand);
+ state->AddBuiltinCommand("target_compile_options",
+ new cmTargetCompileOptionsCommand);
+ state->AddBuiltinCommand("target_include_directories",
+ new cmTargetIncludeDirectoriesCommand);
+ state->AddBuiltinCommand("target_sources", new cmTargetSourcesCommand);
+
+ state->AddDisallowedCommand(
+ "export_library_dependencies", new cmExportLibraryDependenciesCommand,
+ cmPolicies::CMP0033,
+ "The export_library_dependencies command should not be called; "
+ "see CMP0033.");
+ state->AddDisallowedCommand(
+ "load_command", new cmLoadCommandCommand, cmPolicies::CMP0031,
+ "The load_command command should not be called; see CMP0031.");
+ state->AddDisallowedCommand(
+ "output_required_files", new cmOutputRequiredFilesCommand,
+ cmPolicies::CMP0032,
+ "The output_required_files command should not be called; see CMP0032.");
+ state->AddDisallowedCommand(
+ "subdir_depends", new cmSubdirDependsCommand, cmPolicies::CMP0029,
+ "The subdir_depends command should not be called; see CMP0029.");
+ state->AddDisallowedCommand(
+ "utility_source", new cmUtilitySourceCommand, cmPolicies::CMP0034,
+ "The utility_source command should not be called; see CMP0034.");
+ state->AddDisallowedCommand(
+ "variable_requires", new cmVariableRequiresCommand, cmPolicies::CMP0035,
+ "The variable_requires command should not be called; see CMP0035.");
#endif
}
+
+void GetProjectCommandsInScriptMode(cmState* state)
+{
+#define CM_UNEXPECTED_PROJECT_COMMAND(NAME) \
+ state->AddUnexpectedCommand(NAME, "command is not scriptable")
+
+ CM_UNEXPECTED_PROJECT_COMMAND("add_compile_options");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_custom_command");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_custom_target");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_definitions");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_dependencies");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_executable");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_library");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_subdirectory");
+ CM_UNEXPECTED_PROJECT_COMMAND("add_test");
+ CM_UNEXPECTED_PROJECT_COMMAND("aux_source_directory");
+ CM_UNEXPECTED_PROJECT_COMMAND("build_command");
+ CM_UNEXPECTED_PROJECT_COMMAND("create_test_sourcelist");
+ CM_UNEXPECTED_PROJECT_COMMAND("define_property");
+ CM_UNEXPECTED_PROJECT_COMMAND("enable_language");
+ CM_UNEXPECTED_PROJECT_COMMAND("enable_testing");
+ CM_UNEXPECTED_PROJECT_COMMAND("export");
+ CM_UNEXPECTED_PROJECT_COMMAND("fltk_wrap_ui");
+ CM_UNEXPECTED_PROJECT_COMMAND("get_source_file_property");
+ CM_UNEXPECTED_PROJECT_COMMAND("get_target_property");
+ CM_UNEXPECTED_PROJECT_COMMAND("get_test_property");
+ CM_UNEXPECTED_PROJECT_COMMAND("include_directories");
+ CM_UNEXPECTED_PROJECT_COMMAND("include_external_msproject");
+ CM_UNEXPECTED_PROJECT_COMMAND("include_regular_expression");
+ CM_UNEXPECTED_PROJECT_COMMAND("install");
+ CM_UNEXPECTED_PROJECT_COMMAND("link_directories");
+ CM_UNEXPECTED_PROJECT_COMMAND("link_libraries");
+ CM_UNEXPECTED_PROJECT_COMMAND("load_cache");
+ CM_UNEXPECTED_PROJECT_COMMAND("project");
+ CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_cpp");
+ CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_ui");
+ CM_UNEXPECTED_PROJECT_COMMAND("remove_definitions");
+ CM_UNEXPECTED_PROJECT_COMMAND("set_source_files_properties");
+ CM_UNEXPECTED_PROJECT_COMMAND("set_target_properties");
+ CM_UNEXPECTED_PROJECT_COMMAND("set_tests_properties");
+ CM_UNEXPECTED_PROJECT_COMMAND("source_group");
+ CM_UNEXPECTED_PROJECT_COMMAND("target_compile_definitions");
+ CM_UNEXPECTED_PROJECT_COMMAND("target_compile_features");
+ CM_UNEXPECTED_PROJECT_COMMAND("target_compile_options");
+ CM_UNEXPECTED_PROJECT_COMMAND("target_include_directories");
+ CM_UNEXPECTED_PROJECT_COMMAND("target_link_libraries");
+ CM_UNEXPECTED_PROJECT_COMMAND("target_sources");
+ CM_UNEXPECTED_PROJECT_COMMAND("try_compile");
+ CM_UNEXPECTED_PROJECT_COMMAND("try_run");
+
+ // deprected commands
+ CM_UNEXPECTED_PROJECT_COMMAND("export_library_dependencies");
+ CM_UNEXPECTED_PROJECT_COMMAND("load_command");
+ CM_UNEXPECTED_PROJECT_COMMAND("output_required_files");
+ CM_UNEXPECTED_PROJECT_COMMAND("subdir_depends");
+ CM_UNEXPECTED_PROJECT_COMMAND("utility_source");
+ CM_UNEXPECTED_PROJECT_COMMAND("variable_requires");
+
+#undef CM_UNEXPECTED_PROJECT_COMMAND
+}
diff --git a/Source/cmCommands.h b/Source/cmCommands.h
index c56673fed..1f8fafb46 100644
--- a/Source/cmCommands.h
+++ b/Source/cmCommands.h
@@ -1,29 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCommands_h
#define cmCommands_h
-#include "cmStandardIncludes.h"
-class cmCommand;
+class cmState;
+
/**
- * Global function to return all compiled in commands.
- * To add a new command edit cmCommands.cxx or cmBootstrapCommands[12].cxx
- * and add your command.
- * It is up to the caller to delete the commands created by this
- * call.
+ * Global function to register all compiled in commands.
+ * To add a new command edit cmCommands.cxx and add your command.
+ * It is up to the caller to delete the commands created by this call.
*/
-void GetBootstrapCommands1(std::list<cmCommand*>& commands);
-void GetBootstrapCommands2(std::list<cmCommand*>& commands);
-void GetPredefinedCommands(std::list<cmCommand*>& commands);
-
+void GetScriptingCommands(cmState* state);
+void GetProjectCommands(cmState* state);
+void GetProjectCommandsInScriptMode(cmState* state);
#endif
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
new file mode 100644
index 000000000..391d65c40
--- /dev/null
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -0,0 +1,238 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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"
+#include "cmLinkLineComputer.h"
+#include "cmLocalCommonGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmSourceFile.h"
+#include "cmStateTypes.h"
+
+cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
+ : GeneratorTarget(gt)
+ , Makefile(gt->Makefile)
+ , LocalGenerator(static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
+ , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>(
+ gt->LocalGenerator->GetGlobalGenerator()))
+ , ConfigName(LocalGenerator->GetConfigName())
+{
+}
+
+cmCommonTargetGenerator::~cmCommonTargetGenerator()
+{
+}
+
+std::string const& cmCommonTargetGenerator::GetConfigName() const
+{
+ return this->ConfigName;
+}
+
+const char* cmCommonTargetGenerator::GetFeature(const std::string& feature)
+{
+ return this->GeneratorTarget->GetFeature(feature, this->ConfigName);
+}
+
+void cmCommonTargetGenerator::AddModuleDefinitionFlag(
+ cmLinkLineComputer* linkLineComputer, std::string& flags)
+{
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+ if (!mdi || mdi->DefFile.empty()) {
+ return;
+ }
+
+ // TODO: Create a per-language flag variable.
+ const char* defFileFlag =
+ this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+ if (!defFileFlag) {
+ return;
+ }
+
+ // 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);
+}
+
+void cmCommonTargetGenerator::AppendFortranFormatFlags(
+ std::string& flags, cmSourceFile const& source)
+{
+ const char* srcfmt = source.GetProperty("Fortran_FORMAT");
+ cmOutputConverter::FortranFormat format =
+ cmOutputConverter::GetFortranFormat(srcfmt);
+ if (format == cmOutputConverter::FortranFormatNone) {
+ const char* tgtfmt = this->GeneratorTarget->GetProperty("Fortran_FORMAT");
+ format = cmOutputConverter::GetFortranFormat(tgtfmt);
+ }
+ const char* var = CM_NULLPTR;
+ switch (format) {
+ case cmOutputConverter::FortranFormatFixed:
+ var = "CMAKE_Fortran_FORMAT_FIXED_FLAG";
+ break;
+ case cmOutputConverter::FortranFormatFree:
+ var = "CMAKE_Fortran_FORMAT_FREE_FLAG";
+ break;
+ default:
+ break;
+ }
+ if (var) {
+ this->LocalGenerator->AppendFlags(flags,
+ this->Makefile->GetDefinition(var));
+ }
+}
+
+std::string cmCommonTargetGenerator::GetFlags(const std::string& l)
+{
+ ByLanguageMap::iterator i = this->FlagsByLanguage.find(l);
+ if (i == this->FlagsByLanguage.end()) {
+ std::string flags;
+
+ this->LocalGenerator->GetTargetCompileFlags(this->GeneratorTarget,
+ this->ConfigName, l, flags);
+
+ ByLanguageMap::value_type entry(l, flags);
+ i = this->FlagsByLanguage.insert(entry).first;
+ }
+ return i->second;
+}
+
+std::string cmCommonTargetGenerator::GetDefines(const std::string& l)
+{
+ ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
+ if (i == this->DefinesByLanguage.end()) {
+ std::set<std::string> defines;
+ this->LocalGenerator->GetTargetDefines(this->GeneratorTarget,
+ this->ConfigName, l, defines);
+
+ std::string definesString;
+ this->LocalGenerator->JoinDefines(defines, definesString, l);
+
+ ByLanguageMap::value_type entry(l, definesString);
+ i = this->DefinesByLanguage.insert(entry).first;
+ }
+ return i->second;
+}
+
+std::string cmCommonTargetGenerator::GetIncludes(std::string const& l)
+{
+ ByLanguageMap::iterator i = this->IncludesByLanguage.find(l);
+ if (i == this->IncludesByLanguage.end()) {
+ std::string includes;
+ this->AddIncludeFlags(includes, l);
+ ByLanguageMap::value_type entry(l, includes);
+ i = this->IncludesByLanguage.insert(entry).first;
+ }
+ return i->second;
+}
+
+std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
+ const
+{
+ std::vector<std::string> dirs;
+ std::set<cmGeneratorTarget const*> emitted;
+ 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()
+ // 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);
+ }
+ }
+ }
+ return dirs;
+}
+
+std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const
+{
+ std::string compilePdbPath;
+ if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
+ return compilePdbPath;
+ }
+ compilePdbPath =
+ this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName());
+ if (compilePdbPath.empty()) {
+ // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`.
+ // A trailing slash tells the toolchain to add its default file name.
+ compilePdbPath = this->GeneratorTarget->GetSupportDirectory() + "/";
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`.
+ compilePdbPath += this->GeneratorTarget->GetName();
+ compilePdbPath += ".pdb";
+ }
+ }
+
+ return compilePdbPath;
+}
+
+std::string cmCommonTargetGenerator::GetManifests()
+{
+ std::vector<cmSourceFile const*> manifest_srcs;
+ 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()),
+ cmOutputConverter::SHELL));
+ }
+
+ return cmJoin(manifests, " ");
+}
+
+void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
+ const std::string& lang,
+ 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";
+ const char* flag = this->Makefile->GetDefinition(fvar);
+
+ // Skip if no such flag.
+ if (!flag) {
+ return;
+ }
+
+ // Lookup the target version information.
+ int major;
+ int minor;
+ int patch;
+ this->GeneratorTarget->GetTargetVersion(so, major, minor, patch);
+ if (major > 0 || minor > 0 || patch > 0) {
+ // Append the flag since a non-zero version is specified.
+ std::ostringstream vflag;
+ vflag << flag << major << "." << minor << "." << patch;
+ this->LocalGenerator->AppendFlags(flags, vflag.str());
+ }
+}
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
new file mode 100644
index 000000000..c36145fe2
--- /dev/null
+++ b/Source/cmCommonTargetGenerator.h
@@ -0,0 +1,66 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCommonTargetGenerator_h
+#define cmCommonTargetGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+class cmGlobalCommonGenerator;
+class cmLinkLineComputer;
+class cmLocalCommonGenerator;
+class cmMakefile;
+class cmSourceFile;
+
+/** \class cmCommonTargetGenerator
+ * \brief Common infrastructure for Makefile and Ninja per-target generators
+ */
+class cmCommonTargetGenerator
+{
+public:
+ cmCommonTargetGenerator(cmGeneratorTarget* gt);
+ virtual ~cmCommonTargetGenerator();
+
+ std::string const& GetConfigName() const;
+
+protected:
+ // Feature query methods.
+ const char* GetFeature(const std::string& feature);
+
+ // Helper to add flag for windows .def file.
+ void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
+ std::string& flags);
+
+ cmGeneratorTarget* GeneratorTarget;
+ cmMakefile* Makefile;
+ cmLocalCommonGenerator* LocalGenerator;
+ cmGlobalCommonGenerator* GlobalGenerator;
+ std::string ConfigName;
+
+ void AppendFortranFormatFlags(std::string& flags,
+ cmSourceFile const& source);
+
+ virtual void AddIncludeFlags(std::string& flags,
+ std::string const& lang) = 0;
+
+ void AppendOSXVerFlag(std::string& flags, const std::string& lang,
+ const char* name, bool so);
+
+ typedef std::map<std::string, std::string> ByLanguageMap;
+ std::string GetFlags(const std::string& l);
+ ByLanguageMap FlagsByLanguage;
+ std::string GetDefines(const std::string& l);
+ ByLanguageMap DefinesByLanguage;
+ std::string GetIncludes(std::string const& l);
+ ByLanguageMap IncludesByLanguage;
+ std::string GetManifests();
+
+ std::vector<std::string> GetLinkedTargetDirectories() const;
+ std::string ComputeTargetCompilePDB() const;
+};
+
+#endif
diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx
index 5bec6a1ec..a02d8854b 100644
--- a/Source/cmComputeComponentGraph.cxx
+++ b/Source/cmComputeComponentGraph.cxx
@@ -1,23 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeComponentGraph.h"
#include <algorithm>
#include <assert.h>
-//----------------------------------------------------------------------------
-cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input):
- InputGraph(input)
+cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input)
+ : InputGraph(input)
{
// Identify components.
this->Tarjan();
@@ -28,16 +18,14 @@ cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input):
this->TransferEdges();
}
-//----------------------------------------------------------------------------
cmComputeComponentGraph::~cmComputeComponentGraph()
{
}
-//----------------------------------------------------------------------------
void cmComputeComponentGraph::Tarjan()
{
int n = static_cast<int>(this->InputGraph.size());
- TarjanEntry entry = {0,0};
+ TarjanEntry entry = { 0, 0 };
this->TarjanEntries.resize(0);
this->TarjanEntries.resize(n, entry);
this->TarjanComponents.resize(0);
@@ -45,20 +33,17 @@ void cmComputeComponentGraph::Tarjan()
this->TarjanWalkId = 0;
this->TarjanVisited.resize(0);
this->TarjanVisited.resize(n, 0);
- for(int i = 0; i < n; ++i)
- {
+ for (int i = 0; i < n; ++i) {
// Start a new DFS from this node if it has never been visited.
- if(!this->TarjanVisited[i])
- {
+ if (!this->TarjanVisited[i]) {
assert(this->TarjanStack.empty());
++this->TarjanWalkId;
this->TarjanIndex = 0;
this->TarjanVisit(i);
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeComponentGraph::TarjanVisit(int i)
{
// We are now visiting this node.
@@ -72,41 +57,35 @@ 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)
- {
+ for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
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
// it must not belong to the same component and it has already
// been assigned to a component.
- if(this->TarjanVisited[j] > 0 &&
- this->TarjanVisited[j] < this->TarjanWalkId)
- {
+ if (this->TarjanVisited[j] > 0 &&
+ this->TarjanVisited[j] < this->TarjanWalkId) {
continue;
- }
+ }
// Visit the destination if it has not yet been visited.
- if(!this->TarjanVisited[j])
- {
+ if (!this->TarjanVisited[j]) {
this->TarjanVisit(j);
- }
+ }
// If the destination has not yet been assigned to a component,
// check if it has a better root for the current object.
- if(this->TarjanComponents[j] < 0)
- {
- if(this->TarjanEntries[this->TarjanEntries[j].Root].VisitIndex <
- this->TarjanEntries[this->TarjanEntries[i].Root].VisitIndex)
- {
+ if (this->TarjanComponents[j] < 0) {
+ if (this->TarjanEntries[this->TarjanEntries[j].Root].VisitIndex <
+ this->TarjanEntries[this->TarjanEntries[i].Root].VisitIndex) {
this->TarjanEntries[i].Root = this->TarjanEntries[j].Root;
- }
}
}
+ }
// Check if we have found a component.
- if(this->TarjanEntries[i].Root == i)
- {
+ if (this->TarjanEntries[i].Root == i) {
// Yes. Create it.
int c = static_cast<int>(this->Components.size());
this->Components.push_back(NodeList());
@@ -114,8 +93,7 @@ void cmComputeComponentGraph::TarjanVisit(int i)
// Populate the component list.
int j;
- do
- {
+ do {
// Get the next member of the component.
j = this->TarjanStack.top();
this->TarjanStack.pop();
@@ -126,34 +104,30 @@ void cmComputeComponentGraph::TarjanVisit(int i)
// Store the node in its component.
component.push_back(j);
- } while(j != i);
+ } while (j != i);
// Sort the component members for clarity.
std::sort(component.begin(), component.end());
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeComponentGraph::TransferEdges()
{
// Map inter-component edges in the original graph to edges in the
// component graph.
int n = static_cast<int>(this->InputGraph.size());
- for(int i=0; i < n; ++i)
- {
+ 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)
- {
+ for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
int j = *ni;
int j_component = this->TarjanComponents[j];
- if(i_component != j_component)
- {
+ 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()));
- }
}
}
+ }
}
diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h
index a2ce946c1..8cd4fe73a 100644
--- a/Source/cmComputeComponentGraph.h
+++ b/Source/cmComputeComponentGraph.h
@@ -1,22 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmComputeComponentGraph_h
#define cmComputeComponentGraph_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGraphAdjacencyList.h"
#include <stack>
+#include <vector>
/** \class cmComputeComponentGraph
* \brief Analyze a graph to determine strongly connected components.
@@ -40,20 +32,24 @@ public:
~cmComputeComponentGraph();
/** Get the adjacency list of the component graph. */
- Graph const& GetComponentGraph() const
- { return this->ComponentGraph; }
+ Graph const& GetComponentGraph() const { return this->ComponentGraph; }
EdgeList const& GetComponentGraphEdges(int c) const
- { return this->ComponentGraph[c]; }
+ {
+ return this->ComponentGraph[c];
+ }
/** Get map from component index to original node indices. */
std::vector<NodeList> const& GetComponents() const
- { return this->Components; }
- NodeList const& GetComponent(int c) const
- { return this->Components[c]; }
+ {
+ return this->Components;
+ }
+ NodeList const& GetComponent(int c) const { return this->Components[c]; }
/** Get map from original node index to component index. */
std::vector<int> const& GetComponentMap() const
- { return this->TarjanComponents; }
+ {
+ return this->TarjanComponents;
+ }
private:
void TransferEdges();
@@ -67,17 +63,17 @@ private:
int Root;
int VisitIndex;
};
- int TarjanWalkId;
std::vector<int> TarjanVisited;
std::vector<int> TarjanComponents;
std::vector<TarjanEntry> TarjanEntries;
+ std::vector<NodeList> Components;
std::stack<int> TarjanStack;
+ int TarjanWalkId;
int TarjanIndex;
void Tarjan();
void TarjanVisit(int i);
// Connected components.
- std::vector<NodeList> Components;
};
#endif
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index dec2b54d1..9c516ee8d 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -1,26 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeLinkDepends.h"
+#include "cmAlgorithms.h"
#include "cmComputeComponentGraph.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
-#include <cmsys/stl/algorithm>
-
+#include <algorithm>
#include <assert.h>
+#include <iterator>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <utility>
/*
@@ -166,25 +165,27 @@ guaranteed to be acyclic.
The final list of items produced by this procedure consists of the
original user link line followed by minimal additional items needed to
-satisfy dependencies.
+satisfy dependencies. The final list is then filtered to de-duplicate
+items that we know the linker will re-use automatically (shared libs).
*/
-//----------------------------------------------------------------------------
-cmComputeLinkDepends
-::cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget* head)
+cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
+ const std::string& config)
{
// Store context information.
this->Target = target;
- this->HeadTarget = head;
- this->Makefile = this->Target->GetMakefile();
- this->LocalGenerator = this->Makefile->GetLocalGenerator();
- this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
+ this->Makefile = this->Target->Target->GetMakefile();
+ this->GlobalGenerator =
+ this->Target->GetLocalGenerator()->GetGlobalGenerator();
this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
// The configuration being linked.
- this->Config = (config && *config)? config : 0;
- this->LinkType = this->Target->ComputeLinkType(this->Config);
+ this->HasConfig = !config.empty();
+ this->Config = (this->HasConfig) ? config : std::string();
+ std::vector<std::string> debugConfigs =
+ this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+ this->LinkType = CMP0003_ComputeLinkType(this->Config, debugConfigs);
// Enable debug mode if requested.
this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");
@@ -193,28 +194,20 @@ cmComputeLinkDepends
this->OldLinkDirMode = false;
// No computation has been done.
- this->CCG = 0;
+ this->CCG = CM_NULLPTR;
}
-//----------------------------------------------------------------------------
cmComputeLinkDepends::~cmComputeLinkDepends()
{
- for(std::vector<DependSetList*>::iterator
- i = this->InferredDependSets.begin();
- i != this->InferredDependSets.end(); ++i)
- {
- delete *i;
- }
+ cmDeleteAll(this->InferredDependSets);
delete this->CCG;
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::SetOldLinkDirMode(bool b)
{
this->OldLinkDirMode = b;
}
-//----------------------------------------------------------------------------
std::vector<cmComputeLinkDepends::LinkEntry> const&
cmComputeLinkDepends::Compute()
{
@@ -222,23 +215,21 @@ cmComputeLinkDepends::Compute()
this->AddDirectLinkEntries();
// Complete the breadth-first search of dependencies.
- while(!this->BFSQueue.empty())
- {
+ while (!this->BFSQueue.empty()) {
// Get the next entry.
BFSEntry qe = this->BFSQueue.front();
this->BFSQueue.pop();
// Follow the entry's dependencies.
this->FollowLinkEntry(qe);
- }
+ }
// Complete the search of shared library dependencies.
- while(!this->SharedDepQueue.empty())
- {
+ while (!this->SharedDepQueue.empty()) {
// Handle the next entry.
this->HandleSharedDependency(this->SharedDepQueue.front());
this->SharedDepQueue.pop();
- }
+ }
// Infer dependencies of targets for which they were not known.
this->InferDependencies();
@@ -247,60 +238,67 @@ cmComputeLinkDepends::Compute()
this->CleanConstraintGraph();
// Display the constraint graph.
- if(this->DebugMode)
- {
- fprintf(stderr,
- "---------------------------------------"
- "---------------------------------------\n");
+ if (this->DebugMode) {
+ fprintf(stderr, "---------------------------------------"
+ "---------------------------------------\n");
fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
- this->Target->GetName(), this->Config?this->Config:"noconfig");
+ this->Target->GetName().c_str(),
+ this->HasConfig ? this->Config.c_str() : "noconfig");
this->DisplayConstraintGraph();
- }
+ }
// Compute the final ordering.
this->OrderLinkEntires();
// Compute the final set of link entries.
- for(std::vector<int>::const_iterator li = this->FinalLinkOrder.begin();
- li != this->FinalLinkOrder.end(); ++li)
- {
- this->FinalLinkEntries.push_back(this->EntryList[*li]);
- }
+ // 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;
+ 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.
+ bool uniquify = t && t->GetType() == cmStateEnums::SHARED_LIBRARY;
+ if (!uniquify || emmitted.insert(i).second) {
+ this->FinalLinkEntries.push_back(e);
+ }
+ }
+ // Reverse the resulting order since we iterated in reverse.
+ std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end());
// Display the final set.
- if(this->DebugMode)
- {
+ if (this->DebugMode) {
this->DisplayFinalEntries();
- }
+ }
return this->FinalLinkEntries;
}
-//----------------------------------------------------------------------------
-std::map<cmStdString, int>::iterator
-cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
+std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
+ std::string const& item)
{
- std::map<cmStdString, int>::value_type
- index_entry(item, static_cast<int>(this->EntryList.size()));
- std::map<cmStdString, int>::iterator
- lei = this->LinkEntryIndex.insert(index_entry).first;
+ std::map<std::string, 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(0);
+ this->InferredDependSets.push_back(CM_NULLPTR);
this->EntryConstraintGraph.push_back(EdgeList());
return lei;
}
-//----------------------------------------------------------------------------
-int cmComputeLinkDepends::AddLinkEntry(int depender_index,
- std::string const& item)
+int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
{
// Check if the item entry has already been added.
- std::map<cmStdString, int>::iterator lei = this->LinkEntryIndex.find(item);
- if(lei != this->LinkEntryIndex.end())
- {
+ std::map<std::string, int>::iterator 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;
- }
+ }
// Allocate a spot for the item entry.
lei = this->AllocateLinkEntry(item);
@@ -309,129 +307,112 @@ int cmComputeLinkDepends::AddLinkEntry(int depender_index,
int index = lei->second;
LinkEntry& entry = this->EntryList[index];
entry.Item = item;
- entry.Target = this->FindTargetToLink(depender_index, entry.Item.c_str());
+ entry.Target = item.Target;
entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
item.substr(0, 10) != "-framework");
// If the item has dependencies queue it to follow them.
- if(entry.Target)
- {
+ if (entry.Target) {
// Target dependencies are always known. Follow them.
- BFSEntry qe = {index, 0};
+ BFSEntry qe = { index, CM_NULLPTR };
this->BFSQueue.push(qe);
- }
- else
- {
+ } else {
// Look for an old-style <item>_LIB_DEPENDS variable.
std::string var = entry.Item;
var += "_LIB_DEPENDS";
- if(const char* val = this->Makefile->GetDefinition(var.c_str()))
- {
+ if (const char* val = this->Makefile->GetDefinition(var)) {
// The item dependencies are known. Follow them.
- BFSEntry qe = {index, val};
+ BFSEntry qe = { index, val };
this->BFSQueue.push(qe);
- }
- else if(!entry.IsFlag)
- {
+ } else if (!entry.IsFlag) {
// The item dependencies are not known. We need to infer them.
this->InferredDependSets[index] = new DependSetList;
- }
}
+ }
return index;
}
-//----------------------------------------------------------------------------
-void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
+void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
{
// Get this entry representation.
int depender_index = qe.Index;
LinkEntry const& entry = this->EntryList[depender_index];
// Follow the item's dependencies.
- if(entry.Target)
- {
+ if (entry.Target) {
// Follow the target dependencies.
- if(cmTarget::LinkInterface const* iface =
- entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
- {
+ if (cmLinkInterface const* iface =
+ entry.Target->GetLinkInterface(this->Config, this->Target)) {
+ const bool isIface =
+ entry.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY;
// This target provides its own link interface information.
this->AddLinkEntries(depender_index, iface->Libraries);
+ if (isIface) {
+ return;
+ }
+
// Handle dependent shared libraries.
this->FollowSharedDeps(depender_index, iface);
// Support for CMP0003.
- for(std::vector<std::string>::const_iterator
- oi = iface->WrongConfigLibraries.begin();
- oi != iface->WrongConfigLibraries.end(); ++oi)
- {
- this->CheckWrongConfigItem(depender_index, *oi);
- }
+ for (std::vector<cmLinkItem>::const_iterator oi =
+ iface->WrongConfigLibraries.begin();
+ oi != iface->WrongConfigLibraries.end(); ++oi) {
+ this->CheckWrongConfigItem(*oi);
}
}
- else
- {
+ } else {
// Follow the old-style dependency list.
this->AddVarLinkEntries(depender_index, qe.LibDepends);
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmComputeLinkDepends
-::FollowSharedDeps(int depender_index, cmTarget::LinkInterface const* iface,
- bool follow_interface)
+void cmComputeLinkDepends::FollowSharedDeps(int depender_index,
+ cmLinkInterface const* iface,
+ bool follow_interface)
{
// Follow dependencies if we have not followed them already.
- if(this->SharedDepFollowed.insert(depender_index).second)
- {
- if(follow_interface)
- {
+ if (this->SharedDepFollowed.insert(depender_index).second) {
+ if (follow_interface) {
this->QueueSharedDependencies(depender_index, iface->Libraries);
- }
- this->QueueSharedDependencies(depender_index, iface->SharedDeps);
}
+ this->QueueSharedDependencies(depender_index, iface->SharedDeps);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmComputeLinkDepends
-::QueueSharedDependencies(int depender_index,
- std::vector<std::string> const& deps)
+void cmComputeLinkDepends::QueueSharedDependencies(
+ int depender_index, std::vector<cmLinkItem> const& deps)
{
- for(std::vector<std::string>::const_iterator li = deps.begin();
- li != deps.end(); ++li)
- {
+ for (std::vector<cmLinkItem>::const_iterator li = deps.begin();
+ li != deps.end(); ++li) {
SharedDepEntry qe;
qe.Item = *li;
qe.DependerIndex = depender_index;
this->SharedDepQueue.push(qe);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
{
// Check if the target already has an entry.
- std::map<cmStdString, int>::iterator lei =
+ std::map<std::string, int>::iterator lei =
this->LinkEntryIndex.find(dep.Item);
- if(lei == this->LinkEntryIndex.end())
- {
+ 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.Target = this->FindTargetToLink(dep.DependerIndex,
- dep.Item.c_str());
+ entry.Target = dep.Item.Target;
// This item was added specifically because it is a dependent
// shared library. It may get special treatment
// in cmComputeLinkInformation.
entry.IsSharedDep = true;
- }
+ }
// Get the link entry for this target.
int index = lei->second;
@@ -442,18 +423,15 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
this->EntryConstraintGraph[dep.DependerIndex].push_back(index);
// Target items may have their own dependencies.
- if(entry.Target)
- {
- if(cmTarget::LinkInterface const* iface =
- entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
- {
+ if (entry.Target) {
+ if (cmLinkInterface const* iface =
+ entry.Target->GetLinkInterface(this->Config, this->Target)) {
// Follow public and private dependencies transitively.
this->FollowSharedDeps(index, iface, true);
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
const char* value)
{
@@ -464,265 +442,195 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
cmSystemTools::ExpandListArgument(value, deplist);
// Look for entries meant for this configuration.
- std::vector<std::string> actual_libs;
- cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
+ 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")
- {
- llt = cmTarget::DEBUG;
+ for (std::vector<std::string>::const_iterator di = deplist.begin();
+ di != deplist.end(); ++di) {
+ if (*di == "debug") {
+ llt = DEBUG_LibraryType;
haveLLT = true;
- }
- else if(*di == "optimized")
- {
- llt = cmTarget::OPTIMIZED;
+ } else if (*di == "optimized") {
+ llt = OPTIMIZED_LibraryType;
haveLLT = true;
- }
- else if(*di == "general")
- {
- llt = cmTarget::GENERAL;
+ } else if (*di == "general") {
+ llt = GENERAL_LibraryType;
haveLLT = true;
- }
- else if(!di->empty())
- {
+ } else if (!di->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)
- {
+ if (!haveLLT) {
std::string var = *di;
var += "_LINK_TYPE";
- if(const char* val = this->Makefile->GetDefinition(var.c_str()))
- {
- if(strcmp(val, "debug") == 0)
- {
- llt = cmTarget::DEBUG;
- }
- else if(strcmp(val, "optimized") == 0)
- {
- llt = cmTarget::OPTIMIZED;
- }
+ if (const char* val = this->Makefile->GetDefinition(var)) {
+ if (strcmp(val, "debug") == 0) {
+ llt = DEBUG_LibraryType;
+ } else if (strcmp(val, "optimized") == 0) {
+ llt = OPTIMIZED_LibraryType;
}
}
+ }
// If the library is meant for this link type then use it.
- if(llt == cmTarget::GENERAL || llt == this->LinkType)
- {
- actual_libs.push_back(*di);
- }
- else if(this->OldLinkDirMode)
- {
- this->CheckWrongConfigItem(depender_index, *di);
- }
+ if (llt == GENERAL_LibraryType || llt == this->LinkType) {
+ cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di));
+ actual_libs.push_back(item);
+ } else if (this->OldLinkDirMode) {
+ cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di));
+ this->CheckWrongConfigItem(item);
+ }
// Reset the link type until another explicit type is given.
- llt = cmTarget::GENERAL;
+ llt = GENERAL_LibraryType;
haveLLT = false;
- }
}
+ }
// Add the entries from this list.
this->AddLinkEntries(depender_index, actual_libs);
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::AddDirectLinkEntries()
{
// Add direct link dependencies in this configuration.
- cmTarget::LinkImplementation const* impl =
- this->Target->GetLinkImplementation(this->Config, this->HeadTarget);
+ cmLinkImplementation const* impl =
+ this->Target->GetLinkImplementation(this->Config);
this->AddLinkEntries(-1, impl->Libraries);
- for(std::vector<std::string>::const_iterator
- wi = impl->WrongConfigLibraries.begin();
- wi != impl->WrongConfigLibraries.end(); ++wi)
- {
- this->CheckWrongConfigItem(-1, *wi);
- }
+ for (std::vector<cmLinkItem>::const_iterator wi =
+ impl->WrongConfigLibraries.begin();
+ wi != impl->WrongConfigLibraries.end(); ++wi) {
+ this->CheckWrongConfigItem(*wi);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmComputeLinkDepends::AddLinkEntries(int depender_index,
- std::vector<std::string> const& libs)
+template <typename T>
+void cmComputeLinkDepends::AddLinkEntries(int depender_index,
+ std::vector<T> const& libs)
{
// Track inferred dependency sets implied by this list.
std::map<int, DependSet> dependSets;
// Loop over the libraries linked directly by the depender.
- for(std::vector<std::string>::const_iterator li = libs.begin();
- li != libs.end(); ++li)
- {
+ for (typename std::vector<T>::const_iterator li = libs.begin();
+ li != libs.end(); ++li) {
// Skip entries that will resolve to the target getting linked or
// are empty.
- std::string item = this->Target->CheckCMP0004(*li);
- if(item == this->Target->GetName() || item.empty())
- {
+ cmLinkItem const& item = *li;
+ if (item == this->Target->GetName() || item.empty()) {
continue;
- }
+ }
// Add a link entry for this item.
- int dependee_index = this->AddLinkEntry(depender_index, item);
+ int dependee_index = this->AddLinkEntry(*li);
// The dependee must come after the depender.
- if(depender_index >= 0)
- {
+ if (depender_index >= 0) {
this->EntryConstraintGraph[depender_index].push_back(dependee_index);
- }
- else
- {
+ } 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 (std::map<int, DependSet>::iterator dsi = dependSets.begin();
+ dsi != dependSets.end(); ++dsi) {
// 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)
- {
+ if (!this->EntryList[dependee_index].Target &&
+ !this->EntryList[dependee_index].IsFlag &&
+ dependee_index != dsi->first) {
dsi->second.insert(dependee_index);
- }
}
+ }
// If this item needs to have dependencies inferred, do so.
- if(this->InferredDependSets[dependee_index])
- {
+ if (this->InferredDependSets[dependee_index]) {
// 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)
- {
+ for (std::map<int, DependSet>::iterator dsi = dependSets.begin();
+ dsi != dependSets.end(); ++dsi) {
this->InferredDependSets[dsi->first]->push_back(dsi->second);
- }
+ }
}
-//----------------------------------------------------------------------------
-cmTarget* cmComputeLinkDepends::FindTargetToLink(int depender_index,
- const char* name)
+cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
+ int depender_index, const std::string& name)
{
// Look for a target in the scope of the depender.
- cmMakefile* mf = this->Makefile;
- if(depender_index >= 0)
- {
- if(cmTarget* depender = this->EntryList[depender_index].Target)
- {
- mf = depender->GetMakefile();
- }
- }
- cmTarget* tgt = mf->FindTargetToUse(name);
-
- // 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() == cmTarget::EXECUTABLE &&
- !tgt->IsExecutableWithExports())
- {
- tgt = 0;
- }
-
- if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
- e << "Target \"" << this->Target->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.";
- this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
- this->Target->GetBacktrace());
- tgt = 0;
- }
-
- // Return the target found, if any.
- return tgt;
+ cmGeneratorTarget const* from = this->Target;
+ if (depender_index >= 0) {
+ if (cmGeneratorTarget const* depender =
+ this->EntryList[depender_index].Target) {
+ from = depender;
+ }
+ }
+ return from->FindTargetToLink(name);
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::InferDependencies()
{
// The inferred dependency sets for each item list the possible
// dependencies. The intersection of the sets for one item form its
// inferred dependencies.
- for(unsigned int depender_index=0;
- depender_index < this->InferredDependSets.size(); ++depender_index)
- {
+ for (unsigned int depender_index = 0;
+ 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())
- {
+ if (!sets || sets->empty()) {
continue;
- }
+ }
// Intersect the sets for this item.
DependSetList::const_iterator i = sets->begin();
DependSet common = *i;
- for(++i; i != sets->end(); ++i)
- {
+ for (++i; i != sets->end(); ++i) {
DependSet intersection;
- cmsys_stl::set_intersection
- (common.begin(), common.end(), i->begin(), i->end(),
- std::inserter(intersection, intersection.begin()));
+ 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.
- for(DependSet::const_iterator j = common.begin(); j != common.end(); ++j)
- {
- int dependee_index = *j;
- this->EntryConstraintGraph[depender_index].push_back(dependee_index);
- }
- }
+ cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index];
+ edges.insert(edges.end(), common.begin(), common.end());
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::CleanConstraintGraph()
{
- for(Graph::iterator i = this->EntryConstraintGraph.begin();
- i != this->EntryConstraintGraph.end(); ++i)
- {
+ for (Graph::iterator i = this->EntryConstraintGraph.begin();
+ i != this->EntryConstraintGraph.end(); ++i) {
// Sort the outgoing edges for each graph node so that the
// original order will be preserved as much as possible.
- cmsys_stl::sort(i->begin(), i->end());
+ std::sort(i->begin(), i->end());
// Make the edge list unique.
- EdgeList::iterator last = cmsys_stl::unique(i->begin(), i->end());
- i->erase(last, i->end());
- }
+ i->erase(std::unique(i->begin(), i->end()), i->end());
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::DisplayConstraintGraph()
{
// Display the graph nodes and their edges.
- cmOStringStream e;
- for(unsigned int i=0; i < this->EntryConstraintGraph.size(); ++i)
- {
+ std::ostringstream e;
+ for (unsigned int i = 0; i < this->EntryConstraintGraph.size(); ++i) {
EdgeList const& nl = this->EntryConstraintGraph[i];
e << "item " << i << " is [" << this->EntryList[i].Item << "]\n";
- for(EdgeList::const_iterator j = nl.begin(); j != nl.end(); ++j)
- {
- e << " item " << *j << " must follow it\n";
- }
- }
+ e << cmWrap(" item ", nl, " must follow it", "\n") << "\n";
+ }
fprintf(stderr, "%s\n", e.str().c_str());
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::OrderLinkEntires()
{
// Compute the DAG of strongly connected components. The algorithm
@@ -742,73 +650,60 @@ void cmComputeLinkDepends::OrderLinkEntires()
this->ComponentOrderId = n;
// Run in reverse order so the topological order will preserve the
// original order where there are no constraints.
- for(int c = n-1; c >= 0; --c)
- {
+ for (int c = n - 1; c >= 0; --c) {
this->VisitComponent(c);
- }
+ }
// Display the component graph.
- if(this->DebugMode)
- {
+ if (this->DebugMode) {
this->DisplayComponents();
- }
+ }
// Start with the original link line.
- for(std::vector<int>::const_iterator i = this->OriginalEntries.begin();
- i != this->OriginalEntries.end(); ++i)
- {
+ for (std::vector<int>::const_iterator i = this->OriginalEntries.begin();
+ i != this->OriginalEntries.end(); ++i) {
this->VisitEntry(*i);
- }
+ }
// Now explore anything left pending. Since the component graph is
// guaranteed to be acyclic we know this will terminate.
- while(!this->PendingComponents.empty())
- {
+ while (!this->PendingComponents.empty()) {
// Visit one entry from the first pending component. The visit
// logic will update the pending components accordingly. Since
// the pending components are kept in topological order this will
// not repeat one.
int e = *this->PendingComponents.begin()->second.Entries.begin();
this->VisitEntry(e);
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmComputeLinkDepends::DisplayComponents()
+void cmComputeLinkDepends::DisplayComponents()
{
fprintf(stderr, "The strongly connected components are:\n");
std::vector<NodeList> const& components = this->CCG->GetComponents();
- for(unsigned int c=0; c < components.size(); ++c)
- {
+ 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)
- {
+ for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
int i = *ni;
- fprintf(stderr, " item %d [%s]\n", i,
- this->EntryList[i].Item.c_str());
- }
+ 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)
- {
+ for (EdgeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi) {
int i = *oi;
fprintf(stderr, " followed by Component (%d)\n", i);
- }
- fprintf(stderr, " topo order index %d\n",
- this->ComponentOrder[c]);
}
+ fprintf(stderr, " topo order index %d\n", this->ComponentOrder[c]);
+ }
fprintf(stderr, "\n");
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::VisitComponent(unsigned int c)
{
// Check if the node has already been visited.
- if(this->ComponentVisited[c])
- {
+ if (this->ComponentVisited[c]) {
return;
- }
+ }
// We are now visiting this component so mark it.
this->ComponentVisited[c] = 1;
@@ -817,17 +712,15 @@ 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)
- {
+ for (EdgeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
+ ++ni) {
this->VisitComponent(*ni);
- }
+ }
// Assign an ordering id to this component.
this->ComponentOrder[c] = --this->ComponentOrderId;
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::VisitEntry(int index)
{
// Include this entry on the link line.
@@ -838,67 +731,54 @@ void cmComputeLinkDepends::VisitEntry(int index)
int component = this->CCG->GetComponentMap()[index];
std::map<int, PendingComponent>::iterator mi =
this->PendingComponents.find(this->ComponentOrder[component]);
- if(mi != this->PendingComponents.end())
- {
+ if (mi != this->PendingComponents.end()) {
// The entry is in an already pending component.
PendingComponent& pc = mi->second;
// Remove the entry from those pending in its component.
pc.Entries.erase(index);
- if(pc.Entries.empty())
- {
+ if (pc.Entries.empty()) {
// The complete component has been seen since it was last needed.
--pc.Count;
- if(pc.Count == 0)
- {
+ if (pc.Count == 0) {
// The component has been completed.
this->PendingComponents.erase(mi);
completed = true;
- }
- else
- {
+ } else {
// The whole component needs to be seen again.
NodeList const& nl = this->CCG->GetComponent(component);
assert(nl.size() > 1);
pc.Entries.insert(nl.begin(), nl.end());
- }
}
}
- else
- {
+ } else {
// The entry is not in an already pending component.
NodeList const& nl = this->CCG->GetComponent(component);
- if(nl.size() > 1)
- {
+ if (nl.size() > 1) {
// This is a non-trivial component. It is now pending.
PendingComponent& pc = this->MakePendingComponent(component);
// The starting entry has already been seen.
pc.Entries.erase(index);
- }
- else
- {
+ } else {
// This is a trivial component, so it is already complete.
completed = true;
- }
}
+ }
// If the entry completed a component, the component's dependencies
// are now pending.
- if(completed)
- {
+ if (completed) {
EdgeList const& ol = this->CCG->GetComponentGraphEdges(component);
- for(EdgeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi)
- {
+ for (EdgeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi) {
// This entire component is now pending no matter whether it has
// been partially seen already.
this->MakePendingComponent(*oi);
- }
}
+ }
}
-//----------------------------------------------------------------------------
cmComputeLinkDepends::PendingComponent&
cmComputeLinkDepends::MakePendingComponent(unsigned int component)
{
@@ -908,13 +788,10 @@ cmComputeLinkDepends::MakePendingComponent(unsigned int component)
pc.Id = component;
NodeList const& nl = this->CCG->GetComponent(component);
- if(nl.size() == 1)
- {
+ if (nl.size() == 1) {
// Trivial components need be seen only once.
pc.Count = 1;
- }
- else
- {
+ } else {
// This is a non-trivial strongly connected component of the
// original graph. It consists of two or more libraries
// (archives) that mutually require objects from one another. In
@@ -928,7 +805,7 @@ cmComputeLinkDepends::MakePendingComponent(unsigned int component)
// this component will come first which minimizes the number of
// repeats needed.
pc.Count = this->ComputeComponentCount(nl);
- }
+ }
// Store the entries to be seen.
pc.Entries.insert(nl.begin(), nl.end());
@@ -936,64 +813,47 @@ cmComputeLinkDepends::MakePendingComponent(unsigned int component)
return pc;
}
-//----------------------------------------------------------------------------
int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
{
- int count = 2;
- for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
- {
- if(cmTarget* target = this->EntryList[*ni].Target)
- {
- if(cmTarget::LinkInterface const* iface =
- target->GetLinkInterface(this->Config, this->HeadTarget))
- {
- if(iface->Multiplicity > count)
- {
+ unsigned int count = 2;
+ for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
+ if (cmGeneratorTarget const* target = this->EntryList[*ni].Target) {
+ if (cmLinkInterface const* iface =
+ target->GetLinkInterface(this->Config, this->Target)) {
+ if (iface->Multiplicity > count) {
count = iface->Multiplicity;
- }
}
}
}
+ }
return count;
}
-//----------------------------------------------------------------------------
void cmComputeLinkDepends::DisplayFinalEntries()
{
- fprintf(stderr, "target [%s] links to:\n", this->Target->GetName());
- 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());
- }
- else
- {
+ 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());
+ } else {
fprintf(stderr, " item [%s]\n", lei->Item.c_str());
- }
}
+ }
fprintf(stderr, "\n");
}
-//----------------------------------------------------------------------------
-void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index,
- std::string const& item)
+void cmComputeLinkDepends::CheckWrongConfigItem(cmLinkItem const& item)
{
- if(!this->OldLinkDirMode)
- {
+ if (!this->OldLinkDirMode) {
return;
- }
+ }
// For CMake 2.4 bug-compatibility we need to consider the output
// directories of targets linked in another configuration as link
// directories.
- if(cmTarget* tgt = this->FindTargetToLink(depender_index, item.c_str()))
- {
- if(!tgt->IsImported())
- {
- this->OldWrongConfigItems.insert(tgt);
- }
- }
+ if (item.Target && !item.Target->IsImported()) {
+ this->OldWrongConfigItems.insert(item.Target);
+ }
}
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 1d5d1b920..84ee9161f 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -1,29 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmComputeLinkDepends_h
#define cmComputeLinkDepends_h
-#include "cmStandardIncludes.h"
-#include "cmTarget.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGraphAdjacencyList.h"
+#include "cmLinkItem.h"
+#include "cmTargetLinkLibraryType.h"
+#include <map>
#include <queue>
+#include <set>
+#include <string>
+#include <vector>
class cmComputeComponentGraph;
+class cmGeneratorTarget;
class cmGlobalGenerator;
-class cmLocalGenerator;
class cmMakefile;
-class cmTarget;
class cmake;
/** \class cmComputeLinkDepends
@@ -32,61 +27,64 @@ class cmake;
class cmComputeLinkDepends
{
public:
- cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget *head);
+ cmComputeLinkDepends(cmGeneratorTarget const* target,
+ const std::string& config);
~cmComputeLinkDepends();
// Basic information about each link item.
struct LinkEntry
{
std::string Item;
- cmTarget* Target;
+ cmGeneratorTarget const* Target;
bool IsSharedDep;
bool IsFlag;
- LinkEntry(): Item(), Target(0), IsSharedDep(false), IsFlag(false) {}
- LinkEntry(LinkEntry const& r):
- Item(r.Item), Target(r.Target), IsSharedDep(r.IsSharedDep),
- IsFlag(r.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)
+ {
+ }
};
typedef std::vector<LinkEntry> EntryVector;
EntryVector const& Compute();
void SetOldLinkDirMode(bool b);
- std::set<cmTarget*> const& GetOldWrongConfigItems() const
- { return this->OldWrongConfigItems; }
+ std::set<cmGeneratorTarget const*> const& GetOldWrongConfigItems() const
+ {
+ return this->OldWrongConfigItems;
+ }
private:
-
// Context information.
- cmTarget* Target;
- cmTarget* HeadTarget;
+ cmGeneratorTarget const* Target;
cmMakefile* Makefile;
- cmLocalGenerator* LocalGenerator;
- cmGlobalGenerator* GlobalGenerator;
+ cmGlobalGenerator const* GlobalGenerator;
cmake* CMakeInstance;
- bool DebugMode;
-
- // Configuration information.
- const char* Config;
- cmTarget::LinkLibraryType LinkType;
-
- // Output information.
+ std::string Config;
EntryVector FinalLinkEntries;
- typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType;
-
- std::map<cmStdString, int>::iterator
- AllocateLinkEntry(std::string const& item);
- int AddLinkEntry(int depender_index, std::string const& item);
+ std::map<std::string, int>::iterator AllocateLinkEntry(
+ std::string const& item);
+ int AddLinkEntry(cmLinkItem const& item);
void AddVarLinkEntries(int depender_index, const char* value);
void AddDirectLinkEntries();
- void AddLinkEntries(int depender_index,
- std::vector<std::string> const& libs);
- cmTarget* FindTargetToLink(int depender_index, const char* name);
+ template <typename T>
+ void AddLinkEntries(int depender_index, std::vector<T> const& libs);
+ cmGeneratorTarget const* FindTargetToLink(int depender_index,
+ const std::string& name);
// One entry for each unique item.
std::vector<LinkEntry> EntryList;
- std::map<cmStdString, int> LinkEntryIndex;
+ std::map<std::string, int> LinkEntryIndex;
// BFS of initial dependencies.
struct BFSEntry
@@ -95,28 +93,31 @@ private:
const char* LibDepends;
};
std::queue<BFSEntry> BFSQueue;
- void FollowLinkEntry(BFSEntry const&);
+ void FollowLinkEntry(BFSEntry qe);
// Shared libraries that are included only because they are
// dependencies of other shared libraries, not because they are part
// of the interface.
struct SharedDepEntry
{
- std::string Item;
+ cmLinkItem Item;
int DependerIndex;
};
std::queue<SharedDepEntry> SharedDepQueue;
std::set<int> SharedDepFollowed;
- void FollowSharedDeps(int depender_index,
- cmTarget::LinkInterface const* iface,
+ void FollowSharedDeps(int depender_index, cmLinkInterface const* iface,
bool follow_interface = false);
void QueueSharedDependencies(int depender_index,
- std::vector<std::string> const& deps);
+ std::vector<cmLinkItem> const& deps);
void HandleSharedDependency(SharedDepEntry const& dep);
// Dependency inferral for each link item.
- struct DependSet: public std::set<int> {};
- struct DependSetList: public std::vector<DependSet> {};
+ struct DependSet : public std::set<int>
+ {
+ };
+ struct DependSetList : public std::vector<DependSet>
+ {
+ };
std::vector<DependSetList*> InferredDependSets;
void InferDependencies();
@@ -132,7 +133,7 @@ private:
void OrderLinkEntires();
std::vector<char> ComponentVisited;
std::vector<int> ComponentOrder;
- int ComponentOrderId;
+
struct PendingComponent
{
// The real component id. Needed because the map is indexed by
@@ -159,11 +160,14 @@ private:
// Record of the original link line.
std::vector<int> OriginalEntries;
+ std::set<cmGeneratorTarget const*> OldWrongConfigItems;
+ void CheckWrongConfigItem(cmLinkItem const& item);
- // Compatibility help.
+ int ComponentOrderId;
+ cmTargetLinkLibraryType LinkType;
+ bool HasConfig;
+ bool DebugMode;
bool OldLinkDirMode;
- void CheckWrongConfigItem(int depender_index, std::string const& item);
- std::set<cmTarget*> OldWrongConfigItems;
};
#endif
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index fb7b5b67d..b2deaaa85 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -1,26 +1,27 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeLinkInformation.h"
+#include "cmAlgorithms.h"
#include "cmComputeLinkDepends.h"
-#include "cmOrderDirectories.h"
-
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmOrderDirectories.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmStateTypes.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
@@ -237,47 +238,41 @@ because this need be done only for shared libraries without soname-s.
*/
-//----------------------------------------------------------------------------
-cmComputeLinkInformation
-::cmComputeLinkInformation(cmTarget* target, const char* config,
- cmTarget *headTarget)
+cmComputeLinkInformation::cmComputeLinkInformation(
+ const cmGeneratorTarget* target, const std::string& config)
{
// Store context information.
this->Target = target;
- this->HeadTarget = headTarget;
- this->Makefile = this->Target->GetMakefile();
- this->LocalGenerator = this->Makefile->GetLocalGenerator();
- this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
+ this->Makefile = this->Target->Target->GetMakefile();
+ this->GlobalGenerator =
+ this->Target->GetLocalGenerator()->GetGlobalGenerator();
this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
// Check whether to recognize OpenBSD-style library versioned names.
- this->OpenBSD = this->Makefile->GetCMakeInstance()
- ->GetPropertyAsBool("FIND_LIBRARY_USE_OPENBSD_VERSIONING");
+ 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 = 0;
+ this->OrderLinkerSearchPath = new cmOrderDirectories(
+ this->GlobalGenerator, target, "linker search path");
+ this->OrderRuntimeSearchPath = new cmOrderDirectories(
+ this->GlobalGenerator, target, "runtime search path");
+ this->OrderDependentRPath = CM_NULLPTR;
// Get the language used for linking this target.
- this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget);
- if(!this->LinkLanguage)
- {
+ this->LinkLanguage = this->Target->GetLinkerLanguage(config);
+ if (this->LinkLanguage.empty()) {
// The Compute method will do nothing, so skip the rest of the
// initialization.
return;
- }
+ }
// Check whether we should use an import library for linking a target.
this->UseImportLibrary =
- this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")?true:false;
+ this->Makefile->IsDefinitionSet("CMAKE_IMPORT_LIBRARY_SUFFIX");
// Check whether we should skip dependencies on shared library files.
this->LinkDependsNoShared =
@@ -286,15 +281,14 @@ 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 = 0;
- if(!this->UseImportLibrary &&
- this->Target->GetType() == cmTarget::MODULE_LIBRARY)
- {
+ this->LoaderFlag = CM_NULLPTR;
+ if (!this->UseImportLibrary &&
+ this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
loader_flag_var += this->LinkLanguage;
loader_flag_var += "_FLAG";
- this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var.c_str());
- }
+ this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var);
+ }
// Get options needed to link libraries.
this->LibLinkFlag =
@@ -306,22 +300,21 @@ cmComputeLinkInformation
// Get options needed to specify RPATHs.
this->RuntimeUseChrpath = false;
- if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
- {
- const char* tType =
- ((this->Target->GetType() == cmTarget::EXECUTABLE)?
- "EXECUTABLE" : "SHARED_LIBRARY");
+ if (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) {
+ 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 rtSepVar = rtVar + "_SEP";
- this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar.c_str());
- this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar.c_str());
- this->RuntimeAlways =
- (this->Makefile->
- GetSafeDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH"));
+ this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar);
+ this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar);
+ this->RuntimeAlways = (this->Makefile->GetSafeDefinition(
+ "CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH"));
+
this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config);
// Get options needed to help find dependent libraries.
@@ -330,15 +323,15 @@ cmComputeLinkInformation
rlVar += "_RPATH_LINK_";
rlVar += this->LinkLanguage;
rlVar += "_FLAG";
- this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar.c_str());
- }
+ 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";
- this->LinkWithRuntimePath = this->Makefile->IsOn(var.c_str());
+ std::string var = "CMAKE_SHARED_LIBRARY_LINK_";
+ var += this->LinkLanguage;
+ var += "_WITH_RUNTIME_PATH";
+ this->LinkWithRuntimePath = this->Makefile->IsOn(var);
}
// Check the platform policy for missing soname case.
@@ -356,41 +349,30 @@ cmComputeLinkInformation
// Choose a mode for dealing with shared library dependencies.
this->SharedDependencyMode = SharedDepModeNone;
- if(this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_FILES"))
- {
+ if (this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_FILES")) {
this->SharedDependencyMode = SharedDepModeLink;
- }
- else if(this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_DIRS"))
- {
+ } else if (this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_DIRS")) {
this->SharedDependencyMode = SharedDepModeLibDir;
- }
- else if(!this->RPathLinkFlag.empty())
- {
+ } else if (!this->RPathLinkFlag.empty()) {
this->SharedDependencyMode = SharedDepModeDir;
- this->OrderDependentRPath =
- new cmOrderDirectories(this->GlobalGenerator, target,
- "dependent library path");
- }
+ this->OrderDependentRPath = new cmOrderDirectories(
+ this->GlobalGenerator, target, "dependent library path");
+ }
// Add the search path entries requested by the user to path ordering.
- this->OrderLinkerSearchPath
- ->AddUserDirectories(this->Target->GetLinkDirectories());
- this->OrderRuntimeSearchPath
- ->AddUserDirectories(this->Target->GetLinkDirectories());
+ this->OrderLinkerSearchPath->AddUserDirectories(
+ this->Target->GetLinkDirectories());
+ this->OrderRuntimeSearchPath->AddUserDirectories(
+ this->Target->GetLinkDirectories());
// Set up the implicit link directories.
this->LoadImplicitLinkInfo();
- this->OrderLinkerSearchPath
- ->SetImplicitDirectories(this->ImplicitLinkDirs);
- this->OrderRuntimeSearchPath
- ->SetImplicitDirectories(this->ImplicitLinkDirs);
- if(this->OrderDependentRPath)
- {
- this->OrderDependentRPath
- ->SetImplicitDirectories(this->ImplicitLinkDirs);
- this->OrderDependentRPath
- ->AddLanguageDirectories(this->RuntimeLinkDirs);
- }
+ this->OrderLinkerSearchPath->SetImplicitDirectories(this->ImplicitLinkDirs);
+ this->OrderRuntimeSearchPath->SetImplicitDirectories(this->ImplicitLinkDirs);
+ if (this->OrderDependentRPath) {
+ this->OrderDependentRPath->SetImplicitDirectories(this->ImplicitLinkDirs);
+ this->OrderDependentRPath->AddLanguageDirectories(this->RuntimeLinkDirs);
+ }
// Decide whether to enable compatible library search path mode.
// There exists code that effectively does
@@ -405,20 +387,17 @@ cmComputeLinkInformation
// containing libraries linked with a full path to the -L path.
this->OldLinkDirMode =
this->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW;
- if(this->OldLinkDirMode)
- {
+ 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();
- for(std::vector<std::string>::const_iterator di = dirs.begin();
- di != dirs.end(); ++di)
- {
- this->OldLinkDirMask.insert(*di);
- }
- }
+ this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
+ }
+
+ this->CMP0060Warn = this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0060");
}
-//----------------------------------------------------------------------------
cmComputeLinkInformation::~cmComputeLinkInformation()
{
delete this->OrderLinkerSearchPath;
@@ -426,165 +405,150 @@ cmComputeLinkInformation::~cmComputeLinkInformation()
delete this->OrderDependentRPath;
}
-//----------------------------------------------------------------------------
cmComputeLinkInformation::ItemVector const&
cmComputeLinkInformation::GetItems()
{
return this->Items;
}
-//----------------------------------------------------------------------------
std::vector<std::string> const& cmComputeLinkInformation::GetDirectories()
{
return this->OrderLinkerSearchPath->GetOrderedDirectories();
}
-//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::GetRPathLinkString()
{
// If there is no separate linker runtime search flag (-rpath-link)
// there is no reason to compute a string.
- if(!this->OrderDependentRPath)
- {
+ if (!this->OrderDependentRPath) {
return "";
- }
+ }
// Construct the linker runtime search path.
- std::string rpath_link;
- const char* sep = "";
- std::vector<std::string> const& dirs =
- this->OrderDependentRPath->GetOrderedDirectories();
- for(std::vector<std::string>::const_iterator di = dirs.begin();
- di != dirs.end(); ++di)
- {
- rpath_link += sep;
- sep = ":";
- rpath_link += *di;
- }
- return rpath_link;
+ return cmJoin(this->OrderDependentRPath->GetOrderedDirectories(), ":");
}
-//----------------------------------------------------------------------------
std::vector<std::string> const& cmComputeLinkInformation::GetDepends()
{
return this->Depends;
}
-//----------------------------------------------------------------------------
std::vector<std::string> const& cmComputeLinkInformation::GetFrameworkPaths()
{
return this->FrameworkPaths;
}
-//----------------------------------------------------------------------------
-std::set<cmTarget*> const&
+const std::set<const cmGeneratorTarget*>&
cmComputeLinkInformation::GetSharedLibrariesLinked()
{
return this->SharedLibrariesLinked;
}
-//----------------------------------------------------------------------------
bool cmComputeLinkInformation::Compute()
{
// Skip targets that do not link.
- if(!(this->Target->GetType() == cmTarget::EXECUTABLE ||
- this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
- this->Target->GetType() == cmTarget::MODULE_LIBRARY ||
- this->Target->GetType() == cmTarget::STATIC_LIBRARY))
- {
+ if (!(this->Target->GetType() == cmStateEnums::EXECUTABLE ||
+ this->Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->Target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->Target->GetType() == cmStateEnums::STATIC_LIBRARY)) {
return false;
- }
+ }
// We require a link language for the target.
- if(!this->LinkLanguage)
- {
- cmSystemTools::
- Error("CMake can not determine linker language for target: ",
- this->Target->GetName());
+ if (this->LinkLanguage.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: ",
+ this->Target->GetName().c_str());
return false;
- }
+ }
// Compute the ordered link line items.
- cmComputeLinkDepends cld(this->Target, this->Config, this->HeadTarget);
+ cmComputeLinkDepends cld(this->Target, this->Config);
cld.SetOldLinkDirMode(this->OldLinkDirMode);
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)
- {
+ for (cmComputeLinkDepends::EntryVector::const_iterator lei =
+ linkEntries.begin();
+ lei != linkEntries.end(); ++lei) {
+ if (lei->IsSharedDep) {
this->AddSharedDepItem(lei->Item, lei->Target);
- }
- else
- {
+ } else {
this->AddItem(lei->Item, lei->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 (cmSystemTools::IsOn(lss)) {
this->SetCurrentLinkType(LinkStatic);
- }
- else
- {
+ } else {
this->SetCurrentLinkType(this->StartLinkType);
- }
+ }
// Finish listing compatibility paths.
- if(this->OldLinkDirMode)
- {
+ if (this->OldLinkDirMode) {
// For CMake 2.4 bug-compatibility we need to consider the output
// directories of targets linked in another configuration as link
// directories.
- std::set<cmTarget*> const& wrongItems = cld.GetOldWrongConfigItems();
- for(std::set<cmTarget*>::const_iterator i = wrongItems.begin();
- i != wrongItems.end(); ++i)
- {
- cmTarget* tgt = *i;
- bool implib =
- (this->UseImportLibrary &&
- (tgt->GetType() == cmTarget::SHARED_LIBRARY));
- std::string lib = tgt->GetFullPath(this->Config , implib, true);
+ 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
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+ std::string lib = tgt->GetFullPath(this->Config, artifact, true);
this->OldLinkDirItems.push_back(lib);
- }
}
+ }
// Finish setting up linker search directories.
- if(!this->FinishLinkerSearchDirectories())
- {
+ if (!this->FinishLinkerSearchDirectories()) {
return false;
- }
+ }
// Add implicit language runtime libraries and directories.
this->AddImplicitLinkInfo();
+ if (!this->CMP0060WarnItems.empty()) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0060) << "\n"
+ "Some library files are in directories implicitly searched by "
+ "the linker when invoked for " << this->LinkLanguage << ":\n"
+ " " << cmJoin(this->CMP0060WarnItems, "\n ") << "\n"
+ "For compatibility with older versions of CMake, the generated "
+ "link line will ask the linker to search for these by library "
+ "name."
+ ;
+ /* clang-format on */
+ this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
+ this->Target->GetBacktrace());
+ }
+
return true;
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddImplicitLinkInfo()
{
// The link closure lists all languages whose implicit info is needed.
- cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config,
- this->HeadTarget);
- for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
- li != lc->Languages.end(); ++li)
- {
+ 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) {
// Skip those of the linker language. They are implicit.
- if(*li != this->LinkLanguage)
- {
+ if (*li != this->LinkLanguage) {
this->AddImplicitLinkInfo(*li);
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
{
// Add libraries for this language that are not implied by the
@@ -592,228 +556,215 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
std::string libVar = "CMAKE_";
libVar += lang;
libVar += "_IMPLICIT_LINK_LIBRARIES";
- if(const char* libs = this->Makefile->GetDefinition(libVar.c_str()))
- {
+ 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->c_str(), 0);
- }
+ 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);
}
}
+ }
// 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";
- if(const char* dirs = this->Makefile->GetDefinition(dirVar.c_str()))
- {
+ if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
std::vector<std::string> dirsVec;
cmSystemTools::ExpandListArgument(dirs, dirsVec);
this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::AddItem(std::string const& item, cmTarget* tgt)
+void cmComputeLinkInformation::AddItem(std::string const& item,
+ cmGeneratorTarget const* tgt)
{
// Compute the proper name to use to link this library.
- const char* config = this->Config;
+ const std::string& config = this->Config;
bool impexe = (tgt && tgt->IsExecutableWithExports());
- if(impexe && !this->UseImportLibrary && !this->LoaderFlag)
- {
+ if (impexe && !this->UseImportLibrary && !this->LoaderFlag) {
// Skip linking to executables on platforms with no import
// libraries or loader flags.
return;
- }
+ }
- if(tgt && tgt->IsLinkable())
- {
+ if (tgt && tgt->IsLinkable()) {
// This is a CMake target. Ask the target for its real name.
- if(impexe && this->LoaderFlag)
- {
+ if (impexe && this->LoaderFlag) {
// This link item is an executable that may provide symbols
// used by this target. A special flag is needed on this
// platform. Add it now.
std::string linkItem;
linkItem = this->LoaderFlag;
- std::string exe = tgt->GetFullPath(config, this->UseImportLibrary,
- true);
+ cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+ ? 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);
+ } 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));
+
+ // 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);
}
- else
- {
+ } else {
// Decide whether to use an import library.
bool implib =
(this->UseImportLibrary &&
- (impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY));
+ (impexe || tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
+ cmStateEnums::ArtifactType artifact = implib
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
// Pass the full path to the target file.
- std::string lib = tgt->GetFullPath(config, implib, true);
- if(!this->LinkDependsNoShared ||
- tgt->GetType() != cmTarget::SHARED_LIBRARY)
- {
+ std::string lib = tgt->GetFullPath(config, artifact, true);
+ if (!this->LinkDependsNoShared ||
+ tgt->GetType() != cmStateEnums::SHARED_LIBRARY) {
this->Depends.push_back(lib);
- }
+ }
this->AddTargetItem(lib, tgt);
this->AddLibraryRuntimeInfo(lib, tgt);
- }
}
- else
- {
+ } else {
// This is not a CMake target. Use the name given.
- if(cmSystemTools::FileIsFullPath(item.c_str()))
- {
- if(cmSystemTools::FileIsDirectory(item.c_str()))
- {
+ if (cmSystemTools::FileIsFullPath(item.c_str())) {
+ if (cmSystemTools::FileIsDirectory(item)) {
// This is a directory.
this->AddDirectoryItem(item);
- }
- else
- {
+ } else {
// Use the full path given to the library file.
this->Depends.push_back(item);
this->AddFullItem(item);
this->AddLibraryRuntimeInfo(item);
- }
}
- else
- {
+ } else {
// This is a library or option specified by the user.
this->AddUserItem(item, true);
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
- cmTarget* tgt)
+ const cmGeneratorTarget* tgt)
{
// If dropping shared library dependencies, ignore them.
- if(this->SharedDependencyMode == SharedDepModeNone)
- {
+ if (this->SharedDependencyMode == SharedDepModeNone) {
return;
- }
+ }
// The user may have incorrectly named an item. Skip items that are
// not full paths to shared libraries.
- if(tgt)
- {
+ if (tgt) {
// The target will provide a full path. Make sure it is a shared
// library.
- if(tgt->GetType() != cmTarget::SHARED_LIBRARY)
- {
+ if (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) {
return;
- }
}
- else
- {
+ } 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.c_str())) {
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.c_str())) {
// This is not the name of a shared library.
return;
- }
}
+ }
// If in linking mode, just link to the shared library.
- if(this->SharedDependencyMode == SharedDepModeLink)
- {
+ if (this->SharedDependencyMode == SharedDepModeLink) {
this->AddItem(item, tgt);
return;
- }
+ }
// Get a full path to the dependent shared library.
// Add it to the runtime path computation so that the target being
// linked will be able to find it.
std::string lib;
- if(tgt)
- {
- lib = tgt->GetFullPath(this->Config, this->UseImportLibrary);
+ if (tgt) {
+ cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+ lib = tgt->GetFullPath(this->Config, artifact);
this->AddLibraryRuntimeInfo(lib, tgt);
- }
- else
- {
+ } else {
lib = item;
this->AddLibraryRuntimeInfo(lib);
- }
+ }
// Check if we need to include the dependent shared library in other
// path ordering.
- cmOrderDirectories* order = 0;
- if(this->SharedDependencyMode == SharedDepModeLibDir &&
- !this->LinkWithRuntimePath /* AddLibraryRuntimeInfo adds it */)
- {
+ cmOrderDirectories* order = CM_NULLPTR;
+ if (this->SharedDependencyMode == SharedDepModeLibDir &&
+ !this->LinkWithRuntimePath /* AddLibraryRuntimeInfo adds it */) {
// Add the item to the linker search path.
order = this->OrderLinkerSearchPath;
- }
- else if(this->SharedDependencyMode == SharedDepModeDir)
- {
+ } else if (this->SharedDependencyMode == SharedDepModeDir) {
// Add the item to the separate dependent library search path.
order = this->OrderDependentRPath;
- }
- if(order)
- {
- if(tgt)
- {
+ }
+ if (order) {
+ if (tgt) {
std::string soName = tgt->GetSOName(this->Config);
- const char* soname = soName.empty()? 0 : soName.c_str();
+ const char* soname = soName.empty() ? CM_NULLPTR : soName.c_str();
order->AddRuntimeLibrary(lib, soname);
- }
- else
- {
+ } else {
order->AddRuntimeLibrary(lib);
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::ComputeLinkTypeInfo()
{
// Check whether archives may actually be shared libraries.
this->ArchivesMayBeShared =
- this->CMakeInstance->GetPropertyAsBool(
+ this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(
"TARGET_ARCHIVES_MAY_BE_SHARED_LIBS");
// First assume we cannot do link type stuff.
this->LinkTypeEnabled = false;
// Lookup link type selection flags.
- const char* static_link_type_flag = 0;
- const char* shared_link_type_flag = 0;
- const char* target_type_str = 0;
- switch(this->Target->GetType())
- {
- case cmTarget::EXECUTABLE: target_type_str = "EXE"; break;
- case cmTarget::SHARED_LIBRARY: target_type_str = "SHARED_LIBRARY"; break;
- case cmTarget::MODULE_LIBRARY: target_type_str = "SHARED_MODULE"; break;
- default: break;
- }
- if(target_type_str)
- {
+ const char* static_link_type_flag = CM_NULLPTR;
+ const char* shared_link_type_flag = CM_NULLPTR;
+ const char* target_type_str = CM_NULLPTR;
+ switch (this->Target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ target_type_str = "EXE";
+ break;
+ case cmStateEnums::SHARED_LIBRARY:
+ target_type_str = "SHARED_LIBRARY";
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ target_type_str = "SHARED_MODULE";
+ break;
+ default:
+ 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";
static_link_type_flag =
- this->Makefile->GetDefinition(static_link_type_flag_var.c_str());
+ this->Makefile->GetDefinition(static_link_type_flag_var);
std::string shared_link_type_flag_var = "CMAKE_";
shared_link_type_flag_var += target_type_str;
@@ -821,26 +772,24 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
shared_link_type_flag_var += this->LinkLanguage;
shared_link_type_flag_var += "_FLAGS";
shared_link_type_flag =
- this->Makefile->GetDefinition(shared_link_type_flag_var.c_str());
- }
+ this->Makefile->GetDefinition(shared_link_type_flag_var);
+ }
// We can support link type switching only if all needed flags are
// known.
- if(static_link_type_flag && *static_link_type_flag &&
- shared_link_type_flag && *shared_link_type_flag)
- {
+ if (static_link_type_flag && *static_link_type_flag &&
+ shared_link_type_flag && *shared_link_type_flag) {
this->LinkTypeEnabled = true;
this->StaticLinkTypeFlag = static_link_type_flag;
this->SharedLinkTypeFlag = shared_link_type_flag;
- }
+ }
// 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 = cmSystemTools::IsOn(lss) ? LinkStatic : LinkShared;
this->CurrentLinkType = this->StartLinkType;
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::ComputeItemParserInfo()
{
// Get possible library name prefixes.
@@ -858,50 +807,44 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
LinkShared);
this->AddLinkExtension(mf->GetDefinition("CMAKE_LINK_LIBRARY_SUFFIX"),
LinkUnknown);
- if(const char* linkSuffixes =
- mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS"))
- {
+ 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)
- {
+ for (std::vector<std::string>::iterator i = linkSuffixVec.begin();
+ i != linkSuffixVec.end(); ++i) {
this->AddLinkExtension(i->c_str(), LinkUnknown);
- }
}
- if(const char* sharedSuffixes =
- mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES"))
- {
+ }
+ 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)
- {
+ for (std::vector<std::string>::iterator i = sharedSuffixVec.begin();
+ i != sharedSuffixVec.end(); ++i) {
this->AddLinkExtension(i->c_str(), LinkShared);
- }
}
+ }
// Compute a regex to match link extensions.
- std::string libext = this->CreateExtensionRegex(this->LinkExtensions,
- LinkUnknown);
+ std::string libext =
+ this->CreateExtensionRegex(this->LinkExtensions, LinkUnknown);
// Create regex to remove any library extension.
std::string reg("(.*)");
reg += libext;
- this->OrderLinkerSearchPath->SetLinkExtensionInfo(this->LinkExtensions,
- reg);
+ this->OrderLinkerSearchPath->SetLinkExtensionInfo(this->LinkExtensions, reg);
// Create a regex to match a library name. Match index 1 will be
// the prefix if it exists and empty otherwise. Match index 2 will
// be the library name. Match index 3 will be the library
// extension.
reg = "^(";
- for(std::set<cmStdString>::iterator p = this->LinkPrefixes.begin();
- p != this->LinkPrefixes.end(); ++p)
- {
+ for (std::set<std::string>::iterator p = this->LinkPrefixes.begin();
+ p != this->LinkPrefixes.end(); ++p) {
reg += *p;
reg += "|";
- }
+ }
reg += ")";
reg += "([^/:]*)";
@@ -914,68 +857,57 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
this->ExtractAnyLibraryName.compile(reg_any.c_str());
// Create a regex to match static library names.
- if(!this->StaticLinkExtensions.empty())
- {
+ if (!this->StaticLinkExtensions.empty()) {
std::string reg_static = reg;
- reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions,
- LinkStatic);
+ reg_static +=
+ this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic);
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
- fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
+ fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
#endif
this->ExtractStaticLibraryName.compile(reg_static.c_str());
- }
+ }
// Create a regex to match shared library names.
- if(!this->SharedLinkExtensions.empty())
- {
+ if (!this->SharedLinkExtensions.empty()) {
std::string reg_shared = reg;
this->SharedRegexString =
this->CreateExtensionRegex(this->SharedLinkExtensions, LinkShared);
reg_shared += this->SharedRegexString;
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
- fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
+ fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
#endif
this->ExtractSharedLibraryName.compile(reg_shared.c_str());
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddLinkPrefix(const char* p)
{
- if(p && *p)
- {
+ if (p && *p) {
this->LinkPrefixes.insert(p);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type)
{
- if(e && *e)
- {
- if(type == LinkStatic)
- {
+ if (e && *e) {
+ if (type == LinkStatic) {
this->StaticLinkExtensions.push_back(e);
- }
- if(type == LinkShared)
- {
+ }
+ if (type == LinkShared) {
this->SharedLinkExtensions.push_back(e);
- }
- this->LinkExtensions.push_back(e);
}
+ this->LinkExtensions.push_back(e);
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmComputeLinkInformation
-::CreateExtensionRegex(std::vector<std::string> const& exts, LinkType type)
+std::string cmComputeLinkInformation::CreateExtensionRegex(
+ std::vector<std::string> const& exts, LinkType type)
{
// 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::vector<std::string>::const_iterator i = exts.begin();
+ i != exts.end(); ++i) {
// Separate this choice from the previous one.
libext += sep;
sep = "|";
@@ -987,61 +919,49 @@ cmComputeLinkInformation
#else
libext += *i;
#endif
- }
+ }
// Finish the list.
libext += ")";
// Add an optional OpenBSD version component.
- if(this->OpenBSD)
- {
+ if (this->OpenBSD) {
libext += "(\\.[0-9]+\\.[0-9]+)?";
- }
- else if(type == LinkShared)
- {
+ } else if (type == LinkShared) {
libext += "(\\.[0-9]+)?";
- }
+ }
libext += "$";
return libext;
}
-//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::NoCaseExpression(const char* str)
{
std::string ret;
const char* s = str;
- while(*s)
- {
- if(*s == '.')
- {
+ while (*s) {
+ if (*s == '.') {
ret += *s;
- }
- else
- {
+ } else {
ret += "[";
ret += static_cast<char>(tolower(*s));
ret += static_cast<char>(toupper(*s));
ret += "]";
- }
- s++;
}
+ s++;
+ }
return ret;
}
-//-------------------------------------------------------------------
void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt)
{
// If we are changing the current link type add the flag to tell the
// linker about it.
- if(this->CurrentLinkType != lt)
- {
+ if (this->CurrentLinkType != lt) {
this->CurrentLinkType = lt;
- if(this->LinkTypeEnabled)
- {
- switch(this->CurrentLinkType)
- {
+ if (this->LinkTypeEnabled) {
+ switch (this->CurrentLinkType) {
case LinkStatic:
this->Items.push_back(Item(this->StaticLinkTypeFlag, false));
break;
@@ -1050,14 +970,13 @@ void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt)
break;
default:
break;
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddTargetItem(std::string const& item,
- cmTarget* target)
+ cmGeneratorTarget const* target)
{
// This is called to handle a link item that is a full path to a target.
// If the target is not a static library make sure the link type is
@@ -1065,72 +984,63 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item,
// shared and static libraries but static-mode can handle only
// static libraries. If a previous user item changed the link type
// to static we need to make sure it is back to shared.
- if(target->GetType() != cmTarget::STATIC_LIBRARY)
- {
+ if (target->GetType() != cmStateEnums::STATIC_LIBRARY) {
this->SetCurrentLinkType(LinkShared);
- }
+ }
// Keep track of shared library targets linked.
- if(target->GetType() == cmTarget::SHARED_LIBRARY)
- {
+ if (target->GetType() == cmStateEnums::SHARED_LIBRARY) {
this->SharedLibrariesLinked.insert(target);
- }
+ }
// Handle case of an imported shared library with no soname.
- if(this->NoSONameUsesPath &&
- target->IsImportedSharedLibWithoutSOName(this->Config))
- {
+ if (this->NoSONameUsesPath &&
+ target->IsImportedSharedLibWithoutSOName(this->Config)) {
this->AddSharedLibNoSOName(item);
return;
- }
+ }
// If this platform wants a flag before the full path, add it.
- if(!this->LibLinkFileFlag.empty())
- {
+ 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())
- {
+ if (this->OldLinkDirMode && !target->IsFrameworkOnApple() &&
+ this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) ==
+ this->OldLinkDirMask.end()) {
this->OldLinkDirItems.push_back(item);
- }
+ }
// Now add the full path to the library.
this->Items.push_back(Item(item, true, target));
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddFullItem(std::string const& item)
{
// Check for the implicit link directory special case.
- if(this->CheckImplicitDirItem(item))
- {
+ if (this->CheckImplicitDirItem(item)) {
return;
- }
+ }
// Check for case of shared library with no builtin soname.
- if(this->NoSONameUsesPath && this->CheckSharedLibNoSOName(item))
- {
+ if (this->NoSONameUsesPath && this->CheckSharedLibNoSOName(item)) {
return;
- }
+ }
// Full path libraries should specify a valid library file name.
// See documentation of CMP0008.
- if(this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW &&
- (strstr(this->GlobalGenerator->GetName(), "Visual Studio") ||
- strstr(this->GlobalGenerator->GetName(), "Xcode")))
- {
+ std::string generator = this->GlobalGenerator->GetName();
+ if (this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW &&
+ (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.c_str())) {
this->HandleBadFullItem(item, file);
return;
- }
}
+ }
// This is called to handle a link item that is a full path.
// If the target is not a static library make sure the link type is
@@ -1138,67 +1048,76 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
// shared and static libraries but static-mode can handle only
// static libraries. If a previous user item changed the link type
// to static we need to make sure it is back to shared.
- if(this->LinkTypeEnabled)
- {
+ if (this->LinkTypeEnabled) {
std::string name = cmSystemTools::GetFilenameName(item);
- if(this->ExtractSharedLibraryName.find(name))
- {
+ if (this->ExtractSharedLibraryName.find(name)) {
this->SetCurrentLinkType(LinkShared);
- }
- else if(!this->ExtractStaticLibraryName.find(item))
- {
+ } else if (!this->ExtractStaticLibraryName.find(item)) {
// We cannot determine the type. Assume it is the target's
// default type.
this->SetCurrentLinkType(this->StartLinkType);
- }
}
+ }
// 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())
- {
+ if (this->OldLinkDirMode &&
+ this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) ==
+ this->OldLinkDirMask.end()) {
this->OldLinkDirItems.push_back(item);
- }
+ }
// If this platform wants a flag before the full path, add it.
- if(!this->LibLinkFileFlag.empty())
- {
+ 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));
}
-//----------------------------------------------------------------------------
bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
{
// We only switch to a pathless item if the link type may be
// enforced. Fortunately only platforms that support link types
// seem to have magic per-architecture implicit link directories.
- if(!this->LinkTypeEnabled)
- {
+ if (!this->LinkTypeEnabled) {
return false;
- }
+ }
// 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 (this->ImplicitLinkDirs.find(dir) == this->ImplicitLinkDirs.end()) {
// Only libraries in implicit link directories are converted to
// pathless items.
return false;
- }
+ }
// Only apply the policy below if the library file is one that can
// be found by the linker.
std::string file = cmSystemTools::GetFilenameName(item);
- if(!this->ExtractAnyLibraryName.find(file))
- {
+ if (!this->ExtractAnyLibraryName.find(file)) {
return false;
- }
+ }
+
+ // Check the policy for whether we should use the approach below.
+ switch (this->Target->GetPolicyStatusCMP0060()) {
+ case cmPolicies::WARN:
+ if (this->CMP0060Warn) {
+ // Print the warning at most once for this item.
+ std::string const& wid = "CMP0060-WARNING-GIVEN-" + item;
+ if (!this->CMakeInstance->GetPropertyAsBool(wid)) {
+ this->CMakeInstance->SetProperty(wid, "1");
+ this->CMP0060WarnItems.insert(item);
+ }
+ }
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ return false;
+ }
// Many system linkers support multiple architectures by
// automatically selecting the implicit linker search path for the
@@ -1214,7 +1133,6 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
return true;
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddUserItem(std::string const& item,
bool pathNotKnown)
{
@@ -1227,17 +1145,15 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// libfoo.a ==> -Wl,-Bstatic -lfoo
// Pass flags through untouched.
- if(item[0] == '-' || item[0] == '$' || item[0] == '`')
- {
+ if (item[0] == '-' || item[0] == '$' || item[0] == '`') {
// if this is a -l option then we might need to warn about
// CMP0003 so put it in OldUserFlagItems, if it is not a -l
// or -Wl,-l (-framework -pthread), then allow it without a
// CMP0003 as -L will not affect those other linker flags
- if(item.find("-l") == 0 || item.find("-Wl,-l") == 0)
- {
+ if (item.find("-l") == 0 || item.find("-Wl,-l") == 0) {
// This is a linker option provided by the user.
this->OldUserFlagItems.push_back(item);
- }
+ }
// Restore the target link type since this item does not specify
// one.
@@ -1246,7 +1162,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// Use the item verbatim.
this->Items.push_back(Item(item, false));
return;
- }
+ }
// Parse out the prefix, base, and suffix components of the
// library name. If the name matches that of a shared or static
@@ -1259,9 +1175,8 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// libraries. On AIX a library with the name libfoo.a can be
// shared!
std::string lib;
- if(this->ExtractSharedLibraryName.find(item))
- {
- // This matches a shared library file name.
+ if (this->ExtractSharedLibraryName.find(item)) {
+// This matches a shared library file name.
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "shared regex matched [%s] [%s] [%s]\n",
this->ExtractSharedLibraryName.match(1).c_str(),
@@ -1273,10 +1188,8 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// Use just the library name so the linker will search.
lib = this->ExtractSharedLibraryName.match(2);
- }
- else if(this->ExtractStaticLibraryName.find(item))
- {
- // This matches a static library file name.
+ } else if (this->ExtractStaticLibraryName.find(item)) {
+// This matches a static library file name.
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "static regex matched [%s] [%s] [%s]\n",
this->ExtractStaticLibraryName.match(1).c_str(),
@@ -1288,10 +1201,8 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// Use just the library name so the linker will search.
lib = this->ExtractStaticLibraryName.match(2);
- }
- else if(this->ExtractAnyLibraryName.find(item))
- {
- // This matches a library file name.
+ } else if (this->ExtractAnyLibraryName.find(item)) {
+// This matches a library file name.
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "any regex matched [%s] [%s] [%s]\n",
this->ExtractAnyLibraryName.match(1).c_str(),
@@ -1304,21 +1215,18 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// Use just the library name so the linker will search.
lib = this->ExtractAnyLibraryName.match(2);
- }
- else
- {
+ } else {
// This is a name specified by the user.
- if(pathNotKnown)
- {
+ if (pathNotKnown) {
this->OldUserFlagItems.push_back(item);
- }
+ }
// We must ask the linker to search for a library with this name.
// Restore the target link type since this item does not specify
// one.
this->SetCurrentLinkType(this->StartLinkType);
lib = item;
- }
+ }
// Create an option to ask the linker to search for the library.
std::string out = this->LibLinkFlag;
@@ -1332,18 +1240,16 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
// specification.
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
{
// Try to separate the framework name and path.
- if(!this->SplitFramework.find(item.c_str()))
- {
- cmOStringStream e;
+ if (!this->SplitFramework.find(item.c_str())) {
+ std::ostringstream e;
e << "Could not parse framework path \"" << item << "\" "
<< "linked by target " << this->Target->GetName() << ".";
cmSystemTools::Error(e.str().c_str());
return;
- }
+ }
std::string fw_path = this->SplitFramework.match(1);
std::string fw = this->SplitFramework.match(2);
@@ -1362,30 +1268,26 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
// Add the item using the -framework option.
this->Items.push_back(Item("-framework", false));
- fw = this->LocalGenerator->EscapeForShell(fw.c_str());
+ cmOutputConverter converter(this->Makefile->GetStateSnapshot());
+ fw = converter.EscapeForShell(fw);
this->Items.push_back(Item(fw, false));
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddDirectoryItem(std::string const& item)
{
- if(this->Makefile->IsOn("APPLE")
- && cmSystemTools::IsPathToFramework(item.c_str()))
- {
+ if (this->Makefile->IsOn("APPLE") &&
+ cmSystemTools::IsPathToFramework(item.c_str())) {
this->AddFrameworkItem(item);
- }
- else
- {
+ } else {
this->DropDirectoryItem(item);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
{
// A full path to a directory was found as a link item. Warn the
// user.
- cmOStringStream e;
+ std::ostringstream e;
e << "WARNING: Target \"" << this->Target->GetName()
<< "\" requests linking to directory \"" << item << "\". "
<< "Targets may link only to libraries. "
@@ -1393,71 +1295,59 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
cmSystemTools::Message(e.str().c_str());
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::ComputeFrameworkInfo()
{
// Avoid adding implicit framework paths.
std::vector<std::string> implicitDirVec;
// Get platform-wide implicit directories.
- if(const char* implicitLinks = this->Makefile->GetDefinition
- ("CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"))
- {
+ if (const char* implicitLinks = this->Makefile->GetDefinition(
+ "CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")) {
cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec);
- }
+ }
// Get language-specific implicit directories.
std::string implicitDirVar = "CMAKE_";
implicitDirVar += this->LinkLanguage;
implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES";
- if(const char* implicitDirs =
- this->Makefile->GetDefinition(implicitDirVar.c_str()))
- {
+ if (const char* implicitDirs =
+ this->Makefile->GetDefinition(implicitDirVar)) {
cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec);
- }
+ }
- for(std::vector<std::string>::const_iterator i = implicitDirVec.begin();
- i != implicitDirVec.end(); ++i)
- {
- this->FrameworkPathsEmmitted.insert(*i);
- }
+ this->FrameworkPathsEmmitted.insert(implicitDirVec.begin(),
+ implicitDirVec.end());
// Regular expression to extract a framework path and name.
this->SplitFramework.compile("(.*)/(.*)\\.framework$");
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddFrameworkPath(std::string const& p)
{
- if(this->FrameworkPathsEmmitted.insert(p).second)
- {
+ if (this->FrameworkPathsEmmitted.insert(p).second) {
this->FrameworkPaths.push_back(p);
- }
+ }
}
-//----------------------------------------------------------------------------
bool cmComputeLinkInformation::CheckSharedLibNoSOName(std::string const& item)
{
// This platform will use the path to a library as its soname if the
// library is given via path and was not built with an soname. If
// this is a shared library that might be the case.
std::string file = cmSystemTools::GetFilenameName(item);
- if(this->ExtractSharedLibraryName.find(file))
- {
+ if (this->ExtractSharedLibraryName.find(file)) {
// If we can guess the soname fairly reliably then assume the
// library has one. Otherwise assume the library has no builtin
// soname.
std::string soname;
- if(!cmSystemTools::GuessLibrarySOName(item, soname))
- {
+ if (!cmSystemTools::GuessLibrarySOName(item, soname)) {
this->AddSharedLibNoSOName(item);
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::AddSharedLibNoSOName(std::string const& item)
{
// We have a full path to a shared library with no soname. We need
@@ -1472,17 +1362,15 @@ void cmComputeLinkInformation::AddSharedLibNoSOName(std::string const& item)
this->OrderLinkerSearchPath->AddLinkLibrary(item);
}
-//----------------------------------------------------------------------------
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);
- if(i != this->Depends.end())
- {
+ if (i != this->Depends.end()) {
this->Depends.erase(i);
- }
+ }
// Tell the linker to search for the item and provide the proper
// path for it. Do not contribute to any CMP0003 warning (do not
@@ -1491,26 +1379,24 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
this->OrderLinkerSearchPath->AddLinkLibrary(item);
// Produce any needed message.
- switch(this->Target->GetPolicyStatusCMP0008())
- {
- case cmPolicies::WARN:
- {
+ switch (this->Target->GetPolicyStatusCMP0008()) {
+ case cmPolicies::WARN: {
// Print the warning at most once for this item.
std::string wid = "CMP0008-WARNING-GIVEN-";
wid += item;
- if(!this->CMakeInstance->GetPropertyAsBool(wid.c_str()))
- {
- this->CMakeInstance->SetProperty(wid.c_str(), "1");
- cmOStringStream w;
- w << (this->Makefile->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0008)) << "\n"
+ if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(wid)) {
+ this->CMakeInstance->GetState()->SetGlobalProperty(wid, "1");
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0008) << "\n"
<< "Target \"" << this->Target->GetName() << "\" links to item\n"
<< " " << 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->Target->GetBacktrace());
- }
}
+ }
case cmPolicies::OLD:
// OLD behavior does not warn.
break;
@@ -1518,43 +1404,40 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
// NEW behavior will not get here.
break;
case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- {
- cmOStringStream e;
- e << (this->Makefile->GetPolicies()->
- GetRequiredPolicyError(cmPolicies::CMP0008)) << "\n"
+ case cmPolicies::REQUIRED_ALWAYS: {
+ std::ostringstream e;
+ /* clang-format off */
+ e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0008) << "\n"
<< "Target \"" << this->Target->GetName() << "\" links to item\n"
<< " " << 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->Target->GetBacktrace());
- }
- break;
- }
+ } break;
+ }
}
-//----------------------------------------------------------------------------
bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
{
// Support broken projects if necessary.
- if(this->OldLinkDirItems.empty() || this->OldUserFlagItems.empty() ||
- !this->OldLinkDirMode)
- {
+ if (this->OldLinkDirItems.empty() || this->OldUserFlagItems.empty() ||
+ !this->OldLinkDirMode) {
return true;
- }
+ }
// Enforce policy constraints.
- switch(this->Target->GetPolicyStatusCMP0003())
- {
+ switch (this->Target->GetPolicyStatusCMP0003()) {
case cmPolicies::WARN:
- if(!this->CMakeInstance->GetPropertyAsBool("CMP0003-WARNING-GIVEN"))
- {
- this->CMakeInstance->SetProperty("CMP0003-WARNING-GIVEN", "1");
- cmOStringStream w;
+ if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(
+ "CMP0003-WARNING-GIVEN")) {
+ this->CMakeInstance->GetState()->SetGlobalProperty(
+ "CMP0003-WARNING-GIVEN", "1");
+ std::ostringstream w;
this->PrintLinkPolicyDiagnosis(w);
this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
- }
+ }
case cmPolicies::OLD:
// OLD behavior is to add the paths containing libraries with
// known full paths as link directories.
@@ -1563,32 +1446,29 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
// Should never happen due to assignment of OldLinkDirMode
return true;
case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- {
- cmOStringStream e;
- e << (this->Makefile->GetPolicies()->
- GetRequiredPolicyError(cmPolicies::CMP0003)) << "\n";
+ case cmPolicies::REQUIRED_ALWAYS: {
+ std::ostringstream e;
+ e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n";
this->PrintLinkPolicyDiagnosis(e);
this->CMakeInstance->IssueMessage(cmake::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)
- {
+ for (std::vector<std::string>::const_iterator i =
+ this->OldLinkDirItems.begin();
+ i != this->OldLinkDirItems.end(); ++i) {
this->OrderLinkerSearchPath->AddLinkLibrary(*i);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::PrintLinkPolicyDiagnosis(std::ostream& os)
{
// Tell the user what to do.
+ /* clang-format off */
os << "Policy CMP0003 should be set before this line. "
<< "Add code such as\n"
<< " if(COMMAND cmake_policy)\n"
@@ -1596,54 +1476,50 @@ void cmComputeLinkInformation::PrintLinkPolicyDiagnosis(std::ostream& os)
<< " endif(COMMAND cmake_policy)\n"
<< "as early as possible but after the most recent call to "
<< "cmake_minimum_required or cmake_policy(VERSION). ";
+ /* clang-format on */
// List the items that might need the old-style paths.
- os << "This warning appears because target \""
- << this->Target->GetName() << "\" "
+ os << "This warning appears because target \"" << this->Target->GetName()
+ << "\" "
<< "links to some libraries for which the linker must search:\n";
{
- // Format the list of unknown items to be as short as possible while
- // still fitting in the allowed width (a true solution would be the
- // bin packing problem if we were allowed to change the order).
- 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)
- {
- // 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)
- {
- os << line << "\n";
- sep = " ";
- line = "";
+ // Format the list of unknown items to be as short as possible while
+ // still fitting in the allowed width (a true solution would be the
+ // bin packing problem if we were allowed to change the order).
+ 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) {
+ // 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) {
+ os << line << "\n";
+ sep = " ";
+ line = "";
}
- line += sep;
- line += *i;
- // Convert to the other separator.
- sep = ", ";
+ line += sep;
+ line += *i;
+ // Convert to the other separator.
+ sep = ", ";
}
- if(!line.empty())
- {
- os << line << "\n";
+ if (!line.empty()) {
+ os << line << "\n";
}
}
// List the paths old behavior is adding.
os << "and other libraries with known full path:\n";
- std::set<cmStdString> emitted;
- for(std::vector<std::string>::const_iterator
- i = this->OldLinkDirItems.begin();
- i != this->OldLinkDirItems.end(); ++i)
- {
- if(emitted.insert(cmSystemTools::GetFilenamePath(*i)).second)
- {
+ 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";
- }
}
+ }
// Explain.
os << "CMake is adding directories in the second list to the linker "
@@ -1654,216 +1530,178 @@ void cmComputeLinkInformation::PrintLinkPolicyDiagnosis(std::ostream& os)
<< "Run \"cmake --help-policy CMP0003\" for more information.";
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::LoadImplicitLinkInfo()
{
std::vector<std::string> implicitDirVec;
// Get platform-wide implicit directories.
- if(const char* implicitLinks =
- (this->Makefile->GetDefinition
- ("CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES")))
- {
+ if (const char* implicitLinks = (this->Makefile->GetDefinition(
+ "CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES"))) {
cmSystemTools::ExpandListArgument(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"))
- {
+ if (const char* libraryArch =
+ this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
for (std::vector<std::string>::const_iterator i = implicitDirVec.begin();
- i != implicitDirVec.end(); ++i)
- {
+ i != implicitDirVec.end(); ++i) {
this->ImplicitLinkDirs.insert(*i + "/" + libraryArch);
- }
}
+ }
// Get language-specific implicit directories.
std::string implicitDirVar = "CMAKE_";
implicitDirVar += this->LinkLanguage;
implicitDirVar += "_IMPLICIT_LINK_DIRECTORIES";
- if(const char* implicitDirs =
- this->Makefile->GetDefinition(implicitDirVar.c_str()))
- {
+ if (const char* implicitDirs =
+ this->Makefile->GetDefinition(implicitDirVar)) {
cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec);
- }
+ }
// Store implicit link directories.
- for(std::vector<std::string>::const_iterator i = implicitDirVec.begin();
- i != implicitDirVec.end(); ++i)
- {
- this->ImplicitLinkDirs.insert(*i);
- }
+ this->ImplicitLinkDirs.insert(implicitDirVec.begin(), implicitDirVec.end());
// Get language-specific implicit libraries.
std::vector<std::string> implicitLibVec;
std::string implicitLibVar = "CMAKE_";
implicitLibVar += this->LinkLanguage;
implicitLibVar += "_IMPLICIT_LINK_LIBRARIES";
- if(const char* implicitLibs =
- this->Makefile->GetDefinition(implicitLibVar.c_str()))
- {
+ if (const char* implicitLibs =
+ this->Makefile->GetDefinition(implicitLibVar)) {
cmSystemTools::ExpandListArgument(implicitLibs, implicitLibVec);
- }
+ }
// Store implicit link libraries.
- for(std::vector<std::string>::const_iterator i = implicitLibVec.begin();
- i != implicitLibVec.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = implicitLibVec.begin();
+ i != implicitLibVec.end(); ++i) {
// 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')
- {
+ if (item[0] != '-' || item[1] == 'l') {
this->ImplicitLinkLibs.insert(item);
- }
}
+ }
// Get platform specific rpath link directories
- if(const char *rpathDirs =
- (this->Makefile->GetDefinition
- ("CMAKE_PLATFORM_RUNTIME_PATH")))
- {
+ if (const char* rpathDirs =
+ (this->Makefile->GetDefinition("CMAKE_PLATFORM_RUNTIME_PATH"))) {
cmSystemTools::ExpandListArgument(rpathDirs, this->RuntimeLinkDirs);
- }
+ }
}
-//----------------------------------------------------------------------------
std::vector<std::string> const&
cmComputeLinkInformation::GetRuntimeSearchPath()
{
return this->OrderRuntimeSearchPath->GetOrderedDirectories();
}
-//----------------------------------------------------------------------------
-void
-cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
- cmTarget* target)
+void cmComputeLinkInformation::AddLibraryRuntimeInfo(
+ std::string const& fullPath, cmGeneratorTarget const* target)
{
// Ignore targets on Apple where install_name is not @rpath.
// The dependenty library can be found with other means such as
// @loader_path or full paths.
- if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
- if(!target->HasMacOSXRpath(this->Config))
- {
+ if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+ if (!target->HasMacOSXRpathInstallNameDir(this->Config)) {
return;
- }
}
+ }
// Libraries with unknown type must be handled using just the file
// on disk.
- if(target->GetType() == cmTarget::UNKNOWN_LIBRARY)
- {
+ if (target->GetType() == cmStateEnums::UNKNOWN_LIBRARY) {
this->AddLibraryRuntimeInfo(fullPath);
return;
- }
+ }
// Skip targets that are not shared libraries (modules cannot be linked).
- if(target->GetType() != cmTarget::SHARED_LIBRARY)
- {
+ if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
return;
- }
+ }
// 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()? 0 : soName.c_str();
+ const char* soname = soName.empty() ? CM_NULLPTR : soName.c_str();
// Include this library in the runtime path ordering.
this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
- if(this->LinkWithRuntimePath)
- {
+ if (this->LinkWithRuntimePath) {
this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath, soname);
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath)
+void cmComputeLinkInformation::AddLibraryRuntimeInfo(
+ std::string const& fullPath)
{
// Get the name of the library from the file name.
bool is_shared_library = false;
std::string file = cmSystemTools::GetFilenameName(fullPath);
- if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
+ if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
// Check that @rpath is part of the install name.
// If it isn't, return.
std::string soname;
- if(!cmSystemTools::GuessLibraryInstallName(fullPath, soname))
- {
+ if (!cmSystemTools::GuessLibraryInstallName(fullPath, soname)) {
return;
- }
+ }
- if(soname.find("@rpath") == std::string::npos)
- {
+ if (soname.find("@rpath") == std::string::npos) {
return;
- }
}
+ }
- is_shared_library = this->ExtractSharedLibraryName.find(file.c_str());
+ is_shared_library = this->ExtractSharedLibraryName.find(file);
- if(!is_shared_library)
- {
+ 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->ArchivesMayBeShared) {
+ if (this->ExtractStaticLibraryName.find(file.c_str())) {
// This is the name of a shared library or archive.
is_shared_library = true;
- }
}
}
+ }
// It could be an Apple framework
- if(!is_shared_library)
- {
- if(fullPath.find(".framework") != std::string::npos)
- {
- cmsys::RegularExpression splitFramework;
- splitFramework.compile("^(.*)/(.*).framework/(.*)$");
- if(splitFramework.find(fullPath) &&
- (std::string::npos !=
- splitFramework.match(3).find(splitFramework.match(2))))
- {
+ if (!is_shared_library) {
+ if (fullPath.find(".framework") != std::string::npos) {
+ static cmsys::RegularExpression splitFramework(
+ "^(.*)/(.*).framework/(.*)$");
+ if (splitFramework.find(fullPath) &&
+ (std::string::npos !=
+ splitFramework.match(3).find(splitFramework.match(2)))) {
is_shared_library = true;
- }
}
}
+ }
- if(!is_shared_library)
- {
+ if (!is_shared_library) {
return;
- }
+ }
// Include this library in the runtime path ordering.
this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath);
- if(this->LinkWithRuntimePath)
- {
+ if (this->LinkWithRuntimePath) {
this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath);
- }
+ }
}
-//----------------------------------------------------------------------------
static void cmCLI_ExpandListUnique(const char* str,
std::vector<std::string>& out,
- std::set<cmStdString>& emitted)
+ 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)
- {
+ for (std::vector<std::string>::iterator i = tmp.begin(); i != tmp.end();
+ ++i) {
+ if (emitted.insert(*i).second) {
out.push_back(*i);
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
bool for_install)
{
@@ -1882,69 +1720,94 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
bool use_build_rpath =
(outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
!linking_for_install);
- bool use_link_rpath =
- outputRuntime && linking_for_install &&
+ bool use_link_rpath = outputRuntime && linking_for_install &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Construct the RPATH.
- std::set<cmStdString> emitted;
- if(use_install_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);
+ }
+ 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);
}
- if(use_build_rpath || use_link_rpath)
- {
+ }
+ if (use_build_rpath || use_link_rpath) {
+ std::string rootPath;
+ if (const char* sysrootLink =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
+ rootPath = sysrootLink;
+ } else {
+ rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+ }
+ const char* stagePath =
+ this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
+ const char* 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)
- {
+ for (std::vector<std::string>::const_iterator ri = rdirs.begin();
+ ri != rdirs.end(); ++ri) {
// 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)
- {
- if(emitted.insert(*ri).second)
- {
- runtimeDirs.push_back(*ri);
- }
+ if (use_build_rpath) {
+ 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;
+ cmSystemTools::ConvertToUnixSlashes(d);
}
- else if(use_link_rpath)
- {
+ if (emitted.insert(d).second) {
+ runtimeDirs.push_back(d);
+ }
+ } else if (use_link_rpath) {
// Do not add any path inside the source or build tree.
- const char* topSourceDir = this->Makefile->GetHomeDirectory();
- const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
- if(!cmSystemTools::ComparePath(ri->c_str(), topSourceDir) &&
- !cmSystemTools::ComparePath(ri->c_str(), topBinaryDir) &&
- !cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
- !cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
- {
- if(emitted.insert(*ri).second)
- {
- runtimeDirs.push_back(*ri);
- }
+ 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;
+ 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;
+ cmSystemTools::ConvertToUnixSlashes(d);
+ }
+ if (emitted.insert(d).second) {
+ runtimeDirs.push_back(d);
}
}
}
}
+ }
// Add runtime paths required by the languages to always be
// present. This is done even when skipping rpath support.
{
- cmTarget::LinkClosure const* lc =
- this->Target->GetLinkClosure(this->Config, this->HeadTarget);
- for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
- li != lc->Languages.end(); ++li)
- {
- std::string useVar = "CMAKE_" + *li +
- "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
- if(this->Makefile->IsOn(useVar.c_str()))
- {
- std::string dirVar = "CMAKE_" + *li +
- "_IMPLICIT_LINK_DIRECTORIES";
- if(const char* dirs = this->Makefile->GetDefinition(dirVar.c_str()))
- {
- cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted);
+ 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) {
+ std::string useVar =
+ "CMAKE_" + *li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
+ if (this->Makefile->IsOn(useVar)) {
+ std::string dirVar = "CMAKE_" + *li + "_IMPLICIT_LINK_DIRECTORIES";
+ if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
+ cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted);
}
}
}
@@ -1955,7 +1818,6 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted);
}
-//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::GetRPathString(bool for_install)
{
// Get the directories to use.
@@ -1963,48 +1825,32 @@ std::string cmComputeLinkInformation::GetRPathString(bool for_install)
this->GetRPath(runtimeDirs, for_install);
// Concatenate the paths.
- std::string rpath;
- const char* sep = "";
- for(std::vector<std::string>::const_iterator ri = runtimeDirs.begin();
- ri != runtimeDirs.end(); ++ri)
- {
- // Separate from previous path.
- rpath += sep;
- sep = this->GetRuntimeSep().c_str();
-
- // Add this path.
- rpath += *ri;
- }
+ std::string rpath = cmJoin(runtimeDirs, this->GetRuntimeSep());
// If the rpath will be replaced at install time, prepare space.
- if(!for_install && this->RuntimeUseChrpath)
- {
- if(!rpath.empty())
- {
+ if (!for_install && this->RuntimeUseChrpath) {
+ if (!rpath.empty()) {
// Add one trailing separator so the linker does not re-use the
// rpath .dynstr entry for a symbol name that happens to match
// the end of the rpath string.
rpath += this->GetRuntimeSep();
- }
+ }
// Make sure it is long enough to hold the replacement value.
std::string::size_type minLength = this->GetChrpathString().length();
- while(rpath.length() < minLength)
- {
+ while (rpath.length() < minLength) {
rpath += this->GetRuntimeSep();
- }
}
+ }
return rpath;
}
-//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::GetChrpathString()
{
- if(!this->RuntimeUseChrpath)
- {
+ if (!this->RuntimeUseChrpath) {
return "";
- }
+ }
return this->GetRPathString(true);
}
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index e6ee87185..00e3ad265 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -1,27 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmComputeLinkInformation_h
#define cmComputeLinkInformation_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
-class cmake;
+class cmGeneratorTarget;
class cmGlobalGenerator;
-class cmLocalGenerator;
class cmMakefile;
-class cmTarget;
class cmOrderDirectories;
+class cmake;
/** \class cmComputeLinkInformation
* \brief Compute link information for a target in one configuration.
@@ -29,41 +23,51 @@ class cmOrderDirectories;
class cmComputeLinkInformation
{
public:
- cmComputeLinkInformation(cmTarget* target, const char* config,
- cmTarget* headTarget);
+ cmComputeLinkInformation(cmGeneratorTarget const* target,
+ const std::string& config);
~cmComputeLinkInformation();
bool Compute();
struct Item
{
- Item(): Value(), IsPath(true), Target(0) {}
- Item(Item const& item):
- Value(item.Value), IsPath(item.IsPath), Target(item.Target) {}
- Item(std::string const& v, bool p, cmTarget* target = 0):
- Value(v), IsPath(p), Target(target) {}
+ Item()
+ : Value()
+ , IsPath(true)
+ , Target(CM_NULLPTR)
+ {
+ }
+ Item(std::string const& v, bool p,
+ cmGeneratorTarget const* target = CM_NULLPTR)
+ : Value(v)
+ , IsPath(p)
+ , Target(target)
+ {
+ }
std::string Value;
bool IsPath;
- cmTarget* Target;
+ cmGeneratorTarget const* Target;
};
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();
- const char* GetLinkLanguage() const { return this->LinkLanguage; }
+ std::string GetLinkLanguage() const { return this->LinkLanguage; }
std::vector<std::string> const& GetRuntimeSearchPath();
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<cmTarget*> const& GetSharedLibrariesLinked();
+ std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked();
std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
std::string GetRPathLinkString();
+
+ std::string GetConfig() const { return this->Config; }
private:
- void AddItem(std::string const& item, cmTarget* tgt);
- void AddSharedDepItem(std::string const& item, cmTarget* tgt);
+ void AddItem(std::string const& item, const cmGeneratorTarget* tgt);
+ void AddSharedDepItem(std::string const& item, cmGeneratorTarget const* tgt);
// Output information.
ItemVector Items;
@@ -71,20 +75,17 @@ private:
std::vector<std::string> Depends;
std::vector<std::string> FrameworkPaths;
std::vector<std::string> RuntimeSearchPath;
- std::set<cmTarget*> SharedLibrariesLinked;
+ std::set<cmGeneratorTarget const*> SharedLibrariesLinked;
// Context information.
- cmTarget* Target;
- cmTarget* HeadTarget;
+ cmGeneratorTarget const* Target;
cmMakefile* Makefile;
- cmLocalGenerator* LocalGenerator;
cmGlobalGenerator* GlobalGenerator;
cmake* CMakeInstance;
// Configuration information.
- const char* Config;
- const char* LinkLanguage;
- bool LinkDependsNoShared;
+ std::string Config;
+ std::string LinkLanguage;
// Modes for dealing with dependent shared libraries.
enum SharedDepMode
@@ -95,8 +96,6 @@ private:
SharedDepModeLink // List file on link line
};
- // System info.
- bool UseImportLibrary;
const char* LoaderFlag;
std::string LibLinkFlag;
std::string LibLinkFileFlag;
@@ -104,34 +103,34 @@ private:
std::string RuntimeFlag;
std::string RuntimeSep;
std::string RuntimeAlways;
- bool RuntimeUseChrpath;
- bool NoSONameUsesPath;
- bool LinkWithRuntimePath;
std::string RPathLinkFlag;
SharedDepMode SharedDependencyMode;
+ enum LinkType
+ {
+ LinkUnknown,
+ LinkStatic,
+ LinkShared
+ };
+ void SetCurrentLinkType(LinkType lt);
+
// Link type adjustment.
void ComputeLinkTypeInfo();
- enum LinkType { LinkUnknown, LinkStatic, LinkShared };
LinkType StartLinkType;
LinkType CurrentLinkType;
std::string StaticLinkTypeFlag;
std::string SharedLinkTypeFlag;
- bool LinkTypeEnabled;
- void SetCurrentLinkType(LinkType lt);
- bool ArchivesMayBeShared;
// Link item parsing.
void ComputeItemParserInfo();
std::vector<std::string> StaticLinkExtensions;
std::vector<std::string> SharedLinkExtensions;
std::vector<std::string> LinkExtensions;
- std::set<cmStdString> LinkPrefixes;
+ std::set<std::string> LinkPrefixes;
cmsys::RegularExpression ExtractStaticLibraryName;
cmsys::RegularExpression ExtractSharedLibraryName;
cmsys::RegularExpression ExtractAnyLibraryName;
std::string SharedRegexString;
- bool OpenBSD;
void AddLinkPrefix(const char* p);
void AddLinkExtension(const char* e, LinkType type);
std::string CreateExtensionRegex(std::vector<std::string> const& exts,
@@ -139,7 +138,7 @@ private:
std::string NoCaseExpression(const char* str);
// Handling of link items.
- void AddTargetItem(std::string const& item, cmTarget* target);
+ void AddTargetItem(std::string const& item, const cmGeneratorTarget* target);
void AddFullItem(std::string const& item);
bool CheckImplicitDirItem(std::string const& item);
void AddUserItem(std::string const& item, bool pathNotKnown);
@@ -153,7 +152,7 @@ private:
// Framework info.
void ComputeFrameworkInfo();
void AddFrameworkPath(std::string const& p);
- std::set<cmStdString> FrameworkPathsEmmitted;
+ std::set<std::string> FrameworkPathsEmmitted;
cmsys::RegularExpression SplitFramework;
// Linker search path computation.
@@ -165,25 +164,36 @@ private:
void LoadImplicitLinkInfo();
void AddImplicitLinkInfo();
void AddImplicitLinkInfo(std::string const& lang);
- std::set<cmStdString> ImplicitLinkDirs;
- std::set<cmStdString> ImplicitLinkLibs;
+ std::set<std::string> ImplicitLinkDirs;
+ std::set<std::string> ImplicitLinkLibs;
// Additional paths configured by the runtime linker
std::vector<std::string> RuntimeLinkDirs;
// Linker search path compatibility mode.
- std::set<cmStdString> OldLinkDirMask;
+ std::set<std::string> OldLinkDirMask;
std::vector<std::string> OldLinkDirItems;
std::vector<std::string> OldUserFlagItems;
- bool OldLinkDirMode;
-
+ std::set<std::string> CMP0060WarnItems;
+ // Dependent library path computation.
+ cmOrderDirectories* OrderDependentRPath;
// Runtime path computation.
cmOrderDirectories* OrderRuntimeSearchPath;
- void AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget* target);
- void AddLibraryRuntimeInfo(std::string const& fullPath);
- // Dependent library path computation.
- cmOrderDirectories* OrderDependentRPath;
+ bool OldLinkDirMode;
+ bool OpenBSD;
+ bool LinkDependsNoShared;
+ bool UseImportLibrary;
+ bool RuntimeUseChrpath;
+ bool NoSONameUsesPath;
+ bool LinkWithRuntimePath;
+ bool LinkTypeEnabled;
+ bool ArchivesMayBeShared;
+ bool CMP0060Warn;
+
+ void AddLibraryRuntimeInfo(std::string const& fullPath,
+ const cmGeneratorTarget* target);
+ void AddLibraryRuntimeInfo(std::string const& fullPath);
};
#endif
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 0829add20..ff19eac63 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -1,27 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeTargetDepends.h"
#include "cmComputeComponentGraph.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTargetDepend.h"
#include "cmake.h"
-#include <algorithm>
-
#include <assert.h>
+#include <sstream>
+#include <stdio.h>
+#include <utility>
+
+class cmListFileBacktrace;
/*
@@ -92,155 +93,152 @@ transitively on all the static libraries it links.
*/
-//----------------------------------------------------------------------------
cmComputeTargetDepends::cmComputeTargetDepends(cmGlobalGenerator* gg)
{
this->GlobalGenerator = gg;
cmake* cm = this->GlobalGenerator->GetCMakeInstance();
- this->DebugMode = cm->GetPropertyAsBool("GLOBAL_DEPENDS_DEBUG_MODE");
- this->NoCycles = cm->GetPropertyAsBool("GLOBAL_DEPENDS_NO_CYCLES");
+ this->DebugMode =
+ cm->GetState()->GetGlobalPropertyAsBool("GLOBAL_DEPENDS_DEBUG_MODE");
+ this->NoCycles =
+ cm->GetState()->GetGlobalPropertyAsBool("GLOBAL_DEPENDS_NO_CYCLES");
}
-//----------------------------------------------------------------------------
cmComputeTargetDepends::~cmComputeTargetDepends()
{
}
-//----------------------------------------------------------------------------
bool cmComputeTargetDepends::Compute()
{
// Build the original graph.
this->CollectTargets();
this->CollectDepends();
- if(this->DebugMode)
- {
+ if (this->DebugMode) {
this->DisplayGraph(this->InitialGraph, "initial");
- }
+ }
// Identify components.
cmComputeComponentGraph ccg(this->InitialGraph);
- if(this->DebugMode)
- {
+ if (this->DebugMode) {
this->DisplayComponents(ccg);
- }
- if(!this->CheckComponents(ccg))
- {
+ }
+ if (!this->CheckComponents(ccg)) {
return false;
- }
+ }
// Compute the final dependency graph.
- if(!this->ComputeFinalDepends(ccg))
- {
+ if (!this->ComputeFinalDepends(ccg)) {
return false;
- }
- if(this->DebugMode)
- {
+ }
+ if (this->DebugMode) {
this->DisplayGraph(this->FinalGraph, "final");
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
-void
-cmComputeTargetDepends::GetTargetDirectDepends(cmTarget* t,
- cmTargetDependSet& deps)
+void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t,
+ cmTargetDependSet& deps)
{
// Lookup the index for this target. All targets should be known by
// this point.
- std::map<cmTarget*, int>::const_iterator tii = this->TargetIndex.find(t);
+ std::map<cmGeneratorTarget const*, int>::const_iterator 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)
- {
- cmTarget* dep = this->Targets[*ni];
+ 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());
- }
+ }
}
-//----------------------------------------------------------------------------
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)
- {
- cmTargets& targets = lgens[i]->GetMakefile()->GetTargets();
- for(cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti)
- {
- cmTarget* target = &ti->second;
+ 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;
int index = static_cast<int>(this->Targets.size());
- this->TargetIndex[target] = index;
- this->Targets.push_back(target);
- }
+ this->TargetIndex[gt] = index;
+ this->Targets.push_back(gt);
}
+ }
}
-//----------------------------------------------------------------------------
void cmComputeTargetDepends::CollectDepends()
{
// Allocate the dependency graph adjacency lists.
this->InitialGraph.resize(this->Targets.size());
// Compute each dependency list.
- for(unsigned int i=0; i < this->Targets.size(); ++i)
- {
+ for (unsigned int i = 0; i < this->Targets.size(); ++i) {
this->CollectTargetDepends(i);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
{
// Get the depender.
- cmTarget* depender = this->Targets[depender_index];
+ cmGeneratorTarget const* depender = this->Targets[depender_index];
+ if (depender->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
// Loop over all targets linked directly in all configs.
// We need to make targets depend on the union of all config-specific
// dependencies in all targets, because the generated build-systems can't
// deal with config-specific dependencies.
{
- std::set<cmStdString> emitted;
- {
- std::vector<std::string> tlibs;
- depender->GetDirectLinkLibraries(0, tlibs, depender);
- // A target should not depend on itself.
- emitted.insert(depender->GetName());
- for(std::vector<std::string>::const_iterator lib = tlibs.begin();
- lib != tlibs.end(); ++lib)
- {
- // Don't emit the same library twice for this target.
- if(emitted.insert(*lib).second)
- {
- this->AddTargetDepend(depender_index, lib->c_str(), true);
- this->AddInterfaceDepends(depender_index, lib->c_str(),
- true, emitted);
- }
+ std::set<std::string> emitted;
+
+ std::vector<std::string> configs;
+ depender->Makefile->GetConfigurations(configs);
+ if (configs.empty()) {
+ configs.push_back("");
}
- }
- std::vector<std::string> configs;
- depender->GetMakefile()->GetConfigurations(configs);
- for (std::vector<std::string>::const_iterator it = configs.begin();
- it != configs.end(); ++it)
- {
- std::vector<std::string> tlibs;
- depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender);
- // A target should not depend on itself.
- emitted.insert(depender->GetName());
- for(std::vector<std::string>::const_iterator lib = tlibs.begin();
- lib != tlibs.end(); ++lib)
- {
- // Don't emit the same library twice for this target.
- if(emitted.insert(*lib).second)
- {
- this->AddTargetDepend(depender_index, lib->c_str(), true);
- this->AddInterfaceDepends(depender_index, lib->c_str(),
- true, emitted);
+ for (std::vector<std::string>::const_iterator it = configs.begin();
+ it != configs.end(); ++it) {
+ 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;
+ }
+ const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib);
+ }
+ }
+
+ 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) {
+ // 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);
}
}
}
@@ -248,134 +246,135 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
// Loop over all utility dependencies.
{
- std::set<cmStdString> const& tutils = depender->GetUtilities();
- std::set<cmStdString> emitted;
- // A target should not depend on itself.
- emitted.insert(depender->GetName());
- for(std::set<cmStdString>::const_iterator util = tutils.begin();
- util != tutils.end(); ++util)
- {
- // Don't emit the same utility twice for this target.
- if(emitted.insert(*util).second)
- {
- this->AddTargetDepend(depender_index, util->c_str(), false);
+ std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
+ std::set<std::string> 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) {
+ // Don't emit the same utility twice for this target.
+ if (emitted.insert(*util).second) {
+ this->AddTargetDepend(depender_index, *util, false);
}
}
}
}
-//----------------------------------------------------------------------------
-void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
- cmTarget* dependee,
- const char *config,
- std::set<cmStdString> &emitted)
+void cmComputeTargetDepends::AddInterfaceDepends(
+ int depender_index, const cmGeneratorTarget* dependee,
+ const std::string& config, std::set<std::string>& emitted)
{
- cmTarget* depender = this->Targets[depender_index];
- if(cmTarget::LinkInterface const* iface =
- dependee->GetLinkInterface(config, depender))
- {
- for(std::vector<std::string>::const_iterator
- lib = iface->Libraries.begin();
- lib != iface->Libraries.end(); ++lib)
- {
+ 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) {
// Don't emit the same library twice for this target.
- if(emitted.insert(*lib).second)
- {
- this->AddTargetDepend(depender_index, lib->c_str(), true);
- this->AddInterfaceDepends(depender_index, lib->c_str(),
- true, emitted);
- }
+ if (emitted.insert(*lib).second) {
+ this->AddTargetDepend(depender_index, *lib, true);
+ this->AddInterfaceDepends(depender_index, *lib, config, emitted);
}
}
+ }
}
-//----------------------------------------------------------------------------
-void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
- const char* dependee_name,
- bool linking,
- std::set<cmStdString> &emitted)
+void cmComputeTargetDepends::AddInterfaceDepends(
+ int depender_index, cmLinkItem const& dependee_name,
+ const std::string& config, std::set<std::string>& emitted)
{
- cmTarget* depender = this->Targets[depender_index];
- cmTarget* dependee =
- depender->GetMakefile()->FindTargetToUse(dependee_name);
+ cmGeneratorTarget const* depender = this->Targets[depender_index];
+ cmGeneratorTarget const* dependee = dependee_name.Target;
// 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(linking && dependee &&
- dependee->GetType() == cmTarget::EXECUTABLE &&
- !dependee->IsExecutableWithExports())
- {
- dependee = 0;
- }
+ if (dependee && dependee->GetType() == cmStateEnums::EXECUTABLE &&
+ !dependee->IsExecutableWithExports()) {
+ dependee = CM_NULLPTR;
+ }
- if(dependee)
- {
- this->AddInterfaceDepends(depender_index, dependee, 0, emitted);
- std::vector<std::string> configs;
- depender->GetMakefile()->GetConfigurations(configs);
- for (std::vector<std::string>::const_iterator it = configs.begin();
- it != configs.end(); ++it)
- {
- // A target should not depend on itself.
- emitted.insert(depender->GetName());
- this->AddInterfaceDepends(depender_index, dependee,
- it->c_str(), emitted);
- }
- }
+ if (dependee) {
+ // A target should not depend on itself.
+ emitted.insert(depender->GetName());
+ this->AddInterfaceDepends(depender_index, dependee, config, emitted);
+ }
}
-//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(int depender_index,
- const char* dependee_name,
+ cmLinkItem const& dependee_name,
bool linking)
{
// Get the depender.
- cmTarget* depender = this->Targets[depender_index];
+ cmGeneratorTarget const* depender = this->Targets[depender_index];
// Check the target's makefile first.
- cmTarget* dependee =
- depender->GetMakefile()->FindTargetToUse(dependee_name);
+ cmGeneratorTarget const* dependee = dependee_name.Target;
+
+ if (!dependee && !linking &&
+ (depender->GetType() != cmStateEnums::GLOBAL_TARGET)) {
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ bool issueMessage = false;
+ std::ostringstream e;
+ switch (depender->GetPolicyStatusCMP0046()) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\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) {
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+
+ 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());
+ }
+ }
+ }
// 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(linking && dependee &&
- dependee->GetType() == cmTarget::EXECUTABLE &&
- !dependee->IsExecutableWithExports())
- {
- dependee = 0;
- }
+ if (linking && dependee && dependee->GetType() == cmStateEnums::EXECUTABLE &&
+ !dependee->IsExecutableWithExports()) {
+ dependee = CM_NULLPTR;
+ }
- if(dependee)
- {
+ if (dependee) {
this->AddTargetDepend(depender_index, dependee, linking);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(int depender_index,
- cmTarget* dependee,
+ const cmGeneratorTarget* dependee,
bool linking)
{
- if(dependee->IsImported())
- {
- // Skip imported targets but follow their utility dependencies.
- std::set<cmStdString> const& utils = dependee->GetUtilities();
- for(std::set<cmStdString>::const_iterator i = utils.begin();
- i != utils.end(); ++i)
- {
- if(cmTarget* transitive_dependee =
- dependee->GetMakefile()->FindTargetToUse(i->c_str()))
- {
+ 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);
- }
}
}
- else
- {
+ } else {
// Lookup the index for this target. All targets should be known by
// this point.
- std::map<cmTarget*, int>::const_iterator tii =
+ std::map<cmGeneratorTarget const*, int>::const_iterator tii =
this->TargetIndex.find(dependee);
assert(tii != this->TargetIndex.end());
int dependee_index = tii->second;
@@ -383,197 +382,161 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
// Add this entry to the dependency graph.
this->InitialGraph[depender_index].push_back(
cmGraphEdge(dependee_index, !linking));
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmComputeTargetDepends::DisplayGraph(Graph const& graph, const char* name)
+void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
+ const std::string& name)
{
- fprintf(stderr, "The %s target dependency graph is:\n", name);
+ fprintf(stderr, "The %s target dependency graph is:\n", name.c_str());
int n = static_cast<int>(graph.size());
- for(int depender_index = 0; depender_index < n; ++depender_index)
- {
+ for (int depender_index = 0; depender_index < n; ++depender_index) {
EdgeList const& nl = graph[depender_index];
- cmTarget* depender = this->Targets[depender_index];
- fprintf(stderr, "target %d is [%s]\n",
- depender_index, depender->GetName());
- for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
- {
+ 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;
- cmTarget* dependee = this->Targets[dependee_index];
+ cmGeneratorTarget const* dependee = this->Targets[dependee_index];
fprintf(stderr, " depends on target %d [%s] (%s)\n", dependee_index,
- dependee->GetName(), ni->IsStrong()? "strong" : "weak");
- }
+ dependee->GetName().c_str(), ni->IsStrong() ? "strong" : "weak");
}
+ }
fprintf(stderr, "\n");
}
-//----------------------------------------------------------------------------
-void
-cmComputeTargetDepends
-::DisplayComponents(cmComputeComponentGraph const& ccg)
+void cmComputeTargetDepends::DisplayComponents(
+ cmComputeComponentGraph const& ccg)
{
fprintf(stderr, "The strongly connected components are:\n");
std::vector<NodeList> const& components = ccg.GetComponents();
int n = static_cast<int>(components.size());
- for(int c = 0; c < n; ++c)
- {
+ 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)
- {
+ for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
int i = *ni;
- fprintf(stderr, " contains target %d [%s]\n",
- i, this->Targets[i]->GetName());
- }
+ fprintf(stderr, " contains target %d [%s]\n", i,
+ this->Targets[i]->GetName().c_str());
}
+ }
fprintf(stderr, "\n");
}
-//----------------------------------------------------------------------------
-bool
-cmComputeTargetDepends
-::CheckComponents(cmComputeComponentGraph const& ccg)
+bool cmComputeTargetDepends::CheckComponents(
+ cmComputeComponentGraph const& ccg)
{
// All non-trivial components should consist only of static
// libraries.
std::vector<NodeList> const& components = ccg.GetComponents();
int nc = static_cast<int>(components.size());
- for(int c=0; c < nc; ++c)
- {
+ for (int c = 0; c < nc; ++c) {
// Get the current component.
NodeList const& nl = components[c];
// Skip trivial components.
- if(nl.size() < 2)
- {
+ if (nl.size() < 2) {
continue;
- }
+ }
// Immediately complain if no cycles are allowed at all.
- if(this->NoCycles)
- {
+ if (this->NoCycles) {
this->ComplainAboutBadComponent(ccg, c);
return false;
- }
+ }
// 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() != cmTarget::STATIC_LIBRARY)
- {
+ for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
+ if (this->Targets[*ni]->GetType() != cmStateEnums::STATIC_LIBRARY) {
this->ComplainAboutBadComponent(ccg, c);
return false;
- }
}
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-void
-cmComputeTargetDepends
-::ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c,
- bool strong)
+void cmComputeTargetDepends::ComplainAboutBadComponent(
+ cmComputeComponentGraph const& ccg, int c, bool strong)
{
// Construct the error message.
- cmOStringStream e;
+ std::ostringstream e;
e << "The inter-target dependency graph contains the following "
<< "strongly connected component (cycle):\n";
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 (NodeList::const_iterator ci = cl.begin(); ci != cl.end(); ++ci) {
// Get the depender.
int i = *ci;
- cmTarget* depender = this->Targets[i];
+ cmGeneratorTarget const* depender = this->Targets[i];
// Describe the depender.
e << " \"" << depender->GetName() << "\" of type "
- << cmTarget::GetTargetTypeName(depender->GetType()) << "\n";
+ << cmState::GetTargetTypeName(depender->GetType()) << "\n";
// 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)
- {
+ for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
int j = *ni;
- if(cmap[j] == c)
- {
- cmTarget* dependee = this->Targets[j];
+ 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";
}
}
- if(strong)
- {
+ }
+ if (strong) {
// Custom command executable dependencies cannot occur within a
// component of static libraries. The cycle must appear in calls
// to add_dependencies.
e << "The component contains at least one cycle consisting of strong "
<< "dependencies (created by add_dependencies) that cannot be broken.";
- }
- else if(this->NoCycles)
- {
+ } else if (this->NoCycles) {
e << "The GLOBAL_DEPENDS_NO_CYCLES global property is enabled, so "
<< "cyclic dependencies are not allowed even among static libraries.";
- }
- else
- {
+ } else {
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());
}
-//----------------------------------------------------------------------------
-bool
-cmComputeTargetDepends
-::IntraComponent(std::vector<int> const& cmap, int c, int i, int* head,
- std::set<int>& emitted, std::set<int>& visited)
+bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
+ int c, int i, int* head,
+ std::set<int>& emitted,
+ std::set<int>& visited)
{
- if(!visited.insert(i).second)
- {
+ if (!visited.insert(i).second) {
// Cycle in utility depends!
return false;
- }
- if(emitted.insert(i).second)
- {
+ }
+ 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)
- {
+ for (EdgeList::const_iterator ei = el.begin(); ei != el.end(); ++ei) {
int j = *ei;
- if(cmap[j] == c && ei->IsStrong())
- {
+ if (cmap[j] == c && ei->IsStrong()) {
this->FinalGraph[i].push_back(cmGraphEdge(j, true));
- if(!this->IntraComponent(cmap, c, j, head, emitted, visited))
- {
+ if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) {
return false;
- }
}
}
+ }
// Prepend to a linear linked-list of intra-component edges.
- if(*head >= 0)
- {
+ if (*head >= 0) {
this->FinalGraph[i].push_back(cmGraphEdge(*head, false));
- }
- else
- {
+ } else {
this->ComponentTail[c] = i;
- }
- *head = i;
}
+ *head = i;
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmComputeTargetDepends
-::ComputeFinalDepends(cmComputeComponentGraph const& ccg)
+bool cmComputeTargetDepends::ComputeFinalDepends(
+ cmComputeComponentGraph const& ccg)
{
// Get the component graph information.
std::vector<NodeList> const& components = ccg.GetComponents();
@@ -588,38 +551,34 @@ cmComputeTargetDepends
this->ComponentHead.resize(components.size());
this->ComponentTail.resize(components.size());
int nc = static_cast<int>(components.size());
- for(int c=0; c < nc; ++c)
- {
+ for (int c = 0; c < nc; ++c) {
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 (NodeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
+ ++ni) {
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;
- }
}
- this->ComponentHead[c] = head;
}
+ this->ComponentHead[c] = head;
+ }
// Convert inter-component edges to connect component tails to heads.
int n = static_cast<int>(cgraph.size());
- for(int depender_component=0; depender_component < n; ++depender_component)
- {
+ for (int depender_component = 0; depender_component < n;
+ ++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)
- {
+ for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
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].push_back(
+ cmGraphEdge(dependee_component_head, ni->IsStrong()));
}
+ }
return true;
}
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index d6131cf1c..e93e376ce 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -1,26 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmComputeTargetDepends_h
#define cmComputeTargetDepends_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGraphAdjacencyList.h"
-#include <stack>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
class cmComputeComponentGraph;
+class cmGeneratorTarget;
class cmGlobalGenerator;
-class cmTarget;
+class cmLinkItem;
class cmTargetDependSet;
/** \class cmComputeTargetDepends
@@ -38,28 +33,36 @@ public:
bool Compute();
- std::vector<cmTarget*> const& GetTargets() const { return this->Targets; }
- void GetTargetDirectDepends(cmTarget* t, cmTargetDependSet& deps);
+ std::vector<cmGeneratorTarget const*> const& GetTargets() const
+ {
+ return this->Targets;
+ }
+ void GetTargetDirectDepends(cmGeneratorTarget const* t,
+ cmTargetDependSet& deps);
+
private:
void CollectTargets();
void CollectDepends();
void CollectTargetDepends(int depender_index);
- void AddTargetDepend(int depender_index, const char* dependee_name,
+ void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name,
+ bool linking);
+ void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee,
bool linking);
- void AddTargetDepend(int depender_index, cmTarget* dependee, bool linking);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
- void AddInterfaceDepends(int depender_index, const char* dependee_name,
- bool linking, std::set<cmStdString> &emitted);
- void AddInterfaceDepends(int depender_index, cmTarget* dependee,
- const char *config,
- std::set<cmStdString> &emitted);
+ void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
+ const std::string& config,
+ std::set<std::string>& emitted);
+ void AddInterfaceDepends(int depender_index,
+ cmGeneratorTarget const* dependee,
+ const std::string& config,
+ std::set<std::string>& emitted);
cmGlobalGenerator* GlobalGenerator;
bool DebugMode;
bool NoCycles;
// Collect all targets.
- std::vector<cmTarget*> Targets;
- std::map<cmTarget*, int> TargetIndex;
+ std::vector<cmGeneratorTarget const*> Targets;
+ std::map<cmGeneratorTarget const*, int> TargetIndex;
// Represent the target dependency graph. The entry at each
// top-level index corresponds to a depender whose dependencies are
@@ -69,7 +72,7 @@ private:
typedef cmGraphAdjacencyList Graph;
Graph InitialGraph;
Graph FinalGraph;
- void DisplayGraph(Graph const& graph, const char* name);
+ void DisplayGraph(Graph const& graph, const std::string& name);
// Deal with connected components.
void DisplayComponents(cmComputeComponentGraph const& ccg);
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
new file mode 100644
index 000000000..2bacf7321
--- /dev/null
+++ b/Source/cmConditionEvaluator.cxx
@@ -0,0 +1,756 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmConditionEvaluator.h"
+
+#include "cmConfigure.h"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+
+class cmCommand;
+class cmTest;
+
+static std::string const keyAND = "AND";
+static std::string const keyCOMMAND = "COMMAND";
+static std::string const keyDEFINED = "DEFINED";
+static std::string const keyEQUAL = "EQUAL";
+static std::string const keyEXISTS = "EXISTS";
+static std::string const keyGREATER = "GREATER";
+static std::string const keyGREATER_EQUAL = "GREATER_EQUAL";
+static std::string const keyIN_LIST = "IN_LIST";
+static std::string const keyIS_ABSOLUTE = "IS_ABSOLUTE";
+static std::string const keyIS_DIRECTORY = "IS_DIRECTORY";
+static std::string const keyIS_NEWER_THAN = "IS_NEWER_THAN";
+static std::string const keyIS_SYMLINK = "IS_SYMLINK";
+static std::string const keyLESS = "LESS";
+static std::string const keyLESS_EQUAL = "LESS_EQUAL";
+static std::string const keyMATCHES = "MATCHES";
+static std::string const keyNOT = "NOT";
+static std::string const keyOR = "OR";
+static std::string const keyParenL = "(";
+static std::string const keyParenR = ")";
+static std::string const keyPOLICY = "POLICY";
+static std::string const keySTREQUAL = "STREQUAL";
+static std::string const keySTRGREATER = "STRGREATER";
+static std::string const keySTRGREATER_EQUAL = "STRGREATER_EQUAL";
+static std::string const keySTRLESS = "STRLESS";
+static std::string const keySTRLESS_EQUAL = "STRLESS_EQUAL";
+static std::string const keyTARGET = "TARGET";
+static std::string const keyTEST = "TEST";
+static std::string const keyVERSION_EQUAL = "VERSION_EQUAL";
+static std::string const keyVERSION_GREATER = "VERSION_GREATER";
+static std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL";
+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)
+ : Makefile(makefile)
+ , ExecutionContext(context)
+ , Backtrace(bt)
+ , Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012))
+ , Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054))
+ , Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057))
+ , Policy64Status(makefile.GetPolicyStatus(cmPolicies::CMP0064))
+{
+}
+
+//=========================================================================
+// order of operations,
+// 1. ( ) -- parenthetical groups
+// 2. IS_DIRECTORY EXISTS COMMAND DEFINED etc predicates
+// 3. MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL etc binary ops
+// 4. NOT
+// 5. AND OR
+//
+// There is an issue on whether the arguments should be values of references,
+// for example IF (FOO AND BAR) should that compare the strings FOO and BAR
+// or should it really do IF (${FOO} AND ${BAR}) Currently IS_DIRECTORY
+// EXISTS COMMAND and DEFINED all take values. EQUAL, LESS and GREATER can
+// take numeric values or variable names. STRLESS and STRGREATER take
+// variable names but if the variable name is not found it will use the name
+// directly. AND OR take variables or the values 0 or 1.
+
+bool cmConditionEvaluator::IsTrue(
+ const std::vector<cmExpandedCommandArgument>& args, std::string& errorString,
+ cmake::MessageType& status)
+{
+ errorString = "";
+
+ // handle empty invocation
+ if (args.empty()) {
+ return false;
+ }
+
+ // store the reduced args in this vector
+ cmArgumentList newArgs;
+
+ // copy to the list structure
+ newArgs.insert(newArgs.end(), 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
+ // parens
+ if (!this->HandleLevel0(newArgs, errorString, status)) {
+ return false;
+ }
+ // predicates
+ if (!this->HandleLevel1(newArgs, errorString, status)) {
+ return false;
+ }
+ // binary ops
+ if (!this->HandleLevel2(newArgs, errorString, status)) {
+ return false;
+ }
+
+ // NOT
+ if (!this->HandleLevel3(newArgs, errorString, status)) {
+ return false;
+ }
+ // AND OR
+ if (!this->HandleLevel4(newArgs, errorString, status)) {
+ return false;
+ }
+
+ // now at the end there should only be one argument left
+ if (newArgs.size() != 1) {
+ errorString = "Unknown arguments specified";
+ status = cmake::FATAL_ERROR;
+ return false;
+ }
+
+ return this->GetBooleanValueWithAutoDereference(*(newArgs.begin()),
+ errorString, status, true);
+}
+
+//=========================================================================
+const char* cmConditionEvaluator::GetDefinitionIfUnquoted(
+ cmExpandedCommandArgument const& argument) const
+{
+ if ((this->Policy54Status != cmPolicies::WARN &&
+ this->Policy54Status != cmPolicies::OLD) &&
+ argument.WasQuoted()) {
+ return CM_NULLPTR;
+ }
+
+ const char* def = this->Makefile.GetDefinition(argument.GetValue());
+
+ if (def && argument.WasQuoted() &&
+ this->Policy54Status == cmPolicies::WARN) {
+ if (!this->Makefile.HasCMP0054AlreadyBeenReported(
+ this->ExecutionContext)) {
+ std::ostringstream e;
+ e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) << "\n";
+ e << "Quoted variables like \"" << argument.GetValue()
+ << "\" will no longer be dereferenced "
+ "when the policy is set to NEW. "
+ "Since the policy is not set the OLD behavior will be used.";
+
+ this->Makefile.GetCMakeInstance()->IssueMessage(
+ cmake::AUTHOR_WARNING, e.str(), this->Backtrace);
+ }
+ }
+
+ return def;
+}
+
+//=========================================================================
+const char* cmConditionEvaluator::GetVariableOrString(
+ const cmExpandedCommandArgument& argument) const
+{
+ const char* def = this->GetDefinitionIfUnquoted(argument);
+
+ if (!def) {
+ def = argument.c_str();
+ }
+
+ return def;
+}
+
+//=========================================================================
+bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
+ cmExpandedCommandArgument& argument) const
+{
+ if ((this->Policy54Status != cmPolicies::WARN &&
+ this->Policy54Status != cmPolicies::OLD) &&
+ argument.WasQuoted()) {
+ return false;
+ }
+
+ bool isKeyword = argument.GetValue() == keyword;
+
+ if (isKeyword && argument.WasQuoted() &&
+ this->Policy54Status == cmPolicies::WARN) {
+ if (!this->Makefile.HasCMP0054AlreadyBeenReported(
+ this->ExecutionContext)) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) << "\n";
+ e << "Quoted keywords like \"" << argument.GetValue()
+ << "\" will no longer be interpreted as keywords "
+ "when the policy is set to NEW. "
+ "Since the policy is not set the OLD behavior will be used.";
+
+ this->Makefile.GetCMakeInstance()->IssueMessage(
+ cmake::AUTHOR_WARNING, e.str(), this->Backtrace);
+ }
+ }
+
+ return isKeyword;
+}
+
+//=========================================================================
+bool cmConditionEvaluator::GetBooleanValue(
+ cmExpandedCommandArgument& arg) const
+{
+ // Check basic constants.
+ if (arg == "0") {
+ return false;
+ }
+ if (arg == "1") {
+ return true;
+ }
+
+ // Check named constants.
+ if (cmSystemTools::IsOn(arg.c_str())) {
+ return true;
+ }
+ if (cmSystemTools::IsOff(arg.c_str())) {
+ return false;
+ }
+
+ // Check for numbers.
+ if (!arg.empty()) {
+ char* end;
+ double d = strtod(arg.c_str(), &end);
+ if (*end == '\0') {
+ // The whole string is a number. Use C conversion to bool.
+ return static_cast<bool>(d);
+ }
+ }
+
+ // Check definition.
+ const char* def = this->GetDefinitionIfUnquoted(arg);
+ return !cmSystemTools::IsOff(def);
+}
+
+//=========================================================================
+// Boolean value behavior from CMake 2.6.4 and below.
+bool cmConditionEvaluator::GetBooleanValueOld(
+ cmExpandedCommandArgument const& arg, bool one) const
+{
+ if (one) {
+ // Old IsTrue behavior for single argument.
+ if (arg == "0") {
+ return false;
+ }
+ if (arg == "1") {
+ return true;
+ }
+ const char* def = this->GetDefinitionIfUnquoted(arg);
+ return !cmSystemTools::IsOff(def);
+ }
+ // Old GetVariableOrNumber behavior.
+ const char* def = this->GetDefinitionIfUnquoted(arg);
+ if (!def && atoi(arg.c_str())) {
+ def = arg.c_str();
+ }
+ return !cmSystemTools::IsOff(def);
+}
+
+//=========================================================================
+// returns the resulting boolean value
+bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
+ cmExpandedCommandArgument& newArg, std::string& errorString,
+ cmake::MessageType& status, bool oneArg) const
+{
+ // Use the policy if it is set.
+ if (this->Policy12Status == cmPolicies::NEW) {
+ return GetBooleanValue(newArg);
+ }
+ if (this->Policy12Status == cmPolicies::OLD) {
+ return GetBooleanValueOld(newArg, oneArg);
+ }
+
+ // Check policy only if old and new results differ.
+ bool newResult = this->GetBooleanValue(newArg);
+ bool oldResult = this->GetBooleanValueOld(newArg, oneArg);
+ if (newResult != oldResult) {
+ switch (this->Policy12Status) {
+ case cmPolicies::WARN:
+ errorString = "An argument named \"" + newArg.GetValue() +
+ "\" appears in a conditional statement. " +
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0012);
+ status = cmake::AUTHOR_WARNING;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ return oldResult;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS: {
+ errorString = "An argument named \"" + newArg.GetValue() +
+ "\" appears in a conditional statement. " +
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012);
+ status = cmake::FATAL_ERROR;
+ }
+ case cmPolicies::NEW:
+ break;
+ }
+ }
+ return newResult;
+}
+
+//=========================================================================
+void cmConditionEvaluator::IncrementArguments(
+ cmArgumentList& newArgs, cmArgumentList::iterator& argP1,
+ cmArgumentList::iterator& argP2) const
+{
+ if (argP1 != newArgs.end()) {
+ argP1++;
+ argP2 = argP1;
+ if (argP1 != newArgs.end()) {
+ argP2++;
+ }
+ }
+}
+
+//=========================================================================
+// helper function to reduce code duplication
+void cmConditionEvaluator::HandlePredicate(
+ bool value, int& reducible, cmArgumentList::iterator& arg,
+ cmArgumentList& newArgs, cmArgumentList::iterator& argP1,
+ cmArgumentList::iterator& argP2) const
+{
+ if (value) {
+ *arg = cmExpandedCommandArgument("1", true);
+ } else {
+ *arg = cmExpandedCommandArgument("0", true);
+ }
+ newArgs.erase(argP1);
+ argP1 = arg;
+ this->IncrementArguments(newArgs, argP1, argP2);
+ reducible = 1;
+}
+
+//=========================================================================
+// helper function to reduce code duplication
+void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible,
+ cmArgumentList::iterator& arg,
+ cmArgumentList& newArgs,
+ cmArgumentList::iterator& argP1,
+ cmArgumentList::iterator& argP2)
+{
+ if (value) {
+ *arg = cmExpandedCommandArgument("1", true);
+ } else {
+ *arg = cmExpandedCommandArgument("0", true);
+ }
+ newArgs.erase(argP2);
+ newArgs.erase(argP1);
+ argP1 = arg;
+ this->IncrementArguments(newArgs, argP1, argP2);
+ reducible = 1;
+}
+
+//=========================================================================
+// level 0 processes parenthetical expressions
+bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
+ std::string& errorString,
+ cmake::MessageType& status)
+{
+ int reducible;
+ do {
+ reducible = 0;
+ cmArgumentList::iterator arg = newArgs.begin();
+ while (arg != newArgs.end()) {
+ if (IsKeyword(keyParenL, *arg)) {
+ // search for the closing paren for this opening one
+ cmArgumentList::iterator argClose;
+ argClose = arg;
+ argClose++;
+ unsigned int depth = 1;
+ while (argClose != newArgs.end() && depth) {
+ if (this->IsKeyword(keyParenL, *argClose)) {
+ depth++;
+ }
+ if (this->IsKeyword(keyParenR, *argClose)) {
+ depth--;
+ }
+ argClose++;
+ }
+ if (depth) {
+ errorString = "mismatched parenthesis in condition";
+ status = cmake::FATAL_ERROR;
+ return false;
+ }
+ // store the reduced args in this vector
+ std::vector<cmExpandedCommandArgument> newArgs2;
+
+ // copy to the list structure
+ cmArgumentList::iterator argP1 = arg;
+ argP1++;
+ newArgs2.insert(newArgs2.end(), argP1, argClose);
+ newArgs2.pop_back();
+ // now recursively invoke IsTrue to handle the values inside the
+ // parenthetical expression
+ bool value = this->IsTrue(newArgs2, errorString, status);
+ if (value) {
+ *arg = cmExpandedCommandArgument("1", true);
+ } else {
+ *arg = cmExpandedCommandArgument("0", true);
+ }
+ argP1 = arg;
+ argP1++;
+ // remove the now evaluated parenthetical expression
+ newArgs.erase(argP1, argClose);
+ }
+ ++arg;
+ }
+ } while (reducible);
+ return true;
+}
+
+//=========================================================================
+// level one handles most predicates except for NOT
+bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
+ cmake::MessageType&)
+{
+ int reducible;
+ do {
+ reducible = 0;
+ cmArgumentList::iterator arg = newArgs.begin();
+ cmArgumentList::iterator argP1;
+ cmArgumentList::iterator argP2;
+ while (arg != newArgs.end()) {
+ argP1 = arg;
+ this->IncrementArguments(newArgs, argP1, argP2);
+ // does a file exist
+ if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) {
+ this->HandlePredicate(cmSystemTools::FileExists(argP1->c_str()),
+ reducible, arg, newArgs, argP1, argP2);
+ }
+ // does a directory with this name exist
+ if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) {
+ this->HandlePredicate(cmSystemTools::FileIsDirectory(argP1->c_str()),
+ reducible, arg, newArgs, argP1, argP2);
+ }
+ // does a symlink with this name exist
+ if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) {
+ this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->c_str()),
+ reducible, arg, newArgs, argP1, argP2);
+ }
+ // is the given path an absolute path ?
+ if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) {
+ this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->c_str()),
+ reducible, arg, newArgs, argP1, argP2);
+ }
+ // does a command exist
+ if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
+ cmCommand* command =
+ this->Makefile.GetState()->GetCommand(argP1->c_str());
+ this->HandlePredicate(command != CM_NULLPTR, reducible, arg, newArgs,
+ argP1, argP2);
+ }
+ // does a policy exist
+ if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) {
+ cmPolicies::PolicyID pid;
+ this->HandlePredicate(cmPolicies::GetPolicyID(argP1->c_str(), pid),
+ reducible, arg, newArgs, argP1, argP2);
+ }
+ // does a target exist
+ if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) {
+ this->HandlePredicate(
+ this->Makefile.FindTargetToUse(argP1->GetValue()) != CM_NULLPTR,
+ reducible, arg, newArgs, argP1, argP2);
+ }
+ // does a test exist
+ if (this->Policy64Status != cmPolicies::OLD &&
+ 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);
+ }
+ } else if (this->Policy64Status == cmPolicies::WARN &&
+ this->IsKeyword(keyTEST, *arg)) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n";
+ e << "TEST will be interpreted as an operator "
+ "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());
+ }
+ // is a variable defined
+ if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) {
+ size_t argP1len = argP1->GetValue().size();
+ bool bdef = false;
+ 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());
+ } else {
+ bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
+ }
+ this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
+ }
+ ++arg;
+ }
+ } while (reducible);
+ return true;
+}
+
+//=========================================================================
+// level two handles most binary operations except for AND OR
+bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
+ std::string& errorString,
+ cmake::MessageType& status)
+{
+ int reducible;
+ std::string def_buf;
+ const char* def;
+ const char* def2;
+ do {
+ reducible = 0;
+ cmArgumentList::iterator arg = newArgs.begin();
+ cmArgumentList::iterator argP1;
+ cmArgumentList::iterator argP2;
+ while (arg != newArgs.end()) {
+ argP1 = arg;
+ this->IncrementArguments(newArgs, argP1, argP2);
+ if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
+ IsKeyword(keyMATCHES, *argP1)) {
+ def = this->GetVariableOrString(*arg);
+ if (def != arg->c_str() // yes, we compare the pointer value
+ && cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) {
+ // The string to match is owned by our match result variables.
+ // Move it to our own buffer before clearing them.
+ def_buf = def;
+ def = def_buf.c_str();
+ }
+ const char* rex = argP2->c_str();
+ this->Makefile.ClearMatches();
+ cmsys::RegularExpression regEntry;
+ if (!regEntry.compile(rex)) {
+ std::ostringstream error;
+ error << "Regular expression \"" << rex << "\" cannot compile";
+ errorString = error.str();
+ status = cmake::FATAL_ERROR;
+ return false;
+ }
+ if (regEntry.find(def)) {
+ this->Makefile.StoreMatches(regEntry);
+ *arg = cmExpandedCommandArgument("1", true);
+ } else {
+ *arg = cmExpandedCommandArgument("0", true);
+ }
+ newArgs.erase(argP2);
+ newArgs.erase(argP1);
+ argP1 = arg;
+ this->IncrementArguments(newArgs, argP1, argP2);
+ reducible = 1;
+ }
+
+ if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) {
+ *arg = cmExpandedCommandArgument("0", true);
+ newArgs.erase(argP1);
+ argP1 = arg;
+ this->IncrementArguments(newArgs, argP1, argP2);
+ reducible = 1;
+ }
+
+ if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
+ (this->IsKeyword(keyLESS, *argP1) ||
+ this->IsKeyword(keyLESS_EQUAL, *argP1) ||
+ this->IsKeyword(keyGREATER, *argP1) ||
+ this->IsKeyword(keyGREATER_EQUAL, *argP1) ||
+ this->IsKeyword(keyEQUAL, *argP1))) {
+ def = this->GetVariableOrString(*arg);
+ def2 = this->GetVariableOrString(*argP2);
+ double lhs;
+ double rhs;
+ bool result;
+ if (sscanf(def, "%lg", &lhs) != 1 || sscanf(def2, "%lg", &rhs) != 1) {
+ result = false;
+ } else if (*(argP1) == keyLESS) {
+ result = (lhs < rhs);
+ } else if (*(argP1) == keyLESS_EQUAL) {
+ result = (lhs <= rhs);
+ } else if (*(argP1) == keyGREATER) {
+ result = (lhs > rhs);
+ } else if (*(argP1) == keyGREATER_EQUAL) {
+ result = (lhs >= rhs);
+ } else {
+ result = (lhs == rhs);
+ }
+ this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ }
+
+ if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
+ (this->IsKeyword(keySTRLESS, *argP1) ||
+ this->IsKeyword(keySTRLESS_EQUAL, *argP1) ||
+ this->IsKeyword(keySTRGREATER, *argP1) ||
+ this->IsKeyword(keySTRGREATER_EQUAL, *argP1) ||
+ this->IsKeyword(keySTREQUAL, *argP1))) {
+ def = this->GetVariableOrString(*arg);
+ def2 = this->GetVariableOrString(*argP2);
+ int val = strcmp(def, def2);
+ bool result;
+ if (*(argP1) == keySTRLESS) {
+ result = (val < 0);
+ } else if (*(argP1) == keySTRLESS_EQUAL) {
+ result = (val <= 0);
+ } else if (*(argP1) == keySTRGREATER) {
+ result = (val > 0);
+ } else if (*(argP1) == keySTRGREATER_EQUAL) {
+ result = (val >= 0);
+ } else // strequal
+ {
+ result = (val == 0);
+ }
+ this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ }
+
+ if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
+ (this->IsKeyword(keyVERSION_LESS, *argP1) ||
+ this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) ||
+ this->IsKeyword(keyVERSION_GREATER, *argP1) ||
+ this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) ||
+ this->IsKeyword(keyVERSION_EQUAL, *argP1))) {
+ def = this->GetVariableOrString(*arg);
+ def2 = this->GetVariableOrString(*argP2);
+ cmSystemTools::CompareOp op;
+ if (*argP1 == keyVERSION_LESS) {
+ op = cmSystemTools::OP_LESS;
+ } else if (*argP1 == keyVERSION_LESS_EQUAL) {
+ op = cmSystemTools::OP_LESS_EQUAL;
+ } else if (*argP1 == keyVERSION_GREATER) {
+ op = cmSystemTools::OP_GREATER;
+ } else if (*argP1 == keyVERSION_GREATER_EQUAL) {
+ op = cmSystemTools::OP_GREATER_EQUAL;
+ } else { // version_equal
+ op = cmSystemTools::OP_EQUAL;
+ }
+ bool result = cmSystemTools::VersionCompare(op, def, def2);
+ this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ }
+
+ // is file A newer than file B
+ if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
+ this->IsKeyword(keyIS_NEWER_THAN, *argP1)) {
+ int fileIsNewer = 0;
+ bool success = cmSystemTools::FileTimeCompare(
+ arg->GetValue(), (argP2)->GetValue(), &fileIsNewer);
+ this->HandleBinaryOp(
+ (!success || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg,
+ newArgs, argP1, argP2);
+ }
+
+ if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
+ this->IsKeyword(keyIN_LIST, *argP1)) {
+ if (this->Policy57Status != cmPolicies::OLD &&
+ this->Policy57Status != cmPolicies::WARN) {
+ bool result = false;
+
+ def = this->GetVariableOrString(*arg);
+ def2 = this->Makefile.GetDefinition(argP2->GetValue());
+
+ if (def2) {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(def2, list, true);
+
+ result = std::find(list.begin(), list.end(), def) != list.end();
+ }
+
+ this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ } else if (this->Policy57Status == cmPolicies::WARN) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n";
+ e << "IN_LIST will be interpreted as an operator "
+ "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());
+ }
+ }
+
+ ++arg;
+ }
+ } while (reducible);
+ return true;
+}
+
+//=========================================================================
+// level 3 handles NOT
+bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
+ std::string& errorString,
+ cmake::MessageType& status)
+{
+ int reducible;
+ do {
+ reducible = 0;
+ cmArgumentList::iterator arg = newArgs.begin();
+ cmArgumentList::iterator argP1;
+ cmArgumentList::iterator argP2;
+ while (arg != newArgs.end()) {
+ argP1 = arg;
+ IncrementArguments(newArgs, argP1, argP2);
+ if (argP1 != newArgs.end() && IsKeyword(keyNOT, *arg)) {
+ bool rhs = this->GetBooleanValueWithAutoDereference(
+ *argP1, errorString, status);
+ this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
+ }
+ ++arg;
+ }
+ } while (reducible);
+ return true;
+}
+
+//=========================================================================
+// level 4 handles AND OR
+bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs,
+ std::string& errorString,
+ cmake::MessageType& status)
+{
+ int reducible;
+ bool lhs;
+ bool rhs;
+ do {
+ reducible = 0;
+ cmArgumentList::iterator arg = newArgs.begin();
+ cmArgumentList::iterator argP1;
+ cmArgumentList::iterator argP2;
+ while (arg != newArgs.end()) {
+ argP1 = arg;
+ IncrementArguments(newArgs, argP1, argP2);
+ if (argP1 != newArgs.end() && IsKeyword(keyAND, *argP1) &&
+ argP2 != newArgs.end()) {
+ lhs =
+ this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
+ rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString,
+ status);
+ this->HandleBinaryOp((lhs && rhs), reducible, arg, newArgs, argP1,
+ argP2);
+ }
+
+ if (argP1 != newArgs.end() && this->IsKeyword(keyOR, *argP1) &&
+ argP2 != newArgs.end()) {
+ lhs =
+ this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
+ rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString,
+ status);
+ this->HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1,
+ argP2);
+ }
+ ++arg;
+ }
+ } while (reducible);
+ return true;
+}
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
new file mode 100644
index 000000000..50f4edc4f
--- /dev/null
+++ b/Source/cmConditionEvaluator.h
@@ -0,0 +1,92 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmConditionEvaluator_h
+#define cmConditionEvaluator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "cmExpandedCommandArgument.h"
+#include "cmListFileCache.h"
+#include "cmPolicies.h"
+#include "cmake.h"
+
+class cmMakefile;
+
+class cmConditionEvaluator
+{
+public:
+ typedef std::list<cmExpandedCommandArgument> cmArgumentList;
+
+ cmConditionEvaluator(cmMakefile& makefile, cmListFileContext const& context,
+ cmListFileBacktrace const& 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);
+
+private:
+ // Filter the given variable definition based on policy CMP0054.
+ const char* GetDefinitionIfUnquoted(
+ const cmExpandedCommandArgument& argument) const;
+
+ const char* GetVariableOrString(
+ const cmExpandedCommandArgument& argument) const;
+
+ bool IsKeyword(std::string const& keyword,
+ cmExpandedCommandArgument& argument) const;
+
+ bool GetBooleanValue(cmExpandedCommandArgument& arg) const;
+
+ bool GetBooleanValueOld(cmExpandedCommandArgument const& arg,
+ bool one) const;
+
+ bool GetBooleanValueWithAutoDereference(cmExpandedCommandArgument& newArg,
+ std::string& errorString,
+ cmake::MessageType& status,
+ bool oneArg = false) const;
+
+ void IncrementArguments(cmArgumentList& newArgs,
+ cmArgumentList::iterator& argP1,
+ cmArgumentList::iterator& argP2) const;
+
+ void HandlePredicate(bool value, int& reducible,
+ cmArgumentList::iterator& arg, cmArgumentList& newArgs,
+ cmArgumentList::iterator& argP1,
+ cmArgumentList::iterator& argP2) const;
+
+ void HandleBinaryOp(bool value, int& reducible,
+ cmArgumentList::iterator& arg, cmArgumentList& newArgs,
+ cmArgumentList::iterator& argP1,
+ cmArgumentList::iterator& argP2);
+
+ bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString,
+ cmake::MessageType& status);
+
+ bool HandleLevel1(cmArgumentList& newArgs, std::string&,
+ cmake::MessageType&);
+
+ bool HandleLevel2(cmArgumentList& newArgs, std::string& errorString,
+ cmake::MessageType& status);
+
+ bool HandleLevel3(cmArgumentList& newArgs, std::string& errorString,
+ cmake::MessageType& status);
+
+ bool HandleLevel4(cmArgumentList& newArgs, std::string& errorString,
+ cmake::MessageType& status);
+
+ cmMakefile& Makefile;
+ cmListFileContext ExecutionContext;
+ cmListFileBacktrace Backtrace;
+ cmPolicies::PolicyStatus Policy12Status;
+ cmPolicies::PolicyStatus Policy54Status;
+ cmPolicies::PolicyStatus Policy57Status;
+ cmPolicies::PolicyStatus Policy64Status;
+};
+
+#endif
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index ab53b1d27..524fdf808 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -1,22 +1,69 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#cmakedefine CMAKE_NO_STD_NAMESPACE
-#cmakedefine CMAKE_NO_ANSI_STREAM_HEADERS
-#cmakedefine CMAKE_NO_ANSI_STRING_STREAM
-#cmakedefine CMAKE_NO_ANSI_FOR_SCOPE
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmConfigure_h
+#define cmConfigure_h
+
+#include "cmsys/Configure.hxx" // IWYU pragma: export
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4786)
+#pragma warning(disable : 4503)
+#endif
+
+#ifdef __ICL
+#pragma warning(disable : 985)
+#pragma warning(disable : 1572) /* floating-point equality test */
+#endif
+
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
#cmakedefine CMAKE_USE_ELF_PARSER
-#cmakedefine CMAKE_STRICT
-#define CMAKE_ROOT_DIR "${CMake_SOURCE_DIR}"
-#define CMAKE_BUILD_DIR "${CMake_BINARY_DIR}"
+#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_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
+
+#ifdef CMake_HAVE_CXX_NULLPTR
+#define CM_NULLPTR nullptr
+#else
+#define CM_NULLPTR 0
+#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 e52ddef35..18005f27c 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -1,141 +1,114 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmConfigureFileCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmConfigureFileCommand.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include <cmsys/RegularExpression.hxx>
+class cmExecutionStatus;
// cmConfigureFileCommand
-bool cmConfigureFileCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments, expected 2");
return false;
- }
+ }
- const char* inFile = args[0].c_str();
- if(!cmSystemTools::FileIsFullPath(inFile))
- {
- this->InputFile = this->Makefile->GetCurrentDirectory();
+ std::string const& inFile = args[0];
+ if (!cmSystemTools::FileIsFullPath(inFile)) {
+ this->InputFile = this->Makefile->GetCurrentSourceDirectory();
this->InputFile += "/";
- }
+ }
this->InputFile += inFile;
// If the input location is a directory, error out.
- if(cmSystemTools::FileIsDirectory(this->InputFile.c_str()))
- {
- cmOStringStream e;
+ 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.";
- this->SetError(e.str().c_str());
+ /* clang-format on */
+ this->SetError(e.str());
return false;
- }
+ }
- const char* outFile = args[1].c_str();
- if(!cmSystemTools::FileIsFullPath(outFile))
- {
- this->OutputFile = this->Makefile->GetCurrentOutputDirectory();
+ std::string const& outFile = args[1];
+ if (!cmSystemTools::FileIsFullPath(outFile)) {
+ this->OutputFile = this->Makefile->GetCurrentBinaryDirectory();
this->OutputFile += "/";
- }
+ }
this->OutputFile += outFile;
// If the output location is already a directory put the file in it.
- if(cmSystemTools::FileIsDirectory(this->OutputFile.c_str()))
- {
+ if (cmSystemTools::FileIsDirectory(this->OutputFile)) {
this->OutputFile += "/";
this->OutputFile += cmSystemTools::GetFilenameName(inFile);
- }
+ }
- if ( !this->Makefile->CanIWriteThisFile(this->OutputFile.c_str()) )
- {
- std::string e = "attempted to configure a file: " + this->OutputFile
- + " into a source directory.";
- this->SetError(e.c_str());
+ if (!this->Makefile->CanIWriteThisFile(this->OutputFile.c_str())) {
+ std::string e = "attempted to configure a file: " + this->OutputFile +
+ " into a source directory.";
+ this->SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
+ }
std::string errorMessage;
- if (!this->NewLineStyle.ReadFromArguments(args, errorMessage))
- {
- this->SetError(errorMessage.c_str());
+ if (!this->NewLineStyle.ReadFromArguments(args, errorMessage)) {
+ this->SetError(errorMessage);
return false;
- }
+ }
this->CopyOnly = false;
this->EscapeQuotes = false;
- // for CMake 2.0 and earlier CONFIGURE_FILE defaults to the FinalPass,
- // after 2.0 it only does InitialPass
- this->Immediate = !this->Makefile->NeedBackwardsCompatibility(2,0);
-
+ std::string unknown_args;
this->AtOnly = false;
- for(unsigned int i=2;i < args.size();++i)
- {
- if(args[i] == "COPYONLY")
- {
+ for (unsigned int i = 2; i < args.size(); ++i) {
+ if (args[i] == "COPYONLY") {
this->CopyOnly = true;
- if (this->NewLineStyle.IsValid())
- {
+ if (this->NewLineStyle.IsValid()) {
this->SetError("COPYONLY could not be used in combination "
"with NEWLINE_STYLE");
return false;
- }
}
- else if(args[i] == "ESCAPE_QUOTES")
- {
+ } else if (args[i] == "ESCAPE_QUOTES") {
this->EscapeQuotes = true;
- }
- else if(args[i] == "@ONLY")
- {
+ } else if (args[i] == "@ONLY") {
this->AtOnly = true;
- }
- else if(args[i] == "IMMEDIATE")
- {
- this->Immediate = true;
- }
- }
-
- // If we were told to copy the file immediately, then do it on the
- // first pass (now).
- if(this->Immediate)
- {
- if ( !this->ConfigureFile() )
- {
- this->SetError("Problem configuring file");
- return false;
- }
+ } else if (args[i] == "IMMEDIATE") {
+ /* Ignore legacy option. */
+ } else if (args[i] == "NEWLINE_STYLE" || args[i] == "LF" ||
+ args[i] == "UNIX" || args[i] == "CRLF" || args[i] == "WIN32" ||
+ args[i] == "DOS") {
+ /* Options handled by NewLineStyle member above. */
+ } else {
+ unknown_args += " ";
+ unknown_args += args[i];
+ unknown_args += "\n";
}
+ }
+ 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);
+ }
+
+ if (!this->ConfigureFile()) {
+ this->SetError("Problem configuring file");
+ return false;
+ }
return true;
}
-void cmConfigureFileCommand::FinalPass()
-{
- if(!this->Immediate)
- {
- this->ConfigureFile();
- }
-}
-
int cmConfigureFileCommand::ConfigureFile()
{
return this->Makefile->ConfigureFile(
- this->InputFile.c_str(),
- this->OutputFile.c_str(),
- this->CopyOnly,
- this->AtOnly,
- this->EscapeQuotes,
- this->NewLineStyle);
+ 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 0393ecfa9..6cebbd258 100644
--- a/Source/cmConfigureFileCommand.h
+++ b/Source/cmConfigureFileCommand.h
@@ -1,103 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmConfigureFileCommand_h
#define cmConfigureFileCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+#include "cmNewLineStyle.h"
+
+class cmExecutionStatus;
class cmConfigureFileCommand : public cmCommand
{
public:
- cmTypeMacro(cmConfigureFileCommand, cmCommand);
-
- virtual cmCommand* Clone()
- {
- return new cmConfigureFileCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmConfigureFileCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "configure_file";}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Copy a file to another location and modify its contents.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " configure_file(<input> <output>\n"
- " [COPYONLY] [ESCAPE_QUOTES] [@ONLY] \n"
- " [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])\n"
- "Copies a file <input> to file <output> and substitutes variable "
- "values referenced in the file content. "
- "If <input> is a relative path it is evaluated with respect to "
- "the current source directory. "
- "The <input> must be a file, not a directory. "
- "If <output> is a relative path it is evaluated with respect to "
- "the current binary directory. "
- "If <output> names an existing directory the input file is placed "
- "in that directory with its original name. "
- "\n"
- "If the <input> file is modified the build system will re-run CMake "
- "to re-configure the file and generate the build system again."
- "\n"
- "This command replaces any variables in the input file referenced as "
- "${VAR} or @VAR@ with their values as determined by CMake. If a "
- "variable is not defined, it will be replaced with nothing. "
- "If COPYONLY is specified, then no variable expansion will take "
- "place. If ESCAPE_QUOTES is specified then any substituted quotes "
- "will be C-style escaped. "
- "The file will be configured with the current values of CMake "
- "variables. If @ONLY is specified, only variables "
- "of the form @VAR@ will be replaced and ${VAR} will be ignored. "
- "This is useful for configuring scripts that use ${VAR}."
- "\n"
- "Input file lines of the form \"#cmakedefine VAR ...\" "
- "will be replaced with either \"#define VAR ...\" or "
- "\"/* #undef VAR */\" depending on whether VAR is set in CMake to "
- "any value not considered a false constant by the if() command. "
- "(Content of \"...\", if any, is processed as above.) "
- "Input file lines of the form \"#cmakedefine01 VAR\" "
- "will be replaced with either \"#define VAR 1\" or "
- "\"#define VAR 0\" similarly."
- "\n"
- "With NEWLINE_STYLE the line ending could be adjusted: \n"
- " 'UNIX' or 'LF' for \\n, 'DOS', 'WIN32' or 'CRLF' for \\r\\n.\n"
- "COPYONLY must not be used with NEWLINE_STYLE.\n";
- }
-
- virtual void FinalPass();
- virtual bool HasFinalPass() const { return !this->Immediate; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
int ConfigureFile();
@@ -108,10 +34,7 @@ private:
std::string OutputFile;
bool CopyOnly;
bool EscapeQuotes;
- bool Immediate;
bool AtOnly;
};
-
-
#endif
diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx
new file mode 100644
index 000000000..2298a05c5
--- /dev/null
+++ b/Source/cmContinueCommand.cxx
@@ -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. */
+#include "cmContinueCommand.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+// cmContinueCommand
+bool cmContinueCommand::InitialPass(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.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
+ status.SetContinueInvoked();
+
+ if (!args.empty()) {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "The CONTINUE command does not accept any "
+ "arguments.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
+ return true;
+}
diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h
new file mode 100644
index 000000000..92bc68e85
--- /dev/null
+++ b/Source/cmContinueCommand.h
@@ -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. */
+#ifndef cmContinueCommand_h
+#define cmContinueCommand_h
+
+#include "cmConfigure.h"
+
+#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;
+};
+
+#endif
diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py
new file mode 100644
index 000000000..93ab8a82f
--- /dev/null
+++ b/Source/cmConvertMSBuildXMLToJSON.py
@@ -0,0 +1,453 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+import argparse
+import codecs
+import copy
+import logging
+import json
+import os
+
+from collections import OrderedDict
+from xml.dom.minidom import parse, parseString, Element
+
+
+class VSFlags:
+ """Flags corresponding to cmIDEFlagTable."""
+ UserValue = "UserValue" # (1 << 0)
+ UserIgnored = "UserIgnored" # (1 << 1)
+ UserRequired = "UserRequired" # (1 << 2)
+ Continue = "Continue" #(1 << 3)
+ SemicolonAppendable = "SemicolonAppendable" # (1 << 4)
+ UserFollowing = "UserFollowing" # (1 << 5)
+ CaseInsensitive = "CaseInsensitive" # (1 << 6)
+ UserValueIgnored = [UserValue, UserIgnored]
+ UserValueRequired = [UserValue, UserRequired]
+
+
+def vsflags(*args):
+ """Combines the flags."""
+ values = []
+
+ for arg in args:
+ __append_list(values, arg)
+
+ return values
+
+
+def read_msbuild_xml(path, values={}):
+ """Reads the MS Build XML file at the path and returns its contents.
+
+ Keyword arguments:
+ values -- The map to append the contents to (default {})
+ """
+
+ # Attempt to read the file contents
+ try:
+ document = parse(path)
+ except Exception as e:
+ logging.exception('Could not read MS Build XML file at %s', path)
+ return values
+
+ # Convert the XML to JSON format
+ logging.info('Processing MS Build XML file at %s', path)
+
+ # Get the rule node
+ rule = document.getElementsByTagName('Rule')[0]
+
+ rule_name = rule.attributes['Name'].value
+
+ logging.info('Found rules for %s', rule_name)
+
+ # Proprocess Argument values
+ __preprocess_arguments(rule)
+
+ # Get all the values
+ converted_values = []
+ __convert(rule, 'EnumProperty', converted_values, __convert_enum)
+ __convert(rule, 'BoolProperty', converted_values, __convert_bool)
+ __convert(rule, 'StringListProperty', converted_values,
+ __convert_string_list)
+ __convert(rule, 'StringProperty', converted_values, __convert_string)
+ __convert(rule, 'IntProperty', converted_values, __convert_string)
+
+ values[rule_name] = converted_values
+
+ return values
+
+
+def read_msbuild_json(path, values=[]):
+ """Reads the MS Build JSON file at the path and returns its contents.
+
+ Keyword arguments:
+ values -- The list to append the contents to (default [])
+ """
+ if not os.path.exists(path):
+ logging.info('Could not find MS Build JSON file at %s', path)
+ return values
+
+ try:
+ values.extend(__read_json_file(path))
+ except Exception as e:
+ logging.exception('Could not read MS Build JSON file at %s', path)
+ return values
+
+ logging.info('Processing MS Build JSON file at %s', path)
+
+ return values
+
+
+def main():
+ """Script entrypoint."""
+ # Parse the arguments
+ parser = argparse.ArgumentParser(
+ description='Convert MSBuild XML to JSON format')
+
+ parser.add_argument(
+ '-t', '--toolchain', help='The name of the toolchain', required=True)
+ parser.add_argument(
+ '-o', '--output', help='The output directory', default='')
+ parser.add_argument(
+ '-r',
+ '--overwrite',
+ help='Whether previously output should be overwritten',
+ dest='overwrite',
+ action='store_true')
+ parser.set_defaults(overwrite=False)
+ parser.add_argument(
+ '-d',
+ '--debug',
+ help="Debug tool output",
+ action="store_const",
+ dest="loglevel",
+ const=logging.DEBUG,
+ default=logging.WARNING)
+ parser.add_argument(
+ '-v',
+ '--verbose',
+ help="Verbose output",
+ action="store_const",
+ dest="loglevel",
+ const=logging.INFO)
+ parser.add_argument('input', help='The input files', nargs='+')
+
+ args = parser.parse_args()
+
+ toolchain = args.toolchain
+
+ logging.basicConfig(level=args.loglevel)
+ logging.info('Creating %s toolchain files', toolchain)
+
+ values = {}
+
+ # Iterate through the inputs
+ for input in args.input:
+ input = __get_path(input)
+
+ read_msbuild_xml(input, values)
+
+ # Determine if the output directory needs to be created
+ output_dir = __get_path(args.output)
+
+ if not os.path.exists(output_dir):
+ os.mkdir(output_dir)
+ logging.info('Created output directory %s', output_dir)
+
+ for key, value in values.items():
+ output_path = __output_path(toolchain, key, output_dir)
+
+ if os.path.exists(output_path) and not args.overwrite:
+ logging.info('Comparing previous output to current')
+
+ __merge_json_values(value, read_msbuild_json(output_path))
+ else:
+ logging.info('Original output will be overwritten')
+
+ logging.info('Writing MS Build JSON file at %s', output_path)
+
+ __write_json_file(output_path, value)
+
+
+###########################################################################################
+# private joining functions
+def __merge_json_values(current, previous):
+ """Merges the values between the current and previous run of the script."""
+ for value in current:
+ name = value['name']
+
+ # Find the previous value
+ previous_value = __find_and_remove_value(previous, value)
+
+ if previous_value is not None:
+ flags = value['flags']
+ previous_flags = previous_value['flags']
+
+ if flags != previous_flags:
+ logging.warning(
+ 'Flags for %s are different. Using previous value.', name)
+
+ value['flags'] = previous_flags
+ else:
+ logging.warning('Value %s is a new value', name)
+
+ for value in previous:
+ name = value['name']
+ logging.warning(
+ 'Value %s not present in current run. Appending value.', name)
+
+ current.append(value)
+
+
+def __find_and_remove_value(list, compare):
+ """Finds the value in the list that corresponds with the value of compare."""
+ # next throws if there are no matches
+ try:
+ found = next(value for value in list
+ if value['name'] == compare['name'] and value['switch'] ==
+ compare['switch'])
+ except:
+ return None
+
+ list.remove(found)
+
+ return found
+
+
+###########################################################################################
+# private xml functions
+def __convert(root, tag, values, func):
+ """Converts the tag type found in the root and converts them using the func
+ and appends them to the values.
+ """
+ elements = root.getElementsByTagName(tag)
+
+ for element in elements:
+ converted = func(element)
+
+ # Append to the list
+ __append_list(values, converted)
+
+
+def __convert_enum(node):
+ """Converts an EnumProperty node to JSON format."""
+ name = __get_attribute(node, 'Name')
+ logging.debug('Found EnumProperty named %s', name)
+
+ converted_values = []
+
+ for value in node.getElementsByTagName('EnumValue'):
+ converted = __convert_node(value)
+
+ converted['value'] = converted['name']
+ converted['name'] = name
+
+ # Modify flags when there is an argument child
+ __with_argument(value, converted)
+
+ converted_values.append(converted)
+
+ return converted_values
+
+
+def __convert_bool(node):
+ """Converts an BoolProperty node to JSON format."""
+ converted = __convert_node(node, default_value='true')
+
+ # Check for a switch for reversing the value
+ reverse_switch = __get_attribute(node, 'ReverseSwitch')
+
+ if reverse_switch:
+ converted_reverse = copy.deepcopy(converted)
+
+ converted_reverse['switch'] = reverse_switch
+ converted_reverse['value'] = 'false'
+
+ return [converted_reverse, converted]
+
+ # Modify flags when there is an argument child
+ __with_argument(node, converted)
+
+ return __check_for_flag(converted)
+
+
+def __convert_string_list(node):
+ """Converts a StringListProperty node to JSON format."""
+ converted = __convert_node(node)
+
+ # Determine flags for the string list
+ flags = vsflags(VSFlags.UserValue)
+
+ # Check for a separator to determine if it is semicolon appendable
+ # If not present assume the value should be ;
+ separator = __get_attribute(node, 'Separator', default_value=';')
+
+ if separator == ';':
+ flags = vsflags(flags, VSFlags.SemicolonAppendable)
+
+ converted['flags'] = flags
+
+ return __check_for_flag(converted)
+
+
+def __convert_string(node):
+ """Converts a StringProperty node to JSON format."""
+ converted = __convert_node(node, default_flags=vsflags(VSFlags.UserValue))
+
+ return __check_for_flag(converted)
+
+
+def __convert_node(node, default_value='', default_flags=vsflags()):
+ """Converts a XML node to a JSON equivalent."""
+ name = __get_attribute(node, 'Name')
+ logging.debug('Found %s named %s', node.tagName, name)
+
+ converted = {}
+ converted['name'] = name
+ converted['switch'] = __get_attribute(node, 'Switch')
+ converted['comment'] = __get_attribute(node, 'DisplayName')
+ converted['value'] = default_value
+
+ # Check for the Flags attribute in case it was created during preprocessing
+ flags = __get_attribute(node, 'Flags')
+
+ if flags:
+ flags = flags.split(',')
+ else:
+ flags = default_flags
+
+ converted['flags'] = flags
+
+ return converted
+
+
+def __check_for_flag(value):
+ """Checks whether the value has a switch value.
+
+ If not then returns None as it should not be added.
+ """
+ if value['switch']:
+ return value
+ else:
+ logging.warning('Skipping %s which has no command line switch',
+ value['name'])
+ return None
+
+
+def __with_argument(node, value):
+ """Modifies the flags in value if the node contains an Argument."""
+ arguments = node.getElementsByTagName('Argument')
+
+ if arguments:
+ logging.debug('Found argument within %s', value['name'])
+ value['flags'] = vsflags(VSFlags.UserValueIgnored, VSFlags.Continue)
+
+
+def __preprocess_arguments(root):
+ """Preprocesses occurrances 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
+ switch associated with the argument.
+ """
+ # Set the flags to require a value
+ flags = ','.join(vsflags(VSFlags.UserValueRequired))
+
+ # Search through the arguments
+ arguments = root.getElementsByTagName('Argument')
+
+ for argument in arguments:
+ reference = __get_attribute(argument, 'Property')
+ found = None
+
+ # Look for the argument within the root's children
+ for child in root.childNodes:
+ # Ignore Text nodes
+ if isinstance(child, Element):
+ name = __get_attribute(child, 'Name')
+
+ if name == reference:
+ found = child
+ break
+
+ if found is not None:
+ logging.info('Found property named %s', reference)
+ # Get the associated switch
+ switch = __get_attribute(argument.parentNode, 'Switch')
+
+ # See if there is already a switch associated with the element.
+ if __get_attribute(found, 'Switch'):
+ logging.debug('Copying node %s', reference)
+ clone = found.cloneNode(True)
+ root.insertBefore(clone, found)
+ found = clone
+
+ found.setAttribute('Switch', switch)
+ found.setAttribute('Flags', flags)
+ else:
+ logging.warning('Could not find property named %s', reference)
+
+
+def __get_attribute(node, name, default_value=''):
+ """Retrieves the attribute of the given name from the node.
+
+ If not present then the default_value is used.
+ """
+ if node.hasAttribute(name):
+ return node.attributes[name].value.strip()
+ else:
+ return default_value
+
+
+###########################################################################################
+# private path functions
+def __get_path(path):
+ """Gets the path to the file."""
+ if not os.path.isabs(path):
+ path = os.path.join(os.getcwd(), path)
+
+ return os.path.normpath(path)
+
+
+def __output_path(toolchain, rule, output_dir):
+ """Gets the output path for a file given the toolchain, rule and output_dir"""
+ filename = '%s_%s.json' % (toolchain, rule)
+ return os.path.join(output_dir, filename)
+
+
+###########################################################################################
+# private JSON file functions
+def __read_json_file(path):
+ """Reads a JSON file at the path."""
+ with open(path, 'r') as f:
+ return json.load(f)
+
+
+def __write_json_file(path, values):
+ """Writes a JSON file at the path with the values provided."""
+ # Sort the keys to ensure ordering
+ sort_order = ['name', 'switch', 'comment', 'value', 'flags']
+ sorted_values = [
+ OrderedDict(
+ sorted(
+ value.items(), key=lambda value: sort_order.index(value[0])))
+ for value in values
+ ]
+
+ with open(path, 'w') as f:
+ json.dump(sorted_values, f, indent=2, separators=(',', ': '))
+
+
+###########################################################################################
+# private list helpers
+def __append_list(append_to, value):
+ """Appends the value to the list."""
+ if value is not None:
+ if isinstance(value, list):
+ append_to.extend(value)
+ else:
+ append_to.append(value)
+
+###########################################################################################
+# main entry point
+if __name__ == "__main__":
+ main()
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 086f27a58..9a4abf3ca 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -1,620 +1,983 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCoreTryCompile.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
+#include "cmsys/Directory.hxx"
+#include <set>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <utility>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCoreTryCompile.h"
-#include "cmake.h"
-#include "cmCacheManager.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
+#include "cmAlgorithms.h"
#include "cmExportTryCompileFileGenerator.h"
-#include <cmsys/Directory.hxx>
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmVersion.h"
+#include "cmake.h"
-#include <assert.h>
+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_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_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_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES";
+static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET =
+ "CMAKE_OSX_DEPLOYMENT_TARGET";
+static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT";
+static std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
+ "CMAKE_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_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";
+
+static void writeProperty(FILE* fout, std::string const& targetName,
+ std::string const& prop, std::string const& value)
+{
+ fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", targetName.c_str(),
+ cmOutputConverter::EscapeForCMake(prop).c_str(),
+ cmOutputConverter::EscapeForCMake(value).c_str());
+}
+
+std::string cmCoreTryCompile::LookupStdVar(std::string const& var,
+ bool warnCMP0067)
+{
+ std::string value = this->Makefile->GetSafeDefinition(var);
+ if (warnCMP0067 && !value.empty()) {
+ value.clear();
+ this->WarnCMP0067.push_back(var);
+ }
+ return value;
+}
-int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
+int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
+ bool isTryRun)
{
- this->BinaryDirectory = argv[1].c_str();
+ this->BinaryDirectory = argv[1];
this->OutputFile = "";
// which signature were we called with ?
this->SrcFileSignature = true;
+ cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE;
+ const char* tt =
+ this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
+ if (!isTryRun && tt && *tt) {
+ if (strcmp(tt, cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) ==
+ 0) {
+ targetType = cmStateEnums::EXECUTABLE;
+ } 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 +
+ "' for "
+ "CMAKE_TRY_COMPILE_TARGET_TYPE. Only "
+ "'" +
+ cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) + "' and "
+ "'" +
+ cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY) +
+ "' "
+ "are allowed.");
+ return -1;
+ }
+ }
+
const char* sourceDirectory = argv[2].c_str();
- const char* projectName = 0;
- const char* targetName = 0;
- std::vector<std::string> cmakeFlags;
+ const char* projectName = CM_NULLPTR;
+ std::string targetName;
+ std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0]
std::vector<std::string> compileDefs;
std::string outputVariable;
std::string copyFile;
std::string copyFileError;
- std::vector<cmTarget*> targets;
+ std::string cStandard;
+ std::string cxxStandard;
+ std::string cudaStandard;
+ std::string cStandardRequired;
+ std::string cxxStandardRequired;
+ std::string cudaStandardRequired;
+ std::string cExtensions;
+ std::string cxxExtensions;
+ std::string cudaExtensions;
+ std::vector<std::string> targets;
std::string libsToLink = " ";
bool useOldLinkLibs = true;
char targetNameBuf[64];
bool didOutputVariable = false;
bool didCopyFile = false;
bool didCopyFileError = false;
+ bool didCStandard = false;
+ bool didCxxStandard = false;
+ bool didCudaStandard = false;
+ bool didCStandardRequired = false;
+ bool didCxxStandardRequired = false;
+ bool didCudaStandardRequired = false;
+ bool didCExtensions = false;
+ bool didCxxExtensions = false;
+ bool didCudaExtensions = false;
bool useSources = argv[2] == "SOURCES";
std::vector<std::string> sources;
- enum Doing { DoingNone, DoingCMakeFlags, DoingCompileDefinitions,
- DoingLinkLibraries, DoingOutputVariable, DoingCopyFile,
- DoingCopyFileError, DoingSources };
- Doing doing = useSources? DoingSources : DoingNone;
- for(size_t i=3; i < argv.size(); ++i)
- {
- if(argv[i] == "CMAKE_FLAGS")
- {
+ enum Doing
+ {
+ DoingNone,
+ DoingCMakeFlags,
+ DoingCompileDefinitions,
+ DoingLinkLibraries,
+ DoingOutputVariable,
+ DoingCopyFile,
+ DoingCopyFileError,
+ DoingCStandard,
+ DoingCxxStandard,
+ DoingCudaStandard,
+ DoingCStandardRequired,
+ DoingCxxStandardRequired,
+ DoingCudaStandardRequired,
+ DoingCExtensions,
+ DoingCxxExtensions,
+ DoingCudaExtensions,
+ DoingSources
+ };
+ Doing doing = useSources ? DoingSources : DoingNone;
+ for (size_t i = 3; i < argv.size(); ++i) {
+ if (argv[i] == "CMAKE_FLAGS") {
doing = DoingCMakeFlags;
- // CMAKE_FLAGS is the first argument because we need an argv[0] that
- // is not used, so it matches regular command line parsing which has
- // the program name as arg 0
- cmakeFlags.push_back(argv[i]);
- }
- else if(argv[i] == "COMPILE_DEFINITIONS")
- {
+ } else if (argv[i] == "COMPILE_DEFINITIONS") {
doing = DoingCompileDefinitions;
- }
- else if(argv[i] == "LINK_LIBRARIES")
- {
+ } else if (argv[i] == "LINK_LIBRARIES") {
doing = DoingLinkLibraries;
useOldLinkLibs = false;
- }
- else if(argv[i] == "OUTPUT_VARIABLE")
- {
+ } else if (argv[i] == "OUTPUT_VARIABLE") {
doing = DoingOutputVariable;
didOutputVariable = true;
- }
- else if(argv[i] == "COPY_FILE")
- {
+ } else if (argv[i] == "COPY_FILE") {
doing = DoingCopyFile;
didCopyFile = true;
- }
- else if(argv[i] == "COPY_FILE_ERROR")
- {
+ } else if (argv[i] == "COPY_FILE_ERROR") {
doing = DoingCopyFileError;
didCopyFileError = true;
- }
- else if(doing == DoingCMakeFlags)
- {
+ } else if (argv[i] == "C_STANDARD") {
+ doing = DoingCStandard;
+ didCStandard = true;
+ } else if (argv[i] == "CXX_STANDARD") {
+ doing = DoingCxxStandard;
+ didCxxStandard = true;
+ } else if (argv[i] == "CUDA_STANDARD") {
+ doing = DoingCudaStandard;
+ didCudaStandard = true;
+ } else if (argv[i] == "C_STANDARD_REQUIRED") {
+ doing = DoingCStandardRequired;
+ didCStandardRequired = true;
+ } else if (argv[i] == "CXX_STANDARD_REQUIRED") {
+ doing = DoingCxxStandardRequired;
+ didCxxStandardRequired = true;
+ } else if (argv[i] == "CUDA_STANDARD_REQUIRED") {
+ doing = DoingCudaStandardRequired;
+ didCudaStandardRequired = true;
+ } else if (argv[i] == "C_EXTENSIONS") {
+ doing = DoingCExtensions;
+ didCExtensions = true;
+ } else if (argv[i] == "CXX_EXTENSIONS") {
+ doing = DoingCxxExtensions;
+ didCxxExtensions = true;
+ } else if (argv[i] == "CUDA_EXTENSIONS") {
+ doing = DoingCudaExtensions;
+ didCudaExtensions = true;
+ } else if (doing == DoingCMakeFlags) {
cmakeFlags.push_back(argv[i]);
- }
- else if(doing == DoingCompileDefinitions)
- {
+ } else if (doing == DoingCompileDefinitions) {
compileDefs.push_back(argv[i]);
- }
- else if(doing == DoingLinkLibraries)
- {
+ } else if (doing == DoingLinkLibraries) {
libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
- if(cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str()))
- {
- switch(tgt->GetType())
- {
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::UNKNOWN_LIBRARY:
+ if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
+ switch (tgt->GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ case cmStateEnums::UNKNOWN_LIBRARY:
break;
- case cmTarget::EXECUTABLE:
- if (tgt->IsExecutableWithExports())
- {
+ case cmStateEnums::EXECUTABLE:
+ if (tgt->IsExecutableWithExports()) {
break;
- }
+ }
+ CM_FALLTHROUGH;
default:
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "Only libraries may be used as try_compile IMPORTED "
- "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + " of "
- "type " + tgt->GetTargetTypeName(tgt->GetType()) + ".");
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "Only libraries may be used as try_compile or try_run IMPORTED "
+ "LINK_LIBRARIES. Got " +
+ std::string(tgt->GetName()) + " of "
+ "type " +
+ cmState::GetTargetTypeName(tgt->GetType()) + ".");
return -1;
- }
- if (tgt->IsImported())
- {
- targets.push_back(tgt);
- }
+ }
+ if (tgt->IsImported()) {
+ targets.push_back(argv[i]);
}
}
- else if(doing == DoingOutputVariable)
- {
- outputVariable = argv[i].c_str();
+ } else if (doing == DoingOutputVariable) {
+ outputVariable = argv[i];
doing = DoingNone;
- }
- else if(doing == DoingCopyFile)
- {
- copyFile = argv[i].c_str();
+ } else if (doing == DoingCopyFile) {
+ copyFile = argv[i];
doing = DoingNone;
- }
- else if(doing == DoingCopyFileError)
- {
- copyFileError = argv[i].c_str();
+ } else if (doing == DoingCopyFileError) {
+ copyFileError = argv[i];
doing = DoingNone;
- }
- else if(doing == DoingSources)
- {
+ } else if (doing == DoingCStandard) {
+ cStandard = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCxxStandard) {
+ cxxStandard = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCudaStandard) {
+ cudaStandard = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCStandardRequired) {
+ cStandardRequired = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCxxStandardRequired) {
+ cxxStandardRequired = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCudaStandardRequired) {
+ cudaStandardRequired = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCExtensions) {
+ cExtensions = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCxxExtensions) {
+ cxxExtensions = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingCudaExtensions) {
+ cudaExtensions = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingSources) {
sources.push_back(argv[i]);
- }
- else if(i == 3)
- {
+ } else if (i == 3) {
this->SrcFileSignature = false;
projectName = argv[i].c_str();
- }
- else if(i == 4 && !this->SrcFileSignature)
- {
- targetName = argv[i].c_str();
- }
- else
- {
- cmOStringStream m;
+ } 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());
- }
}
+ }
- if(didCopyFile && copyFile.empty())
- {
+ if (didCopyFile && copyFile.empty()) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "COPY_FILE must be followed by a file path");
+ "COPY_FILE must be followed by a file path");
return -1;
- }
+ }
- if(didCopyFileError && copyFileError.empty())
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ if (didCopyFileError && copyFileError.empty()) {
+ this->Makefile->IssueMessage(
+ cmake::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");
+ if (didCopyFileError && !didCopyFile) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "COPY_FILE_ERROR may be used only with COPY_FILE");
return -1;
- }
+ }
- if(didOutputVariable && outputVariable.empty())
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ if (didOutputVariable && outputVariable.empty()) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
"OUTPUT_VARIABLE must be followed by a variable name");
return -1;
- }
+ }
- if(useSources && sources.empty())
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ if (useSources && sources.empty()) {
+ this->Makefile->IssueMessage(
+ cmake::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.");
+ return -1;
+ }
+ if (didCxxStandard && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "CXX_STANDARD allowed only in source file signature.");
+ return -1;
+ }
+ if (didCudaStandard && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "CUDA_STANDARD allowed only in source file signature.");
+ return -1;
+ }
+ if (didCStandardRequired && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "C_STANDARD_REQUIRED allowed only in source file signature.");
+ return -1;
+ }
+ if (didCxxStandardRequired && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "CXX_STANDARD_REQUIRED allowed only in source file signature.");
+ return -1;
+ }
+ if (didCudaStandardRequired && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "CUDA_STANDARD_REQUIRED allowed only in source file signature.");
+ return -1;
+ }
+ if (didCExtensions && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "C_EXTENSIONS allowed only in source file signature.");
+ return -1;
+ }
+ if (didCxxExtensions && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "CXX_EXTENSIONS allowed only in source file signature.");
+ return -1;
+ }
+ if (didCudaExtensions && !this->SrcFileSignature) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "CUDA_EXTENSIONS allowed only in source file signature.");
+ return -1;
+ }
// compute the binary dir when TRY_COMPILE is called with a src file
// signature
- if (this->SrcFileSignature)
- {
+ if (this->SrcFileSignature) {
this->BinaryDirectory += cmake::GetCMakeFilesDirectory();
this->BinaryDirectory += "/CMakeTmp";
- }
- else
- {
+ } else {
// only valid for srcfile signatures
- if (compileDefs.size())
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ if (!compileDefs.empty()) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
"COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE");
return -1;
- }
- if (copyFile.size())
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ }
+ if (!copyFile.empty()) {
+ this->Makefile->IssueMessage(
+ cmake::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());
// do not allow recursive try Compiles
- if (this->BinaryDirectory == this->Makefile->GetHomeOutputDirectory())
- {
- cmOStringStream e;
+ 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());
return -1;
- }
+ }
std::string outFileName = this->BinaryDirectory + "/CMakeLists.txt";
// which signature are we using? If we are using var srcfile bindir
- if (this->SrcFileSignature)
- {
+ if (this->SrcFileSignature) {
// remove any CMakeCache.txt files so we will have a clean test
std::string ccFile = this->BinaryDirectory + "/CMakeCache.txt";
- cmSystemTools::RemoveFile(ccFile.c_str());
+ cmSystemTools::RemoveFile(ccFile);
// Choose sources.
- if(!useSources)
- {
+ if (!useSources) {
sources.push_back(argv[2]);
- }
+ }
// Detect languages to enable.
- cmLocalGenerator* lg = this->Makefile->GetLocalGenerator();
- cmGlobalGenerator* gg = lg->GetGlobalGenerator();
+ cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
std::set<std::string> testLangs;
- for(std::vector<std::string>::iterator si = sources.begin();
- si != sources.end(); ++si)
- {
+ for (std::vector<std::string>::iterator si = sources.begin();
+ si != sources.end(); ++si) {
std::string ext = cmSystemTools::GetFilenameLastExtension(*si);
- if(const char* lang = gg->GetLanguageFromExtension(ext.c_str()))
- {
+ std::string lang = gg->GetLanguageFromExtension(ext.c_str());
+ if (!lang.empty()) {
testLangs.insert(lang);
- }
- else
- {
- cmOStringStream err;
+ } else {
+ std::ostringstream err;
err << "Unknown extension \"" << ext << "\" for file\n"
<< " " << *si << "\n"
<< "try_compile() works only for enabled languages. "
- << "Currently these are:\n ";
+ << "Currently these are:\n ";
std::vector<std::string> langs;
gg->GetEnabledLanguages(langs);
- for(std::vector<std::string>::iterator l = langs.begin();
- l != langs.end(); ++l)
- {
- err << " " << *l;
- }
+ err << cmJoin(langs, " ");
err << "\nSee project() command to enable other languages.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str());
return -1;
- }
}
+ }
+
+ std::string const tcConfig =
+ this->Makefile->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
// we need to create a directory and CMakeLists file etc...
// first create the directories
sourceDirectory = this->BinaryDirectory.c_str();
// now create a CMakeLists.txt file in that directory
- FILE *fout = fopen(outFileName.c_str(),"w");
- if (!fout)
- {
- cmOStringStream e;
+ FILE* fout = cmsys::SystemTools::Fopen(outFileName, "w");
+ if (!fout) {
+ std::ostringstream e;
+ /* clang-format off */
e << "Failed to open\n"
- << " " << outFileName.c_str() << "\n"
+ << " " << outFileName << "\n"
<< cmSystemTools::GetLastSystemError();
+ /* clang-format on */
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return -1;
- }
+ }
const char* def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH");
fprintf(fout, "cmake_minimum_required(VERSION %u.%u.%u.%u)\n",
cmVersion::GetMajorVersion(), cmVersion::GetMinorVersion(),
cmVersion::GetPatchVersion(), cmVersion::GetTweakVersion());
- if(def)
- {
- fprintf(fout, "SET(CMAKE_MODULE_PATH %s)\n", def);
- }
+ if (def) {
+ fprintf(fout, "set(CMAKE_MODULE_PATH \"%s\")\n", def);
+ }
std::string projectLangs;
- for(std::set<std::string>::iterator li = testLangs.begin();
- li != testLangs.end(); ++li)
- {
+ for (std::set<std::string>::iterator li = testLangs.begin();
+ li != testLangs.end(); ++li) {
projectLangs += " " + *li;
std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE";
std::string rulesOverrideLang = rulesOverrideBase + "_" + *li;
- if(const char* rulesOverridePath =
- this->Makefile->GetDefinition(rulesOverrideLang.c_str()))
- {
- fprintf(fout, "SET(%s \"%s\")\n",
- rulesOverrideLang.c_str(), rulesOverridePath);
- }
- else if(const char* rulesOverridePath2 =
- this->Makefile->GetDefinition(rulesOverrideBase.c_str()))
- {
- fprintf(fout, "SET(%s \"%s\")\n",
- rulesOverrideBase.c_str(), rulesOverridePath2);
- }
+ if (const char* rulesOverridePath =
+ this->Makefile->GetDefinition(rulesOverrideLang)) {
+ fprintf(fout, "set(%s \"%s\")\n", rulesOverrideLang.c_str(),
+ rulesOverridePath);
+ } else if (const char* rulesOverridePath2 =
+ this->Makefile->GetDefinition(rulesOverrideBase)) {
+ fprintf(fout, "set(%s \"%s\")\n", rulesOverrideBase.c_str(),
+ rulesOverridePath2);
}
- fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
- fprintf(fout, "SET(CMAKE_VERBOSE_MAKEFILE 1)\n");
- for(std::set<std::string>::iterator li = testLangs.begin();
- li != testLangs.end(); ++li)
- {
+ }
+ fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
+ 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";
- const char* flags = this->Makefile->GetDefinition(langFlags.c_str());
- fprintf(fout, "SET(CMAKE_%s_FLAGS %s)\n", li->c_str(),
- lg->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, "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.size())
- {
- fprintf(fout, "ADD_DEFINITIONS( ");
- for (size_t i = 0; i < compileDefs.size(); ++i)
+ const char* flags = this->Makefile->GetDefinition(langFlags);
+ 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());
+ }
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0066)) {
+ case cmPolicies::WARN:
+ if (this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0066")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0066) << "\n"
+ "For compatibility with older versions of CMake, try_compile "
+ "is not honoring caller config-specific compiler flags "
+ "(e.g. CMAKE_C_FLAGS_DEBUG) in the test project."
+ ;
+ /* clang-format on */
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+ case cmPolicies::OLD:
+ // OLD behavior is to do nothing.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066));
+ CM_FALLTHROUGH;
+ case cmPolicies::NEW: {
+ // NEW behavior is to pass config-specific compiler flags.
+ 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;
+ const char* flagsCfg = this->Makefile->GetDefinition(langFlagsCfg);
+ fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(),
+ cmOutputConverter::EscapeForCMake(flagsCfg ? flagsCfg : "")
+ .c_str());
+ }
+ } break;
+ }
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0056)) {
+ case cmPolicies::WARN:
+ if (this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0056")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0056) << "\n"
+ "For compatibility with older versions of CMake, try_compile "
+ "is not honoring caller link flags (e.g. CMAKE_EXE_LINKER_FLAGS) "
+ "in the test project."
+ ;
+ /* clang-format on */
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+ case cmPolicies::OLD:
+ // OLD behavior is to do nothing.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056));
+ CM_FALLTHROUGH;
+ case cmPolicies::NEW:
+ // NEW behavior is to pass linker flags.
{
- fprintf(fout,"%s ",compileDefs[i].c_str());
+ const char* exeLinkFlags =
+ this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
+ fprintf(
+ fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
+ cmOutputConverter::EscapeForCMake(exeLinkFlags ? exeLinkFlags : "")
+ .c_str());
}
- fprintf(fout, ")\n");
- }
+ break;
+ }
+ 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());
+ }
/* Use a random file name to avoid rapid creation and deletion
of the same executable name (some filesystems fail on that). */
- sprintf(targetNameBuf, "cmTryCompileExec%u",
- cmSystemTools::RandomSeed());
+ sprintf(targetNameBuf, "cmTC_%05x", cmSystemTools::RandomSeed() & 0xFFFFF);
targetName = targetNameBuf;
- if (!targets.empty())
- {
+ if (!targets.empty()) {
std::string fname = "/" + std::string(targetName) + "Targets.cmake";
- cmExportTryCompileFileGenerator tcfg;
+ cmExportTryCompileFileGenerator tcfg(gg, targets, this->Makefile);
tcfg.SetExportFile((this->BinaryDirectory + fname).c_str());
- tcfg.SetExports(targets);
- tcfg.SetConfig(this->Makefile->GetDefinition(
- "CMAKE_TRY_COMPILE_CONFIGURATION"));
+ tcfg.SetConfig(tcConfig);
- if(!tcfg.GenerateImportFile())
- {
+ if (!tcfg.GenerateImportFile()) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
"could not write export file.");
fclose(fout);
return -1;
- }
- fprintf(fout,
- "\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/%s\")\n\n",
+ }
+ fprintf(fout, "\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/%s\")\n\n",
fname.c_str());
+ }
+
+ // Forward a set of variables to the inner project cache.
+ {
+ std::set<std::string> vars;
+ vars.insert(kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN);
+ vars.insert(kCMAKE_C_COMPILER_TARGET);
+ vars.insert(kCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN);
+ vars.insert(kCMAKE_CXX_COMPILER_TARGET);
+ vars.insert(kCMAKE_ENABLE_EXPORTS);
+ vars.insert(kCMAKE_LINK_SEARCH_END_STATIC);
+ vars.insert(kCMAKE_LINK_SEARCH_START_STATIC);
+ vars.insert(kCMAKE_OSX_ARCHITECTURES);
+ vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET);
+ vars.insert(kCMAKE_OSX_SYSROOT);
+ vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE);
+ vars.insert(kCMAKE_SYSROOT);
+ vars.insert(kCMAKE_SYSROOT_COMPILE);
+ vars.insert(kCMAKE_SYSROOT_LINK);
+ vars.insert(kCMAKE_WARN_DEPRECATED);
+
+ if (const char* varListStr = this->Makefile->GetDefinition(
+ kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
+ std::vector<std::string> varList;
+ cmSystemTools::ExpandListArgument(varListStr, varList);
+ vars.insert(varList.begin(), varList.end());
+ }
+
+ /* 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
+ have the tests run for each specific architecture. Since
+ cmLocalGenerator doesn't allow building for "the other"
+ architecture only via CMAKE_OSX_ARCHITECTURES.
+ */
+ if (const char* tcArchs = this->Makefile->GetDefinition(
+ kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) {
+ vars.erase(kCMAKE_OSX_ARCHITECTURES);
+ std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + std::string(tcArchs);
+ cmakeFlags.push_back(flag);
+ }
+
+ for (std::set<std::string>::iterator vi = vars.begin(); vi != vars.end();
+ ++vi) {
+ std::string const& var = *vi;
+ if (const char* val = this->Makefile->GetDefinition(var)) {
+ std::string flag = "-D" + var + "=" + val;
+ cmakeFlags.push_back(flag);
+ }
}
+ }
- /* for the TRY_COMPILEs we want to be able to specify the architecture.
- So the user can set CMAKE_OSX_ARCHITECTURE to i386;ppc and then set
- CMAKE_TRY_COMPILE_OSX_ARCHITECTURE first to i386 and then to ppc to
- have the tests run for each specific architecture. Since
- cmLocalGenerator doesn't allow building for "the other"
- architecture only via CMAKE_OSX_ARCHITECTURES.
- */
- if(this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_OSX_ARCHITECTURES")!=0)
- {
- std::string flag="-DCMAKE_OSX_ARCHITECTURES=";
- flag += this->Makefile->GetSafeDefinition(
- "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES");
- cmakeFlags.push_back(flag);
+ /* Set the appropriate policy information for ENABLE_EXPORTS */
+ fprintf(fout, "cmake_policy(SET CMP0065 %s)\n",
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0065) ==
+ 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",
+ this->BinaryDirectory.c_str());
+ /* Create the actual executable. */
+ fprintf(fout, "add_executable(%s", targetName.c_str());
+ } else // if (targetType == cmStateEnums::STATIC_LIBRARY)
+ {
+ /* Put the static library at a known location (for COPY_FILE). */
+ fprintf(fout, "set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"%s\")\n",
+ this->BinaryDirectory.c_str());
+ /* 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());
+
+ // Add dependencies on any non-temporary sources.
+ if (si->find("CMakeTmp") == std::string::npos) {
+ this->Makefile->AddCMakeDependFile(*si);
}
- else if (this->Makefile->GetDefinition("CMAKE_OSX_ARCHITECTURES")!=0)
- {
- std::string flag="-DCMAKE_OSX_ARCHITECTURES=";
- flag += this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES");
- cmakeFlags.push_back(flag);
+ }
+ fprintf(fout, ")\n");
+
+ bool const testC = testLangs.find("C") != testLangs.end();
+ bool const testCxx = testLangs.find("CXX") != 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) {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
+ case cmPolicies::WARN:
+ warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0067");
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to not honor the language standard variables.
+ honorStandard = false;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067));
+ case cmPolicies::NEW:
+ // NEW behavior is to honor the language standard variables.
+ // We already initialized honorStandard to true.
+ break;
}
- /* on APPLE also pass CMAKE_OSX_SYSROOT to the try_compile */
- if(this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT")!=0)
- {
- std::string flag="-DCMAKE_OSX_SYSROOT=";
- flag += this->Makefile->GetSafeDefinition("CMAKE_OSX_SYSROOT");
- cmakeFlags.push_back(flag);
+ }
+
+ 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);
+ }
}
- /* on APPLE also pass CMAKE_OSX_DEPLOYMENT_TARGET to the try_compile */
- if(this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET")!=0)
- {
- std::string flag="-DCMAKE_OSX_DEPLOYMENT_TARGET=";
- flag += this->Makefile->GetSafeDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
- cmakeFlags.push_back(flag);
+ 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(this->Makefile->GetDefinition("CMAKE_POSITION_INDEPENDENT_CODE")!=0)
- {
- fprintf(fout, "SET(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n");
+ 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);
+ }
}
+ }
- /* Put the executable at a known location (for COPY_FILE). */
- fprintf(fout, "SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
- this->BinaryDirectory.c_str());
- /* Create the actual executable. */
- fprintf(fout, "ADD_EXECUTABLE(%s", targetName);
- for(std::vector<std::string>::iterator si = sources.begin();
- si != sources.end(); ++si)
- {
- fprintf(fout, " \"%s\"", si->c_str());
+ if (!this->WarnCMP0067.empty()) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0067) << "\n"
+ "For compatibility with older versions of CMake, try_compile "
+ "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";
+ }
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
- // Add dependencies on any non-temporary sources.
- if(si->find("CMakeTmp") == si->npos)
- {
- this->Makefile->AddCMakeDependFile(*si);
- }
+ if (testC) {
+ if (!cStandard.empty()) {
+ writeProperty(fout, targetName, "C_STANDARD", cStandard);
}
- fprintf(fout, ")\n");
- if (useOldLinkLibs)
- {
- fprintf(fout,
- "TARGET_LINK_LIBRARIES(%s ${LINK_LIBRARIES})\n",targetName);
+ if (!cStandardRequired.empty()) {
+ writeProperty(fout, targetName, "C_STANDARD_REQUIRED",
+ cStandardRequired);
}
- else
- {
- fprintf(fout, "TARGET_LINK_LIBRARIES(%s %s)\n",
- targetName,
- libsToLink.c_str());
+ if (!cExtensions.empty()) {
+ writeProperty(fout, targetName, "C_EXTENSIONS", cExtensions);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ if (testCuda) {
+ if (!cudaStandard.empty()) {
+ writeProperty(fout, targetName, "CUDA_STANDARD", cudaStandard);
}
+ if (!cudaStandardRequired.empty()) {
+ writeProperty(fout, targetName, "CUDA_STANDARD_REQUIRED",
+ cudaStandardRequired);
+ }
+ if (!cudaExtensions.empty()) {
+ writeProperty(fout, targetName, "CUDA_EXTENSIONS", cudaExtensions);
+ }
+ }
+
+ if (useOldLinkLibs) {
+ fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
+ targetName.c_str());
+ } else {
+ fprintf(fout, "target_link_libraries(%s %s)\n", targetName.c_str(),
+ libsToLink.c_str());
+ }
fclose(fout);
projectName = "CMAKE_TRY_COMPILE";
- }
+ }
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.c_str(),
- projectName,
- targetName,
- this->SrcFileSignature,
- &cmakeFlags,
- &output);
- if ( erroroc )
- {
+ int res = this->Makefile->TryCompile(
+ sourceDirectory, this->BinaryDirectory, projectName, targetName,
+ this->SrcFileSignature, &cmakeFlags, output);
+ if (erroroc) {
cmSystemTools::SetErrorOccured();
- }
+ }
// set the result var to the return value to indicate success or failure
- this->Makefile->AddCacheDefinition(argv[0].c_str(),
- (res == 0 ? "TRUE" : "FALSE"),
+ this->Makefile->AddCacheDefinition(argv[0], (res == 0 ? "TRUE" : "FALSE"),
"Result of TRY_COMPILE",
- cmCacheManager::INTERNAL);
+ cmStateEnums::INTERNAL);
- if ( outputVariable.size() > 0 )
- {
- this->Makefile->AddDefinition(outputVariable.c_str(), output.c_str());
- }
+ if (!outputVariable.empty()) {
+ this->Makefile->AddDefinition(outputVariable, output.c_str());
+ }
- if (this->SrcFileSignature)
- {
+ if (this->SrcFileSignature) {
std::string copyFileErrorMessage;
- this->FindOutputFile(targetName);
+ this->FindOutputFile(targetName, targetType);
- if ((res==0) && (copyFile.size()))
- {
- if(this->OutputFile.empty() ||
- !cmSystemTools::CopyFileAlways(this->OutputFile.c_str(),
- copyFile.c_str()))
- {
- cmOStringStream emsg;
+ if ((res == 0) && !copyFile.empty()) {
+ if (this->OutputFile.empty() ||
+ !cmSystemTools::CopyFileAlways(this->OutputFile, copyFile)) {
+ std::ostringstream emsg;
+ /* clang-format off */
emsg << "Cannot copy output executable\n"
- << " '" << this->OutputFile.c_str() << "'\n"
+ << " '" << this->OutputFile << "'\n"
<< "to destination specified by COPY_FILE:\n"
- << " '" << copyFile.c_str() << "'\n";
- if(!this->FindErrorMessage.empty())
- {
+ << " '" << copyFile << "'\n";
+ /* clang-format on */
+ if (!this->FindErrorMessage.empty()) {
emsg << this->FindErrorMessage.c_str();
- }
- if(copyFileError.empty())
- {
+ }
+ if (copyFileError.empty()) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str());
return -1;
- }
- else
- {
- copyFileErrorMessage = emsg.str();
- }
}
+ copyFileErrorMessage = emsg.str();
}
+ }
- if(!copyFileError.empty())
- {
- this->Makefile->AddDefinition(copyFileError.c_str(),
+ if (!copyFileError.empty()) {
+ this->Makefile->AddDefinition(copyFileError,
copyFileErrorMessage.c_str());
- }
}
+ }
return res;
}
void cmCoreTryCompile::CleanupFiles(const char* binDir)
{
- if ( !binDir )
- {
+ if (!binDir) {
return;
- }
+ }
std::string bdir = binDir;
- if(bdir.find("CMakeTmp") == std::string::npos)
- {
+ if (bdir.find("CMakeTmp") == std::string::npos) {
cmSystemTools::Error(
"TRY_COMPILE attempt to remove -rf directory that does not contain "
- "CMakeTmp:", binDir);
+ "CMakeTmp:",
+ binDir);
return;
- }
+ }
cmsys::Directory dir;
dir.Load(binDir);
- size_t fileNum;
- std::set<cmStdString> deletedFiles;
- for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
- {
- if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
- strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
- {
-
- if(deletedFiles.find( dir.GetFile(static_cast<unsigned long>(fileNum)))
- == deletedFiles.end())
- {
- deletedFiles.insert(dir.GetFile(static_cast<unsigned long>(fileNum)));
- std::string fullPath = binDir;
- fullPath += "/";
- fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if(cmSystemTools::FileIsDirectory(fullPath.c_str()))
- {
+ std::set<std::string> deletedFiles;
+ for (unsigned long i = 0; i < dir.GetNumberOfFiles(); ++i) {
+ const char* fileName = dir.GetFile(i);
+ if (strcmp(fileName, ".") != 0 && strcmp(fileName, "..") != 0) {
+ if (deletedFiles.insert(fileName).second) {
+ std::string const fullPath =
+ std::string(binDir).append("/").append(fileName);
+ if (cmSystemTools::FileIsDirectory(fullPath)) {
this->CleanupFiles(fullPath.c_str());
- cmSystemTools::RemoveADirectory(fullPath.c_str());
- }
- else
- {
+ cmSystemTools::RemoveADirectory(fullPath);
+ } else {
+#ifdef _WIN32
// Sometimes anti-virus software hangs on to new files so we
// cannot delete them immediately. Try a few times.
- int tries = 5;
- while(!cmSystemTools::RemoveFile(fullPath.c_str()) &&
- --tries && cmSystemTools::FileExists(fullPath.c_str()))
- {
- cmSystemTools::Delay(500);
- }
- if(tries == 0)
- {
+ cmSystemTools::WindowsFileRetry retry =
+ cmSystemTools::GetWindowsFileRetry();
+ while (!cmSystemTools::RemoveFile(fullPath.c_str()) &&
+ --retry.Count &&
+ cmSystemTools::FileExists(fullPath.c_str())) {
+ cmSystemTools::Delay(retry.Delay);
+ }
+ if (retry.Count == 0)
+#else
+ if (!cmSystemTools::RemoveFile(fullPath))
+#endif
+ {
std::string m = "Remove failed on file: " + fullPath;
cmSystemTools::ReportLastSystemError(m.c_str());
- }
}
}
}
}
+ }
}
-void cmCoreTryCompile::FindOutputFile(const char* targetName)
+void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
+ cmStateEnums::TargetType targetType)
{
this->FindErrorMessage = "";
this->OutputFile = "";
std::string tmpOutputFile = "/";
- tmpOutputFile += targetName;
- tmpOutputFile +=this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
+ if (targetType == cmStateEnums::EXECUTABLE) {
+ tmpOutputFile += targetName;
+ tmpOutputFile +=
+ this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
+ } else // if (targetType == cmStateEnums::STATIC_LIBRARY)
+ {
+ tmpOutputFile +=
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX");
+ tmpOutputFile += targetName;
+ tmpOutputFile +=
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
+ }
// 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("");
- const char* config = this->Makefile->GetDefinition(
- "CMAKE_TRY_COMPILE_CONFIGURATION");
+ const char* config =
+ this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
// if a config was specified try that first
- if (config && config[0])
- {
+ if (config && config[0]) {
std::string tmp = "/";
tmp += config;
searchDirs.push_back(tmp);
- }
+ }
searchDirs.push_back("/Debug");
+#if defined(__APPLE__)
+ std::string app = "/Debug/" + targetName + ".app";
+ searchDirs.push_back(app);
+#endif
searchDirs.push_back("/Development");
- for(std::vector<std::string>::const_iterator it = searchDirs.begin();
- it != searchDirs.end();
- ++it)
- {
+ 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()))
- {
- tmpOutputFile = cmSystemTools::CollapseFullPath(command.c_str());
- this->OutputFile = tmpOutputFile;
+ if (cmSystemTools::FileExists(command.c_str())) {
+ this->OutputFile = cmSystemTools::CollapseFullPath(command);
return;
- }
}
+ }
- cmOStringStream emsg;
+ std::ostringstream emsg;
emsg << "Unable to find the executable at any of:\n";
- for (unsigned int i = 0; i < searchDirs.size(); ++i)
- {
- emsg << " " << this->BinaryDirectory << searchDirs[i]
- << tmpOutputFile << "\n";
- }
+ emsg << cmWrap(" " + this->BinaryDirectory, searchDirs, tmpOutputFile, "\n")
+ << "\n";
this->FindErrorMessage = emsg.str();
- return;
}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 5c67f1355..365154dfb 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -1,18 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCoreTryCompile_h
#define cmCoreTryCompile_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+#include "cmStateTypes.h"
/** \class cmCoreTryCompile
* \brief Base class for cmTryCompileCommand and cmTryRunCommand
@@ -23,14 +20,13 @@
class cmCoreTryCompile : public cmCommand
{
public:
-
- protected:
+protected:
/**
* This is the core code for try compile. It is here so that other
* commands, such as TryRun can access the same logic without
* duplication.
*/
- int TryCompileCode(std::vector<std::string> const& argv);
+ int TryCompileCode(std::vector<std::string> const& argv, bool isTryRun);
/**
* This deletes all the files created by TryCompileCode.
@@ -44,17 +40,17 @@ public:
TryCompileCode. The result is stored in OutputFile. If nothing is found,
the error message is stored in FindErrorMessage.
*/
- void FindOutputFile(const char* targetName);
-
-
- cmTypeMacro(cmCoreTryCompile, cmCommand);
+ void FindOutputFile(const std::string& targetName,
+ cmStateEnums::TargetType targetType);
std::string BinaryDirectory;
std::string OutputFile;
std::string FindErrorMessage;
bool SrcFileSignature;
+private:
+ std::vector<std::string> WarnCMP0067;
+ std::string LookupStdVar(std::string const& var, bool warnCMP0067);
};
-
#endif
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index de20cb7ef..69532e61b 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -1,63 +1,51 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCreateTestSourceList.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <algorithm>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCreateTestSourceList.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmCreateTestSourceList
-bool cmCreateTestSourceList
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if (args.size() < 3)
- {
+ if (args.size() < 3) {
this->SetError("called with wrong number of arguments.");
return false;
- }
-
+ }
std::vector<std::string>::const_iterator i = args.begin();
std::string extraInclude;
std::string function;
std::vector<std::string> tests;
// extract extra include and function ot
- for(; i != args.end(); i++)
- {
- if(*i == "EXTRA_INCLUDE")
- {
+ for (; i != args.end(); i++) {
+ if (*i == "EXTRA_INCLUDE") {
++i;
- if(i == args.end())
- {
+ if (i == args.end()) {
this->SetError("incorrect arguments to EXTRA_INCLUDE");
return false;
- }
+ }
extraInclude = "#include \"";
extraInclude += *i;
extraInclude += "\"\n";
- }
- else if(*i == "FUNCTION")
- {
+ } else if (*i == "FUNCTION") {
++i;
- if(i == args.end())
- {
+ if (i == args.end()) {
this->SetError("incorrect arguments to FUNCTION");
return false;
- }
+ }
function = *i;
function += "(&ac, &av);\n";
- }
- else
- {
+ } else {
tests.push_back(*i);
- }
}
+ }
i = tests.begin();
// Name of the source list
@@ -67,19 +55,17 @@ bool cmCreateTestSourceList
// Name of the test driver
// make sure they specified an extension
- if (cmSystemTools::GetFilenameExtension(*i).size() < 2)
- {
+ if (cmSystemTools::GetFilenameExtension(*i).size() < 2) {
this->SetError(
"You must specify a file extension for the test driver file.");
return false;
- }
- std::string driver = this->Makefile->GetCurrentOutputDirectory();
+ }
+ std::string driver = this->Makefile->GetCurrentBinaryDirectory();
driver += "/";
driver += *i;
++i;
- std::string configFile =
- this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
+ std::string configFile = cmSystemTools::GetCMakeRoot();
configFile += "/Templates/TestDriver.cxx.in";
// Create the test driver file
@@ -94,96 +80,81 @@ bool cmCreateTestSourceList
// For the moment:
// - replace spaces ' ', ':' and '/' with underscores '_'
std::string forwardDeclareCode;
- for(i = testsBegin; i != tests.end(); ++i)
- {
- if(*i == "EXTRA_INCLUDE")
- {
+ for (i = testsBegin; i != tests.end(); ++i) {
+ if (*i == "EXTRA_INCLUDE") {
break;
- }
+ }
std::string func_name;
- if (cmSystemTools::GetFilenamePath(*i).size() > 0)
- {
+ if (!cmSystemTools::GetFilenamePath(*i).empty()) {
func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
cmSystemTools::GetFilenameWithoutLastExtension(*i);
- }
- else
- {
+ } else {
func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
- }
+ }
cmSystemTools::ConvertToUnixSlashes(func_name);
- cmSystemTools::ReplaceString(func_name, " ", "_");
- cmSystemTools::ReplaceString(func_name, "/", "_");
- cmSystemTools::ReplaceString(func_name, ":", "_");
+ std::replace(func_name.begin(), func_name.end(), ' ', '_');
+ std::replace(func_name.begin(), func_name.end(), '/', '_');
+ std::replace(func_name.begin(), func_name.end(), ':', '_');
tests_func_name.push_back(func_name);
forwardDeclareCode += "int ";
forwardDeclareCode += func_name;
forwardDeclareCode += "(int, char*[]);\n";
- }
+ }
std::string functionMapCode;
int numTests = 0;
std::vector<std::string>::iterator j;
- for(i = testsBegin, j = tests_func_name.begin(); i != tests.end(); ++i, ++j)
- {
+ for (i = testsBegin, j = tests_func_name.begin(); i != tests.end();
+ ++i, ++j) {
std::string func_name;
- if (cmSystemTools::GetFilenamePath(*i).size() > 0)
- {
+ if (!cmSystemTools::GetFilenamePath(*i).empty()) {
func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
cmSystemTools::GetFilenameWithoutLastExtension(*i);
- }
- else
- {
+ } else {
func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
- }
+ }
functionMapCode += " {\n"
- " \"";
+ " \"";
functionMapCode += func_name;
functionMapCode += "\",\n"
- " ";
- functionMapCode += *j;
+ " ";
+ functionMapCode += *j;
functionMapCode += "\n"
- " },\n";
+ " },\n";
numTests++;
- }
- if(extraInclude.size())
- {
+ }
+ if (!extraInclude.empty()) {
this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES",
extraInclude.c_str());
- }
- if(function.size())
- {
+ }
+ if (!function.empty()) {
this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION",
function.c_str());
- }
+ }
this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS",
- forwardDeclareCode.c_str());
+ forwardDeclareCode.c_str());
this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES",
- functionMapCode.c_str());
+ functionMapCode.c_str());
bool res = true;
- if ( !this->Makefile->ConfigureFile(configFile.c_str(), driver.c_str(),
- false, true, false) )
- {
+ if (!this->Makefile->ConfigureFile(configFile.c_str(), driver.c_str(), false,
+ true, false)) {
res = false;
- }
+ }
// Construct the source list.
std::string sourceListValue;
{
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver.c_str());
- sf->SetProperty("ABSTRACT","0");
- sourceListValue = args[1];
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver);
+ sf->SetProperty("ABSTRACT", "0");
+ sourceListValue = args[1];
}
- for(i = testsBegin; i != tests.end(); ++i)
- {
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(i->c_str());
- sf->SetProperty("ABSTRACT","0");
+ for (i = testsBegin; i != tests.end(); ++i) {
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ sf->SetProperty("ABSTRACT", "0");
sourceListValue += ";";
sourceListValue += *i;
- }
+ }
this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
return res;
}
-
-
-
diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h
index 3aa0a79cf..f1f1e4b8a 100644
--- a/Source/cmCreateTestSourceList.h
+++ b/Source/cmCreateTestSourceList.h
@@ -1,21 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCreateTestSourceList_h
#define cmCreateTestSourceList_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmCreateTestSourceList
- * \brief
+ * \brief Test driver generation command
*
*/
@@ -25,66 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmCreateTestSourceList;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmCreateTestSourceList; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "create_test_sourcelist";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Create a test driver and source list for building test programs.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " create_test_sourcelist(sourceListName driverName\n"
- " test1 test2 test3\n"
- " EXTRA_INCLUDE include.h\n"
- " FUNCTION function)\n"
- "A test driver is a program that links together many small tests into "
- "a single executable. This is useful when building static executables "
- "with large libraries to shrink the total required size. "
- "The list of source files "
- "needed to build the test driver will be in sourceListName. "
- "DriverName is the name of the test driver program. The rest of "
- "the arguments consist of a list of test source files, can be "
- "semicolon separated. Each test source file should have a function in "
- "it that is the same name as the file with no extension (foo.cxx "
- "should have int foo(int, char*[]);) DriverName will be able to "
- "call each of the "
- "tests by name on the command line. If EXTRA_INCLUDE is specified, "
- "then the next argument is included into the generated file. If "
- "FUNCTION is specified, then the next argument is taken as a function "
- "name that is passed a pointer to ac and av. This can be used to add "
- "extra command line processing to each test. The cmake variable "
- "CMAKE_TESTDRIVER_BEFORE_TESTMAIN can be set to have code that will be "
- "placed directly before calling the test main function. "
- "CMAKE_TESTDRIVER_AFTER_TESTMAIN can be set to have code that will be "
- "placed directly after the call to the test main function.";
- }
-
- cmTypeMacro(cmCreateTestSourceList, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx
index a4f6ac4b4..7995b2cb3 100644
--- a/Source/cmCryptoHash.cxx
+++ b/Source/cmCryptoHash.cxx
@@ -1,130 +1,192 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCryptoHash.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#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 */
+ RHASH_MD5, //
+ RHASH_SHA1, //
+ RHASH_SHA224, //
+ RHASH_SHA256, //
+ RHASH_SHA384, //
+ RHASH_SHA512, //
+ RHASH_SHA3_224, //
+ RHASH_SHA3_256, //
+ RHASH_SHA3_384, //
+ RHASH_SHA3_512
+};
+
+static int cmCryptoHash_rhash_library_initialized;
+
+static rhash cmCryptoHash_rhash_init(unsigned int id)
+{
+ if (!cmCryptoHash_rhash_library_initialized) {
+ cmCryptoHash_rhash_library_initialized = 1;
+ rhash_library_init();
+ }
+ return rhash_init(id);
+}
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmCryptoHash.h"
+cmCryptoHash::cmCryptoHash(Algo algo)
+ : Id(cmCryptoHashAlgoToId[algo])
+ , CTX(cmCryptoHash_rhash_init(Id))
+{
+}
-#include <cmsys/MD5.h>
-#include "cm_sha2.h"
+cmCryptoHash::~cmCryptoHash()
+{
+ rhash_free(this->CTX);
+}
-//----------------------------------------------------------------------------
-cmsys::auto_ptr<cmCryptoHash> cmCryptoHash::New(const char* algo)
+CM_AUTO_PTR<cmCryptoHash> cmCryptoHash::New(const char* algo)
{
- if(strcmp(algo,"MD5") == 0)
- { return cmsys::auto_ptr<cmCryptoHash>(new cmCryptoHashMD5); }
- else if(strcmp(algo,"SHA1") == 0)
- { return cmsys::auto_ptr<cmCryptoHash>(new cmCryptoHashSHA1); }
- else if(strcmp(algo,"SHA224") == 0)
- { return cmsys::auto_ptr<cmCryptoHash>(new cmCryptoHashSHA224); }
- else if(strcmp(algo,"SHA256") == 0)
- { return cmsys::auto_ptr<cmCryptoHash>(new cmCryptoHashSHA256); }
- else if(strcmp(algo,"SHA384") == 0)
- { return cmsys::auto_ptr<cmCryptoHash>(new cmCryptoHashSHA384); }
- else if(strcmp(algo,"SHA512") == 0)
- { return cmsys::auto_ptr<cmCryptoHash>(new cmCryptoHashSHA512); }
- else
- { return cmsys::auto_ptr<cmCryptoHash>(0); }
+ if (strcmp(algo, "MD5") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoMD5));
+ }
+ if (strcmp(algo, "SHA1") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA1));
+ }
+ if (strcmp(algo, "SHA224") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA224));
+ }
+ if (strcmp(algo, "SHA256") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA256));
+ }
+ if (strcmp(algo, "SHA384") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA384));
+ }
+ if (strcmp(algo, "SHA512") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA512));
+ }
+ if (strcmp(algo, "SHA3_224") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_224));
+ }
+ if (strcmp(algo, "SHA3_256") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_256));
+ }
+ if (strcmp(algo, "SHA3_384") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_384));
+ }
+ if (strcmp(algo, "SHA3_512") == 0) {
+ return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_512));
+ }
+ return CM_AUTO_PTR<cmCryptoHash>(CM_NULLPTR);
}
-//----------------------------------------------------------------------------
-std::string cmCryptoHash::HashString(const char* input)
+bool cmCryptoHash::IntFromHexDigit(char input, char& output)
{
- this->Initialize();
- this->Append(reinterpret_cast<unsigned char const*>(input),
- static_cast<int>(strlen(input)));
- return this->Finalize();
+ if (input >= '0' && input <= '9') {
+ output = char(input - '0');
+ return true;
+ }
+ if (input >= 'a' && input <= 'f') {
+ output = char(input - 'a' + 0xA);
+ return true;
+ }
+ if (input >= 'A' && input <= 'F') {
+ output = char(input - 'A' + 0xA);
+ return true;
+ }
+ return false;
}
-//----------------------------------------------------------------------------
-std::string cmCryptoHash::HashFile(const char* file)
+std::string cmCryptoHash::ByteHashToString(
+ const std::vector<unsigned char>& hash)
{
- std::ifstream fin(file, std::ios::in | cmsys_ios_binary);
- if(!fin)
- {
- return "";
- }
+ // Map from 4-bit index to hexadecimal representation.
+ static char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '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]);
+ }
+ return res;
+}
+std::vector<unsigned char> cmCryptoHash::ByteHashString(
+ const std::string& input)
+{
this->Initialize();
+ this->Append(reinterpret_cast<unsigned char const*>(input.c_str()),
+ static_cast<int>(input.size()));
+ return this->Finalize();
+}
- // Should be efficient enough on most system:
- cm_sha2_uint64_t buffer[512];
- char* buffer_c = reinterpret_cast<char*>(buffer);
- unsigned char const* buffer_uc =
- reinterpret_cast<unsigned char const*>(buffer);
- // 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)
+std::vector<unsigned char> cmCryptoHash::ByteHashFile(const std::string& file)
+{
+ cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary);
+ if (fin) {
+ this->Initialize();
{
- fin.read(buffer_c, sizeof(buffer));
- if(int gcount = static_cast<int>(fin.gcount()))
- {
- this->Append(buffer_uc, gcount);
+ // Should be efficient enough on most system:
+ KWIML_INT_uint64_t buffer[512];
+ char* buffer_c = reinterpret_cast<char*>(buffer);
+ unsigned char const* buffer_uc =
+ reinterpret_cast<unsigned char const*>(buffer);
+ // 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_c, sizeof(buffer));
+ if (int gcount = static_cast<int>(fin.gcount())) {
+ this->Append(buffer_uc, gcount);
+ }
}
}
- if(fin.eof())
- {
- return this->Finalize();
+ if (fin.eof()) {
+ // Success
+ return this->Finalize();
}
- return "";
+ // Finalize anyway
+ this->Finalize();
+ }
+ // Return without success
+ return std::vector<unsigned char>();
}
-//----------------------------------------------------------------------------
-cmCryptoHashMD5::cmCryptoHashMD5(): MD5(cmsysMD5_New())
+std::string cmCryptoHash::HashString(const std::string& input)
{
+ return ByteHashToString(this->ByteHashString(input));
}
-//----------------------------------------------------------------------------
-cmCryptoHashMD5::~cmCryptoHashMD5()
+std::string cmCryptoHash::HashFile(const std::string& file)
{
- cmsysMD5_Delete(this->MD5);
+ return ByteHashToString(this->ByteHashFile(file));
}
-//----------------------------------------------------------------------------
-void cmCryptoHashMD5::Initialize()
+void cmCryptoHash::Initialize()
{
- cmsysMD5_Initialize(this->MD5);
+ rhash_reset(this->CTX);
}
-//----------------------------------------------------------------------------
-void cmCryptoHashMD5::Append(unsigned char const* buf, int sz)
+void cmCryptoHash::Append(void const* buf, size_t sz)
{
- cmsysMD5_Append(this->MD5, buf, sz);
+ rhash_update(this->CTX, buf, sz);
}
-//----------------------------------------------------------------------------
-std::string cmCryptoHashMD5::Finalize()
+void cmCryptoHash::Append(std::string const& str)
{
- char md5out[32];
- cmsysMD5_FinalizeHex(this->MD5, md5out);
- return std::string(md5out, 32);
+ this->Append(str.c_str(), str.size());
}
-
-#define cmCryptoHash_SHA_CLASS_IMPL(SHA) \
-cmCryptoHash##SHA::cmCryptoHash##SHA(): SHA(new SHA_CTX) {} \
-cmCryptoHash##SHA::~cmCryptoHash##SHA() { delete this->SHA; } \
-void cmCryptoHash##SHA::Initialize() { SHA##_Init(this->SHA); } \
-void cmCryptoHash##SHA::Append(unsigned char const* buf, int sz) \
-{ SHA##_Update(this->SHA, buf, sz); } \
-std::string cmCryptoHash##SHA::Finalize() \
-{ \
- char out[SHA##_DIGEST_STRING_LENGTH]; \
- SHA##_End(this->SHA, out); \
- return std::string(out, SHA##_DIGEST_STRING_LENGTH-1); \
+std::vector<unsigned char> cmCryptoHash::Finalize()
+{
+ std::vector<unsigned char> hash(rhash_get_digest_size(this->Id), 0);
+ rhash_final(this->CTX, &hash[0]);
+ return hash;
}
-cmCryptoHash_SHA_CLASS_IMPL(SHA1)
-cmCryptoHash_SHA_CLASS_IMPL(SHA224)
-cmCryptoHash_SHA_CLASS_IMPL(SHA256)
-cmCryptoHash_SHA_CLASS_IMPL(SHA384)
-cmCryptoHash_SHA_CLASS_IMPL(SHA512)
+std::string cmCryptoHash::FinalizeHex()
+{
+ return cmCryptoHash::ByteHashToString(this->Finalize());
+}
diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h
index 1bea9abcb..c380d85ff 100644
--- a/Source/cmCryptoHash.h
+++ b/Source/cmCryptoHash.h
@@ -1,65 +1,87 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCryptoHash_h
#define cmCryptoHash_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <stddef.h>
+#include <string>
+#include <vector>
-#include <cmsys/auto_ptr.hxx>
+#include "cm_auto_ptr.hxx"
+/**
+ * @brief Abstract base class for cryptographic hash generators
+ */
class cmCryptoHash
{
-public:
- virtual ~cmCryptoHash() {}
- static cmsys::auto_ptr<cmCryptoHash> New(const char* algo);
- std::string HashString(const char* input);
- std::string HashFile(const char* file);
-protected:
- virtual void Initialize()=0;
- virtual void Append(unsigned char const*, int)=0;
- virtual std::string Finalize()=0;
-};
+ CM_DISABLE_COPY(cmCryptoHash)
-class cmCryptoHashMD5: public cmCryptoHash
-{
- struct cmsysMD5_s* MD5;
public:
- cmCryptoHashMD5();
- ~cmCryptoHashMD5();
-protected:
- virtual void Initialize();
- virtual void Append(unsigned char const* buf, int sz);
- virtual std::string Finalize();
-};
+ enum Algo
+ {
+ AlgoMD5,
+ AlgoSHA1,
+ AlgoSHA224,
+ AlgoSHA256,
+ AlgoSHA384,
+ AlgoSHA512,
+ AlgoSHA3_224,
+ AlgoSHA3_256,
+ AlgoSHA3_384,
+ AlgoSHA3_512
+ };
+
+ cmCryptoHash(Algo algo);
+ ~cmCryptoHash();
+
+ /// @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);
-#define cmCryptoHash_SHA_CLASS_DECL(SHA) \
- class cmCryptoHash##SHA: public cmCryptoHash \
- { \
- union _SHA_CTX* SHA; \
- public: \
- cmCryptoHash##SHA(); \
- ~cmCryptoHash##SHA(); \
- protected: \
- virtual void Initialize(); \
- virtual void Append(unsigned char const* buf, int sz); \
- virtual std::string Finalize(); \
- }
-
-cmCryptoHash_SHA_CLASS_DECL(SHA1);
-cmCryptoHash_SHA_CLASS_DECL(SHA224);
-cmCryptoHash_SHA_CLASS_DECL(SHA256);
-cmCryptoHash_SHA_CLASS_DECL(SHA384);
-cmCryptoHash_SHA_CLASS_DECL(SHA512);
-
-#undef cmCryptoHash_SHA_CLASS_DECL
+ /// @brief Converts a hex character to its binary value (4 bits)
+ /// @arg input Hex character [0-9a-fA-F].
+ /// @arg output Binary value of the input character (4 bits)
+ /// @return True if input was a valid hex character
+ static bool IntFromHexDigit(char input, char& output);
+
+ /// @brief Converts a byte hash to a sequence of hex character pairs
+ static std::string ByteHashToString(const std::vector<unsigned char>& hash);
+
+ /// @brief Calculates a binary hash from string input data
+ /// @return Binary hash vector
+ std::vector<unsigned char> ByteHashString(const std::string& input);
+
+ /// @brief Calculates a binary hash from file content
+ /// @see ByteHashString()
+ /// @return Non empty binary hash vector if the file was read successfully.
+ /// An empty vector otherwise.
+ std::vector<unsigned char> ByteHashFile(const std::string& file);
+
+ /// @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);
+
+ /// @brief Calculates a hash string from file content
+ /// @see HashString()
+ /// @return Non empty hash string if the file was read successfully.
+ /// An empty string otherwise.
+ std::string HashFile(const std::string& file);
+
+ void Initialize();
+ void Append(void const*, size_t);
+ void Append(std::string const& str);
+ std::vector<unsigned char> Finalize();
+ std::string FinalizeHex();
+
+private:
+ unsigned int Id;
+ struct rhash_context* CTX;
+};
#endif
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
new file mode 100644
index 000000000..341b8c077
--- /dev/null
+++ b/Source/cmCurl.cxx
@@ -0,0 +1,58 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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"
+#endif
+
+// 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
+#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); \
+ }
+
+std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile)
+{
+ std::string e;
+ if (cafile && *cafile) {
+ ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, 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"
+ 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
+ else {
+#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"
+ 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
+ }
+#endif
+ return e;
+}
diff --git a/Source/cmCurl.h b/Source/cmCurl.h
new file mode 100644
index 000000000..a2fa4b1c0
--- /dev/null
+++ b/Source/cmCurl.h
@@ -0,0 +1,13 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCurl_h
+#define cmCurl_h
+
+#include "cmConfigure.h"
+
+#include "cm_curl.h"
+#include <string>
+
+std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = CM_NULLPTR);
+
+#endif
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 3620a3895..5e377b574 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -1,200 +1,150 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCustomCommand.h"
#include "cmMakefile.h"
-#include <cmsys/auto_ptr.hxx>
+#include "cmConfigure.h"
-//----------------------------------------------------------------------------
cmCustomCommand::cmCustomCommand()
+ : Backtrace()
{
this->HaveComment = false;
this->EscapeOldStyle = true;
this->EscapeAllowMakeVars = false;
+ this->UsesTerminal = false;
+ this->CommandExpandLists = false;
}
-//----------------------------------------------------------------------------
-cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
- Outputs(r.Outputs),
- Depends(r.Depends),
- CommandLines(r.CommandLines),
- HaveComment(r.HaveComment),
- Comment(r.Comment),
- WorkingDirectory(r.WorkingDirectory),
- EscapeAllowMakeVars(r.EscapeAllowMakeVars),
- EscapeOldStyle(r.EscapeOldStyle),
- Backtrace(new cmListFileBacktrace(*r.Backtrace))
-{
-}
-
-//----------------------------------------------------------------------------
-cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
-{
- if(this == &r)
- {
- return *this;
- }
-
- this->Outputs = r.Outputs;
- this->Depends = r.Depends;
- this->CommandLines = r.CommandLines;
- this->HaveComment = r.HaveComment;
- this->Comment = r.Comment;
- this->WorkingDirectory = r.WorkingDirectory;
- this->EscapeAllowMakeVars = r.EscapeAllowMakeVars;
- this->EscapeOldStyle = r.EscapeOldStyle;
- this->ImplicitDepends = r.ImplicitDepends;
-
- cmsys::auto_ptr<cmListFileBacktrace>
- newBacktrace(new cmListFileBacktrace(*r.Backtrace));
- delete this->Backtrace;
- this->Backtrace = newBacktrace.release();
-
- return *this;
-}
-
-//----------------------------------------------------------------------------
-cmCustomCommand::cmCustomCommand(cmMakefile* mf,
+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,
const char* comment,
- const char* workingDirectory):
- Outputs(outputs),
- Depends(depends),
- CommandLines(commandLines),
- HaveComment(comment?true:false),
- Comment(comment?comment:""),
- WorkingDirectory(workingDirectory?workingDirectory:""),
- EscapeAllowMakeVars(false),
- EscapeOldStyle(true),
- Backtrace(new cmListFileBacktrace)
-{
- this->EscapeOldStyle = true;
- this->EscapeAllowMakeVars = false;
- if(mf)
- {
- mf->GetBacktrace(*this->Backtrace);
- }
+ const char* workingDirectory)
+ : Outputs(outputs)
+ , Byproducts(byproducts)
+ , Depends(depends)
+ , CommandLines(commandLines)
+ , Backtrace()
+ , Comment(comment ? comment : "")
+ , WorkingDirectory(workingDirectory ? workingDirectory : "")
+ , HaveComment(comment != CM_NULLPTR)
+ , EscapeAllowMakeVars(false)
+ , EscapeOldStyle(true)
+ , CommandExpandLists(false)
+{
+ if (mf) {
+ this->Backtrace = mf->GetBacktrace();
+ }
}
-//----------------------------------------------------------------------------
-cmCustomCommand::~cmCustomCommand()
-{
- delete this->Backtrace;
-}
-
-//----------------------------------------------------------------------------
const std::vector<std::string>& cmCustomCommand::GetOutputs() const
{
return this->Outputs;
}
-//----------------------------------------------------------------------------
-const char* cmCustomCommand::GetWorkingDirectory() const
+const std::vector<std::string>& cmCustomCommand::GetByproducts() const
{
- if(this->WorkingDirectory.size() == 0)
- {
- return 0;
- }
- return this->WorkingDirectory.c_str();
+ return this->Byproducts;
}
-//----------------------------------------------------------------------------
const std::vector<std::string>& cmCustomCommand::GetDepends() const
{
return this->Depends;
}
-//----------------------------------------------------------------------------
const cmCustomCommandLines& cmCustomCommand::GetCommandLines() const
{
return this->CommandLines;
}
-//----------------------------------------------------------------------------
const char* cmCustomCommand::GetComment() const
{
- const char* no_comment = 0;
- return this->HaveComment? this->Comment.c_str() : no_comment;
+ const char* no_comment = CM_NULLPTR;
+ return this->HaveComment ? this->Comment.c_str() : no_comment;
}
-//----------------------------------------------------------------------------
void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
{
- for(cmCustomCommandLines::const_iterator i=commandLines.begin();
- i != commandLines.end(); ++i)
- {
- this->CommandLines.push_back(*i);
- }
+ this->CommandLines.insert(this->CommandLines.end(), commandLines.begin(),
+ commandLines.end());
}
-//----------------------------------------------------------------------------
void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends)
{
- for(std::vector<std::string>::const_iterator i=depends.begin();
- i != depends.end(); ++i)
- {
- this->Depends.push_back(*i);
- }
+ this->Depends.insert(this->Depends.end(), depends.begin(), depends.end());
}
-//----------------------------------------------------------------------------
bool cmCustomCommand::GetEscapeOldStyle() const
{
return this->EscapeOldStyle;
}
-//----------------------------------------------------------------------------
void cmCustomCommand::SetEscapeOldStyle(bool b)
{
this->EscapeOldStyle = b;
}
-//----------------------------------------------------------------------------
bool cmCustomCommand::GetEscapeAllowMakeVars() const
{
return this->EscapeAllowMakeVars;
}
-//----------------------------------------------------------------------------
void cmCustomCommand::SetEscapeAllowMakeVars(bool b)
{
this->EscapeAllowMakeVars = b;
}
-//----------------------------------------------------------------------------
cmListFileBacktrace const& cmCustomCommand::GetBacktrace() const
{
- return *this->Backtrace;
+ return this->Backtrace;
}
-//----------------------------------------------------------------------------
cmCustomCommand::ImplicitDependsList const&
cmCustomCommand::GetImplicitDepends() const
{
return this->ImplicitDepends;
}
-//----------------------------------------------------------------------------
void cmCustomCommand::SetImplicitDepends(ImplicitDependsList const& l)
{
this->ImplicitDepends = l;
}
-//----------------------------------------------------------------------------
void cmCustomCommand::AppendImplicitDepends(ImplicitDependsList const& l)
{
- this->ImplicitDepends.insert(this->ImplicitDepends.end(),
- l.begin(), l.end());
+ this->ImplicitDepends.insert(this->ImplicitDepends.end(), l.begin(),
+ l.end());
+}
+
+bool cmCustomCommand::GetUsesTerminal() const
+{
+ return this->UsesTerminal;
+}
+
+void cmCustomCommand::SetUsesTerminal(bool b)
+{
+ this->UsesTerminal = b;
+}
+
+bool cmCustomCommand::GetCommandExpandLists() const
+{
+ return this->CommandExpandLists;
+}
+
+void cmCustomCommand::SetCommandExpandLists(bool b)
+{
+ this->CommandExpandLists = b;
+}
+
+const std::string& cmCustomCommand::GetDepfile() const
+{
+ return this->Depfile;
+}
+
+void cmCustomCommand::SetDepfile(const std::string& depfile)
+{
+ this->Depfile = depfile;
}
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index e20d2bf40..9e82f2505 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -1,20 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCustomCommand_h
#define cmCustomCommand_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCustomCommandLines.h"
+#include "cmListFileCache.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
class cmMakefile;
-class cmListFileBacktrace;
/** \class cmCustomCommand
* \brief A class to encapsulate a custom command
@@ -26,28 +24,30 @@ class cmCustomCommand
public:
/** Default and copy constructors for STL containers. */
cmCustomCommand();
- cmCustomCommand(const cmCustomCommand& r);
- cmCustomCommand& operator=(cmCustomCommand const& r);
/** Main constructor specifies all information for the command. */
- cmCustomCommand(cmMakefile* mf,
+ 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();
+ const char* comment, const char* workingDirectory);
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
- /** Get the working directory. */
- const char* GetWorkingDirectory() const;
+ /** Get the extra files produced by the command. */
+ const std::vector<std::string>& GetByproducts() const;
/** Get the vector that holds the list of dependencies. */
const std::vector<std::string>& GetDepends() const;
+ /** Get the working directory. */
+ std::string const& GetWorkingDirectory() const
+ {
+ return this->WorkingDirectory;
+ }
+
/** Get the list of command lines. */
const cmCustomCommandLines& GetCommandLines() const;
@@ -72,23 +72,42 @@ public:
/** Backtrace of the command that created this custom command. */
cmListFileBacktrace const& GetBacktrace() const;
- typedef std::pair<cmStdString, cmStdString> ImplicitDependsPair;
- class ImplicitDependsList: public std::vector<ImplicitDependsPair> {};
+ 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;
+ /** Set/Get whether this custom command should be given access to the
+ real console (if possible). */
+ bool GetUsesTerminal() const;
+ void SetUsesTerminal(bool b);
+
+ /** Set/Get whether lists in command lines should be expanded. */
+ bool GetCommandExpandLists() const;
+ void SetCommandExpandLists(bool b);
+
+ /** Set/Get the depfile (used by the Ninja generator) */
+ const std::string& GetDepfile() const;
+ void SetDepfile(const std::string& depfile);
+
private:
std::vector<std::string> Outputs;
+ std::vector<std::string> Byproducts;
std::vector<std::string> Depends;
cmCustomCommandLines CommandLines;
- bool HaveComment;
+ cmListFileBacktrace Backtrace;
+ ImplicitDependsList ImplicitDepends;
std::string Comment;
std::string WorkingDirectory;
+ std::string Depfile;
+ bool HaveComment;
bool EscapeAllowMakeVars;
bool EscapeOldStyle;
- cmListFileBacktrace* Backtrace;
- ImplicitDependsList ImplicitDepends;
+ bool UsesTerminal;
+ bool CommandExpandLists;
};
#endif
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index f2f77eea0..67213ecaa 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -1,73 +1,193 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCustomCommandGenerator.h"
-#include "cmMakefile.h"
#include "cmCustomCommand.h"
-#include "cmLocalGenerator.h"
+#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+
+#include "cmConfigure.h"
-//----------------------------------------------------------------------------
-cmCustomCommandGenerator::cmCustomCommandGenerator(
- cmCustomCommand const& cc, const char* config, cmMakefile* mf):
- CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()),
- OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()),
- GE(new cmGeneratorExpression(cc.GetBacktrace()))
+cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
+ const std::string& config,
+ cmLocalGenerator* lg)
+ : CC(cc)
+ , Config(config)
+ , LG(lg)
+ , OldStyle(cc.GetEscapeOldStyle())
+ , MakeVars(cc.GetEscapeAllowMakeVars())
+ , GE(new cmGeneratorExpression(cc.GetBacktrace()))
+ , DependsDone(false)
{
+ const cmCustomCommandLines& cmdlines = this->CC.GetCommandLines();
+ for (cmCustomCommandLines::const_iterator cmdline = cmdlines.begin();
+ cmdline != cmdlines.end(); ++cmdline) {
+ cmCustomCommandLine argv;
+ for (cmCustomCommandLine::const_iterator clarg = cmdline->begin();
+ clarg != cmdline->end(); ++clarg) {
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->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());
+ } else {
+ argv.push_back(parsed_arg);
+ }
+ }
+ this->CommandLines.push_back(argv);
+ }
}
-//----------------------------------------------------------------------------
cmCustomCommandGenerator::~cmCustomCommandGenerator()
{
delete this->GE;
}
-//----------------------------------------------------------------------------
unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
{
return static_cast<unsigned int>(this->CC.GetCommandLines().size());
}
-//----------------------------------------------------------------------------
-std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
+const char* cmCustomCommandGenerator::GetCrossCompilingEmulator(
+ unsigned int c) const
{
- std::string const& argv0 = this->CC.GetCommandLines()[c][0];
- cmTarget* target = this->Makefile->FindTargetToUse(argv0.c_str());
- if(target && target->GetType() == cmTarget::EXECUTABLE &&
- (target->IsImported() || !this->Makefile->IsOn("CMAKE_CROSSCOMPILING")))
- {
+ if (!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING")) {
+ return CM_NULLPTR;
+ }
+ 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");
+ }
+ return CM_NULLPTR;
+}
+
+const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
+{
+ std::string const& argv0 = this->CommandLines[c][0];
+ cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
+ if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
+ (target->IsImported() ||
+ target->GetProperty("CROSSCOMPILING_EMULATOR") ||
+ !this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) {
return target->GetLocation(this->Config);
+ }
+ return CM_NULLPTR;
+}
+
+std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
+{
+ if (const char* emulator = this->GetCrossCompilingEmulator(c)) {
+ return std::string(emulator);
+ }
+ if (const char* location = this->GetArgv0Location(c)) {
+ return std::string(location);
+ }
+
+ return this->CommandLines[c][0];
+}
+
+std::string escapeForShellOldStyle(const std::string& str)
+{
+ std::string result;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // if there are spaces
+ std::string temp = str;
+ if (temp.find(" ") != std::string::npos &&
+ temp.find("\"") == std::string::npos) {
+ result = "\"";
+ result += str;
+ result += "\"";
+ return result;
+ }
+ return str;
+#else
+ for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
+ if (*ch == ' ') {
+ result += '\\';
}
- return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config);
+ result += *ch;
+ }
+ return result;
+#endif
}
-//----------------------------------------------------------------------------
-void
-cmCustomCommandGenerator
-::AppendArguments(unsigned int c, std::string& cmd) const
+void cmCustomCommandGenerator::AppendArguments(unsigned int c,
+ std::string& cmd) const
{
- cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
- for(unsigned int j=1;j < commandLine.size(); ++j)
- {
- std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile,
- this->Config);
+ unsigned int offset = 1;
+ if (this->GetCrossCompilingEmulator(c) != CM_NULLPTR) {
+ 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) {
+ // GetCommand returned the emulator instead of the argv0 location,
+ // so transform the latter now.
+ arg = location;
+ } else {
+ arg = commandLine[j];
+ }
cmd += " ";
- if(this->OldStyle)
- {
- cmd += this->LG->EscapeForShellOldStyle(arg.c_str());
- }
- else
- {
- cmd += this->LG->EscapeForShell(arg.c_str(), this->MakeVars);
+ if (this->OldStyle) {
+ cmd += escapeForShellOldStyle(arg);
+ } else {
+ cmOutputConverter converter(this->LG->GetStateSnapshot());
+ cmd += converter.EscapeForShell(arg, this->MakeVars);
+ }
+ }
+}
+
+const char* cmCustomCommandGenerator::GetComment() const
+{
+ return this->CC.GetComment();
+}
+
+std::string cmCustomCommandGenerator::GetWorkingDirectory() const
+{
+ return this->CC.GetWorkingDirectory();
+}
+
+std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
+{
+ return this->CC.GetOutputs();
+}
+
+std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
+{
+ return this->CC.GetByproducts();
+}
+
+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 4e89f2731..0a2adb524 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -1,40 +1,46 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCustomCommandGenerator_h
#define cmCustomCommandGenerator_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmCustomCommandLines.h"
+
+#include <string>
+#include <vector>
class cmCustomCommand;
-class cmMakefile;
-class cmLocalGenerator;
class cmGeneratorExpression;
+class cmLocalGenerator;
class cmCustomCommandGenerator
{
cmCustomCommand const& CC;
- const char* Config;
- cmMakefile* Makefile;
+ std::string Config;
cmLocalGenerator* LG;
bool OldStyle;
bool MakeVars;
cmGeneratorExpression* GE;
+ mutable bool DependsDone;
+ mutable std::vector<std::string> Depends;
+ cmCustomCommandLines CommandLines;
+
+ const char* GetCrossCompilingEmulator(unsigned int c) const;
+ const char* GetArgv0Location(unsigned int c) const;
+
public:
- cmCustomCommandGenerator(cmCustomCommand const& cc, const char* config,
- cmMakefile* mf);
+ cmCustomCommandGenerator(cmCustomCommand const& cc,
+ const std::string& config, cmLocalGenerator* lg);
~cmCustomCommandGenerator();
+ cmCustomCommand const& GetCC() const { return this->CC; }
unsigned int GetNumberOfCommands() const;
std::string GetCommand(unsigned int c) const;
void AppendArguments(unsigned int c, std::string& cmd) const;
+ const char* GetComment() const;
+ std::string GetWorkingDirectory() const;
+ std::vector<std::string> const& GetOutputs() const;
+ std::vector<std::string> const& GetByproducts() const;
+ std::vector<std::string> const& GetDepends() const;
};
#endif
diff --git a/Source/cmCustomCommandLines.h b/Source/cmCustomCommandLines.h
new file mode 100644
index 000000000..36838f23f
--- /dev/null
+++ b/Source/cmCustomCommandLines.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 cmCustomCommandLines_h
+#define cmCustomCommandLines_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+/** 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;
+};
+
+#endif
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index 5816829e0..86a83dabe 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -1,137 +1,106 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDefinePropertyCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmDefinePropertyCommand.h"
-#include "cmake.h"
+#include "cmMakefile.h"
+#include "cmProperty.h"
+#include "cmState.h"
+
+class cmExecutionStatus;
-// cmDefinePropertiesCommand
-bool cmDefinePropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmDefinePropertyCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Get the scope in which to define the property.
cmProperty::ScopeType scope;
- if(args[0] == "GLOBAL")
- {
+ std::string const& scope_arg = args[0];
+
+ if (scope_arg == "GLOBAL") {
scope = cmProperty::GLOBAL;
- }
- else if(args[0] == "DIRECTORY")
- {
+ } else if (scope_arg == "DIRECTORY") {
scope = cmProperty::DIRECTORY;
- }
- else if(args[0] == "TARGET")
- {
+ } else if (scope_arg == "TARGET") {
scope = cmProperty::TARGET;
- }
- else if(args[0] == "SOURCE")
- {
+ } else if (scope_arg == "SOURCE") {
scope = cmProperty::SOURCE_FILE;
- }
- else if(args[0] == "TEST")
- {
+ } else if (scope_arg == "TEST") {
scope = cmProperty::TEST;
- }
- else if(args[0] == "VARIABLE")
- {
+ } else if (scope_arg == "VARIABLE") {
scope = cmProperty::VARIABLE;
- }
- else if (args[0] == "CACHED_VARIABLE")
- {
+ } else if (scope_arg == "CACHED_VARIABLE") {
scope = cmProperty::CACHED_VARIABLE;
- }
- else
- {
- cmOStringStream e;
- e << "given invalid scope " << args[0] << ". "
+ } 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Parse remaining arguments.
bool inherited = false;
- enum Doing { DoingNone, DoingProperty, DoingBrief, DoingFull };
+ enum Doing
+ {
+ DoingNone,
+ DoingProperty,
+ DoingBrief,
+ DoingFull
+ };
Doing doing = DoingNone;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "PROPERTY")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "PROPERTY") {
doing = DoingProperty;
- }
- else if(args[i] == "BRIEF_DOCS")
- {
+ } else if (args[i] == "BRIEF_DOCS") {
doing = DoingBrief;
- }
- else if(args[i] == "FULL_DOCS")
- {
+ } else if (args[i] == "FULL_DOCS") {
doing = DoingFull;
- }
- else if(args[i] == "INHERITED")
- {
+ } else if (args[i] == "INHERITED") {
doing = DoingNone;
inherited = true;
- }
- else if(doing == DoingProperty)
- {
+ } else if (doing == DoingProperty) {
doing = DoingNone;
this->PropertyName = args[i];
- }
- else if(doing == DoingBrief)
- {
+ } else if (doing == DoingBrief) {
this->BriefDocs += args[i];
- }
- else if(doing == DoingFull)
- {
+ } else if (doing == DoingFull) {
this->FullDocs += args[i];
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "given invalid argument \"" << args[i] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Make sure a property name was found.
- if(this->PropertyName.empty())
- {
+ if (this->PropertyName.empty()) {
this->SetError("not given a PROPERTY <name> argument.");
return false;
- }
+ }
// Make sure documentation was given.
- if(this->BriefDocs.empty())
- {
+ if (this->BriefDocs.empty()) {
this->SetError("not given a BRIEF_DOCS <brief-doc> argument.");
return false;
- }
- if(this->FullDocs.empty())
- {
+ }
+ if (this->FullDocs.empty()) {
this->SetError("not given a FULL_DOCS <full-doc> argument.");
return false;
- }
+ }
// Actually define the property.
- this->Makefile->GetCMakeInstance()->DefineProperty
- (this->PropertyName.c_str(), scope,
- this->BriefDocs.c_str(), this->FullDocs.c_str(), inherited);
+ this->Makefile->GetState()->DefineProperty(
+ this->PropertyName, scope, this->BriefDocs.c_str(), this->FullDocs.c_str(),
+ inherited);
return true;
}
-
diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h
index b5175d50b..bc120c564 100644
--- a/Source/cmDefinePropertyCommand.h
+++ b/Source/cmDefinePropertyCommand.h
@@ -1,93 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDefinesPropertyCommand_h
#define cmDefinesPropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmDefinePropertyCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmDefinePropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmDefinePropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "define_property";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Define and document custom properties.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " define_property(<GLOBAL | DIRECTORY | TARGET | SOURCE |\n"
- " TEST | VARIABLE | CACHED_VARIABLE>\n"
- " PROPERTY <name> [INHERITED]\n"
- " BRIEF_DOCS <brief-doc> [docs...]\n"
- " FULL_DOCS <full-doc> [docs...])\n"
- "Define one property in a scope for use with the "
- "set_property and get_property commands. "
- "This is primarily useful to associate documentation with property "
- "names that may be retrieved with the get_property command. "
- "The first argument determines the kind of scope in which the "
- "property should be used. It must be one of the following:\n"
- " GLOBAL = associated with the global namespace\n"
- " DIRECTORY = associated with one directory\n"
- " TARGET = associated with one target\n"
- " SOURCE = associated with one source file\n"
- " TEST = associated with a test named with add_test\n"
- " VARIABLE = documents a CMake language variable\n"
- " CACHED_VARIABLE = documents a CMake cache variable\n"
- "Note that unlike set_property and get_property no actual scope "
- "needs to be given; only the kind of scope is important.\n"
- "The required PROPERTY option is immediately followed by the name "
- "of the property being defined.\n"
- "If the INHERITED option then the get_property command will chain "
- "up to the next higher scope when the requested property is not "
- "set in the scope given to the command. "
- "DIRECTORY scope chains to GLOBAL. "
- "TARGET, SOURCE, and TEST chain to DIRECTORY.\n"
- "The BRIEF_DOCS and FULL_DOCS options are followed by strings to be "
- "associated with the property as its brief and full documentation. "
- "Corresponding options to the get_property command will retrieve the "
- "documentation.";
- }
-
- cmTypeMacro(cmDefinePropertyCommand, cmCommand);
private:
std::string PropertyName;
std::string BriefDocs;
std::string FullDocs;
};
-
-
#endif
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 9d2870058..7aa7641e1 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -1,178 +1,119 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDefinitions.h"
-//----------------------------------------------------------------------------
+#include "cmConfigure.h"
+#include <assert.h>
+#include <set>
+#include <utility>
+
cmDefinitions::Def cmDefinitions::NoDef;
-//----------------------------------------------------------------------------
-cmDefinitions::cmDefinitions(cmDefinitions* parent): Up(parent)
+cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
+ StackIter begin,
+ 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;
+ }
+ StackIter it = begin;
+ ++it;
+ if (it == end) {
+ return cmDefinitions::NoDef;
+ }
+ Def const& def = cmDefinitions::GetInternal(key, it, end, raise);
+ if (!raise) {
+ return def;
+ }
+ return begin->Map.insert(MapType::value_type(key, def)).first->second;
}
-//----------------------------------------------------------------------------
-void cmDefinitions::Reset(cmDefinitions* parent)
+const char* cmDefinitions::Get(const std::string& key, StackIter begin,
+ StackIter end)
{
- this->Up = parent;
- this->Map.clear();
+ Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
+ return def.Exists ? def.c_str() : CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-cmDefinitions::Def const&
-cmDefinitions::GetInternal(const char* key)
+void cmDefinitions::Raise(const std::string& key, StackIter begin,
+ StackIter end)
{
- MapType::const_iterator i = this->Map.find(key);
- if(i != this->Map.end())
- {
- return i->second;
- }
- else if(cmDefinitions* up = this->Up)
- {
- // Query the parent scope and store the result locally.
- Def def = up->GetInternal(key);
- return this->Map.insert(MapType::value_type(key, def)).first->second;
- }
- return this->NoDef;
+ cmDefinitions::GetInternal(key, begin, end, true);
}
-//----------------------------------------------------------------------------
-cmDefinitions::Def const&
-cmDefinitions::SetInternal(const char* key, Def const& def)
+bool cmDefinitions::HasKey(const std::string& key, StackIter begin,
+ StackIter end)
{
- if(this->Up || def.Exists)
- {
- // In lower scopes we store keys, defined or not.
- MapType::iterator i = this->Map.find(key);
- if(i == this->Map.end())
- {
- i = this->Map.insert(MapType::value_type(key, def)).first;
- }
- else
- {
- i->second = def;
- }
- return i->second;
+ for (StackIter it = begin; it != end; ++it) {
+ MapType::const_iterator i = it->Map.find(key);
+ if (i != it->Map.end()) {
+ return true;
}
- else
- {
- // In the top-most scope we need not store undefined keys.
- this->Map.erase(key);
- return this->NoDef;
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmDefinitions::Get(const char* key)
-{
- Def const& def = this->GetInternal(key);
- return def.Exists? def.c_str() : 0;
+ }
+ return false;
}
-//----------------------------------------------------------------------------
-const char* cmDefinitions::Set(const char* key, const char* value)
+void cmDefinitions::Set(const std::string& key, const char* value)
{
- Def const& def = this->SetInternal(key, Def(value));
- return def.Exists? def.c_str() : 0;
+ Def def(value);
+ this->Map[key] = def;
}
-//----------------------------------------------------------------------------
-std::set<cmStdString> cmDefinitions::LocalKeys() const
+std::vector<std::string> cmDefinitions::UnusedKeys() const
{
- std::set<cmStdString> keys;
+ 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.Exists)
- {
- keys.insert(mi->first);
- }
+ 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::Closure() const
-{
- return cmDefinitions(ClosureTag(), this);
-}
-
-//----------------------------------------------------------------------------
-cmDefinitions::cmDefinitions(ClosureTag const&, cmDefinitions const* root):
- Up(0)
-{
- std::set<cmStdString> undefined;
- this->ClosureImpl(undefined, root);
-}
-
-//----------------------------------------------------------------------------
-void cmDefinitions::ClosureImpl(std::set<cmStdString>& undefined,
- cmDefinitions const* defs)
+cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end)
{
- // Consider local definitions.
- for(MapType::const_iterator mi = defs->Map.begin();
- mi != defs->Map.end(); ++mi)
- {
- // Use this key if it is not already set or unset.
- if(this->Map.find(mi->first) == this->Map.end() &&
- undefined.find(mi->first) == undefined.end())
- {
- if(mi->second.Exists)
- {
- this->Map.insert(*mi);
- }
- else
- {
- undefined.insert(mi->first);
+ cmDefinitions closure;
+ std::set<std::string> undefined;
+ for (StackIter it = begin; it != end; ++it) {
+ // Consider local definitions.
+ for (MapType::const_iterator mi = it->Map.begin(); mi != it->Map.end();
+ ++mi) {
+ // 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);
+ } else {
+ undefined.insert(mi->first);
}
}
}
-
- // Traverse parents.
- if(cmDefinitions const* up = defs->Up)
- {
- this->ClosureImpl(undefined, up);
- }
-}
-
-//----------------------------------------------------------------------------
-std::set<cmStdString> cmDefinitions::ClosureKeys() const
-{
- std::set<cmStdString> defined;
- std::set<cmStdString> undefined;
- this->ClosureKeys(defined, undefined);
- return defined;
+ }
+ return closure;
}
-//----------------------------------------------------------------------------
-void cmDefinitions::ClosureKeys(std::set<cmStdString>& defined,
- std::set<cmStdString>& undefined) const
+std::vector<std::string> cmDefinitions::ClosureKeys(StackIter begin,
+ StackIter end)
{
- // Consider local definitions.
- for(MapType::const_iterator mi = this->Map.begin();
- mi != this->Map.end(); ++mi)
- {
- // Use this key if it is not already set or unset.
- if(defined.find(mi->first) == defined.end() &&
- undefined.find(mi->first) == undefined.end())
- {
- std::set<cmStdString>& m = mi->second.Exists? defined : undefined;
- m.insert(mi->first);
+ std::set<std::string> bound;
+ std::vector<std::string> defined;
+
+ 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) {
+ // 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);
}
}
+ }
- // Traverse parents.
- if(cmDefinitions const* up = this->Up)
- {
- up->ClosureKeys(defined, undefined);
- }
+ return defined;
}
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index 4834d8443..ddb89188c 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -1,18 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDefinitions_h
#define cmDefinitions_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmLinkedTree.h"
+#include "cm_unordered_map.hxx"
/** \class cmDefinitions
* \brief Store a scope of variable definitions for CMake language.
@@ -23,64 +20,61 @@
*/
class cmDefinitions
{
-public:
- /** Construct with the given parent scope. */
- cmDefinitions(cmDefinitions* parent = 0);
+ typedef cmLinkedTree<cmDefinitions>::iterator StackIter;
- /** Reset object as if newly constructed. */
- void Reset(cmDefinitions* parent = 0);
+public:
+ static const char* Get(const std::string& key, StackIter begin,
+ StackIter end);
- /** Returns the parent scope, if any. */
- cmDefinitions* GetParent() const { return this->Up; }
+ static void Raise(const std::string& key, StackIter begin, StackIter end);
- /** Get the value associated with a key; null if none.
- Store the result locally if it came from a parent. */
- const char* Get(const char* key);
+ static bool HasKey(const std::string& key, StackIter begin, StackIter end);
/** Set (or unset if null) a value associated with a key. */
- const char* Set(const char* key, const char* value);
+ void Set(const std::string& key, const char* value);
- /** Get the set of all local keys. */
- std::set<cmStdString> LocalKeys() const;
+ std::vector<std::string> UnusedKeys() const;
- /** Compute the closure of all defined keys with values.
- This flattens the scope. The result has no parent. */
- cmDefinitions Closure() const;
+ static std::vector<std::string> ClosureKeys(StackIter begin, StackIter end);
- /** Compute the set of all defined keys. */
- std::set<cmStdString> ClosureKeys() const;
+ static cmDefinitions MakeClosure(StackIter begin, StackIter end);
private:
// String with existence boolean.
- struct Def: public cmStdString
+ struct Def : public std::string
{
- Def(): cmStdString(), Exists(false) {}
- Def(const char* v): cmStdString(v?v:""), Exists(v?true:false) {}
- Def(Def const& d): cmStdString(d), Exists(d.Exists) {}
+ 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)
+ {
+ }
bool Exists;
+ bool Used;
};
static Def NoDef;
- // Parent scope, if any.
- cmDefinitions* Up;
-
- // Local definitions, set or unset.
- typedef std::map<cmStdString, Def> MapType;
+ typedef CM_UNORDERED_MAP<std::string, Def> MapType;
MapType Map;
- // Internal query and update methods.
- Def const& GetInternal(const char* key);
- Def const& SetInternal(const char* key, Def const& def);
-
- // Implementation of Closure() method.
- struct ClosureTag {};
- cmDefinitions(ClosureTag const&, cmDefinitions const* root);
- void ClosureImpl(std::set<cmStdString>& undefined,
- cmDefinitions const* defs);
-
- // Implementation of ClosureKeys() method.
- void ClosureKeys(std::set<cmStdString>& defined,
- std::set<cmStdString>& undefined) const;
+ static Def const& GetInternal(const std::string& key, StackIter begin,
+ StackIter end, bool raise);
};
#endif
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 74a0ccb21..c898d12ba 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -1,181 +1,144 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDepends.h"
+#include "cmFileTimeComparison.h"
+#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
-#include "cmFileTimeComparison.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(0),
- TargetDirectory(targetDir),
- MaxPath(16384),
- Dependee(new char[MaxPath]),
- Depender(new char[MaxPath])
+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()
{
- delete [] this->Dependee;
- delete [] this->Depender;
+ delete[] this->Dependee;
+ delete[] this->Depender;
}
-//----------------------------------------------------------------------------
-bool cmDepends::Write(std::ostream &makeDepends,
- std::ostream &internalDepends)
+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.c_str());
+ 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();)
- {
+ 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::string obj = *si++;
-
- // Make sure the object file is relative to the top of the build tree.
- obj = this->LocalGenerator->Convert(obj.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- dependencies[obj].insert(src);
+ if (si == pairs.end()) {
+ break;
}
- for(std::map<std::string, std::set<std::string> >::const_iterator
- it = dependencies.begin(); it != dependencies.end(); ++it)
- {
+ 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) {
// Write the dependencies for this pair.
- if(!this->WriteDependencies(it->second, it->first,
- makeDepends, internalDepends))
- {
+ if (!this->WriteDependencies(it->second, it->first, makeDepends,
+ internalDepends)) {
return false;
- }
}
+ }
return this->Finalize(makeDepends, internalDepends);
}
-//----------------------------------------------------------------------------
-bool cmDepends::Finalize(std::ostream&,
- std::ostream&)
+bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/)
{
return true;
}
-//----------------------------------------------------------------------------
-bool cmDepends::Check(const char *makeFile, const char *internalFile,
+bool cmDepends::Check(const char* makeFile, const char* internalFile,
std::map<std::string, DependencyVector>& validDeps)
{
// Dependency checks must be done in proper working directory.
- std::string oldcwd = ".";
- if(this->CompileDirectory != ".")
- {
- // Get the CWD but do not call CollapseFullPath because
- // we only need it to cd back, and the form does not matter
- oldcwd = cmSystemTools::GetCurrentWorkingDirectory(false);
- cmSystemTools::ChangeDirectory(this->CompileDirectory.c_str());
- }
+ cmWorkingDirectory workdir(this->CompileDirectory);
// Check whether dependencies must be regenerated.
bool okay = true;
- std::ifstream fin(internalFile);
- if(!(fin && this->CheckDependencies(fin, internalFile, validDeps)))
- {
+ cmsys::ifstream fin(internalFile);
+ if (!(fin && this->CheckDependencies(fin, internalFile, validDeps))) {
// Clear all dependencies so they will be regenerated.
this->Clear(makeFile);
cmSystemTools::RemoveFile(internalFile);
okay = false;
- }
-
- // Restore working directory.
- if(oldcwd != ".")
- {
- cmSystemTools::ChangeDirectory(oldcwd.c_str());
- }
+ }
return okay;
}
-//----------------------------------------------------------------------------
-void cmDepends::Clear(const char *file)
+void cmDepends::Clear(const char* file)
{
// Print verbose output.
- if(this->Verbose)
- {
- cmOStringStream msg;
+ if (this->Verbose) {
+ std::ostringstream msg;
msg << "Clearing dependencies in \"" << file << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
- }
+ }
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(file);
- depFileStream
- << "# Empty dependencies file\n"
- << "# This may be replaced when dependencies are built." << std::endl;
+ depFileStream << "# Empty dependencies file\n"
+ << "# This may be replaced when dependencies are built."
+ << std::endl;
}
-//----------------------------------------------------------------------------
-bool cmDepends::WriteDependencies(
- const std::set<std::string>&, const std::string&,
- std::ostream&, std::ostream&)
+bool cmDepends::WriteDependencies(const std::set<std::string>& /*unused*/,
+ const std::string& /*unused*/,
+ std::ostream& /*unused*/,
+ std::ostream& /*unused*/)
{
// This should be implemented by the subclass.
return false;
}
-//----------------------------------------------------------------------------
-bool cmDepends::CheckDependencies(std::istream& internalDepends,
- const char* internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps)
+bool cmDepends::CheckDependencies(
+ std::istream& internalDepends, const char* internalDependsFileName,
+ std::map<std::string, DependencyVector>& validDeps)
{
// 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 = 0;
+ DependencyVector* currentDependencies = CM_NULLPTR;
- while(internalDepends.getline(this->Dependee, this->MaxPath))
- {
- if ( this->Dependee[0] == 0 || this->Dependee[0] == '#' ||
- this->Dependee[0] == '\r' )
- {
+ while (internalDepends.getline(this->Dependee, this->MaxPath)) {
+ if (this->Dependee[0] == 0 || this->Dependee[0] == '#' ||
+ this->Dependee[0] == '\r') {
continue;
- }
- size_t len = internalDepends.gcount()-1;
- if ( this->Dependee[len-1] == '\r' )
- {
- len --;
+ }
+ size_t len = internalDepends.gcount() - 1;
+ if (this->Dependee[len - 1] == '\r') {
+ len--;
this->Dependee[len] = 0;
- }
- if ( this->Dependee[0] != ' ' )
- {
- memcpy(this->Depender, this->Dependee, len+1);
+ }
+ 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,
@@ -187,7 +150,7 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends,
// access.
currentDependencies = &validDeps[this->Depender];
continue;
- }
+ }
/*
// Parse the dependency line.
if(!this->ParseDependency(line.c_str()))
@@ -202,123 +165,103 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends,
// * 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* dependee = this->Dependee + 1;
const char* depender = this->Depender;
- if (currentDependencies != 0)
- {
+ if (currentDependencies != CM_NULLPTR) {
currentDependencies->push_back(dependee);
- }
+ }
- if(!cmSystemTools::FileExists(dependee))
- {
+ if (!cmSystemTools::FileExists(dependee)) {
// The dependee does not exist.
regenerate = true;
// Print verbose output.
- if(this->Verbose)
- {
- cmOStringStream msg;
- msg << "Dependee \"" << dependee
- << "\" does not exist for depender \""
+ if (this->Verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dependee << "\" does not exist for depender \""
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
- }
}
- else
- {
- if(dependerExists)
- {
+ } else {
+ if (dependerExists) {
// The dependee and depender both exist. Compare file times.
int result = 0;
- if((!this->FileComparison->FileTimeCompare(depender, dependee,
- &result) || 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)
- {
- cmOStringStream msg;
- msg << "Dependee \"" << dependee
- << "\" is newer than depender \""
+ if (this->Verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dependee << "\" is newer than depender \""
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
- }
}
}
- else
- {
+ } 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))
- {
+ 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)
- {
- cmOStringStream msg;
+ if (this->Verbose) {
+ std::ostringstream msg;
msg << "Dependee \"" << dependee
<< "\" is newer than depends file \""
<< internalDependsFileName << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
- }
}
}
}
- if(regenerate)
- {
+ }
+ if (regenerate) {
// Dependencies must be regenerated.
okay = false;
// Remove the information of this depender from the map, it needs
// to be rescanned
- if (currentDependencies != 0)
- {
+ if (currentDependencies != CM_NULLPTR) {
validDeps.erase(this->Depender);
- currentDependencies = 0;
- }
+ currentDependencies = CM_NULLPTR;
+ }
// Remove the depender to be sure it is rebuilt.
- if (dependerExists)
- {
+ if (dependerExists) {
cmSystemTools::RemoveFile(depender);
dependerExists = false;
- }
}
}
+ }
return okay;
}
-//----------------------------------------------------------------------------
-void cmDepends::SetIncludePathFromLanguage(const char* lang)
+void cmDepends::SetIncludePathFromLanguage(const std::string& lang)
{
// Look for the new per "TARGET_" variant first:
- const char * includePath = 0;
+ const char* includePath = CM_NULLPTR;
std::string includePathVar = "CMAKE_";
includePathVar += lang;
includePathVar += "_TARGET_INCLUDE_PATH";
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- includePath = mf->GetDefinition(includePathVar.c_str());
- if(includePath)
- {
+ includePath = mf->GetDefinition(includePathVar);
+ if (includePath) {
cmSystemTools::ExpandListArgument(includePath, this->IncludePath);
- }
- else
- {
+ } else {
// Fallback to the old directory level variable if no per-target var:
includePathVar = "CMAKE_";
includePathVar += lang;
includePathVar += "_INCLUDE_PATH";
- includePath = mf->GetDefinition(includePathVar.c_str());
- if(includePath)
- {
+ includePath = mf->GetDefinition(includePathVar);
+ if (includePath) {
cmSystemTools::ExpandListArgument(includePath, this->IncludePath);
- }
}
+ }
}
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index d787eddc6..b33feb902 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -1,18 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDepends_h
#define cmDepends_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <stddef.h>
+#include <string>
+#include <vector>
class cmFileTimeComparison;
class cmLocalGenerator;
@@ -26,13 +24,15 @@ class cmLocalGenerator;
*/
class cmDepends
{
+ CM_DISABLE_COPY(cmDepends)
+
public:
/** Instances need to know the build directory name and the relative
path from the build directory to the target file. */
- cmDepends(cmLocalGenerator* lg=0, const char* targetDir="");
+ cmDepends(cmLocalGenerator* lg = CM_NULLPTR, const char* targetDir = "");
/** at what level will the compile be done from */
- void SetCompileDirectory(const char *dir) {this->CompileDirectory = dir;};
+ void SetCompileDirectory(const char* dir) { this->CompileDirectory = dir; }
/** Set the local generator for the directory in which we are
scanning dependencies. This is not a full local generator; it
@@ -41,7 +41,7 @@ public:
void SetLocalGenerator(cmLocalGenerator* lg) { this->LocalGenerator = lg; }
/** Set the specific language to be scanned. */
- void SetLanguage(const char* lang) { this->Language = lang; }
+ void SetLanguage(const std::string& lang) { this->Language = lang; }
/** Set the target build directory. */
void SetTargetDirectory(const char* dir) { this->TargetDirectory = dir; }
@@ -53,27 +53,30 @@ public:
virtual ~cmDepends();
/** Write dependencies for the target file. */
- bool Write(std::ostream &makeDepends, std::ostream &internalDepends);
+ bool Write(std::ostream& makeDepends, std::ostream& internalDepends);
- class DependencyVector: public std::vector<std::string> {};
+ 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,
+ bool Check(const char* makeFile, const char* internalFile,
std::map<std::string, DependencyVector>& validDeps);
/** Clear dependencies for the target file so they will be regenerated. */
- void Clear(const char *file);
+ void Clear(const char* file);
/** Set the file comparison object */
- void SetFileComparison(cmFileTimeComparison* fc) {
- this->FileComparison = fc; }
+ void SetFileComparison(cmFileTimeComparison* fc)
+ {
+ this->FileComparison = fc;
+ }
protected:
-
// Write dependencies for the target file to the given stream.
// Return true for success and false for failure.
virtual bool WriteDependencies(const std::set<std::string>& sources,
@@ -84,9 +87,9 @@ 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 char* internalDependsFileName,
+ std::map<std::string, DependencyVector>& validDeps);
// Finalize the dependency information for the target.
virtual bool Finalize(std::ostream& makeDepends,
@@ -114,11 +117,7 @@ protected:
// The include file search path.
std::vector<std::string> IncludePath;
- void SetIncludePathFromLanguage(const char* lang);
-
-private:
- cmDepends(cmDepends const&); // Purposely not implemented.
- void operator=(cmDepends const&); // Purposely not implemented.
+ void SetIncludePathFromLanguage(const std::string& lang);
};
#endif
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index a252a1ab7..2c464cc9c 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -1,45 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include <ctype.h> // isspace
-
-
-#define INCLUDE_REGEX_LINE \
- "^[ \t]*#[ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])"
+#define INCLUDE_REGEX_LINE \
+ "^[ \t]*[#%][ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])"
#define INCLUDE_REGEX_LINE_MARKER "#IncludeRegexLine: "
#define INCLUDE_REGEX_SCAN_MARKER "#IncludeRegexScan: "
#define INCLUDE_REGEX_COMPLAIN_MARKER "#IncludeRegexComplain: "
#define INCLUDE_REGEX_TRANSFORM_MARKER "#IncludeRegexTransform: "
-//----------------------------------------------------------------------------
cmDependsC::cmDependsC()
-: ValidDeps(0)
+ : ValidDeps(CM_NULLPTR)
{
}
-//----------------------------------------------------------------------------
-cmDependsC::cmDependsC(cmLocalGenerator* lg,
- const char* targetDir,
- const char* lang,
- const std::map<std::string, DependencyVector>* validDeps)
-: cmDepends(lg, targetDir)
-, ValidDeps(validDeps)
+cmDependsC::cmDependsC(
+ cmLocalGenerator* lg, const char* targetDir, const std::string& lang,
+ const std::map<std::string, DependencyVector>* validDeps)
+ : cmDepends(lg, targetDir)
+ , ValidDeps(validDeps)
{
cmMakefile* mf = lg->GetMakefile();
@@ -50,19 +39,17 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg,
std::string scanRegex = "^.*$";
std::string complainRegex = "^$";
{
- std::string scanRegexVar = "CMAKE_";
- scanRegexVar += lang;
- scanRegexVar += "_INCLUDE_REGEX_SCAN";
- if(const char* sr = mf->GetDefinition(scanRegexVar.c_str()))
- {
- scanRegex = sr;
+ std::string scanRegexVar = "CMAKE_";
+ scanRegexVar += lang;
+ scanRegexVar += "_INCLUDE_REGEX_SCAN";
+ if (const char* sr = mf->GetDefinition(scanRegexVar)) {
+ scanRegex = sr;
}
- std::string complainRegexVar = "CMAKE_";
- complainRegexVar += lang;
- complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
- if(const char* cr = mf->GetDefinition(complainRegexVar.c_str()))
- {
- complainRegex = cr;
+ std::string complainRegexVar = "CMAKE_";
+ complainRegexVar += lang;
+ complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
+ if (const char* cr = mf->GetDefinition(complainRegexVar)) {
+ complainRegex = cr;
}
}
@@ -85,373 +72,314 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg,
this->ReadCacheFile();
}
-//----------------------------------------------------------------------------
cmDependsC::~cmDependsC()
{
this->WriteCacheFile();
-
- for (std::map<cmStdString, cmIncludeLines*>::iterator it=
- this->FileCache.begin(); it!=this->FileCache.end(); ++it)
- {
- delete it->second;
- }
+ cmDeleteAll(this->FileCache);
}
-//----------------------------------------------------------------------------
bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
const std::string& obj,
std::ostream& makeDepends,
std::ostream& internalDepends)
{
// Make sure this is a scanning instance.
- if(sources.empty() || sources.begin()->empty())
- {
+ if (sources.empty() || sources.begin()->empty()) {
cmSystemTools::Error("Cannot scan dependencies without a source file.");
return false;
- }
- if(obj.empty())
- {
+ }
+ if (obj.empty()) {
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false;
- }
+ }
- std::set<cmStdString> dependencies;
+ std::set<std::string> dependencies;
bool haveDeps = false;
- if (this->ValidDeps != 0)
- {
+ if (this->ValidDeps != CM_NULLPTR) {
std::map<std::string, DependencyVector>::const_iterator tmpIt =
- this->ValidDeps->find(obj);
- if (tmpIt!= this->ValidDeps->end())
- {
- for(DependencyVector::const_iterator i=tmpIt->second.begin();
- i != tmpIt->second.end(); ++i)
- {
- dependencies.insert(*i);
- }
+ this->ValidDeps->find(obj);
+ if (tmpIt != this->ValidDeps->end()) {
+ dependencies.insert(tmpIt->second.begin(), tmpIt->second.end());
haveDeps = true;
- }
}
+ }
- if (!haveDeps)
- {
+ if (!haveDeps) {
// Walk the dependency graph starting with the source file.
int srcFiles = (int)sources.size();
this->Encountered.clear();
- for(std::set<std::string>::const_iterator srcIt = sources.begin();
- srcIt != sources.end(); ++srcIt)
- {
+ for (std::set<std::string>::const_iterator srcIt = sources.begin();
+ srcIt != sources.end(); ++srcIt) {
UnscannedEntry root;
root.FileName = *srcIt;
this->Unscanned.push(root);
this->Encountered.insert(*srcIt);
- }
+ }
- std::set<cmStdString> scanned;
+ 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);
+ tempPathStr.reserve(4 * 1024);
- while(!this->Unscanned.empty())
- {
+ while (!this->Unscanned.empty()) {
// Get the next file to scan.
UnscannedEntry current = this->Unscanned.front();
this->Unscanned.pop();
// 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.c_str())) {
+ if (cmSystemTools::FileExists(current.FileName.c_str(), true)) {
fullName = current.FileName;
- }
}
- else if(!current.QuotedLocation.empty() &&
- cmSystemTools::FileExists(current.QuotedLocation.c_str(), true))
- {
+ } else if (!current.QuotedLocation.empty() &&
+ cmSystemTools::FileExists(current.QuotedLocation.c_str(),
+ 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<cmStdString, cmStdString>::iterator
- 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)
- {
- // 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);
-
- // Look for the file in this location.
- if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
- {
- fullName = tempPathStr;
- HeaderLocationCache[current.FileName]=fullName;
- break;
+ } else {
+ std::map<std::string, std::string>::iterator 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) {
+ // 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);
+
+ // Look for the file in this location.
+ if (cmSystemTools::FileExists(tempPathStr.c_str(), true)) {
+ fullName = tempPathStr;
+ HeaderLocationCache[current.FileName] = fullName;
+ break;
}
}
}
+ }
// 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(), "\".");
+ if (fullName.empty() &&
+ this->IncludeRegexComplain.find(current.FileName.c_str())) {
+ cmSystemTools::Error("Cannot find file \"", current.FileName.c_str(),
+ "\".");
return false;
- }
+ }
// Scan the file if it was found and has not been scanned already.
- if(!fullName.empty() && (scanned.find(fullName) == scanned.end()))
- {
+ if (!fullName.empty() && (scanned.find(fullName) == scanned.end())) {
// Record scanned files.
scanned.insert(fullName);
// Check whether this file is already in the cache
- std::map<cmStdString, cmIncludeLines*>::iterator fileIt=
+ std::map<std::string, cmIncludeLines*>::iterator fileIt =
this->FileCache.find(fullName);
- if (fileIt!=this->FileCache.end())
- {
- fileIt->second->Used=true;
+ if (fileIt != this->FileCache.end()) {
+ fileIt->second->Used = true;
dependencies.insert(fullName);
- for (std::vector<UnscannedEntry>::const_iterator incIt=
- fileIt->second->UnscannedEntries.begin();
- incIt!=fileIt->second->UnscannedEntries.end(); ++incIt)
- {
+ for (std::vector<UnscannedEntry>::const_iterator incIt =
+ fileIt->second->UnscannedEntries.begin();
+ incIt != fileIt->second->UnscannedEntries.end(); ++incIt) {
if (this->Encountered.find(incIt->FileName) ==
- this->Encountered.end())
- {
+ this->Encountered.end()) {
this->Encountered.insert(incIt->FileName);
this->Unscanned.push(*incIt);
- }
}
}
- else
- {
+ } else {
// Try to scan the file. Just leave it out if we cannot find
// it.
- std::ifstream fin(fullName.c_str());
- if(fin)
- {
- // Add this file as a dependency.
- dependencies.insert(fullName);
-
- // 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);
+ cmsys::ifstream fin(fullName.c_str());
+ if (fin) {
+ cmsys::FStream::BOM bom = cmsys::FStream::ReadBOM(fin);
+ if (bom == cmsys::FStream::BOM_None ||
+ bom == cmsys::FStream::BOM_UTF8) {
+ // Add this file as a dependency.
+ dependencies.insert(fullName);
+
+ // 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);
+ } else {
+ // Skip file with encoding we do not implement.
}
}
}
+ }
srcFiles--;
- }
}
+ }
// Write the dependencies to the output stream. Makefile rules
// 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.
- internalDepends << obj << std::endl;
- for(std::set<cmStdString>::const_iterator i=dependencies.begin();
- i != dependencies.end(); ++i)
- {
- makeDepends << obj << ": " <<
- this->LocalGenerator->Convert(i->c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
- << std::endl;
- internalDepends << " " << i->c_str() << std::endl;
- }
+ 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());
+ 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;
+ }
makeDepends << std::endl;
return true;
}
-//----------------------------------------------------------------------------
void cmDependsC::ReadCacheFile()
{
- if(this->CacheFileName.size() == 0)
- {
+ if (this->CacheFileName.empty()) {
return;
- }
- std::ifstream fin(this->CacheFileName.c_str());
- if(!fin)
- {
+ }
+ cmsys::ifstream fin(this->CacheFileName.c_str());
+ if (!fin) {
return;
- }
+ }
std::string line;
- cmIncludeLines* cacheEntry=0;
- bool haveFileName=false;
+ cmIncludeLines* cacheEntry = CM_NULLPTR;
+ bool haveFileName = false;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- if (line.empty())
- {
- cacheEntry=0;
- haveFileName=false;
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (line.empty()) {
+ cacheEntry = CM_NULLPTR;
+ haveFileName = false;
continue;
- }
- //the first line after an empty line is the name of the parsed file
- if (haveFileName==false)
- {
- haveFileName=true;
- int newer=0;
+ }
+ // 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);
+ bool res = comp.FileTimeCompare(this->CacheFileName.c_str(),
+ line.c_str(), &newer);
- if ((res==true) && (newer==1)) //cache is newer than the parsed file
- {
- cacheEntry=new cmIncludeLines;
- this->FileCache[line]=cacheEntry;
- }
+ if (res && newer == 1) // cache is newer than the parsed file
+ {
+ cacheEntry = new cmIncludeLines;
+ this->FileCache[line] = cacheEntry;
+ }
// file doesn't exist, check that the regular expressions
// haven't changed
- else if (res==false)
- {
- if (line.find(INCLUDE_REGEX_LINE_MARKER) == 0)
- {
- if (line != this->IncludeRegexLineString)
- {
+ else if (!res) {
+ if (line.find(INCLUDE_REGEX_LINE_MARKER) == 0) {
+ if (line != this->IncludeRegexLineString) {
return;
- }
}
- else if (line.find(INCLUDE_REGEX_SCAN_MARKER) == 0)
- {
- if (line != this->IncludeRegexScanString)
- {
+ } else if (line.find(INCLUDE_REGEX_SCAN_MARKER) == 0) {
+ if (line != this->IncludeRegexScanString) {
return;
- }
}
- else if (line.find(INCLUDE_REGEX_COMPLAIN_MARKER) == 0)
- {
- if (line != this->IncludeRegexComplainString)
- {
+ } else if (line.find(INCLUDE_REGEX_COMPLAIN_MARKER) == 0) {
+ if (line != this->IncludeRegexComplainString) {
return;
- }
}
- else if (line.find(INCLUDE_REGEX_TRANSFORM_MARKER) == 0)
- {
- if (line != this->IncludeRegexTransformString)
- {
+ } else if (line.find(INCLUDE_REGEX_TRANSFORM_MARKER) == 0) {
+ if (line != this->IncludeRegexTransformString) {
return;
- }
}
}
}
- else if (cacheEntry!=0)
- {
+ } else if (cacheEntry != CM_NULLPTR) {
UnscannedEntry entry;
entry.FileName = line;
- if (cmSystemTools::GetLineFromStream(fin, line))
- {
- if (line!="-")
- {
- entry.QuotedLocation=line;
- }
- cacheEntry->UnscannedEntries.push_back(entry);
+ if (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (line != "-") {
+ entry.QuotedLocation = line;
}
+ cacheEntry->UnscannedEntries.push_back(entry);
}
}
+ }
}
-//----------------------------------------------------------------------------
void cmDependsC::WriteCacheFile() const
{
- if(this->CacheFileName.size() == 0)
- {
+ if (this->CacheFileName.empty()) {
return;
- }
- std::ofstream cacheOut(this->CacheFileName.c_str());
- if(!cacheOut)
- {
+ }
+ cmsys::ofstream cacheOut(this->CacheFileName.c_str());
+ if (!cacheOut) {
return;
- }
+ }
cacheOut << this->IncludeRegexLineString << "\n\n";
cacheOut << this->IncludeRegexScanString << "\n\n";
cacheOut << this->IncludeRegexComplainString << "\n\n";
cacheOut << this->IncludeRegexTransformString << "\n\n";
- for (std::map<cmStdString, cmIncludeLines*>::const_iterator fileIt=
+ for (std::map<std::string, cmIncludeLines*>::const_iterator fileIt =
this->FileCache.begin();
- fileIt!=this->FileCache.end(); ++fileIt)
- {
- if (fileIt->second->Used)
- {
- cacheOut<<fileIt->first.c_str()<<std::endl;
-
- for (std::vector<UnscannedEntry>::const_iterator
- incIt=fileIt->second->UnscannedEntries.begin();
- incIt!=fileIt->second->UnscannedEntries.end(); ++incIt)
- {
- cacheOut<<incIt->FileName.c_str()<<std::endl;
- if (incIt->QuotedLocation.empty())
- {
- cacheOut<<"-"<<std::endl;
- }
- else
- {
- cacheOut<<incIt->QuotedLocation.c_str()<<std::endl;
- }
+ 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()) {
+ cacheOut << "-" << std::endl;
+ } else {
+ cacheOut << incIt->QuotedLocation << std::endl;
}
- cacheOut<<std::endl;
}
- }
+ cacheOut << std::endl;
+ }
+ }
}
-//----------------------------------------------------------------------------
void cmDependsC::Scan(std::istream& is, const char* directory,
- const cmStdString& fullName)
+ const std::string& fullName)
{
- cmIncludeLines* newCacheEntry=new cmIncludeLines;
- newCacheEntry->Used=true;
- this->FileCache[fullName]=newCacheEntry;
+ cmIncludeLines* newCacheEntry = new cmIncludeLines;
+ newCacheEntry->Used = true;
+ this->FileCache[fullName] = newCacheEntry;
// Read one line at a time.
std::string line;
- while(cmSystemTools::GetLineFromStream(is, line))
- {
+ while (cmSystemTools::GetLineFromStream(is, line)) {
// Transform the line content first.
- if(!this->TransformRules.empty())
- {
+ if (!this->TransformRules.empty()) {
this->TransformLine(line);
- }
+ }
// Match include directives.
- if(this->IncludeRegexLine.find(line.c_str()))
- {
+ if (this->IncludeRegexLine.find(line.c_str())) {
// 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()))
- {
+ if (this->IncludeRegexLine.match(3) == "\"" &&
+ !cmSystemTools::FileIsFullPath(entry.FileName.c_str())) {
// 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);
- }
+ }
// Queue the file if it has not yet been encountered and it
// matches the regular expression for recursive scanning. Note
@@ -463,111 +391,94 @@ 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()))
- {
+ if (this->IncludeRegexScan.find(entry.FileName.c_str())) {
newCacheEntry->UnscannedEntries.push_back(entry);
- if(this->Encountered.find(entry.FileName) == this->Encountered.end())
- {
+ if (this->Encountered.find(entry.FileName) ==
+ this->Encountered.end()) {
this->Encountered.insert(entry.FileName);
this->Unscanned.push(entry);
- }
}
}
}
+ }
}
-//----------------------------------------------------------------------------
void cmDependsC::SetupTransforms()
{
// Get the transformation rules.
std::vector<std::string> transformRules;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- if(const char* xform =
- mf->GetDefinition("CMAKE_INCLUDE_TRANSFORMS"))
- {
+ if (const char* xform = mf->GetDefinition("CMAKE_INCLUDE_TRANSFORMS")) {
cmSystemTools::ExpandListArgument(xform, transformRules, true);
- }
- for(std::vector<std::string>::const_iterator tri = transformRules.begin();
- tri != transformRules.end(); ++tri)
- {
+ }
+ for (std::vector<std::string>::const_iterator tri = transformRules.begin();
+ tri != transformRules.end(); ++tri) {
this->ParseTransform(*tri);
- }
+ }
this->IncludeRegexTransformString = INCLUDE_REGEX_TRANSFORM_MARKER;
- if(!this->TransformRules.empty())
- {
+ if (!this->TransformRules.empty()) {
// Construct the regular expression to match lines to be
// transformed.
- std::string xform = "^([ \t]*#[ \t]*(include|import)[ \t]*)(";
+ 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 (TransformRulesType::const_iterator tri = this->TransformRules.begin();
+ tri != this->TransformRules.end(); ++tri) {
xform += sep;
xform += tri->first;
sep = "|";
- }
+ }
xform += ")[ \t]*\\(([^),]*)\\)";
this->IncludeRegexTransform.compile(xform.c_str());
// 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 (TransformRulesType::const_iterator tri = this->TransformRules.begin();
+ tri != this->TransformRules.end(); ++tri) {
this->IncludeRegexTransformString += " ";
this->IncludeRegexTransformString += tri->first;
this->IncludeRegexTransformString += "(%)=";
this->IncludeRegexTransformString += tri->second;
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmDependsC::ParseTransform(std::string const& xform)
{
// A transform rule is of the form SOME_MACRO(%)=value-with-%
// We can simply separate with "(%)=".
std::string::size_type pos = xform.find("(%)=");
- if(pos == xform.npos || pos == 0)
- {
+ if (pos == std::string::npos || pos == 0) {
return;
- }
+ }
std::string name = xform.substr(0, pos);
- std::string value = xform.substr(pos+4, xform.npos);
+ std::string value = xform.substr(pos + 4);
this->TransformRules[name] = value;
}
-//----------------------------------------------------------------------------
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.c_str())) {
return;
- }
+ }
TransformRulesType::const_iterator tri =
this->TransformRules.find(this->IncludeRegexTransform.match(3));
- if(tri == this->TransformRules.end())
- {
+ if (tri == this->TransformRules.end()) {
return;
- }
+ }
// 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 (const char* c = tri->second.c_str(); *c; ++c) {
+ if (*c == '%') {
newline += arg;
- }
- else
- {
+ } else {
newline += *c;
- }
}
+ }
// Return the transformed line.
line = newline;
diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h
index 16dfad7bc..250d40f8a 100644
--- a/Source/cmDependsC.h
+++ b/Source/cmDependsC.h
@@ -1,46 +1,49 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDependsC_h
#define cmDependsC_h
+#include "cmConfigure.h"
+
#include "cmDepends.h"
-#include <cmsys/RegularExpression.hxx>
+
+#include "cmsys/RegularExpression.hxx"
+#include <iosfwd>
+#include <map>
#include <queue>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
/** \class cmDependsC
* \brief Dependency scanner for C and C++ object files.
*/
-class cmDependsC: public cmDepends
+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 char* lang,
+ cmDependsC(cmLocalGenerator* lg, const char* targetDir,
+ const std::string& lang,
const std::map<std::string, DependencyVector>* validDeps);
/** Virtual destructor to cleanup subclasses properly. */
- virtual ~cmDependsC();
+ ~cmDependsC() CM_OVERRIDE;
protected:
// Implement writing/checking methods required by superclass.
- virtual bool WriteDependencies(const std::set<std::string>& sources,
- const std::string& obj,
- std::ostream& makeDepends,
- std::ostream& internalDepends);
+ bool WriteDependencies(const std::set<std::string>& sources,
+ const std::string& obj, std::ostream& makeDepends,
+ std::ostream& internalDepends) CM_OVERRIDE;
// Method to scan a single file.
void Scan(std::istream& is, const char* directory,
- const cmStdString& fullName);
+ const std::string& fullName);
// Regular expression to identify C preprocessor include directives.
cmsys::RegularExpression IncludeRegexLine;
@@ -56,7 +59,7 @@ protected:
// Regex to transform #include lines.
std::string IncludeRegexTransformString;
cmsys::RegularExpression IncludeRegexTransform;
- typedef std::map<cmStdString, cmStdString> TransformRulesType;
+ typedef std::map<std::string, std::string> TransformRulesType;
TransformRulesType TransformRules;
void SetupTransforms();
void ParseTransform(std::string const& xform);
@@ -66,31 +69,32 @@ public:
// Data structures for dependency graph walk.
struct UnscannedEntry
{
- cmStdString FileName;
- cmStdString QuotedLocation;
+ std::string FileName;
+ std::string QuotedLocation;
};
struct cmIncludeLines
{
- cmIncludeLines(): Used(false) {}
+ cmIncludeLines()
+ : Used(false)
+ {
+ }
std::vector<UnscannedEntry> UnscannedEntries;
bool Used;
};
+
protected:
const std::map<std::string, DependencyVector>* ValidDeps;
- std::set<cmStdString> Encountered;
+ std::set<std::string> Encountered;
std::queue<UnscannedEntry> Unscanned;
- std::map<cmStdString, cmIncludeLines *> FileCache;
- std::map<cmStdString, cmStdString> HeaderLocationCache;
+ std::map<std::string, cmIncludeLines*> FileCache;
+ std::map<std::string, std::string> HeaderLocationCache;
- cmStdString CacheFileName;
+ std::string CacheFileName;
void WriteCacheFile() const;
void ReadCacheFile();
-private:
- cmDependsC(cmDependsC const&); // Purposely not implemented.
- void operator=(cmDependsC const&); // Purposely not implemented.
};
#endif
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index e41e5ea86..8b05fab49 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -1,140 +1,64 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDependsFortran.h"
-#include "cmSystemTools.h"
+#include "cmsys/FStream.hxx"
+#include <assert.h>
+#include <iostream>
+#include <map>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+
+#include "cmFortranParser.h" /* Interface to parser object. */
+#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
-
-#include "cmDependsFortranParser.h" /* Interface to parser object. */
-
-#include <assert.h>
-#include <stack>
+#include "cmOutputConverter.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.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.
-//----------------------------------------------------------------------------
-// Information about a single source file.
-class cmDependsFortranSourceInfo
-{
-public:
- // The name of the source file.
- std::string Source;
-
- // Set of provided and required modules.
- std::set<cmStdString> Provides;
- std::set<cmStdString> Requires;
-
- // Set of files included in the translation unit.
- std::set<cmStdString> Includes;
-};
-
-//----------------------------------------------------------------------------
-// Parser methods not included in generated interface.
-
-// Get the current buffer processed by the lexer.
-YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner);
-
-// The parser entry point.
-int cmDependsFortran_yyparse(yyscan_t);
-
-//----------------------------------------------------------------------------
-// Define parser object internal structure.
-struct cmDependsFortranFile
-{
- cmDependsFortranFile(FILE* file, YY_BUFFER_STATE buffer,
- const std::string& dir):
- File(file), Buffer(buffer), Directory(dir) {}
- FILE* File;
- YY_BUFFER_STATE Buffer;
- std::string Directory;
-};
-
-struct cmDependsFortranParser_s
-{
- cmDependsFortranParser_s(cmDependsFortran* self,
- std::set<std::string>& ppDefines,
- cmDependsFortranSourceInfo& info);
- ~cmDependsFortranParser_s();
-
- // Pointer back to the main class.
- cmDependsFortran* Self;
-
- // Lexical scanner instance.
- yyscan_t Scanner;
-
- // Stack of open files in the translation unit.
- std::stack<cmDependsFortranFile> FileStack;
-
- // Buffer for string literals.
- std::string TokenString;
-
- // Flag for whether lexer is reading from inside an interface.
- bool InInterface;
-
- int OldStartcond;
- std::set<std::string> PPDefinitions;
- size_t InPPFalseBranch;
- std::stack<bool> SkipToEnd;
-
- // Information about the parsed source.
- cmDependsFortranSourceInfo& Info;
-};
-
-//----------------------------------------------------------------------------
class cmDependsFortranInternals
{
public:
// The set of modules provided by this target.
- std::set<cmStdString> TargetProvides;
+ std::set<std::string> TargetProvides;
// Map modules required by this target to locations.
- typedef std::map<cmStdString, cmStdString> TargetRequiresMap;
+ typedef std::map<std::string, std::string> TargetRequiresMap;
TargetRequiresMap TargetRequires;
// Information about each object file.
- typedef std::map<cmStdString, cmDependsFortranSourceInfo> ObjectInfoMap;
+ typedef std::map<std::string, cmFortranSourceInfo> ObjectInfoMap;
ObjectInfoMap ObjectInfo;
- cmDependsFortranSourceInfo& CreateObjectInfo(const char* obj,
- const char* src)
- {
- std::map<cmStdString, cmDependsFortranSourceInfo>::iterator i =
+ cmFortranSourceInfo& CreateObjectInfo(const char* obj, const char* src)
+ {
+ std::map<std::string, cmFortranSourceInfo>::iterator i =
this->ObjectInfo.find(obj);
- if(i == this->ObjectInfo.end())
- {
- std::map<cmStdString, cmDependsFortranSourceInfo>::value_type
- entry(obj, cmDependsFortranSourceInfo());
+ if (i == this->ObjectInfo.end()) {
+ std::map<std::string, cmFortranSourceInfo>::value_type entry(
+ obj, cmFortranSourceInfo());
i = this->ObjectInfo.insert(entry).first;
i->second.Source = src;
- }
- return i->second;
}
+ return i->second;
+ }
};
-//----------------------------------------------------------------------------
-cmDependsFortran::cmDependsFortran():
- PPDefinitions(0), Internal(0)
+cmDependsFortran::cmDependsFortran()
+ : Internal(CM_NULLPTR)
{
}
-//----------------------------------------------------------------------------
-cmDependsFortran
-::cmDependsFortran(cmLocalGenerator* lg):
- cmDepends(lg),
- Internal(new cmDependsFortranInternals)
+cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg)
+ : cmDepends(lg)
+ , Internal(new cmDependsFortranInternals)
{
// Configure the include file search path.
this->SetIncludePathFromLanguage("Fortran");
@@ -142,81 +66,74 @@ cmDependsFortran
// Get the list of definitions.
std::vector<std::string> definitions;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- if(const char* c_defines =
- mf->GetDefinition("CMAKE_TARGET_DEFINITIONS"))
- {
+ if (const char* c_defines =
+ mf->GetDefinition("CMAKE_TARGET_DEFINITIONS_Fortran")) {
cmSystemTools::ExpandListArgument(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)
- {
+ for (std::vector<std::string>::const_iterator it = definitions.begin();
+ it != definitions.end(); ++it) {
std::string def = *it;
- std::string::size_type assignment = def.find("=");
- if(assignment != std::string::npos)
- {
+ std::string::size_type assignment = def.find('=');
+ if (assignment != std::string::npos) {
def = it->substr(0, assignment);
- }
- this->PPDefinitions.push_back(def);
}
+ this->PPDefinitions.insert(def);
+ }
}
-//----------------------------------------------------------------------------
cmDependsFortran::~cmDependsFortran()
{
delete this->Internal;
}
-//----------------------------------------------------------------------------
-bool cmDependsFortran::WriteDependencies(
- const std::set<std::string>& sources, const std::string& obj,
- std::ostream&, std::ostream&)
+bool cmDependsFortran::WriteDependencies(const std::set<std::string>& sources,
+ const std::string& obj,
+ std::ostream& /*makeDepends*/,
+ std::ostream& /*internalDepends*/)
{
// Make sure this is a scanning instance.
- if(sources.empty() || sources.begin()->empty())
- {
+ if (sources.empty() || sources.begin()->empty()) {
cmSystemTools::Error("Cannot scan dependencies without a source file.");
return false;
- }
- if(obj.empty())
- {
+ }
+ if (obj.empty()) {
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false;
- }
+ }
bool okay = true;
- for(std::set<std::string>::const_iterator it = sources.begin();
- it != sources.end(); ++it)
- {
+ for (std::set<std::string>::const_iterator it = sources.begin();
+ it != sources.end(); ++it) {
const std::string& src = *it;
// Get the information object for this source.
- cmDependsFortranSourceInfo& info =
+ cmFortranSourceInfo& info =
this->Internal->CreateObjectInfo(obj.c_str(), src.c_str());
- // Make a copy of the macros defined via ADD_DEFINITIONS
- std::set<std::string> ppDefines(this->PPDefinitions.begin(),
- this->PPDefinitions.end());
-
- // Create the parser object. The constructor takes ppMacro and info per
- // reference, so we may look into the resulting objects later.
- cmDependsFortranParser parser(this, ppDefines, info);
+ // 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);
// Push on the starting file.
- cmDependsFortranParser_FilePush(&parser, src.c_str());
+ cmFortranParser_FilePush(&parser, src.c_str());
// Parse the translation unit.
- if(cmDependsFortran_yyparse(parser.Scanner) != 0)
- {
+ if (cmFortran_yyparse(parser.Scanner) != 0) {
// Failed to parse the file. Report failure to write dependencies.
okay = false;
- }
- }
+ /* clang-format off */
+ std::cerr <<
+ "warning: failed to parse dependencies from Fortran source "
+ "'" << src << "': " << parser.Error << std::endl
+ ;
+ /* clang-format on */
+ }
+ }
return okay;
}
-//----------------------------------------------------------------------------
bool cmDependsFortran::Finalize(std::ostream& makeDepends,
std::ostream& internalDepends)
{
@@ -227,32 +144,24 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
const char* stamp_dir = this->TargetDirectory.c_str();
// Get the directory in which module files will be created.
- const char* mod_dir;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- if(const char* target_mod_dir =
- mf->GetDefinition("CMAKE_Fortran_TARGET_MODULE_DIR"))
- {
- mod_dir = target_mod_dir;
- }
- else
- {
- mod_dir =
- this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
- }
+ std::string mod_dir =
+ mf->GetSafeDefinition("CMAKE_Fortran_TARGET_MODULE_DIR");
+ if (mod_dir.empty()) {
+ mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
+ }
// Actually write dependencies to the streams.
typedef cmDependsFortranInternals::ObjectInfoMap 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 (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)) {
return false;
- }
}
+ }
// Store the list of modules provided by this target.
std::string fiName = this->TargetDirectory;
@@ -260,24 +169,23 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
cmGeneratedFileStream fiStream(fiName.c_str());
fiStream << "# The fortran modules provided by this target.\n";
fiStream << "provides\n";
- std::set<cmStdString> const& provides = this->Internal->TargetProvides;
- for(std::set<cmStdString>::const_iterator i = provides.begin();
- i != provides.end(); ++i)
- {
+ 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";
- }
+ }
// Create a script to clean the modules.
- if(!provides.empty())
- {
+ if (!provides.empty()) {
std::string fcName = this->TargetDirectory;
fcName += "/cmake_clean_Fortran.cmake";
cmGeneratedFileStream fcStream(fcName.c_str());
fcStream << "# Remove fortran modules provided by this target.\n";
fcStream << "FILE(REMOVE";
- for(std::set<cmStdString>::const_iterator i = provides.begin();
- i != provides.end(); ++i)
- {
+ 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);
@@ -291,54 +199,43 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
stamp += *i;
stamp += ".mod.stamp";
fcStream << "\n";
- fcStream << " \"" <<
- this->LocalGenerator->Convert(mod_lower.c_str(),
- cmLocalGenerator::START_OUTPUT)
+ fcStream << " \""
+ << this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
<< "\"\n";
- fcStream << " \"" <<
- this->LocalGenerator->Convert(mod_upper.c_str(),
- cmLocalGenerator::START_OUTPUT)
+ fcStream << " \""
+ << this->MaybeConvertToRelativePath(currentBinDir, mod_upper)
<< "\"\n";
- fcStream << " \"" <<
- this->LocalGenerator->Convert(stamp.c_str(),
- cmLocalGenerator::START_OUTPUT)
+ fcStream << " \""
+ << this->MaybeConvertToRelativePath(currentBinDir, stamp)
<< "\"\n";
- }
- fcStream << " )\n";
}
+ fcStream << " )\n";
+ }
return true;
}
-//----------------------------------------------------------------------------
void cmDependsFortran::LocateModules()
{
// Collect the set of modules provided and required by all sources.
typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
- for(ObjectInfoMap::const_iterator infoI = objInfo.begin();
- infoI != objInfo.end(); ++infoI)
- {
- cmDependsFortranSourceInfo const& info = infoI->second;
- for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
- i != info.Provides.end(); ++i)
- {
- // Include this module in the set provided by this target.
- this->Internal->TargetProvides.insert(*i);
- }
-
- for(std::set<cmStdString>::const_iterator i = info.Requires.begin();
- i != info.Requires.end(); ++i)
- {
- // Include this module in the set required by this target.
+ for (ObjectInfoMap::const_iterator infoI = objInfo.begin();
+ infoI != objInfo.end(); ++infoI) {
+ 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] = "";
- }
}
+ }
// Short-circuit for simple targets.
- if(this->Internal->TargetRequires.empty())
- {
+ if (this->Internal->TargetRequires.empty()) {
return;
- }
+ }
// Match modules provided by this target to those it requires.
this->MatchLocalModules();
@@ -346,96 +243,77 @@ void cmDependsFortran::LocateModules()
// Load information about other targets.
cmMakefile* mf = this->LocalGenerator->GetMakefile();
std::vector<std::string> infoFiles;
- if(const char* infoFilesValue =
- mf->GetDefinition("CMAKE_TARGET_LINKED_INFO_FILES"))
- {
+ if (const char* infoFilesValue =
+ mf->GetDefinition("CMAKE_TARGET_LINKED_INFO_FILES")) {
cmSystemTools::ExpandListArgument(infoFilesValue, infoFiles);
- }
- for(std::vector<std::string>::const_iterator i = infoFiles.begin();
- i != infoFiles.end(); ++i)
- {
+ }
+ for (std::vector<std::string>::const_iterator i = infoFiles.begin();
+ i != infoFiles.end(); ++i) {
std::string targetDir = cmSystemTools::GetFilenamePath(*i);
std::string fname = targetDir + "/fortran.internal";
- std::ifstream fin(fname.c_str());
- if(fin)
- {
+ cmsys::ifstream fin(fname.c_str());
+ if (fin) {
this->MatchRemoteModules(fin, targetDir.c_str());
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmDependsFortran::MatchLocalModules()
{
const char* stampDir = this->TargetDirectory.c_str();
- std::set<cmStdString> const& provides = this->Internal->TargetProvides;
- for(std::set<cmStdString>::const_iterator i = provides.begin();
- i != provides.end(); ++i)
- {
+ 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);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmDependsFortran::MatchRemoteModules(std::istream& fin,
const char* stampDir)
{
std::string line;
bool doing_provides = false;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
// Ignore comments and empty lines.
- if(line.empty() || line[0] == '#' || line[0] == '\r')
- {
+ if (line.empty() || line[0] == '#' || line[0] == '\r') {
continue;
- }
+ }
- if(line[0] == ' ')
- {
- if(doing_provides)
- {
- this->ConsiderModule(line.c_str()+1, stampDir);
- }
+ if (line[0] == ' ') {
+ if (doing_provides) {
+ this->ConsiderModule(line.c_str() + 1, stampDir);
}
- else if(line == "provides")
- {
+ } else if (line == "provides") {
doing_provides = true;
- }
- else
- {
+ } else {
doing_provides = false;
- }
}
+ }
}
-//----------------------------------------------------------------------------
-void cmDependsFortran::ConsiderModule(const char* name,
- const char* stampDir)
+void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir)
{
// Locate each required module.
typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
TargetRequiresMap::iterator required =
this->Internal->TargetRequires.find(name);
- if(required != this->Internal->TargetRequires.end() &&
- required->second.empty())
- {
+ 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";
required->second = stampFile;
- }
+ }
}
-//----------------------------------------------------------------------------
-bool
-cmDependsFortran
-::WriteDependenciesReal(const char *obj,
- cmDependsFortranSourceInfo const& info,
- const char* mod_dir, const char* stamp_dir,
- std::ostream& makeDepends,
- std::ostream& internalDepends)
+bool cmDependsFortran::WriteDependenciesReal(const char* obj,
+ cmFortranSourceInfo const& info,
+ std::string const& mod_dir,
+ const char* stamp_dir,
+ std::ostream& makeDepends,
+ std::ostream& internalDepends)
{
typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
@@ -443,36 +321,34 @@ cmDependsFortran
const char* src = info.Source.c_str();
// Write the include dependencies to the output stream.
- internalDepends << obj << std::endl;
+ std::string binDir = this->LocalGenerator->GetBinaryDirectory();
+ std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj);
+ std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i.c_str());
+ internalDepends << obj_i << std::endl;
internalDepends << " " << src << std::endl;
- for(std::set<cmStdString>::const_iterator i = info.Includes.begin();
- i != info.Includes.end(); ++i)
- {
- makeDepends << obj << ": " <<
- this->LocalGenerator->Convert(i->c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
+ for (std::set<std::string>::const_iterator i = info.Includes.begin();
+ i != info.Includes.end(); ++i) {
+ makeDepends << obj_m << ": "
+ << cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, *i).c_str())
<< std::endl;
- internalDepends << " " << i->c_str() << std::endl;
- }
+ internalDepends << " " << *i << std::endl;
+ }
makeDepends << std::endl;
// Write module requirements to the output stream.
- for(std::set<cmStdString>::const_iterator i = info.Requires.begin();
- i != info.Requires.end(); ++i)
- {
+ for (std::set<std::string>::const_iterator i = info.Requires.begin();
+ i != info.Requires.end(); ++i) {
// Require only modules not provided in the same source.
- if(std::set<cmStdString>::const_iterator(info.Provides.find(*i)) !=
- info.Provides.end())
- {
+ if (std::set<std::string>::const_iterator(info.Provides.find(*i)) !=
+ info.Provides.end()) {
continue;
- }
+ }
// If the module is provided in this target special handling is
// needed.
- if(this->Internal->TargetProvides.find(*i) !=
- this->Internal->TargetProvides.end())
- {
+ 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.
@@ -480,67 +356,56 @@ cmDependsFortran
proxy += "/";
proxy += *i;
proxy += ".mod.proxy";
- proxy = this->LocalGenerator->Convert(proxy.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
+ proxy = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, proxy).c_str());
// since we require some things add them to our list of requirements
- makeDepends << obj << ".requires: " << proxy << std::endl;
- }
+ 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);
- if(required == this->Internal->TargetRequires.end()) { abort(); }
- if(!required->second.empty())
- {
+ if (required == this->Internal->TargetRequires.end()) {
+ abort();
+ }
+ if (!required->second.empty()) {
// This module is known. Depend on its timestamp file.
- std::string stampFile =
- this->LocalGenerator->Convert(required->second.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << obj << ": " << stampFile << "\n";
- }
- else
- {
+ std::string stampFile = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, required->second).c_str());
+ 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))
- {
- module =
- this->LocalGenerator->Convert(module.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << obj << ": " << module << "\n";
- }
+ if (this->FindModule(*i, module)) {
+ module = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, module).c_str());
+ makeDepends << obj_m << ": " << module << "\n";
}
}
+ }
// Write provided modules to the output stream.
- for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
- i != info.Provides.end(); ++i)
- {
+ 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 = this->LocalGenerator->Convert(proxy.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << proxy << ": " << obj << ".provides" << std::endl;
- }
+ 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())
- {
+ if (!info.Provides.empty()) {
// Create a target to copy the module after the object file
// changes.
- makeDepends << obj << ".provides.build:\n";
- for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
- i != info.Provides.end(); ++i)
- {
+ makeDepends << obj_m << ".provides.build:\n";
+ for (std::set<std::string>::const_iterator i = info.Provides.begin();
+ i != info.Provides.end(); ++i) {
// Include this module in the set provided by this target.
this->Internal->TargetProvides.insert(*i);
@@ -551,49 +416,43 @@ cmDependsFortran
std::string modFile = mod_dir;
modFile += "/";
modFile += *i;
- modFile =
- this->LocalGenerator->Convert(modFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
+ modFile = this->LocalGenerator->ConvertToOutputFormat(
+ this->MaybeConvertToRelativePath(binDir, modFile),
+ cmOutputConverter::SHELL);
std::string stampFile = stamp_dir;
stampFile += "/";
stampFile += m;
stampFile += ".mod.stamp";
- stampFile =
- this->LocalGenerator->Convert(stampFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod "
- << modFile << " " << stampFile;
+ stampFile = this->LocalGenerator->ConvertToOutputFormat(
+ this->MaybeConvertToRelativePath(binDir, stampFile),
+ cmOutputConverter::SHELL);
+ makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile
+ << " " << stampFile;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
const char* cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID");
- if(cid && *cid)
- {
+ if (cid && *cid) {
makeDepends << " " << cid;
- }
- makeDepends << "\n";
}
+ makeDepends << "\n";
+ }
// After copying the modules update the timestamp file so that
// copying will not be done again until the source rebuilds.
- makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj
+ 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";
- driver = this->LocalGenerator->Convert(driver.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << driver << ": " << obj << ".provides.build\n";
- }
+ driver = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, driver).c_str());
+ makeDepends << driver << ": " << obj_m << ".provides.build\n";
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmDependsFortran::FindModule(std::string const& name,
- std::string& module)
+bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
{
// Construct possible names for the module file.
std::string mod_upper = cmSystemTools::UpperCase(name);
@@ -603,33 +462,29 @@ bool cmDependsFortran::FindModule(std::string const& name,
// 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::vector<std::string>::const_iterator i = this->IncludePath.begin();
+ i != this->IncludePath.end(); ++i) {
// Try the lower-case name.
fullName = *i;
fullName += "/";
fullName += mod_lower;
- if(cmSystemTools::FileExists(fullName.c_str(), true))
- {
+ if (cmSystemTools::FileExists(fullName.c_str(), true)) {
module = fullName;
return true;
- }
+ }
// Try the upper-case name.
fullName = *i;
fullName += "/";
fullName += mod_upper;
- if(cmSystemTools::FileExists(fullName.c_str(), true))
- {
+ if (cmSystemTools::FileExists(fullName.c_str(), true)) {
module = fullName;
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
{
// Implements
@@ -645,12 +500,13 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
std::string mod = args[2];
std::string stamp = args[3];
std::string compilerId;
- if(args.size() >= 5)
- {
+ if (args.size() >= 5) {
compilerId = args[4];
- }
+ }
std::string mod_dir = cmSystemTools::GetFilenamePath(mod);
- if(!mod_dir.empty()) { mod_dir += "/"; }
+ 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;
@@ -658,114 +514,96 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
mod += ".mod";
mod_upper += ".mod";
mod_lower += ".mod";
- if(cmSystemTools::FileExists(mod_upper.c_str(), true))
- {
- if(cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(),
- compilerId.c_str()))
- {
- if(!cmSystemTools::CopyFileAlways(mod_upper.c_str(), stamp.c_str()))
- {
- std::cerr << "Error copying Fortran module from \""
- << mod_upper.c_str() << "\" to \"" << stamp.c_str()
- << "\".\n";
+ if (cmSystemTools::FileExists(mod_upper.c_str(), true)) {
+ if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(),
+ compilerId.c_str())) {
+ if (!cmSystemTools::CopyFileAlways(mod_upper, stamp)) {
+ std::cerr << "Error copying Fortran module from \"" << mod_upper
+ << "\" to \"" << stamp << "\".\n";
return false;
- }
}
- return true;
}
- else if(cmSystemTools::FileExists(mod_lower.c_str(), true))
- {
- if(cmDependsFortran::ModulesDiffer(mod_lower.c_str(), stamp.c_str(),
- compilerId.c_str()))
- {
- if(!cmSystemTools::CopyFileAlways(mod_lower.c_str(), stamp.c_str()))
- {
- std::cerr << "Error copying Fortran module from \""
- << mod_lower.c_str() << "\" to \"" << stamp.c_str()
- << "\".\n";
+ 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::CopyFileAlways(mod_lower, stamp)) {
+ std::cerr << "Error copying Fortran module from \"" << mod_lower
+ << "\" to \"" << stamp << "\".\n";
return false;
- }
}
- return true;
}
+ return true;
+ }
- std::cerr << "Error copying Fortran module \"" << args[2].c_str()
- << "\". Tried \"" << mod_upper.c_str()
- << "\" and \"" << mod_lower.c_str() << "\".\n";
+ std::cerr << "Error copying Fortran module \"" << args[2] << "\". Tried \""
+ << mod_upper << "\" and \"" << mod_lower << "\".\n";
return false;
}
-//----------------------------------------------------------------------------
// Helper function to look for a short sequence in a stream. If this
// is later used for longer sequences it should be re-written using an
// efficient string search algorithm such as Boyer-Moore.
-static
-bool cmDependsFortranStreamContainsSequence(std::ifstream& ifs,
- const char* seq, int len)
+static bool cmFortranStreamContainsSequence(std::istream& ifs, const char* seq,
+ int len)
{
assert(len > 0);
int cur = 0;
- while(cur < len)
- {
+ while (cur < len) {
// Get the next character.
int token = ifs.get();
- if(!ifs)
- {
+ if (!ifs) {
return false;
- }
+ }
// Check the character.
- if(token == static_cast<int>(seq[cur]))
- {
+ if (token == static_cast<int>(seq[cur])) {
++cur;
- }
- else
- {
+ } else {
// Assume the sequence has no repeating subsequence.
cur = 0;
- }
}
+ }
// The entire sequence was matched.
return true;
}
-//----------------------------------------------------------------------------
// Helper function to compare the remaining content in two streams.
-static bool cmDependsFortranStreamsDiffer(std::ifstream& ifs1,
- std::ifstream& ifs2)
+static bool cmFortranStreamsDiffer(std::istream& ifs1, std::istream& ifs2)
{
// Compare the remaining content.
- for(;;)
- {
+ for (;;) {
int ifs1_c = ifs1.get();
int ifs2_c = ifs2.get();
- if(!ifs1 && !ifs2)
- {
+ if (!ifs1 && !ifs2) {
// We have reached the end of both streams simultaneously.
// The streams are identical.
return false;
- }
+ }
- if(!ifs1 || !ifs2 || ifs1_c != ifs2_c)
- {
+ if (!ifs1 || !ifs2 || ifs1_c != ifs2_c) {
// We have reached the end of one stream before the other or
// found differing content. The streams are different.
break;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmDependsFortran::ModulesDiffer(const char* modFile,
const char* stampFile,
const char* compilerId)
{
/*
- gnu:
+ gnu >= 4.9:
+ A mod file is an ascii file compressed with gzip.
+ Compiling twice produces identical modules.
+
+ gnu < 4.9:
A mod file is an ascii file.
<bar.mod>
FORTRAN module created from /path/to/foo.f90 on Sun Dec 30 22:47:58 2007
@@ -788,28 +626,25 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
TODO ...
*/
-
/* Compilers which do _not_ produce different mod content when the same
* source is compiled twice
* -SunPro
*/
- if(strcmp(compilerId, "SunPro") == 0)
- {
+ if (strcmp(compilerId, "SunPro") == 0) {
return cmSystemTools::FilesDiffer(modFile, stampFile);
- }
+ }
#if defined(_WIN32) || defined(__CYGWIN__)
- std::ifstream finModFile(modFile, std::ios::in | std::ios::binary);
- std::ifstream finStampFile(stampFile, std::ios::in | std::ios::binary);
+ cmsys::ifstream finModFile(modFile, std::ios::in | std::ios::binary);
+ cmsys::ifstream finStampFile(stampFile, std::ios::in | std::ios::binary);
#else
- std::ifstream finModFile(modFile, std::ios::in);
- std::ifstream finStampFile(stampFile, std::ios::in);
+ cmsys::ifstream finModFile(modFile);
+ cmsys::ifstream finStampFile(stampFile);
#endif
- if(!finModFile || !finStampFile)
- {
+ if (!finModFile || !finStampFile) {
// At least one of the files does not exist. The modules differ.
return true;
- }
+ }
/* Compilers which _do_ produce different mod content when the same
* source is compiled twice
@@ -819,446 +654,64 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
* Eat the stream content until all recompile only related changes
* are left behind.
*/
- if (strcmp(compilerId, "GNU") == 0 )
- {
- const char seq[1] = {'\n'};
- const int seqlen = 1;
-
- if(!cmDependsFortranStreamContainsSequence(finModFile, seq, seqlen))
- {
- // The module is of unexpected format. Assume it is different.
- std::cerr << compilerId << " fortran module " << modFile
- << " has unexpected format." << std::endl;
- return true;
+ if (strcmp(compilerId, "GNU") == 0) {
+ // 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.
+ unsigned char hdr[2];
+ bool okay = !finModFile.read(reinterpret_cast<char*>(hdr), 2).fail();
+ finModFile.seekg(0);
+ if (!okay || hdr[0] != 0x1f || hdr[1] != 0x8b) {
+ const char seq[1] = { '\n' };
+ const int seqlen = 1;
+
+ if (!cmFortranStreamContainsSequence(finModFile, seq, seqlen)) {
+ // The module is of unexpected format. Assume it is different.
+ std::cerr << compilerId << " fortran module " << modFile
+ << " has unexpected format." << std::endl;
+ return true;
}
- if(!cmDependsFortranStreamContainsSequence(finStampFile, seq, seqlen))
- {
- // The stamp must differ if the sequence is not contained.
- return true;
+ if (!cmFortranStreamContainsSequence(finStampFile, seq, seqlen)) {
+ // The stamp must differ if the sequence is not contained.
+ return true;
}
}
- else if(strcmp(compilerId, "Intel") == 0)
- {
- const char seq[2] = {'\n', '\0'};
+ } else if (strcmp(compilerId, "Intel") == 0) {
+ const char seq[2] = { '\n', '\0' };
const int seqlen = 2;
- if(!cmDependsFortranStreamContainsSequence(finModFile, seq, seqlen))
- {
+ // Skip the leading byte which appears to be a version number.
+ // We do not need to check for an error because the sequence search
+ // below will fail in that case.
+ finModFile.get();
+ finStampFile.get();
+
+ if (!cmFortranStreamContainsSequence(finModFile, seq, seqlen)) {
// The module is of unexpected format. Assume it is different.
std::cerr << compilerId << " fortran module " << modFile
<< " has unexpected format." << std::endl;
return true;
- }
+ }
- if(!cmDependsFortranStreamContainsSequence(finStampFile, seq, seqlen))
- {
+ if (!cmFortranStreamContainsSequence(finStampFile, seq, seqlen)) {
// The stamp must differ if the sequence is not contained.
return true;
- }
}
+ }
// Compare the remaining content. If no compiler id matched above,
// including the case none was given, this will compare the whole
// content.
- if(!cmDependsFortranStreamsDiffer(finModFile, finStampFile))
- {
- return false;
- }
-
- // The modules are different.
- return true;
-}
-
-//----------------------------------------------------------------------------
-bool cmDependsFortran::FindIncludeFile(const char* dir,
- const char* includeName,
- std::string& fileName)
-{
- // If the file is a full path, include it directly.
- if(cmSystemTools::FileIsFullPath(includeName))
- {
- fileName = includeName;
- return cmSystemTools::FileExists(fileName.c_str(), true);
- }
- else
- {
- // 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))
- {
- 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))
- {
- fileName = fullName;
- return true;
- }
- }
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-cmDependsFortranParser_s
-::cmDependsFortranParser_s(cmDependsFortran* self,
- std::set<std::string>& ppDefines,
- cmDependsFortranSourceInfo& info):
- Self(self), PPDefinitions(ppDefines), Info(info)
-{
- this->InInterface = 0;
- this->InPPFalseBranch = 0;
-
- // Initialize the lexical scanner.
- cmDependsFortran_yylex_init(&this->Scanner);
- cmDependsFortran_yyset_extra(this, this->Scanner);
-
- // 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 =
- cmDependsFortran_yy_create_buffer(0, 4, this->Scanner);
- cmDependsFortran_yy_switch_to_buffer(buffer, this->Scanner);
-}
-
-//----------------------------------------------------------------------------
-cmDependsFortranParser_s::~cmDependsFortranParser_s()
-{
- cmDependsFortran_yylex_destroy(this->Scanner);
-}
-
-//----------------------------------------------------------------------------
-bool cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
- const char* fname)
-{
- // Open the new file and push it onto the stack. Save the old
- // buffer with it on the stack.
- if(FILE* file = fopen(fname, "rb"))
- {
- YY_BUFFER_STATE current =
- cmDependsFortranLexer_GetCurrentBuffer(parser->Scanner);
- std::string dir = cmSystemTools::GetParentDirectory(fname);
- cmDependsFortranFile f(file, current, dir);
- YY_BUFFER_STATE buffer =
- cmDependsFortran_yy_create_buffer(0, 16384, parser->Scanner);
- cmDependsFortran_yy_switch_to_buffer(buffer, parser->Scanner);
- parser->FileStack.push(f);
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmDependsFortranParser_FilePop(cmDependsFortranParser* parser)
-{
- // Pop one file off the stack and close it. Switch the lexer back
- // to the next one on the stack.
- if(parser->FileStack.empty())
- {
- return 0;
- }
- else
- {
- cmDependsFortranFile f = parser->FileStack.top(); parser->FileStack.pop();
- fclose(f.File);
- YY_BUFFER_STATE current =
- cmDependsFortranLexer_GetCurrentBuffer(parser->Scanner);
- cmDependsFortran_yy_delete_buffer(current, parser->Scanner);
- cmDependsFortran_yy_switch_to_buffer(f.Buffer, parser->Scanner);
- return 1;
- }
+ return cmFortranStreamsDiffer(finModFile, finStampFile);
}
-//----------------------------------------------------------------------------
-int cmDependsFortranParser_Input(cmDependsFortranParser* parser,
- char* buffer, size_t bufferSize)
+std::string cmDependsFortran::MaybeConvertToRelativePath(
+ std::string const& base, std::string const& path)
{
- // Read from the file on top of the stack. If the stack is empty,
- // the end of the translation unit has been reached.
- if(!parser->FileStack.empty())
- {
- FILE* file = parser->FileStack.top().File;
- return (int)fread(buffer, 1, bufferSize, file);
- }
- return 0;
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_StringStart(cmDependsFortranParser* parser)
-{
- parser->TokenString = "";
-}
-
-//----------------------------------------------------------------------------
-const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser)
-{
- return parser->TokenString.c_str();
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser,
- char c)
-{
- parser->TokenString += c;
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser,
- bool in)
-{
- if(parser->InPPFalseBranch)
- {
- return;
- }
-
- parser->InInterface = in;
-}
-
-//----------------------------------------------------------------------------
-bool cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser)
-{
- return parser->InInterface;
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_SetOldStartcond(cmDependsFortranParser* parser,
- int arg)
-{
- parser->OldStartcond = arg;
-}
-
-//----------------------------------------------------------------------------
-int cmDependsFortranParser_GetOldStartcond(cmDependsFortranParser* parser)
-{
- return parser->OldStartcond;
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_Error(cmDependsFortranParser*, const char*)
-{
- // If there is a parser error just ignore it. The source will not
- // compile and the user will edit it. Then dependencies will have
- // to be regenerated anyway.
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser,
- const char* name)
-{
- if(!parser->InPPFalseBranch)
- {
- parser->Info.Requires.insert(cmSystemTools::LowerCase(name) );
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
- const char* name)
-{
- if(parser->InPPFalseBranch)
- {
- return;
- }
-
- // If processing an include statement there must be an open file.
- assert(!parser->FileStack.empty());
-
- // Get the directory containing the source in which the include
- // statement appears. This is always the first search location for
- // Fortran include files.
- std::string dir = parser->FileStack.top().Directory;
-
- // Find the included file. If it cannot be found just ignore the
- // problem because either the source will not compile or the user
- // does not care about depending on this included source.
- std::string fullName;
- if(parser->Self->FindIncludeFile(dir.c_str(), name, fullName))
- {
- // Found the included file. Save it in the set of included files.
- parser->Info.Includes.insert(fullName);
-
- // Parse it immediately to translate the source inline.
- cmDependsFortranParser_FilePush(parser, fullName.c_str());
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
- const char* name)
-{
- if(!parser->InPPFalseBranch && !parser->InInterface)
- {
- parser->Info.Provides.insert(cmSystemTools::LowerCase(name));
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleDefine(cmDependsFortranParser* parser,
- const char* macro)
-{
- if(!parser->InPPFalseBranch)
- {
- parser->PPDefinitions.insert(macro);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleUndef(cmDependsFortranParser* parser,
- const char* macro)
-{
- if(!parser->InPPFalseBranch)
- {
- std::set<std::string>::iterator match;
- match = parser->PPDefinitions.find(macro);
- if(match != parser->PPDefinitions.end())
- {
- parser->PPDefinitions.erase(match);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleIfdef(cmDependsFortranParser* parser,
- const char* macro)
-{
- // A new PP branch has been opened
- parser->SkipToEnd.push(false);
-
- if (parser->InPPFalseBranch)
- {
- parser->InPPFalseBranch++;
- }
- else if(parser->PPDefinitions.find(macro) == parser->PPDefinitions.end())
- {
- parser->InPPFalseBranch=1;
- }
- else
- {
- parser->SkipToEnd.top() = true;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleIfndef(cmDependsFortranParser* parser,
- const char* macro)
-{
- // A new PP branch has been opened
- parser->SkipToEnd.push(false);
-
- if (parser->InPPFalseBranch)
- {
- parser->InPPFalseBranch++;
- }
- else if(parser->PPDefinitions.find(macro) != parser->PPDefinitions.end())
- {
- parser->InPPFalseBranch = 1;
- }
- else
- {
- // ignore other branches
- parser->SkipToEnd.top() = true;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleIf(cmDependsFortranParser* parser)
-{
- /* Note: The current parser is _not_ able to get statements like
- * #if 0
- * #if 1
- * #if MYSMBOL
- * #if defined(MYSYMBOL)
- * #if defined(MYSYMBOL) && ...
- * right. The same for #elif. Thus in
- * #if SYMBOL_1
- * ..
- * #elif SYMBOL_2
- * ...
- * ...
- * #elif SYMBOL_N
- * ..
- * #else
- * ..
- * #endif
- * _all_ N+1 branches are considered. If you got something like this
- * #if defined(MYSYMBOL)
- * #if !defined(MYSYMBOL)
- * use
- * #ifdef MYSYMBOL
- * #ifndef MYSYMBOL
- * instead.
- */
-
- // A new PP branch has been opened
- // Never skip! See note above.
- parser->SkipToEnd.push(false);
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleElif(cmDependsFortranParser* parser)
-{
- /* Note: There are parser limitations. See the note at
- * cmDependsFortranParser_RuleIf(..)
- */
-
- // Always taken unless an #ifdef or #ifndef-branch has been taken
- // already. If the second condition isn't meet already
- // (parser->InPPFalseBranch == 0) correct it.
- if(!parser->SkipToEnd.empty() &&
- parser->SkipToEnd.top() && !parser->InPPFalseBranch)
- {
- parser->InPPFalseBranch = 1;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleElse(cmDependsFortranParser* parser)
-{
- // if the parent branch is false do nothing!
- if(parser->InPPFalseBranch > 1)
- {
- return;
- }
-
- // parser->InPPFalseBranch is either 0 or 1. We change it depending on
- // parser->SkipToEnd.top()
- if(!parser->SkipToEnd.empty() &&
- parser->SkipToEnd.top())
- {
- parser->InPPFalseBranch = 1;
- }
- else
- {
- parser->InPPFalseBranch = 0;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDependsFortranParser_RuleEndif(cmDependsFortranParser* parser)
-{
- if(!parser->SkipToEnd.empty())
- {
- parser->SkipToEnd.pop();
- }
-
- // #endif doesn't know if there was a "#else" in before, so it
- // always decreases InPPFalseBranch
- if(parser->InPPFalseBranch)
- {
- parser->InPPFalseBranch--;
- }
+ if (!cmOutputConverter::ContainedInDirectory(
+ base, path, this->LocalGenerator->GetStateSnapshot().GetDirectory())) {
+ return path;
+ }
+ return cmOutputConverter::ForceToRelativePath(base, path);
}
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index cb40796c8..ec208af3a 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -1,27 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFortran_h
+#define cmFortran_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDependsFortran_h
-#define cmDependsFortran_h
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
#include "cmDepends.h"
class cmDependsFortranInternals;
-class cmDependsFortranSourceInfo;
+class cmFortranSourceInfo;
+class cmLocalGenerator;
/** \class cmDependsFortran
* \brief Dependency scanner for Fortran object files.
*/
-class cmDependsFortran: public cmDepends
+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. */
@@ -34,7 +35,7 @@ public:
cmDependsFortran(cmLocalGenerator* lg);
/** Virtual destructor to cleanup subclasses properly. */
- virtual ~cmDependsFortran();
+ ~cmDependsFortran() CM_OVERRIDE;
/** Callback from build system after a .mod file has been generated
by a Fortran90 compiler to copy the .mod file to the
@@ -43,19 +44,13 @@ 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);
-
- /** Method to find an included file in the include path. Fortran
- always searches the directory containing the including source
- first. */
- bool FindIncludeFile(const char* dir, const char* includeName,
- std::string& fileName);
+ static bool ModulesDiffer(const char* modFile, const char* stampFile,
+ const char* compilerId);
protected:
// Finalize the dependency information for the target.
- virtual bool Finalize(std::ostream& makeDepends,
- std::ostream& internalDepends);
+ bool Finalize(std::ostream& makeDepends,
+ std::ostream& internalDepends) CM_OVERRIDE;
// Find all the modules required by the target.
void LocateModules();
@@ -65,28 +60,27 @@ protected:
bool FindModule(std::string const& name, std::string& module);
// Implement writing/checking methods required by superclass.
- virtual bool WriteDependencies(
- const std::set<std::string>& sources, const std::string& file,
- std::ostream& makeDepends, std::ostream& internalDepends);
+ bool WriteDependencies(const std::set<std::string>& sources,
+ const std::string& file, std::ostream& makeDepends,
+ std::ostream& internalDepends) CM_OVERRIDE;
// Actually write the depenencies to the streams.
- bool WriteDependenciesReal(const char *obj,
- cmDependsFortranSourceInfo const& info,
- const char* mod_dir, const char* stamp_dir,
+ bool WriteDependenciesReal(const char* obj, cmFortranSourceInfo const& info,
+ std::string const& mod_dir, const char* stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends);
// The source file from which to start scanning.
std::string SourceFile;
- std::vector<std::string> PPDefinitions;
+ std::set<std::string> PPDefinitions;
// Internal implementation details.
cmDependsFortranInternals* Internal;
private:
- cmDependsFortran(cmDependsFortran const&); // Purposely not implemented.
- void operator=(cmDependsFortran const&); // Purposely not implemented.
+ std::string MaybeConvertToRelativePath(std::string const& base,
+ std::string const& path);
};
#endif
diff --git a/Source/cmDependsFortranLexer.cxx b/Source/cmDependsFortranLexer.cxx
deleted file mode 100644
index 924d9d2a9..000000000
--- a/Source/cmDependsFortranLexer.cxx
+++ /dev/null
@@ -1,2414 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#line 2 "cmDependsFortranLexer.cxx"
-
-#line 4 "cmDependsFortranLexer.cxx"
-
-#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 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#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
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* 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.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmDependsFortran_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
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
- #define YY_LESS_LINENO(n)
-
-/* 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_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.
- */
- yy_size_t 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 cmDependsFortran_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 cmDependsFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmDependsFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmDependsFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmDependsFortran_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmDependsFortran_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER cmDependsFortran_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *cmDependsFortran_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmDependsFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer cmDependsFortran_yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- cmDependsFortran_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmDependsFortran_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 ){\
- cmDependsFortran_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmDependsFortran_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 cmDependsFortran_yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char 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 yy_fatal_error (yyconst 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 = (size_t) (yy_cp - yy_bp); \
- yyg->yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 44
-#define YY_END_OF_BUFFER 45
-/* 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 yyconst flex_int16_t yy_accept[165] =
- { 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 45, 39, 41, 40, 43, 1, 39, 32, 2, 34,
- 39, 40, 37, 39, 38, 39, 38, 41, 39, 40,
- 39, 38, 9, 8, 9, 4, 3, 39, 0, 10,
- 0, 0, 0, 0, 0, 32, 32, 33, 35, 37,
- 39, 38, 0, 42, 38, 0, 0, 0, 0, 0,
- 0, 0, 0, 39, 0, 11, 38, 0, 0, 5,
- 0, 0, 0, 28, 0, 0, 32, 32, 32, 32,
- 0, 0, 0, 0, 0, 22, 0, 0, 0, 0,
- 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 29, 30, 0, 0, 0, 0, 0, 0,
- 0, 23, 24, 0, 0, 0, 0, 0, 0, 0,
- 0, 31, 26, 0, 0, 19, 0, 0, 25, 20,
- 0, 0, 18, 0, 0, 17, 27, 0, 0, 16,
- 21, 0, 7, 36, 7, 14, 0, 13, 15, 0,
- 0, 0, 12, 0
- } ;
-
-static yyconst flex_int32_t yy_ec[256] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 5, 6, 7, 8, 9, 1, 10, 11, 1,
- 1, 12, 1, 13, 1, 1, 1, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 15, 16, 17,
- 18, 19, 20, 1, 21, 21, 22, 23, 24, 25,
- 21, 21, 26, 21, 21, 27, 21, 28, 21, 21,
- 21, 21, 29, 21, 30, 21, 21, 21, 21, 21,
- 1, 31, 1, 1, 32, 1, 21, 21, 33, 34,
-
- 35, 36, 21, 21, 37, 21, 21, 38, 21, 39,
- 21, 21, 21, 21, 40, 21, 41, 21, 21, 21,
- 21, 21, 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 yyconst flex_int32_t yy_meta[42] =
- { 0,
- 1, 2, 2, 3, 4, 3, 3, 1, 1, 3,
- 3, 1, 3, 5, 1, 3, 1, 3, 6, 1,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 1, 5, 7, 7, 7, 7, 7, 7, 7, 7,
- 7
- } ;
-
-static yyconst flex_int16_t yy_base[174] =
- { 0,
- 0, 40, 0, 41, 188, 48, 44, 54, 56, 65,
- 186, 0, 505, 505, 171, 505, 81, 74, 505, 505,
- 158, 505, 151, 137, 0, 85, 122, 87, 153, 145,
- 194, 226, 505, 143, 91, 505, 505, 0, 142, 505,
- 266, 34, 70, 74, 34, 122, 141, 505, 0, 505,
- 112, 0, 98, 505, 0, 154, 306, 0, 43, 133,
- 139, 46, 130, 347, 130, 505, 0, 121, 163, 179,
- 104, 156, 129, 176, 147, 178, 214, 267, 273, 292,
- 279, 179, 249, 280, 257, 265, 288, 289, 116, 107,
- 317, 505, 287, 289, 291, 302, 307, 310, 307, 311,
-
- 316, 326, 329, 333, 332, 336, 347, 345, 349, 101,
- 86, 346, 505, 505, 350, 351, 353, 350, 357, 362,
- 362, 505, 505, 367, 369, 371, 366, 372, 56, 47,
- 374, 505, 505, 374, 379, 505, 374, 387, 505, 505,
- 387, 391, 505, 117, 0, 505, 505, 392, 394, 505,
- 505, 394, 505, 505, 505, 505, 395, 419, 505, 429,
- 0, 25, 505, 505, 446, 453, 459, 462, 469, 476,
- 483, 490, 497
- } ;
-
-static yyconst flex_int16_t yy_def[174] =
- { 0,
- 164, 1, 1, 1, 1, 1, 165, 165, 165, 165,
- 164, 166, 164, 164, 167, 164, 166, 164, 164, 164,
- 166, 164, 164, 166, 168, 166, 168, 164, 166, 164,
- 169, 164, 164, 164, 164, 164, 164, 166, 167, 164,
- 164, 164, 164, 164, 164, 164, 170, 164, 166, 164,
- 166, 168, 164, 164, 27, 164, 164, 57, 164, 164,
- 164, 164, 164, 169, 169, 164, 32, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 170, 170, 170, 170,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
-
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 171, 172, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 173, 173, 164, 0, 164, 164, 164, 164, 164, 164,
- 164, 164, 164
- } ;
-
-static yyconst flex_int16_t yy_nxt[547] =
- { 0,
- 12, 13, 14, 13, 13, 15, 16, 12, 17, 18,
- 19, 12, 20, 12, 21, 22, 12, 23, 12, 24,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 27, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 28, 28, 163, 28, 28, 34, 29, 29, 28,
- 30, 145, 28, 35, 36, 29, 34, 71, 34, 31,
- 144, 76, 37, 35, 36, 35, 83, 34, 71, 32,
- 32, 37, 76, 88, 35, 46, 46, 83, 46, 47,
- 32, 32, 41, 48, 88, 41, 53, 54, 56, 53,
- 130, 56, 69, 70, 57, 69, 72, 73, 74, 53,
-
- 54, 75, 53, 42, 43, 129, 44, 72, 73, 74,
- 45, 111, 75, 81, 42, 43, 81, 44, 154, 154,
- 110, 45, 38, 46, 46, 90, 46, 47, 93, 38,
- 38, 48, 66, 38, 89, 55, 38, 82, 38, 93,
- 38, 38, 78, 46, 40, 78, 79, 68, 82, 63,
- 80, 96, 38, 55, 58, 56, 51, 58, 56, 84,
- 85, 57, 96, 86, 69, 70, 87, 69, 99, 50,
- 84, 85, 49, 40, 86, 59, 60, 87, 61, 99,
- 91, 94, 62, 91, 95, 164, 59, 60, 92, 61,
- 30, 164, 94, 62, 64, 95, 66, 164, 97, 164,
-
- 100, 64, 64, 98, 164, 64, 101, 64, 64, 97,
- 64, 100, 64, 64, 98, 78, 46, 101, 78, 79,
- 164, 164, 164, 80, 64, 64, 65, 65, 66, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 67,
- 65, 65, 65, 65, 65, 65, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 65, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 41, 78, 46,
- 41, 78, 79, 102, 78, 46, 80, 78, 79, 105,
- 81, 164, 80, 81, 102, 164, 164, 106, 42, 43,
- 105, 44, 107, 78, 46, 45, 78, 79, 106, 42,
-
- 43, 80, 44, 107, 82, 103, 45, 58, 104, 108,
- 58, 109, 112, 113, 114, 82, 103, 164, 91, 104,
- 108, 91, 109, 112, 113, 114, 92, 115, 59, 60,
- 116, 61, 117, 118, 119, 62, 164, 120, 115, 59,
- 60, 116, 61, 117, 118, 119, 62, 64, 120, 66,
- 164, 121, 164, 122, 64, 64, 123, 124, 64, 125,
- 64, 64, 121, 64, 122, 64, 64, 123, 124, 126,
- 125, 127, 128, 131, 132, 133, 134, 64, 64, 135,
- 126, 136, 127, 128, 131, 132, 133, 134, 137, 138,
- 135, 139, 136, 140, 141, 142, 143, 146, 147, 137,
-
- 138, 148, 139, 149, 140, 141, 142, 143, 146, 147,
- 150, 151, 148, 152, 149, 156, 157, 158, 159, 164,
- 160, 150, 151, 160, 152, 164, 156, 157, 158, 159,
- 160, 164, 164, 160, 164, 161, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 161, 33, 33, 33, 33,
- 33, 33, 33, 38, 164, 164, 164, 38, 38, 39,
- 39, 39, 39, 39, 39, 39, 52, 164, 52, 65,
- 65, 65, 65, 65, 65, 65, 77, 77, 77, 77,
- 77, 77, 77, 153, 153, 153, 164, 153, 153, 153,
- 155, 164, 155, 164, 155, 155, 155, 162, 162, 162,
-
- 162, 162, 164, 162, 11, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164
- } ;
-
-static yyconst flex_int16_t yy_chk[547] =
- { 0,
- 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, 2, 4, 162, 2, 4, 7, 2, 4, 6,
- 6, 130, 6, 7, 7, 6, 8, 42, 9, 6,
- 129, 45, 9, 8, 8, 9, 59, 10, 42, 6,
- 6, 10, 45, 62, 10, 18, 18, 59, 18, 18,
- 6, 6, 17, 18, 62, 17, 26, 26, 28, 26,
- 111, 28, 35, 35, 28, 35, 43, 43, 44, 53,
-
- 53, 44, 53, 17, 17, 110, 17, 43, 43, 44,
- 17, 90, 44, 51, 17, 17, 51, 17, 144, 144,
- 89, 17, 27, 46, 46, 68, 46, 46, 71, 27,
- 27, 46, 65, 27, 63, 27, 27, 51, 27, 71,
- 27, 27, 47, 47, 39, 47, 47, 34, 51, 30,
- 47, 73, 27, 27, 29, 56, 24, 29, 56, 60,
- 60, 56, 73, 61, 69, 69, 61, 69, 75, 23,
- 60, 60, 21, 15, 61, 29, 29, 61, 29, 75,
- 70, 72, 29, 70, 72, 11, 29, 29, 70, 29,
- 5, 0, 72, 29, 31, 72, 31, 0, 74, 0,
-
- 76, 31, 31, 74, 0, 31, 82, 31, 31, 74,
- 31, 76, 31, 31, 74, 77, 77, 82, 77, 77,
- 0, 0, 0, 77, 31, 31, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 41, 78, 78,
- 41, 78, 78, 83, 79, 79, 78, 79, 79, 85,
- 81, 0, 79, 81, 83, 0, 0, 86, 41, 41,
- 85, 41, 86, 80, 80, 41, 80, 80, 86, 41,
-
- 41, 80, 41, 86, 81, 84, 41, 57, 84, 87,
- 57, 88, 93, 94, 95, 81, 84, 0, 91, 84,
- 87, 91, 88, 93, 94, 95, 91, 96, 57, 57,
- 97, 57, 98, 99, 100, 57, 0, 101, 96, 57,
- 57, 97, 57, 98, 99, 100, 57, 64, 101, 64,
- 0, 102, 0, 103, 64, 64, 104, 105, 64, 106,
- 64, 64, 102, 64, 103, 64, 64, 104, 105, 107,
- 106, 108, 109, 112, 115, 116, 117, 64, 64, 118,
- 107, 119, 108, 109, 112, 115, 116, 117, 120, 121,
- 118, 124, 119, 125, 126, 127, 128, 131, 134, 120,
-
- 121, 135, 124, 137, 125, 126, 127, 128, 131, 134,
- 138, 141, 135, 142, 137, 148, 149, 152, 157, 0,
- 158, 138, 141, 158, 142, 0, 148, 149, 152, 157,
- 160, 0, 0, 160, 0, 158, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 160, 165, 165, 165, 165,
- 165, 165, 165, 166, 0, 0, 0, 166, 166, 167,
- 167, 167, 167, 167, 167, 167, 168, 0, 168, 169,
- 169, 169, 169, 169, 169, 169, 170, 170, 170, 170,
- 170, 170, 170, 171, 171, 171, 0, 171, 171, 171,
- 172, 0, 172, 0, 172, 172, 172, 173, 173, 173,
-
- 173, 173, 0, 173, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 164, 164, 164, 164
- } ;
-
-/* 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
-#line 1 "cmDependsFortranLexer.in.l"
-#line 2 "cmDependsFortranLexer.in.l"
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*-------------------------------------------------------------------------
- Portions of this source have been derived from makedepf90 version 2.8.8,
-
- Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann@iki.fi>
-
- The code was originally distributed under the GPL but permission
- from the copyright holder has been obtained to distribute this
- derived work under the CMake license.
--------------------------------------------------------------------------*/
-
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex like this:
-
- flex -i --prefix=cmDependsFortran_yy --header-file=cmDependsFortranLexer.h -ocmDependsFortranLexer.cxx cmDependsFortranLexer.in.l
-
-Modify cmDependsFortranLexer.cxx:
- - remove TABs
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmDependsFortran_yyalloc, cmDependsFortran_yyrealloc, cmDependsFortran_yyfree
- - remove "yyscanner = NULL" from end of cmDependsFortran_yylex_destroy
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
-
-Modify cmDependsFortranLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
-
-*/
-
-#include "cmStandardLexer.h"
-
-#define cmDependsFortranLexer_cxx
-#include "cmDependsFortranParser.h" /* Interface to parser object. */
-
-/* Replace the lexer input function. */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
- { result = cmDependsFortranParser_Input(yyextra, buf, max_size); }
-
-/* Include the set of tokens from the parser. */
-#include "cmDependsFortranParserTokens.h"
-
-/*--------------------------------------------------------------------------*/
-
-
-#line 678 "cmDependsFortranLexer.cxx"
-
-#define INITIAL 0
-#define free_fmt 1
-#define fixed_fmt 2
-#define str_sq 3
-#define str_dq 4
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#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 cmDependsFortran_yylex_init (yyscan_t* scanner);
-
-int cmDependsFortran_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 cmDependsFortran_yylex_destroy (yyscan_t yyscanner );
-
-int cmDependsFortran_yyget_debug (yyscan_t yyscanner );
-
-void cmDependsFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE cmDependsFortran_yyget_extra (yyscan_t yyscanner );
-
-void cmDependsFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *cmDependsFortran_yyget_in (yyscan_t yyscanner );
-
-void cmDependsFortran_yyset_in (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *cmDependsFortran_yyget_out (yyscan_t yyscanner );
-
-void cmDependsFortran_yyset_out (FILE * out_str ,yyscan_t yyscanner );
-
-int cmDependsFortran_yyget_leng (yyscan_t yyscanner );
-
-char *cmDependsFortran_yyget_text (yyscan_t yyscanner );
-
-int cmDependsFortran_yyget_lineno (yyscan_t yyscanner );
-
-void cmDependsFortran_yyset_lineno (int line_number ,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 cmDependsFortran_yywrap (yyscan_t yyscanner );
-#else
-extern int cmDependsFortran_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
- static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst 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, 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 = '*'; \
- size_t 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 = fread(buf, 1, 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 cmDependsFortran_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int cmDependsFortran_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 break;
-#endif
-
-#define YY_RULE_SETUP \
- if ( yyleng > 0 ) \
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
- (yytext[yyleng - 1] == '\n'); \
- 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;
-
-#line 71 "cmDependsFortranLexer.in.l"
-
-
-#line 914 "cmDependsFortranLexer.cxx"
-
- 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 ) {
- cmDependsFortran_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmDependsFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmDependsFortran_yy_load_buffer_state(yyscanner );
- }
-
- for(;;) /* 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_current_state += YY_AT_BOL();
-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 >= 165 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 505 );
-
-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
-#line 73 "cmDependsFortranLexer.in.l"
-{
- cmDependsFortranParser_StringStart(yyextra);
- cmDependsFortranParser_SetOldStartcond(yyextra, YY_START);
- BEGIN(str_dq);
-}
- YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 79 "cmDependsFortranLexer.in.l"
-{
- cmDependsFortranParser_StringStart(yyextra);
- cmDependsFortranParser_SetOldStartcond(yyextra, YY_START);
- BEGIN(str_sq);
-}
- YY_BREAK
-case 3:
-#line 86 "cmDependsFortranLexer.in.l"
-case 4:
-YY_RULE_SETUP
-#line 86 "cmDependsFortranLexer.in.l"
-{
- BEGIN(cmDependsFortranParser_GetOldStartcond(yyextra) );
- yylvalp->string = strdup(cmDependsFortranParser_StringEnd(yyextra));
- return STRING;
-}
-case 5:
-/* rule 5 can match eol */
-#line 93 "cmDependsFortranLexer.in.l"
-case 6:
-/* rule 6 can match eol */
-YY_RULE_SETUP
-#line 93 "cmDependsFortranLexer.in.l"
-/* Ignore (continued strings, free fmt) */
- YY_BREAK
-case 7:
-/* rule 7 can match eol */
-YY_RULE_SETUP
-#line 95 "cmDependsFortranLexer.in.l"
-{
- if (cmDependsFortranParser_GetOldStartcond(yyextra) == fixed_fmt)
- ; /* Ignore (cont. strings, fixed fmt) */
- else
- {
- unput(yytext[strlen(yytext)-1]);
- }
-}
- YY_BREAK
-case 8:
-/* rule 8 can match eol */
-YY_RULE_SETUP
-#line 105 "cmDependsFortranLexer.in.l"
-{
- unput ('\n');
- BEGIN(INITIAL);
- return UNTERMINATED_STRING;
-}
-case 9:
-YY_RULE_SETUP
-#line 111 "cmDependsFortranLexer.in.l"
-{
- cmDependsFortranParser_StringAppend(yyextra, yytext[0]);
-}
- YY_BREAK
-case 10:
-/* rule 10 can match eol */
-YY_RULE_SETUP
-#line 115 "cmDependsFortranLexer.in.l"
-{ return EOSTMT; } /* Treat comments like */
-case 11:
-/* rule 11 can match eol */
-YY_RULE_SETUP
-#line 116 "cmDependsFortranLexer.in.l"
-{ return EOSTMT; } /* empty lines */
-case 12:
-/* rule 12 can match eol */
-YY_RULE_SETUP
-#line 118 "cmDependsFortranLexer.in.l"
-{
- yytext[yyleng-1] = 0;
- yylvalp->string = strdup(strchr(yytext, '<')+1);
- return CPP_INCLUDE_ANGLE;
-}
-case 13:
-YY_RULE_SETUP
-#line 123 "cmDependsFortranLexer.in.l"
-{ return CPP_INCLUDE; }
-case 14:
-YY_RULE_SETUP
-#line 124 "cmDependsFortranLexer.in.l"
-{ return F90PPR_INCLUDE; }
-case 15:
-YY_RULE_SETUP
-#line 125 "cmDependsFortranLexer.in.l"
-{ return COCO_INCLUDE; }
-case 16:
-YY_RULE_SETUP
-#line 127 "cmDependsFortranLexer.in.l"
-{ return CPP_DEFINE; }
-case 17:
-YY_RULE_SETUP
-#line 128 "cmDependsFortranLexer.in.l"
-{ return F90PPR_DEFINE; }
-case 18:
-YY_RULE_SETUP
-#line 130 "cmDependsFortranLexer.in.l"
-{ return CPP_UNDEF; }
-case 19:
-YY_RULE_SETUP
-#line 131 "cmDependsFortranLexer.in.l"
-{ return F90PPR_UNDEF; }
-case 20:
-YY_RULE_SETUP
-#line 133 "cmDependsFortranLexer.in.l"
-{ return CPP_IFDEF; }
-case 21:
-YY_RULE_SETUP
-#line 134 "cmDependsFortranLexer.in.l"
-{ return CPP_IFNDEF; }
-case 22:
-YY_RULE_SETUP
-#line 135 "cmDependsFortranLexer.in.l"
-{ return CPP_IF; }
-case 23:
-YY_RULE_SETUP
-#line 136 "cmDependsFortranLexer.in.l"
-{ return CPP_ELIF; }
-case 24:
-YY_RULE_SETUP
-#line 137 "cmDependsFortranLexer.in.l"
-{ return CPP_ELSE; }
-case 25:
-YY_RULE_SETUP
-#line 138 "cmDependsFortranLexer.in.l"
-{ return CPP_ENDIF; }
-case 26:
-YY_RULE_SETUP
-#line 140 "cmDependsFortranLexer.in.l"
-{ return F90PPR_IFDEF; }
-case 27:
-YY_RULE_SETUP
-#line 141 "cmDependsFortranLexer.in.l"
-{ return F90PPR_IFNDEF; }
-case 28:
-YY_RULE_SETUP
-#line 142 "cmDependsFortranLexer.in.l"
-{ return F90PPR_IF; }
-case 29:
-YY_RULE_SETUP
-#line 143 "cmDependsFortranLexer.in.l"
-{ return F90PPR_ELIF; }
-case 30:
-YY_RULE_SETUP
-#line 144 "cmDependsFortranLexer.in.l"
-{ return F90PPR_ELSE; }
-case 31:
-YY_RULE_SETUP
-#line 145 "cmDependsFortranLexer.in.l"
-{ return F90PPR_ENDIF; }
-/* Line continuations, possible involving comments. */
-case 32:
-/* rule 32 can match eol */
-YY_RULE_SETUP
-#line 148 "cmDependsFortranLexer.in.l"
-
- YY_BREAK
-case 33:
-/* rule 33 can match eol */
-YY_RULE_SETUP
-#line 149 "cmDependsFortranLexer.in.l"
-
- YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 151 "cmDependsFortranLexer.in.l"
-{ return COMMA; }
-case 35:
-YY_RULE_SETUP
-#line 153 "cmDependsFortranLexer.in.l"
-{ return DCOLON; }
-case 36:
-/* rule 36 can match eol */
-YY_RULE_SETUP
-#line 155 "cmDependsFortranLexer.in.l"
-{ return GARBAGE; }
-case 37:
-YY_RULE_SETUP
-#line 157 "cmDependsFortranLexer.in.l"
-{ return ASSIGNMENT_OP; }
-case 38:
-YY_RULE_SETUP
-#line 159 "cmDependsFortranLexer.in.l"
-{
- yylvalp->string = strdup(yytext);
- return WORD;
-}
-case 39:
-YY_RULE_SETUP
-#line 164 "cmDependsFortranLexer.in.l"
-{ return GARBAGE; }
-case 40:
-/* rule 40 can match eol */
-YY_RULE_SETUP
-#line 166 "cmDependsFortranLexer.in.l"
-{ return EOSTMT; }
-case 41:
-YY_RULE_SETUP
-#line 169 "cmDependsFortranLexer.in.l"
-/* Ignore */
- YY_BREAK
-case 42:
-/* rule 42 can match eol */
-YY_RULE_SETUP
-#line 170 "cmDependsFortranLexer.in.l"
-/* Ignore line-endings preceeded by \ */
- YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 172 "cmDependsFortranLexer.in.l"
-{ return *yytext; }
-case YY_STATE_EOF(INITIAL):
-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 174 "cmDependsFortranLexer.in.l"
-{
- if(!cmDependsFortranParser_FilePop(yyextra) )
- {
- return YY_NULL;
- }
-}
- YY_BREAK
-case 44:
-YY_RULE_SETUP
-#line 181 "cmDependsFortranLexer.in.l"
-ECHO;
- YY_BREAK
-#line 1270 "cmDependsFortranLexer.cxx"
-
- 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
- * cmDependsFortran_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 ( cmDependsFortran_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 cmDependsFortran_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;
-
- 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. */
- cmDependsFortran_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- 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, (size_t) 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;
- cmDependsFortran_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 ((yy_size_t) (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. */
- yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmDependsFortran_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
- }
-
- 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;
- yy_current_state += YY_AT_BOL();
-
- 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 >= 165 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) 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 >= 165 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 164);
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
- 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 = 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;
-}
-
-#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 = 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. */
- cmDependsFortran_yyrestart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( cmDependsFortran_yywrap(yyscanner ) )
- return EOF;
-
- 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;
-
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
- 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 cmDependsFortran_yyrestart (FILE * input_file , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! YY_CURRENT_BUFFER ){
- cmDependsFortran_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmDependsFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmDependsFortran_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmDependsFortran_yy_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
- void cmDependsFortran_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
- * cmDependsFortran_yypop_buffer_state();
- * cmDependsFortran_yypush_buffer_state(new_buffer);
- */
- cmDependsFortran_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;
- cmDependsFortran_yy_load_buffer_state(yyscanner );
-
- /* We don't actually know whether we did this switch during
- * EOF (cmDependsFortran_yywrap()) processing, but the only time this flag
- * is looked at is after cmDependsFortran_yywrap() is called, so it's safe
- * to go ahead and always set it.
- */
- yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void cmDependsFortran_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 cmDependsFortran_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) cmDependsFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_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 *) cmDependsFortran_yyalloc(b->yy_buf_size + 2 ,yyscanner );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- cmDependsFortran_yy_init_buffer(b,file ,yyscanner);
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with cmDependsFortran_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
- void cmDependsFortran_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 )
- cmDependsFortran_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
- cmDependsFortran_yyfree((void *) b ,yyscanner );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a cmDependsFortran_yyrestart() or at EOF.
- */
- static void cmDependsFortran_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
-
-{
- int oerrno = errno;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- cmDependsFortran_yy_flush_buffer(b ,yyscanner);
-
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
-
- /* If b is the current buffer, then cmDependsFortran_yy_init_buffer was _probably_
- * called from cmDependsFortran_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 cmDependsFortran_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 )
- cmDependsFortran_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 cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (new_buffer == NULL)
- return;
-
- cmDependsFortran_yyensure_buffer_stack(yyscanner);
-
- /* This block is copied from cmDependsFortran_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 cmDependsFortran_yy_switch_to_buffer. */
- cmDependsFortran_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 cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (!YY_CURRENT_BUFFER)
- return;
-
- cmDependsFortran_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) {
- cmDependsFortran_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 cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner)
-{
- int 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;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsFortran_yyalloc
- (num_to_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
- if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_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. */
- int grow_size = 8 /* arbitrary grow size */;
-
- num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsFortran_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 cmDependsFortran_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 cmDependsFortran_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 0;
-
- b = (YY_BUFFER_STATE) cmDependsFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yy_scan_buffer()" );
-
- b->yy_buf_size = 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 = 0;
- 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;
-
- cmDependsFortran_yy_switch_to_buffer(b ,yyscanner );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to cmDependsFortran_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
- * cmDependsFortran_yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE cmDependsFortran_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-
- return cmDependsFortran_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to cmDependsFortran_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 cmDependsFortran_yy_scan_bytes (yyconst 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 = _yybytes_len + 2;
- buf = (char *) cmDependsFortran_yyalloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_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 = cmDependsFortran_yy_scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmDependsFortran_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 yy_fatal_error (yyconst char* msg , yyscan_t)
-{
- (void) 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 cmDependsFortran_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 cmDependsFortran_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 cmDependsFortran_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 *cmDependsFortran_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 *cmDependsFortran_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 cmDependsFortran_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 *cmDependsFortran_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 cmDependsFortran_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
- * @param yyscanner The scanner object.
- */
-void cmDependsFortran_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( "cmDependsFortran_yyset_lineno called with no buffer" , yyscanner);
-
- yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void cmDependsFortran_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( "cmDependsFortran_yyset_column called with no buffer" , yyscanner);
-
- 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 cmDependsFortran_yy_switch_to_buffer
- */
-void cmDependsFortran_yyset_in (FILE * in_str , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = in_str ;
-}
-
-void cmDependsFortran_yyset_out (FILE * out_str , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
-}
-
-int cmDependsFortran_yyget_debug (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yy_flex_debug;
-}
-
-void cmDependsFortran_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 */
-
-/* cmDependsFortran_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 cmDependsFortran_yylex_init(yyscan_t* ptr_yy_globals)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmDependsFortran_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 );
-}
-
-/* cmDependsFortran_yylex_init_extra has the same functionality as cmDependsFortran_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 cmDependsFortran_yyalloc in
- * the yyextra field.
- */
-
-int cmDependsFortran_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
- struct yyguts_t dummy_yyguts;
-
- cmDependsFortran_yyset_extra (yy_user_defined, &dummy_yyguts);
-
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmDependsFortran_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));
-
- cmDependsFortran_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 cmDependsFortran_yylex_destroy(), so don't allocate here.
- */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- 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 = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * cmDependsFortran_yylex_init()
- */
- return 0;
-}
-
-/* cmDependsFortran_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmDependsFortran_yylex_destroy (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* Pop the buffer stack, destroying each element. */
- while(YY_CURRENT_BUFFER){
- cmDependsFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
- YY_CURRENT_BUFFER_LVALUE = NULL;
- cmDependsFortran_yypop_buffer_state(yyscanner);
- }
-
- /* Destroy the stack itself. */
- cmDependsFortran_yyfree(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
-
- /* Destroy the start condition stack. */
- cmDependsFortran_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
- * cmDependsFortran_yylex() is called, initialization will occur. */
- yy_init_globals( yyscanner);
-
- /* Destroy the main struct (reentrant only). */
- cmDependsFortran_yyfree ( yyscanner , yyscanner );
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
- int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
- int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *cmDependsFortran_yyalloc (yy_size_t size , yyscan_t)
-{
- return (void *) malloc( size );
-}
-
-void *cmDependsFortran_yyrealloc (void * ptr, yy_size_t size , yyscan_t)
-{
- /* 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 (void *) realloc( (char *) ptr, size );
-}
-
-void cmDependsFortran_yyfree (void * ptr , yyscan_t)
-{
- free( (char *) ptr ); /* see cmDependsFortran_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 181 "cmDependsFortranLexer.in.l"
-
-
-
-/*--------------------------------------------------------------------------*/
-YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
-{
- /* Hack into the internal flex-generated scanner to get the buffer. */
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return YY_CURRENT_BUFFER;
-}
-
diff --git a/Source/cmDependsFortranParser.h b/Source/cmDependsFortranParser.h
deleted file mode 100644
index 399c3c8d9..000000000
--- a/Source/cmDependsFortranParser.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDependsFortranParser_h
-#define cmDependsFortranParser_h
-
-#include <stddef.h> /* size_t */
-
-/* Forward declare parser object type. */
-typedef struct cmDependsFortranParser_s cmDependsFortranParser;
-
-/* Functions to enter/exit #include'd files in order. */
-bool cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
- const char* fname);
-bool cmDependsFortranParser_FilePop(cmDependsFortranParser* parser);
-
-/* Callbacks for lexer. */
-int cmDependsFortranParser_Input(cmDependsFortranParser* parser,
- char* buffer, size_t bufferSize);
-
-
-void cmDependsFortranParser_StringStart(cmDependsFortranParser* parser);
-const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser);
-void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser,
- char c);
-
-void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser,
- bool is_in);
-bool cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser);
-
-
-void cmDependsFortranParser_SetInPPFalseBranch(cmDependsFortranParser* parser,
- bool is_in);
-bool cmDependsFortranParser_GetInPPFalseBranch(cmDependsFortranParser* parser);
-
-
-void cmDependsFortranParser_SetOldStartcond(cmDependsFortranParser* parser,
- int arg);
-int cmDependsFortranParser_GetOldStartcond(cmDependsFortranParser* parser);
-
-/* Callbacks for parser. */
-void cmDependsFortranParser_Error(cmDependsFortranParser* parser,
- const char* message);
-void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleDefine(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleUndef(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleIfdef(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleIfndef(cmDependsFortranParser* parser,
- const char* name);
-void cmDependsFortranParser_RuleIf(cmDependsFortranParser* parser);
-void cmDependsFortranParser_RuleElif(cmDependsFortranParser* parser);
-void cmDependsFortranParser_RuleElse(cmDependsFortranParser* parser);
-void cmDependsFortranParser_RuleEndif(cmDependsFortranParser* parser);
-
-/* Define the parser stack element type. */
-typedef union cmDependsFortran_yystype_u cmDependsFortran_yystype;
-union cmDependsFortran_yystype_u
-{
- char* string;
-};
-
-/* Setup the proper yylex interface. */
-#define YY_EXTRA_TYPE cmDependsFortranParser*
-#define YY_DECL \
-int cmDependsFortran_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
-#define YYSTYPE cmDependsFortran_yystype
-#define YYSTYPE_IS_DECLARED 1
-#if !defined(cmDependsFortranLexer_cxx)
-# include "cmDependsFortranLexer.h"
-#endif
-#if !defined(cmDependsFortranLexer_cxx)
-#if !defined(cmDependsFortranParser_cxx)
-# undef YY_EXTRA_TYPE
-# undef YY_DECL
-# undef YYSTYPE
-# undef YYSTYPE_IS_DECLARED
-#endif
-#endif
-
-#endif
diff --git a/Source/cmDependsFortranParser.y b/Source/cmDependsFortranParser.y
deleted file mode 100644
index d814f3075..000000000
--- a/Source/cmDependsFortranParser.y
+++ /dev/null
@@ -1,288 +0,0 @@
-%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*-------------------------------------------------------------------------
- Portions of this source have been derived from makedepf90 version 2.8.8,
-
- Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann@iki.fi>
-
- The code was originally distributed under the GPL but permission
- from the copyright holder has been obtained to distribute this
- derived work under the CMake license.
--------------------------------------------------------------------------*/
-
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
- bison --yacc --name-prefix=cmDependsFortran_yy
- --defines=cmDependsFortranParserTokens.h
- -ocmDependsFortranParser.cxx
- cmDependsFortranParser.y
-
-Modify cmDependsFortranParser.cxx:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - Remove the yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
-*/
-
-/*-------------------------------------------------------------------------*/
-#define cmDependsFortranParser_cxx
-#include "cmDependsFortranParser.h" /* Interface to parser object. */
-#include "cmDependsFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */
-
-#include <cmsys/String.h>
-
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmDependsFortran_yyerror(x) \
- cmDependsFortranError(yyscanner, x)
-
-/* Forward declare the lexer entry point. */
-YY_DECL;
-
-/* Helper function to forward error callback. */
-static void cmDependsFortranError(yyscan_t yyscanner, const char* message)
-{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_Error(parser, message);
-}
-
-static bool cmDependsFortranParserIsKeyword(const char* word,
- const char* keyword)
-{
- return cmsysString_strcasecmp(word, keyword) == 0;
-}
-
-/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label. */
-# pragma warning (disable: 4065) /* Switch contains default but no case. */
-# pragma warning (disable: 4701) /* Local variable may not be initialized. */
-# pragma warning (disable: 4702) /* Unreachable code. */
-# pragma warning (disable: 4127) /* Conditional expression is constant. */
-# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
-#endif
-%}
-
-/* Generate a reentrant parser object. */
-%pure-parser
-
-%union {
- char* string;
-}
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token EOSTMT ASSIGNMENT_OP GARBAGE
-%token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
-%token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
-%token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
-%token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF
-%token F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
-%token COMMA DCOLON
-%token <string> CPP_TOENDL
-%token <number> UNTERMINATED_STRING
-%token <string> STRING WORD
-%token <string> CPP_INCLUDE_ANGLE
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-code: /* empty */ | code stmt;
-
-stmt: keyword_stmt | assignment_stmt;
-
-assignment_stmt: WORD ASSIGNMENT_OP other EOSTMT /* Ignore */
- {
- free($1);
- }
-
-keyword_stmt:
- WORD EOSTMT
- {
- if (cmDependsFortranParserIsKeyword($1, "interface"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_SetInInterface(parser, true);
- }
- free($1);
- }
-| WORD WORD other EOSTMT
- {
- if (cmDependsFortranParserIsKeyword($1, "use"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, $2);
- }
- else if (cmDependsFortranParserIsKeyword($1, "module"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleModule(parser, $2);
- }
- else if (cmDependsFortranParserIsKeyword($1, "interface"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_SetInInterface(parser, true);
- }
- else if (cmDependsFortranParserIsKeyword($2, "interface") &&
- cmDependsFortranParserIsKeyword($1, "end"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_SetInInterface(parser, false);
- }
- free($1);
- free($2);
- }
-| WORD DCOLON WORD other EOSTMT
- {
- if (cmDependsFortranParserIsKeyword($1, "use"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, $3);
- }
- free($1);
- free($3);
- }
-| WORD COMMA WORD DCOLON WORD other EOSTMT
- {
- if (cmDependsFortranParserIsKeyword($1, "use") &&
- cmDependsFortranParserIsKeyword($3, "non_intrinsic") )
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, $5);
- }
- free($1);
- free($3);
- free($5);
- }
-| WORD STRING other EOSTMT /* Ignore */
- {
- if (cmDependsFortranParserIsKeyword($1, "include"))
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, $2);
- }
- free($1);
- free($2);
- }
-| CPP_INCLUDE_ANGLE other EOSTMT
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, $1);
- free($1);
- }
-| include STRING other EOSTMT
- {
- cmDependsFortranParser* parser =
- cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, $2);
- free($2);
- }
-| define WORD other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleDefine(parser, $2);
- free($2);
- }
-| undef WORD other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUndef(parser, $2);
- free($2);
- }
-| ifdef WORD other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleIfdef(parser, $2);
- free($2);
- }
-| ifndef WORD other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleIfndef(parser, $2);
- free($2);
- }
-| if other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleIf(parser);
- }
-| elif other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleElif(parser);
- }
-| else other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleElse(parser);
- }
-| endif other EOSTMT
- {
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleEndif(parser);
- }
-| WORD GARBAGE other EOSTMT /* Ignore */
- {
- free($1);
- }
-| GARBAGE other EOSTMT
-| EOSTMT
-| error
-;
-
-
-
-include: CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
-define: CPP_DEFINE | F90PPR_DEFINE;
-undef: CPP_UNDEF | F90PPR_UNDEF ;
-ifdef: CPP_IFDEF | F90PPR_IFDEF ;
-ifndef: CPP_IFNDEF | F90PPR_IFNDEF ;
-if: CPP_IF | F90PPR_IF ;
-elif: CPP_ELIF | F90PPR_ELIF ;
-else: CPP_ELSE | F90PPR_ELSE ;
-endif: CPP_ENDIF | F90PPR_ENDIF ;
-other: /* empty */ | other misc_code ;
-
-misc_code:
- WORD { free ($1); }
-| STRING { free ($1); }
-| GARBAGE
-| ASSIGNMENT_OP
-| DCOLON
-| COMMA
-| UNTERMINATED_STRING
-;
-
-%%
-/* End of grammar */
diff --git a/Source/cmDependsFortranParserTokens.h b/Source/cmDependsFortranParserTokens.h
deleted file mode 100644
index 941eda09c..000000000
--- a/Source/cmDependsFortranParserTokens.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.5. */
-
-/* Bison interface for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2011 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
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- EOSTMT = 258,
- ASSIGNMENT_OP = 259,
- GARBAGE = 260,
- CPP_INCLUDE = 261,
- F90PPR_INCLUDE = 262,
- COCO_INCLUDE = 263,
- F90PPR_DEFINE = 264,
- CPP_DEFINE = 265,
- F90PPR_UNDEF = 266,
- CPP_UNDEF = 267,
- CPP_IFDEF = 268,
- CPP_IFNDEF = 269,
- CPP_IF = 270,
- CPP_ELSE = 271,
- CPP_ELIF = 272,
- CPP_ENDIF = 273,
- F90PPR_IFDEF = 274,
- F90PPR_IFNDEF = 275,
- F90PPR_IF = 276,
- F90PPR_ELSE = 277,
- F90PPR_ELIF = 278,
- F90PPR_ENDIF = 279,
- COMMA = 280,
- DCOLON = 281,
- CPP_TOENDL = 282,
- UNTERMINATED_STRING = 283,
- STRING = 284,
- WORD = 285,
- CPP_INCLUDE_ANGLE = 286
- };
-#endif
-/* Tokens. */
-#define EOSTMT 258
-#define ASSIGNMENT_OP 259
-#define GARBAGE 260
-#define CPP_INCLUDE 261
-#define F90PPR_INCLUDE 262
-#define COCO_INCLUDE 263
-#define F90PPR_DEFINE 264
-#define CPP_DEFINE 265
-#define F90PPR_UNDEF 266
-#define CPP_UNDEF 267
-#define CPP_IFDEF 268
-#define CPP_IFNDEF 269
-#define CPP_IF 270
-#define CPP_ELSE 271
-#define CPP_ELIF 272
-#define CPP_ENDIF 273
-#define F90PPR_IFDEF 274
-#define F90PPR_IFNDEF 275
-#define F90PPR_IF 276
-#define F90PPR_ELSE 277
-#define F90PPR_ELIF 278
-#define F90PPR_ENDIF 279
-#define COMMA 280
-#define DCOLON 281
-#define CPP_TOENDL 282
-#define UNTERMINATED_STRING 283
-#define STRING 284
-#define WORD 285
-#define CPP_INCLUDE_ANGLE 286
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-
-/* Line 2068 of yacc.c */
-#line 89 "cmDependsFortranParser.y"
-
- char* string;
-
-
-
-/* Line 2068 of yacc.c */
-#line 118 "cmDependsFortranParserTokens.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx
index 949d46515..29938ba36 100644
--- a/Source/cmDependsJava.cxx
+++ b/Source/cmDependsJava.cxx
@@ -1,45 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDependsJava.h"
-#include "cmDependsJavaParserHelper.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
cmDependsJava::cmDependsJava()
{
}
-//----------------------------------------------------------------------------
cmDependsJava::~cmDependsJava()
{
}
-//----------------------------------------------------------------------------
bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources,
- const std::string&, std::ostream&, std::ostream&)
+ const std::string& /*obj*/,
+ std::ostream& /*makeDepends*/,
+ std::ostream& /*internalDepends*/)
{
// Make sure this is a scanning instance.
- if(sources.empty() || sources.begin()->empty())
- {
+ if (sources.empty() || sources.begin()->empty()) {
cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
- }
+ }
return true;
}
-bool cmDependsJava::CheckDependencies(std::istream&, const char*,
- std::map<std::string, DependencyVector >&)
+bool cmDependsJava::CheckDependencies(
+ std::istream& /*internalDepends*/, const char* /*internalDependsFileName*/,
+ std::map<std::string, DependencyVector>& /*validDeps*/)
{
return true;
}
diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h
index 22af53f8d..a07bf0979 100644
--- a/Source/cmDependsJava.h
+++ b/Source/cmDependsJava.h
@@ -1,44 +1,40 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDependsJava_h
#define cmDependsJava_h
+#include "cmConfigure.h"
+
#include "cmDepends.h"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+
/** \class cmDependsJava
* \brief Dependency scanner for Java class files.
*/
-class cmDependsJava: public cmDepends
+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. */
- virtual ~cmDependsJava();
+ ~cmDependsJava() CM_OVERRIDE;
protected:
// Implement writing/checking methods required by superclass.
- virtual bool WriteDependencies(
- const std::set<std::string>& sources, const std::string& file,
- std::ostream& makeDepends, std::ostream& internalDepends);
- virtual bool CheckDependencies(std::istream& internalDepends,
- const char* internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps);
-
-private:
- cmDependsJava(cmDependsJava const&); // Purposely not implemented.
- void operator=(cmDependsJava const&); // Purposely not implemented.
+ 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;
};
#endif
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index 6136baa84..7bc91bfd4 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -1,20 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDependsJavaParserHelper.h"
-#include "cmSystemTools.h"
+#include "cmConfigure.h"
+
#include "cmDependsJavaLexer.h"
+#include "cmSystemTools.h"
+
+#include "cmsys/FStream.hxx"
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-int cmDependsJava_yyparse( yyscan_t yyscanner );
+int cmDependsJava_yyparse(yyscan_t yyscanner);
cmDependsJavaParserHelper::cmDependsJavaParserHelper()
{
@@ -28,185 +27,152 @@ cmDependsJavaParserHelper::cmDependsJavaParserHelper()
this->ClassStack.push_back(tl);
}
-
cmDependsJavaParserHelper::~cmDependsJavaParserHelper()
{
this->CleanupParser();
}
-void cmDependsJavaParserHelper::CurrentClass
-::AddFileNamesForPrinting(std::vector<cmStdString> *files,
- const char* prefix, const char* sep)
+void cmDependsJavaParserHelper::CurrentClass::AddFileNamesForPrinting(
+ std::vector<std::string>* files, const char* prefix, const char* sep) const
{
- cmStdString rname = "";
- if ( prefix )
- {
+ std::string rname;
+ if (prefix) {
rname += prefix;
rname += sep;
- }
+ }
rname += this->Name;
files->push_back(rname);
- std::vector<CurrentClass>::iterator it;
- for ( it = this->NestedClasses->begin();
- it != this->NestedClasses->end();
- ++ it )
- {
+ std::vector<CurrentClass>::const_iterator it;
+ for (it = this->NestedClasses.begin(); it != this->NestedClasses.end();
+ ++it) {
it->AddFileNamesForPrinting(files, rname.c_str(), sep);
- }
+ }
}
void cmDependsJavaParserHelper::DeallocateParserType(char** pt)
{
- if (!pt)
- {
+ if (!pt) {
return;
- }
- if (!*pt)
- {
+ }
+ if (!*pt) {
return;
- }
- *pt = 0;
- this->UnionsAvailable --;
+ }
+ *pt = CM_NULLPTR;
+ this->UnionsAvailable--;
}
void cmDependsJavaParserHelper::AddClassFound(const char* sclass)
{
- if( ! sclass )
- {
+ if (!sclass) {
return;
- }
- std::vector<cmStdString>::iterator it;
- for ( it = this->ClassesFound.begin();
- it != this->ClassesFound.end();
- it ++ )
- {
- if ( *it == sclass )
- {
+ }
+ std::vector<std::string>::iterator it;
+ for (it = this->ClassesFound.begin(); it != this->ClassesFound.end(); it++) {
+ if (*it == sclass) {
return;
- }
}
+ }
this->ClassesFound.push_back(sclass);
}
void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass)
{
- std::vector<cmStdString>::iterator it;
- for ( it = this->PackagesImport.begin();
- it != this->PackagesImport.end();
- it ++ )
- {
- if ( *it == sclass )
- {
+ std::vector<std::string>::iterator it;
+ for (it = this->PackagesImport.begin(); it != this->PackagesImport.end();
+ it++) {
+ if (*it == sclass) {
return;
- }
}
+ }
this->PackagesImport.push_back(sclass);
}
-void cmDependsJavaParserHelper::SafePrintMissing(const char* str,
- int line, int cnt)
+void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line,
+ int cnt)
{
- if ( str )
- {
+ if (str) {
std::cout << line << " String " << cnt << " exists: ";
unsigned int cc;
- for ( cc = 0; cc < strlen(str); cc ++ )
- {
+ for (cc = 0; cc < strlen(str); cc++) {
unsigned char ch = str[cc];
- if ( ch >= 32 && ch <= 126 )
- {
+ if (ch >= 32 && ch <= 126) {
std::cout << (char)ch;
- }
- else
- {
+ } else {
std::cout << "<" << (int)ch << ">";
break;
- }
}
- std::cout << "- " << strlen(str) << std::endl;
}
+ std::cout << "- " << strlen(str) << std::endl;
+ }
}
void cmDependsJavaParserHelper::Print(const char* place, const char* str)
{
- if ( this->Verbose )
- {
+ if (this->Verbose) {
std::cout << "[" << place << "=" << str << "]" << std::endl;
- }
+ }
}
-void cmDependsJavaParserHelper::CombineUnions(char** out,
- const char* in1, char** in2,
- const char* sep)
+void cmDependsJavaParserHelper::CombineUnions(char** out, const char* in1,
+ char** in2, const char* sep)
{
size_t len = 1;
- if ( in1 )
- {
+ if (in1) {
len += strlen(in1);
- }
- if ( *in2 )
- {
+ }
+ if (*in2) {
len += strlen(*in2);
- }
- if ( sep )
- {
+ }
+ if (sep) {
len += strlen(sep);
- }
- *out = new char [ len ];
+ }
+ *out = new char[len];
*out[0] = 0;
- if ( in1 )
- {
+ if (in1) {
strcat(*out, in1);
- }
- if ( sep )
- {
+ }
+ if (sep) {
strcat(*out, sep);
- }
- if ( *in2 )
- {
+ }
+ if (*in2) {
strcat(*out, *in2);
- }
- if ( *in2 )
- {
+ }
+ if (*in2) {
this->DeallocateParserType(in2);
- }
- this->UnionsAvailable ++;
+ }
+ this->UnionsAvailable++;
}
-void cmDependsJavaParserHelper
-::CheckEmpty(int line, int cnt, cmDependsJavaParserHelper::ParserType* pt)
+void cmDependsJavaParserHelper::CheckEmpty(
+ int line, int cnt, cmDependsJavaParserHelper::ParserType* pt)
{
int cc;
int kk = -cnt + 1;
- for ( cc = 1; cc <= cnt; cc ++)
- {
+ for (cc = 1; cc <= cnt; cc++) {
cmDependsJavaParserHelper::ParserType* cpt = pt + kk;
this->SafePrintMissing(cpt->str, line, cc);
- kk ++;
- }
+ kk++;
+ }
}
-void cmDependsJavaParserHelper
-::PrepareElement(cmDependsJavaParserHelper::ParserType* me)
+void cmDependsJavaParserHelper::PrepareElement(
+ cmDependsJavaParserHelper::ParserType* me)
{
// Inititalize self
- me->str = 0;
+ me->str = CM_NULLPTR;
}
-void cmDependsJavaParserHelper
-::AllocateParserType(cmDependsJavaParserHelper::ParserType* pt,
- const char* str, int len)
+void cmDependsJavaParserHelper::AllocateParserType(
+ cmDependsJavaParserHelper::ParserType* pt, const char* str, int len)
{
- pt->str = 0;
- if ( len == 0 )
- {
+ pt->str = CM_NULLPTR;
+ if (len == 0) {
len = (int)strlen(str);
- }
- if ( len == 0 )
- {
+ }
+ if (len == 0) {
return;
- }
- this->UnionsAvailable ++;
- pt->str = new char[ len + 1 ];
+ }
+ this->UnionsAvailable++;
+ pt->str = new char[len + 1];
strncpy(pt->str, str, len);
pt->str[len] = 0;
this->Allocates.push_back(pt->str);
@@ -218,129 +184,100 @@ void cmDependsJavaParserHelper::StartClass(const char* cls)
cl.Name = cls;
this->ClassStack.push_back(cl);
- this->CurrentDepth ++;
+ this->CurrentDepth++;
}
void cmDependsJavaParserHelper::EndClass()
{
- CurrentClass* parent = 0;
- CurrentClass* current = 0;
- if ( this->ClassStack.size() > 0 )
- {
- current = &(*(this->ClassStack.end() - 1));
- if ( this->ClassStack.size() > 1 )
- {
- parent = &(*(this->ClassStack.end() - 2));
- }
- }
- if ( current == 0 )
- {
+ if (this->ClassStack.empty()) {
std::cerr << "Error when parsing. Current class is null" << std::endl;
abort();
- }
- if ( parent == 0 )
- {
+ }
+ if (this->ClassStack.size() <= 1) {
std::cerr << "Error when parsing. Parent class is null" << std::endl;
abort();
- }
- this->CurrentDepth --;
- parent->NestedClasses->push_back(*current);
- this->ClassStack.erase(this->ClassStack.end()-1, this->ClassStack.end());
+ }
+ CurrentClass& current = this->ClassStack.back();
+ CurrentClass& parent = this->ClassStack[this->ClassStack.size() - 2];
+ this->CurrentDepth--;
+ parent.NestedClasses.push_back(current);
+ this->ClassStack.pop_back();
}
void cmDependsJavaParserHelper::PrintClasses()
{
- if ( this->ClassStack.size() == 0 )
- {
+ if (this->ClassStack.empty()) {
std::cerr << "Error when parsing. No classes on class stack" << std::endl;
abort();
- }
- std::vector<cmStdString> files = this->GetFilesProduced();
- std::vector<cmStdString>::iterator sit;
- for ( sit = files.begin();
- sit != files.end();
- ++ sit )
- {
- std::cout << " " << sit->c_str() << ".class" << std::endl;
- }
+ }
+ 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;
+ }
}
-std::vector<cmStdString> cmDependsJavaParserHelper::GetFilesProduced()
+std::vector<std::string> cmDependsJavaParserHelper::GetFilesProduced()
{
- std::vector<cmStdString> files;
- CurrentClass* toplevel = &(*(this->ClassStack.begin()));
- std::vector<CurrentClass>::iterator it;
- for ( it = toplevel->NestedClasses->begin();
- it != toplevel->NestedClasses->end();
- ++ it )
- {
- it->AddFileNamesForPrinting(&files, 0, "$");
- }
+ 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, "$");
+ }
return files;
}
int cmDependsJavaParserHelper::ParseString(const char* str, int verb)
{
- if ( !str)
- {
+ if (!str) {
return 0;
- }
+ }
this->Verbose = verb;
this->InputBuffer = str;
this->InputBufferPos = 0;
this->CurrentLine = 0;
-
yyscan_t yyscanner;
cmDependsJava_yylex_init(&yyscanner);
cmDependsJava_yyset_extra(this, yyscanner);
int res = cmDependsJava_yyparse(yyscanner);
cmDependsJava_yylex_destroy(yyscanner);
- if ( res != 0 )
- {
+ if (res != 0) {
std::cout << "JP_Parse returned: " << res << std::endl;
return 0;
- }
+ }
- if ( verb )
- {
- if ( this->CurrentPackage.size() > 0 )
- {
- std::cout << "Current package is: " <<
- this->CurrentPackage.c_str() << std::endl;
- }
+ if (verb) {
+ if (!this->CurrentPackage.empty()) {
+ std::cout << "Current package is: " << this->CurrentPackage << std::endl;
+ }
std::cout << "Imports packages:";
- if ( this->PackagesImport.size() > 0 )
- {
- std::vector<cmStdString>::iterator it;
- for ( it = this->PackagesImport.begin();
- it != this->PackagesImport.end();
- ++ it )
- {
- std::cout << " " << it->c_str();
- }
+ if (!this->PackagesImport.empty()) {
+ std::vector<std::string>::iterator it;
+ for (it = this->PackagesImport.begin(); it != this->PackagesImport.end();
+ ++it) {
+ std::cout << " " << *it;
}
+ }
std::cout << std::endl;
std::cout << "Depends on:";
- if ( this->ClassesFound.size() > 0 )
- {
- std::vector<cmStdString>::iterator it;
- for ( it = this->ClassesFound.begin();
- it != this->ClassesFound.end();
- ++ it )
- {
- std::cout << " " << it->c_str();
- }
+ if (!this->ClassesFound.empty()) {
+ std::vector<std::string>::iterator it;
+ for (it = this->ClassesFound.begin(); it != this->ClassesFound.end();
+ ++it) {
+ std::cout << " " << *it;
}
+ }
std::cout << std::endl;
std::cout << "Generated files:" << std::endl;
this->PrintClasses();
- if ( this->UnionsAvailable != 0 )
- {
- std::cout << "There are still " <<
- this->UnionsAvailable << " unions available" << std::endl;
- }
+ if (this->UnionsAvailable != 0) {
+ std::cout << "There are still " << this->UnionsAvailable
+ << " unions available" << std::endl;
}
+ }
this->CleanupParser();
return 1;
}
@@ -348,82 +285,66 @@ 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;
- }
- this->Allocates.erase(this->Allocates.begin(),
- this->Allocates.end());
+ for (it = this->Allocates.begin(); it != this->Allocates.end(); ++it) {
+ delete[] * it;
+ }
+ this->Allocates.erase(this->Allocates.begin(), this->Allocates.end());
}
int cmDependsJavaParserHelper::LexInput(char* buf, int maxlen)
{
- if ( maxlen < 1 )
- {
+ if (maxlen < 1) {
return 0;
- }
- if ( this->InputBufferPos < this->InputBuffer.size() )
- {
- buf[0] = this->InputBuffer[ this->InputBufferPos++ ];
- if ( buf[0] == '\n' )
- {
- this->CurrentLine ++;
- }
- return(1);
- }
- else
- {
- buf[0] = '\n';
- return( 0 );
- }
+ }
+ if (this->InputBufferPos < this->InputBuffer.size()) {
+ buf[0] = this->InputBuffer[this->InputBufferPos++];
+ if (buf[0] == '\n') {
+ this->CurrentLine++;
+ }
+ return 1;
+ }
+ buf[0] = '\n';
+ return 0;
}
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);
+ 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 ++ )
- {
+ 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;
}
void cmDependsJavaParserHelper::UpdateCombine(const char* str1,
const char* str2)
{
- if ( this->CurrentCombine == "" && str1 != 0)
- {
+ if (this->CurrentCombine == "" && str1 != CM_NULLPTR) {
this->CurrentCombine = str1;
- }
+ }
this->CurrentCombine += ".";
this->CurrentCombine += str2;
}
int cmDependsJavaParserHelper::ParseFile(const char* file)
{
- if ( !cmSystemTools::FileExists(file))
- {
+ if (!cmSystemTools::FileExists(file)) {
return 0;
- }
- std::ifstream ifs(file);
- if ( !ifs )
- {
+ }
+ cmsys::ifstream ifs(file);
+ if (!ifs) {
return 0;
- }
+ }
- cmStdString fullfile = "";
- cmStdString line;
- while ( cmSystemTools::GetLineFromStream(ifs, line) )
- {
+ std::string fullfile;
+ std::string line;
+ while (cmSystemTools::GetLineFromStream(ifs, line)) {
fullfile += line + "\n";
- }
+ }
return this->ParseString(fullfile.c_str(), 0);
}
-
diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h
index 9807a048c..0b445d924 100644
--- a/Source/cmDependsJavaParserHelper.h
+++ b/Source/cmDependsJavaParserHelper.h
@@ -1,36 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmDependsJavaParserHelper_h
#define cmDependsJavaParserHelper_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#define YYSTYPE cmDependsJavaParserHelper::ParserType
-#define YYSTYPE_IS_DECLARED
-#define YY_EXTRA_TYPE cmDependsJavaParserHelper*
-#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+#include <string>
+#include <vector>
/** \class cmDependsJavaParserHelper
* \brief Helper class for parsing java source files
*
* Finds dependencies for java file and list of outputs
*/
-
class cmDependsJavaParserHelper
{
public:
- typedef struct {
+ struct ParserType
+ {
char* str;
- } ParserType;
+ };
cmDependsJavaParserHelper();
~cmDependsJavaParserHelper();
@@ -40,14 +29,14 @@ public:
// For the lexer:
void AllocateParserType(cmDependsJavaParserHelper::ParserType* pt,
- const char* str, int len = 0);
+ const char* str, int len = 0);
int LexInput(char* buf, int maxlen);
void Error(const char* str);
// For yacc
void AddClassFound(const char* sclass);
- void PrepareElement(ParserType* opt);
+ void PrepareElement(ParserType* me);
void DeallocateParserType(char** pt);
void CheckEmpty(int line, int cnt, ParserType* pt);
void StartClass(const char* cls);
@@ -59,50 +48,26 @@ public:
const char* GetCurrentCombine() { return this->CurrentCombine.c_str(); }
void UpdateCombine(const char* str1, const char* str2);
- std::vector<cmStdString>& GetClassesFound() { return this->ClassesFound; }
+ std::vector<std::string>& GetClassesFound() { return this->ClassesFound; }
- std::vector<cmStdString> GetFilesProduced();
+ std::vector<std::string> GetFilesProduced();
private:
class CurrentClass
{
public:
- cmStdString Name;
- std::vector<CurrentClass>* NestedClasses;
- CurrentClass()
- {
- this->NestedClasses = new std::vector<CurrentClass>;
- }
- ~CurrentClass()
- {
- delete this->NestedClasses;
- }
- CurrentClass& operator=(CurrentClass const& c)
- {
- this->NestedClasses->clear();
- this->Name = c.Name;
- std::copy(
- c.NestedClasses->begin(),
- c.NestedClasses->end(),
- std::back_inserter(
- *this->NestedClasses)
- );
- return *this;
- }
- CurrentClass(CurrentClass const& c)
- {
- (*this) = c;
- }
- void AddFileNamesForPrinting(std::vector<cmStdString> *files,
- const char* prefix, const char* sep);
+ std::string Name;
+ std::vector<CurrentClass> NestedClasses;
+ void AddFileNamesForPrinting(std::vector<std::string>* files,
+ const char* prefix, const char* sep) const;
};
- cmStdString CurrentPackage;
- cmStdString::size_type InputBufferPos;
- cmStdString InputBuffer;
+ std::string CurrentPackage;
+ std::string::size_type InputBufferPos;
+ std::string InputBuffer;
std::vector<char> OutputBuffer;
- std::vector<cmStdString> ClassesFound;
- std::vector<cmStdString> PackagesImport;
- cmStdString CurrentCombine;
+ std::vector<std::string> ClassesFound;
+ std::vector<std::string> PackagesImport;
+ std::string CurrentCombine;
std::vector<CurrentClass> ClassStack;
@@ -117,12 +82,15 @@ private:
void PrintClasses();
void Print(const char* place, const char* str);
- void CombineUnions(char** out, const char* in1, char** in2,
- const char* sep);
+ void CombineUnions(char** out, const char* in1, char** in2, const char* sep);
void SafePrintMissing(const char* str, int line, int cnt);
void CleanupParser();
};
-#endif
+#define YYSTYPE cmDependsJavaParserHelper::ParserType
+#define YYSTYPE_IS_DECLARED
+#define YY_EXTRA_TYPE cmDependsJavaParserHelper*
+#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+#endif
diff --git a/Source/cmDependsJavaParserTokens.h b/Source/cmDependsJavaParserTokens.h
deleted file mode 100644
index c7a414f07..000000000
--- a/Source/cmDependsJavaParserTokens.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d. */
-
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
- 1989, 1990, 2000, 2001, 2002, 2003, 2004 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- jp_ABSTRACT = 258,
- jp_ASSERT = 259,
- jp_BOOLEAN_TYPE = 260,
- jp_BREAK = 261,
- jp_BYTE_TYPE = 262,
- jp_CASE = 263,
- jp_CATCH = 264,
- jp_CHAR_TYPE = 265,
- jp_CLASS = 266,
- jp_CONTINUE = 267,
- jp_DEFAULT = 268,
- jp_DO = 269,
- jp_DOUBLE_TYPE = 270,
- jp_ELSE = 271,
- jp_EXTENDS = 272,
- jp_FINAL = 273,
- jp_FINALLY = 274,
- jp_FLOAT_TYPE = 275,
- jp_FOR = 276,
- jp_IF = 277,
- jp_IMPLEMENTS = 278,
- jp_IMPORT = 279,
- jp_INSTANCEOF = 280,
- jp_INT_TYPE = 281,
- jp_INTERFACE = 282,
- jp_LONG_TYPE = 283,
- jp_NATIVE = 284,
- jp_NEW = 285,
- jp_PACKAGE = 286,
- jp_PRIVATE = 287,
- jp_PROTECTED = 288,
- jp_PUBLIC = 289,
- jp_RETURN = 290,
- jp_SHORT_TYPE = 291,
- jp_STATIC = 292,
- jp_STRICTFP = 293,
- jp_SUPER = 294,
- jp_SWITCH = 295,
- jp_SYNCHRONIZED = 296,
- jp_THIS = 297,
- jp_THROW = 298,
- jp_THROWS = 299,
- jp_TRANSIENT = 300,
- jp_TRY = 301,
- jp_VOID = 302,
- jp_VOLATILE = 303,
- jp_WHILE = 304,
- jp_BOOLEANLITERAL = 305,
- jp_CHARACTERLITERAL = 306,
- jp_DECIMALINTEGERLITERAL = 307,
- jp_FLOATINGPOINTLITERAL = 308,
- jp_HEXINTEGERLITERAL = 309,
- jp_NULLLITERAL = 310,
- jp_STRINGLITERAL = 311,
- jp_NAME = 312,
- jp_AND = 313,
- jp_ANDAND = 314,
- jp_ANDEQUALS = 315,
- jp_BRACKETEND = 316,
- jp_BRACKETSTART = 317,
- jp_CARROT = 318,
- jp_CARROTEQUALS = 319,
- jp_COLON = 320,
- jp_COMMA = 321,
- jp_CURLYEND = 322,
- jp_CURLYSTART = 323,
- jp_DIVIDE = 324,
- jp_DIVIDEEQUALS = 325,
- jp_DOLLAR = 326,
- jp_DOT = 327,
- jp_EQUALS = 328,
- jp_EQUALSEQUALS = 329,
- jp_EXCLAMATION = 330,
- jp_EXCLAMATIONEQUALS = 331,
- jp_GREATER = 332,
- jp_GTEQUALS = 333,
- jp_GTGT = 334,
- jp_GTGTEQUALS = 335,
- jp_GTGTGT = 336,
- jp_GTGTGTEQUALS = 337,
- jp_LESLESEQUALS = 338,
- jp_LESSTHAN = 339,
- jp_LTEQUALS = 340,
- jp_LTLT = 341,
- jp_MINUS = 342,
- jp_MINUSEQUALS = 343,
- jp_MINUSMINUS = 344,
- jp_PAREEND = 345,
- jp_PARESTART = 346,
- jp_PERCENT = 347,
- jp_PERCENTEQUALS = 348,
- jp_PIPE = 349,
- jp_PIPEEQUALS = 350,
- jp_PIPEPIPE = 351,
- jp_PLUS = 352,
- jp_PLUSEQUALS = 353,
- jp_PLUSPLUS = 354,
- jp_QUESTION = 355,
- jp_SEMICOL = 356,
- jp_TILDE = 357,
- jp_TIMES = 358,
- jp_TIMESEQUALS = 359,
- jp_ERROR = 360
- };
-#endif
-#define jp_ABSTRACT 258
-#define jp_ASSERT 259
-#define jp_BOOLEAN_TYPE 260
-#define jp_BREAK 261
-#define jp_BYTE_TYPE 262
-#define jp_CASE 263
-#define jp_CATCH 264
-#define jp_CHAR_TYPE 265
-#define jp_CLASS 266
-#define jp_CONTINUE 267
-#define jp_DEFAULT 268
-#define jp_DO 269
-#define jp_DOUBLE_TYPE 270
-#define jp_ELSE 271
-#define jp_EXTENDS 272
-#define jp_FINAL 273
-#define jp_FINALLY 274
-#define jp_FLOAT_TYPE 275
-#define jp_FOR 276
-#define jp_IF 277
-#define jp_IMPLEMENTS 278
-#define jp_IMPORT 279
-#define jp_INSTANCEOF 280
-#define jp_INT_TYPE 281
-#define jp_INTERFACE 282
-#define jp_LONG_TYPE 283
-#define jp_NATIVE 284
-#define jp_NEW 285
-#define jp_PACKAGE 286
-#define jp_PRIVATE 287
-#define jp_PROTECTED 288
-#define jp_PUBLIC 289
-#define jp_RETURN 290
-#define jp_SHORT_TYPE 291
-#define jp_STATIC 292
-#define jp_STRICTFP 293
-#define jp_SUPER 294
-#define jp_SWITCH 295
-#define jp_SYNCHRONIZED 296
-#define jp_THIS 297
-#define jp_THROW 298
-#define jp_THROWS 299
-#define jp_TRANSIENT 300
-#define jp_TRY 301
-#define jp_VOID 302
-#define jp_VOLATILE 303
-#define jp_WHILE 304
-#define jp_BOOLEANLITERAL 305
-#define jp_CHARACTERLITERAL 306
-#define jp_DECIMALINTEGERLITERAL 307
-#define jp_FLOATINGPOINTLITERAL 308
-#define jp_HEXINTEGERLITERAL 309
-#define jp_NULLLITERAL 310
-#define jp_STRINGLITERAL 311
-#define jp_NAME 312
-#define jp_AND 313
-#define jp_ANDAND 314
-#define jp_ANDEQUALS 315
-#define jp_BRACKETEND 316
-#define jp_BRACKETSTART 317
-#define jp_CARROT 318
-#define jp_CARROTEQUALS 319
-#define jp_COLON 320
-#define jp_COMMA 321
-#define jp_CURLYEND 322
-#define jp_CURLYSTART 323
-#define jp_DIVIDE 324
-#define jp_DIVIDEEQUALS 325
-#define jp_DOLLAR 326
-#define jp_DOT 327
-#define jp_EQUALS 328
-#define jp_EQUALSEQUALS 329
-#define jp_EXCLAMATION 330
-#define jp_EXCLAMATIONEQUALS 331
-#define jp_GREATER 332
-#define jp_GTEQUALS 333
-#define jp_GTGT 334
-#define jp_GTGTEQUALS 335
-#define jp_GTGTGT 336
-#define jp_GTGTGTEQUALS 337
-#define jp_LESLESEQUALS 338
-#define jp_LESSTHAN 339
-#define jp_LTEQUALS 340
-#define jp_LTLT 341
-#define jp_MINUS 342
-#define jp_MINUSEQUALS 343
-#define jp_MINUSMINUS 344
-#define jp_PAREEND 345
-#define jp_PARESTART 346
-#define jp_PERCENT 347
-#define jp_PERCENTEQUALS 348
-#define jp_PIPE 349
-#define jp_PIPEEQUALS 350
-#define jp_PIPEPIPE 351
-#define jp_PLUS 352
-#define jp_PLUSEQUALS 353
-#define jp_PLUSPLUS 354
-#define jp_QUESTION 355
-#define jp_SEMICOL 356
-#define jp_TILDE 357
-#define jp_TIMES 358
-#define jp_TIMESEQUALS 359
-#define jp_ERROR 360
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-
-
diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx
new file mode 100644
index 000000000..ce1965d30
--- /dev/null
+++ b/Source/cmDisallowedCommand.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 "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
new file mode 100644
index 000000000..0030116b8
--- /dev/null
+++ b/Source/cmDisallowedCommand.h
@@ -0,0 +1,51 @@
+/* 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/cmDocumentCompileDefinitions.h b/Source/cmDocumentCompileDefinitions.h
deleted file mode 100644
index d15bd6dca..000000000
--- a/Source/cmDocumentCompileDefinitions.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDocumentCompileDefinitions_h
-#define cmDocumentCompileDefinitions_h
-
-#define CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER \
- "Disclaimer: Most native build tools have poor support for escaping " \
- "certain values. CMake has work-arounds for many cases but some " \
- "values may just not be possible to pass correctly. If a value " \
- "does not seem to be escaped correctly, do not attempt to " \
- "work-around the problem by adding escape sequences to the value. " \
- "Your work-around may break in a future version of CMake that " \
- "has improved escape support. Instead consider defining the macro " \
- "in a (configured) header file. Then report the limitation. " \
- "Known limitations include:\n" \
- " # - broken almost everywhere\n" \
- " ; - broken in VS IDE 7.0 and Borland Makefiles\n" \
- " , - broken in VS IDE\n" \
- " % - broken in some cases in NMake\n" \
- " & | - broken in some cases on MinGW\n" \
- " ^ < > \\\" - broken in most Make tools on Windows\n" \
- "CMake does not reject these values outright because they do work " \
- "in some cases. Use with caution. "
-
-#endif
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
deleted file mode 100644
index 46cd77eae..000000000
--- a/Source/cmDocumentGeneratorExpressions.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDocumentGeneratorExpressions_h
-#define cmDocumentGeneratorExpressions_h
-
-#define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
- "Generator expressions are evaluated during build system generation " \
- "to produce information specific to each build configuration. " \
- "Valid expressions are:\n" \
- " $<0:...> = empty string (ignores \"...\")\n" \
- " $<1:...> = content of \"...\"\n" \
- " $<CONFIG:cfg> = '1' if config is \"cfg\", else '0'\n" \
- " $<CONFIGURATION> = configuration name\n" \
- " $<BOOL:...> = '1' if the '...' is true, else '0'\n" \
- " $<STREQUAL:a,b> = '1' if a is STREQUAL b, else '0'\n" \
- " $<ANGLE-R> = A literal '>'. Used to compare " \
- "strings which contain a '>' for example.\n" \
- " $<COMMA> = A literal ','. Used to compare " \
- "strings which contain a ',' for example.\n" \
- " $<SEMICOLON> = A literal ';'. Used to prevent " \
- "list expansion on an argument with ';'.\n" \
- " $<JOIN:list,...> = joins the list with the content of " \
- "\"...\"\n" \
- " $<TARGET_NAME:...> = Marks ... as being the name of a " \
- "target. This is required if exporting targets to multiple " \
- "dependent export sets. The '...' must be a literal name of a " \
- "target- it may not contain generator expressions.\n" \
- " $<INSTALL_INTERFACE:...> = content of \"...\" when the property " \
- "is exported using install(EXPORT), and empty otherwise.\n" \
- " $<BUILD_INTERFACE:...> = content of \"...\" when the property " \
- "is exported using export(), or when the target is used by another " \
- "target in the same buildsystem. Expands to the empty string " \
- "otherwise.\n" \
- " $<C_COMPILER_ID> = The CMake-id of the C compiler " \
- "used.\n" \
- " $<C_COMPILER_ID:comp> = '1' if the CMake-id of the C " \
- "compiler matches comp, otherwise '0'.\n" \
- " $<CXX_COMPILER_ID> = The CMake-id of the CXX compiler " \
- "used.\n" \
- " $<CXX_COMPILER_ID:comp> = '1' if the CMake-id of the CXX " \
- "compiler matches comp, otherwise '0'.\n" \
- " $<VERSION_GREATER:v1,v2> = '1' if v1 is a version greater than " \
- "v2, else '0'.\n" \
- " $<VERSION_LESS:v1,v2> = '1' if v1 is a version less than v2, " \
- "else '0'.\n" \
- " $<VERSION_EQUAL:v1,v2> = '1' if v1 is the same version as v2, " \
- "else '0'.\n" \
- " $<C_COMPILER_VERSION> = The version of the C compiler used.\n" \
- " $<C_COMPILER_VERSION:ver> = '1' if the version of the C " \
- "compiler matches ver, otherwise '0'.\n" \
- " $<CXX_COMPILER_VERSION> = The version of the CXX compiler " \
- "used.\n" \
- " $<CXX_COMPILER_VERSION:ver> = '1' if the version of the CXX " \
- "compiler matches ver, otherwise '0'.\n" \
- " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
- " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
- " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
- "where \"tgt\" is the name of a target. " \
- "Target file expressions produce a full path, but _DIR and _NAME " \
- "versions can produce the directory and file name components:\n" \
- " $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \
- " $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
- " $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
- "\n" \
- " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop " \
- "on the target tgt.\n" \
- "Note that tgt is not added as a dependency of the target this " \
- "expression is evaluated on.\n" \
- " $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \
- "the 'head' target was created, else '0'. If the policy was not " \
- "set, the warning message for the policy will be emitted. This " \
- "generator expression only works for a subset of policies.\n" \
- " $<INSTALL_PREFIX> = Content of the install prefix when " \
- "the target is exported via INSTALL(EXPORT) and empty otherwise.\n" \
- "Boolean expressions:\n" \
- " $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
- " $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
- " $<NOT:?> = '0' if '?' is '1', else '1'\n" \
- "where '?' is always either '0' or '1'.\n" \
- ""
-
-#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
- CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
- "Expressions with an implicit 'this' target:\n" \
- " $<TARGET_PROPERTY:prop> = The value of the property prop on " \
- "the target on which the generator expression is evaluated.\n" \
- ""
-
-#endif
diff --git a/Source/cmDocumentLocationUndefined.h b/Source/cmDocumentLocationUndefined.h
deleted file mode 100644
index 9aecf2163..000000000
--- a/Source/cmDocumentLocationUndefined.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDocumentLocationUndefined_h
-#define cmDocumentLocationUndefined_h
-
-#define CM_LOCATION_UNDEFINED_BEHAVIOR(action) \
- "\n" \
- "Do not set properties that affect the location of a target after " \
- action ". These include properties whose names match " \
- "\"(RUNTIME|LIBRARY|ARCHIVE)_OUTPUT_(NAME|DIRECTORY)(_<CONFIG>)?\", " \
- "\"(IMPLIB_)?(PREFIX|SUFFIX)\", or \"LINKER_LANGUAGE\". " \
- "Failure to follow this rule is not diagnosed and leaves the location " \
- "of the target undefined."
-
-#endif
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
deleted file mode 100644
index c4f6216b6..000000000
--- a/Source/cmDocumentVariables.cxx
+++ /dev/null
@@ -1,2030 +0,0 @@
-#include "cmDocumentVariables.h"
-#include "cmake.h"
-
-#include <cmsys/ios/sstream>
-
-void cmDocumentVariables::DefineVariables(cmake* cm)
-{
- // Subsection: variables defined by cmake, that give
- // information about the project, and cmake
- cm->DefineProperty
- ("CMAKE_AR", cmProperty::VARIABLE,
- "Name of archiving tool for static libraries.",
- "This specifies the name of the program that creates archive "
- "or static libraries.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_COMMAND", cmProperty::VARIABLE,
- "The full path to the cmake executable.",
- "This is the full path to the CMake executable cmake which is "
- "useful from custom commands that want to use the cmake -E "
- "option for portable system commands. "
- "(e.g. /usr/local/bin/cmake", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_BINARY_DIR", cmProperty::VARIABLE,
- "The path to the top level of the build tree.",
- "This is the full path to the top level of the current CMake "
- "build tree. For an in-source build, this would be the same "
- "as CMAKE_SOURCE_DIR.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SOURCE_DIR", cmProperty::VARIABLE,
- "The path to the top level of the source tree.",
- "This is the full path to the top level of the current CMake "
- "source tree. For an in-source build, this would be the same "
- "as CMAKE_BINARY_DIR.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_CURRENT_BINARY_DIR", cmProperty::VARIABLE,
- "The path to the binary directory currently being processed.",
- "This the full path to the build directory that is currently "
- "being processed by cmake. Each directory added by "
- "add_subdirectory will create a binary directory in the build "
- "tree, and as it is being processed this variable will be set. "
- "For in-source builds this is the current source directory "
- "being processed.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_CURRENT_SOURCE_DIR", cmProperty::VARIABLE,
- "The path to the source directory currently being processed.",
- "This the full path to the source directory that is currently "
- "being processed by cmake. ", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_CURRENT_LIST_FILE", cmProperty::VARIABLE,
- "Full path to the listfile currently being processed.",
- "As CMake processes the listfiles in your project this "
- "variable will always be set to the one currently being "
- "processed. "
- "The value has dynamic scope. "
- "When CMake starts processing commands in a source file "
- "it sets this variable to the location of the file. "
- "When CMake finishes processing commands from the file it "
- "restores the previous value. "
- "Therefore the value of the variable inside a macro or "
- "function is the file invoking the bottom-most entry on "
- "the call stack, not the file containing the macro or "
- "function definition."
- "\n"
- "See also CMAKE_PARENT_LIST_FILE.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_CURRENT_LIST_LINE", cmProperty::VARIABLE,
- "The line number of the current file being processed.",
- "This is the line number of the file currently being"
- " processed by cmake.", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_CURRENT_LIST_DIR", cmProperty::VARIABLE,
- "Full directory of the listfile currently being processed.",
- "As CMake processes the listfiles in your project this "
- "variable will always be set to the directory where the listfile which "
- "is currently being processed (CMAKE_CURRENT_LIST_FILE) is located. "
- "The value has dynamic scope. "
- "When CMake starts processing commands in a source file "
- "it sets this variable to the directory where this file is located. "
- "When CMake finishes processing commands from the file it "
- "restores the previous value. "
- "Therefore the value of the variable inside a macro or "
- "function is the directory of the file invoking the bottom-most entry on "
- "the call stack, not the directory of the file containing the macro or "
- "function definition."
- "\n"
- "See also CMAKE_CURRENT_LIST_FILE.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_SCRIPT_MODE_FILE", cmProperty::VARIABLE,
- "Full path to the -P script file currently being processed.",
- "When run in -P script mode, CMake sets this variable to the full "
- "path of the script file. When run to configure a CMakeLists.txt "
- "file, this variable is not set.", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_ARGC", cmProperty::VARIABLE,
- "Number of command line arguments passed to CMake in script mode.",
- "When run in -P script mode, CMake sets this variable to the number "
- "of command line arguments. See also CMAKE_ARGV0, 1, 2 ...", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_ARGV0", cmProperty::VARIABLE,
- "Command line argument passed to CMake in script mode.",
- "When run in -P script mode, CMake sets this variable to "
- "the first command line argument. It then also sets CMAKE_ARGV1, "
- "CMAKE_ARGV2, ... and so on, up to the number of command line arguments "
- "given. See also CMAKE_ARGC.", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_BUILD_TOOL", cmProperty::VARIABLE,
- "Tool used for the actual build process.",
- "This variable is set to the program that will be"
- " needed to build the output of CMake. If the "
- "generator selected was Visual Studio 6, the "
- "CMAKE_BUILD_TOOL will be set to msdev, for "
- "Unix Makefiles it will be set to make or gmake, "
- "and for Visual Studio 7 it set to devenv. For "
- "NMake Makefiles the value is nmake. This can be "
- "useful for adding special flags and commands based"
- " on the final build environment.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_CROSSCOMPILING", cmProperty::VARIABLE,
- "Is CMake currently cross compiling.",
- "This variable will be set to true by CMake if CMake is cross "
- "compiling. Specifically if the build platform is different "
- "from the target platform.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_CACHEFILE_DIR", cmProperty::VARIABLE,
- "The directory with the CMakeCache.txt file.",
- "This is the full path to the directory that has the "
- "CMakeCache.txt file in it. This is the same as "
- "CMAKE_BINARY_DIR.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_CACHE_MAJOR_VERSION", cmProperty::VARIABLE,
- "Major version of CMake used to create the CMakeCache.txt file",
- "This stores the major version of CMake used to "
- "write a CMake cache file. It is only different when "
- "a different version of CMake is run on a previously "
- "created cache file.", false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_CACHE_MINOR_VERSION", cmProperty::VARIABLE,
- "Minor version of CMake used to create the CMakeCache.txt file",
- "This stores the minor version of CMake used to "
- "write a CMake cache file. It is only different when "
- "a different version of CMake is run on a previously "
- "created cache file.", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_CACHE_PATCH_VERSION", cmProperty::VARIABLE,
- "Patch version of CMake used to create the CMakeCache.txt file",
- "This stores the patch version of CMake used to "
- "write a CMake cache file. It is only different when "
- "a different version of CMake is run on a previously "
- "created cache file.", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_CFG_INTDIR", cmProperty::VARIABLE,
- "Build-time reference to per-configuration output subdirectory.",
- "For native build systems supporting multiple configurations "
- "in the build tree (such as Visual Studio and Xcode), "
- "the value is a reference to a build-time variable specifying "
- "the name of the per-configuration output subdirectory. "
- "On Makefile generators this evaluates to \".\" because there "
- "is only one configuration in a build tree. "
- "Example values:\n"
- " $(IntDir) = Visual Studio 6\n"
- " $(OutDir) = Visual Studio 7, 8, 9\n"
- " $(Configuration) = Visual Studio 10\n"
- " $(CONFIGURATION) = Xcode\n"
- " . = Make-based tools\n"
- "Since these values are evaluated by the native build system, this "
- "variable is suitable only for use in command lines that will be "
- "evaluated at build time. "
- "Example of intended usage:\n"
- " add_executable(mytool mytool.c)\n"
- " add_custom_command(\n"
- " OUTPUT out.txt\n"
- " COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mytool\n"
- " ${CMAKE_CURRENT_SOURCE_DIR}/in.txt out.txt\n"
- " DEPENDS mytool in.txt\n"
- " )\n"
- " add_custom_target(drive ALL DEPENDS out.txt)\n"
- "Note that CMAKE_CFG_INTDIR is no longer necessary for this purpose "
- "but has been left for compatibility with existing projects. "
- "Instead add_custom_command() recognizes executable target names in "
- "its COMMAND option, so "
- "\"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mytool\" can be "
- "replaced by just \"mytool\"."
- "\n"
- "This variable is read-only. Setting it is undefined behavior. "
- "In multi-configuration build systems the value of this variable "
- "is passed as the value of preprocessor symbol \"CMAKE_INTDIR\" to "
- "the compilation of all source files.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_CTEST_COMMAND", cmProperty::VARIABLE,
- "Full path to ctest command installed with cmake.",
- "This is the full path to the CTest executable ctest "
- "which is useful from custom commands that want "
- "to use the cmake -E option for portable system "
- "commands.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_DL_LIBS", cmProperty::VARIABLE,
- "Name of library containing dlopen and dlcose.",
- "The name of the library that has dlopen and "
- "dlclose in it, usually -ldl on most UNIX machines.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_EDIT_COMMAND", cmProperty::VARIABLE,
- "Full path to cmake-gui or ccmake.",
- "This is the full path to the CMake executable "
- "that can graphically edit the cache. For example,"
- " cmake-gui, ccmake, or cmake -i.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_GENERATOR", cmProperty::VARIABLE,
- "The generator used to build the project.",
- "The name of the generator that is being used to generate the "
- "build files. (e.g. \"Unix Makefiles\", "
- "\"Visual Studio 6\", etc.)",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_EXTRA_GENERATOR", cmProperty::VARIABLE,
- "The extra generator used to build the project.",
- "When using the Eclipse, CodeBlocks or KDevelop generators, CMake "
- "generates Makefiles (CMAKE_GENERATOR) and additionally project files "
- "for the respective IDE. This IDE project file generator is stored in "
- "CMAKE_EXTRA_GENERATOR (e.g. \"Eclipse CDT4\").",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_GENERATOR_TOOLSET", cmProperty::VARIABLE,
- "Native build system toolset name specified by user.",
- "Some CMake generators support a toolset name to be given to the "
- "native build system to choose a compiler. "
- "If the user specifies a toolset name (e.g. via the cmake -T option) "
- "the value will be available in this variable.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_HOME_DIRECTORY", cmProperty::VARIABLE,
- "Path to top of source tree.",
- "This is the path to the top level of the source tree.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_LINK_LIBRARY_SUFFIX", cmProperty::VARIABLE,
- "The suffix for libraries that you link to.",
- "The suffix to use for the end of a library filename, .lib on Windows."
- ,false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_EXECUTABLE_SUFFIX", cmProperty::VARIABLE,
- "The suffix for executables on this platform.",
- "The suffix to use for the end of an executable filename if any, "
- ".exe on Windows."
- "\n"
- "CMAKE_EXECUTABLE_SUFFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_MAJOR_VERSION", cmProperty::VARIABLE,
- "The Major version of cmake (i.e. the 2 in 2.X.X)",
- "This specifies the major version of the CMake executable"
- " being run.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_MAKE_PROGRAM", cmProperty::VARIABLE,
- "See CMAKE_BUILD_TOOL.",
- "This variable is around for backwards compatibility, "
- "see CMAKE_BUILD_TOOL.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_VS_PLATFORM_TOOLSET", cmProperty::VARIABLE,
- "Visual Studio Platform Toolset name.",
- "VS 10 and above use MSBuild under the hood and support multiple "
- "compiler toolchains. "
- "CMake may specify a toolset explicitly, such as \"v110\" for "
- "VS 11 or \"Windows7.1SDK\" for 64-bit support in VS 10 Express. "
- "CMake provides the name of the chosen toolset in this variable."
- ,false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_XCODE_PLATFORM_TOOLSET", cmProperty::VARIABLE,
- "Xcode compiler selection.",
- "Xcode supports selection of a compiler from one of the installed "
- "toolsets. "
- "CMake provides the name of the chosen toolset in this variable, "
- "if any is explicitly selected (e.g. via the cmake -T option)."
- ,false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_MINOR_VERSION", cmProperty::VARIABLE,
- "The Minor version of cmake (i.e. the 4 in X.4.X).",
- "This specifies the minor version of the CMake"
- " executable being run.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_PATCH_VERSION", cmProperty::VARIABLE,
- "The patch version of cmake (i.e. the 3 in X.X.3).",
- "This specifies the patch version of the CMake"
- " executable being run.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_TWEAK_VERSION", cmProperty::VARIABLE,
- "The tweak version of cmake (i.e. the 1 in X.X.X.1).",
- "This specifies the tweak version of the CMake executable being run. "
- "Releases use tweak < 20000000 and development versions use the date "
- "format CCYYMMDD for the tweak level."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_VERSION", cmProperty::VARIABLE,
- "The full version of cmake in major.minor.patch[.tweak[-id]] format.",
- "This specifies the full version of the CMake executable being run. "
- "This variable is defined by versions 2.6.3 and higher. "
- "See variables CMAKE_MAJOR_VERSION, CMAKE_MINOR_VERSION, "
- "CMAKE_PATCH_VERSION, and CMAKE_TWEAK_VERSION "
- "for individual version components. "
- "The [-id] component appears in non-release versions "
- "and may be arbitrary text.", false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_PARENT_LIST_FILE", cmProperty::VARIABLE,
- "Full path to the CMake file that included the current one.",
- "While processing a CMake file loaded by include() or find_package() "
- "this variable contains the full path to the file including it. "
- "The top of the include stack is always the CMakeLists.txt for the "
- "current directory. "
- "See also CMAKE_CURRENT_LIST_FILE.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_PROJECT_NAME", cmProperty::VARIABLE,
- "The name of the current project.",
- "This specifies name of the current project from"
- " the closest inherited PROJECT command.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_RANLIB", cmProperty::VARIABLE,
- "Name of randomizing tool for static libraries.",
- "This specifies name of the program that randomizes "
- "libraries on UNIX, not used on Windows, but may be present.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_ROOT", cmProperty::VARIABLE,
- "Install directory for running cmake.",
- "This is the install root for the running CMake and"
- " the Modules directory can be found here. This is"
- " commonly used in this format: ${CMAKE_ROOT}/Modules",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SIZEOF_VOID_P", cmProperty::VARIABLE,
- "Size of a void pointer.",
- "This is set to the size of a pointer on the machine, "
- "and is determined by a try compile. If a 64 bit size "
- "is found, then the library search path is modified to "
- "look for 64 bit libraries first.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SKIP_RPATH", cmProperty::VARIABLE,
- "If true, do not add run time path information.",
- "If this is set to TRUE, then the rpath information "
- "is not added to compiled executables. The default "
- "is to add rpath information if the platform supports it. "
- "This allows for easy running from the build tree. To omit RPATH "
- "in the install step, but not the build step, use "
- "CMAKE_SKIP_INSTALL_RPATH instead.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SOURCE_DIR", cmProperty::VARIABLE,
- "Source directory for project.",
- "This is the top level source directory for the project. "
- "It corresponds to the source directory given to "
- "cmake-gui or ccmake.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_STANDARD_LIBRARIES", cmProperty::VARIABLE,
- "Libraries linked into every executable and shared library.",
- "This is the list of libraries that are linked "
- "into all executables and libraries.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_VERBOSE_MAKEFILE", cmProperty::VARIABLE,
- "Create verbose makefiles if on.",
- "This variable defaults to false. You can set "
- "this variable to true to make CMake produce verbose "
- "makefiles that show each command line as it is used.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("PROJECT_BINARY_DIR", cmProperty::VARIABLE,
- "Full path to build directory for project.",
- "This is the binary directory of the most recent "
- "PROJECT command.",false,"Variables that Provide Information");
- cm->DefineProperty
- ("PROJECT_NAME", cmProperty::VARIABLE,
- "Name of the project given to the project command.",
- "This is the name given to the most "
- "recent PROJECT command.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("PROJECT_SOURCE_DIR", cmProperty::VARIABLE,
- "Top level source directory for the current project.",
- "This is the source directory of the most recent "
- "PROJECT command.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("[Project name]_BINARY_DIR", cmProperty::VARIABLE,
- "Top level binary directory for the named project.",
- "A variable is created with the name used in the PROJECT "
- "command, and is the binary directory for the project. "
- " This can be useful when SUBDIR is used to connect "
- "several projects.",false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("[Project name]_SOURCE_DIR", cmProperty::VARIABLE,
- "Top level source directory for the named project.",
- "A variable is created with the name used in the PROJECT "
- "command, and is the source directory for the project."
- " This can be useful when add_subdirectory "
- "is used to connect several projects.",false,
- "Variables that Provide Information");
-
- cm->DefineProperty
- ("CMAKE_IMPORT_LIBRARY_PREFIX", cmProperty::VARIABLE,
- "The prefix for import libraries that you link to.",
- "The prefix to use for the name of an import library if used "
- "on this platform."
- "\n"
- "CMAKE_IMPORT_LIBRARY_PREFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_IMPORT_LIBRARY_SUFFIX", cmProperty::VARIABLE,
- "The suffix for import libraries that you link to.",
- "The suffix to use for the end of an import library filename if used "
- "on this platform."
- "\n"
- "CMAKE_IMPORT_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SHARED_LIBRARY_PREFIX", cmProperty::VARIABLE,
- "The prefix for shared libraries that you link to.",
- "The prefix to use for the name of a shared library, lib on UNIX."
- "\n"
- "CMAKE_SHARED_LIBRARY_PREFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SHARED_LIBRARY_SUFFIX", cmProperty::VARIABLE,
- "The suffix for shared libraries that you link to.",
- "The suffix to use for the end of a shared library filename, "
- ".dll on Windows."
- "\n"
- "CMAKE_SHARED_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SHARED_MODULE_PREFIX", cmProperty::VARIABLE,
- "The prefix for loadable modules that you link to.",
- "The prefix to use for the name of a loadable module on this platform."
- "\n"
- "CMAKE_SHARED_MODULE_PREFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_SHARED_MODULE_SUFFIX", cmProperty::VARIABLE,
- "The suffix for shared libraries that you link to.",
- "The suffix to use for the end of a loadable module filename "
- "on this platform"
- "\n"
- "CMAKE_SHARED_MODULE_SUFFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_STATIC_LIBRARY_PREFIX", cmProperty::VARIABLE,
- "The prefix for static libraries that you link to.",
- "The prefix to use for the name of a static library, lib on UNIX."
- "\n"
- "CMAKE_STATIC_LIBRARY_PREFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_STATIC_LIBRARY_SUFFIX", cmProperty::VARIABLE,
- "The suffix for static libraries that you link to.",
- "The suffix to use for the end of a static library filename, "
- ".lib on Windows."
- "\n"
- "CMAKE_STATIC_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>."
- ,false, "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES", cmProperty::VARIABLE,
- "Additional suffixes for shared libraries.",
- "Extensions for shared libraries other than that specified by "
- "CMAKE_SHARED_LIBRARY_SUFFIX, if any. "
- "CMake uses this to recognize external shared library files during "
- "analysis of libraries linked by a target.",
- false,
- "Variables that Provide Information");
- cm->DefineProperty
- ("CMAKE_MINIMUM_REQUIRED_VERSION", cmProperty::VARIABLE,
- "Version specified to cmake_minimum_required command",
- "Variable containing the VERSION component specified in the "
- "cmake_minimum_required command.",
- false,
- "Variables that Provide Information");
-
-
- // Variables defined by cmake, that change the behavior
- // of cmake
-
- cm->DefineProperty
- ("CMAKE_POLICY_DEFAULT_CMP<NNNN>", cmProperty::VARIABLE,
- "Default for CMake Policy CMP<NNNN> when it is otherwise left unset.",
- "Commands cmake_minimum_required(VERSION) and cmake_policy(VERSION) "
- "by default leave policies introduced after the given version unset. "
- "Set CMAKE_POLICY_DEFAULT_CMP<NNNN> to OLD or NEW to specify the "
- "default for policy CMP<NNNN>, where <NNNN> is the policy number."
- "\n"
- "This variable should not be set by a project in CMake code; "
- "use cmake_policy(SET) instead. "
- "Users running CMake may set this variable in the cache "
- "(e.g. -DCMAKE_POLICY_DEFAULT_CMP<NNNN>=<OLD|NEW>) "
- "to set a policy not otherwise set by the project. "
- "Set to OLD to quiet a policy warning while using old behavior "
- "or to NEW to try building the project with new behavior.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_AUTOMOC_RELAXED_MODE", cmProperty::VARIABLE,
- "Switch between strict and relaxed automoc mode.",
- "By default, automoc behaves exactly as described in the documentation "
- "of the AUTOMOC target property. "
- "When set to TRUE, it accepts more input and tries to find the correct "
- "input file for moc even if it differs from the documented behaviour. "
- "In this mode it e.g. also checks whether a header file is intended to "
- "be processed by moc when a \"foo.moc\" file has been included.\n"
- "Relaxed mode has to be enabled for KDE4 compatibility.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME", cmProperty::VARIABLE,
- "Default component used in install() commands.",
- "If an install() command is used without the COMPONENT argument, "
- "these files will be grouped into a default component. The name of this "
- "default install component will be taken from this variable. "
- "It defaults to \"Unspecified\".",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_FIND_LIBRARY_PREFIXES", cmProperty::VARIABLE,
- "Prefixes to prepend when looking for libraries.",
- "This specifies what prefixes to add to library names when "
- "the find_library command looks for libraries. On UNIX "
- "systems this is typically lib, meaning that when trying "
- "to find the foo library it will look for libfoo.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_FIND_LIBRARY_SUFFIXES", cmProperty::VARIABLE,
- "Suffixes to append when looking for libraries.",
- "This specifies what suffixes to add to library names when "
- "the find_library command looks for libraries. On Windows "
- "systems this is typically .lib and .dll, meaning that when trying "
- "to find the foo library it will look for foo.dll etc.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_CONFIGURATION_TYPES", cmProperty::VARIABLE,
- "Specifies the available build types on multi-config generators.",
- "This specifies what build types (configurations) will be available "
- "such as Debug, Release, RelWithDebInfo etc. "
- "This has reasonable defaults on most platforms, "
- "but can be extended to provide other build types. "
- "See also CMAKE_BUILD_TYPE for details of managing configuration data, "
- "and CMAKE_CFG_INTDIR."
- ,false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_BUILD_TYPE", cmProperty::VARIABLE,
- "Specifies the build type on single-configuration generators.",
- "This statically specifies what build type (configuration) "
- "will be built in this build tree. Possible values are "
- "empty, Debug, Release, RelWithDebInfo and MinSizeRel. "
- "This variable is only meaningful to single-configuration generators "
- "(such as make and Ninja) i.e. "
- "those which choose a single configuration "
- "when CMake runs to generate a build tree as opposed to "
- "multi-configuration generators which offer selection of the build "
- "configuration within the generated build environment. "
- "There are many per-config properties and variables "
- "(usually following clean SOME_VAR_<CONFIG> order conventions), "
- "such as CMAKE_C_FLAGS_<CONFIG>, specified as uppercase: "
- "CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL]. "
- "For example, in a build tree configured "
- "to build type Debug, CMake will see to having "
- "CMAKE_C_FLAGS_DEBUG settings get added to the CMAKE_C_FLAGS settings. "
- "See also CMAKE_CONFIGURATION_TYPES."
- ,false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_BACKWARDS_COMPATIBILITY", cmProperty::VARIABLE,
- "Version of cmake required to build project",
- "From the point of view of backwards compatibility, this "
- "specifies what version of CMake should be supported. By "
- "default this value is the version number of CMake that "
- "you are running. You can set this to an older version of"
- " CMake to support deprecated commands of CMake in projects"
- " that were written to use older versions of CMake. This "
- "can be set by the user or set at the beginning of a "
- "CMakeLists file.",false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_INSTALL_PREFIX", cmProperty::VARIABLE,
- "Install directory used by install.",
- "If \"make install\" is invoked or INSTALL is built"
- ", this directory is prepended onto all install "
- "directories. This variable defaults to /usr/local"
- " on UNIX and c:/Program Files on Windows.\n"
- "On UNIX one can use the DESTDIR mechanism in order"
- " to relocate the whole installation. "
- "DESTDIR means DESTination DIRectory. It is "
- "commonly used by makefile users "
- "in order to install software at non-default location. "
- "It is usually invoked like this:\n"
- " make DESTDIR=/home/john install\n"
- "which will install the concerned software using the"
- " installation prefix, e.g. \"/usr/local\" prepended with "
- "the DESTDIR value which finally gives \"/home/john/usr/local\".\n"
- "WARNING: DESTDIR may not be used on Windows because installation"
- " prefix usually contains a drive letter like in \"C:/Program Files\""
- " which cannot be prepended with some other prefix."
- "\n"
- "The installation prefix is also added to CMAKE_SYSTEM_PREFIX_PATH "
- "so that find_package, find_program, find_library, find_path, and "
- "find_file will search the prefix for other software."
- ,false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY", cmProperty::VARIABLE,
- "Don't make the install target depend on the all target.",
- "By default, the \"install\" target depends on the \"all\" target. "
- "This has the effect, that when \"make install\" is invoked or INSTALL "
- "is built, first the \"all\" target is built, then the installation "
- "starts. "
- "If CMAKE_SKIP_INSTALL_ALL_DEPENDENCY is set to TRUE, this dependency "
- "is not created, so the installation process will start immediately, "
- "independent from whether the project has been completely built or not."
- ,false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_MODULE_PATH", cmProperty::VARIABLE,
- "List of directories to search for CMake modules.",
- "Commands like include() and find_package() search for files in "
- "directories listed by this variable before checking the default "
- "modules that come with CMake.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_WARN_DEPRECATED", cmProperty::VARIABLE,
- "Whether to issue deprecation warnings for macros and functions.",
- "If TRUE, this can be used by macros and functions to issue "
- "deprecation warnings. This variable is FALSE by default.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_ERROR_DEPRECATED", cmProperty::VARIABLE,
- "Whether to issue deprecation errors for macros and functions.",
- "If TRUE, this can be used by macros and functions to issue "
- "fatal errors when deprecated macros or functions are used. This "
- "variable is FALSE by default.",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_PREFIX_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_XXX(), with appropriate suffixes added.",
- "Specifies a path which will be used by the FIND_XXX() commands. It "
- "contains the \"base\" directories, the FIND_XXX() commands append "
- "appropriate subdirectories to the base directories. So FIND_PROGRAM() "
- "adds /bin to each of the directories in the path, FIND_LIBRARY() "
- "appends /lib to each of the directories, and FIND_PATH() and "
- "FIND_FILE() append /include . By default it is empty, it is intended "
- "to be set by the project. See also CMAKE_SYSTEM_PREFIX_PATH, "
- "CMAKE_INCLUDE_PATH, CMAKE_LIBRARY_PATH, CMAKE_PROGRAM_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_INCLUDE_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_FILE() and FIND_PATH().",
- "Specifies a path which will be used both by FIND_FILE() and "
- "FIND_PATH(). Both commands will check each of the contained directories "
- "for the existence of the file which is currently searched. By default "
- "it is empty, it is intended to be set by the project. See also "
- "CMAKE_SYSTEM_INCLUDE_PATH, CMAKE_PREFIX_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_LIBRARY_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_LIBRARY().",
- "Specifies a path which will be used by FIND_LIBRARY(). FIND_LIBRARY() "
- "will check each of the contained directories for the existence of the "
- "library which is currently searched. By default it is empty, it is "
- "intended to be set by the project. See also CMAKE_SYSTEM_LIBRARY_PATH, "
- "CMAKE_PREFIX_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_PROGRAM_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_PROGRAM().",
- "Specifies a path which will be used by FIND_PROGRAM(). FIND_PROGRAM() "
- "will check each of the contained directories for the existence of the "
- "program which is currently searched. By default it is empty, it is "
- "intended to be set by the project. See also CMAKE_SYSTEM_PROGRAM_PATH, "
- " CMAKE_PREFIX_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_SYSTEM_PREFIX_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_XXX(), with appropriate suffixes added.",
- "Specifies a path which will be used by the FIND_XXX() commands. It "
- "contains the \"base\" directories, the FIND_XXX() commands append "
- "appropriate subdirectories to the base directories. So FIND_PROGRAM() "
- "adds /bin to each of the directories in the path, FIND_LIBRARY() "
- "appends /lib to each of the directories, and FIND_PATH() and "
- "FIND_FILE() append /include . By default this contains the standard "
- "directories for the current system and the CMAKE_INSTALL_PREFIX. "
- "It is NOT intended "
- "to be modified by the project, use CMAKE_PREFIX_PATH for this. See also "
- "CMAKE_SYSTEM_INCLUDE_PATH, CMAKE_SYSTEM_LIBRARY_PATH, "
- "CMAKE_SYSTEM_PROGRAM_PATH, and CMAKE_SYSTEM_IGNORE_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_SYSTEM_IGNORE_PATH", cmProperty::VARIABLE,
- "Path to be ignored by FIND_XXX() commands.",
- "Specifies directories to be ignored by searches in FIND_XXX() "
- "commands. "
- "This is useful in cross-compiled environments where some system "
- "directories contain incompatible but possibly linkable libraries. For "
- "example, on cross-compiled cluster environments, this allows a user to "
- "ignore directories containing libraries meant for the front-end "
- "machine that modules like FindX11 (and others) would normally search. "
- "By default this contains a list of directories containing incompatible "
- "binaries for the host system. "
- "See also CMAKE_SYSTEM_PREFIX_PATH, CMAKE_SYSTEM_LIBRARY_PATH, "
- "CMAKE_SYSTEM_INCLUDE_PATH, and CMAKE_SYSTEM_PROGRAM_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_IGNORE_PATH", cmProperty::VARIABLE,
- "Path to be ignored by FIND_XXX() commands.",
- "Specifies directories to be ignored by searches in FIND_XXX() "
- "commands. "
- "This is useful in cross-compiled environments where some system "
- "directories contain incompatible but possibly linkable libraries. For "
- "example, on cross-compiled cluster environments, this allows a user to "
- "ignore directories containing libraries meant for the front-end "
- "machine that modules like FindX11 (and others) would normally search. "
- "By default this is empty; it is intended to be set by the project. "
- "Note that CMAKE_IGNORE_PATH takes a list of directory names, NOT a "
- "list of prefixes. If you want to ignore paths under prefixes (bin, "
- "include, lib, etc.), you'll need to specify them explicitly. "
- "See also CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_INCLUDE_PATH, "
- "CMAKE_PROGRAM_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_SYSTEM_INCLUDE_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_FILE() and FIND_PATH().",
- "Specifies a path which will be used both by FIND_FILE() and "
- "FIND_PATH(). Both commands will check each of the contained directories "
- "for the existence of the file which is currently searched. By default "
- "it contains the standard directories for the current system. It is "
- "NOT intended to be modified by the project, use CMAKE_INCLUDE_PATH "
- "for this. See also CMAKE_SYSTEM_PREFIX_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_SYSTEM_LIBRARY_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_LIBRARY().",
- "Specifies a path which will be used by FIND_LIBRARY(). FIND_LIBRARY() "
- "will check each of the contained directories for the existence of the "
- "library which is currently searched. By default it contains the "
- "standard directories for the current system. It is NOT intended to be "
- "modified by the project, use CMAKE_LIBRARY_PATH for this. See "
- "also CMAKE_SYSTEM_PREFIX_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_SYSTEM_PROGRAM_PATH", cmProperty::VARIABLE,
- "Path used for searching by FIND_PROGRAM().",
- "Specifies a path which will be used by FIND_PROGRAM(). FIND_PROGRAM() "
- "will check each of the contained directories for the existence of the "
- "program which is currently searched. By default it contains the "
- "standard directories for the current system. It is NOT intended to be "
- "modified by the project, use CMAKE_PROGRAM_PATH for this. See also "
- "CMAKE_SYSTEM_PREFIX_PATH.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_DISABLE_FIND_PACKAGE_<PackageName>", cmProperty::VARIABLE,
- "Variable for disabling find_package() calls.",
- "Every non-REQUIRED find_package() call in a project can be disabled "
- "by setting the variable CMAKE_DISABLE_FIND_PACKAGE_<PackageName> to "
- "TRUE. This can be used to build a project without an optional package, "
- "although that package is installed.\n"
- "This switch should be used during the initial CMake run. Otherwise if "
- "the package has already been found in a previous CMake run, the "
- "variables which have been stored in the cache will still be there. "
- "In that case it is recommended to remove the cache variables for "
- "this package from the cache using the cache editor or cmake -U", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_FIND_PACKAGE_WARN_NO_MODULE", cmProperty::VARIABLE,
- "Tell find_package to warn if called without an explicit mode.",
- "If find_package is called without an explicit mode option "
- "(MODULE, CONFIG or NO_MODULE) and no Find<pkg>.cmake module is "
- "in CMAKE_MODULE_PATH then CMake implicitly assumes that the "
- "caller intends to search for a package configuration file. "
- "If no package configuration file is found then the wording "
- "of the failure message must account for both the case that the "
- "package is really missing and the case that the project has a "
- "bug and failed to provide the intended Find module. "
- "If instead the caller specifies an explicit mode option then "
- "the failure message can be more specific."
- "\n"
- "Set CMAKE_FIND_PACKAGE_WARN_NO_MODULE to TRUE to tell find_package "
- "to warn when it implicitly assumes Config mode. "
- "This helps developers enforce use of an explicit mode in all calls "
- "to find_package within a project.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_USER_MAKE_RULES_OVERRIDE", cmProperty::VARIABLE,
- "Specify a CMake file that overrides platform information.",
- "CMake loads the specified file while enabling support for each "
- "language from either the project() or enable_language() commands. "
- "It is loaded after CMake's builtin compiler and platform information "
- "modules have been loaded but before the information is used. "
- "The file may set platform information variables to override CMake's "
- "defaults."
- "\n"
- "This feature is intended for use only in overriding information "
- "variables that must be set before CMake builds its first test "
- "project to check that the compiler for a language works. "
- "It should not be used to load a file in cases that a normal include() "
- "will work. "
- "Use it only as a last resort for behavior that cannot be achieved "
- "any other way. "
- "For example, one may set CMAKE_C_FLAGS_INIT to change the default "
- "value used to initialize CMAKE_C_FLAGS before it is cached. "
- "The override file should NOT be used to set anything that could "
- "be set after languages are enabled, such as variables like "
- "CMAKE_RUNTIME_OUTPUT_DIRECTORY that affect the placement of binaries. "
- "Information set in the file will be used for try_compile and try_run "
- "builds too."
- ,false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("BUILD_SHARED_LIBS", cmProperty::VARIABLE,
- "Global flag to cause add_library to create shared libraries if on.",
- "If present and true, this will cause all libraries to be "
- "built shared unless the library was explicitly added as a "
- "static library. This variable is often added to projects "
- "as an OPTION so that each user of a project can decide if "
- "they want to build the project using shared or static "
- "libraries.",false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_NOT_USING_CONFIG_FLAGS", cmProperty::VARIABLE,
- "Skip _BUILD_TYPE flags if true.",
- "This is an internal flag used by the generators in "
- "CMake to tell CMake to skip the _BUILD_TYPE flags.",false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_MFC_FLAG", cmProperty::VARIABLE,
- "Tell cmake to use MFC for an executable or dll.",
- "This can be set in a CMakeLists.txt file and will "
- "enable MFC in the application. It should be set "
- "to 1 for the static MFC library, and 2 for "
- "the shared MFC library. This is used in Visual "
- "Studio 6 and 7 project files. The CMakeSetup "
- "dialog used MFC and the CMakeLists.txt looks like this:\n"
- " add_definitions(-D_AFXDLL)\n"
- " set(CMAKE_MFC_FLAG 2)\n"
- " add_executable(CMakeSetup WIN32 ${SRCS})\n",false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_COLOR_MAKEFILE", cmProperty::VARIABLE,
- "Enables color output when using the Makefile generator.",
- "When enabled, the generated Makefiles will produce colored output. "
- "Default is ON.",false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_ABSOLUTE_DESTINATION_FILES", cmProperty::VARIABLE,
- "List of files which have been installed using "
- " an ABSOLUTE DESTINATION path.",
- "This variable is defined by CMake-generated cmake_install.cmake "
- "scripts."
- " It can be used (read-only) by programs or scripts that source those"
- " install scripts. This is used by some CPack generators (e.g. RPM).",
- false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", cmProperty::VARIABLE,
- "Ask cmake_install.cmake script to warn each time a file with "
- "absolute INSTALL DESTINATION is encountered.",
- "This variable is used by CMake-generated cmake_install.cmake"
- " scripts. If one sets this variable to ON while running the"
- " script, it may get warning messages from the script.", false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", cmProperty::VARIABLE,
- "Ask cmake_install.cmake script to error out as soon as "
- "a file with absolute INSTALL DESTINATION is encountered.",
- "The fatal error is emitted before the installation of "
- "the offending file takes place."
- " This variable is used by CMake-generated cmake_install.cmake"
- " scripts. If one sets this variable to ON while running the"
- " script, it may get fatal error messages from the script.",false,
- "Variables That Change Behavior");
-
- cm->DefineProperty
- ("CMAKE_DEBUG_TARGET_PROPERTIES", cmProperty::VARIABLE,
- "Enables tracing output for target properties.",
- "This variable can be populated with a list of properties to generate "
- "debug output for when evaluating target properties. Currently it can "
- "only be used when evaluating the INCLUDE_DIRECTORIES, "
- "COMPILE_DEFINITIONS and COMPILE_OPTIONS target properties. "
- "In that case, it outputs a backtrace for each entry in the target "
- "property. Default is unset.", false, "Variables That Change Behavior");
-
- // Variables defined by CMake that describe the system
-
- cm->DefineProperty
- ("CMAKE_SYSTEM", cmProperty::VARIABLE,
- "Name of system cmake is compiling for.",
- "This variable is the composite of CMAKE_SYSTEM_NAME "
- "and CMAKE_SYSTEM_VERSION, like this "
- "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}. "
- "If CMAKE_SYSTEM_VERSION is not set, then "
- "CMAKE_SYSTEM is the same as CMAKE_SYSTEM_NAME.",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_SYSTEM_NAME", cmProperty::VARIABLE,
- "Name of the OS CMake is building for.",
- "This is the name of the operating system on "
- "which CMake is targeting. On systems that "
- "have the uname command, this variable is set "
- "to the output of uname -s. Linux, Windows, "
- " and Darwin for Mac OS X are the values found "
- " on the big three operating systems." ,false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_SYSTEM_PROCESSOR", cmProperty::VARIABLE,
- "The name of the CPU CMake is building for.",
- "On systems that support uname, this variable is "
- "set to the output of uname -p, on windows it is "
- "set to the value of the environment variable "
- "PROCESSOR_ARCHITECTURE",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_SYSTEM_VERSION", cmProperty::VARIABLE,
- "OS version CMake is building for.",
- "A numeric version string for the system, on "
- "systems that support uname, this variable is "
- "set to the output of uname -r. On other "
- "systems this is set to major-minor version numbers.",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_LIBRARY_ARCHITECTURE", cmProperty::VARIABLE,
- "Target architecture library directory name, if detected.",
- "This is the value of CMAKE_<lang>_LIBRARY_ARCHITECTURE as "
- "detected for one of the enabled languages.",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_LIBRARY_ARCHITECTURE_REGEX", cmProperty::VARIABLE,
- "Regex matching possible target architecture library directory names.",
- "This is used to detect CMAKE_<lang>_LIBRARY_ARCHITECTURE from the "
- "implicit linker search path by matching the <arch> name.",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_HOST_SYSTEM", cmProperty::VARIABLE,
- "Name of system cmake is being run on.",
- "The same as CMAKE_SYSTEM but for the host system instead "
- "of the target system when cross compiling.",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_HOST_SYSTEM_NAME", cmProperty::VARIABLE,
- "Name of the OS CMake is running on.",
- "The same as CMAKE_SYSTEM_NAME but for the host system instead "
- "of the target system when cross compiling.",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_HOST_SYSTEM_PROCESSOR", cmProperty::VARIABLE,
- "The name of the CPU CMake is running on.",
- "The same as CMAKE_SYSTEM_PROCESSOR but for the host system instead "
- "of the target system when cross compiling.",false,
- "Variables That Describe the System");
- cm->DefineProperty
- ("CMAKE_HOST_SYSTEM_VERSION", cmProperty::VARIABLE,
- "OS version CMake is running on.",
- "The same as CMAKE_SYSTEM_VERSION but for the host system instead "
- "of the target system when cross compiling.",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("APPLE", cmProperty::VARIABLE,
- "True if running on Mac OS X.",
- "Set to true on Mac OS X."
- ,false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("BORLAND", cmProperty::VARIABLE,
- "True if the Borland compiler is being used.",
- "This is set to true if the Borland compiler is being used.",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CYGWIN", cmProperty::VARIABLE,
- "True for Cygwin.",
- "Set to true when using Cygwin."
- ,false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("MSVC", cmProperty::VARIABLE,
- "True when using Microsoft Visual C",
- "Set to true when the compiler is some version of Microsoft Visual C.",
- false,
- "Variables That Describe the System");
-
- int msvc_versions[] = { 60, 70, 71, 80, 90, 100, 110, 120, 0 };
- for (int i = 0; msvc_versions[i] != 0; i ++)
- {
- const char minor = (char)('0' + (msvc_versions[i] % 10));
- cmStdString varName = "MSVC";
- cmsys_ios::ostringstream majorStr;
-
- majorStr << (msvc_versions[i] / 10);
- varName += majorStr.str();
- if (msvc_versions[i] < 100)
- {
- varName += minor;
- }
-
- cmStdString verString = majorStr.str() + "." + minor;
-
- cmStdString shortStr = "True when using Microsoft Visual C " + verString;
- cmStdString fullStr = "Set to true when the compiler is version " +
- verString +
- " of Microsoft Visual C.";
- cm->DefineProperty
- (varName.c_str(), cmProperty::VARIABLE,
- shortStr.c_str(),
- fullStr.c_str(),
- false,
- "Variables That Describe the System");
- }
-
- cm->DefineProperty
- ("MSVC_IDE", cmProperty::VARIABLE,
- "True when using the Microsoft Visual C IDE",
- "Set to true when the target platform is the Microsoft Visual C IDE, "
- "as opposed to the command line compiler.",
- false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("MSVC_VERSION", cmProperty::VARIABLE,
- "The version of Microsoft Visual C/C++ being used if any.",
- "Known version numbers are:\n"
- " 1200 = VS 6.0\n"
- " 1300 = VS 7.0\n"
- " 1310 = VS 7.1\n"
- " 1400 = VS 8.0\n"
- " 1500 = VS 9.0\n"
- " 1600 = VS 10.0\n"
- " 1700 = VS 11.0\n"
- " 1800 = VS 12.0\n"
- "",
- false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_CL_64", cmProperty::VARIABLE,
- "Using the 64 bit compiler from Microsoft",
- "Set to true when using the 64 bit cl compiler from Microsoft.",
- false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_COMPILER_2005", cmProperty::VARIABLE,
- "Using the Visual Studio 2005 compiler from Microsoft",
- "Set to true when using the Visual Studio 2005 compiler "
- "from Microsoft.",
- false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("UNIX", cmProperty::VARIABLE,
- "True for UNIX and UNIX like operating systems.",
- "Set to true when the target system is UNIX or UNIX like "
- "(i.e. APPLE and CYGWIN).",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("WIN32", cmProperty::VARIABLE,
- "True on windows systems, including win64.",
- "Set to true when the target system is Windows.",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("XCODE_VERSION", cmProperty::VARIABLE,
- "Version of Xcode (Xcode generator only).",
- "Under the Xcode generator, this is the version of Xcode as specified in "
- "\"Xcode.app/Contents/version.plist\" (such as \"3.1.2\").",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_HOST_APPLE", cmProperty::VARIABLE,
- "True for Apple OS X operating systems.",
- "Set to true when the host system is Apple OS X.",
- false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_HOST_UNIX", cmProperty::VARIABLE,
- "True for UNIX and UNIX like operating systems.",
- "Set to true when the host system is UNIX or UNIX like "
- "(i.e. APPLE and CYGWIN).",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_HOST_WIN32", cmProperty::VARIABLE,
- "True on windows systems, including win64.",
- "Set to true when the host system is Windows and on Cygwin."
- ,false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("CMAKE_OBJECT_PATH_MAX", cmProperty::VARIABLE,
- "Maximum object file full-path length allowed by native build tools.",
- "CMake computes for every source file an object file name that is "
- "unique to the source file and deterministic with respect to the "
- "full path to the source file. "
- "This allows multiple source files in a target to share the same name "
- "if they lie in different directories without rebuilding when one is "
- "added or removed. "
- "However, it can produce long full paths in a few cases, so CMake "
- "shortens the path using a hashing scheme when the full path to an "
- "object file exceeds a limit. "
- "CMake has a built-in limit for each platform that is sufficient for "
- "common tools, but some native tools may have a lower limit. "
- "This variable may be set to specify the limit explicitly. "
- "The value must be an integer no less than 128.",false,
- "Variables That Describe the System");
-
- cm->DefineProperty
- ("ENV", cmProperty::VARIABLE,
- "Access environment variables.",
- "Use the syntax $ENV{VAR} to read environment variable VAR. "
- "See also the set() command to set ENV{VAR}."
- ,false,
- "Variables That Describe the System");
-
- // Variables that affect the building of object files and
- // targets.
- //
- cm->DefineProperty
- ("CMAKE_INCLUDE_CURRENT_DIR", cmProperty::VARIABLE,
- "Automatically add the current source- and build directories "
- "to the include path.",
- "If this variable is enabled, CMake automatically adds in each "
- "directory ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} "
- "to the include path for this directory. These additional include "
- "directories do not propagate down to subdirectories. This is useful "
- "mainly for out-of-source builds, where files generated into the "
- "build tree are included by files located in the source tree.\n"
- "By default CMAKE_INCLUDE_CURRENT_DIR is OFF.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE", cmProperty::VARIABLE,
- "Automatically add the current source- and build directories "
- "to the INTERFACE_INCLUDE_DIRECTORIES.",
- "If this variable is enabled, CMake automatically adds for each shared "
- "library target, static library target, module target and executable "
- "target, ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} to "
- "the INTERFACE_INCLUDE_DIRECTORIES."
- "By default CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE is OFF.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE,
- "The rpath to use for installed targets.",
- "A semicolon-separated list specifying the rpath "
- "to use in installed targets (for platforms that support it). "
- "This is used to initialize the target property "
- "INSTALL_RPATH for all targets.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_INSTALL_RPATH_USE_LINK_PATH", cmProperty::VARIABLE,
- "Add paths to linker search and installed rpath.",
- "CMAKE_INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true "
- "will append directories in the linker search path and outside the "
- "project to the INSTALL_RPATH. "
- "This is used to initialize the target property "
- "INSTALL_RPATH_USE_LINK_PATH for all targets.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_INSTALL_NAME_DIR", cmProperty::VARIABLE,
- "Mac OS X directory name for installed targets.",
- "CMAKE_INSTALL_NAME_DIR is used to initialize the "
- "INSTALL_NAME_DIR property on all targets. See that target "
- "property for more information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_Fortran_FORMAT", cmProperty::VARIABLE,
- "Set to FIXED or FREE to indicate the Fortran source layout.",
- "This variable is used to initialize the Fortran_FORMAT "
- "property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_Fortran_MODULE_DIRECTORY", cmProperty::VARIABLE,
- "Fortran module output directory.",
- "This variable is used to initialize the "
- "Fortran_MODULE_DIRECTORY property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_LIBRARY_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
- "Where to put all the LIBRARY targets when built.",
- "This variable is used to initialize the "
- "LIBRARY_OUTPUT_DIRECTORY property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_ARCHIVE_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
- "Where to put all the ARCHIVE targets when built.",
- "This variable is used to initialize the "
- "ARCHIVE_OUTPUT_DIRECTORY property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_RUNTIME_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
- "Where to put all the RUNTIME targets when built.",
- "This variable is used to initialize the "
- "RUNTIME_OUTPUT_DIRECTORY property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
- "Where to put all the MS debug symbol files from linker.",
- "This variable is used to initialize the "
- "PDB_OUTPUT_DIRECTORY property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_LINK_DEPENDS_NO_SHARED", cmProperty::VARIABLE,
- "Whether to skip link dependencies on shared library files.",
- "This variable initializes the LINK_DEPENDS_NO_SHARED "
- "property on targets when they are created. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_AUTOMOC", cmProperty::VARIABLE,
- "Whether to handle moc automatically for Qt targets.",
- "This variable is used to initialize the "
- "AUTOMOC property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_AUTOMOC_MOC_OPTIONS", cmProperty::VARIABLE,
- "Additional options for moc when using automoc (see CMAKE_AUTOMOC).",
- "This variable is used to initialize the "
- "AUTOMOC_MOC_OPTIONS property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_GNUtoMS", cmProperty::VARIABLE,
- "Convert GNU import libraries (.dll.a) to MS format (.lib).",
- "This variable is used to initialize the GNUtoMS property on targets "
- "when they are created. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_DEBUG_POSTFIX", cmProperty::VARIABLE,
- "See variable CMAKE_<CONFIG>_POSTFIX.",
- "This variable is a special case of the more-general "
- "CMAKE_<CONFIG>_POSTFIX variable for the DEBUG configuration.",
- false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_<CONFIG>_POSTFIX", cmProperty::VARIABLE,
- "Default filename postfix for libraries under configuration <CONFIG>.",
- "When a non-executable target is created its <CONFIG>_POSTFIX "
- "target property is initialized with the value of this variable "
- "if it is set.",
- false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_BUILD_WITH_INSTALL_RPATH", cmProperty::VARIABLE,
- "Use the install path for the RPATH",
- "Normally CMake uses the build tree for the RPATH when building "
- "executables etc on systems that use RPATH. When the software "
- "is installed the executables etc are relinked by CMake to have "
- "the install RPATH. If this variable is set to true then the software "
- "is always built with the install path for the RPATH and does not "
- "need to be relinked when installed.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_NO_BUILTIN_CHRPATH", cmProperty::VARIABLE,
- "Do not use the builtin ELF editor to fix RPATHs on installation.",
- "When an ELF binary needs to have a different RPATH after installation "
- "than it does in the build tree, CMake uses a builtin editor to change "
- "the RPATH in the installed copy. "
- "If this variable is set to true then CMake will relink the binary "
- "before installation instead of using its builtin editor.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_SKIP_BUILD_RPATH", cmProperty::VARIABLE,
- "Do not include RPATHs in the build tree.",
- "Normally CMake uses the build tree for the RPATH when building "
- "executables etc on systems that use RPATH. When the software "
- "is installed the executables etc are relinked by CMake to have "
- "the install RPATH. If this variable is set to true then the software "
- "is always built with no RPATH.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_SKIP_INSTALL_RPATH", cmProperty::VARIABLE,
- "Do not include RPATHs in the install tree.",
- "Normally CMake uses the build tree for the RPATH when building "
- "executables etc on systems that use RPATH. When the software "
- "is installed the executables etc are relinked by CMake to have "
- "the install RPATH. If this variable is set to true then the software "
- "is always installed without RPATH, even if RPATH is enabled when "
- "building. This can be useful for example to allow running tests from "
- "the build directory with RPATH enabled before the installation step. "
- "To omit RPATH in both the build and install steps, use "
- "CMAKE_SKIP_RPATH instead.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_EXE_LINKER_FLAGS", cmProperty::VARIABLE,
- "Linker flags to be used to create executables.",
- "These flags will be used by the linker when creating an executable."
- ,false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_EXE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
- "Flags to be used when linking an executable.",
- "Same as CMAKE_C_FLAGS_* but used by the linker "
- "when creating executables.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_MODULE_LINKER_FLAGS", cmProperty::VARIABLE,
- "Linker flags to be used to create modules.",
- "These flags will be used by the linker when creating a module."
- ,false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_MODULE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
- "Flags to be used when linking a module.",
- "Same as CMAKE_C_FLAGS_* but used by the linker "
- "when creating modules.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_SHARED_LINKER_FLAGS", cmProperty::VARIABLE,
- "Linker flags to be used to create shared libraries.",
- "These flags will be used by the linker when creating a shared library."
- ,false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_SHARED_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
- "Flags to be used when linking a shared library.",
- "Same as CMAKE_C_FLAGS_* but used by the linker "
- "when creating shared libraries.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_STATIC_LINKER_FLAGS", cmProperty::VARIABLE,
- "Linker flags to be used to create static libraries.",
- "These flags will be used by the linker when creating a static library."
- ,false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_STATIC_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
- "Flags to be used when linking a static library.",
- "Same as CMAKE_C_FLAGS_* but used by the linker "
- "when creating static libraries.",false,
- "Variables that Control the Build");
-
- cm->DefineProperty
- ("CMAKE_LIBRARY_PATH_FLAG", cmProperty::VARIABLE,
- "The flag to be used to add a library search path to a compiler.",
- "The flag will be used to specify a library directory to the compiler. "
- "On most compilers this is \"-L\".",false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_LINK_DEF_FILE_FLAG ", cmProperty::VARIABLE,
- "Linker flag to be used to specify a .def file for dll creation.",
- "The flag will be used to add a .def file when creating "
- "a dll on Windows; this is only defined on Windows."
- ,false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_LINK_LIBRARY_FLAG", cmProperty::VARIABLE,
- "Flag to be used to link a library into an executable.",
- "The flag will be used to specify a library to link to an executable. "
- "On most compilers this is \"-l\".",false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_LINK_LIBRARY_FILE_FLAG", cmProperty::VARIABLE,
- "Flag to be used to link a library specified by a path to its file.",
- "The flag will be used before a library file path is given to the "
- "linker. "
- "This is needed only on very few platforms.", false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_USE_RELATIVE_PATHS", cmProperty::VARIABLE,
- "Use relative paths (May not work!).",
- "If this is set to TRUE, then CMake will use "
- "relative paths between the source and binary tree. "
- "This option does not work for more complicated "
- "projects, and relative paths are used when possible. "
- "In general, it is not possible to move CMake generated"
- " makefiles to a different location regardless "
- "of the value of this variable.",false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("EXECUTABLE_OUTPUT_PATH", cmProperty::VARIABLE,
- "Old executable location variable.",
- "The target property RUNTIME_OUTPUT_DIRECTORY supercedes "
- "this variable for a target if it is set. "
- "Executable targets are otherwise placed in this directory.",false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("LIBRARY_OUTPUT_PATH", cmProperty::VARIABLE,
- "Old library location variable.",
- "The target properties ARCHIVE_OUTPUT_DIRECTORY, "
- "LIBRARY_OUTPUT_DIRECTORY, and RUNTIME_OUTPUT_DIRECTORY supercede "
- "this variable for a target if they are set. "
- "Library targets are otherwise placed in this directory.",false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_TRY_COMPILE_CONFIGURATION", cmProperty::VARIABLE,
- "Build configuration used for try_compile and try_run projects.",
- "Projects built by try_compile and try_run are built "
- "synchronously during the CMake configuration step. "
- "Therefore a specific build configuration must be chosen even "
- "if the generated build system supports multiple configurations.",false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_LINK_INTERFACE_LIBRARIES", cmProperty::VARIABLE,
- "Default value for LINK_INTERFACE_LIBRARIES of targets.",
- "This variable is used to initialize the "
- "LINK_INTERFACE_LIBRARIES property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_WIN32_EXECUTABLE", cmProperty::VARIABLE,
- "Default value for WIN32_EXECUTABLE of targets.",
- "This variable is used to initialize the "
- "WIN32_EXECUTABLE property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_MACOSX_BUNDLE", cmProperty::VARIABLE,
- "Default value for MACOSX_BUNDLE of targets.",
- "This variable is used to initialize the "
- "MACOSX_BUNDLE property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_POSITION_INDEPENDENT_CODE", cmProperty::VARIABLE,
- "Default value for POSITION_INDEPENDENT_CODE of targets.",
- "This variable is used to initialize the "
- "POSITION_INDEPENDENT_CODE property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_<LANG>_VISIBILITY_PRESET", cmProperty::VARIABLE,
- "Default value for <LANG>_VISIBILITY_PRESET of targets.",
- "This variable is used to initialize the "
- "<LANG>_VISIBILITY_PRESET property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
- cm->DefineProperty
- ("CMAKE_VISIBILITY_INLINES_HIDDEN", cmProperty::VARIABLE,
- "Default value for VISIBILITY_INLINES_HIDDEN of targets.",
- "This variable is used to initialize the "
- "VISIBILITY_INLINES_HIDDEN property on all the targets. "
- "See that target property for additional information.",
- false,
- "Variables that Control the Build");
-
-// Variables defined when the a language is enabled These variables will
-// also be defined whenever CMake has loaded its support for compiling (LANG)
-// programs. This support will be loaded whenever CMake is used to compile
-// (LANG) files. C and CXX are examples of the most common values for (LANG).
-
- cm->DefineProperty
- ("CMAKE_USER_MAKE_RULES_OVERRIDE_<LANG>", cmProperty::VARIABLE,
- "Specify a CMake file that overrides platform information for <LANG>.",
- "This is a language-specific version of "
- "CMAKE_USER_MAKE_RULES_OVERRIDE loaded only when enabling "
- "language <LANG>.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_COMPILER", cmProperty::VARIABLE,
- "The full path to the compiler for LANG.",
- "This is the command that will be used as the <LANG> compiler. "
- "Once set, you can not change this variable.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_COMPILER_ID", cmProperty::VARIABLE,
- "Compiler identification string.",
- "A short string unique to the compiler vendor. "
- "Possible values include:\n"
- " Absoft = Absoft Fortran (absoft.com)\n"
- " ADSP = Analog VisualDSP++ (analog.com)\n"
- " Clang = LLVM Clang (clang.llvm.org)\n"
- " Cray = Cray Compiler (cray.com)\n"
- " Embarcadero, Borland = Embarcadero (embarcadero.com)\n"
- " G95 = G95 Fortran (g95.org)\n"
- " GNU = GNU Compiler Collection (gcc.gnu.org)\n"
- " HP = Hewlett-Packard Compiler (hp.com)\n"
- " Intel = Intel Compiler (intel.com)\n"
- " MIPSpro = SGI MIPSpro (sgi.com)\n"
- " MSVC = Microsoft Visual Studio (microsoft.com)\n"
- " PGI = The Portland Group (pgroup.com)\n"
- " PathScale = PathScale (pathscale.com)\n"
- " SDCC = Small Device C Compiler (sdcc.sourceforge.net)\n"
- " SunPro = Oracle Solaris Studio (oracle.com)\n"
- " TI = Texas Instruments (ti.com)\n"
- " TinyCC = Tiny C Compiler (tinycc.org)\n"
- " Watcom = Open Watcom (openwatcom.org)\n"
- " XL, VisualAge, zOS = IBM XL (ibm.com)\n"
- "This variable is not guaranteed to be defined for all "
- "compilers or languages.",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_PLATFORM_ID", cmProperty::VARIABLE,
- "An internal variable subject to change.",
- "This is used in determining the platform and is subject to change.",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_COMPILER_ABI", cmProperty::VARIABLE,
- "An internal variable subject to change.",
- "This is used in determining the compiler ABI and is subject to change.",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_COMPILER_VERSION", cmProperty::VARIABLE,
- "Compiler version string.",
- "Compiler version in major[.minor[.patch[.tweak]]] format. "
- "This variable is not guaranteed to be defined for all "
- "compilers or languages.",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_INTERNAL_PLATFORM_ABI", cmProperty::VARIABLE,
- "An internal variable subject to change.",
- "This is used in determining the compiler ABI and is subject to change.",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_SIZEOF_DATA_PTR", cmProperty::VARIABLE,
- "Size of pointer-to-data types for language <LANG>.",
- "This holds the size (in bytes) of pointer-to-data types in the target "
- "platform ABI. "
- "It is defined for languages C and CXX (C++).",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_COMPILER_IS_GNU<LANG>", cmProperty::VARIABLE,
- "True if the compiler is GNU.",
- "If the selected <LANG> compiler is the GNU "
- "compiler then this is TRUE, if not it is FALSE. "
- "Unlike the other per-language variables, this uses the GNU syntax for "
- "identifying languages instead of the CMake syntax. Recognized values of "
- "the <LANG> suffix are:\n"
- " CC = C compiler\n"
- " CXX = C++ compiler\n"
- " G77 = Fortran compiler",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_FLAGS", cmProperty::VARIABLE,
- "Flags for all build types.",
- "<LANG> flags used regardless of the value of CMAKE_BUILD_TYPE.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_FLAGS_DEBUG", cmProperty::VARIABLE,
- "Flags for Debug build type or configuration.",
- "<LANG> flags used when CMAKE_BUILD_TYPE is Debug.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_FLAGS_MINSIZEREL", cmProperty::VARIABLE,
- "Flags for MinSizeRel build type or configuration.",
- "<LANG> flags used when CMAKE_BUILD_TYPE is MinSizeRel."
- "Short for minimum size release.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_FLAGS_RELEASE", cmProperty::VARIABLE,
- "Flags for Release build type or configuration.",
- "<LANG> flags used when CMAKE_BUILD_TYPE is Release",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_FLAGS_RELWITHDEBINFO", cmProperty::VARIABLE,
- "Flags for RelWithDebInfo type or configuration.",
- "<LANG> flags used when CMAKE_BUILD_TYPE is RelWithDebInfo. "
- "Short for Release With Debug Information.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_COMPILE_OBJECT", cmProperty::VARIABLE,
- "Rule variable to compile a single object file.",
- "This is a rule variable that tells CMake how to "
- "compile a single object file for the language <LANG>."
- ,false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_CREATE_SHARED_LIBRARY", cmProperty::VARIABLE,
- "Rule variable to create a shared library.",
- "This is a rule variable that tells CMake how to "
- "create a shared library for the language <LANG>.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_CREATE_SHARED_MODULE", cmProperty::VARIABLE,
- "Rule variable to create a shared module.",
- "This is a rule variable that tells CMake how to "
- "create a shared library for the language <LANG>.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_CREATE_STATIC_LIBRARY", cmProperty::VARIABLE,
- "Rule variable to create a static library.",
- "This is a rule variable that tells CMake how "
- "to create a static library for the language <LANG>.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_ARCHIVE_CREATE", cmProperty::VARIABLE,
- "Rule variable to create a new static archive.",
- "This is a rule variable that tells CMake how to create a static "
- "archive. It is used in place of CMAKE_<LANG>_CREATE_STATIC_LIBRARY "
- "on some platforms in order to support large object counts. "
- "See also CMAKE_<LANG>_ARCHIVE_APPEND and CMAKE_<LANG>_ARCHIVE_FINISH.",
- false, "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_ARCHIVE_APPEND", cmProperty::VARIABLE,
- "Rule variable to append to a static archive.",
- "This is a rule variable that tells CMake how to append to a static "
- "archive. It is used in place of CMAKE_<LANG>_CREATE_STATIC_LIBRARY "
- "on some platforms in order to support large object counts. "
- "See also CMAKE_<LANG>_ARCHIVE_CREATE and CMAKE_<LANG>_ARCHIVE_FINISH.",
- false, "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_ARCHIVE_FINISH", cmProperty::VARIABLE,
- "Rule variable to finish an existing static archive.",
- "This is a rule variable that tells CMake how to finish a static "
- "archive. It is used in place of CMAKE_<LANG>_CREATE_STATIC_LIBRARY "
- "on some platforms in order to support large object counts. "
- "See also CMAKE_<LANG>_ARCHIVE_CREATE and CMAKE_<LANG>_ARCHIVE_APPEND.",
- false, "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_IGNORE_EXTENSIONS", cmProperty::VARIABLE,
- "File extensions that should be ignored by the build.",
- "This is a list of file extensions that may be "
- "part of a project for a given language but are not compiled.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES", cmProperty::VARIABLE,
- "Directories implicitly searched by the compiler for header files.",
- "CMake does not explicitly specify these directories on compiler "
- "command lines for language <LANG>. "
- "This prevents system include directories from being treated as user "
- "include directories on some compilers.", false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES", cmProperty::VARIABLE,
- "Implicit linker search path detected for language <LANG>.",
- "Compilers typically pass directories containing language runtime "
- "libraries and default library search paths when they invoke a linker. "
- "These paths are implicit linker search directories for the compiler's "
- "language. "
- "CMake automatically detects these directories for each language and "
- "reports the results in this variable."
- "\n"
- "When a library in one of these directories is given by full path to "
- "target_link_libraries() CMake will generate the -l<name> form on "
- "link lines to ensure the linker searches its implicit directories "
- "for the library. "
- "Note that some toolchains read implicit directories from an "
- "environment variable such as LIBRARY_PATH so keep its value "
- "consistent when operating in a given build tree.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", cmProperty::VARIABLE,
- "Implicit linker framework search path detected for language <LANG>.",
- "These paths are implicit linker framework search directories for "
- "the compiler's language. "
- "CMake automatically detects these directories for each language and "
- "reports the results in this variable.", false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES", cmProperty::VARIABLE,
- "Implicit link libraries and flags detected for language <LANG>.",
- "Compilers typically pass language runtime library names and "
- "other flags when they invoke a linker. "
- "These flags are implicit link options for the compiler's language. "
- "CMake automatically detects these libraries and flags for each "
- "language and reports the results in this variable.", false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_LIBRARY_ARCHITECTURE", cmProperty::VARIABLE,
- "Target architecture library directory name detected for <lang>.",
- "If the <lang> compiler passes to the linker an architecture-specific "
- "system library search directory such as <prefix>/lib/<arch> this "
- "variable contains the <arch> name if/as detected by CMake.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_LINKER_PREFERENCE_PROPAGATES", cmProperty::VARIABLE,
- "True if CMAKE_<LANG>_LINKER_PREFERENCE propagates across targets.",
- "This is used when CMake selects a linker language for a target. "
- "Languages compiled directly into the target are always considered. "
- "A language compiled into static libraries linked by the target is "
- "considered if this variable is true.", false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_LINKER_PREFERENCE", cmProperty::VARIABLE,
- "Preference value for linker language selection.",
- "The \"linker language\" for executable, shared library, and module "
- "targets is the language whose compiler will invoke the linker. "
- "The LINKER_LANGUAGE target property sets the language explicitly. "
- "Otherwise, the linker language is that whose linker preference value "
- "is highest among languages compiled and linked into the target. "
- "See also the CMAKE_<LANG>_LINKER_PREFERENCE_PROPAGATES variable.",
- false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_LINK_EXECUTABLE ", cmProperty::VARIABLE,
- "Rule variable to link an executable.",
- "Rule variable to link an executable for the given language."
- ,false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_OUTPUT_EXTENSION", cmProperty::VARIABLE,
- "Extension for the output of a compile for a single file.",
- "This is the extension for an object file for "
- "the given <LANG>. For example .obj for C on Windows.",false,
- "Variables for Languages");
-
- cm->DefineProperty
- ("CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS", cmProperty::VARIABLE,
- "Extensions of source files for the given language.",
- "This is the list of extensions for a "
- "given language's source files."
- ,false,
- "Variables for Languages");
-
- cm->DefineProperty(
- "CMAKE_<LANG>_COMPILER_LOADED", cmProperty::VARIABLE,
- "Defined to true if the language is enabled.",
- "When language <LANG> is enabled by project() or enable_language() "
- "this variable is defined to 1.",
- false,"Variables for Languages");
-
- cm->DefineProperty(
- "CMAKE_Fortran_MODDIR_FLAG", cmProperty::VARIABLE,
- "Fortran flag for module output directory.",
- "This stores the flag needed to pass the value of the "
- "Fortran_MODULE_DIRECTORY target property to the compiler.",
- false,"Variables for Languages");
-
- cm->DefineProperty(
- "CMAKE_Fortran_MODDIR_DEFAULT", cmProperty::VARIABLE,
- "Fortran default module output directory.",
- "Most Fortran compilers write .mod files to the current working "
- "directory. "
- "For those that do not, this is set to \".\" and used when the "
- "Fortran_MODULE_DIRECTORY target property is not set.",
- false,"Variables for Languages");
-
- cm->DefineProperty(
- "CMAKE_Fortran_MODOUT_FLAG", cmProperty::VARIABLE,
- "Fortran flag to enable module output.",
- "Most Fortran compilers write .mod files out by default. "
- "For others, this stores the flag needed to enable module output.",
- false,"Variables for Languages");
-
- // variables that are used by cmake but not to be documented
- cm->DefineProperty("CMAKE_MATCH_0", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_1", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_2", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_3", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_4", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_5", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_6", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_7", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_8", cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MATCH_9", cmProperty::VARIABLE,0,0);
-
- cm->DefineProperty("CMAKE_<LANG>_COMPILER_ARG1",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_COMPILER_ENV_VAR",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_COMPILER_ID_RUN",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_ABI_FILES",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_CREATE_ASSEMBLY_SOURCE",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_CREATE_PREPROCESSED_SOURCE",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_FLAGS_DEBUG_INIT",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_FLAGS_INIT",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_FLAGS_MINSIZEREL_INIT",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_FLAGS_RELEASE_INIT",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_FLAGS_RELWITHDEBINFO_INIT",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_INFORMATION_LOADED",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_LINK_EXECUTABLE",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_LINK_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_RESPONSE_FILE_LINK_FLAG",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_STANDARD_LIBRARIES",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_STANDARD_LIBRARIES_INIT",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_USE_RESPONSE_FILE_FOR_INCLUDES",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_USE_RESPONSE_FILE_FOR_OBJECTS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_EXECUTABLE_SUFFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_EXE_LINK_DYNAMIC_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_EXE_LINK_STATIC_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_GENERATOR_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_IMPORT_LIBRARY_PREFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_IMPORT_LIBRARY_SUFFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_INCLUDE_FLAG_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_INCLUDE_FLAG_SEP_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_INCLUDE_SYSTEM_FLAG_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_NEEDS_REQUIRES_STEP_<LANG>_FLAG",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_CREATE_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_LINK_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_LINK_STATIC_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_PREFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_SUFFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG_SEP",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_LIBRARY_RPATH_LINK_<LANG>_FLAG",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG_SEP",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_EXECUTABLE_RPATH_LINK_<LANG>_FLAG",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty(
- "CMAKE_<LANG>_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_MODULE_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_MODULE_LINK_DYNAMIC_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_MODULE_LINK_STATIC_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_MODULE_PREFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_SHARED_MODULE_SUFFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_STATIC_LIBRARY_PREFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_STATIC_LIBRARY_SUFFIX_<LANG>",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_LINK_DEPENDENT_LIBRARY_FILES",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_LINK_DEPENDENT_LIBRARY_DIRS",
- cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_MAKE_INCLUDE_FROM_ROOT",
- cmProperty::VARIABLE,0,0);
-}
diff --git a/Source/cmDocumentVariables.h b/Source/cmDocumentVariables.h
deleted file mode 100644
index 1d59b2450..000000000
--- a/Source/cmDocumentVariables.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmDocumentVariables_h
-#define cmDocumentVariables_h
-class cmake;
-class cmDocumentVariables
-{
-public:
- static void DefineVariables(cmake* cm);
-};
-
-#endif
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index 4edacbb1a..c6286b35a 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -1,1971 +1,754 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDocumentation.h"
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+#include "cmDocumentationSection.h"
+#include "cmRST.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
#include <algorithm>
-
-//----------------------------------------------------------------------------
-static const char *cmDocumentationStandardOptions[][3] =
-{
- {"--copyright [file]", "Print the CMake copyright and exit.",
- "If a file is specified, the copyright is written into it."},
- {"--help,-help,-usage,-h,-H,/?", "Print usage information and exit.",
- "Usage describes the basic command line interface and its options."},
- {"--help-full [file]", "Print full help and exit.",
- "Full help displays most of the documentation provided by the UNIX "
- "man page. It is provided for use on non-UNIX platforms, but is "
- "also convenient if the man page is not installed. If a file is "
- "specified, the help is written into it."},
- {"--help-html [file]", "Print full help in HTML format.",
- "This option is used by CMake authors to help produce web pages. "
- "If a file is specified, the help is written into it."},
- {"--help-man [file]", "Print full help as a UNIX man page and exit.",
- "This option is used by the cmake build to generate the UNIX man page. "
- "If a file is specified, the help is written into it."},
- {"--version,-version,/V [file]",
- "Show program name/version banner and exit.",
- "If a file is specified, the version is written into it."},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmModulesDocumentationDescription[][3] =
-{
- {0,
- " CMake Modules - Modules coming with CMake, the Cross-Platform Makefile "
- "Generator.", 0},
-// CMAKE_DOCUMENTATION_OVERVIEW,
- {0,
- "This is the documentation for the modules and scripts coming with CMake. "
- "Using these modules you can check the computer system for "
- "installed software packages, features of the compiler and the "
- "existence of headers to name just a few.", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmCustomModulesDocumentationDescription[][3] =
-{
- {0,
- " Custom CMake Modules - Additional Modules for CMake.", 0},
-// CMAKE_DOCUMENTATION_OVERVIEW,
- {0,
- "This is the documentation for additional modules and scripts for CMake. "
- "Using these modules you can check the computer system for "
- "installed software packages, features of the compiler and the "
- "existence of headers to name just a few.", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmPropertiesDocumentationDescription[][3] =
-{
- {0,
- " CMake Properties - Properties supported by CMake, "
- "the Cross-Platform Makefile Generator.", 0},
-// CMAKE_DOCUMENTATION_OVERVIEW,
- {0,
- "This is the documentation for the properties supported by CMake. "
- "Properties can have different scopes. They can either be assigned to a "
- "source file, a directory, a target or globally to CMake. By modifying the "
- "values of properties the behaviour of the build system can be customized.",
- 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmCompatCommandsDocumentationDescription[][3] =
-{
- {0,
- " CMake Compatibility Listfile Commands - "
- "Obsolete commands supported by CMake for compatibility.", 0},
-// CMAKE_DOCUMENTATION_OVERVIEW,
- {0,
- "This is the documentation for now obsolete listfile commands from previous "
- "CMake versions, which are still supported for compatibility reasons. You "
- "should instead use the newer, faster and shinier new commands. ;-)", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmDocumentationModulesHeader[][3] =
-{
- {0,
- "The following modules are provided with CMake. "
- "They can be used with INCLUDE(ModuleName).", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmDocumentationCustomModulesHeader[][3] =
-{
- {0,
- "The following modules are also available for CMake. "
- "They can be used with INCLUDE(ModuleName).", 0},
- {0,0,0}
+#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." },
+ { "--help-full [<f>]", "Print all help manuals and exit." },
+ { "--help-manual <man> [<f>]", "Print one help manual and exit." },
+ { "--help-manual-list [<f>]", "List help manuals available and exit." },
+ { "--help-command <cmd> [<f>]", "Print help for one command and exit." },
+ { "--help-command-list [<f>]",
+ "List commands with help available and exit." },
+ { "--help-commands [<f>]", "Print cmake-commands manual and exit." },
+ { "--help-module <mod> [<f>]", "Print help for one module and exit." },
+ { "--help-module-list [<f>]", "List modules with help available and exit." },
+ { "--help-modules [<f>]", "Print cmake-modules manual and exit." },
+ { "--help-policy <cmp> [<f>]", "Print help for one policy and exit." },
+ { "--help-policy-list [<f>]",
+ "List policies with help available and exit." },
+ { "--help-policies [<f>]", "Print cmake-policies manual and exit." },
+ { "--help-property <prop> [<f>]", "Print help for one property and exit." },
+ { "--help-property-list [<f>]",
+ "List properties with help available and exit." },
+ { "--help-properties [<f>]", "Print cmake-properties manual and exit." },
+ { "--help-variable var [<f>]", "Print help for one variable and exit." },
+ { "--help-variable-list [<f>]",
+ "List variables with help available and exit." },
+ { "--help-variables [<f>]", "Print cmake-variables manual and exit." },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char *cmDocumentationGeneratorsHeader[][3] =
-{
- {0,
- "The following generators are available on this platform:", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char *cmDocumentationStandardSeeAlso[][3] =
-{
- {0,
- "The following resources are available to get help using CMake:", 0},
- {"Home Page",
- "http://www.cmake.org",
- "The primary starting point for learning about CMake."},
- {"Frequently Asked Questions",
- "http://www.cmake.org/Wiki/CMake_FAQ",
- "A Wiki is provided containing answers to frequently asked questions. "},
- {"Online Documentation",
- "http://www.cmake.org/HTML/Documentation.html",
- "Links to available documentation may be found on this web page."},
- {"Mailing List",
- "http://www.cmake.org/HTML/MailingLists.html",
- "For help and discussion about using cmake, a mailing list is provided at "
- "cmake@cmake.org. "
- "The list is member-post-only but one may sign up on the CMake web page. "
- "Please first read the full documentation at "
- "http://www.cmake.org before posting questions to the list."},
- {0,0,0}
+static const char* cmDocumentationGeneratorsHeader[][2] = {
+ { CM_NULLPTR, "The following generators are available on this platform:" },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char *cmDocumentationCopyright[][3] =
-{
- {0,
- "Copyright 2000-2012 Kitware, Inc., Insight Software Consortium. "
- "All rights reserved.", 0},
- {0,
- "Redistribution and use in source and binary forms, with or without "
- "modification, are permitted provided that the following conditions are "
- "met:", 0},
- {"",
- "Redistributions of source code must retain the above copyright notice, "
- "this list of conditions and the following disclaimer.", 0},
- {"",
- "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.",
- 0},
- {"",
- "Neither the names of Kitware, Inc., the Insight Software Consortium, "
- "nor the names of their contributors may be used to endorse or promote "
- "products derived from this software without specific prior written "
- "permission.", 0},
- {0,
- "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT "
- "HOLDER 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.",
- 0},
- {0, 0, 0}
-};
-
-//----------------------------------------------------------------------------
-#define DOCUMENT_INTRO(type, default_name, desc) \
- static char const *cmDocumentation##type##Intro[2] = { default_name, desc };
-#define GET_DOCUMENT_INTRO(type) cmDocumentation##type##Intro
-
-DOCUMENT_INTRO(Modules, "cmakemodules",
- "Reference of available CMake modules.");
-DOCUMENT_INTRO(CustomModules, "cmakecustommodules",
- "Reference of available CMake custom modules.");
-DOCUMENT_INTRO(Policies, "cmakepolicies",
- "Reference of CMake policies.");
-DOCUMENT_INTRO(Properties, "cmakeprops",
- "Reference of CMake properties.");
-DOCUMENT_INTRO(Variables, "cmakevars",
- "Reference of CMake variables.");
-DOCUMENT_INTRO(Commands, "cmakecommands",
- "Reference of available CMake commands.");
-DOCUMENT_INTRO(CompatCommands, "cmakecompat",
- "Reference of CMake compatibility commands.");
-
-//----------------------------------------------------------------------------
cmDocumentation::cmDocumentation()
-:CurrentFormatter(0)
{
- this->SetForm(TextForm, 0);
this->addCommonStandardDocSections();
this->ShowGenerators = true;
}
-//----------------------------------------------------------------------------
cmDocumentation::~cmDocumentation()
{
- for(std::vector< char* >::iterator i = this->ModuleStrings.begin();
- i != this->ModuleStrings.end(); ++i)
- {
- delete [] *i;
- }
- for(std::map<std::string,cmDocumentationSection *>::iterator i =
- this->AllSections.begin();
- i != this->AllSections.end(); ++i)
- {
- delete i->second;
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintCopyright(std::ostream& os)
-{
- cmDocumentationSection *sec = this->AllSections["Copyright"];
- const std::vector<cmDocumentationEntry> &entries = sec->GetEntries();
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op)
- {
- if(op->Name.size())
- {
- os << " * ";
- this->TextFormatter.SetIndent(" ");
- this->TextFormatter.PrintColumn(os, op->Brief.c_str());
- }
- else
- {
- this->TextFormatter.SetIndent("");
- this->TextFormatter.PrintColumn(os, op->Brief.c_str());
- }
- os << "\n";
- }
- return true;
+ cmDeleteAll(this->AllSections);
}
-//----------------------------------------------------------------------------
bool cmDocumentation::PrintVersion(std::ostream& os)
{
- os << this->GetNameString() << " version "
- << cmVersion::GetCMakeVersion() << "\n";
+ /* clang-format off */
+ os <<
+ this->GetNameString() <<
+ " version " << cmVersion::GetCMakeVersion() << "\n"
+ "\n"
+ "CMake suite maintained and supported by Kitware (kitware.com/cmake).\n"
+ ;
+ /* clang-format on */
return true;
}
-//----------------------------------------------------------------------------
-void cmDocumentation::AddSectionToPrint(const char *section)
-{
- if (this->AllSections.find(section) != this->AllSections.end())
- {
- this->PrintSections.push_back(this->AllSections[section]);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation::ClearSections()
+bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
{
- this->PrintSections.erase(this->PrintSections.begin(),
- this->PrintSections.end());
- this->ModulesFound.clear();
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation::AddDocumentIntroToPrint(const char* intro[2])
-{
- const char* docname = this->GetDocName(false);
- if(intro && docname)
- {
- cmDocumentationSection* section;
- std::string desc("");
-
- desc += docname;
- desc += " - ";
- desc += intro[1];
-
- section = new cmDocumentationSection("Introduction", "NAME");
- section->Append(0, desc.c_str(), 0);
- this->PrintSections.push_back(section);
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os,
- const char* docname)
-{
- if ((this->CurrentFormatter->GetForm() != HTMLForm)
- && (this->CurrentFormatter->GetForm() != DocbookForm)
- && (this->CurrentFormatter->GetForm() != ManForm))
- {
- this->PrintVersion(os);
- }
-
- // Handle Document Name. docname==0 disables intro.
- this->SetDocName("");
- if (docname)
- {
- if (*docname)
- this->SetDocName(docname);
- else // empty string was given. select default if possible
- this->SetDocName(this->GetDefaultDocName(ht));
- }
-
- switch (ht)
- {
+ switch (ht) {
case cmDocumentation::Usage:
- return this->PrintDocumentationUsage(os);
- case cmDocumentation::Single:
- return this->PrintDocumentationSingle(os);
- case cmDocumentation::SingleModule:
- return this->PrintDocumentationSingleModule(os);
- case cmDocumentation::SinglePolicy:
- return this->PrintDocumentationSinglePolicy(os);
- case cmDocumentation::SingleProperty:
- return this->PrintDocumentationSingleProperty(os);
- case cmDocumentation::SingleVariable:
- return this->PrintDocumentationSingleVariable(os);
- case cmDocumentation::List:
- this->PrintDocumentationList(os,"Commands");
- this->PrintDocumentationList(os,"Compatibility Commands");
- return true;
- case cmDocumentation::ModuleList:
- // find the modules first, print the custom module docs only if
- // any custom modules have been found actually, Alex
- this->CreateCustomModulesSection();
- this->CreateModulesSection();
- if (this->AllSections.find("Custom CMake Modules")
- != this->AllSections.end())
- {
- this->PrintDocumentationList(os,"Custom CMake Modules");
- }
- this->PrintDocumentationList(os,"Modules");
- return true;
- case cmDocumentation::PropertyList:
- this->PrintDocumentationList(os,"Properties Description");
- for (std::vector<std::string>::iterator i =
- this->PropertySections.begin();
- i != this->PropertySections.end(); ++i)
- {
- this->PrintDocumentationList(os,i->c_str());
- }
- return true;
- case cmDocumentation::VariableList:
- for (std::vector<std::string>::iterator i =
- this->VariableSections.begin();
- i != this->VariableSections.end(); ++i)
- {
- this->PrintDocumentationList(os,i->c_str());
- }
- return true;
+ return this->PrintUsage(os);
+ case cmDocumentation::Help:
+ return this->PrintHelp(os);
case cmDocumentation::Full:
- return this->PrintDocumentationFull(os);
- case cmDocumentation::Modules:
- return this->PrintDocumentationModules(os);
- case cmDocumentation::CustomModules:
- return this->PrintDocumentationCustomModules(os);
- case cmDocumentation::Policies:
- return this->PrintDocumentationPolicies(os);
- case cmDocumentation::Properties:
- return this->PrintDocumentationProperties(os);
- case cmDocumentation::Variables:
- return this->PrintDocumentationVariables(os);
- case cmDocumentation::Commands:
- return this->PrintDocumentationCurrentCommands(os);
- case cmDocumentation::CompatCommands:
- return this->PrintDocumentationCompatCommands(os);
-
- case cmDocumentation::Copyright:
- return this->PrintCopyright(os);
+ return this->PrintHelpFull(os);
+ case cmDocumentation::OneManual:
+ return this->PrintHelpOneManual(os);
+ case cmDocumentation::OneCommand:
+ return this->PrintHelpOneCommand(os);
+ case cmDocumentation::OneModule:
+ return this->PrintHelpOneModule(os);
+ case cmDocumentation::OnePolicy:
+ return this->PrintHelpOnePolicy(os);
+ case cmDocumentation::OneProperty:
+ return this->PrintHelpOneProperty(os);
+ case cmDocumentation::OneVariable:
+ return this->PrintHelpOneVariable(os);
+ case cmDocumentation::ListManuals:
+ return this->PrintHelpListManuals(os);
+ case cmDocumentation::ListCommands:
+ return this->PrintHelpListCommands(os);
+ case cmDocumentation::ListModules:
+ return this->PrintHelpListModules(os);
+ case cmDocumentation::ListProperties:
+ return this->PrintHelpListProperties(os);
+ case cmDocumentation::ListVariables:
+ return this->PrintHelpListVariables(os);
+ case cmDocumentation::ListPolicies:
+ return this->PrintHelpListPolicies(os);
+ case cmDocumentation::ListGenerators:
+ return this->PrintHelpListGenerators(os);
case cmDocumentation::Version:
- return true;
- default: return false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmDocumentation::CreateModulesSection()
-{
- cmDocumentationSection *sec =
- new cmDocumentationSection("Standard CMake Modules", "MODULES");
- this->AllSections["Modules"] = sec;
- std::string cmakeModules = this->CMakeRoot;
- cmakeModules += "/Modules";
- cmsys::Directory dir;
- dir.Load(cmakeModules.c_str());
- if (dir.GetNumberOfFiles() > 0)
- {
- sec->Append(cmDocumentationModulesHeader[0]);
- sec->Append(cmModulesDocumentationDescription);
- this->CreateModuleDocsForDir(dir, *this->AllSections["Modules"]);
- }
- return true;
-}
-
-//----------------------------------------------------------------------------
-bool cmDocumentation::CreateCustomModulesSection()
-{
- bool sectionHasHeader = false;
-
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs);
-
- for(std::vector<std::string>::const_iterator dirIt = dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- cmsys::Directory dir;
- dir.Load(dirIt->c_str());
- if (dir.GetNumberOfFiles() > 0)
- {
- if (!sectionHasHeader)
- {
- cmDocumentationSection *sec =
- new cmDocumentationSection("Custom CMake Modules","CUSTOM MODULES");
- this->AllSections["Custom CMake Modules"] = sec;
- sec->Append(cmDocumentationCustomModulesHeader[0]);
- sec->Append(cmCustomModulesDocumentationDescription);
- sectionHasHeader = true;
- }
- this->CreateModuleDocsForDir
- (dir, *this->AllSections["Custom CMake Modules"]);
- }
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation
-::CreateModuleDocsForDir(cmsys::Directory& dir,
- cmDocumentationSection &moduleSection)
-{
- // sort the files alphabetically, so the docs for one module are easier
- // to find than if they are in random order
- std::vector<std::string> sortedFiles;
- for(unsigned int i = 0; i < dir.GetNumberOfFiles(); ++i)
- {
- sortedFiles.push_back(dir.GetFile(i));
+ return this->PrintVersion(os);
+ case cmDocumentation::OldCustomModules:
+ return this->PrintOldCustomModules(os);
+ default:
+ return false;
}
- std::sort(sortedFiles.begin(), sortedFiles.end());
-
- for(std::vector<std::string>::const_iterator fname = sortedFiles.begin();
- fname!=sortedFiles.end(); ++fname)
- {
- if(fname->length() > 6)
- {
- if(fname->substr(fname->length()-6, 6) == ".cmake")
- {
- std::string moduleName = fname->substr(0, fname->length()-6);
- // this check is to avoid creating documentation for the modules with
- // the same name in multiple directories of CMAKE_MODULE_PATH
- if (this->ModulesFound.find(moduleName) == this->ModulesFound.end())
- {
- this->ModulesFound.insert(moduleName);
- std::string path = dir.GetPath();
- path += "/";
- path += (*fname);
- this->CreateSingleModule(path.c_str(), moduleName.c_str(),
- moduleSection);
- }
- }
- }
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmDocumentation::CreateSingleModule(const char* fname,
- const char* moduleName,
- cmDocumentationSection &moduleSection)
-{
- std::ifstream fin(fname);
- if(!fin)
- {
- std::cerr << "Internal error: can not open module." << fname << std::endl;
- return false;
- }
- std::string line;
- std::string text;
- std::string brief;
- brief = " ";
- bool newParagraph = true;
- while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
- {
- if(line.size() && line[0] == '#')
- {
- /* line beginnings with ## are mark-up ignore them */
- if (line.size()>=2 && line[1] == '#') continue;
- // blank line
- if(line.size() <= 2)
- {
- text += "\n";
- newParagraph = true;
- }
- else if(line[2] == '-')
- {
- brief = line.c_str()+4;
- }
- else
- {
- // two spaces
- if(line[1] == ' ' && line[2] == ' ')
- {
- if(!newParagraph)
- {
- text += "\n";
- newParagraph = true;
- }
- // Skip #, and leave space for preformatted
- text += line.c_str()+1;
- text += "\n";
- }
- else if(line[1] == ' ')
- {
- if(!newParagraph)
- {
- text += " ";
- }
- newParagraph = false;
- // skip # and space
- text += line.c_str()+2;
- }
- else
- {
- if(!newParagraph)
- {
- text += " ";
- }
- newParagraph = false;
- // skip #
- text += line.c_str()+1;
- }
- }
- }
- else
- {
- break;
- }
- }
-
- if(text.length() < 2 && brief.length() == 1)
- {
- return false;
- }
-
- char* pname = strcpy(new char[strlen(moduleName)+1], moduleName);
- char* ptext = strcpy(new char[text.length()+1], text.c_str());
- this->ModuleStrings.push_back(pname);
- this->ModuleStrings.push_back(ptext);
- char* pbrief = strcpy(new char[brief.length()+1], brief.c_str());
- this->ModuleStrings.push_back(pbrief);
- moduleSection.Append(pname, pbrief, ptext);
- return true;
}
-
-//----------------------------------------------------------------------------
bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
{
+ int count = 0;
bool result = true;
// Loop over requested documentation types.
- for(std::vector<RequestedHelpItem>::const_iterator
- i = this->RequestedHelpItems.begin();
- i != this->RequestedHelpItems.end();
- ++i)
- {
- this->SetForm(i->HelpForm, i->ManSection);
+ for (std::vector<RequestedHelpItem>::const_iterator i =
+ this->RequestedHelpItems.begin();
+ i != this->RequestedHelpItems.end(); ++i) {
this->CurrentArgument = i->Argument;
// If a file name was given, use it. Otherwise, default to the
// given stream.
- std::ofstream* fout = 0;
+ cmsys::ofstream fout;
std::ostream* s = &os;
- std::string docname("");
- if(i->Filename.length() > 0)
- {
- fout = new std::ofstream(i->Filename.c_str(), std::ios::out);
- if(fout)
- {
- s = fout;
- }
- else
- {
- result = false;
- }
- if(i->Filename != "-")
- {
- docname = cmSystemTools::GetFilenameWithoutLastExtension(i->Filename);
- }
- }
+ if (!i->Filename.empty()) {
+ fout.open(i->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, docname.c_str()) || !*s)
- {
+ if (!this->PrintDocumentation(i->HelpType, *s) || s->fail()) {
result = false;
- }
-
- // Close the file if we wrote one.
- if(fout)
- {
- delete fout;
- }
}
+ }
return result;
}
-#define GET_OPT_ARGUMENT(target) \
- if((i+1 < argc) && !this->IsOption(argv[i+1])) \
- { \
- target = argv[i+1]; \
- i = i+1; \
- };
-
+#define GET_OPT_ARGUMENT(target) \
+ if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \
+ (target) = argv[i + 1]; \
+ i = i + 1; \
+ };
-cmDocumentation::Form cmDocumentation::GetFormFromFilename(
- const std::string& filename,
- int* manSection)
+void cmDocumentation::WarnFormFromFilename(
+ cmDocumentation::RequestedHelpItem& request, bool& result)
{
- std::string ext = cmSystemTools::GetFilenameLastExtension(filename);
+ std::string ext = cmSystemTools::GetFilenameLastExtension(request.Filename);
ext = cmSystemTools::UpperCase(ext);
- if ((ext == ".HTM") || (ext == ".HTML"))
- {
- return cmDocumentation::HTMLForm;
- }
-
- if (ext == ".DOCBOOK")
- {
- return cmDocumentation::DocbookForm;
- }
-
+ if ((ext == ".HTM") || (ext == ".HTML")) {
+ request.HelpType = cmDocumentation::None;
+ result = true;
+ cmSystemTools::Message("Warning: HTML help format no longer supported");
+ } else if (ext == ".DOCBOOK") {
+ request.HelpType = cmDocumentation::None;
+ result = true;
+ cmSystemTools::Message("Warning: Docbook help format no longer supported");
+ }
// ".1" to ".9" should be manpages
- if ((ext.length()==2) && (ext[1] >='1') && (ext[1]<='9'))
- {
- if (manSection)
- {
- *manSection = ext[1] - '0';
- }
- return cmDocumentation::ManForm;
- }
-
- return cmDocumentation::TextForm;
+ else if ((ext.length() == 2) && (ext[1] >= '1') && (ext[1] <= '9')) {
+ request.HelpType = cmDocumentation::None;
+ result = true;
+ cmSystemTools::Message("Warning: Man help format no longer supported");
+ }
}
-//----------------------------------------------------------------------------
void cmDocumentation::addCommonStandardDocSections()
{
- cmDocumentationSection *sec;
-
- sec = new cmDocumentationSection("Author","AUTHOR");
- sec->Append(cmDocumentationEntry
- (0,
- "This manual page was generated by the \"--help-man\" option.",
- 0));
- this->AllSections["Author"] = sec;
-
- sec = new cmDocumentationSection("Copyright","COPYRIGHT");
- sec->Append(cmDocumentationCopyright);
- this->AllSections["Copyright"] = sec;
-
- sec = new cmDocumentationSection("See Also","SEE ALSO");
- sec->Append(cmDocumentationStandardSeeAlso);
- this->AllSections["Standard See Also"] = sec;
+ cmDocumentationSection* sec;
- sec = new cmDocumentationSection("Options","OPTIONS");
- sec->Append(cmDocumentationStandardOptions);
- this->AllSections["Options"] = sec;
-
- sec = new cmDocumentationSection("Compatibility Commands",
- "COMPATIBILITY COMMANDS");
- sec->Append(cmCompatCommandsDocumentationDescription);
- this->AllSections["Compatibility Commands"] = sec;
+ sec = new cmDocumentationSection("Options", "OPTIONS");
+ sec->Append(cmDocumentationStandardOptions);
+ this->AllSections["Options"] = sec;
}
-//----------------------------------------------------------------------------
void cmDocumentation::addCMakeStandardDocSections()
{
- cmDocumentationSection *sec;
-
- sec = new cmDocumentationSection("Properties","PROPERTIES");
- sec->Append(cmPropertiesDocumentationDescription);
- this->AllSections["Properties Description"] = sec;
-
- sec = new cmDocumentationSection("Generators","GENERATORS");
- sec->Append(cmDocumentationGeneratorsHeader);
- this->AllSections["Generators"] = sec;
-
- this->PropertySections.push_back("Properties of Global Scope");
- this->PropertySections.push_back("Properties on Directories");
- this->PropertySections.push_back("Properties on Targets");
- this->PropertySections.push_back("Properties on Tests");
- this->PropertySections.push_back("Properties on Source Files");
- this->PropertySections.push_back("Properties on Cache Entries");
-
- this->VariableSections.push_back("Variables that Provide Information");
- this->VariableSections.push_back("Variables That Change Behavior");
- this->VariableSections.push_back("Variables That Describe the System");
- this->VariableSections.push_back("Variables that Control the Build");
- this->VariableSections.push_back("Variables for Languages");
+ cmDocumentationSection* sec;
+ sec = new cmDocumentationSection("Generators", "GENERATORS");
+ sec->Append(cmDocumentationGeneratorsHeader);
+ this->AllSections["Generators"] = sec;
}
-//----------------------------------------------------------------------------
void cmDocumentation::addCTestStandardDocSections()
{
- // This is currently done for backward compatibility reason
- // We may suppress some of these.
- addCMakeStandardDocSections();
+ // This is currently done for backward compatibility reason
+ // We may suppress some of these.
+ addCMakeStandardDocSections();
}
-//----------------------------------------------------------------------------
void cmDocumentation::addCPackStandardDocSections()
{
- cmDocumentationSection *sec;
+ cmDocumentationSection* sec;
- sec = new cmDocumentationSection("Generators","GENERATORS");
- sec->Append(cmDocumentationGeneratorsHeader);
- this->AllSections["Generators"] = sec;
-
- this->VariableSections.push_back(
- "Variables common to all CPack generators");
+ sec = new cmDocumentationSection("Generators", "GENERATORS");
+ sec->Append(cmDocumentationGeneratorsHeader);
+ this->AllSections["Generators"] = sec;
}
-void cmDocumentation::addAutomaticVariableSections(const std::string& section)
-{
- std::vector<std::string>::iterator it;
- it = std::find(this->VariableSections.begin(),
- this->VariableSections.end(),
- section);
- /* if the section does not exist then add it */
- if (it==this->VariableSections.end())
- {
- this->VariableSections.push_back(section);
- }
-}
-//----------------------------------------------------------------------------
-int cmDocumentation::getDocumentedModulesListInDir(
- std::string path,
- std::string globExpr,
- documentedModulesList_t& docedModuleList)
-{
- cmsys::Glob gl;
- std::string findExpr;
- std::vector<std::string> files;
- std::string line;
- documentedModuleSectionPair_t docPair;
- int nbDocumentedModules = 0;
-
- findExpr = path + "/" + globExpr;
- if (gl.FindFiles(findExpr))
- {
- files = gl.GetFiles();
- for (std::vector<std::string>::iterator itf=files.begin();
- itf!=files.end();++itf)
- {
- std::ifstream fin((*itf).c_str());
- // file access trouble ignore it (ignore this kind of error)
- if (!fin) continue;
- /* read first line in order to get doc section */
- if (cmSystemTools::GetLineFromStream(fin, line))
- {
- /* Doc section indicates that
- * this file has structured doc in it.
- */
- if (line.find("##section")!=std::string::npos)
- {
- // ok found one more documented module
- ++nbDocumentedModules;
- docPair.first = *itf;
- // 10 is the size of '##section' + 1
- docPair.second = line.substr(10,std::string::npos);
- docedModuleList.push_back(docPair);
- }
- // No else if no section is found (undocumented module)
- }
- // No else cannot read first line (ignore this kind of error)
- line = "";
- }
- }
- if (nbDocumentedModules>0)
- {
- return 0;
- }
- else
- {
- return 1;
- }
-}
-
-//----------------------------------------------------------------------------
-static void trim(std::string& s)
-{
- std::string::size_type pos = s.find_last_not_of(' ');
- if(pos != std::string::npos)
- {
- s.erase(pos + 1);
- pos = s.find_first_not_of(' ');
- if(pos != std::string::npos) s.erase(0, pos);
- }
- else
- {
- s.erase(s.begin(), s.end());
- }
-}
-
-int cmDocumentation::GetStructuredDocFromFile(
- const char* fname,
- std::vector<cmDocumentationEntry>& commands,
- cmake* cm)
-{
- typedef enum sdoce {
- SDOC_NONE, SDOC_MODULE, SDOC_MACRO, SDOC_FUNCTION, SDOC_VARIABLE,
- SDOC_SECTION,
- SDOC_UNKNOWN} sdoc_t;
- int nbDocItemFound = 0;
- int docCtxIdx = 0;
- std::vector<int> docContextStack(60);
- docContextStack[docCtxIdx]=SDOC_NONE;
- cmDocumentationEntry e;
- std::ifstream fin(fname);
- if(!fin)
- {
- return nbDocItemFound;
- }
- std::string section;
- std::string name;
- std::string full;
- std::string brief;
- std::string line;
- bool newCtx = false; /* we've just entered ##<beginkey> context */
- bool inBrief = false; /* we are currently parsing brief desc. */
- bool inFullFirstParagraph = false; /* we are currently parsing full
- desc. first paragraph */
- brief = "";
- full = "";
- bool newParagraph = true;
- while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
- {
- if(line.size() && line[0] == '#')
- {
- /* handle structured doc context */
- if ((line.size()>=2) && line[1]=='#')
- {
- /* markup word is following '##' stopping at first space
- * Some markup word like 'section' may have more characters
- * following but we don't handle those here.
- */
- std::string mkword = line.substr(2,line.find(' ',2)-2);
- if (mkword=="macro")
- {
- docCtxIdx++;
- docContextStack[docCtxIdx]=SDOC_MACRO;
- newCtx = true;
- }
- else if (mkword=="variable")
- {
- docCtxIdx++;
- docContextStack[docCtxIdx]=SDOC_VARIABLE;
- newCtx = true;
- }
- else if (mkword=="function")
- {
- docCtxIdx++;
- docContextStack[docCtxIdx]=SDOC_FUNCTION;
- newCtx = true;
- }
- else if (mkword=="module")
- {
- docCtxIdx++;
- docContextStack[docCtxIdx]=SDOC_MODULE;
- newCtx = true;
- }
- else if (mkword=="section")
- {
- docCtxIdx++;
- docContextStack[docCtxIdx]=SDOC_SECTION;
- // 10 is the size of '##section' + 1
- section = line.substr(10,std::string::npos);
- /* drop the rest of the line */
- line = "";
- newCtx = true;
- }
- else if (mkword.substr(0,3)=="end")
- {
- switch (docContextStack[docCtxIdx]) {
- case SDOC_MACRO:
- /* for now MACRO and FUNCTION are handled in the same way */
- case SDOC_FUNCTION:
- commands.push_back(cmDocumentationEntry(name.c_str(),
- brief.c_str(),full.c_str()));
- break;
- case SDOC_VARIABLE:
- this->addAutomaticVariableSections(section);
- cm->DefineProperty
- (name.c_str(), cmProperty::VARIABLE,
- brief.c_str(),
- full.c_str(),false,
- section.c_str());
- break;
- case SDOC_MODULE:
- /* not implemented */
- break;
- case SDOC_SECTION:
- /* not implemented */
- break;
- default:
- /* ignore other cases */
- break;
- }
- docCtxIdx--;
- newCtx = false;
- ++nbDocItemFound;
- }
- else
- {
- // error out unhandled context
- return nbDocItemFound;
- }
- /* context is set go to next doc line */
- continue;
- }
-
- // Now parse the text attached to the context
-
- // The first line after the context mark-up contains::
- // name - brief until. (brief is dot terminated or
- // followed by a blank line)
- if (newCtx)
- {
- // no brief (for easy variable definition)
- if (line.find("-")==std::string::npos)
- {
- name = line.substr(1,std::string::npos);
- trim(name);
- brief = "";
- inBrief = false;
- full = "";
- }
- // here we have a name and brief beginning
- else
- {
- name = line.substr(1,line.find("-")-1);
- trim(name);
- // we are parsing the brief context
- brief = line.substr(line.find("-")+1,std::string::npos);
- trim(brief);
- // Brief may already be terminated on the first line
- if (brief.find('.')!=std::string::npos)
- {
- inBrief = false;
- full = brief.substr(brief.find('.')+1,std::string::npos);
- trim(full);
- inFullFirstParagraph = true;
- brief = brief.substr(0,brief.find('.'));
- }
- // brief is continued on following lines
- else
- {
- inBrief = true;
- full = "";
- }
- }
- newCtx = false;
- continue;
- }
- // blank line
- if(line.size() <= 2)
- {
- if (inBrief) {
- inBrief = false;
- full = "";
- } else {
- if (full.length()>0)
- {
- full += "\n";
- }
- // the first paragraph of full has ended
- inFullFirstParagraph = false;
- }
- newParagraph = true;
- }
- // brief is terminated by '.'
- else if (inBrief && (line.find('.')!=std::string::npos))
- {
- /* the brief just ended */
- inBrief = false;
- std::string endBrief = line.substr(1,line.find('.'));
- trim(endBrief);
- trim(brief);
- brief += " " + endBrief;
- full += line.substr(line.find('.')+1,std::string::npos);
- trim(full);
- inFullFirstParagraph = true;
- }
- // we handle full text or multi-line brief.
- else
- {
- std::string* text;
- if (inBrief)
- {
- text = &brief;
- }
- else
- {
- text = &full;
- }
- // two spaces
- if(line[1] == ' ' && line[2] == ' ')
- {
- // there is no "full first paragraph at all."
- if (line[3] == ' ')
- {
- inFullFirstParagraph = false;
- }
-
- if(!newParagraph && !inFullFirstParagraph)
- {
- *text += "\n";
- newParagraph = true;
- }
- // Skip #, and leave space for pre-formatted
- if (inFullFirstParagraph)
- {
- std::string temp = line.c_str()+1;
- trim(temp);
- *text += " " + temp;
- }
- else
- {
- *text += line.c_str()+1;
- *text += "\n";
- }
- }
- else if(line[1] == ' ')
- {
- if(!newParagraph)
- {
- *text += " ";
- }
- newParagraph = false;
- // skip # and space
- *text += line.c_str()+2;
- }
- else
- {
- if(!newParagraph)
- {
- *text += " ";
- }
- newParagraph = false;
- // skip #
- *text += line.c_str()+1;
- }
- }
- }
- /* next line is not the first context line */
- newCtx = false;
- }
- return nbDocItemFound;
-}
-
-//----------------------------------------------------------------------------
bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
const char* exitOpt)
{
// Providing zero arguments gives usage information.
- if(argc == 1)
- {
+ if (argc == 1) {
RequestedHelpItem help;
help.HelpType = cmDocumentation::Usage;
- help.HelpForm = cmDocumentation::UsageForm;
this->RequestedHelpItems.push_back(help);
return true;
- }
+ }
// Search for supported help options.
bool result = false;
- for(int i=1; i < argc; ++i)
- {
- if(exitOpt && strcmp(argv[i], exitOpt) == 0)
- {
+ for (int i = 1; i < argc; ++i) {
+ if (exitOpt && strcmp(argv[i], exitOpt) == 0) {
return result;
- }
+ }
RequestedHelpItem help;
// Check if this is a supported help option.
- if((strcmp(argv[i], "-help") == 0) ||
- (strcmp(argv[i], "--help") == 0) ||
- (strcmp(argv[i], "/?") == 0) ||
- (strcmp(argv[i], "-usage") == 0) ||
- (strcmp(argv[i], "-h") == 0) ||
- (strcmp(argv[i], "-H") == 0))
- {
- help.HelpType = cmDocumentation::Usage;
- help.HelpForm = cmDocumentation::UsageForm;
+ if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0) ||
+ (strcmp(argv[i], "/?") == 0) || (strcmp(argv[i], "-usage") == 0) ||
+ (strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-H") == 0)) {
+ help.HelpType = cmDocumentation::Help;
GET_OPT_ARGUMENT(help.Argument);
help.Argument = cmSystemTools::LowerCase(help.Argument);
// special case for single command
- if (!help.Argument.empty())
- {
- help.HelpType = cmDocumentation::Single;
- }
+ if (!help.Argument.empty()) {
+ help.HelpType = cmDocumentation::OneCommand;
}
- else if(strcmp(argv[i], "--help-properties") == 0)
- {
- help.HelpType = cmDocumentation::Properties;
+ } else if (strcmp(argv[i], "--help-properties") == 0) {
+ help.HelpType = cmDocumentation::OneManual;
+ help.Argument = "cmake-properties.7";
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-policies") == 0)
- {
- help.HelpType = cmDocumentation::Policies;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-policies") == 0) {
+ help.HelpType = cmDocumentation::OneManual;
+ help.Argument = "cmake-policies.7";
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-variables") == 0)
- {
- help.HelpType = cmDocumentation::Variables;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-variables") == 0) {
+ help.HelpType = cmDocumentation::OneManual;
+ help.Argument = "cmake-variables.7";
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-modules") == 0)
- {
- help.HelpType = cmDocumentation::Modules;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-modules") == 0) {
+ help.HelpType = cmDocumentation::OneManual;
+ help.Argument = "cmake-modules.7";
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-custom-modules") == 0)
- {
- help.HelpType = cmDocumentation::CustomModules;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-custom-modules") == 0) {
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
+ cmSystemTools::Message(
+ "Warning: --help-custom-modules no longer supported");
+ if (help.Filename.empty()) {
+ return true;
}
- else if(strcmp(argv[i], "--help-commands") == 0)
- {
- help.HelpType = cmDocumentation::Commands;
+ // Avoid breaking old project builds completely by at least generating
+ // the output file. Abuse help.Argument to give the file name to
+ // PrintOldCustomModules without disrupting our internal API.
+ help.HelpType = cmDocumentation::OldCustomModules;
+ help.Argument = cmSystemTools::GetFilenameName(help.Filename);
+ } else if (strcmp(argv[i], "--help-commands") == 0) {
+ help.HelpType = cmDocumentation::OneManual;
+ help.Argument = "cmake-commands.7";
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-compatcommands") == 0)
- {
- help.HelpType = cmDocumentation::CompatCommands;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-compatcommands") == 0) {
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-full") == 0)
- {
+ cmSystemTools::Message(
+ "Warning: --help-compatcommands no longer supported");
+ return true;
+ } else if (strcmp(argv[i], "--help-full") == 0) {
help.HelpType = cmDocumentation::Full;
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-html") == 0)
- {
- help.HelpType = cmDocumentation::Full;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-html") == 0) {
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::HTMLForm;
- }
- else if(strcmp(argv[i], "--help-man") == 0)
- {
- help.HelpType = cmDocumentation::Full;
+ cmSystemTools::Message("Warning: --help-html no longer supported");
+ return true;
+ } else if (strcmp(argv[i], "--help-man") == 0) {
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::ManForm;
- help.ManSection = 1;
- }
- else if(strcmp(argv[i], "--help-command") == 0)
- {
- help.HelpType = cmDocumentation::Single;
+ cmSystemTools::Message("Warning: --help-man no longer supported");
+ return true;
+ } else if (strcmp(argv[i], "--help-command") == 0) {
+ help.HelpType = cmDocumentation::OneCommand;
GET_OPT_ARGUMENT(help.Argument);
GET_OPT_ARGUMENT(help.Filename);
help.Argument = cmSystemTools::LowerCase(help.Argument);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-module") == 0)
- {
- help.HelpType = cmDocumentation::SingleModule;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-module") == 0) {
+ help.HelpType = cmDocumentation::OneModule;
GET_OPT_ARGUMENT(help.Argument);
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-property") == 0)
- {
- help.HelpType = cmDocumentation::SingleProperty;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-property") == 0) {
+ help.HelpType = cmDocumentation::OneProperty;
GET_OPT_ARGUMENT(help.Argument);
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-policy") == 0)
- {
- help.HelpType = cmDocumentation::SinglePolicy;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-policy") == 0) {
+ help.HelpType = cmDocumentation::OnePolicy;
GET_OPT_ARGUMENT(help.Argument);
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-variable") == 0)
- {
- help.HelpType = cmDocumentation::SingleVariable;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-variable") == 0) {
+ help.HelpType = cmDocumentation::OneVariable;
GET_OPT_ARGUMENT(help.Argument);
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = this->GetFormFromFilename(help.Filename,
- &help.ManSection);
- }
- else if(strcmp(argv[i], "--help-command-list") == 0)
- {
- help.HelpType = cmDocumentation::List;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-manual") == 0) {
+ help.HelpType = cmDocumentation::OneManual;
+ GET_OPT_ARGUMENT(help.Argument);
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::TextForm;
- }
- else if(strcmp(argv[i], "--help-module-list") == 0)
- {
- help.HelpType = cmDocumentation::ModuleList;
+ this->WarnFormFromFilename(help, result);
+ } else if (strcmp(argv[i], "--help-command-list") == 0) {
+ help.HelpType = cmDocumentation::ListCommands;
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::TextForm;
- }
- else if(strcmp(argv[i], "--help-property-list") == 0)
- {
- help.HelpType = cmDocumentation::PropertyList;
+ } else if (strcmp(argv[i], "--help-module-list") == 0) {
+ help.HelpType = cmDocumentation::ListModules;
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::TextForm;
- }
- else if(strcmp(argv[i], "--help-variable-list") == 0)
- {
- help.HelpType = cmDocumentation::VariableList;
+ } else if (strcmp(argv[i], "--help-property-list") == 0) {
+ help.HelpType = cmDocumentation::ListProperties;
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::TextForm;
- }
- else if(strcmp(argv[i], "--copyright") == 0)
- {
- help.HelpType = cmDocumentation::Copyright;
+ } else if (strcmp(argv[i], "--help-variable-list") == 0) {
+ help.HelpType = cmDocumentation::ListVariables;
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::UsageForm;
- }
- else if((strcmp(argv[i], "--version") == 0) ||
- (strcmp(argv[i], "-version") == 0) ||
- (strcmp(argv[i], "/V") == 0))
- {
+ } else if (strcmp(argv[i], "--help-policy-list") == 0) {
+ help.HelpType = cmDocumentation::ListPolicies;
+ GET_OPT_ARGUMENT(help.Filename);
+ } else if (strcmp(argv[i], "--help-manual-list") == 0) {
+ help.HelpType = cmDocumentation::ListManuals;
+ GET_OPT_ARGUMENT(help.Filename);
+ } else if (strcmp(argv[i], "--copyright") == 0) {
+ GET_OPT_ARGUMENT(help.Filename);
+ cmSystemTools::Message("Warning: --copyright no longer supported");
+ return true;
+ } else if ((strcmp(argv[i], "--version") == 0) ||
+ (strcmp(argv[i], "-version") == 0) ||
+ (strcmp(argv[i], "/V") == 0)) {
help.HelpType = cmDocumentation::Version;
GET_OPT_ARGUMENT(help.Filename);
- help.HelpForm = cmDocumentation::UsageForm;
- }
- if(help.HelpType != None)
- {
+ }
+ if (help.HelpType != None) {
// This is a help option. See if there is a file name given.
result = true;
this->RequestedHelpItems.push_back(help);
- }
}
+ }
return result;
}
-//----------------------------------------------------------------------------
-void cmDocumentation::Print(Form f, int manSection, std::ostream& os)
-{
- this->SetForm(f, manSection);
- this->Print(os);
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation::Print(std::ostream& os)
-{
- // if the formatter supports it, print a master index for
- // all sections
- this->CurrentFormatter->PrintIndex(os, this->PrintSections);
- for(unsigned int i=0; i < this->PrintSections.size(); ++i)
- {
- std::string name = this->PrintSections[i]->
- GetName((this->CurrentFormatter->GetForm()));
- this->CurrentFormatter->PrintSection(os,*this->PrintSections[i],
- name.c_str());
- }
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation::SetName(const char* name)
-{
- this->NameString = name?name:"";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation::SetDocName(const char *docname)
+void cmDocumentation::SetName(const std::string& name)
{
- this->DocName = docname?docname:"";
+ this->NameString = name;
}
-//----------------------------------------------------------------------------
-void cmDocumentation::SetSection(const char *name,
- cmDocumentationSection *section)
+void cmDocumentation::SetSection(const char* name,
+ cmDocumentationSection* section)
{
- if (this->AllSections.find(name) != this->AllSections.end())
- {
+ if (this->AllSections.find(name) != this->AllSections.end()) {
delete this->AllSections[name];
- }
+ }
this->AllSections[name] = section;
}
-//----------------------------------------------------------------------------
-void cmDocumentation::SetSection(const char *name,
- std::vector<cmDocumentationEntry> &docs)
+void cmDocumentation::SetSection(const char* name,
+ std::vector<cmDocumentationEntry>& docs)
{
- cmDocumentationSection *sec =
- new cmDocumentationSection(name,
- cmSystemTools::UpperCase(name).c_str());
+ cmDocumentationSection* sec =
+ new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
sec->Append(docs);
- this->SetSection(name,sec);
+ this->SetSection(name, sec);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::SetSection(const char *name,
- const char *docs[][3])
+void cmDocumentation::SetSection(const char* name, const char* docs[][2])
{
- cmDocumentationSection *sec =
- new cmDocumentationSection(name,
- cmSystemTools::UpperCase(name).c_str());
+ cmDocumentationSection* sec =
+ new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
sec->Append(docs);
- this->SetSection(name,sec);
+ this->SetSection(name, sec);
}
-//----------------------------------------------------------------------------
-void cmDocumentation
-::SetSections(std::map<std::string,cmDocumentationSection *> &sections)
+void cmDocumentation::SetSections(
+ 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 (std::map<std::string, cmDocumentationSection*>::const_iterator it =
+ sections.begin();
+ it != sections.end(); ++it) {
+ this->SetSection(it->first.c_str(), it->second);
+ }
}
-//----------------------------------------------------------------------------
-void cmDocumentation::PrependSection(const char *name,
- const char *docs[][3])
+void cmDocumentation::PrependSection(const char* name, const char* docs[][2])
{
- cmDocumentationSection *sec = 0;
- if (this->AllSections.find(name) == this->AllSections.end())
- {
- sec = new cmDocumentationSection
- (name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name,sec);
- }
- else
- {
+ 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);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::PrependSection(const char *name,
- std::vector<cmDocumentationEntry> &docs)
+void cmDocumentation::PrependSection(const char* name,
+ std::vector<cmDocumentationEntry>& docs)
{
- cmDocumentationSection *sec = 0;
- if (this->AllSections.find(name) == this->AllSections.end())
- {
- sec = new cmDocumentationSection
- (name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name,sec);
- }
- else
- {
+ 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);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::AppendSection(const char *name,
- const char *docs[][3])
+void cmDocumentation::AppendSection(const char* name, const char* docs[][2])
{
- cmDocumentationSection *sec = 0;
- if (this->AllSections.find(name) == this->AllSections.end())
- {
- sec = new cmDocumentationSection
- (name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name,sec);
- }
- else
- {
+ 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);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::AppendSection(const char *name,
- std::vector<cmDocumentationEntry> &docs)
+void cmDocumentation::AppendSection(const char* name,
+ std::vector<cmDocumentationEntry>& docs)
{
- cmDocumentationSection *sec = 0;
- if (this->AllSections.find(name) == this->AllSections.end())
- {
- sec = new cmDocumentationSection
- (name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name,sec);
- }
- else
- {
+ 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);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::AppendSection(const char *name,
- cmDocumentationEntry &docs)
+void cmDocumentation::AppendSection(const char* name,
+ cmDocumentationEntry& docs)
{
std::vector<cmDocumentationEntry> docsVec;
docsVec.push_back(docs);
- this->AppendSection(name,docsVec);
+ this->AppendSection(name, docsVec);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::PrependSection(const char *name,
- cmDocumentationEntry &docs)
+void cmDocumentation::PrependSection(const char* name,
+ cmDocumentationEntry& docs)
{
std::vector<cmDocumentationEntry> docsVec;
docsVec.push_back(docs);
- this->PrependSection(name,docsVec);
+ this->PrependSection(name, docsVec);
}
-//----------------------------------------------------------------------------
-void cmDocumentation::SetSeeAlsoList(const char *data[][3])
+void cmDocumentation::GlobHelp(std::vector<std::string>& files,
+ std::string const& pattern)
{
- cmDocumentationSection *sec =
- new cmDocumentationSection("See Also", "SEE ALSO");
- this->AllSections["See Also"] = sec;
- this->SeeAlsoString = ".B ";
- int i = 0;
- while(data[i][1])
- {
- this->SeeAlsoString += data[i][1];
- this->SeeAlsoString += data[i+1][1]? "(1), ":"(1)";
- ++i;
- }
- sec->Append(0,this->SeeAlsoString.c_str(),0);
- sec->Append(cmDocumentationStandardSeeAlso);
+ cmsys::Glob gl;
+ std::string findExpr =
+ cmSystemTools::GetCMakeRoot() + "/Help/" + pattern + ".rst";
+ if (gl.FindFiles(findExpr)) {
+ files = gl.GetFiles();
+ }
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationGeneric(std::ostream& os,
- const char *section)
+void cmDocumentation::PrintNames(std::ostream& os, std::string const& pattern)
{
- if(this->AllSections.find(section) == this->AllSections.end())
- {
- os << "Internal error: " << section << " list is empty." << std::endl;
- return false;
- }
- if(this->CurrentArgument.length() == 0)
- {
- os << "Required argument missing.\n";
- return false;
- }
- const std::vector<cmDocumentationEntry> &entries =
- this->AllSections[section]->GetEntries();
- for(std::vector<cmDocumentationEntry>::const_iterator ei =
- entries.begin();
- ei != entries.end(); ++ei)
- {
- if(this->CurrentArgument == ei->Name)
- {
- this->PrintDocumentationCommand(os, *ei);
- return true;
+ 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) {
+ std::string line;
+ cmsys::ifstream fin(i->c_str());
+ while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
+ if (!line.empty() && (isalnum(line[0]) || line[0] == '<')) {
+ names.push_back(line);
+ break;
}
}
- return false;
+ }
+ std::sort(names.begin(), names.end());
+ for (std::vector<std::string>::iterator i = names.begin(); i != names.end();
+ ++i) {
+ os << *i << "\n";
+ }
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationSingle(std::ostream& os)
+bool cmDocumentation::PrintFiles(std::ostream& os, std::string const& pattern)
{
- if (this->PrintDocumentationGeneric(os,"Commands"))
- {
- return true;
- }
- if (this->PrintDocumentationGeneric(os,"Compatibility Commands"))
- {
- return true;
- }
-
- // Argument was not a command. Complain.
- os << "Argument \"" << this->CurrentArgument.c_str()
- << "\" to --help-command is not a CMake command. "
- << "Use --help-command-list to see all commands.\n";
- return false;
+ bool found = false;
+ std::vector<std::string> files;
+ 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;
+ }
+ return found;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os)
+bool cmDocumentation::PrintHelpFull(std::ostream& os)
{
- if(this->CurrentArgument.length() == 0)
- {
- os << "Argument --help-module needs a module name.\n";
- return false;
- }
-
- std::string moduleName;
- // find the module
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs);
- for(std::vector<std::string>::const_iterator dirIt = dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- moduleName = *dirIt;
- moduleName += "/";
- moduleName += this->CurrentArgument;
- moduleName += ".cmake";
- if(cmSystemTools::FileExists(moduleName.c_str()))
- {
- break;
- }
- moduleName = "";
- }
-
- if (moduleName.empty())
- {
- moduleName = this->CMakeRoot;
- moduleName += "/Modules/";
- moduleName += this->CurrentArgument;
- moduleName += ".cmake";
- if(!cmSystemTools::FileExists(moduleName.c_str()))
- {
- moduleName = "";
- }
- }
-
- if(!moduleName.empty())
- {
- cmDocumentationSection *sec =
- new cmDocumentationSection("Standard CMake Modules", "MODULES");
- this->AllSections["Modules"] = sec;
- if (this->CreateSingleModule(moduleName.c_str(),
- this->CurrentArgument.c_str(),
- *this->AllSections["Modules"]))
- {
- if(this->AllSections["Modules"]->GetEntries().size())
- {
- this->PrintDocumentationCommand
- (os, this->AllSections["Modules"]->GetEntries()[0]);
- os << "\n Defined in: ";
- os << moduleName << "\n";
- return true;
- }
- else
- {
- return false;
- }
- }
- }
-
- // Argument was not a module. Complain.
- os << "Argument \"" << this->CurrentArgument.c_str()
- << "\" to --help-module is not a CMake module.\n";
- return false;
+ return this->PrintFiles(os, "index");
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os)
+bool cmDocumentation::PrintHelpOneManual(std::ostream& os)
{
- bool done = false;
- for (std::vector<std::string>::iterator i =
- this->PropertySections.begin();
- !done && i != this->PropertySections.end(); ++i)
- {
- done = this->PrintDocumentationGeneric(os,i->c_str());
- }
-
- if (done)
- {
+ std::string mname = this->CurrentArgument;
+ std::string::size_type mlen = mname.length();
+ if (mlen > 3 && mname[mlen - 3] == '(' && mname[mlen - 1] == ')') {
+ mname = mname.substr(0, mlen - 3) + "." + mname[mlen - 2];
+ }
+ if (this->PrintFiles(os, "manual/" + mname) ||
+ this->PrintFiles(os, "manual/" + mname + ".[0-9]")) {
return true;
- }
-
- // Argument was not a command. Complain.
- os << "Argument \"" << this->CurrentArgument.c_str()
- << "\" to --help-property is not a CMake property. "
- << "Use --help-property-list to see all properties.\n";
+ }
+ // Argument was not a manual. Complain.
+ os << "Argument \"" << this->CurrentArgument
+ << "\" to --help-manual is not an available manual. "
+ << "Use --help-manual-list to see all available manuals.\n";
return false;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationSinglePolicy(std::ostream& os)
+bool cmDocumentation::PrintHelpListManuals(std::ostream& os)
{
- if (this->PrintDocumentationGeneric(os,"Policies"))
- {
- return true;
- }
-
- // Argument was not a command. Complain.
- os << "Argument \"" << this->CurrentArgument.c_str()
- << "\" to --help-policy is not a CMake policy.\n";
- return false;
+ this->PrintNames(os, "manual/*");
+ return true;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationSingleVariable(std::ostream& os)
+bool cmDocumentation::PrintHelpOneCommand(std::ostream& os)
{
- bool done = false;
- for (std::vector<std::string>::iterator i =
- this->VariableSections.begin();
- !done && i != this->VariableSections.end(); ++i)
- {
- done = this->PrintDocumentationGeneric(os,i->c_str());
- }
-
- if (done)
- {
+ std::string cname = cmSystemTools::LowerCase(this->CurrentArgument);
+ if (this->PrintFiles(os, "command/" + cname)) {
return true;
- }
-
+ }
// Argument was not a command. Complain.
- os << "Argument \"" << this->CurrentArgument.c_str()
- << "\" to --help-variable is not a defined variable. "
- << "Use --help-variable-list to see all defined variables.\n";
+ os << "Argument \"" << this->CurrentArgument
+ << "\" to --help-command is not a CMake command. "
+ << "Use --help-command-list to see all commands.\n";
return false;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationList(std::ostream& os,
- const char *section)
+bool cmDocumentation::PrintHelpListCommands(std::ostream& os)
{
- if(this->AllSections.find(section) == this->AllSections.end())
- {
- os << "Internal error: " << section << " list is empty." << std::endl;
- return false;
- }
-
- const std::vector<cmDocumentationEntry> &entries =
- this->AllSections[section]->GetEntries();
- for(std::vector<cmDocumentationEntry>::const_iterator ei =
- entries.begin();
- ei != entries.end(); ++ei)
- {
- if(ei->Name.size())
- {
- os << ei->Name << std::endl;
- }
- }
+ this->PrintNames(os, "command/*");
return true;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationUsage(std::ostream& os)
+bool cmDocumentation::PrintHelpOneModule(std::ostream& os)
{
- this->ClearSections();
- this->AddSectionToPrint("Usage");
- this->AddSectionToPrint("Options");
- if(this->ShowGenerators)
- {
- this->AddSectionToPrint("Generators");
- }
- this->Print(os);
- return true;
+ std::string mname = this->CurrentArgument;
+ if (this->PrintFiles(os, "module/" + mname)) {
+ return true;
+ }
+ // Argument was not a module. Complain.
+ os << "Argument \"" << this->CurrentArgument
+ << "\" to --help-module is not a CMake module.\n";
+ return false;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationFull(std::ostream& os)
+bool cmDocumentation::PrintHelpListModules(std::ostream& os)
{
- this->CreateFullDocumentation();
- this->CurrentFormatter->PrintHeader(GetNameString(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(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);
+ 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";
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationModules(std::ostream& os)
+bool cmDocumentation::PrintHelpOneProperty(std::ostream& os)
{
- this->ClearSections();
- this->CreateModulesSection();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Modules));
- this->AddSectionToPrint("Description");
- this->AddSectionToPrint("Modules");
- this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("See Also");
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
- return true;
+ std::string pname = cmSystemTools::HelpFileName(this->CurrentArgument);
+ if (this->PrintFiles(os, "prop_*/" + pname)) {
+ return true;
+ }
+ // Argument was not a property. Complain.
+ os << "Argument \"" << this->CurrentArgument
+ << "\" to --help-property is not a CMake property. "
+ << "Use --help-property-list to see all properties.\n";
+ return false;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationCustomModules(std::ostream& os)
+bool cmDocumentation::PrintHelpListProperties(std::ostream& os)
{
- this->ClearSections();
- this->CreateCustomModulesSection();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(CustomModules));
- this->AddSectionToPrint("Description");
- this->AddSectionToPrint("Custom CMake Modules");
-// the custom modules are most probably not under Kitware's copyright, Alex
-// this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("See Also");
-
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
+ this->PrintNames(os, "prop_*/*");
return true;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationPolicies(std::ostream& os)
+bool cmDocumentation::PrintHelpOnePolicy(std::ostream& os)
{
- this->ClearSections();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Policies));
- this->AddSectionToPrint("Description");
- this->AddSectionToPrint("Policies");
- this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("See Also");
+ std::string pname = this->CurrentArgument;
+ std::vector<std::string> files;
+ if (this->PrintFiles(os, "policy/" + pname)) {
+ return true;
+ }
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
- return true;
+ // Argument was not a policy. Complain.
+ os << "Argument \"" << this->CurrentArgument
+ << "\" to --help-policy is not a CMake policy.\n";
+ return false;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationProperties(std::ostream& os)
+bool cmDocumentation::PrintHelpListPolicies(std::ostream& os)
{
- this->ClearSections();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Properties));
- this->AddSectionToPrint("Properties Description");
- for (std::vector<std::string>::iterator i =
- this->PropertySections.begin();
- i != this->PropertySections.end(); ++i)
- {
- this->AddSectionToPrint(i->c_str());
- }
- this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("Standard See Also");
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
+ this->PrintNames(os, "policy/*");
return true;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationVariables(std::ostream& os)
+bool cmDocumentation::PrintHelpListGenerators(std::ostream& os)
{
- this->ClearSections();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Variables));
- for (std::vector<std::string>::iterator i =
- this->VariableSections.begin();
- i != this->VariableSections.end(); ++i)
- {
- this->AddSectionToPrint(i->c_str());
- }
- this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("Standard See Also");
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
+ std::map<std::string, cmDocumentationSection*>::iterator si;
+ si = this->AllSections.find("Generators");
+ if (si != this->AllSections.end()) {
+ this->Formatter.SetIndent(" ");
+ this->Formatter.PrintSection(os, *si->second);
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationCurrentCommands(std::ostream& os)
+bool cmDocumentation::PrintHelpOneVariable(std::ostream& os)
{
- this->ClearSections();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Commands));
- this->AddSectionToPrint("Commands");
- this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("Standard See Also");
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
- return true;
+ std::string vname = cmSystemTools::HelpFileName(this->CurrentArgument);
+ if (this->PrintFiles(os, "variable/" + vname)) {
+ return true;
+ }
+ // Argument was not a variable. Complain.
+ os << "Argument \"" << this->CurrentArgument
+ << "\" to --help-variable is not a defined variable. "
+ << "Use --help-variable-list to see all defined variables.\n";
+ return false;
}
-//----------------------------------------------------------------------------
-bool cmDocumentation::PrintDocumentationCompatCommands(std::ostream& os)
+bool cmDocumentation::PrintHelpListVariables(std::ostream& os)
{
- this->ClearSections();
- this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(CompatCommands));
- this->AddSectionToPrint("Compatibility Commands Description");
- this->AddSectionToPrint("Compatibility Commands");
- this->AddSectionToPrint("Copyright");
- this->AddSectionToPrint("Standard See Also");
- this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
- this->Print(os);
- this->CurrentFormatter->PrintFooter(os);
+ this->PrintNames(os, "variable/*");
return true;
}
-//----------------------------------------------------------------------------
-void cmDocumentation
-::PrintDocumentationCommand(std::ostream& os,
- const cmDocumentationEntry &entry)
+bool cmDocumentation::PrintUsage(std::ostream& os)
{
- // the string "SingleItem" will be used in a few places to detect the case
- // that only the documentation for a single item is printed
- cmDocumentationSection *sec = new cmDocumentationSection("SingleItem","");
- sec->Append(entry);
- this->AllSections["temp"] = sec;
- this->ClearSections();
- this->AddSectionToPrint("temp");
- this->Print(os);
- this->AllSections.erase("temp");
- delete sec;
+ std::map<std::string, cmDocumentationSection*>::iterator si;
+ si = this->AllSections.find("Usage");
+ if (si != this->AllSections.end()) {
+ this->Formatter.PrintSection(os, *si->second);
+ }
+ return true;
}
-//----------------------------------------------------------------------------
-void cmDocumentation::CreateFullDocumentation()
+bool cmDocumentation::PrintHelp(std::ostream& os)
{
- this->ClearSections();
- this->CreateCustomModulesSection();
- this->CreateModulesSection();
-
- std::set<std::string> emitted;
- this->AddSectionToPrint("Name");
- emitted.insert("Name");
- this->AddSectionToPrint("Usage");
- emitted.insert("Usage");
- this->AddSectionToPrint("Description");
- emitted.insert("Description");
- this->AddSectionToPrint("Options");
- emitted.insert("Options");
- this->AddSectionToPrint("Generators");
- emitted.insert("Generators");
- this->AddSectionToPrint("Commands");
- emitted.insert("Commands");
-
-
- this->AddSectionToPrint("Properties Description");
- emitted.insert("Properties Description");
- for (std::vector<std::string>::iterator i =
- this->PropertySections.begin();
- i != this->PropertySections.end(); ++i)
- {
- this->AddSectionToPrint(i->c_str());
- emitted.insert(i->c_str());
- }
-
- emitted.insert("Copyright");
- emitted.insert("See Also");
- emitted.insert("Standard See Also");
- emitted.insert("Author");
-
- // add any sections not yet written out, or to be written out
- for (std::map<std::string, cmDocumentationSection*>::iterator i =
- this->AllSections.begin();
- i != this->AllSections.end(); ++i)
- {
- if (emitted.find(i->first) == emitted.end())
- {
- this->AddSectionToPrint(i->first.c_str());
- }
- }
-
- this->AddSectionToPrint("Copyright");
-
- if(this->CurrentFormatter->GetForm() == ManForm)
- {
- this->AddSectionToPrint("See Also");
- this->AddSectionToPrint("Author");
- }
- else
- {
- this->AddSectionToPrint("Standard See Also");
+ std::map<std::string, cmDocumentationSection*>::iterator si;
+ si = this->AllSections.find("Usage");
+ if (si != this->AllSections.end()) {
+ this->Formatter.PrintSection(os, *si->second);
+ }
+ si = this->AllSections.find("Options");
+ if (si != this->AllSections.end()) {
+ 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);
}
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentation::SetForm(Form f, int manSection)
-{
- switch(f)
- {
- case HTMLForm:
- this->CurrentFormatter = &this->HTMLFormatter;
- break;
- case DocbookForm:
- this->CurrentFormatter = &this->DocbookFormatter;
- break;
- case ManForm:
- this->ManFormatter.SetManSection(manSection);
- this->CurrentFormatter = &this->ManFormatter;
- break;
- case TextForm:
- this->CurrentFormatter = &this->TextFormatter;
- break;
- case UsageForm:
- this->CurrentFormatter = & this->UsageFormatter;
- break;
}
+ return true;
}
-
-//----------------------------------------------------------------------------
const char* cmDocumentation::GetNameString() const
{
- if(this->NameString.length() > 0)
- {
+ if (!this->NameString.empty()) {
return this->NameString.c_str();
- }
- else
- {
- return "CMake";
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmDocumentation::GetDocName(bool fallbackToNameString) const
-{
- if (this->DocName.length() > 0)
- {
- return this->DocName.c_str();
- }
- else if (fallbackToNameString)
- {
- return this->GetNameString();
- }
- else
- return 0;
-}
-
-//----------------------------------------------------------------------------
-#define CASE_DEFAULT_DOCNAME(doctype) \
- case cmDocumentation::doctype : \
- return GET_DOCUMENT_INTRO(doctype)[0];
-const char* cmDocumentation::GetDefaultDocName(Type ht) const
-{
- switch (ht)
- {
- CASE_DEFAULT_DOCNAME(Modules)
- CASE_DEFAULT_DOCNAME(CustomModules)
- CASE_DEFAULT_DOCNAME(Policies)
- CASE_DEFAULT_DOCNAME(Properties)
- CASE_DEFAULT_DOCNAME(Variables)
- CASE_DEFAULT_DOCNAME(Commands)
- CASE_DEFAULT_DOCNAME(CompatCommands)
- default: break;
- }
- return 0;
+ }
+ return "CMake";
}
-//----------------------------------------------------------------------------
bool cmDocumentation::IsOption(const char* arg) const
{
return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) ||
(strcmp(arg, "/?") == 0));
}
+
+bool cmDocumentation::PrintOldCustomModules(std::ostream& os)
+{
+ // CheckOptions abuses the Argument field to give us the file name.
+ std::string filename = this->CurrentArgument;
+ std::string ext = cmSystemTools::UpperCase(
+ cmSystemTools::GetFilenameLastExtension(filename));
+ std::string name = cmSystemTools::GetFilenameWithoutLastExtension(filename);
+
+ const char* summary = "cmake --help-custom-modules no longer supported\n";
+ const char* detail =
+ "CMake versions prior to 3.0 exposed their internal module help page\n"
+ "generation functionality through the --help-custom-modules option.\n"
+ "CMake versions 3.0 and above use other means to generate their module\n"
+ "help pages so this functionality is no longer available to be exposed.\n"
+ "\n"
+ "This file was generated as a placeholder to provide this information.\n";
+ if ((ext == ".HTM") || (ext == ".HTML")) {
+ os << "<html><title>" << name << "</title><body>\n"
+ << summary << "<p/>\n"
+ << detail << "</body></html>\n";
+ } else if ((ext.length() == 2) && (ext[1] >= '1') && (ext[1] <= '9')) {
+ /* clang-format off */
+ os <<
+ ".TH " << name << " " << ext[1] << " \"" <<
+ cmSystemTools::GetCurrentDateTime("%B %d, %Y") <<
+ "\" \"cmake " << cmVersion::GetCMakeVersion() << "\"\n"
+ ".SH NAME\n"
+ ".PP\n" <<
+ name << " \\- " << summary <<
+ "\n"
+ ".SH DESCRIPTION\n"
+ ".PP\n" <<
+ detail
+ ;
+ /* clang-format on */
+ } else {
+ os << name << "\n\n" << summary << "\n" << detail;
+ }
+ return true;
+}
diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h
index e180f60f5..2866fef03 100644
--- a/Source/cmDocumentation.h
+++ b/Source/cmDocumentation.h
@@ -1,35 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef _cmDocumentation_h
#define _cmDocumentation_h
-#include "cmStandardIncludes.h"
-#include "cmProperty.h"
+#include "cmConfigure.h"
+
#include "cmDocumentationFormatter.h"
-#include "cmDocumentationFormatterHTML.h"
-#include "cmDocumentationFormatterDocbook.h"
-#include "cmDocumentationFormatterMan.h"
-#include "cmDocumentationFormatterText.h"
-#include "cmDocumentationFormatterUsage.h"
-#include "cmDocumentationSection.h"
-#include "cmake.h"
-namespace cmsys
-{
- class Directory;
-}
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <vector>
+
+class cmDocumentationSection;
+struct cmDocumentationEntry;
/** Class to generate documentation. */
-class cmDocumentation: public cmDocumentationEnums
+class cmDocumentation : public cmDocumentationEnums
{
public:
cmDocumentation();
@@ -37,22 +24,6 @@ public:
~cmDocumentation();
/**
- * An helper type pair for [structured] documented modules.
- * The comment of those module contains structure markup
- * which makes it possible to retrieve the documentation
- * of variables, macros and functions defined in the module.
- * - first is the filename of the module
- * - second is the section of the doc the module belongs too
- */
- typedef std::pair<std::string,std::string> documentedModuleSectionPair_t;
- /**
- * A list of documented module(s).
- */
- typedef std::list<documentedModuleSectionPair_t> documentedModulesList_t;
-
- // High-level interface for standard documents:
-
- /**
* Check command line arguments for documentation options. Returns
* true if documentation options are found, and false otherwise.
* When true is returned, PrintRequestedDocumentation should be
@@ -61,7 +32,7 @@ public:
* help arguments.
*/
bool CheckOptions(int argc, const char* const* argv,
- const char* exitOpt =0);
+ const char* exitOpt = CM_NULLPTR);
/**
* Print help requested on the command line. Call after
@@ -72,69 +43,30 @@ public:
bool PrintRequestedDocumentation(std::ostream& os);
/** Print help of the given type. */
- bool PrintDocumentation(Type ht, std::ostream& os, const char* docname=0);
+ bool PrintDocumentation(Type ht, std::ostream& os);
void SetShowGenerators(bool showGen) { this->ShowGenerators = showGen; }
/** Set the program name for standard document generation. */
- void SetName(const char* name);
+ void SetName(const std::string& name);
/** Set a section of the documentation. Typical sections include Name,
- Usage, Description, Options, SeeAlso */
- void SetSection(const char *sectionName,
- cmDocumentationSection *section);
- void SetSection(const char *sectionName,
- std::vector<cmDocumentationEntry> &docs);
- void SetSection(const char *sectionName,
- const char *docs[][3]);
- void SetSections(std::map<std::string,cmDocumentationSection *>
- &sections);
+ Usage, Description, Options */
+ 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);
/** Add the documentation to the beginning/end of the section */
- void PrependSection(const char *sectionName,
- const char *docs[][3]);
- void PrependSection(const char *sectionName,
- std::vector<cmDocumentationEntry> &docs);
- void PrependSection(const char *sectionName,
- cmDocumentationEntry &docs);
- void AppendSection(const char *sectionName,
- const char *docs[][3]);
- void AppendSection(const char *sectionName,
- std::vector<cmDocumentationEntry> &docs);
- void AppendSection(const char *sectionName,
- cmDocumentationEntry &docs);
-
- /**
- * Print documentation in the given form. All previously added
- * sections will be generated.
- */
- void Print(Form f, int manSection, std::ostream& os);
-
- /**
- * Print documentation in the current form. All previously added
- * sections will be generated.
- */
- void Print(std::ostream& os);
-
- /**
- * Add a section of documentation. This can be used to generate custom help
- * documents.
- */
- void AddSectionToPrint(const char *section);
-
- void SetSeeAlsoList(const char *data[][3]);
-
- /** Clear all previously added sections of help. */
- void ClearSections();
-
- /** Set cmake root so we can find installed files */
- void SetCMakeRoot(const char* root) { this->CMakeRoot = root;}
-
- /** Set CMAKE_MODULE_PATH so we can find additional cmake modules */
- void SetCMakeModulePath(const char* path) { this->CMakeModulePath = path;}
-
- static Form GetFormFromFilename(const std::string& filename,
- int* ManSection);
+ void PrependSection(const char* sectionName, const char* docs[][2]);
+ void PrependSection(const char* sectionName,
+ std::vector<cmDocumentationEntry>& docs);
+ void PrependSection(const char* sectionName, cmDocumentationEntry& docs);
+ void AppendSection(const char* sectionName, const char* docs[][2]);
+ void AppendSection(const char* sectionName,
+ std::vector<cmDocumentationEntry>& docs);
+ void AppendSection(const char* sectionName, cmDocumentationEntry& docs);
/** Add common (to all tools) documentation section(s) */
void addCommonStandardDocSections();
@@ -148,124 +80,55 @@ public:
/** Add the CPack standard documentation section(s) */
void addCPackStandardDocSections();
- /** Add automatic variables sections */
- void addAutomaticVariableSections(const std::string& section);
-
- /**
- * Retrieve the list of documented module located in
- * path which match the globing expression globExpr.
- * @param[in] path, directory where to start the search
- * we will recurse into it.
- * @param[in] globExpr, the globing expression used to
- * match the file in path.
- * @param[out] the list of obtained pairs (may be empty)
- * @return 0 on success 1 on error or empty list
- */
- int getDocumentedModulesListInDir(
- std::string path,
- std::string globExpr,
- documentedModulesList_t& docModuleList);
-
- /**
- * Get the documentation of macros, functions and variable documented
- * with CMake structured documentation in a CMake script.
- * (in fact it may be in any file which follow the structured doc format)
- * Structured documentation begin with
- * ## (double sharp) in column 1 & 2 immediately followed
- * by a markup. Those ## are ignored by the legacy module
- * documentation parser @see CreateSingleModule.
- * Current markup are ##section, ##module,
- * ##macro, ##function, ##variable and ##end.
- * ##end is closing either of the previous ones.
- * @param[in] fname the script file name to be parsed for documentation
- * @param[in,out] commands the vector of command/macros documentation
- * entry found in the script file.
- * @param[in,out] the cmake object instance to which variable documentation
- * will be attached (using @see cmake::DefineProperty)
- * @param[in] the documentation section in which the property will be
- * inserted.
- * @return the number of documented items (command and variable)
- * found in the file.
- */
- int GetStructuredDocFromFile(const char* fname,
- std::vector<cmDocumentationEntry>& commands,
- cmake* cm);
private:
- void SetForm(Form f, int manSection);
- void SetDocName(const char* docname);
-
- bool CreateSingleModule(const char* fname,
- const char* moduleName,
- cmDocumentationSection &sec);
- void CreateModuleDocsForDir(cmsys::Directory& dir,
- cmDocumentationSection &moduleSection);
- bool CreateModulesSection();
- bool CreateCustomModulesSection();
- void CreateFullDocumentation();
+ void GlobHelp(std::vector<std::string>& files, std::string const& pattern);
+ void PrintNames(std::ostream& os, std::string const& pattern);
+ bool PrintFiles(std::ostream& os, std::string const& pattern);
- void AddDocumentIntroToPrint(const char* intro[2]);
-
- bool PrintCopyright(std::ostream& os);
bool PrintVersion(std::ostream& os);
- bool PrintDocumentationGeneric(std::ostream& os, const char *section);
- bool PrintDocumentationList(std::ostream& os, const char *section);
- bool PrintDocumentationSingle(std::ostream& os);
- bool PrintDocumentationSingleModule(std::ostream& os);
- bool PrintDocumentationSingleProperty(std::ostream& os);
- bool PrintDocumentationSinglePolicy(std::ostream& os);
- bool PrintDocumentationSingleVariable(std::ostream& os);
- bool PrintDocumentationUsage(std::ostream& os);
- bool PrintDocumentationFull(std::ostream& os);
- bool PrintDocumentationModules(std::ostream& os);
- bool PrintDocumentationCustomModules(std::ostream& os);
- bool PrintDocumentationPolicies(std::ostream& os);
- bool PrintDocumentationProperties(std::ostream& os);
- bool PrintDocumentationVariables(std::ostream& os);
- bool PrintDocumentationCurrentCommands(std::ostream& os);
- bool PrintDocumentationCompatCommands(std::ostream& os);
- void PrintDocumentationCommand(std::ostream& os,
- const cmDocumentationEntry &entry);
-
+ bool PrintUsage(std::ostream& os);
+ bool PrintHelp(std::ostream& os);
+ bool PrintHelpFull(std::ostream& os);
+ bool PrintHelpOneManual(std::ostream& os);
+ bool PrintHelpOneCommand(std::ostream& os);
+ bool PrintHelpOneModule(std::ostream& os);
+ bool PrintHelpOnePolicy(std::ostream& os);
+ bool PrintHelpOneProperty(std::ostream& os);
+ bool PrintHelpOneVariable(std::ostream& os);
+ bool PrintHelpListManuals(std::ostream& os);
+ bool PrintHelpListCommands(std::ostream& os);
+ bool PrintHelpListModules(std::ostream& os);
+ bool PrintHelpListProperties(std::ostream& os);
+ bool PrintHelpListVariables(std::ostream& os);
+ bool PrintHelpListPolicies(std::ostream& os);
+ bool PrintHelpListGenerators(std::ostream& os);
+ bool PrintOldCustomModules(std::ostream& os);
const char* GetNameString() const;
- const char* GetDocName(bool fallbackToNameString = true) const;
- const char* GetDefaultDocName(Type ht) const;
bool IsOption(const char* arg) const;
bool ShowGenerators;
std::string NameString;
- std::string DocName;
- std::map<std::string,cmDocumentationSection*> AllSections;
+ std::map<std::string, cmDocumentationSection*> AllSections;
- std::string SeeAlsoString;
- std::string CMakeRoot;
- std::string CMakeModulePath;
- std::set<std::string> ModulesFound;
- std::vector< char* > ModuleStrings;
- std::vector<const cmDocumentationSection *> PrintSections;
std::string CurrentArgument;
struct RequestedHelpItem
{
- RequestedHelpItem():HelpForm(TextForm), HelpType(None), ManSection(1) {}
- cmDocumentationEnums::Form HelpForm;
+ RequestedHelpItem()
+ : HelpType(None)
+ {
+ }
cmDocumentationEnums::Type HelpType;
std::string Filename;
std::string Argument;
- int ManSection;
};
std::vector<RequestedHelpItem> RequestedHelpItems;
- cmDocumentationFormatter* CurrentFormatter;
- cmDocumentationFormatterHTML HTMLFormatter;
- cmDocumentationFormatterDocbook DocbookFormatter;
- cmDocumentationFormatterMan ManFormatter;
- cmDocumentationFormatterText TextFormatter;
- cmDocumentationFormatterUsage UsageFormatter;
+ cmDocumentationFormatter Formatter;
- std::vector<std::string> PropertySections;
- std::vector<std::string> VariableSections;
+ static void WarnFormFromFilename(RequestedHelpItem& request, bool& result);
};
#endif
diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h
new file mode 100644
index 000000000..ea43b88c3
--- /dev/null
+++ b/Source/cmDocumentationEntry.h
@@ -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. */
+#ifndef cmDocumentationEntry_h
+#define cmDocumentationEntry_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** Standard documentation entry for cmDocumentation's formatting. */
+struct cmDocumentationEntry
+{
+ std::string Name;
+ std::string Brief;
+ cmDocumentationEntry() {}
+ cmDocumentationEntry(const char* doc[2])
+ {
+ if (doc[0]) {
+ this->Name = doc[0];
+ }
+ if (doc[1]) {
+ this->Brief = doc[1];
+ }
+ }
+ cmDocumentationEntry(const char* n, const char* b)
+ {
+ if (n) {
+ this->Name = n;
+ }
+ if (b) {
+ this->Brief = b;
+ }
+ }
+};
+
+#endif
diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx
index 9f01949b9..001826318 100644
--- a/Source/cmDocumentationFormatter.cxx
+++ b/Source/cmDocumentationFormatter.cxx
@@ -1,17 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDocumentationFormatter.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmDocumentationEntry.h"
+#include "cmDocumentationSection.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmDocumentationFormatter.h"
+#include <ostream>
+#include <string.h>
+#include <string>
+#include <vector>
cmDocumentationFormatter::cmDocumentationFormatter()
+ : TextWidth(77)
+ , TextIndent("")
{
}
@@ -22,135 +23,172 @@ cmDocumentationFormatter::~cmDocumentationFormatter()
void cmDocumentationFormatter::PrintFormatted(std::ostream& os,
const char* text)
{
- if(!text)
- {
+ if (!text) {
return;
- }
+ }
const char* ptr = text;
- while(*ptr)
- {
+ while (*ptr) {
// Any ptrs starting in a space are treated as preformatted text.
std::string preformatted;
- while(*ptr == ' ')
- {
- for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr)
- {
+ while (*ptr == ' ') {
+ for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) {
preformatted.append(1, ch);
- }
- if(*ptr)
- {
+ }
+ if (*ptr) {
++ptr;
preformatted.append(1, '\n');
- }
}
- if(preformatted.length())
- {
+ }
+ if (!preformatted.empty()) {
this->PrintPreformatted(os, preformatted.c_str());
- }
+ }
// Other ptrs are treated as paragraphs.
std::string paragraph;
- for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr)
- {
+ for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) {
paragraph.append(1, ch);
- }
- if(*ptr)
- {
+ }
+ if (*ptr) {
++ptr;
paragraph.append(1, '\n');
- }
- if(paragraph.length())
- {
+ }
+ if (!paragraph.empty()) {
this->PrintParagraph(os, paragraph.c_str());
- }
}
+ }
+}
+
+void cmDocumentationFormatter::PrintPreformatted(std::ostream& os,
+ const char* text)
+{
+ bool newline = true;
+ for (const char* ptr = text; *ptr; ++ptr) {
+ if (newline && *ptr != '\n') {
+ os << this->TextIndent;
+ newline = false;
+ }
+ os << *ptr;
+ if (*ptr == '\n') {
+ newline = true;
+ }
+ }
+ os << "\n";
+}
+
+void cmDocumentationFormatter::PrintParagraph(std::ostream& os,
+ const char* text)
+{
+ os << this->TextIndent;
+ this->PrintColumn(os, text);
+ os << "\n";
+}
+
+void cmDocumentationFormatter::SetIndent(const char* indent)
+{
+ this->TextIndent = indent;
}
-//----------------------------------------------------------------------------
-std::string
-cmDocumentationFormatter::ComputeSectionLinkPrefix(std::string const& name)
+void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text)
{
- // Map from section name to a prefix for links pointing within the
- // section. For example, the commands section should have HTML
- // links to each command with names like #command:ADD_EXECUTABLE.
- if(name.find("Command") != name.npos)
- {
- return "command";
+ // Print text arranged in an indented column of fixed witdh.
+ const char* l = text;
+ long column = 0;
+ bool newSentence = false;
+ bool firstLine = true;
+ int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent));
+
+ // Loop until the end of the text.
+ while (*l) {
+ // Parse the next word.
+ const char* r = l;
+ while (*r && (*r != '\n') && (*r != ' ')) {
+ ++r;
}
- else if(name.find("Propert") != name.npos)
- {
- if(name.find("Global") != name.npos)
- {
- return "prop_global";
- }
- else if(name.find("Direct") != name.npos)
- {
- return "prop_dir";
- }
- else if(name.find("Target") != name.npos)
- {
- return "prop_tgt";
+
+ // Does it fit on this line?
+ if (r - l < (width - column - (newSentence ? 1 : 0))) {
+ // Word fits on this line.
+ if (r > l) {
+ if (column) {
+ // Not first word on line. Separate from the previous word
+ // by a space, or two if this is a new sentence.
+ if (newSentence) {
+ os << " ";
+ column += 2;
+ } else {
+ os << " ";
+ column += 1;
+ }
+ } else {
+ // First word on line. Print indentation unless this is the
+ // first line.
+ os << (firstLine ? "" : this->TextIndent);
+ }
+
+ // Print the word.
+ os.write(l, static_cast<long>(r - l));
+ newSentence = (*(r - 1) == '.');
}
- else if(name.find("Test") != name.npos)
- {
- return "prop_test";
+
+ if (*r == '\n') {
+ // Text provided a newline. Start a new line.
+ os << "\n";
+ ++r;
+ column = 0;
+ firstLine = false;
+ } else {
+ // No provided newline. Continue this line.
+ column += static_cast<long>(r - l);
}
- else if(name.find("Source") != name.npos)
- {
- return "prop_sf";
+ } else {
+ // Word does not fit on this line. Start a new line.
+ os << "\n";
+ firstLine = false;
+ if (r > l) {
+ os << this->TextIndent;
+ os.write(l, static_cast<long>(r - l));
+ column = static_cast<long>(r - l);
+ newSentence = (*(r - 1) == '.');
+ } else {
+ column = 0;
}
- return "property";
- }
- else if(name.find("Variable") != name.npos)
- {
- return "variable";
- }
- else if(name.find("Polic") != name.npos)
- {
- return "policy";
- }
- else if(name.find("Module") != name.npos)
- {
- return "module";
- }
- else if(name.find("Name") != name.npos ||
- name.find("Introduction") != name.npos)
- {
- return "name";
- }
- else if(name.find("Usage") != name.npos)
- {
- return "usage";
- }
- else if(name.find("Description") != name.npos)
- {
- return "desc";
}
- else if(name.find("Generators") != name.npos)
- {
- return "gen";
- }
- else if(name.find("Options") != name.npos)
- {
- return "opt";
- }
- else if(name.find("Copyright") != name.npos)
- {
- return "copy";
- }
- else if(name.find("See Also") != name.npos)
- {
- return "see";
- }
- else if(name.find("SingleItem") != name.npos)
- {
- return "single_item";
- }
- else
- {
- std::cerr
- << "WARNING: ComputeSectionLinkPrefix failed for \"" << name << "\""
- << std::endl;
- return "other";
+
+ // Move to beginning of next word. Skip over whitespace.
+ l = r;
+ while (*l == ' ') {
+ ++l;
}
+ }
+}
+
+void cmDocumentationFormatter::PrintSection(
+ std::ostream& os, cmDocumentationSection const& section)
+{
+ 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;
+ this->TextIndent = " ";
+ int align = static_cast<int>(strlen(this->TextIndent)) - 4;
+ for (int i = static_cast<int>(op->Name.size()); i < align; ++i) {
+ os << " ";
+ }
+ if (op->Name.size() > strlen(this->TextIndent) - 4) {
+ os << "\n";
+ os.write(this->TextIndent, strlen(this->TextIndent) - 2);
+ }
+ os << "= ";
+ this->PrintColumn(os, op->Brief.c_str());
+ os << "\n";
+ } else {
+ os << "\n";
+ this->TextIndent = "";
+ this->PrintFormatted(os, op->Brief.c_str());
+ }
+ }
+ os << "\n";
}
diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h
index 665b9b61a..1f04250c9 100644
--- a/Source/cmDocumentationFormatter.h
+++ b/Source/cmDocumentationFormatter.h
@@ -1,18 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef _cmDocumentationFormatter_h
#define _cmDocumentationFormatter_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
/** This is just a helper class to make it build with MSVC 6.0.
Actually the enums and internal classes could directly go into
@@ -25,19 +18,32 @@ class cmDocumentationEnums
public:
/** Types of help provided. */
enum Type
- { None, Usage, Single, SingleModule, SingleProperty, SingleVariable,
- List, ModuleList, PropertyList, VariableList,
- Full, Properties, Variables, Modules, CustomModules, Commands,
- CompatCommands, Copyright, Version, Policies, SinglePolicy };
-
- /** Forms of documentation output. */
- enum Form { TextForm, HTMLForm, ManForm, UsageForm, DocbookForm };
+ {
+ None,
+ Version,
+ Usage,
+ Help,
+ Full,
+ ListManuals,
+ ListCommands,
+ ListModules,
+ ListProperties,
+ ListVariables,
+ ListPolicies,
+ ListGenerators,
+ OneManual,
+ OneCommand,
+ OneModule,
+ OneProperty,
+ OneVariable,
+ OnePolicy,
+ OldCustomModules
+ };
};
class cmDocumentationSection;
-/** Base class for printing the documentation in the various supported
- formats. */
+/** Print documentation in a simple text format. */
class cmDocumentationFormatter
{
public:
@@ -45,23 +51,16 @@ public:
virtual ~cmDocumentationFormatter();
void PrintFormatted(std::ostream& os, const char* text);
- virtual cmDocumentationEnums::Form GetForm() const = 0;
-
- virtual void PrintHeader(const char* /*docname*/,
- const char* /*appname*/,
- std::ostream& /*os*/) {}
- virtual void PrintFooter(std::ostream& /*os*/) {}
virtual void PrintSection(std::ostream& os,
- const cmDocumentationSection& section,
- const char* name) = 0;
- virtual void PrintPreformatted(std::ostream& os, const char* text) = 0;
- virtual void PrintParagraph(std::ostream& os, const char* text) = 0;
- virtual void PrintIndex(std::ostream& ,
- std::vector<const cmDocumentationSection *>&)
- {}
+ cmDocumentationSection const& section);
+ virtual void PrintPreformatted(std::ostream& os, const char* text);
+ virtual void PrintParagraph(std::ostream& os, const char* text);
+ void PrintColumn(std::ostream& os, const char* text);
+ void SetIndent(const char* indent);
- /** Compute a prefix for links into a section (#\<prefix\>_SOMETHING). */
- std::string ComputeSectionLinkPrefix(std::string const& name);
+private:
+ int TextWidth;
+ const char* TextIndent;
};
#endif
diff --git a/Source/cmDocumentationFormatterDocbook.cxx b/Source/cmDocumentationFormatterDocbook.cxx
deleted file mode 100644
index 706ce0a02..000000000
--- a/Source/cmDocumentationFormatterDocbook.cxx
+++ /dev/null
@@ -1,254 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmDocumentationFormatterDocbook.h"
-#include "cmDocumentationSection.h"
-#include <algorithm>
-#include <ctype.h> // for isalnum
-
-static int cmIsAlnum(int c)
-{
- return isalnum(c);
-}
-
-//----------------------------------------------------------------------------
-
-// this function is a copy of the one in the HTML formatter
-// the three functions below are slightly modified copies
-static bool cmDocumentationIsHyperlinkCharDocbook(char c)
-{
- // This is not a complete list but works for CMake documentation.
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '-' || c == '.' || c == '/' || c == '~' || c == '@' ||
- c == ':' || c == '_' || c == '&' || c == '?' || c == '=');
-}
-
-//----------------------------------------------------------------------------
-static void cmDocumentationPrintDocbookChar(std::ostream& os, char c)
-{
- // Use an escape sequence if necessary.
- switch(c)
- {
- case '<':
- os << "&lt;";
- break;
- case '>':
- os << "&gt;";
- break;
- case '&':
- os << "&amp;";
- break;
- default:
- os << c;
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmDocumentationPrintDocbookLink(std::ostream& os,const char* begin)
-{
- // Look for the end of the link.
- const char* end = begin;
- while(cmDocumentationIsHyperlinkCharDocbook(*end))
- {
- ++end;
- }
-
- // Print the hyperlink itself.
- os << "<ulink url=\"";
- for(const char* c = begin; c != end; ++c)
- {
- cmDocumentationPrintDocbookChar(os, *c);
- }
- os << "\" />";
-
- return end;
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationPrintDocbookEscapes(std::ostream& os, const char* text)
-{
- // Hyperlink prefixes.
- static const char* hyperlinks[] = {"http://", "ftp://", "mailto:", 0};
-
- // Print each character.
- for(const char* p = text; *p;)
- {
- // Handle hyperlinks specially to make them active.
- bool found_hyperlink = false;
- for(const char** h = hyperlinks; !found_hyperlink && *h; ++h)
- {
- if(strncmp(p, *h, strlen(*h)) == 0)
- {
- p = cmDocumentationPrintDocbookLink(os, p);
- found_hyperlink = true;
- }
- }
-
- // Print other characters normally.
- if(!found_hyperlink)
- {
- cmDocumentationPrintDocbookChar(os, *p++);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-cmDocumentationFormatterDocbook::cmDocumentationFormatterDocbook()
-:cmDocumentationFormatter()
-{
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterDocbook
-::PrintSection(std::ostream& os,
- const cmDocumentationSection &section,
- const char* name)
-{
- os << "<sect1 id=\"";
- this->PrintId(os, 0, name);
- os << "\">\n<title>" << name << "</title>\n";
-
- std::string prefix = this->ComputeSectionLinkPrefix(name);
- const std::vector<cmDocumentationEntry> &entries = section.GetEntries();
-
- bool hasSubSections = false;
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op)
- {
- if(op->Name.size())
- {
- hasSubSections = true;
- break;
- }
- }
-
- bool inAbstract = false;
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op)
- {
- if(op->Name.size())
- {
- if(inAbstract)
- {
- os << "</abstract>\n";
- inAbstract = false;
- }
- os << "<sect2 id=\"";
- this->PrintId(os, prefix.c_str(), op->Name);
- os << "\">\n<title>";
- cmDocumentationPrintDocbookEscapes(os, op->Name.c_str());
- os << "</title>\n";
- if(op->Full.size())
- {
- os << "<abstract>\n<para>";
- cmDocumentationPrintDocbookEscapes(os, op->Brief.c_str());
- os << "</para>\n</abstract>\n";
- this->PrintFormatted(os, op->Full.c_str());
- }
- else
- {
- this->PrintFormatted(os, op->Brief.c_str());
- }
- os << "</sect2>\n";
- }
- else
- {
- if(hasSubSections && op == entries.begin())
- {
- os << "<abstract>\n";
- inAbstract = true;
- }
- this->PrintFormatted(os, op->Brief.c_str());
- }
- }
-
- // empty sections are not allowed in docbook.
- if(entries.empty())
- {
- os << "<para/>\n";
- }
-
- os << "</sect1>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterDocbook
-::PrintPreformatted(std::ostream& os, const char* text)
-{
- os << "<para>\n<programlisting>";
- cmDocumentationPrintDocbookEscapes(os, text);
- os << "</programlisting>\n</para>\n";
-}
-
-void cmDocumentationFormatterDocbook
-::PrintParagraph(std::ostream& os, const char* text)
-{
- os << "<para>";
- cmDocumentationPrintDocbookEscapes(os, text);
- os << "</para>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterDocbook
-::PrintHeader(const char* docname, const char* appname, std::ostream& os)
-{
- this->Docname = docname;
-
- // this one is used to ensure that we don't create multiple link targets
- // with the same name. We can clear it here since we are at the
- // start of a document here.
- this->EmittedLinkIds.clear();
-
- os << "<?xml version=\"1.0\" ?>\n"
- "<!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook V4.5//EN\" "
- "\"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd\" [\n"
- "<!ENTITY % addindex \"IGNORE\">\n"
- "<!ENTITY % English \"INCLUDE\"> ]>\n"
- "<article>\n"
- "<articleinfo>\n"
- "<title>" << docname << " - " << appname << "</title>\n"
- "</articleinfo>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterDocbook::PrintFooter(std::ostream& os)
-{
- os << "</article>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterDocbook
-::PrintId(std::ostream& os, const char* prefix, std::string id)
-{
- std::replace_if(id.begin(), id.end(),
- std::not1(std::ptr_fun(cmIsAlnum)), '_');
- if(prefix)
- {
- id = std::string(prefix) + "." + id;
- }
- os << this->Docname << '.' << id;
-
- // make sure that each id exists only once. Since it seems
- // not easily possible to determine which link refers to which id,
- // we have at least to make sure that the duplicated id's get a
- // different name (by appending an increasing number), Alex
- if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end())
- {
- this->EmittedLinkIds.insert(id);
- }
- else
- {
- static unsigned int i=0;
- os << i++;
- }
-}
diff --git a/Source/cmDocumentationFormatterDocbook.h b/Source/cmDocumentationFormatterDocbook.h
deleted file mode 100644
index 0352d342a..000000000
--- a/Source/cmDocumentationFormatterDocbook.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef _cmDocumentationFormatterDocbook_h
-#define _cmDocumentationFormatterDocbook_h
-
-#include "cmStandardIncludes.h"
-
-#include "cmDocumentationFormatter.h"
-
-/** Class to print the documentation as Docbook.
- http://www.oasis-open.org/docbook/xml/4.2/ */
-class cmDocumentationFormatterDocbook : public cmDocumentationFormatter
-{
-public:
- cmDocumentationFormatterDocbook();
-
- virtual cmDocumentationEnums::Form GetForm() const
- { return cmDocumentationEnums::DocbookForm;}
-
- virtual void PrintHeader(const char* docname, const char* appname,
- std::ostream& os);
- virtual void PrintFooter(std::ostream& os);
- virtual void PrintSection(std::ostream& os,
- const cmDocumentationSection& section,
- const char* name);
- virtual void PrintPreformatted(std::ostream& os, const char* text);
- virtual void PrintParagraph(std::ostream& os, const char* text);
-private:
- void PrintId(std::ostream& os, const char* prefix, std::string id);
- std::set<std::string> EmittedLinkIds;
- std::string Docname;
-};
-
-#endif
diff --git a/Source/cmDocumentationFormatterHTML.cxx b/Source/cmDocumentationFormatterHTML.cxx
deleted file mode 100644
index 7213b43de..000000000
--- a/Source/cmDocumentationFormatterHTML.cxx
+++ /dev/null
@@ -1,288 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmDocumentationFormatterHTML.h"
-#include "cmDocumentationSection.h"
-#include "cmVersion.h"
-//----------------------------------------------------------------------------
-static bool cmDocumentationIsHyperlinkChar(char c)
-{
- // This is not a complete list but works for CMake documentation.
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '-' || c == '.' || c == '/' || c == '~' || c == '@' ||
- c == ':' || c == '_' || c == '&' || c == '?' || c == '=');
-}
-
-//----------------------------------------------------------------------------
-static void cmDocumentationPrintHTMLChar(std::ostream& os, char c)
-{
- // Use an escape sequence if necessary.
- switch (c)
- {
- case '<':
- os << "&lt;";
- break;
- case '>':
- os << "&gt;";
- break;
- case '&':
- os << "&amp;";
- break;
- case '\n':
- os << "<br />";
- break;
- default:
- os << c;
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmDocumentationHTMLIsIdChar(char c)
-{
- // From the HTML specification:
- // ID and NAME tokens must begin with a letter ([A-Za-z]) and may
- // be followed by any number of letters, digits ([0-9]), hyphens
- // ("-"), underscores ("_"), colons (":"), and periods (".").
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '-' || c == '_' || c == ':' || c == '.');
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationPrintHTMLId(std::ostream& os, const char* begin)
-{
- for(const char* c = begin; *c; ++c)
- {
- if(cmDocumentationHTMLIsIdChar(*c))
- {
- os << *c;
- }
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmDocumentationPrintHTMLLink(std::ostream& os, const char* begin)
-{
- // Look for the end of the link.
- const char* end = begin;
- while(cmDocumentationIsHyperlinkChar(*end))
- {
- ++end;
- }
-
- // Print the hyperlink itself.
- os << "<a href=\"";
- for(const char* c = begin; c != end; ++c)
- {
- cmDocumentationPrintHTMLChar(os, *c);
- }
- os << "\">";
-
- // The name of the hyperlink is the text itself.
- for(const char* c = begin; c != end; ++c)
- {
- cmDocumentationPrintHTMLChar(os, *c);
- }
- os << "</a>";
-
- // Return the position at which to continue scanning the input
- // string.
- return end;
-}
-
-
-cmDocumentationFormatterHTML::cmDocumentationFormatterHTML()
-:cmDocumentationFormatter()
-{
-}
-
-void cmDocumentationFormatterHTML
-::PrintSection(std::ostream& os,
- const cmDocumentationSection &section,
- const char* name)
-{
- std::string prefix = this->ComputeSectionLinkPrefix(name);
-
- const std::vector<cmDocumentationEntry> &entries =
- section.GetEntries();
-
- // skip the index if the help for only a single item (--help-command,
- // --help-policy, --help-property, --help-module) is printed
- bool isSingleItemHelp = ((name!=0) && (strcmp(name, "SingleItem")==0));
-
- if (!isSingleItemHelp)
- {
- if (name)
- {
- os << "<h2><a name=\"section_";
- cmDocumentationPrintHTMLId(os, name);
- os << "\"></a>" << name << "</h2>\n";
- }
-
- // Is a list needed?
- for(std::vector<cmDocumentationEntry>::const_iterator op
- = entries.begin(); op != entries.end(); ++ op )
- {
- if (op->Name.size())
- {
- os << "<ul>\n";
- for(;op != entries.end() && op->Name.size(); ++op)
- {
- if(op->Name.size())
- {
- os << " <li><a href=\"#" << prefix << ":";
- cmDocumentationPrintHTMLId(os, op->Name.c_str());
- os << "\"><b><code>";
- this->PrintHTMLEscapes(os, op->Name.c_str());
- os << "</code></b></a></li>\n";
- }
- }
- os << "</ul>\n" ;
- break; // Skip outer loop termination test
- }
- }
- }
-
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end();)
- {
- if(op->Name.size())
- {
- os << "<ul>\n";
- for(;op != entries.end() && op->Name.size(); ++op)
- {
- os << " <li>\n";
- if(op->Name.size())
- {
- os << " <a name=\"" << prefix << ":";
- cmDocumentationPrintHTMLId(os, op->Name.c_str());
- os << "\"></a><b><code>";
- this->PrintHTMLEscapes(os, op->Name.c_str());
- os << "</code></b>: ";
- }
- this->PrintHTMLEscapes(os, op->Brief.c_str());
- if(op->Full.size())
- {
- os << "<br />\n ";
- this->PrintFormatted(os, op->Full.c_str());
- }
- os << "\n";
- os << " </li>\n";
- }
- os << "</ul>\n";
- }
- else
- {
- this->PrintFormatted(os, op->Brief.c_str());
- os << "\n";
- ++op;
- }
- }
-}
-
-void cmDocumentationFormatterHTML::PrintPreformatted(std::ostream& os,
- const char* text)
-{
- os << "<pre>";
- this->PrintHTMLEscapes(os, text);
- os << "</pre>\n ";
-}
-
-void cmDocumentationFormatterHTML::PrintParagraph(std::ostream& os,
- const char* text)
-{
- os << "<p>";
- this->PrintHTMLEscapes(os, text);
- os << "</p>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterHTML::PrintHeader(const char* docname,
- const char* appname,
- std::ostream& os)
-{
- os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
- << " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
- os << "<html xmlns=\"http://www.w3.org/1999/xhtml\""
- << " xml:lang=\"en\" lang=\"en\">\n";
- os << "<head><meta http-equiv=\"Content-Type\" "
- << "content=\"text/html;charset=utf-8\" /><title>";
- os << docname << " - " << appname;
- os << "</title></head><body>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterHTML::PrintFooter(std::ostream& os)
-{
- os << "</body></html>\n";
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterHTML::PrintHTMLEscapes(std::ostream& os,
- const char* text)
-{
- // Hyperlink prefixes.
- static const char* hyperlinks[] = {"http://", "ftp://", "mailto:", 0};
-
- // Print each character.
- for(const char* p = text; *p;)
- {
- // Handle hyperlinks specially to make them active.
- bool found_hyperlink = false;
- for(const char** h = hyperlinks; !found_hyperlink && *h; ++h)
- {
- if(strncmp(p, *h, strlen(*h)) == 0)
- {
- p = cmDocumentationPrintHTMLLink(os, p);
- found_hyperlink = true;
- }
- }
-
- // Print other characters normally.
- if(!found_hyperlink)
- {
- cmDocumentationPrintHTMLChar(os, *p++);
- }
- }
-}
-
-void cmDocumentationFormatterHTML
-::PrintIndex(std::ostream& os,
- std::vector<const cmDocumentationSection *>& sections)
-{
- // skip the index if only the help for a single item is printed
- if ((sections.size() == 1)
- && (sections[0]->GetName(this->GetForm()) != 0 )
- && (std::string(sections[0]->GetName(this->GetForm())) == "SingleItem"))
- {
- return;
- }
-
- os << "<h2><a name=\"section_Index\"></a>Master Index "
- << "CMake " << cmVersion::GetCMakeVersion()
- << "</h2>\n";
-
- if (!sections.empty())
- {
- os << "<ul>\n";
- for(unsigned int i=0; i < sections.size(); ++i)
- {
- std::string name = sections[i]->GetName((this->GetForm()));
- os << " <li><a href=\"#section_";
- cmDocumentationPrintHTMLId(os, name.c_str());
- os << "\"><b>" << name << "</b></a></li>\n";
- }
- os << "</ul>\n";
- }
-}
diff --git a/Source/cmDocumentationFormatterHTML.h b/Source/cmDocumentationFormatterHTML.h
deleted file mode 100644
index 44bf24026..000000000
--- a/Source/cmDocumentationFormatterHTML.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef _cmDocumentationFormatterHTML_h
-#define _cmDocumentationFormatterHTML_h
-
-#include "cmStandardIncludes.h"
-
-#include "cmDocumentationFormatter.h"
-
-/** Class to print the documentation as HTML. */
-class cmDocumentationFormatterHTML : public cmDocumentationFormatter
-{
-public:
- cmDocumentationFormatterHTML();
-
- virtual cmDocumentationEnums::Form GetForm() const
- { return cmDocumentationEnums::HTMLForm;}
-
- virtual void PrintHeader(const char* docname, const char* appname,
- std::ostream& os);
- virtual void PrintFooter(std::ostream& os);
- virtual void PrintSection(std::ostream& os,
- const cmDocumentationSection& section,
- const char* name);
- virtual void PrintPreformatted(std::ostream& os, const char* text);
- virtual void PrintParagraph(std::ostream& os, const char* text);
- virtual void PrintIndex(std::ostream& ,
- std::vector<const cmDocumentationSection *>&);
-private:
- void PrintHTMLEscapes(std::ostream& os, const char* text);
-};
-
-#endif
diff --git a/Source/cmDocumentationFormatterMan.cxx b/Source/cmDocumentationFormatterMan.cxx
deleted file mode 100644
index 4123c85cb..000000000
--- a/Source/cmDocumentationFormatterMan.cxx
+++ /dev/null
@@ -1,102 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-#include "cmDocumentationFormatterMan.h"
-#include "cmDocumentationSection.h"
-
-#include "cmSystemTools.h"
-#include "cmVersion.h"
-
-
-cmDocumentationFormatterMan::cmDocumentationFormatterMan()
-:cmDocumentationFormatter()
-,ManSection(1)
-{
-}
-
-void cmDocumentationFormatterMan::SetManSection(int manSection)
-{
- this->ManSection = manSection;
-}
-
-void cmDocumentationFormatterMan
-::PrintSection(std::ostream& os,
- const cmDocumentationSection &section,
- const char* name)
-{
- if(name)
- {
- os << ".SH " << name << "\n";
- }
-
- const std::vector<cmDocumentationEntry> &entries =
- section.GetEntries();
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op)
- {
- if(op->Name.size())
- {
- os << ".TP\n"
- << ".B " << (op->Name.size()?op->Name.c_str():"*") << "\n";
- this->PrintFormatted(os, op->Brief.c_str());
- this->PrintFormatted(os, op->Full.c_str());
- }
- else
- {
- os << ".PP\n";
- this->PrintFormatted(os, op->Brief.c_str());
- }
- }
-}
-
-void cmDocumentationFormatterMan::EscapeText(std::string& man_text)
-{
- cmSystemTools::ReplaceString(man_text, "\\", "\\\\");
- cmSystemTools::ReplaceString(man_text, "-", "\\-");
-}
-
-void cmDocumentationFormatterMan::PrintPreformatted(std::ostream& os,
- const char* text)
-{
- std::string man_text = text;
- this->EscapeText(man_text);
- os << ".nf\n" << man_text;
- if (*text && man_text.at(man_text.length()-1) != '\n')
- os << "\n";
- os << ".fi\n\n";
-}
-
-void cmDocumentationFormatterMan::PrintParagraph(std::ostream& os,
- const char* text)
-{
- std::string man_text = text;
- this->EscapeText(man_text);
- os << man_text << "\n\n";
-}
-
-
-//----------------------------------------------------------------------------
-void cmDocumentationFormatterMan::PrintHeader(const char* docname,
- const char* appname,
- std::ostream& os)
-{
- std::string s_docname(docname), s_appname(appname);
-
- this->EscapeText(s_docname);
- this->EscapeText(s_appname);
- os << ".TH " << s_docname << " " << this->ManSection << " \""
- << cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str()
- << "\" \"" << s_appname
- << " " << cmVersion::GetCMakeVersion()
- << "\"\n";
-}
-
diff --git a/Source/cmDocumentationFormatterMan.h b/Source/cmDocumentationFormatterMan.h
deleted file mode 100644
index b3d069c36..000000000
--- a/Source/cmDocumentationFormatterMan.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef _cmDocumentationFormatterMan_h
-#define _cmDocumentationFormatterMan_h
-
-#include "cmStandardIncludes.h"
-
-#include "cmDocumentationFormatter.h"
-
-/** Class to print the documentation as man page. */
-class cmDocumentationFormatterMan : public cmDocumentationFormatter
-{
-public:
- cmDocumentationFormatterMan();
-
- void SetManSection(int manSection);
-
- virtual cmDocumentationEnums::Form GetForm() const
- { return cmDocumentationEnums::ManForm;}
-
- virtual void PrintHeader(const char* docname, const char* appname,
- std::ostream& os);
- virtual void PrintSection(std::ostream& os,
- const cmDocumentationSection& section,
- const char* name);
- virtual void PrintPreformatted(std::ostream& os, const char* text);
- virtual void PrintParagraph(std::ostream& os, const char* text);
-
-private:
- void EscapeText(std::string& man_text);
- int ManSection;
-};
-
-#endif
diff --git a/Source/cmDocumentationFormatterText.cxx b/Source/cmDocumentationFormatterText.cxx
deleted file mode 100644
index 5def1947a..000000000
--- a/Source/cmDocumentationFormatterText.cxx
+++ /dev/null
@@ -1,180 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-#include "cmDocumentationFormatterText.h"
-#include "cmDocumentationSection.h"
-
-cmDocumentationFormatterText::cmDocumentationFormatterText()
-:cmDocumentationFormatter()
-,TextWidth(77)
-,TextIndent("")
-{
-}
-
-void cmDocumentationFormatterText
-::PrintSection(std::ostream& os,
- const cmDocumentationSection &section,
- const char* name)
-{
- if(name && (strcmp(name, "SingleItem")!=0))
- {
- os <<
- "---------------------------------------"
- "---------------------------------------\n";
- os << name << "\n\n";
- }
-
- const std::vector<cmDocumentationEntry> &entries =
- section.GetEntries();
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op)
- {
- if(op->Name.size())
- {
- os << " " << op->Name << "\n";
- this->TextIndent = " ";
- this->PrintFormatted(os, op->Brief.c_str());
- if(op->Full.size())
- {
- os << "\n";
- this->PrintFormatted(os, op->Full.c_str());
- }
- }
- else
- {
- this->TextIndent = "";
- this->PrintFormatted(os, op->Brief.c_str());
- }
- os << "\n";
- }
-}
-
-void cmDocumentationFormatterText::PrintPreformatted(std::ostream& os,
- const char* text)
-{
- bool newline = true;
- for(const char* ptr = text; *ptr; ++ptr)
- {
- if(newline && *ptr != '\n')
- {
- os << this->TextIndent;
- newline = false;
- }
- os << *ptr;
- if(*ptr == '\n')
- {
- newline = true;
- }
- }
- os << "\n";
-}
-
-void cmDocumentationFormatterText::PrintParagraph(std::ostream& os,
- const char* text)
-{
- os << this->TextIndent;
- this->PrintColumn(os, text);
- os << "\n";
-}
-
-void cmDocumentationFormatterText::SetIndent(const char* indent)
-{
- this->TextIndent = indent;
-}
-
-void cmDocumentationFormatterText::PrintColumn(std::ostream& os,
- const char* text)
-{
- // Print text arranged in an indented column of fixed witdh.
- const char* l = text;
- long column = 0;
- bool newSentence = false;
- bool firstLine = true;
- int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent));
-
- // Loop until the end of the text.
- while(*l)
- {
- // Parse the next word.
- const char* r = l;
- while(*r && (*r != '\n') && (*r != ' ')) { ++r; }
-
- // Does it fit on this line?
- if(r-l < (width-column-(newSentence?1:0)))
- {
- // Word fits on this line.
- if(r > l)
- {
- if(column)
- {
- // Not first word on line. Separate from the previous word
- // by a space, or two if this is a new sentence.
- if(newSentence)
- {
- os << " ";
- column += 2;
- }
- else
- {
- os << " ";
- column += 1;
- }
- }
- else
- {
- // First word on line. Print indentation unless this is the
- // first line.
- os << (firstLine?"":this->TextIndent);
- }
-
- // Print the word.
- os.write(l, static_cast<long>(r-l));
- newSentence = (*(r-1) == '.');
- }
-
- if(*r == '\n')
- {
- // Text provided a newline. Start a new line.
- os << "\n";
- ++r;
- column = 0;
- firstLine = false;
- }
- else
- {
- // No provided newline. Continue this line.
- column += static_cast<long>(r-l);
- }
- }
- else
- {
- // Word does not fit on this line. Start a new line.
- os << "\n";
- firstLine = false;
- if(r > l)
- {
- os << this->TextIndent;
- os.write(l, static_cast<long>(r-l));
- column = static_cast<long>(r-l);
- newSentence = (*(r-1) == '.');
- }
- else
- {
- column = 0;
- }
- }
-
- // Move to beginning of next word. Skip over whitespace.
- l = r;
- while(*l && (*l == ' ')) { ++l; }
- }
-}
diff --git a/Source/cmDocumentationFormatterText.h b/Source/cmDocumentationFormatterText.h
deleted file mode 100644
index d9c2af297..000000000
--- a/Source/cmDocumentationFormatterText.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef _cmDocumentationFormatterText_h
-#define _cmDocumentationFormatterText_h
-
-#include "cmStandardIncludes.h"
-
-#include "cmDocumentationFormatter.h"
-
-/** Class to print the documentation as plain text. */
-class cmDocumentationFormatterText : public cmDocumentationFormatter
-{
-public:
- cmDocumentationFormatterText();
-
- virtual cmDocumentationEnums::Form GetForm() const
- { return cmDocumentationEnums::TextForm;}
-
- virtual void PrintSection(std::ostream& os,
- const cmDocumentationSection& section,
- const char* name);
- virtual void PrintPreformatted(std::ostream& os, const char* text);
- virtual void PrintParagraph(std::ostream& os, const char* text);
- void PrintColumn(std::ostream& os, const char* text);
- void SetIndent(const char* indent);
-protected:
- int TextWidth;
- const char* TextIndent;
-};
-
-#endif
diff --git a/Source/cmDocumentationFormatterUsage.cxx b/Source/cmDocumentationFormatterUsage.cxx
deleted file mode 100644
index a068e5682..000000000
--- a/Source/cmDocumentationFormatterUsage.cxx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-#include "cmDocumentationFormatterUsage.h"
-#include "cmDocumentationSection.h"
-
-cmDocumentationFormatterUsage::cmDocumentationFormatterUsage()
-:cmDocumentationFormatterText()
-{
-}
-
-void cmDocumentationFormatterUsage
-::PrintSection(std::ostream& os,
- const cmDocumentationSection &section,
- const char* name)
-{
- if(name)
- {
- os << name << "\n";
- }
-
- const std::vector<cmDocumentationEntry> &entries =
- section.GetEntries();
- for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op)
- {
- if(op->Name.size())
- {
- os << " " << op->Name;
- this->TextIndent = " ";
- int align = static_cast<int>(strlen(this->TextIndent))-4;
- for(int i = static_cast<int>(op->Name.size()); i < align; ++i)
- {
- os << " ";
- }
- if (op->Name.size() > strlen(this->TextIndent)-4 )
- {
- os << "\n";
- os.write(this->TextIndent, strlen(this->TextIndent)-2);
- }
- os << "= ";
- this->PrintColumn(os, op->Brief.c_str());
- os << "\n";
- }
- else
- {
- os << "\n";
- this->TextIndent = "";
- this->PrintFormatted(os, op->Brief.c_str());
- }
- }
- os << "\n";
-}
-
diff --git a/Source/cmDocumentationFormatterUsage.h b/Source/cmDocumentationFormatterUsage.h
deleted file mode 100644
index 3ed3442cb..000000000
--- a/Source/cmDocumentationFormatterUsage.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef _cmDocumentationFormatterUsage_h
-#define _cmDocumentationFormatterUsage_h
-
-#include "cmDocumentationFormatterText.h"
-
-/** Class to print the documentation as usage on the command line. */
-class cmDocumentationFormatterUsage : public cmDocumentationFormatterText
-{
-public:
- cmDocumentationFormatterUsage();
-
- virtual cmDocumentationEnums::Form GetForm() const
- { return cmDocumentationEnums::UsageForm;}
-
- virtual void PrintSection(std::ostream& os,
- const cmDocumentationSection& section,
- const char* name);
-};
-
-#endif
diff --git a/Source/cmDocumentationSection.cxx b/Source/cmDocumentationSection.cxx
index a2dfe70d0..c47f33e4f 100644
--- a/Source/cmDocumentationSection.cxx
+++ b/Source/cmDocumentationSection.cxx
@@ -1,81 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDocumentationSection.h"
-
-//----------------------------------------------------------------------------
-void cmDocumentationSection::Append(const char *data[][3])
+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],
- data[i][2]));
+ while (data[i][1]) {
+ this->Entries.push_back(cmDocumentationEntry(data[i][0], data[i][1]));
data += 1;
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmDocumentationSection::Prepend(const char *data[][3])
+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],
- data[i][2]));
+ while (data[i][1]) {
+ tmp.push_back(cmDocumentationEntry(data[i][0], data[i][1]));
data += 1;
- }
- this->Entries.insert(this->Entries.begin(),tmp.begin(),tmp.end());
-}
-
-//----------------------------------------------------------------------------
-void cmDocumentationSection::Append(const char *n, const char *b,
- const char *f)
-{
- this->Entries.push_back(cmDocumentationEntry(n,b,f));
+ }
+ this->Entries.insert(this->Entries.begin(), tmp.begin(), tmp.end());
}
-#if 0
-//----------------------------------------------------------------------------
-void cmDocumentationSection::Set(const cmDocumentationEntry* header,
- const cmDocumentationEntry* section,
- const cmDocumentationEntry* footer)
+void cmDocumentationSection::Append(const char* n, const char* b)
{
- this->Entries.erase(this->Entries.begin(), this->Entries.end());
- if(header)
- {
- for(const cmDocumentationEntry* op = header; op->brief; ++op)
- {
- this->Entries.push_back(*op);
- }
- }
- if(section)
- {
- for(const cmDocumentationEntry* op = section; op->brief; ++op)
- {
- this->Entries.push_back(*op);
- }
- }
- if(footer)
- {
- for(const cmDocumentationEntry* op = footer; op->brief; ++op)
- {
- this->Entries.push_back(*op);
- }
- }
- cmDocumentationEntry empty = {0,0,0};
- this->Entries.push_back(empty);
+ this->Entries.push_back(cmDocumentationEntry(n, b));
}
-#endif
diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h
index 4f8c10d3e..d9e8187f8 100644
--- a/Source/cmDocumentationSection.h
+++ b/Source/cmDocumentationSection.h
@@ -1,19 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef _cmDocumentationSection_h
#define _cmDocumentationSection_h
-#include "cmStandardIncludes.h"
-#include "cmDocumentationFormatter.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmDocumentationEntry.h"
+
+#include <string>
+#include <vector>
// Low-level interface for custom documents:
/** Internal class representing a section of the documentation.
@@ -24,8 +19,10 @@ class cmDocumentationSection
{
public:
/** Create a cmSection, with a special name for man-output mode. */
- cmDocumentationSection(const char* name, const char* manName)
- :Name(name), ManName(manName) {}
+ cmDocumentationSection(const char* name, const char*)
+ : Name(name)
+ {
+ }
/** Has any content been added to this section or is it empty ? */
bool IsEmpty() const { return this->Entries.empty(); }
@@ -33,35 +30,39 @@ public:
/** Clear contents. */
void Clear() { this->Entries.clear(); }
- /** Return the name of this section for the given output form. */
- const char* GetName(cmDocumentationEnums::Form form) const
- { return (form==cmDocumentationEnums::ManForm ?
- this->ManName.c_str() : this->Name.c_str()); }
+ /** Return the name of this section. */
+ std::string GetName() const { return this->Name; }
/** Return a pointer to the first entry of this section. */
- const std::vector<cmDocumentationEntry> &GetEntries() const
- { return this->Entries; }
+ const std::vector<cmDocumentationEntry>& GetEntries() const
+ {
+ return this->Entries;
+ }
/** Append an entry to this section. */
void Append(const cmDocumentationEntry& entry)
- { this->Entries.push_back(entry); }
- void Append(const std::vector<cmDocumentationEntry> &entries)
- { this->Entries.insert(this->Entries.end(),entries.begin(),entries.end()); }
+ {
+ this->Entries.push_back(entry);
+ }
+ void Append(const std::vector<cmDocumentationEntry>& entries)
+ {
+ this->Entries.insert(this->Entries.end(), entries.begin(), entries.end());
+ }
/** Append an entry to this section using NULL terminated chars */
- void Append(const char *[][3]);
- void Append(const char *n, const char *b, const char *f);
+ void Append(const char* [][2]);
+ void Append(const char* n, const char* b);
/** prepend some documentation to this section */
- void Prepend(const char *[][3]);
- void Prepend(const std::vector<cmDocumentationEntry> &entries)
- { this->Entries.insert(this->Entries.begin(),
- entries.begin(),entries.end()); }
-
+ void Prepend(const char* [][2]);
+ void Prepend(const std::vector<cmDocumentationEntry>& entries)
+ {
+ this->Entries.insert(this->Entries.begin(), entries.begin(),
+ entries.end());
+ }
private:
std::string Name;
- std::string ManName;
std::vector<cmDocumentationEntry> Entries;
};
diff --git a/Source/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx
index 6a0ab7b1b..7fbe75c7b 100644
--- a/Source/cmDynamicLoader.cxx
+++ b/Source/cmDynamicLoader.cxx
@@ -1,106 +1,94 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDynamicLoader.h"
+#include <map>
+#include <string>
+#include <utility>
+
class cmDynamicLoaderCache
{
public:
~cmDynamicLoaderCache();
- void CacheFile(const char* path,
- const cmsys::DynamicLoader::LibraryHandle&);
- bool GetCacheFile(const char* path, cmsys::DynamicLoader::LibraryHandle&);
+ void CacheFile(const char* path, cmsys::DynamicLoader::LibraryHandle /*p*/);
+ bool GetCacheFile(const char* path,
+ cmsys::DynamicLoader::LibraryHandle& /*p*/);
bool FlushCache(const char* path);
void FlushCache();
static cmDynamicLoaderCache* GetInstance();
private:
- std::map<cmStdString, cmsys::DynamicLoader::LibraryHandle> CacheMap;
+ std::map<std::string, cmsys::DynamicLoader::LibraryHandle> CacheMap;
static cmDynamicLoaderCache* Instance;
};
-cmDynamicLoaderCache* cmDynamicLoaderCache::Instance = 0;
+cmDynamicLoaderCache* cmDynamicLoaderCache::Instance = CM_NULLPTR;
cmDynamicLoaderCache::~cmDynamicLoaderCache()
{
}
void cmDynamicLoaderCache::CacheFile(const char* path,
- const cmsys::DynamicLoader::LibraryHandle& p)
+ cmsys::DynamicLoader::LibraryHandle p)
{
cmsys::DynamicLoader::LibraryHandle h;
- if ( this->GetCacheFile(path, h) )
- {
+ if (this->GetCacheFile(path, h)) {
this->FlushCache(path);
- }
+ }
this->CacheMap[path] = p;
}
bool cmDynamicLoaderCache::GetCacheFile(const char* path,
- cmsys::DynamicLoader::LibraryHandle& p)
+ cmsys::DynamicLoader::LibraryHandle& p)
{
- std::map<cmStdString, cmsys::DynamicLoader::LibraryHandle>::iterator it
- = this->CacheMap.find(path);
- if ( it != this->CacheMap.end() )
- {
+ std::map<std::string, cmsys::DynamicLoader::LibraryHandle>::iterator it =
+ this->CacheMap.find(path);
+ if (it != this->CacheMap.end()) {
p = it->second;
return true;
- }
+ }
return false;
}
bool cmDynamicLoaderCache::FlushCache(const char* path)
{
- std::map<cmStdString, cmsys::DynamicLoader::LibraryHandle>::iterator it
- = this->CacheMap.find(path);
+ std::map<std::string, cmsys::DynamicLoader::LibraryHandle>::iterator it =
+ this->CacheMap.find(path);
bool ret = false;
- if ( it != this->CacheMap.end() )
- {
+ if (it != this->CacheMap.end()) {
cmsys::DynamicLoader::CloseLibrary(it->second);
this->CacheMap.erase(it);
ret = true;
- }
+ }
return ret;
}
void cmDynamicLoaderCache::FlushCache()
{
- for ( std::map<cmStdString,
- cmsys::DynamicLoader::LibraryHandle>::iterator it
- = this->CacheMap.begin();
- it != this->CacheMap.end(); it++ )
- {
+ for (std::map<std::string, cmsys::DynamicLoader::LibraryHandle>::iterator
+ it = this->CacheMap.begin();
+ it != this->CacheMap.end(); it++) {
cmsys::DynamicLoader::CloseLibrary(it->second);
- }
+ }
delete cmDynamicLoaderCache::Instance;
- cmDynamicLoaderCache::Instance = 0;
+ cmDynamicLoaderCache::Instance = CM_NULLPTR;
}
cmDynamicLoaderCache* cmDynamicLoaderCache::GetInstance()
{
- if ( !cmDynamicLoaderCache::Instance )
- {
+ if (!cmDynamicLoaderCache::Instance) {
cmDynamicLoaderCache::Instance = new cmDynamicLoaderCache;
- }
+ }
return cmDynamicLoaderCache::Instance;
}
cmsys::DynamicLoader::LibraryHandle cmDynamicLoader::OpenLibrary(
- const char* libname )
+ const char* libname)
{
cmsys::DynamicLoader::LibraryHandle lh;
- if ( cmDynamicLoaderCache::GetInstance()->GetCacheFile(libname, lh) )
- {
+ if (cmDynamicLoaderCache::GetInstance()->GetCacheFile(libname, lh)) {
return lh;
- }
+ }
lh = cmsys::DynamicLoader::OpenLibrary(libname);
cmDynamicLoaderCache::GetInstance()->CacheFile(libname, lh);
return lh;
diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h
index acf8011f2..7c46dd5d4 100644
--- a/Source/cmDynamicLoader.h
+++ b/Source/cmDynamicLoader.h
@@ -1,29 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
// .NAME cmDynamicLoader - class interface to system dynamic libraries
// .SECTION Description
// cmDynamicLoader provides a portable interface to loading dynamic
// libraries into a process.
+#ifndef cmDynamicLoader_h
+#define cmDynamicLoader_h
-#ifndef __cmDynamicLoader_h
-#define __cmDynamicLoader_h
-
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
-#include <cmsys/DynamicLoader.hxx>
+#include "cmsys/DynamicLoader.hxx" // IWYU pragma: export
class cmDynamicLoader
{
+ CM_DISABLE_COPY(cmDynamicLoader)
+
public:
// Description:
// Load a dynamic library into the current process.
@@ -36,12 +28,8 @@ public:
static void FlushCache();
protected:
- cmDynamicLoader() {};
- ~cmDynamicLoader() {};
-
-private:
- cmDynamicLoader(const cmDynamicLoader&); // Not implemented.
- void operator=(const cmDynamicLoader&); // Not implemented.
+ cmDynamicLoader() {}
+ ~cmDynamicLoader() {}
};
#endif
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 30de9a8a6..fc97bf3b3 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -1,58 +1,93 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmStandardIncludes.h" // to get CMAKE_USE_ELF_PARSER first
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmELF.h"
-#include <cmsys/auto_ptr.hxx>
-
-// Need the native byte order of the running CPU.
-#define cmsys_CPU_UNKNOWN_OKAY // We can decide at runtime if not known.
-#include <cmsys/CPU.h>
+#include "cm_auto_ptr.hxx"
+#include "cm_kwiml.h"
+#include "cmsys/FStream.hxx"
+#include <map>
+#include <sstream>
+#include <stddef.h>
+#include <utility>
+#include <vector>
// Include the ELF format information system header.
#if defined(__OpenBSD__)
-# include <stdint.h>
-# include <elf_abi.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
#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.
+#endif
+#ifndef DT_RUNPATH
+#define DT_RUNPATH 29
#endif
-//----------------------------------------------------------------------------
// Low-level byte swapping implementation.
-template <size_t s> struct cmELFByteSwapSize {};
-void cmELFByteSwap(char*, cmELFByteSwapSize<1> const&)
+template <size_t s>
+struct cmELFByteSwapSize
+{
+};
+void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> /*unused*/)
{
}
-void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const&)
+void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/)
{
char one_byte;
- one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
+ one_byte = data[0];
+ data[0] = data[1];
+ data[1] = one_byte;
}
-void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const&)
+void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
{
char one_byte;
- one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
- one_byte = data[1]; data[1] = data[2]; data[2] = one_byte;
+ one_byte = data[0];
+ data[0] = data[3];
+ data[3] = one_byte;
+ one_byte = data[1];
+ data[1] = data[2];
+ data[2] = one_byte;
}
-void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const&)
+void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/)
{
char one_byte;
- one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
- one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
- one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
- one_byte = data[3]; data[3] = data[4]; data[4] = one_byte;
+ one_byte = data[0];
+ data[0] = data[7];
+ data[7] = one_byte;
+ one_byte = data[1];
+ data[1] = data[6];
+ data[6] = one_byte;
+ one_byte = data[2];
+ data[2] = data[5];
+ data[5] = one_byte;
+ one_byte = data[3];
+ data[3] = data[4];
+ data[4] = one_byte;
}
// Low-level byte swapping interface.
@@ -62,28 +97,30 @@ void cmELFByteSwap(T& x)
cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
}
-//----------------------------------------------------------------------------
class cmELFInternal
{
public:
typedef cmELF::StringEntry StringEntry;
- enum ByteOrderType { ByteOrderMSB, ByteOrderLSB };
+ enum ByteOrderType
+ {
+ ByteOrderMSB,
+ ByteOrderLSB
+ };
// Construct and take ownership of the file stream object.
- cmELFInternal(cmELF* external,
- cmsys::auto_ptr<std::ifstream>& fin,
- ByteOrderType order):
- External(external),
- Stream(*fin.release()),
- ByteOrder(order),
- ELFType(cmELF::FileTypeInvalid)
- {
- // In most cases the processor-specific byte order will match that
- // of the target execution environment. If we choose wrong here
- // it is fixed when the header is read.
-#if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE
+ cmELFInternal(cmELF* external, CM_AUTO_PTR<cmsys::ifstream>& fin,
+ ByteOrderType order)
+ : External(external)
+ , Stream(*fin.release())
+ , ByteOrder(order)
+ , ELFType(cmELF::FileTypeInvalid)
+ {
+// In most cases the processor-specific byte order will match that
+// of the target execution environment. If we choose wrong here
+// it is fixed when the header is read.
+#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
-#elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG
+#elif KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_BIG
this->NeedSwap = (this->ByteOrder == ByteOrderLSB);
#else
this->NeedSwap = false; // Final decision is at runtime anyway.
@@ -91,49 +128,37 @@ public:
// We have not yet loaded the section info.
this->DynamicSectionIndex = -1;
- }
+ }
// Destruct and delete the file stream object.
- virtual ~cmELFInternal()
- {
- delete &this->Stream;
- }
+ virtual ~cmELFInternal() { delete &this->Stream; }
// Forward to the per-class implementation.
virtual unsigned int GetNumberOfSections() const = 0;
- virtual unsigned int GetDynamicEntryCount() = 0;
virtual unsigned long GetDynamicEntryPosition(int j) = 0;
- virtual StringEntry const* GetDynamicSectionString(int tag) = 0;
+ virtual cmELF::DynamicEntryList GetDynamicEntries() = 0;
+ virtual std::vector<char> EncodeDynamicEntries(
+ const cmELF::DynamicEntryList&) = 0;
+ virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0;
virtual void PrintInfo(std::ostream& os) const = 0;
- bool ReadBytes(unsigned long pos, unsigned long size, char* buf)
- {
- this->Stream.seekg(pos);
- this->Stream.read(buf, size);
- return this->Stream?true:false;
- }
-
// Lookup the SONAME in the DYNAMIC section.
StringEntry const* GetSOName()
- {
+ {
return this->GetDynamicSectionString(DT_SONAME);
- }
+ }
// Lookup the RPATH in the DYNAMIC section.
StringEntry const* GetRPath()
- {
+ {
return this->GetDynamicSectionString(DT_RPATH);
- }
+ }
// Lookup the RUNPATH in the DYNAMIC section.
StringEntry const* GetRunPath()
- {
-#if defined(DT_RUNPATH)
+ {
return this->GetDynamicSectionString(DT_RUNPATH);
-#else
- return 0;
-#endif
- }
+ }
// Return the recorded ELF type.
cmELF::FileType GetFileType() const { return this->ELFType; }
@@ -160,80 +185,81 @@ protected:
// Helper methods for subclasses.
void SetErrorMessage(const char* msg)
- {
+ {
this->External->ErrorMessage = msg;
this->ELFType = cmELF::FileTypeInvalid;
- }
+ }
// Store string table entry states.
- std::map<int, StringEntry> DynamicSectionStrings;
+ std::map<unsigned int, StringEntry> DynamicSectionStrings;
};
-//----------------------------------------------------------------------------
// 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_Dyn ELF_Dyn;
typedef Elf32_Half ELF_Half;
+ typedef KWIML_INT_uint32_t tagtype;
static const char* GetName() { return "32-bit"; }
};
-// Configure the implementation template for 32-bit ELF files.
+// Configure the implementation template for 64-bit ELF files.
+#ifndef _SCO_DS
struct cmELFTypes64
{
typedef Elf64_Ehdr ELF_Ehdr;
typedef Elf64_Shdr ELF_Shdr;
- typedef Elf64_Dyn ELF_Dyn;
+ typedef Elf64_Dyn ELF_Dyn;
typedef Elf64_Half ELF_Half;
+ typedef KWIML_INT_uint64_t tagtype;
static const char* GetName() { return "64-bit"; }
};
+#endif
-//----------------------------------------------------------------------------
// Parser implementation template.
template <class Types>
-class cmELFInternalImpl: public cmELFInternal
+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_Dyn ELF_Dyn;
typedef typename Types::ELF_Half ELF_Half;
+ typedef typename Types::tagtype tagtype;
// Construct with a stream and byte swap indicator.
- cmELFInternalImpl(cmELF* external,
- cmsys::auto_ptr<std::ifstream>& fin,
+ cmELFInternalImpl(cmELF* external, CM_AUTO_PTR<cmsys::ifstream>& fin,
ByteOrderType order);
// Return the number of sections as specified by the ELF header.
- virtual unsigned int GetNumberOfSections() const
- {
+ unsigned int GetNumberOfSections() const CM_OVERRIDE
+ {
return static_cast<unsigned int>(this->ELFHeader.e_shnum);
- }
+ }
- // Get the file position and size of a dynamic section entry.
- virtual unsigned int GetDynamicEntryCount();
- virtual unsigned long GetDynamicEntryPosition(int j);
+ // Get the file position of a dynamic section entry.
+ unsigned long GetDynamicEntryPosition(int j) CM_OVERRIDE;
+
+ cmELF::DynamicEntryList GetDynamicEntries() CM_OVERRIDE;
+ std::vector<char> EncodeDynamicEntries(const cmELF::DynamicEntryList&)
+ CM_OVERRIDE;
// Lookup a string from the dynamic section with the given tag.
- virtual StringEntry const* GetDynamicSectionString(int tag);
+ StringEntry const* GetDynamicSectionString(unsigned int tag) CM_OVERRIDE;
// Print information about the ELF file.
- virtual void PrintInfo(std::ostream& os) const
- {
+ void PrintInfo(std::ostream& os) const CM_OVERRIDE
+ {
os << "ELF " << Types::GetName();
- if(this->ByteOrder == ByteOrderMSB)
- {
+ if (this->ByteOrder == ByteOrderMSB) {
os << " MSB";
- }
- else if(this->ByteOrder == ByteOrderLSB)
- {
+ } else if (this->ByteOrder == ByteOrderLSB) {
os << " LSB";
- }
- switch(this->ELFType)
- {
+ }
+ switch (this->ELFType) {
case cmELF::FileTypeInvalid:
os << " invalid file";
break;
@@ -255,13 +281,17 @@ public:
case cmELF::FileTypeSpecificProc:
os << " processor-specific type";
break;
- }
- os << "\n";
}
+ os << "\n";
+ }
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];
+
void ByteSwap(ELF_Ehdr& elf_header)
- {
+ {
cmELFByteSwap(elf_header.e_type);
cmELFByteSwap(elf_header.e_machine);
cmELFByteSwap(elf_header.e_version);
@@ -275,10 +305,10 @@ private:
cmELFByteSwap(elf_header.e_shentsize);
cmELFByteSwap(elf_header.e_shnum);
cmELFByteSwap(elf_header.e_shstrndx);
- }
+ }
void ByteSwap(ELF_Shdr& sec_header)
- {
+ {
cmELFByteSwap(sec_header.sh_name);
cmELFByteSwap(sec_header.sh_type);
cmELFByteSwap(sec_header.sh_flags);
@@ -289,97 +319,40 @@ private:
cmELFByteSwap(sec_header.sh_info);
cmELFByteSwap(sec_header.sh_addralign);
cmELFByteSwap(sec_header.sh_entsize);
- }
+ }
void ByteSwap(ELF_Dyn& dyn)
- {
+ {
cmELFByteSwap(dyn.d_tag);
- switch (dyn.d_tag)
- {
- case DT_NULL: /* dyn.d_un ignored */ break;
- case DT_NEEDED: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_PLTRELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_PLTGOT: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_HASH: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_STRTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_SYMTAB: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_RELA: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_RELASZ: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_RELAENT: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_STRSZ: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_SYMENT: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_INIT: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_FINI: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_SONAME: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_RPATH: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_SYMBOLIC: /* dyn.d_un ignored */ break;
- case DT_REL: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_RELSZ: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_RELENT: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_PLTREL: cmELFByteSwap(dyn.d_un.d_val); break;
- case DT_DEBUG: cmELFByteSwap(dyn.d_un.d_ptr); break;
- case DT_TEXTREL: /* dyn.d_un ignored */ break;
- case DT_JMPREL: cmELFByteSwap(dyn.d_un.d_ptr); break;
-#ifdef T_BIND_NOW
- case T_BIND_NOW: /* dyn.d_un ignored */ break;
-#endif
-#ifdef DT_INIT_ARRAY
- case DT_INIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
-#endif
-#ifdef DT_FINI_ARRAY
- case DT_FINI_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
-#endif
-#ifdef DT_INIT_ARRAYSZ
- case DT_INIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
-#endif
-#ifdef DT_FINI_ARRAYSZ
- case DT_FINI_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
-#endif
-#ifdef DT_RUNPATH
- case DT_RUNPATH: cmELFByteSwap(dyn.d_un.d_val); break;
-#endif
-#ifdef DT_FLAGS
- case DT_FLAGS: cmELFByteSwap(dyn.d_un.d_val); break;
-#endif
-#ifdef DT_PREINIT_ARRAY
- case DT_PREINIT_ARRAY: cmELFByteSwap(dyn.d_un.d_ptr); break;
-#endif
-#ifdef DT_PREINIT_ARRAYSZ
- case DT_PREINIT_ARRAYSZ: cmELFByteSwap(dyn.d_un.d_val); break;
-#endif
- }
- }
+ cmELFByteSwap(dyn.d_un.d_val);
+ }
bool FileTypeValid(ELF_Half et)
- {
+ {
unsigned int eti = static_cast<unsigned int>(et);
- if(eti == ET_NONE || eti == ET_REL || eti == ET_EXEC ||
- eti == ET_DYN || eti == ET_CORE)
- {
+ if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN ||
+ eti == ET_CORE) {
return true;
- }
+ }
#if defined(ET_LOOS) && defined(ET_HIOS)
- if(eti >= ET_LOOS && eti <= ET_HIOS)
- {
+ if (eti >= ET_LOOS && eti <= ET_HIOS) {
return true;
- }
+ }
#endif
#if defined(ET_LOPROC) && defined(ET_HIPROC)
- if(eti >= ET_LOPROC && eti <= ET_HIPROC)
- {
+ if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
return true;
- }
+ }
#endif
return false;
- }
+ }
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;
- }
+ }
// The byte order of ELF header fields may not match that of the
// processor-specific data. The header fields are ordered to
@@ -388,63 +361,55 @@ private:
// value. As a heuristic, if the type is invalid but its
// swapped value is okay then flip our swap mode.
ELF_Half et = x.e_type;
- if(this->NeedSwap)
- {
+ if (this->NeedSwap) {
cmELFByteSwap(et);
- }
- if(!this->FileTypeValid(et))
- {
+ }
+ if (!this->FileTypeValid(et)) {
cmELFByteSwap(et);
- if(this->FileTypeValid(et))
- {
+ if (this->FileTypeValid(et)) {
// The previous byte order guess was wrong. Flip it.
this->NeedSwap = !this->NeedSwap;
- }
}
+ }
// Fix the byte order of the header.
- if(this->NeedSwap)
- {
+ if (this->NeedSwap) {
ByteSwap(x);
- }
- return true;
}
+ return true;
+ }
bool Read(ELF_Shdr& x)
- {
- if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
- this->NeedSwap)
- {
+ {
+ if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
+ this->NeedSwap) {
ByteSwap(x);
- }
- return this->Stream? true:false;
}
+ return !this->Stream.fail();
+ }
bool Read(ELF_Dyn& x)
- {
- if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
- this->NeedSwap)
- {
+ {
+ if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
+ this->NeedSwap) {
ByteSwap(x);
- }
- return this->Stream? true:false;
}
+ 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);
- if(!this->Read(this->SectionHeaders[i]))
- {
+ if (!this->Read(this->SectionHeaders[i])) {
return false;
- }
+ }
// Identify some important sections.
- if(this->SectionHeaders[i].sh_type == SHT_DYNAMIC)
- {
+ if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) {
this->DynamicSectionIndex = i;
- }
- return true;
}
+ return true;
+ }
bool LoadDynamicSection();
@@ -458,24 +423,20 @@ private:
std::vector<ELF_Dyn> DynamicSectionEntries;
};
-//----------------------------------------------------------------------------
template <class Types>
-cmELFInternalImpl<Types>
-::cmELFInternalImpl(cmELF* external,
- cmsys::auto_ptr<std::ifstream>& fin,
- ByteOrderType order):
- cmELFInternal(external, fin, order)
+cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
+ CM_AUTO_PTR<cmsys::ifstream>& fin,
+ ByteOrderType order)
+ : cmELFInternal(external, fin, order)
{
// Read the main header.
- if(!this->Read(this->ELFHeader))
- {
+ if (!this->Read(this->ELFHeader)) {
this->SetErrorMessage("Failed to read main ELF header.");
return;
- }
+ }
// Determine the ELF file type.
- switch(this->ELFHeader.e_type)
- {
+ switch (this->ELFHeader.e_type) {
case ET_NONE:
this->SetErrorMessage("ELF file type is NONE.");
return;
@@ -491,131 +452,150 @@ cmELFInternalImpl<Types>
case ET_CORE:
this->ELFType = cmELF::FileTypeCore;
break;
- default:
- {
+ default: {
unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
#if defined(ET_LOOS) && defined(ET_HIOS)
- if(eti >= ET_LOOS && eti <= ET_HIOS)
- {
+ if (eti >= ET_LOOS && eti <= ET_HIOS) {
this->ELFType = cmELF::FileTypeSpecificOS;
break;
- }
+ }
#endif
#if defined(ET_LOPROC) && defined(ET_HIPROC)
- if(eti >= ET_LOPROC && eti <= ET_HIPROC)
- {
+ if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
this->ELFType = cmELF::FileTypeSpecificProc;
break;
- }
+ }
#endif
- cmOStringStream e;
+ std::ostringstream e;
e << "Unknown ELF file type " << eti;
this->SetErrorMessage(e.str().c_str());
return;
- }
}
+ }
// Load the section headers.
this->SectionHeaders.resize(this->ELFHeader.e_shnum);
- for(ELF_Half i=0; i < this->ELFHeader.e_shnum; ++i)
- {
- if(!this->LoadSectionHeader(i))
- {
+ for (ELF_Half i = 0; i < this->ELFHeader.e_shnum; ++i) {
+ if (!this->LoadSectionHeader(i)) {
this->SetErrorMessage("Failed to load section headers.");
return;
- }
}
+ }
}
-//----------------------------------------------------------------------------
template <class Types>
bool cmELFInternalImpl<Types>::LoadDynamicSection()
{
// If there is no dynamic section we are done.
- if(this->DynamicSectionIndex < 0)
- {
+ if (this->DynamicSectionIndex < 0) {
return false;
- }
+ }
// If the section was already loaded we are done.
- if(!this->DynamicSectionEntries.empty())
- {
+ if (!this->DynamicSectionEntries.empty()) {
return true;
- }
+ }
- // Allocate the dynamic section entries.
+ // If there are no entries we are done.
ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
+ if (sec.sh_entsize == 0) {
+ return false;
+ }
+
+ // Allocate the dynamic section entries.
int n = static_cast<int>(sec.sh_size / sec.sh_entsize);
this->DynamicSectionEntries.resize(n);
// Read each entry.
- for(int j=0; j < n; ++j)
- {
+ 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.
- if(!this->Read(dyn))
- {
+ if (!this->Read(dyn)) {
this->SetErrorMessage("Error reading entry from DYNAMIC section.");
this->DynamicSectionIndex = -1;
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
template <class Types>
-unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount()
+unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
{
- if(!this->LoadDynamicSection())
- {
+ if (!this->LoadDynamicSection()) {
return 0;
- }
- for(unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i)
- {
- if(this->DynamicSectionEntries[i].d_tag == DT_NULL)
- {
- return i;
- }
- }
- return static_cast<unsigned int>(this->DynamicSectionEntries.size());
+ }
+ if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) {
+ return 0;
+ }
+ ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
+ return static_cast<unsigned long>(sec.sh_offset + sec.sh_entsize * j);
}
-//----------------------------------------------------------------------------
template <class Types>
-unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
+cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries()
{
- if(!this->LoadDynamicSection())
- {
- return 0;
- }
- if(j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size()))
- {
- return 0;
+ cmELF::DynamicEntryList result;
+
+ // Ensure entries have been read from file
+ if (!this->LoadDynamicSection()) {
+ return result;
+ }
+
+ // 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));
+ }
+
+ return result;
+}
+
+template <class Types>
+std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
+ const cmELF::DynamicEntryList& entries)
+{
+ std::vector<char> result;
+ result.reserve(sizeof(ELF_Dyn) * entries.size());
+
+ for (cmELF::DynamicEntryList::const_iterator it = entries.begin();
+ it != entries.end(); it++) {
+ // 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);
+
+ if (this->NeedSwap) {
+ ByteSwap(dyn);
}
- ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
- return static_cast<unsigned long>(sec.sh_offset + sec.sh_entsize*j);
+
+ char* pdyn = reinterpret_cast<char*>(&dyn);
+ result.insert(result.end(), pdyn, pdyn + sizeof(ELF_Dyn));
+ }
+
+ return result;
}
-//----------------------------------------------------------------------------
template <class Types>
-cmELF::StringEntry const*
-cmELFInternalImpl<Types>::GetDynamicSectionString(int tag)
+cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
+ unsigned int tag)
{
// Short-circuit if already checked.
- std::map<int, StringEntry>::iterator dssi =
+ std::map<unsigned int, StringEntry>::iterator dssi =
this->DynamicSectionStrings.find(tag);
- if(dssi != this->DynamicSectionStrings.end())
- {
- if(dssi->second.Position > 0)
- {
+ if (dssi != this->DynamicSectionStrings.end()) {
+ if (dssi->second.Position > 0) {
return &dssi->second;
- }
- return 0;
}
+ return CM_NULLPTR;
+ }
// Create an entry for this tag. Assume it is missing until found.
StringEntry& se = this->DynamicSectionStrings[tag];
@@ -624,36 +604,31 @@ cmELFInternalImpl<Types>::GetDynamicSectionString(int tag)
se.IndexInSection = -1;
// Try reading the dynamic section.
- if(!this->LoadDynamicSection())
- {
- return 0;
- }
+ if (!this->LoadDynamicSection()) {
+ return CM_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())
- {
+ if (sec.sh_link >= this->SectionHeaders.size()) {
this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
- return 0;
- }
+ return CM_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();
- di != this->DynamicSectionEntries.end(); ++di)
- {
+ for (typename std::vector<ELF_Dyn>::iterator di =
+ this->DynamicSectionEntries.begin();
+ di != this->DynamicSectionEntries.end(); ++di) {
ELF_Dyn& dyn = *di;
- if(dyn.d_tag == tag)
- {
+ if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) {
// We found the tag requested.
// Make sure the position given is within the string section.
- if(dyn.d_un.d_val >= strtab.sh_size)
- {
+ if (dyn.d_un.d_val >= strtab.sh_size) {
this->SetErrorMessage("Section DYNAMIC references string beyond "
"the end of its string section.");
- return 0;
- }
+ return CM_NULLPTR;
+ }
// Seek to the position reported by the entry.
unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
@@ -668,26 +643,21 @@ cmELFInternalImpl<Types>::GetDynamicSectionString(int tag)
// 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)
- {
+ if (c) {
se.Value += c;
- }
- else
- {
+ } else {
terminated = true;
- }
}
+ }
// Make sure the whole value was read.
- if(!this->Stream)
- {
+ if (!this->Stream) {
this->SetErrorMessage("Dynamic section specifies unreadable RPATH.");
se.Value = "";
- return 0;
- }
+ return CM_NULLPTR;
+ }
// The value has been read successfully. Report it.
se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
@@ -695,231 +665,180 @@ cmELFInternalImpl<Types>::GetDynamicSectionString(int tag)
se.IndexInSection =
static_cast<int>(di - this->DynamicSectionEntries.begin());
return &se;
- }
}
- return 0;
+ }
+ return CM_NULLPTR;
}
//============================================================================
// External class implementation.
-//----------------------------------------------------------------------------
-cmELF::cmELF(const char* fname): Internal(0)
+const long cmELF::TagRPath = DT_RPATH;
+const long cmELF::TagRunPath = DT_RUNPATH;
+
+#ifdef DT_MIPS_RLD_MAP_REL
+const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL;
+#else
+const long cmELF::TagMipsRldMapRel = 0;
+#endif
+
+cmELF::cmELF(const char* fname)
+ : Internal(CM_NULLPTR)
{
// Try to open the file.
- cmsys::auto_ptr<std::ifstream> fin(new std::ifstream(fname));
+ CM_AUTO_PTR<cmsys::ifstream> fin(new cmsys::ifstream(fname));
// Quit now if the file could not be opened.
- if(!fin.get() || !*fin)
- {
+ if (!fin.get() || !*fin) {
this->ErrorMessage = "Error opening input file.";
return;
- }
+ }
// Read the ELF identification block.
char ident[EI_NIDENT];
- if(!fin->read(ident, EI_NIDENT))
- {
+ if (!fin->read(ident, EI_NIDENT)) {
this->ErrorMessage = "Error reading ELF identification.";
return;
- }
- if(!fin->seekg(0))
- {
+ }
+ if (!fin->seekg(0)) {
this->ErrorMessage = "Error seeking to beginning of file.";
return;
- }
+ }
// Verify the ELF identification.
- if(!(ident[EI_MAG0] == ELFMAG0 &&
- ident[EI_MAG1] == ELFMAG1 &&
- ident[EI_MAG2] == ELFMAG2 &&
- ident[EI_MAG3] == ELFMAG3))
- {
+ if (!(ident[EI_MAG0] == ELFMAG0 && ident[EI_MAG1] == ELFMAG1 &&
+ ident[EI_MAG2] == ELFMAG2 && ident[EI_MAG3] == ELFMAG3)) {
this->ErrorMessage = "File does not have a valid ELF identification.";
return;
- }
+ }
// Check the byte order in which the rest of the file is encoded.
cmELFInternal::ByteOrderType order;
- if(ident[EI_DATA] == ELFDATA2LSB)
- {
+ if (ident[EI_DATA] == ELFDATA2LSB) {
// File is LSB.
- order = cmELFInternal::ByteOrderLSB;
- }
- else if(ident[EI_DATA] == ELFDATA2MSB)
- {
+ order = cmELFInternal::ByteOrderLSB;
+ } else if (ident[EI_DATA] == ELFDATA2MSB) {
// File is MSB.
- order = cmELFInternal::ByteOrderMSB;
- }
- else
- {
+ order = cmELFInternal::ByteOrderMSB;
+ } else {
this->ErrorMessage = "ELF file is not LSB or MSB encoded.";
return;
- }
+ }
// Check the class of the file and construct the corresponding
// parser implementation.
- if(ident[EI_CLASS] == ELFCLASS32)
- {
+ if (ident[EI_CLASS] == ELFCLASS32) {
// 32-bit ELF
this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
- }
- else if(ident[EI_CLASS] == ELFCLASS64)
- {
+ }
+#ifndef _SCO_DS
+ else if (ident[EI_CLASS] == ELFCLASS64) {
// 64-bit ELF
this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
- }
- else
- {
+ }
+#endif
+ else {
this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
return;
- }
+ }
}
-//----------------------------------------------------------------------------
cmELF::~cmELF()
{
delete this->Internal;
}
-//----------------------------------------------------------------------------
bool cmELF::Valid() const
{
return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
}
-//----------------------------------------------------------------------------
cmELF::FileType cmELF::GetFileType() const
{
- if(this->Valid())
- {
+ if (this->Valid()) {
return this->Internal->GetFileType();
- }
- else
- {
- return FileTypeInvalid;
- }
+ }
+ return FileTypeInvalid;
}
-//----------------------------------------------------------------------------
unsigned int cmELF::GetNumberOfSections() const
{
- if(this->Valid())
- {
+ if (this->Valid()) {
return this->Internal->GetNumberOfSections();
- }
- else
- {
- return 0;
- }
+ }
+ return 0;
}
-//----------------------------------------------------------------------------
-unsigned int cmELF::GetDynamicEntryCount() const
+unsigned long cmELF::GetDynamicEntryPosition(int index) const
{
- if(this->Valid())
- {
- return this->Internal->GetDynamicEntryCount();
- }
- else
- {
- return 0;
- }
+ if (this->Valid()) {
+ return this->Internal->GetDynamicEntryPosition(index);
+ }
+ return 0;
}
-//----------------------------------------------------------------------------
-unsigned long cmELF::GetDynamicEntryPosition(int index) const
+cmELF::DynamicEntryList cmELF::GetDynamicEntries() const
{
- if(this->Valid())
- {
- return this->Internal->GetDynamicEntryPosition(index);
- }
- else
- {
- return 0;
- }
+ if (this->Valid()) {
+ return this->Internal->GetDynamicEntries();
+ }
+
+ return cmELF::DynamicEntryList();
}
-//----------------------------------------------------------------------------
-bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const
+std::vector<char> cmELF::EncodeDynamicEntries(
+ const cmELF::DynamicEntryList& dentries) const
{
- if(this->Valid())
- {
- return this->Internal->ReadBytes(pos, size, buf);
- }
- else
- {
- return false;
- }
+ if (this->Valid()) {
+ return this->Internal->EncodeDynamicEntries(dentries);
+ }
+
+ return std::vector<char>();
}
-//----------------------------------------------------------------------------
bool cmELF::GetSOName(std::string& soname)
{
- if(StringEntry const* se = this->GetSOName())
- {
+ if (StringEntry const* se = this->GetSOName()) {
soname = se->Value;
return true;
- }
- else
- {
- return false;
- }
+ }
+ return false;
}
-//----------------------------------------------------------------------------
cmELF::StringEntry const* cmELF::GetSOName()
{
- if(this->Valid() &&
- this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)
- {
+ if (this->Valid() &&
+ this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) {
return this->Internal->GetSOName();
- }
- else
- {
- return 0;
- }
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
cmELF::StringEntry const* cmELF::GetRPath()
{
- if(this->Valid() &&
- (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
- this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary))
- {
+ if (this->Valid() &&
+ (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
+ this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
return this->Internal->GetRPath();
- }
- else
- {
- return 0;
- }
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
cmELF::StringEntry const* cmELF::GetRunPath()
{
- if(this->Valid() &&
- (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
- this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary))
- {
+ if (this->Valid() &&
+ (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
+ this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
return this->Internal->GetRunPath();
- }
- else
- {
- return 0;
- }
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
void cmELF::PrintInfo(std::ostream& os) const
{
- if(this->Valid())
- {
+ if (this->Valid()) {
this->Internal->PrintInfo(os);
- }
- else
- {
+ } else {
os << "Not a valid ELF file.\n";
- }
+ }
}
diff --git a/Source/cmELF.h b/Source/cmELF.h
index ab9be4245..a6e407fe1 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmELF_h
#define cmELF_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#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;
@@ -31,10 +29,7 @@ public:
~cmELF();
/** Get the error message if any. */
- std::string const& GetErrorMessage() const
- {
- return this->ErrorMessage;
- }
+ std::string const& GetErrorMessage() const { return this->ErrorMessage; }
/** Boolean conversion. True if the ELF file is valid. */
operator bool() const { return this->Valid(); }
@@ -68,22 +63,27 @@ public:
int IndexInSection;
};
+ /** Represent entire dynamic section header */
+ typedef std::vector<std::pair<long, unsigned long> > DynamicEntryList;
+
/** Get the type of the file opened. */
FileType GetFileType() const;
/** Get the number of ELF sections present. */
unsigned int GetNumberOfSections() const;
- /** Get the number of DYNAMIC section entries before the first
- DT_NULL. Returns zero on error. */
- unsigned int GetDynamicEntryCount() const;
-
/** Get the position of a DYNAMIC section header entry. Returns
zero on error. */
unsigned long GetDynamicEntryPosition(int index) const;
- /** Read bytes from the file. */
- bool ReadBytes(unsigned long pos, unsigned long size, char* buf) const;
+ /** Get a copy of all the DYNAMIC section header entries.
+ Returns an empty vector on error */
+ DynamicEntryList GetDynamicEntries() const;
+
+ /** Encodes a DYNAMIC section header entry list into a char vector according
+ to the type of ELF file this is */
+ std::vector<char> EncodeDynamicEntries(
+ const DynamicEntryList& entries) const;
/** Get the SONAME field if any. */
bool GetSOName(std::string& soname);
@@ -98,6 +98,10 @@ public:
/** Print human-readable information about the ELF file. */
void PrintInfo(std::ostream& os) const;
+ /** Interesting dynamic tags.
+ If the tag is 0, it does not exist in the host ELF implementation */
+ static const long TagRPath, TagRunPath, TagMipsRldMapRel;
+
private:
friend class cmELFInternal;
bool Valid() const;
diff --git a/Source/cmElseCommand.cxx b/Source/cmElseCommand.cxx
deleted file mode 100644
index 163d006ad..000000000
--- a/Source/cmElseCommand.cxx
+++ /dev/null
@@ -1,21 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmElseCommand.h"
-
-bool cmElseCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &)
-{
- this->SetError("An ELSE command was found outside of a proper "
- "IF ENDIF structure. Or its arguments did not match "
- "the opening IF command.");
- return false;
-}
diff --git a/Source/cmElseCommand.h b/Source/cmElseCommand.h
deleted file mode 100644
index f25991943..000000000
--- a/Source/cmElseCommand.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmElseCommand_h
-#define cmElseCommand_h
-
-#include "cmIfCommand.h"
-
-/** \class cmElseCommand
- * \brief ends an if block
- *
- * cmElseCommand ends an if block
- */
-class cmElseCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmElseCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "else";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Starts the else portion of an if block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " else(expression)\n"
- "See the if command.";
- }
-
- cmTypeMacro(cmElseCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmElseIfCommand.cxx b/Source/cmElseIfCommand.cxx
deleted file mode 100644
index cd9742bbd..000000000
--- a/Source/cmElseIfCommand.cxx
+++ /dev/null
@@ -1,20 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmElseIfCommand.h"
-
-bool cmElseIfCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &)
-{
- this->SetError("An ELSEIF command was found outside of a proper "
- "IF ENDIF structure.");
- return false;
-}
diff --git a/Source/cmElseIfCommand.h b/Source/cmElseIfCommand.h
deleted file mode 100644
index 46e2bd9f9..000000000
--- a/Source/cmElseIfCommand.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmElseIfCommand_h
-#define cmElseIfCommand_h
-
-#include "cmIfCommand.h"
-
-/** \class cmElseIfCommand
- * \brief ends an if block
- *
- * cmElseIfCommand ends an if block
- */
-class cmElseIfCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmElseIfCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "elseif";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Starts the elseif portion of an if block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " elseif(expression)\n"
- "See the if command.";
- }
-
- cmTypeMacro(cmElseIfCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmEnableLanguageCommand.cxx b/Source/cmEnableLanguageCommand.cxx
index dcabf6a46..c57b7b15c 100644
--- a/Source/cmEnableLanguageCommand.cxx
+++ b/Source/cmEnableLanguageCommand.cxx
@@ -1,43 +1,30 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmEnableLanguageCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEnableLanguageCommand.h"
+class cmExecutionStatus;
// cmEnableLanguageCommand
-bool cmEnableLanguageCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmEnableLanguageCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
bool optional = false;
std::vector<std::string> languages;
- if(args.size() < 1 )
- {
- this->SetError
- ("called with incorrect number of arguments");
+ if (args.empty()) {
+ this->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")
- {
+ it != args.end(); ++it) {
+ if ((*it) == "OPTIONAL") {
optional = true;
- }
- else
- {
+ } else {
languages.push_back(*it);
- }
}
+ }
this->Makefile->EnableLanguage(languages, optional);
return true;
}
-
diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h
index 747448b3e..33c1c22bf 100644
--- a/Source/cmEnableLanguageCommand.h
+++ b/Source/cmEnableLanguageCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmEnableLanguageCommand_h
#define cmEnableLanguageCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmEnableLanguageCommand
* \brief Specify the name for this build project.
*
@@ -28,57 +26,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmEnableLanguageCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmEnableLanguageCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "enable_language";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Enable a language (CXX/C/Fortran/etc)";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " enable_language(<lang> [OPTIONAL] )\n"
- "This command enables support for the named language in CMake. "
- "This is the same as the project command but does not create "
- "any of the extra variables that are created by the project command. "
- "Example languages are CXX, C, Fortran. "
- "\n"
- "This command must be called in file scope, not in a function call. "
- "Furthermore, it must be called in the highest directory common to "
- "all targets using the named language directly for compiling sources "
- "or indirectly through link dependencies. "
- "It is simplest to enable all needed languages in the top-level "
- "directory of a project."
- "\n"
- "The OPTIONAL keyword is a placeholder for future implementation "
- "and does not currently work.";
- }
-
- cmTypeMacro(cmEnableLanguageCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmEnableTestingCommand.cxx b/Source/cmEnableTestingCommand.cxx
index aa41ef73b..6a64450f5 100644
--- a/Source/cmEnableTestingCommand.cxx
+++ b/Source/cmEnableTestingCommand.cxx
@@ -1,22 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmEnableTestingCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEnableTestingCommand.h"
-#include "cmLocalGenerator.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 &)
+ cmExecutionStatus&)
{
- this->Makefile->AddDefinition("CMAKE_TESTING_ENABLED","1");
+ this->Makefile->AddDefinition("CMAKE_TESTING_ENABLED", "1");
return true;
}
diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h
index 9b9e9851b..e24966221 100644
--- a/Source/cmEnableTestingCommand.h
+++ b/Source/cmEnableTestingCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmEnableTestingCommand_h
#define cmEnableTestingCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmEnableTestingCommand
* \brief Enable testing for this directory and below.
*
@@ -33,47 +31,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmEnableTestingCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmEnableTestingCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "enable_testing";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Enable testing for current directory and below.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " enable_testing()\n"
- "Enables testing for this directory and below. "
- "See also the add_test command. Note that ctest expects to find "
- "a test file in the build directory root. Therefore, this command "
- "should be in the source directory root.";
- }
-
- cmTypeMacro(cmEnableTestingCommand, cmCommand);
-
+ bool InitialPass(std::vector<std::string> const&,
+ cmExecutionStatus&) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmEndForEachCommand.cxx b/Source/cmEndForEachCommand.cxx
deleted file mode 100644
index 7f11ae5f9..000000000
--- a/Source/cmEndForEachCommand.cxx
+++ /dev/null
@@ -1,23 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEndForEachCommand.h"
-
-bool cmEndForEachCommand
-::InvokeInitialPass(std::vector<cmListFileArgument> const&,
- cmExecutionStatus &)
-{
- this->SetError("An ENDFOREACH command was found outside of a proper "
- "FOREACH ENDFOREACH structure. Or its arguments did "
- "not match the opening FOREACH command.");
- return false;
-}
-
diff --git a/Source/cmEndForEachCommand.h b/Source/cmEndForEachCommand.h
deleted file mode 100644
index d5ee8a6ae..000000000
--- a/Source/cmEndForEachCommand.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmEndForEachCommand_h
-#define cmEndForEachCommand_h
-
-#include "cmCommand.h"
-
-/** \class cmEndForEachCommand
- * \brief ends an if block
- *
- * cmEndForEachCommand ends an if block
- */
-class cmEndForEachCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmEndForEachCommand;
- }
-
- /**
- * Override cmCommand::InvokeInitialPass to get arguments before
- * expansion.
- */
- virtual bool InvokeInitialPass(std::vector<cmListFileArgument> const&,
- cmExecutionStatus &);
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) {return false;}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "endforeach";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Ends a list of commands in a FOREACH block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " endforeach(expression)\n"
- "See the FOREACH command.";
- }
-
- cmTypeMacro(cmEndForEachCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmEndFunctionCommand.cxx b/Source/cmEndFunctionCommand.cxx
deleted file mode 100644
index 04b242d70..000000000
--- a/Source/cmEndFunctionCommand.cxx
+++ /dev/null
@@ -1,23 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEndFunctionCommand.h"
-
-bool cmEndFunctionCommand
-::InvokeInitialPass(std::vector<cmListFileArgument> const&,
- cmExecutionStatus &)
-{
- this->SetError("An ENDFUNCTION command was found outside of a proper "
- "FUNCTION ENDFUNCTION structure. Or its arguments did not "
- "match the opening FUNCTION command.");
- return false;
-}
-
diff --git a/Source/cmEndFunctionCommand.h b/Source/cmEndFunctionCommand.h
deleted file mode 100644
index d7b74e98b..000000000
--- a/Source/cmEndFunctionCommand.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmEndFunctionCommand_h
-#define cmEndFunctionCommand_h
-
-#include "cmCommand.h"
-
-/** \class cmEndFunctionCommand
- * \brief ends an if block
- *
- * cmEndFunctionCommand ends an if block
- */
-class cmEndFunctionCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmEndFunctionCommand;
- }
-
- /**
- * Override cmCommand::InvokeInitialPass to get arguments before
- * expansion.
- */
- virtual bool InvokeInitialPass(std::vector<cmListFileArgument> const&,
- cmExecutionStatus &);
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) {return false;}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "endfunction";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Ends a list of commands in a function block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " endfunction(expression)\n"
- "See the function command.";
- }
-
- cmTypeMacro(cmEndFunctionCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmEndIfCommand.cxx b/Source/cmEndIfCommand.cxx
deleted file mode 100644
index 0ac09de72..000000000
--- a/Source/cmEndIfCommand.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEndIfCommand.h"
-#include <stdlib.h> // required for atof
-bool cmEndIfCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &)
-{
- const char* versionValue
- = this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
- if (!versionValue || (atof(versionValue) <= 1.4))
- {
- return true;
- }
-
- this->SetError("An ENDIF command was found outside of a proper "
- "IF ENDIF structure. Or its arguments did not match "
- "the opening IF command.");
- return false;
-}
-
diff --git a/Source/cmEndIfCommand.h b/Source/cmEndIfCommand.h
deleted file mode 100644
index 5c4b9e36a..000000000
--- a/Source/cmEndIfCommand.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmEndIfCommand_h
-#define cmEndIfCommand_h
-
-#include "cmIfCommand.h"
-
-/** \class cmEndIfCommand
- * \brief ends an if block
- *
- * cmEndIfCommand ends an if block
- */
-class cmEndIfCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmEndIfCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "endif";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Ends a list of commands in an if block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " endif(expression)\n"
- "See the if command.";
- }
-
- cmTypeMacro(cmEndIfCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmEndMacroCommand.cxx b/Source/cmEndMacroCommand.cxx
deleted file mode 100644
index 86d907ba4..000000000
--- a/Source/cmEndMacroCommand.cxx
+++ /dev/null
@@ -1,23 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEndMacroCommand.h"
-
-bool cmEndMacroCommand
-::InvokeInitialPass(std::vector<cmListFileArgument> const&,
- cmExecutionStatus &)
-{
- this->SetError("An ENDMACRO command was found outside of a proper "
- "MACRO ENDMACRO structure. Or its arguments did not "
- "match the opening MACRO command.");
- return false;
-}
-
diff --git a/Source/cmEndMacroCommand.h b/Source/cmEndMacroCommand.h
deleted file mode 100644
index 9d0e70fdc..000000000
--- a/Source/cmEndMacroCommand.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmEndMacroCommand_h
-#define cmEndMacroCommand_h
-
-#include "cmCommand.h"
-
-/** \class cmEndMacroCommand
- * \brief ends an if block
- *
- * cmEndMacroCommand ends an if block
- */
-class cmEndMacroCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmEndMacroCommand;
- }
-
- /**
- * Override cmCommand::InvokeInitialPass to get arguments before
- * expansion.
- */
- virtual bool InvokeInitialPass(std::vector<cmListFileArgument> const&,
- cmExecutionStatus &);
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) {return false;}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "endmacro";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Ends a list of commands in a macro block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " endmacro(expression)\n"
- "See the macro command.";
- }
-
- cmTypeMacro(cmEndMacroCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmEndWhileCommand.cxx b/Source/cmEndWhileCommand.cxx
deleted file mode 100644
index abb9e5e0b..000000000
--- a/Source/cmEndWhileCommand.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmEndWhileCommand.h"
-
-bool cmEndWhileCommand
-::InvokeInitialPass(std::vector<cmListFileArgument> const& args,
- cmExecutionStatus &)
-{
- if (args.empty())
- {
- this->SetError("An ENDWHILE command was found outside of a proper "
- "WHILE ENDWHILE structure.");
- }
- else
- {
- this->SetError("An ENDWHILE command was found outside of a proper "
- "WHILE ENDWHILE structure. Or its arguments did not "
- "match the opening WHILE command.");
- }
-
- return false;
-}
-
diff --git a/Source/cmEndWhileCommand.h b/Source/cmEndWhileCommand.h
deleted file mode 100644
index 18ba5ea31..000000000
--- a/Source/cmEndWhileCommand.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmEndWhileCommand_h
-#define cmEndWhileCommand_h
-
-#include "cmCommand.h"
-
-/** \class cmEndWhileCommand
- * \brief ends a while loop
- *
- * cmEndWhileCommand ends a while loop
- */
-class cmEndWhileCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmEndWhileCommand;
- }
-
- /**
- * Override cmCommand::InvokeInitialPass to get arguments before
- * expansion.
- */
- virtual bool InvokeInitialPass(std::vector<cmListFileArgument> const& args,
- cmExecutionStatus &status);
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) {return false;}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "endwhile";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Ends a list of commands in a while block.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " endwhile(expression)\n"
- "See the while command.";
- }
-
- cmTypeMacro(cmEndWhileCommand, cmCommand);
-};
-
-
-#endif
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 9fdb1e896..fcc3c45c6 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -1,26 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExecProgramCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/Process.h"
+#include <stdio.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmExecProgramCommand.h"
+#include "cmMakefile.h"
+#include "cmProcessOutput.h"
#include "cmSystemTools.h"
+class cmExecutionStatus;
+
// cmExecProgramCommand
-bool cmExecProgramCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::string arguments;
bool doingargs = false;
int count = 0;
@@ -28,118 +26,261 @@ bool cmExecProgramCommand
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 (size_t i = 0; i < args.size(); ++i) {
+ if (args[i] == "OUTPUT_VARIABLE") {
count++;
doingargs = false;
havereturn_variable = false;
haveoutput_variable = true;
- }
- else if ( haveoutput_variable )
- {
- if ( output_variable.size() > 0 )
- {
+ } else if (haveoutput_variable) {
+ if (!output_variable.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
output_variable = args[i];
haveoutput_variable = false;
- count ++;
- }
- else if(args[i] == "RETURN_VALUE")
- {
+ count++;
+ } else if (args[i] == "RETURN_VALUE") {
count++;
doingargs = false;
haveoutput_variable = false;
havereturn_variable = true;
- }
- else if ( havereturn_variable )
- {
- if ( return_variable.size() > 0 )
- {
+ } else if (havereturn_variable) {
+ if (!return_variable.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
return_variable = args[i];
havereturn_variable = false;
- count ++;
- }
- else if(args[i] == "ARGS")
- {
+ count++;
+ } else if (args[i] == "ARGS") {
count++;
havereturn_variable = false;
haveoutput_variable = false;
doingargs = true;
- }
- else if(doingargs)
- {
+ } else if (doingargs) {
arguments += args[i];
arguments += " ";
count++;
- }
}
+ }
std::string command;
- if(arguments.size())
- {
+ if (!arguments.empty()) {
command = cmSystemTools::ConvertToRunCommandPath(args[0].c_str());
command += " ";
command += arguments;
- }
- else
- {
+ } else {
command = args[0];
- }
+ }
bool verbose = true;
- if(output_variable.size() > 0)
- {
+ if (!output_variable.empty()) {
verbose = false;
- }
+ }
int retVal = 0;
std::string output;
bool result = true;
- if(args.size() - count == 2)
- {
+ if (args.size() - count == 2) {
cmSystemTools::MakeDirectory(args[1].c_str());
- result = cmSystemTools::RunCommand(command.c_str(), output, retVal,
- args[1].c_str(), verbose);
- }
- else
- {
- result = cmSystemTools::RunCommand(command.c_str(), output,
- retVal, 0, verbose);
- }
- if(!result)
- {
+ result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal,
+ args[1].c_str(), verbose);
+ } else {
+ result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal,
+ CM_NULLPTR, verbose);
+ }
+ if (!result) {
retVal = -1;
- }
+ }
- if ( output_variable.size() > 0 )
- {
+ if (!output_variable.empty()) {
std::string::size_type first = output.find_first_not_of(" \n\t\r");
std::string::size_type last = output.find_last_not_of(" \n\t\r");
- if(first == std::string::npos)
- {
+ if (first == std::string::npos) {
first = 0;
+ }
+ if (last == std::string::npos) {
+ last = output.size() - 1;
+ }
+
+ std::string coutput = std::string(output, first, last - first + 1);
+ this->Makefile->AddDefinition(output_variable, coutput.c_str());
+ }
+
+ if (!return_variable.empty()) {
+ char buffer[100];
+ sprintf(buffer, "%d", retVal);
+ this->Makefile->AddDefinition(return_variable, buffer);
+ }
+
+ return true;
+}
+
+bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
+ int& retVal, const char* dir,
+ bool verbose, Encoding encoding)
+{
+ if (cmSystemTools::GetRunCommandOutput()) {
+ verbose = false;
+ }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // if the command does not start with a quote, then
+ // 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] == '\"') {
+ // count the number of quotes
+ for (const char* s = command; *s != 0; ++s) {
+ if (*s == '\"') {
+ count++;
+ if (count > 2) {
+ break;
+ }
}
- if(last == std::string::npos)
- {
- last = output.size()-1;
+ }
+ // if there are more than two double quotes use
+ // GetShortPathName, the cmd.exe program in windows which
+ // is used by system fails to execute if there are more than
+ // one set of quotes in the arguments
+ if (count > 2) {
+ cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
+ if (quoted.find(command)) {
+ std::string cmd = quoted.match(1);
+ std::string args = quoted.match(2);
+ if (!cmSystemTools::FileExists(cmd.c_str())) {
+ shortCmd = cmd;
+ } else if (!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) {
+ cmSystemTools::Error("GetShortPath failed for ", cmd.c_str());
+ return false;
+ }
+ shortCmd += " ";
+ shortCmd += args;
+
+ command = shortCmd.c_str();
+ } else {
+ cmSystemTools::Error("Could not parse command line with quotes ",
+ command);
}
+ }
+ }
+#endif
- std::string coutput = std::string(output, first, last-first+1);
- this->Makefile->AddDefinition(output_variable.c_str(), coutput.c_str());
+ // Allocate a process instance.
+ cmsysProcess* cp = cmsysProcess_New();
+ if (!cp) {
+ cmSystemTools::Error("Error allocating process instance.");
+ return false;
+ }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (dir) {
+ cmsysProcess_SetWorkingDirectory(cp, dir);
+ }
+ if (cmSystemTools::GetRunCommandHideConsole()) {
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
+ }
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
+ const char* cmd[] = { command, 0 };
+ cmsysProcess_SetCommand(cp, cmd);
+#else
+ std::string commandInDir;
+ if (dir) {
+ commandInDir = "cd \"";
+ commandInDir += dir;
+ commandInDir += "\" && ";
+ commandInDir += command;
+ } else {
+ commandInDir = command;
+ }
+#ifndef __VMS
+ commandInDir += " 2>&1";
+#endif
+ command = commandInDir.c_str();
+ if (verbose) {
+ cmSystemTools::Stdout("running ");
+ cmSystemTools::Stdout(command);
+ cmSystemTools::Stdout("\n");
+ }
+ fflush(stdout);
+ fflush(stderr);
+ const char* cmd[] = { "/bin/sh", "-c", command, CM_NULLPTR };
+ cmsysProcess_SetCommand(cp, cmd);
+#endif
+
+ cmsysProcess_Execute(cp);
+
+ // Read the process output.
+ int length;
+ char* data;
+ int p;
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
+ while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
+ if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) {
+ if (verbose) {
+ processOutput.DecodeText(data, length, strdata);
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ }
+ output.append(data, length);
}
+ }
- if ( return_variable.size() > 0 )
- {
- char buffer[100];
- sprintf(buffer, "%d", retVal);
- this->Makefile->AddDefinition(return_variable.c_str(), buffer);
+ if (verbose) {
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
}
+ }
+
+ // All output has been read. Wait for the process to exit.
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ processOutput.DecodeText(output, output);
+
+ // Check the result of running the process.
+ std::string msg;
+ switch (cmsysProcess_GetState(cp)) {
+ case cmsysProcess_State_Exited:
+ retVal = cmsysProcess_GetExitValue(cp);
+ break;
+ case cmsysProcess_State_Exception:
+ retVal = -1;
+ msg += "\nProcess terminated due to: ";
+ msg += cmsysProcess_GetExceptionString(cp);
+ break;
+ case cmsysProcess_State_Error:
+ retVal = -1;
+ msg += "\nProcess failed because: ";
+ msg += cmsysProcess_GetErrorString(cp);
+ break;
+ case cmsysProcess_State_Expired:
+ retVal = -1;
+ msg += "\nProcess terminated due to timeout.";
+ break;
+ }
+ if (!msg.empty()) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Old Windows process execution printed this info.
+ msg += "\n\nfor command: ";
+ msg += command;
+ if (dir) {
+ msg += "\nin dir: ";
+ msg += dir;
+ }
+ msg += "\n";
+ if (verbose) {
+ cmSystemTools::Stdout(msg.c_str());
+ }
+ output += msg;
+#else
+ // Old UNIX process execution only put message in output.
+ output += msg;
+#endif
+ }
+
+ // Delete the process instance.
+ cmsysProcess_Delete(cp);
return true;
}
-
diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h
index f752501fa..6463c4db5 100644
--- a/Source/cmExecProgramCommand.h
+++ b/Source/cmExecProgramCommand.h
@@ -1,18 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExecProgramCommand_h
#define cmExecProgramCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+#include "cmProcessOutput.h"
+
+class cmExecutionStatus;
/** \class cmExecProgramCommand
* \brief Command that adds a target to the build system.
@@ -24,72 +23,24 @@
class cmExecProgramCommand : public cmCommand
{
public:
+ typedef cmProcessOutput::Encoding Encoding;
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmExecProgramCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmExecProgramCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const
- {return "exec_program";}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Deprecated. Use the execute_process() command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "Run an executable program during the processing of the CMakeList.txt"
- " file.\n"
- " exec_program(Executable [directory in which to run]\n"
- " [ARGS <arguments to executable>]\n"
- " [OUTPUT_VARIABLE <var>]\n"
- " [RETURN_VALUE <var>])\n"
- "The executable is run in the optionally specified directory. The "
- "executable can include arguments if it is double quoted, but it is "
- "better to use the optional ARGS argument to specify arguments to the "
- "program. This is because cmake will then be able to escape spaces "
- "in the executable path. An optional argument OUTPUT_VARIABLE "
- "specifies a variable in which to store the output. "
- "To capture the return value of the execution, provide a RETURN_VALUE. "
- "If OUTPUT_VARIABLE is specified, then no output will go to the "
- "stdout/stderr of the console running cmake.\n"
- ;
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmExecProgramCommand, cmCommand);
+ 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);
};
#endif
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 994c1707b..8c10dbe29 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -1,20 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExecuteProcessCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/Process.h"
+#include <ctype.h> /* isspace */
+#include <sstream>
+#include <stdio.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmExecuteProcessCommand.h"
+#include "cmMakefile.h"
+#include "cmProcessOutput.h"
#include "cmSystemTools.h"
-#include <cmsys/Process.h>
-
-#include <ctype.h> /* isspace */
+class cmExecutionStatus;
static bool cmExecuteProcessCommandIsWhitespace(char c)
{
@@ -23,19 +20,18 @@ static bool cmExecuteProcessCommandIsWhitespace(char c)
void cmExecuteProcessCommandFixText(std::vector<char>& output,
bool strip_trailing_whitespace);
-void cmExecuteProcessCommandAppend(std::vector<char>& output,
- const char* data, int length);
+void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
+ int length);
// cmExecuteProcessCommand
-bool cmExecuteProcessCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- std::vector< std::vector<const char*> > cmds;
+ }
+ std::vector<std::vector<const char*> > cmds;
std::string arguments;
bool doing_command = false;
size_t command_index = 0;
@@ -51,235 +47,181 @@ bool cmExecuteProcessCommand
std::string error_variable;
std::string result_variable;
std::string working_directory;
- for(size_t i=0; i < args.size(); ++i)
- {
- if(args[i] == "COMMAND")
- {
+ 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")
- {
+ } else if (args[i] == "OUTPUT_VARIABLE") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
output_variable = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for OUTPUT_VARIABLE.");
return false;
- }
}
- else if(args[i] == "ERROR_VARIABLE")
- {
+ } else if (args[i] == "ERROR_VARIABLE") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
error_variable = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for ERROR_VARIABLE.");
return false;
- }
}
- else if(args[i] == "RESULT_VARIABLE")
- {
+ } else if (args[i] == "RESULT_VARIABLE") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
result_variable = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for RESULT_VARIABLE.");
return false;
- }
}
- else if(args[i] == "WORKING_DIRECTORY")
- {
+ } else if (args[i] == "WORKING_DIRECTORY") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
working_directory = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for WORKING_DIRECTORY.");
return false;
- }
}
- else if(args[i] == "INPUT_FILE")
- {
+ } else if (args[i] == "INPUT_FILE") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
input_file = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for INPUT_FILE.");
return false;
- }
}
- else if(args[i] == "OUTPUT_FILE")
- {
+ } else if (args[i] == "OUTPUT_FILE") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
output_file = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for OUTPUT_FILE.");
return false;
- }
}
- else if(args[i] == "ERROR_FILE")
- {
+ } else if (args[i] == "ERROR_FILE") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
error_file = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for ERROR_FILE.");
return false;
- }
}
- else if(args[i] == "TIMEOUT")
- {
+ } else if (args[i] == "TIMEOUT") {
doing_command = false;
- if(++i < args.size())
- {
+ if (++i < args.size()) {
timeout_string = args[i];
- }
- else
- {
+ } else {
this->SetError(" called with no value for TIMEOUT.");
return false;
- }
}
- else if(args[i] == "OUTPUT_QUIET")
- {
+ } else if (args[i] == "OUTPUT_QUIET") {
doing_command = false;
output_quiet = true;
- }
- else if(args[i] == "ERROR_QUIET")
- {
+ } else if (args[i] == "ERROR_QUIET") {
doing_command = false;
error_quiet = true;
- }
- else if(args[i] == "OUTPUT_STRIP_TRAILING_WHITESPACE")
- {
+ } else if (args[i] == "OUTPUT_STRIP_TRAILING_WHITESPACE") {
doing_command = false;
output_strip_trailing_whitespace = true;
- }
- else if(args[i] == "ERROR_STRIP_TRAILING_WHITESPACE")
- {
+ } 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)
- {
+ } else if (doing_command) {
cmds[command_index].push_back(args[i].c_str());
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << " given unknown argument \"" << args[i] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
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.c_str());
+ 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);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
+ }
// Check for commands given.
- if(cmds.empty())
- {
+ if (cmds.empty()) {
this->SetError(" called with no COMMAND argument.");
return false;
- }
- for(unsigned int i=0; i < cmds.size(); ++i)
- {
- if(cmds[i].empty())
- {
+ }
+ for (unsigned int i = 0; i < cmds.size(); ++i) {
+ if (cmds[i].empty()) {
this->SetError(" given COMMAND argument with no value.");
return false;
- }
- else
- {
- // Add the null terminating pointer to the command argument list.
- cmds[i].push_back(0);
- }
}
+ // 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)
- {
+ if (!timeout_string.empty()) {
+ if (sscanf(timeout_string.c_str(), "%lg", &timeout) != 1) {
this->SetError(" called with TIMEOUT value that could not be parsed.");
return false;
- }
}
+ }
// Create a process instance.
cmsysProcess* cp = cmsysProcess_New();
// Set the command sequence.
- for(unsigned int i=0; i < cmds.size(); ++i)
- {
+ for (unsigned int i = 0; i < cmds.size(); ++i) {
cmsysProcess_AddCommand(cp, &*cmds[i].begin());
- }
+ }
// Set the process working directory.
- if(!working_directory.empty())
- {
+ if (!working_directory.empty()) {
cmsysProcess_SetWorkingDirectory(cp, working_directory.c_str());
- }
+ }
// Always hide the process window.
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
// Check the output variables.
- bool merge_output = (output_variable == error_variable);
- if(error_variable.empty() && !error_quiet)
- {
- cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
- }
- if(!input_file.empty())
- {
+ bool merge_output = false;
+ if (!input_file.empty()) {
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str());
- }
- if(!output_file.empty())
- {
+ }
+ if (!output_file.empty()) {
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDOUT,
output_file.c_str());
+ }
+ if (!error_file.empty()) {
+ if (error_file == output_file) {
+ merge_output = true;
+ } else {
+ cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
+ error_file.c_str());
}
- if(!error_file.empty())
- {
- cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
- error_file.c_str());
- }
+ }
+ if (!output_variable.empty() && output_variable == error_variable) {
+ merge_output = true;
+ }
+ if (merge_output) {
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
+ }
// Set the timeout if any.
- if(timeout >= 0)
- {
+ if (timeout >= 0) {
cmsysProcess_SetTimeout(cp, timeout);
- }
+ }
// Start the process.
cmsysProcess_Execute(cp);
@@ -290,78 +232,79 @@ bool cmExecuteProcessCommand
int length;
char* data;
int p;
- while((p = cmsysProcess_WaitForData(cp, &data, &length, 0), p))
- {
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
+ while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
// Put the output in the right place.
- if((p == cmsysProcess_Pipe_STDOUT && !output_quiet) ||
- (p == cmsysProcess_Pipe_STDERR && !error_quiet && merge_output))
- {
- if(output_variable.empty())
- {
- cmSystemTools::Stdout(data, length);
- }
- else
- {
+ if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) {
+ if (output_variable.empty()) {
+ processOutput.DecodeText(data, length, strdata, 1);
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ } else {
cmExecuteProcessCommandAppend(tempOutput, data, length);
- }
}
- else if(p == cmsysProcess_Pipe_STDERR && !error_quiet)
- {
- if(!error_variable.empty())
- {
+ } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) {
+ if (error_variable.empty()) {
+ processOutput.DecodeText(data, length, strdata, 2);
+ cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ } else {
cmExecuteProcessCommandAppend(tempError, data, length);
- }
}
}
+ }
+ if (!output_quiet && output_variable.empty()) {
+ processOutput.DecodeText(std::string(), strdata, 1);
+ if (!strdata.empty()) {
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ }
+ }
+ if (!error_quiet && error_variable.empty()) {
+ processOutput.DecodeText(std::string(), strdata, 2);
+ if (!strdata.empty()) {
+ cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ }
+ }
// All output has been read. Wait for the process to exit.
- cmsysProcess_WaitForExit(cp, 0);
+ cmsysProcess_WaitForExit(cp, CM_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, output_strip_trailing_whitespace);
+ cmExecuteProcessCommandFixText(tempError, error_strip_trailing_whitespace);
// Store the output obtained.
- if(!output_variable.empty() && tempOutput.size())
- {
- this->Makefile->AddDefinition(output_variable.c_str(),
- &*tempOutput.begin());
- }
- if(!merge_output && !error_variable.empty() && tempError.size())
- {
- this->Makefile->AddDefinition(error_variable.c_str(),
- &*tempError.begin());
- }
+ if (!output_variable.empty() && !tempOutput.empty()) {
+ this->Makefile->AddDefinition(output_variable, &*tempOutput.begin());
+ }
+ if (!merge_output && !error_variable.empty() && !tempError.empty()) {
+ this->Makefile->AddDefinition(error_variable, &*tempError.begin());
+ }
// Store the result of running the process.
- if(!result_variable.empty())
- {
- switch(cmsysProcess_GetState(cp))
- {
- case cmsysProcess_State_Exited:
- {
+ if (!result_variable.empty()) {
+ switch (cmsysProcess_GetState(cp)) {
+ case cmsysProcess_State_Exited: {
int v = cmsysProcess_GetExitValue(cp);
char buf[100];
sprintf(buf, "%d", v);
- this->Makefile->AddDefinition(result_variable.c_str(), buf);
- }
- break;
+ this->Makefile->AddDefinition(result_variable, buf);
+ } break;
case cmsysProcess_State_Exception:
- this->Makefile->AddDefinition(result_variable.c_str(),
- cmsysProcess_GetExceptionString(cp));
+ this->Makefile->AddDefinition(result_variable,
+ cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- this->Makefile->AddDefinition(result_variable.c_str(),
- cmsysProcess_GetErrorString(cp));
+ this->Makefile->AddDefinition(result_variable,
+ cmsysProcess_GetErrorString(cp));
break;
case cmsysProcess_State_Expired:
- this->Makefile->AddDefinition(result_variable.c_str(),
- "Process terminated due to timeout");
+ this->Makefile->AddDefinition(result_variable,
+ "Process terminated due to timeout");
break;
- }
}
+ }
// Delete the process instance.
cmsysProcess_Delete(cp);
@@ -369,32 +312,28 @@ bool cmExecuteProcessCommand
return true;
}
-//----------------------------------------------------------------------------
void cmExecuteProcessCommandFixText(std::vector<char>& output,
bool strip_trailing_whitespace)
{
// Remove \0 characters and the \r part of \r\n pairs.
unsigned int in_index = 0;
unsigned int out_index = 0;
- while(in_index < output.size())
- {
+ while (in_index < output.size()) {
char c = output[in_index++];
- if((c != '\r' || !(in_index < output.size() && output[in_index] == '\n'))
- && c != '\0')
- {
+ if ((c != '\r' ||
+ !(in_index < output.size() && output[in_index] == '\n')) &&
+ c != '\0') {
output[out_index++] = c;
- }
}
+ }
// Remove trailing whitespace if requested.
- if(strip_trailing_whitespace)
- {
- while(out_index > 0 &&
- cmExecuteProcessCommandIsWhitespace(output[out_index-1]))
- {
+ if (strip_trailing_whitespace) {
+ while (out_index > 0 &&
+ cmExecuteProcessCommandIsWhitespace(output[out_index - 1])) {
--out_index;
- }
}
+ }
// Shrink the vector to the size needed.
output.resize(out_index);
@@ -403,20 +342,18 @@ void cmExecuteProcessCommandFixText(std::vector<char>& output,
output.push_back('\0');
}
-//----------------------------------------------------------------------------
-void cmExecuteProcessCommandAppend(std::vector<char>& output,
- const char* data, int length)
+void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
+ int length)
{
#if defined(__APPLE__)
// HACK on Apple to work around bug with inserting at the
// end of an empty vector. This resulted in random failures
// that were hard to reproduce.
- if(output.empty() && length > 0)
- {
+ if (output.empty() && length > 0) {
output.push_back(data[0]);
++data;
--length;
- }
+ }
#endif
- output.insert(output.end(), data, data+length);
+ output.insert(output.end(), data, data + length);
}
diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h
index 0e20a4b19..08fde0adc 100644
--- a/Source/cmExecuteProcessCommand.h
+++ b/Source/cmExecuteProcessCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExecuteProcessCommand_h
#define cmExecuteProcessCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmExecuteProcessCommand
* \brief Command that adds a target to the build system.
*
@@ -26,88 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmExecuteProcessCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmExecuteProcessCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const
- {return "execute_process";}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Execute one or more child processes.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " execute_process(COMMAND <cmd1> [args1...]]\n"
- " [COMMAND <cmd2> [args2...] [...]]\n"
- " [WORKING_DIRECTORY <directory>]\n"
- " [TIMEOUT <seconds>]\n"
- " [RESULT_VARIABLE <variable>]\n"
- " [OUTPUT_VARIABLE <variable>]\n"
- " [ERROR_VARIABLE <variable>]\n"
- " [INPUT_FILE <file>]\n"
- " [OUTPUT_FILE <file>]\n"
- " [ERROR_FILE <file>]\n"
- " [OUTPUT_QUIET]\n"
- " [ERROR_QUIET]\n"
- " [OUTPUT_STRIP_TRAILING_WHITESPACE]\n"
- " [ERROR_STRIP_TRAILING_WHITESPACE])\n"
- "Runs the given sequence of one or more commands with the standard "
- "output of each process piped to the standard input of the next. "
- "A single standard error pipe is used for all processes. "
- "If WORKING_DIRECTORY is given the named directory will be set as "
- "the current working directory of the child processes. "
- "If TIMEOUT is given the child processes will be terminated if they "
- "do not finish in the specified number of seconds "
- "(fractions are allowed). "
- "If RESULT_VARIABLE is given the variable will be set to contain "
- "the result of running the processes. This will be an integer return "
- "code from the last child or a string describing an error condition. "
- "If OUTPUT_VARIABLE or ERROR_VARIABLE are given the variable named "
- "will be set with the contents of the standard output and standard "
- "error pipes respectively. If the same variable is named for both "
- "pipes their output will be merged in the order produced. "
- "If INPUT_FILE, OUTPUT_FILE, or ERROR_FILE is given the file named "
- "will be attached to the standard input of the first process, "
- "standard output of the last process, or standard error of all "
- "processes respectively. "
- "If OUTPUT_QUIET or ERROR_QUIET is given then the standard output "
- "or standard error results will be quietly ignored. "
- "If more than one OUTPUT_* or ERROR_* option is given for the same "
- "pipe the precedence is not specified. "
- "If no OUTPUT_* or ERROR_* options are given the output will be shared "
- "with the corresponding pipes of the CMake process itself.\n"
- "The execute_process command is a newer more powerful version of "
- "exec_program, but the old command has been kept for compatibility."
- ;
- }
-
- cmTypeMacro(cmExecuteProcessCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
#endif
diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h
index 1488924c7..ac5fe1d72 100644
--- a/Source/cmExecutionStatus.h
+++ b/Source/cmExecutionStatus.h
@@ -1,54 +1,48 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExecutionStatus_h
#define cmExecutionStatus_h
-#include "cmObject.h"
-
/** \class cmExecutionStatus
* \brief Superclass for all command status classes
*
* when a command is involked it may set values on a command status instance
*/
-class cmExecutionStatus : public cmObject
+class cmExecutionStatus
{
public:
- cmTypeMacro(cmExecutionStatus, cmObject);
-
- cmExecutionStatus() { this->Clear();};
-
- virtual void SetReturnInvoked(bool val)
- { this->ReturnInvoked = val; }
- virtual bool GetReturnInvoked()
- { return this->ReturnInvoked; }
-
- virtual void SetBreakInvoked(bool val)
- { this->BreakInvoked = val; }
- virtual bool GetBreakInvoked()
- { return this->BreakInvoked; }
-
- virtual void Clear()
- {
+ cmExecutionStatus()
+ : ReturnInvoked(false)
+ , BreakInvoked(false)
+ , ContinueInvoked(false)
+ , NestedError(false)
+ {
+ }
+
+ void Clear()
+ {
this->ReturnInvoked = false;
this->BreakInvoked = false;
+ this->ContinueInvoked = false;
this->NestedError = false;
- }
- virtual void SetNestedError(bool val) { this->NestedError = val; }
- virtual bool GetNestedError() { return this->NestedError; }
+ }
+
+ void SetReturnInvoked() { this->ReturnInvoked = true; }
+ bool GetReturnInvoked() const { return this->ReturnInvoked; }
+
+ void SetBreakInvoked() { this->BreakInvoked = true; }
+ bool GetBreakInvoked() const { return this->BreakInvoked; }
+
+ void SetContinueInvoked() { this->ContinueInvoked = true; }
+ bool GetContinueInvoked() const { return this->ContinueInvoked; }
+ void SetNestedError() { this->NestedError = true; }
+ bool GetNestedError() const { return this->NestedError; }
-protected:
+private:
bool ReturnInvoked;
bool BreakInvoked;
+ bool ContinueInvoked;
bool NestedError;
};
diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx
new file mode 100644
index 000000000..0bea65fd0
--- /dev/null
+++ b/Source/cmExpandedCommandArgument.cxx
@@ -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. */
+#include "cmExpandedCommandArgument.h"
+
+cmExpandedCommandArgument::cmExpandedCommandArgument()
+ : Quoted(false)
+{
+}
+
+cmExpandedCommandArgument::cmExpandedCommandArgument(std::string const& value,
+ bool quoted)
+ : Value(value)
+ , Quoted(quoted)
+{
+}
+
+std::string const& cmExpandedCommandArgument::GetValue() const
+{
+ return this->Value;
+}
+
+bool cmExpandedCommandArgument::WasQuoted() const
+{
+ return this->Quoted;
+}
+
+bool cmExpandedCommandArgument::operator==(std::string const& value) const
+{
+ return this->Value == value;
+}
+
+bool cmExpandedCommandArgument::empty() const
+{
+ return this->Value.empty();
+}
+
+const char* cmExpandedCommandArgument::c_str() const
+{
+ return this->Value.c_str();
+}
diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h
new file mode 100644
index 000000000..fe86528db
--- /dev/null
+++ b/Source/cmExpandedCommandArgument.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmExpandedCommandArgument_h
+#define cmExpandedCommandArgument_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** \class cmExpandedCommandArgument
+ * \brief Represents an expanded command argument
+ *
+ * cmCommandArgument stores a string representing an expanded
+ * command argument and context information.
+ */
+
+class cmExpandedCommandArgument
+{
+public:
+ cmExpandedCommandArgument();
+ cmExpandedCommandArgument(std::string const& value, bool quoted);
+
+ std::string const& GetValue() const;
+
+ bool WasQuoted() const;
+
+ bool operator==(std::string const& value) const;
+
+ bool empty() const;
+
+ const char* c_str() const;
+
+private:
+ std::string Value;
+ bool Quoted;
+};
+
+#endif
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
new file mode 100644
index 000000000..b443fb0b4
--- /dev/null
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -0,0 +1,204 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.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;
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
+ std::ostream& os, const std::string&)
+{
+ os << "LOCAL_PATH := $(call my-dir)\n\n";
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
+ std::ostream&, const std::string&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
+ std::ostream& os, const cmGeneratorTarget* target)
+{
+ std::string targetName = this->Namespace;
+ targetName += 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());
+ os << path << "\n";
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode(
+ std::ostream&, const std::string&, cmGeneratorTarget const*,
+ ImportPropertyMap const&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode(
+ std::ostream&, const std::vector<std::string>&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ const cmGeneratorTarget* target, std::ostream& os,
+ const ImportPropertyMap& properties)
+{
+ std::string config;
+ if (!this->Configurations.empty()) {
+ config = this->Configurations[0];
+ }
+ cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ target, os, properties, cmExportBuildAndroidMKGenerator::BUILD, config);
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ const cmGeneratorTarget* target, std::ostream& os,
+ const ImportPropertyMap& properties, GenerateType type,
+ std::string const& config)
+{
+ const bool newCMP0022Behavior =
+ target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (!newCMP0022Behavior) {
+ std::ostringstream w;
+ if (type == cmExportBuildAndroidMKGenerator::BUILD) {
+ w << "export(TARGETS ... ANDROID_MK) called with policy CMP0022";
+ } else {
+ w << "install( EXPORT_ANDROID_MK ...) called with policy CMP0022";
+ }
+ 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());
+ }
+ 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") {
+ 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);
+ 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);
+ if (gt) {
+
+ if (gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ sharedLibs += " " + *i;
+ } else {
+ staticLibs += " " + *i;
+ }
+ } 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) == "../";
+ }
+ // 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 it is not a path and does not have a -l then add -l
+ } else if (!evaluated.empty()) {
+ ldlibs += " -l" + evaluated;
+ }
+ }
+ }
+ if (!sharedLibs.empty()) {
+ os << "LOCAL_SHARED_LIBRARIES :=" << sharedLibs << "\n";
+ }
+ if (!staticLibs.empty()) {
+ os << "LOCAL_STATIC_LIBRARIES :=" << staticLibs << "\n";
+ }
+ 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);
+ os << "LOCAL_EXPORT_C_INCLUDES := ";
+ std::string end;
+ for (std::vector<std::string>::iterator i = includeList.begin();
+ i != includeList.end(); ++i) {
+ os << end << *i;
+ end = "\\\n";
+ }
+ os << "\n";
+ } else {
+ os << "# " << pi->first << " " << (pi->second) << "\n";
+ }
+ }
+ }
+
+ // 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()) {
+ os << "LOCAL_HAS_CPP := true\n";
+ }
+ }
+
+ switch (target->GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ os << "include $(PREBUILT_SHARED_LIBRARY)\n";
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ os << "include $(PREBUILT_STATIC_LIBRARY)\n";
+ break;
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ break;
+ }
+ os << "\n";
+}
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
new file mode 100644
index 000000000..d028ef48d
--- /dev/null
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -0,0 +1,66 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmExportBuildAndroidMKGenerator_h
+#define cmExportBuildAndroidMKGenerator_h
+
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmExportBuildFileGenerator.h"
+#include "cmExportFileGenerator.h"
+
+class cmGeneratorTarget;
+
+/** \class cmExportBuildAndroidMKGenerator
+ * \brief Generate a file exporting targets from a build tree.
+ *
+ * cmExportBuildAndroidMKGenerator generates a file exporting targets from
+ * a build tree. This exports the targets to the Android ndk build tool
+ * makefile format for prebuilt libraries.
+ *
+ * This is used to implement the EXPORT() command.
+ */
+class cmExportBuildAndroidMKGenerator : public cmExportBuildFileGenerator
+{
+public:
+ cmExportBuildAndroidMKGenerator();
+ // this is so cmExportInstallAndroidMKGenerator can share this
+ // function as they are almost the same
+ enum GenerateType
+ {
+ BUILD,
+ INSTALL
+ };
+ static void GenerateInterfaceProperties(cmGeneratorTarget const* target,
+ std::ostream& os,
+ const ImportPropertyMap& properties,
+ GenerateType type,
+ std::string const& config);
+
+protected:
+ // Implement virtual methods from the superclass.
+ void GeneratePolicyHeaderCode(std::ostream&) CM_OVERRIDE {}
+ void GeneratePolicyFooterCode(std::ostream&) CM_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;
+ 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;
+ void GenerateMissingTargetsCheckCode(
+ std::ostream& os,
+ const std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ void GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties) CM_OVERRIDE;
+};
+
+#endif
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index cdc3316c4..a1c424aca 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -1,133 +1,154 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExportBuildFileGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmAlgorithms.h"
+#include "cmExportSet.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetExport.h"
+#include "cmake.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmExportBuildFileGenerator.h"
+#include <algorithm>
+#include <map>
+#include <set>
+#include <sstream>
+#include <utility>
-#include "cmExportCommand.h"
+class cmSourceFile;
-//----------------------------------------------------------------------------
cmExportBuildFileGenerator::cmExportBuildFileGenerator()
{
- this->ExportCommand = 0;
+ this->LG = CM_NULLPTR;
+ this->ExportSet = CM_NULLPTR;
+}
+
+void cmExportBuildFileGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LG = lg;
+ if (this->ExportSet) {
+ this->ExportSet->Compute(lg);
+ }
}
-//----------------------------------------------------------------------------
bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
{
- std::vector<cmTarget*> allTargets;
{
- std::string expectedTargets;
- std::string sep;
- for(std::vector<cmTarget*>::const_iterator
- tei = this->Exports->begin();
- tei != this->Exports->end(); ++tei)
- {
- expectedTargets += sep + this->Namespace + (*tei)->GetExportName();
- sep = " ";
- cmTarget* te = *tei;
- if(this->ExportedTargets.insert(te).second)
- {
- allTargets.push_back(te);
- }
- else
- {
- if(this->ExportCommand && this->ExportCommand->ErrorMessage.empty())
- {
- cmOStringStream e;
+ std::string expectedTargets;
+ std::string sep;
+ std::vector<std::string> targets;
+ this->GetTargets(targets);
+ for (std::vector<std::string>::const_iterator tei = targets.begin();
+ tei != targets.end(); ++tei) {
+ cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(*tei);
+ expectedTargets += sep + this->Namespace + te->GetExportName();
+ sep = " ";
+ if (this->ExportedTargets.insert(te).second) {
+ this->Exports.push_back(te);
+ } else {
+ std::ostringstream e;
e << "given target \"" << te->GetName() << "\" more than once.";
- this->ExportCommand->ErrorMessage = e.str();
- }
- return false;
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, e.str(),
+ this->LG->GetMakefile()->GetBacktrace());
+ return false;
+ }
+ if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ this->GenerateRequiredCMakeVersion(os, "3.0.0");
}
}
- this->GenerateExpectedTargetsCode(os, expectedTargets);
+ this->GenerateExpectedTargetsCode(os, expectedTargets);
}
std::vector<std::string> missingTargets;
// Create all the imported targets.
- for(std::vector<cmTarget*>::const_iterator
- tei = allTargets.begin();
- tei != allTargets.end(); ++tei)
- {
- cmTarget* te = *tei;
- this->GenerateImportTargetCode(os, te);
+ for (std::vector<cmGeneratorTarget*>::const_iterator tei =
+ this->Exports.begin();
+ tei != this->Exports.end(); ++tei) {
+ cmGeneratorTarget* gte = *tei;
+ this->GenerateImportTargetCode(os, gte);
- te->AppendBuildInterfaceIncludes();
+ gte->Target->AppendBuildInterfaceIncludes();
ImportPropertyMap properties;
- this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
+ this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
+ this->PopulateInterfaceProperty("INTERFACE_SOURCES", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", te,
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
- te, properties);
- const bool newCMP0022Behavior =
- te->GetPolicyStatusCMP0022() != cmPolicies::WARN
- && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
- if (newCMP0022Behavior)
- {
- this->PopulateInterfaceLinkLibrariesProperty(te,
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
- }
- this->PopulateCompatibleInterfaceProperties(te, properties);
-
- this->GenerateInterfaceProperties(te, os, properties);
+ this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
+ properties);
+ const bool newCMP0022Behavior =
+ gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (newCMP0022Behavior) {
+ this->PopulateInterfaceLinkLibrariesProperty(
+ gte, cmGeneratorExpression::BuildInterface, properties,
+ missingTargets);
}
+ this->PopulateCompatibleInterfaceProperties(gte, properties);
+
+ this->GenerateInterfaceProperties(gte, os, properties);
+ }
// 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->c_str(), missingTargets);
- }
+ for (std::vector<std::string>::const_iterator ci =
+ this->Configurations.begin();
+ ci != this->Configurations.end(); ++ci) {
+ this->GenerateImportConfig(os, *ci, missingTargets);
+ }
this->GenerateMissingTargetsCheckCode(os, missingTargets);
return true;
}
-//----------------------------------------------------------------------------
-void
-cmExportBuildFileGenerator
-::GenerateImportTargetsConfig(std::ostream& os,
- const char* config, std::string const& suffix,
- std::vector<std::string> &missingTargets)
+void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
+ std::ostream& os, const std::string& config, std::string const& suffix,
+ std::vector<std::string>& missingTargets)
{
- for(std::vector<cmTarget*>::const_iterator
- tei = this->Exports->begin();
- tei != this->Exports->end(); ++tei)
- {
+ for (std::vector<cmGeneratorTarget*>::const_iterator tei =
+ this->Exports.begin();
+ tei != this->Exports.end(); ++tei) {
// Collect import properties for this target.
- cmTarget* target = *tei;
+ cmGeneratorTarget* target = *tei;
ImportPropertyMap properties;
- this->SetImportLocationProperty(config, suffix, target, properties);
- if(!properties.empty())
- {
- // Get the rest of the target details.
- this->SetImportDetailProperties(config, suffix,
- target, properties, missingTargets);
- this->SetImportLinkInterface(config, suffix,
- cmGeneratorExpression::BuildInterface,
- target, properties, missingTargets);
+ if (target->GetType() != 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) {
+ this->SetImportDetailProperties(config, suffix, target, properties,
+ missingTargets);
+ this->SetImportLinkInterface(config, suffix,
+ cmGeneratorExpression::BuildInterface,
+ target, properties, missingTargets);
+ }
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
@@ -137,105 +158,168 @@ cmExportBuildFileGenerator
// Generate code in the export file.
this->GenerateImportPropertyCode(os, config, target, properties);
- }
}
+ }
+}
+
+void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
+{
+ this->ExportSet = exportSet;
}
-//----------------------------------------------------------------------------
-void
-cmExportBuildFileGenerator
-::SetImportLocationProperty(const char* config, std::string const& suffix,
- cmTarget* target, ImportPropertyMap& properties)
+void cmExportBuildFileGenerator::SetImportLocationProperty(
+ const std::string& config, std::string const& suffix,
+ cmGeneratorTarget* target, ImportPropertyMap& properties)
{
// Get the makefile in which to lookup target information.
- cmMakefile* mf = target->GetMakefile();
+ cmMakefile* mf = target->Makefile;
- // Add the main target file.
- {
- std::string prop = "IMPORTED_LOCATION";
- prop += suffix;
- std::string value;
- if(target->IsAppBundleOnApple())
- {
- value = target->GetFullPath(config, false);
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string prop = "IMPORTED_OBJECTS";
+ prop += suffix;
+
+ // Compute all the object files inside this target and setup
+ // IMPORTED_OBJECTS as a list of object files
+ std::vector<cmSourceFile const*> objectSources;
+ 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);
+ objects.push_back(obj_dir + obj);
}
- else
+
+ // Store the property.
+ properties[prop] = cmJoin(objects, ";");
+ } else {
+ // Add the main target file.
{
- value = target->GetFullPath(config, false, true);
+ std::string prop = "IMPORTED_LOCATION";
+ prop += suffix;
+ std::string value;
+ if (target->IsAppBundleOnApple()) {
+ value =
+ target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+ } else {
+ value = target->GetFullPath(config,
+ cmStateEnums::RuntimeBinaryArtifact, true);
+ }
+ properties[prop] = value;
}
- properties[prop] = value;
- }
- // Check whether this is a DLL platform.
- bool dll_platform =
- (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
-
- // Add the import library for windows DLLs.
- if(dll_platform &&
- (target->GetType() == cmTarget::SHARED_LIBRARY ||
- target->IsExecutableWithExports()) &&
- mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
- {
- std::string prop = "IMPORTED_IMPLIB";
- prop += suffix;
- std::string value = target->GetFullPath(config, true);
- target->GetImplibGNUtoMS(value, value,
- "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
- properties[prop] = value;
+ // Add the import library for windows DLLs.
+ if (target->HasImportLibrary() &&
+ mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+ std::string prop = "IMPORTED_IMPLIB";
+ prop += suffix;
+ std::string value =
+ target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
+ target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ properties[prop] = value;
}
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportBuildFileGenerator::HandleMissingTarget(
- std::string& link_libs, std::vector<std::string>&,
- cmMakefile*, cmTarget* depender, cmTarget* dependee)
+void cmExportBuildFileGenerator::HandleMissingTarget(
+ std::string& link_libs, std::vector<std::string>& missingTargets,
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
{
// The target is not in the export.
- if(!this->AppendMode)
- {
+ if (!this->AppendMode) {
+ 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];
+
+ missingTarget += dependee->GetExportName();
+ link_libs += missingTarget;
+ missingTargets.push_back(missingTarget);
+ return;
+ }
// We are not appending, so all exported targets should be
// known here. This is probably user-error.
- this->ComplainAboutMissingTarget(depender, dependee);
- }
+ this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+ }
// Assume the target will be exported by another command.
// Append it with the export namespace.
link_libs += this->Namespace;
link_libs += dependee->GetExportName();
}
-//----------------------------------------------------------------------------
-void
-cmExportBuildFileGenerator
-::ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee)
+void cmExportBuildFileGenerator::GetTargets(
+ std::vector<std::string>& targets) const
{
- if(!this->ExportCommand || !this->ExportCommand->ErrorMessage.empty())
- {
+ 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);
+ }
return;
+ }
+ targets = this->Targets;
+}
+
+std::vector<std::string> cmExportBuildFileGenerator::FindNamespaces(
+ cmGlobalGenerator* gg, const std::string& name)
+{
+ std::vector<std::string> namespaces;
+
+ 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;
+ std::vector<std::string> targets;
+ exportSet->GetTargets(targets);
+ if (std::find(targets.begin(), targets.end(), name) != targets.end()) {
+ namespaces.push_back(exportSet->GetNamespace());
}
+ }
+
+ return namespaces;
+}
- cmOStringStream e;
- e << "called with target \"" << depender->GetName()
- << "\" which requires target \"" << dependee->GetName()
- << "\" that is not in the export list.\n"
- << "If the required target is not easy to reference in this call, "
+void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences)
+{
+ 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";
+ } else {
+ e << "that is not in this export set, but " << occurrences
+ << " times in others.\n";
+ }
+ e << "If the required target is not easy to reference in this call, "
<< "consider using the APPEND option with multiple separate calls.";
- this->ExportCommand->ErrorMessage = e.str();
+
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace());
}
-std::string
-cmExportBuildFileGenerator::InstallNameDir(cmTarget* target,
- const std::string& config)
+std::string cmExportBuildFileGenerator::InstallNameDir(
+ cmGeneratorTarget* target, const std::string& config)
{
std::string install_name_dir;
- cmMakefile* mf = target->GetMakefile();
- if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
- install_name_dir =
- target->GetInstallNameDirForBuildTree(config.c_str());
- }
+ cmMakefile* mf = target->Target->GetMakefile();
+ if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+ install_name_dir = target->GetInstallNameDirForBuildTree(config);
+ }
return install_name_dir;
}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 3ffdf8b13..0556983ac 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -1,20 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExportBuildFileGenerator_h
#define cmExportBuildFileGenerator_h
+#include "cmConfigure.h"
+
#include "cmExportFileGenerator.h"
-class cmExportCommand;
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmExportSet;
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmLocalGenerator;
/** \class cmExportBuildFileGenerator
* \brief Generate a file exporting targets from a build tree.
@@ -25,46 +25,59 @@ class cmExportCommand;
*
* This is used to implement the EXPORT() command.
*/
-class cmExportBuildFileGenerator: public cmExportFileGenerator
+class cmExportBuildFileGenerator : public cmExportFileGenerator
{
public:
cmExportBuildFileGenerator();
/** Set the list of targets to export. */
- void SetExports(std::vector<cmTarget*> const* exports)
- { this->Exports = exports; }
+ void SetTargets(std::vector<std::string> const& targets)
+ {
+ this->Targets = targets;
+ }
+ 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());
+ }
+ void SetExportSet(cmExportSet*);
/** Set whether to append generated code to the output file. */
void SetAppendMode(bool append) { this->AppendMode = append; }
- /** Set the command instance through which errors should be reported. */
- void SetCommand(cmExportCommand* cmd) { this->ExportCommand = cmd; }
+ void Compute(cmLocalGenerator* lg);
+
protected:
// Implement virtual methods from the superclass.
- virtual bool GenerateMainFile(std::ostream& os);
- virtual void GenerateImportTargetsConfig(std::ostream& os,
- const char* config,
- std::string const& suffix,
- std::vector<std::string> &missingTargets);
- virtual void HandleMissingTarget(std::string& link_libs,
- std::vector<std::string>& missingTargets,
- cmMakefile* mf,
- cmTarget* depender,
- cmTarget* dependee);
+ bool GenerateMainFile(std::ostream& os) CM_OVERRIDE;
+ void GenerateImportTargetsConfig(
+ std::ostream& os, const std::string& config, std::string const& suffix,
+ std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ void HandleMissingTarget(std::string& link_libs,
+ std::vector<std::string>& missingTargets,
+ cmGeneratorTarget* depender,
+ cmGeneratorTarget* dependee) CM_OVERRIDE;
- void ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee);
+ void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
+ cmGeneratorTarget* dependee,
+ int occurrences);
/** Fill in properties indicating built file locations. */
- void SetImportLocationProperty(const char* config,
+ void SetImportLocationProperty(const std::string& config,
std::string const& suffix,
- cmTarget* target,
+ cmGeneratorTarget* target,
ImportPropertyMap& properties);
- std::string InstallNameDir(cmTarget* target, const std::string& config);
+ std::string InstallNameDir(cmGeneratorTarget* target,
+ const std::string& config) CM_OVERRIDE;
+
+ std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg,
+ const std::string& name);
- std::vector<cmTarget*> const* Exports;
- cmExportCommand* ExportCommand;
+ std::vector<std::string> Targets;
+ cmExportSet* ExportSet;
+ std::vector<cmGeneratorTarget*> Exports;
+ cmLocalGenerator* LG;
};
#endif
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index f059ceba6..38cd511ea 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -1,253 +1,275 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExportCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
+#include <map>
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmExportCommand.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
+#include "cmExportBuildAndroidMKGenerator.h"
+#include "cmExportBuildFileGenerator.h"
+#include "cmExportSetMap.h"
#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmake.h"
-#include <cmsys/RegularExpression.hxx>
-
-#include "cmExportBuildFileGenerator.h"
+class cmExecutionStatus;
#if defined(__HAIKU__)
-#include <StorageKit.h>
+#include <FindDirectory.h>
+#include <StorageDefs.h>
#endif
cmExportCommand::cmExportCommand()
-:cmCommand()
-,ArgumentGroup()
-,Targets(&Helper, "TARGETS")
-,Append(&Helper, "APPEND", &ArgumentGroup)
-,Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
-,Filename(&Helper, "FILE", &ArgumentGroup)
-,ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
+ : 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")
{
- // at first TARGETS
- this->Targets.Follows(0);
- // and after that the other options in any order
- this->ArgumentGroup.Follows(&this->Targets);
+ this->ExportSet = CM_NULLPTR;
}
-
// cmExportCommand
-bool cmExportCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with too few arguments");
return false;
- }
+ }
- if(args[0] == "PACKAGE")
- {
+ if (args[0] == "PACKAGE") {
return this->HandlePackage(args);
- }
+ }
+ if (args[0] == "EXPORT") {
+ this->ExportSetName.Follows(CM_NULLPTR);
+ this->ArgumentGroup.Follows(&this->ExportSetName);
+ } else {
+ this->Targets.Follows(CM_NULLPTR);
+ this->ArgumentGroup.Follows(&this->Targets);
+ }
std::vector<std::string> unknownArgs;
this->Helper.Parse(&args, &unknownArgs);
- if (!unknownArgs.empty())
- {
+ if (!unknownArgs.empty()) {
this->SetError("Unknown arguments.");
return false;
- }
+ }
- if (this->Targets.WasFound() == false)
- {
- this->SetError("TARGETS option missing.");
- return false;
- }
-
- if(!this->Filename.WasFound())
- {
- this->SetError("FILE <filename> option missing.");
- return false;
+ std::string fname;
+ bool android = false;
+ if (this->AndroidMKFile.WasFound()) {
+ fname = this->AndroidMKFile.GetString();
+ android = true;
+ }
+ if (!this->Filename.WasFound() && fname.empty()) {
+ if (args[0] != "EXPORT") {
+ this->SetError("FILE <filename> option missing.");
+ return false;
}
-
- // Make sure the file has a .cmake extension.
- if(cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString())
- != ".cmake")
- {
- cmOStringStream e;
- e << "FILE option given filename \"" << this->Filename.GetString()
- << "\" which does not have an extension of \".cmake\".\n";
- this->SetError(e.str().c_str());
- return false;
+ fname = this->ExportSetName.GetString() + ".cmake";
+ } else if (fname.empty()) {
+ // Make sure the file has a .cmake extension.
+ if (cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString()) !=
+ ".cmake") {
+ std::ostringstream e;
+ e << "FILE option given filename \"" << this->Filename.GetString()
+ << "\" which does not have an extension of \".cmake\".\n";
+ this->SetError(e.str());
+ return false;
}
+ fname = this->Filename.GetString();
+ }
// Get the file to write.
- std::string fname = this->Filename.GetString();
- if(cmSystemTools::FileIsFullPath(fname.c_str()))
- {
- if(!this->Makefile->CanIWriteThisFile(fname.c_str()))
- {
- cmOStringStream e;
+ if (cmSystemTools::FileIsFullPath(fname.c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(fname.c_str())) {
+ std::ostringstream e;
e << "FILE option given filename \"" << fname
<< "\" which is in the source tree.\n";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- else
- {
+ } else {
// Interpret relative paths with respect to the current build dir.
- fname = this->Makefile->GetCurrentOutputDirectory();
- fname += "/";
- fname += this->Filename.GetString();
+ std::string dir = this->Makefile->GetCurrentBinaryDirectory();
+ fname = dir + "/" + fname;
+ }
+
+ std::vector<std::string> targets;
+
+ cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+
+ 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;
}
- // Collect the targets to be exported.
- std::vector<cmTarget*> targets;
- for(std::vector<std::string>::const_iterator
- currentTarget = this->Targets.GetVector().begin();
- currentTarget != this->Targets.GetVector().end();
- ++currentTarget)
- {
- if (this->Makefile->IsAlias(currentTarget->c_str()))
- {
- cmOStringStream e;
- e << "given ALIAS target \"" << *currentTarget
- << "\" which may not be exported.";
- this->SetError(e.str().c_str());
+ 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;
- }
+ }
- if(cmTarget* target =
- this->Makefile->GetLocalGenerator()->
- GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
- {
- if((target->GetType() == cmTarget::EXECUTABLE) ||
- (target->GetType() == cmTarget::STATIC_LIBRARY) ||
- (target->GetType() == cmTarget::SHARED_LIBRARY) ||
- (target->GetType() == cmTarget::MODULE_LIBRARY))
- {
- targets.push_back(target);
- }
- else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
- e << "given OBJECT library \"" << *currentTarget
+ cmExportSetMap& setMap = gg->GetExportSets();
+ std::string setName = this->ExportSetName.GetString();
+ if (setMap.find(setName) == setMap.end()) {
+ std::ostringstream e;
+ e << "Export set \"" << setName << "\" not found.";
+ this->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)) {
+ std::ostringstream e;
+ e << "given ALIAS target \"" << *currentTarget
<< "\" which may not be exported.";
- this->SetError(e.str().c_str());
+ this->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 (target->GetType() == cmStateEnums::UTILITY) {
+ this->SetError("given custom target \"" + *currentTarget +
+ "\" which may not be exported.");
+ return false;
}
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "given target \"" << *currentTarget
- << "\" which is not an executable or library.";
- this->SetError(e.str().c_str());
+ << "\" which is not built by this project.";
+ this->SetError(e.str());
return false;
- }
}
- else
- {
- cmOStringStream e;
- e << "given target \"" << *currentTarget
- << "\" which is not built by this project.";
- this->SetError(e.str().c_str());
- return false;
+ targets.push_back(*currentTarget);
+ }
+ if (this->Append.IsEnabled()) {
+ if (cmExportBuildFileGenerator* ebfg =
+ gg->GetExportedTargetsFile(fname)) {
+ ebfg->AppendTargets(targets);
+ return true;
}
}
+ } else {
+ this->SetError("EXPORT or TARGETS specifier missing.");
+ return false;
+ }
// Setup export file generation.
- cmExportBuildFileGenerator ebfg;
- ebfg.SetExportFile(fname.c_str());
- ebfg.SetNamespace(this->Namespace.GetCString());
- ebfg.SetAppendMode(this->Append.IsEnabled());
- ebfg.SetExports(&targets);
- ebfg.SetCommand(this);
- ebfg.SetExportOld(this->ExportOld.IsEnabled());
+ cmExportBuildFileGenerator* ebfg = CM_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);
+ } else {
+ ebfg->SetTargets(targets);
+ }
+ this->Makefile->AddExportBuildFileGenerator(ebfg);
+ ebfg->SetExportOld(this->ExportOld.IsEnabled());
// Compute the set of configurations exported.
std::vector<std::string> configurationTypes;
this->Makefile->GetConfigurations(configurationTypes);
- if(!configurationTypes.empty())
- {
- for(std::vector<std::string>::const_iterator
- ci = configurationTypes.begin();
- ci != configurationTypes.end(); ++ci)
- {
- ebfg.AddConfiguration(ci->c_str());
- }
- }
- else
- {
- ebfg.AddConfiguration("");
- }
-
- // Generate the import file.
- if(!ebfg.GenerateImportFile() && this->ErrorMessage.empty())
- {
- this->SetError("could not write export file.");
- return false;
- }
-
- // Report generated error message if any.
- if(!this->ErrorMessage.empty())
- {
- this->SetError(this->ErrorMessage.c_str());
- return false;
- }
+ if (configurationTypes.empty()) {
+ configurationTypes.push_back("");
+ }
+ for (std::vector<std::string>::const_iterator ci =
+ configurationTypes.begin();
+ ci != configurationTypes.end(); ++ci) {
+ ebfg->AddConfiguration(*ci);
+ }
+ if (this->ExportSet) {
+ gg->AddBuildExportExportSet(ebfg);
+ } else {
+ gg->AddBuildExportSet(ebfg);
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
{
// Parse PACKAGE mode arguments.
- enum Doing { DoingNone, DoingPackage };
+ enum Doing
+ {
+ DoingNone,
+ DoingPackage
+ };
Doing doing = DoingPackage;
std::string package;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(doing == DoingPackage)
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (doing == DoingPackage) {
package = args[i];
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "PACKAGE given unknown argument: " << args[i];
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Verify the package name.
- if(package.empty())
- {
+ if (package.empty()) {
this->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()))
- {
- cmOStringStream e;
+ if (!packageRegex.find(package.c_str())) {
+ std::ostringstream e;
e << "PACKAGE given invalid package name \"" << package << "\". "
<< "Package names must match \"" << packageExpr << "\".";
- this->SetError(e.str().c_str());
+ this->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;
+ }
// 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->GetCurrentOutputDirectory();
+ const char* outDir = this->Makefile->GetCurrentBinaryDirectory();
std::string hash = cmSystemTools::ComputeStringMD5(outDir);
#if defined(_WIN32) && !defined(__CYGWIN__)
this->StorePackageRegistryWin(package, outDir, hash.c_str());
@@ -259,29 +281,24 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <windows.h>
-# undef GetCurrentDirectory
-//----------------------------------------------------------------------------
+#include <windows.h>
+
void cmExportCommand::ReportRegistryError(std::string const& msg,
- std::string const& key,
- long err)
+ std::string const& key, long err)
{
- cmOStringStream e;
+ std::ostringstream e;
e << msg << "\n"
<< " HKEY_CURRENT_USER\\" << key << "\n";
- char winmsg[1024];
- if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, 0, err,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- winmsg, 1024, 0) > 0)
- {
+ wchar_t winmsg[1024];
+ if (FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), winmsg, 1024, 0) > 0) {
e << "Windows reported:\n"
- << " " << winmsg;
- }
+ << " " << cmsys::Encoding::ToNarrow(winmsg);
+ }
this->Makefile->IssueMessage(cmake::WARNING, e.str());
}
-//----------------------------------------------------------------------------
void cmExportCommand::StorePackageRegistryWin(std::string const& package,
const char* content,
const char* hash)
@@ -289,48 +306,46 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
std::string key = "Software\\Kitware\\CMake\\Packages\\";
key += package;
HKEY hKey;
- LONG err = RegCreateKeyEx(HKEY_CURRENT_USER,
- 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);
+ 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);
return;
- }
- err = RegSetValueEx(hKey, hash, 0, REG_SZ, (BYTE const*)content,
- static_cast<DWORD>(strlen(content)+1));
+ }
+
+ std::wstring wcontent = cmsys::Encoding::ToWide(content);
+ err =
+ RegSetValueExW(hKey, cmsys::Encoding::ToWide(hash).c_str(), 0, REG_SZ,
+ (BYTE const*)wcontent.c_str(),
+ static_cast<DWORD>(wcontent.size() + 1) * sizeof(wchar_t));
RegCloseKey(hKey);
- if(err != ERROR_SUCCESS)
- {
- cmOStringStream msg;
+ if (err != ERROR_SUCCESS) {
+ std::ostringstream msg;
msg << "Cannot set registry value \"" << hash << "\" under key";
this->ReportRegistryError(msg.str(), key, err);
return;
- }
+ }
}
#else
-//----------------------------------------------------------------------------
void cmExportCommand::StorePackageRegistryDir(std::string const& package,
const char* content,
const char* hash)
{
#if defined(__HAIKU__)
- BPath dir;
- if (find_directory(B_USER_SETTINGS_DIRECTORY, &dir) != B_OK)
- {
+ char dir[B_PATH_NAME_LENGTH];
+ if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) !=
+ B_OK) {
return;
- }
- dir.Append("cmake/packages");
- dir.Append(package.c_str());
- std::string fname = dir.Path();
+ }
+ std::string fname = dir;
+ fname += "/cmake/packages/";
+ fname += package;
#else
- const char* home = cmSystemTools::GetEnv("HOME");
- if(!home)
- {
+ std::string fname;
+ if (!cmSystemTools::GetEnv("HOME", fname)) {
return;
- }
- std::string fname = home;
+ }
cmSystemTools::ConvertToUnixSlashes(fname);
fname += "/.cmake/packages/";
fname += package;
@@ -338,21 +353,19 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
cmSystemTools::MakeDirectory(fname.c_str());
fname += "/";
fname += hash;
- if(!cmSystemTools::FileExists(fname.c_str()))
- {
+ if (!cmSystemTools::FileExists(fname.c_str())) {
cmGeneratedFileStream entry(fname.c_str(), true);
- if(entry)
- {
+ if (entry) {
entry << content << "\n";
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
+ /* clang-format off */
e << "Cannot create package registry file:\n"
<< " " << fname << "\n"
<< cmSystemTools::GetLastSystemError() << "\n";
+ /* clang-format on */
this->Makefile->IssueMessage(cmake::WARNING, e.str());
- }
}
+ }
}
#endif
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index 87c345284..c47bc42b9 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -1,21 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExportCommand_h
#define cmExportCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmDocumentLocationUndefined.h"
+#include "cmCommandArgumentsHelper.h"
-class cmExportBuildFileGenerator;
+class cmExecutionStatus;
+class cmExportSet;
/** \class cmExportLibraryDependenciesCommand
* \brief Add a test to the lists of tests to run.
@@ -30,97 +27,38 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmExportCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmExportCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "export";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Export targets from the build tree for use by outside projects.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n"
- " [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])\n"
- "Create a file <filename> that may be included by outside projects to "
- "import targets from the current project's build tree. "
- "This is useful during cross-compiling to build utility executables "
- "that can run on the host platform in one project and then import "
- "them into another project being compiled for the target platform. "
- "If the NAMESPACE option is given the <namespace> string will be "
- "prepended to all target names written to the file. "
- "If the APPEND option is given the generated code will be appended "
- "to the file instead of overwriting it. "
- "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the "
- "contents of the properties matching "
- "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when "
- "policy CMP0022 is NEW. "
- "If a library target is included in the export but "
- "a target to which it links is not included the behavior is "
- "unspecified."
- "\n"
- "The file created by this command is specific to the build tree and "
- "should never be installed. "
- "See the install(EXPORT) command to export targets from an "
- "installation tree."
- CM_LOCATION_UNDEFINED_BEHAVIOR("passing it to this command")
- "\n"
- " export(PACKAGE <name>)\n"
- "Store the current build directory in the CMake user package registry "
- "for package <name>. "
- "The find_package command may consider the directory while searching "
- "for package <name>. "
- "This helps dependent projects find and use a package from the "
- "current project's build tree without help from the user. "
- "Note that the entry in the package registry that this command "
- "creates works only in conjunction with a package configuration "
- "file (<name>Config.cmake) that works with the build tree."
- ;
- }
-
- cmTypeMacro(cmExportCommand, cmCommand);
+ 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 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);
};
-
#endif
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 14be5cd47..972f4b9d1 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -1,101 +1,94 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportFileGenerator.h"
-#include "cmExportSet.h"
+#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
#include "cmGeneratedFileStream.h"
-#include "cmGlobalGenerator.h"
-#include "cmInstallExportGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
-#include "cmVersion.h"
-#include "cmComputeLinkInformation.h"
+#include "cmake.h"
-#include <cmsys/auto_ptr.hxx>
+#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)
+{
+ // Escape a property value for writing into a .cmake file.
+ std::string result = cmOutputConverter::EscapeForCMake(str);
+ // Un-escape variable references generated by our own export code.
+ cmSystemTools::ReplaceString(result, "\\${_IMPORT_PREFIX}",
+ "${_IMPORT_PREFIX}");
+ cmSystemTools::ReplaceString(result, "\\${CMAKE_IMPORT_LIBRARY_SUFFIX}",
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ return result;
+}
-//----------------------------------------------------------------------------
cmExportFileGenerator::cmExportFileGenerator()
{
this->AppendMode = false;
this->ExportOld = false;
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::AddConfiguration(const char* config)
+void cmExportFileGenerator::AddConfiguration(const std::string& config)
{
this->Configurations.push_back(config);
}
-//----------------------------------------------------------------------------
void cmExportFileGenerator::SetExportFile(const char* mainFile)
{
this->MainImportFile = mainFile;
- this->FileDir =
- cmSystemTools::GetFilenamePath(this->MainImportFile);
+ this->FileDir = cmSystemTools::GetFilenamePath(this->MainImportFile);
this->FileBase =
cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
this->FileExt =
cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
}
-//----------------------------------------------------------------------------
+const char* cmExportFileGenerator::GetMainExportFileName() const
+{
+ return this->MainImportFile.c_str();
+}
+
bool cmExportFileGenerator::GenerateImportFile()
{
// Open the output file to generate it.
- cmsys::auto_ptr<std::ofstream> foutPtr;
- if(this->AppendMode)
- {
+ CM_AUTO_PTR<cmsys::ofstream> foutPtr;
+ if (this->AppendMode) {
// Open for append.
- cmsys::auto_ptr<std::ofstream>
- ap(new std::ofstream(this->MainImportFile.c_str(), std::ios::app));
+ CM_AUTO_PTR<cmsys::ofstream> ap(
+ new cmsys::ofstream(this->MainImportFile.c_str(), std::ios::app));
foutPtr = ap;
- }
- else
- {
+ } else {
// Generate atomically and with copy-if-different.
- cmsys::auto_ptr<cmGeneratedFileStream>
- ap(new cmGeneratedFileStream(this->MainImportFile.c_str(), true));
+ CM_AUTO_PTR<cmGeneratedFileStream> ap(
+ new cmGeneratedFileStream(this->MainImportFile.c_str(), true));
ap->SetCopyIfDifferent(true);
foutPtr = ap;
- }
- if(!foutPtr.get() || !*foutPtr)
- {
+ }
+ if (!foutPtr.get() || !*foutPtr) {
std::string se = cmSystemTools::GetLastSystemError();
- cmOStringStream e;
- e << "cannot write to file \"" << this->MainImportFile
- << "\": " << se;
+ std::ostringstream e;
+ e << "cannot write to file \"" << this->MainImportFile << "\": " << se;
cmSystemTools::Error(e.str().c_str());
return false;
- }
+ }
std::ostream& os = *foutPtr;
- // Protect that file against use with older CMake versions.
- os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
- os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
- << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
- << "endif()\n";
-
- // Isolate the file policy level.
- // We use 2.6 here instead of the current version because newer
- // versions of CMake should be able to export files imported by 2.6
- // until the import format changes.
- os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6)\n";
-
// Start with the import file header.
+ this->GeneratePolicyHeaderCode(os);
this->GenerateImportHeaderCode(os);
// Create all the imported targets.
@@ -103,737 +96,785 @@ bool cmExportFileGenerator::GenerateImportFile()
// End with the import file footer.
this->GenerateImportFooterCode(os);
- os << "cmake_policy(POP)\n";
+ this->GeneratePolicyFooterCode(os);
return result;
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
- const char* config,
- std::vector<std::string> &missingTargets)
+void cmExportFileGenerator::GenerateImportConfig(
+ std::ostream& os, const std::string& config,
+ std::vector<std::string>& missingTargets)
{
// Construct the property configuration suffix.
std::string suffix = "_";
- if(config && *config)
- {
+ if (!config.empty()) {
suffix += cmSystemTools::UpperCase(config);
- }
- else
- {
+ } else {
suffix += "NOCONFIG";
- }
+ }
// Generate the per-config target information.
this->GenerateImportTargetsConfig(os, config, suffix, missingTargets);
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
- cmTarget *target,
- ImportPropertyMap &properties)
+void cmExportFileGenerator::PopulateInterfaceProperty(
+ const std::string& propName, cmGeneratorTarget* target,
+ ImportPropertyMap& properties)
{
- const char *input = target->GetProperty(propName);
- if (input)
- {
+ const char* input = target->GetProperty(propName);
+ if (input) {
properties[propName] = input;
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
- const char *outputName,
- cmTarget *target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets)
+void cmExportFileGenerator::PopulateInterfaceProperty(
+ const std::string& propName, const std::string& outputName,
+ cmGeneratorTarget* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- const char *input = target->GetProperty(propName);
- if (input)
- {
- if (!*input)
- {
+ const char* input = target->GetProperty(propName);
+ if (input) {
+ if (!*input) {
// Set to empty
properties[outputName] = "";
return;
- }
+ }
- std::string prepro = cmGeneratorExpression::Preprocess(input,
- preprocessRule);
- if (!prepro.empty())
- {
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule);
+ if (!prepro.empty()) {
this->ResolveTargetsInGeneratorExpressions(prepro, target,
missingTargets);
properties[outputName] = prepro;
- }
}
+ }
}
-void cmExportFileGenerator::GenerateRequiredCMakeVersion(std::ostream& os,
- const char *versionString)
+void cmExportFileGenerator::GenerateRequiredCMakeVersion(
+ std::ostream& os, const char* versionString)
{
+ /* clang-format off */
os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n"
" message(FATAL_ERROR \"This file relies on consumers using "
"CMake " << versionString << " or greater.\")\n"
"endif()\n\n";
+ /* clang-format on */
}
-//----------------------------------------------------------------------------
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
- cmTarget *target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets)
+ cmGeneratorTarget* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- if(!target->IsLinkable())
- {
+ if (!target->IsLinkable()) {
return false;
- }
- const char *input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
- if (input)
- {
- std::string prepro = cmGeneratorExpression::Preprocess(input,
- preprocessRule);
- if (!prepro.empty())
- {
- this->ResolveTargetsInGeneratorExpressions(prepro, target,
- missingTargets,
- ReplaceFreeTargets);
+ }
+ const char* input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
+ if (input) {
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(
+ prepro, target, missingTargets, ReplaceFreeTargets);
properties["INTERFACE_LINK_LIBRARIES"] = prepro;
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
static bool isSubDirectory(const char* a, const char* b)
{
return (cmSystemTools::ComparePath(a, b) ||
cmSystemTools::IsSubDirectory(a, b));
}
-//----------------------------------------------------------------------------
-static bool checkInterfaceDirs(const std::string &prepro,
- cmTarget *target)
+static bool checkInterfaceDirs(const std::string& prepro,
+ cmGeneratorTarget* target,
+ const std::string& prop)
{
const char* installDir =
- target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
- const char* topSourceDir = target->GetMakefile()->GetHomeDirectory();
- const char* topBinaryDir = target->GetMakefile()->GetHomeOutputDirectory();
+ target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ const char* topSourceDir = target->GetLocalGenerator()->GetSourceDirectory();
+ const char* topBinaryDir = target->GetLocalGenerator()->GetBinaryDirectory();
std::vector<std::string> parts;
cmGeneratorExpression::Split(prepro, parts);
const bool inSourceBuild = strcmp(topSourceDir, topBinaryDir) == 0;
- for(std::vector<std::string>::iterator li = parts.begin();
- li != parts.end(); ++li)
- {
- if (cmGeneratorExpression::Find(*li) != std::string::npos)
- {
+ bool hadFatalError = false;
+
+ for (std::vector<std::string>::iterator li = parts.begin();
+ li != parts.end(); ++li) {
+ size_t genexPos = cmGeneratorExpression::Find(*li);
+ if (genexPos == 0) {
continue;
+ }
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
+ std::ostringstream e;
+ if (genexPos != std::string::npos) {
+ if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
+ switch (target->GetPolicyStatusCMP0041()) {
+ case cmPolicies::WARN:
+ messageType = cmake::WARNING;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
+ break;
+ case cmPolicies::OLD:
+ continue;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ hadFatalError = true;
+ break; // Issue fatal message.
+ }
+ } else {
+ hadFatalError = true;
}
- if (strncmp(li->c_str(), "${_IMPORT_PREFIX}", 17) == 0)
- {
+ }
+ if (cmHasLiteralPrefix(li->c_str(), "${_IMPORT_PREFIX}")) {
continue;
- }
- if (!cmSystemTools::FileIsFullPath(li->c_str()))
- {
- cmOStringStream e;
- e << "Target \"" << target->GetName() << "\" "
- "INTERFACE_INCLUDE_DIRECTORIES property contains relative path:\n"
+ }
+ if (!cmSystemTools::FileIsFullPath(li->c_str())) {
+ /* clang-format off */
+ e << "Target \"" << target->GetName() << "\" " << prop <<
+ " property contains relative path:\n"
" \"" << *li << "\"";
- target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
- e.str().c_str());
- return false;
+ /* 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)) {
+ // 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
+ // also inside the source tree or build tree.
+ bool shouldContinue =
+ (!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
+ (!inSource || isSubDirectory(installDir, topSourceDir));
+
+ if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
+ if (!shouldContinue) {
+ switch (target->GetPolicyStatusCMP0052()) {
+ case cmPolicies::WARN: {
+ std::ostringstream s;
+ s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
+ 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 "
+ << (inBinary ? "build" : "source") << " tree:\n \""
+ << (inBinary ? topBinaryDir : topSourceDir) << "\""
+ << std::endl;
+ target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING,
+ s.str());
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD:
+ shouldContinue = true;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ break;
+ }
+ }
}
- if (isSubDirectory(li->c_str(), installDir))
- {
- continue;
+ if (shouldContinue) {
+ continue;
}
- if (isSubDirectory(li->c_str(), topBinaryDir))
- {
- cmOStringStream e;
- e << "Target \"" << target->GetName() << "\" "
- "INTERFACE_INCLUDE_DIRECTORIES property contains path:\n"
+ }
+ if (inBinary) {
+ /* clang-format off */
+ e << "Target \"" << target->GetName() << "\" " << prop <<
+ " property contains path:\n"
" \"" << *li << "\"\nwhich is prefixed in the build directory.";
- target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
- e.str().c_str());
- return false;
- }
- if (!inSourceBuild)
- {
- if (isSubDirectory(li->c_str(), topSourceDir))
- {
- cmOStringStream e;
- e << "Target \"" << target->GetName() << "\" "
- "INTERFACE_INCLUDE_DIRECTORIES property contains path:\n"
- " \"" << *li << "\"\nwhich is prefixed in the source directory.";
- target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
- e.str().c_str());
- return false;
- }
+ /* clang-format on */
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ }
+ if (!inSourceBuild) {
+ if (inSource) {
+ e << "Target \"" << target->GetName() << "\" " << prop
+ << " property contains path:\n"
+ " \""
+ << *li << "\"\nwhich is prefixed in the source directory.";
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
}
}
- return true;
+ }
+ return !hadFatalError;
+}
+
+static void prefixItems(std::string& exportDirs)
+{
+ std::vector<std::string> entries;
+ cmGeneratorExpression::Split(exportDirs, entries);
+ exportDirs = "";
+ const char* sep = "";
+ for (std::vector<std::string>::const_iterator ei = entries.begin();
+ ei != entries.end(); ++ei) {
+ exportDirs += sep;
+ sep = ";";
+ if (!cmSystemTools::FileIsFullPath(ei->c_str()) &&
+ ei->find("${_IMPORT_PREFIX}") == std::string::npos) {
+ exportDirs += "${_IMPORT_PREFIX}/";
+ }
+ exportDirs += *ei;
+ }
+}
+
+void cmExportFileGenerator::PopulateSourcesInterface(
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+{
+ cmGeneratorTarget* gt = tei->Target;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char* propName = "INTERFACE_SOURCES";
+ const char* input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (!*input) {
+ properties[propName] = "";
+ 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::PopulateIncludeDirectoriesInterface(
- cmTargetExport *tei,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets)
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmTarget *target = tei->Target;
+ cmGeneratorTarget* target = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
- const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
- const char *input = target->GetProperty(propName);
+ const char* propName = "INTERFACE_INCLUDE_DIRECTORIES";
+ const char* input = target->GetProperty(propName);
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
+ cmGeneratorExpression ge;
- std::string dirs = tei->InterfaceIncludeDirectories;
+ std::string dirs = cmGeneratorExpression::Preprocess(
+ tei->InterfaceIncludeDirectories, preprocessRule, true);
this->ReplaceInstallPrefix(dirs);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
- std::string exportDirs = cge->Evaluate(target->GetMakefile(), 0,
- false, target);
-
- if (cge->GetHadContextSensitiveCondition())
- {
- cmMakefile* mf = target->GetMakefile();
- cmOStringStream e;
- e << "Target \"" << target->GetName() << "\" is installed with "
- "INCLUDES DESTINATION set to a context sensitive path. Paths which "
- "depend on the configuration, policy values or the link interface are "
- "not supported. Consider using target_include_directories instead.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
+ std::string exportDirs =
+ cge->Evaluate(target->GetLocalGenerator(), "", false, target);
+
+ if (cge->GetHadContextSensitiveCondition()) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::ostringstream e;
+ e << "Target \"" << target->GetName()
+ << "\" is installed with "
+ "INCLUDES DESTINATION set to a context sensitive path. Paths which "
+ "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());
return;
- }
+ }
- if (!input && exportDirs.empty())
- {
+ if (!input && exportDirs.empty()) {
return;
- }
- if ((input && !*input) && exportDirs.empty())
- {
+ }
+ if ((input && !*input) && exportDirs.empty()) {
// Set to empty
properties[propName] = "";
return;
- }
+ }
+
+ prefixItems(exportDirs);
- std::string includes = (input?input:"");
+ std::string includes = (input ? input : "");
const char* sep = input ? ";" : "";
includes += sep + exportDirs;
- std::string prepro = cmGeneratorExpression::Preprocess(includes,
- preprocessRule,
- true);
- if (!prepro.empty())
- {
- this->ResolveTargetsInGeneratorExpressions(prepro, target,
- missingTargets);
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(includes, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target, missingTargets);
- if (!checkInterfaceDirs(prepro, target))
- {
+ if (!checkInterfaceDirs(prepro, target, propName)) {
return;
- }
- properties[propName] = prepro;
}
+ properties[propName] = prepro;
+ }
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
- cmTarget *target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets)
+void cmExportFileGenerator::PopulateInterfaceProperty(
+ const std::string& propName, cmGeneratorTarget* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
- properties, missingTargets);
+ properties, missingTargets);
}
-
-//----------------------------------------------------------------------------
-void getPropertyContents(cmTarget *tgt, const char *prop,
- std::set<std::string> &ifaceProperties)
+void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
+ std::set<std::string>& ifaceProperties)
{
- const char *p = tgt->GetProperty(prop);
- if (!p)
- {
+ const char* p = tgt->GetProperty(prop);
+ if (!p) {
return;
- }
+ }
std::vector<std::string> content;
cmSystemTools::ExpandListArgument(p, content);
- for (std::vector<std::string>::const_iterator ci = content.begin();
- ci != content.end(); ++ci)
- {
- ifaceProperties.insert(*ci);
- }
+ ifaceProperties.insert(content.begin(), content.end());
}
-//----------------------------------------------------------------------------
-void getCompatibleInterfaceProperties(cmTarget *target,
- std::set<std::string> &ifaceProperties,
- const char *config)
+void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
+ std::set<std::string>& ifaceProperties,
+ const std::string& config)
{
- cmComputeLinkInformation *info = target->GetLinkInformation(config);
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // object libraries have no link information, so nothing to compute
+ return;
+ }
- if (!info)
- {
- cmMakefile* mf = target->GetMakefile();
- cmOStringStream e;
- e << "Exporting the target \"" << target->GetName() << "\" is not "
+ cmComputeLinkInformation* info = target->GetLinkInformation(config);
+
+ if (!info) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::ostringstream e;
+ e << "Exporting the target \"" << target->GetName()
+ << "\" is not "
"allowed since its linker language cannot be determined";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
+ }
- const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
+ const cmComputeLinkInformation::ItemVector& deps = info->GetItems();
- for(cmComputeLinkInformation::ItemVector::const_iterator li =
- deps.begin();
- li != deps.end(); ++li)
- {
- if (!li->Target)
- {
+ for (cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin();
+ li != deps.end(); ++li) {
+ if (!li->Target) {
continue;
- }
- getPropertyContents(li->Target,
- "COMPATIBLE_INTERFACE_BOOL",
+ }
+ getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_BOOL",
ifaceProperties);
- getPropertyContents(li->Target,
- "COMPATIBLE_INTERFACE_STRING",
+ getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_STRING",
ifaceProperties);
- }
+ getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_NUMBER_MIN",
+ ifaceProperties);
+ getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_NUMBER_MAX",
+ ifaceProperties);
+ }
}
-//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
- cmTarget *target,
- ImportPropertyMap &properties)
+ cmGeneratorTarget* gtarget, ImportPropertyMap& properties)
{
- this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL",
- target, properties);
- this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING",
- target, properties);
+ this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget,
+ properties);
+ this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", gtarget,
+ properties);
+ this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MIN", gtarget,
+ properties);
+ this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MAX", gtarget,
+ properties);
std::set<std::string> ifaceProperties;
- getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
- getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
+ getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
+ getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
+ getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_NUMBER_MIN",
+ ifaceProperties);
+ getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_NUMBER_MAX",
+ ifaceProperties);
- getCompatibleInterfaceProperties(target, ifaceProperties, 0);
+ if (gtarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ getCompatibleInterfaceProperties(gtarget, ifaceProperties, "");
- std::vector<std::string> configNames;
- target->GetMakefile()->GetConfigurations(configNames);
+ 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(target, ifaceProperties, ci->c_str());
+ for (std::vector<std::string>::const_iterator ci = configNames.begin();
+ ci != configNames.end(); ++ci) {
+ getCompatibleInterfaceProperties(gtarget, ifaceProperties, *ci);
}
+ }
for (std::set<std::string>::const_iterator it = ifaceProperties.begin();
- it != ifaceProperties.end(); ++it)
- {
- this->PopulateInterfaceProperty(("INTERFACE_" + *it).c_str(),
- target, properties);
- }
+ it != ifaceProperties.end(); ++it) {
+ this->PopulateInterfaceProperty("INTERFACE_" + *it, gtarget, properties);
+ }
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
- std::ostream& os,
- const ImportPropertyMap &properties)
+void cmExportFileGenerator::GenerateInterfaceProperties(
+ const cmGeneratorTarget* target, std::ostream& os,
+ const ImportPropertyMap& properties)
{
- if (!properties.empty())
- {
+ if (!properties.empty()) {
std::string targetName = this->Namespace;
targetName += target->GetExportName();
os << "set_target_properties(" << targetName << " PROPERTIES\n";
- for(ImportPropertyMap::const_iterator pi = properties.begin();
- pi != properties.end(); ++pi)
- {
- os << " " << pi->first << " \"" << pi->second << "\"\n";
- }
- os << ")\n\n";
+ for (ImportPropertyMap::const_iterator pi = properties.begin();
+ pi != properties.end(); ++pi) {
+ os << " " << pi->first << " " << cmExportFileGeneratorEscape(pi->second)
+ << "\n";
}
+ os << ")\n\n";
+ }
}
-//----------------------------------------------------------------------------
-bool
-cmExportFileGenerator::AddTargetNamespace(std::string &input,
- cmTarget* target,
- std::vector<std::string> &missingTargets)
+bool cmExportFileGenerator::AddTargetNamespace(
+ std::string& input, cmGeneratorTarget* target,
+ std::vector<std::string>& missingTargets)
{
- cmMakefile *mf = target->GetMakefile();
+ cmLocalGenerator* lg = target->GetLocalGenerator();
- cmTarget *tgt = mf->FindTargetToUse(input.c_str());
- if (!tgt)
- {
+ cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(input);
+ if (!tgt) {
return false;
- }
+ }
- if(tgt->IsImported())
- {
+ if (tgt->IsImported()) {
return true;
- }
- if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
- {
+ }
+ if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) {
input = this->Namespace + tgt->GetExportName();
- }
- else
- {
+ } else {
std::string namespacedTarget;
- this->HandleMissingTarget(namespacedTarget, missingTargets,
- mf, target, tgt);
- if (!namespacedTarget.empty())
- {
+ this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt);
+ if (!namespacedTarget.empty()) {
input = namespacedTarget;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
- std::string &input,
- cmTarget* target,
- std::vector<std::string> &missingTargets,
- FreeTargetsReplace replace)
+void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
+ std::string& input, cmGeneratorTarget* target,
+ std::vector<std::string>& missingTargets, FreeTargetsReplace replace)
{
- if (replace == NoReplaceFreeTargets)
- {
+ if (replace == NoReplaceFreeTargets) {
this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
return;
- }
+ }
std::vector<std::string> parts;
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)
- {
+ 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);
- }
- else
- {
- this->ResolveTargetsInGeneratorExpression(
- *li,
- target,
- missingTargets);
- }
+ } else {
+ this->ResolveTargetsInGeneratorExpression(*li, target, missingTargets);
+ }
input += sep + *li;
sep = ";";
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
- std::string &input,
- cmTarget* target,
- std::vector<std::string> &missingTargets)
+void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
+ std::string& input, cmGeneratorTarget* target,
+ std::vector<std::string>& missingTargets)
{
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
- cmMakefile *mf = target->GetMakefile();
-
- while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos)
- {
- std::string::size_type nameStartPos = pos +
- sizeof("$<TARGET_PROPERTY:") - 1;
- std::string::size_type closePos = input.find(">", nameStartPos);
- std::string::size_type commaPos = input.find(",", nameStartPos);
+ while ((pos = input.find("$<TARGET_PROPERTY:", lastPos)) !=
+ std::string::npos) {
+ std::string::size_type nameStartPos =
+ pos + sizeof("$<TARGET_PROPERTY:") - 1;
+ std::string::size_type closePos = input.find('>', nameStartPos);
+ std::string::size_type commaPos = input.find(',', nameStartPos);
std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
- if (commaPos == input.npos // Implied 'this' target
- || closePos == input.npos // Imcomplete expression.
- || closePos < commaPos // Implied 'this' target
- || nextOpenPos < commaPos) // Non-literal
- {
+ if (commaPos == std::string::npos // Implied 'this' target
+ || closePos == std::string::npos // Imcomplete expression.
+ || closePos < commaPos // Implied 'this' target
+ || nextOpenPos < commaPos) // Non-literal
+ {
lastPos = nameStartPos;
continue;
- }
+ }
- std::string targetName = input.substr(nameStartPos,
- commaPos - nameStartPos);
+ std::string targetName =
+ input.substr(nameStartPos, commaPos - nameStartPos);
- if (this->AddTargetNamespace(targetName, target, missingTargets))
- {
+ if (this->AddTargetNamespace(targetName, target, missingTargets)) {
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
- }
- lastPos = nameStartPos + targetName.size() + 1;
}
+ lastPos = nameStartPos + targetName.size() + 1;
+ }
std::string errorString;
pos = 0;
lastPos = pos;
- while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos)
- {
+ while ((pos = input.find("$<TARGET_NAME:", lastPos)) != std::string::npos) {
std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
- std::string::size_type endPos = input.find(">", nameStartPos);
- if (endPos == input.npos)
- {
+ std::string::size_type endPos = input.find('>', nameStartPos);
+ if (endPos == std::string::npos) {
errorString = "$<TARGET_NAME:...> expression incomplete";
break;
- }
- std::string targetName = input.substr(nameStartPos,
- endPos - nameStartPos);
- if(targetName.find("$<") != input.npos)
- {
+ }
+ std::string targetName = input.substr(nameStartPos, endPos - nameStartPos);
+ if (targetName.find("$<") != std::string::npos) {
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"literal.";
break;
- }
- if (!this->AddTargetNamespace(targetName, target, missingTargets))
- {
+ }
+ if (!this->AddTargetNamespace(targetName, target, missingTargets)) {
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"reachable target.";
break;
- }
+ }
input.replace(pos, endPos - pos + 1, targetName);
lastPos = endPos;
+ }
+
+ pos = 0;
+ lastPos = pos;
+ while (errorString.empty() &&
+ (pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) {
+ std::string::size_type nameStartPos = pos + sizeof("$<LINK_ONLY:") - 1;
+ std::string::size_type endPos = input.find('>', nameStartPos);
+ if (endPos == std::string::npos) {
+ errorString = "$<LINK_ONLY:...> expression incomplete";
+ break;
}
+ std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
+ if (cmGeneratorExpression::IsValidTargetName(libName) &&
+ this->AddTargetNamespace(libName, target, missingTargets)) {
+ input.replace(nameStartPos, endPos - nameStartPos, libName);
+ }
+ lastPos = nameStartPos + libName.size() + 1;
+ }
this->ReplaceInstallPrefix(input);
- if (!errorString.empty())
- {
- mf->IssueMessage(cmake::FATAL_ERROR, errorString);
- }
+ if (!errorString.empty()) {
+ target->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, errorString);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator::ReplaceInstallPrefix(std::string &)
+void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/)
{
// Do nothing
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator
-::SetImportLinkInterface(const char* config, std::string const& suffix,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- cmTarget* target, ImportPropertyMap& properties,
- std::vector<std::string>& missingTargets)
+void cmExportFileGenerator::SetImportLinkInterface(
+ const std::string& config, std::string const& suffix,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets)
{
// Add the transitive link dependencies for this configuration.
- cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
- target);
- if (!iface)
- {
+ cmLinkInterface const* iface = target->GetLinkInterface(config, target);
+ if (!iface) {
return;
- }
+ }
- if (iface->ImplementationIsInterface)
- {
+ if (iface->ImplementationIsInterface) {
// Policy CMP0022 must not be NEW.
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);
return;
- }
+ }
- const char *propContent;
+ const char* propContent;
- if (const char *prop_suffixed = target->GetProperty(
- ("LINK_INTERFACE_LIBRARIES" + suffix).c_str()))
- {
+ if (const char* prop_suffixed =
+ target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
propContent = prop_suffixed;
- }
- else if (const char *prop = target->GetProperty(
- "LINK_INTERFACE_LIBRARIES"))
- {
+ } else if (const char* prop =
+ target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
propContent = prop;
- }
- else
- {
+ } else {
return;
- }
+ }
const bool newCMP0022Behavior =
- target->GetPolicyStatusCMP0022() != cmPolicies::WARN
- && target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
-
- if(newCMP0022Behavior && !this->ExportOld)
- {
- cmMakefile *mf = target->GetMakefile();
- cmOStringStream e;
- e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, "
+ target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+
+ if (newCMP0022Behavior && !this->ExportOld) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::ostringstream e;
+ e << "Target \"" << target->GetName()
+ << "\" has policy CMP0022 enabled, "
"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";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
+ }
- if (!*propContent)
- {
+ if (!*propContent) {
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
return;
- }
+ }
- std::string prepro = cmGeneratorExpression::Preprocess(propContent,
- preprocessRule);
- if (!prepro.empty())
- {
- this->ResolveTargetsInGeneratorExpressions(prepro, target,
- missingTargets,
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(propContent, preprocessRule);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target, missingTargets,
ReplaceFreeTargets);
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator
-::SetImportDetailProperties(const char* config, std::string const& suffix,
- cmTarget* target, ImportPropertyMap& properties,
- std::vector<std::string>& missingTargets
- )
+void cmExportFileGenerator::SetImportDetailProperties(
+ const std::string& config, std::string const& suffix,
+ cmGeneratorTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets)
{
// Get the makefile in which to lookup target information.
- cmMakefile* mf = target->GetMakefile();
+ cmMakefile* mf = target->Makefile;
// Add the soname for unix shared libraries.
- if(target->GetType() == cmTarget::SHARED_LIBRARY ||
- target->GetType() == cmTarget::MODULE_LIBRARY)
- {
- // Check whether this is a DLL platform.
- bool dll_platform =
- (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
- if(!dll_platform)
- {
+ if (target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ if (!target->IsDLLPlatform()) {
std::string prop;
std::string value;
- if(target->HasSOName(config))
- {
- if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
+ if (target->HasSOName(config)) {
+ if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
value = this->InstallNameDir(target, config);
- }
+ }
prop = "IMPORTED_SONAME";
value += target->GetSOName(config);
- }
- else
- {
+ } else {
prop = "IMPORTED_NO_SONAME";
value = "TRUE";
- }
+ }
prop += suffix;
properties[prop] = value;
- }
}
+ }
// Add the transitive link dependencies for this configuration.
- if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
- target))
- {
+ if (cmLinkInterface const* iface =
+ target->GetLinkInterface(config, target)) {
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties, missingTargets);
+ std::vector<std::string> dummy;
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
- iface->SharedDeps, properties, missingTargets);
- if(iface->Multiplicity > 0)
- {
+ iface->SharedDeps, properties, dummy);
+ if (iface->Multiplicity > 0) {
std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
prop += suffix;
- cmOStringStream m;
+ std::ostringstream m;
m << iface->Multiplicity;
properties[prop] = m.str();
- }
}
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator
-::SetImportLinkProperty(std::string const& suffix,
- cmTarget* target,
- const char* propName,
- std::vector<std::string> const& libs,
- ImportPropertyMap& properties,
- std::vector<std::string>& missingTargets
- )
+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)
{
- // Skip the property if there are no libraries.
- if(libs.empty())
- {
+ // Skip the property if there are no entries.
+ if (entries.empty()) {
return;
- }
+ }
// Construct the property value.
- std::string link_libs;
+ std::string link_entries;
const char* sep = "";
- for(std::vector<std::string>::const_iterator li = libs.begin();
- li != libs.end(); ++li)
- {
+ for (typename std::vector<T>::const_iterator li = entries.begin();
+ li != entries.end(); ++li) {
// Separate this from the previous entry.
- link_libs += sep;
+ link_entries += sep;
sep = ";";
std::string temp = *li;
this->AddTargetNamespace(temp, target, missingTargets);
- link_libs += temp;
- }
+ link_entries += temp;
+ }
// Store the property.
std::string prop = propName;
prop += suffix;
- properties[prop] = link_libs;
+ properties[prop] = link_entries;
}
+void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
+{
+ // Protect that file against use with older CMake versions.
+ /* clang-format off */
+ os << "# Generated by CMake\n\n";
+ os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
+ << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
+ << "endif()\n";
+ /* clang-format on */
+
+ // Isolate the file policy level.
+ // We use 2.6 here instead of the current version because newer
+ // versions of CMake should be able to export files imported by 2.6
+ // until the import format changes.
+ /* clang-format off */
+ os << "cmake_policy(PUSH)\n"
+ << "cmake_policy(VERSION 2.6)\n";
+ /* clang-format on */
+}
+
+void cmExportFileGenerator::GeneratePolicyFooterCode(std::ostream& os)
+{
+ os << "cmake_policy(POP)\n";
+}
-//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
- const char* config)
+ const std::string& config)
{
os << "#----------------------------------------------------------------\n"
<< "# Generated CMake target import file";
- if(config)
- {
+ if (!config.empty()) {
os << " for configuration \"" << config << "\".\n";
- }
- else
- {
+ } else {
os << ".\n";
- }
+ }
os << "#----------------------------------------------------------------\n"
<< "\n";
this->GenerateImportVersionCode(os);
}
-//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
{
os << "# Commands beyond this point should not need to know the version.\n"
<< "set(CMAKE_IMPORT_FILE_VERSION)\n";
}
-//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
{
// Store an import file format version. This will let us change the
// format later while still allowing old import files to work.
+ /* clang-format off */
os << "# Commands may need to know the format version.\n"
<< "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
<< "\n";
+ /* clang-format on */
}
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
- const std::string &expectedTargets)
+void cmExportFileGenerator::GenerateExpectedTargetsCode(
+ std::ostream& os, const std::string& expectedTargets)
{
+ /* clang-format off */
os << "# Protect against multiple inclusion, which would fail when already "
"imported targets are added once more.\n"
"set(_targetsDefined)\n"
@@ -849,6 +890,9 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
" endif()\n"
"endforeach()\n"
"if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
+ " unset(_targetsDefined)\n"
+ " unset(_targetsNotDefined)\n"
+ " unset(_expectedTargets)\n"
" set(CMAKE_IMPORT_FILE_VERSION)\n"
" cmake_policy(POP)\n"
" return()\n"
@@ -862,11 +906,10 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
"unset(_targetsNotDefined)\n"
"unset(_expectedTargets)\n"
"\n\n";
+ /* clang-format on */
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator
-::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
+void cmExportFileGenerator::GenerateImportTargetCode(
+ std::ostream& os, const cmGeneratorTarget* target)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
@@ -875,62 +918,58 @@ cmExportFileGenerator
// Create the imported target.
os << "# Create imported target " << targetName << "\n";
- switch(target->GetType())
- {
- case cmTarget::EXECUTABLE:
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
- case cmTarget::STATIC_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
os << "add_library(" << targetName << " STATIC IMPORTED)\n";
break;
- case cmTarget::SHARED_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
os << "add_library(" << targetName << " SHARED IMPORTED)\n";
break;
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
os << "add_library(" << targetName << " MODULE IMPORTED)\n";
break;
- case cmTarget::UNKNOWN_LIBRARY:
+ case cmStateEnums::UNKNOWN_LIBRARY:
os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
break;
- default: // should never happen
+ case cmStateEnums::OBJECT_LIBRARY:
+ os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
break;
- }
+ case cmStateEnums::INTERFACE_LIBRARY:
+ os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
+ break;
+ default: // should never happen
+ break;
+ }
// Mark the imported executable if it has exports.
- if(target->IsExecutableWithExports())
- {
+ if (target->IsExecutableWithExports()) {
os << "set_property(TARGET " << targetName
<< " PROPERTY ENABLE_EXPORTS 1)\n";
- }
+ }
// Mark the imported library if it is a framework.
- if(target->IsFrameworkOnApple())
- {
- os << "set_property(TARGET " << targetName
- << " PROPERTY FRAMEWORK 1)\n";
- }
+ if (target->IsFrameworkOnApple()) {
+ os << "set_property(TARGET " << targetName << " PROPERTY FRAMEWORK 1)\n";
+ }
// Mark the imported executable if it is an application bundle.
- if(target->IsAppBundleOnApple())
- {
+ if (target->IsAppBundleOnApple()) {
os << "set_property(TARGET " << targetName
<< " PROPERTY MACOSX_BUNDLE 1)\n";
- }
+ }
- if (target->IsCFBundleOnApple())
- {
- os << "set_property(TARGET " << targetName
- << " PROPERTY BUNDLE 1)\n";
- }
+ if (target->IsCFBundleOnApple()) {
+ os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n";
+ }
os << "\n";
}
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator
-::GenerateImportPropertyCode(std::ostream& os, const char* config,
- cmTarget* target,
- ImportPropertyMap const& properties)
+void cmExportFileGenerator::GenerateImportPropertyCode(
+ std::ostream& os, const std::string& config, cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
@@ -942,49 +981,46 @@ cmExportFileGenerator
<< config << "\"\n";
os << "set_property(TARGET " << targetName
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
- if(config && *config)
- {
+ if (!config.empty()) {
os << cmSystemTools::UpperCase(config);
- }
- else
- {
+ } else {
os << "NOCONFIG";
- }
+ }
os << ")\n";
os << "set_target_properties(" << targetName << " PROPERTIES\n";
- for(ImportPropertyMap::const_iterator pi = properties.begin();
- pi != properties.end(); ++pi)
- {
- os << " " << pi->first << " \"" << pi->second << "\"\n";
- }
+ for (ImportPropertyMap::const_iterator pi = properties.begin();
+ pi != properties.end(); ++pi) {
+ os << " " << pi->first << " " << cmExportFileGeneratorEscape(pi->second)
+ << "\n";
+ }
os << " )\n"
<< "\n";
}
-
-//----------------------------------------------------------------------------
-void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
- const std::vector<std::string>& missingTargets)
+void cmExportFileGenerator::GenerateMissingTargetsCheckCode(
+ std::ostream& os, const std::vector<std::string>& missingTargets)
{
- if (missingTargets.empty())
- {
+ if (missingTargets.empty()) {
+ /* clang-format off */
os << "# This file does not depend on other imported targets which have\n"
"# been exported from the same project but in a separate "
"export set.\n\n";
+ /* clang-format on */
return;
- }
+ }
+ /* clang-format off */
os << "# Make sure the targets which have been exported in some other \n"
"# export set exist.\n"
"unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
"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 (unsigned int i = 0; i < missingTargets.size(); ++i) {
+ if (emitted.insert(missingTargets[i]).second) {
+ os << "\"" << missingTargets[i] << "\" ";
}
+ }
+ /* clang-format off */
os << ")\n"
" if(NOT TARGET \"${_target}\" )\n"
" set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets \""
@@ -1008,12 +1044,10 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
"endif()\n"
"unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
"\n";
+ /* clang-format on */
}
-
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
+void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
{
// Add code which verifies at cmake time that the file which is being
// imported actually exists on disk. This should in theory always be theory
@@ -1022,6 +1056,7 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
// the non-development package, something similar happened to me without
// on SUSE with a mysql pkg-config file, which claimed everything is fine,
// but the development package was not installed.).
+ /* clang-format off */
os << "# Loop over all imported files and verify that they actually exist\n"
"foreach(target ${_IMPORT_CHECK_TARGETS} )\n"
" foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
@@ -1042,33 +1077,30 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
"endforeach()\n"
"unset(_IMPORT_CHECK_TARGETS)\n"
"\n";
+ /* clang-format on */
}
-
-//----------------------------------------------------------------------------
-void
-cmExportFileGenerator
-::GenerateImportedFileChecksCode(std::ostream& os, cmTarget* target,
- ImportPropertyMap const& properties,
- const std::set<std::string>& importedLocations)
+void cmExportFileGenerator::GenerateImportedFileChecksCode(
+ std::ostream& os, cmGeneratorTarget* target,
+ ImportPropertyMap const& properties,
+ const std::set<std::string>& importedLocations)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
targetName += target->GetExportName();
- os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
- "list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
+ 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)
- {
+ for (std::set<std::string>::const_iterator li = importedLocations.begin();
+ li != importedLocations.end(); ++li) {
ImportPropertyMap::const_iterator pi = properties.find(*li);
- if (pi != properties.end())
- {
- os << "\"" << pi->second << "\" ";
- }
+ if (pi != properties.end()) {
+ os << cmExportFileGeneratorEscape(pi->second) << " ";
}
+ }
os << ")\n\n";
}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 9628b9681..985c8f6bc 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -1,19 +1,31 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExportFileGenerator_h
#define cmExportFileGenerator_h
-#include "cmCommand.h"
+#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>
+
+class cmGeneratorTarget;
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+#define DEVEL_CMAKE_VERSION(major, minor) \
+ (CMake_VERSION_ENCODE(major, minor, 0) > \
+ CMake_VERSION_ENCODE(CMake_VERSION_MAJOR, CMake_VERSION_MINOR, 0) \
+ ? STRINGIFY(CMake_VERSION_MAJOR) "." STRINGIFY( \
+ CMake_VERSION_MINOR) "." STRINGIFY(CMake_VERSION_PATCH) \
+ : #major "." #minor ".0")
class cmTargetExport;
@@ -33,54 +45,66 @@ public:
/** Set the full path to the export file to generate. */
void SetExportFile(const char* mainFile);
+ const char* GetMainExportFileName() const;
/** Set the namespace in which to place exported target names. */
- void SetNamespace(const char* ns) { this->Namespace = ns; }
+ void SetNamespace(const std::string& ns) { this->Namespace = ns; }
+ std::string GetNamespace() const { return this->Namespace; }
void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
/** Add a configuration to be exported. */
- void AddConfiguration(const char* config);
+ void AddConfiguration(const std::string& config);
/** Actually generate the export file. Returns whether there was an
error. */
bool GenerateImportFile();
-protected:
- typedef std::map<cmStdString, cmStdString> ImportPropertyMap;
+protected:
+ typedef std::map<std::string, std::string> ImportPropertyMap;
// Generate per-configuration target information to the given output
// stream.
- void GenerateImportConfig(std::ostream& os, const char* config,
- std::vector<std::string> &missingTargets);
+ void GenerateImportConfig(std::ostream& os, const std::string& config,
+ std::vector<std::string>& missingTargets);
// Methods to implement export file code generation.
- void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
- void GenerateImportFooterCode(std::ostream& os);
+ virtual void GeneratePolicyHeaderCode(std::ostream& os);
+ virtual void GeneratePolicyFooterCode(std::ostream& os);
+ virtual void GenerateImportHeaderCode(std::ostream& os,
+ const std::string& config = "");
+ virtual void GenerateImportFooterCode(std::ostream& os);
void GenerateImportVersionCode(std::ostream& os);
- void GenerateImportTargetCode(std::ostream& os, cmTarget* target);
- void GenerateImportPropertyCode(std::ostream& os, const char* config,
- cmTarget* target,
- ImportPropertyMap const& properties);
- void GenerateImportedFileChecksCode(std::ostream& os, cmTarget* target,
- ImportPropertyMap const& properties,
- const std::set<std::string>& importedLocations);
- void GenerateImportedFileCheckLoop(std::ostream& os);
- void GenerateMissingTargetsCheckCode(std::ostream& os,
- const std::vector<std::string>& missingTargets);
-
- void GenerateExpectedTargetsCode(std::ostream& os,
- const std::string &expectedTargets);
+ virtual void GenerateImportTargetCode(std::ostream& os,
+ cmGeneratorTarget const* target);
+ virtual void GenerateImportPropertyCode(std::ostream& os,
+ const std::string& config,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties);
+ virtual void GenerateImportedFileChecksCode(
+ std::ostream& os, cmGeneratorTarget* target,
+ ImportPropertyMap const& properties,
+ const std::set<std::string>& importedLocations);
+ virtual void GenerateImportedFileCheckLoop(std::ostream& os);
+ virtual void GenerateMissingTargetsCheckCode(
+ std::ostream& os, const std::vector<std::string>& missingTargets);
+
+ virtual void GenerateExpectedTargetsCode(std::ostream& os,
+ const std::string& expectedTargets);
// Collect properties with detailed information about targets beyond
// their location on disk.
- void SetImportDetailProperties(const char* config,
- std::string const& suffix, cmTarget* target,
+ void SetImportDetailProperties(const std::string& config,
+ std::string const& suffix,
+ cmGeneratorTarget* target,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
+
+ template <typename T>
void SetImportLinkProperty(std::string const& suffix,
- cmTarget* target, const char* propName,
- std::vector<std::string> const& libs,
+ cmGeneratorTarget* target,
+ const std::string& propName,
+ std::vector<T> const& entries,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
@@ -88,56 +112,59 @@ protected:
virtual bool GenerateMainFile(std::ostream& os) = 0;
/** Each subclass knows where the target files are located. */
- virtual void GenerateImportTargetsConfig(std::ostream& os,
- const char* config,
- std::string const& suffix,
- std::vector<std::string> &missingTargets) = 0;
+ virtual void GenerateImportTargetsConfig(
+ std::ostream& os, const std::string& config, std::string const& suffix,
+ std::vector<std::string>& missingTargets) = 0;
/** Each subclass knows how to deal with a target that is missing from an
* export set. */
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmMakefile* mf,
- cmTarget* depender,
- cmTarget* dependee) = 0;
- void PopulateInterfaceProperty(const char *,
- cmTarget *target,
- cmGeneratorExpression::PreprocessContext,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets);
- bool PopulateInterfaceLinkLibrariesProperty(cmTarget *target,
+ cmGeneratorTarget* depender,
+ cmGeneratorTarget* dependee) = 0;
+ void PopulateInterfaceProperty(const std::string&, cmGeneratorTarget* target,
cmGeneratorExpression::PreprocessContext,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets);
- void PopulateInterfaceProperty(const char *propName, cmTarget *target,
- ImportPropertyMap &properties);
- void PopulateCompatibleInterfaceProperties(cmTarget *target,
- ImportPropertyMap &properties);
- void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
- const ImportPropertyMap &properties);
+ ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
+ bool PopulateInterfaceLinkLibrariesProperty(
+ cmGeneratorTarget* target, cmGeneratorExpression::PreprocessContext,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateInterfaceProperty(const std::string& propName,
+ cmGeneratorTarget* target,
+ ImportPropertyMap& properties);
+ void PopulateCompatibleInterfaceProperties(cmGeneratorTarget* target,
+ ImportPropertyMap& properties);
+ virtual void GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties);
void PopulateIncludeDirectoriesInterface(
- cmTargetExport *target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets);
-
- void SetImportLinkInterface(const char* config, std::string const& suffix,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- cmTarget* target, ImportPropertyMap& properties,
- std::vector<std::string>& missingTargets);
-
- enum FreeTargetsReplace {
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateSourcesInterface(
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+
+ void SetImportLinkInterface(
+ const std::string& config, std::string const& suffix,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
+
+ enum FreeTargetsReplace
+ {
ReplaceFreeTargets,
NoReplaceFreeTargets
};
- void ResolveTargetsInGeneratorExpressions(std::string &input,
- cmTarget* target,
- std::vector<std::string> &missingTargets,
- FreeTargetsReplace replace = NoReplaceFreeTargets);
+ void ResolveTargetsInGeneratorExpressions(
+ std::string& input, cmGeneratorTarget* target,
+ std::vector<std::string>& missingTargets,
+ FreeTargetsReplace replace = NoReplaceFreeTargets);
- void GenerateRequiredCMakeVersion(std::ostream& os,
- const char *versionString);
+ virtual void GenerateRequiredCMakeVersion(std::ostream& os,
+ const char* versionString);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
@@ -155,25 +182,25 @@ protected:
bool AppendMode;
// The set of targets included in the export.
- std::set<cmTarget*> ExportedTargets;
+ std::set<cmGeneratorTarget*> ExportedTargets;
private:
- void PopulateInterfaceProperty(const char *, const char *,
- cmTarget *target,
+ void PopulateInterfaceProperty(const std::string&, const std::string&,
+ cmGeneratorTarget* target,
cmGeneratorExpression::PreprocessContext,
- ImportPropertyMap &properties,
- std::vector<std::string> &missingTargets);
+ ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
- bool AddTargetNamespace(std::string &input, cmTarget* target,
- std::vector<std::string> &missingTargets);
+ bool AddTargetNamespace(std::string& input, cmGeneratorTarget* target,
+ std::vector<std::string>& missingTargets);
- void ResolveTargetsInGeneratorExpression(std::string &input,
- cmTarget* target,
- std::vector<std::string> &missingTargets);
+ void ResolveTargetsInGeneratorExpression(
+ std::string& input, cmGeneratorTarget* target,
+ std::vector<std::string>& missingTargets);
- virtual void ReplaceInstallPrefix(std::string &input);
+ virtual void ReplaceInstallPrefix(std::string& input);
- virtual std::string InstallNameDir(cmTarget* target,
+ virtual std::string InstallNameDir(cmGeneratorTarget* target,
const std::string& config) = 0;
};
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
new file mode 100644
index 000000000..9a1c647d3
--- /dev/null
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -0,0 +1,138 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExportInstallAndroidMKGenerator.h"
+
+#include <ostream>
+#include <stddef.h>
+
+#include "cmExportBuildAndroidMKGenerator.h"
+#include "cmExportSet.h"
+#include "cmGeneratorTarget.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetExport.h"
+
+cmExportInstallAndroidMKGenerator::cmExportInstallAndroidMKGenerator(
+ cmInstallExportGenerator* iegen)
+ : cmExportInstallFileGenerator(iegen)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
+ std::ostream& os, const std::string&)
+{
+ std::string installDir = this->IEGen->GetDestination();
+ os << "LOCAL_PATH := $(call my-dir)\n";
+ size_t numDotDot = cmSystemTools::CountChar(installDir.c_str(), '/');
+ numDotDot += installDir.empty() ? 0 : 1;
+ std::string path;
+ for (size_t n = 0; n < numDotDot; n++) {
+ path += "/..";
+ }
+ 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) {
+ // Collect import properties for this target.
+ cmTargetExport const* te = *tei;
+ if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+ std::string dest;
+ if (te->LibraryGenerator) {
+ dest = te->LibraryGenerator->GetDestination("");
+ }
+ if (te->ArchiveGenerator) {
+ dest = te->ArchiveGenerator->GetDestination("");
+ }
+ te->Target->Target->SetProperty("__dest", dest.c_str());
+ }
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
+ std::ostream& os, const cmGeneratorTarget* target)
+{
+ std::string targetName = this->Namespace;
+ targetName += target->GetExportName();
+ os << "include $(CLEAR_VARS)\n";
+ os << "LOCAL_MODULE := ";
+ os << targetName << "\n";
+ os << "LOCAL_SRC_FILES := $(_IMPORT_PREFIX)/";
+ os << target->Target->GetProperty("__dest") << "/";
+ std::string config;
+ if (!this->Configurations.empty()) {
+ config = this->Configurations[0];
+ }
+ os << target->GetFullName(config) << "\n";
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateExpectedTargetsCode(
+ std::ostream&, const std::string&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode(
+ std::ostream&, const std::string&, cmGeneratorTarget const*,
+ ImportPropertyMap const&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateMissingTargetsCheckCode(
+ std::ostream&, const std::vector<std::string>&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties)
+{
+ std::string config;
+ if (!this->Configurations.empty()) {
+ config = this->Configurations[0];
+ }
+ cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ target, os, properties, cmExportBuildAndroidMKGenerator::INSTALL, config);
+}
+
+void cmExportInstallAndroidMKGenerator::LoadConfigFiles(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportPrefix(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateRequiredCMakeVersion(
+ std::ostream&, const char*)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::CleanupTemporaryVariables(
+ std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportedFileCheckLoop(
+ std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportedFileChecksCode(
+ std::ostream&, cmGeneratorTarget*, ImportPropertyMap const&,
+ const std::set<std::string>&)
+{
+}
+
+bool cmExportInstallAndroidMKGenerator::GenerateImportFileConfig(
+ const std::string&, std::vector<std::string>&)
+{
+ return true;
+}
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
new file mode 100644
index 000000000..ebef78365
--- /dev/null
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -0,0 +1,72 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmExportInstallAndroidMKGenerator_h
+#define cmExportInstallAndroidMKGenerator_h
+
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cmExportFileGenerator.h"
+#include "cmExportInstallFileGenerator.h"
+
+class cmGeneratorTarget;
+class cmInstallExportGenerator;
+
+/** \class cmExportInstallAndroidMKGenerator
+ * \brief Generate a file exporting targets from an install tree.
+ *
+ * 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
+ * libraries to the ndk build system.
+ *
+ * This is used to implement the INSTALL(EXPORT_ANDROID_MK) command.
+ */
+class cmExportInstallAndroidMKGenerator : public cmExportInstallFileGenerator
+{
+public:
+ /** Construct with the export installer that will install the
+ files. */
+ cmExportInstallAndroidMKGenerator(cmInstallExportGenerator* iegen);
+
+protected:
+ // Implement virtual methods from the superclass.
+ void GeneratePolicyHeaderCode(std::ostream&) CM_OVERRIDE {}
+ void GeneratePolicyFooterCode(std::ostream&) CM_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;
+ 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;
+ void GenerateMissingTargetsCheckCode(
+ std::ostream& os,
+ const std::vector<std::string>& missingTargets) CM_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;
+ void GenerateRequiredCMakeVersion(std::ostream& os,
+ const char* versionString) CM_OVERRIDE;
+ void CleanupTemporaryVariables(std::ostream&) CM_OVERRIDE;
+ void GenerateImportedFileCheckLoop(std::ostream& os) CM_OVERRIDE;
+ void GenerateImportedFileChecksCode(
+ std::ostream& os, cmGeneratorTarget* target,
+ ImportPropertyMap const& properties,
+ const std::set<std::string>& importedLocations) CM_OVERRIDE;
+ bool GenerateImportFileConfig(const std::string& config,
+ std::vector<std::string>&) CM_OVERRIDE;
+};
+
+#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index c8b4a7985..664a34276 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -1,33 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallFileGenerator.h"
+#include "cmAlgorithms.h"
#include "cmExportSet.h"
#include "cmExportSetMap.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmTargetExport.h"
-//----------------------------------------------------------------------------
-cmExportInstallFileGenerator
-::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
- IEGen(iegen)
+#include <sstream>
+#include <utility>
+
+cmExportInstallFileGenerator::cmExportInstallFileGenerator(
+ cmInstallExportGenerator* iegen)
+ : IEGen(iegen)
{
}
-//----------------------------------------------------------------------------
std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
{
std::string glob = this->FileBase;
@@ -36,57 +36,171 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
return glob;
}
-//----------------------------------------------------------------------------
bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
std::vector<cmTargetExport*> allTargets;
{
- 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();
- sep = " ";
- cmTargetExport * te = *tei;
- if(this->ExportedTargets.insert(te->Target).second)
- {
- allTargets.push_back(te);
+ 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();
+ sep = " ";
+ cmTargetExport* te = *tei;
+ if (this->ExportedTargets.insert(te->Target).second) {
+ allTargets.push_back(te);
+ } 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());
+ return false;
}
- else
- {
- cmOStringStream 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());
- return false;
+ }
+
+ this->GenerateExpectedTargetsCode(os, expectedTargets);
+ }
+
+ // Compute the relative import prefix for the file
+ this->GenerateImportPrefix(os);
+
+ std::vector<std::string> missingTargets;
+
+ bool require2_8_12 = false;
+ bool require3_0_0 = false;
+ 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;
+
+ requiresConfigFiles =
+ requiresConfigFiles || gt->GetType() != cmStateEnums::INTERFACE_LIBRARY;
+
+ this->GenerateImportTargetCode(os, gt);
+
+ ImportPropertyMap properties;
+
+ this->PopulateIncludeDirectoriesInterface(
+ *tei, cmGeneratorExpression::InstallInterface, properties,
+ missingTargets);
+ this->PopulateSourcesInterface(*tei,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", 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);
+
+ const bool newCMP0022Behavior =
+ gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (newCMP0022Behavior) {
+ if (this->PopulateInterfaceLinkLibrariesProperty(
+ gt, cmGeneratorExpression::InstallInterface, properties,
+ missingTargets) &&
+ !this->ExportOld) {
+ require2_8_12 = true;
}
}
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ require3_0_0 = true;
+ }
+ if (gt->GetProperty("INTERFACE_SOURCES")) {
+ // We can only generate INTERFACE_SOURCES in CMake 3.3, but CMake 3.1
+ // can consume them.
+ require3_1_0 = true;
+ }
+
+ this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gt,
+ properties);
+
+ this->PopulateCompatibleInterfaceProperties(gt, properties);
+
+ this->GenerateInterfaceProperties(gt, os, properties);
+ }
+
+ if (require3_1_0) {
+ this->GenerateRequiredCMakeVersion(os, "3.1.0");
+ } else if (require3_0_0) {
+ this->GenerateRequiredCMakeVersion(os, "3.0.0");
+ } else if (require2_8_12) {
+ this->GenerateRequiredCMakeVersion(os, "2.8.12");
+ }
+
+ this->LoadConfigFiles(os);
+
+ this->CleanupTemporaryVariables(os);
+ this->GenerateImportedFileCheckLoop(os);
- this->GenerateExpectedTargetsCode(os, expectedTargets);
+ bool result = true;
+ // 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)) {
+ result = false;
+ }
+ }
}
- // Add code to compute the installation prefix relative to the
- // import file location.
- const char* installDest = this->IEGen->GetDestination();
- if(!cmSystemTools::FileIsFullPath(installDest))
- {
- std::string installPrefix =
- this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
- std::string absDest = installPrefix + "/" + installDest;
+ this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
+ return result;
+}
+
+void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os)
+{
+ // Set an _IMPORT_PREFIX variable for import location properties
+ // to reference if they are relative to the install prefix.
+ std::string installPrefix =
+ this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
+ "CMAKE_INSTALL_PREFIX");
+ std::string const& expDest = this->IEGen->GetDestination();
+ if (cmSystemTools::FileIsFullPath(expDest)) {
+ // The export file is being installed to an absolute path so the
+ // package is not relocatable. Use the configured install prefix.
+ /* clang-format off */
+ os <<
+ "# The installation prefix configured by this project.\n"
+ "set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
+ "\n";
+ /* clang-format on */
+ } else {
+ // Add code to compute the installation prefix relative to the
+ // import file location.
+ std::string absDest = installPrefix + "/" + expDest;
std::string absDestS = absDest + "/";
os << "# Compute the installation prefix relative to this file.\n"
<< "get_filename_component(_IMPORT_PREFIX"
<< " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
- if(strncmp(absDestS.c_str(), "/lib/", 5) == 0 ||
- strncmp(absDestS.c_str(), "/lib64/", 7) == 0 ||
- strncmp(absDestS.c_str(), "/usr/lib/", 9) == 0 ||
- strncmp(absDestS.c_str(), "/usr/lib64/", 11) == 0)
- {
+ 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/")) {
// Handle "/usr move" symlinks created by some Linux distros.
+ /* clang-format off */
os <<
"# Use original install prefix when loaded through a\n"
"# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
@@ -97,75 +211,34 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
"endif()\n"
"unset(_realOrig)\n"
"unset(_realCurr)\n";
- }
- std::string dest = installDest;
- while(!dest.empty())
- {
- os <<
- "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
- dest = cmSystemTools::GetFilenamePath(dest);
- }
- os << "\n";
-
- // Import location properties may reference this variable.
- this->ImportPrefix = "${_IMPORT_PREFIX}/";
+ /* clang-format on */
}
-
- std::vector<std::string> missingTargets;
-
- bool require2_8_12 = false;
- // Create all the imported targets.
- for(std::vector<cmTargetExport*>::const_iterator
- tei = allTargets.begin();
- tei != allTargets.end(); ++tei)
- {
- cmTarget* te = (*tei)->Target;
- this->GenerateImportTargetCode(os, te);
-
- ImportPropertyMap properties;
-
- this->PopulateIncludeDirectoriesInterface(*tei,
- cmGeneratorExpression::InstallInterface,
- properties, missingTargets);
- this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
- te,
- cmGeneratorExpression::InstallInterface,
- properties, missingTargets);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
- te,
- cmGeneratorExpression::InstallInterface,
- properties, missingTargets);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS",
- te,
- cmGeneratorExpression::InstallInterface,
- properties, missingTargets);
-
- const bool newCMP0022Behavior =
- te->GetPolicyStatusCMP0022() != cmPolicies::WARN
- && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
- if (newCMP0022Behavior)
- {
- if (this->PopulateInterfaceLinkLibrariesProperty(te,
- cmGeneratorExpression::InstallInterface,
- properties, missingTargets)
- && !this->ExportOld)
- {
- require2_8_12 = true;
- }
- }
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
- te, properties);
- this->PopulateCompatibleInterfaceProperties(te, properties);
-
- this->GenerateInterfaceProperties(te, os, properties);
+ std::string dest = expDest;
+ while (!dest.empty()) {
+ os << "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" "
+ "PATH)\n";
+ dest = cmSystemTools::GetFilenamePath(dest);
}
+ os << "if(_IMPORT_PREFIX STREQUAL \"/\")\n"
+ << " set(_IMPORT_PREFIX \"\")\n"
+ << "endif()\n"
+ << "\n";
+ }
+}
- if (require2_8_12)
- {
- this->GenerateRequiredCMakeVersion(os, "2.8.12");
- }
+void cmExportInstallFileGenerator::CleanupTemporaryVariables(std::ostream& os)
+{
+ /* clang-format off */
+ os << "# Cleanup temporary variables.\n"
+ << "set(_IMPORT_PREFIX)\n"
+ << "\n";
+ /* clang-format on */
+}
+void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os)
+{
// Now load per-configuration properties for them.
+ /* clang-format off */
os << "# Load information for each installed configuration.\n"
<< "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
<< "file(GLOB CONFIG_FILES \"${_DIR}/"
@@ -174,85 +247,51 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
<< " include(${f})\n"
<< "endforeach()\n"
<< "\n";
-
- // Cleanup the import prefix variable.
- if(!this->ImportPrefix.empty())
- {
- os << "# Cleanup temporary variables.\n"
- << "set(_IMPORT_PREFIX)\n"
- << "\n";
- }
- this->GenerateImportedFileCheckLoop(os);
-
- // Generate an import file for each configuration.
- bool result = true;
- for(std::vector<std::string>::const_iterator
- ci = this->Configurations.begin();
- ci != this->Configurations.end(); ++ci)
- {
- if(!this->GenerateImportFileConfig(ci->c_str(), missingTargets))
- {
- result = false;
- }
- }
-
- this->GenerateMissingTargetsCheckCode(os, missingTargets);
-
- return result;
+ /* clang-format on */
}
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string &input)
+void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input)
{
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
- while((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != input.npos)
- {
+ while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) !=
+ std::string::npos) {
std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1;
input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}");
lastPos = endPos;
- }
+ }
}
-//----------------------------------------------------------------------------
-bool
-cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config,
- std::vector<std::string> &missingTargets)
+bool cmExportInstallFileGenerator::GenerateImportFileConfig(
+ const std::string& config, std::vector<std::string>& missingTargets)
{
// Skip configurations not enabled for this export.
- if(!this->IEGen->InstallsForConfig(config))
- {
+ if (!this->IEGen->InstallsForConfig(config)) {
return true;
- }
+ }
// Construct the name of the file to generate.
std::string fileName = this->FileDir;
fileName += "/";
fileName += this->FileBase;
fileName += "-";
- if(config && *config)
- {
+ if (!config.empty()) {
fileName += cmSystemTools::LowerCase(config);
- }
- else
- {
+ } else {
fileName += "noconfig";
- }
+ }
fileName += this->FileExt;
// Open the output file to generate it.
cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
- if(!exportFileStream)
- {
+ if (!exportFileStream) {
std::string se = cmSystemTools::GetLastSystemError();
- cmOStringStream e;
- e << "cannot write to file \"" << fileName.c_str()
- << "\": " << se;
+ std::ostringstream e;
+ e << "cannot write to file \"" << fileName << "\": " << se;
cmSystemTools::Error(e.str().c_str());
return false;
- }
+ }
std::ostream& os = exportFileStream;
// Start with the import file header.
@@ -270,29 +309,31 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config,
return true;
}
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator
-::GenerateImportTargetsConfig(std::ostream& os,
- const char* config, std::string const& suffix,
- std::vector<std::string> &missingTargets)
+void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
+ std::ostream& os, const std::string& config, std::string const& suffix,
+ 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::vector<cmTargetExport*>::const_iterator tei =
+ this->IEGen->GetExportSet()->GetTargetExports()->begin();
+ tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) {
// Collect import properties for this target.
cmTargetExport const* te = *tei;
+ if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+
ImportPropertyMap properties;
std::set<std::string> importedLocations;
+
this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
properties, importedLocations);
- this->SetImportLocationProperty(config, suffix,
- te->RuntimeGenerator, properties,
- importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator,
+ properties, importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator,
+ properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
@@ -300,15 +341,15 @@ cmExportInstallFileGenerator
// If any file location was set for the target add it to the
// import file.
- if(!properties.empty())
- {
+ if (!properties.empty()) {
// Get the rest of the target details.
- this->SetImportDetailProperties(config, suffix,
- te->Target, properties, missingTargets);
+ cmGeneratorTarget* gtgt = te->Target;
+ this->SetImportDetailProperties(config, suffix, gtgt, properties,
+ missingTargets);
this->SetImportLinkInterface(config, suffix,
cmGeneratorExpression::InstallInterface,
- te->Target, properties, missingTargets);
+ gtgt, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
@@ -317,48 +358,37 @@ cmExportInstallFileGenerator
// properties);
// Generate code in the export file.
- this->GenerateImportPropertyCode(os, config, te->Target, properties);
- this->GenerateImportedFileChecksCode(os, te->Target, properties,
+ this->GenerateImportPropertyCode(os, config, gtgt, properties);
+ this->GenerateImportedFileChecksCode(os, gtgt, properties,
importedLocations);
- }
}
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator
-::SetImportLocationProperty(const char* config, std::string const& suffix,
- cmInstallTargetGenerator* itgen,
- ImportPropertyMap& properties,
- std::set<std::string>& importedLocations
- )
+void cmExportInstallFileGenerator::SetImportLocationProperty(
+ const std::string& config, std::string const& suffix,
+ cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
+ std::set<std::string>& importedLocations)
{
// Skip rules that do not match this configuration.
- if(!(itgen && itgen->InstallsForConfig(config)))
- {
+ if (!(itgen && itgen->InstallsForConfig(config))) {
return;
- }
+ }
// Get the target to be installed.
- cmTarget* target = itgen->GetTarget();
+ cmGeneratorTarget* target = itgen->GetTarget();
// Construct the installed location of the target.
- std::string dest = itgen->GetDestination();
+ std::string dest = itgen->GetDestination(config);
std::string value;
- if(!cmSystemTools::FileIsFullPath(dest.c_str()))
- {
+ if (!cmSystemTools::FileIsFullPath(dest.c_str())) {
// The target is installed relative to the installation prefix.
- if(this->ImportPrefix.empty())
- {
- this->ComplainAboutImportPrefix(itgen);
- }
- value = this->ImportPrefix;
- }
+ value = "${_IMPORT_PREFIX}/";
+ }
value += dest;
value += "/";
- if(itgen->IsImportLibrary())
- {
+ if (itgen->IsImportLibrary()) {
// Construct the property name.
std::string prop = "IMPORTED_IMPLIB";
prop += suffix;
@@ -370,153 +400,123 @@ cmExportInstallFileGenerator
// 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;
+
+ // 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;
}
- else
- {
+
+ // Store the property.
+ properties[prop] = cmJoin(objects, ";");
+ importedLocations.insert(prop);
+ } else {
// Construct the property name.
std::string prop = "IMPORTED_LOCATION";
prop += suffix;
// Append the installed file name.
- if(target->IsAppBundleOnApple())
- {
+ if (target->IsAppBundleOnApple()) {
value += itgen->GetInstallFilename(target, config);
value += ".app/Contents/MacOS/";
value += itgen->GetInstallFilename(target, config);
- }
- else
- {
+ } else {
value += itgen->GetInstallFilename(target, config,
cmInstallTargetGenerator::NameReal);
- }
+ }
// Store the property.
properties[prop] = value;
importedLocations.insert(prop);
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator::HandleMissingTarget(
+void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
- cmMakefile* mf, cmTarget* depender, cmTarget* dependee)
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
{
const std::string name = dependee->GetName();
- std::vector<std::string> namespaces = this->FindNamespaces(mf, name);
+ cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
+ std::vector<std::string> namespaces = this->FindNamespaces(gg, name);
int targetOccurrences = (int)namespaces.size();
- if (targetOccurrences == 1)
- {
+ if (targetOccurrences == 1) {
std::string missingTarget = namespaces[0];
missingTarget += dependee->GetExportName();
link_libs += missingTarget;
missingTargets.push_back(missingTarget);
- }
- else
- {
- // We are not appending, so all exported targets should be
- // known here. This is probably user-error.
+ } else {
+ // All exported targets should be known here and should be unique.
+ // This is probably user-error.
this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
- }
+ }
}
-//----------------------------------------------------------------------------
-std::vector<std::string>
-cmExportInstallFileGenerator
-::FindNamespaces(cmMakefile* mf, const std::string& name)
+std::vector<std::string> cmExportInstallFileGenerator::FindNamespaces(
+ cmGlobalGenerator* gg, const std::string& name)
{
std::vector<std::string> namespaces;
- cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator();
const cmExportSetMap& exportSets = gg->GetExportSets();
- for(cmExportSetMap::const_iterator expIt = exportSets.begin();
- expIt != exportSets.end();
- ++expIt)
- {
+ for (cmExportSetMap::const_iterator expIt = exportSets.begin();
+ expIt != exportSets.end(); ++expIt) {
const cmExportSet* exportSet = expIt->second;
std::vector<cmTargetExport*> const* targets =
- exportSet->GetTargetExports();
+ exportSet->GetTargetExports();
bool containsTarget = false;
- for(unsigned int i=0; i<targets->size(); i++)
- {
- if (name == (*targets)[i]->Target->GetName())
- {
+ for (unsigned int i = 0; i < targets->size(); i++) {
+ if (name == (*targets)[i]->TargetName) {
containsTarget = true;
break;
- }
}
+ }
- if (containsTarget)
- {
+ if (containsTarget) {
std::vector<cmInstallExportGenerator const*> const* installs =
- exportSet->GetInstallations();
- for(unsigned int i=0; i<installs->size(); i++)
- {
+ exportSet->GetInstallations();
+ for (unsigned int i = 0; i < installs->size(); i++) {
namespaces.push_back((*installs)[i]->GetNamespace());
- }
}
}
+ }
return namespaces;
}
-
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator
-::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
+void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences)
{
- const char* installDest = this->IEGen->GetDestination();
- cmOStringStream e;
- e << "install(EXPORT \""
- << this->IEGen->GetExportSet()->GetName()
- << "\") given absolute "
- << "DESTINATION \"" << installDest << "\" but the export "
- << "references an installation of target \""
- << itgen->GetTarget()->GetName() << "\" which has relative "
- << "DESTINATION \"" << itgen->GetDestination() << "\".";
- cmSystemTools::Error(e.str().c_str());
-}
-
-//----------------------------------------------------------------------------
-void
-cmExportInstallFileGenerator
-::ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee,
- int occurrences)
-{
- cmOStringStream e;
- e << "install(EXPORT \""
- << this->IEGen->GetExportSet()->GetName()
+ std::ostringstream e;
+ e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName() << "\" ";
- if (occurrences == 0)
- {
+ if (occurrences == 0) {
e << "that is not in the export set.";
- }
- else
- {
+ } else {
e << "that is not in this export set, but " << occurrences
- << " times in others.";
- }
+ << " times in others.";
+ }
cmSystemTools::Error(e.str().c_str());
}
-std::string
-cmExportInstallFileGenerator::InstallNameDir(cmTarget* target,
- const std::string&)
+std::string cmExportInstallFileGenerator::InstallNameDir(
+ cmGeneratorTarget* target, const std::string& /*config*/)
{
std::string install_name_dir;
- cmMakefile* mf = target->GetMakefile();
- if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
- install_name_dir =
- target->GetInstallNameDirForInstallTree();
- }
+ cmMakefile* mf = target->Target->GetMakefile();
+ if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+ install_name_dir = target->GetInstallNameDirForInstallTree();
+ }
return install_name_dir;
}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 7c634a4d8..8fa9b7f88 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -1,19 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExportInstallFileGenerator_h
#define cmExportInstallFileGenerator_h
+#include "cmConfigure.h"
+
#include "cmExportFileGenerator.h"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+class cmGlobalGenerator;
class cmInstallExportGenerator;
class cmInstallTargetGenerator;
@@ -31,7 +32,7 @@ class cmInstallTargetGenerator;
*
* This is used to implement the INSTALL(EXPORT) command.
*/
-class cmExportInstallFileGenerator: public cmExportFileGenerator
+class cmExportInstallFileGenerator : public cmExportFileGenerator
{
public:
/** Construct with the export installer that will install the
@@ -41,58 +42,61 @@ public:
/** Get the per-config file generated for each configuraiton. This
maps from the configuration name to the file temporary location
for installation. */
- std::map<cmStdString, cmStdString> const& GetConfigImportFiles()
- { return this->ConfigImportFiles; }
+ std::map<std::string, std::string> const& GetConfigImportFiles()
+ {
+ return this->ConfigImportFiles;
+ }
/** Compute the globbing expression used to load per-config import
files from the main file. */
std::string GetConfigImportFileGlob();
-protected:
+protected:
// Implement virtual methods from the superclass.
- virtual bool GenerateMainFile(std::ostream& os);
- virtual void GenerateImportTargetsConfig(std::ostream& os,
- const char* config,
- std::string const& suffix,
- std::vector<std::string> &missingTargets);
- virtual void HandleMissingTarget(std::string& link_libs,
- std::vector<std::string>& missingTargets,
- cmMakefile* mf,
- cmTarget* depender,
- cmTarget* dependee);
-
- virtual void ReplaceInstallPrefix(std::string &input);
-
- void ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee,
+ bool GenerateMainFile(std::ostream& os) CM_OVERRIDE;
+ void GenerateImportTargetsConfig(
+ std::ostream& os, const std::string& config, std::string const& suffix,
+ std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ void HandleMissingTarget(std::string& link_libs,
+ std::vector<std::string>& missingTargets,
+ cmGeneratorTarget* depender,
+ cmGeneratorTarget* dependee) CM_OVERRIDE;
+
+ void ReplaceInstallPrefix(std::string& input) CM_OVERRIDE;
+
+ void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
+ cmGeneratorTarget* dependee,
int occurrences);
- std::vector<std::string> FindNamespaces(cmMakefile* mf,
+ std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg,
const std::string& name);
+ /** Generate the relative import prefix. */
+ virtual void GenerateImportPrefix(std::ostream&);
+
+ /** Generate the relative import prefix. */
+ virtual void LoadConfigFiles(std::ostream&);
+
+ virtual void CleanupTemporaryVariables(std::ostream&);
/** Generate a per-configuration file for the targets. */
- bool GenerateImportFileConfig(const char* config,
- std::vector<std::string> &missingTargets);
+ virtual bool GenerateImportFileConfig(
+ const std::string& config, std::vector<std::string>& missingTargets);
/** Fill in properties indicating installed file locations. */
- void SetImportLocationProperty(const char* config,
+ void SetImportLocationProperty(const std::string& config,
std::string const& suffix,
cmInstallTargetGenerator* itgen,
ImportPropertyMap& properties,
- std::set<std::string>& importedLocations
- );
+ std::set<std::string>& importedLocations);
- void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
-
- std::string InstallNameDir(cmTarget* target, const std::string& config);
+ std::string InstallNameDir(cmGeneratorTarget* target,
+ const std::string& config) CM_OVERRIDE;
cmInstallExportGenerator* IEGen;
- std::string ImportPrefix;
-
// The import file generated for each configuration.
- std::map<cmStdString, cmStdString> ConfigImportFiles;
+ std::map<std::string, std::string> ConfigImportFiles;
};
#endif
diff --git a/Source/cmExportLibraryDependencies.cxx b/Source/cmExportLibraryDependencies.cxx
deleted file mode 100644
index f07b783d6..000000000
--- a/Source/cmExportLibraryDependencies.cxx
+++ /dev/null
@@ -1,204 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmExportLibraryDependencies.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmGeneratedFileStream.h"
-#include "cmake.h"
-#include "cmVersion.h"
-
-#include <cmsys/auto_ptr.hxx>
-
-bool cmExportLibraryDependenciesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
-{
- if(args.size() < 1 )
- {
- 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
-{
- // Use copy-if-different if not appending.
- cmsys::auto_ptr<std::ofstream> foutPtr;
- if(this->Append)
- {
- cmsys::auto_ptr<std::ofstream> ap(
- new std::ofstream(this->Filename.c_str(), std::ios::app));
- foutPtr = ap;
- }
- else
- {
- cmsys::auto_ptr<cmGeneratedFileStream> ap(
- new cmGeneratedFileStream(this->Filename.c_str(), true));
- ap->SetCopyIfDifferent(true);
- foutPtr = ap;
- }
- std::ostream& fout = *foutPtr.get();
-
- if (!fout)
- {
- cmSystemTools::Error("Error Writing ", this->Filename.c_str());
- cmSystemTools::ReportLastSystemError("");
- return;
- }
-
- // Collect dependency information about all library targets built in
- // the project.
- cmake* cm = this->Makefile->GetCMakeInstance();
- cmGlobalGenerator* global = cm->GetGlobalGenerator();
- const std::vector<cmLocalGenerator *>& locals = global->GetLocalGenerators();
- std::map<cmStdString, cmStdString> libDepsOld;
- std::map<cmStdString, cmStdString> libDepsNew;
- std::map<cmStdString, cmStdString> libTypes;
- for(std::vector<cmLocalGenerator *>::const_iterator i = locals.begin();
- i != locals.end(); ++i)
- {
- const cmLocalGenerator* gen = *i;
- const cmTargets &tgts = gen->GetMakefile()->GetTargets();
- for(cmTargets::const_iterator l = tgts.begin();
- l != tgts.end(); ++l)
- {
- // Get the current target.
- cmTarget const& target = l->second;
-
- // Skip non-library targets.
- if(target.GetType() < cmTarget::STATIC_LIBRARY
- || target.GetType() > cmTarget::MODULE_LIBRARY)
- {
- continue;
- }
-
- // Construct the dependency variable name.
- std::string targetEntry = target.GetName();
- targetEntry += "_LIB_DEPENDS";
-
- // Construct the dependency variable value. It is safe to use
- // the target GetLinkLibraries method here because this code is
- // called at the end of configure but before generate so library
- // dependencies have yet to be analyzed. Therefore the value
- // will be the direct link dependencies.
- std::string valueOld;
- std::string valueNew;
- cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
- for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
- li != libs.end(); ++li)
- {
- std::string ltVar = li->first;
- ltVar += "_LINK_TYPE";
- std::string ltValue;
- switch(li->second)
- {
- case cmTarget::GENERAL:
- valueNew += "general;";
- ltValue = "general";
- break;
- case cmTarget::DEBUG:
- valueNew += "debug;";
- ltValue = "debug";
- break;
- case cmTarget::OPTIMIZED:
- valueNew += "optimized;";
- ltValue = "optimized";
- break;
- }
- std::string lib = li->first;
- if(cmTarget* libtgt = global->FindTarget(0, lib.c_str()))
- {
- // Handle simple output name changes. This command is
- // deprecated so we do not support full target name
- // translation (which requires per-configuration info).
- if(const char* outname = libtgt->GetProperty("OUTPUT_NAME"))
- {
- lib = outname;
- }
- }
- valueOld += lib;
- valueOld += ";";
- valueNew += lib;
- valueNew += ";";
-
- std::string& ltEntry = libTypes[ltVar];
- if(ltEntry.empty())
- {
- ltEntry = ltValue;
- }
- else if(ltEntry != ltValue)
- {
- ltEntry = "general";
- }
- }
- libDepsNew[targetEntry] = valueNew;
- libDepsOld[targetEntry] = valueOld;
- }
- }
-
- // Generate dependency information for both old and new style CMake
- // versions.
- const char* vertest =
- "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
- fout << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
- fout << "IF(" << vertest << ")\n";
- fout << " # Information for CMake 2.6 and above.\n";
- for(std::map<cmStdString, cmStdString>::const_iterator
- i = libDepsNew.begin();
- i != libDepsNew.end(); ++i)
- {
- if(!i->second.empty())
- {
- fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
- }
- }
- fout << "ELSE(" << vertest << ")\n";
- fout << " # Information for CMake 2.4 and lower.\n";
- for(std::map<cmStdString, cmStdString>::const_iterator
- i = libDepsOld.begin();
- i != libDepsOld.end(); ++i)
- {
- if(!i->second.empty())
- {
- fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
- }
- }
- for(std::map<cmStdString, cmStdString>::const_iterator i = libTypes.begin();
- i != libTypes.end(); ++i)
- {
- if(i->second != "general")
- {
- fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
- }
- }
- fout << "ENDIF(" << vertest << ")\n";
- return;
-}
diff --git a/Source/cmExportLibraryDependencies.h b/Source/cmExportLibraryDependencies.h
deleted file mode 100644
index d8b65ccf1..000000000
--- a/Source/cmExportLibraryDependencies.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmExportLibraryDependenciesCommand_h
-#define cmExportLibraryDependenciesCommand_h
-
-#include "cmCommand.h"
-
-/** \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 cmExportLibraryDependenciesCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmExportLibraryDependenciesCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This is called at the end after all the information
- * specified by the command is accumulated.
- */
- virtual void FinalPass();
- virtual bool HasFinalPass() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "export_library_dependencies";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use INSTALL(EXPORT) or EXPORT command.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "This command generates an old-style library dependencies file. "
- "Projects requiring CMake 2.6 or later should not use the command. "
- "Use instead the install(EXPORT) command to help export targets "
- "from an installation tree and the export() command to export targets "
- "from a build tree.\n"
- "The old-style library dependencies file does not take into account "
- "per-configuration names of libraries or the LINK_INTERFACE_LIBRARIES "
- "target property.\n"
- " export_library_dependencies(<file> [APPEND])\n"
- "Create a file named <file> that can be included into a CMake listfile "
- "with the INCLUDE command. The file will contain a number of SET "
- "commands that will set all the variables needed for library dependency "
- "information. This should be the last command in the top level "
- "CMakeLists.txt file of the project. If the APPEND option is "
- "specified, the SET commands will be appended to the given file "
- "instead of replacing it.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmExportLibraryDependenciesCommand, cmCommand);
-
-private:
- std::string Filename;
- bool Append;
- void ConstFinalPass() const;
-};
-
-
-#endif
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
new file mode 100644
index 000000000..69150aee4
--- /dev/null
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -0,0 +1,176 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExportLibraryDependenciesCommand.h"
+
+#include "cmsys/FStream.hxx"
+#include <map>
+#include <utility>
+
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.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
+{
+ // 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;
+ } else {
+ CM_AUTO_PTR<cmGeneratedFileStream> ap(
+ new cmGeneratedFileStream(this->Filename.c_str(), true));
+ ap->SetCopyIfDifferent(true);
+ foutPtr = ap;
+ }
+ std::ostream& fout = *foutPtr;
+
+ if (!fout) {
+ cmSystemTools::Error("Error Writing ", this->Filename.c_str());
+ cmSystemTools::ReportLastSystemError("");
+ return;
+ }
+
+ // Collect dependency information about all library targets built in
+ // the project.
+ cmake* cm = this->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) {
+ // Get the current target.
+ cmTarget const& target = l->second;
+
+ // Skip non-library targets.
+ if (target.GetType() < cmStateEnums::STATIC_LIBRARY ||
+ target.GetType() > cmStateEnums::MODULE_LIBRARY) {
+ continue;
+ }
+
+ // Construct the dependency variable name.
+ std::string targetEntry = target.GetName();
+ targetEntry += "_LIB_DEPENDS";
+
+ // Construct the dependency variable value with the direct link
+ // dependencies.
+ std::string valueOld;
+ 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";
+ std::string ltValue;
+ switch (li->second) {
+ case GENERAL_LibraryType:
+ valueNew += "general;";
+ ltValue = "general";
+ break;
+ case DEBUG_LibraryType:
+ valueNew += "debug;";
+ ltValue = "debug";
+ break;
+ case OPTIMIZED_LibraryType:
+ valueNew += "optimized;";
+ ltValue = "optimized";
+ break;
+ }
+ 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
+ // translation (which requires per-configuration info).
+ if (const char* outname = libtgt->GetProperty("OUTPUT_NAME")) {
+ lib = outname;
+ }
+ }
+ valueOld += lib;
+ valueOld += ";";
+ valueNew += lib;
+ valueNew += ";";
+
+ std::string& ltEntry = libTypes[ltVar];
+ if (ltEntry.empty()) {
+ ltEntry = ltValue;
+ } else if (ltEntry != ltValue) {
+ ltEntry = "general";
+ }
+ }
+ libDepsNew[targetEntry] = valueNew;
+ libDepsOld[targetEntry] = valueOld;
+ }
+ }
+
+ // Generate dependency information for both old and new style CMake
+ // versions.
+ const char* vertest =
+ "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
+ 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";
+ }
+ }
+ 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 (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";
+ }
+ }
+ fout << "endif()\n";
+}
diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h
new file mode 100644
index 000000000..5559af94b
--- /dev/null
+++ b/Source/cmExportLibraryDependenciesCommand.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 cmExportLibraryDependenciesCommand_h
+#define cmExportLibraryDependenciesCommand_h
+
+#include "cmConfigure.h"
+
+#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;
+};
+
+#endif
diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx
index 33b063037..a93667994 100644
--- a/Source/cmExportSet.cxx
+++ b/Source/cmExportSet.cxx
@@ -1,24 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportSet.h"
+
+#include "cmAlgorithms.h"
+#include "cmLocalGenerator.h"
#include "cmTargetExport.h"
cmExportSet::~cmExportSet()
{
- for(unsigned int i = 0; i < this->TargetExports.size(); ++ i)
- {
- delete this->TargetExports[i];
- }
+ cmDeleteAll(this->TargetExports);
+}
+
+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);
+ }
}
void cmExportSet::AddTargetExport(cmTargetExport* te)
diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h
index a57aa1204..58ad617d4 100644
--- a/Source/cmExportSet.h
+++ b/Source/cmExportSet.h
@@ -1,30 +1,31 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExportSet_h
#define cmExportSet_h
-#include "cmSystemTools.h"
-class cmTargetExport;
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
class cmInstallExportGenerator;
+class cmLocalGenerator;
+class cmTargetExport;
/// A set of targets that were installed with the same EXPORT parameter.
class cmExportSet
{
public:
/// Construct an empty export set named \a name
- cmExportSet(const std::string &name) : Name(name) {}
+ cmExportSet(const std::string& name)
+ : Name(name)
+ {
+ }
/// Destructor
~cmExportSet();
+ void Compute(cmLocalGenerator* lg);
+
void AddTargetExport(cmTargetExport* tgt);
void AddInstallation(cmInstallExportGenerator const* installation);
@@ -32,10 +33,14 @@ public:
std::string const& GetName() const { return this->Name; }
std::vector<cmTargetExport*> const* GetTargetExports() const
- { return &this->TargetExports; }
+ {
+ return &this->TargetExports;
+ }
std::vector<cmInstallExportGenerator const*> const* GetInstallations() const
- { return &this->Installations; }
+ {
+ return &this->Installations;
+ }
private:
std::vector<cmTargetExport*> TargetExports;
diff --git a/Source/cmExportSetMap.cxx b/Source/cmExportSetMap.cxx
index 96fdb3e4f..074082835 100644
--- a/Source/cmExportSetMap.cxx
+++ b/Source/cmExportSetMap.cxx
@@ -1,34 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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"
-cmExportSet* cmExportSetMap::operator[](const std::string &name)
+#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()
{
- for(std::map<std::string, cmExportSet*>::iterator it = this->begin();
- it != this->end();
- ++ it)
- {
- delete it->second;
- }
+ this->clear();
}
diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h
index 4663c5538..0f71c790c 100644
--- a/Source/cmExportSetMap.h
+++ b/Source/cmExportSetMap.h
@@ -1,30 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 "cmSystemTools.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);
+ cmExportSet* operator[](const std::string& name);
+
+ void clear();
/// Overloaded destructor deletes all member export sets.
~cmExportSetMap();
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index 819ac371e..cd0a7e69a 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -1,133 +1,130 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportTryCompileFileGenerator.h"
-#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.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)
+{
+ gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
+}
-//----------------------------------------------------------------------------
bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
{
- std::set<cmTarget*> emitted;
- std::set<cmTarget*> emittedDeps;
- while(!this->Exports.empty())
- {
- cmTarget* te = this->Exports.back();
+ std::set<cmGeneratorTarget const*> emitted;
+ std::set<cmGeneratorTarget const*> emittedDeps;
+ while (!this->Exports.empty()) {
+ cmGeneratorTarget const* te = this->Exports.back();
this->Exports.pop_back();
- if (emitted.insert(te).second)
- {
+ if (emitted.insert(te).second) {
emittedDeps.insert(te);
this->GenerateImportTargetCode(os, te);
ImportPropertyMap properties;
-#define FIND_TARGETS(PROPERTY) \
- this->FindTargets(#PROPERTY, te, emittedDeps);
+#define FIND_TARGETS(PROPERTY) \
+ this->FindTargets("INTERFACE_" #PROPERTY, te, emittedDeps);
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
+#undef FIND_TARGETS
+
this->PopulateProperties(te, properties, emittedDeps);
this->GenerateInterfaceProperties(te, os, properties);
- }
}
+ }
return true;
}
-std::string cmExportTryCompileFileGenerator::FindTargets(const char *propName,
- cmTarget *tgt,
- std::set<cmTarget*> &emitted)
+std::string cmExportTryCompileFileGenerator::FindTargets(
+ const std::string& propName, cmGeneratorTarget const* tgt,
+ std::set<cmGeneratorTarget const*>& emitted)
{
- const char *prop = tgt->GetProperty(propName);
- if(!prop)
- {
+ const char* prop = tgt->GetProperty(propName);
+ if (!prop) {
return std::string();
- }
+ }
+
+ cmGeneratorExpression ge;
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
+ cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName,
+ CM_NULLPTR, CM_NULLPTR);
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- tgt->GetName(),
- propName, 0, 0);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+ cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE,
+ cmTarget::VisibilityNormal, tgt->Target->GetMakefile());
- cmTarget dummyHead;
- dummyHead.SetType(cmTarget::EXECUTABLE, "try_compile_dummy_exe");
- dummyHead.SetMakefile(tgt->GetMakefile());
+ cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
- std::string result = cge->Evaluate(tgt->GetMakefile(), this->Config,
- false, &dummyHead, tgt, &dagChecker);
+ std::string result = cge->Evaluate(tgt->GetLocalGenerator(), this->Config,
+ false, &gDummyHead, tgt, &dagChecker);
- const std::set<cmTarget*> &allTargets = cge->GetAllTargetsSeen();
- for(std::set<cmTarget*>::const_iterator li = allTargets.begin();
- li != allTargets.end(); ++li)
- {
- if(emitted.insert(*li).second)
- {
+ 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);
- }
}
+ }
return result;
}
-//----------------------------------------------------------------------------
-void
-cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target,
- ImportPropertyMap& properties,
- std::set<cmTarget*> &emitted)
+void cmExportTryCompileFileGenerator::PopulateProperties(
+ const cmGeneratorTarget* target, ImportPropertyMap& properties,
+ std::set<cmGeneratorTarget const*>& emitted)
{
- cmPropertyMap props = target->GetProperties();
- for(cmPropertyMap::const_iterator i = props.begin(); i != props.end(); ++i)
- {
- properties[i->first] = i->second.GetValue();
+ std::vector<std::string> props = target->GetPropertyKeys();
+ for (std::vector<std::string>::const_iterator i = props.begin();
+ i != props.end(); ++i) {
- if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
- || i->first.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0
- || i->first.find("INTERFACE_LINK_LIBRARIES") == 0)
- {
- const std::string libs = i->second.GetValue();
+ properties[*i] = target->GetProperty(*i);
- std::string evalResult = this->FindTargets(i->first.c_str(),
- target, emitted);
+ 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);
std::vector<std::string> depends;
cmSystemTools::ExpandListArgument(evalResult, depends);
- for(std::vector<std::string>::const_iterator li = depends.begin();
- li != depends.end(); ++li)
- {
- cmTarget *tgt = target->GetMakefile()->FindTargetToUse(li->c_str());
- if(tgt && emitted.insert(tgt).second)
- {
+ for (std::vector<std::string>::const_iterator li = depends.begin();
+ li != depends.end(); ++li) {
+ cmGeneratorTarget* tgt =
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(*li);
+ if (tgt && emitted.insert(tgt).second) {
this->Exports.push_back(tgt);
- }
}
}
}
+ }
}
-std::string
-cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target,
- const std::string& config)
+
+std::string cmExportTryCompileFileGenerator::InstallNameDir(
+ cmGeneratorTarget* target, const std::string& config)
{
std::string install_name_dir;
- cmMakefile* mf = target->GetMakefile();
- if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
- install_name_dir =
- target->GetInstallNameDirForBuildTree(config.c_str());
- }
+ cmMakefile* mf = target->Target->GetMakefile();
+ if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+ install_name_dir = target->GetInstallNameDirForBuildTree(config);
+ }
return install_name_dir;
}
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 91b4a6153..9671fac8f 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -1,57 +1,58 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmExportTryCompileFileGenerator_h
+#define cmExportTryCompileFileGenerator_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmExportInstallFileGenerator_h
-#define cmExportInstallFileGenerator_h
+#include "cmConfigure.h"
#include "cmExportFileGenerator.h"
-class cmInstallExportGenerator;
-class cmInstallTargetGenerator;
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
-class cmExportTryCompileFileGenerator: public cmExportFileGenerator
+class cmExportTryCompileFileGenerator : public cmExportFileGenerator
{
public:
+ cmExportTryCompileFileGenerator(cmGlobalGenerator* gg,
+ std::vector<std::string> const& targets,
+ cmMakefile* mf);
+
/** Set the list of targets to export. */
- void SetExports(const std::vector<cmTarget*> &exports)
- { this->Exports = exports; }
- void SetConfig(const char *config) { this->Config = config; }
+ void SetConfig(const std::string& config) { this->Config = config; }
protected:
-
// Implement virtual methods from the superclass.
- virtual bool GenerateMainFile(std::ostream& os);
-
- virtual void GenerateImportTargetsConfig(std::ostream&,
- const char*,
- std::string const&,
- std::vector<std::string>&) {}
- virtual void HandleMissingTarget(std::string&,
- std::vector<std::string>&,
- cmMakefile*,
- cmTarget*,
- cmTarget*) {}
-
- void PopulateProperties(cmTarget* target,
+ bool GenerateMainFile(std::ostream& os) CM_OVERRIDE;
+
+ void GenerateImportTargetsConfig(std::ostream&, const std::string&,
+ std::string const&,
+ std::vector<std::string>&) CM_OVERRIDE
+ {
+ }
+ void HandleMissingTarget(std::string&, std::vector<std::string>&,
+ cmGeneratorTarget*, cmGeneratorTarget*) CM_OVERRIDE
+ {
+ }
+
+ void PopulateProperties(cmGeneratorTarget const* target,
ImportPropertyMap& properties,
- std::set<cmTarget*> &emitted);
+ std::set<const cmGeneratorTarget*>& emitted);
- std::string InstallNameDir(cmTarget* target,
- const std::string& config);
-private:
- std::string FindTargets(const char *prop, cmTarget *tgt,
- std::set<cmTarget*> &emitted);
+ std::string InstallNameDir(cmGeneratorTarget* target,
+ const std::string& config) CM_OVERRIDE;
+private:
+ std::string FindTargets(const std::string& prop,
+ const cmGeneratorTarget* tgt,
+ std::set<const cmGeneratorTarget*>& emitted);
- std::vector<cmTarget*> Exports;
- const char *Config;
+ std::vector<cmGeneratorTarget const*> Exports;
+ std::string Config;
};
#endif
diff --git a/Source/cmExprLexer.cxx b/Source/cmExprLexer.cxx
deleted file mode 100644
index 9947c77f1..000000000
--- a/Source/cmExprLexer.cxx
+++ /dev/null
@@ -1,1928 +0,0 @@
-#include "cmStandardIncludes.h"
-#line 2 "/home/andy/vtk/CMake-bin/Source/cmExprLexer.cxx"
-
-#line 4 "/home/andy/vtk/CMake-bin/Source/cmExprLexer.cxx"
-
-#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 5
-#define YY_FLEX_SUBMINOR_VERSION 31
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#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
-#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;
-#endif /* ! C99 */
-
-/* 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
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_CONST
-
-#endif /* __STDC__ */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* 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.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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
-
-int cmExpr_yylex_init (yyscan_t* scanner);
-
-/* 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 cmExpr_yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#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)
-
-/* 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 )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int 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.
- */
- yy_size_t 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 cmExpr_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 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)
-
-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 );
-
-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 );
-
-#define yy_new_buffer cmExpr_yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- cmExpr_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmExpr_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); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmExpr_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(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char 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 yy_fatal_error (yyconst 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 = (size_t) (yy_cp - yy_bp); \
- 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
-/* 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 yyconst flex_int16_t yy_accept[23] =
- { 0,
- 0, 0, 16, 15, 6, 8, 13, 14, 4, 2,
- 3, 5, 1, 15, 15, 9, 7, 10, 1, 11,
- 12, 0
- } ;
-
-static yyconst flex_int32_t yy_ec[256] =
- { 0,
- 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, 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, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 14, 1, 15, 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 yyconst flex_int32_t yy_meta[16] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
- } ;
-
-static yyconst flex_int16_t yy_base[23] =
- { 0,
- 0, 0, 20, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 9, 7, 5, 21, 21, 21, 6, 21,
- 21, 21
- } ;
-
-static yyconst flex_int16_t yy_def[23] =
- { 0,
- 22, 1, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 0
- } ;
-
-static yyconst flex_int16_t yy_nxt[37] =
- { 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
- } ;
-
-static yyconst flex_int16_t yy_chk[37] =
- { 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
- } ;
-
-/* 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
-#line 1 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-#line 2 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex like this:
-
- flex --prefix=cmExpr_yy --header-file=cmExprLexer.h -ocmExprLexer.cxx cmExprLexer.in.l
-
-Modify cmExprLexer.cxx:
- - remove TABs
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmExpr_yyalloc, cmExpr_yyrealloc, cmExpr_yyfree
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
-
-Modify cmExprLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
-
-*/
-
-#include "cmStandardLexer.h"
-
-#include "cmExprParserHelper.h"
-
-/* Replace the lexer input function. */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
-
-/* Include the set of tokens from the parser. */
-#include "cmExprParserTokens.h"
-
-/*--------------------------------------------------------------------------*/
-#line 518 "/home/andy/vtk/CMake-bin/Source/cmExprLexer.cxx"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#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 */
-
-/* Accessor methods to globals.
- These are made visible to non-reentrant scanners for convenience. */
-
-int cmExpr_yylex_destroy (yyscan_t yyscanner );
-
-int cmExpr_yyget_debug (yyscan_t yyscanner );
-
-void cmExpr_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE cmExpr_yyget_extra (yyscan_t yyscanner );
-
-void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *cmExpr_yyget_in (yyscan_t yyscanner );
-
-void cmExpr_yyset_in (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *cmExpr_yyget_out (yyscan_t yyscanner );
-
-void cmExpr_yyset_out (FILE * out_str ,yyscan_t yyscanner );
-
-int cmExpr_yyget_leng (yyscan_t yyscanner );
-
-char *cmExpr_yyget_text (yyscan_t yyscanner );
-
-int cmExpr_yyget_lineno (yyscan_t yyscanner );
-
-void cmExpr_yyset_lineno (int line_number ,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 cmExpr_yywrap (yyscan_t yyscanner );
-#else
-extern int cmExpr_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst 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
-#define YY_READ_BUF_SIZE 8192
-#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 (void) fwrite( yytext, yyleng, 1, yyout )
-#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 = '*'; \
- size_t 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 = fread(buf, 1, 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 cmExpr_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int cmExpr_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 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;
-
-#line 86 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-
-
-#line 736 "/home/andy/vtk/CMake-bin/Source/cmExprLexer.cxx"
-
- if ( yyg->yy_init )
- {
- yyg->yy_init = 0;
-
-#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 ) {
- cmExpr_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmExpr_yy_load_buffer_state(yyscanner );
- }
-
- for(;;) /* 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 >= 23 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 21 );
-
-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
-#line 88 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ yylvalp->Number = atoi(yytext); return exp_NUMBER; }
-case 2:
-YY_RULE_SETUP
-#line 90 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_PLUS; }
-case 3:
-YY_RULE_SETUP
-#line 91 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_MINUS; }
-case 4:
-YY_RULE_SETUP
-#line 92 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_TIMES; }
-case 5:
-YY_RULE_SETUP
-#line 93 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_DIVIDE; }
-case 6:
-YY_RULE_SETUP
-#line 94 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_MOD; }
-case 7:
-YY_RULE_SETUP
-#line 95 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_OR; }
-case 8:
-YY_RULE_SETUP
-#line 96 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_AND; }
-case 9:
-YY_RULE_SETUP
-#line 97 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_XOR; }
-case 10:
-YY_RULE_SETUP
-#line 98 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_NOT; }
-case 11:
-YY_RULE_SETUP
-#line 99 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_SHIFTLEFT; }
-case 12:
-YY_RULE_SETUP
-#line 100 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_SHIFTRIGHT; }
-case 13:
-YY_RULE_SETUP
-#line 101 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_OPENPARENT; }
-case 14:
-YY_RULE_SETUP
-#line 102 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-{ return exp_CLOSEPARENT; }
-case 15:
-YY_RULE_SETUP
-#line 104 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-ECHO;
- YY_BREAK
-#line 894 "/home/andy/vtk/CMake-bin/Source/cmExprLexer.cxx"
-case YY_STATE_EOF(INITIAL):
- yyterminate();
-
- 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
- * cmExpr_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 ( cmExpr_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 */
-return 0; /* this should not happen but it silences a warning*/
-} /* end of cmExpr_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
- {
- size_t nuto_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
- while ( nuto_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;
-
- 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. */
- cmExpr_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- 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];
-
- nuto_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
-
- }
-
- if ( nuto_read > YY_READ_BUF_SIZE )
- nuto_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, nuto_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;
- cmExpr_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;
-
- 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 >= 23 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) 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;
- 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 >= 23 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 22);
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
-#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 = 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. */
- cmExpr_yyrestart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( cmExpr_yywrap(yyscanner ) )
- return EOF;
-
- 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 cmExpr_yyrestart (FILE * input_file , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! YY_CURRENT_BUFFER ){
- cmExpr_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmExpr_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmExpr_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)
-{
- 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);
- */
- cmExpr_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;
- cmExpr_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
- * 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)
-{
- 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 cmExpr_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 );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_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 *) cmExpr_yyalloc(b->yy_buf_size + 2 ,yyscanner );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- cmExpr_yy_init_buffer(b,file ,yyscanner);
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with cmExpr_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
- void cmExpr_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 )
- cmExpr_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
- cmExpr_yyfree((void *) b ,yyscanner );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-
-/* 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.
- */
- static void cmExpr_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);
-
- 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.
- * 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 cmExpr_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 )
- cmExpr_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 cmExpr_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);
-
- /* This block is copied from cmExpr_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 cmExpr_yy_switch_to_buffer. */
- cmExpr_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 cmExpr_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_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 );
- 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 cmExpr_yyensure_buffer_stack (yyscan_t yyscanner)
-{
- int nuto_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.
- */
- nuto_alloc = 1;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmExpr_yyalloc
- (nuto_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
-
- memset(yyg->yy_buffer_stack, 0, nuto_alloc * sizeof(struct yy_buffer_state*));
-
- yyg->yy_buffer_stack_max = nuto_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. */
- int grow_size = 8 /* arbitrary grow size */;
-
- nuto_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmExpr_yyrealloc
- (yyg->yy_buffer_stack,
- nuto_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
-
- /* 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 = nuto_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 cmExpr_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 0;
-
- b = (YY_BUFFER_STATE) cmExpr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_scan_buffer()" );
-
- b->yy_buf_size = 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 = 0;
- 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;
-
- cmExpr_yy_switch_to_buffer(b ,yyscanner );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to cmExpr_yylex() will
- * scan from a @e copy of @a yy_str.
- * @param yy_str 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_BUFFER_STATE cmExpr_yy_scan_string (yyconst char * yy_str , yyscan_t yyscanner)
-{
-
- return cmExpr_yy_scan_bytes(yy_str,strlen(yy_str) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to cmExpr_yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param 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 * bytes, int 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 = len + 2;
- buf = (char *) cmExpr_yyalloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_scan_bytes()" );
-
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
-
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
-
- b = cmExpr_yy_scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmExpr_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 yy_fatal_error (yyconst char* msg , yyscan_t)
-{
- (void) 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 cmExpr_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 cmExpr_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 cmExpr_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 *cmExpr_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 *cmExpr_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 cmExpr_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 *cmExpr_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 cmExpr_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
- * @param yyscanner The scanner object.
- */
-void cmExpr_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" , yyscanner);
-
- yylineno = line_number;
-}
-
-/** Set the current column.
- * @param column_no
- * @param yyscanner The scanner object.
- */
-void cmExpr_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" , yyscanner);
-
- 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 cmExpr_yy_switch_to_buffer
- */
-void cmExpr_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)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
-}
-
-int cmExpr_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)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-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 once per scanner lifetime. */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- yyg->yy_init = 1;
- yyg->yy_start = 0;
- yyg->yy_start_stack_ptr = 0;
- yyg->yy_start_stack_depth = 0;
- yyg->yy_start_stack = (int *) 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
- yyin = stdin;
- yyout = stdout;
-#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * cmExpr_yylex_init()
- */
- return 0;
-}
-
-/* User-visible API */
-
-/* cmExpr_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)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmExpr_yyalloc ( sizeof( struct yyguts_t ), NULL );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- memset(*ptr_yy_globals,0,sizeof(struct yyguts_t));
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* cmExpr_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmExpr_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_CURRENT_BUFFER_LVALUE = NULL;
- cmExpr_yypop_buffer_state(yyscanner);
- }
-
- /* Destroy the stack itself. */
- cmExpr_yyfree(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
-
- /* Destroy the start condition stack. */
- cmExpr_yyfree(yyg->yy_start_stack ,yyscanner );
- yyg->yy_start_stack = NULL;
-
- /* Destroy the main struct (reentrant only). */
- cmExpr_yyfree ( yyscanner , yyscanner );
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
- int i;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
- int n;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *cmExpr_yyalloc (yy_size_t size , yyscan_t)
-{
- return (void *) malloc( size );
-}
-
-void *cmExpr_yyrealloc (void * ptr, yy_size_t size , yyscan_t)
-{
- /* 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 (void *) realloc( (char *) ptr, size );
-}
-
-void cmExpr_yyfree (void * ptr , yyscan_t)
-{
- free( (char *) ptr ); /* see cmExpr_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-#line 104 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
-
-
-
diff --git a/Source/cmExprLexer.in.l b/Source/cmExprLexer.in.l
deleted file mode 100644
index febd244fe..000000000
--- a/Source/cmExprLexer.in.l
+++ /dev/null
@@ -1,74 +0,0 @@
-%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex like this:
-
- flex --prefix=cmExpr_yy --header-file=cmExprLexer.h -ocmExprLexer.cxx cmExprLexer.in.l
-
-Modify cmExprLexer.cxx:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - remove "yyscanner" argument from these methods:
- yy_fatal_error, cmExpr_yyalloc, cmExpr_yyrealloc, cmExpr_yyfree
- - remove all YY_BREAK lines occurring right after return statements
- - change while ( 1 ) to for(;;)
-
-Modify cmExprLexer.h:
- - remove TABs
- - remove the yy_init_globals function
- - remove the block that includes unistd.h
- - remove #line directives (avoids bogus warning on old Sun)
-
-*/
-
-#include "cmStandardLexer.h"
-
-#include "cmExprParserHelper.h"
-
-/* Replace the lexer input function. */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
-
-/* Include the set of tokens from the parser. */
-#include "cmExprParserTokens.h"
-
-/*--------------------------------------------------------------------------*/
-%}
-
-%option reentrant
-%option noyywrap
-%pointer
-
-%%
-
-[0-9][0-9]* { yylvalp->Number = atoi(yytext); return exp_NUMBER; }
-
-"+" { return exp_PLUS; }
-"-" { return exp_MINUS; }
-"*" { return exp_TIMES; }
-"/" { return exp_DIVIDE; }
-"%" { return exp_MOD; }
-"\|" { return exp_OR; }
-"&" { return exp_AND; }
-"^" { return exp_XOR; }
-"~" { return exp_NOT; }
-"<<" { return exp_SHIFTLEFT; }
-">>" { return exp_SHIFTRIGHT; }
-"(" { return exp_OPENPARENT; }
-")" { return exp_CLOSEPARENT; }
-
-%%
diff --git a/Source/cmExprParser.cxx b/Source/cmExprParser.cxx
deleted file mode 100644
index 77880c0a3..000000000
--- a/Source/cmExprParser.cxx
+++ /dev/null
@@ -1,1433 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d. */
-
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
- 1989, 1990, 2000, 2001, 2002, 2003, 2004 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* Written by Richard Stallman by simplifying the original so called
- ``semantic'' parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* turn off some warning as this is generated code */
-#if defined(_MSC_VER)
-# pragma warning ( disable : 4702 ) /* unreachable code */
-#endif
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 1
-
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-/* If NAME_PREFIX is specified substitute the variables and functions
- names. */
-#define yyparse cmExpr_yyparse
-#define yylex cmExpr_yylex
-#define yyerror cmExpr_yyerror
-#define yylval cmExpr_yylval
-#define yychar cmExpr_yychar
-#define yydebug cmExpr_yydebug
-#define yynerrs cmExpr_yynerrs
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- exp_PLUS = 258,
- exp_MINUS = 259,
- exp_TIMES = 260,
- exp_DIVIDE = 261,
- exp_MOD = 262,
- exp_SHIFTLEFT = 263,
- exp_SHIFTRIGHT = 264,
- exp_OPENPARENT = 265,
- exp_CLOSEPARENT = 266,
- exp_OR = 267,
- exp_AND = 268,
- exp_XOR = 269,
- exp_NOT = 270,
- exp_NUMBER = 271
- };
-#endif
-#define exp_PLUS 258
-#define exp_MINUS 259
-#define exp_TIMES 260
-#define exp_DIVIDE 261
-#define exp_MOD 262
-#define exp_SHIFTLEFT 263
-#define exp_SHIFTRIGHT 264
-#define exp_OPENPARENT 265
-#define exp_CLOSEPARENT 266
-#define exp_OR 267
-#define exp_AND 268
-#define exp_XOR 269
-#define exp_NOT 270
-#define exp_NUMBER 271
-
-
-
-
-/* Copy the first part of user declarations. */
-
-
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
- bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h
- -ocmExprParser.cxx cmExprParser.y
-
-Modify cmExprParser.cxx:
- - remove TABs
- - add __HP_aCC to the #if test for yyerrorlab warning suppression
-
-*/
-
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmExpr_yyerror(x) \
- cmExprError(yyscanner, x)
-#define yyGetParser (cmExpr_yyget_extra(yyscanner))
-
-/*-------------------------------------------------------------------------*/
-#include "cmExprParserHelper.h" /* Interface to parser object. */
-#include "cmExprLexer.h" /* Interface to lexer object. */
-#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */
-
-#include <math.h>
-
-/* Forward declare the lexer entry point. */
-YY_DECL;
-
-/* Internal utility functions. */
-static void cmExprError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-//#define YYMAXDEPTH 100000
-//#define YYINITDEPTH 10000
-
-
-/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label. */
-# pragma warning (disable: 4065) /* Switch statement contains default but
- no case. */
-#endif
-
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 214 of yacc.c. */
-
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-# define YYFREE free
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# endif
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# define YYSTACK_ALLOC alloca
-# endif
-# else
-# if defined (alloca) || defined (_ALLOCA_H)
-# define YYSTACK_ALLOC alloca
-# else
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
-
-
-#if (! defined (yyoverflow) \
- && (! defined (__cplusplus) \
- || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- short int yyss;
- YYSTYPE yyvs;
- };
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
- + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined (__GNUC__) && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (0)
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (0)
-
-#endif
-
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short int yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 12
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 25
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 17
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 9
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 20
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 34
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 271
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const unsigned char yyprhs[] =
-{
- 0, 0, 3, 5, 7, 11, 13, 17, 19, 23,
- 25, 29, 33, 35, 39, 43, 45, 49, 53, 57,
- 59
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
-{
- 18, 0, -1, 19, -1, 20, -1, 19, 12, 20,
- -1, 21, -1, 20, 14, 21, -1, 22, -1, 21,
- 13, 22, -1, 23, -1, 22, 8, 23, -1, 22,
- 9, 23, -1, 24, -1, 23, 3, 24, -1, 23,
- 4, 24, -1, 25, -1, 24, 5, 25, -1, 24,
- 6, 25, -1, 24, 7, 25, -1, 16, -1, 10,
- 19, 11, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned char yyrline[] =
-{
- 0, 94, 94, 100, 103, 107, 110, 114, 117, 121,
- 124, 127, 132, 135, 138, 142, 145, 148, 151, 155,
- 158
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "exp_PLUS", "exp_MINUS", "exp_TIMES",
- "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT", "exp_SHIFTRIGHT",
- "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR", "exp_AND", "exp_XOR",
- "exp_NOT", "exp_NUMBER", "$accept", "Start", "exp", "bitwiseor",
- "bitwisexor", "bitwiseand", "shift", "term", "factor", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const unsigned short int yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 270, 271
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned char yyr1[] =
-{
- 0, 17, 18, 19, 19, 20, 20, 21, 21, 22,
- 22, 22, 23, 23, 23, 24, 24, 24, 24, 25,
- 25
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
-{
- 0, 2, 1, 1, 3, 1, 3, 1, 3, 1,
- 3, 3, 1, 3, 3, 1, 3, 3, 3, 1,
- 3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const unsigned char yydefact[] =
-{
- 0, 0, 19, 0, 2, 3, 5, 7, 9, 12,
- 15, 0, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 20, 4, 6, 8, 10, 11, 13,
- 14, 16, 17, 18
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yysigned_char yydefgoto[] =
-{
- -1, 3, 4, 5, 6, 7, 8, 9, 10
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -14
-static const yysigned_char yypact[] =
-{
- -10, -10, -14, 18, 7, 6, 8, 2, 1, -4,
- -14, 3, -14, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -14, 6, 8, 2, 1, 1, -4,
- -4, -14, -14, -14
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yysigned_char yypgoto[] =
-{
- -14, -14, 21, 10, 11, 9, 0, -6, -13
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
-static const unsigned char yytable[] =
-{
- 1, 20, 21, 22, 18, 19, 2, 31, 32, 33,
- 16, 17, 29, 30, 23, 13, 27, 28, 12, 13,
- 14, 15, 11, 24, 26, 25
-};
-
-static const unsigned char yycheck[] =
-{
- 10, 5, 6, 7, 3, 4, 16, 20, 21, 22,
- 8, 9, 18, 19, 11, 12, 16, 17, 0, 12,
- 14, 13, 1, 13, 15, 14
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const unsigned char yystos[] =
-{
- 0, 10, 16, 18, 19, 20, 21, 22, 23, 24,
- 25, 19, 0, 12, 14, 13, 8, 9, 3, 4,
- 5, 6, 7, 11, 20, 21, 22, 23, 23, 24,
- 24, 25, 25, 25
-};
-
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror ("syntax error: cannot back up");\
- YYERROR; \
- } \
-while (0)
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
- are run). */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- ((Current).first_line = (Rhs)[1].first_line, \
- (Current).first_column = (Rhs)[1].first_column, \
- (Current).last_line = (Rhs)[N].last_line, \
- (Current).last_column = (Rhs)[N].last_column)
-#endif
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (0)
-
-# define YYDSYMPRINT(Args) \
-do { \
- if (yydebug) \
- yysymprint Args; \
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Token, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_stack_print (short int *bottom, short int *top)
-#else
-static void
-yy_stack_print (bottom, top)
- short int *bottom;
- short int *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
-static void
-yy_reduce_print (yyrule)
- int yyrule;
-#endif
-{
- int yyi;
- unsigned int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
- yyrule - 1, yylno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (Rule); \
-} while (0)
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined (__GLIBC__) && defined (_STRING_H)
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
-yystrlen (const char *yystr)
-# else
-yystrlen (yystr)
- const char *yystr;
-# endif
-{
- const char *yys = yystr;
-
- while (*yys++ != '\0')
- continue;
-
- return yys - yystr - 1;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-static char *
-# if defined (__STDC__) || defined (__cplusplus)
-yystpcpy (char *yydest, const char *yysrc)
-# else
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-
-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
-
- if (yytype < YYNTOKENS)
- {
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
- }
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- switch (yytype)
- {
- default:
- break;
- }
- YYFPRINTF (yyoutput, ")");
-}
-
-#endif /* ! YYDEBUG */
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
-
- switch (yytype)
- {
-
- default:
- break;
- }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM);
-# else
-int yyparse ();
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
- /* The lookahead symbol. */
-int yychar;
-
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- short int yyssa[YYINITDEPTH];
- short int *yyss = yyssa;
- short int *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK (yyvsp--, yyssp--)
-
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
-
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
-
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- 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;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- short int *yyss1 = yyss;
-
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow ("parser stack overflow",
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
-
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyoverflowlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyoverflowlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- short int *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyoverflowlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
-# 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));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- 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. */
-/* yyresume: */
-
- /* First try to decide what to do without reference to lookahead token. */
-
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Shift the lookahead token. */
- YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
-
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
-
- {
- yyGetParser->SetResult(yyvsp[0].Number);
-}
- break;
-
- case 3:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 4:
-
- {yyval.Number = yyvsp[-2].Number | yyvsp[0].Number;}
- break;
-
- case 5:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 6:
-
- {yyval.Number = yyvsp[-2].Number ^ yyvsp[0].Number;}
- break;
-
- case 7:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 8:
-
- {yyval.Number = yyvsp[-2].Number & yyvsp[0].Number;}
- break;
-
- case 9:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 10:
-
- {yyval.Number = yyvsp[-2].Number << yyvsp[0].Number;}
- break;
-
- case 11:
-
- {yyval.Number = yyvsp[-2].Number >> yyvsp[0].Number;}
- break;
-
- case 12:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 13:
-
- {yyval.Number = yyvsp[-2].Number + yyvsp[0].Number;}
- break;
-
- case 14:
-
- {yyval.Number = yyvsp[-2].Number - yyvsp[0].Number;}
- break;
-
- case 15:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 16:
-
- {yyval.Number = yyvsp[-2].Number * yyvsp[0].Number;}
- break;
-
- case 17:
-
- {yyval.Number = yyvsp[-2].Number / yyvsp[0].Number;}
- break;
-
- case 18:
-
- {yyval.Number = yyvsp[-2].Number % yyvsp[0].Number;}
- break;
-
- case 19:
-
- {yyval.Number = yyvsp[0].Number;}
- break;
-
- case 20:
-
- {yyval.Number = yyvsp[-1].Number;}
- break;
-
-
- }
-
-/* Line 1010 of yacc.c. */
-
-
- yyvsp -= yylen;
- yyssp -= yylen;
-
-
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
-
-
- /* 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];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- YYSIZE_T yysize = 0;
- int yytype = YYTRANSLATE (yychar);
- const char* yyprefix;
- char *yymsg;
- int yyx;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 0;
-
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
- yycount += 1;
- if (yycount == 5)
- {
- yysize = 0;
- break;
- }
- }
- yysize += (sizeof ("syntax error, unexpected ")
- + yystrlen (yytname[yytype]));
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg != 0)
- {
- char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
- yyp = yystpcpy (yyp, yytname[yytype]);
-
- if (yycount < 5)
- {
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yyp = yystpcpy (yyp, yyprefix);
- yyp = yystpcpy (yyp, yytname[yyx]);
- yyprefix = " or ";
- }
- }
- yyerror (yymsg);
- YYSTACK_FREE (yymsg);
- }
- else
- yyerror ("syntax error; also virtual memory exhausted");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror ("syntax error");
- }
-
-
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* If at end of input, pop the error token,
- then the rest of the stack, then return failure. */
- if (yychar == YYEOF)
- for (;;)
- {
- YYPOPSTACK;
- if (yyssp == yyss)
- YYABORT;
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[*yyssp], yyvsp);
- }
- }
- else
- {
- YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
- yydestruct (yytoken, &yylval);
- yychar = YYEMPTY;
-
- }
- }
-
- /* Else will try to reuse lookahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
-#if defined( __GNUC__ ) || defined(__HP_aCC)
- /* Pacify GCC when the user code never invokes YYERROR and the label
- yyerrorlab therefore never appears in user code. */
- if (0)
- goto yyerrorlab;
-#endif
-
- yyvsp -= yylen;
- yyssp -= yylen;
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[yystate], yyvsp);
- YYPOPSTACK;
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- YYDPRINTF ((stderr, "Shifting error token, "));
-
- *++yyvsp = yylval;
-
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here. |
-`----------------------------------------------*/
-yyoverflowlab:
- yyerror ("parser stack overflow");
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
- return yyresult;
-}
-
-
-
-
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmExprError(yyscan_t yyscanner, const char* message)
-{
- yyGetParser->Error(message);
-}
-
-
diff --git a/Source/cmExprParser.y b/Source/cmExprParser.y
deleted file mode 100644
index 12c2e4806..000000000
--- a/Source/cmExprParser.y
+++ /dev/null
@@ -1,170 +0,0 @@
-%{
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
- bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
-
-Modify cmExprParser.cxx:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - add __HP_aCC to the #if test for yyerrorlab warning suppression
-
-*/
-
-/* Configure the parser to use a lexer object. */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmExpr_yyerror(x) \
- cmExprError(yyscanner, x)
-#define yyGetParser (cmExpr_yyget_extra(yyscanner))
-
-/*-------------------------------------------------------------------------*/
-#include "cmExprParserHelper.h" /* Interface to parser object. */
-#include "cmExprLexer.h" /* Interface to lexer object. */
-#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */
-
-#include <math.h>
-
-/* Forward declare the lexer entry point. */
-YY_DECL;
-
-/* Internal utility functions. */
-static void cmExprError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-//#define YYMAXDEPTH 100000
-//#define YYINITDEPTH 10000
-
-
-/* Disable some warnings in the generated code. */
-#ifdef __BORLANDC__
-# pragma warn -8004 /* Variable assigned a value that is not used. */
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8060 /* possibly incorrect assignment */
-# pragma warn -8066 /* unreachable code */
-#endif
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label. */
-# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
-#endif
-%}
-
-/* Generate a reentrant parser object. */
-%pure_parser
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token exp_PLUS
-%token exp_MINUS
-%token exp_TIMES
-%token exp_DIVIDE
-%token exp_MOD
-%token exp_SHIFTLEFT
-%token exp_SHIFTRIGHT
-%token exp_OPENPARENT
-%token exp_CLOSEPARENT
-%token exp_OR;
-%token exp_AND;
-%token exp_XOR;
-%token exp_NOT;
-%token exp_NUMBER;
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-
-Start:
-exp
-{
- yyGetParser->SetResult($<Number>1);
-}
-
-exp:
-bitwiseor
-{$<Number>$ = $<Number>1;}
-|
-exp exp_OR bitwiseor
-{$<Number>$ = $<Number>1 | $<Number>3;}
-
-bitwiseor:
-bitwisexor
-{$<Number>$ = $<Number>1;}
-|
-bitwiseor exp_XOR bitwisexor
-{$<Number>$ = $<Number>1 ^ $<Number>3;}
-
-bitwisexor:
-bitwiseand
-{$<Number>$ = $<Number>1;}
-|
-bitwisexor exp_AND bitwiseand
-{$<Number>$ = $<Number>1 & $<Number>3;}
-
-bitwiseand:
-shift
-{$<Number>$ = $<Number>1;}
-|
-bitwiseand exp_SHIFTLEFT shift
-{$<Number>$ = $<Number>1 << $<Number>3;}
-|
-bitwiseand exp_SHIFTRIGHT shift
-{$<Number>$ = $<Number>1 >> $<Number>3;}
-
-
-shift:
-term
-{$<Number>$ = $<Number>1;}
-|
-shift exp_PLUS term
-{$<Number>$ = $<Number>1 + $<Number>3;}
-|
-shift exp_MINUS term
-{$<Number>$ = $<Number>1 - $<Number>3;}
-
-term:
-factor
-{$<Number>$ = $<Number>1;}
-|
-term exp_TIMES factor
-{$<Number>$ = $<Number>1 * $<Number>3;}
-|
-term exp_DIVIDE factor
-{$<Number>$ = $<Number>1 / $<Number>3;}
-|
-term exp_MOD factor
-{$<Number>$ = $<Number>1 % $<Number>3;}
-
-factor:
-exp_NUMBER
-{$<Number>$ = $<Number>1;}
-|
-exp_OPENPARENT exp exp_CLOSEPARENT
-{$<Number>$ = $<Number>2;}
-;
-
-
-%%
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmExprError(yyscan_t yyscanner, const char* message)
-{
- yyGetParser->Error(message);
-}
-
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index cc35f84cd..c3f026a4e 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -1,30 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExprParserHelper.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
+#include "cmConfigure.h"
#include "cmExprLexer.h"
-int cmExpr_yyparse( yyscan_t yyscanner );
+#include <iostream>
+#include <sstream>
+
+int cmExpr_yyparse(yyscan_t yyscanner);
//
cmExprParserHelper::cmExprParserHelper()
{
this->FileLine = -1;
- this->FileName = 0;
+ this->FileName = CM_NULLPTR;
}
-
cmExprParserHelper::~cmExprParserHelper()
{
this->CleanupParser();
@@ -32,11 +24,10 @@ cmExprParserHelper::~cmExprParserHelper()
int cmExprParserHelper::ParseString(const char* str, int verb)
{
- if ( !str)
- {
+ if (!str) {
return 0;
- }
- //printf("Do some parsing: %s\n", str);
+ }
+ // printf("Do some parsing: %s\n", str);
this->Verbose = verb;
this->InputBuffer = str;
@@ -50,20 +41,18 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
cmExpr_yyset_extra(this, yyscanner);
int res = cmExpr_yyparse(yyscanner);
cmExpr_yylex_destroy(yyscanner);
- if ( res != 0 )
- {
- //str << "CAL_Parser returned: " << res << std::endl;
- //std::cerr << "When parsing: [" << str << "]" << std::endl;
+ if (res != 0) {
+ // str << "CAL_Parser returned: " << res << std::endl;
+ // std::cerr << "When parsing: [" << str << "]" << std::endl;
return 0;
- }
+ }
this->CleanupParser();
- if ( Verbose )
- {
- std::cerr << "Expanding [" << str << "] produced: ["
- << this->Result << "]" << std::endl;
- }
+ if (Verbose) {
+ std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
+ << std::endl;
+ }
return 1;
}
@@ -73,33 +62,27 @@ void cmExprParserHelper::CleanupParser()
int cmExprParserHelper::LexInput(char* buf, int maxlen)
{
- //std::cout << "JPLexInput ";
- //std::cout.write(buf, maxlen);
- //std::cout << std::endl;
- if ( maxlen < 1 )
- {
+ // std::cout << "JPLexInput ";
+ // std::cout.write(buf, maxlen);
+ // std::cout << std::endl;
+ if (maxlen < 1) {
return 0;
+ }
+ if (this->InputBufferPos < this->InputBuffer.size()) {
+ buf[0] = this->InputBuffer[this->InputBufferPos++];
+ if (buf[0] == '\n') {
+ this->CurrentLine++;
}
- if ( this->InputBufferPos < this->InputBuffer.size() )
- {
- buf[0] = this->InputBuffer[ this->InputBufferPos++ ];
- if ( buf[0] == '\n' )
- {
- this->CurrentLine ++;
- }
- return(1);
- }
- else
- {
- buf[0] = '\n';
- return( 0 );
- }
+ return (1);
+ }
+ buf[0] = '\n';
+ return (0);
}
void cmExprParserHelper::Error(const char* str)
{
unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
- cmOStringStream ostr;
+ std::ostringstream ostr;
ostr << str << " (" << pos << ")";
this->ErrorString = ostr.str();
}
@@ -108,5 +91,3 @@ void cmExprParserHelper::SetResult(int value)
{
this->Result = value;
}
-
-
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index 4b76b3322..dcdaca967 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -1,38 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExprParserHelper_h
#define cmExprParserHelper_h
-#include "cmStandardIncludes.h"
-
-#define YYSTYPE cmExprParserHelper::ParserType
-#define YYSTYPE_IS_DECLARED
-#define YY_EXTRA_TYPE cmExprParserHelper*
-#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
-
-/** \class cmExprParserHelper
- * \brief Helper class for parsing java source files
- *
- * Finds dependencies for java file and list of outputs
- */
+#include "cmConfigure.h" // IWYU pragma: keep
-class cmMakefile;
+#include <string>
+#include <vector>
class cmExprParserHelper
{
public:
- typedef struct {
+ struct ParserType
+ {
int Number;
- } ParserType;
+ };
cmExprParserHelper();
~cmExprParserHelper();
@@ -49,8 +31,8 @@ public:
const char* GetError() { return this->ErrorString.c_str(); }
private:
- cmStdString::size_type InputBufferPos;
- cmStdString InputBuffer;
+ std::string::size_type InputBufferPos;
+ std::string InputBuffer;
std::vector<char> OutputBuffer;
int CurrentLine;
int Verbose;
@@ -65,7 +47,9 @@ private:
std::string ErrorString;
};
-#endif
-
-
+#define YYSTYPE cmExprParserHelper::ParserType
+#define YYSTYPE_IS_DECLARED
+#define YY_EXTRA_TYPE cmExprParserHelper*
+#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+#endif
diff --git a/Source/cmExprParserTokens.h b/Source/cmExprParserTokens.h
deleted file mode 100644
index 0309c09a1..000000000
--- a/Source/cmExprParserTokens.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d. */
-
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
- 1989, 1990, 2000, 2001, 2002, 2003, 2004 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- exp_PLUS = 258,
- exp_MINUS = 259,
- exp_TIMES = 260,
- exp_DIVIDE = 261,
- exp_MOD = 262,
- exp_SHIFTLEFT = 263,
- exp_SHIFTRIGHT = 264,
- exp_OPENPARENT = 265,
- exp_CLOSEPARENT = 266,
- exp_OR = 267,
- exp_AND = 268,
- exp_XOR = 269,
- exp_NOT = 270,
- exp_NUMBER = 271
- };
-#endif
-#define exp_PLUS 258
-#define exp_MINUS 259
-#define exp_TIMES 260
-#define exp_DIVIDE 261
-#define exp_MOD 262
-#define exp_SHIFTLEFT 263
-#define exp_SHIFTRIGHT 264
-#define exp_OPENPARENT 265
-#define exp_CLOSEPARENT 266
-#define exp_OR 267
-#define exp_AND 268
-#define exp_XOR 269
-#define exp_NOT 270
-#define exp_NUMBER 271
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-
-
diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx
index 9c965cc24..825ec654e 100644
--- a/Source/cmExternalMakefileProjectGenerator.cxx
+++ b/Source/cmExternalMakefileProjectGenerator.cxx
@@ -1,64 +1,60 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExternalMakefileProjectGenerator.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include <assert.h>
+class cmMakefile;
-#include "cmExternalMakefileProjectGenerator.h"
+void cmExternalMakefileProjectGenerator::EnableLanguage(
+ std::vector<std::string> const& /*unused*/, cmMakefile* /*unused*/,
+ bool /*unused*/)
+{
+}
std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- const char* globalGenerator,
- const char* extraGenerator)
+ const std::string& globalGenerator, const std::string& extraGenerator)
{
std::string fullName;
- if (globalGenerator)
- {
- if (extraGenerator && *extraGenerator)
- {
+ if (!globalGenerator.empty()) {
+ if (!extraGenerator.empty()) {
fullName = extraGenerator;
fullName += " - ";
- }
- fullName += globalGenerator;
}
+ fullName += globalGenerator;
+ }
return fullName;
}
-const char* cmExternalMakefileProjectGenerator::GetGlobalGeneratorName(
- const char* fullName)
+cmExternalMakefileProjectGeneratorFactory::
+ cmExternalMakefileProjectGeneratorFactory(const std::string& n,
+ const std::string& doc)
+ : Name(n)
+ , Documentation(doc)
{
- // at least one global generator must be supported
- assert(!this->SupportedGlobalGenerators.empty());
+}
- if (fullName==0)
- {
- return 0;
- }
+cmExternalMakefileProjectGeneratorFactory::
+ ~cmExternalMakefileProjectGeneratorFactory()
+{
+}
- std::string currentName = fullName;
- // if we get only the short name, take the first global generator as default
- if (currentName == this->GetName())
- {
- return this->SupportedGlobalGenerators[0].c_str();
- }
+std::string cmExternalMakefileProjectGeneratorFactory::GetName() const
+{
+ return this->Name;
+}
- // otherwise search for the matching global generator
- for (std::vector<std::string>::const_iterator
- it = this->SupportedGlobalGenerators.begin();
- it != this->SupportedGlobalGenerators.end();
- ++it)
- {
- if (this->CreateFullGeneratorName(it->c_str(), this->GetName())
- == currentName)
- {
- return it->c_str();
- }
- }
- return 0;
+std::string cmExternalMakefileProjectGeneratorFactory::GetDocumentation() const
+{
+ return this->Documentation;
+}
+
+std::vector<std::string>
+cmExternalMakefileProjectGeneratorFactory::GetSupportedGlobalGenerators() const
+{
+ return this->SupportedGlobalGenerators;
+}
+
+void cmExternalMakefileProjectGeneratorFactory::AddSupportedGlobalGenerator(
+ const std::string& base)
+{
+ this->SupportedGlobalGenerators.push_back(base);
}
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index 182c1a8f6..6b8903790 100644
--- a/Source/cmExternalMakefileProjectGenerator.h
+++ b/Source/cmExternalMakefileProjectGenerator.h
@@ -1,22 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExternalMakefileProjectGenerator_h
#define cmExternalMakefileProjectGenerator_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmDocumentation.h"
+#include <string>
+#include <vector>
class cmGlobalGenerator;
+class cmMakefile;
/** \class cmExternalMakefileProjectGenerator
* \brief Base class for generators for "External Makefile based IDE projects".
@@ -33,38 +26,85 @@ class cmGlobalGenerator;
class cmExternalMakefileProjectGenerator
{
public:
-
virtual ~cmExternalMakefileProjectGenerator() {}
- ///! Get the name for this generator.
- virtual const char* GetName() const = 0;
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry,
- const char* fullName) const = 0;
+ virtual void EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
///! set the global generator which will generate the makefiles
virtual void SetGlobalGenerator(cmGlobalGenerator* generator)
- {this->GlobalGenerator = generator;}
+ {
+ this->GlobalGenerator = generator;
+ }
///! Return the list of global generators supported by this extra generator
const std::vector<std::string>& GetSupportedGlobalGenerators() const
- {return this->SupportedGlobalGenerators;}
+ {
+ return this->SupportedGlobalGenerators;
+ }
- ///! Get the name of the global generator for the given full name
- const char* GetGlobalGeneratorName(const char* fullName);
/** Create a full name from the given global generator name and the
* extra generator name
*/
- static std::string CreateFullGeneratorName(const char* globalGenerator,
- const char* extraGenerator);
+ static std::string CreateFullGeneratorName(
+ const std::string& globalGenerator, const std::string& extraGenerator);
///! 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; }
+
protected:
///! 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;
+
+ std::string Name;
+};
+
+class cmExternalMakefileProjectGeneratorFactory
+{
+public:
+ cmExternalMakefileProjectGeneratorFactory(const std::string& n,
+ const std::string& doc);
+ virtual ~cmExternalMakefileProjectGeneratorFactory();
+
+ std::string GetName() const;
+ std::string GetDocumentation() const;
+ std::vector<std::string> GetSupportedGlobalGenerators() const;
+ std::vector<std::string> Aliases;
+
+ virtual cmExternalMakefileProjectGenerator*
+ CreateExternalMakefileProjectGenerator() const = 0;
+
+ void AddSupportedGlobalGenerator(const std::string& base);
+
+private:
+ std::string Name;
+ std::string Documentation;
+ std::vector<std::string> SupportedGlobalGenerators;
+};
+
+template <class T>
+class cmExternalMakefileProjectGeneratorSimpleFactory
+ : public cmExternalMakefileProjectGeneratorFactory
+{
+public:
+ cmExternalMakefileProjectGeneratorSimpleFactory(const std::string& n,
+ const std::string& doc)
+ : cmExternalMakefileProjectGeneratorFactory(n, doc)
+ {
+ }
+
+ cmExternalMakefileProjectGenerator* CreateExternalMakefileProjectGenerator()
+ const CM_OVERRIDE
+ {
+ T* p = new T;
+ p->SetName(GetName());
+ return p;
+ }
};
#endif
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index dfbb1c0ad..5b7b82762 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -1,27 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraCodeBlocksGenerator.h"
-#include "cmGlobalUnixMakefileGenerator3.h"
-#include "cmLocalUnixMakefileGenerator3.h"
+
+#include <map>
+#include <ostream>
+#include <string.h>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmake.h"
#include "cmSourceFile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmTarget.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
-
-#include <cmsys/SystemTools.hxx>
+#include "cmXMLWriter.h"
+#include "cmake.h"
/* Some useful URLs:
Homepage:
@@ -36,66 +32,59 @@ Discussion:
http://forums.codeblocks.org/index.php/topic,6789.0.html
*/
-//----------------------------------------------------------------------------
-void cmExtraCodeBlocksGenerator
-::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
+ : cmExternalMakefileProjectGenerator()
{
- entry.Name = this->GetName();
- entry.Brief = "Generates CodeBlocks project files.";
- entry.Full =
- "Project files for CodeBlocks will be created in the top directory "
- "and in every subdirectory which features a CMakeLists.txt file "
- "containing a PROJECT() call. "
- "Additionally a hierarchy of makefiles is generated into the "
- "build tree. The appropriate make program can build the project through "
- "the default make target. A \"make install\" target is also provided.";
}
-cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
-:cmExternalMakefileProjectGenerator()
+cmExternalMakefileProjectGeneratorFactory*
+cmExtraCodeBlocksGenerator::GetFactory()
{
+ static cmExternalMakefileProjectGeneratorSimpleFactory<
+ cmExtraCodeBlocksGenerator>
+ factory("CodeBlocks", "Generates CodeBlocks project files.");
+
+ if (factory.GetSupportedGlobalGenerators().empty()) {
#if defined(_WIN32)
- this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
- this->SupportedGlobalGenerators.push_back("NMake Makefiles");
+ factory.AddSupportedGlobalGenerator("MinGW Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles JOM");
// disable until somebody actually tests it:
-// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
+// this->AddSupportedGlobalGenerator("MSYS Makefiles");
#endif
- this->SupportedGlobalGenerators.push_back("Ninja");
- this->SupportedGlobalGenerators.push_back("Unix Makefiles");
-}
+ factory.AddSupportedGlobalGenerator("Ninja");
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
+ }
+ return &factory;
+}
void cmExtraCodeBlocksGenerator::Generate()
{
// for each sub project in the project create a codeblocks project
- for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it!= this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
+ for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
// create a project file
this->CreateProjectFile(it->second);
- }
+ }
}
-
/* create the project file */
void cmExtraCodeBlocksGenerator::CreateProjectFile(
- const std::vector<cmLocalGenerator*>& lgs)
+ const std::vector<cmLocalGenerator*>& lgs)
{
- const cmMakefile* mf=lgs[0]->GetMakefile();
- std::string outputDir=mf->GetStartOutputDirectory();
- std::string projectName=mf->GetProjectName();
+ 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 = outputDir + "/";
+ filename += projectName + ".cbp";
+ std::string sessionFilename = outputDir + "/";
+ sessionFilename += projectName + ".layout";
this->CreateNewProjectFile(lgs, filename);
}
-
/* Tree is used to create a "Virtual Folder" in CodeBlocks, in which all
CMake files this project depends on will be put. This means additionally
to the "Sources" and "Headers" virtual folders of CodeBlocks, there will
@@ -104,720 +93,683 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile(
files in QtCreator).*/
struct Tree
{
- std::string path; //only one component of the path
+ std::string path; // only one component of the path
std::vector<Tree> folders;
std::vector<std::string> files;
void InsertPath(const std::vector<std::string>& splitted,
std::vector<std::string>::size_type start,
const std::string& fileName);
- void BuildVirtualFolder(std::string& virtualFolders) const;
+ void BuildVirtualFolder(cmXMLWriter& xml) const;
void BuildVirtualFolderImpl(std::string& virtualFolders,
const std::string& prefix) const;
- void BuildUnit(std::string& unitString, const std::string& fsPath) const;
- void BuildUnitImpl(std::string& unitString,
- const std::string& virtualFolderPath,
+ void BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const;
+ void BuildUnitImpl(cmXMLWriter& xml, const std::string& virtualFolderPath,
const std::string& fsPath) const;
};
-
void Tree::InsertPath(const std::vector<std::string>& splitted,
std::vector<std::string>::size_type start,
const std::string& fileName)
{
- if (start == splitted.size())
- {
+ if (start == splitted.size()) {
files.push_back(fileName);
return;
- }
- for (std::vector<Tree>::iterator
- it = folders.begin();
- it != folders.end();
- ++it)
- {
- if ((*it).path == splitted[start])
- {
- if (start + 1 < splitted.size())
- {
+ }
+ for (std::vector<Tree>::iterator it = folders.begin(); it != folders.end();
+ ++it) {
+ if ((*it).path == splitted[start]) {
+ if (start + 1 < splitted.size()) {
it->InsertPath(splitted, start + 1, fileName);
return;
- }
- else
- {
- // last part of splitted
- it->files.push_back(fileName);
- return;
- }
}
+ // last part of splitted
+ it->files.push_back(fileName);
+ return;
}
+ }
// Not found in folders, thus insert
Tree newFolder;
newFolder.path = splitted[start];
- if (start + 1 < splitted.size())
- {
+ if (start + 1 < splitted.size()) {
newFolder.InsertPath(splitted, start + 1, fileName);
folders.push_back(newFolder);
return;
- }
- else
- {
- // last part of splitted
- newFolder.files.push_back(fileName);
- folders.push_back(newFolder);
- return;
- }
+ }
+ // last part of splitted
+ newFolder.files.push_back(fileName);
+ folders.push_back(newFolder);
}
-
-void Tree::BuildVirtualFolder(std::string& virtualFolders) const
+void Tree::BuildVirtualFolder(cmXMLWriter& xml) const
{
- virtualFolders += "<Option virtualFolders=\"CMake Files\\;";
+ xml.StartElement("Option");
+ std::string virtualFolders = "CMake Files\\;";
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
+ it != folders.end(); ++it) {
it->BuildVirtualFolderImpl(virtualFolders, "");
- }
- virtualFolders += "\" />";
+ }
+ xml.Attribute("virtualFolders", virtualFolders);
+ xml.EndElement();
}
-
void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
const std::string& prefix) const
{
- virtualFolders += "CMake Files\\" + prefix + path + "\\;";
+ virtualFolders += "CMake Files\\" + prefix + path + "\\;";
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
+ it != folders.end(); ++it) {
it->BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
- }
+ }
}
-
-void Tree::BuildUnit(std::string& unitString, const std::string& fsPath) const
+void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
{
for (std::vector<std::string>::const_iterator it = files.begin();
- it != files.end();
- ++it)
- {
- unitString += " <Unit filename=\"" + fsPath + *it + "\">\n";
- unitString += " <Option virtualFolder=\"CMake Files\\\" />\n";
- unitString += " </Unit>\n";
- }
+ it != files.end(); ++it) {
+ xml.StartElement("Unit");
+ xml.Attribute("filename", fsPath + *it);
+
+ xml.StartElement("Option");
+ xml.Attribute("virtualFolder", "CMake Files\\");
+ xml.EndElement();
+
+ xml.EndElement();
+ }
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
- it->BuildUnitImpl(unitString, "", fsPath);
- }
+ it != folders.end(); ++it) {
+ it->BuildUnitImpl(xml, "", fsPath);
+ }
}
-
-void Tree::BuildUnitImpl(std::string& unitString,
+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)
- {
- unitString += " <Unit filename=\"" +fsPath+path+ "/" + *it + "\">\n";
- unitString += " <Option virtualFolder=\"CMake Files\\"
- + virtualFolderPath + path + "\\\" />\n";
- unitString += " </Unit>\n";
- }
+ it != files.end(); ++it) {
+ xml.StartElement("Unit");
+ xml.Attribute("filename", fsPath + path + "/" + *it);
+
+ xml.StartElement("Option");
+ xml.Attribute("virtualFolder",
+ "CMake Files\\" + virtualFolderPath + path + "\\");
+ xml.EndElement();
+
+ xml.EndElement();
+ }
for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end();
- ++it)
- {
- it->BuildUnitImpl(unitString,
- virtualFolderPath + path + "\\", fsPath + path + "/");
- }
+ it != folders.end(); ++it) {
+ it->BuildUnitImpl(xml, virtualFolderPath + path + "\\",
+ fsPath + path + "/");
+ }
}
-
-void cmExtraCodeBlocksGenerator
- ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
- const std::string& filename)
+void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
- const cmMakefile* mf=lgs[0]->GetMakefile();
+ const cmMakefile* mf = lgs[0]->GetMakefile();
cmGeneratedFileStream fout(filename.c_str());
- if(!fout)
- {
+ if (!fout) {
return;
- }
+ }
Tree tree;
// build tree of virtual folders
- for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
+ for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
// 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();
+ 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());
- }
+ }
// Convert
- const char* cmakeRoot = mf->GetDefinition("CMAKE_ROOT");
for (std::vector<std::string>::const_iterator jt = listFiles.begin();
- jt != listFiles.end();
- ++jt)
- {
+ jt != listFiles.end(); ++jt) {
// don't put cmake's own files into the project (#12110):
- if (jt->find(cmakeRoot) == 0)
- {
+ if (jt->find(cmSystemTools::GetCMakeRoot()) == 0) {
continue;
- }
+ }
- const std::string &relative = cmSystemTools::RelativePath(
- it->second[0]->GetMakefile()->GetHomeDirectory(),
- jt->c_str());
+ const std::string& relative = cmSystemTools::RelativePath(
+ it->second[0]->GetSourceDirectory(), jt->c_str());
std::vector<std::string> splitted;
- cmSystemTools::SplitPath(relative.c_str(), splitted, false);
+ cmSystemTools::SplitPath(relative, splitted, false);
// Split filename from path
- std::string fileName = *(splitted.end()-1);
+ std::string fileName = *(splitted.end() - 1);
splitted.erase(splitted.end() - 1, splitted.end());
// We don't want paths with CMakeFiles in them
// or do we?
// In speedcrunch those where purely internal
- if (splitted.size() >= 1
- && relative.find("CMakeFiles") == std::string::npos)
- {
+ if (!splitted.empty() &&
+ relative.find("CMakeFiles") == std::string::npos) {
tree.InsertPath(splitted, 1, fileName);
- }
}
}
-
- // Now build a virtual tree string
- std::string virtualFolders;
- tree.BuildVirtualFolder(virtualFolders);
- // And one for <Unit>
- std::string unitFiles;
- tree.BuildUnit(unitFiles, std::string(mf->GetHomeDirectory()) + "/");
+ }
// figure out the compiler
std::string compiler = this->GetCBCompilerId(mf);
std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string makeArgs =
+ mf->GetSafeDefinition("CMAKE_CODEBLOCKS_MAKE_ARGUMENTS");
+
+ cmXMLWriter xml(fout);
+ xml.StartDocument();
+ xml.StartElement("CodeBlocks_project_file");
+
+ xml.StartElement("FileVersion");
+ xml.Attribute("major", 1);
+ xml.Attribute("minor", 6);
+ xml.EndElement();
+
+ xml.StartElement("Project");
+
+ xml.StartElement("Option");
+ xml.Attribute("title", lgs[0]->GetProjectName());
+ xml.EndElement();
- fout<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
- "<CodeBlocks_project_file>\n"
- " <FileVersion major=\"1\" minor=\"6\" />\n"
- " <Project>\n"
- " <Option title=\"" << mf->GetProjectName()<<"\" />\n"
- " <Option makefile_is_custom=\"1\" />\n"
- " <Option compiler=\"" << compiler << "\" />\n"
- " "<<virtualFolders<<"\n"
- " <Build>\n";
+ xml.StartElement("Option");
+ xml.Attribute("makefile_is_custom", 1);
+ xml.EndElement();
- this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str());
+ xml.StartElement("Option");
+ xml.Attribute("compiler", compiler);
+ xml.EndElement();
+
+ // Now build a virtual tree
+ tree.BuildVirtualFolder(xml);
+
+ xml.StartElement("Build");
+
+ this->AppendTarget(xml, "all", CM_NULLPTR, make.c_str(), lgs[0],
+ compiler.c_str(), 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++)
- {
- cmMakefile* makefile=(*lg)->GetMakefile();
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- switch(ti->second.GetType())
- {
- case cmTarget::GLOBAL_TARGET:
- {
- bool insertTarget = false;
+ 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()) {
+ case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp(makefile->GetStartOutputDirectory(),
- makefile->GetHomeOutputDirectory())==0)
- {
- insertTarget = true;
- // only add the "edit_cache" target if it's not ccmake, because
- // this will not work within the IDE
- if (ti->first == "edit_cache")
- {
- const char* editCommand = makefile->GetDefinition
- ("CMAKE_EDIT_COMMAND");
- if (editCommand == 0)
- {
- insertTarget = false;
- }
- else if (strstr(editCommand, "ccmake")!=NULL)
- {
- insertTarget = false;
- }
- }
- }
- if (insertTarget)
- {
- this->AppendTarget(fout, ti->first.c_str(), 0,
- make.c_str(), makefile, compiler.c_str());
- }
+ if (strcmp((*lg)->GetCurrentBinaryDirectory(),
+ (*lg)->GetBinaryDirectory()) == 0) {
+ this->AppendTarget(xml, targetName, CM_NULLPTR, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
}
- break;
- case cmTarget::UTILITY:
+ } break;
+ case cmStateEnums::UTILITY:
// Add all utility targets, except the Nightly/Continuous/
// Experimental-"sub"targets as e.g. NightlyStart
- if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly"))
- || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
- || ((ti->first.find("Experimental")==0)
- && (ti->first!="Experimental")))
- {
+ if (((targetName.find("Nightly") == 0) &&
+ (targetName != "Nightly")) ||
+ ((targetName.find("Continuous") == 0) &&
+ (targetName != "Continuous")) ||
+ ((targetName.find("Experimental") == 0) &&
+ (targetName != "Experimental"))) {
break;
- }
+ }
- this->AppendTarget(fout, ti->first.c_str(), 0,
- make.c_str(), makefile, compiler.c_str());
+ this->AppendTarget(xml, targetName, CM_NULLPTR, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
break;
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- {
- this->AppendTarget(fout, ti->first.c_str(), &ti->second,
- make.c_str(), makefile, compiler.c_str());
- std::string fastTarget = ti->first;
+ 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(fout, fastTarget.c_str(), &ti->second,
- make.c_str(), makefile, compiler.c_str());
- }
- break;
+ this->AppendTarget(xml, fastTarget, gt, make.c_str(), *lg,
+ compiler.c_str(), makeArgs);
+ } break;
default:
break;
- }
}
}
-
- fout<<" </Build>\n";
-
-
- // 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
- 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();
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- switch(ti->second.GetType())
+ }
+
+ 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
+ // that should be looked for.
+ typedef std::map<std::string, CbpUnit> all_files_map_t;
+ all_files_map_t allFiles;
+ std::vector<std::string> cFiles;
+
+ std::vector<std::string> const& srcExts =
+ this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
+
+ 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()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::UTILITY: // can have sources since 2.6.3
{
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::UTILITY: // can have sources since 2.6.3
- {
- const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
- for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();
- si!=sources.end(); si++)
- {
- // don't add source files which have the GENERATED property set:
- if ((*si)->GetPropertyAsBool("GENERATED"))
- {
+ std::vector<cmSourceFile*> sources;
+ cmGeneratorTarget* gt = *ti;
+ gt->GetSourceFiles(sources,
+ makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
+ for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
+ si != sources.end(); si++) {
+ // don't add source files from UTILITY target which have the
+ // GENERATED property set:
+ if (gt->GetType() == cmStateEnums::UTILITY &&
+ (*si)->GetPropertyAsBool("GENERATED")) {
continue;
- }
+ }
// check whether it is a C/C++ implementation file
bool isCFile = false;
- if ((*si)->GetLanguage() && (*(*si)->GetLanguage() == 'C'))
- {
- for(std::vector<std::string>::const_iterator
- ext = mf->GetSourceExtensions().begin();
- ext != mf->GetSourceExtensions().end();
- ++ext)
- {
- if ((*si)->GetExtension() == *ext)
- {
+ 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;
- }
}
}
+ }
- // then put it accordingly into one of the two containers
- if (isCFile)
- {
- cFiles[(*si)->GetFullPath()] = *si ;
- }
- else
- {
- otherFiles.insert((*si)->GetFullPath());
- }
+ std::string const& fullPath = (*si)->GetFullPath();
+
+ if (isCFile) {
+ cFiles.push_back(fullPath);
}
+
+ CbpUnit& cbpUnit = allFiles[fullPath];
+ cbpUnit.Targets.push_back(*ti);
}
- default: // intended fallthrough
- break;
}
+ default: // intended fallthrough
+ break;
}
}
+ }
+
+ std::vector<std::string> const& headerExts =
+ this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
// The following loop tries to add header files matching to implementation
- // files to the project. It does that by iterating over all source files,
+ // files to the project. It does that by iterating over all
+ // 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
// 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 (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);
// check if there's a matching header around
- for(std::vector<std::string>::const_iterator
- ext = mf->GetHeaderExtensions().begin();
- ext != mf->GetHeaderExtensions().end();
- ++ext)
- {
- std::string hname=headerBasename;
+ for (std::vector<std::string>::const_iterator ext = headerExts.begin();
+ ext != headerExts.end(); ++ext) {
+ std::string hname = headerBasename;
hname += ".";
hname += *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);
- if (headerIt != otherFiles.end())
- {
+ if (allFiles.find(hname) != allFiles.end()) {
break;
- }
+ }
- if(cmSystemTools::FileExists(hname.c_str()))
- {
- otherFiles.insert(hname);
+ if (cmSystemTools::FileExists(hname.c_str())) {
+ allFiles[hname].Targets = allFiles[fileName].Targets;
break;
- }
}
}
+ }
// insert all source files in the CodeBlocks project
- // first the C/C++ implementation files, then all others
- for (std::map<std::string, cmSourceFile*>::const_iterator
- sit=cFiles.begin();
- sit!=cFiles.end();
- ++sit)
- {
- fout<<" <Unit filename=\""<< sit->first <<"\">\n"
- " </Unit>\n";
- }
- for (std::set<std::string>::const_iterator
- sit=otherFiles.begin();
- sit!=otherFiles.end();
- ++sit)
- {
- fout<<" <Unit filename=\""<< sit->c_str() <<"\">\n"
- " </Unit>\n";
+ 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;
+
+ xml.StartElement("Unit");
+ xml.Attribute("filename", unitFilename);
+
+ for (std::vector<const cmGeneratorTarget*>::const_iterator ti =
+ unit.Targets.begin();
+ ti != unit.Targets.end(); ++ti) {
+ xml.StartElement("Option");
+ xml.Attribute("target", (*ti)->GetName());
+ xml.EndElement();
}
+ xml.EndElement();
+ }
+
// Add CMakeLists.txt
- fout<<unitFiles;
+ tree.BuildUnit(xml, std::string(mf->GetHomeDirectory()) + "/");
- fout<<" </Project>\n"
- "</CodeBlocks_project_file>\n";
+ xml.EndElement(); // Project
+ xml.EndElement(); // CodeBlocks_project_file
+ xml.EndDocument();
}
-
// Write a dummy file for OBJECT libraries, so C::B can reference some file
std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
- cmMakefile* mf, cmTarget* target) const
+ cmLocalGenerator* lg, cmGeneratorTarget* target) const
{
// 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 = mf->GetCurrentOutputDirectory();
+ std::string filename = lg->GetCurrentBinaryDirectory();
filename += "/";
- filename += mf->GetLocalGenerator()->GetTargetDirectory(*target);
+ filename += lg->GetTargetDirectory(target);
filename += "/";
filename += target->GetName();
filename += ".objlib";
cmGeneratedFileStream fout(filename.c_str());
- if(fout)
- {
+ if (fout) {
+ /* clang-format off */
fout << "# This is a dummy file for the OBJECT library "
<< target->GetName()
<< " for the CMake CodeBlocks project generator.\n"
<< "# Don't edit, this file will be overwritten.\n";
- }
+ /* clang-format on */
+ }
return filename;
}
-
// Generate the xml code for one target.
-void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
- const char* targetName,
- cmTarget* target,
- const char* make,
- const cmMakefile* makefile,
- const char* compiler)
+void cmExtraCodeBlocksGenerator::AppendTarget(
+ cmXMLWriter& xml, const std::string& targetName, cmGeneratorTarget* target,
+ const char* make, const cmLocalGenerator* lg, const char* compiler,
+ const std::string& makeFlags)
{
- std::string makefileName = makefile->GetStartOutputDirectory();
+ cmMakefile const* makefile = lg->GetMakefile();
+ std::string makefileName = lg->GetCurrentBinaryDirectory();
makefileName += "/Makefile";
- fout<<" <Target title=\"" << targetName << "\">\n";
- if (target!=0)
- {
+ xml.StartElement("Target");
+ xml.Attribute("title", targetName);
+
+ if (target != CM_NULLPTR) {
int cbTargetType = this->GetCBTargetType(target);
- std::string workingDir = makefile->GetStartOutputDirectory();
- if ( target->GetType()==cmTarget::EXECUTABLE)
- {
+ std::string workingDir = lg->GetCurrentBinaryDirectory();
+ if (target->GetType() == cmStateEnums::EXECUTABLE) {
// Determine the directory where the executable target is created, and
// set the working directory to this dir.
- const char* runtimeOutputDir = makefile->GetDefinition(
- "CMAKE_RUNTIME_OUTPUT_DIRECTORY");
- if (runtimeOutputDir != 0)
- {
+ const char* runtimeOutputDir =
+ makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
+ if (runtimeOutputDir != CM_NULLPTR) {
workingDir = runtimeOutputDir;
- }
- else
- {
- const char* executableOutputDir = makefile->GetDefinition(
- "EXECUTABLE_OUTPUT_PATH");
- if (executableOutputDir != 0)
- {
+ } else {
+ const char* executableOutputDir =
+ makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
+ if (executableOutputDir != CM_NULLPTR) {
workingDir = executableOutputDir;
- }
}
}
+ }
- const char* buildType = makefile->GetDefinition("CMAKE_BUILD_TYPE");
+ std::string buildType = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
std::string location;
- if ( target->GetType()==cmTarget::OBJECT_LIBRARY)
- {
- location = this->CreateDummyTargetFile(const_cast<cmMakefile*>(makefile),
- target);
- }
- else
- {
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ location =
+ this->CreateDummyTargetFile(const_cast<cmLocalGenerator*>(lg), target);
+ } else {
location = target->GetLocation(buildType);
- }
+ }
+
+ xml.StartElement("Option");
+ xml.Attribute("output", location);
+ xml.Attribute("prefix_auto", 0);
+ xml.Attribute("extension_auto", 0);
+ xml.EndElement();
+
+ xml.StartElement("Option");
+ xml.Attribute("working_dir", workingDir);
+ xml.EndElement();
- fout<<" <Option output=\"" << location
- << "\" prefix_auto=\"0\" extension_auto=\"0\" />\n"
- " <Option working_dir=\"" << workingDir << "\" />\n"
- " <Option object_output=\"./\" />\n"
- " <Option type=\"" << cbTargetType << "\" />\n"
- " <Option compiler=\"" << compiler << "\" />\n"
- " <Compiler>\n";
+ xml.StartElement("Option");
+ xml.Attribute("object_output", "./");
+ xml.EndElement();
- cmGeneratorTarget *gtgt = this->GlobalGenerator
- ->GetGeneratorTarget(target);
+ xml.StartElement("Option");
+ xml.Attribute("type", cbTargetType);
+ xml.EndElement();
+
+ xml.StartElement("Option");
+ xml.Attribute("compiler", compiler);
+ xml.EndElement();
+
+ xml.StartElement("Compiler");
// the compilerdefines for this target
std::vector<std::string> cdefs;
- target->GetCompileDefinitions(cdefs, buildType);
+ target->GetCompileDefinitions(cdefs, buildType, "C");
// Expand the list.
- for(std::vector<std::string>::const_iterator di = cdefs.begin();
- di != cdefs.end(); ++di)
- {
- cmXMLSafe safedef(di->c_str());
- fout <<" <Add option=\"-D" << safedef.str() << "\" />\n";
- }
+ for (std::vector<std::string>::const_iterator di = cdefs.begin();
+ di != cdefs.end(); ++di) {
+ xml.StartElement("Add");
+ xml.Attribute("option", "-D" + *di);
+ xml.EndElement();
+ }
// the include directories for this target
- std::set<std::string> uniqIncludeDirs;
+ std::vector<std::string> allIncludeDirs;
std::vector<std::string> includes;
- target->GetMakefile()->GetLocalGenerator()->
- GetIncludeDirectories(includes, gtgt, "C", buildType);
- for(std::vector<std::string>::const_iterator dirIt=includes.begin();
- dirIt != includes.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
+ lg->GetIncludeDirectories(includes, target, "C", buildType);
+
+ allIncludeDirs.insert(allIncludeDirs.end(), includes.begin(),
+ includes.end());
std::string systemIncludeDirs = makefile->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
- if (!systemIncludeDirs.empty())
- {
+ "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
+ if (!systemIncludeDirs.empty()) {
std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
- for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
- }
+ cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+ }
systemIncludeDirs = makefile->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
- if (!systemIncludeDirs.empty())
- {
+ "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
+ if (!systemIncludeDirs.empty()) {
std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
- for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
- }
+ cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+ }
- for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin();
- dirIt != uniqIncludeDirs.end();
- ++dirIt)
- {
- fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n";
- }
+ std::vector<std::string>::const_iterator end =
+ cmRemoveDuplicates(allIncludeDirs);
- fout<<" </Compiler>\n";
- }
- else // e.g. all and the GLOBAL and UTILITY targets
- {
- fout<<" <Option working_dir=\""
- << makefile->GetStartOutputDirectory() << "\" />\n"
- <<" <Option type=\"" << 4 << "\" />\n";
+ for (std::vector<std::string>::const_iterator i = allIncludeDirs.begin();
+ i != end; ++i) {
+ xml.StartElement("Add");
+ xml.Attribute("directory", *i);
+ xml.EndElement();
}
- fout<<" <MakeCommands>\n"
- " <Build command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(), targetName)
- << "\" />\n"
- " <CompileFile command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(),"&quot;$file&quot;")
- << "\" />\n"
- " <Clean command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
- << "\" />\n"
- " <DistClean command=\""
- << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
- << "\" />\n"
- " </MakeCommands>\n"
- " </Target>\n";
+ xml.EndElement(); // Compiler
+ } else // e.g. all and the GLOBAL and UTILITY targets
+ {
+ xml.StartElement("Option");
+ xml.Attribute("working_dir", lg->GetCurrentBinaryDirectory());
+ xml.EndElement();
-}
+ xml.StartElement("Option");
+ xml.Attribute("type", 4);
+ xml.EndElement();
+ }
+
+ xml.StartElement("MakeCommands");
+ xml.StartElement("Build");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ targetName, makeFlags));
+ xml.EndElement();
+
+ xml.StartElement("CompileFile");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ "\"$file\"", makeFlags));
+ xml.EndElement();
+
+ xml.StartElement("Clean");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ "clean", makeFlags));
+ xml.EndElement();
+
+ xml.StartElement("DistClean");
+ xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
+ "clean", makeFlags));
+ xml.EndElement();
+
+ xml.EndElement(); // MakeCommands
+ xml.EndElement(); // Target
+}
// Translate the cmake compiler id into the CodeBlocks compiler id
std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
{
// figure out which language to use
- // for now care only for C and C++
- std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
- if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false)
- {
+ // for now care only for C, C++, and Fortran
+
+ // projects with C/C++ and Fortran are handled as C/C++ projects
+ bool pureFortran = false;
+ std::string compilerIdVar;
+ if (this->GlobalGenerator->GetLanguageEnabled("CXX")) {
+ compilerIdVar = "CMAKE_CXX_COMPILER_ID";
+ } else if (this->GlobalGenerator->GetLanguageEnabled("C")) {
compilerIdVar = "CMAKE_C_COMPILER_ID";
- }
-
- std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
- std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- std::string compilerId = mf->GetSafeDefinition(compilerIdVar.c_str());
- std::string compiler = "gcc"; // default to gcc
- if (compilerId == "MSVC")
- {
- compiler = "msvc8";
- }
- else if (compilerId == "Borland")
- {
+ } else if (this->GlobalGenerator->GetLanguageEnabled("Fortran")) {
+ compilerIdVar = "CMAKE_Fortran_COMPILER_ID";
+ pureFortran = true;
+ }
+
+ std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string compiler = "gcc"; // default to gcc
+ if (compilerId == "MSVC") {
+ if (mf->IsDefinitionSet("MSVC10")) {
+ compiler = "msvc10";
+ } else {
+ compiler = "msvc8";
+ }
+ } else if (compilerId == "Borland") {
compiler = "bcc";
- }
- else if (compilerId == "SDCC")
- {
+ } else if (compilerId == "SDCC") {
compiler = "sdcc";
+ } else if (compilerId == "Intel") {
+ if (pureFortran && mf->IsDefinitionSet("WIN32")) {
+ compiler = "ifcwin"; // Intel Fortran for Windows (known by cbFortran)
+ } else {
+ compiler = "icc";
}
- else if (compilerId == "Intel")
- {
- compiler = "icc";
- }
- else if (compilerId == "Watcom")
- {
+ } else if (compilerId == "Watcom" || compilerId == "OpenWatcom") {
compiler = "ow";
- }
- else if (compilerId == "GNU")
- {
- compiler = "gcc";
- }
+ } else if (compilerId == "Clang") {
+ compiler = "clang";
+ } else if (compilerId == "PGI") {
+ if (pureFortran) {
+ compiler = "pgifortran";
+ } else {
+ compiler = "pgi"; // does not exist as default in CodeBlocks 16.01
+ }
+ } else if (compilerId == "GNU") {
+ if (pureFortran) {
+ compiler = "gfortran";
+ } else {
+ compiler = "gcc";
+ }
+ }
return compiler;
}
-
// Translate the cmake target type into the CodeBlocks target type id
-int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
+int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target)
{
- if ( target->GetType()==cmTarget::EXECUTABLE)
- {
- if ((target->GetPropertyAsBool("WIN32_EXECUTABLE"))
- || (target->GetPropertyAsBool("MACOSX_BUNDLE")))
- {
- return 0;
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ if ((target->GetPropertyAsBool("WIN32_EXECUTABLE")) ||
+ (target->GetPropertyAsBool("MACOSX_BUNDLE"))) {
+ return 0;
}
- else
- {
return 1;
- }
- }
- else if (( target->GetType()==cmTarget::STATIC_LIBRARY)
- || (target->GetType()==cmTarget::OBJECT_LIBRARY))
- {
- return 2;
- }
- else if ((target->GetType()==cmTarget::SHARED_LIBRARY)
- || (target->GetType()==cmTarget::MODULE_LIBRARY))
- {
- return 3;
- }
- return 4;
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ return 2;
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ return 3;
+ default:
+ return 4;
+ }
}
// 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 char* target)
+ const std::string& make, const char* makefile, const std::string& target,
+ const std::string& makeFlags)
{
std::string command = make;
- if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
- {
+ if (!makeFlags.empty()) {
+ command += " ";
+ command += makeFlags;
+ }
+
+ std::string generator = this->GlobalGenerator->GetName();
+ if (generator == "NMake Makefiles" || generator == "NMake Makefiles JOM") {
+ // For Windows ConvertToOutputPath already adds quotes when required.
+ // These need to be escaped, see
+ // https://gitlab.kitware.com/cmake/cmake/issues/13952
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += " /NOLOGO /f &quot;";
+ command += " /NOLOGO /f ";
command += makefileName;
- command += "&quot; ";
command += " VERBOSE=1 ";
command += target;
- }
- else if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
- {
+ } else if (generator == "MinGW Makefiles") {
// no escaping of spaces in this case, see
- // http://public.kitware.com/Bug/view.php?id=10014
+ // https://gitlab.kitware.com/cmake/cmake/issues/10014
std::string makefileName = makefile;
- command += " -f &quot;";
+ command += " -f \"";
command += makefileName;
- command += "&quot; ";
+ command += "\" ";
command += " VERBOSE=1 ";
command += target;
- }
- else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
- {
+ } else if (generator == "Ninja") {
command += " -v ";
command += target;
- }
- else
- {
+ } else {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += " -f &quot;";
+ command += " -f \"";
command += makefileName;
- command += "&quot; ";
+ command += "\" ";
command += " VERBOSE=1 ";
command += target;
- }
+ }
return command;
}
diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h
index e0a64ca01..450a9d02c 100644
--- a/Source/cmExtraCodeBlocksGenerator.h
+++ b/Source/cmExtraCodeBlocksGenerator.h
@@ -1,24 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExtraCodeBlocksGenerator_h
#define cmExtraCodeBlocksGenerator_h
+#include "cmConfigure.h"
+
#include "cmExternalMakefileProjectGenerator.h"
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
class cmLocalGenerator;
class cmMakefile;
-class cmTarget;
-class cmGeneratedFileStream;
+class cmXMLWriter;
/** \class cmExtraCodeBlocksGenerator
* \brief Write CodeBlocks project files for Makefile based projects
@@ -28,35 +23,32 @@ class cmExtraCodeBlocksGenerator : public cmExternalMakefileProjectGenerator
public:
cmExtraCodeBlocksGenerator();
- virtual const char* GetName() const
- { return cmExtraCodeBlocksGenerator::GetActualName();}
- static const char* GetActualName() { return "CodeBlocks";}
- static cmExternalMakefileProjectGenerator* New()
- { return new cmExtraCodeBlocksGenerator; }
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry,
- const char* fullName) const;
+ static cmExternalMakefileProjectGeneratorFactory* GetFactory();
+
+ void Generate() CM_OVERRIDE;
- virtual void Generate();
private:
+ struct CbpUnit
+ {
+ std::vector<const cmGeneratorTarget*> Targets;
+ };
void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
- const std::string& filename);
- std::string CreateDummyTargetFile(cmMakefile* mf, cmTarget* target) const;
+ const std::string& filename);
+ std::string CreateDummyTargetFile(cmLocalGenerator* lg,
+ cmGeneratorTarget* target) const;
std::string GetCBCompilerId(const cmMakefile* mf);
- int GetCBTargetType(cmTarget* target);
+ int GetCBTargetType(cmGeneratorTarget* target);
std::string BuildMakeCommand(const std::string& make, const char* makefile,
- const char* target);
- void AppendTarget(cmGeneratedFileStream& fout,
- const char* targetName,
- cmTarget* target,
- const char* make,
- const cmMakefile* makefile,
- const char* compiler);
-
+ 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,
+ const std::string& makeFlags);
};
#endif
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
new file mode 100644
index 000000000..b478f34fa
--- /dev/null
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -0,0 +1,710 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExtraCodeLiteGenerator.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 "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)
+{
+}
+
+cmExternalMakefileProjectGeneratorFactory*
+cmExtraCodeLiteGenerator::GetFactory()
+{
+ static cmExternalMakefileProjectGeneratorSimpleFactory<
+ cmExtraCodeLiteGenerator>
+ factory("CodeLite", "Generates CodeLite project files.");
+
+ if (factory.GetSupportedGlobalGenerators().empty()) {
+#if defined(_WIN32)
+ factory.AddSupportedGlobalGenerator("MinGW Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles");
+#endif
+ factory.AddSupportedGlobalGenerator("Ninja");
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
+ }
+
+ return &factory;
+}
+
+void cmExtraCodeLiteGenerator::Generate()
+{
+ // Hold root tree information for creating the workspace
+ std::string workspaceProjectName;
+ std::string workspaceOutputDir;
+ std::string workspaceFileName;
+ std::string workspaceSourcePath;
+
+ 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();
+ 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();
+ ;
+ break;
+ }
+ }
+
+ cmGeneratedFileStream fout(workspaceFileName.c_str());
+ cmXMLWriter xml(fout);
+
+ xml.StartDocument("utf-8");
+ xml.StartElement("CodeLite_Workspace");
+ xml.Attribute("Name", workspaceProjectName);
+
+ bool const targetsAreProjects =
+ this->GlobalGenerator->GlobalSettingIsOn("CMAKE_CODELITE_USE_TARGETS");
+
+ std::vector<std::string> ProjectNames;
+ if (targetsAreProjects) {
+ ProjectNames = CreateProjectsByTarget(&xml);
+ } else {
+ ProjectNames = CreateProjectsByProjectMaps(&xml);
+ }
+
+ xml.StartElement("BuildMatrix");
+ xml.StartElement("WorkspaceConfiguration");
+ xml.Attribute("Name", this->ConfigName);
+ xml.Attribute("Selected", "yes");
+
+ for (std::vector<std::string>::iterator it(ProjectNames.begin());
+ it != ProjectNames.end(); it++) {
+ xml.StartElement("Project");
+ xml.Attribute("Name", *it);
+ xml.Attribute("ConfigName", this->ConfigName);
+ xml.EndElement();
+ }
+
+ xml.EndElement(); // WorkspaceConfiguration
+ xml.EndElement(); // BuildMatrix
+ xml.EndElement(); // CodeLite_Workspace
+}
+
+// Create projects where targets are the projects
+std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
+ cmXMLWriter* xml)
+{
+ std::vector<std::string> retval;
+ // 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";
+ 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 visualname = targetName;
+ switch (type) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ visualname = "lib" + visualname;
+ CM_FALLTHROUGH;
+ case cmStateEnums::EXECUTABLE:
+ xml->StartElement("Project");
+ xml->Attribute("Name", visualname);
+ xml->Attribute("Path", relafilename);
+ xml->Attribute("Active", "No");
+ xml->EndElement();
+
+ CreateNewProjectFile(*lt, filename);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return retval;
+}
+
+// The "older way of doing it.
+std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
+ cmXMLWriter* xml)
+{
+ 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++) {
+
+ std::string outputDir = it->second[0]->GetCurrentBinaryDirectory();
+ std::string projectName = it->second[0]->GetProjectName();
+ retval.push_back(projectName);
+ std::string filename = outputDir + "/" + projectName + ".project";
+
+ // Make the project file relative to the workspace
+ filename = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
+ filename.c_str());
+
+ // create a project file
+ this->CreateProjectFile(it->second);
+ xml->StartElement("Project");
+ xml->Attribute("Name", projectName);
+ xml->Attribute("Path", filename);
+ xml->Attribute("Active", "No");
+ xml->EndElement();
+ }
+ return retval;
+}
+
+/* create the project file */
+void cmExtraCodeLiteGenerator::CreateProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs)
+{
+ std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
+ std::string projectName = lgs[0]->GetProjectName();
+ std::string filename = outputDir + "/";
+
+ filename += projectName + ".project";
+ this->CreateNewProjectFile(lgs, filename);
+}
+
+std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
+ const cmMakefile* makefile, const cmGeneratorTarget* gt,
+ 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: {
+ projectType = "Executable";
+ } break;
+ case cmStateEnums::STATIC_LIBRARY: {
+ projectType = "Static Library";
+ } break;
+ case cmStateEnums::SHARED_LIBRARY: {
+ projectType = "Dynamic Library";
+ } break;
+ case cmStateEnums::MODULE_LIBRARY: {
+ projectType = "Dynamic Library";
+ } break;
+ default: // intended fallthrough
+ break;
+ }
+
+ switch (gt->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY: {
+ 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;
+ }
+ }
+ }
+
+ // then put it accordingly into one of the two containers
+ if (isCFile) {
+ cFiles[(*si)->GetFullPath()] = *si;
+ } else {
+ otherFiles.insert((*si)->GetFullPath());
+ }
+ }
+ }
+ default: // intended fallthrough
+ break;
+ }
+ return projectType;
+}
+
+void cmExtraCodeLiteGenerator::CreateNewProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
+{
+ const cmMakefile* mf = lgs[0]->GetMakefile();
+ cmGeneratedFileStream fout(filename.c_str());
+ if (!fout) {
+ return;
+ }
+ cmXMLWriter xml(fout);
+
+ ////////////////////////////////////
+ xml.StartDocument("utf-8");
+ xml.StartElement("CodeLite_Project");
+ xml.Attribute("Name", lgs[0]->GetProjectName());
+ xml.Attribute("InternalType", "");
+
+ std::string projectType;
+
+ // 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
+ 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);
+ }
+ }
+
+ // Get the project path ( we need it later to convert files to
+ // their relative path)
+ std::string projectPath = cmSystemTools::GetFilenamePath(filename);
+
+ CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
+ projectType, "");
+
+ xml.EndElement(); // CodeLite_Project
+}
+
+void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
+ std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles)
+{
+
+ const std::vector<std::string>& headerExts =
+ this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
+
+ // The following loop tries to add header files matching to implementation
+ // 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
+ // 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);
+
+ // 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;
+ // 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);
+ if (headerIt != otherFiles.end()) {
+ break;
+ }
+
+ if (cmSystemTools::FileExists(hname.c_str())) {
+ otherFiles.insert(hname);
+ break;
+ }
+ }
+ }
+}
+
+void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
+ std::set<std::string>& cFiles, cmXMLWriter& xml,
+ const std::string& projectPath)
+{
+ std::vector<std::string> tmp_path;
+ 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());
+ cmsys::SystemTools::SplitPath(frelapath, components, false);
+ components.pop_back(); // erase last member -> it is file, not folder
+ components.erase(components.begin()); // erase "root"
+
+ size_t sizeOfSkip = 0;
+
+ for (size_t i = 0; i < components.size(); ++i) {
+ // skip relative path
+ if (components[i] == ".." || components[i] == ".") {
+ sizeOfSkip++;
+ continue;
+ }
+
+ // same folder
+ if (tmp_path.size() > i - sizeOfSkip &&
+ tmp_path[i - sizeOfSkip] == components[i]) {
+ continue;
+ }
+
+ // delete "old" subfolders
+ if (tmp_path.size() > i - sizeOfSkip) {
+ numOfEndEl = tmp_path.size() - i + sizeOfSkip;
+ tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
+ for (; numOfEndEl--;) {
+ xml.EndElement();
+ }
+ }
+
+ // add folder
+ xml.StartElement("VirtualDirectory");
+ xml.Attribute("Name", components[i]);
+ tmp_path.push_back(components[i]);
+ }
+
+ // delete "old" subfolders
+ numOfEndEl = tmp_path.size() - components.size() + sizeOfSkip;
+ if (numOfEndEl) {
+ tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
+ for (; numOfEndEl--;) {
+ xml.EndElement();
+ }
+ }
+
+ // add file
+ xml.StartElement("File");
+ xml.Attribute("Name", frelapath);
+ xml.EndElement();
+ }
+
+ // end of folders
+ numOfEndEl = tmp_path.size();
+ for (; numOfEndEl--;) {
+ xml.EndElement();
+ }
+}
+
+void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
+ std::map<std::string, cmSourceFile*>& cFiles, cmXMLWriter& xml,
+ 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);
+ }
+ this->CreateFoldersAndFiles(s, xml, projectPath);
+}
+
+void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
+ std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles, cmXMLWriter* _xml,
+ 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
+ // and place all the implementation files into the src
+ // folder, the rest goes to the include folder
+ xml.StartElement("VirtualDirectory");
+ xml.Attribute("Name", "src");
+
+ // insert all source files in the codelite project
+ // first the C/C++ implementation files, then all others
+ this->CreateFoldersAndFiles(cFiles, xml, projectPath);
+ xml.EndElement(); // VirtualDirectory
+
+ xml.StartElement("VirtualDirectory");
+ xml.Attribute("Name", "include");
+ this->CreateFoldersAndFiles(otherFiles, xml, projectPath);
+ xml.EndElement(); // VirtualDirectory
+
+ // Get the number of CPUs. We use this information for the make -jN
+ // command
+ cmsys::SystemInformation info;
+ info.RunCPUCheck();
+
+ this->CpuCount =
+ info.GetNumberOfLogicalCPU() * info.GetNumberOfPhysicalCPU();
+
+ std::string codeliteCompilerName = this->GetCodeLiteCompilerName(mf);
+
+ xml.StartElement("Settings");
+ xml.Attribute("Type", projectType);
+
+ xml.StartElement("Configuration");
+ xml.Attribute("Name", this->ConfigName);
+ xml.Attribute("CompilerType", this->GetCodeLiteCompilerName(mf));
+ xml.Attribute("DebuggerType", "GNU gdb debugger");
+ xml.Attribute("Type", projectType);
+ xml.Attribute("BuildCmpWithGlobalSettings", "append");
+ xml.Attribute("BuildLnkWithGlobalSettings", "append");
+ xml.Attribute("BuildResWithGlobalSettings", "append");
+
+ xml.StartElement("Compiler");
+ xml.Attribute("Options", "-g");
+ xml.Attribute("Required", "yes");
+ xml.Attribute("PreCompiledHeader", "");
+ xml.StartElement("IncludePath");
+ xml.Attribute("Value", ".");
+ xml.EndElement(); // IncludePath
+ xml.EndElement(); // Compiler
+
+ xml.StartElement("Linker");
+ xml.Attribute("Options", "");
+ xml.Attribute("Required", "yes");
+ xml.EndElement(); // Linker
+
+ xml.StartElement("ResourceCompiler");
+ xml.Attribute("Options", "");
+ xml.Attribute("Required", "no");
+ xml.EndElement(); // ResourceCompiler
+
+ xml.StartElement("General");
+ std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ std::string relapath;
+ if (!outputPath.empty()) {
+ relapath = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
+ outputPath.c_str());
+ xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
+ } else {
+ xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
+ }
+ xml.Attribute("IntermediateDirectory", "./");
+ xml.Attribute("Command", "./$(ProjectName)");
+ xml.Attribute("CommandArguments", "");
+ if (!outputPath.empty()) {
+ xml.Attribute("WorkingDirectory", relapath);
+ } else {
+ xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)");
+ }
+ xml.Attribute("PauseExecWhenProcTerminates", "yes");
+ xml.EndElement(); // General
+
+ xml.StartElement("Debugger");
+ xml.Attribute("IsRemote", "no");
+ xml.Attribute("RemoteHostName", "");
+ xml.Attribute("RemoteHostPort", "");
+ xml.Attribute("DebuggerPath", "");
+ xml.Element("PostConnectCommands");
+ xml.Element("StartupCommands");
+ xml.EndElement(); // Debugger
+
+ xml.Element("PreBuild");
+ xml.Element("PostBuild");
+
+ xml.StartElement("CustomBuild");
+ xml.Attribute("Enabled", "yes");
+ xml.Element("RebuildCommand", GetRebuildCommand(mf, targetName));
+ xml.Element("CleanCommand", GetCleanCommand(mf, targetName));
+ xml.Element("BuildCommand", GetBuildCommand(mf, targetName));
+ xml.Element("SingleFileCommand", GetSingleFileBuildCommand(mf));
+ xml.Element("PreprocessFileCommand");
+ xml.Element("WorkingDirectory", "$(WorkspacePath)");
+ xml.EndElement(); // CustomBuild
+
+ xml.StartElement("AdditionalRules");
+ xml.Element("CustomPostBuild");
+ xml.Element("CustomPreBuild");
+ xml.EndElement(); // AdditionalRules
+
+ xml.EndElement(); // Configuration
+ xml.StartElement("GlobalSettings");
+
+ xml.StartElement("Compiler");
+ xml.Attribute("Options", "");
+ xml.StartElement("IncludePath");
+ xml.Attribute("Value", ".");
+ xml.EndElement(); // IncludePath
+ xml.EndElement(); // Compiler
+
+ xml.StartElement("Linker");
+ xml.Attribute("Options", "");
+ xml.StartElement("LibraryPath");
+ xml.Attribute("Value", ".");
+ xml.EndElement(); // LibraryPath
+ xml.EndElement(); // Linker
+
+ xml.StartElement("ResourceCompiler");
+ xml.Attribute("Options", "");
+ xml.EndElement(); // ResourceCompiler
+
+ xml.EndElement(); // GlobalSettings
+ xml.EndElement(); // Settings
+}
+
+void cmExtraCodeLiteGenerator::CreateNewProjectFile(
+ const cmGeneratorTarget* gt, const std::string& filename)
+{
+ const cmMakefile* mf = gt->Makefile;
+ cmGeneratedFileStream fout(filename.c_str());
+ if (!fout) {
+ return;
+ }
+ cmXMLWriter xml(fout);
+
+ ////////////////////////////////////
+ xml.StartDocument("utf-8");
+ xml.StartElement("CodeLite_Project");
+ std::string targetName = gt->GetName();
+ std::string visualname = targetName;
+ switch (gt->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ visualname = "lib" + targetName;
+ default: // intended fallthrough
+ break;
+ }
+ xml.Attribute("Name", visualname);
+ xml.Attribute("InternalType", "");
+
+ // 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
+ std::string projectType;
+
+ std::map<std::string, cmSourceFile*> cFiles;
+ std::set<std::string> otherFiles;
+
+ projectType = CollectSourceFiles(mf, gt, cFiles, otherFiles);
+
+ // Get the project path ( we need it later to convert files to
+ // their relative path)
+ std::string projectPath = cmSystemTools::GetFilenamePath(filename);
+
+ CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
+ projectType, targetName);
+
+ xml.EndElement(); // CodeLite_Project
+}
+
+std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName(
+ const cmMakefile* mf) const
+{
+ // figure out which language to use
+ // for now care only for C and C++
+ std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
+ if (!this->GlobalGenerator->GetLanguageEnabled("CXX")) {
+ compilerIdVar = "CMAKE_C_COMPILER_ID";
+ }
+
+ std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string compiler = "gnu g++"; // default to g++
+
+ // Since we need the compiler for parsing purposes only
+ // it does not matter if we use clang or clang++, same as
+ // "gnu gcc" vs "gnu g++"
+ if (compilerId == "MSVC") {
+ compiler = "VC++";
+ } else if (compilerId == "Clang") {
+ compiler = "clang++";
+ } else if (compilerId == "GNU") {
+ compiler = "gnu g++";
+ }
+ return compiler;
+}
+
+std::string cmExtraCodeLiteGenerator::GetConfigurationName(
+ const cmMakefile* mf) const
+{
+ std::string confName = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ // Trim the configuration name from whitespaces (left and right)
+ confName.erase(0, confName.find_first_not_of(" \t\r\v\n"));
+ confName.erase(confName.find_last_not_of(" \t\r\v\n") + 1);
+ if (confName.empty()) {
+ confName = "NoConfig";
+ }
+ return confName;
+}
+
+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");
+ 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;
+ }
+ if (!targetName.empty()) {
+ ss << " " << targetName;
+ }
+ buildCommand = ss.str();
+ return buildCommand;
+}
+
+std::string cmExtraCodeLiteGenerator::GetCleanCommand(
+ const cmMakefile* mf, const std::string& targetName) const
+{
+ std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
+ std::ostringstream ss;
+ std::string buildcommand = GetBuildCommand(mf, "");
+ if (!targetName.empty() && generator == "Ninja") {
+ ss << buildcommand << " -t clean " << targetName;
+ } else {
+ ss << buildcommand << " clean";
+ }
+ return ss.str();
+}
+
+std::string cmExtraCodeLiteGenerator::GetRebuildCommand(
+ const cmMakefile* mf, const std::string& targetName) const
+{
+ return GetCleanCommand(mf, targetName) + " && " +
+ GetBuildCommand(mf, targetName);
+}
+
+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");
+ if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
+ std::ostringstream ss;
+ ss << make << " -f$(ProjectPath)/Makefile $(CurrentFileName).cpp.o";
+ buildCommand = ss.str();
+ }
+ return buildCommand;
+}
diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h
new file mode 100644
index 000000000..de330988d
--- /dev/null
+++ b/Source/cmExtraCodeLiteGenerator.h
@@ -0,0 +1,72 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGlobalCodeLiteGenerator_h
+#define cmGlobalCodeLiteGenerator_h
+
+#include "cmConfigure.h"
+
+#include "cmExternalMakefileProjectGenerator.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
+class cmMakefile;
+class cmGeneratorTarget;
+class cmXMLWriter;
+class cmSourceFile;
+
+class cmExtraCodeLiteGenerator : public cmExternalMakefileProjectGenerator
+{
+protected:
+ std::string ConfigName;
+ std::string WorkspacePath;
+ unsigned int CpuCount;
+
+protected:
+ std::string GetCodeLiteCompilerName(const cmMakefile* mf) const;
+ std::string GetConfigurationName(const cmMakefile* mf) const;
+ std::string GetBuildCommand(const cmMakefile* mf,
+ const std::string& targetName) const;
+ std::string GetCleanCommand(const cmMakefile* mf,
+ const std::string& targetName) const;
+ std::string GetRebuildCommand(const cmMakefile* mf,
+ const std::string& targetName) const;
+ std::string GetSingleFileBuildCommand(const cmMakefile* mf) const;
+ std::vector<std::string> CreateProjectsByTarget(cmXMLWriter* xml);
+ std::vector<std::string> CreateProjectsByProjectMaps(cmXMLWriter* xml);
+ std::string CollectSourceFiles(const cmMakefile* makefile,
+ const cmGeneratorTarget* gt,
+ std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles);
+ void FindMatchingHeaderfiles(std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles);
+ void CreateProjectSourceEntries(std::map<std::string, cmSourceFile*>& cFiles,
+ std::set<std::string>& otherFiles,
+ cmXMLWriter* xml,
+ const std::string& projectPath,
+ const cmMakefile* mf,
+ const std::string& projectType,
+ const std::string& targetName);
+ void CreateFoldersAndFiles(std::set<std::string>& cFiles, cmXMLWriter& xml,
+ const std::string& projectPath);
+ void CreateFoldersAndFiles(std::map<std::string, cmSourceFile*>& cFiles,
+ cmXMLWriter& xml, const std::string& projectPath);
+
+public:
+ cmExtraCodeLiteGenerator();
+
+ static cmExternalMakefileProjectGeneratorFactory* GetFactory();
+
+ void Generate() CM_OVERRIDE;
+ void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
+
+ void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
+ const std::string& filename);
+ void CreateNewProjectFile(const cmGeneratorTarget* lg,
+ const std::string& filename);
+};
+
+#endif
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index d80e775bf..2a6ce98a7 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -1,129 +1,164 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
- Copyright 2007 Miguel A. Figueroa-Villanueva
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraEclipseCDT4Generator.h"
-#include "cmGlobalUnixMakefileGenerator3.h"
-#include "cmLocalUnixMakefileGenerator3.h"
-#include "cmMakefile.h"
+
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <assert.h>
+#include <map>
+#include <sstream>
+#include <stdio.h>
+#include <utility>
+
#include "cmGeneratedFileStream.h"
-#include "cmTarget.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
-
+#include "cmSourceGroup.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include <stdlib.h>
-#include <assert.h>
+#include "cmXMLWriter.h"
+#include "cmake.h"
-//----------------------------------------------------------------------------
-cmExtraEclipseCDT4Generator
-::cmExtraEclipseCDT4Generator() : cmExternalMakefileProjectGenerator()
+static void AppendAttribute(cmXMLWriter& xml, const char* keyval)
{
+ xml.StartElement("attribute");
+ xml.Attribute("key", keyval);
+ xml.Attribute("value", keyval);
+ xml.EndElement();
+}
+
+template <typename T>
+void AppendDictionary(cmXMLWriter& xml, const char* key, T const& value)
+{
+ xml.StartElement("dictionary");
+ xml.Element("key", key);
+ xml.Element("value", value);
+ xml.EndElement();
+}
+
+cmExtraEclipseCDT4Generator::cmExtraEclipseCDT4Generator()
+ : cmExternalMakefileProjectGenerator()
+{
+ this->SupportsVirtualFolders = true;
+ this->GenerateLinkedResources = true;
+ this->SupportsGmakeErrorParser = true;
+ this->SupportsMachO64Parser = true;
+ this->CEnabled = false;
+ this->CXXEnabled = false;
+}
+
+cmExternalMakefileProjectGeneratorFactory*
+cmExtraEclipseCDT4Generator::GetFactory()
+{
+ static cmExternalMakefileProjectGeneratorSimpleFactory<
+ cmExtraEclipseCDT4Generator>
+ factory("Eclipse CDT4", "Generates Eclipse CDT 4.0 project files.");
+
+ if (factory.GetSupportedGlobalGenerators().empty()) {
// TODO: Verify if __CYGWIN__ should be checked.
//#if defined(_WIN32) && !defined(__CYGWIN__)
#if defined(_WIN32)
- this->SupportedGlobalGenerators.push_back("NMake Makefiles");
- this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
-// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles");
+ factory.AddSupportedGlobalGenerator("MinGW Makefiles");
+// factory.AddSupportedGlobalGenerator("MSYS Makefiles");
#endif
- this->SupportedGlobalGenerators.push_back("Ninja");
- this->SupportedGlobalGenerators.push_back("Unix Makefiles");
+ factory.AddSupportedGlobalGenerator("Ninja");
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
+ }
- this->SupportsVirtualFolders = true;
- this->GenerateLinkedResources = true;
- this->SupportsGmakeErrorParser = true;
+ return &factory;
}
-//----------------------------------------------------------------------------
-void cmExtraEclipseCDT4Generator
-::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+void cmExtraEclipseCDT4Generator::EnableLanguage(
+ std::vector<std::string> const& languages, cmMakefile* /*unused*/,
+ bool /*optional*/)
{
- entry.Name = this->GetName();
- entry.Brief = "Generates Eclipse CDT 4.0 project files.";
- entry.Full =
- "Project files for Eclipse will be created in the top directory. "
- "In out of source builds, a linked resource to the top level source "
- "directory will be created. "
- "Additionally a hierarchy of makefiles is generated into the "
- "build tree. The appropriate make program can build the project through "
- "the default make target. A \"make install\" target is also provided.";
+ for (std::vector<std::string>::const_iterator lit = languages.begin();
+ lit != languages.end(); ++lit) {
+ if (*lit == "CXX") {
+ this->Natures.insert("org.eclipse.cdt.core.ccnature");
+ this->Natures.insert("org.eclipse.cdt.core.cnature");
+ this->CXXEnabled = true;
+ } else if (*lit == "C") {
+ this->Natures.insert("org.eclipse.cdt.core.cnature");
+ this->CEnabled = true;
+ } else if (*lit == "Java") {
+ this->Natures.insert("org.eclipse.jdt.core.javanature");
+ }
+ }
}
-//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::Generate()
{
- const cmMakefile* mf
- = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
+ cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const cmMakefile* mf = lg->GetMakefile();
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.c_str())) {
unsigned int majorVersion = 0;
unsigned int minorVersion = 0;
- int res=sscanf(regex.match(1).c_str(), "%u.%u", &majorVersion,
- &minorVersion);
- if (res == 2)
- {
+ int res =
+ sscanf(regex.match(1).c_str(), "%u.%u", &majorVersion, &minorVersion);
+ if (res == 2) {
int version = majorVersion * 1000 + minorVersion;
if (version < 3006) // 3.6 is Helios
- {
+ {
this->SupportsVirtualFolders = false;
- }
+ this->SupportsMachO64Parser = false;
+ }
if (version < 3007) // 3.7 is Indigo
- {
+ {
this->SupportsGmakeErrorParser = false;
- }
}
}
+ }
// TODO: Decide if these are local or member variables
- this->HomeDirectory = mf->GetHomeDirectory();
- this->HomeOutputDirectory = mf->GetHomeOutputDirectory();
-
- this->GenerateLinkedResources = mf->IsOn(
- "CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES");
-
- this->IsOutOfSourceBuild = (this->HomeDirectory!=this->HomeOutputDirectory);
-
- this->GenerateSourceProject = (this->IsOutOfSourceBuild &&
- mf->IsOn("CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT"));
-
- if ((this->GenerateSourceProject == false)
- && (mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT")))
- {
+ this->HomeDirectory = lg->GetSourceDirectory();
+ this->HomeOutputDirectory = lg->GetBinaryDirectory();
+
+ this->GenerateLinkedResources =
+ mf->IsOn("CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES");
+
+ this->IsOutOfSourceBuild =
+ (this->HomeDirectory != this->HomeOutputDirectory);
+
+ this->GenerateSourceProject =
+ (this->IsOutOfSourceBuild &&
+ mf->IsOn("CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT"));
+
+ if (!this->GenerateSourceProject &&
+ (mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"))) {
+ mf->IssueMessage(
+ cmake::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.");
+ }
+
+ if (cmSystemTools::IsSubDirectory(this->HomeOutputDirectory,
+ this->HomeDirectory)) {
mf->IssueMessage(cmake::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.");
- }
-
- if (cmSystemTools::IsSubDirectory(this->HomeOutputDirectory.c_str(),
- this->HomeDirectory.c_str()))
- {
- mf->IssueMessage(cmake::WARNING, "The build directory is a subdirectory "
+ "The build directory is a subdirectory "
"of the source directory.\n"
"This is not supported well by Eclipse. It is strongly "
"recommended to use a build directory which is a "
"sibling of the source directory.");
- }
+ }
// NOTE: This is not good, since it pollutes the source tree. However,
// Eclipse doesn't allow CVS/SVN to work when the .project is not in
// the cvs/svn root directory. Hence, this is provided as an option.
- if (this->GenerateSourceProject)
- {
+ if (this->GenerateSourceProject) {
// create .project file in the source tree
this->CreateSourceProjectFile();
- }
+ }
// create a .project file
this->CreateProjectFile();
@@ -137,1111 +172,948 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile()
assert(this->HomeDirectory != this->HomeOutputDirectory);
// set up the project name: <project>-Source@<baseSourcePathName>
- const cmMakefile* mf
- = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
- std::string name = this->GenerateProjectName(mf->GetProjectName(), "Source",
- this->GetPathBasename(this->HomeDirectory));
+ cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ std::string name =
+ this->GenerateProjectName(lg->GetProjectName(), "Source",
+ this->GetPathBasename(this->HomeDirectory));
const std::string filename = this->HomeDirectory + "/.project";
cmGeneratedFileStream fout(filename.c_str());
- if (!fout)
- {
+ if (!fout) {
return;
- }
-
- fout <<
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<projectDescription>\n"
- "\t<name>" << this->EscapeForXML(name) << "</name>\n"
- "\t<comment></comment>\n"
- "\t<projects>\n"
- "\t</projects>\n"
- "\t<buildSpec>\n"
- "\t</buildSpec>\n"
- "\t<natures>\n"
- "\t</natures>\n"
- "\t<linkedResources>\n";
-
- if (this->SupportsVirtualFolders)
- {
- this->CreateLinksToSubprojects(fout, this->HomeDirectory);
+ }
+
+ cmXMLWriter xml(fout);
+ xml.StartDocument("UTF-8");
+ xml.StartElement("projectDescription");
+ xml.Element("name", name);
+ xml.Element("comment", "");
+ xml.Element("projects", "");
+ xml.Element("buildSpec", "");
+ xml.Element("natures", "");
+ xml.StartElement("linkedResources");
+
+ if (this->SupportsVirtualFolders) {
+ this->CreateLinksToSubprojects(xml, this->HomeDirectory);
this->SrcLinkedResources.clear();
- }
+ }
- fout <<
- "\t</linkedResources>\n"
- "</projectDescription>\n"
- ;
+ xml.EndElement(); // linkedResources
+ xml.EndElement(); // projectDescription
+ xml.EndDocument();
}
-
-//----------------------------------------------------------------------------
-void cmExtraEclipseCDT4Generator::AddEnvVar(cmGeneratedFileStream& fout,
- const char* envVar, cmMakefile* mf)
+void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
+ const char* envVar,
+ cmLocalGenerator* lg)
{
+ cmMakefile* mf = lg->GetMakefile();
+
// get the variables from the environment and from the cache and then
// figure out which one to use:
- const char* envVarValue = getenv(envVar);
+ std::string envVarValue;
+ const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_";
cacheEntryName += envVar;
- const char* cacheValue = mf->GetCacheManager()->GetCacheValue(
- cacheEntryName.c_str());
+ const char* cacheValue =
+ lg->GetState()->GetInitializedCacheValue(cacheEntryName);
// now we have both, decide which one to use
std::string valueToUse;
- if (envVarValue==0 && cacheValue==0)
- {
+ if (!envVarSet && cacheValue == CM_NULLPTR) {
// nothing known, do nothing
valueToUse = "";
- }
- else if (envVarValue!=0 && cacheValue==0)
- {
+ } else if (envVarSet && cacheValue == CM_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.c_str(), valueToUse.c_str(),
- cacheEntryName.c_str(), cmCacheManager::STRING,
- true);
- mf->GetCacheManager()->SaveCache(mf->GetHomeOutputDirectory());
- }
- else if (envVarValue==0 && cacheValue!=0)
- {
+ mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
+ cacheEntryName.c_str(), cmStateEnums::STRING, true);
+ mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
+ } else if (!envVarSet && cacheValue != CM_NULLPTR) {
// It is already in the cache, but not in the env, so use it from the cache
valueToUse = cacheValue;
- }
- else
- {
+ } 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;
- if (valueToUse.find(envVarValue) == std::string::npos)
- {
+ if (valueToUse.find(envVarValue) == std::string::npos) {
valueToUse = envVarValue;
- mf->AddCacheDefinition(cacheEntryName.c_str(), valueToUse.c_str(),
- cacheEntryName.c_str(), cmCacheManager::STRING,
+ mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
+ cacheEntryName.c_str(), cmStateEnums::STRING,
true);
- mf->GetCacheManager()->SaveCache(mf->GetHomeOutputDirectory());
- }
+ mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
}
+ }
- if (!valueToUse.empty())
- {
- fout << envVar << "=" << valueToUse << "|";
- }
+ if (!valueToUse.empty()) {
+ out << envVar << "=" << valueToUse << "|";
+ }
}
-
-//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::CreateProjectFile()
{
- cmMakefile* mf
- = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
+ cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ cmMakefile* mf = lg->GetMakefile();
const std::string filename = this->HomeOutputDirectory + "/.project";
cmGeneratedFileStream fout(filename.c_str());
- if (!fout)
- {
+ if (!fout) {
return;
- }
+ }
std::string compilerId = mf->GetSafeDefinition("CMAKE_C_COMPILER_ID");
- if (compilerId.empty()) // no C compiler, try the C++ compiler:
- {
+ if (compilerId.empty()) // no C compiler, try the C++ compiler:
+ {
compilerId = mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID");
- }
+ }
+
+ cmXMLWriter xml(fout);
- fout <<
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<projectDescription>\n"
- "\t<name>" <<
- this->GenerateProjectName(mf->GetProjectName(),
- mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
- this->GetPathBasename(this->HomeOutputDirectory))
- << "</name>\n"
- "\t<comment></comment>\n"
- "\t<projects>\n"
- "\t</projects>\n"
- "\t<buildSpec>\n"
- "\t\t<buildCommand>\n"
- "\t\t\t<name>org.eclipse.cdt.make.core.makeBuilder</name>\n"
- "\t\t\t<triggers>clean,full,incremental,</triggers>\n"
- "\t\t\t<arguments>\n"
- ;
+ 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("comment", "");
+ xml.Element("projects", "");
+
+ xml.StartElement("buildSpec");
+ xml.StartElement("buildCommand");
+ xml.Element("name", "org.eclipse.cdt.make.core.makeBuilder");
+ xml.Element("triggers", "clean,full,incremental,");
+ xml.StartElement("arguments");
// use clean target
- fout <<
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>\n"
- "\t\t\t\t\t<value>clean</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\n"
- "\t\t\t\t\t<value>true</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.append_environment</key>\n"
- "\t\t\t\t\t<value>true</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.stopOnError</key>\n"
- "\t\t\t\t\t<value>true</value>\n"
- "\t\t\t\t</dictionary>\n"
- ;
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.cleanBuildTarget", "clean");
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.enableCleanBuild", "true");
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.append_environment",
+ "true");
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.stopOnError", "true");
// set the make command
- std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- const std::string makeArgs = mf->GetSafeDefinition(
- "CMAKE_ECLIPSE_MAKE_ARGUMENTS");
-
- fout <<
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\n"
- "\t\t\t\t\t<value>true</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.command</key>\n"
- "\t\t\t\t\t<value>" << this->GetEclipsePath(make) << "</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.contents</key>\n"
- "\t\t\t\t\t<value>org.eclipse.cdt.make.core.activeConfigSettings</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.inc</key>\n"
- "\t\t\t\t\t<value>all</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.arguments</key>\n"
- "\t\t\t\t\t<value>" << makeArgs << "</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildLocation</key>\n"
- "\t\t\t\t\t<value>"
- << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>\n"
- "\t\t\t\t\t<value>false</value>\n"
- "\t\t\t\t</dictionary>\n"
- ;
+ 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.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.useDefaultBuildCmd",
+ "false");
// set project specific environment
- fout <<
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.environment</key>\n"
- "\t\t\t\t\t<value>VERBOSE=1|CMAKE_NO_VERBOSE=1|" //verbose Makefile output
- ;
+ std::ostringstream environment;
+ environment << "VERBOSE=1|CMAKE_NO_VERBOSE=1|"; // verbose Makefile output
// set vsvars32.bat environment available at CMake time,
// but not necessarily when eclipse is open
- if (compilerId == "MSVC")
- {
- AddEnvVar(fout, "PATH", mf);
- AddEnvVar(fout, "INCLUDE", mf);
- AddEnvVar(fout, "LIB", mf);
- AddEnvVar(fout, "LIBPATH", mf);
- }
- else if (compilerId == "Intel")
- {
+ if (compilerId == "MSVC") {
+ AddEnvVar(environment, "PATH", lg);
+ AddEnvVar(environment, "INCLUDE", lg);
+ AddEnvVar(environment, "LIB", lg);
+ AddEnvVar(environment, "LIBPATH", lg);
+ } else if (compilerId == "Intel") {
// if the env.var is set, use this one and put it in the cache
// if the env.var is not set, but the value is in the cache,
// use it from the cache:
- AddEnvVar(fout, "INTEL_LICENSE_FILE", mf);
- }
- fout <<
- "</value>\n"
- "\t\t\t\t</dictionary>\n"
- ;
-
- fout <<
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableFullBuild</key>\n"
- "\t\t\t\t\t<value>true</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.auto</key>\n"
- "\t\t\t\t\t<value>all</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableAutoBuild</key>\n"
- "\t\t\t\t\t<value>false</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.clean</key>\n"
- "\t\t\t\t\t<value>clean</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.fullBuildTarget</key>\n"
- "\t\t\t\t\t<value>all</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildArguments</key>\n"
- "\t\t\t\t\t<value></value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.location</key>\n"
- "\t\t\t\t\t<value>"
- << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
- "\t\t\t\t</dictionary>\n"
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.make.core.autoBuildTarget</key>\n"
- "\t\t\t\t\t<value>all</value>\n"
- "\t\t\t\t</dictionary>\n"
- ;
+ AddEnvVar(environment, "INTEL_LICENSE_FILE", lg);
+ }
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.environment",
+ environment.str());
+
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.enableFullBuild", "true");
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.auto", "all");
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.enableAutoBuild", "false");
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.clean",
+ "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.autoBuildTarget", "all");
// set error parsers
- fout <<
- "\t\t\t\t<dictionary>\n"
- "\t\t\t\t\t<key>org.eclipse.cdt.core.errorOutputParser</key>\n"
- "\t\t\t\t\t<value>"
- ;
- if (compilerId == "MSVC")
- {
- fout << "org.eclipse.cdt.core.VCErrorParser;";
- }
- else if (compilerId == "Intel")
- {
- fout << "org.eclipse.cdt.core.ICCErrorParser;";
- }
+ std::ostringstream errorOutputParser;
+
+ if (compilerId == "MSVC") {
+ errorOutputParser << "org.eclipse.cdt.core.VCErrorParser;";
+ } else if (compilerId == "Intel") {
+ errorOutputParser << "org.eclipse.cdt.core.ICCErrorParser;";
+ }
+
+ if (this->SupportsGmakeErrorParser) {
+ errorOutputParser << "org.eclipse.cdt.core.GmakeErrorParser;";
+ } else {
+ errorOutputParser << "org.eclipse.cdt.core.MakeErrorParser;";
+ }
+
+ errorOutputParser << "org.eclipse.cdt.core.GCCErrorParser;"
+ "org.eclipse.cdt.core.GASErrorParser;"
+ "org.eclipse.cdt.core.GLDErrorParser;";
+ AppendDictionary(xml, "org.eclipse.cdt.core.errorOutputParser",
+ errorOutputParser.str());
+
+ xml.EndElement(); // arguments
+ xml.EndElement(); // buildCommand
+ xml.StartElement("buildCommand");
+ xml.Element("name", "org.eclipse.cdt.make.core.ScannerConfigBuilder");
+ xml.StartElement("arguments");
+ xml.EndElement(); // arguments
+ xml.EndElement(); // buildCommand
+ xml.EndElement(); // buildSpec
- if (this->SupportsGmakeErrorParser)
- {
- fout << "org.eclipse.cdt.core.GmakeErrorParser;";
- }
- else
- {
- fout << "org.eclipse.cdt.core.MakeErrorParser;";
+ // set natures for c/c++ projects
+ 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);
+ }
+
+ 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);
}
+ }
- fout <<
- "org.eclipse.cdt.core.GCCErrorParser;"
- "org.eclipse.cdt.core.GASErrorParser;"
- "org.eclipse.cdt.core.GLDErrorParser;"
- "</value>\n"
- "\t\t\t\t</dictionary>\n"
- ;
-
- fout <<
- "\t\t\t</arguments>\n"
- "\t\t</buildCommand>\n"
- "\t\t<buildCommand>\n"
- "\t\t\t<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>\n"
- "\t\t\t<arguments>\n"
- "\t\t\t</arguments>\n"
- "\t\t</buildCommand>\n"
- "\t</buildSpec>\n"
- ;
+ xml.EndElement(); // natures
- // set natures for c/c++ projects
- fout <<
- "\t<natures>\n"
- // TODO: ccnature only if it is c++ ???
- "\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n"
- "\t\t<nature>org.eclipse.cdt.make.core.makeNature</nature>\n"
- "\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n"
- "\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n"
- "\t</natures>\n"
- ;
-
- fout << "\t<linkedResources>\n";
+ xml.StartElement("linkedResources");
// create linked resources
- if (this->IsOutOfSourceBuild)
- {
+ if (this->IsOutOfSourceBuild) {
// create a linked resource to CMAKE_SOURCE_DIR
// (this is not done anymore for each project because of
- // http://public.kitware.com/Bug/view.php?id=9978 and because I found it
- // actually quite confusing in bigger projects with many directories and
+ // https://gitlab.kitware.com/cmake/cmake/issues/9978 and because I found
+ // it actually quite confusing in bigger projects with many directories and
// projects, Alex
std::string sourceLinkedResourceName = "[Source directory]";
- std::string linkSourceDirectory = this->GetEclipsePath(
- mf->GetStartDirectory());
+ std::string linkSourceDirectory =
+ this->GetEclipsePath(lg->GetCurrentSourceDirectory());
// .project dir can't be subdir of a linked resource dir
- if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory.c_str(),
- linkSourceDirectory.c_str()))
- {
- this->AppendLinkedResource(fout, sourceLinkedResourceName,
+ if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory,
+ linkSourceDirectory)) {
+ this->AppendLinkedResource(xml, sourceLinkedResourceName,
this->GetEclipsePath(linkSourceDirectory),
LinkToFolder);
this->SrcLinkedResources.push_back(sourceLinkedResourceName);
- }
-
}
+ }
- if (this->SupportsVirtualFolders)
- {
- this->CreateLinksToSubprojects(fout, this->HomeOutputDirectory);
-
- this->CreateLinksForTargets(fout);
- }
+ if (this->SupportsVirtualFolders) {
+ this->CreateLinksToSubprojects(xml, this->HomeOutputDirectory);
- fout << "\t</linkedResources>\n";
+ this->CreateLinksForTargets(xml);
+ }
- fout << "</projectDescription>\n";
+ xml.EndElement(); // linkedResources
+ xml.EndElement(); // projectDescription
}
+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();
+
+ std::replace(linkName3.begin(), linkName3.end(), '\\', '/');
+
+ this->AppendLinkedResource(xml, linkName3, "virtual:/virtual",
+ VirtualFolder);
+ std::vector<cmSourceGroup> const& children = sgIt->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();
+
+ if (!cmSystemTools::FileIsDirectory(fullPath)) {
+ std::string linkName4 = linkName3;
+ linkName4 += "/";
+ linkName4 += cmSystemTools::GetFilenameName(fullPath);
+ this->AppendLinkedResource(xml, linkName4,
+ this->GetEclipsePath(fullPath), LinkToFile);
+ }
+ }
+ }
+}
-//----------------------------------------------------------------------------
-void cmExtraEclipseCDT4Generator::CreateLinksForTargets(
- cmGeneratedFileStream& fout)
+void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
{
std::string linkName = "[Targets]";
- this->AppendLinkedResource(fout, linkName, "virtual:/virtual",VirtualFolder);
+ this->AppendLinkedResource(xml, linkName, "virtual:/virtual", VirtualFolder);
- for (std::vector<cmLocalGenerator*>::const_iterator
- lgIt = this->GlobalGenerator->GetLocalGenerators().begin();
- lgIt != this->GlobalGenerator->GetLocalGenerators().end();
- ++lgIt)
- {
+ for (std::vector<cmLocalGenerator*>::const_iterator lgIt =
+ this->GlobalGenerator->GetLocalGenerators().begin();
+ lgIt != this->GlobalGenerator->GetLocalGenerators().end(); ++lgIt) {
cmMakefile* makefile = (*lgIt)->GetMakefile();
- const cmTargets& targets = makefile->GetTargets();
+ const std::vector<cmGeneratorTarget*> targets =
+ (*lgIt)->GetGeneratorTargets();
- for(cmTargets::const_iterator ti=targets.begin(); ti!=targets.end();++ti)
- {
+ for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
+ ti != targets.end(); ++ti) {
std::string linkName2 = linkName;
linkName2 += "/";
- switch(ti->second.GetType())
- {
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- {
- const char* prefix = (ti->second.GetType()==cmTarget::EXECUTABLE ?
- "[exe] " : "[lib] ");
+ switch ((*ti)->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] ");
linkName2 += prefix;
- linkName2 += ti->first;
- this->AppendLinkedResource(fout, linkName2, "virtual:/virtual",
+ linkName2 += (*ti)->GetName();
+ this->AppendLinkedResource(xml, linkName2, "virtual:/virtual",
VirtualFolder);
- if (!this->GenerateLinkedResources)
- {
+ if (!this->GenerateLinkedResources) {
break; // skip generating the linked resources to the source files
- }
- std::vector<cmSourceGroup> sourceGroups=makefile->GetSourceGroups();
+ }
+ std::vector<cmSourceGroup> sourceGroups =
+ makefile->GetSourceGroups();
// get the files from the source lists then add them to the groups
- cmTarget* tgt = const_cast<cmTarget*>(&ti->second);
- std::vector<cmSourceFile*>const & files = tgt->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator sfIt = files.begin();
- sfIt != files.end();
- sfIt++)
- {
+ cmGeneratorTarget* gt = const_cast<cmGeneratorTarget*>(*ti);
+ 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++) {
// Add the file to the list of sources.
- std::string source = (*sfIt)->GetFullPath();
- cmSourceGroup& sourceGroup =
- makefile->FindSourceGroup(source.c_str(), sourceGroups);
- sourceGroup.AssignSource(*sfIt);
- }
-
- for(std::vector<cmSourceGroup>::iterator sgIt = sourceGroups.begin();
- sgIt != sourceGroups.end();
- ++sgIt)
- {
- std::string linkName3 = linkName2;
- linkName3 += "/";
- linkName3 += sgIt->GetFullName();
- this->AppendLinkedResource(fout, linkName3, "virtual:/virtual",
- VirtualFolder);
-
- std::vector<const cmSourceFile*> sFiles = sgIt->GetSourceFiles();
- for(std::vector<const cmSourceFile*>::const_iterator fileIt =
- sFiles.begin();
- fileIt != sFiles.end();
- ++fileIt)
- {
- std::string fullPath = (*fileIt)->GetFullPath();
- if (!cmSystemTools::FileIsDirectory(fullPath.c_str()))
- {
- std::string linkName4 = linkName3;
- linkName4 += "/";
- linkName4 += cmSystemTools::GetFilenameName(fullPath);
- this->AppendLinkedResource(fout, linkName4,
- fullPath, LinkToFile);
- }
- }
- }
+ std::string const& source = (*sfIt)->GetFullPath();
+ cmSourceGroup* sourceGroup =
+ makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ sourceGroup->AssignSource(*sfIt);
}
- break;
+
+ this->WriteGroups(sourceGroups, linkName2, xml);
+ } break;
// ignore all others:
default:
break;
- }
}
}
+ }
}
-
-//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
- cmGeneratedFileStream& fout, const std::string& baseDir)
+ cmXMLWriter& xml, const std::string& baseDir)
{
- if (!this->GenerateLinkedResources)
- {
+ if (!this->GenerateLinkedResources) {
return;
- }
+ }
// for each sub project create a linked resource to the source dir
// - only if it is an out-of-source build
- this->AppendLinkedResource(fout, "[Subprojects]",
- "virtual:/virtual", VirtualFolder);
-
- for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
- std::string linkSourceDirectory = this->GetEclipsePath(
- it->second[0]->GetMakefile()->GetStartDirectory());
+ this->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) {
+ std::string linkSourceDirectory =
+ this->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.c_str(),
- linkSourceDirectory.c_str()))
- {
+ !cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) {
std::string linkName = "[Subprojects]/";
linkName += it->first;
- this->AppendLinkedResource(fout, linkName,
+ this->AppendLinkedResource(xml, linkName,
this->GetEclipsePath(linkSourceDirectory),
- LinkToFolder
- );
+ LinkToFolder);
// Don't add it to the srcLinkedResources, because listing multiple
// directories confuses the Eclipse indexer (#13596).
- }
}
+ }
}
-
-//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
- cmGeneratedFileStream& fout,
- const std::vector<std::string>& includeDirs,
- std::set<std::string>& emittedDirs)
+ 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->c_str());
+ for (std::vector<std::string>::const_iterator inc = includeDirs.begin();
+ inc != includeDirs.end(); ++inc) {
+ 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.c_str())) {
dir = frameworkRx.match(1);
- }
+ }
- if(emittedDirs.find(dir) == emittedDirs.end())
- {
+ if (emittedDirs.find(dir) == emittedDirs.end()) {
emittedDirs.insert(dir);
- fout << "<pathentry include=\""
- << cmExtraEclipseCDT4Generator::EscapeForXML(
- cmExtraEclipseCDT4Generator::GetEclipsePath(dir))
- << "\" kind=\"inc\" path=\"\" system=\"true\"/>\n";
- }
+ xml.StartElement("pathentry");
+ xml.Attribute("include",
+ cmExtraEclipseCDT4Generator::GetEclipsePath(dir));
+ xml.Attribute("kind", "inc");
+ xml.Attribute("path", "");
+ xml.Attribute("system", "true");
+ xml.EndElement();
}
}
+ }
}
-//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
{
std::set<std::string> emmited;
- const cmMakefile* mf
- = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
+ cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const cmMakefile* mf = lg->GetMakefile();
const std::string filename = this->HomeOutputDirectory + "/.cproject";
cmGeneratedFileStream fout(filename.c_str());
- if (!fout)
- {
+ if (!fout) {
return;
- }
+ }
+
+ cmXMLWriter xml(fout);
// add header
- fout <<
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
- "<?fileVersion 4.0.0?>\n\n"
- "<cproject>\n"
- "<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n"
- ;
+ xml.StartDocument("UTF-8");
+ xml.ProcessingInstruction("fileVersion", "4.0.0");
+ xml.StartElement("cproject");
+ xml.StartElement("storageModule");
+ xml.Attribute("moduleId", "org.eclipse.cdt.core.settings");
- fout << "<cconfiguration id=\"org.eclipse.cdt.core.default.config.1\">\n";
+ xml.StartElement("cconfiguration");
+ xml.Attribute("id", "org.eclipse.cdt.core.default.config.1");
// Configuration settings...
- fout <<
- "<storageModule"
- " buildSystemId=\"org.eclipse.cdt.core.defaultConfigDataProvider\""
- " id=\"org.eclipse.cdt.core.default.config.1\""
- " moduleId=\"org.eclipse.cdt.core.settings\" name=\"Configuration\">\n"
- "<externalSettings/>\n"
- "<extensions>\n"
- ;
+ xml.StartElement("storageModule");
+ xml.Attribute("buildSystemId",
+ "org.eclipse.cdt.core.defaultConfigDataProvider");
+ xml.Attribute("id", "org.eclipse.cdt.core.default.config.1");
+ xml.Attribute("moduleId", "org.eclipse.cdt.core.settings");
+ xml.Attribute("name", "Configuration");
+ xml.Element("externalSettings");
+ xml.StartElement("extensions");
+
// TODO: refactor this out...
- std::string executableFormat = mf->GetSafeDefinition(
- "CMAKE_EXECUTABLE_FORMAT");
- if (executableFormat == "ELF")
- {
- fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
- " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
- ;
- fout << "<extension id=\"org.eclipse.cdt.core.GNU_ELF\""
- " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
- "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
- "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
- "</extension>\n"
- ;
- }
- else
- {
+ std::string executableFormat =
+ mf->GetSafeDefinition("CMAKE_EXECUTABLE_FORMAT");
+ if (executableFormat == "ELF") {
+ xml.StartElement("extension");
+ xml.Attribute("id", "org.eclipse.cdt.core.ELF");
+ xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
+ xml.EndElement(); // extension
+
+ xml.StartElement("extension");
+ xml.Attribute("id", "org.eclipse.cdt.core.GNU_ELF");
+ xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
+ AppendAttribute(xml, "addr2line");
+ AppendAttribute(xml, "c++filt");
+ xml.EndElement(); // extension
+ } else {
std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- if (systemName == "CYGWIN")
- {
- fout << "<extension id=\"org.eclipse.cdt.core.Cygwin_PE\""
- " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
- "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
- "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
- "<attribute key=\"cygpath\" value=\"cygpath\"/>\n"
- "<attribute key=\"nm\" value=\"nm\"/>\n"
- "</extension>\n"
- ;
- }
- else if (systemName == "Windows")
- {
- fout << "<extension id=\"org.eclipse.cdt.core.PE\""
- " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
- ;
- }
- else if (systemName == "Darwin")
- {
- fout << "<extension id=\"org.eclipse.cdt.core.MachO\""
- " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
- "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
- "</extension>\n"
- ;
- }
- else
- {
+ if (systemName == "CYGWIN") {
+ xml.StartElement("extension");
+ xml.Attribute("id", "org.eclipse.cdt.core.Cygwin_PE");
+ xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
+ AppendAttribute(xml, "addr2line");
+ AppendAttribute(xml, "c++filt");
+ AppendAttribute(xml, "cygpath");
+ AppendAttribute(xml, "nm");
+ xml.EndElement(); // extension
+ } else if (systemName == "Windows") {
+ xml.StartElement("extension");
+ xml.Attribute("id", "org.eclipse.cdt.core.PE");
+ xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
+ xml.EndElement(); // extension
+ } else if (systemName == "Darwin") {
+ xml.StartElement("extension");
+ xml.Attribute("id", this->SupportsMachO64Parser
+ ? "org.eclipse.cdt.core.MachO64"
+ : "org.eclipse.cdt.core.MachO");
+ xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
+ AppendAttribute(xml, "c++filt");
+ xml.EndElement(); // extension
+ } else {
// *** Should never get here ***
- fout << "<error_toolchain_type/>\n";
- }
+ xml.Element("error_toolchain_type");
}
+ }
- fout << "</extensions>\n"
- "</storageModule>\n"
- ;
+ xml.EndElement(); // extensions
+ xml.EndElement(); // storageModule
// ???
- fout <<
- "<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
- "<project-mappings/>\n"
- "</storageModule>\n"
- ;
+ xml.StartElement("storageModule");
+ xml.Attribute("moduleId", "org.eclipse.cdt.core.language.mapping");
+ xml.Element("project-mappings");
+ xml.EndElement(); // storageModule
// ???
- fout<<"<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n"
- ;
+ xml.StartElement("storageModule");
+ xml.Attribute("moduleId", "org.eclipse.cdt.core.externalSettings");
+ xml.EndElement(); // storageModule
// set the path entries (includes, libs, source dirs, etc.)
- fout << "<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\">\n"
- ;
+ xml.StartElement("storageModule");
+ xml.Attribute("moduleId", "org.eclipse.cdt.core.pathentry");
+
// for each sub project with a linked resource to the source dir:
// - make it type 'src'
// - and exclude it from type 'out'
std::string excludeFromOut;
-/* I don't know what the pathentry kind="src" are good for, e.g. autocompletion
- * works also without them. Done wrong, the indexer complains, see #12417
- * and #12213.
- * According to #13596, this entry at least limits the directories the
- * indexer is searching for files. So now the "src" entry contains only
- * the linked resource to CMAKE_SOURCE_DIR.
- * The CDT documentation is very terse on that:
- * "CDT_SOURCE: Entry kind constant describing a path entry identifying a
- * folder containing source code to be compiled."
- * Also on the cdt-dev list didn't bring any information:
- * http://web.archiveorange.com/archive/v/B4NlJDNIpYoOS1SbxFNy
- * Alex */
-
- for (std::vector<std::string>::const_iterator
- it = this->SrcLinkedResources.begin();
- it != this->SrcLinkedResources.end();
- ++it)
- {
- fout << "<pathentry kind=\"src\" path=\"" << this->EscapeForXML(*it)
- << "\"/>\n";
+ /* I don't know what the pathentry kind="src" are good for, e.g.
+ * autocompletion
+ * works also without them. Done wrong, the indexer complains, see #12417
+ * and #12213.
+ * According to #13596, this entry at least limits the directories the
+ * indexer is searching for files. So now the "src" entry contains only
+ * the linked resource to CMAKE_SOURCE_DIR.
+ * The CDT documentation is very terse on that:
+ * "CDT_SOURCE: Entry kind constant describing a path entry identifying a
+ * folder containing source code to be compiled."
+ * Also on the cdt-dev list didn't bring any information:
+ * http://web.archiveorange.com/archive/v/B4NlJDNIpYoOS1SbxFNy
+ * Alex */
+ // include subprojects directory to the src pathentry
+ // eclipse cdt indexer uses this entries as reference to index source files
+ if (this->GenerateLinkedResources) {
+ xml.StartElement("pathentry");
+ xml.Attribute("kind", "src");
+ xml.Attribute("path", "[Subprojects]");
+ xml.EndElement();
+ }
+
+ for (std::vector<std::string>::const_iterator it =
+ this->SrcLinkedResources.begin();
+ it != this->SrcLinkedResources.end(); ++it) {
+ xml.StartElement("pathentry");
+ xml.Attribute("kind", "src");
+ xml.Attribute("path", *it);
+ xml.EndElement();
// exlude source directory from output search path
// - only if not named the same as an output directory
if (!cmSystemTools::FileIsDirectory(
- std::string(this->HomeOutputDirectory + "/" + *it).c_str()))
- {
- excludeFromOut += this->EscapeForXML(*it) + "/|";
- }
+ std::string(this->HomeOutputDirectory + "/" + *it))) {
+ excludeFromOut += *it + "/|";
}
+ }
excludeFromOut += "**/CMakeFiles/";
- fout << "<pathentry excluding=\"" << excludeFromOut
- << "\" kind=\"out\" path=\"\"/>\n";
+
+ xml.StartElement("pathentry");
+ xml.Attribute("excluding", excludeFromOut);
+ xml.Attribute("kind", "out");
+ xml.Attribute("path", "");
+ xml.EndElement();
// 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)
- {
-
- if(const char* cdefs = (*it)->GetMakefile()->GetProperty(
- "COMPILE_DEFINITIONS"))
- {
+ for (std::vector<cmLocalGenerator*>::const_iterator it =
+ this->GlobalGenerator->GetLocalGenerators().begin();
+ it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) {
+
+ if (const char* cdefs =
+ (*it)->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) {
// Expand the list.
std::vector<std::string> defs;
- cmSystemTools::ExpandListArgument(cdefs, 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) {
+ continue;
+ }
- for(std::vector<std::string>::const_iterator di = defs.begin();
- di != defs.end(); ++di)
- {
std::string::size_type equals = di->find('=', 0);
std::string::size_type enddef = di->length();
std::string def;
std::string val;
- if (equals != std::string::npos && equals < enddef)
- {
+ if (equals != std::string::npos && equals < enddef) {
// we have -DFOO=BAR
def = di->substr(0, equals);
val = di->substr(equals + 1, enddef - equals + 1);
- }
- else
- {
+ } else {
// we have -DFOO
def = *di;
- }
+ }
// insert the definition if not already added.
- if(emmited.find(def) == emmited.end())
- {
+ if (emmited.find(def) == emmited.end()) {
emmited.insert(def);
- fout << "<pathentry kind=\"mac\" name=\"" << def
- << "\" path=\"\" value=\"" << this->EscapeForXML(val)
- << "\"/>\n";
- }
+ xml.StartElement("pathentry");
+ xml.Attribute("kind", "mac");
+ xml.Attribute("name", def);
+ xml.Attribute("path", "");
+ xml.Attribute("value", val);
+ xml.EndElement();
}
}
}
+ }
// add system defined c macros
- const char* cDefs=mf->GetDefinition(
- "CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS");
- if(cDefs)
- {
+ const char* cDefs =
+ 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);
// the list must contain only definition-value pairs:
- if ((defs.size() % 2) == 0)
- {
+ if ((defs.size() % 2) == 0) {
std::vector<std::string>::const_iterator di = defs.begin();
- while (di != defs.end())
- {
+ while (di != defs.end()) {
std::string def = *di;
++di;
std::string val;
- if (di != defs.end())
- {
+ if (di != defs.end()) {
val = *di;
++di;
- }
+ }
// insert the definition if not already added.
- if(emmited.find(def) == emmited.end())
- {
+ if (emmited.find(def) == emmited.end()) {
emmited.insert(def);
- fout << "<pathentry kind=\"mac\" name=\"" << def
- << "\" path=\"\" value=\"" << this->EscapeForXML(val)
- << "\"/>\n";
- }
+ xml.StartElement("pathentry");
+ xml.Attribute("kind", "mac");
+ xml.Attribute("name", def);
+ xml.Attribute("path", "");
+ xml.Attribute("value", val);
+ xml.EndElement();
}
}
}
+ }
// add system defined c++ macros
- const char* cxxDefs = mf->GetDefinition(
- "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS");
- if(cxxDefs)
- {
+ const char* cxxDefs =
+ 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);
// the list must contain only definition-value pairs:
- if ((defs.size() % 2) == 0)
- {
+ if ((defs.size() % 2) == 0) {
std::vector<std::string>::const_iterator di = defs.begin();
- while (di != defs.end())
- {
+ while (di != defs.end()) {
std::string def = *di;
++di;
std::string val;
- if (di != defs.end())
- {
+ if (di != defs.end()) {
val = *di;
++di;
- }
+ }
// insert the definition if not already added.
- if(emmited.find(def) == emmited.end())
- {
+ if (emmited.find(def) == emmited.end()) {
emmited.insert(def);
- fout << "<pathentry kind=\"mac\" name=\"" << def
- << "\" path=\"\" value=\"" << this->EscapeForXML(val)
- << "\"/>\n";
- }
+ xml.StartElement("pathentry");
+ xml.Attribute("kind", "mac");
+ xml.Attribute("name", def);
+ xml.Attribute("path", "");
+ xml.Attribute("value", val);
+ xml.EndElement();
}
}
}
+ }
// include dirs
emmited.clear();
- for (std::vector<cmLocalGenerator*>::const_iterator
- it = this->GlobalGenerator->GetLocalGenerators().begin();
- it != this->GlobalGenerator->GetLocalGenerators().end();
- ++it)
- {
- cmGeneratorTargetsType targets = (*it)->GetMakefile()
- ->GetGeneratorTargets();
- for (cmGeneratorTargetsType::iterator l = targets.begin();
- l != targets.end(); ++l)
- {
- if (l->first->IsImported())
- {
- continue;
- }
+ 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) {
std::vector<std::string> includeDirs;
- const char *config = mf->GetDefinition("CMAKE_BUILD_TYPE");
- (*it)->GetIncludeDirectories(includeDirs, l->second, "C", config);
- this->AppendIncludeDirectories(fout, includeDirs, emmited);
- }
+ std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ (*it)->GetIncludeDirectories(includeDirs, *l, "C", config);
+ this->AppendIncludeDirectories(xml, includeDirs, emmited);
}
+ }
// now also the system include directories, in case we found them in
// CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
// standard headers.
std::string compiler = mf->GetSafeDefinition("CMAKE_C_COMPILER");
- if (!compiler.empty())
- {
- std::string systemIncludeDirs = mf->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
+ 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.c_str(), dirs);
- this->AppendIncludeDirectories(fout, dirs, emmited);
- }
+ cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ this->AppendIncludeDirectories(xml, dirs, emmited);
+ }
compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
- if (!compiler.empty())
- {
- std::string systemIncludeDirs = mf->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
+ 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.c_str(), dirs);
- this->AppendIncludeDirectories(fout, dirs, emmited);
- }
+ cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ this->AppendIncludeDirectories(xml, dirs, emmited);
+ }
- fout << "</storageModule>\n";
+ xml.EndElement(); // storageModule
// add build targets
- fout <<
- "<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
- "<buildTargets>\n"
- ;
+ xml.StartElement("storageModule");
+ 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 = mf->GetSafeDefinition(
- "CMAKE_ECLIPSE_MAKE_ARGUMENTS");
- const std::string cmake = mf->GetRequiredDefinition("CMAKE_COMMAND");
+ const std::string makeArgs =
+ mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS");
- cmGlobalGenerator* generator
- = const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
+ cmGlobalGenerator* generator =
+ const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
std::string allTarget;
std::string cleanTarget;
- if (generator->GetAllTargetName())
- {
+ if (generator->GetAllTargetName()) {
allTarget = generator->GetAllTargetName();
- }
- if (generator->GetCleanTargetName())
- {
+ }
+ if (generator->GetCleanTargetName()) {
cleanTarget = generator->GetCleanTargetName();
- }
+ }
// 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 cmTargets& targets = (*it)->GetMakefile()->GetTargets();
- cmMakefile* makefile=(*it)->GetMakefile();
- std::string subdir = (*it)->Convert(makefile->GetCurrentOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
- if (subdir == ".")
- {
+ 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());
+ if (subdir == ".") {
subdir = "";
- }
+ }
- for(cmTargets::const_iterator ti=targets.begin(); ti!=targets.end(); ++ti)
- {
- switch(ti->second.GetType())
- {
- case cmTarget::GLOBAL_TARGET:
- {
- bool insertTarget = false;
+ for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
+ ti != targets.end(); ++ti) {
+ std::string targetName = (*ti)->GetName();
+ switch ((*ti)->GetType()) {
+ case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (subdir.empty())
- {
- insertTarget = true;
- // only add the "edit_cache" target if it's not ccmake, because
- // this will not work within the IDE
- if (ti->first == "edit_cache")
- {
- const char* editCommand = makefile->GetDefinition
- ("CMAKE_EDIT_COMMAND");
- if (editCommand == 0)
- {
- insertTarget = false;
- }
- else if (strstr(editCommand, "ccmake")!=NULL)
- {
- insertTarget = false;
- }
- }
- }
- if (insertTarget)
- {
- this->AppendTarget(fout, ti->first, make, makeArgs, subdir, ": ");
- }
- }
- break;
- case cmTarget::UTILITY:
- // Add all utility targets, except the Nightly/Continuous/
- // Experimental-"sub"targets as e.g. NightlyStart
- if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly"))
- || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
- || ((ti->first.find("Experimental")==0)
- && (ti->first!="Experimental")))
- {
- break;
- }
-
- this->AppendTarget(fout, ti->first, make, makeArgs, subdir, ": ");
- break;
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- {
- const char* prefix = (ti->second.GetType()==cmTarget::EXECUTABLE ?
- "[exe] " : "[lib] ");
- this->AppendTarget(fout, ti->first, make, makeArgs, subdir, prefix);
- std::string fastTarget = ti->first;
- fastTarget += "/fast";
- this->AppendTarget(fout, 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 += ti->first;
- std::string buildArgs = "-C \"";
- buildArgs += makefile->GetHomeOutputDirectory();
- buildArgs += "\" ";
- buildArgs += makeArgs;
- this->AppendTarget(fout, "Build", make, buildArgs, virtDir, "",
- ti->first.c_str());
-
- std::string cleanArgs = "-E chdir \"";
- cleanArgs += makefile->GetCurrentOutputDirectory();
- cleanArgs += "\" \"";
- cleanArgs += cmake;
- cleanArgs += "\" -P \"";
- cleanArgs += (*it)->GetTargetDirectory(ti->second);
- cleanArgs += "/cmake_clean.cmake\"";
- this->AppendTarget(fout, "Clean", cmake, cleanArgs, virtDir, "", "");
+ if (subdir.empty()) {
+ this->AppendTarget(xml, targetName, make, makeArgs, subdir, ": ");
}
- }
- break;
+ } break;
+ case cmStateEnums::UTILITY:
+ // Add all utility targets, except the Nightly/Continuous/
+ // Experimental-"sub"targets as e.g. NightlyStart
+ if (((targetName.find("Nightly") == 0) &&
+ (targetName != "Nightly")) ||
+ ((targetName.find("Continuous") == 0) &&
+ (targetName != "Continuous")) ||
+ ((targetName.find("Experimental") == 0) &&
+ (targetName != "Experimental"))) {
+ break;
+ }
+
+ this->AppendTarget(xml, targetName, make, makeArgs, subdir, ": ");
+ break;
+ 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] ");
+ this->AppendTarget(xml, targetName, make, makeArgs, subdir, prefix);
+ std::string fastTarget = targetName;
+ fastTarget += "/fast";
+ this->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);
+ cleanArgs += "/cmake_clean.cmake\"";
+ this->AppendTarget(xml, "Clean", cmSystemTools::GetCMakeCommand(),
+ cleanArgs, virtDir, "", "");
+ }
+ } break;
default:
break;
- }
}
+ }
// insert the all and clean targets in every subdir
- if (!allTarget.empty())
- {
- this->AppendTarget(fout, allTarget, make, makeArgs, subdir, ": ");
- }
- if (!cleanTarget.empty())
- {
- this->AppendTarget(fout, cleanTarget, make, makeArgs, subdir, ": ");
- }
+ if (!allTarget.empty()) {
+ this->AppendTarget(xml, allTarget, make, makeArgs, subdir, ": ");
+ }
+ if (!cleanTarget.empty()) {
+ this->AppendTarget(xml, cleanTarget, make, makeArgs, subdir, ": ");
+ }
- //insert rules for compiling, preprocessing and assembling individual files
+ // 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)
- {
+ for (std::vector<std::string>::const_iterator fit =
+ objectFileTargets.begin();
+ fit != objectFileTargets.end(); ++fit) {
const char* prefix = "[obj] ";
- if ((*fit)[fit->length()-1] == 's')
- {
+ if ((*fit)[fit->length() - 1] == 's') {
prefix = "[to asm] ";
- }
- else if ((*fit)[fit->length()-1] == 'i')
- {
+ } else if ((*fit)[fit->length() - 1] == 'i') {
prefix = "[pre] ";
- }
- this->AppendTarget(fout, *fit, make, makeArgs, subdir, prefix);
}
+ this->AppendTarget(xml, *fit, make, makeArgs, subdir, prefix);
}
+ }
- fout << "</buildTargets>\n"
- "</storageModule>\n"
- ;
-
- this->AppendStorageScanners(fout, *mf);
-
- fout << "</cconfiguration>\n"
- "</storageModule>\n"
- "<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
- "<project id=\"" << this->EscapeForXML(mf->GetProjectName())
- << ".null.1\" name=\"" << this->EscapeForXML(mf->GetProjectName())
- << "\"/>\n"
- "</storageModule>\n"
- "</cproject>\n"
- ;
+ xml.EndElement(); // buildTargets
+ xml.EndElement(); // storageModule
+
+ this->AppendStorageScanners(xml, *mf);
+
+ xml.EndElement(); // cconfiguration
+ xml.EndElement(); // storageModule
+
+ xml.StartElement("storageModule");
+ xml.Attribute("moduleId", "cdtBuildSystem");
+ xml.Attribute("version", "4.0.0");
+
+ xml.StartElement("project");
+ xml.Attribute("id", std::string(lg->GetProjectName()) + ".null.1");
+ xml.Attribute("name", lg->GetProjectName());
+ xml.EndElement(); // project
+
+ xml.EndElement(); // storageModule
+ xml.EndElement(); // cproject
}
-//----------------------------------------------------------------------------
-std::string
-cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string& path)
+std::string cmExtraEclipseCDT4Generator::GetEclipsePath(
+ const std::string& path)
{
#if defined(__CYGWIN__)
std::string cmd = "cygpath -m " + path;
std::string out;
- if (!cmSystemTools::RunCommand(cmd.c_str(), out, 0, false))
- {
+ if (!cmSystemTools::RunSingleCommand(cmd.c_str(), &out, &out)) {
return path;
- }
- else
- {
+ } else {
out.erase(out.find_last_of('\n'));
return out;
- }
+ }
#else
return path;
#endif
}
-std::string
-cmExtraEclipseCDT4Generator::GetPathBasename(const std::string& path)
+std::string cmExtraEclipseCDT4Generator::GetPathBasename(
+ const std::string& path)
{
std::string outputBasename = path;
- while (outputBasename.size() > 0 &&
+ while (!outputBasename.empty() &&
(outputBasename[outputBasename.size() - 1] == '/' ||
- outputBasename[outputBasename.size() - 1] == '\\'))
- {
+ outputBasename[outputBasename.size() - 1] == '\\')) {
outputBasename.resize(outputBasename.size() - 1);
- }
+ }
std::string::size_type loc = outputBasename.find_last_of("/\\");
- if (loc != std::string::npos)
- {
+ if (loc != std::string::npos) {
outputBasename = outputBasename.substr(loc + 1);
- }
+ }
return outputBasename;
}
-std::string
-cmExtraEclipseCDT4Generator::GenerateProjectName(const std::string& name,
- const std::string& type,
- const std::string& path)
-{
- return cmExtraEclipseCDT4Generator::EscapeForXML(name)
- +(type.empty() ? "" : "-") + type + "@" + path;
-}
-
-std::string cmExtraEclipseCDT4Generator::EscapeForXML(const std::string& value)
+std::string cmExtraEclipseCDT4Generator::GenerateProjectName(
+ const std::string& name, const std::string& type, const std::string& path)
{
- std::string str = value;
- cmSystemTools::ReplaceString(str, "&", "&amp;");
- cmSystemTools::ReplaceString(str, "<", "&lt;");
- cmSystemTools::ReplaceString(str, ">", "&gt;");
- cmSystemTools::ReplaceString(str, "\"", "&quot;");
- // NOTE: This one is not necessary, since as of Eclipse CDT4 it will
- // automatically change this to the original value (').
- //cmSystemTools::ReplaceString(str, "'", "&apos;");
- return str;
+ return name + (type.empty() ? "" : "-") + type + "@" + path;
}
-//----------------------------------------------------------------------------
// Helper functions
-//----------------------------------------------------------------------------
-void cmExtraEclipseCDT4Generator
-::AppendStorageScanners(cmGeneratedFileStream& fout,
- const cmMakefile& makefile)
+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");
std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
std::string arg1 = makefile.GetSafeDefinition("CMAKE_C_COMPILER_ARG1");
- if (compiler.empty())
- {
+ if (compiler.empty()) {
compiler = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER");
arg1 = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER_ARG1");
- }
- if (compiler.empty()) //Hmm, what to do now ?
- {
+ }
+ if (compiler.empty()) // Hmm, what to do now ?
+ {
compiler = "gcc";
- }
+ }
// the following right now hardcodes gcc behaviour :-/
std::string compilerArgs =
- "-E -P -v -dD ${plugin_state_location}/${specs_file}";
- if (!arg1.empty())
- {
+ "-E -P -v -dD ${plugin_state_location}/${specs_file}";
+ if (!arg1.empty()) {
arg1 += " ";
compilerArgs = arg1 + compilerArgs;
- }
-
- fout <<
- "<storageModule moduleId=\"scannerConfiguration\">\n"
- "<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\""
- " selectedProfileId="
- "\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\n"
- ;
- cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
- "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile",
- true, "", true, "specsFile",
- compilerArgs,
- compiler, true, true);
- cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
- "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile",
- true, "", true, "makefileGenerator",
- "-f ${project_name}_scd.mk",
- make, true, true);
-
- fout << "</storageModule>\n";
+ }
+
+ xml.StartElement("storageModule");
+ xml.Attribute("moduleId", "scannerConfiguration");
+
+ xml.StartElement("autodiscovery");
+ xml.Attribute("enabled", "true");
+ xml.Attribute("problemReportingEnabled", "true");
+ xml.Attribute("selectedProfileId",
+ "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile");
+ xml.EndElement(); // autodiscovery
+
+ cmExtraEclipseCDT4Generator::AppendScannerProfile(
+ xml, "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile", true,
+ "", true, "specsFile", compilerArgs, compiler, true, true);
+ cmExtraEclipseCDT4Generator::AppendScannerProfile(
+ xml, "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile", true, "",
+ true, "makefileGenerator", "-f ${project_name}_scd.mk", make, true, true);
+
+ xml.EndElement(); // storageModule
}
// The prefix is prepended before the actual name of the target. The purpose
@@ -1252,93 +1124,77 @@ void cmExtraEclipseCDT4Generator
// finally the assembly files "[to asm] ". Note the "to" in "to asm",
// without it, "asm" would be the first targets in the list, with the "to"
// they are the last targets, which makes more sense.
-void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream& fout,
- const std::string& target,
- const std::string& make,
- const std::string& makeArgs,
- const std::string& path,
- const char* prefix,
- const char* makeTarget
- )
+void cmExtraEclipseCDT4Generator::AppendTarget(
+ cmXMLWriter& xml, const std::string& target, const std::string& make,
+ const std::string& makeArgs, const std::string& path, const char* prefix,
+ const char* makeTarget)
{
- std::string targetXml = cmExtraEclipseCDT4Generator::EscapeForXML(target);
- std::string makeTargetXml = targetXml;
- if (makeTarget != NULL)
- {
- makeTargetXml = cmExtraEclipseCDT4Generator::EscapeForXML(makeTarget);
- }
- cmExtraEclipseCDT4Generator::EscapeForXML(target);
- std::string pathXml = cmExtraEclipseCDT4Generator::EscapeForXML(path);
- fout <<
- "<target name=\"" << prefix << targetXml << "\""
- " path=\"" << pathXml.c_str() << "\""
- " targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
- "<buildCommand>"
- << cmExtraEclipseCDT4Generator::GetEclipsePath(make)
- << "</buildCommand>\n"
- "<buildArguments>" << makeArgs << "</buildArguments>\n"
- "<buildTarget>" << makeTargetXml << "</buildTarget>\n"
- "<stopOnError>true</stopOnError>\n"
- "<useDefaultCommand>false</useDefaultCommand>\n"
- "</target>\n"
- ;
+ xml.StartElement("target");
+ xml.Attribute("name", prefix + target);
+ xml.Attribute("path", path);
+ xml.Attribute("targetID", "org.eclipse.cdt.make.MakeTargetBuilder");
+ xml.Element("buildCommand",
+ cmExtraEclipseCDT4Generator::GetEclipsePath(make));
+ xml.Element("buildArguments", makeArgs);
+ xml.Element("buildTarget", makeTarget ? makeTarget : target.c_str());
+ xml.Element("stopOnError", "true");
+ xml.Element("useDefaultCommand", "false");
+ xml.EndElement();
}
-void cmExtraEclipseCDT4Generator
-::AppendScannerProfile(cmGeneratedFileStream& fout,
- const std::string& profileID,
- bool openActionEnabled,
- const std::string& openActionFilePath,
- bool pParserEnabled,
- const std::string& scannerInfoProviderID,
- const std::string& runActionArguments,
- const std::string& runActionCommand,
- bool runActionUseDefault,
- bool sipParserEnabled)
+void cmExtraEclipseCDT4Generator::AppendScannerProfile(
+ cmXMLWriter& xml, const std::string& profileID, bool openActionEnabled,
+ const std::string& openActionFilePath, bool pParserEnabled,
+ const std::string& scannerInfoProviderID,
+ const std::string& runActionArguments, const std::string& runActionCommand,
+ bool runActionUseDefault, bool sipParserEnabled)
{
- fout <<
- "<profile id=\"" << profileID << "\">\n"
- "<buildOutputProvider>\n"
- "<openAction enabled=\"" << (openActionEnabled ? "true" : "false")
- << "\" filePath=\"" << openActionFilePath << "\"/>\n"
- "<parser enabled=\"" << (pParserEnabled ? "true" : "false") << "\"/>\n"
- "</buildOutputProvider>\n"
- "<scannerInfoProvider id=\"" << scannerInfoProviderID << "\">\n"
- "<runAction arguments=\"" << runActionArguments << "\""
- " command=\"" << runActionCommand
- << "\" useDefault=\"" << (runActionUseDefault ? "true":"false") << "\"/>\n"
- "<parser enabled=\"" << (sipParserEnabled ? "true" : "false") << "\"/>\n"
- "</scannerInfoProvider>\n"
- "</profile>\n"
- ;
+ xml.StartElement("profile");
+ xml.Attribute("id", profileID);
+
+ xml.StartElement("buildOutputProvider");
+ xml.StartElement("openAction");
+ xml.Attribute("enabled", openActionEnabled ? "true" : "false");
+ xml.Attribute("filePath", openActionFilePath);
+ xml.EndElement(); // openAction
+ xml.StartElement("parser");
+ xml.Attribute("enabled", pParserEnabled ? "true" : "false");
+ xml.EndElement(); // parser
+ xml.EndElement(); // buildOutputProvider
+
+ xml.StartElement("scannerInfoProvider");
+ xml.Attribute("id", scannerInfoProviderID);
+ xml.StartElement("runAction");
+ xml.Attribute("arguments", runActionArguments);
+ xml.Attribute("command", runActionCommand);
+ xml.Attribute("useDefault", runActionUseDefault ? "true" : "false");
+ xml.EndElement(); // runAction
+ xml.StartElement("parser");
+ xml.Attribute("enabled", sipParserEnabled ? "true" : "false");
+ xml.EndElement(); // parser
+ xml.EndElement(); // scannerInfoProvider
+
+ xml.EndElement(); // profile
}
-void cmExtraEclipseCDT4Generator
-::AppendLinkedResource (cmGeneratedFileStream& fout,
- const std::string& name,
- const std::string& path,
- LinkType linkType)
+void cmExtraEclipseCDT4Generator::AppendLinkedResource(cmXMLWriter& xml,
+ const std::string& name,
+ const std::string& path,
+ LinkType linkType)
{
const char* locationTag = "location";
- const char* typeTag = "2";
+ int typeTag = 2;
if (linkType == VirtualFolder) // ... and not a linked folder
- {
+ {
locationTag = "locationURI";
- }
- if (linkType == LinkToFile)
- {
- typeTag = "1";
- }
-
- fout <<
- "\t\t<link>\n"
- "\t\t\t<name>"
- << cmExtraEclipseCDT4Generator::EscapeForXML(name)
- << "</name>\n"
- "\t\t\t<type>" << typeTag << "</type>\n"
- "\t\t\t<" << locationTag << ">"
- << cmExtraEclipseCDT4Generator::EscapeForXML(path)
- << "</" << locationTag << ">\n"
- "\t\t</link>\n"
- ;
+ }
+ if (linkType == LinkToFile) {
+ typeTag = 1;
+ }
+
+ xml.StartElement("link");
+ xml.Element("name", name);
+ xml.Element("type", typeTag);
+ xml.Element(locationTag, path);
+ xml.EndElement();
}
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index b31cce74c..1380d1867 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -1,23 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
- Copyright 2007 Miguel A. Figueroa-Villanueva
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExtraEclipseCDT4Generator_h
#define cmExtraEclipseCDT4Generator_h
+#include "cmConfigure.h"
+
#include "cmExternalMakefileProjectGenerator.h"
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
class cmMakefile;
-class cmGeneratedFileStream;
+class cmSourceGroup;
+class cmXMLWriter;
/** \class cmExtraEclipseCDT4Generator
* \brief Write Eclipse project files for Makefile based projects
@@ -25,24 +23,21 @@ class cmGeneratedFileStream;
class cmExtraEclipseCDT4Generator : public cmExternalMakefileProjectGenerator
{
public:
- enum LinkType {VirtualFolder, LinkToFolder, LinkToFile };
+ enum LinkType
+ {
+ VirtualFolder,
+ LinkToFolder,
+ LinkToFile
+ };
cmExtraEclipseCDT4Generator();
- static cmExternalMakefileProjectGenerator* New() {
- return new cmExtraEclipseCDT4Generator;
- }
-
- virtual const char* GetName() const {
- return cmExtraEclipseCDT4Generator::GetActualName();
- }
+ static cmExternalMakefileProjectGeneratorFactory* GetFactory();
- static const char* GetActualName() { return "Eclipse CDT4"; }
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) CM_OVERRIDE;
- virtual void GetDocumentation(cmDocumentationEntry& entry,
- const char* fullName) const;
-
- virtual void Generate();
+ void Generate() CM_OVERRIDE;
private:
// create .project file in the source tree
@@ -65,46 +60,38 @@ private:
const std::string& type,
const std::string& path);
- static std::string EscapeForXML(const std::string& value);
-
// Helper functions
- static void AppendStorageScanners(cmGeneratedFileStream& fout,
+ static void AppendStorageScanners(cmXMLWriter& xml,
const cmMakefile& makefile);
- static void AppendTarget (cmGeneratedFileStream& fout,
- const std::string& target,
- const std::string& make,
- const std::string& makeArguments,
- const std::string& path,
- const char* prefix = "",
- const char* makeTarget = NULL);
- static void AppendScannerProfile (cmGeneratedFileStream& fout,
- const std::string& profileID,
- bool openActionEnabled,
- const std::string& openActionFilePath,
- bool pParserEnabled,
- const std::string& scannerInfoProviderID,
- const std::string& runActionArguments,
- const std::string& runActionCommand,
- bool runActionUseDefault,
- bool sipParserEnabled);
-
- static void AppendLinkedResource (cmGeneratedFileStream& fout,
- const std::string& name,
- const std::string& path,
- LinkType linkType);
-
- static void AppendIncludeDirectories(cmGeneratedFileStream& fout,
- const std::vector<std::string>& includeDirs,
- std::set<std::string>& emittedDirs);
-
- static void AddEnvVar(cmGeneratedFileStream& fout, const char* envVar,
- cmMakefile* mf);
-
- void CreateLinksToSubprojects(cmGeneratedFileStream& fout,
- const std::string& baseDir);
- void CreateLinksForTargets(cmGeneratedFileStream& fout);
+ static void AppendTarget(cmXMLWriter& xml, const std::string& target,
+ const std::string& make,
+ const std::string& makeArguments,
+ const std::string& path, const char* prefix = "",
+ const char* makeTarget = CM_NULLPTR);
+ static void AppendScannerProfile(
+ cmXMLWriter& xml, const std::string& profileID, bool openActionEnabled,
+ const std::string& openActionFilePath, bool pParserEnabled,
+ const std::string& scannerInfoProviderID,
+ const std::string& runActionArguments, const std::string& runActionCommand,
+ bool runActionUseDefault, bool sipParserEnabled);
+
+ static void AppendLinkedResource(cmXMLWriter& xml, const std::string& name,
+ const std::string& path, LinkType linkType);
+
+ static void AppendIncludeDirectories(
+ cmXMLWriter& xml, const std::vector<std::string>& includeDirs,
+ std::set<std::string>& emittedDirs);
+
+ static void AddEnvVar(std::ostream& out, const char* envVar,
+ cmLocalGenerator* lg);
+
+ void WriteGroups(std::vector<cmSourceGroup> const& sourceGroups,
+ std::string& linkName, cmXMLWriter& xml);
+ void CreateLinksToSubprojects(cmXMLWriter& xml, const std::string& baseDir);
+ void CreateLinksForTargets(cmXMLWriter& xml);
std::vector<std::string> SrcLinkedResources;
+ std::set<std::string> Natures;
std::string HomeDirectory;
std::string HomeOutputDirectory;
bool IsOutOfSourceBuild;
@@ -112,7 +99,9 @@ private:
bool GenerateLinkedResources;
bool SupportsVirtualFolders;
bool SupportsGmakeErrorParser;
-
+ bool SupportsMachO64Parser;
+ bool CEnabled;
+ bool CXXEnabled;
};
#endif
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
new file mode 100644
index 000000000..373043309
--- /dev/null
+++ b/Source/cmExtraKateGenerator.cxx
@@ -0,0 +1,316 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmExtraKateGenerator.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 <ostream>
+#include <set>
+#include <string.h>
+#include <vector>
+
+cmExtraKateGenerator::cmExtraKateGenerator()
+ : cmExternalMakefileProjectGenerator()
+{
+}
+
+cmExternalMakefileProjectGeneratorFactory* cmExtraKateGenerator::GetFactory()
+{
+ static cmExternalMakefileProjectGeneratorSimpleFactory<cmExtraKateGenerator>
+ factory("Kate", "Generates Kate project files.");
+
+ if (factory.GetSupportedGlobalGenerators().empty()) {
+#if defined(_WIN32)
+ factory.AddSupportedGlobalGenerator("MinGW Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles");
+// disable until somebody actually tests it:
+// factory.AddSupportedGlobalGenerator("MSYS Makefiles");
+#endif
+ factory.AddSupportedGlobalGenerator("Ninja");
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
+ }
+
+ return &factory;
+}
+
+void cmExtraKateGenerator::Generate()
+{
+ cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const cmMakefile* mf = lg->GetMakefile();
+ this->ProjectName = this->GenerateProjectName(
+ lg->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
+ this->GetPathBasename(lg->GetBinaryDirectory()));
+ this->UseNinja = (this->GlobalGenerator->GetName() == "Ninja");
+
+ this->CreateKateProjectFile(lg);
+ this->CreateDummyKateProjectFile(lg);
+}
+
+void cmExtraKateGenerator::CreateKateProjectFile(
+ const cmLocalGenerator* lg) const
+{
+ std::string filename = lg->GetBinaryDirectory();
+ filename += "/.kateproject";
+ cmGeneratedFileStream fout(filename.c_str());
+ if (!fout) {
+ return;
+ }
+
+ /* clang-format off */
+ fout <<
+ "{\n"
+ "\t\"name\": \"" << this->ProjectName << "\",\n"
+ "\t\"directory\": \"" << lg->GetSourceDirectory() << "\",\n"
+ "\t\"files\": [ { " << this->GenerateFilesString(lg) << "} ],\n";
+ /* clang-format on */
+ this->WriteTargets(lg, fout);
+ fout << "}\n";
+}
+
+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 =
+ mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS");
+ const char* homeOutputDir = lg->GetBinaryDirectory();
+
+ /* clang-format off */
+ fout <<
+ "\t\"build\": {\n"
+ "\t\t\"directory\": \"" << lg->GetBinaryDirectory() << "\",\n"
+ "\t\t\"default_target\": \"all\",\n"
+ "\t\t\"clean_target\": \"clean\",\n";
+ /* clang-format on */
+
+ // build, clean and quick are for the build plugin kate <= 4.12:
+ fout << "\t\t\"build\": \"" << make << " -C \\\"" << homeOutputDir << "\\\" "
+ << makeArgs << " "
+ << "all\",\n";
+ fout << "\t\t\"clean\": \"" << make << " -C \\\"" << homeOutputDir << "\\\" "
+ << makeArgs << " "
+ << "clean\",\n";
+ fout << "\t\t\"quick\": \"" << make << " -C \\\"" << homeOutputDir << "\\\" "
+ << makeArgs << " "
+ << "install\",\n";
+
+ // this is for kate >= 4.13:
+ fout << "\t\t\"targets\":[\n";
+
+ this->AppendTarget(fout, "all", make, makeArgs, homeOutputDir,
+ homeOutputDir);
+ this->AppendTarget(fout, "clean", make, makeArgs, homeOutputDir,
+ homeOutputDir);
+
+ // 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()) {
+ case cmStateEnums::GLOBAL_TARGET: {
+ bool insertTarget = false;
+ // Only add the global targets from CMAKE_BINARY_DIR,
+ // not from the subdirs
+ if (topLevel) {
+ insertTarget = true;
+ // only add the "edit_cache" target if it's not ccmake, because
+ // this will not work within the IDE
+ if (targetName == "edit_cache") {
+ const char* editCommand =
+ (*it)->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND");
+ if (editCommand == CM_NULLPTR) {
+ insertTarget = false;
+ } else if (strstr(editCommand, "ccmake") != CM_NULLPTR) {
+ insertTarget = false;
+ }
+ }
+ }
+ if (insertTarget) {
+ this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
+ homeOutputDir);
+ }
+ } break;
+ case cmStateEnums::UTILITY:
+ // Add all utility targets, except the Nightly/Continuous/
+ // Experimental-"sub"targets as e.g. NightlyStart
+ if (((targetName.find("Nightly") == 0) &&
+ (targetName != "Nightly")) ||
+ ((targetName.find("Continuous") == 0) &&
+ (targetName != "Continuous")) ||
+ ((targetName.find("Experimental") == 0) &&
+ (targetName != "Experimental"))) {
+ break;
+ }
+
+ this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
+ homeOutputDir);
+ break;
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY: {
+ this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
+ homeOutputDir);
+ std::string fastTarget = targetName;
+ fastTarget += "/fast";
+ this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir,
+ homeOutputDir);
+
+ } break;
+ default:
+ break;
+ }
+ }
+
+ // 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);
+ }
+ }
+
+ fout << "\t] }\n";
+}
+
+void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout,
+ const std::string& target,
+ const std::string& make,
+ const std::string& makeArgs,
+ const std::string& path,
+ const char* homeOutputDir) const
+{
+ static char JsonSep = ' ';
+
+ fout << "\t\t\t" << JsonSep << "{\"name\":\"" << target << "\", "
+ "\"build_cmd\":\""
+ << make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path.c_str())
+ << "\\\" " << makeArgs << " " << target << "\"}\n";
+
+ JsonSep = ',';
+}
+
+void cmExtraKateGenerator::CreateDummyKateProjectFile(
+ const cmLocalGenerator* lg) const
+{
+ std::string filename = lg->GetBinaryDirectory();
+ filename += "/";
+ filename += this->ProjectName;
+ filename += ".kateproject";
+ cmGeneratedFileStream fout(filename.c_str());
+ if (!fout) {
+ return;
+ }
+
+ fout << "#Generated by " << cmSystemTools::GetCMakeCommand()
+ << ", do not edit.\n";
+}
+
+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 ");
+ }
+
+ s = lg->GetSourceDirectory();
+ s += "/.svn";
+ if (cmSystemTools::FileExists(s.c_str())) {
+ return std::string("\"svn\": 1 ");
+ }
+
+ s = lg->GetSourceDirectory();
+ s += "/";
+
+ 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();
+ const std::vector<std::string>& listFiles = makefile->GetListFiles();
+ for (std::vector<std::string>::const_iterator lt = listFiles.begin();
+ lt != listFiles.end(); lt++) {
+ tmp = *lt;
+ {
+ 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")) {
+ continue;
+ }
+
+ tmp = sf->GetFullPath();
+ files.insert(tmp);
+ }
+ }
+
+ const char* sep = "";
+ tmp = "\"list\": [";
+ for (std::set<std::string>::const_iterator it = files.begin();
+ it != files.end(); ++it) {
+ tmp += sep;
+ tmp += " \"";
+ tmp += *it;
+ tmp += "\"";
+ sep = ",";
+ }
+ tmp += "] ";
+
+ return tmp;
+}
+
+std::string cmExtraKateGenerator::GenerateProjectName(
+ const std::string& name, const std::string& type,
+ const std::string& path) const
+{
+ return name + (type.empty() ? "" : "-") + type + "@" + path;
+}
+
+std::string cmExtraKateGenerator::GetPathBasename(
+ const std::string& path) const
+{
+ std::string outputBasename = path;
+ while (!outputBasename.empty() &&
+ (outputBasename[outputBasename.size() - 1] == '/' ||
+ outputBasename[outputBasename.size() - 1] == '\\')) {
+ outputBasename.resize(outputBasename.size() - 1);
+ }
+ std::string::size_type loc = outputBasename.find_last_of("/\\");
+ if (loc != std::string::npos) {
+ outputBasename = outputBasename.substr(loc + 1);
+ }
+
+ return outputBasename;
+}
diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h
new file mode 100644
index 000000000..6b9c7af5c
--- /dev/null
+++ b/Source/cmExtraKateGenerator.h
@@ -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. */
+#ifndef cmExtraKateGenerator_h
+#define cmExtraKateGenerator_h
+
+#include "cmConfigure.h"
+
+#include "cmExternalMakefileProjectGenerator.h"
+
+#include <string>
+
+class cmGeneratedFileStream;
+class cmLocalGenerator;
+
+/** \class cmExtraKateGenerator
+ * \brief Write Kate project files for Makefile or ninja based projects
+ */
+class cmExtraKateGenerator : public cmExternalMakefileProjectGenerator
+{
+public:
+ cmExtraKateGenerator();
+
+ static cmExternalMakefileProjectGeneratorFactory* GetFactory();
+
+ void Generate() CM_OVERRIDE;
+
+private:
+ void CreateKateProjectFile(const cmLocalGenerator* lg) const;
+ void CreateDummyKateProjectFile(const cmLocalGenerator* lg) const;
+ void WriteTargets(const cmLocalGenerator* lg,
+ 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;
+
+ std::string GenerateFilesString(const cmLocalGenerator* lg) const;
+ std::string GetPathBasename(const std::string& path) const;
+ std::string GenerateProjectName(const std::string& name,
+ const std::string& type,
+ const std::string& path) const;
+
+ std::string ProjectName;
+ bool UseNinja;
+};
+
+#endif
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 523fca9aa..1fd1418de 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -1,29 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraSublimeTextGenerator.h"
-#include "cmake.h"
+
+#include "cmsys/RegularExpression.hxx"
+#include <set>
+#include <sstream>
+#include <string.h>
+#include <utility>
+
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
-#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
-#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cmXMLSafe.h"
-
-#include <cmsys/SystemTools.hxx>
+#include "cmake.h"
/*
Sublime Text 2 Generator
@@ -39,97 +33,92 @@ http://www.sublimetext.com/docs/2/projects.html
http://sublimetext.info/docs/en/reference/build_systems.html
*/
-//----------------------------------------------------------------------------
-void cmExtraSublimeTextGenerator
-::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+cmExternalMakefileProjectGeneratorFactory*
+cmExtraSublimeTextGenerator::GetFactory()
{
- entry.Name = this->GetName();
- entry.Brief = "Generates Sublime Text 2 project files.";
- entry.Full =
- "Project files for Sublime Text 2 will be created in the top directory "
- "and in every subdirectory which features a CMakeLists.txt file "
- "containing a PROJECT() call. "
- "Additionally Makefiles (or build.ninja files) are generated into the "
- "build tree. The appropriate make program can build the project through "
- "the default make target. A \"make install\" target is also provided.";
-}
+ static cmExternalMakefileProjectGeneratorSimpleFactory<
+ cmExtraSublimeTextGenerator>
+ factory("Sublime Text 2", "Generates Sublime Text 2 project files.");
-cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator()
-:cmExternalMakefileProjectGenerator()
-{
+ if (factory.GetSupportedGlobalGenerators().empty()) {
#if defined(_WIN32)
- this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
- this->SupportedGlobalGenerators.push_back("NMake Makefiles");
+ factory.AddSupportedGlobalGenerator("MinGW Makefiles");
+ factory.AddSupportedGlobalGenerator("NMake Makefiles");
// disable until somebody actually tests it:
-// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
+// factory.AddSupportedGlobalGenerator("MSYS Makefiles");
#endif
- this->SupportedGlobalGenerators.push_back("Ninja");
- this->SupportedGlobalGenerators.push_back("Unix Makefiles");
+ factory.AddSupportedGlobalGenerator("Ninja");
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
+ }
+
+ return &factory;
}
+cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator()
+ : cmExternalMakefileProjectGenerator()
+{
+ this->ExcludeBuildFolder = false;
+}
void cmExtraSublimeTextGenerator::Generate()
{
+ this->ExcludeBuildFolder = this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE");
+ this->EnvSettings = this->GlobalGenerator->GetSafeGlobalSetting(
+ "CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS");
+
// for each sub project in the project create a sublime text 2 project
- for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it!= this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
+ for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
// create a project file
this->CreateProjectFile(it->second);
- }
+ }
}
-
void cmExtraSublimeTextGenerator::CreateProjectFile(
- const std::vector<cmLocalGenerator*>& lgs)
+ const std::vector<cmLocalGenerator*>& lgs)
{
- const cmMakefile* mf=lgs[0]->GetMakefile();
- std::string outputDir=mf->GetStartOutputDirectory();
- std::string projectName=mf->GetProjectName();
+ std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
+ std::string projectName = lgs[0]->GetProjectName();
const std::string filename =
- outputDir + "/" + projectName + ".sublime-project";
+ outputDir + "/" + projectName + ".sublime-project";
this->CreateNewProjectFile(lgs, filename);
}
-void cmExtraSublimeTextGenerator
- ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
- const std::string& filename)
+void cmExtraSublimeTextGenerator::CreateNewProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
- const cmMakefile* mf=lgs[0]->GetMakefile();
+ const cmMakefile* mf = lgs[0]->GetMakefile();
+
cmGeneratedFileStream fout(filename.c_str());
- if(!fout)
- {
+ if (!fout) {
return;
- }
+ }
- const std::string &sourceRootRelativeToOutput = cmSystemTools::RelativePath(
- mf->GetHomeOutputDirectory(),
- mf->GetHomeDirectory());
+ const std::string& sourceRootRelativeToOutput = cmSystemTools::RelativePath(
+ lgs[0]->GetBinaryDirectory(), lgs[0]->GetSourceDirectory());
// Write the folder entries to the project file
fout << "{\n";
fout << "\t\"folders\":\n\t[\n\t";
- if (!sourceRootRelativeToOutput.empty())
- {
- fout << "\t{\n\t\t\t\"path\": \"" << sourceRootRelativeToOutput << "\"";
- const std::string &outputRelativeToSourceRoot =
- cmSystemTools::RelativePath(mf->GetHomeDirectory(),
- mf->GetHomeOutputDirectory());
- if ((!outputRelativeToSourceRoot.empty()) &&
+ if (!sourceRootRelativeToOutput.empty()) {
+ fout << "\t{\n\t\t\t\"path\": \"" << sourceRootRelativeToOutput << "\"";
+ const std::string& outputRelativeToSourceRoot =
+ cmSystemTools::RelativePath(lgs[0]->GetSourceDirectory(),
+ lgs[0]->GetBinaryDirectory());
+ if ((!outputRelativeToSourceRoot.empty()) &&
((outputRelativeToSourceRoot.length() < 3) ||
- (outputRelativeToSourceRoot.substr(0, 3) != "../")))
- {
- fout << ",\n\t\t\t\"folder_exclude_patterns\": [\"" <<
- outputRelativeToSourceRoot << "\"]";
- }
- }
- else
- {
- fout << "\t{\n\t\t\t\"path\": \"./\"";
+ (outputRelativeToSourceRoot.substr(0, 3) != "../"))) {
+ if (this->ExcludeBuildFolder) {
+ fout << ",\n\t\t\t\"folder_exclude_patterns\": [\""
+ << outputRelativeToSourceRoot << "\"]";
+ }
}
+ } else {
+ fout << "\t{\n\t\t\t\"path\": \"./\"";
+ }
fout << "\n\t\t}";
// End of the folders section
fout << "\n\t]";
@@ -145,330 +134,273 @@ void cmExtraSublimeTextGenerator
// End of build_systems
fout << "\n\t]";
- fout << "\n\t}";
+ std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
+ std::vector<std::string> tokens;
+ cmSystemTools::ExpandListArgument(this->EnvSettings, tokens);
+
+ if (!this->EnvSettings.empty()) {
+ fout << ",";
+ fout << "\n\t\"env\":";
+ 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('=');
+
+ if (pos != std::string::npos) {
+ std::string varName = i->substr(0, pos);
+ std::string varValue = i->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());
+ }
+ }
+ fout << "\n\t\t}";
+ fout << "\n\t}";
+ }
+ fout << "\n}";
}
-
-void cmExtraSublimeTextGenerator::
- AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
- const cmMakefile* mf,
- cmGeneratedFileStream& fout,
- MapSourceFileFlags& sourceFileFlags)
+void cmExtraSublimeTextGenerator::AppendAllTargets(
+ const std::vector<cmLocalGenerator*>& lgs, const cmMakefile* mf,
+ cmGeneratedFileStream& fout, MapSourceFileFlags& sourceFileFlags)
{
std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- std::string compiler = "";
- if (!lgs.empty())
- {
- this->AppendTarget(fout, "all", lgs[0], 0, make.c_str(), mf,
- compiler.c_str(), sourceFileFlags, true);
- this->AppendTarget(fout, "clean", lgs[0], 0, make.c_str(), mf,
- compiler.c_str(), sourceFileFlags, false);
- }
+ std::string compiler;
+ if (!lgs.empty()) {
+ this->AppendTarget(fout, "all", lgs[0], CM_NULLPTR, make.c_str(), mf,
+ compiler.c_str(), sourceFileFlags, true);
+ this->AppendTarget(fout, "clean", lgs[0], CM_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();
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- switch(ti->second.GetType())
- {
- case cmTarget::GLOBAL_TARGET:
- {
- bool insertTarget = false;
+ 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()) {
+ case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp(makefile->GetStartOutputDirectory(),
- makefile->GetHomeOutputDirectory())==0)
- {
- insertTarget = true;
- // only add the "edit_cache" target if it's not ccmake, because
- // this will not work within the IDE
- if (ti->first == "edit_cache")
- {
- const char* editCommand = makefile->GetDefinition
- ("CMAKE_EDIT_COMMAND");
- if (editCommand == 0)
- {
- insertTarget = false;
- }
- else if (strstr(editCommand, "ccmake")!=NULL)
- {
- insertTarget = false;
- }
- }
- }
- if (insertTarget)
- {
- this->AppendTarget(fout, ti->first.c_str(), *lg, 0,
- make.c_str(), makefile, compiler.c_str(),
- sourceFileFlags, false);
- }
+ if (strcmp((*lg)->GetCurrentBinaryDirectory(),
+ (*lg)->GetBinaryDirectory()) == 0) {
+ this->AppendTarget(fout, targetName, *lg, CM_NULLPTR, make.c_str(),
+ makefile, compiler.c_str(), sourceFileFlags,
+ false);
}
- break;
- case cmTarget::UTILITY:
+ } break;
+ case cmStateEnums::UTILITY:
// Add all utility targets, except the Nightly/Continuous/
// Experimental-"sub"targets as e.g. NightlyStart
- if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly"))
- || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
- || ((ti->first.find("Experimental")==0)
- && (ti->first!="Experimental")))
- {
+ if (((targetName.find("Nightly") == 0) &&
+ (targetName != "Nightly")) ||
+ ((targetName.find("Continuous") == 0) &&
+ (targetName != "Continuous")) ||
+ ((targetName.find("Experimental") == 0) &&
+ (targetName != "Experimental"))) {
break;
- }
+ }
- this->AppendTarget(fout, ti->first.c_str(), *lg, 0,
- make.c_str(), makefile, compiler.c_str(),
- sourceFileFlags, false);
+ this->AppendTarget(fout, targetName, *lg, CM_NULLPTR, make.c_str(),
+ makefile, compiler.c_str(), sourceFileFlags,
+ false);
break;
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- {
- this->AppendTarget(fout, ti->first.c_str(), *lg, &ti->second,
- make.c_str(), makefile, compiler.c_str(),
- sourceFileFlags, false);
- std::string fastTarget = ti->first;
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY: {
+ this->AppendTarget(fout, targetName, *lg, *ti, make.c_str(),
+ makefile, compiler.c_str(), sourceFileFlags,
+ false);
+ std::string fastTarget = targetName;
fastTarget += "/fast";
- this->AppendTarget(fout, fastTarget.c_str(), *lg, &ti->second,
- make.c_str(), makefile, compiler.c_str(),
- sourceFileFlags, false);
- }
- break;
+ this->AppendTarget(fout, fastTarget, *lg, *ti, make.c_str(),
+ makefile, compiler.c_str(), sourceFileFlags,
+ false);
+ } break;
default:
break;
- }
}
}
+ }
}
-void cmExtraSublimeTextGenerator::
- AppendTarget(cmGeneratedFileStream& fout,
- const char* targetName,
- cmLocalGenerator* lg,
- cmTarget* target,
- const char* make,
- const cmMakefile* makefile,
- const char*, //compiler
- MapSourceFileFlags& sourceFileFlags,
- bool firstTarget)
+void cmExtraSublimeTextGenerator::AppendTarget(
+ cmGeneratedFileStream& fout, const std::string& targetName,
+ cmLocalGenerator* lg, cmGeneratorTarget* target, const char* make,
+ const cmMakefile* makefile, const char* /*compiler*/,
+ MapSourceFileFlags& sourceFileFlags, bool firstTarget)
{
- if (target != 0)
- {
- cmGeneratorTarget *gtgt = this->GlobalGenerator
- ->GetGeneratorTarget(target);
- std::vector<cmSourceFile*> const& sourceFiles = target->GetSourceFiles();
- 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());
- if (sourceFileFlagsIter == sourceFileFlags.end())
- {
- sourceFileFlagsIter =
- sourceFileFlags.insert(MapSourceFileFlags::value_type(
- sourceFile->GetFullPath(), std::vector<std::string>())).first;
- }
- std::vector<std::string>& flags = sourceFileFlagsIter->second;
- std::string flagsString =
- this->ComputeFlagsForObject(*iter, lg, target, gtgt);
- std::string definesString =
- this->ComputeDefines(*iter, lg, target, gtgt);
- flags.clear();
- cmsys::RegularExpression flagRegex;
- // Regular expression to extract compiler flags from a string
- // https://gist.github.com/3944250
- const char* regexString =
- "(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
- flagRegex.compile(regexString);
- std::string workString = flagsString + " " + definesString;
- while (flagRegex.find(workString))
- {
- std::string::size_type start = flagRegex.start();
- if (workString[start] == ' ')
- {
- start++;
- }
- flags.push_back(workString.substr(start,
- flagRegex.end() - start));
- if (flagRegex.end() < workString.size())
- {
- workString = workString.substr(flagRegex.end());
- }
- else
- {
- workString = "";
- }
- }
+ if (target != CM_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());
+ if (sourceFileFlagsIter == sourceFileFlags.end()) {
+ sourceFileFlagsIter =
+ sourceFileFlags
+ .insert(MapSourceFileFlags::value_type(sourceFile->GetFullPath(),
+ 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);
+ flags.clear();
+ cmsys::RegularExpression flagRegex;
+ // Regular expression to extract compiler flags from a string
+ // https://gist.github.com/3944250
+ const char* regexString =
+ "(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
+ flagRegex.compile(regexString);
+ std::string workString = flagsString + " " + definesString;
+ while (flagRegex.find(workString)) {
+ std::string::size_type start = flagRegex.start();
+ if (workString[start] == ' ') {
+ start++;
}
+ flags.push_back(workString.substr(start, flagRegex.end() - start));
+ if (flagRegex.end() < workString.size()) {
+ workString = workString.substr(flagRegex.end());
+ } else {
+ workString = "";
+ }
+ }
}
+ }
// Ninja uses ninja.build files (look for a way to get the output file name
// from cmMakefile or something)
std::string makefileName;
- if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
- {
- makefileName = "build.ninja";
- }
- else
- {
- makefileName = "Makefile";
- }
- if (!firstTarget)
- {
+ if (this->GlobalGenerator->GetName() == "Ninja") {
+ makefileName = "build.ninja";
+ } else {
+ makefileName = "Makefile";
+ }
+ if (!firstTarget) {
fout << ",\n\t";
- }
- fout << "\t{\n\t\t\t\"name\": \"" << makefile->GetProjectName() << " - " <<
- targetName << "\",\n";
- fout << "\t\t\t\"cmd\": [" <<
- this->BuildMakeCommand(make, makefileName.c_str(), targetName) <<
- "],\n";
+ }
+ fout << "\t{\n\t\t\t\"name\": \"" << lg->GetProjectName() << " - "
+ << targetName << "\",\n";
+ fout << "\t\t\t\"cmd\": ["
+ << this->BuildMakeCommand(make, makefileName.c_str(), targetName)
+ << "],\n";
fout << "\t\t\t\"working_dir\": \"${project_path}\",\n";
- fout << "\t\t\t\"file_regex\": \"^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$\"\n";
+ fout << "\t\t\t\"file_regex\": \""
+ "^(..[^:]*)(?::|\\\\()([0-9]+)(?::|\\\\))(?:([0-9]+):)?\\\\s*(.*)"
+ "\"\n";
fout << "\t\t}";
}
// Create the command line for building the given target using the selected
// make
std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
- const std::string& make, const char* makefile, const char* target)
+ const std::string& make, const char* makefile, const std::string& target)
{
std::string command = "\"";
command += make + "\"";
- if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
- {
+ std::string generator = this->GlobalGenerator->GetName();
+ if (generator == "NMake Makefiles") {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
command += ", \"/NOLOGO\", \"/f\", \"";
command += makefileName + "\"";
- command += ", \"VERBOSE=1\", \"";
- command += target;
- command += "\"";
- }
- else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
- {
+ command += ", \"" + target + "\"";
+ } else if (generator == "Ninja") {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
command += ", \"-f\", \"";
command += makefileName + "\"";
- command += ", \"-v\", \"";
- command += target;
- command += "\"";
- }
- else
- {
+ command += ", \"" + target + "\"";
+ } else {
std::string makefileName;
- if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
- {
- // no escaping of spaces in this case, see
- // http://public.kitware.com/Bug/view.php?id=10014
- makefileName = makefile;
- }
- else
- {
- makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- }
+ if (generator == "MinGW Makefiles") {
+ // no escaping of spaces in this case, see
+ // https://gitlab.kitware.com/cmake/cmake/issues/10014
+ makefileName = makefile;
+ } else {
+ makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ }
command += ", \"-f\", \"";
command += makefileName + "\"";
- command += ", \"VERBOSE=1\", \"";
- command += target;
- command += "\"";
- }
+ command += ", \"" + target + "\"";
+ }
return command;
}
// TODO: Most of the code is picked up from the Ninja generator, refactor it.
-std::string
-cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
- cmLocalGenerator* lg,
- cmTarget *target,
- cmGeneratorTarget* gtgt)
+std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
+ cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* gtgt)
{
std::string flags;
+ std::string language = source->GetLanguage();
+ if (language.empty()) {
+ language = "C";
+ }
+ std::string const& config =
+ lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
- cmMakefile *makefile = lg->GetMakefile();
- const char* language = source->GetLanguage();
- if (language == NULL)
- {
- language = "C";
- }
- const char* config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- // Add language-specific flags.
- lg->AddLanguageFlags(flags, language, config);
-
- lg->AddArchitectureFlags(flags, gtgt, language, config);
-
- // TODO: Fortran support.
- // // Fortran-specific flags computed for this target.
- // if(*l == "Fortran")
- // {
- // this->AddFortranFlags(flags);
- // }
-
- // Add shared-library flags if needed.
- lg->AddCMP0018Flags(flags, target, language, config);
+ 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.c_str());
+ 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);
}
- // Append old-style preprocessor definition flags.
- lg->AppendFlags(flags, makefile->GetDefineFlags());
-
- // Add target-specific flags.
- lg->AddCompileOptions(flags, target, config, language);
-
// Add source file specific flags.
- lg->AppendFlags(flags, source->GetProperty("COMPILE_FLAGS"));
-
- // TODO: Handle Apple frameworks.
+ if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
+ cmGeneratorExpression ge;
+ const char* processed = ge.Parse(cflags)->Evaluate(lg, config);
+ lg->AppendFlags(flags, processed);
+ }
return flags;
}
// TODO: Refactor with
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
-std::string
-cmExtraSublimeTextGenerator::
-ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
- cmGeneratorTarget*)
+std::string cmExtraSublimeTextGenerator::ComputeDefines(
+ cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* target)
{
std::set<std::string> defines;
- cmMakefile *makefile = lg->GetMakefile();
- const char* language = source->GetLanguage();
- if (language == NULL)
- {
- language = "";
- }
- const char* config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmMakefile* makefile = lg->GetMakefile();
+ const std::string& language = source->GetLanguage();
+ const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
// Add the export symbol definition for shared library objects.
- if(const char* exportMacro = target->GetExportMacro())
- {
+ if (const char* exportMacro = target->GetExportMacro()) {
lg->AppendDefines(defines, exportMacro);
- }
+ }
// Add preprocessor definitions for this target and configuration.
- lg->AddCompileDefinitions(defines, target, config);
+ 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.c_str()));
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(config);
+ lg->AppendDefines(defines, source->GetProperty(defPropName));
}
std::string definesString;
diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h
index 790259372..9022d3754 100644
--- a/Source/cmExtraSublimeTextGenerator.h
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -1,26 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmExtraSublimeTextGenerator_h
#define cmExtraSublimeTextGenerator_h
+#include "cmConfigure.h"
+
#include "cmExternalMakefileProjectGenerator.h"
-#include "cmSourceFile.h"
-class cmLocalGenerator;
-class cmMakefile;
-class cmTarget;
+#include <map>
+#include <string>
+#include <vector>
+
class cmGeneratedFileStream;
class cmGeneratorTarget;
+class cmLocalGenerator;
+class cmMakefile;
+class cmSourceFile;
/** \class cmExtraSublimeTextGenerator
* \brief Write Sublime Text 2 project files for Makefile based projects
@@ -28,62 +23,50 @@ class cmGeneratorTarget;
class cmExtraSublimeTextGenerator : public cmExternalMakefileProjectGenerator
{
public:
+ static cmExternalMakefileProjectGeneratorFactory* GetFactory();
typedef std::map<std::string, std::vector<std::string> > MapSourceFileFlags;
cmExtraSublimeTextGenerator();
- virtual const char* GetName() const
- { return cmExtraSublimeTextGenerator::GetActualName();}
- static const char* GetActualName()
- { return "Sublime Text 2";}
- static cmExternalMakefileProjectGenerator* New()
- { return new cmExtraSublimeTextGenerator; }
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry,
- const char* fullName) const;
+ void Generate() CM_OVERRIDE;
- virtual void Generate();
private:
-
void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
- const std::string& filename);
+ const std::string& filename);
/** Appends all targets as build systems to the project file and get all
* include directories and compiler definitions used.
*/
void AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
- const cmMakefile* mf,
- cmGeneratedFileStream& fout,
+ const cmMakefile* mf, cmGeneratedFileStream& fout,
MapSourceFileFlags& sourceFileFlags);
/** Returns the build command that needs to be executed to build the
* specified target.
*/
std::string BuildMakeCommand(const std::string& make, const char* makefile,
- const char* target);
+ const std::string& target);
/** Appends the specified target to the generated project file as a Sublime
* Text build system.
*/
- void AppendTarget(cmGeneratedFileStream& fout,
- const char* targetName,
- cmLocalGenerator* lg,
- cmTarget* target,
- const char* make,
- const cmMakefile* makefile,
- const char* compiler,
- MapSourceFileFlags& sourceFileFlags, bool firstTarget);
+ void AppendTarget(cmGeneratedFileStream& fout, const std::string& targetName,
+ cmLocalGenerator* lg, cmGeneratorTarget* target,
+ const char* make, const cmMakefile* makefile,
+ const char* compiler, MapSourceFileFlags& sourceFileFlags,
+ bool firstTarget);
/**
* Compute the flags for compilation of object files for a given @a language.
* @note Generally it is the value of the variable whose name is computed
* by LanguageFlagsVarName().
*/
- std::string ComputeFlagsForObject(cmSourceFile *source,
- cmLocalGenerator* lg,
- cmTarget *target,
+ std::string ComputeFlagsForObject(cmSourceFile* source, cmLocalGenerator* lg,
cmGeneratorTarget* gtgt);
- std::string ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg,
- cmTarget *target, cmGeneratorTarget* gtgt);
+ std::string ComputeDefines(cmSourceFile* source, cmLocalGenerator* lg,
+ cmGeneratorTarget* gtgt);
+
+ bool ExcludeBuildFolder;
+ std::string EnvSettings;
};
#endif
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index b08c335ac..ff78f52e3 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -1,58 +1,51 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFLTKWrapUICommand.h"
+#include <stddef.h>
+
+#include "cmCustomCommandLines.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
+class cmTarget;
// cmFLTKWrapUICommand
-bool cmFLTKWrapUICommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// what is the current source dir
- std::string cdir = this->Makefile->GetCurrentDirectory();
+ std::string cdir = this->Makefile->GetCurrentSourceDirectory();
const char* fluid_exe =
this->Makefile->GetRequiredDefinition("FLTK_FLUID_EXECUTABLE");
// get parameter for the command
- this->Target = args[0]; // Target that will use the generated files
-
- std::vector<std::string> newArgs;
- this->Makefile->ExpandSourceListArguments(args,newArgs, 1);
+ this->Target = args[0]; // Target that will use the generated files
// get the list of GUI files from which .cxx and .h will be generated
- std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory();
+ std::string outputDirectory = this->Makefile->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 );
+ // 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);
}
- for(std::vector<std::string>::iterator i = (newArgs.begin() + 1);
- i != newArgs.end(); i++)
- {
- cmSourceFile *curr = this->Makefile->GetSource(i->c_str());
+ for (std::vector<std::string>::const_iterator i = (args.begin() + 1);
+ i != args.end(); i++) {
+ cmSourceFile* curr = this->Makefile->GetSource(*i);
// if we should use the source GUI
// to generate .cxx and .h files
- if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE"))
- {
+ if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) {
std::string outName = outputDirectory;
outName += "/";
outName += cmSystemTools::GetFilenameWithoutExtension(*i);
@@ -73,44 +66,40 @@ bool cmFLTKWrapUICommand
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
+ commandLine.push_back(origname); // name of the GUI fluid file
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
// Add command for generating the .h and .cxx files
- const char* no_main_dependency = 0;
- const char* no_comment = 0;
- const char* no_working_dir = 0;
- this->Makefile->AddCustomCommandToOutput(cxxres.c_str(),
- depends, no_main_dependency,
- commandLines, no_comment,
- no_working_dir);
- this->Makefile->AddCustomCommandToOutput(hname.c_str(),
- depends, no_main_dependency,
- commandLines, no_comment,
- no_working_dir);
-
- cmSourceFile *sf = this->Makefile->GetSource(cxxres.c_str());
- sf->AddDepend(hname.c_str());
- sf->AddDepend(origname.c_str());
+ 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);
+ sf->AddDepend(hname);
+ sf->AddDepend(origname);
this->GeneratedSourcesClasses.push_back(sf);
- }
}
+ }
// create the variable with the list of sources in it
size_t lastHeadersClass = this->GeneratedSourcesClasses.size();
std::string sourceListValue;
- for(size_t classNum = 0; classNum < lastHeadersClass; classNum++)
- {
- if (classNum)
- {
+ for (size_t classNum = 0; classNum < lastHeadersClass; classNum++) {
+ if (classNum) {
sourceListValue += ";";
- }
- sourceListValue += this->GeneratedSourcesClasses[classNum]->GetFullPath();
}
+ sourceListValue += this->GeneratedSourcesClasses[classNum]->GetFullPath();
+ }
std::string varName = this->Target;
varName += "_FLTK_UI_SRCS";
- this->Makefile->AddDefinition(varName.c_str(), sourceListValue.c_str());
+ this->Makefile->AddDefinition(varName, sourceListValue.c_str());
return true;
}
@@ -120,58 +109,15 @@ 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->FindTarget(this->Target.c_str());
- if(!target)
- {
+ 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->GetStartDirectory();
+ 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");
+ cmSystemTools::Message(msg.c_str(), "Warning");
return;
- }
- std::vector<cmSourceFile*> const& srcs =
- target->GetSourceFiles();
- bool found = false;
- for (unsigned int i = 0; i < srcs.size(); ++i)
- {
- if (srcs[i]->GetFullPath() ==
- this->GeneratedSourcesClasses[0]->GetFullPath())
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- std::string msg =
- "In CMake 2.2 the FLTK_WRAP_UI command sets a variable to the list of "
- "source files that should be added to your executable or library. It "
- "appears that you have not added these source files to your target. "
- "You should change your CMakeLists.txt file to "
- "directly add the generated files to the target. "
- "For example FTLK_WRAP_UI(foo src1 src2 src3) "
- "will create a variable named foo_FLTK_UI_SRCS that contains the list "
- "of sources to add to your target when you call ADD_LIBRARY or "
- "ADD_EXECUTABLE. For now CMake will add the sources to your target "
- "for you as was done in CMake 2.0 and earlier. In the future this may "
- "become an error.";
- msg +="The problem was found while processing the source directory: ";
- msg += this->Makefile->GetStartDirectory();
- cmSystemTools::Message(msg.c_str(),"Warning");
- // first we add the rules for all the .fl to .h and .cxx files
- size_t lastHeadersClass = this->GeneratedSourcesClasses.size();
-
- // Generate code for all the .fl files
- for(size_t classNum = 0; classNum < lastHeadersClass; classNum++)
- {
- this->Makefile->GetTargets()[this->Target]
- .AddSourceFile(this->GeneratedSourcesClasses[classNum]);
- }
- }
+ }
}
-
-
-
diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h
index 530de2c96..d8045ab6a 100644
--- a/Source/cmFLTKWrapUICommand.h
+++ b/Source/cmFLTKWrapUICommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFLTKWrapUICommand_h
#define cmFLTKWrapUICommand_h
+#include "cmConfigure.h"
+
+#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
*
@@ -23,22 +22,17 @@
class cmFLTKWrapUICommand : public cmCommand
{
public:
- cmTypeMacro(cmFLTKWrapUICommand, cmCommand);
-
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFLTKWrapUICommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFLTKWrapUICommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
* This is called at the end after all the information
@@ -46,41 +40,14 @@ public:
* not implement this method. At this point, reading and
* writing to the cache can be done.
*/
- virtual void FinalPass();
- virtual bool HasFinalPass() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "fltk_wrap_ui";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Create FLTK user interfaces Wrappers.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " fltk_wrap_ui(resultingLibraryName source1\n"
- " source2 ... sourceN )\n"
- "Produce .h and .cxx files for all the .fl and .fld files listed. "
- "The resulting .h and .cxx files will be added to a variable named "
- "resultingLibraryName_FLTK_UI_SRCS which should be added to your "
- "library.";
- }
+ void FinalPass() CM_OVERRIDE;
+ bool HasFinalPass() const CM_OVERRIDE { return true; }
private:
/**
* List of produced files.
*/
- std::vector<cmSourceFile *> GeneratedSourcesClasses;
+ std::vector<cmSourceFile*> GeneratedSourcesClasses;
/**
* List of Fluid files that provide the source
@@ -89,6 +56,4 @@ private:
std::string Target;
};
-
-
#endif
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 4446f7216..5777fb204 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1,37 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vector>
+
+#include "cmAlgorithms.h"
+#include "cmCommandArgumentsHelper.h"
#include "cmCryptoHash.h"
-#include "cmake.h"
+#include "cmFileLockPool.h"
+#include "cmFileTimeComparison.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
#include "cmHexFileConverter.h"
#include "cmInstallType.h"
-#include "cmFileTimeComparison.h"
-#include "cmCryptoHash.h"
-
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmPolicies.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"
#endif
-#undef GetCurrentDirectory
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#if defined(CMAKE_USE_ELF_PARSER)
+#include "cmELF.h"
+#endif
-#include <cmsys/auto_ptr.hxx>
-#include <cmsys/Directory.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+class cmSystemToolsFileTime;
// Table of permissions flags.
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -60,372 +77,348 @@ static mode_t mode_setuid = S_ISUID;
static mode_t mode_setgid = S_ISGID;
#endif
+#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 ret = url;
+ if (strncmp(url.c_str(), "file://", 7) == 0) {
+ std::wstring wurl = cmsys::Encoding::ToWide(url);
+ if (!wurl.empty()) {
+ int mblen =
+ WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, NULL, 0, NULL, NULL);
+ if (mblen > 0) {
+ std::vector<char> chars(mblen);
+ mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, &chars[0],
+ mblen, NULL, NULL);
+ if (mblen > 0) {
+ ret = &chars[0];
+ }
+ }
+ }
+ }
+ return ret;
+}
+#endif
+
// cmLibraryCommand
-bool cmFileCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("must be called with at least two arguments.");
return false;
- }
- std::string subCommand = args[0];
- if ( subCommand == "WRITE" )
- {
+ }
+ std::string const& subCommand = args[0];
+ if (subCommand == "WRITE") {
return this->HandleWriteCommand(args, false);
- }
- else if ( subCommand == "APPEND" )
- {
+ }
+ if (subCommand == "APPEND") {
return this->HandleWriteCommand(args, true);
- }
- else if ( subCommand == "DOWNLOAD" )
- {
+ }
+ if (subCommand == "DOWNLOAD") {
return this->HandleDownloadCommand(args);
- }
- else if ( subCommand == "UPLOAD" )
- {
+ }
+ if (subCommand == "UPLOAD") {
return this->HandleUploadCommand(args);
- }
- else if ( subCommand == "READ" )
- {
+ }
+ if (subCommand == "READ") {
return this->HandleReadCommand(args);
- }
- else if ( subCommand == "MD5" ||
- subCommand == "SHA1" ||
- subCommand == "SHA224" ||
- subCommand == "SHA256" ||
- subCommand == "SHA384" ||
- subCommand == "SHA512" )
- {
+ }
+ 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);
- }
- else if ( subCommand == "STRINGS" )
- {
+ }
+ if (subCommand == "STRINGS") {
return this->HandleStringsCommand(args);
- }
- else if ( subCommand == "GLOB" )
- {
+ }
+ if (subCommand == "GLOB") {
return this->HandleGlobCommand(args, false);
- }
- else if ( subCommand == "GLOB_RECURSE" )
- {
+ }
+ if (subCommand == "GLOB_RECURSE") {
return this->HandleGlobCommand(args, true);
- }
- else if ( subCommand == "MAKE_DIRECTORY" )
- {
+ }
+ if (subCommand == "MAKE_DIRECTORY") {
return this->HandleMakeDirectoryCommand(args);
- }
- else if ( subCommand == "RENAME" )
- {
+ }
+ if (subCommand == "RENAME") {
return this->HandleRename(args);
- }
- else if ( subCommand == "REMOVE" )
- {
+ }
+ if (subCommand == "REMOVE") {
return this->HandleRemove(args, false);
- }
- else if ( subCommand == "REMOVE_RECURSE" )
- {
+ }
+ if (subCommand == "REMOVE_RECURSE") {
return this->HandleRemove(args, true);
- }
- else if ( subCommand == "COPY" )
- {
+ }
+ if (subCommand == "COPY") {
return this->HandleCopyCommand(args);
- }
- else if ( subCommand == "INSTALL" )
- {
+ }
+ if (subCommand == "INSTALL") {
return this->HandleInstallCommand(args);
- }
- else if ( subCommand == "DIFFERENT" )
- {
+ }
+ if (subCommand == "DIFFERENT") {
return this->HandleDifferentCommand(args);
- }
- else if ( subCommand == "RPATH_CHANGE" || subCommand == "CHRPATH" )
- {
+ }
+ if (subCommand == "RPATH_CHANGE" || subCommand == "CHRPATH") {
return this->HandleRPathChangeCommand(args);
- }
- else if ( subCommand == "RPATH_CHECK" )
- {
+ }
+ if (subCommand == "RPATH_CHECK") {
return this->HandleRPathCheckCommand(args);
- }
- else if ( subCommand == "RPATH_REMOVE" )
- {
+ }
+ if (subCommand == "RPATH_REMOVE") {
return this->HandleRPathRemoveCommand(args);
- }
- else if ( subCommand == "RELATIVE_PATH" )
- {
+ }
+ if (subCommand == "READ_ELF") {
+ return this->HandleReadElfCommand(args);
+ }
+ if (subCommand == "RELATIVE_PATH") {
return this->HandleRelativePathCommand(args);
- }
- else if ( subCommand == "TO_CMAKE_PATH" )
- {
+ }
+ if (subCommand == "TO_CMAKE_PATH") {
return this->HandleCMakePathCommand(args, false);
- }
- else if ( subCommand == "TO_NATIVE_PATH" )
- {
+ }
+ if (subCommand == "TO_NATIVE_PATH") {
return this->HandleCMakePathCommand(args, true);
- }
- else if ( subCommand == "TIMESTAMP" )
- {
+ }
+ if (subCommand == "TIMESTAMP") {
return this->HandleTimestampCommand(args);
- }
- else if ( subCommand == "GENERATE" )
- {
+ }
+ 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.c_str());
+ 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)
+ bool append)
{
- std::string message;
std::vector<std::string>::const_iterator i = args.begin();
i++; // Get rid of subcommand
std::string fileName = *i;
- if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
- {
- fileName = this->Makefile->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
+ fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + *i;
- }
+ }
i++;
- for(;i != args.end(); ++i)
- {
- message += *i;
- }
- if ( !this->Makefile->CanIWriteThisFile(fileName.c_str()) )
- {
- std::string e
- = "attempted to write a file: " + fileName +
- " into a source directory.";
- this->SetError(e.c_str());
+ if (!this->Makefile->CanIWriteThisFile(fileName.c_str())) {
+ std::string e =
+ "attempted to write a file: " + fileName + " into a source directory.";
+ this->SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
+ }
std::string dir = cmSystemTools::GetFilenamePath(fileName);
cmSystemTools::MakeDirectory(dir.c_str());
mode_t mode = 0;
// Set permissions to writable
- if ( cmSystemTools::GetPermissions(fileName.c_str(), mode) )
- {
+ if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
cmSystemTools::SetPermissions(fileName.c_str(),
-#if defined( _MSC_VER ) || defined( __MINGW32__ )
- mode | S_IWRITE
-#elif defined( __BORLANDC__ )
- mode | S_IWUSR
+#if defined(_MSC_VER) || defined(__MINGW32__)
+ mode | S_IWRITE
#else
- mode | S_IWUSR | S_IWGRP
+ mode | S_IWUSR | S_IWGRP
#endif
- );
- }
+ );
+ }
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
- std::ofstream file(fileName.c_str(), append?std::ios::app: std::ios::out);
- if ( !file )
- {
- std::string error = "Internal CMake error when trying to open file: ";
- error += fileName.c_str();
- error += " for writing.";
- this->SetError(error.c_str());
+ 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);
return false;
- }
+ }
+ std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
file << message;
file.close();
- if(mode)
- {
+ if (mode) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
{
- if ( args.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("READ must be called with at least two additional "
"arguments");
return false;
- }
+ }
cmCommandArgumentsHelper argHelper;
cmCommandArgumentGroup group;
- cmCAString readArg (&argHelper, "READ");
- cmCAString fileNameArg (&argHelper, 0);
- cmCAString resultArg (&argHelper, 0);
+ cmCAString readArg(&argHelper, "READ");
+ cmCAString fileNameArg(&argHelper, CM_NULLPTR);
+ cmCAString resultArg(&argHelper, CM_NULLPTR);
- cmCAString offsetArg (&argHelper, "OFFSET", &group);
- cmCAString limitArg (&argHelper, "LIMIT", &group);
- cmCAEnabler hexOutputArg (&argHelper, "HEX", &group);
- readArg.Follows(0);
+ 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, 0);
+ argHelper.Parse(&args, CM_NULLPTR);
std::string fileName = fileNameArg.GetString();
- if ( !cmsys::SystemTools::FileIsFullPath(fileName.c_str()) )
- {
- fileName = this->Makefile->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
+ fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + fileNameArg.GetString();
- }
+ }
std::string variable = resultArg.GetString();
- // Open the specified file.
+// Open the specified file.
#if defined(_WIN32) || defined(__CYGWIN__)
- std::ifstream file(fileName.c_str(), std::ios::in |
- (hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in));
+ cmsys::ifstream file(
+ fileName.c_str(), std::ios::in |
+ (hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in));
#else
- std::ifstream file(fileName.c_str(), std::ios::in);
+ cmsys::ifstream file(fileName.c_str());
#endif
- if ( !file )
- {
- std::string error = "Internal CMake error when trying to open file: ";
- error += fileName.c_str();
- error += " for reading.";
- this->SetError(error.c_str());
+ if (!file) {
+ std::string error = "failed to open for reading (";
+ error += cmSystemTools::GetLastSystemError();
+ error += "):\n ";
+ error += fileName;
+ this->SetError(error);
return false;
- }
+ }
// is there a limit?
long sizeLimit = -1;
- if (limitArg.GetString().size() > 0)
- {
+ if (!limitArg.GetString().empty()) {
sizeLimit = atoi(limitArg.GetCString());
- }
+ }
// is there an offset?
long offset = 0;
- if (offsetArg.GetString().size() > 0)
- {
+ if (!offsetArg.GetString().empty()) {
offset = atoi(offsetArg.GetCString());
- }
+ }
file.seekg(offset, std::ios::beg); // explicit ios::beg for IBM VisualAge 6
std::string output;
- if (hexOutputArg.IsEnabled())
- {
+ if (hexOutputArg.IsEnabled()) {
// Convert part of the file into hex code
char c;
- while((sizeLimit != 0) && (file.get(c)))
- {
+ while ((sizeLimit != 0) && (file.get(c))) {
char hex[4];
- sprintf(hex, "%.2x", c&0xff);
+ sprintf(hex, "%.2x", c & 0xff);
output += hex;
- if (sizeLimit > 0)
- {
+ if (sizeLimit > 0) {
sizeLimit--;
- }
}
}
- else
- {
+ } else {
std::string line;
bool has_newline = false;
- while (sizeLimit != 0 &&
- cmSystemTools::GetLineFromStream(file, line, &has_newline,
- sizeLimit) )
- {
- if (sizeLimit > 0)
- {
+ while (sizeLimit != 0 && cmSystemTools::GetLineFromStream(
+ file, line, &has_newline, sizeLimit)) {
+ if (sizeLimit > 0) {
sizeLimit = sizeLimit - static_cast<long>(line.size());
- if (has_newline)
- {
+ if (has_newline) {
sizeLimit--;
- }
- if (sizeLimit < 0)
- {
+ }
+ if (sizeLimit < 0) {
sizeLimit = 0;
- }
}
+ }
output += line;
- if ( has_newline )
- {
+ if (has_newline) {
output += "\n";
- }
}
}
- this->Makefile->AddDefinition(variable.c_str(), output.c_str());
+ }
+ this->Makefile->AddDefinition(variable, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleHashCommand(std::vector<std::string> const& args)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
- if(args.size() != 3)
- {
- cmOStringStream e;
+ if (args.size() != 3) {
+ std::ostringstream e;
e << args[0] << " requires a file name and output variable";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- cmsys::auto_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
- if(hash.get())
- {
- std::string out = hash->HashFile(args[1].c_str());
- if(!out.empty())
- {
- this->Makefile->AddDefinition(args[2].c_str(), out.c_str());
+ CM_AUTO_PTR<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
+ if (hash.get()) {
+ std::string out = hash->HashFile(args[1]);
+ if (!out.empty()) {
+ this->Makefile->AddDefinition(args[2], out.c_str());
return true;
- }
- cmOStringStream e;
- e << args[0] << " failed to read file \"" << args[1] << "\": "
- << cmSystemTools::GetLastSystemError();
- this->SetError(e.str().c_str());
}
+ std::ostringstream e;
+ e << args[0] << " failed to read file \"" << args[1]
+ << "\": " << cmSystemTools::GetLastSystemError();
+ this->SetError(e.str());
+ }
return false;
#else
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " not available during bootstrap";
this->SetError(e.str().c_str());
return false;
#endif
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
{
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->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->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
+ fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + args[1];
- }
+ }
// Get the variable in which to store the results.
std::string outVar = args[2];
// Parse the options.
- enum { arg_none,
- arg_limit_input,
- arg_limit_output,
- arg_limit_count,
- arg_length_minimum,
- arg_length_maximum,
- arg__maximum,
- arg_regex };
+ enum
+ {
+ arg_none,
+ arg_limit_input,
+ arg_limit_output,
+ arg_limit_count,
+ arg_length_minimum,
+ arg_length_maximum,
+ arg__maximum,
+ arg_regex,
+ arg_encoding
+ };
unsigned int minlen = 0;
unsigned int maxlen = 0;
int limit_input = -1;
@@ -435,261 +428,303 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
bool have_regex = false;
bool newline_consume = false;
bool hex_conversion_enabled = true;
+ enum
+ {
+ encoding_none = cmsys::FStream::BOM_None,
+ encoding_utf8 = cmsys::FStream::BOM_UTF8,
+ encoding_utf16le = cmsys::FStream::BOM_UTF16LE,
+ encoding_utf16be = cmsys::FStream::BOM_UTF16BE,
+ encoding_utf32le = cmsys::FStream::BOM_UTF32LE,
+ encoding_utf32be = cmsys::FStream::BOM_UTF32BE
+ };
+ int encoding = encoding_none;
int arg_mode = arg_none;
- for(unsigned int i=3; i < args.size(); ++i)
- {
- if(args[i] == "LIMIT_INPUT")
- {
+ for (unsigned int i = 3; i < args.size(); ++i) {
+ if (args[i] == "LIMIT_INPUT") {
arg_mode = arg_limit_input;
- }
- else if(args[i] == "LIMIT_OUTPUT")
- {
+ } else if (args[i] == "LIMIT_OUTPUT") {
arg_mode = arg_limit_output;
- }
- else if(args[i] == "LIMIT_COUNT")
- {
+ } else if (args[i] == "LIMIT_COUNT") {
arg_mode = arg_limit_count;
- }
- else if(args[i] == "LENGTH_MINIMUM")
- {
+ } else if (args[i] == "LENGTH_MINIMUM") {
arg_mode = arg_length_minimum;
- }
- else if(args[i] == "LENGTH_MAXIMUM")
- {
+ } else if (args[i] == "LENGTH_MAXIMUM") {
arg_mode = arg_length_maximum;
- }
- else if(args[i] == "REGEX")
- {
+ } else if (args[i] == "REGEX") {
arg_mode = arg_regex;
- }
- else if(args[i] == "NEWLINE_CONSUME")
- {
+ } else if (args[i] == "NEWLINE_CONSUME") {
newline_consume = true;
arg_mode = arg_none;
- }
- else if(args[i] == "NO_HEX_CONVERSION")
- {
+ } else if (args[i] == "NO_HEX_CONVERSION") {
hex_conversion_enabled = false;
arg_mode = arg_none;
- }
- else if(arg_mode == arg_limit_input)
- {
- if(sscanf(args[i].c_str(), "%d", &limit_input) != 1 ||
- limit_input < 0)
- {
- cmOStringStream e;
- e << "STRINGS option LIMIT_INPUT value \""
- << args[i] << "\" is not an unsigned integer.";
- this->SetError(e.str().c_str());
+ } else if (args[i] == "ENCODING") {
+ arg_mode = arg_encoding;
+ } 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());
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)
- {
- cmOStringStream e;
- e << "STRINGS option LIMIT_OUTPUT value \""
- << args[i] << "\" is not an unsigned integer.";
- this->SetError(e.str().c_str());
- 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());
+ return false;
}
- else if(arg_mode == arg_limit_count)
- {
+ arg_mode = arg_none;
+ } else if (arg_mode == arg_limit_count) {
int count;
- if(sscanf(args[i].c_str(), "%d", &count) != 1 || count < 0)
- {
- cmOStringStream e;
- e << "STRINGS option LIMIT_COUNT value \""
- << args[i] << "\" is not an unsigned integer.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
+ }
limit_count = count;
arg_mode = arg_none;
- }
- else if(arg_mode == arg_length_minimum)
- {
+ } else if (arg_mode == arg_length_minimum) {
int len;
- if(sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0)
- {
- cmOStringStream e;
- e << "STRINGS option LENGTH_MINIMUM value \""
- << args[i] << "\" is not an unsigned integer.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
+ }
minlen = len;
arg_mode = arg_none;
- }
- else if(arg_mode == arg_length_maximum)
- {
+ } else if (arg_mode == arg_length_maximum) {
int len;
- if(sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0)
- {
- cmOStringStream e;
- e << "STRINGS option LENGTH_MAXIMUM value \""
- << args[i] << "\" is not an unsigned integer.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
+ }
maxlen = len;
arg_mode = arg_none;
- }
- else if(arg_mode == arg_regex)
- {
- if(!regex.compile(args[i].c_str()))
- {
- cmOStringStream e;
- e << "STRINGS option REGEX value \""
- << args[i] << "\" could not be compiled.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
have_regex = true;
arg_mode = arg_none;
+ } else if (arg_mode == arg_encoding) {
+ if (args[i] == "UTF-8") {
+ encoding = encoding_utf8;
+ } else if (args[i] == "UTF-16LE") {
+ encoding = encoding_utf16le;
+ } else if (args[i] == "UTF-16BE") {
+ encoding = encoding_utf16be;
+ } else if (args[i] == "UTF-32LE") {
+ encoding = encoding_utf32le;
+ } 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());
+ return false;
}
- else
- {
- cmOStringStream e;
- e << "STRINGS given unknown argument \""
- << args[i] << "\"";
- this->SetError(e.str().c_str());
+ arg_mode = arg_none;
+ } else {
+ std::ostringstream e;
+ e << "STRINGS given unknown argument \"" << args[i] << "\"";
+ this->SetError(e.str());
return false;
- }
}
+ }
- if (hex_conversion_enabled)
- {
+ if (hex_conversion_enabled) {
// TODO: should work without temp file, but just on a memory buffer
- std::string binaryFileName = this->Makefile->GetCurrentOutputDirectory();
+ std::string binaryFileName = this->Makefile->GetCurrentBinaryDirectory();
binaryFileName += cmake::GetCMakeFilesDirectory();
binaryFileName += "/FileCommandStringsBinaryFile";
- if(cmHexFileConverter::TryConvert(fileName.c_str(),binaryFileName.c_str()))
- {
+ if (cmHexFileConverter::TryConvert(fileName.c_str(),
+ binaryFileName.c_str())) {
fileName = binaryFileName;
- }
}
+ }
- // Open the specified file.
+// Open the specified file.
#if defined(_WIN32) || defined(__CYGWIN__)
- std::ifstream fin(fileName.c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream fin(fileName.c_str(), std::ios::in | std::ios::binary);
#else
- std::ifstream fin(fileName.c_str(), std::ios::in);
+ cmsys::ifstream fin(fileName.c_str());
#endif
- if(!fin)
- {
- cmOStringStream e;
+ if (!fin) {
+ std::ostringstream e;
e << "STRINGS file \"" << fileName << "\" cannot be read.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
+
+ // If BOM is found and encoding was not specified, use the BOM
+ int bom_found = cmsys::FStream::ReadBOM(fin);
+ if (encoding == encoding_none && bom_found != cmsys::FStream::BOM_None) {
+ encoding = bom_found;
+ }
+
+ unsigned int bytes_rem = 0;
+ if (encoding == encoding_utf16le || encoding == encoding_utf16be) {
+ bytes_rem = 1;
+ }
+ if (encoding == encoding_utf32le || encoding == encoding_utf32be) {
+ bytes_rem = 3;
+ }
// Parse strings out of the file.
int output_size = 0;
std::vector<std::string> strings;
std::string s;
- int c;
- while((!limit_count || strings.size() < limit_count) &&
- (limit_input < 0 || static_cast<int>(fin.tellg()) < limit_input) &&
- (c = fin.get(), fin))
- {
- if(c == '\n' && !newline_consume)
- {
+ while ((!limit_count || strings.size() < limit_count) &&
+ (limit_input < 0 || static_cast<int>(fin.tellg()) < limit_input) &&
+ fin) {
+ std::string current_str;
+
+ int c = fin.get();
+ for (unsigned int i = 0; i < bytes_rem; ++i) {
+ int c1 = fin.get();
+ if (!fin) {
+ fin.putback(static_cast<char>(c1));
+ break;
+ }
+ c = (c << 8) | c1;
+ }
+ if (encoding == encoding_utf16le) {
+ c = ((c & 0xFF) << 8) | ((c & 0xFF00) >> 8);
+ } else if (encoding == encoding_utf32le) {
+ c = (((c & 0xFF) << 24) | ((c & 0xFF00) << 8) | ((c & 0xFF0000) >> 8) |
+ ((c & 0xFF000000) >> 24));
+ }
+
+ if (c == '\r') {
+ // Ignore CR character to make output always have UNIX newlines.
+ continue;
+ }
+
+ if ((c >= 0x20 && c < 0x7F) || 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...
+ current_str += static_cast<char>(c);
+ } 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 },
+ };
+
+ // how many octets are there?
+ unsigned int num_utf8_bytes = 0;
+ for (unsigned int j = 0; num_utf8_bytes == 0 && j < 3; j++) {
+ if ((c & utf8_check_table[j][0]) == utf8_check_table[j][1]) {
+ num_utf8_bytes = j + 2;
+ }
+ }
+
+ // get subsequent octets and check that they are valid
+ for (unsigned int j = 0; j < num_utf8_bytes; j++) {
+ if (j != 0) {
+ c = fin.get();
+ if (!fin || (c & 0xC0) != 0x80) {
+ fin.putback(static_cast<char>(c));
+ break;
+ }
+ }
+ current_str += static_cast<char>(c);
+ }
+
+ // if this was an invalid utf8 sequence, discard the data, and put
+ // back subsequent characters
+ if ((current_str.length() != num_utf8_bytes)) {
+ for (unsigned int j = 0; j < current_str.size() - 1; j++) {
+ c = current_str[current_str.size() - 1 - j];
+ fin.putback(static_cast<char>(c));
+ }
+ current_str = "";
+ }
+ }
+
+ if (c == '\n' && !newline_consume) {
// 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.c_str()))) {
output_size += static_cast<int>(s.size()) + 1;
- if(limit_output >= 0 && output_size >= limit_output)
- {
+ if (limit_output >= 0 && output_size >= limit_output) {
s = "";
break;
- }
- strings.push_back(s);
}
+ strings.push_back(s);
+ }
// Reset the string to empty.
s = "";
- }
- else if(c == '\r')
- {
- // Ignore CR character to make output always have UNIX newlines.
- }
- else if((c >= 0x20 && c < 0x7F) || 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...
- s += static_cast<char>(c);
- }
- else
- {
- // TODO: Support ENCODING option. See issue #10519.
+ } 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.length() >= 1 &&
- (!have_regex || regex.find(s.c_str())))
- {
+ if (s.length() >= minlen && !s.empty() &&
+ (!have_regex || regex.find(s.c_str()))) {
output_size += static_cast<int>(s.size()) + 1;
- if(limit_output >= 0 && output_size >= limit_output)
- {
+ if (limit_output >= 0 && output_size >= limit_output) {
s = "";
break;
- }
- strings.push_back(s);
}
+ strings.push_back(s);
+ }
// Reset the string to empty.
s = "";
- }
+ } else {
+ s += current_str;
+ }
- // Terminate a string if the maximum length is reached.
- if(maxlen > 0 && s.size() == maxlen)
- {
- if(s.length() >= minlen &&
- (!have_regex || regex.find(s.c_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()))) {
output_size += static_cast<int>(s.size()) + 1;
- if(limit_output >= 0 && output_size >= limit_output)
- {
+ if (limit_output >= 0 && output_size >= limit_output) {
s = "";
break;
- }
- strings.push_back(s);
}
- s = "";
+ strings.push_back(s);
}
+ s = "";
}
+ }
// If there is a non-empty current string we have hit the end of the
// 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())))
- {
+ if ((!limit_count || strings.size() < limit_count) && !s.empty() &&
+ s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
output_size += static_cast<int>(s.size()) + 1;
- if(limit_output < 0 || output_size < limit_output)
- {
+ if (limit_output < 0 || output_size < limit_output) {
strings.push_back(s);
- }
}
+ }
// 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::vector<std::string>::const_iterator si = strings.begin();
+ si != strings.end(); ++si) {
// Separate the strings in the output to make it a list.
output += sep;
sep = ";";
@@ -697,24 +732,21 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
// 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 (unsigned int i = 0; i < sr.size(); ++i) {
+ if (sr[i] == ';') {
output += '\\';
- }
- output += sr[i];
}
+ output += sr[i];
}
+ }
// Save the output in a makefile variable.
- this->Makefile->AddDefinition(outVar.c_str(), output.c_str());
+ this->Makefile->AddDefinition(outVar, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
- bool recurse)
+ bool recurse)
{
// File commands has at least one argument
assert(args.size() > 1);
@@ -731,123 +763,141 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
bool explicitFollowSymlinks = false;
cmPolicies::PolicyStatus status =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0009);
- if(recurse)
- {
- switch(status)
- {
+ if (recurse) {
+ switch (status) {
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
g.RecurseThroughSymlinksOff();
break;
case cmPolicies::OLD:
case cmPolicies::WARN:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
g.RecurseThroughSymlinksOn();
break;
- }
}
+ }
- std::string output = "";
+ std::string output;
bool first = true;
- for ( ; i != args.end(); ++i )
- {
- if ( recurse && (*i == "FOLLOW_SYMLINKS") )
- {
+ for (; i != args.end(); ++i) {
+ if (*i == "LIST_DIRECTORIES") {
+ ++i;
+ if (i != args.end()) {
+ if (cmSystemTools::IsOn(i->c_str())) {
+ g.SetListDirs(true);
+ g.SetRecurseListDirs(true);
+ } else if (cmSystemTools::IsOff(i->c_str())) {
+ g.SetListDirs(false);
+ g.SetRecurseListDirs(false);
+ } else {
+ this->SetError("LIST_DIRECTORIES missing bool value.");
+ return false;
+ }
+ } else {
+ this->SetError("LIST_DIRECTORIES missing bool value.");
+ return false;
+ }
+ continue;
+ }
+
+ if (recurse && (*i == "FOLLOW_SYMLINKS")) {
explicitFollowSymlinks = true;
g.RecurseThroughSymlinksOn();
++i;
- if ( i == args.end() )
- {
+ if (i == args.end()) {
this->SetError(
"GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
return false;
- }
}
+ }
- if ( *i == "RELATIVE" )
- {
+ if (*i == "RELATIVE") {
++i; // skip RELATIVE
- if ( i == args.end() )
- {
+ if (i == args.end()) {
this->SetError("GLOB requires a directory after the RELATIVE tag");
return false;
- }
+ }
g.SetRelative(i->c_str());
++i;
- if(i == args.end())
- {
+ if (i == args.end()) {
this->SetError("GLOB requires a glob expression after the directory");
return false;
- }
}
+ }
- if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
- {
- std::string expr = this->Makefile->GetCurrentDirectory();
+ cmsys::Glob::GlobMessages globMessages;
+ if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
+ std::string expr = this->Makefile->GetCurrentSourceDirectory();
// Handle script mode
- if ( expr.size() > 0 )
- {
+ if (!expr.empty()) {
expr += "/" + *i;
- g.FindFiles(expr);
- }
- else
- {
- g.FindFiles(*i);
+ g.FindFiles(expr, &globMessages);
+ } else {
+ g.FindFiles(*i, &globMessages);
+ }
+ } 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);
+ } else {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
+ *i + "' - " + it->content);
+ shouldExit = true;
}
}
- else
- {
- g.FindFiles(*i);
+ if (shouldExit) {
+ return false;
}
+ }
std::vector<std::string>::size_type cc;
std::vector<std::string>& files = g.GetFiles();
- for ( cc = 0; cc < files.size(); cc ++ )
- {
- if ( !first )
- {
+ std::sort(files.begin(), files.end());
+ for (cc = 0; cc < files.size(); cc++) {
+ if (!first) {
output += ";";
- }
+ }
output += files[cc];
first = false;
- }
}
+ }
- if(recurse && !explicitFollowSymlinks)
- {
- switch (status)
- {
+ 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.
+ // 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,
- this->Makefile->GetPolicies()->
- GetPolicyWarning(cmPolicies::CMP0009));
- }
+ if (g.GetFollowedSymlinkCount() != 0) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
+ }
break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- this->SetError("policy CMP0009 error");
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- this->Makefile->GetPolicies()->
- GetRequiredPolicyError(cmPolicies::CMP0009));
- return false;
- }
}
+ }
- this->Makefile->AddDefinition(variable.c_str(), output.c_str());
+ this->Makefile->AddDefinition(variable, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleMakeDirectoryCommand(
std::vector<std::string> const& args)
{
@@ -859,118 +909,106 @@ bool cmFileCommand::HandleMakeDirectoryCommand(
i++; // Get rid of subcommand
std::string expr;
- for ( ; i != args.end(); ++i )
- {
+ for (; i != args.end(); ++i) {
const std::string* cdir = &(*i);
- if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
- {
- expr = this->Makefile->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
+ expr = this->Makefile->GetCurrentSourceDirectory();
expr += "/" + *i;
cdir = &expr;
- }
- if ( !this->Makefile->CanIWriteThisFile(cdir->c_str()) )
- {
- std::string e = "attempted to create a directory: " + *cdir
- + " into a source directory.";
- this->SetError(e.c_str());
+ }
+ if (!this->Makefile->CanIWriteThisFile(cdir->c_str())) {
+ std::string e = "attempted to create a directory: " + *cdir +
+ " into a source directory.";
+ this->SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
- if ( !cmSystemTools::MakeDirectory(cdir->c_str()) )
- {
+ }
+ if (!cmSystemTools::MakeDirectory(cdir->c_str())) {
std::string error = "problem creating directory: " + *cdir;
- this->SetError(error.c_str());
+ this->SetError(error);
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmFileCommand::HandleDifferentCommand(std::vector<std::string> const& args)
+bool cmFileCommand::HandleDifferentCommand(
+ std::vector<std::string> const& args)
{
/*
FILE(DIFFERENT <variable> FILES <lhs> <rhs>)
*/
// Evaluate arguments.
- const char* file_lhs = 0;
- const char* file_rhs = 0;
- const char* var = 0;
- enum Doing { DoingNone, DoingVar, DoingFileLHS, DoingFileRHS };
+ const char* file_lhs = CM_NULLPTR;
+ const char* file_rhs = CM_NULLPTR;
+ const char* var = CM_NULLPTR;
+ enum Doing
+ {
+ DoingNone,
+ DoingVar,
+ DoingFileLHS,
+ DoingFileRHS
+ };
Doing doing = DoingVar;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "FILES")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "FILES") {
doing = DoingFileLHS;
- }
- else if(doing == DoingVar)
- {
+ } else if (doing == DoingVar) {
var = args[i].c_str();
doing = DoingNone;
- }
- else if(doing == DoingFileLHS)
- {
+ } else if (doing == DoingFileLHS) {
file_lhs = args[i].c_str();
doing = DoingFileRHS;
- }
- else if(doing == DoingFileRHS)
- {
+ } else if (doing == DoingFileRHS) {
file_rhs = args[i].c_str();
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "DIFFERENT given unknown argument " << args[i];
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- if(!var)
- {
+ }
+ if (!var) {
this->SetError("DIFFERENT not given result variable name.");
return false;
- }
- if(!file_lhs || !file_rhs)
- {
+ }
+ if (!file_lhs || !file_rhs) {
this->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";
+ 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(0),
- UseGivenPermissionsFile(false),
- UseGivenPermissionsDir(false),
- UseSourcePermissions(true),
- Doing(DoingNone)
- {
- }
+ 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:
+protected:
cmFileCommand* FileCommand;
cmMakefile* Makefile;
const char* Name;
@@ -989,24 +1027,29 @@ protected:
{
bool Exclude;
mode_t Permissions;
- MatchProperties(): Exclude(false), Permissions(0) {}
+ MatchProperties()
+ : Exclude(false)
+ , Permissions(0)
+ {
+ }
};
- struct MatchRule;
- friend struct MatchRule;
struct MatchRule
{
cmsys::RegularExpression Regex;
MatchProperties Properties;
std::string RegexString;
- MatchRule(std::string const& regex):
- Regex(regex.c_str()), RegexString(regex) {}
+ 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.
+ {
+// 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();
@@ -1017,67 +1060,75 @@ protected:
// 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))
- {
+ 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)
- {
+ }
+ if (!matched && !this->MatchlessFiles) {
result.Exclude = !cmSystemTools::FileIsDirectory(file);
- }
- return result;
}
+ return result;
+ }
bool SetPermissions(const char* toFile, mode_t permissions)
- {
- if(permissions && !cmSystemTools::SetPermissions(toFile, permissions))
- {
- cmOStringStream e;
+ {
+ if (permissions && !cmSystemTools::SetPermissions(toFile, permissions)) {
+ std::ostringstream e;
e << this->Name << " cannot set permissions on \"" << toFile << "\"";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
return false;
- }
- return true;
}
+ 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
- {
- cmOStringStream e;
+ {
+ 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().c_str());
+ this->FileCommand->SetError(e.str());
return false;
- }
- return true;
}
+ return true;
+ }
bool InstallSymlink(const char* fromFile, const char* toFile);
bool InstallFile(const char* fromFile, const char* toFile,
- MatchProperties const& match_properties);
+ MatchProperties match_properties);
bool InstallDirectory(const char* source, const char* destination,
- MatchProperties const& match_properties);
+ MatchProperties match_properties);
virtual bool Install(const char* fromFile, const char* toFile);
virtual std::string const& ToName(std::string const& fromName)
- { return fromName; }
+ {
+ return fromName;
+ }
enum Type
{
@@ -1087,19 +1138,20 @@ protected:
};
virtual void ReportCopy(const char*, Type, bool) {}
virtual bool ReportMissing(const char* fromFile)
- {
+ {
// The input file does not exist and installation is not optional.
- cmOStringStream e;
+ std::ostringstream e;
e << this->Name << " cannot find \"" << fromFile << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ 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;
@@ -1109,6 +1161,7 @@ protected:
DoingNone,
DoingError,
DoingDestination,
+ DoingFilesFromDir,
DoingFiles,
DoingPattern,
DoingRegex,
@@ -1121,30 +1174,30 @@ protected:
virtual bool CheckValue(std::string const& arg);
void NotBeforeMatch(std::string const& arg)
- {
- cmOStringStream e;
+ {
+ std::ostringstream e;
e << "option " << arg << " may not appear before PATTERN or REGEX.";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
this->Doing = DoingError;
- }
+ }
void NotAfterMatch(std::string const& arg)
- {
- cmOStringStream e;
+ {
+ std::ostringstream e;
e << "option " << arg << " may not appear after PATTERN or REGEX.";
- this->FileCommand->SetError(e.str().c_str());
+ 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;
@@ -1154,200 +1207,147 @@ protected:
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)
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
// Check this argument.
- if(!this->CheckKeyword(args[i]) &&
- !this->CheckValue(args[i]))
- {
- cmOStringStream e;
+ if (!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) {
+ std::ostringstream e;
e << "called with unknown argument \"" << args[i] << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
return false;
- }
+ }
// Quit if an argument is invalid.
- if(this->Doing == DoingError)
- {
+ if (this->Doing == DoingError) {
return false;
- }
}
+ }
// Require a destination.
- if(this->Destination.empty())
- {
- cmOStringStream e;
+ if (this->Destination.empty()) {
+ std::ostringstream e;
e << this->Name << " given no DESTINATION";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
return false;
- }
+ }
// If file permissions were not specified set default permissions.
- if(!this->UseGivenPermissionsFile && !this->UseSourcePermissions)
- {
+ if (!this->UseGivenPermissionsFile && !this->UseSourcePermissions) {
this->DefaultFilePermissions();
- }
+ }
// If directory permissions were not specified set default permissions.
- if(!this->UseGivenPermissionsDir && !this->UseSourcePermissions)
- {
+ if (!this->UseGivenPermissionsDir && !this->UseSourcePermissions) {
this->DefaultDirectoryPermissions();
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCopier::CheckKeyword(std::string const& arg)
{
- if(arg == "DESTINATION")
- {
- if(this->CurrentMatchRule)
- {
+ if (arg == "DESTINATION") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingDestination;
- }
}
- else if(arg == "PATTERN")
- {
- this->Doing = DoingPattern;
+ } else if (arg == "FILES_FROM_DIR") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingFilesFromDir;
}
- else if(arg == "REGEX")
- {
+ } else if (arg == "PATTERN") {
+ this->Doing = DoingPattern;
+ } else if (arg == "REGEX") {
this->Doing = DoingRegex;
- }
- else if(arg == "EXCLUDE")
- {
+ } else if (arg == "EXCLUDE") {
// Add this property to the current match rule.
- if(this->CurrentMatchRule)
- {
+ if (this->CurrentMatchRule) {
this->CurrentMatchRule->Properties.Exclude = true;
this->Doing = DoingNone;
- }
- else
- {
+ } else {
this->NotBeforeMatch(arg);
- }
}
- else if(arg == "PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "PERMISSIONS") {
+ if (this->CurrentMatchRule) {
this->Doing = DoingPermissionsMatch;
- }
- else
- {
+ } else {
this->NotBeforeMatch(arg);
- }
}
- else if(arg == "FILE_PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "FILE_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingPermissionsFile;
this->UseGivenPermissionsFile = true;
- }
}
- else if(arg == "DIRECTORY_PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "DIRECTORY_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingPermissionsDir;
this->UseGivenPermissionsDir = true;
- }
}
- else if(arg == "USE_SOURCE_PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "USE_SOURCE_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingNone;
this->UseSourcePermissions = true;
- }
}
- else if(arg == "NO_SOURCE_PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "NO_SOURCE_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingNone;
this->UseSourcePermissions = false;
- }
}
- else if(arg == "FILES_MATCHING")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "FILES_MATCHING") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingNone;
this->MatchlessFiles = false;
- }
}
- else
- {
+ } else {
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCopier::CheckValue(std::string const& arg)
{
- switch(this->Doing)
- {
+ switch (this->Doing) {
case DoingFiles:
- if(arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str()))
- {
- this->Files.push_back(arg);
- }
- else
- {
- std::string file = this->Makefile->GetCurrentDirectory();
- file += "/" + arg;
- this->Files.push_back(file);
- }
+ this->Files.push_back(arg);
break;
case DoingDestination:
- if(arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str()))
- {
+ if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
this->Destination = arg;
- }
- else
- {
- this->Destination = this->Makefile->GetCurrentOutputDirectory();
+ } 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:
- {
+ 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
@@ -1356,281 +1356,270 @@ bool cmFileCopier::CheckValue(std::string const& arg)
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->CurrentMatchRule = &*(this->MatchRules.end() - 1);
+ if (this->CurrentMatchRule->Regex.is_valid()) {
this->Doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "could not compile PATTERN \"" << arg << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
this->Doing = DoingError;
- }
}
- break;
+ } break;
case DoingRegex:
this->MatchRules.push_back(MatchRule(arg));
- this->CurrentMatchRule = &*(this->MatchRules.end()-1);
- if(this->CurrentMatchRule->Regex.is_valid())
- {
+ this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
+ if (this->CurrentMatchRule->Regex.is_valid()) {
this->Doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "could not compile REGEX \"" << arg << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
this->Doing = DoingError;
- }
+ }
break;
case DoingPermissionsFile:
- if(!this->CheckPermissions(arg, this->FilePermissions))
- {
+ if (!this->CheckPermissions(arg, this->FilePermissions)) {
this->Doing = DoingError;
- }
+ }
break;
case DoingPermissionsDir:
- if(!this->CheckPermissions(arg, this->DirPermissions))
- {
+ if (!this->CheckPermissions(arg, this->DirPermissions)) {
this->Doing = DoingError;
- }
+ }
break;
case DoingPermissionsMatch:
- if(!this->CheckPermissions(
- arg, this->CurrentMatchRule->Properties.Permissions))
- {
+ 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))
- {
+ 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;
}
- std::vector<std::string> const& files = this->Files;
- for(std::vector<std::string>::size_type i = 0; i < files.size(); ++i)
- {
// Split the input file into its directory and name components.
std::vector<std::string> fromPathComponents;
- cmSystemTools::SplitPath(files[i].c_str(), fromPathComponents);
- std::string fromName = *(fromPathComponents.end()-1);
- std::string fromDir = cmSystemTools::JoinPath(fromPathComponents.begin(),
- fromPathComponents.end()-1);
+ 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())
- {
+ 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())
- {
+ if (!fromName.empty()) {
fromFile += "/";
fromFile += fromName;
- }
+ }
- if(!this->Install(fromFile.c_str(), toFile.c_str()))
- {
+ if (!this->Install(fromFile.c_str(), toFile.c_str())) {
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCopier::Install(const char* fromFile, const char* toFile)
{
- if(!*fromFile)
- {
- cmOStringStream e;
+ if (!*fromFile) {
+ std::ostringstream e;
e << "INSTALL encountered an empty string input file name.";
- this->FileCommand->SetError(e.str().c_str());
+ 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)
- {
+ if (match_properties.Exclude) {
return true;
- }
+ }
- if(cmSystemTools::SameFile(fromFile, toFile))
- {
+ if (cmSystemTools::SameFile(fromFile, toFile)) {
return true;
- }
- else if(cmSystemTools::FileIsSymlink(fromFile))
- {
+ }
+ if (cmSystemTools::FileIsSymlink(fromFile)) {
return this->InstallSymlink(fromFile, toFile);
- }
- else if(cmSystemTools::FileIsDirectory(fromFile))
- {
+ }
+ if (cmSystemTools::FileIsDirectory(fromFile)) {
return this->InstallDirectory(fromFile, toFile, match_properties);
- }
- else if(cmSystemTools::FileExists(fromFile))
- {
+ }
+ 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))
- {
- cmOStringStream e;
+ if (!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) {
+ std::ostringstream e;
e << this->Name << " cannot read symlink \"" << fromFile
<< "\" to duplicate at \"" << toFile << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ 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)
- {
+ if (!this->Always) {
std::string oldSymlinkTarget;
- if(cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget))
- {
- if(symlinkTarget == 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)
- {
+ 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.c_str(), toFile))
- {
- cmOStringStream e;
- e << this->Name << " cannot duplicate symlink \"" << fromFile
+ if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
+ std::ostringstream e;
+ e << this->Name << " cannot duplicate symlink \"" << fromFile
<< "\" at \"" << toFile << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ this->FileCommand->SetError(e.str());
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile,
- MatchProperties const& match_properties)
+ MatchProperties match_properties)
{
// Determine whether we will copy the file.
bool copy = true;
- if(!this->Always)
- {
+ if (!this->Always) {
// If both files exist with the same time do not copy.
- if(!this->FileTimes.FileTimesDiffer(fromFile, toFile))
- {
+ 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))
- {
- cmOStringStream e;
- e << this->Name << " cannot copy file \"" << fromFile
- << "\" to \"" << toFile << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ 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)
- {
+ 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))
- {
+ if (cmSystemTools::GetPermissions(toFile, perm)) {
cmSystemTools::SetPermissions(toFile, perm | mode_owner_write);
- }
- if (!cmSystemTools::CopyFileTime(fromFile, toFile))
- {
- cmOStringStream e;
- e << this->Name << " cannot set modification time on \""
- << toFile << "\"";
- this->FileCommand->SetError(e.str().c_str());
+ }
+ 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)
- {
+ 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 const& match_properties)
+ MatchProperties match_properties)
{
// Inform the user about this directory installation.
- this->ReportCopy(destination, TypeDir, true);
+ this->ReportCopy(destination, TypeDir,
+ !cmSystemTools::FileIsDirectory(destination));
// Make sure the destination directory exists.
- if(!cmSystemTools::MakeDirectory(destination))
- {
- cmOStringStream e;
- e << this->Name << " cannot make directory \"" << destination << "\": "
- << cmSystemTools::GetLastSystemError();
- this->FileCommand->SetError(e.str().c_str());
+ 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)
- {
+ 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.
@@ -1642,391 +1631,355 @@ bool cmFileCopier::InstallDirectory(const char* source,
// permissions temporarily during file installation.
mode_t permissions_before = 0;
mode_t permissions_after = 0;
- if((permissions & required_permissions) == required_permissions)
- {
+ if ((permissions & required_permissions) == required_permissions) {
permissions_before = permissions;
- }
- else
- {
+ } else {
permissions_before = permissions | required_permissions;
permissions_after = permissions;
- }
+ }
// Set the required permissions of the destination directory.
- if(!this->SetPermissions(destination, permissions_before))
- {
+ if (!this->SetPermissions(destination, permissions_before)) {
return false;
- }
+ }
// Load the directory contents to traverse it recursively.
cmsys::Directory dir;
- if(source && *source)
- {
+ 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))
- {
- cmsys_stl::string fromPath = source;
+ 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()))
- {
+ 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);
return copier.Run(args);
}
-//----------------------------------------------------------------------------
-struct cmFileInstaller: public cmFileCopier
+struct cmFileInstaller : public cmFileCopier
{
- cmFileInstaller(cmFileCommand* command):
- cmFileCopier(command, "INSTALL"),
- InstallType(cmInstallType_FILES),
- Optional(false),
- DestDirLength(0)
- {
+ 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.
- this->Always =
- cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
+ 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()
- {
+ }
+ ~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)
- {
- this->Manifest += ";";
- this->Manifest += file.substr(this->DestDirLength);
+ {
+ if (!this->Manifest.empty()) {
+ this->Manifest += ";";
}
+ this->Manifest += file.substr(this->DestDirLength);
+ }
- virtual std::string const& ToName(std::string const& fromName)
- { return this->Rename.empty()? fromName : this->Rename; }
+ std::string const& ToName(std::string const& fromName) CM_OVERRIDE
+ {
+ return this->Rename.empty() ? fromName : this->Rename;
+ }
- virtual void ReportCopy(const char* toFile, Type type, bool copy)
- {
- std::string message = (copy? "Installing: " : "Up-to-date: ");
- message += toFile;
- this->Makefile->DisplayStatus(message.c_str(), -1);
- if(type != TypeDir)
- {
+ 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);
- }
}
- virtual bool ReportMissing(const char* fromFile)
- {
- return (this->Optional ||
- this->cmFileCopier::ReportMissing(fromFile));
- }
- virtual bool Install(const char* fromFile, const char* 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)
- {
+ if (this->InstallType == cmInstallType_DIRECTORY && !*fromFile) {
return this->InstallDirectory(fromFile, toFile, MatchProperties());
- }
- return this->cmFileCopier::Install(fromFile, toFile);
}
+ return this->cmFileCopier::Install(fromFile, toFile);
+ }
- virtual bool Parse(std::vector<std::string> const& args);
+ bool Parse(std::vector<std::string> const& args) CM_OVERRIDE;
enum
{
DoingType = DoingLast1,
DoingRename,
DoingLast2
};
- virtual bool CheckKeyword(std::string const& arg);
- virtual bool CheckValue(std::string const& arg);
- virtual void DefaultFilePermissions()
- {
+ 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)
- {
+ switch (this->InstallType) {
case cmInstallType_SHARED_LIBRARY:
case cmInstallType_MODULE_LIBRARY:
- if(this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE"))
- {
+ 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;
- }
+ default:
+ break;
}
+ }
bool GetTargetTypeFromString(const std::string& stype);
bool HandleInstallDestination();
};
-//----------------------------------------------------------------------------
bool cmFileInstaller::Parse(std::vector<std::string> const& args)
{
- if(!this->cmFileCopier::Parse(args))
- {
+ if (!this->cmFileCopier::Parse(args)) {
return false;
- }
+ }
- if(!this->Rename.empty())
- {
- if(this->InstallType != cmInstallType_FILES &&
- this->InstallType != cmInstallType_PROGRAMS)
- {
+ 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)
- {
+ }
+ if (this->Files.size() > 1) {
this->FileCommand->SetError("INSTALL option RENAME may be used "
"only with one file.");
return false;
- }
}
+ }
- if(!this->HandleInstallDestination())
- {
+ 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)
- {
+ if (arg == "TYPE") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingType;
- }
}
- else if(arg == "FILES")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "FILES") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingFiles;
- }
}
- else if(arg == "RENAME")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "RENAME") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingRename;
- }
}
- else if(arg == "OPTIONAL")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "OPTIONAL") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
this->Doing = DoingNone;
this->Optional = true;
- }
}
- else if(arg == "PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } 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
- {
+ } else {
// file(INSTALL) aliases PERMISSIONS to FILE_PERMISSIONS
this->Doing = DoingPermissionsFile;
this->UseGivenPermissionsFile = true;
- }
}
- else if(arg == "DIR_PERMISSIONS")
- {
- if(this->CurrentMatchRule)
- {
+ } else if (arg == "DIR_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
this->NotAfterMatch(arg);
- }
- else
- {
+ } else {
// file(INSTALL) aliases DIR_PERMISSIONS to DIRECTORY_PERMISSIONS
this->Doing = DoingPermissionsDir;
this->UseGivenPermissionsDir = true;
- }
}
- else if(arg == "COMPONENTS" || arg == "CONFIGURATIONS" ||
- arg == "PROPERTIES")
- {
- cmOStringStream e;
+ } 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().c_str());
+ this->FileCommand->SetError(e.str());
this->Doing = DoingError;
- }
- else
- {
+ } else {
return this->cmFileCopier::CheckKeyword(arg);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFileInstaller::CheckValue(std::string const& arg)
{
- switch(this->Doing)
- {
+ switch (this->Doing) {
case DoingType:
- if(!this->GetTargetTypeFromString(arg))
- {
+ 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)
+bool cmFileInstaller::GetTargetTypeFromString(const std::string& stype)
{
- if ( stype == "EXECUTABLE" )
- {
+ if (stype == "EXECUTABLE") {
this->InstallType = cmInstallType_EXECUTABLE;
- }
- else if ( stype == "FILE" )
- {
+ } else if (stype == "FILE") {
this->InstallType = cmInstallType_FILES;
- }
- else if ( stype == "PROGRAM" )
- {
+ } else if (stype == "PROGRAM") {
this->InstallType = cmInstallType_PROGRAMS;
- }
- else if ( stype == "STATIC_LIBRARY" )
- {
+ } else if (stype == "STATIC_LIBRARY") {
this->InstallType = cmInstallType_STATIC_LIBRARY;
- }
- else if ( stype == "SHARED_LIBRARY" )
- {
+ } else if (stype == "SHARED_LIBRARY") {
this->InstallType = cmInstallType_SHARED_LIBRARY;
- }
- else if ( stype == "MODULE" )
- {
+ } else if (stype == "MODULE") {
this->InstallType = cmInstallType_MODULE_LIBRARY;
- }
- else if ( stype == "DIRECTORY" )
- {
+ } else if (stype == "DIRECTORY") {
this->InstallType = cmInstallType_DIRECTORY;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "Option TYPE given unknown value \"" << stype << "\".";
- this->FileCommand->SetError(e.str().c_str());
+ 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 != "/" )
- {
+ if (destination.size() < 2 && destination != "/") {
this->FileCommand->SetError("called with inappropriate arguments. "
- "No DESTINATION provided or .");
+ "No DESTINATION provided or .");
return false;
- }
+ }
- const char* destdir = cmSystemTools::GetEnv("DESTDIR");
- if ( destdir && *destdir )
- {
- std::string sdestdir = destdir;
+ 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 )
- {
+ if (destination.size() > 2) {
ch3 = destination[2];
- }
+ }
int skip = 0;
- if ( ch1 != '/' )
- {
+ if (ch1 != '/') {
int relative = 0;
if (((ch1 >= 'a' && ch1 <= 'z') || (ch1 >= 'A' && ch1 <= 'Z')) &&
- ch2 == ':' )
- {
+ ch2 == ':') {
// Assume windows
// let's do some destdir magic:
skip = 2;
- if ( ch3 != '/' )
- {
+ if (ch3 != '/') {
relative = 1;
- }
}
- else
- {
+ } else {
relative = 1;
- }
- if ( relative )
- {
+ }
+ if (relative) {
// This is relative path on unix or windows. Since we are doing
// destdir, this case does not make sense.
this->FileCommand->SetError(
@@ -2034,368 +1987,383 @@ bool cmFileInstaller::HandleInstallDestination()
"does not make sense when using DESTDIR. Specify "
"absolute path or remove DESTDIR environment variable.");
return false;
- }
}
- else
- {
- if ( ch2 == '/' )
- {
+ } else {
+ if (ch2 == '/') {
// looks like a network path.
- std::string message = "called with network path DESTINATION. This "
+ 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.c_str());
+ this->FileCommand->SetError(message);
return false;
- }
}
+ }
destination = sdestdir + (destination.c_str() + skip);
this->DestDirLength = int(sdestdir.size());
- }
+ }
- if ( !cmSystemTools::FileExists(destination.c_str()) )
- {
- if ( !cmSystemTools::MakeDirectory(destination.c_str()) )
- {
- std::string errstring = "cannot create directory: " + destination +
+ 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.c_str());
- return false;
+ this->FileCommand->SetError(errstring);
+ return false;
}
}
- if ( !cmSystemTools::FileIsDirectory(destination.c_str()) )
- {
- std::string errstring = "INSTALL destination: " + destination +
- " is not a directory.";
- this->FileCommand->SetError(errstring.c_str());
- 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 cmFileCommand::HandleRPathChangeCommand(
+ std::vector<std::string> const& args)
{
// Evaluate arguments.
- const char* file = 0;
- const char* oldRPath = 0;
- const char* newRPath = 0;
- enum Doing { DoingNone, DoingFile, DoingOld, DoingNew };
+ const char* file = CM_NULLPTR;
+ const char* oldRPath = CM_NULLPTR;
+ const char* newRPath = CM_NULLPTR;
+ enum Doing
+ {
+ DoingNone,
+ DoingFile,
+ DoingOld,
+ DoingNew
+ };
Doing doing = DoingNone;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "OLD_RPATH")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "OLD_RPATH") {
doing = DoingOld;
- }
- else if(args[i] == "NEW_RPATH")
- {
+ } else if (args[i] == "NEW_RPATH") {
doing = DoingNew;
- }
- else if(args[i] == "FILE")
- {
+ } else if (args[i] == "FILE") {
doing = DoingFile;
- }
- else if(doing == DoingFile)
- {
+ } else if (doing == DoingFile) {
file = args[i].c_str();
doing = DoingNone;
- }
- else if(doing == DoingOld)
- {
+ } else if (doing == DoingOld) {
oldRPath = args[i].c_str();
doing = DoingNone;
- }
- else if(doing == DoingNew)
- {
+ } else if (doing == DoingNew) {
newRPath = args[i].c_str();
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "RPATH_CHANGE given unknown argument " << args[i];
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- if(!file)
- {
+ }
+ if (!file) {
this->SetError("RPATH_CHANGE not given FILE option.");
return false;
- }
- if(!oldRPath)
- {
+ }
+ if (!oldRPath) {
this->SetError("RPATH_CHANGE not given OLD_RPATH option.");
return false;
- }
- if(!newRPath)
- {
+ }
+ if (!newRPath) {
this->SetError("RPATH_CHANGE not given NEW_RPATH option.");
return false;
- }
- if(!cmSystemTools::FileExists(file, true))
- {
- cmOStringStream e;
+ }
+ if (!cmSystemTools::FileExists(file, true)) {
+ std::ostringstream e;
e << "RPATH_CHANGE given FILE \"" << file << "\" that does not exist.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
bool success = true;
cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew();
bool have_ft = cmSystemTools::FileTimeGet(file, ft);
std::string emsg;
bool changed;
- if(!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg, &changed))
- {
- cmOStringStream e;
+ 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;
- this->SetError(e.str().c_str());
+ /* clang-format on */
+ this->SetError(e.str());
success = false;
- }
- if(success)
- {
- if(changed)
- {
+ }
+ 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)
- {
+ }
+ if (have_ft) {
cmSystemTools::FileTimeSet(file, ft);
- }
}
+ }
cmSystemTools::FileTimeDelete(ft);
return success;
}
-//----------------------------------------------------------------------------
-bool
-cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args)
+bool cmFileCommand::HandleRPathRemoveCommand(
+ std::vector<std::string> const& args)
{
// Evaluate arguments.
- const char* file = 0;
- enum Doing { DoingNone, DoingFile };
+ const char* file = CM_NULLPTR;
+ enum Doing
+ {
+ DoingNone,
+ DoingFile
+ };
Doing doing = DoingNone;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "FILE")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "FILE") {
doing = DoingFile;
- }
- else if(doing == DoingFile)
- {
+ } else if (doing == DoingFile) {
file = args[i].c_str();
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "RPATH_REMOVE given unknown argument " << args[i];
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- if(!file)
- {
+ }
+ if (!file) {
this->SetError("RPATH_REMOVE not given FILE option.");
return false;
- }
- if(!cmSystemTools::FileExists(file, true))
- {
- cmOStringStream e;
+ }
+ if (!cmSystemTools::FileExists(file, true)) {
+ std::ostringstream e;
e << "RPATH_REMOVE given FILE \"" << file << "\" that does not exist.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
bool success = true;
cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew();
bool have_ft = cmSystemTools::FileTimeGet(file, ft);
std::string emsg;
bool removed;
- if(!cmSystemTools::RemoveRPath(file, &emsg, &removed))
- {
- cmOStringStream e;
+ 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;
- this->SetError(e.str().c_str());
+ /* clang-format on */
+ this->SetError(e.str());
success = false;
- }
- if(success)
- {
- if(removed)
- {
+ }
+ if (success) {
+ if (removed) {
std::string message = "Removed runtime path from \"";
message += file;
message += "\"";
this->Makefile->DisplayStatus(message.c_str(), -1);
- }
- if(have_ft)
- {
+ }
+ if (have_ft) {
cmSystemTools::FileTimeSet(file, ft);
- }
}
+ }
cmSystemTools::FileTimeDelete(ft);
return success;
}
-//----------------------------------------------------------------------------
-bool
-cmFileCommand::HandleRPathCheckCommand(std::vector<std::string> const& args)
+bool cmFileCommand::HandleRPathCheckCommand(
+ std::vector<std::string> const& args)
{
// Evaluate arguments.
- const char* file = 0;
- const char* rpath = 0;
- enum Doing { DoingNone, DoingFile, DoingRPath };
+ const char* file = CM_NULLPTR;
+ const char* rpath = CM_NULLPTR;
+ enum Doing
+ {
+ DoingNone,
+ DoingFile,
+ DoingRPath
+ };
Doing doing = DoingNone;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "RPATH")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "RPATH") {
doing = DoingRPath;
- }
- else if(args[i] == "FILE")
- {
+ } else if (args[i] == "FILE") {
doing = DoingFile;
- }
- else if(doing == DoingFile)
- {
+ } else if (doing == DoingFile) {
file = args[i].c_str();
doing = DoingNone;
- }
- else if(doing == DoingRPath)
- {
+ } else if (doing == DoingRPath) {
rpath = args[i].c_str();
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "RPATH_CHECK given unknown argument " << args[i];
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- if(!file)
- {
+ }
+ if (!file) {
this->SetError("RPATH_CHECK not given FILE option.");
return false;
- }
- if(!rpath)
- {
+ }
+ if (!rpath) {
this->SetError("RPATH_CHECK not given RPATH option.");
return false;
- }
+ }
// If the file exists but does not have the desired RPath then
// delete it. This is used during installation to re-install a file
// if its RPath will change.
- if(cmSystemTools::FileExists(file, true) &&
- !cmSystemTools::CheckRPath(file, rpath))
- {
+ if (cmSystemTools::FileExists(file, true) &&
+ !cmSystemTools::CheckRPath(file, rpath)) {
cmSystemTools::RemoveFile(file);
+ }
+
+ return true;
+}
+
+bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 4) {
+ this->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);
+
+ cmCAString rpathArg(&argHelper, "RPATH", &group);
+ cmCAString runpathArg(&argHelper, "RUNPATH", &group);
+ cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group);
+
+ readArg.Follows(CM_NULLPTR);
+ fileNameArg.Follows(&readArg);
+ group.Follows(&fileNameArg);
+ argHelper.Parse(&args, CM_NULLPTR);
+
+ if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) {
+ std::ostringstream e;
+ e << "READ_ELF given FILE \"" << fileNameArg.GetString()
+ << "\" that does not exist.";
+ this->SetError(e.str());
+ return false;
+ }
+
+#if defined(CMAKE_USE_ELF_PARSER)
+ cmELF elf(fileNameArg.GetCString());
+
+ if (!rpathArg.GetString().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());
}
+ }
+ if (!runpathArg.GetString().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());
+ }
+ }
return true;
+#else
+ std::string error = "ELF parser not available on this platform.";
+ if (errorArg.GetString().empty()) {
+ this->SetError(error);
+ return false;
+ } else {
+ this->Makefile->AddDefinition(errorArg.GetString(), error.c_str());
+ return true;
+ }
+#endif
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
{
cmFileInstaller installer(this);
return installer.Run(args);
}
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleRelativePathCommand(
std::vector<std::string> const& args)
{
- if(args.size() != 4 )
- {
+ if (args.size() != 4) {
this->SetError("RELATIVE_PATH called with incorrect number of arguments");
return false;
- }
+ }
const std::string& outVar = args[1];
const std::string& directoryName = args[2];
const std::string& fileName = args[3];
- if(!cmSystemTools::FileIsFullPath(directoryName.c_str()))
- {
+ if (!cmSystemTools::FileIsFullPath(directoryName.c_str())) {
std::string errstring =
- "RELATIVE_PATH must be passed a full path to the directory: "
- + directoryName;
- this->SetError(errstring.c_str());
+ "RELATIVE_PATH must be passed a full path to the directory: " +
+ directoryName;
+ this->SetError(errstring);
return false;
- }
- if(!cmSystemTools::FileIsFullPath(fileName.c_str()))
- {
+ }
+ if (!cmSystemTools::FileIsFullPath(fileName.c_str())) {
std::string errstring =
- "RELATIVE_PATH must be passed a full path to the file: "
- + fileName;
- this->SetError(errstring.c_str());
+ "RELATIVE_PATH must be passed a full path to the file: " + fileName;
+ this->SetError(errstring);
return false;
- }
+ }
- std::string res = cmSystemTools::RelativePath(directoryName.c_str(),
- fileName.c_str());
- this->Makefile->AddDefinition(outVar.c_str(),
- res.c_str());
+ std::string res =
+ cmSystemTools::RelativePath(directoryName.c_str(), fileName.c_str());
+ this->Makefile->AddDefinition(outVar, res.c_str());
return true;
}
-
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleRename(std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
this->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->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(oldname.c_str())) {
+ oldname = this->Makefile->GetCurrentSourceDirectory();
oldname += "/" + args[1];
- }
+ }
std::string newname = args[2];
- if(!cmsys::SystemTools::FileIsFullPath(newname.c_str()))
- {
- newname = this->Makefile->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(newname.c_str())) {
+ newname = this->Makefile->GetCurrentSourceDirectory();
newname += "/" + args[2];
- }
+ }
- if(!cmSystemTools::RenameFile(oldname.c_str(), newname.c_str()))
- {
+ if (!cmSystemTools::RenameFile(oldname.c_str(), newname.c_str())) {
std::string err = cmSystemTools::GetLastSystemError();
- cmOStringStream e;
+ std::ostringstream e;
+ /* clang-format off */
e << "RENAME failed to rename\n"
<< " " << oldname << "\n"
<< "to\n"
<< " " << newname << "\n"
<< "because: " << err << "\n";
- this->SetError(e.str().c_str());
+ /* clang-format on */
+ this->SetError(e.str());
return false;
- }
+ }
return true;
}
-
-//----------------------------------------------------------------------------
bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
bool recurse)
{
@@ -2404,80 +2372,64 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
std::vector<std::string>::const_iterator i = args.begin();
i++; // Get rid of subcommand
- for(;i != args.end(); ++i)
- {
+ for (; i != args.end(); ++i) {
std::string fileName = *i;
- if(!cmsys::SystemTools::FileIsFullPath(fileName.c_str()))
- {
- fileName = this->Makefile->GetCurrentDirectory();
+ if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
+ fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + *i;
- }
+ }
- if(cmSystemTools::FileIsDirectory(fileName.c_str()) &&
- !cmSystemTools::FileIsSymlink(fileName.c_str()) && recurse)
- {
- cmSystemTools::RemoveADirectory(fileName.c_str());
- }
- else
- {
- cmSystemTools::RemoveFile(fileName.c_str());
- }
+ if (cmSystemTools::FileIsDirectory(fileName) &&
+ !cmSystemTools::FileIsSymlink(fileName) && recurse) {
+ cmSystemTools::RemoveADirectory(fileName);
+ } else {
+ cmSystemTools::RemoveFile(fileName);
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmFileCommand::HandleCMakePathCommand(std::vector<std::string>
- const& args,
- bool nativePath)
+bool cmFileCommand::HandleCMakePathCommand(
+ std::vector<std::string> const& args, bool nativePath)
{
std::vector<std::string>::const_iterator i = args.begin();
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
this->SetError("FILE([TO_CMAKE_PATH|TO_NATIVE_PATH] path result) must be "
- "called with exactly three arguments.");
+ "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->c_str(),
- pathSep);
+ std::vector<cmsys::String> path = cmSystemTools::SplitString(*i, pathSep);
i++;
- const char* var = i->c_str();
+ 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())
- {
+ for (std::vector<cmsys::String>::iterator j = path.begin(); j != path.end();
+ ++j) {
+ if (j != path.begin()) {
value += ";";
- }
- if(!nativePath)
- {
+ }
+ if (!nativePath) {
cmSystemTools::ConvertToUnixSlashes(*j);
- }
- else
- {
+ } else {
*j = cmSystemTools::ConvertToOutputPath(j->c_str());
// remove double quotes in the path
cmsys::String& s = *j;
- if(s.size() > 1 && s[0] == '\"' && s[s.size()-1] == '\"')
- {
- s = s.substr(1,s.size()-2);
- }
+ if (s.size() > 1 && s[0] == '\"' && s[s.size() - 1] == '\"') {
+ s = s.substr(1, s.size() - 2);
}
- value += *j;
}
+ value += *j;
+ }
this->Makefile->AddDefinition(var, value.c_str());
return true;
}
-
#if defined(CMAKE_BUILD_WITH_CMAKE)
// Stuff for curl download/upload
@@ -2485,184 +2437,174 @@ typedef std::vector<char> cmFileCommandVectorOfChar;
namespace {
- size_t
- cmWriteToFileCallback(void *ptr, size_t size, size_t nmemb,
- void *data)
- {
- int realsize = (int)(size * nmemb);
- std::ofstream* fout = static_cast<std::ofstream*>(data);
- const char* chPtr = static_cast<char*>(ptr);
- fout->write(chPtr, realsize);
- return realsize;
- }
-
-
- size_t
- cmWriteToMemoryCallback(void *ptr, size_t size, size_t nmemb,
- void *data)
- {
- int realsize = (int)(size * nmemb);
- cmFileCommandVectorOfChar *vec
- = static_cast<cmFileCommandVectorOfChar*>(data);
- const char* chPtr = static_cast<char*>(ptr);
- vec->insert(vec->end(), chPtr, chPtr + realsize);
- return realsize;
- }
-
+size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
+{
+ int realsize = (int)(size * nmemb);
+ cmsys::ofstream* fout = static_cast<cmsys::ofstream*>(data);
+ const char* chPtr = static_cast<char*>(ptr);
+ fout->write(chPtr, realsize);
+ return realsize;
+}
- static size_t
- cmFileCommandCurlDebugCallback(CURL *, curl_infotype, char *chPtr,
- size_t size, void *data)
- {
- cmFileCommandVectorOfChar *vec
- = static_cast<cmFileCommandVectorOfChar*>(data);
- vec->insert(vec->end(), chPtr, chPtr + size);
- return size;
- }
+size_t cmWriteToMemoryCallback(void* ptr, size_t size, size_t nmemb,
+ void* data)
+{
+ int realsize = (int)(size * nmemb);
+ cmFileCommandVectorOfChar* vec =
+ static_cast<cmFileCommandVectorOfChar*>(data);
+ const char* chPtr = static_cast<char*>(ptr);
+ vec->insert(vec->end(), 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);
+ switch (type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_IN:
+ case CURLINFO_HEADER_OUT:
+ vec->insert(vec->end(), chPtr, chPtr + size);
+ break;
+ case CURLINFO_DATA_IN:
+ case CURLINFO_DATA_OUT:
+ case CURLINFO_SSL_DATA_IN:
+ case CURLINFO_SSL_DATA_OUT: {
+ char buf[128];
+ 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);
+ }
+ } break;
+ default:
+ break;
+ }
+ return 0;
+}
- class cURLProgressHelper
+class cURLProgressHelper
+{
+public:
+ cURLProgressHelper(cmFileCommand* fc, const char* text)
{
- public:
- cURLProgressHelper(cmFileCommand *fc, const char *text)
- {
- this->CurrentPercentage = -1;
- this->FileCommand = fc;
- this->Text = text;
- }
+ this->CurrentPercentage = -1;
+ this->FileCommand = fc;
+ this->Text = text;
+ }
- bool UpdatePercentage(double value, double total, std::string &status)
- {
- int OldPercentage = this->CurrentPercentage;
-
- if (total > 0.0)
- {
- this->CurrentPercentage = static_cast<int>(value/total*100.0 + 0.5);
- }
-
- bool updated = (OldPercentage != this->CurrentPercentage);
-
- if (updated)
- {
- cmOStringStream oss;
- oss << "[" << this->Text << " " << this->CurrentPercentage
- << "% complete]";
- status = oss.str();
- }
+ bool UpdatePercentage(double value, double total, std::string& status)
+ {
+ int OldPercentage = this->CurrentPercentage;
- return updated;
+ if (total > 0.0) {
+ this->CurrentPercentage = static_cast<int>(value / total * 100.0 + 0.5);
+ if (this->CurrentPercentage > 100) {
+ // Avoid extra progress reports for unexpected data beyond total.
+ this->CurrentPercentage = 100;
}
+ }
- cmFileCommand *GetFileCommand()
- {
- return this->FileCommand;
- }
+ bool updated = (OldPercentage != this->CurrentPercentage);
- private:
- int CurrentPercentage;
- cmFileCommand *FileCommand;
- std::string Text;
- };
+ if (updated) {
+ std::ostringstream oss;
+ oss << "[" << this->Text << " " << this->CurrentPercentage
+ << "% complete]";
+ status = oss.str();
+ }
+ return updated;
+ }
- static int
- cmFileDownloadProgressCallback(void *clientp,
- double dltotal, double dlnow,
- double ultotal, double ulnow)
- {
- cURLProgressHelper *helper =
- reinterpret_cast<cURLProgressHelper *>(clientp);
+ cmFileCommand* GetFileCommand() { return this->FileCommand; }
- static_cast<void>(ultotal);
- static_cast<void>(ulnow);
+private:
+ int CurrentPercentage;
+ cmFileCommand* FileCommand;
+ std::string Text;
+};
- std::string status;
- if (helper->UpdatePercentage(dlnow, dltotal, status))
- {
- cmFileCommand *fc = helper->GetFileCommand();
- cmMakefile *mf = fc->GetMakefile();
- mf->DisplayStatus(status.c_str(), -1);
- }
+int cmFileDownloadProgressCallback(void* clientp, double dltotal, double dlnow,
+ double ultotal, double ulnow)
+{
+ cURLProgressHelper* helper = reinterpret_cast<cURLProgressHelper*>(clientp);
- return 0;
- }
+ static_cast<void>(ultotal);
+ static_cast<void>(ulnow);
+ std::string status;
+ if (helper->UpdatePercentage(dlnow, dltotal, status)) {
+ cmFileCommand* fc = helper->GetFileCommand();
+ cmMakefile* mf = fc->GetMakefile();
+ mf->DisplayStatus(status.c_str(), -1);
+ }
- static int
- cmFileUploadProgressCallback(void *clientp,
- double dltotal, double dlnow,
- double ultotal, double ulnow)
- {
- cURLProgressHelper *helper =
- reinterpret_cast<cURLProgressHelper *>(clientp);
+ return 0;
+}
- static_cast<void>(dltotal);
- static_cast<void>(dlnow);
+int cmFileUploadProgressCallback(void* clientp, double dltotal, double dlnow,
+ double ultotal, double ulnow)
+{
+ cURLProgressHelper* helper = reinterpret_cast<cURLProgressHelper*>(clientp);
- std::string status;
- if (helper->UpdatePercentage(ulnow, ultotal, status))
- {
- cmFileCommand *fc = helper->GetFileCommand();
- cmMakefile *mf = fc->GetMakefile();
- mf->DisplayStatus(status.c_str(), -1);
- }
+ static_cast<void>(dltotal);
+ static_cast<void>(dlnow);
- return 0;
- }
-}
+ std::string status;
+ if (helper->UpdatePercentage(ulnow, ultotal, status)) {
+ cmFileCommand* fc = helper->GetFileCommand();
+ cmMakefile* mf = fc->GetMakefile();
+ mf->DisplayStatus(status.c_str(), -1);
+ }
+ return 0;
+}
+}
namespace {
- class cURLEasyGuard
+class cURLEasyGuard
+{
+public:
+ cURLEasyGuard(CURL* easy)
+ : Easy(easy)
{
- public:
- cURLEasyGuard(CURL * easy)
- : Easy(easy)
- {}
-
- ~cURLEasyGuard(void)
- {
- if (this->Easy)
- {
- ::curl_easy_cleanup(this->Easy);
- }
- }
+ }
- inline void release(void)
- {
- this->Easy = 0;
- return;
- }
+ ~cURLEasyGuard()
+ {
+ if (this->Easy) {
+ ::curl_easy_cleanup(this->Easy);
+ }
+ }
- private:
- ::CURL * Easy;
- };
+ void release() { this->Easy = CM_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; \
+ }
-#define check_curl_result(result, errstr) \
- if (result != CURLE_OK) \
- { \
- std::string e(errstr); \
- e += ::curl_easy_strerror(result); \
- this->SetError(e.c_str()); \
- return false; \
- }
-
-
-bool
-cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
+bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
std::vector<std::string>::const_iterator i = args.begin();
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->SetError("DOWNLOAD must be called with at least three arguments.");
return false;
- }
+ }
++i; // Get rid of subcommand
std::string url = *i;
++i;
@@ -2671,188 +2613,172 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
long timeout = 0;
long inactivity_timeout = 0;
- std::string verboseLog;
+ std::string logVar;
std::string statusVar;
bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY");
const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO");
std::string expectedHash;
std::string hashMatchMSG;
- cmsys::auto_ptr<cmCryptoHash> hash;
+ CM_AUTO_PTR<cmCryptoHash> hash;
bool showProgress = false;
+ std::string userpwd;
- while(i != args.end())
- {
- if(*i == "TIMEOUT")
- {
+ std::vector<std::string> curl_headers;
+
+ while (i != args.end()) {
+ if (*i == "TIMEOUT") {
++i;
- if(i != args.end())
- {
+ if (i != args.end()) {
timeout = atol(i->c_str());
- }
- else
- {
+ } else {
this->SetError("DOWNLOAD missing time for TIMEOUT.");
return false;
- }
}
- else if(*i == "INACTIVITY_TIMEOUT")
- {
+ } else if (*i == "INACTIVITY_TIMEOUT") {
++i;
- if(i != args.end())
- {
+ if (i != args.end()) {
inactivity_timeout = atol(i->c_str());
- }
- else
- {
+ } else {
this->SetError("DOWNLOAD missing time for INACTIVITY_TIMEOUT.");
return false;
- }
}
- else if(*i == "LOG")
- {
+ } else if (*i == "LOG") {
++i;
- if( i == args.end())
- {
+ if (i == args.end()) {
this->SetError("DOWNLOAD missing VAR for LOG.");
return false;
- }
- verboseLog = *i;
}
- else if(*i == "STATUS")
- {
+ logVar = *i;
+ } else if (*i == "STATUS") {
++i;
- if( i == args.end())
- {
+ if (i == args.end()) {
this->SetError("DOWNLOAD missing VAR for STATUS.");
return false;
- }
- statusVar = *i;
}
- else if(*i == "TLS_VERIFY")
- {
+ statusVar = *i;
+ } else if (*i == "TLS_VERIFY") {
++i;
- if(i != args.end())
- {
+ if (i != args.end()) {
tls_verify = cmSystemTools::IsOn(i->c_str());
- }
- else
- {
+ } else {
this->SetError("TLS_VERIFY missing bool value.");
return false;
- }
}
- else if(*i == "TLS_CAINFO")
- {
+ } else if (*i == "TLS_CAINFO") {
++i;
- if(i != args.end())
- {
+ if (i != args.end()) {
cainfo = i->c_str();
- }
- else
- {
+ } else {
this->SetError("TLS_CAFILE missing file value.");
return false;
- }
}
- else if(*i == "EXPECTED_MD5")
- {
+ } else if (*i == "EXPECTED_MD5") {
++i;
- if( i == args.end())
- {
+ if (i == args.end()) {
this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5.");
return false;
- }
- hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New("MD5"));
+ }
+ hash =
+ CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(cmCryptoHash::AlgoMD5));
hashMatchMSG = "MD5 sum";
expectedHash = cmSystemTools::LowerCase(*i);
- }
- else if(*i == "SHOW_PROGRESS")
- {
+ } else if (*i == "SHOW_PROGRESS") {
showProgress = true;
- }
- else if(*i == "EXPECTED_HASH")
- {
+ } else if (*i == "EXPECTED_HASH") {
++i;
- if(i == args.end())
- {
+ if (i == args.end()) {
this->SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH.");
return false;
- }
+ }
std::string::size_type pos = i->find("=");
- if(pos == std::string::npos)
- {
+ if (pos == std::string::npos) {
std::string err =
"DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ";
err += *i;
- this->SetError(err.c_str());
+ this->SetError(err);
return false;
- }
+ }
std::string algo = i->substr(0, pos);
- expectedHash = cmSystemTools::LowerCase(i->substr(pos+1));
- hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New(algo.c_str()));
- if(!hash.get())
- {
+ 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.c_str());
+ this->SetError(err);
return false;
- }
+ }
hashMatchMSG = algo + " hash";
+ } else if (*i == "USERPWD") {
+ ++i;
+ if (i == args.end()) {
+ this->SetError("DOWNLOAD missing string for USERPWD.");
+ return false;
}
- ++i;
+ userpwd = *i;
+ } else if (*i == "HTTPHEADER") {
+ ++i;
+ if (i == args.end()) {
+ this->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);
}
+ ++i;
+ }
// If file exists already, and caller specified an expected md5 or sha,
// and the existing file already has the expected hash, then simply
// return.
//
- if(cmSystemTools::FileExists(file.c_str()) && hash.get())
- {
+ if (cmSystemTools::FileExists(file.c_str()) && hash.get()) {
std::string msg;
- std::string actualHash = hash->HashFile(file.c_str());
- if(actualHash == expectedHash)
- {
+ std::string actualHash = hash->HashFile(file);
+ if (actualHash == expectedHash) {
msg = "returning early; file already exists with expected ";
msg += hashMatchMSG;
msg += "\"";
- if(statusVar.size())
- {
- cmOStringStream result;
+ if (!statusVar.empty()) {
+ std::ostringstream result;
result << (int)0 << ";\"" << msg;
- this->Makefile->AddDefinition(statusVar.c_str(),
- result.str().c_str());
- }
- return true;
+ this->Makefile->AddDefinition(statusVar, result.str().c_str());
}
+ return true;
}
+ }
// Make sure parent directory exists so we can write to the file
// as we receive downloaded bits from curl...
//
- std::string dir = cmSystemTools::GetFilenamePath(file.c_str());
- if(!cmSystemTools::FileExists(dir.c_str()) &&
- !cmSystemTools::MakeDirectory(dir.c_str()))
- {
- std::string errstring = "DOWNLOAD error: cannot create directory '"
- + dir + "' - Specify file by full path name and verify that you "
+ std::string dir = cmSystemTools::GetFilenamePath(file);
+ if (!cmSystemTools::FileExists(dir.c_str()) &&
+ !cmSystemTools::MakeDirectory(dir.c_str())) {
+ 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.c_str());
+ this->SetError(errstring);
return false;
- }
+ }
- std::ofstream fout(file.c_str(), std::ios::binary);
- if(!fout)
- {
+ cmsys::ofstream fout(file.c_str(), std::ios::binary);
+ if (!fout) {
this->SetError("DOWNLOAD cannot open file for write.");
return false;
- }
+ }
- ::CURL *curl;
+#if defined(_WIN32)
+ url = fix_file_url_windows(url);
+#endif
+
+ ::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
curl = ::curl_easy_init();
- if(!curl)
- {
+ if (!curl) {
this->SetError("DOWNLOAD error initializing curl.");
return false;
- }
+ }
cURLEasyGuard g_curl(curl);
::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
@@ -2865,8 +2791,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
res = ::curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/" LIBCURL_VERSION);
check_curl_result(res, "DOWNLOAD cannot set user agent option: ");
- res = ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
- cmWriteToFileCallback);
+ res = ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cmWriteToFileCallback);
check_curl_result(res, "DOWNLOAD cannot set write function: ");
res = ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
@@ -2874,53 +2799,47 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
check_curl_result(res, "DOWNLOAD cannot set debug function: ");
// check to see if TLS verification is requested
- if(tls_verify)
- {
+ if (tls_verify) {
res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
check_curl_result(res, "Unable to set TLS/SSL Verify on: ");
- }
- else
- {
+ } else {
res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
check_curl_result(res, "Unable to set TLS/SSL Verify off: ");
- }
+ }
// check to see if a CAINFO file has been specified
// command arg comes first
- if(cainfo && *cainfo)
- {
- res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo);
- check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
- }
+ std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo);
+ if (!cainfo_err.empty()) {
+ this->SetError(cainfo_err);
+ return false;
+ }
cmFileCommandVectorOfChar chunkDebug;
- res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&fout);
+ res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&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, (void*)&chunkDebug);
check_curl_result(res, "DOWNLOAD cannot set debug data: ");
res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
check_curl_result(res, "DOWNLOAD cannot set follow-redirect option: ");
- if(verboseLog.size())
- {
+ if (!logVar.empty()) {
res = ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
check_curl_result(res, "DOWNLOAD cannot set verbose: ");
- }
+ }
- if(timeout > 0)
- {
- res = ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout );
+ if (timeout > 0) {
+ res = ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
check_curl_result(res, "DOWNLOAD cannot set timeout: ");
- }
+ }
- if(inactivity_timeout > 0)
- {
+ if (inactivity_timeout > 0) {
// Give up if there is no progress for a long time.
::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, inactivity_timeout);
- }
+ }
// Need the progress helper's scope to last through the duration of
// the curl_easy_perform call... so this object is declared at function
@@ -2929,33 +2848,44 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
//
cURLProgressHelper helper(this, "download");
- if(showProgress)
- {
+ if (showProgress) {
res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
check_curl_result(res, "DOWNLOAD cannot set noprogress value: ");
- res = ::curl_easy_setopt(curl,
- CURLOPT_PROGRESSFUNCTION, cmFileDownloadProgressCallback);
+ res = ::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
+ cmFileDownloadProgressCallback);
check_curl_result(res, "DOWNLOAD cannot set progress function: ");
- res = ::curl_easy_setopt(curl,
- CURLOPT_PROGRESSDATA, reinterpret_cast<void*>(&helper));
+ res = ::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA,
+ reinterpret_cast<void*>(&helper));
check_curl_result(res, "DOWNLOAD cannot set progress data: ");
- }
+ }
+
+ if (!userpwd.empty()) {
+ res = ::curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
+ 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());
+ }
+ ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = ::curl_easy_perform(curl);
+ ::curl_slist_free_all(headers);
+
/* always cleanup */
g_curl.release();
::curl_easy_cleanup(curl);
- if(statusVar.size())
- {
- cmOStringStream result;
+ if (!statusVar.empty()) {
+ std::ostringstream result;
result << (int)res << ";\"" << ::curl_easy_strerror(res) << "\"";
- this->Makefile->AddDefinition(statusVar.c_str(),
- result.str().c_str());
- }
+ this->Makefile->AddDefinition(statusVar, result.str().c_str());
+ }
::curl_global_cleanup();
@@ -2966,45 +2896,38 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// Verify MD5 sum if requested:
//
- if (hash.get())
- {
- std::string actualHash = hash->HashFile(file.c_str());
- if (actualHash.size() == 0)
- {
+ if (hash.get()) {
+ std::string actualHash = hash->HashFile(file);
+ if (actualHash.empty()) {
this->SetError("DOWNLOAD cannot compute hash on downloaded file");
return false;
- }
+ }
- if (expectedHash != actualHash)
- {
- cmOStringStream oss;
+ 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
- ;
- this->SetError(oss.str().c_str());
- return false;
- }
- }
+ << " 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(chunkDebug.size())
- {
- chunkDebug.push_back(0);
- if(CURLE_OPERATION_TIMEOUTED == res)
- {
- std::string output = &*chunkDebug.begin();
-
- if(verboseLog.size())
- {
- this->Makefile->AddDefinition(verboseLog.c_str(),
- &*chunkDebug.begin());
- }
+ if (!statusVar.empty() && res == 0) {
+ std::string status = "1;HASH mismatch: "
+ "expected: " +
+ expectedHash + " actual: " + actualHash;
+ this->Makefile->AddDefinition(statusVar, status.c_str());
}
- this->Makefile->AddDefinition(verboseLog.c_str(),
- &*chunkDebug.begin());
+ this->SetError(oss.str());
+ return false;
}
+ }
+
+ if (!logVar.empty()) {
+ chunkDebug.push_back(0);
+ this->Makefile->AddDefinition(logVar, &*chunkDebug.begin());
+ }
return true;
#else
@@ -3013,16 +2936,13 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
#endif
}
-
-bool
-cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
+bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->SetError("UPLOAD must be called with at least three arguments.");
return false;
- }
+ }
std::vector<std::string>::const_iterator i = args.begin();
++i;
std::string filename = *i;
@@ -3035,98 +2955,97 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
std::string logVar;
std::string statusVar;
bool showProgress = false;
+ std::string userpwd;
- while(i != args.end())
- {
- if(*i == "TIMEOUT")
- {
+ std::vector<std::string> curl_headers;
+
+ while (i != args.end()) {
+ if (*i == "TIMEOUT") {
++i;
- if(i != args.end())
- {
+ if (i != args.end()) {
timeout = atol(i->c_str());
- }
- else
- {
+ } else {
this->SetError("UPLOAD missing time for TIMEOUT.");
return false;
- }
}
- else if(*i == "INACTIVITY_TIMEOUT")
- {
+ } else if (*i == "INACTIVITY_TIMEOUT") {
++i;
- if(i != args.end())
- {
+ if (i != args.end()) {
inactivity_timeout = atol(i->c_str());
- }
- else
- {
+ } else {
this->SetError("UPLOAD missing time for INACTIVITY_TIMEOUT.");
return false;
- }
}
- else if(*i == "LOG")
- {
+ } else if (*i == "LOG") {
++i;
- if( i == args.end())
- {
+ if (i == args.end()) {
this->SetError("UPLOAD missing VAR for LOG.");
return false;
- }
- logVar = *i;
}
- else if(*i == "STATUS")
- {
+ logVar = *i;
+ } else if (*i == "STATUS") {
++i;
- if( i == args.end())
- {
+ if (i == args.end()) {
this->SetError("UPLOAD missing VAR for STATUS.");
return false;
- }
- statusVar = *i;
}
- else if(*i == "SHOW_PROGRESS")
- {
+ statusVar = *i;
+ } else if (*i == "SHOW_PROGRESS") {
showProgress = true;
+ } else if (*i == "USERPWD") {
+ ++i;
+ if (i == args.end()) {
+ this->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.");
+ 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);
+ }
++i;
- }
+ }
// Open file for reading:
//
- FILE *fin = fopen(filename.c_str(), "rb");
- if(!fin)
- {
+ FILE* fin = cmsys::SystemTools::Fopen(filename, "rb");
+ if (!fin) {
std::string errStr = "UPLOAD cannot open file '";
errStr += filename + "' for reading.";
- this->SetError(errStr.c_str());
+ this->SetError(errStr);
return false;
- }
+ }
- struct stat st;
- if(::stat(filename.c_str(), &st))
- {
- std::string errStr = "UPLOAD cannot stat file '";
- errStr += filename + "'.";
- this->SetError(errStr.c_str());
- fclose(fin);
- return false;
- }
+ unsigned long file_size = cmsys::SystemTools::FileLength(filename);
+
+#if defined(_WIN32)
+ url = fix_file_url_windows(url);
+#endif
- ::CURL *curl;
+ ::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
curl = ::curl_easy_init();
- if(!curl)
- {
+ if (!curl) {
this->SetError("UPLOAD error initializing curl.");
fclose(fin);
return false;
- }
+ }
cURLEasyGuard g_curl(curl);
// enable HTTP ERROR parsing
::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+ check_curl_result(res, "UPLOAD cannot set fail on error flag: ");
// enable uploading
res = ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
@@ -3135,8 +3054,8 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
check_curl_result(res, "UPLOAD cannot set url: ");
- res = ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
- cmWriteToMemoryCallback);
+ res =
+ ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cmWriteToMemoryCallback);
check_curl_result(res, "UPLOAD cannot set write function: ");
res = ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
@@ -3146,33 +3065,30 @@ 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, (void*)&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, (void*)&chunkDebug);
check_curl_result(res, "UPLOAD cannot set debug data: ");
res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
check_curl_result(res, "UPLOAD cannot set follow-redirect option: ");
- if(logVar.size())
- {
+ if (!logVar.empty()) {
res = ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
check_curl_result(res, "UPLOAD cannot set verbose: ");
- }
+ }
- if(timeout > 0)
- {
- res = ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout );
+ if (timeout > 0) {
+ res = ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
check_curl_result(res, "UPLOAD cannot set timeout: ");
- }
+ }
- if(inactivity_timeout > 0)
- {
+ if (inactivity_timeout > 0) {
// Give up if there is no progress for a long time.
::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, inactivity_timeout);
- }
+ }
// Need the progress helper's scope to last through the duration of
// the curl_easy_perform call... so this object is declared at function
@@ -3181,71 +3097,79 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
//
cURLProgressHelper helper(this, "upload");
- if(showProgress)
- {
+ if (showProgress) {
res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
check_curl_result(res, "UPLOAD cannot set noprogress value: ");
- res = ::curl_easy_setopt(curl,
- CURLOPT_PROGRESSFUNCTION, cmFileUploadProgressCallback);
+ res = ::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
+ cmFileUploadProgressCallback);
check_curl_result(res, "UPLOAD cannot set progress function: ");
- res = ::curl_easy_setopt(curl,
- CURLOPT_PROGRESSDATA, reinterpret_cast<void*>(&helper));
+ res = ::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA,
+ reinterpret_cast<void*>(&helper));
check_curl_result(res, "UPLOAD cannot set progress data: ");
- }
+ }
// now specify which file to upload
res = ::curl_easy_setopt(curl, CURLOPT_INFILE, fin);
check_curl_result(res, "UPLOAD cannot set input file: ");
// and give the size of the upload (optional)
- res = ::curl_easy_setopt(curl,
- CURLOPT_INFILESIZE, static_cast<long>(st.st_size));
+ res =
+ ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, static_cast<long>(file_size));
check_curl_result(res, "UPLOAD cannot set input file size: ");
+ if (!userpwd.empty()) {
+ res = ::curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
+ 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());
+ }
+ ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
res = ::curl_easy_perform(curl);
+ ::curl_slist_free_all(headers);
+
/* always cleanup */
g_curl.release();
::curl_easy_cleanup(curl);
- if(statusVar.size())
- {
- cmOStringStream result;
+ if (!statusVar.empty()) {
+ std::ostringstream result;
result << (int)res << ";\"" << ::curl_easy_strerror(res) << "\"";
- this->Makefile->AddDefinition(statusVar.c_str(),
- result.str().c_str());
- }
+ this->Makefile->AddDefinition(statusVar, result.str().c_str());
+ }
::curl_global_cleanup();
fclose(fin);
- fin = NULL;
+ fin = CM_NULLPTR;
- if(logVar.size())
- {
+ if (!logVar.empty()) {
std::string log;
- if(chunkResponse.size())
- {
+ if (!chunkResponse.empty()) {
chunkResponse.push_back(0);
log += "Response:\n";
log += &*chunkResponse.begin();
log += "\n";
- }
+ }
- if(chunkDebug.size())
- {
+ if (!chunkDebug.empty()) {
chunkDebug.push_back(0);
log += "Debug:\n";
log += &*chunkDebug.begin();
log += "\n";
- }
-
- this->Makefile->AddDefinition(logVar.c_str(), log.c_str());
}
+ this->Makefile->AddDefinition(logVar, log.c_str());
+ }
+
return true;
#else
this->SetError("UPLOAD not supported by bootstrap cmake.");
@@ -3253,94 +3177,234 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
#endif
}
-//----------------------------------------------------------------------------
-void cmFileCommand::AddEvaluationFile(const std::string &inputName,
- const std::string &outputExpr,
- const std::string &condition,
- bool inputIsContent
- )
+void cmFileCommand::AddEvaluationFile(const std::string& inputName,
+ const std::string& outputExpr,
+ const std::string& condition,
+ bool inputIsContent)
{
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
cmGeneratorExpression outputGe(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> outputCge
- = outputGe.Parse(outputExpr);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> outputCge =
+ outputGe.Parse(outputExpr);
cmGeneratorExpression conditionGe(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge
- = conditionGe.Parse(condition);
-
- this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->AddEvaluationFile(inputName,
- outputCge,
- this->Makefile,
- conditionCge,
- inputIsContent);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> conditionCge =
+ conditionGe.Parse(condition);
+
+ this->Makefile->AddEvaluationFile(inputName, outputCge, conditionCge,
+ inputIsContent);
}
-//----------------------------------------------------------------------------
-bool cmFileCommand::HandleGenerateCommand(
- std::vector<std::string> const& args)
+bool cmFileCommand::HandleGenerateCommand(std::vector<std::string> const& args)
{
- if (args.size() < 5)
- {
+ if (args.size() < 5) {
this->SetError("Incorrect arguments to GENERATE subcommand.");
return false;
- }
- if (args[1] != "OUTPUT")
- {
+ }
+ if (args[1] != "OUTPUT") {
this->SetError("Incorrect arguments to GENERATE subcommand.");
return false;
- }
+ }
std::string condition;
- if (args.size() > 5)
- {
- if (args[5] != "CONDITION")
- {
+ if (args.size() > 5) {
+ if (args[5] != "CONDITION") {
this->SetError("Incorrect arguments to GENERATE subcommand.");
return false;
- }
- if (args.size() != 7)
- {
+ }
+ if (args.size() != 7) {
this->SetError("Incorrect arguments to GENERATE subcommand.");
return false;
- }
+ }
condition = args[6];
- if (condition.empty())
- {
+ if (condition.empty()) {
this->SetError("CONDITION of sub-command GENERATE must not be empty if "
- "specified.");
+ "specified.");
return false;
- }
}
+ }
std::string output = args[2];
const bool inputIsContent = args[3] != "INPUT";
- if (inputIsContent && args[3] != "CONTENT")
- {
+ if (inputIsContent && args[3] != "CONTENT") {
this->SetError("Incorrect arguments to GENERATE subcommand.");
return false;
- }
+ }
std::string input = args[4];
this->AddEvaluationFile(input, output, condition, inputIsContent);
return true;
}
-//----------------------------------------------------------------------------
+bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
+{
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ // Default values
+ bool directory = false;
+ bool release = false;
+ enum Guard
+ {
+ GUARD_FUNCTION,
+ GUARD_FILE,
+ GUARD_PROCESS
+ };
+ Guard guard = GUARD_PROCESS;
+ std::string resultVariable;
+ unsigned long timeout = static_cast<unsigned long>(-1);
+
+ // Parse arguments
+ if (args.size() < 2) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "sub-command LOCK requires at least two arguments.");
+ return false;
+ }
+
+ std::string path = args[1];
+ for (unsigned i = 2; i < args.size(); ++i) {
+ if (args[i] == "DIRECTORY") {
+ directory = true;
+ } else if (args[i] == "RELEASE") {
+ release = true;
+ } else if (args[i] == "GUARD") {
+ ++i;
+ const char* merr = "expected FUNCTION, FILE or PROCESS after GUARD";
+ if (i >= args.size()) {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, merr);
+ return false;
+ }
+ if (args[i] == "FUNCTION") {
+ guard = GUARD_FUNCTION;
+ } else if (args[i] == "FILE") {
+ guard = GUARD_FILE;
+ } 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());
+ 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");
+ 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");
+ 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());
+ 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());
+ return false;
+ }
+ }
+
+ if (directory) {
+ path += "/cmake.lock";
+ }
+
+ if (!cmsys::SystemTools::FileIsFullPath(path)) {
+ path = this->Makefile->GetCurrentSourceDirectory() + ("/" + path);
+ }
+
+ // Unify path (remove '//', '/../', ...)
+ path = cmSystemTools::CollapseFullPath(path);
+
+ // 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());
+ 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());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ fclose(file);
+
+ // Actual lock/unlock
+ cmFileLockPool& lockPool =
+ this->Makefile->GetGlobalGenerator()->GetFileLockPool();
+
+ cmFileLockResult fileLockResult(cmFileLockResult::MakeOk());
+ if (release) {
+ fileLockResult = lockPool.Release(path);
+ } else {
+ switch (guard) {
+ case GUARD_FUNCTION:
+ fileLockResult = lockPool.LockFunctionScope(path, timeout);
+ break;
+ case GUARD_FILE:
+ fileLockResult = lockPool.LockFileScope(path, timeout);
+ break;
+ case GUARD_PROCESS:
+ fileLockResult = lockPool.LockProcessScope(path, timeout);
+ break;
+ default:
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ }
+
+ 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());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ if (!resultVariable.empty()) {
+ this->Makefile->AddDefinition(resultVariable, result.c_str());
+ }
+
+ return true;
+#else
+ static_cast<void>(args);
+ this->SetError("sub-command LOCK not implemented in bootstrap cmake");
+ return false;
+#endif
+}
+
bool cmFileCommand::HandleTimestampCommand(
std::vector<std::string> const& args)
{
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->SetError("sub-command TIMESTAMP requires at least two arguments.");
return false;
- }
- else if(args.size() > 5)
- {
+ }
+ if (args.size() > 5) {
this->SetError("sub-command TIMESTAMP takes at most four arguments.");
return false;
- }
+ }
unsigned int argsIndex = 1;
@@ -3349,31 +3413,26 @@ bool cmFileCommand::HandleTimestampCommand(
const std::string& outputVariable = args[argsIndex++];
std::string formatString;
- if(args.size() > argsIndex && args[argsIndex] != "UTC")
- {
+ if (args.size() > argsIndex && args[argsIndex] != "UTC") {
formatString = args[argsIndex++];
- }
+ }
bool utcFlag = false;
- if(args.size() > argsIndex)
- {
- if(args[argsIndex] == "UTC")
- {
+ if (args.size() > argsIndex) {
+ if (args[argsIndex] == "UTC") {
utcFlag = true;
- }
- else
- {
+ } else {
std::string e = " TIMESTAMP sub-command does not recognize option " +
- args[argsIndex] + ".";
- this->SetError(e.c_str());
+ args[argsIndex] + ".";
+ this->SetError(e);
return false;
- }
}
+ }
cmTimestamp timestamp;
- std::string result = timestamp.FileModificationTime(
- filename.c_str(), formatString, utcFlag);
- this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str());
+ std::string result =
+ timestamp.FileModificationTime(filename.c_str(), formatString, utcFlag);
+ this->Makefile->AddDefinition(outputVariable, result.c_str());
return true;
}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index aa755d1f5..d09ef42f1 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -1,20 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFileCommand_h
#define cmFileCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-struct cmFileInstaller;
+class cmExecutionStatus;
/** \class cmFileCommand
* \brief Command for manipulation of files
@@ -26,236 +22,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFileCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFileCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "file";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "File manipulation command.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " file(WRITE filename \"message to write\"... )\n"
- " file(APPEND filename \"message to write\"... )\n"
- " file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX])\n"
- " file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> filename variable)\n"
- " file(STRINGS filename variable [LIMIT_COUNT num]\n"
- " [LIMIT_INPUT numBytes] [LIMIT_OUTPUT numBytes]\n"
- " [LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUM numBytes]\n"
- " [NEWLINE_CONSUME] [REGEX regex]\n"
- " [NO_HEX_CONVERSION])\n"
- " file(GLOB variable [RELATIVE path] [globbing expressions]...)\n"
- " file(GLOB_RECURSE variable [RELATIVE path] \n"
- " [FOLLOW_SYMLINKS] [globbing expressions]...)\n"
- " file(RENAME <oldname> <newname>)\n"
- " file(REMOVE [file1 ...])\n"
- " file(REMOVE_RECURSE [file1 ...])\n"
- " file(MAKE_DIRECTORY [directory1 directory2 ...])\n"
- " file(RELATIVE_PATH variable directory file)\n"
- " file(TO_CMAKE_PATH path result)\n"
- " file(TO_NATIVE_PATH path result)\n"
- " file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout]\n"
- " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]\n"
- " [EXPECTED_HASH ALGO=value] [EXPECTED_MD5 sum]\n"
- " [TLS_VERIFY on|off] [TLS_CAINFO file])\n"
- " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n"
- " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n"
- " file(TIMESTAMP filename variable [<format string>] [UTC])\n"
- " file(GENERATE OUTPUT output_file\n"
- " <INPUT input_file|CONTENT input_content>\n"
- " [CONDITION expression])\n"
- "WRITE will write a message into a file called 'filename'. It "
- "overwrites the file if it already exists, and creates the file "
- "if it does not exist. (If the file is a build input, use "
- "configure_file to update the file only when its content changes.)\n"
- "APPEND will write a message into a file same as WRITE, except "
- "it will append it to the end of the file\n"
- "READ will read the content of a file and store it into the "
- "variable. It will start at the given offset and read up to numBytes. "
- "If the argument HEX is given, the binary data will be converted to "
- "hexadecimal representation and this will be stored in the variable.\n"
- "MD5, SHA1, SHA224, SHA256, SHA384, and SHA512 "
- "will compute a cryptographic hash of the content of a file.\n"
- "STRINGS will parse a list of ASCII strings from a file and "
- "store it in a variable. Binary data in the file are ignored. Carriage "
- "return (CR) characters are ignored. It works also for Intel Hex and "
- "Motorola S-record files, which are automatically converted to binary "
- "format when reading them. Disable this using NO_HEX_CONVERSION.\n"
- "LIMIT_COUNT sets the maximum number of strings to return. "
- "LIMIT_INPUT sets the maximum number of bytes to read from "
- "the input file. "
- "LIMIT_OUTPUT sets the maximum number of bytes to store in the "
- "output variable. "
- "LENGTH_MINIMUM sets the minimum length of a string to return. "
- "Shorter strings are ignored. "
- "LENGTH_MAXIMUM sets the maximum length of a string to return. Longer "
- "strings are split into strings no longer than the maximum length. "
- "NEWLINE_CONSUME allows newlines to be included in strings instead "
- "of terminating them.\n"
- "REGEX specifies a regular expression that a string must match to be "
- "returned. Typical usage \n"
- " file(STRINGS myfile.txt myfile)\n"
- "stores a list in the variable \"myfile\" in which each item is "
- "a line from the input file.\n"
- "GLOB will generate a list of all files that match the globbing "
- "expressions and store it into the variable. Globbing expressions "
- "are similar to regular expressions, but much simpler. If RELATIVE "
- "flag is specified for an expression, the results will be returned "
- "as a relative path to the given path. "
- "(We do not recommend using GLOB to collect a list of source files "
- "from your source tree. If no CMakeLists.txt file changes when a "
- "source is added or removed then the generated build system cannot "
- "know when to ask CMake to regenerate.)"
- "\n"
- "Examples of globbing expressions include:\n"
- " *.cxx - match all files with extension cxx\n"
- " *.vt? - match all files with extension vta,...,vtz\n"
- " f[3-5].txt - match files f3.txt, f4.txt, f5.txt\n"
- "GLOB_RECURSE will generate a list similar to the regular GLOB, except "
- "it will traverse all the subdirectories of the matched directory and "
- "match the files. Subdirectories that are symlinks are only traversed "
- "if FOLLOW_SYMLINKS is given or cmake policy CMP0009 is not set to NEW. "
- "See cmake --help-policy CMP0009 for more information.\n"
- "Examples of recursive globbing include:\n"
- " /dir/*.py - match all python files in /dir and subdirectories\n"
- "MAKE_DIRECTORY will create the given directories, also if their parent "
- "directories don't exist yet\n"
- "RENAME moves a file or directory within a filesystem, "
- "replacing the destination atomically."
- "\n"
- "REMOVE will remove the given files, also in subdirectories\n"
- "REMOVE_RECURSE will remove the given files and directories, also "
- "non-empty directories\n"
- "RELATIVE_PATH will determine relative path from directory to the given"
- " file.\n"
- "TO_CMAKE_PATH will convert path into a cmake style path with unix /. "
- " The input can be a single path or a system path like \"$ENV{PATH}\". "
- " Note the double quotes around the ENV call TO_CMAKE_PATH only takes "
- " one argument. This command will also convert the native list"
- " delimiters for a list of paths like the PATH environment variable.\n"
- "TO_NATIVE_PATH works just like TO_CMAKE_PATH, but will convert from "
- " a cmake style path into the native path style \\ for windows and / "
- "for UNIX.\n"
- "DOWNLOAD will download the given URL to the given file. "
- "If LOG var is specified a log of the download will be put in var. "
- "If STATUS var is specified the status of the operation will"
- " be put in var. The status is returned in a list of length 2. "
- "The first element is the numeric return value for the operation, "
- "and the second element is a string value for the error. A 0 "
- "numeric error means no error in the operation. "
- "If TIMEOUT time is specified, the operation will "
- "timeout after time seconds, time should be specified as an integer. "
- "The INACTIVITY_TIMEOUT specifies an integer number of seconds of "
- "inactivity after which the operation should terminate. "
- "If EXPECTED_HASH ALGO=value is specified, the operation will verify "
- "that the downloaded file's actual hash matches the expected value, "
- "where ALGO is one of MD5, SHA1, SHA224, SHA256, SHA384, or SHA512. "
- "If it does not match, the operation fails with an error. "
- "(\"EXPECTED_MD5 sum\" is short-hand for \"EXPECTED_HASH MD5=sum\".) "
- "If SHOW_PROGRESS is specified, progress information will be printed "
- "as status messages until the operation is complete. "
- "For https URLs CMake must be built with OpenSSL. "
- "TLS/SSL certificates are not checked by default. "
- "Set TLS_VERIFY to ON to check certificates and/or use "
- "EXPECTED_HASH to verify downloaded content. "
- "Set TLS_CAINFO to specify a custom Certificate Authority file. "
- "If either TLS option is not given CMake will check variables "
- "CMAKE_TLS_VERIFY and CMAKE_TLS_CAINFO, "
- "respectively."
- "\n"
- "UPLOAD will upload the given file to the given URL. "
- "If LOG var is specified a log of the upload will be put in var. "
- "If STATUS var is specified the status of the operation will"
- " be put in var. The status is returned in a list of length 2. "
- "The first element is the numeric return value for the operation, "
- "and the second element is a string value for the error. A 0 "
- "numeric error means no error in the operation. "
- "If TIMEOUT time is specified, the operation will "
- "timeout after time seconds, time should be specified as an integer. "
- "The INACTIVITY_TIMEOUT specifies an integer number of seconds of "
- "inactivity after which the operation should terminate. "
- "If SHOW_PROGRESS is specified, progress information will be printed "
- "as status messages until the operation is complete."
- "\n"
- "TIMESTAMP will write a string representation of "
- "the modification time of filename to variable.\n"
- "Should the command be unable to obtain a timestamp "
- "variable will be set to the empty string \"\".\n"
- "See documentation of the string TIMESTAMP sub-command for more details."
- "\n"
- "The file() command also provides COPY and INSTALL signatures:\n"
- " file(<COPY|INSTALL> files... DESTINATION <dir>\n"
- " [FILE_PERMISSIONS permissions...]\n"
- " [DIRECTORY_PERMISSIONS permissions...]\n"
- " [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]\n"
- " [FILES_MATCHING]\n"
- " [[PATTERN <pattern> | REGEX <regex>]\n"
- " [EXCLUDE] [PERMISSIONS permissions...]] [...])\n"
- "The COPY signature copies files, directories, and symlinks to a "
- "destination folder. "
- "Relative input paths are evaluated with respect to the current "
- "source directory, and a relative destination is evaluated with "
- "respect to the current build directory. "
- "Copying preserves input file timestamps, and optimizes out a file "
- "if it exists at the destination with the same timestamp. "
- "Copying preserves input permissions unless explicit permissions or "
- "NO_SOURCE_PERMISSIONS are given (default is USE_SOURCE_PERMISSIONS). "
- "See the install(DIRECTORY) command for documentation of permissions, "
- "PATTERN, REGEX, and EXCLUDE options. "
- "\n"
- "The INSTALL signature differs slightly from COPY: "
- "it prints status messages, and NO_SOURCE_PERMISSIONS is default. "
- "Installation scripts generated by the install() command use this "
- "signature (with some undocumented options for internal use)."
- "\n"
- "GENERATE will write an <output_file> with content from an "
- "<input_file>, or from <input_content>. The output is generated "
- "conditionally based on the content of the <condition>. The file is "
- "written at CMake generate-time and the input may contain generator "
- "expressions. The <condition>, <output_file> and <input_file> may "
- "also contain generator expressions. The <condition> must evaluate to "
- "either '0' or '1'. The <output_file> must evaluate to a unique name "
- "among all configurations and among all invocations of file(GENERATE)."
- // Undocumented INSTALL options:
- // - RENAME <name>
- // - OPTIONAL
- // - FILES keyword to re-enter files... list
- // - PERMISSIONS before REGEX is alias for FILE_PERMISSIONS
- // - DIR_PERMISSIONS is alias for DIRECTORY_PERMISSIONS
- // - TYPE <FILE|DIRECTORY|EXECUTABLE|PROGRAM|
- // STATIC_LIBRARY|SHARED_LIBRARY|MODULE>
- // - COMPONENTS, CONFIGURATIONS, PROPERTIES (ignored for compat)
- ;
- }
-
- cmTypeMacro(cmFileCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
protected:
bool HandleRename(std::vector<std::string> const& args);
@@ -270,6 +44,7 @@ protected:
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);
@@ -282,13 +57,12 @@ protected:
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);
+ void AddEvaluationFile(const std::string& inputName,
+ const std::string& outputExpr,
+ const std::string& condition, bool inputIsContent);
};
-
#endif
diff --git a/Source/cmFileLock.cxx b/Source/cmFileLock.cxx
new file mode 100644
index 000000000..786d6c63f
--- /dev/null
+++ b/Source/cmFileLock.cxx
@@ -0,0 +1,60 @@
+/* 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 "cmFileLockResult.h"
+#include <assert.h>
+
+// Common implementation
+
+cmFileLock::~cmFileLock()
+{
+ if (!this->Filename.empty()) {
+ const cmFileLockResult result = this->Release();
+ static_cast<void>(result);
+ assert(result.IsOk());
+ }
+}
+
+cmFileLockResult cmFileLock::Lock(const std::string& filename,
+ unsigned long timeout)
+{
+ if (filename.empty()) {
+ // Error is internal since all the directories and file must be created
+ // before actual lock called.
+ return cmFileLockResult::MakeInternal();
+ }
+
+ if (!this->Filename.empty()) {
+ // Error is internal since double-lock must be checked in class
+ // cmFileLockPool by the cmFileLock::IsLocked method.
+ return cmFileLockResult::MakeInternal();
+ }
+
+ this->Filename = filename;
+ cmFileLockResult result = this->OpenFile();
+ if (result.IsOk()) {
+ if (timeout == static_cast<unsigned long>(-1)) {
+ result = this->LockWithoutTimeout();
+ } else {
+ result = this->LockWithTimeout(timeout);
+ }
+ }
+
+ if (!result.IsOk()) {
+ this->Filename = "";
+ }
+
+ return result;
+}
+
+bool cmFileLock::IsLocked(const std::string& filename) const
+{
+ return filename == this->Filename;
+}
+
+#if defined(_WIN32)
+#include "cmFileLockWin32.cxx"
+#else
+#include "cmFileLockUnix.cxx"
+#endif
diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h
new file mode 100644
index 000000000..ccef50816
--- /dev/null
+++ b/Source/cmFileLock.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 cmFileLock_h
+#define cmFileLock_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#if defined(_WIN32)
+#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.
+ */
+class cmFileLock
+{
+ CM_DISABLE_COPY(cmFileLock)
+
+public:
+ cmFileLock();
+ ~cmFileLock();
+
+ /**
+ * @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.
+ */
+ cmFileLockResult Release();
+
+ /**
+ * @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:
+ cmFileLockResult OpenFile();
+ cmFileLockResult LockWithoutTimeout();
+ cmFileLockResult LockWithTimeout(unsigned long timeoutSec);
+
+#if defined(_WIN32)
+ typedef HANDLE FileId;
+ BOOL LockFile(DWORD flags);
+#else
+ typedef int FileId;
+ int LockFile(int cmd, int type);
+#endif
+
+ FileId File;
+ std::string Filename;
+};
+
+#endif // cmFileLock_h
diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx
new file mode 100644
index 000000000..7b1564c34
--- /dev/null
+++ b/Source/cmFileLockPool.cxx
@@ -0,0 +1,158 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileLockPool.h"
+
+#include <assert.h>
+
+#include "cmAlgorithms.h"
+#include "cmFileLock.h"
+#include "cmFileLockResult.h"
+
+cmFileLockPool::cmFileLockPool()
+{
+}
+
+cmFileLockPool::~cmFileLockPool()
+{
+ cmDeleteAll(this->FunctionScopes);
+ cmDeleteAll(this->FileScopes);
+}
+
+void cmFileLockPool::PushFunctionScope()
+{
+ this->FunctionScopes.push_back(new ScopePool());
+}
+
+void cmFileLockPool::PopFunctionScope()
+{
+ assert(!this->FunctionScopes.empty());
+ delete this->FunctionScopes.back();
+ this->FunctionScopes.pop_back();
+}
+
+void cmFileLockPool::PushFileScope()
+{
+ this->FileScopes.push_back(new ScopePool());
+}
+
+void cmFileLockPool::PopFileScope()
+{
+ assert(!this->FileScopes.empty());
+ delete this->FileScopes.back();
+ this->FileScopes.pop_back();
+}
+
+cmFileLockResult cmFileLockPool::LockFunctionScope(const std::string& filename,
+ unsigned long timeoutSec)
+{
+ if (this->IsAlreadyLocked(filename)) {
+ return cmFileLockResult::MakeAlreadyLocked();
+ }
+ if (this->FunctionScopes.empty()) {
+ return cmFileLockResult::MakeNoFunction();
+ }
+ return this->FunctionScopes.back()->Lock(filename, timeoutSec);
+}
+
+cmFileLockResult cmFileLockPool::LockFileScope(const std::string& filename,
+ unsigned long timeoutSec)
+{
+ if (this->IsAlreadyLocked(filename)) {
+ return cmFileLockResult::MakeAlreadyLocked();
+ }
+ assert(!this->FileScopes.empty());
+ return this->FileScopes.back()->Lock(filename, timeoutSec);
+}
+
+cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename,
+ unsigned long timeoutSec)
+{
+ if (this->IsAlreadyLocked(filename)) {
+ return cmFileLockResult::MakeAlreadyLocked();
+ }
+ return this->ProcessScope.Lock(filename, timeoutSec);
+}
+
+cmFileLockResult cmFileLockPool::Release(const std::string& filename)
+{
+ for (It i = this->FunctionScopes.begin(); i != this->FunctionScopes.end();
+ ++i) {
+ const cmFileLockResult result = (*i)->Release(filename);
+ if (!result.IsOk()) {
+ return result;
+ }
+ }
+
+ for (It i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) {
+ const cmFileLockResult result = (*i)->Release(filename);
+ if (!result.IsOk()) {
+ return result;
+ }
+ }
+
+ return this->ProcessScope.Release(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);
+ if (result) {
+ return true;
+ }
+ }
+
+ for (CIt i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) {
+ const bool result = (*i)->IsAlreadyLocked(filename);
+ if (result) {
+ return true;
+ }
+ }
+
+ return this->ProcessScope.IsAlreadyLocked(filename);
+}
+
+cmFileLockPool::ScopePool::ScopePool()
+{
+}
+
+cmFileLockPool::ScopePool::~ScopePool()
+{
+ cmDeleteAll(this->Locks);
+}
+
+cmFileLockResult cmFileLockPool::ScopePool::Lock(const std::string& filename,
+ unsigned long timeoutSec)
+{
+ cmFileLock* lock = new cmFileLock();
+ const cmFileLockResult result = lock->Lock(filename, timeoutSec);
+ if (result.IsOk()) {
+ this->Locks.push_back(lock);
+ return cmFileLockResult::MakeOk();
+ }
+ delete lock;
+ return result;
+}
+
+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();
+ }
+ }
+ return cmFileLockResult::MakeOk();
+}
+
+bool cmFileLockPool::ScopePool::IsAlreadyLocked(
+ const std::string& filename) const
+{
+ for (CIt i = this->Locks.begin(); i != this->Locks.end(); ++i) {
+ if ((*i)->IsLocked(filename)) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h
new file mode 100644
index 000000000..c96a8c2f8
--- /dev/null
+++ b/Source/cmFileLockPool.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 cmFileLockPool_h
+#define cmFileLockPool_h
+
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
+class cmFileLock;
+class cmFileLockResult;
+
+class cmFileLockPool
+{
+ CM_DISABLE_COPY(cmFileLockPool)
+
+public:
+ cmFileLockPool();
+ ~cmFileLockPool();
+
+ //@{
+ /**
+ * @brief Function scope control.
+ */
+ void PushFunctionScope();
+ void PopFunctionScope();
+ //@}
+
+ //@{
+ /**
+ * @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.
+ */
+ cmFileLockResult LockFunctionScope(const std::string& filename,
+ unsigned long timeoutSec);
+ cmFileLockResult LockFileScope(const std::string& filename,
+ unsigned long timeoutSec);
+ cmFileLockResult LockProcessScope(const std::string& filename,
+ unsigned long timeoutSec);
+ //@}
+
+ /**
+ * @brief Unlock the file explicitly.
+ */
+ cmFileLockResult Release(const std::string& filename);
+
+private:
+ bool IsAlreadyLocked(const std::string& filename) const;
+
+ class ScopePool
+ {
+ CM_DISABLE_COPY(ScopePool)
+
+ public:
+ ScopePool();
+ ~ScopePool();
+
+ 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;
+
+ List Locks;
+ };
+
+ typedef std::vector<ScopePool*> List;
+
+ typedef List::iterator It;
+ typedef List::const_iterator CIt;
+
+ List FunctionScopes;
+ List FileScopes;
+ ScopePool ProcessScope;
+};
+
+#endif // cmFileLockPool_h
diff --git a/Source/cmFileLockResult.cxx b/Source/cmFileLockResult.cxx
new file mode 100644
index 000000000..a040705e8
--- /dev/null
+++ b/Source/cmFileLockResult.cxx
@@ -0,0 +1,92 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileLockResult.h"
+
+#include <errno.h>
+#include <string.h>
+
+cmFileLockResult cmFileLockResult::MakeOk()
+{
+ return cmFileLockResult(OK, 0);
+}
+
+cmFileLockResult cmFileLockResult::MakeSystem()
+{
+#if defined(_WIN32)
+ const Error lastError = GetLastError();
+#else
+ const Error lastError = errno;
+#endif
+ return cmFileLockResult(SYSTEM, lastError);
+}
+
+cmFileLockResult cmFileLockResult::MakeTimeout()
+{
+ return cmFileLockResult(TIMEOUT, 0);
+}
+
+cmFileLockResult cmFileLockResult::MakeAlreadyLocked()
+{
+ return cmFileLockResult(ALREADY_LOCKED, 0);
+}
+
+cmFileLockResult cmFileLockResult::MakeInternal()
+{
+ return cmFileLockResult(INTERNAL, 0);
+}
+
+cmFileLockResult cmFileLockResult::MakeNoFunction()
+{
+ return cmFileLockResult(NO_FUNCTION, 0);
+}
+
+bool cmFileLockResult::IsOk() const
+{
+ return this->Type == OK;
+}
+
+std::string cmFileLockResult::GetOutputMessage() const
+{
+ switch (this->Type) {
+ case OK:
+ return "0";
+ 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);
+ return message;
+ } else {
+ return "Internal error (FormatMessageA failed)";
+ }
+ }
+#else
+ return strerror(this->ErrorValue);
+#endif
+ case TIMEOUT:
+ return "Timeout reached";
+ case ALREADY_LOCKED:
+ return "File already locked";
+ case NO_FUNCTION:
+ return "'GUARD FUNCTION' not used in function definition";
+ case INTERNAL:
+ default:
+ return "Internal error";
+ }
+}
+
+cmFileLockResult::cmFileLockResult(ErrorType typeValue, Error errorValue)
+ : Type(typeValue)
+ , ErrorValue(errorValue)
+{
+}
diff --git a/Source/cmFileLockResult.h b/Source/cmFileLockResult.h
new file mode 100644
index 000000000..4cedc0ae6
--- /dev/null
+++ b/Source/cmFileLockResult.h
@@ -0,0 +1,77 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileLockResult_h
+#define cmFileLockResult_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+#if defined(_WIN32)
+#include <windows.h> // DWORD
+#endif
+
+/**
+ * @brief Result of the locking/unlocking file.
+ * @note See @c cmFileLock
+ */
+class cmFileLockResult
+{
+public:
+#if defined(_WIN32)
+ typedef DWORD Error;
+#else
+ typedef int Error;
+#endif
+
+ /**
+ * @brief Successful lock/unlock.
+ */
+ static cmFileLockResult MakeOk();
+
+ /**
+ * @brief Lock/Unlock failed. Read error/GetLastError.
+ */
+ static cmFileLockResult MakeSystem();
+
+ /**
+ * @brief Lock/Unlock failed. Timeout reached.
+ */
+ static cmFileLockResult MakeTimeout();
+
+ /**
+ * @brief File already locked.
+ */
+ static cmFileLockResult MakeAlreadyLocked();
+
+ /**
+ * @brief Internal error.
+ */
+ static cmFileLockResult MakeInternal();
+
+ /**
+ * @brief Try to lock with function guard outside of the function
+ */
+ static cmFileLockResult MakeNoFunction();
+
+ bool IsOk() const;
+ std::string GetOutputMessage() const;
+
+private:
+ enum ErrorType
+ {
+ OK,
+ SYSTEM,
+ TIMEOUT,
+ ALREADY_LOCKED,
+ INTERNAL,
+ NO_FUNCTION
+ };
+
+ cmFileLockResult(ErrorType type, Error errorValue);
+
+ ErrorType Type;
+ Error ErrorValue;
+};
+
+#endif // cmFileLockResult_h
diff --git a/Source/cmFileLockUnix.cxx b/Source/cmFileLockUnix.cxx
new file mode 100644
index 000000000..7353b01fc
--- /dev/null
+++ b/Source/cmFileLockUnix.cxx
@@ -0,0 +1,78 @@
+/* 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 "cmSystemTools.h"
+#include <errno.h> // errno
+#include <fcntl.h>
+#include <stdio.h> // SEEK_SET
+#include <unistd.h>
+
+cmFileLock::cmFileLock()
+ : File(-1)
+{
+}
+
+cmFileLockResult cmFileLock::Release()
+{
+ if (this->Filename.empty()) {
+ return cmFileLockResult::MakeOk();
+ }
+ const int lockResult = this->LockFile(F_SETLK, F_UNLCK);
+
+ this->Filename = "";
+
+ ::close(this->File);
+ this->File = -1;
+
+ if (lockResult == 0) {
+ return cmFileLockResult::MakeOk();
+ }
+ return cmFileLockResult::MakeSystem();
+}
+
+cmFileLockResult cmFileLock::OpenFile()
+{
+ this->File = ::open(this->Filename.c_str(), O_RDWR);
+ if (this->File == -1) {
+ return cmFileLockResult::MakeSystem();
+ }
+ return cmFileLockResult::MakeOk();
+}
+
+cmFileLockResult cmFileLock::LockWithoutTimeout()
+{
+ if (this->LockFile(F_SETLKW, F_WRLCK) == -1) {
+ return cmFileLockResult::MakeSystem();
+ }
+ return cmFileLockResult::MakeOk();
+}
+
+cmFileLockResult cmFileLock::LockWithTimeout(unsigned long seconds)
+{
+ while (true) {
+ if (this->LockFile(F_SETLK, F_WRLCK) == -1) {
+ if (errno != EACCES && errno != EAGAIN) {
+ return cmFileLockResult::MakeSystem();
+ }
+ } else {
+ return cmFileLockResult::MakeOk();
+ }
+ if (seconds == 0) {
+ return cmFileLockResult::MakeTimeout();
+ }
+ --seconds;
+ cmSystemTools::Delay(1000);
+ }
+}
+
+int cmFileLock::LockFile(int cmd, int type)
+{
+ struct ::flock lock;
+ lock.l_start = 0;
+ lock.l_len = 0; // lock all bytes
+ lock.l_pid = 0; // unused (for F_GETLK only)
+ lock.l_type = static_cast<short>(type); // exclusive lock
+ lock.l_whence = SEEK_SET;
+ return ::fcntl(this->File, cmd, &lock);
+}
diff --git a/Source/cmFileLockWin32.cxx b/Source/cmFileLockWin32.cxx
new file mode 100644
index 000000000..51ac24993
--- /dev/null
+++ b/Source/cmFileLockWin32.cxx
@@ -0,0 +1,88 @@
+/* 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 "cmSystemTools.h"
+#include <windows.h> // CreateFileW
+
+cmFileLock::cmFileLock()
+ : File(INVALID_HANDLE_VALUE)
+{
+}
+
+cmFileLockResult cmFileLock::Release()
+{
+ if (this->Filename.empty()) {
+ return cmFileLockResult::MakeOk();
+ }
+ const unsigned long len = static_cast<unsigned long>(-1);
+ static OVERLAPPED overlapped;
+ const DWORD reserved = 0;
+ const BOOL unlockResult =
+ UnlockFileEx(File, reserved, len, len, &overlapped);
+
+ this->Filename = "";
+
+ CloseHandle(this->File);
+ this->File = INVALID_HANDLE_VALUE;
+
+ if (unlockResult) {
+ return cmFileLockResult::MakeOk();
+ } else {
+ return cmFileLockResult::MakeSystem();
+ }
+}
+
+cmFileLockResult cmFileLock::OpenFile()
+{
+ const DWORD access = GENERIC_READ | GENERIC_WRITE;
+ const DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ const PSECURITY_ATTRIBUTES security = NULL;
+ const DWORD attr = 0;
+ const HANDLE templ = NULL;
+ this->File = CreateFileW(
+ cmSystemTools::ConvertToWindowsExtendedPath(this->Filename).c_str(),
+ access, shareMode, security, OPEN_EXISTING, attr, templ);
+ if (this->File == INVALID_HANDLE_VALUE) {
+ return cmFileLockResult::MakeSystem();
+ } else {
+ return cmFileLockResult::MakeOk();
+ }
+}
+
+cmFileLockResult cmFileLock::LockWithoutTimeout()
+{
+ if (!this->LockFile(LOCKFILE_EXCLUSIVE_LOCK)) {
+ return cmFileLockResult::MakeSystem();
+ } else {
+ return cmFileLockResult::MakeOk();
+ }
+}
+
+cmFileLockResult cmFileLock::LockWithTimeout(unsigned long seconds)
+{
+ const DWORD flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
+ while (true) {
+ const BOOL result = this->LockFile(flags);
+ if (result) {
+ return cmFileLockResult::MakeOk();
+ }
+ const DWORD error = GetLastError();
+ if (error != ERROR_LOCK_VIOLATION) {
+ return cmFileLockResult::MakeSystem();
+ }
+ if (seconds == 0) {
+ return cmFileLockResult::MakeTimeout();
+ }
+ --seconds;
+ cmSystemTools::Delay(1000);
+ }
+}
+
+BOOL cmFileLock::LockFile(DWORD flags)
+{
+ const DWORD reserved = 0;
+ const unsigned long len = static_cast<unsigned long>(-1);
+ static OVERLAPPED overlapped;
+ return LockFileEx(this->File, flags, reserved, len, len, &overlapped);
+}
diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx
new file mode 100644
index 000000000..80275357c
--- /dev/null
+++ b/Source/cmFileMonitor.cxx
@@ -0,0 +1,389 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 <unordered_map>
+#include <utility>
+
+namespace {
+void on_directory_change(uv_fs_event_t* handle, const char* filename,
+ int events, int status);
+void on_fs_close(uv_handle_t* handle);
+} // namespace
+
+class cmIBaseWatcher
+{
+public:
+ cmIBaseWatcher() = default;
+ virtual ~cmIBaseWatcher() = default;
+
+ virtual void Trigger(const std::string& pathSegment, int events,
+ int status) const = 0;
+ virtual std::string Path() const = 0;
+ virtual uv_loop_t* Loop() const = 0;
+
+ virtual void StartWatching() = 0;
+ virtual void StopWatching() = 0;
+
+ virtual std::vector<std::string> WatchedFiles() const = 0;
+ virtual std::vector<std::string> WatchedDirectories() const = 0;
+};
+
+class cmVirtualDirectoryWatcher : public cmIBaseWatcher
+{
+public:
+ ~cmVirtualDirectoryWatcher() override { cmDeleteAll(this->Children); }
+
+ cmIBaseWatcher* Find(const std::string& ps)
+ {
+ const auto i = this->Children.find(ps);
+ return (i == this->Children.end()) ? nullptr : i->second;
+ }
+
+ void Trigger(const std::string& pathSegment, int events,
+ int status) const final
+ {
+ if (pathSegment.empty()) {
+ for (const auto& i : this->Children) {
+ i.second->Trigger(std::string(), events, status);
+ }
+ } else {
+ const auto i = this->Children.find(pathSegment);
+ if (i != this->Children.end()) {
+ i->second->Trigger(std::string(), events, status);
+ }
+ }
+ }
+
+ void StartWatching() override
+ {
+ for (const auto& i : this->Children) {
+ i.second->StartWatching();
+ }
+ }
+
+ void StopWatching() override
+ {
+ for (const auto& i : this->Children) {
+ i.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);
+ }
+ }
+ return result;
+ }
+
+ 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);
+ }
+ }
+ return result;
+ }
+
+ void Reset()
+ {
+ cmDeleteAll(this->Children);
+ this->Children.clear();
+ }
+
+ void AddChildWatcher(const std::string& ps, cmIBaseWatcher* watcher)
+ {
+ assert(!ps.empty());
+ assert(this->Children.find(ps) == this->Children.end());
+ assert(watcher);
+
+ this->Children.emplace(std::make_pair(ps, watcher));
+ }
+
+private:
+ std::unordered_map<std::string, cmIBaseWatcher*> Children; // owned!
+};
+
+// Root of all the different (on windows!) root directories:
+class cmRootWatcher : public cmVirtualDirectoryWatcher
+{
+public:
+ cmRootWatcher(uv_loop_t* loop)
+ : mLoop(loop)
+ {
+ assert(loop);
+ }
+
+ std::string Path() const final
+ {
+ assert(false);
+ return std::string();
+ }
+ uv_loop_t* Loop() const final { return this->mLoop; }
+
+private:
+ uv_loop_t* const mLoop; // no ownership!
+};
+
+// Real directories:
+class cmRealDirectoryWatcher : public cmVirtualDirectoryWatcher
+{
+public:
+ cmRealDirectoryWatcher(cmVirtualDirectoryWatcher* p, const std::string& ps)
+ : Parent(p)
+ , PathSegment(ps)
+ {
+ assert(p);
+ assert(!ps.empty());
+
+ p->AddChildWatcher(ps, this);
+ }
+
+ ~cmRealDirectoryWatcher() override
+ {
+ // Handle is freed via uv_handle_close callback!
+ }
+
+ void StartWatching() final
+ {
+ if (!this->Handle) {
+ this->Handle = new uv_fs_event_t;
+
+ uv_fs_event_init(this->Loop(), this->Handle);
+ this->Handle->data = this;
+ uv_fs_event_start(this->Handle, &on_directory_change, Path().c_str(), 0);
+ }
+ cmVirtualDirectoryWatcher::StartWatching();
+ }
+
+ void StopWatching() final
+ {
+ if (this->Handle) {
+ uv_fs_event_stop(this->Handle);
+ uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
+ this->Handle = nullptr;
+ }
+ cmVirtualDirectoryWatcher::StopWatching();
+ }
+
+ uv_loop_t* Loop() const final { return this->Parent->Loop(); }
+
+ std::vector<std::string> WatchedDirectories() const override
+ {
+ std::vector<std::string> result = { Path() };
+ for (const auto& j : cmVirtualDirectoryWatcher::WatchedDirectories()) {
+ result.push_back(j);
+ }
+ return result;
+ }
+
+protected:
+ cmVirtualDirectoryWatcher* const Parent;
+ const std::string PathSegment;
+
+private:
+ uv_fs_event_t* Handle = nullptr; // owner!
+};
+
+// Root directories:
+class cmRootDirectoryWatcher : public cmRealDirectoryWatcher
+{
+public:
+ cmRootDirectoryWatcher(cmRootWatcher* p, const std::string& ps)
+ : cmRealDirectoryWatcher(p, ps)
+ {
+ }
+
+ std::string Path() const final { return this->PathSegment; }
+};
+
+// Normal directories below root:
+class cmDirectoryWatcher : public cmRealDirectoryWatcher
+{
+public:
+ cmDirectoryWatcher(cmRealDirectoryWatcher* p, const std::string& ps)
+ : cmRealDirectoryWatcher(p, ps)
+ {
+ }
+
+ std::string Path() const final
+ {
+ return this->Parent->Path() + this->PathSegment + "/";
+ }
+};
+
+class cmFileWatcher : public cmIBaseWatcher
+{
+public:
+ cmFileWatcher(cmRealDirectoryWatcher* p, const std::string& ps,
+ cmFileMonitor::Callback cb)
+ : Parent(p)
+ , PathSegment(ps)
+ , CbList({ std::move(cb) })
+ {
+ assert(p);
+ assert(!ps.empty());
+ p->AddChildWatcher(ps, this);
+ }
+
+ void StartWatching() final {}
+
+ void StopWatching() final {}
+
+ void AppendCallback(cmFileMonitor::Callback const& cb)
+ {
+ this->CbList.push_back(cb);
+ }
+
+ std::string Path() const final
+ {
+ return this->Parent->Path() + this->PathSegment;
+ }
+
+ std::vector<std::string> WatchedDirectories() const final { return {}; }
+
+ std::vector<std::string> WatchedFiles() const final
+ {
+ return { this->Path() };
+ }
+
+ void Trigger(const std::string& ps, int events, int status) const final
+ {
+ assert(ps.empty());
+ assert(status == 0);
+ static_cast<void>(ps);
+
+ const std::string path = this->Path();
+ for (const auto& cb : this->CbList) {
+ cb(path, events, status);
+ }
+ }
+
+ uv_loop_t* Loop() const final { return this->Parent->Loop(); }
+
+private:
+ cmRealDirectoryWatcher* Parent;
+ const std::string PathSegment;
+ std::vector<cmFileMonitor::Callback> CbList;
+};
+
+namespace {
+
+void on_directory_change(uv_fs_event_t* handle, const char* filename,
+ int events, int status)
+{
+ const cmIBaseWatcher* const watcher =
+ static_cast<const cmIBaseWatcher*>(handle->data);
+ const std::string pathSegment(filename ? filename : "");
+ watcher->Trigger(pathSegment, events, status);
+}
+
+void on_fs_close(uv_handle_t* handle)
+{
+ delete reinterpret_cast<uv_fs_event_t*>(handle);
+}
+
+} // namespace
+
+cmFileMonitor::cmFileMonitor(uv_loop_t* l)
+ : Root(new cmRootWatcher(l))
+{
+}
+
+cmFileMonitor::~cmFileMonitor()
+{
+ delete this->Root;
+}
+
+void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths,
+ Callback const& cb)
+{
+ for (const auto& p : paths) {
+ std::vector<std::string> pathSegments;
+ cmsys::SystemTools::SplitPath(p, pathSegments, true);
+
+ const size_t segmentCount = pathSegments.size();
+ if (segmentCount < 2) { // Expect at least rootdir and filename
+ continue;
+ }
+ cmVirtualDirectoryWatcher* currentWatcher = this->Root;
+ for (size_t i = 0; i < segmentCount; ++i) {
+ assert(currentWatcher);
+
+ const bool fileSegment = (i == segmentCount - 1);
+ const bool rootSegment = (i == 0);
+ assert(
+ !(fileSegment &&
+ rootSegment)); // Can not be both filename and root part of the path!
+
+ const std::string& currentSegment = pathSegments[i];
+ if (currentSegment.empty()) {
+ continue;
+ }
+
+ cmIBaseWatcher* nextWatcher = currentWatcher->Find(currentSegment);
+ if (!nextWatcher) {
+ if (rootSegment) { // Root part
+ assert(currentWatcher == this->Root);
+ nextWatcher = new cmRootDirectoryWatcher(this->Root, currentSegment);
+ assert(currentWatcher->Find(currentSegment) == nextWatcher);
+ } else if (fileSegment) { // File part
+ assert(currentWatcher != this->Root);
+ nextWatcher = new cmFileWatcher(
+ dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
+ currentSegment, cb);
+ assert(currentWatcher->Find(currentSegment) == nextWatcher);
+ } else { // Any normal directory in between
+ nextWatcher = new cmDirectoryWatcher(
+ dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
+ currentSegment);
+ assert(currentWatcher->Find(currentSegment) == nextWatcher);
+ }
+ } else {
+ if (fileSegment) {
+ auto filePtr = dynamic_cast<cmFileWatcher*>(nextWatcher);
+ assert(filePtr);
+ filePtr->AppendCallback(cb);
+ continue;
+ }
+ }
+ currentWatcher = dynamic_cast<cmVirtualDirectoryWatcher*>(nextWatcher);
+ }
+ }
+ this->Root->StartWatching();
+}
+
+void cmFileMonitor::StopMonitoring()
+{
+ this->Root->StopWatching();
+ this->Root->Reset();
+}
+
+std::vector<std::string> cmFileMonitor::WatchedFiles() const
+{
+ std::vector<std::string> result;
+ if (this->Root) {
+ result = this->Root->WatchedFiles();
+ }
+ return result;
+}
+
+std::vector<std::string> cmFileMonitor::WatchedDirectories() const
+{
+ std::vector<std::string> result;
+ if (this->Root) {
+ result = this->Root->WatchedDirectories();
+ }
+ return result;
+}
diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h
new file mode 100644
index 000000000..d7ec92a17
--- /dev/null
+++ b/Source/cmFileMonitor.h
@@ -0,0 +1,32 @@
+/* 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"
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include "cm_uv.h"
+
+class cmRootWatcher;
+
+class cmFileMonitor
+{
+ CM_DISABLE_COPY(cmFileMonitor)
+
+public:
+ cmFileMonitor(uv_loop_t* l);
+ ~cmFileMonitor();
+
+ using Callback = std::function<void(const std::string&, int, int)>;
+ void MonitorPaths(const std::vector<std::string>& paths, Callback const& cb);
+ void StopMonitoring();
+
+ std::vector<std::string> WatchedFiles() const;
+ std::vector<std::string> WatchedDirectories() const;
+
+private:
+ cmRootWatcher* Root;
+};
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
new file mode 100644
index 000000000..62f52e590
--- /dev/null
+++ b/Source/cmFilePathChecksum.cxx
@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFilePathChecksum.h"
+
+#include "cmBase32.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include <vector>
+
+cmFilePathChecksum::cmFilePathChecksum()
+{
+}
+
+cmFilePathChecksum::cmFilePathChecksum(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir)
+{
+ setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
+}
+
+cmFilePathChecksum::cmFilePathChecksum(cmMakefile* makefile)
+{
+ setupParentDirs(makefile->GetCurrentSourceDirectory(),
+ makefile->GetCurrentBinaryDirectory(),
+ makefile->GetHomeDirectory(),
+ makefile->GetHomeOutputDirectory());
+}
+
+void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& 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);
+
+ parentDirs[0].second = "CurrentSource";
+ parentDirs[1].second = "CurrentBinary";
+ parentDirs[2].second = "ProjectSource";
+ parentDirs[3].second = "ProjectBinary";
+}
+
+std::string cmFilePathChecksum::get(const std::string& filePath) const
+{
+ std::string relPath;
+ std::string relSeed;
+ {
+ const std::string fileReal = cmsys::SystemTools::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;
+ break;
+ }
+ }
+ // Use file system root as fallback parent directory
+ if (parentDir.empty()) {
+ relSeed = "FileSystemRoot";
+ cmsys::SystemTools::SplitPathRootComponent(fileReal, &parentDir);
+ }
+ // Calculate relative path from project parent directory
+ relPath = cmsys::SystemTools::RelativePath(
+ parentDir, cmsys::SystemTools::GetParentDirectory(fileReal));
+ }
+
+ // Calculate the file ( seed + relative path ) binary checksum
+ std::vector<unsigned char> hashBytes =
+ cmCryptoHash(cmCryptoHash::AlgoSHA256).ByteHashString(relSeed + relPath);
+
+ // Convert binary checksum to string
+ return cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(),
+ false);
+}
+
+std::string cmFilePathChecksum::getPart(const std::string& filePath,
+ size_t length) const
+{
+ return get(filePath).substr(0, length);
+}
diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h
new file mode 100644
index 000000000..9d570eb4d
--- /dev/null
+++ b/Source/cmFilePathChecksum.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 cmFilePathChecksum_h
+#define cmFilePathChecksum_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stddef.h>
+#include <string>
+#include <utility>
+
+class cmMakefile;
+
+/** \class cmFilePathChecksum
+ * @brief Generates a checksum for the parent directory of a file
+ *
+ * The checksum is calculated from the relative file path to the
+ * closest known project directory. This guarantees reproducibility
+ * when source and build directory differ e.g. for different project
+ * build directories.
+ */
+class cmFilePathChecksum
+{
+public:
+ /// Maximum number of characters to use from the path checksum
+ static const size_t partLengthDefault = 10;
+
+ /// @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 Initilizes 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);
+
+ /* @brief Calculates the path checksum for the parent directory of a file
+ *
+ */
+ std::string get(const std::string& filePath) const;
+
+ /* @brief Same as get() but returns only the first length characters
+ *
+ */
+ std::string getPart(const std::string& 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];
+};
+
+#endif
diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx
index 3167be496..f591a8dc7 100644
--- a/Source/cmFileTimeComparison.cxx
+++ b/Source/cmFileTimeComparison.cxx
@@ -1,32 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileTimeComparison.h"
-// Use a hash table to avoid duplicate file time checks from disk.
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <cmsys/hash_map.hxx>
-#endif
+#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__)
-# define cmFileTimeComparison_Type struct stat
-# include <ctype.h>
-# include <sys/stat.h>
+#include "cm_sys_stat.h"
+#define cmFileTimeComparison_Type struct stat
#else
-# define cmFileTimeComparison_Type FILETIME
-# include <windows.h>
+#include "cmsys/Encoding.hxx"
+#include <windows.h>
+#define cmFileTimeComparison_Type FILETIME
#endif
-//----------------------------------------------------------------------------
class cmFileTimeComparisonInternal
{
public:
@@ -36,21 +27,9 @@ public:
bool FileTimesDiffer(const char* f1, const char* f2);
private:
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- // Use a hash table to efficiently map from file name to modification time.
- class HashString
- {
- public:
- size_t operator()(const cmStdString& s) const
- {
- return h(s.c_str());
- }
- cmsys::hash<const char*> h;
- };
- typedef cmsys::hash_map<cmStdString,
- cmFileTimeComparison_Type, HashString> FileStatsMap;
+ typedef CM_UNORDERED_MAP<std::string, cmFileTimeComparison_Type>
+ FileStatsMap;
FileStatsMap Files;
-#endif
// Internal methods to lookup and compare modification times.
inline bool Stat(const char* fname, cmFileTimeComparison_Type* st);
@@ -60,108 +39,99 @@ private:
cmFileTimeComparison_Type* st2);
};
-//----------------------------------------------------------------------------
bool cmFileTimeComparisonInternal::Stat(const char* fname,
cmFileTimeComparison_Type* st)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
// Use the stored time if available.
cmFileTimeComparisonInternal::FileStatsMap::iterator fit =
this->Files.find(fname);
- if ( fit != this->Files.end() )
- {
+ if (fit != this->Files.end()) {
*st = fit->second;
return true;
- }
-#endif
+ }
#if !defined(_WIN32) || defined(__CYGWIN__)
// POSIX version. Use the stat function.
int res = ::stat(fname, st);
- if ( res != 0 )
- {
+ if (res != 0) {
return false;
- }
+ }
#else
// Windows version. Get the modification time from extended file
// attributes.
WIN32_FILE_ATTRIBUTE_DATA fdata;
- if(!GetFileAttributesEx(fname, GetFileExInfoStandard, &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
-#if defined(CMAKE_BUILD_WITH_CMAKE)
// Store the time for future use.
this->Files[fname] = *st;
-#endif
-
return true;
}
-//----------------------------------------------------------------------------
cmFileTimeComparison::cmFileTimeComparison()
{
this->Internals = new cmFileTimeComparisonInternal;
}
-//----------------------------------------------------------------------------
cmFileTimeComparison::~cmFileTimeComparison()
{
delete this->Internals;
}
-//----------------------------------------------------------------------------
-bool cmFileTimeComparison::FileTimeCompare(const char* f1,
- const char* f2, int* result)
+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 cmsys_STAT_HAS_ST_MTIM
+#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_mtim.tv_sec < s2->st_mtim.tv_sec)
- {
+ if (s1->st_mtimespec.tv_sec < s2->st_mtimespec.tv_sec) {
return -1;
- }
- else if(s1->st_mtim.tv_sec > s2->st_mtim.tv_sec)
- {
+ } else if (s1->st_mtimespec.tv_sec > s2->st_mtimespec.tv_sec) {
return 1;
- }
- else if(s1->st_mtim.tv_nsec < s2->st_mtim.tv_nsec)
- {
+ } else if (s1->st_mtimespec.tv_nsec < s2->st_mtimespec.tv_nsec) {
return -1;
- }
- else if(s1->st_mtim.tv_nsec > s2->st_mtim.tv_nsec)
- {
+ } else if (s1->st_mtimespec.tv_nsec > s2->st_mtimespec.tv_nsec) {
return 1;
- }
-# else
+ }
+#else
// Compare using 1 second resolution.
- if(s1->st_mtime < s2->st_mtime)
- {
+ if (s1->st_mtime < s2->st_mtime) {
return -1;
- }
- else if(s1->st_mtime > s2->st_mtime)
- {
+ } else if (s1->st_mtime > s2->st_mtime) {
return 1;
- }
-# endif
+ }
+#endif
// Files have the same time.
return 0;
#else
@@ -170,43 +140,44 @@ int cmFileTimeComparisonInternal::Compare(cmFileTimeComparison_Type* s1,
#endif
}
-//----------------------------------------------------------------------------
bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1,
cmFileTimeComparison_Type* s2)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
-# if cmsys_STAT_HAS_ST_MTIM
+#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)
- {
+ 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)
- {
+ } else if (t2 < t1) {
return (t1 - t2) >= bil;
- }
- else
- {
+ } else {
return false;
- }
-# else
+ }
+#else
// Times are integers in units of 1s.
- if(s1->st_mtime < s2->st_mtime)
- {
+ if (s1->st_mtime < s2->st_mtime) {
return (s2->st_mtime - s1->st_mtime) >= 1;
- }
- else if(s1->st_mtime > s2->st_mtime)
- {
+ } else if (s1->st_mtime > s2->st_mtime) {
return (s1->st_mtime - s2->st_mtime) >= 1;
- }
- else
- {
+ } else {
return false;
- }
-# endif
+ }
+#endif
#else
// Times are integers in units of 100ns.
LARGE_INTEGER t1;
@@ -215,60 +186,42 @@ bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1,
t1.HighPart = s1->dwHighDateTime;
t2.LowPart = s2->dwLowDateTime;
t2.HighPart = s2->dwHighDateTime;
- if(t1.QuadPart < t2.QuadPart)
- {
+ if (t1.QuadPart < t2.QuadPart) {
return (t2.QuadPart - t1.QuadPart) >= static_cast<LONGLONG>(10000000);
- }
- else if(t2.QuadPart < t1.QuadPart)
- {
+ } else if (t2.QuadPart < t1.QuadPart) {
return (t1.QuadPart - t2.QuadPart) >= static_cast<LONGLONG>(10000000);
- }
- else
- {
+ } else {
return false;
- }
+ }
#endif
}
-//----------------------------------------------------------------------------
bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1,
- const char* f2,
- int* result)
+ 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))
- {
+ if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) {
// Compare the two modification times.
*result = this->Compare(&s1, &s2);
return true;
- }
- else
- {
- // No comparison available. Default to the same time.
- *result = 0;
- return false;
- }
+ }
+ // 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))
- {
+ if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) {
// Compare the two modification times.
return this->TimesDiffer(&s1, &s2);
- }
- else
- {
- // No comparison available. Default to different times.
- return true;
- }
+ }
+ // No comparison available. Default to different times.
+ return true;
}
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
index cc1ef633d..b1f8ed636 100644
--- a/Source/cmFileTimeComparison.h
+++ b/Source/cmFileTimeComparison.h
@@ -1,18 +1,9 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
class cmFileTimeComparisonInternal;
@@ -42,10 +33,7 @@ public:
bool FileTimesDiffer(const char* f1, const char* f2);
protected:
-
cmFileTimeComparisonInternal* Internals;
};
-
#endif
-
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 7ce003216..10c6fe46f 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -1,15 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFindBase.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
+#include <deque>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <stddef.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmFindBase.h"
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmSearchPath.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
cmFindBase::cmFindBase()
{
@@ -19,169 +24,52 @@ cmFindBase::cmFindBase()
this->NamesPerDirAllowed = false;
}
-//----------------------------------------------------------------------------
-void cmFindBase::GenerateDocumentation()
-{
- this->cmFindCommon::GenerateDocumentation();
- cmSystemTools::ReplaceString(this->GenericDocumentationPathsOrder,
- "FIND_ARGS_XXX", "<VAR> NAMES name");
- this->GenericDocumentation =
- " FIND_XXX(<VAR> name1 [path1 path2 ...])\n"
- "This is the short-hand signature for the command that "
- "is sufficient in many cases. It is the same "
- "as FIND_XXX(<VAR> name1 [PATHS path1 path2 ...])\n"
- " FIND_XXX(\n"
- " <VAR>\n"
- " name | NAMES name1 [name2 ...]\n"
- " [HINTS path1 [path2 ... ENV var]]\n"
- " [PATHS path1 [path2 ... ENV var]]\n"
- " [PATH_SUFFIXES suffix1 [suffix2 ...]]\n"
- " [DOC \"cache documentation string\"]\n"
- " [NO_DEFAULT_PATH]\n"
- " [NO_CMAKE_ENVIRONMENT_PATH]\n"
- " [NO_CMAKE_PATH]\n"
- " [NO_SYSTEM_ENVIRONMENT_PATH]\n"
- " [NO_CMAKE_SYSTEM_PATH]\n"
- " [CMAKE_FIND_ROOT_PATH_BOTH |\n"
- " ONLY_CMAKE_FIND_ROOT_PATH |\n"
- " NO_CMAKE_FIND_ROOT_PATH]\n"
- " )\n"
- ""
- "This command is used to find a SEARCH_XXX_DESC. "
- "A cache entry named by <VAR> is created to store the result "
- "of this command. "
- "If the SEARCH_XXX is found the result is stored in the variable "
- "and the search will not be repeated unless the variable is cleared. "
- "If nothing is found, the result will be "
- "<VAR>-NOTFOUND, and the search will be attempted again the "
- "next time FIND_XXX is invoked with the same variable. "
- "The name of the SEARCH_XXX that "
- "is searched for is specified by the names listed "
- "after the NAMES argument. Additional search locations "
- "can be specified after the PATHS argument. If ENV var is "
- "found in the HINTS or PATHS section the environment variable var "
- "will be read and converted from a system environment variable to "
- "a cmake style list of paths. For example ENV PATH would be a way "
- "to list the system path variable. The argument "
- "after DOC will be used for the documentation string in "
- "the cache. "
- "PATH_SUFFIXES specifies additional subdirectories to check below "
- "each search path."
- "\n"
- "If NO_DEFAULT_PATH is specified, then no additional paths are "
- "added to the search. "
- "If NO_DEFAULT_PATH is not specified, the search process is as follows:\n"
- "1. Search paths specified in cmake-specific cache variables. "
- "These are intended to be used on the command line with a -DVAR=value. "
- "This can be skipped if NO_CMAKE_PATH is passed.\n"
- "XXX_EXTRA_PREFIX_ENTRY"
- " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
- " CMAKE_XXX_PATH\n"
- " CMAKE_XXX_MAC_PATH\n"
- "2. Search paths specified in cmake-specific environment variables. "
- "These are intended to be set in the user's shell configuration. "
- "This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n"
- "XXX_EXTRA_PREFIX_ENTRY"
- " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
- " CMAKE_XXX_PATH\n"
- " CMAKE_XXX_MAC_PATH\n"
- "3. Search the paths specified by the HINTS option. "
- "These should be paths computed by system introspection, such as a "
- "hint provided by the location of another item already found. "
- "Hard-coded guesses should be specified with the PATHS option.\n"
- "4. Search the standard system environment variables. "
- "This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is an argument.\n"
- " PATH\n"
- " XXX_SYSTEM\n" // replace with "", LIB, or INCLUDE
- "5. Search cmake variables defined in the Platform files "
- "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH "
- "is passed.\n"
- "XXX_EXTRA_PREFIX_ENTRY"
- " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n"
- " CMAKE_SYSTEM_XXX_PATH\n"
- " CMAKE_SYSTEM_XXX_MAC_PATH\n"
- "6. Search the paths specified by the PATHS option "
- "or in the short-hand version of the command. "
- "These are typically hard-coded guesses.\n"
- ;
- this->GenericDocumentation += this->GenericDocumentationMacPolicy;
- this->GenericDocumentation += this->GenericDocumentationRootPath;
- this->GenericDocumentation += this->GenericDocumentationPathsOrder;
-}
-
-//----------------------------------------------------------------------------
-const char* cmFindBase::GetFullDocumentation() const
-{
- if(this->GenericDocumentation.empty())
- {
- const_cast<cmFindBase *>(this)->GenerateDocumentation();
- }
- return this->GenericDocumentation.c_str();
-}
-
-//----------------------------------------------------------------------------
bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
{
- if(argsIn.size() < 2 )
- {
+ if (argsIn.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
-
- // CMake versions below 2.3 did not search all these extra
- // locations. Preserve compatibility unless a modern argument is
- // passed.
- bool compatibility = this->Makefile->NeedBackwardsCompatibility(2,3);
+ }
// copy argsIn into args so it can be modified,
// in the process extract the DOC "documentation"
size_t size = argsIn.size();
std::vector<std::string> args;
bool foundDoc = false;
- for(unsigned int j = 0; j < size; ++j)
- {
- if(foundDoc || argsIn[j] != "DOC" )
- {
- if(argsIn[j] == "ENV")
- {
- if(j+1 < size)
- {
+ for (unsigned int j = 0; j < size; ++j) {
+ if (foundDoc || argsIn[j] != "DOC") {
+ if (argsIn[j] == "ENV") {
+ if (j + 1 < size) {
j++;
cmSystemTools::GetPath(args, argsIn[j].c_str());
- }
}
- else
- {
+ } else {
args.push_back(argsIn[j]);
- }
}
- else
- {
- if(j+1 < size)
- {
+ } else {
+ if (j + 1 < size) {
foundDoc = true;
- this->VariableDocumentation = argsIn[j+1];
+ this->VariableDocumentation = argsIn[j + 1];
j++;
- if(j >= size)
- {
+ if (j >= size) {
break;
- }
}
}
}
- if(args.size() < 2 )
- {
+ }
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
this->VariableName = args[0];
- if(this->CheckForVariableInCache())
- {
+ if (this->CheckForVariableInCache()) {
this->AlreadyInCache = true;
return true;
- }
+ }
this->AlreadyInCache = false;
+ this->SelectDefaultNoPackageRootPath();
+
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -189,131 +77,83 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->SelectDefaultMacMode();
bool newStyle = false;
- enum Doing { DoingNone, DoingNames, DoingPaths, DoingPathSuffixes,
- DoingHints };
+ enum Doing
+ {
+ DoingNone,
+ DoingNames,
+ DoingPaths,
+ DoingPathSuffixes,
+ DoingHints
+ };
Doing doing = DoingNames; // assume it starts with a name
- for (unsigned int j = 1; j < args.size(); ++j)
- {
- if(args[j] == "NAMES")
- {
+ for (unsigned int j = 1; j < args.size(); ++j) {
+ if (args[j] == "NAMES") {
doing = DoingNames;
newStyle = true;
- }
- else if (args[j] == "PATHS")
- {
+ } else if (args[j] == "PATHS") {
doing = DoingPaths;
newStyle = true;
- }
- else if (args[j] == "HINTS")
- {
+ } else if (args[j] == "HINTS") {
doing = DoingHints;
newStyle = true;
- }
- else if (args[j] == "PATH_SUFFIXES")
- {
+ } else if (args[j] == "PATH_SUFFIXES") {
doing = DoingPathSuffixes;
- compatibility = false;
newStyle = true;
- }
- else if (args[j] == "NAMES_PER_DIR")
- {
+ } else if (args[j] == "NAMES_PER_DIR") {
doing = DoingNone;
- if(this->NamesPerDirAllowed)
- {
+ if (this->NamesPerDirAllowed) {
this->NamesPerDir = true;
- }
- else
- {
+ } else {
this->SetError("does not support NAMES_PER_DIR");
return false;
- }
}
- else if (args[j] == "NO_SYSTEM_PATH")
- {
+ } else if (args[j] == "NO_SYSTEM_PATH") {
doing = DoingNone;
this->NoDefaultPath = true;
- }
- else if (this->CheckCommonArgument(args[j]))
- {
+ } else if (this->CheckCommonArgument(args[j])) {
doing = DoingNone;
- compatibility = false;
// Some common arguments were accidentally supported by CMake
// 2.4 and 2.6.0 in the short-hand form of the command, so we
// must support it even though it is not documented.
- }
- else if(doing == DoingNames)
- {
+ } else if (doing == DoingNames) {
this->Names.push_back(args[j]);
- }
- else if(doing == DoingPaths)
- {
- this->AddUserPath(args[j], this->UserPaths);
- }
- else if(doing == DoingHints)
- {
- this->AddUserPath(args[j], this->UserHints);
- }
- else if(doing == DoingPathSuffixes)
- {
+ } else if (doing == DoingPaths) {
+ this->UserGuessArgs.push_back(args[j]);
+ } else if (doing == DoingHints) {
+ this->UserHintsArgs.push_back(args[j]);
+ } else if (doing == DoingPathSuffixes) {
this->AddPathSuffix(args[j]);
- }
}
+ }
- // Now that arguments have been parsed check the compatibility
- // setting. If we need to be compatible with CMake 2.2 and earlier
- // do not add the CMake system paths. It is safe to add the CMake
- // environment paths and system environment paths because that
- // existed in 2.2. It is safe to add the CMake user variable paths
- // because the user or project has explicitly set them.
- if(compatibility)
- {
- this->NoCMakeSystemPath = true;
- }
-
- if(this->VariableDocumentation.size() == 0)
- {
+ if (this->VariableDocumentation.empty()) {
this->VariableDocumentation = "Where can ";
- if(this->Names.size() == 0)
- {
+ if (this->Names.empty()) {
this->VariableDocumentation += "the (unknown) library be found";
- }
- else if(this->Names.size() == 1)
- {
- this->VariableDocumentation += "the "
- + this->Names[0] + " library be found";
- }
- else
- {
- this->VariableDocumentation += "one of the " + this->Names[0];
- for (unsigned int j = 1; j < this->Names.size() - 1; ++j)
- {
- this->VariableDocumentation += ", " + this->Names[j];
- }
- this->VariableDocumentation += " or "
- + this->Names[this->Names.size() - 1] + " libraries be found";
- }
+ } else if (this->Names.size() == 1) {
+ this->VariableDocumentation +=
+ "the " + this->Names[0] + " 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";
}
+ }
// look for old style
// FIND_*(VAR name path1 path2 ...)
- if(!newStyle)
- {
+ if (!newStyle) {
// 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]);
- for(unsigned int j = 1; j < shortArgs.size(); ++j)
- {
- this->AddUserPath(shortArgs[j], this->UserPaths);
- }
- }
+ this->UserGuessArgs.insert(this->UserGuessArgs.end(),
+ shortArgs.begin() + 1, shortArgs.end());
+ }
this->ExpandPaths();
- // Filter out ignored paths from the prefix list
- std::set<std::string> ignored;
- this->GetIgnoredPaths(ignored);
- this->FilterPaths(this->SearchPaths, ignored);
-
this->ComputeFinalPaths();
return true;
@@ -321,224 +161,144 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
void cmFindBase::ExpandPaths()
{
- this->AddCMakeVariablePath();
- this->AddCMakeEnvironmentPath();
- this->AddUserHintsPath();
- this->AddSystemEnvironmentPath();
- this->AddCMakeSystemVariablePath();
- this->AddUserGuessPath();
-
- // Add suffixes and clean up paths.
- this->AddPathSuffixes();
-}
-
-//----------------------------------------------------------------------------
-void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
- PathType pathType)
-{
- // default for programs
- std::string subdir = "bin";
-
- if (this->CMakePathName == "INCLUDE")
- {
- subdir = "include";
+ if (!this->NoDefaultPath) {
+ if (!this->NoPackageRootPath) {
+ this->FillPackageRootPath();
}
- else if (this->CMakePathName == "LIBRARY")
- {
- subdir = "lib";
+ if (!this->NoCMakePath) {
+ this->FillCMakeVariablePath();
}
- else if (this->CMakePathName == "FRAMEWORK")
- {
- subdir = ""; // ? what to do for frameworks ?
+ if (!this->NoCMakeEnvironmentPath) {
+ this->FillCMakeEnvironmentPath();
}
-
- for(std::vector<std::string>::const_iterator it = in_paths.begin();
- it != in_paths.end(); ++it)
- {
- std::string dir = it->c_str();
- if(!subdir.empty() && !dir.empty() && dir[dir.size()-1] != '/')
- {
- dir += "/";
- }
- if(subdir == "include" || subdir == "lib")
- {
- const char* arch =
- this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
- if(arch && *arch)
- {
- this->AddPathInternal(dir+subdir+"/"+arch, pathType);
- }
- }
- std::string add = dir + subdir;
- if(add != "/")
- {
- this->AddPathInternal(add, pathType);
- }
- if (subdir == "bin")
- {
- this->AddPathInternal(dir+"sbin", pathType);
- }
- if(!subdir.empty() && *it != "/")
- {
- this->AddPathInternal(*it, pathType);
- }
+ }
+ this->FillUserHintsPath();
+ if (!this->NoDefaultPath) {
+ if (!this->NoSystemEnvironmentPath) {
+ this->FillSystemEnvironmentPath();
}
-}
-
-//----------------------------------------------------------------------------
-void cmFindBase::AddCMakePrefixPath(const char* variable)
-{
- // Get a path from a CMake variable.
- if(const char* varPath = this->Makefile->GetDefinition(variable))
- {
- std::vector<std::string> tmp;
- cmSystemTools::ExpandListArgument(varPath, tmp);
- this->AddPrefixPaths(tmp, CMakePath);
+ if (!this->NoCMakeSystemPath) {
+ this->FillCMakeSystemVariablePath();
}
+ }
+ this->FillUserGuessPath();
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddEnvPrefixPath(const char* variable)
+void cmFindBase::FillCMakeEnvironmentPath()
{
- // Get a path from the environment.
- std::vector<std::string> tmp;
- cmSystemTools::GetPath(tmp, variable);
- this->AddPrefixPaths(tmp, EnvPath);
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
+
+ // Add CMAKE_*_PATH environment variables
+ std::string var = "CMAKE_";
+ var += this->CMakePathName;
+ var += "_PATH";
+ paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH");
+ paths.AddEnvPath(var);
+
+ if (this->CMakePathName == "PROGRAM") {
+ paths.AddEnvPath("CMAKE_APPBUNDLE_PATH");
+ } else {
+ paths.AddEnvPath("CMAKE_FRAMEWORK_PATH");
+ }
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddCMakeEnvironmentPath()
+void cmFindBase::FillPackageRootPath()
{
- if(!this->NoCMakeEnvironmentPath && !this->NoDefaultPath)
- {
- // Add CMAKE_*_PATH environment variables
- std::string var = "CMAKE_";
- var += this->CMakePathName;
- var += "_PATH";
- this->AddEnvPrefixPath("CMAKE_PREFIX_PATH");
- this->AddEnvPath(var.c_str());
-
- if(this->CMakePathName == "PROGRAM")
- {
- this->AddEnvPath("CMAKE_APPBUNDLE_PATH");
- }
- else
- {
- this->AddEnvPath("CMAKE_FRAMEWORK_PATH");
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void cmFindBase::AddCMakeVariablePath()
-{
- if(!this->NoCMakePath && !this->NoDefaultPath)
- {
- // Add CMake varibles of the same name as the previous environment
- // varibles CMAKE_*_PATH to be used most of the time with -D
- // command line options
- std::string var = "CMAKE_";
- var += this->CMakePathName;
- var += "_PATH";
- this->AddCMakePrefixPath("CMAKE_PREFIX_PATH");
- this->AddCMakePath(var.c_str());
-
- if(this->CMakePathName == "PROGRAM")
- {
- this->AddCMakePath("CMAKE_APPBUNDLE_PATH");
- }
- else
- {
- this->AddCMakePath("CMAKE_FRAMEWORK_PATH");
- }
- }
+ 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);
+ }
+
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddSystemEnvironmentPath()
+void cmFindBase::FillCMakeVariablePath()
{
- if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
- {
- // Add LIB or INCLUDE
- if(!this->EnvironmentPath.empty())
- {
- this->AddEnvPath(this->EnvironmentPath.c_str());
- }
- // Add PATH
- this->AddEnvPath(0);
- }
+ 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
+ // command line options
+ std::string var = "CMAKE_";
+ var += this->CMakePathName;
+ var += "_PATH";
+ paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH");
+ paths.AddCMakePath(var);
+
+ if (this->CMakePathName == "PROGRAM") {
+ paths.AddCMakePath("CMAKE_APPBUNDLE_PATH");
+ } else {
+ paths.AddCMakePath("CMAKE_FRAMEWORK_PATH");
+ }
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddCMakeSystemVariablePath()
+void cmFindBase::FillSystemEnvironmentPath()
{
- if(!this->NoCMakeSystemPath && !this->NoDefaultPath)
- {
- std::string var = "CMAKE_SYSTEM_";
- var += this->CMakePathName;
- var += "_PATH";
- this->AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
- this->AddCMakePath(var.c_str());
-
- if(this->CMakePathName == "PROGRAM")
- {
- this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
- }
- else
- {
- this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
- }
- }
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemEnvironment];
+
+ // Add LIB or INCLUDE
+ if (!this->EnvironmentPath.empty()) {
+ paths.AddEnvPath(this->EnvironmentPath);
+#if defined(_WIN32) || defined(__CYGWIN__)
+ paths.AddEnvPrefixPath("PATH", true);
+#endif
+ }
+ // Add PATH
+ paths.AddEnvPath("PATH");
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddUserHintsPath()
+void cmFindBase::FillCMakeSystemVariablePath()
{
- this->AddPathsInternal(this->UserHints, CMakePath);
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
+
+ std::string var = "CMAKE_SYSTEM_";
+ var += this->CMakePathName;
+ var += "_PATH";
+ paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
+ paths.AddCMakePath(var);
+
+ if (this->CMakePathName == "PROGRAM") {
+ paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
+ } else {
+ paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
+ }
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddUserGuessPath()
+void cmFindBase::FillUserHintsPath()
{
- this->AddPathsInternal(this->UserPaths, CMakePath);
+ 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);
+ }
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
-//----------------------------------------------------------------------------
-void cmFindBase::AddPathSuffixes()
+void cmFindBase::FillUserGuessPath()
{
- std::vector<std::string>& paths = this->SearchPaths;
- std::vector<std::string> finalPath = paths;
- std::vector<std::string>::iterator i;
- // clear the path
- paths.clear();
- // convert all paths to unix slashes and add search path suffixes
- // if there are any
- for(i = finalPath.begin();
- i != finalPath.end(); ++i)
- {
- cmSystemTools::ConvertToUnixSlashes(*i);
- // copy each finalPath combined with SearchPathSuffixes
- // to the SearchPaths ivar
- for(std::vector<std::string>::iterator j =
- this->SearchPathSuffixes.begin();
- j != this->SearchPathSuffixes.end(); ++j)
- {
- // 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 = *i;
- if(p.size() && p[p.size()-1] != '/')
- {
- p += std::string("/");
- }
- p += *j;
- // add to all paths because the search path may be modified
- // later with lib being replaced for lib64 which may exist
- paths.push_back(p);
- }
- // now put the path without the path suffixes in the SearchPaths
- paths.push_back(*i);
- }
+ 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);
+ }
+ paths.AddSuffixes(this->SearchPathSuffixes);
}
void cmFindBase::PrintFindStuff()
@@ -550,64 +310,49 @@ void cmFindBase::PrintFindStuff()
std::cerr << "SearchAppBundleOnly: " << this->SearchAppBundleOnly << "\n";
std::cerr << "SearchAppBundleFirst: " << this->SearchAppBundleFirst << "\n";
std::cerr << "VariableName " << this->VariableName << "\n";
- std::cerr << "VariableDocumentation "
- << this->VariableDocumentation << "\n";
+ std::cerr << "VariableDocumentation " << this->VariableDocumentation << "\n";
std::cerr << "NoDefaultPath " << this->NoDefaultPath << "\n";
- std::cerr << "NoCMakeEnvironmentPath "
- << this->NoCMakeEnvironmentPath << "\n";
+ std::cerr << "NoCMakeEnvironmentPath " << this->NoCMakeEnvironmentPath
+ << "\n";
std::cerr << "NoCMakePath " << this->NoCMakePath << "\n";
- std::cerr << "NoSystemEnvironmentPath "
- << this->NoSystemEnvironmentPath << "\n";
+ std::cerr << "NoSystemEnvironmentPath " << this->NoSystemEnvironmentPath
+ << "\n";
std::cerr << "NoCMakeSystemPath " << this->NoCMakeSystemPath << "\n";
std::cerr << "EnvironmentPath " << this->EnvironmentPath << "\n";
std::cerr << "CMakePathName " << this->CMakePathName << "\n";
- std::cerr << "Names ";
- for(unsigned int i =0; i < this->Names.size(); ++i)
- {
- std::cerr << this->Names[i] << " ";
- }
- std::cerr << "\n";
+ std::cerr << "Names " << cmJoin(this->Names, " ") << "\n";
std::cerr << "\n";
std::cerr << "SearchPathSuffixes ";
- for(unsigned int i =0; i < this->SearchPathSuffixes.size(); ++i)
- {
- std::cerr << this->SearchPathSuffixes[i] << "\n";
- }
- std::cerr << "\n";
+ std::cerr << cmJoin(this->SearchPathSuffixes, "\n") << "\n";
std::cerr << "SearchPaths\n";
- for(unsigned int i =0; i < this->SearchPaths.size(); ++i)
- {
- std::cerr << "[" << this->SearchPaths[i] << "]\n";
- }
+ std::cerr << cmWrap("[", this->SearchPaths, "]", "\n") << "\n";
}
bool cmFindBase::CheckForVariableInCache()
{
- if(const char* cacheValue =
- this->Makefile->GetDefinition(this->VariableName.c_str()))
- {
- cmCacheManager::CacheIterator it =
- this->Makefile->GetCacheManager()->
- GetCacheIterator(this->VariableName.c_str());
+ if (const char* cacheValue =
+ this->Makefile->GetDefinition(this->VariableName)) {
+ cmState* state = this->Makefile->GetState();
+ const char* cacheEntry = state->GetCacheEntryValue(this->VariableName);
bool found = !cmSystemTools::IsNOTFOUND(cacheValue);
- bool cached = !it.IsAtEnd();
- if(found)
- {
+ bool cached = cacheEntry != CM_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
// original value. Tell the subclass implementations to do
// this.
- if(cached && it.GetType() == cmCacheManager::UNINITIALIZED)
- {
+ if (cached &&
+ state->GetCacheEntryType(this->VariableName) ==
+ cmStateEnums::UNINITIALIZED) {
this->AlreadyInCacheWithoutMetaInfo = true;
- }
- return true;
- }
- else if(cached)
- {
- const char* hs = it.GetProperty("HELPSTRING");
- this->VariableDocumentation = hs?hs:"(none)";
}
+ return true;
+ }
+ if (cached) {
+ const char* hs =
+ state->GetCacheEntryProperty(this->VariableName, "HELPSTRING");
+ this->VariableDocumentation = hs ? hs : "(none)";
}
+ }
return false;
}
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index 84b03300c..88b5b6c18 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -1,17 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindBase_h
#define cmFindBase_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
#include "cmFindCommon.h"
/** \class cmFindBase
@@ -29,50 +25,38 @@ public:
* the CMakeLists.txt file.
*/
virtual bool ParseArguments(std::vector<std::string> const& args);
- cmTypeMacro(cmFindBase, cmFindCommon);
-
- virtual const char* GetFullDocumentation() const;
protected:
- virtual void GenerateDocumentation();
void PrintFindStuff();
void ExpandPaths();
- void AddPathSuffixes();
// see if the VariableName is already set in the cache,
// also copy the documentation from the cache to VariableDocumentation
// if it has documentation in the cache
bool CheckForVariableInCache();
- cmStdString GenericDocumentation;
// use by command during find
- cmStdString VariableDocumentation;
- cmStdString VariableName;
+ std::string VariableDocumentation;
+ std::string VariableName;
std::vector<std::string> Names;
bool NamesPerDir;
bool NamesPerDirAllowed;
// CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM
- cmStdString EnvironmentPath; // LIB,INCLUDE
+ std::string EnvironmentPath; // LIB,INCLUDE
bool AlreadyInCache;
bool AlreadyInCacheWithoutMetaInfo;
+
private:
// Add pieces of the search.
- void AddCMakeEnvironmentPath();
- void AddCMakeVariablePath();
- void AddSystemEnvironmentPath();
- void AddCMakeSystemVariablePath();
- void AddUserHintsPath();
- void AddUserGuessPath();
-
- // Helpers.
- void AddCMakePrefixPath(const char* variable);
- void AddEnvPrefixPath(const char* variable);
- void AddPrefixPaths(std::vector<std::string> const& in_paths,
- PathType pathType);
+ void FillPackageRootPath();
+ void FillCMakeVariablePath();
+ void FillCMakeEnvironmentPath();
+ void FillUserHintsPath();
+ void FillSystemEnvironmentPath();
+ void FillCMakeSystemVariablePath();
+ void FillUserGuessPath();
};
-
-
#endif
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index b44864e13..4ef0f3ec1 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -1,28 +1,38 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindCommon.h"
-//----------------------------------------------------------------------------
+#include <algorithm>
+#include <string.h>
+#include <utility>
+
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::PackageRoot(
+ "PackageName_ROOT");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::CMake("CMAKE");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeEnvironment(
+ "CMAKE_ENVIRONMENT");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::Hints("HINTS");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::SystemEnvironment(
+ "SYSTM_ENVIRONMENT");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeSystem("CMAKE_SYSTEM");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::Guess("GUESS");
+
cmFindCommon::cmFindCommon()
{
this->FindRootPathMode = RootPathModeBoth;
this->NoDefaultPath = false;
+ this->NoPackageRootPath = false;
this->NoCMakePath = false;
this->NoCMakeEnvironmentPath = false;
this->NoSystemEnvironmentPath = false;
this->NoCMakeSystemPath = false;
- // OS X Bundle and Framework search policy. The default is to
- // search frameworks first on apple.
+// OS X Bundle and Framework search policy. The default is to
+// search frameworks first on apple.
#if defined(__APPLE__)
this->SearchFrameworkFirst = true;
this->SearchAppBundleFirst = true;
@@ -34,144 +44,114 @@ cmFindCommon::cmFindCommon()
this->SearchFrameworkLast = false;
this->SearchAppBundleOnly = false;
this->SearchAppBundleLast = false;
+
+ this->InitializeSearchPathGroups();
}
-//----------------------------------------------------------------------------
-void cmFindCommon::GenerateDocumentation()
+cmFindCommon::~cmFindCommon()
{
- // Documentation components.
- this->GenericDocumentationMacPolicy =
- "On Darwin or systems supporting OS X Frameworks, the cmake variable"
- " CMAKE_FIND_FRAMEWORK can be set to empty or one of the following:\n"
- " \"FIRST\" - Try to find frameworks before standard\n"
- " libraries or headers. This is the default on Darwin.\n"
- " \"LAST\" - Try to find frameworks after standard\n"
- " libraries or headers.\n"
- " \"ONLY\" - Only try to find frameworks.\n"
- " \"NEVER\" - Never try to find frameworks.\n"
- "On Darwin or systems supporting OS X Application Bundles, the cmake "
- "variable CMAKE_FIND_APPBUNDLE can be set to empty or one of the "
- "following:\n"
- " \"FIRST\" - Try to find application bundles before standard\n"
- " programs. This is the default on Darwin.\n"
- " \"LAST\" - Try to find application bundles after standard\n"
- " programs.\n"
- " \"ONLY\" - Only try to find application bundles.\n"
- " \"NEVER\" - Never try to find application bundles.\n";
- this->GenericDocumentationRootPath =
- "The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more "
- "directories to be prepended to all other search directories. "
- "This effectively \"re-roots\" the entire search under given locations. "
- "By default it is empty. It is especially useful when "
- "cross-compiling to point to the root directory of the "
- "target environment and CMake will search there too. By default at first "
- "the directories listed in CMAKE_FIND_ROOT_PATH and then the non-rooted "
- "directories will be searched. "
- "The default behavior can be adjusted by setting "
- "CMAKE_FIND_ROOT_PATH_MODE_XXX. This behavior can be manually "
- "overridden on a per-call basis. "
- "By using CMAKE_FIND_ROOT_PATH_BOTH the search order will "
- "be as described above. If NO_CMAKE_FIND_ROOT_PATH is used "
- "then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH "
- "is used then only the re-rooted directories will be searched.\n";
- this->GenericDocumentationPathsOrder =
- "The default search order is designed to be most-specific to "
- "least-specific for common use cases. "
- "Projects may override the order by simply calling the command "
- "multiple times and using the NO_* options:\n"
- " FIND_XXX(FIND_ARGS_XXX PATHS paths... NO_DEFAULT_PATH)\n"
- " FIND_XXX(FIND_ARGS_XXX)\n"
- "Once one of the calls succeeds the result variable will be set "
- "and stored in the cache so that no call will search again.";
}
-//----------------------------------------------------------------------------
-cmFindCommon::~cmFindCommon()
+void cmFindCommon::InitializeSearchPathGroups()
{
+ std::vector<PathLabel>* labels;
+
+ // Define the varoius different groups of path types
+
+ // All search paths
+ labels = &this->PathGroupLabelMap[PathGroup::All];
+ labels->push_back(PathLabel::PackageRoot);
+ labels->push_back(PathLabel::CMake);
+ labels->push_back(PathLabel::CMakeEnvironment);
+ labels->push_back(PathLabel::Hints);
+ labels->push_back(PathLabel::SystemEnvironment);
+ labels->push_back(PathLabel::CMakeSystem);
+ labels->push_back(PathLabel::Guess);
+
+ // Define the search group order
+ this->PathGroupOrder.push_back(PathGroup::All);
+
+ // Create the idividual labeld search paths
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::PackageRoot, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::CMake, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::CMakeEnvironment, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::Hints, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::SystemEnvironment, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::CMakeSystem, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::Guess, cmSearchPath(this)));
}
-//----------------------------------------------------------------------------
-void cmFindCommon::SelectDefaultRootPathMode()
+void cmFindCommon::SelectDefaultNoPackageRootPath()
{
- // Use both by default.
- this->FindRootPathMode = RootPathModeBoth;
+ 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 rootPathMode =
- this->Makefile->GetSafeDefinition(findRootPathVar.c_str());
- if (rootPathMode=="NEVER")
- {
- this->FindRootPathMode = RootPathModeNoRootPath;
- }
- else if (rootPathMode=="ONLY")
- {
- this->FindRootPathMode = RootPathModeOnlyRootPath;
- }
- else if (rootPathMode=="BOTH")
- {
+ this->Makefile->GetSafeDefinition(findRootPathVar);
+ if (rootPathMode == "NEVER") {
+ this->FindRootPathMode = RootPathModeNever;
+ } else if (rootPathMode == "ONLY") {
+ this->FindRootPathMode = RootPathModeOnly;
+ } else if (rootPathMode == "BOTH") {
this->FindRootPathMode = RootPathModeBoth;
- }
+ }
}
-//----------------------------------------------------------------------------
void cmFindCommon::SelectDefaultMacMode()
{
std::string ff = this->Makefile->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
- if(ff == "NEVER")
- {
+ if (ff == "NEVER") {
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = false;
- }
- else if(ff == "ONLY")
- {
+ } else if (ff == "ONLY") {
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = true;
- }
- else if(ff == "FIRST")
- {
+ } else if (ff == "FIRST") {
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = true;
this->SearchFrameworkOnly = false;
- }
- else if(ff == "LAST")
- {
+ } else if (ff == "LAST") {
this->SearchFrameworkLast = true;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = false;
- }
+ }
std::string fab = this->Makefile->GetSafeDefinition("CMAKE_FIND_APPBUNDLE");
- if(fab == "NEVER")
- {
+ if (fab == "NEVER") {
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = false;
- }
- else if(fab == "ONLY")
- {
+ } else if (fab == "ONLY") {
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = true;
- }
- else if(fab == "FIRST")
- {
+ } else if (fab == "FIRST") {
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = true;
this->SearchAppBundleOnly = false;
- }
- else if(fab == "LAST")
- {
+ } else if (fab == "LAST") {
this->SearchAppBundleLast = true;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = false;
- }
+ }
}
-//----------------------------------------------------------------------------
void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
{
#if 0
@@ -181,117 +161,106 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
fprintf(stderr, "[%s]\n", i->c_str());
}
#endif
-
// Short-circuit if there is nothing to do.
- if(this->FindRootPathMode == RootPathModeNoRootPath)
- {
+ if (this->FindRootPathMode == RootPathModeNever) {
return;
- }
- const char* rootPath =
- this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
- if((rootPath == 0) || (strlen(rootPath) == 0))
- {
+ }
+
+ const char* sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
+ const char* sysrootCompile =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE");
+ const char* sysrootLink =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK");
+ const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
+ const bool noSysroot = !sysroot || !*sysroot;
+ const bool noCompileSysroot = !sysrootCompile || !*sysrootCompile;
+ const bool noLinkSysroot = !sysrootLink || !*sysrootLink;
+ const bool noRootPath = !rootPath || !*rootPath;
+ if (noSysroot && noCompileSysroot && noLinkSysroot && noRootPath) {
return;
- }
+ }
// Construct the list of path roots with no trailing slashes.
std::vector<std::string> roots;
- cmSystemTools::ExpandListArgument(rootPath, roots);
- for(std::vector<std::string>::iterator ri = roots.begin();
- ri != roots.end(); ++ri)
- {
+ if (rootPath) {
+ cmSystemTools::ExpandListArgument(rootPath, roots);
+ }
+ if (sysrootCompile) {
+ roots.push_back(sysrootCompile);
+ }
+ if (sysrootLink) {
+ roots.push_back(sysrootLink);
+ }
+ if (sysroot) {
+ roots.push_back(sysroot);
+ }
+ for (std::vector<std::string>::iterator ri = roots.begin();
+ ri != roots.end(); ++ri) {
cmSystemTools::ConvertToUnixSlashes(*ri);
- }
+ }
+
+ const char* stagePrefix =
+ this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
// Copy the original set of unrooted 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::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) {
// 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->c_str(), ri->c_str()))
- {
+ if (cmSystemTools::IsSubDirectory(*ui, *ri) ||
+ (stagePrefix && cmSystemTools::IsSubDirectory(*ui, stagePrefix))) {
rootedDir = *ui;
- }
- else if(!ui->empty() && (*ui)[0] != '~')
- {
+ } else if (!ui->empty() && (*ui)[0] != '~') {
// Start with the new root.
rootedDir = *ri;
rootedDir += "/";
// Append the original path with its old root removed.
- rootedDir += cmSystemTools::SplitPathRootComponent(ui->c_str());
- }
+ rootedDir += cmSystemTools::SplitPathRootComponent(*ui);
+ }
// Store the new path.
paths.push_back(rootedDir);
- }
}
+ }
// If searching both rooted and unrooted paths add the original
// paths again.
- if(this->FindRootPathMode == RootPathModeBoth)
- {
+ if (this->FindRootPathMode == RootPathModeBoth) {
paths.insert(paths.end(), unrootedPaths.begin(), unrootedPaths.end());
- }
-}
-
-//----------------------------------------------------------------------------
-void cmFindCommon::FilterPaths(std::vector<std::string>& paths,
- const std::set<std::string>& ignore)
-{
- // Now filter out anything that's in the ignore set.
- std::vector<std::string> unfiltered;
- unfiltered.swap(paths);
-
- for(std::vector<std::string>::iterator pi = unfiltered.begin();
- pi != unfiltered.end(); ++pi)
- {
- if (ignore.count(*pi) == 0)
- {
- paths.push_back(*pi);
- }
- }
+ }
}
-
-//----------------------------------------------------------------------------
void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
{
// null-terminated list of paths.
- static const char *paths[] =
- { "CMAKE_SYSTEM_IGNORE_PATH", "CMAKE_IGNORE_PATH", 0 };
+ static const char* paths[] = { "CMAKE_SYSTEM_IGNORE_PATH",
+ "CMAKE_IGNORE_PATH", CM_NULLPTR };
// Construct the list of path roots with no trailing slashes.
- for(const char **pathName = paths; *pathName; ++pathName)
- {
+ 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 == 0) || (strlen(ignorePath) == 0))
- {
+ if ((ignorePath == CM_NULLPTR) || (strlen(ignorePath) == 0)) {
continue;
- }
+ }
cmSystemTools::ExpandListArgument(ignorePath, ignore);
- }
+ }
- for(std::vector<std::string>::iterator i = ignore.begin();
- i != ignore.end(); ++i)
- {
+ for (std::vector<std::string>::iterator i = ignore.begin();
+ i != ignore.end(); ++i) {
cmSystemTools::ConvertToUnixSlashes(*i);
- }
+ }
}
-
-//----------------------------------------------------------------------------
void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
{
std::vector<std::string> ignoreVec;
@@ -299,207 +268,84 @@ void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
ignore.insert(ignoreVec.begin(), ignoreVec.end());
}
-
-
-//----------------------------------------------------------------------------
bool cmFindCommon::CheckCommonArgument(std::string const& arg)
{
- if(arg == "NO_DEFAULT_PATH")
- {
+ if (arg == "NO_DEFAULT_PATH") {
this->NoDefaultPath = true;
- }
- else if(arg == "NO_CMAKE_ENVIRONMENT_PATH")
- {
- this->NoCMakeEnvironmentPath = true;
- }
- else if(arg == "NO_CMAKE_PATH")
- {
+ } else if (arg == "NO_PACKAGE_ROOT_PATH") {
+ this->NoPackageRootPath = true;
+ } else if (arg == "NO_CMAKE_PATH") {
this->NoCMakePath = true;
- }
- else if(arg == "NO_SYSTEM_ENVIRONMENT_PATH")
- {
+ } else if (arg == "NO_CMAKE_ENVIRONMENT_PATH") {
+ this->NoCMakeEnvironmentPath = true;
+ } else if (arg == "NO_SYSTEM_ENVIRONMENT_PATH") {
this->NoSystemEnvironmentPath = true;
- }
- else if(arg == "NO_CMAKE_SYSTEM_PATH")
- {
+ } else if (arg == "NO_CMAKE_SYSTEM_PATH") {
this->NoCMakeSystemPath = true;
- }
- else if(arg == "NO_CMAKE_FIND_ROOT_PATH")
- {
- this->FindRootPathMode = RootPathModeNoRootPath;
- }
- else if(arg == "ONLY_CMAKE_FIND_ROOT_PATH")
- {
- this->FindRootPathMode = RootPathModeOnlyRootPath;
- }
- else if(arg == "CMAKE_FIND_ROOT_PATH_BOTH")
- {
+ } else if (arg == "NO_CMAKE_FIND_ROOT_PATH") {
+ this->FindRootPathMode = RootPathModeNever;
+ } else if (arg == "ONLY_CMAKE_FIND_ROOT_PATH") {
+ this->FindRootPathMode = RootPathModeOnly;
+ } else if (arg == "CMAKE_FIND_ROOT_PATH_BOTH") {
this->FindRootPathMode = RootPathModeBoth;
- }
- else
- {
+ } else {
// The argument is not one of the above.
return false;
- }
+ }
// The argument is one of the above.
return true;
}
-//----------------------------------------------------------------------------
void cmFindCommon::AddPathSuffix(std::string const& arg)
{
std::string suffix = arg;
// Strip leading and trailing slashes.
- if(suffix.empty())
- {
+ if (suffix.empty()) {
return;
- }
- if(suffix[0] == '/')
- {
- suffix = suffix.substr(1, suffix.npos);
- }
- if(suffix.empty())
- {
+ }
+ if (suffix[0] == '/') {
+ suffix = suffix.substr(1);
+ }
+ if (suffix.empty()) {
return;
- }
- if(suffix[suffix.size()-1] == '/')
- {
- suffix = suffix.substr(0, suffix.size()-1);
- }
- if(suffix.empty())
- {
+ }
+ if (suffix[suffix.size() - 1] == '/') {
+ suffix = suffix.substr(0, suffix.size() - 1);
+ }
+ if (suffix.empty()) {
return;
- }
+ }
// Store the suffix.
this->SearchPathSuffixes.push_back(suffix);
}
-//----------------------------------------------------------------------------
-void cmFindCommon::AddUserPath(std::string const& p,
- std::vector<std::string>& paths)
+void AddTrailingSlash(std::string& s)
{
- // 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(this->Makefile->PlatformIs64Bit())
- {
- view = cmSystemTools::KeyWOW64_64;
- other_view = cmSystemTools::KeyWOW64_32;
- }
-
- // Expand using the view of the target application.
- std::string expanded = p;
- cmSystemTools::ExpandRegistryValues(expanded, view);
- cmSystemTools::GlobDirs(expanded.c_str(), paths);
-
- // Executables can be either 32-bit or 64-bit, so expand using the
- // alternative view.
- if(expanded != p && this->CMakePathName == "PROGRAM")
- {
- expanded = p;
- cmSystemTools::ExpandRegistryValues(expanded, other_view);
- cmSystemTools::GlobDirs(expanded.c_str(), paths);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmFindCommon::AddCMakePath(const char* variable)
-{
- // Get a path from a CMake variable.
- if(const char* varPath = this->Makefile->GetDefinition(variable))
- {
- std::vector<std::string> tmp;
- cmSystemTools::ExpandListArgument(varPath, tmp);
-
- // Relative paths are interpreted with respect to the current
- // source directory.
- this->AddPathsInternal(tmp, CMakePath);
- }
+ if (!s.empty() && *s.rbegin() != '/') {
+ s += '/';
+ }
}
-
-//----------------------------------------------------------------------------
-void cmFindCommon::AddEnvPath(const char* variable)
-{
- // Get a path from the environment.
- std::vector<std::string> tmp;
- cmSystemTools::GetPath(tmp, variable);
- // Relative paths are interpreted with respect to the current
- // working directory.
- this->AddPathsInternal(tmp, EnvPath);
-}
-
-//----------------------------------------------------------------------------
-void cmFindCommon::AddPathsInternal(std::vector<std::string> const& in_paths,
- PathType pathType)
-{
- for(std::vector<std::string>::const_iterator i = in_paths.begin();
- i != in_paths.end(); ++i)
- {
- this->AddPathInternal(*i, pathType);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmFindCommon::AddPathInternal(std::string const& in_path,
- PathType pathType)
-{
- if(in_path.empty())
- {
- return;
- }
-
- // Select the base path with which to interpret relative paths.
- const char* relbase = 0;
- if(pathType == CMakePath)
- {
- relbase = this->Makefile->GetCurrentDirectory();
- }
-
- // Convert to clean full path.
- std::string fullPath =
- cmSystemTools::CollapseFullPath(in_path.c_str(), relbase);
-
- // Insert the path if has not already been emitted.
- if(this->SearchPathsEmitted.insert(fullPath).second)
- {
- this->SearchPaths.push_back(fullPath.c_str());
- }
-}
-
-//----------------------------------------------------------------------------
void cmFindCommon::ComputeFinalPaths()
{
- std::vector<std::string>& paths = this->SearchPaths;
+ // Filter out ignored paths from the prefix list
+ std::set<std::string> ignored;
+ this->GetIgnoredPaths(ignored);
+
+ // Combine the seperate 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);
+ }
// Expand list of paths inside all search roots.
- this->RerootPaths(paths);
+ this->RerootPaths(this->SearchPaths);
// Add a trailing slash to all paths to aid the search process.
- for(std::vector<std::string>::iterator i = paths.begin();
- i != paths.end(); ++i)
- {
- std::string& p = *i;
- if(!p.empty() && p[p.size()-1] != '/')
- {
- p += "/";
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void cmFindCommon::SetMakefile(cmMakefile* makefile)
-{
- cmCommand::SetMakefile(makefile);
-
- // If we are building for Apple (OSX or also iphone), make sure
- // that frameworks and bundles are searched first.
- if(this->Makefile->IsOn("APPLE"))
- {
- this->SearchFrameworkFirst = true;
- this->SearchAppBundleFirst = true;
- }
+ std::for_each(this->SearchPaths.begin(), this->SearchPaths.end(),
+ &AddTrailingSlash);
}
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index 542805faf..72dcd355d 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -1,18 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindCommon_h
#define cmFindCommon_h
+#include "cmConfigure.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+#include "cmPathLabel.h"
+#include "cmSearchPath.h"
/** \class cmFindCommon
* \brief Base class for FIND_XXX implementations.
@@ -25,16 +25,54 @@ class cmFindCommon : public cmCommand
{
public:
cmFindCommon();
- ~cmFindCommon();
- cmTypeMacro(cmFindCommon, cmCommand);
+ ~cmFindCommon() CM_OVERRIDE;
protected:
-
- enum RootPathMode { RootPathModeBoth,
- RootPathModeOnlyRootPath,
- RootPathModeNoRootPath };
-
- enum PathType { FullPath, CMakePath, EnvPath };
+ friend class cmSearchPath;
+
+ /** Used to define groups of path labels */
+ class PathGroup : public cmPathLabel
+ {
+ protected:
+ PathGroup();
+
+ public:
+ PathGroup(const std::string& label)
+ : cmPathLabel(label)
+ {
+ }
+ static PathGroup All;
+ };
+
+ /* Individual path types */
+ class PathLabel : public cmPathLabel
+ {
+ protected:
+ PathLabel();
+
+ public:
+ PathLabel(const std::string& label)
+ : cmPathLabel(label)
+ {
+ }
+ static PathLabel PackageRoot;
+ static PathLabel CMake;
+ static PathLabel CMakeEnvironment;
+ static PathLabel Hints;
+ static PathLabel SystemEnvironment;
+ static PathLabel CMakeSystem;
+ static PathLabel Guess;
+ };
+
+ enum RootPathMode
+ {
+ RootPathModeNever,
+ RootPathModeOnly,
+ RootPathModeBoth
+ };
+
+ /** Construct the various path groups and labels */
+ void InitializeSearchPathGroups();
/** Place a set of search paths under the search roots. */
void RerootPaths(std::vector<std::string>& paths);
@@ -43,51 +81,44 @@ protected:
void GetIgnoredPaths(std::vector<std::string>& ignore);
void GetIgnoredPaths(std::set<std::string>& ignore);
- /** Remove paths in the ignore set from the supplied vector. */
- void FilterPaths(std::vector<std::string>& paths,
- const std::set<std::string>& ignore);
-
/** 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();
- virtual void GenerateDocumentation();
+ // Path arguments prior to path manipulation routines
+ std::vector<std::string> UserHintsArgs;
+ std::vector<std::string> UserGuessArgs;
- cmStdString CMakePathName;
+ std::string CMakePathName;
RootPathMode FindRootPathMode;
bool CheckCommonArgument(std::string const& arg);
void AddPathSuffix(std::string const& arg);
- void AddUserPath(std::string const& p,
- std::vector<std::string>& paths);
- void AddCMakePath(const char* variable);
- void AddEnvPath(const char* variable);
- void AddPathsInternal(std::vector<std::string> const& in_paths,
- PathType pathType);
- void AddPathInternal(std::string const& in_path, PathType pathType);
-
- void SetMakefile(cmMakefile* makefile);
bool NoDefaultPath;
+ bool NoPackageRootPath;
bool NoCMakePath;
bool NoCMakeEnvironmentPath;
bool NoSystemEnvironmentPath;
bool NoCMakeSystemPath;
std::vector<std::string> SearchPathSuffixes;
- std::vector<std::string> UserPaths;
- std::vector<std::string> UserHints;
- std::vector<std::string> SearchPaths;
- std::set<cmStdString> SearchPathsEmitted;
- std::string GenericDocumentationMacPolicy;
- std::string GenericDocumentationRootPath;
- std::string GenericDocumentationPathsOrder;
+ std::map<PathGroup, std::vector<PathLabel> > PathGroupLabelMap;
+ std::vector<PathGroup> PathGroupOrder;
+ std::map<std::string, PathLabel> PathLabelStringMap;
+ std::map<PathLabel, cmSearchPath> LabeledPaths;
+
+ std::vector<std::string> SearchPaths;
+ std::set<std::string> SearchPathsEmitted;
bool SearchFrameworkFirst;
bool SearchFrameworkOnly;
diff --git a/Source/cmFindFileCommand.cxx b/Source/cmFindFileCommand.cxx
index fa66fa11d..9840c4f49 100644
--- a/Source/cmFindFileCommand.cxx
+++ b/Source/cmFindFileCommand.cxx
@@ -1,30 +1,8 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindFileCommand.h"
-#include "cmSystemTools.h"
cmFindFileCommand::cmFindFileCommand()
{
this->IncludeFileInPath = true;
}
-
-void cmFindFileCommand::GenerateDocumentation()
-{
- this->cmFindPathCommand::GenerateDocumentation();
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "find_path", "find_file");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "directory containing the named file",
- "full path to named file");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "file in a directory", "full path to a file");
-}
diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h
index 1bfdcbd16..bf57fecd3 100644
--- a/Source/cmFindFileCommand.h
+++ b/Source/cmFindFileCommand.h
@@ -1,19 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindFileCommand_h
#define cmFindFileCommand_h
+#include "cmConfigure.h"
+
#include "cmFindPathCommand.h"
+class cmCommand;
+
/** \class cmFindFileCommand
* \brief Define a command to search for an executable program.
*
@@ -29,25 +24,7 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFindFileCommand;
- }
- virtual const char* GetName() const { return "find_file";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Find the full path to a file.";
- }
-
- cmTypeMacro(cmFindFileCommand, cmFindPathCommand);
-protected:
- virtual void GenerateDocumentation();
+ cmCommand* Clone() CM_OVERRIDE { return new cmFindFileCommand; }
};
-
-
#endif
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 4af7e11bf..a6b1a2155 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -1,18 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFindLibraryCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <set>
+#include <stdio.h>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmFindLibraryCommand.h"
-#include "cmCacheManager.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/stl/algorithm>
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
cmFindLibraryCommand::cmFindLibraryCommand()
{
@@ -20,199 +22,159 @@ cmFindLibraryCommand::cmFindLibraryCommand()
this->NamesPerDirAllowed = true;
}
-//----------------------------------------------------------------------------
-void cmFindLibraryCommand::GenerateDocumentation()
-{
- this->cmFindBase::GenerateDocumentation();
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "FIND_XXX", "find_library");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_XXX_PATH", "CMAKE_LIBRARY_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_XXX_MAC_PATH",
- "CMAKE_FRAMEWORK_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_SYSTEM_XXX_MAC_PATH",
- "CMAKE_SYSTEM_FRAMEWORK_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_SYSTEM", "LIB");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_SYSTEM_XXX_PATH",
- "CMAKE_SYSTEM_LIBRARY_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "SEARCH_XXX_DESC", "library");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "SEARCH_XXX", "library");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_SUBDIR", "lib");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "NAMES name1 [name2 ...]",
- "NAMES name1 [name2 ...] [NAMES_PER_DIR]");
- cmSystemTools::ReplaceString(
- this->GenericDocumentation,
- "XXX_EXTRA_PREFIX_ENTRY",
- " <prefix>/lib/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and\n");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_FIND_ROOT_PATH_MODE_XXX",
- "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY");
- this->GenericDocumentation +=
- "\n"
- "When more than one value is given to the NAMES option this command "
- "by default will consider one name at a time and search every directory "
- "for it. "
- "The NAMES_PER_DIR option tells this command to consider one directory "
- "at a time and search for all names in it."
- "\n"
- "If the library found is a framework, then VAR will be set to "
- "the full path to the framework <fullPath>/A.framework. "
- "When a full path to a framework is used as a library, "
- "CMake will use a -framework A, and a -F<fullPath> to "
- "link the framework to the target."
- "\n"
- "If the global property FIND_LIBRARY_USE_LIB64_PATHS is set all search "
- "paths will be tested as normal, with \"64/\" appended, and with all "
- "matches of \"lib/\" replaced with \"lib64/\". This property is "
- "automatically set for the platforms that are known to need it if at "
- "least one of the languages supported by the PROJECT command is enabled.";
-}
-
// cmFindLibraryCommand
-bool cmFindLibraryCommand
-::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
+bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn,
+ cmExecutionStatus&)
{
this->VariableDocumentation = "Path to a library.";
this->CMakePathName = "LIBRARY";
- if(!this->ParseArguments(argsIn))
- {
+ if (!this->ParseArguments(argsIn)) {
return false;
- }
- if(this->AlreadyInCache)
- {
+ }
+ if (this->AlreadyInCache) {
// If the user specifies the entry on the command line without a
// type we should add the type and docstring but keep the original
// value.
- if(this->AlreadyInCacheWithoutMetaInfo)
- {
- this->Makefile->AddCacheDefinition(this->VariableName.c_str(), "",
+ if (this->AlreadyInCacheWithoutMetaInfo) {
+ this->Makefile->AddCacheDefinition(this->VariableName, "",
this->VariableDocumentation.c_str(),
- cmCacheManager::FILEPATH);
- }
- return true;
- }
-
- if(const char* abi_name =
- this->Makefile->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI"))
- {
- std::string abi = abi_name;
- if(abi.find("ELF N32") != abi.npos)
- {
- // Convert lib to lib32.
- this->AddArchitecturePaths("32");
- }
- }
-
- if(this->Makefile->GetCMakeInstance()
- ->GetPropertyAsBool("FIND_LIBRARY_USE_LIB64_PATHS"))
- {
- // add special 64 bit paths if this is a 64 bit compile.
- if(this->Makefile->PlatformIs64Bit())
- {
- this->AddArchitecturePaths("64");
- }
+ cmStateEnums::FILEPATH);
}
+ return true;
+ }
+
+ // add custom lib<qual> paths instead of using fixed lib32, lib64 or
+ // libx32
+ if (const char* customLib = this->Makefile->GetDefinition(
+ "CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX")) {
+ this->AddArchitecturePaths(customLib);
+ }
+ // add special 32 bit paths if this is a 32 bit compile.
+ else if (this->Makefile->PlatformIs32Bit() &&
+ this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_LIB32_PATHS")) {
+ this->AddArchitecturePaths("32");
+ }
+ // add special 64 bit paths if this is a 64 bit compile.
+ else if (this->Makefile->PlatformIs64Bit() &&
+ this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_LIB64_PATHS")) {
+ this->AddArchitecturePaths("64");
+ }
+ // add special 32 bit paths if this is an x32 compile.
+ else if (this->Makefile->PlatformIsx32() &&
+ this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_LIBX32_PATHS")) {
+ this->AddArchitecturePaths("x32");
+ }
std::string library = this->FindLibrary();
- if(library != "")
- {
+ if (library != "") {
// Save the value in the cache
- this->Makefile->AddCacheDefinition(this->VariableName.c_str(),
- library.c_str(),
+ this->Makefile->AddCacheDefinition(this->VariableName, library.c_str(),
this->VariableDocumentation.c_str(),
- cmCacheManager::FILEPATH);
+ cmStateEnums::FILEPATH);
return true;
- }
+ }
std::string notfound = this->VariableName + "-NOTFOUND";
- this->Makefile->AddCacheDefinition(this->VariableName.c_str(),
- notfound.c_str(),
+ this->Makefile->AddCacheDefinition(this->VariableName, notfound.c_str(),
this->VariableDocumentation.c_str(),
- cmCacheManager::FILEPATH);
+ cmStateEnums::FILEPATH);
return true;
}
-//----------------------------------------------------------------------------
void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix)
{
std::vector<std::string> original;
original.swap(this->SearchPaths);
- for(std::vector<std::string>::iterator i = original.begin();
- i != original.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = original.begin();
+ i != original.end(); ++i) {
this->AddArchitecturePath(*i, 0, suffix);
- }
+ }
+}
+
+static bool cmLibDirsLinked(std::string const& l, std::string const& r)
+{
+ // Compare the real paths of the two directories.
+ // Since our caller only changed the trailing component of each
+ // directory, the real paths can be the same only if at least one of
+ // the trailing components is a symlink. Use this as an optimization
+ // to avoid excessive realpath calls.
+ return (cmSystemTools::FileIsSymlink(l) ||
+ cmSystemTools::FileIsSymlink(r)) &&
+ cmSystemTools::GetRealPath(l) == cmSystemTools::GetRealPath(r);
}
-//----------------------------------------------------------------------------
void cmFindLibraryCommand::AddArchitecturePath(
- std::string const& dir, std::string::size_type start_pos,
- const char* suffix, bool fresh)
+ std::string const& dir, std::string::size_type start_pos, const char* suffix,
+ bool fresh)
{
std::string::size_type pos = dir.find("lib/", start_pos);
- if(pos != std::string::npos)
- {
- std::string cur_dir = dir.substr(0,pos+3);
-
- // Follow "lib<suffix>".
- std::string next_dir = cur_dir + suffix;
- if(cmSystemTools::FileIsDirectory(next_dir.c_str()))
- {
- next_dir += dir.substr(pos+3);
- std::string::size_type next_pos = pos+3+strlen(suffix)+1;
- this->AddArchitecturePath(next_dir, next_pos, suffix);
- }
- // Follow "lib".
- if(cmSystemTools::FileIsDirectory(cur_dir.c_str()))
- {
- this->AddArchitecturePath(dir, pos+3+1, suffix, false);
- }
+ if (pos != std::string::npos) {
+ // Check for "lib".
+ std::string lib = dir.substr(0, pos + 3);
+ bool use_lib = cmSystemTools::FileIsDirectory(lib);
+
+ // Check for "lib<suffix>" and use it first.
+ std::string libX = lib + suffix;
+ bool use_libX = cmSystemTools::FileIsDirectory(libX);
+
+ // Avoid copies of the same directory due to symlinks.
+ if (use_libX && use_lib && cmLibDirsLinked(libX, lib)) {
+ use_libX = false;
}
- if(fresh)
- {
- // Check for <dir><suffix>/.
- std::string cur_dir = dir + suffix + "/";
- if(cmSystemTools::FileIsDirectory(cur_dir.c_str()))
- {
- this->SearchPaths.push_back(cur_dir);
- }
- // Now add the original unchanged path
- if(cmSystemTools::FileIsDirectory(dir.c_str()))
- {
+ if (use_libX) {
+ libX += dir.substr(pos + 3);
+ std::string::size_type libX_pos = pos + 3 + strlen(suffix) + 1;
+ this->AddArchitecturePath(libX, libX_pos, suffix);
+ }
+
+ if (use_lib) {
+ this->AddArchitecturePath(dir, pos + 3 + 1, suffix, false);
+ }
+ }
+
+ if (fresh) {
+ // Check for the original unchanged path.
+ bool use_dir = cmSystemTools::FileIsDirectory(dir);
+
+ // Check for <dir><suffix>/ and use it first.
+ std::string dirX = dir + suffix;
+ bool use_dirX = cmSystemTools::FileIsDirectory(dirX);
+
+ // Avoid copies of the same directory due to symlinks.
+ if (use_dirX && use_dir && cmLibDirsLinked(dirX, dir)) {
+ use_dirX = false;
+ }
+
+ if (use_dirX) {
+ dirX += "/";
+ this->SearchPaths.push_back(dirX);
+ }
+
+ if (use_dir) {
this->SearchPaths.push_back(dir);
- }
}
+ }
}
-//----------------------------------------------------------------------------
std::string cmFindLibraryCommand::FindLibrary()
{
std::string library;
- if(this->SearchFrameworkFirst || this->SearchFrameworkOnly)
- {
+ if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) {
library = this->FindFrameworkLibrary();
- }
- if(library.empty() && !this->SearchFrameworkOnly)
- {
+ }
+ if (library.empty() && !this->SearchFrameworkOnly) {
library = this->FindNormalLibrary();
- }
- if(library.empty() && this->SearchFrameworkLast)
- {
+ }
+ if (library.empty() && this->SearchFrameworkLast) {
library = this->FindFrameworkLibrary();
- }
+ }
return library;
}
-//----------------------------------------------------------------------------
struct cmFindLibraryHelper
{
cmFindLibraryHelper(cmMakefile* mf);
@@ -240,7 +202,10 @@ struct cmFindLibraryHelper
bool TryRaw;
std::string Raw;
cmsys::RegularExpression Regex;
- Name(): TryRaw(false) {}
+ Name()
+ : TryRaw(false)
+ {
+ }
};
std::vector<Name> Names;
@@ -250,26 +215,26 @@ struct cmFindLibraryHelper
void RegexFromLiteral(std::string& out, std::string const& in);
void RegexFromList(std::string& out, std::vector<std::string> const& in);
size_type GetPrefixIndex(std::string const& prefix)
- {
- return cmsys_stl::find(this->Prefixes.begin(), this->Prefixes.end(),
- prefix) - this->Prefixes.begin();
- }
+ {
+ return std::find(this->Prefixes.begin(), this->Prefixes.end(), prefix) -
+ this->Prefixes.begin();
+ }
size_type GetSuffixIndex(std::string const& suffix)
- {
- return cmsys_stl::find(this->Suffixes.begin(), this->Suffixes.end(),
- suffix) - this->Suffixes.begin();
- }
+ {
+ return std::find(this->Suffixes.begin(), this->Suffixes.end(), suffix) -
+ this->Suffixes.begin();
+ }
bool HasValidSuffix(std::string const& name);
void AddName(std::string const& name);
+ void SetName(std::string const& name);
bool CheckDirectory(std::string const& path);
bool CheckDirectoryForName(std::string const& path, Name& name);
};
-//----------------------------------------------------------------------------
-cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf):
- Makefile(mf)
+cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf)
+ : Makefile(mf)
{
- this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
+ this->GG = this->Makefile->GetGlobalGenerator();
// Collect the list of library name prefixes/suffixes to try.
const char* prefixes_list =
@@ -282,33 +247,28 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf):
this->RegexFromList(this->SuffixRegexStr, this->Suffixes);
// Check whether to use OpenBSD-style library version comparisons.
- this->OpenBSD =
- this->Makefile->GetCMakeInstance()
- ->GetPropertyAsBool("FIND_LIBRARY_USE_OPENBSD_VERSIONING");
+ this->OpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_OPENBSD_VERSIONING");
}
-//----------------------------------------------------------------------------
void cmFindLibraryHelper::RegexFromLiteral(std::string& out,
std::string const& in)
{
- for(std::string::const_iterator ci = in.begin(); ci != in.end(); ++ci)
- {
+ for (std::string::const_iterator ci = in.begin(); ci != in.end(); ++ci) {
char ch = *ci;
- if(ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '\\' ||
- ch == '.' || ch == '*' || ch == '+' || ch == '?' || ch == '-' ||
- ch == '^' || ch == '$')
- {
+ if (ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '\\' ||
+ ch == '.' || ch == '*' || ch == '+' || ch == '?' || ch == '-' ||
+ ch == '^' || ch == '$') {
out += "\\";
- }
+ }
#if defined(_WIN32) || defined(__APPLE__)
out += tolower(ch);
#else
out += ch;
#endif
- }
+ }
}
-//----------------------------------------------------------------------------
void cmFindLibraryHelper::RegexFromList(std::string& out,
std::vector<std::string> const& in)
{
@@ -316,47 +276,40 @@ 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::vector<std::string>::const_iterator si = in.begin();
+ si != in.end(); ++si) {
// Separate from previous item.
out += sep;
sep = "|";
// Append this item.
this->RegexFromLiteral(out, *si);
- }
+ }
out += ")";
}
-//----------------------------------------------------------------------------
bool cmFindLibraryHelper::HasValidSuffix(std::string const& name)
{
- for(std::vector<std::string>::const_iterator si = this->Suffixes.begin();
- si != this->Suffixes.end(); ++si)
- {
+ for (std::vector<std::string>::const_iterator si = this->Suffixes.begin();
+ si != this->Suffixes.end(); ++si) {
std::string suffix = *si;
- if(name.length() <= suffix.length())
- {
+ if (name.length() <= suffix.length()) {
continue;
- }
+ }
// Check if the given name ends in a valid library suffix.
- if(name.substr(name.size()-suffix.length()) == suffix)
- {
+ if (name.substr(name.size() - suffix.length()) == suffix) {
return true;
- }
+ }
// Check if a valid library suffix is somewhere in the name,
// this may happen e.g. for versioned shared libraries: libfoo.so.2
suffix += ".";
- if(name.find(suffix) != name.npos)
- {
+ if (name.find(suffix) != std::string::npos) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmFindLibraryHelper::AddName(std::string const& name)
{
Name entry;
@@ -370,30 +323,31 @@ void cmFindLibraryHelper::AddName(std::string const& name)
regex += this->PrefixRegexStr;
this->RegexFromLiteral(regex, name);
regex += this->SuffixRegexStr;
- if(this->OpenBSD)
- {
+ if (this->OpenBSD) {
regex += "(\\.[0-9]+\\.[0-9]+)?";
- }
+ }
regex += "$";
entry.Regex.compile(regex.c_str());
this->Names.push_back(entry);
}
-//----------------------------------------------------------------------------
+void cmFindLibraryHelper::SetName(std::string const& name)
+{
+ this->Names.clear();
+ this->AddName(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 (std::vector<Name>::iterator i = this->Names.begin();
+ i != this->Names.end(); ++i) {
+ if (this->CheckDirectoryForName(path, *i)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
Name& name)
{
@@ -402,18 +356,15 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
// specifically for a static library on some platforms (on MS tools
// one cannot tell just from the library name whether it is a static
// library or an import library).
- if(name.TryRaw)
- {
+ if (name.TryRaw) {
this->TestPath = path;
this->TestPath += name.Raw;
- if(cmSystemTools::FileExists(this->TestPath.c_str(), true))
- {
- this->BestPath =
- cmSystemTools::CollapseFullPath(this->TestPath.c_str());
+ if (cmSystemTools::FileExists(this->TestPath.c_str(), true)) {
+ this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
cmSystemTools::ConvertToUnixSlashes(this->BestPath);
return true;
- }
}
+ }
// No library file has yet been found.
size_type bestPrefix = this->Prefixes.size();
@@ -424,22 +375,19 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
// Search for a file matching the library name regex.
std::string dir = path;
cmSystemTools::ConvertToUnixSlashes(dir);
- std::set<cmStdString> const& files = this->GG->GetDirectoryContent(dir);
- for(std::set<cmStdString>::const_iterator fi = files.begin();
- fi != files.end(); ++fi)
- {
+ 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;
#if defined(_WIN32) || defined(__APPLE__)
std::string testName = cmSystemTools::LowerCase(origName);
#else
std::string const& testName = origName;
#endif
- if(name.Regex.find(testName))
- {
+ if (name.Regex.find(testName)) {
this->TestPath = path;
this->TestPath += origName;
- if(!cmSystemTools::FileIsDirectory(this->TestPath.c_str()))
- {
+ 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,
// followed by earlier suffixes. For OpenBSD, shared library
@@ -448,152 +396,123 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
size_type suffix = this->GetSuffixIndex(name.Regex.match(2));
unsigned int major = 0;
unsigned int minor = 0;
- if(this->OpenBSD)
- {
+ if (this->OpenBSD) {
sscanf(name.Regex.match(3).c_str(), ".%u.%u", &major, &minor);
- }
- if(this->BestPath.empty() || prefix < bestPrefix ||
- (prefix == bestPrefix && suffix < bestSuffix) ||
- (prefix == bestPrefix && suffix == bestSuffix &&
- (major > bestMajor ||
- (major == bestMajor && minor > bestMinor))))
- {
+ }
+ if (this->BestPath.empty() || prefix < bestPrefix ||
+ (prefix == bestPrefix && suffix < bestSuffix) ||
+ (prefix == bestPrefix && suffix == bestSuffix &&
+ (major > bestMajor ||
+ (major == bestMajor && minor > bestMinor)))) {
this->BestPath = this->TestPath;
bestPrefix = prefix;
bestSuffix = suffix;
bestMajor = major;
bestMinor = minor;
- }
}
}
}
+ }
// Use the best candidate found in this directory, if any.
return !this->BestPath.empty();
}
-//----------------------------------------------------------------------------
std::string cmFindLibraryCommand::FindNormalLibrary()
{
- if(this->NamesPerDir)
- {
+ if (this->NamesPerDir) {
return this->FindNormalLibraryNamesPerDir();
- }
- else
- {
- return this->FindNormalLibraryDirsPerName();
- }
+ }
+ return this->FindNormalLibraryDirsPerName();
}
-//----------------------------------------------------------------------------
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)
- {
+ for (std::vector<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni) {
helper.AddName(*ni);
- }
+ }
// 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::vector<std::string>::const_iterator p = this->SearchPaths.begin();
+ p != this->SearchPaths.end(); ++p) {
+ if (helper.CheckDirectory(*p)) {
return helper.BestPath;
- }
}
+ }
// Couldn't find the library.
return "";
}
-//----------------------------------------------------------------------------
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::vector<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni) {
// Switch to searching for this name.
- std::string const& name = *ni;
- helper.AddName(name);
+ helper.SetName(*ni);
// 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::vector<std::string>::const_iterator p =
+ this->SearchPaths.begin();
+ p != this->SearchPaths.end(); ++p) {
+ if (helper.CheckDirectory(*p)) {
return helper.BestPath;
- }
}
}
+ }
// Couldn't find the library.
return "";
}
-//----------------------------------------------------------------------------
std::string cmFindLibraryCommand::FindFrameworkLibrary()
{
- if(this->NamesPerDir)
- {
+ if (this->NamesPerDir) {
return this->FindFrameworkLibraryNamesPerDir();
- }
- else
- {
- return this->FindFrameworkLibraryDirsPerName();
- }
+ }
+ return this->FindFrameworkLibraryDirsPerName();
}
-//----------------------------------------------------------------------------
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)
- {
+ 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";
- if(cmSystemTools::FileIsDirectory(fwPath.c_str()))
- {
- return cmSystemTools::CollapseFullPath(fwPath.c_str());
- }
+ if (cmSystemTools::FileIsDirectory(fwPath)) {
+ return cmSystemTools::CollapseFullPath(fwPath);
}
}
+ }
// No framework found.
return "";
}
-//----------------------------------------------------------------------------
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)
- {
+ 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";
- if(cmSystemTools::FileIsDirectory(fwPath.c_str()))
- {
- return cmSystemTools::CollapseFullPath(fwPath.c_str());
- }
+ if (cmSystemTools::FileIsDirectory(fwPath)) {
+ return cmSystemTools::CollapseFullPath(fwPath);
}
}
+ }
// No framework found.
return "";
diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h
index cd0fce8ad..9d38eab33 100644
--- a/Source/cmFindLibraryCommand.h
+++ b/Source/cmFindLibraryCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindLibraryCommand_h
#define cmFindLibraryCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmFindBase.h"
+class cmCommand;
+class cmExecutionStatus;
/** \class cmFindLibraryCommand
* \brief Define a command to search for a library.
@@ -29,45 +27,22 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFindLibraryCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFindLibraryCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "find_library";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Find a library.";
- }
- cmTypeMacro(cmFindLibraryCommand, cmFindBase);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
protected:
void AddArchitecturePaths(const char* suffix);
void AddArchitecturePath(std::string const& dir,
std::string::size_type start_pos,
- const char* suffix,
- bool fresh = true);
+ const char* suffix, bool fresh = true);
std::string FindLibrary();
- virtual void GenerateDocumentation();
+
private:
std::string FindNormalLibrary();
std::string FindNormalLibraryNamesPerDir();
@@ -77,6 +52,4 @@ private:
std::string FindFrameworkLibraryDirsPerName();
};
-
-
#endif
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index aa3a73d26..7797700d6 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -1,54 +1,86 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindPackageCommand.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/RegularExpression.hxx>
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmVariableWatch.h"
-#endif
+#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 <deque>
+#include <functional>
+#include <iterator>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmSearchPath.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmVersion.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
#if defined(__HAIKU__)
-#include <StorageKit.h>
+#include <FindDirectory.h>
+#include <StorageDefs.h>
#endif
-void cmFindPackageNeedBackwardsCompatibility(const std::string& variable,
- int access_type, void*, const char* newValue,
- const cmMakefile*)
+class cmExecutionStatus;
+class cmFileList;
+
+cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::UserRegistry(
+ "PACKAGE_REGISTRY");
+cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds(
+ "BUILDS");
+cmFindPackageCommand::PathLabel
+ cmFindPackageCommand::PathLabel::SystemRegistry("SYSTEM_PACKAGE_REGISTRY");
+
+struct StrverscmpGreater
+{
+ bool operator()(const std::string& lhs, const std::string& rhs) const
+ {
+ return cmSystemTools::strverscmp(lhs, rhs) > 0;
+ }
+};
+
+struct StrverscmpLesser
+{
+ bool operator()(const std::string& lhs, const std::string& rhs) const
+ {
+ return cmSystemTools::strverscmp(lhs, rhs) < 0;
+ }
+};
+
+void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin,
+ std::vector<std::string>::iterator end,
+ SortOrderType order, SortDirectionType dir)
{
- (void)newValue;
-#ifdef CMAKE_BUILD_WITH_CMAKE
- if(access_type == cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS)
- {
- std::string message = "An attempt was made to access a variable: ";
- message += variable;
- message +=
- " that has not been defined. This variable is created by the "
- "FIND_PACKAGE command. CMake version 1.6 always converted the "
- "variable name to upper-case, but this behavior is no longer the "
- "case. To fix this you might need to set the cache value of "
- "CMAKE_BACKWARDS_COMPATIBILITY to 1.6 or less. If you are writing a "
- "CMake listfile, you should change the variable reference to use "
- "the case of the argument to FIND_PACKAGE.";
- cmSystemTools::Error(message.c_str());
+ if (order == Name_order) {
+ if (dir == Dec) {
+ std::sort(begin, end, std::greater<std::string>());
+ } else {
+ std::sort(begin, end);
+ }
+ } else if (order == Natural)
+ // natural order uses letters and numbers (contiguous numbers digit are
+ // compared such that e.g. 000 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10
+ {
+ if (dir == Dec) {
+ std::sort(begin, end, StrverscmpGreater());
+ } else {
+ std::sort(begin, end, StrverscmpLesser());
}
-#else
- (void)variable;
- (void)access_type;
-#endif
+ }
+ // else do not sort
}
-//----------------------------------------------------------------------------
cmFindPackageCommand::cmFindPackageCommand()
{
this->CMakePathName = "PACKAGE";
@@ -56,11 +88,12 @@ cmFindPackageCommand::cmFindPackageCommand()
this->Required = false;
this->NoUserRegistry = false;
this->NoSystemRegistry = false;
- this->NoBuilds = false;
this->UseConfigFiles = true;
this->UseFindModules = true;
this->DebugMode = false;
+ this->UseLib32Paths = false;
this->UseLib64Paths = false;
+ this->UseLibx32Paths = false;
this->PolicyScope = true;
this->VersionMajor = 0;
this->VersionMinor = 0;
@@ -74,360 +107,109 @@ cmFindPackageCommand::cmFindPackageCommand()
this->VersionFoundTweak = 0;
this->VersionFoundCount = 0;
this->RequiredCMakeVersion = 0;
+ this->SortOrder = None;
+ this->SortDirection = Asc;
+ this->AppendSearchPathGroups();
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::GenerateDocumentation()
+void cmFindPackageCommand::AppendSearchPathGroups()
{
- this->cmFindCommon::GenerateDocumentation();
- cmSystemTools::ReplaceString(this->GenericDocumentationRootPath,
- "CMAKE_FIND_ROOT_PATH_MODE_XXX",
- "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE");
- cmSystemTools::ReplaceString(this->GenericDocumentationPathsOrder,
- "FIND_ARGS_XXX", "<package>");
- cmSystemTools::ReplaceString(this->GenericDocumentationPathsOrder,
- "FIND_XXX", "find_package");
- this->CommandDocumentation =
- " find_package(<package> [version] [EXACT] [QUIET] [MODULE]\n"
- " [REQUIRED] [[COMPONENTS] [components...]]\n"
- " [OPTIONAL_COMPONENTS components...]\n"
- " [NO_POLICY_SCOPE])\n"
- "Finds and loads settings from an external project. "
- "<package>_FOUND will be set to indicate whether the package was found. "
- "When the package is found package-specific information is provided "
- "through variables and imported targets documented by the package "
- "itself. "
- "The QUIET option disables messages if the package cannot be found. "
- "The MODULE option disables the second signature documented below. "
- "The REQUIRED option stops processing with an error message if the "
- "package cannot be found."
- "\n"
- "A package-specific list of required components may be listed after the "
- "COMPONENTS option (or after the REQUIRED option if present). "
- "Additional optional components may be listed after OPTIONAL_COMPONENTS. "
- "Available components and their influence on whether a package is "
- "considered to be found are defined by the target package."
- "\n"
- "The [version] argument requests a version with which the package found "
- "should be compatible (format is major[.minor[.patch[.tweak]]]). "
- "The EXACT option requests that the version be matched exactly. "
- "If no [version] and/or component list is given to a recursive "
- "invocation inside a find-module, the corresponding arguments "
- "are forwarded automatically from the outer call (including the "
- "EXACT flag for [version]). "
- "Version support is currently provided only on a package-by-package "
- "basis (details below).\n"
- "User code should generally look for packages using the above simple "
- "signature. The remainder of this command documentation specifies the "
- "full command signature and details of the search process. Project "
- "maintainers wishing to provide a package to be found by this command "
- "are encouraged to read on.\n"
- "The command has two modes by which it searches for packages: "
- "\"Module\" mode and \"Config\" mode. "
- "Module mode is available when the command is invoked with the above "
- "reduced signature. "
- "CMake searches for a file called \"Find<package>.cmake\" in "
- "the CMAKE_MODULE_PATH followed by the CMake installation. "
- "If the file is found, it is read and processed by CMake. "
- "It is responsible for finding the package, checking the version, "
- "and producing any needed messages. "
- "Many find-modules provide limited or no support for versioning; "
- "check the module documentation. "
- "If no module is found and the MODULE option is not given the command "
- "proceeds to Config mode.\n"
- "The complete Config mode command signature is:\n"
- " find_package(<package> [version] [EXACT] [QUIET]\n"
- " [REQUIRED] [[COMPONENTS] [components...]]\n"
- " [CONFIG|NO_MODULE]\n"
- " [NO_POLICY_SCOPE]\n"
- " [NAMES name1 [name2 ...]]\n"
- " [CONFIGS config1 [config2 ...]]\n"
- " [HINTS path1 [path2 ... ]]\n"
- " [PATHS path1 [path2 ... ]]\n"
- " [PATH_SUFFIXES suffix1 [suffix2 ...]]\n"
- " [NO_DEFAULT_PATH]\n"
- " [NO_CMAKE_ENVIRONMENT_PATH]\n"
- " [NO_CMAKE_PATH]\n"
- " [NO_SYSTEM_ENVIRONMENT_PATH]\n"
- " [NO_CMAKE_PACKAGE_REGISTRY]\n"
- " [NO_CMAKE_BUILDS_PATH]\n"
- " [NO_CMAKE_SYSTEM_PATH]\n"
- " [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]\n"
- " [CMAKE_FIND_ROOT_PATH_BOTH |\n"
- " ONLY_CMAKE_FIND_ROOT_PATH |\n"
- " NO_CMAKE_FIND_ROOT_PATH])\n"
- "The CONFIG option may be used to skip Module mode explicitly and "
- "switch to Config mode. It is synonymous to using NO_MODULE. "
- "Config mode is also implied by use of options not specified in the "
- "reduced signature. "
- "\n"
- "Config mode attempts to locate a configuration file provided by the "
- "package to be found. A cache entry called <package>_DIR is created to "
- "hold the directory containing the file. "
- "By default the command searches for a package with the name <package>. "
- "If the NAMES option is given the names following it are used instead "
- "of <package>. "
- "The command searches for a file called \"<name>Config.cmake\" or "
- "\"<lower-case-name>-config.cmake\" for each name specified. "
- "A replacement set of possible configuration file names may be given "
- "using the CONFIGS option. "
- "The search procedure is specified below. Once found, the configuration "
- "file is read and processed by CMake. Since the file is provided by the "
- "package it already knows the location of package contents. "
- "The full path to the configuration file is stored in the cmake "
- "variable <package>_CONFIG."
- "\n"
- "All configuration files which have been considered by CMake while "
- "searching for an installation of the package with an appropriate "
- "version are stored in the cmake variable <package>_CONSIDERED_CONFIGS, "
- "the associated versions in <package>_CONSIDERED_VERSIONS. "
- "\n"
- "If the package configuration file cannot be found CMake "
- "will generate an error describing the problem unless the QUIET "
- "argument is specified. If REQUIRED is specified and the package "
- "is not found a fatal error is generated and the configure step stops "
- "executing. If <package>_DIR has been set to a directory not containing "
- "a configuration file CMake will ignore it and search from scratch."
- "\n"
- "When the [version] argument is given Config mode will only find a "
- "version of the package that claims compatibility with the requested "
- "version (format is major[.minor[.patch[.tweak]]]). "
- "If the EXACT option is given only a version of the package claiming "
- "an exact match of the requested version may be found. "
- "CMake does not establish any convention for the meaning of version "
- "numbers. "
- "Package version numbers are checked by \"version\" files provided by "
- "the packages themselves. "
- "For a candidate package configuration file \"<config-file>.cmake\" the "
- "corresponding version file is located next to it and named either "
- "\"<config-file>-version.cmake\" or \"<config-file>Version.cmake\". "
- "If no such version file is available then the configuration file "
- "is assumed to not be compatible with any requested version. "
- "A basic version file containing generic version matching code can be "
- "created using the macro write_basic_package_version_file(), see its "
- "documentation for more details. "
- "When a version file is found it is loaded to check the requested "
- "version number. "
- "The version file is loaded in a nested scope in which the following "
- "variables have been defined:\n"
- " PACKAGE_FIND_NAME = the <package> name\n"
- " PACKAGE_FIND_VERSION = full requested version string\n"
- " PACKAGE_FIND_VERSION_MAJOR = major version if requested, else 0\n"
- " PACKAGE_FIND_VERSION_MINOR = minor version if requested, else 0\n"
- " PACKAGE_FIND_VERSION_PATCH = patch version if requested, else 0\n"
- " PACKAGE_FIND_VERSION_TWEAK = tweak version if requested, else 0\n"
- " PACKAGE_FIND_VERSION_COUNT = number of version components, 0 to 4\n"
- "The version file checks whether it satisfies the requested version "
- "and sets these variables:\n"
- " PACKAGE_VERSION = full provided version string\n"
- " PACKAGE_VERSION_EXACT = true if version is exact match\n"
- " PACKAGE_VERSION_COMPATIBLE = true if version is compatible\n"
- " PACKAGE_VERSION_UNSUITABLE = true if unsuitable as any version\n"
- "These variables are checked by the find_package command to determine "
- "whether the configuration file provides an acceptable version. "
- "They are not available after the find_package call returns. "
- "If the version is acceptable the following variables are set:\n"
- " <package>_VERSION = full provided version string\n"
- " <package>_VERSION_MAJOR = major version if provided, else 0\n"
- " <package>_VERSION_MINOR = minor version if provided, else 0\n"
- " <package>_VERSION_PATCH = patch version if provided, else 0\n"
- " <package>_VERSION_TWEAK = tweak version if provided, else 0\n"
- " <package>_VERSION_COUNT = number of version components, 0 to 4\n"
- "and the corresponding package configuration file is loaded. "
- "When multiple package configuration files are available whose version "
- "files claim compatibility with the version requested it is unspecified "
- "which one is chosen. "
- "No attempt is made to choose a highest or closest version number."
- "\n"
- "Config mode provides an elaborate interface and search procedure. "
- "Much of the interface is provided for completeness and for use "
- "internally by find-modules loaded by Module mode. "
- "Most user code should simply call\n"
- " find_package(<package> [major[.minor]] [EXACT] [REQUIRED|QUIET])\n"
- "in order to find a package. Package maintainers providing CMake "
- "package configuration files are encouraged to name and install "
- "them such that the procedure outlined below will find them "
- "without requiring use of additional options."
- "\n"
- "CMake constructs a set of possible installation prefixes for the "
- "package. Under each prefix several directories are searched for a "
- "configuration file. The tables below show the directories searched. "
- "Each entry is meant for installation trees following Windows (W), "
- "UNIX (U), or Apple (A) conventions.\n"
- " <prefix>/ (W)\n"
- " <prefix>/(cmake|CMake)/ (W)\n"
- " <prefix>/<name>*/ (W)\n"
- " <prefix>/<name>*/(cmake|CMake)/ (W)\n"
- " <prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)\n"
- " <prefix>/(lib/<arch>|lib|share)/<name>*/ (U)\n"
- " <prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)\n"
- "On systems supporting OS X Frameworks and Application Bundles "
- "the following directories are searched for frameworks or bundles "
- "containing a configuration file:\n"
- " <prefix>/<name>.framework/Resources/ (A)\n"
- " <prefix>/<name>.framework/Resources/CMake/ (A)\n"
- " <prefix>/<name>.framework/Versions/*/Resources/ (A)\n"
- " <prefix>/<name>.framework/Versions/*/Resources/CMake/ (A)\n"
- " <prefix>/<name>.app/Contents/Resources/ (A)\n"
- " <prefix>/<name>.app/Contents/Resources/CMake/ (A)\n"
- "In all cases the <name> is treated as case-insensitive and corresponds "
- "to any of the names specified (<package> or names given by NAMES). "
- "Paths with lib/<arch> are enabled if CMAKE_LIBRARY_ARCHITECTURE is set. "
- "If PATH_SUFFIXES is specified the suffixes are appended to each "
- "(W) or (U) directory entry one-by-one.\n"
- "This set of directories is intended to work in cooperation with "
- "projects that provide configuration files in their installation trees. "
- "Directories above marked with (W) are intended for installations on "
- "Windows where the prefix may point at the top of an application's "
- "installation directory. Those marked with (U) are intended for "
- "installations on UNIX platforms where the prefix is shared by "
- "multiple packages. This is merely a convention, so all (W) and (U) "
- "directories are still searched on all platforms. "
- "Directories marked with (A) are intended for installations on "
- "Apple platforms. The cmake variables CMAKE_FIND_FRAMEWORK and "
- "CMAKE_FIND_APPBUNDLE determine the order of preference "
- "as specified below.\n"
- "The set of installation prefixes is constructed using the following "
- "steps. If NO_DEFAULT_PATH is specified all NO_* options are enabled.\n"
- "1. Search paths specified in cmake-specific cache variables. "
- "These are intended to be used on the command line with a -DVAR=value. "
- "This can be skipped if NO_CMAKE_PATH is passed.\n"
- " CMAKE_PREFIX_PATH\n"
- " CMAKE_FRAMEWORK_PATH\n"
- " CMAKE_APPBUNDLE_PATH\n"
- "2. Search paths specified in cmake-specific environment variables. "
- "These are intended to be set in the user's shell configuration. "
- "This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n"
- " <package>_DIR\n"
- " CMAKE_PREFIX_PATH\n"
- " CMAKE_FRAMEWORK_PATH\n"
- " CMAKE_APPBUNDLE_PATH\n"
- "3. Search paths specified by the HINTS option. "
- "These should be paths computed by system introspection, such as a "
- "hint provided by the location of another item already found. "
- "Hard-coded guesses should be specified with the PATHS option.\n"
- "4. Search the standard system environment variables. "
- "This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is passed. "
- "Path entries ending in \"/bin\" or \"/sbin\" are automatically "
- "converted to their parent directories.\n"
- " PATH\n"
- "5. Search project build trees recently configured in a CMake GUI. "
- "This can be skipped if NO_CMAKE_BUILDS_PATH is passed. "
- "It is intended for the case when a user is building multiple "
- "dependent projects one after another.\n"
- "6. Search paths stored in the CMake user package registry. "
- "This can be skipped if NO_CMAKE_PACKAGE_REGISTRY is passed. "
- "On Windows a <package> may appear under registry key\n"
- " HKEY_CURRENT_USER\\Software\\Kitware\\CMake\\Packages\\<package>\n"
- "as a REG_SZ value, with arbitrary name, that specifies the directory "
- "containing the package configuration file. "
- "On UNIX platforms a <package> may appear under the directory\n"
- " ~/.cmake/packages/<package>\n"
- "as a file, with arbitrary name, whose content specifies the directory "
- "containing the package configuration file. "
- "See the export(PACKAGE) command to create user package registry entries "
- "for project build trees."
- "\n"
- "7. Search cmake variables defined in the Platform files "
- "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH "
- "is passed.\n"
- " CMAKE_SYSTEM_PREFIX_PATH\n"
- " CMAKE_SYSTEM_FRAMEWORK_PATH\n"
- " CMAKE_SYSTEM_APPBUNDLE_PATH\n"
- "8. Search paths stored in the CMake system package registry. "
- "This can be skipped if NO_CMAKE_SYSTEM_PACKAGE_REGISTRY is passed. "
- "On Windows a <package> may appear under registry key\n"
- " HKEY_LOCAL_MACHINE\\Software\\Kitware\\CMake\\Packages\\<package>\n"
- "as a REG_SZ value, with arbitrary name, that specifies the directory "
- "containing the package configuration file. "
- "There is no system package registry on non-Windows platforms."
- "\n"
- "9. Search paths specified by the PATHS option. "
- "These are typically hard-coded guesses.\n"
- ;
- this->CommandDocumentation += this->GenericDocumentationMacPolicy;
- this->CommandDocumentation += this->GenericDocumentationRootPath;
- this->CommandDocumentation += this->GenericDocumentationPathsOrder;
- this->CommandDocumentation +=
- "\n"
- "Every non-REQUIRED find_package() call can be disabled by setting the "
- "variable CMAKE_DISABLE_FIND_PACKAGE_<package> to TRUE. See the "
- "documentation for the CMAKE_DISABLE_FIND_PACKAGE_<package> variable for "
- "more information.\n"
- "When loading a find module or package configuration file find_package "
- "defines variables to provide information about the call arguments "
- "(and restores their original state before returning):\n"
- " <package>_FIND_REQUIRED = true if REQUIRED option was given\n"
- " <package>_FIND_QUIETLY = true if QUIET option was given\n"
- " <package>_FIND_VERSION = full requested version string\n"
- " <package>_FIND_VERSION_MAJOR = major version if requested, else 0\n"
- " <package>_FIND_VERSION_MINOR = minor version if requested, else 0\n"
- " <package>_FIND_VERSION_PATCH = patch version if requested, else 0\n"
- " <package>_FIND_VERSION_TWEAK = tweak version if requested, else 0\n"
- " <package>_FIND_VERSION_COUNT = number of version components, 0 to 4\n"
- " <package>_FIND_VERSION_EXACT = true if EXACT option was given\n"
- " <package>_FIND_COMPONENTS = list of requested components\n"
- " <package>_FIND_REQUIRED_<c> = true if component <c> is required\n"
- " false if component <c> is optional\n"
- "In Module mode the loaded find module is responsible to honor the "
- "request detailed by these variables; see the find module for details. "
- "In Config mode find_package handles REQUIRED, QUIET, and version "
- "options automatically but leaves it to the package configuration file "
- "to handle components in a way that makes sense for the package. "
- "The package configuration file may set <package>_FOUND to false "
- "to tell find_package that component requirements are not satisfied."
- "\n"
- "See the cmake_policy() command documentation for discussion of the "
- "NO_POLICY_SCOPE option."
- ;
-}
-
-//----------------------------------------------------------------------------
-const char* cmFindPackageCommand::GetFullDocumentation() const
-{
- if(this->CommandDocumentation.empty())
- {
- const_cast<cmFindPackageCommand *>(this)->GenerateDocumentation();
- }
- return this->CommandDocumentation.c_str();
+ std::vector<cmFindCommon::PathLabel>* labels;
+
+ // Update the All group with new paths
+ labels = &this->PathGroupLabelMap[PathGroup::All];
+ labels->insert(
+ std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem),
+ PathLabel::UserRegistry);
+ labels->insert(
+ std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem),
+ PathLabel::Builds);
+ labels->insert(std::find(labels->begin(), labels->end(), PathLabel::Guess),
+ PathLabel::SystemRegistry);
+
+ // Create the new path objects
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::UserRegistry, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ std::make_pair(PathLabel::Builds, cmSearchPath(this)));
+ this->LabeledPaths.insert(
+ 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,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Lookup required version of CMake.
- if(const char* rv =
- this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"))
- {
- unsigned int v[3] = {0,0,0};
+ if (const char* rv =
+ this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
+ unsigned int v[3] = { 0, 0, 0 };
sscanf(rv, "%u.%u.%u", &v[0], &v[1], &v[2]);
- this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0],v[1],v[2]);
- }
+ this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]);
+ }
// Check for debug mode.
this->DebugMode = this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE");
// Lookup target architecture, if any.
- if(const char* arch =
- this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"))
- {
+ if (const char* arch =
+ this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
this->LibraryArchitecture = arch;
- }
+ }
+
+ // Lookup whether lib32 paths should be used.
+ if (this->Makefile->PlatformIs32Bit() &&
+ this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_LIB32_PATHS")) {
+ this->UseLib32Paths = true;
+ }
// Lookup whether lib64 paths should be used.
- if(this->Makefile->PlatformIs64Bit() &&
- this->Makefile->GetCMakeInstance()
- ->GetPropertyAsBool("FIND_LIBRARY_USE_LIB64_PATHS"))
- {
+ if (this->Makefile->PlatformIs64Bit() &&
+ this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_LIB64_PATHS")) {
this->UseLib64Paths = true;
+ }
+
+ // Lookup whether libx32 paths should be used.
+ if (this->Makefile->PlatformIsx32() &&
+ this->Makefile->GetState()->GetGlobalPropertyAsBool(
+ "FIND_LIBRARY_USE_LIBX32_PATHS")) {
+ this->UseLibx32Paths = true;
+ }
+
+ // Check if User Package Registry should be disabled
+ 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")) {
+ this->NoSystemRegistry = true;
+ }
+
+ // Check if Sorting should be enabled
+ if (const char* so =
+ this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) {
+
+ if (strcmp(so, "NAME") == 0) {
+ this->SortOrder = Name_order;
+ } else if (strcmp(so, "NATURAL") == 0) {
+ this->SortOrder = Natural;
+ } else {
+ this->SortOrder = None;
}
+ }
+ if (const char* sd =
+ this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) {
+ this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
+ }
+
+ this->SelectDefaultNoPackageRootPath();
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -442,358 +224,287 @@ bool cmFindPackageCommand
std::set<std::string> requiredComponents;
std::set<std::string> optionalComponents;
- // Check ancient compatibility.
- this->Compatibility_1_6 =
- this->Makefile->GetLocalGenerator()
- ->NeedBackwardsCompatibility(1, 6);
-
// Always search directly in a generated path.
this->SearchPathSuffixes.push_back("");
// Parse the arguments.
- enum Doing { DoingNone, DoingComponents, DoingOptionalComponents, DoingNames,
- DoingPaths, DoingPathSuffixes, DoingConfigs, DoingHints };
+ enum Doing
+ {
+ DoingNone,
+ DoingComponents,
+ DoingOptionalComponents,
+ DoingNames,
+ DoingPaths,
+ DoingPathSuffixes,
+ DoingConfigs,
+ DoingHints
+ };
Doing doing = DoingNone;
cmsys::RegularExpression version("^[0-9.]+$");
bool haveVersion = false;
std::set<unsigned int> configArgs;
std::set<unsigned int> moduleArgs;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "QUIET")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "QUIET") {
this->Quiet = true;
doing = DoingNone;
- }
- else if(args[i] == "EXACT")
- {
+ } else if (args[i] == "EXACT") {
this->VersionExact = true;
- this->Compatibility_1_6 = false;
doing = DoingNone;
- }
- else if(args[i] == "MODULE")
- {
+ } else if (args[i] == "MODULE") {
moduleArgs.insert(i);
doing = DoingNone;
- }
- else if(args[i] == "CONFIG")
- {
+ } else if (args[i] == "CONFIG") {
configArgs.insert(i);
doing = DoingNone;
- }
- else if(args[i] == "NO_MODULE")
- {
+ } else if (args[i] == "NO_MODULE") {
configArgs.insert(i);
doing = DoingNone;
- }
- else if(args[i] == "REQUIRED")
- {
+ } else if (args[i] == "REQUIRED") {
this->Required = true;
doing = DoingComponents;
- }
- else if(args[i] == "COMPONENTS")
- {
- this->Compatibility_1_6 = false;
+ } else if (args[i] == "COMPONENTS") {
doing = DoingComponents;
- }
- else if(args[i] == "OPTIONAL_COMPONENTS")
- {
- this->Compatibility_1_6 = false;
+ } else if (args[i] == "OPTIONAL_COMPONENTS") {
doing = DoingOptionalComponents;
- }
- else if(args[i] == "NAMES")
- {
+ } else if (args[i] == "NAMES") {
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingNames;
- }
- else if(args[i] == "PATHS")
- {
+ } else if (args[i] == "PATHS") {
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingPaths;
- }
- else if(args[i] == "HINTS")
- {
+ } else if (args[i] == "HINTS") {
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingHints;
- }
- else if(args[i] == "PATH_SUFFIXES")
- {
+ } else if (args[i] == "PATH_SUFFIXES") {
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingPathSuffixes;
- }
- else if(args[i] == "CONFIGS")
- {
+ } else if (args[i] == "CONFIGS") {
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingConfigs;
- }
- else if(args[i] == "NO_POLICY_SCOPE")
- {
+ } else if (args[i] == "NO_POLICY_SCOPE") {
this->PolicyScope = false;
- this->Compatibility_1_6 = false;
doing = DoingNone;
- }
- else if(args[i] == "NO_CMAKE_PACKAGE_REGISTRY")
- {
+ } else if (args[i] == "NO_CMAKE_PACKAGE_REGISTRY") {
this->NoUserRegistry = true;
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingNone;
- }
- else if(args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY")
- {
+ } else if (args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY") {
this->NoSystemRegistry = true;
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingNone;
- }
- else if(args[i] == "NO_CMAKE_BUILDS_PATH")
- {
- this->NoBuilds = true;
+ } else if (args[i] == "NO_CMAKE_BUILDS_PATH") {
+ // Ignore legacy option.
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingNone;
- }
- else if(this->CheckCommonArgument(args[i]))
- {
+ } else if (this->CheckCommonArgument(args[i])) {
configArgs.insert(i);
- this->Compatibility_1_6 = false;
doing = DoingNone;
- }
- else if((doing == DoingComponents) || (doing == DoingOptionalComponents))
- {
+ } else if ((doing == DoingComponents) ||
+ (doing == DoingOptionalComponents)) {
// Set a variable telling the find script whether this component
// is required.
const char* isRequired = "1";
- if (doing == DoingOptionalComponents)
- {
+ if (doing == DoingOptionalComponents) {
isRequired = "0";
optionalComponents.insert(args[i]);
- }
- else
- {
+ } else {
requiredComponents.insert(args[i]);
- }
+ }
std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i];
- this->AddFindDefinition(req_var.c_str(), isRequired);
+ this->AddFindDefinition(req_var, isRequired);
// Append to the list of required components.
components += components_sep;
components += args[i];
components_sep = ";";
- }
- else if(doing == DoingNames)
- {
+ } else if (doing == DoingNames) {
this->Names.push_back(args[i]);
- }
- else if(doing == DoingPaths)
- {
- this->AddUserPath(args[i], this->UserPaths);
- }
- else if(doing == DoingHints)
- {
- this->AddUserPath(args[i], this->UserHints);
- }
- else if(doing == DoingPathSuffixes)
- {
+ } else if (doing == DoingPaths) {
+ this->UserGuessArgs.push_back(args[i]);
+ } else if (doing == DoingHints) {
+ this->UserHintsArgs.push_back(args[i]);
+ } else if (doing == DoingPathSuffixes) {
this->AddPathSuffix(args[i]);
- }
- else if(doing == DoingConfigs)
- {
- if(args[i].find_first_of(":/\\") != args[i].npos ||
- cmSystemTools::GetFilenameLastExtension(args[i]) != ".cmake")
- {
- cmOStringStream e;
- e << "given CONFIGS option followed by invalid file name \""
- << args[i] << "\". The names given must be file names without "
+ } 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().c_str());
+ this->SetError(e.str());
return false;
- }
- this->Configs.push_back(args[i]);
}
- else if(!haveVersion && version.find(args[i].c_str()))
- {
+ this->Configs.push_back(args[i]);
+ } else if (!haveVersion && version.find(args[i].c_str())) {
haveVersion = true;
this->Version = args[i];
- }
- else
- {
- cmOStringStream e;
- e << "called with invalid argument \"" << args[i].c_str() << "\"";
- this->SetError(e.str().c_str());
+ } else {
+ std::ostringstream e;
+ e << "called with invalid argument \"" << args[i] << "\"";
+ this->SetError(e.str());
return false;
- }
}
+ }
std::vector<std::string> doubledComponents;
std::set_intersection(requiredComponents.begin(), requiredComponents.end(),
optionalComponents.begin(), optionalComponents.end(),
std::back_inserter(doubledComponents));
- if(!doubledComponents.empty())
- {
- cmOStringStream e;
+ if (!doubledComponents.empty()) {
+ std::ostringstream e;
e << "called with components that are both required and optional:\n";
- for(unsigned int i=0; i<doubledComponents.size(); ++i)
- {
- e << " " << doubledComponents[i] << "\n";
- }
- this->SetError(e.str().c_str());
+ e << cmWrap(" ", doubledComponents, "", "\n") << "\n";
+ this->SetError(e.str());
return false;
- }
+ }
// Maybe choose one mode exclusively.
this->UseFindModules = configArgs.empty();
this->UseConfigFiles = moduleArgs.empty();
- if(!this->UseFindModules && !this->UseConfigFiles)
- {
- cmOStringStream e;
+ 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)
- {
+ for (std::set<unsigned int>::const_iterator si = moduleArgs.begin();
+ si != moduleArgs.end(); ++si) {
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)
- {
+ for (std::set<unsigned int>::const_iterator si = configArgs.begin();
+ si != configArgs.end(); ++si) {
e << " " << args[*si] << "\n";
- }
+ }
e << "The options are incompatible.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Ignore EXACT with no version.
- if(this->Version.empty() && this->VersionExact)
- {
+ if (this->Version.empty() && this->VersionExact) {
this->VersionExact = false;
this->Makefile->IssueMessage(
cmake::AUTHOR_WARNING, "Ignoring EXACT since no version is requested.");
- }
+ }
- if(this->Version.empty() || components.empty())
- {
+ 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";
- if(this->Makefile->IsOn(mod.c_str()))
- {
- if(this->Version.empty())
- {
+ 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";
- this->Version = this->Makefile->GetSafeDefinition(ver.c_str());
+ this->Version = this->Makefile->GetSafeDefinition(ver);
// Whether an exact version is required.
std::string exact = this->Name;
exact += "_FIND_VERSION_EXACT";
- this->VersionExact = this->Makefile->IsOn(exact.c_str());
- }
- if(components.empty())
- {
+ this->VersionExact = this->Makefile->IsOn(exact);
+ }
+ if (components.empty()) {
std::string components_var = this->Name + "_FIND_COMPONENTS";
- components = this->Makefile->GetSafeDefinition(components_var.c_str());
- }
+ components = this->Makefile->GetSafeDefinition(components_var);
}
}
+ }
- if(!this->Version.empty())
- {
+ if (!this->Version.empty()) {
// Try to parse the version number and store the results that were
// successfully parsed.
unsigned int parsed_major;
unsigned int parsed_minor;
unsigned int parsed_patch;
unsigned int parsed_tweak;
- this->VersionCount = sscanf(this->Version.c_str(), "%u.%u.%u.%u",
- &parsed_major, &parsed_minor,
- &parsed_patch, &parsed_tweak);
- switch(this->VersionCount)
- {
- case 4: this->VersionTweak = parsed_tweak; // no break!
- case 3: this->VersionPatch = parsed_patch; // no break!
- case 2: this->VersionMinor = parsed_minor; // no break!
- case 1: this->VersionMajor = parsed_major; // no break!
- default: break;
- }
+ this->VersionCount =
+ sscanf(this->Version.c_str(), "%u.%u.%u.%u", &parsed_major,
+ &parsed_minor, &parsed_patch, &parsed_tweak);
+ switch (this->VersionCount) {
+ case 4:
+ this->VersionTweak = parsed_tweak;
+ CM_FALLTHROUGH;
+ case 3:
+ this->VersionPatch = parsed_patch;
+ CM_FALLTHROUGH;
+ case 2:
+ this->VersionMinor = parsed_minor;
+ CM_FALLTHROUGH;
+ case 1:
+ this->VersionMajor = parsed_major;
+ CM_FALLTHROUGH;
+ default:
+ break;
}
+ }
std::string disableFindPackageVar = "CMAKE_DISABLE_FIND_PACKAGE_";
disableFindPackageVar += this->Name;
- if(this->Makefile->IsOn(disableFindPackageVar.c_str()))
- {
- if (this->Required)
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
-
- return true;
}
+ return true;
+ }
this->SetModuleVariables(components);
// See if there is a Find<package>.cmake module.
- if(this->UseFindModules)
- {
+ if (this->UseFindModules) {
bool foundModule = false;
- if(!this->FindModule(foundModule))
- {
+ if (!this->FindModule(foundModule)) {
this->AppendSuccessInformation();
return false;
- }
- if(foundModule)
- {
+ }
+ if (foundModule) {
this->AppendSuccessInformation();
return true;
- }
}
+ }
- if(this->UseFindModules && this->UseConfigFiles &&
- this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE"))
- {
- cmOStringStream aw;
- if(this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2,8,8))
- {
+ 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.";
- }
+ "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.)";
+ "(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.
@@ -801,17 +512,14 @@ bool cmFindPackageCommand
this->Variable += "_DIR";
// Add the default name.
- if(this->Names.empty())
- {
+ if (this->Names.empty()) {
this->Names.push_back(this->Name);
- }
+ }
// Add the default configs.
- if(this->Configs.empty())
- {
- for(std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni)
- {
+ 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";
this->Configs.push_back(config);
@@ -819,8 +527,8 @@ bool cmFindPackageCommand
config = cmSystemTools::LowerCase(*ni);
config += "-config.cmake";
this->Configs.push_back(config);
- }
}
+ }
// get igonored paths from vars and reroot them.
std::vector<std::string> ignored;
@@ -837,116 +545,104 @@ bool cmFindPackageCommand
return result;
}
-
-//----------------------------------------------------------------------------
void cmFindPackageCommand::SetModuleVariables(const std::string& components)
{
this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name.c_str());
// Store the list of components.
std::string components_var = this->Name + "_FIND_COMPONENTS";
- this->AddFindDefinition(components_var.c_str(), components.c_str());
+ this->AddFindDefinition(components_var, components.c_str());
- if(this->Quiet)
- {
+ 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";
- this->AddFindDefinition(quietly.c_str(), "1");
- }
+ this->AddFindDefinition(quietly, "1");
+ }
- if(this->Required)
- {
+ 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";
- this->AddFindDefinition(req.c_str(), "1");
- }
+ this->AddFindDefinition(req, "1");
+ }
- if(!this->Version.empty())
- {
+ 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";
- this->AddFindDefinition(ver.c_str(), this->Version.c_str());
+ this->AddFindDefinition(ver, this->Version.c_str());
char buf[64];
sprintf(buf, "%u", this->VersionMajor);
- this->AddFindDefinition((ver+"_MAJOR").c_str(), buf);
+ this->AddFindDefinition(ver + "_MAJOR", buf);
sprintf(buf, "%u", this->VersionMinor);
- this->AddFindDefinition((ver+"_MINOR").c_str(), buf);
+ this->AddFindDefinition(ver + "_MINOR", buf);
sprintf(buf, "%u", this->VersionPatch);
- this->AddFindDefinition((ver+"_PATCH").c_str(), buf);
+ this->AddFindDefinition(ver + "_PATCH", buf);
sprintf(buf, "%u", this->VersionTweak);
- this->AddFindDefinition((ver+"_TWEAK").c_str(), buf);
+ this->AddFindDefinition(ver + "_TWEAK", buf);
sprintf(buf, "%u", this->VersionCount);
- this->AddFindDefinition((ver+"_COUNT").c_str(), buf);
+ this->AddFindDefinition(ver + "_COUNT", buf);
// Tell the module whether an exact version has been requested.
std::string exact = this->Name;
exact += "_FIND_VERSION_EXACT";
- this->AddFindDefinition(exact.c_str(), this->VersionExact? "1":"0");
- }
+ this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
+ }
+
+ // Push on to the pacakge stack
+ this->Makefile->FindPackageModuleStack.push_back(this->Name);
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddFindDefinition(const char* var, const char* val)
+void cmFindPackageCommand::AddFindDefinition(const std::string& var,
+ const char* val)
{
- if(const char* old = this->Makefile->GetDefinition(var))
- {
+ if (const char* old = this->Makefile->GetDefinition(var)) {
this->OriginalDefs[var].exists = true;
this->OriginalDefs[var].value = old;
- }
- else
- {
+ } else {
this->OriginalDefs[var].exists = false;
- }
+ }
this->Makefile->AddDefinition(var, val);
}
-//----------------------------------------------------------------------------
void cmFindPackageCommand::RestoreFindDefinitions()
{
- for(std::map<cmStdString, OriginalDef>::iterator
- i = this->OriginalDefs.begin(); i != this->OriginalDefs.end(); ++i)
- {
+ for (std::map<std::string, OriginalDef>::iterator i =
+ this->OriginalDefs.begin();
+ i != this->OriginalDefs.end(); ++i) {
OriginalDef const& od = i->second;
- if(od.exists)
- {
- this->Makefile->AddDefinition(i->first.c_str(), od.value.c_str());
- }
- else
- {
- this->Makefile->RemoveDefinition(i->first.c_str());
- }
+ if (od.exists) {
+ this->Makefile->AddDefinition(i->first, od.value.c_str());
+ } else {
+ 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());
- if ( mfile.size() )
- {
+ if (!mfile.empty()) {
// 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";
- this->Makefile->AddDefinition(var.c_str(), "1");
+ this->Makefile->AddDefinition(var, "1");
bool result = this->ReadListFile(mfile.c_str(), DoPolicyScope);
- this->Makefile->RemoveDefinition(var.c_str());
+ this->Makefile->RemoveDefinition(var);
return result;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::HandlePackageMode()
{
this->ConsideredConfigs.clear();
@@ -956,66 +652,44 @@ bool cmFindPackageCommand::HandlePackageMode()
std::string upperFound = cmSystemTools::UpperCase(this->Name);
upperDir += "_DIR";
upperFound += "_FOUND";
- if(upperDir == this->Variable)
- {
- this->Compatibility_1_6 = false;
- }
// Try to find the config file.
- const char* def = this->Makefile->GetDefinition(this->Variable.c_str());
- if(this->Compatibility_1_6 && cmSystemTools::IsOff(def))
- {
- // Use the setting of the old name of the variable to provide the
- // value of the new.
- const char* oldDef = this->Makefile->GetDefinition(upperDir.c_str());
- if(!cmSystemTools::IsOff(oldDef))
- {
- this->Makefile->AddDefinition(this->Variable.c_str(), oldDef);
- def = this->Makefile->GetDefinition(this->Variable.c_str());
- }
- }
+ 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 (this->UseConfigFiles) {
+ if (!cmSystemTools::IsOff(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.c_str())) {
dir = "/" + dir;
- dir = this->Makefile->GetCurrentDirectory() + dir;
- }
+ dir = this->Makefile->GetCurrentSourceDirectory() + dir;
+ }
// The file location was cached. Look for the correct file.
std::string file;
- if (this->FindConfigFile(dir, file))
- {
+ if (this->FindConfigFile(dir, file)) {
this->FileFound = file;
fileFound = true;
- }
- def = this->Makefile->GetDefinition(this->Variable.c_str());
}
+ def = this->Makefile->GetDefinition(this->Variable);
+ }
// Search for the config file if it is not already found.
- if(cmSystemTools::IsOff(def) || !fileFound)
- {
+ if (cmSystemTools::IsOff(def) || !fileFound) {
fileFound = this->FindConfig();
- def = this->Makefile->GetDefinition(this->Variable.c_str());
- }
+ }
// Sanity check.
- if(fileFound && this->FileFound.empty())
- {
+ if (fileFound && this->FileFound.empty()) {
this->Makefile->IssueMessage(
cmake::INTERNAL_ERROR, "fileFound is true but FileFound is empty!");
fileFound = false;
- }
}
+ }
std::string foundVar = this->Name;
foundVar += "_FOUND";
@@ -1028,209 +702,168 @@ bool cmFindPackageCommand::HandlePackageMode()
bool found = false;
bool configFileSetFOUNDFalse = false;
- if(fileFound)
- {
- if ((this->Makefile->IsDefinitionSet(foundVar.c_str()))
- && (this->Makefile->IsOn(foundVar.c_str()) == false))
- {
+ if (fileFound) {
+ if (this->Makefile->IsDefinitionSet(foundVar) &&
+ !this->Makefile->IsOn(foundVar)) {
// by removing Foo_FOUND here if it is FALSE, we don't really change
// the situation for the Config file which is about to be included,
// but we make it possible to detect later on whether the Config file
// has set Foo_FOUND to FALSE itself:
- this->Makefile->RemoveDefinition(foundVar.c_str());
- }
- this->Makefile->RemoveDefinition(notFoundMessageVar.c_str());
+ this->Makefile->RemoveDefinition(foundVar);
+ }
+ this->Makefile->RemoveDefinition(notFoundMessageVar);
// Set the version variables before loading the config file.
// It may override them.
this->StoreVersionFound();
// Parse the configuration file.
- if(this->ReadListFile(this->FileFound.c_str(), DoPolicyScope))
- {
+ if (this->ReadListFile(this->FileFound.c_str(), DoPolicyScope)) {
// The package has been found.
found = true;
// Check whether the Config file has set Foo_FOUND to FALSE:
- if ((this->Makefile->IsDefinitionSet(foundVar.c_str()))
- && (this->Makefile->IsOn(foundVar.c_str()) == false))
- {
+ if (this->Makefile->IsDefinitionSet(foundVar) &&
+ !this->Makefile->IsOn(foundVar)) {
// we get here if the Config file has set Foo_FOUND actively to FALSE
found = false;
configFileSetFOUNDFalse = true;
- notFoundMessage = this->Makefile->GetSafeDefinition(
- notFoundMessageVar.c_str());
- }
+ notFoundMessage =
+ this->Makefile->GetSafeDefinition(notFoundMessageVar);
}
- else
- {
+ } else {
// The configuration file is invalid.
result = false;
- }
}
+ }
- if (result && !found && (!this->Quiet || this->Required))
- {
- // The variable is not set.
- cmOStringStream e;
- cmOStringStream aw;
- if (configFileSetFOUNDFalse)
- {
- e << "Found package configuration file:\n"
- " " << this->FileFound << "\n"
- "but it set " << foundVar << " to FALSE so package \"" <<
- this->Name << "\" is considered to be NOT FOUND.";
- if (!notFoundMessage.empty())
- {
- e << " Reason given by package: \n" << notFoundMessage << "\n";
+ // 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()))) {
+ // The variable is not set.
+ std::ostringstream e;
+ std::ostringstream aw;
+ if (configFileSetFOUNDFalse) {
+ /* clang-format off */
+ e << "Found package configuration file:\n"
+ " " << this->FileFound << "\n"
+ "but it set " << foundVar << " to FALSE so package \"" <<
+ this->Name << "\" is considered to be NOT FOUND.";
+ /* clang-format on */
+ if (!notFoundMessage.empty()) {
+ e << " Reason given by package: \n" << notFoundMessage << "\n";
}
}
- // 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.size() > 0)
- {
- 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>::size_type i=0;
- i<this->ConsideredConfigs.size(); i++)
- {
- e << " " << this->ConsideredConfigs[i].filename
- << ", version: " << this->ConsideredConfigs[i].version << "\n";
+ // 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);
+ 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";
}
- }
- else
- {
- std::string requestedVersionString;
- if(!this->Version.empty())
- {
- requestedVersionString = " (requested version ";
- requestedVersionString += this->Version;
- requestedVersionString += ")";
+ } else {
+ std::string requestedVersionString;
+ if (!this->Version.empty()) {
+ requestedVersionString = " (requested version ";
+ requestedVersionString += this->Version;
+ requestedVersionString += ")";
}
- if (this->UseConfigFiles)
- {
- if(this->UseFindModules)
- {
- e << "By not providing \"Find" << this->Name << ".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";
+ if (this->UseConfigFiles) {
+ if (this->UseFindModules) {
+ e << "By not providing \"Find" << this->Name
+ << ".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";
}
- if(this->Configs.size() == 1)
- {
- e << "Could not find a package configuration file named \""
- << this->Configs[0] << "\" provided by package \""
- << this->Name << "\"" << requestedVersionString <<".\n";
- }
- else
- {
- e << "Could not find a package configuration file provided by \""
- << this->Name << "\"" << requestedVersionString
- << " with any of the following names:\n";
- for(std::vector<std::string>::const_iterator ci =
- this->Configs.begin();
- ci != this->Configs.end(); ++ci)
- {
- e << " " << *ci << "\n";
- }
+ if (this->Configs.size() == 1) {
+ e << "Could not find a package configuration file named \""
+ << this->Configs[0] << "\" provided by package \"" << this->Name
+ << "\"" << requestedVersionString << ".\n";
+ } else {
+ e << "Could not find a package configuration file provided by \""
+ << this->Name << "\"" << requestedVersionString
+ << " with any of the following names:\n"
+ << cmWrap(" ", this->Configs, "", "\n") << "\n";
}
- e << "Add the installation prefix of \"" << this->Name << "\" to "
- "CMAKE_PREFIX_PATH or set \"" << this->Variable << "\" 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.";
- }
- else // if(!this->UseFindModules && !this->UseConfigFiles)
+ e << "Add the installation prefix of \"" << this->Name
+ << "\" to "
+ "CMAKE_PREFIX_PATH or set \""
+ << this->Variable
+ << "\" 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.";
+ } else // if(!this->UseFindModules && !this->UseConfigFiles)
{
- e << "No \"Find" << this->Name << ".cmake\" found in "
- << "CMAKE_MODULE_PATH.";
-
- aw<< "Find"<< this->Name <<".cmake must either be part of this "
- "project itself, in this case adjust CMAKE_MODULE_PATH so that "
- "it points to the correct location inside its source tree.\n"
- "Or it must be installed by a package which has already been "
- "found via find_package(). In this case make sure that "
- "package has indeed been found and adjust CMAKE_MODULE_PATH to "
- "contain the location where that package has installed "
- "Find" << this->Name << ".cmake. This must be a location "
- "provided by that package. This error in general means that "
- "the buildsystem of this project is relying on a Find-module "
- "without ensuring that it is actually available.\n";
+ e << "No \"Find" << this->Name << ".cmake\" found in "
+ << "CMAKE_MODULE_PATH.";
+
+ aw
+ << "Find" << this->Name
+ << ".cmake must either be part of this "
+ "project itself, in this case adjust CMAKE_MODULE_PATH so that "
+ "it points to the correct location inside its source tree.\n"
+ "Or it must be installed by a package which has already been "
+ "found via find_package(). In this case make sure that "
+ "package has indeed been found and adjust CMAKE_MODULE_PATH to "
+ "contain the location where that package has installed "
+ "Find"
+ << this->Name
+ << ".cmake. This must be a location "
+ "provided by that package. This error in general means that "
+ "the buildsystem of this project is relying on a Find-module "
+ "without ensuring that it is actually available.\n";
}
}
-
- this->Makefile->IssueMessage(
- this->Required? cmake::FATAL_ERROR : cmake::WARNING, e.str());
- if (this->Required)
- {
- cmSystemTools::SetFatalErrorOccured();
+ this->Makefile->IssueMessage(
+ this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str());
+ if (this->Required) {
+ cmSystemTools::SetFatalErrorOccured();
}
- if (!aw.str().empty())
- {
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,aw.str());
+ if (!aw.str().empty()) {
+ this->Makefile->IssueMessage(cmake::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);
+ }
+ }
// Set a variable marking whether the package was found.
- this->Makefile->AddDefinition(foundVar.c_str(), found? "1":"0");
+ this->Makefile->AddDefinition(foundVar, found ? "1" : "0");
// Set a variable naming the configuration file that was found.
std::string fileVar = this->Name;
fileVar += "_CONFIG";
- if(found)
- {
- this->Makefile->AddDefinition(fileVar.c_str(), this->FileFound.c_str());
- }
- else
- {
- this->Makefile->RemoveDefinition(fileVar.c_str());
- }
-
- // Handle some ancient compatibility stuff.
- if(this->Compatibility_1_6)
- {
- // Listfiles will be looking for the capitalized version of the
- // name. Provide it.
- this->Makefile->AddDefinition
- (upperDir.c_str(),
- this->Makefile->GetDefinition(this->Variable.c_str()));
- this->Makefile->AddDefinition
- (upperFound.c_str(),
- this->Makefile->GetDefinition(foundVar.c_str()));
- }
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
- if(!(upperDir == this->Variable))
- {
- if(this->Compatibility_1_6)
- {
- // Listfiles may use the capitalized version of the name.
- // Remove any previously added watch.
- this->Makefile->GetVariableWatch()->RemoveWatch(
- upperDir.c_str(),
- cmFindPackageNeedBackwardsCompatibility
- );
- }
- else
- {
- // Listfiles should not be using the capitalized version of the
- // name. Add a watch to warn the user.
- this->Makefile->GetVariableWatch()->AddWatch(
- upperDir.c_str(),
- cmFindPackageNeedBackwardsCompatibility
- );
- }
- }
-#endif
+ if (found) {
+ this->Makefile->AddDefinition(fileVar, this->FileFound.c_str());
+ } else {
+ this->Makefile->RemoveDefinition(fileVar);
+ }
std::string consideredConfigsVar = this->Name;
consideredConfigsVar += "_CONSIDERED_CONFIGS";
@@ -1241,26 +874,25 @@ bool cmFindPackageCommand::HandlePackageMode()
std::string consideredVersions;
const char* sep = "";
- for(std::vector<ConfigFileInfo>::size_type i=0;
- i<this->ConsideredConfigs.size(); i++)
- {
+ for (std::vector<ConfigFileInfo>::const_iterator i =
+ this->ConsideredConfigs.begin();
+ i != this->ConsideredConfigs.end(); ++i) {
consideredConfigFiles += sep;
consideredVersions += sep;
- consideredConfigFiles += this->ConsideredConfigs[i].filename;
- consideredVersions += this->ConsideredConfigs[i].version;
+ consideredConfigFiles += i->filename;
+ consideredVersions += i->version;
sep = ";";
- }
+ }
- this->Makefile->AddDefinition(consideredConfigsVar.c_str(),
+ this->Makefile->AddDefinition(consideredConfigsVar,
consideredConfigFiles.c_str());
- this->Makefile->AddDefinition(consideredVersionsVar.c_str(),
+ this->Makefile->AddDefinition(consideredVersionsVar,
consideredVersions.c_str());
return result;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::FindConfig()
{
// Compute the set of search prefixes.
@@ -1270,196 +902,155 @@ bool cmFindPackageCommand::FindConfig()
bool found = false;
// Search for frameworks.
- if(!found && (this->SearchFrameworkFirst || this->SearchFrameworkOnly))
- {
+ if (!found && (this->SearchFrameworkFirst || this->SearchFrameworkOnly)) {
found = this->FindFrameworkConfig();
- }
+ }
// Search for apps.
- if(!found && (this->SearchAppBundleFirst || this->SearchAppBundleOnly))
- {
+ if (!found && (this->SearchAppBundleFirst || this->SearchAppBundleOnly)) {
found = this->FindAppBundleConfig();
- }
+ }
// Search prefixes.
- if(!found && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly))
- {
+ if (!found && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) {
found = this->FindPrefixedConfig();
- }
+ }
// Search for frameworks.
- if(!found && this->SearchFrameworkLast)
- {
+ if (!found && this->SearchFrameworkLast) {
found = this->FindFrameworkConfig();
- }
+ }
// Search for apps.
- if(!found && this->SearchAppBundleLast)
- {
+ if (!found && this->SearchAppBundleLast) {
found = this->FindAppBundleConfig();
- }
+ }
// Store the entry in the cache so it can be set by the user.
std::string init;
- if(found)
- {
+ if (found) {
init = cmSystemTools::GetFilenamePath(this->FileFound);
- }
- else
- {
+ } else {
init = this->Variable + "-NOTFOUND";
- }
+ }
std::string help =
"The directory containing a CMake configuration file for ";
help += this->Name;
help += ".";
// We force the value since we do not get here if it was already set.
- this->Makefile->AddCacheDefinition(this->Variable.c_str(),
- init.c_str(), help.c_str(),
- cmCacheManager::PATH, true);
+ this->Makefile->AddCacheDefinition(this->Variable, init.c_str(),
+ help.c_str(), cmStateEnums::PATH, true);
return found;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::FindPrefixedConfig()
{
- std::vector<std::string>& prefixes = this->SearchPaths;
- for(std::vector<std::string>::const_iterator pi = prefixes.begin();
- pi != prefixes.end(); ++pi)
- {
- if(this->SearchPrefix(*pi))
- {
+ 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)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::FindFrameworkConfig()
{
- std::vector<std::string>& prefixes = this->SearchPaths;
- for(std::vector<std::string>::const_iterator i = prefixes.begin();
- i != prefixes.end(); ++i)
- {
- if(this->SearchFrameworkPrefix(*i))
- {
+ 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)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::FindAppBundleConfig()
{
- std::vector<std::string>& prefixes = this->SearchPaths;
- for(std::vector<std::string>::const_iterator i = prefixes.begin();
- i != prefixes.end(); ++i)
- {
- if(this->SearchAppBundlePrefix(*i))
- {
+ 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)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::ReadListFile(const char* f, PolicyScopeRule psr)
{
- if(this->Makefile->ReadListFile(this->Makefile->GetCurrentListFile(), f, 0,
- !this->PolicyScope || psr == NoPolicyScope))
- {
+ 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 += "\".";
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
void cmFindPackageCommand::AppendToFoundProperty(bool found)
{
std::vector<std::string> foundContents;
- const char *foundProp =
- this->Makefile->GetCMakeInstance()->GetProperty("PACKAGES_FOUND");
- if (foundProp && *foundProp)
- {
+ const char* foundProp =
+ this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND");
+ if (foundProp && *foundProp) {
std::string tmp = foundProp;
cmSystemTools::ExpandListArgument(tmp, foundContents, false);
- std::vector<std::string>::iterator nameIt = std::find(
- foundContents.begin(), foundContents.end(), this->Name);
- if(nameIt != foundContents.end())
- {
+ std::vector<std::string>::iterator nameIt =
+ std::find(foundContents.begin(), foundContents.end(), this->Name);
+ if (nameIt != foundContents.end()) {
foundContents.erase(nameIt);
- }
}
+ }
std::vector<std::string> notFoundContents;
- const char *notFoundProp =
- this->Makefile->GetCMakeInstance()->GetProperty("PACKAGES_NOT_FOUND");
- if (notFoundProp && *notFoundProp)
- {
+ const char* notFoundProp =
+ this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND");
+ if (notFoundProp && *notFoundProp) {
std::string tmp = notFoundProp;
cmSystemTools::ExpandListArgument(tmp, notFoundContents, false);
- std::vector<std::string>::iterator nameIt = std::find(
- notFoundContents.begin(), notFoundContents.end(), this->Name);
- if(nameIt != notFoundContents.end())
- {
+ std::vector<std::string>::iterator nameIt =
+ std::find(notFoundContents.begin(), notFoundContents.end(), this->Name);
+ if (nameIt != notFoundContents.end()) {
notFoundContents.erase(nameIt);
- }
}
+ }
- if(found)
- {
+ if (found) {
foundContents.push_back(this->Name);
- }
- else
- {
+ } else {
notFoundContents.push_back(this->Name);
- }
-
-
- std::string tmp;
- const char* sep ="";
- for(size_t i=0; i<foundContents.size(); i++)
- {
- tmp += sep;
- tmp += foundContents[i];
- sep = ";";
- }
+ }
- this->Makefile->GetCMakeInstance()->SetProperty("PACKAGES_FOUND",
- tmp.c_str());
+ std::string tmp = cmJoin(foundContents, ";");
+ this->Makefile->GetState()->SetGlobalProperty("PACKAGES_FOUND", tmp.c_str());
- tmp = "";
- sep = "";
- for(size_t i=0; i<notFoundContents.size(); i++)
- {
- tmp += sep;
- tmp += notFoundContents[i];
- sep = ";";
- }
- this->Makefile->GetCMakeInstance()->SetProperty("PACKAGES_NOT_FOUND",
- tmp.c_str());
+ tmp = cmJoin(notFoundContents, ";");
+ this->Makefile->GetState()->SetGlobalProperty("PACKAGES_NOT_FOUND",
+ tmp.c_str());
}
-//----------------------------------------------------------------------------
void cmFindPackageCommand::AppendSuccessInformation()
{
+ {
+ std::string transitivePropName = "_CMAKE_";
+ transitivePropName += this->Name + "_TRANSITIVE_DEPENDENCY";
+ this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False");
+ }
std::string found = this->Name;
found += "_FOUND";
std::string upperFound = cmSystemTools::UpperCase(found);
- const char* upperResult = this->Makefile->GetDefinition(upperFound.c_str());
- const char* result = this->Makefile->GetDefinition(found.c_str());
- bool packageFound = ((cmSystemTools::IsOn(result))
- || (cmSystemTools::IsOn(upperResult)));
+ const char* upperResult = this->Makefile->GetDefinition(upperFound);
+ const char* result = this->Makefile->GetDefinition(found);
+ bool packageFound =
+ ((cmSystemTools::IsOn(result)) || (cmSystemTools::IsOn(upperResult)));
this->AppendToFoundProperty(packageFound);
@@ -1468,147 +1059,160 @@ void cmFindPackageCommand::AppendSuccessInformation()
std::string quietInfoPropName = "_CMAKE_";
quietInfoPropName += this->Name;
quietInfoPropName += "_QUIET";
- this->Makefile->GetCMakeInstance()->SetProperty(quietInfoPropName.c_str(),
- this->Quiet ? "TRUE" : "FALSE");
+ 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 versionInfo;
- if(!this->Version.empty())
- {
+ if (!this->Version.empty()) {
versionInfo = this->VersionExact ? "==" : ">=";
versionInfo += " ";
versionInfo += this->Version;
- }
- this->Makefile->GetCMakeInstance()->SetProperty(versionInfoPropName.c_str(),
- versionInfo.c_str());
- if (this->Required)
- {
+ }
+ this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
+ versionInfo.c_str());
+ if (this->Required) {
std::string requiredInfoPropName = "_CMAKE_";
requiredInfoPropName += this->Name;
requiredInfoPropName += "_TYPE";
- this->Makefile->GetCMakeInstance()->SetProperty(
- requiredInfoPropName.c_str(), "REQUIRED");
- }
-
+ this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
+ "REQUIRED");
+ }
// Restore original state of "_FIND_" variables we set.
this->RestoreFindDefinitions();
+
+ // Pop the package stack
+ this->Makefile->FindPackageModuleStack.pop_back();
}
-//----------------------------------------------------------------------------
void cmFindPackageCommand::ComputePrefixes()
{
- this->AddPrefixesCMakeVariable();
- this->AddPrefixesCMakeEnvironment();
- this->AddPrefixesUserHints();
- this->AddPrefixesSystemEnvironment();
- this->AddPrefixesUserRegistry();
- this->AddPrefixesBuilds();
- this->AddPrefixesCMakeSystemVariable();
- this->AddPrefixesSystemRegistry();
- this->AddPrefixesUserGuess();
+ if (!this->NoDefaultPath) {
+ if (!this->NoPackageRootPath) {
+ this->FillPrefixesPackageRoot();
+ }
+ if (!this->NoCMakePath) {
+ this->FillPrefixesCMakeVariable();
+ }
+ if (!this->NoCMakeEnvironmentPath) {
+ this->FillPrefixesCMakeEnvironment();
+ }
+ }
+ this->FillPrefixesUserHints();
+ if (!this->NoDefaultPath) {
+ if (!this->NoSystemEnvironmentPath) {
+ this->FillPrefixesSystemEnvironment();
+ }
+ if (!this->NoUserRegistry) {
+ this->FillPrefixesUserRegistry();
+ }
+ if (!this->NoCMakeSystemPath) {
+ this->FillPrefixesCMakeSystemVariable();
+ }
+ if (!this->NoSystemRegistry) {
+ this->FillPrefixesSystemRegistry();
+ }
+ }
+ this->FillPrefixesUserGuess();
+
this->ComputeFinalPaths();
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesCMakeEnvironment()
+void cmFindPackageCommand::FillPrefixesPackageRoot()
{
- if(!this->NoCMakeEnvironmentPath && !this->NoDefaultPath)
- {
- // Check the environment variable with the same name as the cache
- // entry.
- std::string env;
- if(cmSystemTools::GetEnv(this->Variable.c_str(), env) && env.length() > 0)
- {
- cmSystemTools::ConvertToUnixSlashes(env);
- this->AddPathInternal(env, EnvPath);
- }
-
- this->AddEnvPath("CMAKE_PREFIX_PATH");
- this->AddEnvPath("CMAKE_FRAMEWORK_PATH");
- this->AddEnvPath("CMAKE_APPBUNDLE_PATH");
- }
+ 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);
+ }
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesCMakeVariable()
+void cmFindPackageCommand::FillPrefixesCMakeEnvironment()
{
- if(!this->NoCMakePath && !this->NoDefaultPath)
- {
- this->AddCMakePath("CMAKE_PREFIX_PATH");
- this->AddCMakePath("CMAKE_FRAMEWORK_PATH");
- this->AddCMakePath("CMAKE_APPBUNDLE_PATH");
- }
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
+
+ // Check the environment variable with the same name as the cache
+ // entry.
+ paths.AddEnvPath(this->Variable);
+
+ // And now the general CMake environment variables
+ paths.AddEnvPath("CMAKE_PREFIX_PATH");
+ paths.AddEnvPath("CMAKE_FRAMEWORK_PATH");
+ paths.AddEnvPath("CMAKE_APPBUNDLE_PATH");
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesSystemEnvironment()
+void cmFindPackageCommand::FillPrefixesCMakeVariable()
{
- if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
- {
- // Use the system search path to generate prefixes.
- // Relative paths are interpreted with respect to the current
- // working directory.
- std::vector<std::string> tmp;
- cmSystemTools::GetPath(tmp);
- for(std::vector<std::string>::iterator i = tmp.begin();
- i != tmp.end(); ++i)
- {
- std::string const& d = *i;
-
- // If the path is a PREFIX/bin case then add its parent instead.
- if((d.size() >= 4 && strcmp(d.c_str()+d.size()-4, "/bin") == 0) ||
- (d.size() >= 5 && strcmp(d.c_str()+d.size()-5, "/sbin") == 0))
- {
- this->AddPathInternal(cmSystemTools::GetFilenamePath(d), EnvPath);
- }
- else
- {
- this->AddPathInternal(d, EnvPath);
- }
- }
- }
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
+
+ paths.AddCMakePath("CMAKE_PREFIX_PATH");
+ paths.AddCMakePath("CMAKE_FRAMEWORK_PATH");
+ paths.AddCMakePath("CMAKE_APPBUNDLE_PATH");
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesUserRegistry()
+void cmFindPackageCommand::FillPrefixesSystemEnvironment()
{
- if(this->NoUserRegistry || this->NoDefaultPath)
- {
- return;
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemEnvironment];
+
+ // Use the system search path to generate prefixes.
+ // Relative paths are interpreted with respect to the current
+ // working directory.
+ std::vector<std::string> tmp;
+ cmSystemTools::GetPath(tmp);
+ for (std::vector<std::string>::iterator i = tmp.begin(); i != tmp.end();
+ ++i) {
+ // 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));
+ } else {
+ paths.AddPath(*i);
}
+ }
+}
+void cmFindPackageCommand::FillPrefixesUserRegistry()
+{
#if defined(_WIN32) && !defined(__CYGWIN__)
this->LoadPackageRegistryWinUser();
#elif defined(__HAIKU__)
- BPath dir;
- if (find_directory(B_USER_SETTINGS_DIRECTORY, &dir) == B_OK)
- {
- dir.Append("cmake/packages");
- dir.Append(this->Name.c_str());
- this->LoadPackageRegistryDir(dir.Path());
- }
+ 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;
+ this->LoadPackageRegistryDir(fname,
+ this->LabeledPaths[PathLabel::UserRegistry]);
+ }
#else
- if(const char* home = cmSystemTools::GetEnv("HOME"))
- {
- std::string dir = home;
+ std::string dir;
+ if (cmSystemTools::GetEnv("HOME", dir)) {
dir += "/.cmake/packages/";
dir += this->Name;
- this->LoadPackageRegistryDir(dir);
- }
+ this->LoadPackageRegistryDir(dir,
+ this->LabeledPaths[PathLabel::UserRegistry]);
+ }
#endif
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesSystemRegistry()
+void cmFindPackageCommand::FillPrefixesSystemRegistry()
{
- if(this->NoSystemRegistry || this->NoDefaultPath)
- {
+ if (this->NoSystemRegistry || this->NoDefaultPath) {
return;
- }
+ }
#if defined(_WIN32) && !defined(__CYGWIN__)
this->LoadPackageRegistryWinSystem();
@@ -1616,299 +1220,256 @@ void cmFindPackageCommand::AddPrefixesSystemRegistry()
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <windows.h>
-# undef GetCurrentDirectory
- // 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
-//----------------------------------------------------------------------------
+#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
void cmFindPackageCommand::LoadPackageRegistryWinUser()
{
// HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views.
- this->LoadPackageRegistryWin(true, 0);
+ this->LoadPackageRegistryWin(true, 0,
+ this->LabeledPaths[PathLabel::UserRegistry]);
}
-//----------------------------------------------------------------------------
void cmFindPackageCommand::LoadPackageRegistryWinSystem()
{
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemRegistry];
+
// HKEY_LOCAL_MACHINE\\SOFTWARE has separate 32-bit and 64-bit views.
// Prefer the target platform view first.
- if(this->Makefile->PlatformIs64Bit())
- {
- this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY);
- this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY);
- }
- else
- {
- this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY);
- this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY);
- }
+ if (this->Makefile->PlatformIs64Bit()) {
+ this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths);
+ this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths);
+ } else {
+ this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths);
+ this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths);
+ }
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
- unsigned int view)
+void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view,
+ cmSearchPath& outPaths)
{
- std::string key = "Software\\Kitware\\CMake\\Packages\\";
- key += this->Name;
- std::set<cmStdString> bad;
+ std::wstring key = L"Software\\Kitware\\CMake\\Packages\\";
+ key += cmsys::Encoding::ToWide(this->Name);
+ std::set<std::wstring> bad;
HKEY hKey;
- if(RegOpenKeyEx(user? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(),
- 0, KEY_QUERY_VALUE|view, &hKey) == ERROR_SUCCESS)
- {
+ if (RegOpenKeyExW(user ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(),
+ 0, KEY_QUERY_VALUE | view, &hKey) == ERROR_SUCCESS) {
DWORD valueType = REG_NONE;
- char name[16384];
- std::vector<char> data(512);
+ wchar_t name[16383]; // RegEnumValue docs limit name to 32767 _bytes_
+ std::vector<wchar_t> data(512);
bool done = false;
DWORD index = 0;
- while(!done)
- {
+ while (!done) {
DWORD nameSize = static_cast<DWORD>(sizeof(name));
- DWORD dataSize = static_cast<DWORD>(data.size()-1);
- switch(RegEnumValue(hKey, index, name, &nameSize,
- 0, &valueType, (BYTE*)&data[0], &dataSize))
- {
+ DWORD dataSize = static_cast<DWORD>(data.size() * sizeof(data[0]));
+ switch (RegEnumValueW(hKey, index, name, &nameSize, 0, &valueType,
+ (BYTE*)&data[0], &dataSize)) {
case ERROR_SUCCESS:
++index;
- if(valueType == REG_SZ)
- {
+ if (valueType == REG_SZ) {
data[dataSize] = 0;
- cmsys_ios::stringstream ss(&data[0]);
- if(!this->CheckPackageRegistryEntry(ss))
- {
+ if (!this->CheckPackageRegistryEntry(
+ cmsys::Encoding::ToNarrow(&data[0]), outPaths)) {
// The entry is invalid.
bad.insert(name);
- }
}
+ }
break;
case ERROR_MORE_DATA:
- data.resize(dataSize+1);
+ data.resize((dataSize + sizeof(data[0]) - 1) / sizeof(data[0]));
+ break;
+ case ERROR_NO_MORE_ITEMS:
+ default:
+ done = true;
break;
- case ERROR_NO_MORE_ITEMS: default: done = true; break;
- }
}
- RegCloseKey(hKey);
}
+ RegCloseKey(hKey);
+ }
// Remove bad values if possible.
- if(user && !bad.empty() &&
- RegOpenKeyEx(HKEY_CURRENT_USER, key.c_str(),
- 0, KEY_SET_VALUE|view, &hKey) == ERROR_SUCCESS)
- {
- for(std::set<cmStdString>::const_iterator vi = bad.begin();
- vi != bad.end(); ++vi)
- {
- RegDeleteValue(hKey, vi->c_str());
- }
- RegCloseKey(hKey);
+ 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());
}
+ RegCloseKey(hKey);
+ }
}
#else
-//----------------------------------------------------------------------------
class cmFindPackageCommandHoldFile
{
const char* File;
+
public:
- cmFindPackageCommandHoldFile(const char* f): File(f) {}
+ cmFindPackageCommandHoldFile(const char* f)
+ : File(f)
+ {
+ }
~cmFindPackageCommandHoldFile()
- { if(this->File) { cmSystemTools::RemoveFile(this->File); } }
- void Release() { this->File = 0; }
+ {
+ if (this->File) {
+ cmSystemTools::RemoveFile(this->File);
+ }
+ }
+ void Release() { this->File = CM_NULLPTR; }
};
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir)
+void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
+ cmSearchPath& outPaths)
{
cmsys::Directory files;
- if(!files.Load(dir.c_str()))
- {
+ if (!files.Load(dir)) {
return;
- }
+ }
std::string fname;
- for(unsigned long i=0; i < files.GetNumberOfFiles(); ++i)
- {
+ for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) {
fname = dir;
fname += "/";
fname += files.GetFile(i);
- if(!cmSystemTools::FileIsDirectory(fname.c_str()))
- {
+ if (!cmSystemTools::FileIsDirectory(fname)) {
// Hold this file hostage until it behaves.
cmFindPackageCommandHoldFile holdFile(fname.c_str());
// Load the file.
- std::ifstream fin(fname.c_str(), std::ios::in | cmsys_ios_binary);
- if(fin && this->CheckPackageRegistryEntry(fin))
- {
+ cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
+ std::string fentry;
+ if (fin && cmSystemTools::GetLineFromStream(fin, fentry) &&
+ this->CheckPackageRegistryEntry(fentry, outPaths)) {
// The file references an existing package, so release it.
holdFile.Release();
- }
}
}
+ }
// TODO: Wipe out the directory if it is empty.
}
#endif
-//----------------------------------------------------------------------------
-bool cmFindPackageCommand::CheckPackageRegistryEntry(std::istream& is)
+bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname,
+ cmSearchPath& outPaths)
{
// Parse the content of one package registry entry.
- std::string fname;
- if(cmSystemTools::GetLineFromStream(is, fname) &&
- cmSystemTools::FileIsFullPath(fname.c_str()))
- {
+ if (cmSystemTools::FileIsFullPath(fname.c_str())) {
// 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.c_str())) {
// The path exists. Look for the package here.
- if(!cmSystemTools::FileIsDirectory(fname.c_str()))
- {
- fname = cmSystemTools::GetFilenamePath(fname);
- }
- this->AddPathInternal(fname, FullPath);
- return true;
+ if (!cmSystemTools::FileIsDirectory(fname)) {
+ outPaths.AddPath(cmSystemTools::GetFilenamePath(fname));
+ } else {
+ outPaths.AddPath(fname);
}
- else
- {
- // The path does not exist. Assume the stream content is
- // associated with an old package that no longer exists, and
- // delete it to keep the package registry clean.
- return false;
- }
- }
- else
- {
- // The first line in the stream is not the full path to a file or
- // directory. Assume the stream content was created by a future
- // version of CMake that uses a different format, and leave it.
- return true;
+ return true;
}
+ // The path does not exist. Assume the stream content is
+ // associated with an old package that no longer exists, and
+ // delete it to keep the package registry clean.
+ return false;
+ }
+ // The first line in the stream is not the full path to a file or
+ // directory. Assume the stream content was created by a future
+ // version of CMake that uses a different format, and leave it.
+ return true;
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesBuilds()
+void cmFindPackageCommand::FillPrefixesCMakeSystemVariable()
{
- if(!this->NoBuilds && !this->NoDefaultPath)
- {
- // It is likely that CMake will have recently built the project.
- for(int i=0; i <= 10; ++i)
- {
- cmOStringStream r;
- r <<
- "[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\"
- "Settings\\StartPath;WhereBuild" << i << "]";
- std::string f = r.str();
- cmSystemTools::ExpandRegistryValues(f);
- cmSystemTools::ConvertToUnixSlashes(f);
- if(cmSystemTools::FileIsFullPath(f.c_str()) &&
- cmSystemTools::FileIsDirectory(f.c_str()))
- {
- this->AddPathInternal(f, FullPath);
- }
- }
- }
-}
+ cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesCMakeSystemVariable()
-{
- if(!this->NoCMakeSystemPath && !this->NoDefaultPath)
- {
- this->AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
- this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
- this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
- }
+ paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
+ paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
+ paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesUserGuess()
+void cmFindPackageCommand::FillPrefixesUserGuess()
{
- // Add guesses specified by the caller.
- this->AddPathsInternal(this->UserPaths, CMakePath);
+ 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);
+ }
}
-//----------------------------------------------------------------------------
-void cmFindPackageCommand::AddPrefixesUserHints()
+void cmFindPackageCommand::FillPrefixesUserHints()
{
- // Add hints specified by the caller.
- this->AddPathsInternal(this->UserHints, CMakePath);
+ 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);
+ }
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::SearchDirectory(std::string const& dir)
{
- assert(!dir.empty() && dir[dir.size()-1] == '/');
+ assert(!dir.empty() && dir[dir.size() - 1] == '/');
// 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::vector<std::string>::const_iterator si =
+ this->SearchPathSuffixes.begin();
+ si != this->SearchPathSuffixes.end(); ++si) {
std::string d = dir;
- if(!si->empty())
- {
+ if (!si->empty()) {
d += *si;
d += "/";
- }
- if(this->CheckDirectory(d))
- {
+ }
+ if (this->CheckDirectory(d)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::CheckDirectory(std::string const& dir)
{
- assert(!dir.empty() && dir[dir.size()-1] == '/');
+ assert(!dir.empty() && dir[dir.size() - 1] == '/');
// Look for the file in this directory.
- std::string d = dir.substr(0, dir.size()-1);
- if(this->FindConfigFile(d, this->FileFound))
- {
+ std::string d = dir.substr(0, dir.size() - 1);
+ if (this->FindConfigFile(d, this->FileFound)) {
// Remove duplicate slashes.
cmSystemTools::ConvertToUnixSlashes(this->FileFound);
return true;
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
std::string& file)
{
- if (this->IgnoredPaths.count(dir))
- {
+ if (this->IgnoredPaths.count(dir)) {
return false;
- }
+ }
- for(std::vector<std::string>::const_iterator ci = this->Configs.begin();
- ci != this->Configs.end(); ++ci)
- {
+ for (std::vector<std::string>::const_iterator ci = this->Configs.begin();
+ ci != this->Configs.end(); ++ci) {
file = dir;
file += "/";
file += *ci;
- if(this->DebugMode)
- {
+ 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.c_str(), true) &&
+ this->CheckVersion(file)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
{
bool result = false; // by default, assume the version is not ok.
@@ -1922,30 +1483,23 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
// Look for foo-config-version.cmake
std::string version_file = version_file_base;
version_file += "-version.cmake";
- if ((haveResult == false)
- && (cmSystemTools::FileExists(version_file.c_str(), true)))
- {
+ if (!haveResult && cmSystemTools::FileExists(version_file.c_str(), true)) {
result = this->CheckVersionFile(version_file, version);
haveResult = true;
- }
+ }
// Look for fooConfigVersion.cmake
version_file = version_file_base;
version_file += "Version.cmake";
- if ((haveResult == false)
- && (cmSystemTools::FileExists(version_file.c_str(), true)))
- {
+ if (!haveResult && cmSystemTools::FileExists(version_file.c_str(), true)) {
result = this->CheckVersionFile(version_file, version);
haveResult = true;
- }
-
+ }
// If no version was requested a versionless package is acceptable.
- if ((haveResult == false) && (this->Version.empty()))
- {
+ if (!haveResult && this->Version.empty()) {
result = true;
- haveResult = true;
- }
+ }
ConfigFileInfo configFileInfo;
configFileInfo.filename = config_file;
@@ -1955,7 +1509,6 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
return result;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
std::string& result_version)
{
@@ -1973,8 +1526,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
// 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_VERSION", this->Version.c_str());
char buf[64];
sprintf(buf, "%u", this->VersionMajor);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MAJOR", buf);
@@ -1990,21 +1542,18 @@ 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.c_str(), NoPolicyScope)) {
// Check the output variables.
bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT");
bool unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE");
- if(!okay && !this->VersionExact)
- {
+ if (!okay && !this->VersionExact) {
okay = this->Makefile->IsOn("PACKAGE_VERSION_COMPATIBLE");
- }
+ }
// The package is suitable if the version is okay and not
// explicitly unsuitable.
suitable = !unsuitable && (okay || this->Version.empty());
- if(suitable)
- {
+ if (suitable) {
// Get the version found.
this->VersionFound =
this->Makefile->GetSafeDefinition("PACKAGE_VERSION");
@@ -2016,131 +1565,130 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
unsigned int parsed_patch;
unsigned int parsed_tweak;
this->VersionFoundCount =
- sscanf(this->VersionFound.c_str(), "%u.%u.%u.%u",
- &parsed_major, &parsed_minor,
- &parsed_patch, &parsed_tweak);
- switch(this->VersionFoundCount)
- {
- case 4: this->VersionFoundTweak = parsed_tweak; // no break!
- case 3: this->VersionFoundPatch = parsed_patch; // no break!
- case 2: this->VersionFoundMinor = parsed_minor; // no break!
- case 1: this->VersionFoundMajor = parsed_major; // no break!
- default: break;
- }
+ sscanf(this->VersionFound.c_str(), "%u.%u.%u.%u", &parsed_major,
+ &parsed_minor, &parsed_patch, &parsed_tweak);
+ switch (this->VersionFoundCount) {
+ case 4:
+ this->VersionFoundTweak = parsed_tweak;
+ CM_FALLTHROUGH;
+ case 3:
+ this->VersionFoundPatch = parsed_patch;
+ CM_FALLTHROUGH;
+ case 2:
+ this->VersionFoundMinor = parsed_minor;
+ CM_FALLTHROUGH;
+ case 1:
+ this->VersionFoundMajor = parsed_major;
+ CM_FALLTHROUGH;
+ default:
+ break;
}
}
+ }
result_version = this->Makefile->GetSafeDefinition("PACKAGE_VERSION");
- if (result_version.empty())
- {
+ if (result_version.empty()) {
result_version = "unknown";
- }
+ }
// Succeed if the version is suitable.
return suitable;
}
-//----------------------------------------------------------------------------
void cmFindPackageCommand::StoreVersionFound()
{
// Store the whole version string.
std::string ver = this->Name;
ver += "_VERSION";
- if(this->VersionFound.empty())
- {
- this->Makefile->RemoveDefinition(ver.c_str());
- }
- else
- {
- this->Makefile->AddDefinition(ver.c_str(), this->VersionFound.c_str());
- }
+ if (this->VersionFound.empty()) {
+ this->Makefile->RemoveDefinition(ver);
+ } else {
+ this->Makefile->AddDefinition(ver, this->VersionFound.c_str());
+ }
// Store the version components.
char buf[64];
sprintf(buf, "%u", this->VersionFoundMajor);
- this->Makefile->AddDefinition((ver+"_MAJOR").c_str(), buf);
+ this->Makefile->AddDefinition(ver + "_MAJOR", buf);
sprintf(buf, "%u", this->VersionFoundMinor);
- this->Makefile->AddDefinition((ver+"_MINOR").c_str(), buf);
+ this->Makefile->AddDefinition(ver + "_MINOR", buf);
sprintf(buf, "%u", this->VersionFoundPatch);
- this->Makefile->AddDefinition((ver+"_PATCH").c_str(), buf);
+ this->Makefile->AddDefinition(ver + "_PATCH", buf);
sprintf(buf, "%u", this->VersionFoundTweak);
- this->Makefile->AddDefinition((ver+"_TWEAK").c_str(), buf);
+ this->Makefile->AddDefinition(ver + "_TWEAK", buf);
sprintf(buf, "%u", this->VersionFoundCount);
- this->Makefile->AddDefinition((ver+"_COUNT").c_str(), buf);
+ this->Makefile->AddDefinition(ver + "_COUNT", buf);
}
-//----------------------------------------------------------------------------
-#include <cmsys/Glob.hxx>
-#include <cmsys/String.h>
-#include <cmsys/auto_ptr.hxx>
-
-class cmFileList;
class cmFileListGeneratorBase
{
public:
virtual ~cmFileListGeneratorBase() {}
+
protected:
bool Consider(std::string const& fullPath, cmFileList& listing);
+
private:
bool Search(cmFileList&);
virtual bool Search(std::string const& parent, cmFileList&) = 0;
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const = 0;
+ virtual CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const = 0;
friend class cmFileList;
cmFileListGeneratorBase* SetNext(cmFileListGeneratorBase const& next);
- cmsys::auto_ptr<cmFileListGeneratorBase> Next;
+ CM_AUTO_PTR<cmFileListGeneratorBase> Next;
};
class cmFileList
{
public:
- cmFileList(): First(), Last(0) {}
+ cmFileList()
+ : First()
+ , Last(CM_NULLPTR)
+ {
+ }
virtual ~cmFileList() {}
cmFileList& operator/(cmFileListGeneratorBase const& rhs)
- {
- if(this->Last)
- {
+ {
+ if (this->Last) {
this->Last = this->Last->SetNext(rhs);
- }
- else
- {
+ } else {
this->First = rhs.Clone();
this->Last = this->First.get();
- }
- return *this;
}
+ return *this;
+ }
bool Search()
- {
- if(this->First.get())
- {
+ {
+ if (this->First.get()) {
return this->First->Search(*this);
- }
- return false;
}
+ return false;
+ }
+
private:
virtual bool Visit(std::string const& fullPath) = 0;
friend class cmFileListGeneratorBase;
- cmsys::auto_ptr<cmFileListGeneratorBase> First;
+ CM_AUTO_PTR<cmFileListGeneratorBase> First;
cmFileListGeneratorBase* Last;
};
-class cmFindPackageFileList: public cmFileList
+class cmFindPackageFileList : public cmFileList
{
public:
- cmFindPackageFileList(cmFindPackageCommand* fpc,
- bool use_suffixes = true):
- cmFileList(), FPC(fpc), UseSuffixes(use_suffixes) {}
+ cmFindPackageFileList(cmFindPackageCommand* fpc, bool use_suffixes = true)
+ : cmFileList()
+ , FPC(fpc)
+ , UseSuffixes(use_suffixes)
+ {
+ }
+
private:
- bool Visit(std::string const& fullPath)
- {
- if(this->UseSuffixes)
- {
+ bool Visit(std::string const& fullPath) CM_OVERRIDE
+ {
+ if (this->UseSuffixes) {
return this->FPC->SearchDirectory(fullPath);
- }
- else
- {
- return this->FPC->CheckDirectory(fullPath);
- }
}
+ return this->FPC->CheckDirectory(fullPath);
+ }
cmFindPackageCommand* FPC;
bool UseSuffixes;
};
@@ -2150,8 +1698,8 @@ bool cmFileListGeneratorBase::Search(cmFileList& listing)
return this->Search("", listing);
}
-cmFileListGeneratorBase*
-cmFileListGeneratorBase::SetNext(cmFileListGeneratorBase const& next)
+cmFileListGeneratorBase* cmFileListGeneratorBase::SetNext(
+ cmFileListGeneratorBase const& next)
{
this->Next = next.Clone();
return this->Next.get();
@@ -2160,486 +1708,543 @@ cmFileListGeneratorBase::SetNext(cmFileListGeneratorBase const& next)
bool cmFileListGeneratorBase::Consider(std::string const& fullPath,
cmFileList& listing)
{
- if(this->Next.get())
- {
+ if (this->Next.get()) {
return this->Next->Search(fullPath + "/", listing);
- }
- else
- {
- return listing.Visit(fullPath + "/");
- }
+ }
+ return listing.Visit(fullPath + "/");
}
-class cmFileListGeneratorFixed: public cmFileListGeneratorBase
+class cmFileListGeneratorFixed : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorFixed(std::string const& str):
- cmFileListGeneratorBase(), String(str) {}
- cmFileListGeneratorFixed(cmFileListGeneratorFixed const& r):
- cmFileListGeneratorBase(), String(r.String) {}
+ cmFileListGeneratorFixed(std::string const& str)
+ : cmFileListGeneratorBase()
+ , String(str)
+ {
+ }
+ cmFileListGeneratorFixed(cmFileListGeneratorFixed const& r)
+ : cmFileListGeneratorBase()
+ , String(r.String)
+ {
+ }
+
private:
std::string String;
- virtual bool Search(std::string const& parent, cmFileList& lister)
- {
+ bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ {
std::string fullPath = parent + this->String;
return this->Consider(fullPath, lister);
- }
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const
- {
- cmsys::auto_ptr<cmFileListGeneratorBase>
- g(new cmFileListGeneratorFixed(*this));
+ }
+ CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ {
+ CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ new cmFileListGeneratorFixed(*this));
return g;
- }
+ }
};
-class cmFileListGeneratorEnumerate: public cmFileListGeneratorBase
+class cmFileListGeneratorEnumerate : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorEnumerate(std::vector<std::string> const& v):
- cmFileListGeneratorBase(), Vector(v) {}
- cmFileListGeneratorEnumerate(cmFileListGeneratorEnumerate const& r):
- cmFileListGeneratorBase(), Vector(r.Vector) {}
+ cmFileListGeneratorEnumerate(std::vector<std::string> const& v)
+ : cmFileListGeneratorBase()
+ , Vector(v)
+ {
+ }
+ cmFileListGeneratorEnumerate(cmFileListGeneratorEnumerate const& r)
+ : cmFileListGeneratorBase()
+ , Vector(r.Vector)
+ {
+ }
+
private:
std::vector<std::string> const& Vector;
- virtual bool Search(std::string const& parent, cmFileList& lister)
- {
- for(std::vector<std::string>::const_iterator i = this->Vector.begin();
- i != this->Vector.end(); ++i)
- {
- if(this->Consider(parent + *i, lister))
- {
+ bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ {
+ for (std::vector<std::string>::const_iterator i = this->Vector.begin();
+ i != this->Vector.end(); ++i) {
+ if (this->Consider(parent + *i, lister)) {
return true;
- }
}
- return false;
}
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const
- {
- cmsys::auto_ptr<cmFileListGeneratorBase>
- g(new cmFileListGeneratorEnumerate(*this));
+ return false;
+ }
+ CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ {
+ CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ new cmFileListGeneratorEnumerate(*this));
return g;
- }
+ }
};
-class cmFileListGeneratorProject: public cmFileListGeneratorBase
+class cmFileListGeneratorProject : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorProject(std::vector<std::string> const& names):
- cmFileListGeneratorBase(), Names(names) {}
- cmFileListGeneratorProject(cmFileListGeneratorProject const& r):
- cmFileListGeneratorBase(), Names(r.Names) {}
+ cmFileListGeneratorProject(std::vector<std::string> const& names,
+ cmFindPackageCommand::SortOrderType so,
+ cmFindPackageCommand::SortDirectionType sd)
+ : cmFileListGeneratorBase()
+ , Names(names)
+ {
+ this->SetSort(so, sd);
+ }
+ cmFileListGeneratorProject(cmFileListGeneratorProject const& r)
+ : cmFileListGeneratorBase()
+ , Names(r.Names)
+ {
+ this->SetSort(r.SortOrder, r.SortDirection);
+ }
+
+ void SetSort(cmFindPackageCommand::SortOrderType o,
+ cmFindPackageCommand::SortDirectionType d)
+ {
+ SortOrder = o;
+ SortDirection = d;
+ }
+
+protected:
+ // sort parameters
+ cmFindPackageCommand::SortOrderType SortOrder;
+ cmFindPackageCommand::SortDirectionType SortDirection;
+
private:
std::vector<std::string> const& Names;
- virtual bool Search(std::string const& parent, cmFileList& lister)
- {
+ bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ {
// Construct a list of matches.
std::vector<std::string> matches;
cmsys::Directory d;
- d.Load(parent.c_str());
- for(unsigned long i=0; i < d.GetNumberOfFiles(); ++i)
- {
+ d.Load(parent);
+ for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
const char* fname = d.GetFile(i);
- if(strcmp(fname, ".") == 0 ||
- strcmp(fname, "..") == 0)
- {
+ 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)
- {
+ }
+ 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::vector<std::string>::const_iterator i = matches.begin();
- i != matches.end(); ++i)
- {
- if(this->Consider(parent + *i, lister))
- {
+ // before testing the matches check if there is a specific sorting order to
+ // perform
+ if (this->SortOrder != cmFindPackageCommand::None) {
+ cmFindPackageCommand::Sort(matches.begin(), matches.end(), SortOrder,
+ SortDirection);
+ }
+
+ for (std::vector<std::string>::const_iterator i = matches.begin();
+ i != matches.end(); ++i) {
+ if (this->Consider(parent + *i, lister)) {
return true;
- }
}
- return false;
}
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const
- {
- cmsys::auto_ptr<cmFileListGeneratorBase>
- g(new cmFileListGeneratorProject(*this));
+ return false;
+ }
+ CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ {
+ CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ new cmFileListGeneratorProject(*this));
return g;
- }
+ }
};
-class cmFileListGeneratorMacProject: public cmFileListGeneratorBase
+class cmFileListGeneratorMacProject : public cmFileListGeneratorBase
{
public:
cmFileListGeneratorMacProject(std::vector<std::string> const& names,
- const char* ext):
- cmFileListGeneratorBase(), Names(names), Extension(ext) {}
- cmFileListGeneratorMacProject(cmFileListGeneratorMacProject const& r):
- cmFileListGeneratorBase(), Names(r.Names), Extension(r.Extension) {}
+ const char* ext)
+ : cmFileListGeneratorBase()
+ , Names(names)
+ , Extension(ext)
+ {
+ }
+ cmFileListGeneratorMacProject(cmFileListGeneratorMacProject const& r)
+ : cmFileListGeneratorBase()
+ , Names(r.Names)
+ , Extension(r.Extension)
+ {
+ }
+
private:
std::vector<std::string> const& Names;
std::string Extension;
- virtual bool Search(std::string const& parent, cmFileList& lister)
- {
+ bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ {
// Construct a list of matches.
std::vector<std::string> matches;
cmsys::Directory d;
- d.Load(parent.c_str());
- for(unsigned long i=0; i < d.GetNumberOfFiles(); ++i)
- {
+ d.Load(parent);
+ for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
const char* fname = d.GetFile(i);
- if(strcmp(fname, ".") == 0 ||
- strcmp(fname, "..") == 0)
- {
+ if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
continue;
- }
- for(std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni)
- {
+ }
+ for (std::vector<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni) {
std::string name = *ni;
name += this->Extension;
- if(cmsysString_strcasecmp(fname, name.c_str()) == 0)
- {
+ if (cmsysString_strcasecmp(fname, name.c_str()) == 0) {
matches.push_back(fname);
- }
}
}
+ }
- for(std::vector<std::string>::const_iterator i = matches.begin();
- i != matches.end(); ++i)
- {
- if(this->Consider(parent + *i, lister))
- {
+ for (std::vector<std::string>::const_iterator i = matches.begin();
+ i != matches.end(); ++i) {
+ if (this->Consider(parent + *i, lister)) {
return true;
- }
}
- return false;
}
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const
- {
- cmsys::auto_ptr<cmFileListGeneratorBase>
- g(new cmFileListGeneratorMacProject(*this));
+ return false;
+ }
+ CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ {
+ CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ new cmFileListGeneratorMacProject(*this));
return g;
- }
+ }
};
-class cmFileListGeneratorCaseInsensitive: public cmFileListGeneratorBase
+class cmFileListGeneratorCaseInsensitive : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorCaseInsensitive(std::string const& str):
- cmFileListGeneratorBase(), String(str) {}
+ cmFileListGeneratorCaseInsensitive(std::string const& str)
+ : cmFileListGeneratorBase()
+ , String(str)
+ {
+ }
cmFileListGeneratorCaseInsensitive(
- cmFileListGeneratorCaseInsensitive const& r):
- cmFileListGeneratorBase(), String(r.String) {}
+ cmFileListGeneratorCaseInsensitive const& r)
+ : cmFileListGeneratorBase()
+ , String(r.String)
+ {
+ }
+
private:
std::string String;
- virtual bool Search(std::string const& parent, cmFileList& lister)
- {
+ bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ {
// Look for matching files.
std::vector<std::string> matches;
cmsys::Directory d;
- d.Load(parent.c_str());
- for(unsigned long i=0; i < d.GetNumberOfFiles(); ++i)
- {
+ d.Load(parent);
+ for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
const char* fname = d.GetFile(i);
- if(strcmp(fname, ".") == 0 ||
- strcmp(fname, "..") == 0)
- {
+ if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
continue;
- }
- if(cmsysString_strcasecmp(fname, this->String.c_str()) == 0)
- {
- if(this->Consider(parent + fname, lister))
- {
+ }
+ if (cmsysString_strcasecmp(fname, this->String.c_str()) == 0) {
+ if (this->Consider(parent + fname, lister)) {
return true;
- }
}
}
- return false;
}
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const
- {
- cmsys::auto_ptr<cmFileListGeneratorBase>
- g(new cmFileListGeneratorCaseInsensitive(*this));
+ return false;
+ }
+ CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ {
+ CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ new cmFileListGeneratorCaseInsensitive(*this));
return g;
- }
+ }
};
-class cmFileListGeneratorGlob: public cmFileListGeneratorBase
+class cmFileListGeneratorGlob : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorGlob(std::string const& str):
- cmFileListGeneratorBase(), Pattern(str) {}
- cmFileListGeneratorGlob(cmFileListGeneratorGlob const& r):
- cmFileListGeneratorBase(), Pattern(r.Pattern) {}
+ cmFileListGeneratorGlob(std::string const& str)
+ : cmFileListGeneratorBase()
+ , Pattern(str)
+ {
+ }
+ cmFileListGeneratorGlob(cmFileListGeneratorGlob const& r)
+ : cmFileListGeneratorBase()
+ , Pattern(r.Pattern)
+ {
+ }
+
private:
std::string Pattern;
- virtual bool Search(std::string const& parent, cmFileList& lister)
- {
+ bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ {
// Glob the set of matching files.
std::string expr = parent;
expr += this->Pattern;
cmsys::Glob g;
- if(!g.FindFiles(expr))
- {
+ if (!g.FindFiles(expr)) {
return false;
- }
+ }
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->c_str()))
- {
- if(this->Consider(*fi, lister))
- {
+ for (std::vector<std::string>::const_iterator fi = files.begin();
+ fi != files.end(); ++fi) {
+ if (cmSystemTools::FileIsDirectory(*fi)) {
+ if (this->Consider(*fi, lister)) {
return true;
- }
}
}
- return false;
}
- virtual cmsys::auto_ptr<cmFileListGeneratorBase> Clone() const
- {
- cmsys::auto_ptr<cmFileListGeneratorBase>
- g(new cmFileListGeneratorGlob(*this));
+ return false;
+ }
+ CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ {
+ CM_AUTO_PTR<cmFileListGeneratorBase> g(new cmFileListGeneratorGlob(*this));
return g;
- }
+ }
};
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size()-1] == '/');
- if(this->DebugMode)
- {
+ assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ if (this->DebugMode) {
fprintf(stderr, "Checking prefix [%s]\n", prefix_in.c_str());
- }
+ }
// Skip this if the prefix does not exist.
- if(!cmSystemTools::FileIsDirectory(prefix_in.c_str()))
- {
+ if (!cmSystemTools::FileIsDirectory(prefix_in)) {
return false;
- }
+ }
// PREFIX/ (useful on windows or in build trees)
- if(this->SearchDirectory(prefix_in))
- {
+ if (this->SearchDirectory(prefix_in)) {
return true;
- }
+ }
// Strip the trailing slash because the path generator is about to
// add one.
- std::string prefix = prefix_in.substr(0, prefix_in.size()-1);
+ std::string prefix = prefix_in.substr(0, prefix_in.size() - 1);
// PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorCaseInsensitive("cmake");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
}
}
// PREFIX/(Foo|foo|FOO).*/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorProject(this->Names);
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection);
+ if (lister.Search()) {
+ return true;
}
}
// PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorProject(this->Names)
- / cmFileListGeneratorCaseInsensitive("cmake");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection) /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
}
}
// Construct list of common install locations (lib and share).
std::vector<std::string> common;
- if(!this->LibraryArchitecture.empty())
- {
- common.push_back("lib/"+this->LibraryArchitecture);
- }
- if(this->UseLib64Paths)
- {
+ if (!this->LibraryArchitecture.empty()) {
+ common.push_back("lib/" + this->LibraryArchitecture);
+ }
+ if (this->UseLib32Paths) {
+ common.push_back("lib32");
+ }
+ if (this->UseLib64Paths) {
common.push_back("lib64");
- }
+ }
+ if (this->UseLibx32Paths) {
+ common.push_back("libx32");
+ }
common.push_back("lib");
common.push_back("share");
// PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorEnumerate(common)
- / cmFileListGeneratorFixed("cmake")
- / cmFileListGeneratorProject(this->Names);
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorEnumerate(common) /
+ cmFileListGeneratorFixed("cmake") /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection);
+ if (lister.Search()) {
+ return true;
}
}
// PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorEnumerate(common)
- / cmFileListGeneratorProject(this->Names);
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorEnumerate(common) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection);
+ if (lister.Search()) {
+ return true;
}
}
// PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorEnumerate(common)
- / cmFileListGeneratorProject(this->Names)
- / cmFileListGeneratorCaseInsensitive("cmake");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorEnumerate(common) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection) /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
+ }
+ }
+
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ {
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection) /
+ cmFileListGeneratorEnumerate(common) /
+ cmFileListGeneratorFixed("cmake") /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection);
+ if (lister.Search()) {
+ return true;
+ }
+ }
+
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ {
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection) /
+ cmFileListGeneratorEnumerate(common) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection);
+ if (lister.Search()) {
+ return true;
+ }
+ }
+
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ {
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection) /
+ cmFileListGeneratorEnumerate(common) /
+ cmFileListGeneratorProject(this->Names, this->SortOrder,
+ this->SortDirection) /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
}
}
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size()-1] == '/');
- if(this->DebugMode)
- {
+ assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ if (this->DebugMode) {
fprintf(stderr, "Checking framework prefix [%s]\n", prefix_in.c_str());
- }
+ }
// Strip the trailing slash because the path generator is about to
// add one.
- std::string prefix = prefix_in.substr(0, prefix_in.size()-1);
+ std::string prefix = prefix_in.substr(0, prefix_in.size() - 1);
// <prefix>/Foo.framework/Resources/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorMacProject(this->Names, ".framework")
- / cmFileListGeneratorFixed("Resources");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorMacProject(this->Names, ".framework") /
+ cmFileListGeneratorFixed("Resources");
+ if (lister.Search()) {
+ return true;
}
}
// <prefix>/Foo.framework/Resources/CMake/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorMacProject(this->Names, ".framework")
- / cmFileListGeneratorFixed("Resources")
- / cmFileListGeneratorCaseInsensitive("cmake");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorMacProject(this->Names, ".framework") /
+ cmFileListGeneratorFixed("Resources") /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
}
}
// <prefix>/Foo.framework/Versions/*/Resources/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorMacProject(this->Names, ".framework")
- / cmFileListGeneratorFixed("Versions")
- / cmFileListGeneratorGlob("*/Resources");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorMacProject(this->Names, ".framework") /
+ cmFileListGeneratorFixed("Versions") /
+ cmFileListGeneratorGlob("*/Resources");
+ if (lister.Search()) {
+ return true;
}
}
// <prefix>/Foo.framework/Versions/*/Resources/CMake/
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorMacProject(this->Names, ".framework")
- / cmFileListGeneratorFixed("Versions")
- / cmFileListGeneratorGlob("*/Resources")
- / cmFileListGeneratorCaseInsensitive("cmake");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorMacProject(this->Names, ".framework") /
+ cmFileListGeneratorFixed("Versions") /
+ cmFileListGeneratorGlob("*/Resources") /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
}
}
return false;
}
-//----------------------------------------------------------------------------
bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size()-1] == '/');
- if(this->DebugMode)
- {
+ assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ if (this->DebugMode) {
fprintf(stderr, "Checking bundle prefix [%s]\n", prefix_in.c_str());
- }
+ }
// Strip the trailing slash because the path generator is about to
// add one.
- std::string prefix = prefix_in.substr(0, prefix_in.size()-1);
+ std::string prefix = prefix_in.substr(0, prefix_in.size() - 1);
// <prefix>/Foo.app/Contents/Resources
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorMacProject(this->Names, ".app")
- / cmFileListGeneratorFixed("Contents/Resources");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorMacProject(this->Names, ".app") /
+ cmFileListGeneratorFixed("Contents/Resources");
+ if (lister.Search()) {
+ return true;
}
}
// <prefix>/Foo.app/Contents/Resources/CMake
{
- cmFindPackageFileList lister(this);
- lister
- / cmFileListGeneratorFixed(prefix)
- / cmFileListGeneratorMacProject(this->Names, ".app")
- / cmFileListGeneratorFixed("Contents/Resources")
- / cmFileListGeneratorCaseInsensitive("cmake");
- if(lister.Search())
- {
- return true;
+ cmFindPackageFileList lister(this);
+ lister / cmFileListGeneratorFixed(prefix) /
+ cmFileListGeneratorMacProject(this->Names, ".app") /
+ cmFileListGeneratorFixed("Contents/Resources") /
+ cmFileListGeneratorCaseInsensitive("cmake");
+ if (lister.Search()) {
+ return true;
}
}
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index c3801220d..99b0059ba 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -1,20 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindPackageCommand_h
#define cmFindPackageCommand_h
+#include "cmConfigure.h"
+
+#include "cm_kwiml.h"
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmFindCommon.h"
-class cmFindPackageFileList;
+class cmCommand;
+class cmExecutionStatus;
+class cmSearchPath;
/** \class cmFindPackageCommand
* \brief Load settings from an external project.
@@ -24,80 +25,97 @@ class cmFindPackageFileList;
class cmFindPackageCommand : public cmFindCommon
{
public:
+ /*! A sorting order strategy to be applied to recovered package folders (see
+ * FIND_PACKAGE_SORT_ORDER)*/
+ enum /*class*/ SortOrderType
+ {
+ None,
+ Name_order,
+ Natural
+ };
+ /*! A sorting direction to be applied to recovered package folders (see
+ * FIND_PACKAGE_SORT_DIRECTION)*/
+ enum /*class*/ SortDirectionType
+ {
+ Asc,
+ Dec
+ };
+
+ /*! sorts a given list of string based on the input sort parameters */
+ static void Sort(std::vector<std::string>::iterator begin,
+ std::vector<std::string>::iterator end, SortOrderType order,
+ SortDirectionType dir);
+
cmFindPackageCommand();
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFindPackageCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFindPackageCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "find_package";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
+private:
+ class PathLabel : public cmFindCommon::PathLabel
+ {
+ protected:
+ PathLabel();
+
+ public:
+ PathLabel(const std::string& label)
+ : cmFindCommon::PathLabel(label)
{
- return "Load settings for an external project.";
}
+ static PathLabel UserRegistry;
+ static PathLabel Builds;
+ static PathLabel SystemRegistry;
+ };
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const;
+ // Add additional search path labels and groups not present in the
+ // parent class
+ void AppendSearchPathGroups();
- cmTypeMacro(cmFindPackageCommand, cmFindCommon);
-protected:
- virtual void GenerateDocumentation();
-private:
void AppendSuccessInformation();
void AppendToFoundProperty(bool found);
void SetModuleVariables(const std::string& components);
bool FindModule(bool& found);
- void AddFindDefinition(const char* var, const char* val);
+ void AddFindDefinition(const std::string& var, const char* val);
void RestoreFindDefinitions();
bool HandlePackageMode();
bool FindConfig();
bool FindPrefixedConfig();
bool FindFrameworkConfig();
bool FindAppBundleConfig();
- enum PolicyScopeRule { NoPolicyScope, DoPolicyScope };
+ enum PolicyScopeRule
+ {
+ NoPolicyScope,
+ DoPolicyScope
+ };
bool ReadListFile(const char* f, PolicyScopeRule psr);
void StoreVersionFound();
void ComputePrefixes();
- void AddPrefixesCMakeEnvironment();
- void AddPrefixesCMakeVariable();
- void AddPrefixesSystemEnvironment();
- void AddPrefixesUserRegistry();
- void AddPrefixesSystemRegistry();
- void AddPrefixesBuilds();
- void AddPrefixesCMakeSystemVariable();
- void AddPrefixesUserGuess();
- void AddPrefixesUserHints();
- void LoadPackageRegistryDir(std::string const& dir);
+ void FillPrefixesPackageRoot();
+ void FillPrefixesCMakeEnvironment();
+ void FillPrefixesCMakeVariable();
+ void FillPrefixesSystemEnvironment();
+ void FillPrefixesUserRegistry();
+ void FillPrefixesSystemRegistry();
+ void FillPrefixesCMakeSystemVariable();
+ void FillPrefixesUserGuess();
+ void FillPrefixesUserHints();
+ void LoadPackageRegistryDir(std::string const& dir, cmSearchPath& outPaths);
void LoadPackageRegistryWinUser();
void LoadPackageRegistryWinSystem();
- void LoadPackageRegistryWin(bool user, unsigned int view);
- bool CheckPackageRegistryEntry(std::istream& is);
+ void LoadPackageRegistryWin(bool user, unsigned int view,
+ cmSearchPath& outPaths);
+ bool CheckPackageRegistryEntry(const std::string& fname,
+ cmSearchPath& outPaths);
bool SearchDirectory(std::string const& dir);
bool CheckDirectory(std::string const& dir);
bool FindConfigFile(std::string const& dir, std::string& file);
@@ -110,44 +128,71 @@ private:
friend class cmFindPackageFileList;
- struct OriginalDef { bool exists; std::string value; };
- std::map<cmStdString, OriginalDef> OriginalDefs;
+ struct OriginalDef
+ {
+ bool exists;
+ std::string value;
+ };
+ std::map<std::string, OriginalDef> OriginalDefs;
- std::string CommandDocumentation;
- cmStdString Name;
- cmStdString Variable;
- cmStdString Version;
+ std::string Name;
+ std::string Variable;
+ std::string Version;
unsigned int VersionMajor;
unsigned int VersionMinor;
unsigned int VersionPatch;
unsigned int VersionTweak;
unsigned int VersionCount;
bool VersionExact;
- cmStdString FileFound;
- cmStdString VersionFound;
+ std::string FileFound;
+ std::string VersionFound;
unsigned int VersionFoundMajor;
unsigned int VersionFoundMinor;
unsigned int VersionFoundPatch;
unsigned int VersionFoundTweak;
unsigned int VersionFoundCount;
- unsigned int RequiredCMakeVersion;
+ KWIML_INT_uint64_t RequiredCMakeVersion;
bool Quiet;
bool Required;
- bool Compatibility_1_6;
bool UseConfigFiles;
bool UseFindModules;
bool NoUserRegistry;
bool NoSystemRegistry;
- bool NoBuilds;
bool DebugMode;
+ bool UseLib32Paths;
bool UseLib64Paths;
+ bool UseLibx32Paths;
bool PolicyScope;
std::string LibraryArchitecture;
std::vector<std::string> Names;
std::vector<std::string> Configs;
std::set<std::string> IgnoredPaths;
- struct ConfigFileInfo { std::string filename; std::string version; };
+ /*! the selected sortOrder (None by default)*/
+ SortOrderType SortOrder;
+ /*! the selected sortDirection (Asc by default)*/
+ SortDirectionType SortDirection;
+
+ struct ConfigFileInfo
+ {
+ std::string filename;
+ std::string version;
+
+ bool operator<(ConfigFileInfo const& rhs) const
+ {
+ return this->filename < rhs.filename;
+ }
+
+ bool operator==(ConfigFileInfo const& rhs) const
+ {
+ return this->filename == rhs.filename;
+ }
+
+ bool operator!=(ConfigFileInfo const& rhs) const
+ {
+ return !(*this == rhs);
+ }
+ };
std::vector<ConfigFileInfo> ConsideredConfigs;
};
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 6a432984d..d3541ca94 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -1,18 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFindPathCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/Glob.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmFindPathCommand.h"
-#include "cmCacheManager.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
-#include <cmsys/Glob.hxx>
+class cmExecutionStatus;
cmFindPathCommand::cmFindPathCommand()
{
@@ -20,223 +16,144 @@ cmFindPathCommand::cmFindPathCommand()
this->IncludeFileInPath = false;
}
-void cmFindPathCommand::GenerateDocumentation()
-{
- this->cmFindBase::GenerateDocumentation();
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "FIND_XXX", "find_path");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_XXX_PATH", "CMAKE_INCLUDE_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_XXX_MAC_PATH",
- "CMAKE_FRAMEWORK_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_SYSTEM_XXX_MAC_PATH",
- "CMAKE_SYSTEM_FRAMEWORK_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_SYSTEM", "INCLUDE");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_SYSTEM_XXX_PATH",
- "CMAKE_SYSTEM_INCLUDE_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "SEARCH_XXX_DESC",
- "directory containing the named file");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "SEARCH_XXX", "file in a directory");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_SUBDIR", "include");
- cmSystemTools::ReplaceString(
- this->GenericDocumentation,
- "XXX_EXTRA_PREFIX_ENTRY",
- " <prefix>/include/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and\n");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_FIND_ROOT_PATH_MODE_XXX",
- "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE");
- if(!this->IncludeFileInPath)
- {
- this->GenericDocumentation +=
- "\n"
- "When searching for frameworks, if the file is specified as "
- "A/b.h, then the framework search will look for "
- "A.framework/Headers/b.h. "
- "If that is found the path will be set to the path to the framework. "
- "CMake will convert this to the correct -F option to include the "
- "file. ";
- }
-}
-
// cmFindPathCommand
-bool cmFindPathCommand
-::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
+bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn,
+ cmExecutionStatus&)
{
this->VariableDocumentation = "Path to a file.";
this->CMakePathName = "INCLUDE";
- if(!this->ParseArguments(argsIn))
- {
+ if (!this->ParseArguments(argsIn)) {
return false;
- }
- if(this->AlreadyInCache)
- {
+ }
+ if (this->AlreadyInCache) {
// If the user specifies the entry on the command line without a
// type we should add the type and docstring but keep the original
// value.
- if(this->AlreadyInCacheWithoutMetaInfo)
- {
+ if (this->AlreadyInCacheWithoutMetaInfo) {
this->Makefile->AddCacheDefinition(
- this->VariableName.c_str(), "",
- this->VariableDocumentation.c_str(),
- (this->IncludeFileInPath ?
- cmCacheManager::FILEPATH :cmCacheManager::PATH)
- );
- }
- return true;
+ this->VariableName, "", this->VariableDocumentation.c_str(),
+ (this->IncludeFileInPath ? cmStateEnums::FILEPATH
+ : cmStateEnums::PATH));
}
+ return true;
+ }
std::string result = this->FindHeader();
- if(result.size() != 0)
- {
- this->Makefile->AddCacheDefinition
- (this->VariableName.c_str(), result.c_str(),
- this->VariableDocumentation.c_str(),
- (this->IncludeFileInPath) ?
- cmCacheManager::FILEPATH :cmCacheManager::PATH);
+ if (!result.empty()) {
+ this->Makefile->AddCacheDefinition(
+ this->VariableName, result.c_str(), this->VariableDocumentation.c_str(),
+ (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH);
return true;
- }
- this->Makefile->AddCacheDefinition
- (this->VariableName.c_str(),
- (this->VariableName + "-NOTFOUND").c_str(),
- this->VariableDocumentation.c_str(),
- (this->IncludeFileInPath) ?
- cmCacheManager::FILEPATH :cmCacheManager::PATH);
+ }
+ this->Makefile->AddCacheDefinition(
+ this->VariableName, (this->VariableName + "-NOTFOUND").c_str(),
+ this->VariableDocumentation.c_str(),
+ (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH);
return true;
}
-//----------------------------------------------------------------------------
std::string cmFindPathCommand::FindHeader()
{
std::string header;
- if(this->SearchFrameworkFirst || this->SearchFrameworkOnly)
- {
+ if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) {
header = this->FindFrameworkHeader();
- }
- if(header.empty() && !this->SearchFrameworkOnly)
- {
+ }
+ if (header.empty() && !this->SearchFrameworkOnly) {
header = this->FindNormalHeader();
- }
- if(header.empty() && this->SearchFrameworkLast)
- {
+ }
+ if (header.empty() && this->SearchFrameworkLast) {
header = this->FindFrameworkHeader();
- }
+ }
return header;
}
-std::string
-cmFindPathCommand::FindHeaderInFramework(std::string const& file,
- std::string const& dir)
+std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
+ std::string const& dir)
{
- cmStdString fileName = file;
- cmStdString frameWorkName;
- cmStdString::size_type pos = fileName.find("/");
+ std::string fileName = file;
+ std::string frameWorkName;
+ std::string::size_type pos = fileName.find('/');
// if there is a / in the name try to find the header as a framework
// For example bar/foo.h would look for:
// bar.framework/Headers/foo.h
- if(pos != fileName.npos)
- {
+ if (pos != std::string::npos) {
// remove the name from the slash;
- fileName = fileName.substr(pos+1);
+ fileName = fileName.substr(pos + 1);
frameWorkName = file;
frameWorkName =
- frameWorkName.substr(0, frameWorkName.size()-fileName.size()-1);
+ frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1);
// if the framework has a path in it then just use the filename
- if(frameWorkName.find("/") != frameWorkName.npos)
- {
+ if (frameWorkName.find('/') != std::string::npos) {
fileName = file;
frameWorkName = "";
- }
- if(frameWorkName.size())
- {
+ }
+ 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()))
- {
- if(this->IncludeFileInPath)
- {
+ if (cmSystemTools::FileExists(intPath.c_str())) {
+ if (this->IncludeFileInPath) {
return intPath;
- }
- return fpath;
}
+ return fpath;
}
}
+ }
// 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>
- cmStdString glob = dir;
+ std::string glob = dir;
glob += "*.framework/Headers/";
glob += file;
cmsys::Glob globIt;
globIt.FindFiles(glob);
std::vector<std::string> files = globIt.GetFiles();
- if(files.size())
- {
- cmStdString fheader = cmSystemTools::CollapseFullPath(files[0].c_str());
- if(this->IncludeFileInPath)
- {
+ if (!files.empty()) {
+ std::string fheader = cmSystemTools::CollapseFullPath(files[0]);
+ if (this->IncludeFileInPath) {
return fheader;
- }
- fheader = cmSystemTools::GetFilenamePath(fheader);
- return fheader;
}
+ fheader.resize(fheader.size() - file.size());
+ return fheader;
+ }
return "";
}
-//----------------------------------------------------------------------------
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)
- {
+ 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()))
- {
- if(this->IncludeFileInPath)
- {
+ if (cmSystemTools::FileExists(tryPath.c_str())) {
+ if (this->IncludeFileInPath) {
return tryPath;
- }
- else
- {
- return *p;
- }
}
+ return *p;
}
}
+ }
return "";
}
-//----------------------------------------------------------------------------
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)
- {
+ 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);
- if(!fwPath.empty())
- {
+ if (!fwPath.empty()) {
return fwPath;
- }
}
}
+ }
return "";
}
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index 759567dc1..3761145b2 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindPathCommand_h
#define cmFindPathCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmFindBase.h"
+class cmCommand;
+class cmExecutionStatus;
/** \class cmFindPathCommand
* \brief Define a command to search for a library.
@@ -29,40 +27,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFindPathCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFindPathCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "find_path";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Find the directory containing a file.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- cmTypeMacro(cmFindPathCommand, cmFindBase);
bool IncludeFileInPath;
-protected:
- virtual void GenerateDocumentation();
+
private:
std::string FindHeaderInFramework(std::string const& file,
std::string const& dir);
@@ -71,6 +46,4 @@ private:
std::string FindFrameworkHeader();
};
-
-
#endif
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 909b333ff..9327c1805 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -1,145 +1,221 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFindProgramCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmFindProgramCommand.h"
-#include "cmCacheManager.h"
-#include <stdlib.h>
+class cmExecutionStatus;
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
#endif
-void cmFindProgramCommand::GenerateDocumentation()
+struct cmFindProgramHelper
{
- this->cmFindBase::GenerateDocumentation();
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "FIND_XXX", "find_program");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_XXX_PATH", "CMAKE_PROGRAM_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_XXX_MAC_PATH",
- "CMAKE_APPBUNDLE_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_SYSTEM_XXX_MAC_PATH",
- "CMAKE_SYSTEM_APPBUNDLE_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_SYSTEM", "");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_SYSTEM_XXX_PATH",
- "CMAKE_SYSTEM_PROGRAM_PATH");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "SEARCH_XXX_DESC", "program");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "SEARCH_XXX", "program");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_SUBDIR", "[s]bin");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_EXTRA_PREFIX_ENTRY", "");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "CMAKE_FIND_ROOT_PATH_MODE_XXX",
- "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM");
+ cmFindProgramHelper()
+ {
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+ // Consider platform-specific extensions.
+ this->Extensions.push_back(".com");
+ this->Extensions.push_back(".exe");
+#endif
+ // Consider original name with no extensions.
+ this->Extensions.push_back("");
+ }
+
+ // List of valid extensions.
+ std::vector<std::string> Extensions;
+
+ // Keep track of the best program file found so far.
+ std::string BestPath;
+
+ // Current names under consideration.
+ std::vector<std::string> Names;
+
+ // Current full path under consideration.
+ std::string TestPath;
+
+ void AddName(std::string const& name) { this->Names.push_back(name); }
+ void SetName(std::string const& name)
+ {
+ this->Names.clear();
+ this->AddName(name);
+ }
+ 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)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ 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())) {
+ continue;
+ }
+ this->TestPath += *ext;
+ if (cmSystemTools::FileExists(this->TestPath, true)) {
+ this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+cmFindProgramCommand::cmFindProgramCommand()
+{
+ this->NamesPerDirAllowed = true;
}
// cmFindProgramCommand
-bool cmFindProgramCommand
-::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
+bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn,
+ cmExecutionStatus&)
{
this->VariableDocumentation = "Path to a program.";
this->CMakePathName = "PROGRAM";
// call cmFindBase::ParseArguments
- if(!this->ParseArguments(argsIn))
- {
+ if (!this->ParseArguments(argsIn)) {
return false;
- }
- if(this->AlreadyInCache)
- {
+ }
+ if (this->AlreadyInCache) {
// If the user specifies the entry on the command line without a
// type we should add the type and docstring but keep the original
// value.
- if(this->AlreadyInCacheWithoutMetaInfo)
- {
- this->Makefile->AddCacheDefinition(this->VariableName.c_str(), "",
+ if (this->AlreadyInCacheWithoutMetaInfo) {
+ this->Makefile->AddCacheDefinition(this->VariableName, "",
this->VariableDocumentation.c_str(),
- cmCacheManager::FILEPATH);
- }
- return true;
+ cmStateEnums::FILEPATH);
}
+ return true;
+ }
- std::string result = FindProgram(this->Names);
- if(result != "")
- {
+ std::string result = FindProgram();
+ if (result != "") {
// Save the value in the cache
- this->Makefile->AddCacheDefinition(this->VariableName.c_str(),
- result.c_str(),
+ this->Makefile->AddCacheDefinition(this->VariableName, result.c_str(),
this->VariableDocumentation.c_str(),
- cmCacheManager::FILEPATH);
+ cmStateEnums::FILEPATH);
return true;
- }
- this->Makefile->AddCacheDefinition(this->VariableName.c_str(),
- (this->VariableName + "-NOTFOUND").c_str(),
- this->VariableDocumentation.c_str(),
- cmCacheManager::FILEPATH);
+ }
+ this->Makefile->AddCacheDefinition(
+ this->VariableName, (this->VariableName + "-NOTFOUND").c_str(),
+ this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH);
return true;
}
-std::string cmFindProgramCommand::FindProgram(std::vector<std::string> names)
+std::string cmFindProgramCommand::FindProgram()
{
- std::string program = "";
+ std::string program;
+
+ if (this->SearchAppBundleFirst || this->SearchAppBundleOnly) {
+ program = FindAppBundle();
+ }
+ if (program.empty() && !this->SearchAppBundleOnly) {
+ program = this->FindNormalProgram();
+ }
+
+ if (program.empty() && this->SearchAppBundleLast) {
+ program = this->FindAppBundle();
+ }
+ return program;
+}
+
+std::string cmFindProgramCommand::FindNormalProgram()
+{
+ if (this->NamesPerDir) {
+ return this->FindNormalProgramNamesPerDir();
+ }
+ return this->FindNormalProgramDirsPerName();
+}
+
+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);
+ }
+
+ // Check for the names themselves (e.g. absolute paths).
+ if (helper.CheckDirectory(std::string())) {
+ return helper.BestPath;
+ }
- if(this->SearchAppBundleFirst || this->SearchAppBundleOnly)
- {
- program = FindAppBundle(names);
+ // Search every directory.
+ for (std::vector<std::string>::const_iterator p = this->SearchPaths.begin();
+ p != this->SearchPaths.end(); ++p) {
+ if (helper.CheckDirectory(*p)) {
+ return helper.BestPath;
}
- if(program.empty() && !this->SearchAppBundleOnly)
- {
- program = cmSystemTools::FindProgram(names, this->SearchPaths, true);
+ }
+ // Couldn't find the program.
+ return "";
+}
+
+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) {
+ // Switch to searching for this name.
+ helper.SetName(*ni);
+
+ // Check for the name by itself (e.g. an absolute path).
+ if (helper.CheckDirectory(std::string())) {
+ return helper.BestPath;
}
- if(program.empty() && this->SearchAppBundleLast)
- {
- program = this->FindAppBundle(names);
+ // Search every directory.
+ for (std::vector<std::string>::const_iterator p =
+ this->SearchPaths.begin();
+ p != this->SearchPaths.end(); ++p) {
+ if (helper.CheckDirectory(*p)) {
+ return helper.BestPath;
+ }
}
- return program;
+ }
+ // Couldn't find the program.
+ return "";
}
-std::string cmFindProgramCommand
-::FindAppBundle(std::vector<std::string> names)
+std::string cmFindProgramCommand::FindAppBundle()
{
- for(std::vector<std::string>::const_iterator name = names.begin();
- name != names.end() ; ++name)
- {
+ for (std::vector<std::string>::const_iterator name = this->Names.begin();
+ name != this->Names.end(); ++name) {
std::string appName = *name + std::string(".app");
- std::string appPath = cmSystemTools::FindDirectory(appName.c_str(),
- this->SearchPaths,
- true);
+ std::string appPath =
+ cmSystemTools::FindDirectory(appName, this->SearchPaths, true);
- if ( !appPath.empty() )
- {
+ if (!appPath.empty()) {
std::string executable = GetBundleExecutable(appPath);
- if (!executable.empty())
- {
- return cmSystemTools::CollapseFullPath(executable.c_str());
- }
+ if (!executable.empty()) {
+ return cmSystemTools::CollapseFullPath(executable);
}
}
+ }
// Couldn't find app bundle
return "";
}
-std::string cmFindProgramCommand::GetBundleExecutable(std::string bundlePath)
+std::string cmFindProgramCommand::GetBundleExecutable(
+ std::string const& bundlePath)
{
- std::string executable = "";
+ std::string executable;
(void)bundlePath;
#if defined(__APPLE__)
// Started with an example on developer.apple.com about finding bundles
@@ -147,45 +223,40 @@ std::string cmFindProgramCommand::GetBundleExecutable(std::string bundlePath)
// Get a CFString of the app bundle path
// XXX - Is it safe to assume everything is in UTF8?
- CFStringRef bundlePathCFS =
- CFStringCreateWithCString(kCFAllocatorDefault ,
- bundlePath.c_str(), kCFStringEncodingUTF8 );
+ CFStringRef bundlePathCFS = CFStringCreateWithCString(
+ kCFAllocatorDefault, bundlePath.c_str(), kCFStringEncodingUTF8);
// Make a CFURLRef from the CFString representation of the
// bundle’s path.
- CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
- bundlePathCFS,
- kCFURLPOSIXPathStyle,
- true );
+ CFURLRef bundleURL = CFURLCreateWithFileSystemPath(
+ kCFAllocatorDefault, bundlePathCFS, kCFURLPOSIXPathStyle, true);
// Make a bundle instance using the URLRef.
- CFBundleRef appBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
+ CFBundleRef appBundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);
// returned executableURL is relative to <appbundle>/Contents/MacOS/
CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
- if (executableURL != NULL)
- {
+ if (executableURL != NULL) {
const int MAX_OSX_PATH_SIZE = 1024;
char buffer[MAX_OSX_PATH_SIZE];
// Convert the CFString to a C string
- CFStringGetCString( CFURLGetString(executableURL), buffer,
- MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 );
+ CFStringGetCString(CFURLGetString(executableURL), buffer,
+ MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8);
// And finally to a c++ string
executable = bundlePath + "/Contents/MacOS/" + std::string(buffer);
// Only release CFURLRef if it's not null
- CFRelease( executableURL );
- }
+ CFRelease(executableURL);
+ }
// Any CF objects returned from functions with "create" or
// "copy" in their names must be released by us!
- CFRelease( bundlePathCFS );
- CFRelease( bundleURL );
- CFRelease( appBundle );
+ CFRelease(bundlePathCFS);
+ CFRelease(bundleURL);
+ CFRelease(appBundle);
#endif
return executable;
}
-
diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h
index 8350c9b42..b0cd42096 100644
--- a/Source/cmFindProgramCommand.h
+++ b/Source/cmFindProgramCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFindProgramCommand_h
#define cmFindProgramCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmFindBase.h"
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmFindProgramCommand
* \brief Define a command to search for an executable program.
*
@@ -25,51 +24,26 @@
class cmFindProgramCommand : public cmFindBase
{
public:
+ cmFindProgramCommand();
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFindProgramCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFindProgramCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "find_program";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Find an executable program.";
- }
-
- cmTypeMacro(cmFindProgramCommand, cmFindBase);
-
-protected:
- std::string FindProgram(std::vector<std::string> names);
- virtual void GenerateDocumentation();
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
- std::string FindAppBundle(std::vector<std::string> names);
- std::string GetBundleExecutable(std::string bundlePath);
-
+ std::string FindProgram();
+ std::string FindNormalProgram();
+ std::string FindNormalProgramDirsPerName();
+ std::string FindNormalProgramNamesPerDir();
+ std::string FindAppBundle();
+ std::string GetBundleExecutable(std::string const& bundlePath);
};
-
-
#endif
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index d69706730..8346b2309 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -1,88 +1,89 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmForEachCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmForEachCommand.h"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
+
+cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)
+ : Makefile(mf)
+ , Depth(0)
+{
+ this->Makefile->PushLoopBlock();
+}
-#include <cmsys/auto_ptr.hxx>
+cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
+{
+ this->Makefile->PopLoopBlock();
+}
-bool cmForEachFunctionBlocker::
-IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
- cmExecutionStatus &inStatus)
+bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
+ cmMakefile& mf,
+ cmExecutionStatus& inStatus)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(),"foreach"))
- {
+ 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"))
- {
+ } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
// if this is the endofreach for this statement
- if (!this->Depth)
- {
+ if (!this->Depth) {
// Remove the function blocker for this scope or bail.
- cmsys::auto_ptr<cmFunctionBlocker>
- fb(mf.RemoveFunctionBlocker(this, lff));
- if(!fb.get()) { return false; }
+ CM_AUTO_PTR<cmFunctionBlocker> fb(mf.RemoveFunctionBlocker(this, lff));
+ if (!fb.get()) {
+ return false;
+ }
// at end of for each execute recorded commands
// store the old value
std::string oldDef;
- if (mf.GetDefinition(this->Args[0].c_str()))
- {
- oldDef = mf.GetDefinition(this->Args[0].c_str());
- }
+ if (mf.GetDefinition(this->Args[0])) {
+ oldDef = mf.GetDefinition(this->Args[0]);
+ }
std::vector<std::string>::const_iterator j = this->Args.begin();
++j;
- std::string tmps;
- cmListFileArgument arg;
- for( ; j != this->Args.end(); ++j)
- {
+ for (; j != this->Args.end(); ++j) {
// set the variable to the loop value
- mf.AddDefinition(this->Args[0].c_str(),j->c_str());
+ 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)
- {
+ for (unsigned int c = 0; c < this->Functions.size(); ++c) {
status.Clear();
- mf.ExecuteCommand(this->Functions[c],status);
- if (status.GetReturnInvoked())
- {
- inStatus.SetReturnInvoked(true);
+ mf.ExecuteCommand(this->Functions[c], status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
// restore the variable to its prior value
- mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
+ mf.AddDefinition(this->Args[0], oldDef.c_str());
return true;
- }
- if (status.GetBreakInvoked())
- {
+ }
+ if (status.GetBreakInvoked()) {
// restore the variable to its prior value
- mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
+ mf.AddDefinition(this->Args[0], oldDef.c_str());
return true;
- }
- if(cmSystemTools::GetFatalErrorOccured() )
- {
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
return true;
- }
}
}
+ }
+
// restore the variable to its prior value
- mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
+ mf.AddDefinition(this->Args[0], oldDef.c_str());
return true;
- }
- else
- {
- // close out a nested foreach
- this->Depth--;
- }
}
+ // close out a nested foreach
+ this->Depth--;
+ }
// record the command
this->Functions.push_back(lff);
@@ -91,156 +92,128 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
return true;
}
-bool cmForEachFunctionBlocker::
-ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
+bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
+ cmMakefile& mf)
{
- if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
- {
+ 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])))
- {
+ (expandedArguments[0] == this->Args[0]))) {
return true;
- }
}
+ }
return false;
}
-bool cmForEachCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- if(args.size() > 1 && args[1] == "IN")
- {
+ }
+ if (args.size() > 1 && args[1] == "IN") {
return this->HandleInMode(args);
- }
+ }
// create a function blocker
- cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
- if ( args.size() > 1 )
- {
- if ( args[1] == "RANGE" )
- {
+ cmForEachFunctionBlocker* f = new cmForEachFunctionBlocker(this->Makefile);
+ if (args.size() > 1) {
+ if (args[1] == "RANGE") {
int start = 0;
int stop = 0;
int step = 0;
- if ( args.size() == 3 )
- {
+ if (args.size() == 3) {
stop = atoi(args[2].c_str());
- }
- if ( args.size() == 4 )
- {
+ }
+ if (args.size() == 4) {
start = atoi(args[2].c_str());
stop = atoi(args[3].c_str());
- }
- if ( args.size() == 5 )
- {
+ }
+ if (args.size() == 5) {
start = atoi(args[2].c_str());
stop = atoi(args[3].c_str());
step = atoi(args[4].c_str());
- }
- if ( step == 0 )
- {
- if ( start > stop )
- {
+ }
+ if (step == 0) {
+ if (start > stop) {
step = -1;
- }
- else
- {
+ } else {
step = 1;
- }
}
- if (
- (start > stop && step > 0) ||
- (start < stop && step < 0) ||
- step == 0
- )
- {
- cmOStringStream str;
+ }
+ 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().c_str());
+ this->SetError(str.str());
return false;
- }
+ }
std::vector<std::string> range;
char buffer[100];
range.push_back(args[0]);
int cc;
- for ( cc = start; ; cc += step )
- {
- if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) )
- {
+ for (cc = start;; cc += step) {
+ if ((step > 0 && cc > stop) || (step < 0 && cc < stop)) {
break;
- }
+ }
sprintf(buffer, "%d", cc);
range.push_back(buffer);
- if ( cc == stop )
- {
+ if (cc == stop) {
break;
- }
}
- f->Args = range;
}
- else
- {
+ f->Args = range;
+ } else {
f->Args = args;
- }
}
- else
- {
+ } else {
f->Args = args;
- }
+ }
this->Makefile->AddFunctionBlocker(f);
return true;
}
-//----------------------------------------------------------------------------
bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
{
- cmsys::auto_ptr<cmForEachFunctionBlocker> f(new cmForEachFunctionBlocker());
+ CM_AUTO_PTR<cmForEachFunctionBlocker> f(
+ new cmForEachFunctionBlocker(this->Makefile));
f->Args.push_back(args[0]);
- enum Doing { DoingNone, DoingLists, DoingItems };
+ enum Doing
+ {
+ DoingNone,
+ DoingLists,
+ DoingItems
+ };
Doing doing = DoingNone;
- for(unsigned int i=2; i < args.size(); ++i)
- {
- if(doing == DoingItems)
- {
+ for (unsigned int i = 2; i < args.size(); ++i) {
+ if (doing == DoingItems) {
f->Args.push_back(args[i]);
- }
- else if(args[i] == "LISTS")
- {
+ } else if (args[i] == "LISTS") {
doing = DoingLists;
- }
- else if(args[i] == "ITEMS")
- {
+ } else if (args[i] == "ITEMS") {
doing = DoingItems;
- }
- else if(doing == DoingLists)
- {
- const char* value = this->Makefile->GetDefinition(args[i].c_str());
- if(value && *value)
- {
+ } else if (doing == DoingLists) {
+ const char* value = this->Makefile->GetDefinition(args[i]);
+ if (value && *value) {
cmSystemTools::ExpandListArgument(value, f->Args, true);
- }
}
- else
- {
- cmOStringStream e;
- e << "Unknown argument:\n" << " " << args[i] << "\n";
+ } else {
+ std::ostringstream e;
+ e << "Unknown argument:\n"
+ << " " << args[i] << "\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return true;
- }
}
+ }
this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass auto_ptr
+
return true;
}
diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h
index dc4761306..7c8a6d836 100644
--- a/Source/cmForEachCommand.h
+++ b/Source/cmForEachCommand.h
@@ -1,34 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmForEachCommand_h
#define cmForEachCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
+class cmExecutionStatus;
+class cmMakefile;
+
class cmForEachFunctionBlocker : public cmFunctionBlocker
{
public:
- cmForEachFunctionBlocker() {this->Depth = 0;}
- virtual ~cmForEachFunctionBlocker() {}
- virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile &mf,
- cmExecutionStatus &);
- virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
+ 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;
};
@@ -39,78 +39,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmForEachCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmForEachCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "foreach";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Evaluate a group of commands for each value in a list.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " foreach(loop_var arg1 arg2 ...)\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " endforeach(loop_var)\n"
- "All commands between foreach and the matching endforeach are recorded "
- "without being invoked. Once the endforeach is evaluated, the "
- "recorded list of commands is invoked once for each argument listed "
- "in the original foreach command. Before each iteration of the loop "
- "\"${loop_var}\" will be set as a variable with "
- "the current value in the list.\n"
- " foreach(loop_var RANGE total)\n"
- " foreach(loop_var RANGE start stop [step])\n"
- "Foreach can also iterate over a generated range of numbers. "
- "There are three types of this iteration:\n"
- "* When specifying single number, the range will have elements "
- "0 to \"total\".\n"
- "* When specifying two numbers, the range will have elements from "
- "the first number to the second number.\n"
- "* The third optional number is the increment used to iterate from "
- "the first number to the second number."
- "\n"
- " foreach(loop_var IN [LISTS [list1 [...]]]\n"
- " [ITEMS [item1 [...]]])\n"
- "Iterates over a precise list of items. "
- "The LISTS option names list-valued variables to be traversed, "
- "including empty elements (an empty string is a zero-length list). "
- "The ITEMS option ends argument parsing and includes all arguments "
- "following it in the iteration."
- ;
- }
-
- cmTypeMacro(cmForEachCommand, cmCommand);
private:
bool HandleInMode(std::vector<std::string> const& args);
};
-
#endif
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
new file mode 100644
index 000000000..d8b002309
--- /dev/null
+++ b/Source/cmFortranParser.h
@@ -0,0 +1,160 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFortranParser_h
+#define cmFortranParser_h
+
+#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
+#include "cmConfigure.h"
+
+#include <set>
+#include <string>
+#include <vector>
+#endif
+
+#include <stddef.h> /* size_t */
+
+/* Forward declare parser object type. */
+typedef struct cmFortranParser_s cmFortranParser;
+
+/* Functions to enter/exit #include'd files in order. */
+bool cmFortranParser_FilePush(cmFortranParser* parser, const char* fname);
+bool cmFortranParser_FilePop(cmFortranParser* parser);
+
+/* Callbacks for lexer. */
+int cmFortranParser_Input(cmFortranParser* parser, char* buffer,
+ size_t bufferSize);
+
+void cmFortranParser_StringStart(cmFortranParser* parser);
+const char* cmFortranParser_StringEnd(cmFortranParser* parser);
+void cmFortranParser_StringAppend(cmFortranParser* parser, char c);
+
+void cmFortranParser_SetInInterface(cmFortranParser* parser, bool is_in);
+bool cmFortranParser_GetInInterface(cmFortranParser* parser);
+
+void cmFortranParser_SetInPPFalseBranch(cmFortranParser* parser, bool is_in);
+bool cmFortranParser_GetInPPFalseBranch(cmFortranParser* parser);
+
+void cmFortranParser_SetOldStartcond(cmFortranParser* parser, int arg);
+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_RuleLineDirective(cmFortranParser* parser,
+ const char* filename);
+void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleModule(cmFortranParser* parser, const char* 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);
+void cmFortranParser_RuleIfndef(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleIf(cmFortranParser* parser);
+void cmFortranParser_RuleElif(cmFortranParser* parser);
+void cmFortranParser_RuleElse(cmFortranParser* parser);
+void cmFortranParser_RuleEndif(cmFortranParser* parser);
+
+/* Define the parser stack element type. */
+struct cmFortran_yystype
+{
+ char* string;
+};
+
+/* Setup the proper yylex interface. */
+#define YY_EXTRA_TYPE cmFortranParser*
+#define YY_DECL int cmFortran_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+#define YYSTYPE cmFortran_yystype
+#define YYSTYPE_IS_DECLARED 1
+#if !defined(cmFortranLexer_cxx)
+#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
+#endif
+
+#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
+#include <stack>
+
+// Information about a single source file.
+class cmFortranSourceInfo
+{
+public:
+ // The name of the source file.
+ std::string Source;
+
+ // 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;
+};
+
+// Parser methods not included in generated interface.
+
+// Get the current buffer processed by the lexer.
+YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner);
+
+// The parser entry point.
+int cmFortran_yyparse(yyscan_t);
+
+// Define parser object internal structure.
+struct cmFortranFile
+{
+ cmFortranFile(FILE* file, YY_BUFFER_STATE buffer, const std::string& dir)
+ : File(file)
+ , Buffer(buffer)
+ , Directory(dir)
+ , LastCharWasNewline(false)
+ {
+ }
+ FILE* File;
+ YY_BUFFER_STATE Buffer;
+ std::string Directory;
+ bool LastCharWasNewline;
+};
+
+struct cmFortranParser_s
+{
+ cmFortranParser_s(std::vector<std::string> const& includes,
+ std::set<std::string> const& defines,
+ cmFortranSourceInfo& info);
+ ~cmFortranParser_s();
+
+ bool FindIncludeFile(const char* dir, const char* includeName,
+ std::string& fileName);
+
+ // The include file search path.
+ std::vector<std::string> IncludePath;
+
+ // Lexical scanner instance.
+ yyscan_t Scanner;
+
+ // Stack of open files in the translation unit.
+ std::stack<cmFortranFile> FileStack;
+
+ // Buffer for string literals.
+ std::string TokenString;
+
+ // Error message text if a parser error occurs.
+ std::string Error;
+
+ // Flag for whether lexer is reading from inside an interface.
+ bool InInterface;
+
+ int OldStartcond;
+ std::set<std::string> PPDefinitions;
+ size_t InPPFalseBranch;
+ std::stack<bool> SkipToEnd;
+
+ // Information about the parsed source.
+ cmFortranSourceInfo& Info;
+};
+#endif
+
+#endif
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
new file mode 100644
index 000000000..4e23f3691
--- /dev/null
+++ b/Source/cmFortranParserImpl.cxx
@@ -0,0 +1,361 @@
+/* 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 <set>
+#include <stack>
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+bool cmFortranParser_s::FindIncludeFile(const char* dir,
+ const char* includeName,
+ std::string& fileName)
+{
+ // If the file is a full path, include it directly.
+ if (cmSystemTools::FileIsFullPath(includeName)) {
+ fileName = includeName;
+ return cmSystemTools::FileExists(fileName.c_str(), 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)) {
+ 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)) {
+ fileName = fullName;
+ return true;
+ }
+ }
+ return false;
+}
+
+cmFortranParser_s::cmFortranParser_s(std::vector<std::string> const& includes,
+ std::set<std::string> const& defines,
+ cmFortranSourceInfo& info)
+ : IncludePath(includes)
+ , PPDefinitions(defines)
+ , Info(info)
+{
+ this->InInterface = false;
+ this->InPPFalseBranch = 0;
+
+ // Initialize the lexical scanner.
+ cmFortran_yylex_init(&this->Scanner);
+ cmFortran_yyset_extra(this, this->Scanner);
+
+ // 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_switch_to_buffer(buffer, this->Scanner);
+}
+
+cmFortranParser_s::~cmFortranParser_s()
+{
+ cmFortran_yylex_destroy(this->Scanner);
+}
+
+bool cmFortranParser_FilePush(cmFortranParser* parser, const char* fname)
+{
+ // Open the new file and push it onto the stack. Save the old
+ // buffer with it on the stack.
+ if (FILE* file = cmsys::SystemTools::Fopen(fname, "rb")) {
+ YY_BUFFER_STATE current = cmFortranLexer_GetCurrentBuffer(parser->Scanner);
+ 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_switch_to_buffer(buffer, parser->Scanner);
+ parser->FileStack.push(f);
+ return true;
+ }
+ return false;
+}
+
+bool cmFortranParser_FilePop(cmFortranParser* parser)
+{
+ // Pop one file off the stack and close it. Switch the lexer back
+ // to the next one on the stack.
+ if (parser->FileStack.empty()) {
+ return false;
+ }
+ cmFortranFile f = parser->FileStack.top();
+ parser->FileStack.pop();
+ fclose(f.File);
+ YY_BUFFER_STATE current = cmFortranLexer_GetCurrentBuffer(parser->Scanner);
+ cmFortran_yy_delete_buffer(current, parser->Scanner);
+ cmFortran_yy_switch_to_buffer(f.Buffer, parser->Scanner);
+ return true;
+}
+
+int cmFortranParser_Input(cmFortranParser* parser, char* buffer,
+ size_t bufferSize)
+{
+ // Read from the file on top of the stack. If the stack is empty,
+ // the end of the translation unit has been reached.
+ if (!parser->FileStack.empty()) {
+ cmFortranFile& ff = parser->FileStack.top();
+ FILE* file = ff.File;
+ size_t n = fread(buffer, 1, bufferSize, file);
+ if (n > 0) {
+ ff.LastCharWasNewline = buffer[n - 1] == '\n';
+ } else if (!ff.LastCharWasNewline) {
+ // The file ended without a newline. Inject one so
+ // that the file always ends in an end-of-statement.
+ buffer[0] = '\n';
+ n = 1;
+ ff.LastCharWasNewline = true;
+ }
+ return (int)n;
+ }
+ return 0;
+}
+
+void cmFortranParser_StringStart(cmFortranParser* parser)
+{
+ parser->TokenString = "";
+}
+
+const char* cmFortranParser_StringEnd(cmFortranParser* parser)
+{
+ return parser->TokenString.c_str();
+}
+
+void cmFortranParser_StringAppend(cmFortranParser* parser, char c)
+{
+ parser->TokenString += c;
+}
+
+void cmFortranParser_SetInInterface(cmFortranParser* parser, bool in)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ parser->InInterface = in;
+}
+
+bool cmFortranParser_GetInInterface(cmFortranParser* parser)
+{
+ return parser->InInterface;
+}
+
+void cmFortranParser_SetOldStartcond(cmFortranParser* parser, int arg)
+{
+ parser->OldStartcond = arg;
+}
+
+int cmFortranParser_GetOldStartcond(cmFortranParser* parser)
+{
+ return parser->OldStartcond;
+}
+
+void cmFortranParser_Error(cmFortranParser* parser, const char* msg)
+{
+ parser->Error = msg ? msg : "unknown error";
+}
+
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name)
+{
+ if (!parser->InPPFalseBranch) {
+ parser->Info.Requires.insert(cmSystemTools::LowerCase(name));
+ }
+}
+
+void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
+ const char* filename)
+{
+ // This is a #line directive naming a file encountered during preprocessing.
+ std::string included = filename;
+
+ // Skip #line directives referencing non-files like
+ // "<built-in>" or "<command-line>".
+ if (included.empty() || included[0] == '<') {
+ return;
+ }
+
+ // Fix windows file path separators since our lexer does not
+ // process escape sequences in string literals.
+ cmSystemTools::ReplaceString(included, "\\\\", "\\");
+ cmSystemTools::ConvertToUnixSlashes(included);
+
+ // Save the named file as included in the source.
+ if (cmSystemTools::FileExists(included, true)) {
+ parser->Info.Includes.insert(included);
+ }
+}
+
+void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ // If processing an include statement there must be an open file.
+ assert(!parser->FileStack.empty());
+
+ // Get the directory containing the source in which the include
+ // statement appears. This is always the first search location for
+ // Fortran include files.
+ std::string dir = parser->FileStack.top().Directory;
+
+ // Find the included file. If it cannot be found just ignore the
+ // problem because either the source will not compile or the user
+ // does not care about depending on this included source.
+ std::string fullName;
+ if (parser->FindIncludeFile(dir.c_str(), name, fullName)) {
+ // Found the included file. Save it in the set of included files.
+ parser->Info.Includes.insert(fullName);
+
+ // Parse it immediately to translate the source inline.
+ cmFortranParser_FilePush(parser, fullName.c_str());
+ }
+}
+
+void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name)
+{
+ if (!parser->InPPFalseBranch && !parser->InInterface) {
+ parser->Info.Provides.insert(cmSystemTools::LowerCase(name));
+ }
+}
+
+void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* macro)
+{
+ if (!parser->InPPFalseBranch) {
+ parser->PPDefinitions.insert(macro);
+ }
+}
+
+void cmFortranParser_RuleUndef(cmFortranParser* parser, const char* macro)
+{
+ if (!parser->InPPFalseBranch) {
+ std::set<std::string>::iterator match;
+ match = parser->PPDefinitions.find(macro);
+ if (match != parser->PPDefinitions.end()) {
+ parser->PPDefinitions.erase(match);
+ }
+ }
+}
+
+void cmFortranParser_RuleIfdef(cmFortranParser* parser, const char* macro)
+{
+ // A new PP branch has been opened
+ parser->SkipToEnd.push(false);
+
+ if (parser->InPPFalseBranch) {
+ parser->InPPFalseBranch++;
+ } else if (parser->PPDefinitions.find(macro) ==
+ parser->PPDefinitions.end()) {
+ parser->InPPFalseBranch = 1;
+ } else {
+ parser->SkipToEnd.top() = true;
+ }
+}
+
+void cmFortranParser_RuleIfndef(cmFortranParser* parser, const char* macro)
+{
+ // A new PP branch has been opened
+ parser->SkipToEnd.push(false);
+
+ if (parser->InPPFalseBranch) {
+ parser->InPPFalseBranch++;
+ } else if (parser->PPDefinitions.find(macro) !=
+ parser->PPDefinitions.end()) {
+ parser->InPPFalseBranch = 1;
+ } else {
+ // ignore other branches
+ parser->SkipToEnd.top() = true;
+ }
+}
+
+void cmFortranParser_RuleIf(cmFortranParser* parser)
+{
+ /* Note: The current parser is _not_ able to get statements like
+ * #if 0
+ * #if 1
+ * #if MYSMBOL
+ * #if defined(MYSYMBOL)
+ * #if defined(MYSYMBOL) && ...
+ * right. The same for #elif. Thus in
+ * #if SYMBOL_1
+ * ..
+ * #elif SYMBOL_2
+ * ...
+ * ...
+ * #elif SYMBOL_N
+ * ..
+ * #else
+ * ..
+ * #endif
+ * _all_ N+1 branches are considered. If you got something like this
+ * #if defined(MYSYMBOL)
+ * #if !defined(MYSYMBOL)
+ * use
+ * #ifdef MYSYMBOL
+ * #ifndef MYSYMBOL
+ * instead.
+ */
+
+ // A new PP branch has been opened
+ // Never skip! See note above.
+ parser->SkipToEnd.push(false);
+}
+
+void cmFortranParser_RuleElif(cmFortranParser* parser)
+{
+ /* Note: There are parser limitations. See the note at
+ * cmFortranParser_RuleIf(..)
+ */
+
+ // Always taken unless an #ifdef or #ifndef-branch has been taken
+ // already. If the second condition isn't meet already
+ // (parser->InPPFalseBranch == 0) correct it.
+ if (!parser->SkipToEnd.empty() && parser->SkipToEnd.top() &&
+ !parser->InPPFalseBranch) {
+ parser->InPPFalseBranch = 1;
+ }
+}
+
+void cmFortranParser_RuleElse(cmFortranParser* parser)
+{
+ // if the parent branch is false do nothing!
+ if (parser->InPPFalseBranch > 1) {
+ return;
+ }
+
+ // parser->InPPFalseBranch is either 0 or 1. We change it depending on
+ // parser->SkipToEnd.top()
+ if (!parser->SkipToEnd.empty() && parser->SkipToEnd.top()) {
+ parser->InPPFalseBranch = 1;
+ } else {
+ parser->InPPFalseBranch = 0;
+ }
+}
+
+void cmFortranParser_RuleEndif(cmFortranParser* parser)
+{
+ if (!parser->SkipToEnd.empty()) {
+ parser->SkipToEnd.pop();
+ }
+
+ // #endif doesn't know if there was a "#else" in before, so it
+ // always decreases InPPFalseBranch
+ if (parser->InPPFalseBranch) {
+ parser->InPPFalseBranch--;
+ }
+}
diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h
index 68bf76286..b3450b3f2 100644
--- a/Source/cmFunctionBlocker.h
+++ b/Source/cmFunctionBlocker.h
@@ -1,20 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFunctionBlocker_h
#define cmFunctionBlocker_h
-#include "cmStandardIncludes.h"
-#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
+
+class cmExecutionStatus;
class cmMakefile;
class cmFunctionBlocker
@@ -23,24 +14,30 @@ public:
/**
* should a function be blocked
*/
- virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile&mf,
- cmExecutionStatus &status) = 0;
+ 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;}
+ virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile&)
+ {
+ return false;
+ }
virtual ~cmFunctionBlocker() {}
/** Set/Get the context in which this blocker is created. */
void SetStartingContext(cmListFileContext const& lfc)
- { this->StartingContext = lfc; }
- cmListFileContext const& GetStartingContext()
- { return this->StartingContext; }
+ {
+ this->StartingContext = lfc;
+ }
+ cmListFileContext const& GetStartingContext() const
+ {
+ return this->StartingContext;
+ }
+
private:
cmListFileContext StartingContext;
};
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index a126cd110..ee52bde37 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -1,17 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFunctionCommand.h"
-#include "cmake.h"
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
// define the class for function commands
class cmFunctionHelperCommand : public cmCommand
@@ -20,81 +18,43 @@ public:
cmFunctionHelperCommand() {}
///! clean up any memory allocated by the function
- ~cmFunctionHelperCommand() {};
-
- /**
- * This is used to avoid including this command
- * in documentation. This is mainly used by
- * cmMacroHelperCommand and cmFunctionHelperCommand
- * which cannot provide appropriate documentation.
- */
- virtual bool ShouldAppearInDocumentation() const
- {
- return false;
- }
+ ~cmFunctionHelperCommand() CM_OVERRIDE {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
+ cmCommand* Clone() CM_OVERRIDE
{
- cmFunctionHelperCommand *newC = new cmFunctionHelperCommand;
+ 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 determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &);
-
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) { return false; };
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return this->Args[0].c_str(); }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- std::string docs = "Function named: ";
- docs += this->GetName();
- return docs.c_str();
- }
+ bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus&) CM_OVERRIDE;
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
+ bool InitialPass(std::vector<std::string> const&,
+ cmExecutionStatus&) CM_OVERRIDE
{
- return this->GetTerseDocumentation();
+ return false;
}
- cmTypeMacro(cmFunctionHelperCommand, cmCommand);
-
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::InvokeInitialPass(
+ const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
{
// Expand the argument list to the function.
std::vector<std::string> expandedArgs;
@@ -102,69 +62,41 @@ bool cmFunctionHelperCommand::InvokeInitialPass
// make sure the number of arguments passed is at least the number
// required by the signature
- if (expandedArgs.size() < this->Args.size() - 1)
- {
+ 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.c_str());
+ this->SetError(errorMsg);
return false;
- }
-
- // we push a scope on the makefile
- cmMakefile::LexicalPushPop lexScope(this->Makefile);
- cmMakefile::ScopePushPop varScope(this->Makefile);
- static_cast<void>(varScope);
+ }
- // Push a weak policy scope which restores the policies recorded at
- // function creation.
- cmMakefile::PolicyPushPop polScope(this->Makefile, true, this->Policies);
+ cmMakefile::FunctionPushPop functionScope(this->Makefile, this->FilePath,
+ this->Policies);
// set the value of argc
- cmOStringStream strStream;
+ std::ostringstream strStream;
strStream << expandedArgs.size();
- this->Makefile->AddDefinition("ARGC",strStream.str().c_str());
+ this->Makefile->AddDefinition("ARGC", strStream.str().c_str());
this->Makefile->MarkVariableAsUsed("ARGC");
// set the values for ARGV0 ARGV1 ...
- for (unsigned int t = 0; t < expandedArgs.size(); ++t)
- {
- cmOStringStream tmpStream;
+ for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
+ std::ostringstream tmpStream;
tmpStream << "ARGV" << t;
- this->Makefile->AddDefinition(tmpStream.str().c_str(),
- expandedArgs[t].c_str());
- this->Makefile->MarkVariableAsUsed(tmpStream.str().c_str());
- }
+ this->Makefile->AddDefinition(tmpStream.str(), expandedArgs[t].c_str());
+ this->Makefile->MarkVariableAsUsed(tmpStream.str());
+ }
// define the formal arguments
- for (unsigned int j = 1; j < this->Args.size(); ++j)
- {
- this->Makefile->AddDefinition(this->Args[j].c_str(),
- expandedArgs[j-1].c_str());
- }
+ for (unsigned int j = 1; j < this->Args.size(); ++j) {
+ this->Makefile->AddDefinition(this->Args[j], expandedArgs[j - 1].c_str());
+ }
// define ARGV and ARGN
- std::vector<std::string>::const_iterator eit;
- std::string argvDef;
- std::string argnDef;
- unsigned int cnt = 0;
- for ( eit = expandedArgs.begin(); eit != expandedArgs.end(); ++eit )
- {
- if ( argvDef.size() > 0 )
- {
- argvDef += ";";
- }
- argvDef += *eit;
- if ( cnt >= this->Args.size()-1 )
- {
- if ( argnDef.size() > 0 )
- {
- argnDef += ";";
- }
- argnDef += *eit;
- }
- cnt ++;
- }
+ std::string argvDef = cmJoin(expandedArgs, ";");
+ std::vector<std::string>::const_iterator 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());
@@ -172,85 +104,49 @@ bool cmFunctionHelperCommand::InvokeInitialPass
// Invoke all the functions that were collected in the block.
// for each function
- for(unsigned int c = 0; c < this->Functions.size(); ++c)
- {
+ for (unsigned int c = 0; c < this->Functions.size(); ++c) {
cmExecutionStatus status;
- if (!this->Makefile->ExecuteCommand(this->Functions[c],status) ||
- status.GetNestedError())
- {
+ if (!this->Makefile->ExecuteCommand(this->Functions[c], status) ||
+ status.GetNestedError()) {
// The error message should have already included the call stack
// so we do not need to report an error here.
- lexScope.Quiet();
- polScope.Quiet();
- inStatus.SetNestedError(true);
+ functionScope.Quiet();
+ inStatus.SetNestedError();
return false;
- }
- if (status.GetReturnInvoked())
- {
+ }
+ if (status.GetReturnInvoked()) {
return true;
- }
}
+ }
// pop scope on the makefile
return true;
}
-bool cmFunctionFunctionBlocker::
-IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
- cmExecutionStatus &)
+bool cmFunctionFunctionBlocker::IsFunctionBlocked(
+ const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&)
{
// 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"))
- {
+ if (!cmSystemTools::Strucmp(lff.Name.c_str(), "function")) {
this->Depth++;
- }
- else if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endfunction"))
- {
+ } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
// if this is the endfunction for this function then execute
- if (!this->Depth)
- {
- std::string name = this->Args[0];
- std::vector<std::string>::size_type cc;
- name += "(";
- for ( cc = 0; cc < this->Args.size(); cc ++ )
- {
- name += " " + this->Args[cc];
- }
- name += " )";
-
+ if (!this->Depth) {
// create a new command and add it to cmake
- cmFunctionHelperCommand *f = new cmFunctionHelperCommand();
+ cmFunctionHelperCommand* f = new cmFunctionHelperCommand();
f->Args = this->Args;
f->Functions = this->Functions;
+ f->FilePath = this->GetStartingContext().FilePath;
mf.RecordPolicies(f->Policies);
-
- // Set the FilePath on the arguments to match the function since it is
- // not stored and the original values may be freed
- for (unsigned int i = 0; i < f->Functions.size(); ++i)
- {
- for (unsigned int j = 0; j < f->Functions[i].Arguments.size(); ++j)
- {
- f->Functions[i].Arguments[j].FilePath =
- f->Functions[i].FilePath.c_str();
- }
- }
-
- std::string newName = "_" + this->Args[0];
- mf.GetCMakeInstance()->RenameCommand(this->Args[0].c_str(),
- newName.c_str());
- mf.AddCommand(f);
-
+ mf.GetState()->AddScriptedCommand(this->Args[0], f);
// remove the function blocker now that the function is defined
mf.RemoveFunctionBlocker(this, lff);
return true;
- }
- else
- {
- // decrement for each nested function that ends
- this->Depth--;
- }
}
+ // decrement for each nested function that ends
+ this->Depth--;
+ }
// if it wasn't an endfunction and we are not executing then we must be
// recording
@@ -258,43 +154,35 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
return true;
}
-
-bool cmFunctionFunctionBlocker::
-ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf)
+bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
+ cmMakefile& mf)
{
- if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endfunction"))
- {
+ if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
std::vector<std::string> expandedArguments;
- mf.ExpandArguments(lff.Arguments, 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])))
- {
+ (expandedArguments[0] == this->Args[0]))) {
return true;
- }
}
+ }
return false;
}
-bool cmFunctionCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// create a function blocker
- cmFunctionFunctionBlocker *f = new cmFunctionFunctionBlocker();
- for(std::vector<std::string>::const_iterator j = args.begin();
- j != args.end(); ++j)
- {
- f->Args.push_back(*j);
- }
+ cmFunctionFunctionBlocker* f = new cmFunctionFunctionBlocker();
+ f->Args.insert(f->Args.end(), args.begin(), args.end());
this->Makefile->AddFunctionBlocker(f);
return true;
}
-
diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h
index 0a029dc5f..f26312632 100644
--- a/Source/cmFunctionCommand.h
+++ b/Source/cmFunctionCommand.h
@@ -1,29 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFunctionCommand_h
#define cmFunctionCommand_h
+#include "cmConfigure.h"
+
+#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;}
- virtual ~cmFunctionFunctionBlocker() {}
- virtual bool IsFunctionBlocked(const cmListFileFunction&,
- cmMakefile &mf,
- cmExecutionStatus &);
- virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile &mf);
+ 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;
@@ -37,70 +36,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmFunctionCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmFunctionCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "function";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Start recording a function for later invocation as a command.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " function(<name> [arg1 [arg2 [arg3 ...]]])\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " endfunction(<name>)\n"
- "Define a function named <name> that takes arguments named "
- "arg1 arg2 arg3 (...). Commands listed after function, but before "
- "the matching endfunction, are not invoked until the function "
- "is invoked. When it is invoked, the commands recorded in the "
- "function are first modified by replacing formal parameters (${arg1}) "
- "with the arguments passed, and then invoked as normal commands. In "
- "addition to referencing the formal parameters you can reference "
- "the variable ARGC which will be set to the number of arguments "
- "passed into the function as well as ARGV0 ARGV1 ARGV2 ... which "
- "will have the actual values of the arguments passed in. This "
- "facilitates creating functions with optional arguments. Additionally "
- "ARGV holds the list of all arguments given to the function and ARGN "
- "holds the list of arguments past the last expected argument."
- "\n"
- "A function opens a new scope: see set(var PARENT_SCOPE) for details."
- "\n"
- "See the cmake_policy() command documentation for the behavior of "
- "policies inside functions."
- ;
- }
-
- cmTypeMacro(cmFunctionCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 0af07532a..6aa593cc0 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -1,43 +1,49 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratedFileStream.h"
+#include <stdio.h>
+
#include "cmSystemTools.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <cm_zlib.h>
+#include "cm_codecvt.hxx"
+#include "cm_zlib.h"
#endif
-//----------------------------------------------------------------------------
-cmGeneratedFileStream::cmGeneratedFileStream():
- cmGeneratedFileStreamBase(), Stream()
+cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
+ : cmGeneratedFileStreamBase()
+ , Stream()
{
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ if (encoding != codecvt::None) {
+ imbue(std::locale(getloc(), new codecvt(encoding)));
+ }
+#else
+ static_cast<void>(encoding);
+#endif
}
-//----------------------------------------------------------------------------
-cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet):
- cmGeneratedFileStreamBase(name),
- Stream(TempName.c_str())
+cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet,
+ Encoding encoding)
+ : cmGeneratedFileStreamBase(name)
+ , Stream(TempName.c_str())
{
// Check if the file opened.
- if(!*this && !quiet)
- {
+ if (!*this && !quiet) {
cmSystemTools::Error("Cannot open file for write: ",
this->TempName.c_str());
cmSystemTools::ReportLastSystemError("");
- }
+ }
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ if (encoding != codecvt::None) {
+ imbue(std::locale(getloc(), new codecvt(encoding)));
+ }
+#else
+ static_cast<void>(encoding);
+#endif
}
-//----------------------------------------------------------------------------
cmGeneratedFileStream::~cmGeneratedFileStream()
{
// This is the first destructor called. Check the status of the
@@ -45,43 +51,36 @@ cmGeneratedFileStream::~cmGeneratedFileStream()
// stream will be destroyed which will close the temporary file.
// Finally the base destructor will be called to replace the
// destination file.
- this->Okay = (*this)?true:false;
+ this->Okay = !this->fail();
}
-//----------------------------------------------------------------------------
-cmGeneratedFileStream&
-cmGeneratedFileStream::Open(const char* name, bool quiet, bool binaryFlag)
+cmGeneratedFileStream& cmGeneratedFileStream::Open(const char* name,
+ bool quiet, bool binaryFlag)
{
// Store the file name and construct the temporary file name.
this->cmGeneratedFileStreamBase::Open(name);
// Open the temporary output file.
- if ( binaryFlag )
- {
+ if (binaryFlag) {
this->Stream::open(this->TempName.c_str(),
std::ios::out | std::ios::binary);
- }
- else
- {
- this->Stream::open(this->TempName.c_str(), std::ios::out);
- }
+ } else {
+ this->Stream::open(this->TempName.c_str());
+ }
// Check if the file opened.
- if(!*this && !quiet)
- {
+ if (!*this && !quiet) {
cmSystemTools::Error("Cannot open file for write: ",
this->TempName.c_str());
cmSystemTools::ReportLastSystemError("");
- }
+ }
return *this;
}
-//----------------------------------------------------------------------------
-bool
-cmGeneratedFileStream::Close()
+bool cmGeneratedFileStream::Close()
{
// Save whether the temporary output file is valid before closing.
- this->Okay = (*this)?true:false;
+ this->Okay = !this->fail();
// Close the temporary output file.
this->Stream::close();
@@ -90,54 +89,47 @@ cmGeneratedFileStream::Close()
return this->cmGeneratedFileStreamBase::Close();
}
-//----------------------------------------------------------------------------
void cmGeneratedFileStream::SetCopyIfDifferent(bool copy_if_different)
{
this->CopyIfDifferent = copy_if_different;
}
-//----------------------------------------------------------------------------
void cmGeneratedFileStream::SetCompression(bool compression)
{
this->Compress = compression;
}
-//----------------------------------------------------------------------------
void cmGeneratedFileStream::SetCompressionExtraExtension(bool ext)
{
this->CompressExtraExtension = ext;
}
-//----------------------------------------------------------------------------
-cmGeneratedFileStreamBase::cmGeneratedFileStreamBase():
- Name(),
- TempName(),
- CopyIfDifferent(false),
- Okay(false),
- Compress(false),
- CompressExtraExtension(true)
+cmGeneratedFileStreamBase::cmGeneratedFileStreamBase()
+ : Name()
+ , TempName()
+ , CopyIfDifferent(false)
+ , Okay(false)
+ , Compress(false)
+ , CompressExtraExtension(true)
{
}
-//----------------------------------------------------------------------------
-cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(const char* name):
- Name(),
- TempName(),
- CopyIfDifferent(false),
- Okay(false),
- Compress(false),
- CompressExtraExtension(true)
+cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(const char* name)
+ : Name()
+ , TempName()
+ , CopyIfDifferent(false)
+ , Okay(false)
+ , Compress(false)
+ , CompressExtraExtension(true)
{
this->Open(name);
}
-//----------------------------------------------------------------------------
cmGeneratedFileStreamBase::~cmGeneratedFileStreamBase()
{
this->Close();
}
-//----------------------------------------------------------------------------
void cmGeneratedFileStreamBase::Open(const char* name)
{
// Save the original name of the file.
@@ -152,84 +144,71 @@ void cmGeneratedFileStreamBase::Open(const char* name)
#endif
// Make sure the temporary file that will be used is not present.
- cmSystemTools::RemoveFile(this->TempName.c_str());
+ cmSystemTools::RemoveFile(this->TempName);
std::string dir = cmSystemTools::GetFilenamePath(this->TempName);
cmSystemTools::MakeDirectory(dir.c_str());
}
-//----------------------------------------------------------------------------
bool cmGeneratedFileStreamBase::Close()
{
bool replaced = false;
std::string resname = this->Name;
- if ( this->Compress && this->CompressExtraExtension )
- {
+ if (this->Compress && this->CompressExtraExtension) {
resname += ".gz";
- }
+ }
// Only consider replacing the destination file if no error
// occurred.
- if(!this->Name.empty() &&
- this->Okay &&
- (!this->CopyIfDifferent ||
- cmSystemTools::FilesDiffer(this->TempName.c_str(), resname.c_str())))
- {
+ if (!this->Name.empty() && this->Okay &&
+ (!this->CopyIfDifferent ||
+ cmSystemTools::FilesDiffer(this->TempName, resname))) {
// The destination is to be replaced. Rename the temporary to the
// destination atomically.
- if ( this->Compress )
- {
+ if (this->Compress) {
std::string gzname = this->TempName + ".temp.gz";
- if ( this->CompressFile(this->TempName.c_str(), gzname.c_str()) )
- {
+ if (this->CompressFile(this->TempName.c_str(), gzname.c_str())) {
this->RenameFile(gzname.c_str(), resname.c_str());
- }
- cmSystemTools::RemoveFile(gzname.c_str());
}
- else
- {
+ cmSystemTools::RemoveFile(gzname);
+ } else {
this->RenameFile(this->TempName.c_str(), resname.c_str());
- }
+ }
replaced = true;
- }
+ }
// Else, the destination was not replaced.
//
// Always delete the temporary file. We never want it to stay around.
- cmSystemTools::RemoveFile(this->TempName.c_str());
+ cmSystemTools::RemoveFile(this->TempName);
return replaced;
}
-//----------------------------------------------------------------------------
#ifdef CMAKE_BUILD_WITH_CMAKE
int cmGeneratedFileStreamBase::CompressFile(const char* oldname,
const char* newname)
{
gzFile gf = gzopen(newname, "w");
- if ( !gf )
- {
+ if (!gf) {
return 0;
- }
- FILE* ifs = fopen(oldname, "r");
- if ( !ifs )
- {
+ }
+ FILE* ifs = cmsys::SystemTools::Fopen(oldname, "r");
+ if (!ifs) {
return 0;
- }
+ }
size_t res;
const size_t BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
- while ( (res = fread(buffer, 1, BUFFER_SIZE, ifs)) > 0 )
- {
- if ( !gzwrite(gf, buffer, static_cast<int>(res)) )
- {
+ while ((res = fread(buffer, 1, BUFFER_SIZE, ifs)) > 0) {
+ if (!gzwrite(gf, buffer, static_cast<int>(res))) {
fclose(ifs);
gzclose(gf);
return 0;
- }
}
+ }
fclose(ifs);
gzclose(gf);
return 1;
@@ -241,20 +220,13 @@ int cmGeneratedFileStreamBase::CompressFile(const char*, const char*)
}
#endif
-//----------------------------------------------------------------------------
int cmGeneratedFileStreamBase::RenameFile(const char* oldname,
const char* newname)
{
return cmSystemTools::RenameFile(oldname, newname);
}
-//----------------------------------------------------------------------------
-void cmGeneratedFileStream::SetName(const char* fname)
+void cmGeneratedFileStream::SetName(const std::string& fname)
{
- if ( !fname )
- {
- this->Name = "";
- return;
- }
this->Name = fname;
}
diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h
index dac9c7b40..56f9988ff 100644
--- a/Source/cmGeneratedFileStream.h
+++ b/Source/cmGeneratedFileStream.h
@@ -1,22 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratedFileStream_h
#define cmGeneratedFileStream_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma set woff 1375 /* base class destructor not virtual */
-#endif
+#include "cm_codecvt.hxx"
+#include "cmsys/FStream.hxx"
+#include <string>
// This is the first base class of cmGeneratedFileStream. It will be
// created before and destroyed after the ofstream portion and can
@@ -59,10 +50,10 @@ protected:
// Whether the real file stream was valid when it was closed.
bool Okay;
- // Whether the destionation file is compressed
+ // Whether the destination file is compressed
bool Compress;
- // Whether the destionation file is compressed
+ // Whether the destination file is compressed
bool CompressExtraExtension;
};
@@ -76,17 +67,18 @@ protected:
* contents have changed to prevent the file modification time from
* being updated.
*/
-class cmGeneratedFileStream: private cmGeneratedFileStreamBase,
- public std::ofstream
+class cmGeneratedFileStream : private cmGeneratedFileStreamBase,
+ public cmsys::ofstream
{
public:
- typedef std::ofstream Stream;
+ typedef cmsys::ofstream Stream;
+ typedef codecvt::Encoding Encoding;
/**
* This constructor prepares a default stream. The open method must
* be used before writing to the stream.
*/
- cmGeneratedFileStream();
+ cmGeneratedFileStream(Encoding encoding = codecvt::None);
/**
* This constructor takes the name of the file to be generated. It
@@ -94,14 +86,15 @@ 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(const char* name, bool quiet = false,
+ Encoding encoding = codecvt::None);
/**
* The destructor checks the stream status to be sure the temporary
* file was successfully written before allowing the original to be
* replaced.
*/
- ~cmGeneratedFileStream();
+ ~cmGeneratedFileStream() CM_OVERRIDE;
/**
* Open an output file by name. This should be used only with a
@@ -109,8 +102,8 @@ 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,
- bool binaryFlag=false);
+ cmGeneratedFileStream& Open(const char* name, bool quiet = false,
+ bool binaryFlag = false);
/**
* Close the output file. This should be used only with an open
@@ -139,14 +132,10 @@ public:
* Set name of the file that will hold the actual output. This method allows
* the output file to be changed during the use of cmGeneratedFileStream.
*/
- void SetName(const char* fname);
+ void SetName(const std::string& fname);
private:
cmGeneratedFileStream(cmGeneratedFileStream const&); // not implemented
};
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma reset woff 1375 /* base class destructor not virtual */
-#endif
-
#endif
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index d73c72c10..00b5ff4ef 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -1,118 +1,98 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpression.h"
-#include "cmMakefile.h"
-#include "cmTarget.h"
-#include "assert.h"
-
-#include <cmsys/String.h>
+#include "cmsys/RegularExpression.hxx"
+#include <utility>
+#include "assert.h"
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionLexer.h"
#include "cmGeneratorExpressionParser.h"
-#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
-//----------------------------------------------------------------------------
cmGeneratorExpression::cmGeneratorExpression(
- cmListFileBacktrace const& backtrace):
- Backtrace(backtrace)
+ const cmListFileBacktrace& backtrace)
+ : Backtrace(backtrace)
{
}
-//----------------------------------------------------------------------------
-cmsys::auto_ptr<cmCompiledGeneratorExpression>
-cmGeneratorExpression::Parse(std::string const& input)
+CM_AUTO_PTR<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
+ std::string const& input)
{
- return this->Parse(input.c_str());
+ return CM_AUTO_PTR<cmCompiledGeneratorExpression>(
+ new cmCompiledGeneratorExpression(this->Backtrace, input));
}
-//----------------------------------------------------------------------------
-cmsys::auto_ptr<cmCompiledGeneratorExpression>
-cmGeneratorExpression::Parse(const char* input)
+CM_AUTO_PTR<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
+ const char* input)
{
- return cmsys::auto_ptr<cmCompiledGeneratorExpression>(
- new cmCompiledGeneratorExpression(
- this->Backtrace,
- input));
+ return this->Parse(std::string(input ? input : ""));
}
cmGeneratorExpression::~cmGeneratorExpression()
{
}
-//----------------------------------------------------------------------------
-const char *cmCompiledGeneratorExpression::Evaluate(
- cmMakefile* mf, const char* config, bool quiet,
- cmTarget *headTarget,
- cmGeneratorExpressionDAGChecker *dagChecker) const
+const char* cmCompiledGeneratorExpression::Evaluate(
+ cmLocalGenerator* lg, const std::string& config, bool quiet,
+ const cmGeneratorTarget* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& language) const
{
- return this->Evaluate(mf,
- config,
- quiet,
- headTarget,
- headTarget,
- dagChecker);
+ return this->Evaluate(lg, config, quiet, headTarget, headTarget, dagChecker,
+ language);
}
-//----------------------------------------------------------------------------
-const char *cmCompiledGeneratorExpression::Evaluate(
- cmMakefile* mf, const char* config, bool quiet,
- cmTarget *headTarget,
- cmTarget *currentTarget,
- cmGeneratorExpressionDAGChecker *dagChecker) const
+const char* cmCompiledGeneratorExpression::Evaluate(
+ cmLocalGenerator* lg, const std::string& config, bool quiet,
+ const cmGeneratorTarget* headTarget, const cmGeneratorTarget* currentTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& language) const
{
- if (!this->NeedsParsing)
- {
+ cmGeneratorExpressionContext context(
+ lg, config, quiet, headTarget, currentTarget ? currentTarget : headTarget,
+ this->EvaluateForBuildsystem, this->Backtrace, language);
+
+ return this->EvaluateWithContext(context, dagChecker);
+}
+
+const char* cmCompiledGeneratorExpression::EvaluateWithContext(
+ cmGeneratorExpressionContext& context,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ if (!this->NeedsEvaluation) {
return this->Input.c_str();
- }
+ }
this->Output = "";
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
- = this->Evaluators.begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
- = this->Evaluators.end();
-
- cmGeneratorExpressionContext context;
- context.Makefile = mf;
- context.Config = config;
- context.Quiet = quiet;
- context.HadError = false;
- context.HadContextSensitiveCondition = false;
- context.HeadTarget = headTarget;
- context.CurrentTarget = currentTarget ? currentTarget : headTarget;
- context.Backtrace = this->Backtrace;
-
- for ( ; it != end; ++it)
- {
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
+ this->Evaluators.begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
+ this->Evaluators.end();
+
+ for (; it != end; ++it) {
this->Output += (*it)->Evaluate(&context, dagChecker);
- for(std::set<cmStdString>::const_iterator
- p = context.SeenTargetProperties.begin();
- p != context.SeenTargetProperties.end(); ++p)
- {
- this->SeenTargetProperties.insert(*p);
- }
- if (context.HadError)
- {
+ this->SeenTargetProperties.insert(context.SeenTargetProperties.begin(),
+ context.SeenTargetProperties.end());
+ if (context.HadError) {
this->Output = "";
break;
- }
}
- if (!context.HadError)
- {
+ }
+
+ this->MaxLanguageStandard = context.MaxLanguageStandard;
+
+ if (!context.HadError) {
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
- }
+ this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition;
+ this->SourceSensitiveTargets = context.SourceSensitiveTargets;
+ }
this->DependTargets = context.DependTargets;
this->AllTargetsSeen = context.AllTargets;
@@ -121,338 +101,288 @@ const char *cmCompiledGeneratorExpression::Evaluate(
}
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
- cmListFileBacktrace const& backtrace,
- const char *input)
- : Backtrace(backtrace), Input(input ? input : ""),
- HadContextSensitiveCondition(false)
+ cmListFileBacktrace const& backtrace, const std::string& input)
+ : Backtrace(backtrace)
+ , Input(input)
+ , HadContextSensitiveCondition(false)
+ , HadHeadSensitiveCondition(false)
+ , EvaluateForBuildsystem(false)
{
cmGeneratorExpressionLexer l;
- std::vector<cmGeneratorExpressionToken> tokens =
- l.Tokenize(this->Input.c_str());
- this->NeedsParsing = l.GetSawGeneratorExpression();
+ std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input);
+ this->NeedsEvaluation = l.GetSawGeneratorExpression();
- if (this->NeedsParsing)
- {
+ if (this->NeedsEvaluation) {
cmGeneratorExpressionParser p(tokens);
p.Parse(this->Evaluators);
- }
+ }
}
-
-//----------------------------------------------------------------------------
cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
{
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
- = this->Evaluators.begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
- = this->Evaluators.end();
-
- for ( ; it != end; ++it)
- {
- delete *it;
- }
+ cmDeleteAll(this->Evaluators);
}
-//----------------------------------------------------------------------------
std::string cmGeneratorExpression::StripEmptyListElements(
- const std::string &input)
+ const std::string& input)
{
+ if (input.find(';') == std::string::npos) {
+ return input;
+ }
std::string result;
+ result.reserve(input.size());
- const char *c = input.c_str();
+ const char* c = input.c_str();
+ const char* last = c;
bool skipSemiColons = true;
- for ( ; *c; ++c)
- {
- if(c[0] == ';')
- {
- if(skipSemiColons)
- {
- continue;
- }
- skipSemiColons = true;
+ for (; *c; ++c) {
+ if (*c == ';') {
+ if (skipSemiColons) {
+ result.append(last, c - last);
+ last = c + 1;
}
- else
- {
+ skipSemiColons = true;
+ } else {
skipSemiColons = false;
- }
- result += *c;
}
+ }
+ result.append(last);
- if (!result.empty() && *(result.end() - 1) == ';')
- {
+ if (!result.empty() && *(result.end() - 1) == ';') {
result.resize(result.size() - 1);
- }
+ }
return result;
}
-//----------------------------------------------------------------------------
-static std::string stripAllGeneratorExpressions(const std::string &input)
+static std::string stripAllGeneratorExpressions(const std::string& input)
{
std::string result;
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
int nestingLevel = 0;
- while((pos = input.find("$<", lastPos)) != input.npos)
- {
+ while ((pos = input.find("$<", lastPos)) != std::string::npos) {
result += input.substr(lastPos, pos - lastPos);
pos += 2;
nestingLevel = 1;
- const char *c = input.c_str() + pos;
- const char * const cStart = c;
- for ( ; *c; ++c)
- {
- if(c[0] == '$' && c[1] == '<')
- {
+ const char* c = input.c_str() + pos;
+ const char* const cStart = c;
+ for (; *c; ++c) {
+ if (c[0] == '$' && c[1] == '<') {
++nestingLevel;
++c;
continue;
- }
- if(c[0] == '>')
- {
+ }
+ if (c[0] == '>') {
--nestingLevel;
- if (nestingLevel == 0)
- {
+ if (nestingLevel == 0) {
break;
- }
}
}
+ }
const std::string::size_type traversed = (c - cStart) + 1;
- if (!*c)
- {
+ if (!*c) {
result += "$<" + input.substr(pos, traversed);
- }
+ }
pos += traversed;
lastPos = pos;
- }
- if (nestingLevel == 0)
- {
+ }
+ if (nestingLevel == 0) {
result += input.substr(lastPos);
- }
+ }
return cmGeneratorExpression::StripEmptyListElements(result);
}
-//----------------------------------------------------------------------------
-static void prefixItems(const std::string &content, std::string &result,
- const std::string &prefix)
+static void prefixItems(const std::string& content, std::string& result,
+ const std::string& prefix)
{
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)
- {
+ const char* sep = "";
+ for (std::vector<std::string>::const_iterator ei = entries.begin();
+ ei != entries.end(); ++ei) {
result += sep;
sep = ";";
- if (!cmSystemTools::FileIsFullPath(ei->c_str())
- && cmGeneratorExpression::Find(*ei) == std::string::npos)
- {
+ if (!cmSystemTools::FileIsFullPath(ei->c_str()) &&
+ cmGeneratorExpression::Find(*ei) != 0) {
result += prefix;
- }
- result += *ei;
}
+ result += *ei;
+ }
}
-//----------------------------------------------------------------------------
-static std::string stripExportInterface(const std::string &input,
- cmGeneratorExpression::PreprocessContext context,
- bool resolveRelative)
+static std::string stripExportInterface(
+ const std::string& input, cmGeneratorExpression::PreprocessContext context,
+ bool resolveRelative)
{
std::string result;
int nestingLevel = 0;
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
- while (true)
- {
+ while (true) {
std::string::size_type bPos = input.find("$<BUILD_INTERFACE:", lastPos);
std::string::size_type iPos = input.find("$<INSTALL_INTERFACE:", lastPos);
- if (bPos == std::string::npos && iPos == std::string::npos)
- {
+ if (bPos == std::string::npos && iPos == std::string::npos) {
break;
- }
+ }
- if (bPos == std::string::npos)
- {
+ if (bPos == std::string::npos) {
pos = iPos;
- }
- else if (iPos == std::string::npos)
- {
+ } else if (iPos == std::string::npos) {
pos = bPos;
- }
- else
- {
+ } else {
pos = (bPos < iPos) ? bPos : iPos;
- }
+ }
result += input.substr(lastPos, pos - lastPos);
const bool gotInstallInterface = input[pos + 2] == 'I';
pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
: sizeof("$<BUILD_INTERFACE:") - 1;
nestingLevel = 1;
- const char *c = input.c_str() + pos;
- const char * const cStart = c;
- for ( ; *c; ++c)
- {
- if(c[0] == '$' && c[1] == '<')
- {
+ const char* c = input.c_str() + pos;
+ const char* const cStart = c;
+ for (; *c; ++c) {
+ if (c[0] == '$' && c[1] == '<') {
++nestingLevel;
++c;
continue;
- }
- if(c[0] == '>')
- {
+ }
+ if (c[0] == '>') {
--nestingLevel;
- if (nestingLevel != 0)
- {
+ if (nestingLevel != 0) {
continue;
- }
- if(context == cmGeneratorExpression::BuildInterface
- && !gotInstallInterface)
- {
+ }
+ if (context == cmGeneratorExpression::BuildInterface &&
+ !gotInstallInterface) {
result += input.substr(pos, c - cStart);
- }
- else if(context == cmGeneratorExpression::InstallInterface
- && gotInstallInterface)
- {
+ } else if (context == cmGeneratorExpression::InstallInterface &&
+ gotInstallInterface) {
const std::string content = input.substr(pos, c - cStart);
- if (resolveRelative)
- {
+ if (resolveRelative) {
prefixItems(content, result, "${_IMPORT_PREFIX}/");
- }
- else
- {
+ } else {
result += content;
- }
}
- break;
}
+ break;
}
+ }
const std::string::size_type traversed = (c - cStart) + 1;
- if (!*c)
- {
+ if (!*c) {
result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
- : "$<BUILD_INTERFACE:")
- + input.substr(pos, traversed);
- }
+ : "$<BUILD_INTERFACE:") +
+ input.substr(pos, traversed);
+ }
pos += traversed;
lastPos = pos;
- }
- if (nestingLevel == 0)
- {
+ }
+ if (nestingLevel == 0) {
result += input.substr(lastPos);
- }
+ }
return cmGeneratorExpression::StripEmptyListElements(result);
}
-//----------------------------------------------------------------------------
-void cmGeneratorExpression::Split(const std::string &input,
- std::vector<std::string> &output)
+void cmGeneratorExpression::Split(const std::string& input,
+ std::vector<std::string>& output)
{
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
- while((pos = input.find("$<", lastPos)) != input.npos)
- {
+ while ((pos = input.find("$<", lastPos)) != std::string::npos) {
std::string part = input.substr(lastPos, pos - lastPos);
std::string preGenex;
- if (!part.empty())
- {
- std::string::size_type startPos = input.rfind(";", pos);
- if (startPos == std::string::npos)
- {
+ if (!part.empty()) {
+ std::string::size_type startPos = input.rfind(';', pos);
+ if (startPos == std::string::npos) {
preGenex = part;
part = "";
- }
- else if (startPos != pos - 1 && startPos >= lastPos)
- {
+ } 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.c_str(), output);
- }
}
+ if (!part.empty()) {
+ cmSystemTools::ExpandListArgument(part, output);
+ }
+ }
pos += 2;
int nestingLevel = 1;
- const char *c = input.c_str() + pos;
- const char * const cStart = c;
- for ( ; *c; ++c)
- {
- if(c[0] == '$' && c[1] == '<')
- {
+ const char* c = input.c_str() + pos;
+ const char* const cStart = c;
+ for (; *c; ++c) {
+ if (c[0] == '$' && c[1] == '<') {
++nestingLevel;
++c;
continue;
- }
- if(c[0] == '>')
- {
+ }
+ if (c[0] == '>') {
--nestingLevel;
- if (nestingLevel == 0)
- {
+ if (nestingLevel == 0) {
break;
- }
}
}
- for ( ; *c; ++c)
- {
+ }
+ for (; *c; ++c) {
// Capture the part after the genex and before the next ';'
- if(c[0] == ';')
- {
+ if (c[0] == ';') {
--c;
break;
- }
}
+ }
const std::string::size_type traversed = (c - cStart) + 1;
output.push_back(preGenex + "$<" + input.substr(pos, traversed));
pos += traversed;
lastPos = pos;
- }
- if (lastPos < input.size())
- {
+ }
+ if (lastPos < input.size()) {
cmSystemTools::ExpandListArgument(input.substr(lastPos), output);
- }
+ }
}
-//----------------------------------------------------------------------------
-std::string cmGeneratorExpression::Preprocess(const std::string &input,
+std::string cmGeneratorExpression::Preprocess(const std::string& input,
PreprocessContext context,
bool resolveRelative)
{
- if (context == StripAllGeneratorExpressions)
- {
+ if (context == StripAllGeneratorExpressions) {
return stripAllGeneratorExpressions(input);
- }
- else if (context == BuildInterface || context == InstallInterface)
- {
+ }
+ if (context == BuildInterface || context == InstallInterface) {
return stripExportInterface(input, context, resolveRelative);
- }
+ }
- assert(!"cmGeneratorExpression::Preprocess called with invalid args");
+ assert(false &&
+ "cmGeneratorExpression::Preprocess called with invalid args");
return std::string();
}
-//----------------------------------------------------------------------------
-std::string::size_type cmGeneratorExpression::Find(const std::string &input)
+std::string::size_type cmGeneratorExpression::Find(const std::string& input)
{
const std::string::size_type openpos = input.find("$<");
- if (openpos != std::string::npos
- && input.find(">", openpos) != std::string::npos)
- {
+ if (openpos != std::string::npos &&
+ input.find('>', openpos) != std::string::npos) {
return openpos;
- }
+ }
return std::string::npos;
}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpression::IsValidTargetName(const std::string &input)
+bool cmGeneratorExpression::IsValidTargetName(const std::string& input)
{
- cmsys::RegularExpression targetNameValidator;
// The ':' is supported to allow use with IMPORTED targets. At least
// Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter.
- targetNameValidator.compile("^[A-Za-z0-9_.:+-]+$");
+ static cmsys::RegularExpression targetNameValidator("^[A-Za-z0-9_.:+-]+$");
+
+ return targetNameValidator.find(input);
+}
- return targetNameValidator.find(input.c_str());
+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);
+ if (it != this->MaxLanguageStandard.end()) {
+ mapping = it->second;
+ }
}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index c20f130c9..34516f5c5 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -1,34 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorExpression_h
#define cmGeneratorExpression_h
-#include "cmStandardIncludes.h"
-#include "cmListFileCache.h"
-
-#include <stack>
+#include "cmConfigure.h"
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/auto_ptr.hxx>
-
-class cmTarget;
-class cmMakefile;
-class cmListFileBacktrace;
+#include "cmListFileCache.h"
-struct cmGeneratorExpressionEvaluator;
-struct cmGeneratorExpressionDAGChecker;
+#include "cm_auto_ptr.hxx"
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
class cmCompiledGeneratorExpression;
+class cmGeneratorTarget;
+class cmLocalGenerator;
+struct cmGeneratorExpressionContext;
+struct cmGeneratorExpressionDAGChecker;
+struct cmGeneratorExpressionEvaluator;
/** \class cmGeneratorExpression
* \brief Evaluate generate-time query expression syntax.
@@ -41,98 +31,125 @@ class cmCompiledGeneratorExpression;
*/
class cmGeneratorExpression
{
+ CM_DISABLE_COPY(cmGeneratorExpression)
+
public:
/** Construct. */
- cmGeneratorExpression(cmListFileBacktrace const& backtrace);
+ cmGeneratorExpression(
+ cmListFileBacktrace const& backtrace = cmListFileBacktrace());
~cmGeneratorExpression();
- cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(
- std::string const& input);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(const char* input);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> Parse(std::string const& input);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> Parse(const char* input);
- enum PreprocessContext {
+ enum PreprocessContext
+ {
StripAllGeneratorExpressions,
BuildInterface,
InstallInterface
};
- static std::string Preprocess(const std::string &input,
+ static std::string Preprocess(const std::string& input,
PreprocessContext context,
bool resolveRelative = false);
- static void Split(const std::string &input,
- std::vector<std::string> &output);
+ static void Split(const std::string& input,
+ std::vector<std::string>& output);
- static std::string::size_type Find(const std::string &input);
+ static std::string::size_type Find(const std::string& input);
- static bool IsValidTargetName(const std::string &input);
+ static bool IsValidTargetName(const std::string& input);
- static std::string StripEmptyListElements(const std::string &input);
-private:
- cmGeneratorExpression(const cmGeneratorExpression &);
- void operator=(const cmGeneratorExpression &);
+ static std::string StripEmptyListElements(const std::string& input);
- cmListFileBacktrace const& Backtrace;
+private:
+ cmListFileBacktrace Backtrace;
};
class cmCompiledGeneratorExpression
{
+ CM_DISABLE_COPY(cmCompiledGeneratorExpression)
+
public:
- const char* Evaluate(cmMakefile* mf, const char* config,
- bool quiet = false,
- cmTarget *headTarget = 0,
- cmTarget *currentTarget = 0,
- cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
- const char* Evaluate(cmMakefile* mf, const char* config,
- bool quiet,
- cmTarget *headTarget,
- cmGeneratorExpressionDAGChecker *dagChecker) const;
+ 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,
+ 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<cmTarget*> const& GetTargets() const
- { return this->DependTargets; }
+ std::set<cmGeneratorTarget*> const& GetTargets() const
+ {
+ return this->DependTargets;
+ }
- std::set<cmStdString> const& GetSeenTargetProperties() const
- { return this->SeenTargetProperties; }
+ std::set<std::string> const& GetSeenTargetProperties() const
+ {
+ return this->SeenTargetProperties;
+ }
- std::set<cmTarget*> const& GetAllTargetsSeen() const
- { return this->AllTargetsSeen; }
+ std::set<cmGeneratorTarget const*> const& GetAllTargetsSeen() const
+ {
+ return this->AllTargetsSeen;
+ }
~cmCompiledGeneratorExpression();
- std::string GetInput() const
+ std::string const& GetInput() const { return this->Input; }
+
+ cmListFileBacktrace GetBacktrace() const { return this->Backtrace; }
+ bool GetHadContextSensitiveCondition() const
{
- return this->Input;
+ return this->HadContextSensitiveCondition;
}
-
- cmListFileBacktrace GetBacktrace() const
+ bool GetHadHeadSensitiveCondition() const
{
- return this->Backtrace;
+ return this->HadHeadSensitiveCondition;
}
- bool GetHadContextSensitiveCondition() const
+ std::set<cmGeneratorTarget const*> GetSourceSensitiveTargets() const
{
- return this->HadContextSensitiveCondition;
+ return this->SourceSensitiveTargets;
+ }
+
+ void SetEvaluateForBuildsystem(bool eval)
+ {
+ this->EvaluateForBuildsystem = eval;
}
+ void GetMaxLanguageStandard(cmGeneratorTarget const* tgt,
+ std::map<std::string, std::string>& mapping);
+
private:
+ const char* EvaluateWithContext(
+ cmGeneratorExpressionContext& context,
+ cmGeneratorExpressionDAGChecker* dagChecker) const;
+
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
- const char *input);
+ const std::string& input);
friend class cmGeneratorExpression;
- cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &);
- void operator=(const cmCompiledGeneratorExpression &);
-
cmListFileBacktrace Backtrace;
std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
const std::string Input;
- bool NeedsParsing;
-
- mutable std::set<cmTarget*> DependTargets;
- mutable std::set<cmTarget*> AllTargetsSeen;
- mutable std::set<cmStdString> SeenTargetProperties;
+ bool NeedsEvaluation;
+
+ 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> >
+ MaxLanguageStandard;
mutable std::string Output;
mutable bool HadContextSensitiveCondition;
+ mutable bool HadHeadSensitiveCondition;
+ mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets;
+ bool EvaluateForBuildsystem;
};
#endif
diff --git a/Source/cmGeneratorExpressionContext.cxx b/Source/cmGeneratorExpressionContext.cxx
new file mode 100644
index 000000000..a6dde5d39
--- /dev/null
+++ b/Source/cmGeneratorExpressionContext.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 "cmGeneratorExpressionContext.h"
+
+cmGeneratorExpressionContext::cmGeneratorExpressionContext(
+ cmLocalGenerator* lg, std::string const& config, bool quiet,
+ cmGeneratorTarget const* headTarget, const cmGeneratorTarget* currentTarget,
+ bool evaluateForBuildsystem, cmListFileBacktrace const& backtrace,
+ std::string const& language)
+ : Backtrace(backtrace)
+ , LG(lg)
+ , Config(config)
+ , Language(language)
+ , HeadTarget(headTarget)
+ , CurrentTarget(currentTarget)
+ , Quiet(quiet)
+ , HadError(false)
+ , HadContextSensitiveCondition(false)
+ , HadHeadSensitiveCondition(false)
+ , EvaluateForBuildsystem(evaluateForBuildsystem)
+{
+}
diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h
new file mode 100644
index 000000000..cf292dcef
--- /dev/null
+++ b/Source/cmGeneratorExpressionContext.h
@@ -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. */
+#ifndef cmGeneratorExpressionContext_h
+#define cmGeneratorExpressionContext_h
+
+#include "cmListFileCache.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
+
+struct cmGeneratorExpressionContext
+{
+ cmGeneratorExpressionContext(cmLocalGenerator* lg, std::string const& config,
+ bool quiet, const cmGeneratorTarget* headTarget,
+ cmGeneratorTarget const* currentTarget,
+ bool evaluateForBuildsystem,
+ cmListFileBacktrace const& backtrace,
+ std::string const& 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> >
+ MaxLanguageStandard;
+ cmLocalGenerator* LG;
+ std::string Config;
+ std::string Language;
+ // The target whose property is being evaluated.
+ cmGeneratorTarget const* HeadTarget;
+ // The dependent of HeadTarget which appears
+ // directly or indirectly in the property.
+ cmGeneratorTarget const* CurrentTarget;
+ bool Quiet;
+ bool HadError;
+ bool HadContextSensitiveCondition;
+ bool HadHeadSensitiveCondition;
+ bool EvaluateForBuildsystem;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 92dc054c9..c0266311b 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -1,212 +1,224 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGeneratorExpressionDAGChecker.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorExpressionEvaluator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmake.h"
-#include "cmGeneratorExpressionDAGChecker.h"
+#include <sstream>
+#include <string.h>
+#include <utility>
-#include "cmMakefile.h"
+cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
+ const cmListFileBacktrace& backtrace, const std::string& target,
+ const std::string& property, const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* parent)
+ : Parent(parent)
+ , Target(target)
+ , Property(property)
+ , Content(content)
+ , Backtrace(backtrace)
+ , TransitivePropertiesOnly(false)
+{
+ Initialize();
+}
-//----------------------------------------------------------------------------
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
- const cmListFileBacktrace &backtrace,
- const std::string &target,
- const std::string &property,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *parent)
- : Parent(parent), Target(target), Property(property),
- Content(content), Backtrace(backtrace), TransitivePropertiesOnly(false)
+ const std::string& target, const std::string& property,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* parent)
+ : Parent(parent)
+ , Target(target)
+ , Property(property)
+ , Content(content)
+ , Backtrace()
+ , TransitivePropertiesOnly(false)
{
- const cmGeneratorExpressionDAGChecker *top = this;
- const cmGeneratorExpressionDAGChecker *p = this->Parent;
- while (p)
- {
+ Initialize();
+}
+
+void cmGeneratorExpressionDAGChecker::Initialize()
+{
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* p = this->Parent;
+ while (p) {
top = p;
p = p->Parent;
- }
- this->CheckResult = this->checkGraph();
-
-#define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) \
- top->METHOD () ||
-
- if (CheckResult == DAG && (
- CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(TEST_TRANSITIVE_PROPERTY_METHOD)
- false)
- )
- {
- std::map<cmStdString, std::set<cmStdString> >::const_iterator it
- = top->Seen.find(target);
- if (it != top->Seen.end())
- {
- const std::set<cmStdString> &propSet = it->second;
- const std::set<cmStdString>::const_iterator i = propSet.find(property);
- if (i != propSet.end())
- {
+ }
+ this->CheckResult = this->CheckGraph();
+
+#define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) top->METHOD() ||
+
+ if (CheckResult == DAG &&
+ (CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
+ TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy)
+#undef TEST_TRANSITIVE_PROPERTY_METHOD
+ {
+ std::map<std::string, std::set<std::string> >::const_iterator 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()) {
this->CheckResult = ALREADY_SEEN;
return;
- }
}
- const_cast<cmGeneratorExpressionDAGChecker *>(top)
- ->Seen[target].insert(property);
}
+ const_cast<cmGeneratorExpressionDAGChecker*>(top)
+ ->Seen[this->Target]
+ .insert(this->Property);
+ }
}
-//----------------------------------------------------------------------------
cmGeneratorExpressionDAGChecker::Result
-cmGeneratorExpressionDAGChecker::check() const
+cmGeneratorExpressionDAGChecker::Check() const
{
return this->CheckResult;
}
-//----------------------------------------------------------------------------
-void cmGeneratorExpressionDAGChecker::reportError(
- cmGeneratorExpressionContext *context,
- const std::string &expr)
+void cmGeneratorExpressionDAGChecker::ReportError(
+ cmGeneratorExpressionContext* context, const std::string& expr)
{
- if (this->CheckResult == DAG)
- {
+ if (this->CheckResult == DAG) {
return;
- }
+ }
context->HadError = true;
- if (context->Quiet)
- {
+ if (context->Quiet) {
return;
- }
+ }
- const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
- if (parent && !parent->Parent)
- {
- cmOStringStream e;
+ if (parent && !parent->Parent) {
+ std::ostringstream e;
e << "Error evaluating generator expression:\n"
<< " " << expr << "\n"
- << "Self reference on target \""
- << context->HeadTarget->GetName() << "\".\n";
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- parent->Backtrace);
+ << "Self reference on target \"" << context->HeadTarget->GetName()
+ << "\".\n";
+ context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ parent->Backtrace);
return;
- }
+ }
{
- cmOStringStream e;
+ std::ostringstream e;
+ /* clang-format off */
e << "Error evaluating generator expression:\n"
<< " " << expr << "\n"
<< "Dependency loop found.";
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- context->Backtrace);
+ /* clang-format on */
+ context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ context->Backtrace);
}
int loopStep = 1;
- while (parent)
- {
- cmOStringStream e;
+ while (parent) {
+ std::ostringstream e;
e << "Loop step " << loopStep << "\n"
<< " "
<< (parent->Content ? parent->Content->GetOriginalExpression() : expr)
<< "\n";
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- parent->Backtrace);
+ context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ parent->Backtrace);
parent = parent->Parent;
++loopStep;
- }
+ }
}
-//----------------------------------------------------------------------------
cmGeneratorExpressionDAGChecker::Result
-cmGeneratorExpressionDAGChecker::checkGraph() const
+cmGeneratorExpressionDAGChecker::CheckGraph() const
{
- const cmGeneratorExpressionDAGChecker *parent = this->Parent;
- while (parent)
- {
- if (this->Target == parent->Target && this->Property == parent->Property)
- {
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
+ if (this->Target == parent->Target && this->Property == parent->Property) {
return (parent == this->Parent) ? SELF_REFERENCE : CYCLIC_REFERENCE;
- }
- parent = parent->Parent;
}
+ parent = parent->Parent;
+ }
return DAG;
}
-//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly()
{
- const cmGeneratorExpressionDAGChecker *top = this;
- const cmGeneratorExpressionDAGChecker *parent = this->Parent;
- while (parent)
- {
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
top = parent;
parent = parent->Parent;
- }
+ }
return top->TransitivePropertiesOnly;
}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
+bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
{
- const cmGeneratorExpressionDAGChecker *top = this;
- const cmGeneratorExpressionDAGChecker *parent = this->Parent;
- while (parent)
- {
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
top = parent;
parent = parent->Parent;
- }
+ }
- const char *prop = top->Property.c_str();
+ const char* prop = top->Property.c_str();
- if (tgt)
- {
+ if (tgt) {
return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0;
- }
+ }
- return (strcmp(prop, "LINK_LIBRARIES") == 0
- || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
- || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
- || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0
- || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0)
- || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
+ return (strcmp(prop, "LINK_LIBRARIES") == 0 ||
+ strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 ||
+ strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 ||
+ cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
+ cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_")) ||
+ strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() const
+std::string cmGeneratorExpressionDAGChecker::TopTarget() const
{
- const char *prop = this->Property.c_str();
- return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0
- || strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 );
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
+ top = parent;
+ parent = parent->Parent;
+ }
+ return top->Target;
}
-//----------------------------------------------------------------------------
-bool
-cmGeneratorExpressionDAGChecker::EvaluatingSystemIncludeDirectories() const
+enum TransitiveProperty
{
- const char *prop = this->Property.c_str();
- return strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0;
-}
-
-//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
+#define DEFINE_ENUM_ENTRY(NAME) NAME,
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY)
+#undef DEFINE_ENUM_ENTRY
+ TransitivePropertyTerminal
+};
+
+template <TransitiveProperty>
+bool additionalTest(const char* const /*unused*/)
{
- const char *prop = this->Property.c_str();
- return (strcmp(prop, "COMPILE_DEFINITIONS") == 0
- || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
- || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
+ return false;
}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const
+template <>
+bool additionalTest<COMPILE_DEFINITIONS>(const char* const prop)
{
- const char *prop = this->Property.c_str();
- return (strcmp(prop, "COMPILE_OPTIONS") == 0
- || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 );
+ return cmHasLiteralPrefix(prop, "COMPILE_DEFINITIONS_");
}
+
+#define DEFINE_TRANSITIVE_PROPERTY_METHOD(METHOD, PROPERTY) \
+ bool cmGeneratorExpressionDAGChecker::METHOD() const \
+ { \
+ const char* const prop = this->Property.c_str(); \
+ if (strcmp(prop, #PROPERTY) == 0 || \
+ strcmp(prop, "INTERFACE_" #PROPERTY) == 0) { \
+ return true; \
+ } \
+ return additionalTest<PROPERTY>(prop); \
+ }
+
+CM_FOR_EACH_TRANSITIVE_PROPERTY(DEFINE_TRANSITIVE_PROPERTY_METHOD)
+
+#undef DEFINE_TRANSITIVE_PROPERTY_METHOD
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 0b7ef025c..557a19220 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -1,74 +1,89 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorExpressionDAGChecker_h
#define cmGeneratorExpressionDAGChecker_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include "cmListFileCache.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+struct GeneratorExpressionContent;
+struct cmGeneratorExpressionContext;
-#include "cmGeneratorExpressionEvaluator.h"
+#define CM_SELECT_BOTH(F, A1, A2) F(A1, A2)
+#define CM_SELECT_FIRST(F, A1, A2) F(A1)
+#define CM_SELECT_SECOND(F, A1, A2) F(A2)
-#define CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(F) \
- F(EvaluatingIncludeDirectories) \
- F(EvaluatingSystemIncludeDirectories) \
- F(EvaluatingCompileDefinitions) \
- F(EvaluatingCompileOptions)
+#define CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, SELECT) \
+ SELECT(F, EvaluatingIncludeDirectories, INCLUDE_DIRECTORIES) \
+ SELECT(F, EvaluatingSystemIncludeDirectories, SYSTEM_INCLUDE_DIRECTORIES) \
+ SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \
+ SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
+ SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \
+ SELECT(F, EvaluatingSources, SOURCES) \
+ SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES)
-#define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \
- F(INTERFACE_INCLUDE_DIRECTORIES) \
- F(INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) \
- F(INTERFACE_COMPILE_DEFINITIONS) \
- F(INTERFACE_COMPILE_OPTIONS)
+#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
+
+#define CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(F) \
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_FIRST)
+
+#define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_SECOND)
-//----------------------------------------------------------------------------
struct cmGeneratorExpressionDAGChecker
{
- cmGeneratorExpressionDAGChecker(const cmListFileBacktrace &backtrace,
- const std::string &target,
- const std::string &property,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *parent);
-
- enum Result {
+ cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace,
+ const std::string& target,
+ const std::string& property,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* parent);
+ cmGeneratorExpressionDAGChecker(const std::string& target,
+ const std::string& property,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* parent);
+
+ enum Result
+ {
DAG,
SELF_REFERENCE,
CYCLIC_REFERENCE,
ALREADY_SEEN
};
- Result check() const;
+ Result Check() const;
- void reportError(cmGeneratorExpressionContext *context,
- const std::string &expr);
+ void ReportError(cmGeneratorExpressionContext* context,
+ const std::string& expr);
- bool EvaluatingLinkLibraries(const char *tgt = 0);
+ bool EvaluatingLinkLibraries(const char* tgt = CM_NULLPTR);
-#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) \
- bool METHOD () const;
+#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
-CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
+
+#undef DECLARE_TRANSITIVE_PROPERTY_METHOD
bool GetTransitivePropertiesOnly();
- void SetTransitivePropertiesOnly()
- { this->TransitivePropertiesOnly = true; }
+ void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; }
+
+ std::string TopTarget() const;
private:
- Result checkGraph() const;
+ Result CheckGraph() const;
+ void Initialize();
private:
- const cmGeneratorExpressionDAGChecker * const Parent;
+ const cmGeneratorExpressionDAGChecker* const Parent;
const std::string Target;
const std::string Property;
- std::map<cmStdString, std::set<cmStdString> > Seen;
- const GeneratorExpressionContent * const Content;
+ std::map<std::string, std::set<std::string> > Seen;
+ const GeneratorExpressionContent* const Content;
const cmListFileBacktrace Backtrace;
Result CheckResult;
bool TransitivePropertiesOnly;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index cab99ed04..15264545b 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -1,151 +1,161 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionEvaluationFile.h"
-#include "cmMakefile.h"
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
+#include <sstream>
+#include <utility>
-#include <assert.h>
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-//----------------------------------------------------------------------------
cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
- const std::string &input,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr,
- cmMakefile *makefile,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent)
- : Input(input),
- OutputFileExpr(outputFileExpr),
- Makefile(makefile),
- Condition(condition),
- InputIsContent(inputIsContent)
+ const std::string& input,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> outputFileExpr,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent)
+ : Input(input)
+ , OutputFileExpr(outputFileExpr)
+ , Condition(condition)
+ , InputIsContent(inputIsContent)
{
}
-//----------------------------------------------------------------------------
-void cmGeneratorExpressionEvaluationFile::Generate(const char *config,
- cmCompiledGeneratorExpression* inputExpression,
- std::map<std::string, std::string> &outputFiles)
+void cmGeneratorExpressionEvaluationFile::Generate(
+ cmLocalGenerator* lg, const std::string& config, const std::string& lang,
+ cmCompiledGeneratorExpression* inputExpression,
+ std::map<std::string, std::string>& outputFiles, mode_t perm)
{
std::string rawCondition = this->Condition->GetInput();
- if (!rawCondition.empty())
- {
- std::string condResult = this->Condition->Evaluate(this->Makefile, config);
- if (condResult == "0")
- {
+ if (!rawCondition.empty()) {
+ std::string condResult = this->Condition->Evaluate(
+ lg, config, false, CM_NULLPTR, CM_NULLPTR, CM_NULLPTR, lang);
+ if (condResult == "0") {
return;
- }
- if (condResult != "1")
- {
- cmOStringStream e;
- e << "Evaluation file condition \"" << rawCondition << "\" did "
- "not evaluate to valid content. Got \"" << condResult << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ }
+ if (condResult != "1") {
+ std::ostringstream e;
+ e << "Evaluation file condition \"" << rawCondition
+ << "\" did "
+ "not evaluate to valid content. Got \""
+ << condResult << "\".";
+ lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
}
+ }
- const std::string outputFileName
- = this->OutputFileExpr->Evaluate(this->Makefile, config);
- const std::string outputContent
- = inputExpression->Evaluate(this->Makefile, config);
+ 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::map<std::string, std::string>::iterator it
- = outputFiles.find(outputFileName);
+ std::map<std::string, std::string>::iterator it =
+ outputFiles.find(outputFileName);
- if(it != outputFiles.end())
- {
- if (it->second == outputContent)
- {
+ if (it != outputFiles.end()) {
+ if (it->second == outputContent) {
return;
- }
- cmOStringStream e;
- e << "Evaluation file to be written multiple times for different "
- "configurations with different content:\n " << outputFileName;
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- return;
}
+ std::ostringstream e;
+ e << "Evaluation file to be written multiple times with different "
+ "content. "
+ "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());
+ return;
+ }
+ lg->GetMakefile()->AddCMakeOutputFile(outputFileName);
this->Files.push_back(outputFileName);
outputFiles[outputFileName] = outputContent;
- std::ofstream fout(outputFileName.c_str());
-
- if(!fout)
- {
- cmOStringStream e;
- e << "Evaluation file \"" << outputFileName << "\" cannot be written.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- return;
- }
-
+ cmGeneratedFileStream fout(outputFileName.c_str());
+ fout.SetCopyIfDifferent(true);
fout << outputContent;
+ if (fout.Close() && perm) {
+ cmSystemTools::SetPermissions(outputFileName.c_str(), perm);
+ }
+}
- fout.close();
+void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
+ cmLocalGenerator* lg, std::string const& config)
+{
+ 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) {
+ std::string name = this->OutputFileExpr->Evaluate(
+ lg, config, false, CM_NULLPTR, CM_NULLPTR, CM_NULLPTR, *le);
+ cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(name);
+ sf->SetProperty("GENERATED", "1");
+
+ gg->SetFilenameTargetDepends(
+ sf, this->OutputFileExpr->GetSourceSensitiveTargets());
+ }
}
-//----------------------------------------------------------------------------
-void cmGeneratorExpressionEvaluationFile::Generate()
+void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
{
+ mode_t perm = 0;
std::string inputContent;
- if (this->InputIsContent)
- {
+ if (this->InputIsContent) {
inputContent = this->Input;
- }
- else
- {
- std::ifstream fin(this->Input.c_str());
- if(!fin)
- {
- cmOStringStream e;
+ } else {
+ lg->GetMakefile()->AddCMakeDependFile(this->Input);
+ cmSystemTools::GetPermissions(this->Input.c_str(), perm);
+ cmsys::ifstream fin(this->Input.c_str());
+ if (!fin) {
+ std::ostringstream e;
e << "Evaluation file \"" << this->Input << "\" cannot be read.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
+ }
std::string line;
std::string sep;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
inputContent += sep + line;
sep = "\n";
- }
- inputContent += sep;
}
+ inputContent += sep;
+ }
cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace();
cmGeneratorExpression contentGE(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> inputExpression
- = contentGE.Parse(inputContent);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> inputExpression =
+ contentGE.Parse(inputContent);
std::map<std::string, std::string> outputFiles;
std::vector<std::string> allConfigs;
- this->Makefile->GetConfigurations(allConfigs);
-
- if (allConfigs.empty())
- {
- this->Generate(0, inputExpression.get(), outputFiles);
- }
- else
- {
- for(std::vector<std::string>::const_iterator li = allConfigs.begin();
- li != allConfigs.end(); ++li)
- {
- this->Generate(li->c_str(), inputExpression.get(), outputFiles);
- if(cmSystemTools::GetFatalErrorOccured())
- {
+ lg->GetMakefile()->GetConfigurations(allConfigs);
+
+ if (allConfigs.empty()) {
+ allConfigs.push_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);
+ if (cmSystemTools::GetFatalErrorOccured()) {
return;
- }
}
}
+ }
}
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 20ee5cb2d..98727460e 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -1,46 +1,44 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorExpressionEvaluationFile_h
#define cmGeneratorExpressionEvaluationFile_h
-#include "cmStandardIncludes.h"
-#include <cmsys/auto_ptr.hxx>
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
#include "cmGeneratorExpression.h"
+#include "cm_auto_ptr.hxx"
+#include "cm_sys_stat.h"
+
+class cmLocalGenerator;
-//----------------------------------------------------------------------------
class cmGeneratorExpressionEvaluationFile
{
public:
- cmGeneratorExpressionEvaluationFile(const std::string &input,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr,
- cmMakefile *makefile,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent);
+ cmGeneratorExpressionEvaluationFile(
+ const std::string& input,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> outputFileExpr,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent);
- void Generate();
+ void Generate(cmLocalGenerator* lg);
std::vector<std::string> GetFiles() const { return this->Files; }
+ void CreateOutputFile(cmLocalGenerator* lg, std::string const& config);
+
private:
- void Generate(const char *config,
- cmCompiledGeneratorExpression* inputExpression,
- std::map<std::string, std::string> &outputFiles);
+ void Generate(cmLocalGenerator* lg, const std::string& config,
+ const std::string& lang,
+ cmCompiledGeneratorExpression* inputExpression,
+ std::map<std::string, std::string>& outputFiles, mode_t perm);
private:
const std::string Input;
- const cmsys::auto_ptr<cmCompiledGeneratorExpression> OutputFileExpr;
- cmMakefile *Makefile;
- const cmsys::auto_ptr<cmCompiledGeneratorExpression> Condition;
+ const CM_AUTO_PTR<cmCompiledGeneratorExpression> OutputFileExpr;
+ const CM_AUTO_PTR<cmCompiledGeneratorExpression> Condition;
std::vector<std::string> Files;
const bool InputIsContent;
};
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 8b3135412..6ce4a8e72 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -1,1654 +1,192 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmMakefile.h"
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionEvaluator.h"
-#include "cmGeneratorExpressionParser.h"
-#include "cmGeneratorExpressionDAGChecker.h"
-#include "cmGeneratorExpression.h"
-
-#include <cmsys/String.h>
-
-#include <assert.h>
-
-//----------------------------------------------------------------------------
-#if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510
-static
-#endif
-void reportError(cmGeneratorExpressionContext *context,
- const std::string &expr, const std::string &result)
-{
- context->HadError = true;
- if (context->Quiet)
- {
- return;
- }
-
- cmOStringStream e;
- e << "Error evaluating generator expression:\n"
- << " " << expr << "\n"
- << result;
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- context->Backtrace);
-}
-
-//----------------------------------------------------------------------------
-struct cmGeneratorExpressionNode
-{
- enum {
- DynamicParameters = 0,
- OneOrMoreParameters = -1,
- ZeroOrMoreParameters = -2
- };
- virtual ~cmGeneratorExpressionNode() {}
-
- virtual bool GeneratesContent() const { return true; }
-
- virtual bool RequiresLiteralInput() const { return false; }
-
- virtual bool AcceptsArbitraryContentParameter() const
- { return false; }
-
- virtual int NumExpectedParameters() const { return 1; }
-
- virtual std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker
- ) const = 0;
-};
-
-//----------------------------------------------------------------------------
-static const struct ZeroNode : public cmGeneratorExpressionNode
-{
- ZeroNode() {}
-
- virtual bool GeneratesContent() const { return false; }
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- // Unreachable
- return std::string();
- }
-} zeroNode;
-
-//----------------------------------------------------------------------------
-static const struct OneNode : public cmGeneratorExpressionNode
-{
- OneNode() {}
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- // Unreachable
- return std::string();
- }
-} oneNode;
-
-//----------------------------------------------------------------------------
-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; \
- } \
- else 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
-{
- NotNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- if (*parameters.begin() != "0" && *parameters.begin() != "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";
- }
-} notNode;
-
-//----------------------------------------------------------------------------
-static const struct BoolNode : public cmGeneratorExpressionNode
-{
- BoolNode() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
- }
-} boolNode;
-
-//----------------------------------------------------------------------------
-static const struct StrEqualNode : public cmGeneratorExpressionNode
-{
- StrEqualNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return *parameters.begin() == parameters[1] ? "1" : "0";
- }
-} strEqualNode;
-
-//----------------------------------------------------------------------------
-static const struct Angle_RNode : public cmGeneratorExpressionNode
-{
- Angle_RNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return ">";
- }
-} angle_rNode;
-
-//----------------------------------------------------------------------------
-static const struct CommaNode : public cmGeneratorExpressionNode
-{
- CommaNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return ",";
- }
-} commaNode;
-
-//----------------------------------------------------------------------------
-static const struct SemicolonNode : public cmGeneratorExpressionNode
-{
- SemicolonNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return ";";
- }
-} semicolonNode;
-
-//----------------------------------------------------------------------------
-struct CompilerIdNode : public cmGeneratorExpressionNode
-{
- CompilerIdNode() {}
-
- virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
-
- std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *,
- const std::string &lang) const
- {
- const char *compilerId = context->Makefile ?
- context->Makefile->GetSafeDefinition((
- "CMAKE_" + lang + "_COMPILER_ID").c_str()) : "";
- if (parameters.size() == 0)
- {
- return compilerId ? compilerId : "";
- }
- cmsys::RegularExpression compilerIdValidator;
- compilerIdValidator.compile("^[A-Za-z0-9_]*$");
- if (!compilerIdValidator.find(parameters.begin()->c_str()))
- {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- if (!compilerId)
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0)
- {
- return "1";
- }
- return "0";
- }
-};
-
-//----------------------------------------------------------------------------
-static const struct CCompilerIdNode : public CompilerIdNode
-{
- CCompilerIdNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_ID> expression requires one or two parameters");
- return std::string();
- }
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_ID> may only be used with targets. It may not "
- "be used with add_custom_command.");
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "C");
- }
-} cCompilerIdNode;
-
-//----------------------------------------------------------------------------
-static const struct CXXCompilerIdNode : public CompilerIdNode
-{
- CXXCompilerIdNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_ID> expression requires one or two parameters");
- return std::string();
- }
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_ID> may only be used with targets. It may not "
- "be used with add_custom_command.");
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "CXX");
- }
-} cxxCompilerIdNode;
-
-//----------------------------------------------------------------------------
-struct CompilerVersionNode : public cmGeneratorExpressionNode
-{
- CompilerVersionNode() {}
-
- virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
-
- std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *,
- const std::string &lang) const
- {
- const char *compilerVersion = context->Makefile ?
- context->Makefile->GetSafeDefinition((
- "CMAKE_" + lang + "_COMPILER_VERSION").c_str()) : "";
- if (parameters.size() == 0)
- {
- return compilerVersion ? compilerVersion : "";
- }
-
- cmsys::RegularExpression compilerIdValidator;
- compilerIdValidator.compile("^[0-9\\.]*$");
- if (!compilerIdValidator.find(parameters.begin()->c_str()))
- {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- if (!compilerVersion)
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.begin()->c_str(),
- compilerVersion) ? "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
- {
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_VERSION> expression requires one or two parameters");
- return std::string();
- }
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_VERSION> may only be used with targets. It may not "
- "be used with add_custom_command.");
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "C");
- }
-} cCompilerVersionNode;
-
-//----------------------------------------------------------------------------
-static const struct CxxCompilerVersionNode : public CompilerVersionNode
-{
- CxxCompilerVersionNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_VERSION> expression requires one or two "
- "parameters");
- return std::string();
- }
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_VERSION> may only be used with targets. It may "
- "not be used with add_custom_command.");
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "CXX");
- }
-} cxxCompilerVersionNode;
-
-
-//----------------------------------------------------------------------------
-static const struct VersionGreaterNode : public cmGeneratorExpressionNode
-{
- VersionGreaterNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
- parameters.front().c_str(),
- parameters[1].c_str()) ? "1" : "0";
- }
-} versionGreaterNode;
-
-//----------------------------------------------------------------------------
-static const struct VersionLessNode : public cmGeneratorExpressionNode
-{
- VersionLessNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
- parameters.front().c_str(),
- parameters[1].c_str()) ? "1" : "0";
- }
-} versionLessNode;
-
-//----------------------------------------------------------------------------
-static const struct VersionEqualNode : public cmGeneratorExpressionNode
-{
- VersionEqualNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.front().c_str(),
- parameters[1].c_str()) ? "1" : "0";
- }
-} versionEqualNode;
-
-//----------------------------------------------------------------------------
-static const struct LinkOnlyNode : public cmGeneratorExpressionNode
-{
- LinkOnlyNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if(!dagChecker->GetTransitivePropertiesOnly())
- {
- return parameters.front();
- }
- return "";
- }
-} linkOnlyNode;
-
-//----------------------------------------------------------------------------
-static const struct ConfigurationNode : public cmGeneratorExpressionNode
-{
- ConfigurationNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- context->HadContextSensitiveCondition = true;
- return context->Config ? context->Config : "";
- }
-} configurationNode;
-
-//----------------------------------------------------------------------------
-static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
-{
- ConfigurationTestNode() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- cmsys::RegularExpression configValidator;
- configValidator.compile("^[A-Za-z0-9_]*$");
- if (!configValidator.find(parameters.begin()->c_str()))
- {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- context->HadContextSensitiveCondition = true;
- if (!context->Config)
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- if (cmsysString_strcasecmp(parameters.begin()->c_str(),
- context->Config) == 0)
- {
- return "1";
- }
-
- if (context->CurrentTarget
- && context->CurrentTarget->IsImported())
- {
- const char* loc = 0;
- const char* imp = 0;
- std::string suffix;
- if (context->CurrentTarget->GetMappedConfig(context->Config,
- &loc,
- &imp,
- suffix))
- {
- // This imported target has an appropriate location
- // 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);
- if(const char* mapValue =
- context->CurrentTarget->GetProperty(mapProp.c_str()))
- {
- cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
- mappedConfigs);
- return std::find(mappedConfigs.begin(), mappedConfigs.end(),
- cmSystemTools::UpperCase(parameters.front()))
- != mappedConfigs.end() ? "1" : "0";
- }
- }
- }
- return "0";
- }
-} configurationTestNode;
-
-static const struct JoinNode : public cmGeneratorExpressionNode
-{
- JoinNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- std::string result;
-
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(parameters.front(), list);
- std::string sep;
- for(std::vector<std::string>::const_iterator li = list.begin();
- li != list.end(); ++li)
- {
- result += sep + *li;
- sep = parameters[1];
- }
- return result;
- }
-} joinNode;
-
-#define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
- , #PROPERTY
-
-//----------------------------------------------------------------------------
-static const char* targetPropertyTransitiveWhitelist[] = {
- 0
- CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
-};
-
-std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
- cmTarget *target,
- cmTarget *headTarget,
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker,
- const std::string &interfacePropertyName)
-{
- cmGeneratorExpression ge(context->Backtrace);
-
- std::string sep;
- std::string depString;
- for (std::vector<std::string>::const_iterator
- it = libraries.begin();
- it != libraries.end(); ++it)
- {
- if (*it == target->GetName())
- {
- // 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.
- continue;
- }
- if (context->Makefile->FindTargetToUse(it->c_str()))
- {
- depString +=
- sep + "$<TARGET_PROPERTY:" + *it + "," + interfacePropertyName + ">";
- sep = ";";
- }
- }
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString);
- std::string linkedTargetsContent = cge->Evaluate(context->Makefile,
- context->Config,
- context->Quiet,
- headTarget,
- target,
- dagChecker);
- if (cge->GetHadContextSensitiveCondition())
- {
- context->HadContextSensitiveCondition = true;
- }
- return linkedTargetsContent;
-}
-
-//----------------------------------------------------------------------------
-struct TransitiveWhitelistCompare
-{
- explicit TransitiveWhitelistCompare(const std::string &needle)
- : Needle(needle) {}
- bool operator() (const char *item)
- { return strcmp(item, this->Needle.c_str()) == 0; }
-private:
- std::string Needle;
-};
-
-//----------------------------------------------------------------------------
-static const struct TargetPropertyNode : public cmGeneratorExpressionNode
-{
- TargetPropertyNode() {}
-
- // This node handles errors on parameter count itself.
- virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagCheckerParent
- ) const
- {
- if (parameters.size() != 1 && parameters.size() != 2)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression requires one or two parameters");
- return std::string();
- }
- cmsys::RegularExpression propertyNameValidator;
- propertyNameValidator.compile("^[A-Za-z0-9_]+$");
-
- cmTarget* target = context->HeadTarget;
- std::string propertyName = *parameters.begin();
-
- if (!target && parameters.size() == 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:prop> may only be used with targets. It may not "
- "be used with add_custom_command. Specify the target to read a "
- "property from using the $<TARGET_PROPERTY:tgt,prop> signature "
- "instead.");
- return std::string();
- }
-
- 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();
- }
-
- std::string targetName = parameters.front();
- 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.");
- return std::string();
- }
- if(propertyName == "ALIASED_TARGET")
- {
- if(context->Makefile->IsAlias(targetName.c_str()))
- {
- if(cmTarget* tgt =
- context->Makefile->FindTargetToUse(targetName.c_str()))
- {
- return tgt->GetName();
- }
- }
- return "";
- }
- target = context->Makefile->FindTargetToUse(
- targetName.c_str());
-
- if (!target)
- {
- cmOStringStream e;
- e << "Target \""
- << targetName
- << "\" not found.";
- reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
- }
- context->AllTargets.insert(target);
- }
-
- if (target == context->HeadTarget)
- {
- // 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);
- }
-
- if (propertyName.empty())
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression requires a non-empty property "
- "name.");
- return std::string();
- }
-
- if (!propertyNameValidator.find(propertyName.c_str()))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Property name not supported.");
- return std::string();
- }
-
- assert(target);
-
- if (propertyName == "LINKER_LANGUAGE")
- {
- if (target->LinkLanguagePropagatesToDependents() &&
- dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
- {
- reportError(context, content->GetOriginalExpression(),
- "LINKER_LANGUAGE target property can not be used while evaluating "
- "link libraries for a static library");
- return std::string();
- }
- const char *lang = target->GetLinkerLanguage(context->Config);
- return lang ? lang : "";
- }
-
- cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
- target->GetName(),
- propertyName,
- content,
- dagCheckerParent);
-
- 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 < (sizeof(targetPropertyTransitiveWhitelist) /
- sizeof(*targetPropertyTransitiveWhitelist));
- ++i)
- {
- if (targetPropertyTransitiveWhitelist[i] == propertyName)
- {
- // No error. We're not going to find anything new here.
- return std::string();
- }
- }
- case cmGeneratorExpressionDAGChecker::DAG:
- break;
- }
- const char *prop = target->GetProperty(propertyName.c_str());
-
- if (dagCheckerParent)
- {
- if (dagCheckerParent->EvaluatingLinkLibraries())
- {
- 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);
- }
- }
-
- std::string linkedTargetsContent;
-
- std::string interfacePropertyName;
-
- if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
- || propertyName == "INCLUDE_DIRECTORIES")
- {
- interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
- }
- else if (propertyName == "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")
- {
- interfacePropertyName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
- }
- else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS"
- || propertyName == "COMPILE_DEFINITIONS"
- || strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0)
- {
- interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
- }
- else if (propertyName == "INTERFACE_COMPILE_OPTIONS"
- || propertyName == "COMPILE_OPTIONS")
- {
- interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
- }
-
- cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
-
- const char **transBegin = targetPropertyTransitiveWhitelist + 1;
- const char **transEnd = targetPropertyTransitiveWhitelist
- + (sizeof(targetPropertyTransitiveWhitelist) /
- sizeof(*targetPropertyTransitiveWhitelist));
- if (std::find_if(transBegin, transEnd,
- TransitiveWhitelistCompare(propertyName)) != transEnd)
- {
-
- std::vector<std::string> libs;
- target->GetTransitivePropertyLinkLibraries(context->Config,
- headTarget, libs);
- if (!libs.empty())
- {
- linkedTargetsContent =
- getLinkedTargetsContent(libs, target,
- headTarget,
- context, &dagChecker,
- interfacePropertyName);
- }
- }
- else if (std::find_if(transBegin, transEnd,
- TransitiveWhitelistCompare(interfacePropertyName)) != transEnd)
- {
- const cmTarget::LinkImplementation *impl = target->GetLinkImplementation(
- context->Config,
- headTarget);
- if(impl)
- {
- linkedTargetsContent =
- getLinkedTargetsContent(impl->Libraries, target,
- headTarget,
- context, &dagChecker,
- interfacePropertyName);
- }
- }
-
- linkedTargetsContent =
- cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
-
- if (!prop)
- {
- if (target->IsImported())
- {
- return linkedTargetsContent;
- }
- if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- return target->GetLinkInterfaceDependentBoolProperty(
- propertyName,
- context->Config) ? "1" : "0";
- }
- if (target->IsLinkInterfaceDependentStringProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- const char *propContent =
- target->GetLinkInterfaceDependentStringProperty(
- propertyName,
- context->Config);
- return propContent ? propContent : "";
- }
-
- return linkedTargetsContent;
- }
-
- for (size_t i = 1;
- i < (sizeof(targetPropertyTransitiveWhitelist) /
- sizeof(*targetPropertyTransitiveWhitelist));
- ++i)
- {
- if (targetPropertyTransitiveWhitelist[i] == interfacePropertyName)
- {
- cmGeneratorExpression ge(context->Backtrace);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
- std::string result = cge->Evaluate(context->Makefile,
- context->Config,
- context->Quiet,
- headTarget,
- target,
- &dagChecker);
-
- if (cge->GetHadContextSensitiveCondition())
- {
- context->HadContextSensitiveCondition = true;
- }
- if (!linkedTargetsContent.empty())
- {
- result += (result.empty() ? "" : ";") + linkedTargetsContent;
- }
- return result;
- }
- }
- return prop;
- }
-} targetPropertyNode;
-
-//----------------------------------------------------------------------------
-static const struct TargetNameNode : public cmGeneratorExpressionNode
-{
- TargetNameNode() {}
-
- virtual bool GeneratesContent() const { return true; }
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
- virtual bool RequiresLiteralInput() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return parameters.front();
- }
-
- virtual int NumExpectedParameters() const { return 1; }
-
-} targetNameNode;
-
-//----------------------------------------------------------------------------
-static const char* targetPolicyWhitelist[] = {
- 0
-#define TARGET_POLICY_STRING(POLICY) \
- , #POLICY
-
- CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
-
-#undef TARGET_POLICY_STRING
-};
-
-cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
-{
-#define RETURN_POLICY(POLICY) \
- if (strcmp(policy, #POLICY) == 0) \
- { \
- return tgt->GetPolicyStatus ## POLICY (); \
- } \
-
- CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
-
-#undef RETURN_POLICY
-
- assert("!Unreachable code. Not a valid policy");
- return cmPolicies::WARN;
-}
-
-cmPolicies::PolicyID policyForString(const char *policy_id)
-{
-#define RETURN_POLICY_ID(POLICY_ID) \
- if (strcmp(policy_id, #POLICY_ID) == 0) \
- { \
- return cmPolicies:: POLICY_ID; \
- } \
-
- CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
-
-#undef RETURN_POLICY_ID
-
- assert("!Unreachable code. Not a valid policy");
- return cmPolicies::CMP0002;
-}
-
-//----------------------------------------------------------------------------
-static const struct TargetPolicyNode : public cmGeneratorExpressionNode
-{
- TargetPolicyNode() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context ,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_POLICY:prop> may only be used with targets. It may not "
- "be used with add_custom_command.");
- return std::string();
- }
-
- context->HadContextSensitiveCondition = true;
-
- for (size_t i = 1;
- i < (sizeof(targetPolicyWhitelist) /
- sizeof(*targetPolicyWhitelist));
- ++i)
- {
- const char *policy = targetPolicyWhitelist[i];
- if (parameters.front() == policy)
- {
- cmMakefile *mf = context->HeadTarget->GetMakefile();
- switch(statusForTarget(context->HeadTarget, policy))
- {
- case cmPolicies::WARN:
- mf->IssueMessage(cmake::AUTHOR_WARNING,
- mf->GetPolicies()->
- GetPolicyWarning(policyForString(policy)));
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::OLD:
- return "0";
- case cmPolicies::NEW:
- return "1";
- }
- }
- }
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_POLICY:prop> may only be used with a limited number of "
- "policies. Currently it may be used with the following policies:\n"
-
-#define STRINGIFY_HELPER(X) #X
-#define STRINGIFY(X) STRINGIFY_HELPER(X)
-
-#define TARGET_POLICY_LIST_ITEM(POLICY) \
- " * " STRINGIFY(POLICY) "\n"
-
- CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
-
-#undef TARGET_POLICY_LIST_ITEM
- );
- return std::string();
- }
-
-} targetPolicyNode;
-
-//----------------------------------------------------------------------------
-static const struct InstallPrefixNode : public cmGeneratorExpressionNode
-{
- InstallPrefixNode() {}
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorExpressionNode.h"
- virtual bool GeneratesContent() const { return true; }
- virtual int NumExpectedParameters() const { return 0; }
+#include <algorithm>
+#include <sstream>
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- reportError(context, content->GetOriginalExpression(),
- "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
- "should never be evaluated.");
- return std::string();
- }
-
-} installPrefixNode;
-
-//----------------------------------------------------------------------------
-template<bool linker, bool soname>
-struct TargetFilesystemArtifactResultCreator
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content);
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<false, true>
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content)
- {
- // The target soname file (.so.1).
- if(target->IsDLLPlatform())
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_SONAME_FILE is not allowed "
- "for DLL target platforms.");
- return std::string();
- }
- if(target->GetType() != cmTarget::SHARED_LIBRARY)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_SONAME_FILE is allowed only for "
- "SHARED libraries.");
- return std::string();
- }
- std::string result = target->GetDirectory(context->Config);
- result += "/";
- result += target->GetSOName(context->Config);
- return result;
- }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<true, false>
-{
- static std::string Create(cmTarget* 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 is allowed only for libraries and "
- "executables with ENABLE_EXPORTS.");
- return std::string();
- }
- return target->GetFullPath(context->Config,
- target->HasImportLibrary());
- }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<false, false>
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *)
- {
- return target->GetFullPath(context->Config, false, true);
- }
-};
-
-
-//----------------------------------------------------------------------------
-template<bool dirQual, bool nameQual>
-struct TargetFilesystemArtifactResultGetter
-{
- static std::string Get(const std::string &result);
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultGetter<false, true>
-{
- static std::string Get(const std::string &result)
- { return cmSystemTools::GetFilenameName(result); }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultGetter<true, false>
-{
- static std::string Get(const std::string &result)
- { return cmSystemTools::GetFilenamePath(result); }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultGetter<false, false>
-{
- static std::string Get(const std::string &result)
- { return result; }
-};
-
-//----------------------------------------------------------------------------
-template<bool linker, bool soname, bool dirQual, bool nameQual>
-struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
-{
- TargetFilesystemArtifact() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- // Lookup the referenced target.
- std::string name = *parameters.begin();
-
- if (!cmGeneratorExpression::IsValidTargetName(name))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- cmTarget* target = context->Makefile->FindTargetToUse(name.c_str());
- if(!target)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "No target \"" + name + "\"");
- return std::string();
- }
- if(target->GetType() >= cmTarget::OBJECT_LIBRARY &&
- target->GetType() != cmTarget::UNKNOWN_LIBRARY)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Target \"" + name + "\" is not an executable or library.");
- return std::string();
- }
- if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str()))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Expressions which require the linker language may not "
- "be used while evaluating link libraries");
- return std::string();
- }
- context->DependTargets.insert(target);
- context->AllTargets.insert(target);
-
- std::string result =
- TargetFilesystemArtifactResultCreator<linker, soname>::Create(
- target,
- context,
- content);
- if (context->HadError)
- {
- return std::string();
- }
- return
- TargetFilesystemArtifactResultGetter<dirQual, nameQual>::Get(result);
- }
-};
-
-//----------------------------------------------------------------------------
-static const
-TargetFilesystemArtifact<false, false, false, false> targetFileNode;
-static const
-TargetFilesystemArtifact<true, false, false, false> targetLinkerFileNode;
-static const
-TargetFilesystemArtifact<false, true, false, false> targetSoNameFileNode;
-static const
-TargetFilesystemArtifact<false, false, false, true> targetFileNameNode;
-static const
-TargetFilesystemArtifact<true, false, false, true> targetLinkerFileNameNode;
-static const
-TargetFilesystemArtifact<false, true, false, true> targetSoNameFileNameNode;
-static const
-TargetFilesystemArtifact<false, false, true, false> targetFileDirNode;
-static const
-TargetFilesystemArtifact<true, false, true, false> targetLinkerFileDirNode;
-static const
-TargetFilesystemArtifact<false, true, true, false> targetSoNameFileDirNode;
-
-//----------------------------------------------------------------------------
-static const
-cmGeneratorExpressionNode* GetNode(const std::string &identifier)
-{
- if (identifier == "0")
- return &zeroNode;
- else if (identifier == "1")
- return &oneNode;
- else if (identifier == "AND")
- return &andNode;
- else if (identifier == "OR")
- return &orNode;
- else if (identifier == "NOT")
- return &notNode;
- else if (identifier == "C_COMPILER_ID")
- return &cCompilerIdNode;
- else if (identifier == "CXX_COMPILER_ID")
- return &cxxCompilerIdNode;
- else if (identifier == "VERSION_GREATER")
- return &versionGreaterNode;
- else if (identifier == "VERSION_LESS")
- return &versionLessNode;
- else if (identifier == "VERSION_EQUAL")
- return &versionEqualNode;
- else if (identifier == "C_COMPILER_VERSION")
- return &cCompilerVersionNode;
- else if (identifier == "CXX_COMPILER_VERSION")
- return &cxxCompilerVersionNode;
- else if (identifier == "CONFIGURATION")
- return &configurationNode;
- else if (identifier == "CONFIG")
- return &configurationTestNode;
- else if (identifier == "TARGET_FILE")
- return &targetFileNode;
- else if (identifier == "TARGET_LINKER_FILE")
- return &targetLinkerFileNode;
- else if (identifier == "TARGET_SONAME_FILE")
- return &targetSoNameFileNode;
- else if (identifier == "TARGET_FILE_NAME")
- return &targetFileNameNode;
- else if (identifier == "TARGET_LINKER_FILE_NAME")
- return &targetLinkerFileNameNode;
- else if (identifier == "TARGET_SONAME_FILE_NAME")
- return &targetSoNameFileNameNode;
- else if (identifier == "TARGET_FILE_DIR")
- return &targetFileDirNode;
- else if (identifier == "TARGET_LINKER_FILE_DIR")
- return &targetLinkerFileDirNode;
- else if (identifier == "TARGET_SONAME_FILE_DIR")
- return &targetSoNameFileDirNode;
- else if (identifier == "STREQUAL")
- return &strEqualNode;
- else if (identifier == "BOOL")
- return &boolNode;
- else if (identifier == "ANGLE-R")
- return &angle_rNode;
- else if (identifier == "COMMA")
- return &commaNode;
- else if (identifier == "SEMICOLON")
- return &semicolonNode;
- else if (identifier == "TARGET_PROPERTY")
- return &targetPropertyNode;
- else if (identifier == "TARGET_NAME")
- return &targetNameNode;
- else if (identifier == "TARGET_POLICY")
- return &targetPolicyNode;
- else if (identifier == "BUILD_INTERFACE")
- return &buildInterfaceNode;
- else if (identifier == "INSTALL_INTERFACE")
- return &installInterfaceNode;
- else if (identifier == "INSTALL_PREFIX")
- return &installPrefixNode;
- else if (identifier == "JOIN")
- return &joinNode;
- else if (identifier == "LINK_ONLY")
- return &linkOnlyNode;
- return 0;
-
-}
-
-//----------------------------------------------------------------------------
GeneratorExpressionContent::GeneratorExpressionContent(
- const char *startContent,
- unsigned int length)
- : StartContent(startContent), ContentLength(length)
+ const char* startContent, size_t length)
+ : StartContent(startContent)
+ , ContentLength(length)
{
-
}
-//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::GetOriginalExpression() const
{
return std::string(this->StartContent, this->ContentLength);
}
-//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::ProcessArbitraryContent(
- const cmGeneratorExpressionNode *node,
- const std::string &identifier,
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker,
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ const cmGeneratorExpressionNode* node, const std::string& identifier,
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pit) const
{
std::string result;
- const
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- 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)
- {
- if (node->RequiresLiteralInput())
- {
- if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
- {
- reportError(context, this->GetOriginalExpression(),
- "$<" + identifier + "> expression requires literal input.");
+ const std::vector<
+ std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator 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) {
+ if (node->RequiresLiteralInput()) {
+ if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) {
+ reportError(context, this->GetOriginalExpression(), "$<" +
+ identifier + "> expression requires literal input.");
return std::string();
- }
}
+ }
result += (*it)->Evaluate(context, dagChecker);
- if (context->HadError)
- {
+ if (context->HadError) {
return std::string();
- }
}
- if ((pit + 1) != pend)
- {
- result += ",";
- }
}
- if (node->RequiresLiteralInput())
- {
+ if ((pit + 1) != pend) {
+ result += ",";
+ }
+ }
+ if (node->RequiresLiteralInput()) {
std::vector<std::string> parameters;
parameters.push_back(result);
return node->Evaluate(parameters, context, this, dagChecker);
- }
+ }
return result;
}
-//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::Evaluate(
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker) const
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
{
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);
- if (context->HadError)
- {
- return std::string();
+ 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);
+ if (context->HadError) {
+ return std::string();
}
}
}
- const cmGeneratorExpressionNode *node = GetNode(identifier);
+ const cmGeneratorExpressionNode* node =
+ cmGeneratorExpressionNode::GetNode(identifier);
- if (!node)
- {
+ if (!node) {
reportError(context, this->GetOriginalExpression(),
- "Expression did not evaluate to a known generator expression");
+ "Expression did not evaluate to a known generator expression");
return std::string();
- }
+ }
- if (!node->GeneratesContent())
- {
- if (node->NumExpectedParameters() == 1
- && node->AcceptsArbitraryContentParameter())
- {
- if (this->ParamChildren.empty())
- {
+ if (!node->GeneratesContent()) {
+ if (node->NumExpectedParameters() == 1 &&
+ node->AcceptsArbitraryContentParameter()) {
+ if (this->ParamChildren.empty()) {
reportError(context, this->GetOriginalExpression(),
- "$<" + identifier + "> expression requires a parameter.");
- }
+ "$<" + identifier + "> expression requires a parameter.");
}
- else
- {
+ } else {
std::vector<std::string> parameters;
this->EvaluateParameters(node, identifier, context, dagChecker,
parameters);
- }
- return std::string();
- }
-
- if (node->NumExpectedParameters() == 1
- && node->AcceptsArbitraryContentParameter())
- {
- return this->ProcessArbitraryContent(node, identifier, context,
- dagChecker,
- this->ParamChildren.begin());
}
+ return std::string();
+ }
std::vector<std::string> parameters;
this->EvaluateParameters(node, identifier, context, dagChecker, parameters);
- if (context->HadError)
- {
+ if (context->HadError) {
return std::string();
- }
+ }
return node->Evaluate(parameters, context, this, dagChecker);
}
-//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::EvaluateParameters(
- const cmGeneratorExpressionNode *node,
- const std::string &identifier,
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker,
- std::vector<std::string> &parameters) const
+ const cmGeneratorExpressionNode* node, const std::string& identifier,
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<std::string>& parameters) const
{
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();
- const bool acceptsArbitraryContent
- = node->AcceptsArbitraryContentParameter();
- for ( ; pit != pend; ++pit)
- {
- 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);
- if (context->HadError)
- {
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit = this->ParamChildren.begin();
+ const std::vector<
+ std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator 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);
return std::string();
- }
}
- parameters.push_back(parameter);
- if (acceptsArbitraryContent
- && parameters.size() == (unsigned int)numExpected - 1)
- {
- assert(pit != pend);
- std::string lastParam = this->ProcessArbitraryContent(node, identifier,
- context,
- dagChecker,
- pit + 1);
- parameters.push_back(lastParam);
- 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);
+ if (context->HadError) {
+ return std::string();
+ }
}
+ parameters.push_back(parameter);
}
}
- if ((numExpected > cmGeneratorExpressionNode::DynamicParameters
- && (unsigned int)numExpected != parameters.size()))
- {
- if (numExpected == 0)
- {
+ if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
+ (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 + "> expression requires "
- "exactly one parameter.");
- }
- else
- {
- cmOStringStream e;
- e << "$<" + identifier + "> expression requires "
- << numExpected
- << " comma separated parameters, but got "
- << parameters.size() << " instead.";
+ } else if (numExpected == 1) {
+ reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ "> expression requires "
+ "exactly one parameter.");
+ } else {
+ std::ostringstream e;
+ e << "$<" + identifier + "> expression requires " << numExpected
+ << " comma separated parameters, but got " << parameters.size()
+ << " instead.";
reportError(context, this->GetOriginalExpression(), e.str());
- }
- return std::string();
}
+ return std::string();
+ }
- if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters
- && parameters.empty())
- {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier
- + "> expression requires at least one parameter.");
- }
+ if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
+ parameters.empty()) {
+ reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ "> expression requires at least one parameter.");
+ }
+ if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
+ parameters.size() > 1) {
+ reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ "> expression requires one or zero parameters.");
+ }
return std::string();
}
-//----------------------------------------------------------------------------
-static void deleteAll(const std::vector<cmGeneratorExpressionEvaluator*> &c)
-{
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
- = c.begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
- = c.end();
- for ( ; it != end; ++it)
- {
- delete *it;
- }
-}
-
-//----------------------------------------------------------------------------
GeneratorExpressionContent::~GeneratorExpressionContent()
{
- deleteAll(this->IdentifierChildren);
-
- typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
- std::vector<EvaluatorVector>::const_iterator pit =
- this->ParamChildren.begin();
- const std::vector<EvaluatorVector>::const_iterator pend =
- this->ParamChildren.end();
- for ( ; pit != pend; ++pit)
- {
- deleteAll(*pit);
- }
+ cmDeleteAll(this->IdentifierChildren);
+ std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(),
+ cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*> >);
}
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 218abf160..a0a826ac6 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -1,45 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorExpressionEvaluator_h
#define cmGeneratorExpressionEvaluator_h
-#include <vector>
-#include <string>
-
-#include "cmListFileCache.h"
-
-class cmTarget;
+#include "cmConfigure.h"
-//----------------------------------------------------------------------------
-struct cmGeneratorExpressionContext
-{
- cmListFileBacktrace Backtrace;
- std::set<cmTarget*> DependTargets;
- std::set<cmTarget*> AllTargets;
- std::set<cmStdString> SeenTargetProperties;
- cmMakefile *Makefile;
- const char *Config;
- cmTarget *HeadTarget; // The target whose property is being evaluated.
- cmTarget *CurrentTarget; // The dependent of HeadTarget which appears
- // directly or indirectly in the property.
- bool Quiet;
- bool HadError;
- bool HadContextSensitiveCondition;
-};
+#include <stddef.h>
+#include <string>
+#include <vector>
+struct cmGeneratorExpressionContext;
struct cmGeneratorExpressionDAGChecker;
struct cmGeneratorExpressionNode;
-//----------------------------------------------------------------------------
struct cmGeneratorExpressionEvaluator
{
cmGeneratorExpressionEvaluator() {}
@@ -53,95 +26,88 @@ struct cmGeneratorExpressionEvaluator
virtual Type GetType() const = 0;
- virtual std::string Evaluate(cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *) const = 0;
+ virtual std::string Evaluate(cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker*) const = 0;
private:
- cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator &);
- void operator=(const cmGeneratorExpressionEvaluator &);
+ CM_DISABLE_COPY(cmGeneratorExpressionEvaluator)
};
struct TextContent : public cmGeneratorExpressionEvaluator
{
- TextContent(const char *start, unsigned int length)
- : Content(start), Length(length)
+ TextContent(const char* start, size_t length)
+ : Content(start)
+ , Length(length)
{
-
}
- std::string Evaluate(cmGeneratorExpressionContext *,
- cmGeneratorExpressionDAGChecker *) const
+ std::string Evaluate(cmGeneratorExpressionContext*,
+ cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE
{
return std::string(this->Content, this->Length);
}
- Type GetType() const
+ Type GetType() const CM_OVERRIDE
{
return cmGeneratorExpressionEvaluator::Text;
}
- void Extend(unsigned int length)
- {
- this->Length += length;
- }
+ void Extend(size_t length) { this->Length += length; }
- unsigned int GetLength()
- {
- return this->Length;
- }
+ size_t GetLength() { return this->Length; }
private:
- const char *Content;
- unsigned int Length;
+ const char* Content;
+ size_t Length;
};
-//----------------------------------------------------------------------------
struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
- GeneratorExpressionContent(const char *startContent, unsigned int length);
- void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
+ GeneratorExpressionContent(const char* startContent, size_t length);
+ void SetIdentifier(
+ std::vector<cmGeneratorExpressionEvaluator*> const& identifier)
{
this->IdentifierChildren = identifier;
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters)
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> > const&
+ parameters)
{
this->ParamChildren = parameters;
}
- Type GetType() const
+ Type GetType() const CM_OVERRIDE
{
return cmGeneratorExpressionEvaluator::Generator;
}
- std::string Evaluate(cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *) const;
+ std::string Evaluate(cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE;
std::string GetOriginalExpression() const;
- ~GeneratorExpressionContent();
+ ~GeneratorExpressionContent() CM_OVERRIDE;
private:
- std::string EvaluateParameters(const cmGeneratorExpressionNode *node,
- const std::string &identifier,
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker,
- std::vector<std::string> &parameters) const;
+ std::string EvaluateParameters(const cmGeneratorExpressionNode* node,
+ const std::string& identifier,
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<std::string>& parameters) const;
std::string ProcessArbitraryContent(
- const cmGeneratorExpressionNode *node,
- const std::string &identifier,
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker,
+ const cmGeneratorExpressionNode* node, const std::string& identifier,
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker,
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- pit) const;
+ pit) const;
private:
std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;
- const char *StartContent;
- unsigned int ContentLength;
+ const char* StartContent;
+ size_t ContentLength;
};
#endif
diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx
index cd71ec033..931fd4d62 100644
--- a/Source/cmGeneratorExpressionLexer.cxx
+++ b/Source/cmGeneratorExpressionLexer.cxx
@@ -1,82 +1,63 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionLexer.h"
-
-//----------------------------------------------------------------------------
cmGeneratorExpressionLexer::cmGeneratorExpressionLexer()
- : SawBeginExpression(false), SawGeneratorExpression(false)
+ : SawBeginExpression(false)
+ , SawGeneratorExpression(false)
{
-
}
-//----------------------------------------------------------------------------
-static void InsertText(const char *upto, const char *c,
- std::vector<cmGeneratorExpressionToken> &result)
+static void InsertText(const char* upto, const char* c,
+ std::vector<cmGeneratorExpressionToken>& result)
{
- if (upto != c)
- {
+ if (upto != c) {
result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::Text, upto, c - upto));
- }
+ cmGeneratorExpressionToken::Text, upto, c - upto));
+ }
}
-//----------------------------------------------------------------------------
-std::vector<cmGeneratorExpressionToken>
-cmGeneratorExpressionLexer::Tokenize(const char *input)
+std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize(
+ const std::string& input)
{
std::vector<cmGeneratorExpressionToken> result;
- if (!input)
- return result;
- const char *c = input;
- const char *upto = c;
+ const char* c = input.c_str();
+ const char* upto = c;
- for ( ; *c; ++c)
- {
- if(c[0] == '$' && c[1] == '<')
- {
- InsertText(upto, c, result);
- upto = c;
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::BeginExpression, upto, 2));
- upto = c + 2;
- ++c;
- SawBeginExpression = true;
- }
- else if(c[0] == '>')
- {
- InsertText(upto, c, result);
- upto = c;
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::EndExpression, upto, 1));
- upto = c + 1;
- SawGeneratorExpression = SawBeginExpression;
- }
- else if(c[0] == ':')
- {
- InsertText(upto, c, result);
- upto = c;
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::ColonSeparator, upto, 1));
- upto = c + 1;
- }
- else if(c[0] == ',')
- {
- InsertText(upto, c, result);
- upto = c;
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::CommaSeparator, upto, 1));
- upto = c + 1;
+ for (; *c; ++c) {
+ switch (*c) {
+ case '$':
+ if (c[1] == '<') {
+ InsertText(upto, c, result);
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::BeginExpression, c, 2));
+ upto = c + 2;
+ ++c;
+ SawBeginExpression = true;
+ }
+ break;
+ case '>':
+ InsertText(upto, c, result);
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::EndExpression, c, 1));
+ upto = c + 1;
+ SawGeneratorExpression = SawBeginExpression;
+ break;
+ case ':':
+ InsertText(upto, c, result);
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::ColonSeparator, c, 1));
+ upto = c + 1;
+ break;
+ case ',':
+ InsertText(upto, c, result);
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::CommaSeparator, c, 1));
+ upto = c + 1;
+ break;
+ default:
+ break;
}
}
InsertText(upto, c, result);
diff --git a/Source/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h
index 5f16712fb..e53f0b547 100644
--- a/Source/cmGeneratorExpressionLexer.h
+++ b/Source/cmGeneratorExpressionLexer.h
@@ -1,29 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorExpressionLexer_h
#define cmGeneratorExpressionLexer_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <stddef.h>
+#include <string>
#include <vector>
-//----------------------------------------------------------------------------
struct cmGeneratorExpressionToken
{
- cmGeneratorExpressionToken(unsigned type, const char *c, unsigned l)
- : TokenType(type), Content(c), Length(l)
+ cmGeneratorExpressionToken(unsigned type, const char* c, size_t l)
+ : TokenType(type)
+ , Content(c)
+ , Length(l)
{
}
- enum {
+ enum
+ {
Text,
BeginExpression,
EndExpression,
@@ -31,8 +26,8 @@ struct cmGeneratorExpressionToken
CommaSeparator
};
unsigned TokenType;
- const char *Content;
- unsigned Length;
+ const char* Content;
+ size_t Length;
};
/** \class cmGeneratorExpressionLexer
@@ -43,7 +38,7 @@ class cmGeneratorExpressionLexer
public:
cmGeneratorExpressionLexer();
- std::vector<cmGeneratorExpressionToken> Tokenize(const char *input);
+ std::vector<cmGeneratorExpressionToken> Tokenize(const std::string& input);
bool GetSawGeneratorExpression() const
{
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
new file mode 100644
index 000000000..a57d2a0d8
--- /dev/null
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -0,0 +1,1897 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGeneratorExpressionNode.h"
+
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpressionEvaluator.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.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)
+{
+ cmGeneratorExpression ge(context->Backtrace);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+ cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
+ std::string result =
+ cge->Evaluate(lg, context->Config, context->Quiet, headTarget,
+ currentTarget, dagChecker, context->Language);
+ if (cge->GetHadContextSensitiveCondition()) {
+ context->HadContextSensitiveCondition = true;
+ }
+ if (cge->GetHadHeadSensitiveCondition()) {
+ context->HadHeadSensitiveCondition = true;
+ }
+ return result;
+}
+
+static const struct ZeroNode : public cmGeneratorExpressionNode
+{
+ ZeroNode() {}
+
+ bool GeneratesContent() const CM_OVERRIDE { return false; }
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& /*parameters*/,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ return std::string();
+ }
+} zeroNode;
+
+static const struct OneNode : public cmGeneratorExpressionNode
+{
+ OneNode() {}
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ return parameters.front();
+ }
+} oneNode;
+
+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
+{
+ NotNode() {}
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ if (*parameters.begin() != "0" && *parameters.begin() != "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";
+ }
+} notNode;
+
+static const struct BoolNode : public cmGeneratorExpressionNode
+{
+ BoolNode() {}
+
+ 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
+ {
+ return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
+ }
+} boolNode;
+
+static const struct IfNode : public cmGeneratorExpressionNode
+{
+ IfNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return 3; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE
+ {
+ if (parameters[0] != "1" && parameters[0] != "0") {
+ reportError(context, content->GetOriginalExpression(),
+ "First parameter to $<IF> must resolve to exactly one '0' "
+ "or '1' value.");
+ return std::string();
+ }
+ return parameters[0] == "1" ? parameters[1] : parameters[2];
+ }
+} ifNode;
+
+static const struct StrEqualNode : public cmGeneratorExpressionNode
+{
+ StrEqualNode() {}
+
+ 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 *parameters.begin() == parameters[1] ? "1" : "0";
+ }
+} strEqualNode;
+
+static const struct EqualNode : public cmGeneratorExpressionNode
+{
+ EqualNode() {}
+
+ 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
+ {
+ char* pEnd;
+
+ int base = 0;
+ bool flipSign = false;
+
+ const char* lhs = parameters[0].c_str();
+ if (cmHasLiteralPrefix(lhs, "0b") || cmHasLiteralPrefix(lhs, "0B")) {
+ base = 2;
+ lhs += 2;
+ }
+ if (cmHasLiteralPrefix(lhs, "-0b") || cmHasLiteralPrefix(lhs, "-0B")) {
+ base = 2;
+ lhs += 3;
+ flipSign = true;
+ }
+ if (cmHasLiteralPrefix(lhs, "+0b") || cmHasLiteralPrefix(lhs, "+0B")) {
+ base = 2;
+ lhs += 3;
+ }
+
+ long lnum = strtol(lhs, &pEnd, base);
+ if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[0] +
+ " is not a valid integer.");
+ return std::string();
+ }
+
+ if (flipSign) {
+ lnum = -lnum;
+ }
+
+ base = 0;
+ flipSign = false;
+
+ const char* rhs = parameters[1].c_str();
+ if (cmHasLiteralPrefix(rhs, "0b") || cmHasLiteralPrefix(rhs, "0B")) {
+ base = 2;
+ rhs += 2;
+ }
+ if (cmHasLiteralPrefix(rhs, "-0b") || cmHasLiteralPrefix(rhs, "-0B")) {
+ base = 2;
+ rhs += 3;
+ flipSign = true;
+ }
+ if (cmHasLiteralPrefix(rhs, "+0b") || cmHasLiteralPrefix(rhs, "+0B")) {
+ base = 2;
+ rhs += 3;
+ }
+
+ long rnum = strtol(rhs, &pEnd, base);
+ if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[1] +
+ " is not a valid integer.");
+ return std::string();
+ }
+
+ if (flipSign) {
+ rnum = -rnum;
+ }
+
+ return lnum == rnum ? "1" : "0";
+ }
+} equalNode;
+
+static const struct LowerCaseNode : public cmGeneratorExpressionNode
+{
+ LowerCaseNode() {}
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ return cmSystemTools::LowerCase(parameters.front());
+ }
+} lowerCaseNode;
+
+static const struct UpperCaseNode : public cmGeneratorExpressionNode
+{
+ UpperCaseNode() {}
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ return cmSystemTools::UpperCase(parameters.front());
+ }
+} upperCaseNode;
+
+static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
+{
+ MakeCIdentifierNode() {}
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ return cmSystemTools::MakeCidentifier(parameters.front());
+ }
+} makeCIdentifierNode;
+
+static const struct Angle_RNode : public cmGeneratorExpressionNode
+{
+ Angle_RNode() {}
+
+ 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
+ {
+ return ">";
+ }
+} angle_rNode;
+
+static const struct CommaNode : 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
+ {
+ return ",";
+ }
+} commaNode;
+
+static const struct SemicolonNode : public cmGeneratorExpressionNode
+{
+ SemicolonNode() {}
+
+ 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
+ {
+ return ";";
+ }
+} semicolonNode;
+
+struct CompilerIdNode : public cmGeneratorExpressionNode
+{
+ CompilerIdNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+
+ std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*unused*/,
+ const std::string& lang) const
+ {
+ const char* 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();
+ }
+ if (!compilerId) {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (strcmp(parameters.begin()->c_str(), compilerId) == 0) {
+ return "1";
+ }
+
+ 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;
+ }
+ case cmPolicies::OLD:
+ return "1";
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
+ }
+ }
+ return "0";
+ }
+};
+
+static const struct CCompilerIdNode : public CompilerIdNode
+{
+ CCompilerIdNode() {}
+
+ 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_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() {}
+
+ 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_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,
+ "CXX");
+ }
+} cxxCompilerIdNode;
+
+struct CompilerVersionNode : public cmGeneratorExpressionNode
+{
+ CompilerVersionNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+
+ std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*unused*/,
+ const std::string& lang) const
+ {
+ const char* compilerVersion =
+ context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
+ "_COMPILER_VERSION");
+ if (parameters.empty()) {
+ return compilerVersion ? compilerVersion : "";
+ }
+
+ static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
+ if (!compilerIdValidator.find(*parameters.begin())) {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ if (!compilerVersion) {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+ parameters.begin()->c_str(),
+ compilerVersion)
+ ? "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() {}
+
+ 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;
+
+struct PlatformIdNode : public cmGeneratorExpressionNode
+{
+ PlatformIdNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ const char* platformId =
+ context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME");
+ if (parameters.empty()) {
+ return platformId ? platformId : "";
+ }
+
+ if (!platformId) {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (strcmp(parameters.begin()->c_str(), platformId) == 0) {
+ 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
+{
+ VersionLessEqNode() {}
+
+ 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_EQUAL,
+ 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 struct LinkOnlyNode : public cmGeneratorExpressionNode
+{
+ LinkOnlyNode() {}
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+ CM_OVERRIDE
+ {
+ if (!dagChecker) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<LINK_ONLY:...> may only be used for linking");
+ return std::string();
+ }
+ if (!dagChecker->GetTransitivePropertiesOnly()) {
+ return parameters.front();
+ }
+ return std::string();
+ }
+} linkOnlyNode;
+
+static const struct ConfigurationNode : public cmGeneratorExpressionNode
+{
+ ConfigurationNode() {}
+
+ 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
+ {
+ context->HadContextSensitiveCondition = true;
+ return context->Config;
+ }
+} configurationNode;
+
+static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
+{
+ ConfigurationTestNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ if (parameters.empty()) {
+ return configurationNode.Evaluate(parameters, context, content,
+ CM_NULLPTR);
+ }
+ static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
+ if (!configValidator.find(*parameters.begin())) {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ context->HadContextSensitiveCondition = true;
+ if (context->Config.empty()) {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (cmsysString_strcasecmp(parameters.begin()->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;
+ std::string suffix;
+ if (context->CurrentTarget->Target->GetMappedConfig(
+ context->Config, &loc, &imp, suffix)) {
+ // This imported target has an appropriate location
+ // 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);
+ 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()
+ ? "1"
+ : "0";
+ }
+ }
+ }
+ return "0";
+ }
+} configurationTestNode;
+
+static const struct JoinNode : public cmGeneratorExpressionNode
+{
+ JoinNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return 2; }
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(parameters.front(), list);
+ return cmJoin(list, parameters[1]);
+ }
+} joinNode;
+
+static const struct CompileLanguageNode : public cmGeneratorExpressionNode
+{
+ CompileLanguageNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+ CM_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 "
+ "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) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_LANGUAGE:...> may not be used with Visual Studio "
+ "generators.");
+ 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";
+ }
+} languageNode;
+
+#define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
+
+static const char* targetPropertyTransitiveWhitelist[] = {
+ CM_NULLPTR CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
+};
+
+#undef TRANSITIVE_PROPERTY_NAME
+
+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;
+}
+
+static const struct TargetPropertyNode : public cmGeneratorExpressionNode
+{
+ TargetPropertyNode() {}
+
+ // This node handles errors on parameter count itself.
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrMoreParameters; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+ CM_OVERRIDE
+ {
+ 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 (!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 (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();
+ }
+
+ std::string targetName = parameters.front();
+ 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.");
+ return std::string();
+ }
+ if (propertyName == "ALIASED_TARGET") {
+ if (context->LG->GetMakefile()->IsAlias(targetName)) {
+ if (cmGeneratorTarget* tgt =
+ context->LG->FindGeneratorTargetToUse(targetName)) {
+ return tgt->GetName();
+ }
+ }
+ return "";
+ }
+ target = context->LG->FindGeneratorTargetToUse(targetName);
+
+ if (!target) {
+ std::ostringstream e;
+ e << "Target \"" << targetName << "\" not found.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ context->AllTargets.insert(target);
+ }
+
+ if (target == context->HeadTarget) {
+ // 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);
+ }
+ if (propertyName == "SOURCES") {
+ context->SourceSensitiveTargets.insert(target);
+ }
+
+ if (propertyName.empty()) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression requires a non-empty property "
+ "name.");
+ return std::string();
+ }
+
+ if (!propertyNameValidator.find(propertyName)) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Property name not supported.");
+ return std::string();
+ }
+
+ assert(target);
+
+ if (propertyName == "LINKER_LANGUAGE") {
+ if (target->LinkLanguagePropagatesToDependents() && dagCheckerParent &&
+ (dagCheckerParent->EvaluatingLinkLibraries() ||
+ dagCheckerParent->EvaluatingSources())) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "LINKER_LANGUAGE target property can not be used while evaluating "
+ "link libraries for a static library");
+ return std::string();
+ }
+ return target->GetLinkerLanguage(context->Config);
+ }
+
+ cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
+ target->GetName(), propertyName,
+ content, dagCheckerParent);
+
+ 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;
+ }
+
+ const char* prop = target->GetProperty(propertyName);
+
+ 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)
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression in link libraries "
+ "evaluation depends on target property which is transitive "
+ "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;
+
+#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.c_str(),
+ "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
+ 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);
+ }
+ }
+
+ if (!prop) {
+ if (target->IsImported() ||
+ target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return linkedTargetsContent;
+ }
+ if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
+ context->Config)) {
+ context->HadContextSensitiveCondition = true;
+ return target->GetLinkInterfaceDependentBoolProperty(propertyName,
+ context->Config)
+ ? "1"
+ : "0";
+ }
+ if (target->IsLinkInterfaceDependentStringProperty(propertyName,
+ context->Config)) {
+ context->HadContextSensitiveCondition = true;
+ const char* propContent =
+ target->GetLinkInterfaceDependentStringProperty(propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
+ context->Config)) {
+ context->HadContextSensitiveCondition = true;
+ const char* propContent =
+ target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
+ context->Config)) {
+ context->HadContextSensitiveCondition = true;
+ const char* propContent =
+ target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+
+ return linkedTargetsContent;
+ }
+
+ if (!target->IsImported() && dagCheckerParent &&
+ !dagCheckerParent->EvaluatingLinkLibraries()) {
+ if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
+ context->Config)) {
+ context->HadContextSensitiveCondition = true;
+ const char* propContent =
+ target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
+ context->Config)) {
+ context->HadContextSensitiveCondition = true;
+ const char* propContent =
+ target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ }
+ if (!interfacePropertyName.empty()) {
+ std::string result = this->EvaluateDependentExpression(
+ prop, context->LG, context, headTarget, target, &dagChecker);
+ if (!linkedTargetsContent.empty()) {
+ result += (result.empty() ? "" : ";") + linkedTargetsContent;
+ }
+ return result;
+ }
+ return prop;
+ }
+} targetPropertyNode;
+
+static const struct TargetNameNode : public cmGeneratorExpressionNode
+{
+ TargetNameNode() {}
+
+ bool GeneratesContent() const CM_OVERRIDE { return true; }
+
+ bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool RequiresLiteralInput() const CM_OVERRIDE { return true; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ return parameters.front();
+ }
+
+ int NumExpectedParameters() const CM_OVERRIDE { return 1; }
+
+} targetNameNode;
+
+static const struct TargetObjectsNode : public cmGeneratorExpressionNode
+{
+ TargetObjectsNode() {}
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ std::string tgtName = parameters.front();
+ cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
+ if (!gt) {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but no such target exists.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ if (gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but is not an OBJECT library.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ if (!context->EvaluateForBuildsystem) {
+ cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
+ std::string reason;
+ if (!gg->HasKnownObjectFileLocation(&reason)) {
+ 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.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ }
+
+ std::vector<std::string> objects;
+
+ if (gt->IsImported()) {
+ const char* loc = CM_NULLPTR;
+ const char* imp = CM_NULLPTR;
+ std::string suffix;
+ if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) {
+ cmSystemTools::ExpandListArgument(loc, objects);
+ }
+ context->HadContextSensitiveCondition = true;
+ } else {
+ gt->GetTargetObjectNames(context->Config, objects);
+
+ std::string obj_dir;
+ if (context->EvaluateForBuildsystem) {
+ // Use object file directory with buildsystem placeholder.
+ obj_dir = gt->ObjectDirectory;
+ // Here we assume that the set of object files produced
+ // by an object library does not vary with configuration
+ // and do not set HadContextSensitiveCondition to true.
+ } else {
+ // Use object file directory with per-config location.
+ obj_dir = gt->GetObjectDirectory(context->Config);
+ context->HadContextSensitiveCondition = true;
+ }
+
+ for (std::vector<std::string>::iterator oi = objects.begin();
+ oi != objects.end(); ++oi) {
+ *oi = obj_dir + *oi;
+ }
+ }
+
+ // 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);
+ }
+
+ return cmJoin(objects, ";");
+ }
+} targetObjectsNode;
+
+static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
+{
+ CompileFeaturesNode() {}
+
+ int NumExpectedParameters() const CM_OVERRIDE { return OneOrMoreParameters; }
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+ CM_OVERRIDE
+ {
+ cmGeneratorTarget const* target = context->HeadTarget;
+ if (!target) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<COMPILE_FEATURE> may only be used with binary targets. It may "
+ "not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+ context->HadHeadSensitiveCondition = true;
+
+ typedef std::map<std::string, std::vector<std::string> > LangMap;
+ static LangMap availableFeatures;
+
+ LangMap testedFeatures;
+
+ for (std::vector<std::string>::const_iterator it = parameters.begin();
+ it != parameters.end(); ++it) {
+ std::string error;
+ std::string lang;
+ if (!context->LG->GetMakefile()->CompileFeatureKnown(
+ context->HeadTarget->Target, *it, lang, &error)) {
+ reportError(context, content->GetOriginalExpression(), error);
+ return std::string();
+ }
+ testedFeatures[lang].push_back(*it);
+
+ if (availableFeatures.find(lang) == availableFeatures.end()) {
+ const char* featuresKnown =
+ context->LG->GetMakefile()->CompileFeaturesAvailable(lang, &error);
+ if (!featuresKnown) {
+ reportError(context, content->GetOriginalExpression(), error);
+ return std::string();
+ }
+ cmSystemTools::ExpandListArgument(featuresKnown,
+ availableFeatures[lang]);
+ }
+ }
+
+ bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
+
+ for (LangMap::const_iterator lit = testedFeatures.begin();
+ lit != testedFeatures.end(); ++lit) {
+ std::vector<std::string> const& langAvailable =
+ 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()) {
+ return "0";
+ }
+ if (standardDefault && !*standardDefault) {
+ // This compiler has no notion of language standard levels.
+ // All features known for the language are always available.
+ continue;
+ }
+ if (!context->LG->GetMakefile()->HaveStandardAvailable(
+ target->Target, lit->first, *it)) {
+ if (evalLL) {
+ const char* l = target->GetProperty(lit->first + "_STANDARD");
+ if (!l) {
+ l = standardDefault;
+ }
+ assert(l);
+ context->MaxLanguageStandard[target][lit->first] = l;
+ } else {
+ return "0";
+ }
+ }
+ }
+ }
+ return "1";
+ }
+} compileFeaturesNode;
+
+static const char* targetPolicyWhitelist[] = {
+ CM_NULLPTR
+#define TARGET_POLICY_STRING(POLICY) , #POLICY
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
+
+#undef TARGET_POLICY_STRING
+};
+
+cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
+ const char* policy)
+{
+#define RETURN_POLICY(POLICY) \
+ if (strcmp(policy, #POLICY) == 0) { \
+ return tgt->GetPolicyStatus##POLICY(); \
+ }
+
+ CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
+
+#undef RETURN_POLICY
+
+ assert(false && "Unreachable code. Not a valid policy");
+ return cmPolicies::WARN;
+}
+
+cmPolicies::PolicyID policyForString(const char* policy_id)
+{
+#define RETURN_POLICY_ID(POLICY_ID) \
+ if (strcmp(policy_id, #POLICY_ID) == 0) { \
+ return cmPolicies::POLICY_ID; \
+ }
+
+ CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
+
+#undef RETURN_POLICY_ID
+
+ assert(false && "Unreachable code. Not a valid policy");
+ return cmPolicies::CMP0002;
+}
+
+static const struct TargetPolicyNode : public cmGeneratorExpressionNode
+{
+ TargetPolicyNode() {}
+
+ 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
+ {
+ if (!context->HeadTarget) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_POLICY:prop> may only be used with binary targets. It "
+ "may not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+
+ context->HadContextSensitiveCondition = true;
+ context->HadHeadSensitiveCondition = true;
+
+ for (size_t i = 1; i < cmArraySize(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,
+ cmPolicies::GetPolicyWarning(policyForString(policy)));
+ CM_FALLTHROUGH;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::OLD:
+ return "0";
+ case cmPolicies::NEW:
+ return "1";
+ }
+ }
+ }
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_POLICY:prop> may only be used with a limited number of "
+ "policies. Currently it may be used with the following policies:\n"
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+#define TARGET_POLICY_LIST_ITEM(POLICY) " * " STRINGIFY(POLICY) "\n"
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
+
+#undef TARGET_POLICY_LIST_ITEM
+ );
+ return std::string();
+ }
+
+} targetPolicyNode;
+
+static const struct InstallPrefixNode : public cmGeneratorExpressionNode
+{
+ InstallPrefixNode() {}
+
+ bool GeneratesContent() const CM_OVERRIDE { return true; }
+ 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
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
+ "should never be evaluated.");
+ return std::string();
+ }
+
+} installPrefixNode;
+
+class ArtifactDirTag;
+class ArtifactLinkerTag;
+class ArtifactNameTag;
+class ArtifactPathTag;
+class ArtifactPdbTag;
+class ArtifactSonameTag;
+class ArtifactBundleDirTag;
+class ArtifactBundleContentDirTag;
+
+template <typename ArtifactT>
+struct TargetFilesystemArtifactResultCreator
+{
+ static std::string Create(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content);
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
+{
+ static std::string Create(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ // The target soname file (.so.1).
+ if (target->IsDLLPlatform()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_SONAME_FILE is not allowed "
+ "for DLL target platforms.");
+ return std::string();
+ }
+ if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_SONAME_FILE is allowed only for "
+ "SHARED libraries.");
+ return std::string();
+ }
+ std::string result = target->GetDirectory(context->Config);
+ result += "/";
+ result += target->GetSOName(context->Config);
+ return result;
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
+{
+ static std::string Create(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (target->IsImported()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE 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 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 is allowed only for "
+ "targets with linker created artifacts.");
+ return std::string();
+ }
+
+ std::string result = target->GetPDBDirectory(context->Config);
+ result += "/";
+ result += target->GetPDBName(context->Config);
+ return result;
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
+{
+ static std::string Create(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 is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+ cmStateEnums::ArtifactType artifact = target->HasImportLibrary()
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+ return target->GetFullPath(context->Config, artifact);
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag>
+{
+ static std::string Create(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (target->IsImported()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_BUNDLE_DIR not allowed for IMPORTED targets.");
+ return std::string();
+ }
+ if (!target->IsBundleOnApple()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_BUNDLE_DIR is allowed only for Bundle targets.");
+ return std::string();
+ }
+
+ std::string outpath = target->GetDirectory(context->Config) + '/';
+ return target->BuildBundleDirectory(outpath, context->Config,
+ cmGeneratorTarget::BundleDirLevel);
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag>
+{
+ static std::string Create(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (target->IsImported()) {
+ ::reportError(
+ context, content->GetOriginalExpression(),
+ "TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets.");
+ return std::string();
+ }
+ if (!target->IsBundleOnApple()) {
+ ::reportError(
+ context, content->GetOriginalExpression(),
+ "TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets.");
+ return std::string();
+ }
+
+ std::string outpath = target->GetDirectory(context->Config) + '/';
+ return target->BuildBundleDirectory(outpath, context->Config,
+ cmGeneratorTarget::ContentLevel);
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
+{
+ static std::string Create(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*unused*/)
+ {
+ return target->GetFullPath(context->Config,
+ cmStateEnums::RuntimeBinaryArtifact, true);
+ }
+};
+
+template <typename ArtifactT>
+struct TargetFilesystemArtifactResultGetter
+{
+ static std::string Get(const std::string& result);
+};
+
+template <>
+struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
+{
+ static std::string Get(const std::string& result)
+ {
+ return cmSystemTools::GetFilenameName(result);
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
+{
+ static std::string Get(const std::string& result)
+ {
+ return cmSystemTools::GetFilenamePath(result);
+ }
+};
+
+template <>
+struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
+{
+ static std::string Get(const std::string& result) { return result; }
+};
+
+template <typename ArtifactT, typename ComponentT>
+struct TargetFilesystemArtifact : 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
+ {
+ // Lookup the referenced target.
+ std::string name = *parameters.begin();
+
+ if (!cmGeneratorExpression::IsValidTargetName(name)) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ cmGeneratorTarget* target = context->LG->FindGeneratorTargetToUse(name);
+ if (!target) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "No target \"" + name + "\"");
+ return std::string();
+ }
+ 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(),
+ "Expressions which require the linker language may not "
+ "be used while evaluating link libraries");
+ return std::string();
+ }
+ context->DependTargets.insert(target);
+ context->AllTargets.insert(target);
+
+ std::string result =
+ TargetFilesystemArtifactResultCreator<ArtifactT>::Create(target, context,
+ content);
+ if (context->HadError) {
+ return std::string();
+ }
+ return TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
+ }
+};
+
+template <typename ArtifactT>
+struct TargetFilesystemArtifactNodeGroup
+{
+ TargetFilesystemArtifactNodeGroup() {}
+
+ TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
+ TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
+ TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
+};
+
+static const TargetFilesystemArtifactNodeGroup<ArtifactNameTag>
+ targetNodeGroup;
+
+static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag>
+ targetLinkerNodeGroup;
+
+static const TargetFilesystemArtifactNodeGroup<ArtifactSonameTag>
+ targetSoNameNodeGroup;
+
+static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag>
+ targetPdbNodeGroup;
+
+static const TargetFilesystemArtifact<ArtifactBundleDirTag, ArtifactPathTag>
+ targetBundleDirNode;
+
+static const TargetFilesystemArtifact<ArtifactBundleContentDirTag,
+ ArtifactPathTag>
+ targetBundleContentDirNode;
+
+static const struct ShellPathNode : public cmGeneratorExpressionNode
+{
+ ShellPathNode() {}
+
+ std::string Evaluate(const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
+ CM_OVERRIDE
+ {
+ if (!cmSystemTools::FileIsFullPath(parameters.front())) {
+ reportError(context, content->GetOriginalExpression(),
+ "\"" + parameters.front() + "\" is not an absolute path.");
+ return std::string();
+ }
+ cmOutputConverter converter(context->LG->GetStateSnapshot());
+ return converter.ConvertDirectorySeparatorsForShell(parameters.front());
+ }
+} 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;
+}
+
+void reportError(cmGeneratorExpressionContext* context,
+ const std::string& expr, const std::string& result)
+{
+ context->HadError = true;
+ if (context->Quiet) {
+ return;
+ }
+
+ std::ostringstream e;
+ /* clang-format off */
+ e << "Error evaluating generator expression:\n"
+ << " " << expr << "\n"
+ << result;
+ /* clang-format on */
+ context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ context->Backtrace);
+}
diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h
new file mode 100644
index 000000000..ece1c113c
--- /dev/null
+++ b/Source/cmGeneratorExpressionNode.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 cmGeneratorExpressionNode_h
+#define cmGeneratorExpressionNode_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
+struct GeneratorExpressionContent;
+struct cmGeneratorExpressionContext;
+struct cmGeneratorExpressionDAGChecker;
+
+struct cmGeneratorExpressionNode
+{
+ enum
+ {
+ DynamicParameters = 0,
+ OneOrMoreParameters = -1,
+ OneOrZeroParameters = -2
+ };
+ virtual ~cmGeneratorExpressionNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+
+ virtual bool RequiresLiteralInput() const { return false; }
+
+ virtual bool AcceptsArbitraryContentParameter() const { return false; }
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ virtual std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const = 0;
+
+ static std::string EvaluateDependentExpression(
+ std::string const& prop, cmLocalGenerator* lg,
+ cmGeneratorExpressionContext* context, const cmGeneratorTarget* headTarget,
+ const cmGeneratorTarget* currentTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker);
+
+ static const cmGeneratorExpressionNode* GetNode(
+ const std::string& identifier);
+};
+
+void reportError(cmGeneratorExpressionContext* context,
+ const std::string& expr, const std::string& result);
+
+#endif
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index e1fb8f1de..c33349a63 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -1,71 +1,55 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionParser.h"
#include "cmGeneratorExpressionEvaluator.h"
-#include "assert.h"
+#include <assert.h>
+#include <stddef.h>
-//----------------------------------------------------------------------------
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
- const std::vector<cmGeneratorExpressionToken> &tokens)
- : Tokens(tokens), NestingLevel(0)
+ const std::vector<cmGeneratorExpressionToken>& tokens)
+ : Tokens(tokens)
+ , NestingLevel(0)
{
}
-//----------------------------------------------------------------------------
void cmGeneratorExpressionParser::Parse(
- std::vector<cmGeneratorExpressionEvaluator*> &result)
+ std::vector<cmGeneratorExpressionEvaluator*>& result)
{
it = this->Tokens.begin();
- while (this->it != this->Tokens.end())
- {
+ while (this->it != this->Tokens.end()) {
this->ParseContent(result);
- }
+ }
}
-//----------------------------------------------------------------------------
-static void extendText(std::vector<cmGeneratorExpressionEvaluator*> &result,
- std::vector<cmGeneratorExpressionToken>::const_iterator it)
+static void extendText(
+ std::vector<cmGeneratorExpressionEvaluator*>& result,
+ std::vector<cmGeneratorExpressionToken>::const_iterator it)
{
- if (result.size() > 0
- && (*(result.end() - 1))->GetType()
- == cmGeneratorExpressionEvaluator::Text)
- {
- TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
+ if (!result.empty() &&
+ (*(result.end() - 1))->GetType() ==
+ cmGeneratorExpressionEvaluator::Text) {
+ TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1));
textContent->Extend(it->Length);
- }
- else
- {
- TextContent *textContent = new TextContent(it->Content, it->Length);
+ } else {
+ TextContent* textContent = new TextContent(it->Content, it->Length);
result.push_back(textContent);
- }
+ }
}
-//----------------------------------------------------------------------------
-static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result,
- const std::vector<cmGeneratorExpressionEvaluator*> &contents)
+static void extendResult(
+ std::vector<cmGeneratorExpressionEvaluator*>& result,
+ const std::vector<cmGeneratorExpressionEvaluator*>& contents)
{
- if (result.size() > 0
- && (*(result.end() - 1))->GetType()
- == cmGeneratorExpressionEvaluator::Text
- && (*contents.begin())->GetType()
- == cmGeneratorExpressionEvaluator::Text)
- {
- TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
+ if (!result.empty() &&
+ (*(result.end() - 1))->GetType() ==
+ cmGeneratorExpressionEvaluator::Text &&
+ (*contents.begin())->GetType() == cmGeneratorExpressionEvaluator::Text) {
+ TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1));
textContent->Extend(
- static_cast<TextContent*>(*contents.begin())->GetLength());
+ static_cast<TextContent*>(*contents.begin())->GetLength());
delete *contents.begin();
result.insert(result.end(), contents.begin() + 1, contents.end());
} else {
@@ -73,210 +57,179 @@ static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result,
}
}
-//----------------------------------------------------------------------------
void cmGeneratorExpressionParser::ParseGeneratorExpression(
- std::vector<cmGeneratorExpressionEvaluator*> &result)
+ std::vector<cmGeneratorExpressionEvaluator*>& result)
{
assert(this->it != this->Tokens.end());
unsigned int nestedLevel = this->NestingLevel;
++this->NestingLevel;
- std::vector<cmGeneratorExpressionToken>::const_iterator startToken
- = this->it - 1;
+ std::vector<cmGeneratorExpressionToken>::const_iterator startToken =
+ this->it - 1;
std::vector<cmGeneratorExpressionEvaluator*> identifier;
- while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression
- && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator)
- {
- if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
- {
+ while (this->it->TokenType != cmGeneratorExpressionToken::EndExpression &&
+ this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator) {
+ if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) {
extendText(identifier, this->it);
++this->it;
- }
- else
- {
+ } else {
this->ParseContent(identifier);
- }
- if (this->it == this->Tokens.end())
- {
+ }
+ if (this->it == this->Tokens.end()) {
break;
- }
}
- if (identifier.empty())
- {
+ }
+ if (identifier.empty()) {
// ERROR
- }
+ }
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);
+ this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
+ 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);
result.push_back(content);
return;
- }
+ }
std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
- commaTokens;
+ commaTokens;
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
bool emptyParamTermination = false;
if (this->it != this->Tokens.end() &&
- this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
- {
+ this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) {
colonToken = this->it;
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
- if(this->it == this->Tokens.end())
- {
+ if (this->it == this->Tokens.end()) {
emptyParamTermination = true;
- }
+ }
while (this->it != this->Tokens.end() &&
- this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
- {
+ this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) {
commaTokens.push_back(this->it);
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
- if(this->it == this->Tokens.end())
- {
+ if (this->it == this->Tokens.end()) {
emptyParamTermination = true;
- }
}
+ }
while (this->it != this->Tokens.end() &&
- this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
- {
+ this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) {
extendText(*(parameters.end() - 1), this->it);
assert(this->it != this->Tokens.end());
++this->it;
- }
+ }
while (this->it != this->Tokens.end() &&
- this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
- {
+ this->it->TokenType != cmGeneratorExpressionToken::EndExpression) {
this->ParseContent(*(parameters.end() - 1));
- if (this->it == this->Tokens.end())
- {
+ if (this->it == this->Tokens.end()) {
break;
- }
+ }
while (this->it != this->Tokens.end() &&
- this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
- {
+ this->it->TokenType ==
+ cmGeneratorExpressionToken::CommaSeparator) {
commaTokens.push_back(this->it);
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
- if(this->it == this->Tokens.end())
- {
+ if (this->it == this->Tokens.end()) {
emptyParamTermination = true;
- }
}
+ }
while (this->it != this->Tokens.end() &&
- this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
- {
+ this->it->TokenType ==
+ cmGeneratorExpressionToken::ColonSeparator) {
extendText(*(parameters.end() - 1), this->it);
assert(this->it != this->Tokens.end());
++this->it;
- }
}
- if(this->it != this->Tokens.end()
- && this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
- {
- --this->NestingLevel;
- assert(this->it != this->Tokens.end());
- ++this->it;
- }
}
+ if (this->it != this->Tokens.end() &&
+ this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
+ --this->NestingLevel;
+ assert(this->it != this->Tokens.end());
+ ++this->it;
+ }
+ }
- if (nestedLevel != this->NestingLevel)
- {
+ if (nestedLevel != this->NestingLevel) {
// There was a '$<' in the text, but no corresponding '>'. Rebuild to
// treat the '$<' as having been plain text, along with the
// corresponding : and , tokens that might have been found.
extendText(result, startToken);
extendResult(result, identifier);
- if (!parameters.empty())
- {
+ 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();
+ parameters.end();
std::vector<TokenVector::const_iterator>::const_iterator commaIt =
- commaTokens.begin();
+ commaTokens.begin();
assert(parameters.size() > commaTokens.size());
- for ( ; pit != pend; ++pit, ++commaIt)
- {
- if (!pit->empty() && !emptyParamTermination)
- {
+ for (; pit != pend; ++pit, ++commaIt) {
+ if (!pit->empty() && !emptyParamTermination) {
extendResult(result, *pit);
- }
- if (commaIt != commaTokens.end())
- {
+ }
+ if (commaIt != commaTokens.end()) {
extendText(result, *commaIt);
- }
- else
- {
+ } else {
break;
- }
}
}
+ }
return;
}
- int contentLength = ((this->it - 1)->Content
- - startToken->Content)
- + (this->it - 1)->Length;
- GeneratorExpressionContent *content = new GeneratorExpressionContent(
- startToken->Content, contentLength);
+ size_t contentLength =
+ ((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
+ GeneratorExpressionContent* content =
+ new GeneratorExpressionContent(startToken->Content, contentLength);
content->SetIdentifier(identifier);
content->SetParameters(parameters);
result.push_back(content);
}
-//----------------------------------------------------------------------------
void cmGeneratorExpressionParser::ParseContent(
- std::vector<cmGeneratorExpressionEvaluator*> &result)
+ std::vector<cmGeneratorExpressionEvaluator*>& result)
{
assert(this->it != this->Tokens.end());
- switch(this->it->TokenType)
- {
- case cmGeneratorExpressionToken::Text:
- {
- if (this->NestingLevel == 0)
- {
- if (result.size() > 0
- && (*(result.end() - 1))->GetType()
- == cmGeneratorExpressionEvaluator::Text)
- {
+ switch (this->it->TokenType) {
+ case cmGeneratorExpressionToken::Text: {
+ if (this->NestingLevel == 0) {
+ if (!result.empty() &&
+ (*(result.end() - 1))->GetType() ==
+ cmGeneratorExpressionEvaluator::Text) {
// A comma in 'plain text' could have split text that should
// otherwise be continuous. Extend the last text content instead of
// creating a new one.
- TextContent *textContent =
- static_cast<TextContent*>(*(result.end() - 1));
+ TextContent* textContent =
+ static_cast<TextContent*>(*(result.end() - 1));
textContent->Extend(this->it->Length);
assert(this->it != this->Tokens.end());
++this->it;
return;
- }
}
- cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
- this->it->Length);
+ }
+ cmGeneratorExpressionEvaluator* n =
+ new TextContent(this->it->Content, this->it->Length);
result.push_back(n);
assert(this->it != this->Tokens.end());
++this->it;
- return ;
+ return;
}
case cmGeneratorExpressionToken::BeginExpression:
assert(this->it != this->Tokens.end());
@@ -286,17 +239,14 @@ void cmGeneratorExpressionParser::ParseContent(
case cmGeneratorExpressionToken::EndExpression:
case cmGeneratorExpressionToken::ColonSeparator:
case cmGeneratorExpressionToken::CommaSeparator:
- if (this->NestingLevel == 0)
- {
+ if (this->NestingLevel == 0) {
extendText(result, this->it);
- }
- else
- {
- assert(!"Got unexpected syntax token.");
- }
+ } else {
+ assert(false && "Got unexpected syntax token.");
+ }
assert(this->it != this->Tokens.end());
++this->it;
return;
- }
- assert(!"Unhandled token in generator expression.");
+ }
+ assert(false && "Unhandled token in generator expression.");
}
diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h
index 28f14410f..633381c8a 100644
--- a/Source/cmGeneratorExpressionParser.h
+++ b/Source/cmGeneratorExpressionParser.h
@@ -1,40 +1,26 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorExpressionParser_h
#define cmGeneratorExpressionParser_h
-#include "cmGeneratorExpressionLexer.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
#include <vector>
-#include "cmListFileCache.h"
+#include "cmGeneratorExpressionLexer.h"
-class cmMakefile;
-class cmTarget;
struct cmGeneratorExpressionEvaluator;
-//----------------------------------------------------------------------------
struct cmGeneratorExpressionParser
{
cmGeneratorExpressionParser(
- const std::vector<cmGeneratorExpressionToken> &tokens);
+ const std::vector<cmGeneratorExpressionToken>& tokens);
- void Parse(std::vector<cmGeneratorExpressionEvaluator*> &result);
+ void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result);
private:
- void ParseContent(std::vector<cmGeneratorExpressionEvaluator*> &);
- void ParseGeneratorExpression(
- std::vector<cmGeneratorExpressionEvaluator*> &);
+ void ParseContent(std::vector<cmGeneratorExpressionEvaluator*>&);
+ void ParseGeneratorExpression(std::vector<cmGeneratorExpressionEvaluator*>&);
private:
std::vector<cmGeneratorExpressionToken>::const_iterator it;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 62ac2638d..c9924f670 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1,319 +1,5526 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorTarget.h"
-#include "cmTarget.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-#include "cmSourceFile.h"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <assert.h>
+#include <errno.h>
+#include <iterator>
+#include <queue>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPropertyMap.h"
+#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmState.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"
-//----------------------------------------------------------------------------
-cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
+class cmMessenger;
+
+template <>
+const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
+ cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
+ cmListFileBacktrace const& /* context */)
+{
+ return tgt->GetSourcesProperty();
+}
+
+template <>
+const char* cmTargetPropertyComputer::ComputeLocationForBuild<
+ cmGeneratorTarget>(cmGeneratorTarget const* tgt)
+{
+ return tgt->GetLocation("");
+}
+
+template <>
+const char* cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
+ cmGeneratorTarget const* tgt, const std::string& config)
+{
+ return tgt->GetLocation(config);
+}
+
+class cmGeneratorTarget::TargetPropertyEntry
+{
+ static cmLinkImplItem NoLinkImplItem;
+
+public:
+ TargetPropertyEntry(CM_AUTO_PTR<cmCompiledGeneratorExpression> cge,
+ cmLinkImplItem const& item = NoLinkImplItem)
+ : ge(cge)
+ , LinkImplItem(item)
+ {
+ }
+ const CM_AUTO_PTR<cmCompiledGeneratorExpression> ge;
+ cmLinkImplItem const& LinkImplItem;
+};
+cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
+
+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));
+ }
+}
+
+cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
+ : Target(t)
+ , FortranModuleDirectoryCreated(false)
+ , SourceFileFlagsConstructed(false)
+ , PolicyWarnedCMP0022(false)
+ , PolicyReportedCMP0069(false)
+ , DebugIncludesDone(false)
+ , DebugCompileOptionsDone(false)
+ , DebugCompileFeaturesDone(false)
+ , DebugCompileDefinitionsDone(false)
+ , DebugSourcesDone(false)
+ , LinkImplementationLanguageIsContextDependent(true)
+ , UtilityItemsDone(false)
{
this->Makefile = this->Target->GetMakefile();
- this->LocalGenerator = this->Makefile->GetLocalGenerator();
+ this->LocalGenerator = lg;
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
- this->ClassifySources();
- this->LookupObjectLibraries();
+
+ this->GlobalGenerator->ComputeTargetObjectDirectory(this);
+
+ CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(),
+ t->GetIncludeDirectoriesBacktraces(),
+ this->IncludeDirectoriesEntries);
+
+ CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(),
+ t->GetCompileOptionsBacktraces(),
+ this->CompileOptionsEntries);
+
+ CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(),
+ t->GetCompileFeaturesBacktraces(),
+ this->CompileFeaturesEntries);
+
+ CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(),
+ t->GetCompileDefinitionsBacktraces(),
+ this->CompileDefinitionsEntries);
+
+ 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;
}
-//----------------------------------------------------------------------------
-int cmGeneratorTarget::GetType() const
+cmGeneratorTarget::~cmGeneratorTarget()
+{
+ cmDeleteAll(this->IncludeDirectoriesEntries);
+ cmDeleteAll(this->CompileOptionsEntries);
+ cmDeleteAll(this->CompileFeaturesEntries);
+ cmDeleteAll(this->CompileDefinitionsEntries);
+ cmDeleteAll(this->SourceEntries);
+ cmDeleteAll(this->LinkInformation);
+}
+
+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());
+ }
+ static std::string value;
+ value.clear();
+ value = cmJoin(values, ";");
+ return value.c_str();
+}
+
+cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
+{
+ return this->GetLocalGenerator()->GetGlobalGenerator();
+}
+
+cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
+{
+ return this->LocalGenerator;
+}
+
+cmStateEnums::TargetType cmGeneratorTarget::GetType() const
{
return this->Target->GetType();
}
-//----------------------------------------------------------------------------
-const char *cmGeneratorTarget::GetName() const
+const std::string& cmGeneratorTarget::GetName() const
{
return this->Target->GetName();
}
-//----------------------------------------------------------------------------
-const char *cmGeneratorTarget::GetProperty(const char *prop)
+std::string cmGeneratorTarget::GetExportName() const
+{
+ const char* exportName = this->GetProperty("EXPORT_NAME");
+
+ if (exportName && *exportName) {
+ if (!cmGeneratorExpression::IsValidTargetName(exportName)) {
+ std::ostringstream e;
+ e << "EXPORT_NAME property \"" << exportName << "\" for \""
+ << this->GetName() << "\": is not valid.";
+ cmSystemTools::Error(e.str().c_str());
+ return "";
+ }
+ return exportName;
+ }
+ return this->GetName();
+}
+
+const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
{
+ if (!cmTargetPropertyComputer::PassesWhitelist(
+ this->GetType(), prop, this->Makefile->GetMessenger(),
+ this->GetBacktrace())) {
+ return CM_NULLPTR;
+ }
+ if (const char* result = cmTargetPropertyComputer::GetProperty(
+ this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
+ return result;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return CM_NULLPTR;
+ }
return this->Target->GetProperty(prop);
}
-//----------------------------------------------------------------------------
-bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
- const char *config)
+const char* cmGeneratorTarget::GetOutputTargetType(
+ cmStateEnums::ArtifactType artifact) const
+{
+ switch (this->GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ if (this->IsDLLPlatform()) {
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // A DLL shared library is treated as a runtime target.
+ return "RUNTIME";
+ case cmStateEnums::ImportLibraryArtifact:
+ // A DLL import library is treated as an archive target.
+ return "ARCHIVE";
+ }
+ } else {
+ // For non-DLL platforms shared libraries are treated as
+ // library targets.
+ return "LIBRARY";
+ }
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ // Static libraries are always treated as archive targets.
+ return "ARCHIVE";
+ case cmStateEnums::MODULE_LIBRARY:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // Module import libraries are treated as archive targets.
+ return "LIBRARY";
+ case cmStateEnums::ImportLibraryArtifact:
+ // Module libraries are always treated as library targets.
+ return "ARCHIVE";
+ }
+ break;
+ case cmStateEnums::EXECUTABLE:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // Executables are always treated as runtime targets.
+ return "RUNTIME";
+ case cmStateEnums::ImportLibraryArtifact:
+ // Executable import libraries are treated as archive targets.
+ return "ARCHIVE";
+ }
+ break;
+ default:
+ break;
+ }
+ return "";
+}
+
+std::string cmGeneratorTarget::GetOutputName(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ // Lookup/compute/cache the output name for this configuration.
+ OutputNameKey key(config, artifact);
+ cmGeneratorTarget::OutputNameMapType::iterator i =
+ this->OutputNameMap.find(key);
+ if (i == this->OutputNameMap.end()) {
+ // Add empty name in map to detect potential recursion.
+ OutputNameMapType::value_type entry(key, "");
+ i = this->OutputNameMap.insert(entry).first;
+
+ // Compute output name.
+ std::vector<std::string> props;
+ std::string type = this->GetOutputTargetType(artifact);
+ std::string configUpper = cmSystemTools::UpperCase(config);
+ if (!type.empty() && !configUpper.empty()) {
+ // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
+ props.push_back(type + "_OUTPUT_NAME_" + configUpper);
+ }
+ if (!type.empty()) {
+ // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
+ props.push_back(type + "_OUTPUT_NAME");
+ }
+ if (!configUpper.empty()) {
+ // OUTPUT_NAME_<CONFIG>
+ props.push_back("OUTPUT_NAME_" + configUpper);
+ // <CONFIG>_OUTPUT_NAME
+ props.push_back(configUpper + "_OUTPUT_NAME");
+ }
+ // OUTPUT_NAME
+ props.push_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)) {
+ outName = outNameProp;
+ break;
+ }
+ }
+
+ if (outName.empty()) {
+ outName = this->GetName();
+ }
+
+ // 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);
+ } 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,
+ "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
+ this->GetBacktrace());
+ }
+ return i->second;
+}
+
+void cmGeneratorTarget::AddSourceCommon(const std::string& src)
+{
+ 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;
+}
+
+void cmGeneratorTarget::AddSource(const std::string& src)
+{
+ this->Target->AddSource(src);
+ this->AddSourceCommon(src);
+}
+
+void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
+{
+ this->Target->AddTracedSources(srcs);
+ if (!srcs.empty()) {
+ this->AddSourceCommon(cmJoin(srcs, ";"));
+ }
+}
+
+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));
+}
+
+std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
+ cmSourceFile const* sf) const
+{
+ SourceEntriesType::const_iterator i = this->SourceDepends.find(sf);
+ if (i != this->SourceDepends.end()) {
+ return &i->second.Depends;
+ }
+ return CM_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)
+{
+ 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);
+ }
+ if (!depTgt->IsImported() || excludeImported) {
+ return;
+ }
+
+ if (const char* dirs =
+ depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
+ cmGeneratorExpression ge;
+ cmSystemTools::ExpandListArgument(
+ ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
+ dagChecker),
+ result);
+ }
+}
+
+/* clang-format off */
+#define IMPLEMENT_VISIT(KIND) \
+ { \
+ 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); \
+ } \
+ } \
+ }
+/* clang-format on */
+
+void cmGeneratorTarget::GetObjectSources(
+ std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindObjectSource);
+
+ if (!this->Objects.empty()) {
+ return;
+ }
+
+ for (std::vector<cmSourceFile const*>::const_iterator it = data.begin();
+ it != data.end(); ++it) {
+ this->Objects[*it];
+ }
+
+ this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
+}
+
+void cmGeneratorTarget::ComputeObjectMapping()
+{
+ if (!this->Objects.empty()) {
+ 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<cmSourceFile const*> sourceFiles;
+ this->GetObjectSources(sourceFiles, *ci);
+ }
+}
+
+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);
+ if (const char* value = this->GetProperty(featureConfig)) {
+ return value;
+ }
+ }
+ if (const char* value = this->GetProperty(feature)) {
+ return value;
+ }
+ return this->LocalGenerator->GetFeature(feature, config);
+}
+
+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));
+
+ if (!result) {
+ // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
+ return false;
+ }
+
+ if (lang != "C" && lang != "CXX" && lang != "Fortran") {
+ // We do not define IPO behavior for other languages.
+ return false;
+ }
+
+ cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();
+
+ if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
+ if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) {
+ return true;
+ }
+ if (this->PolicyReportedCMP0069) {
+ // problem is already reported, no need to issue a message
+ return false;
+ }
+ const bool in_try_compile =
+ this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile();
+ if (cmp0069 == cmPolicies::WARN && !in_try_compile) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n";
+ w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
+ << "'" << this->GetName() << "'.";
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+
+ this->PolicyReportedCMP0069 = true;
+ }
+ return false;
+ }
+
+ // Note: check consistency with messages from CheckIPOSupported
+ const char* message = CM_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 +
+ "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
+ message = "Compiler doesn't support IPO";
+ } else if (!this->GlobalGenerator->IsIPOSupported()) {
+ message = "CMake doesn't support IPO for current generator";
+ }
+
+ if (!message) {
+ // No error/warning messages
+ return true;
+ }
+
+ if (this->PolicyReportedCMP0069) {
+ // problem is already reported, no need to issue a message
+ return false;
+ }
+
+ this->PolicyReportedCMP0069 = true;
+
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, message, this->GetBacktrace());
+ return false;
+}
+
+const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
+{
+ this->ComputeObjectMapping();
+ return this->Objects[file];
+}
+
+const char* cmGeneratorTarget::GetCustomObjectExtension() const
+{
+ static std::string extension;
+ const bool has_ptx_extension =
+ this->GetPropertyAsBool("CUDA_PTX_COMPILATION");
+ if (has_ptx_extension) {
+ extension = ".ptx";
+ return extension.c_str();
+ }
+ return CM_NULLPTR;
+}
+
+void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
+{
+ this->ExplicitObjectName.insert(sf);
+}
+
+bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
+{
+ const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
+ std::set<cmSourceFile const*>::const_iterator it =
+ this->ExplicitObjectName.find(file);
+ return it != this->ExplicitObjectName.end();
+}
+
+void cmGeneratorTarget::GetModuleDefinitionSources(
+ std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindModuleDefinition);
+}
+
+void cmGeneratorTarget::GetHeaderSources(
+ std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindHeader);
+}
+
+void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
+ const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindExtra);
+}
+
+void cmGeneratorTarget::GetCustomCommands(
+ std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindCustomCommand);
+}
+
+void cmGeneratorTarget::GetExternalObjects(
+ std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindExternalObject);
+}
+
+void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers,
+ const std::string& config) const
+{
+ KindedSources const& kinded = this->GetKindedSources(config);
+ headers = kinded.ExpectedResxHeaders;
+}
+
+void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& data,
+ const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindResx);
+}
+
+void cmGeneratorTarget::GetAppManifest(std::vector<cmSourceFile const*>& data,
+ const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindAppManifest);
+}
+
+void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
+ const std::string& config) const
{
+ IMPLEMENT_VISIT(SourceKindManifest);
+}
+
+void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data,
+ const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindCertificate);
+}
+
+void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
+ const std::string& config) const
+{
+ KindedSources const& kinded = this->GetKindedSources(config);
+ headers = kinded.ExpectedXamlHeaders;
+}
+
+void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
+ const std::string& config) const
+{
+ KindedSources const& kinded = this->GetKindedSources(config);
+ srcs = kinded.ExpectedXamlSources;
+}
+
+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));
+ }
+ }
+ return this->UtilityItems;
+}
+
+void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data,
+ const std::string& config) const
+{
+ IMPLEMENT_VISIT(SourceKindXaml);
+}
+
+const char* cmGeneratorTarget::GetLocation(const std::string& config) const
+{
+ static std::string location;
+ if (this->IsImported()) {
+ location = this->Target->ImportedGetFullPath(
+ config, cmStateEnums::RuntimeBinaryArtifact);
+ } else {
+ location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+ }
+ return location.c_str();
+}
+
+std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
+ const
+{
+ return this->Target->GetPreBuildCommands();
+}
+
+std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreLinkCommands()
+ const
+{
+ return this->Target->GetPreLinkCommands();
+}
+
+std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
+ const
+{
+ return this->Target->GetPostBuildCommands();
+}
+
+bool cmGeneratorTarget::IsImported() const
+{
+ return this->Target->IsImported();
+}
+
+bool cmGeneratorTarget::IsImportedGloballyVisible() const
+{
+ return this->Target->IsImportedGloballyVisible();
+}
+
+const char* cmGeneratorTarget::GetLocationForBuild() const
+{
+ static std::string location;
+ if (this->IsImported()) {
+ location = this->Target->ImportedGetFullPath(
+ "", cmStateEnums::RuntimeBinaryArtifact);
+ return location.c_str();
+ }
+
+ // Now handle the deprecated build-time configuration location.
+ location = this->GetDirectory();
+ const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
+ if (cfgid && strcmp(cfgid, ".") != 0) {
+ location += "/";
+ location += cfgid;
+ }
+
+ if (this->IsAppBundleOnApple()) {
+ std::string macdir = this->BuildBundleDirectory("", "", FullLevel);
+ if (!macdir.empty()) {
+ location += "/";
+ location += macdir;
+ }
+ }
+ location += "/";
+ location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact);
+ return location.c_str();
+}
+
+bool cmGeneratorTarget::IsSystemIncludeDirectory(
+ const std::string& dir, const std::string& config) const
+{
+ assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
std::string config_upper;
- if(config && *config)
- {
+ if (!config.empty()) {
config_upper = cmSystemTools::UpperCase(config);
- }
+ }
typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
- IncludeCacheType::iterator iter =
- this->SystemIncludesCache.find(config_upper);
+ IncludeCacheType::const_iterator iter =
+ this->SystemIncludesCache.find(config_upper);
+
+ if (iter == this->SystemIncludesCache.end()) {
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", CM_NULLPTR, CM_NULLPTR);
+
+ bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
- if (iter == this->SystemIncludesCache.end())
- {
std::vector<std::string> result;
- for (std::set<cmStdString>::const_iterator
- it = this->Target->GetSystemIncludeDirectories().begin();
- it != this->Target->GetSystemIncludeDirectories().end(); ++it)
- {
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
+ 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);
+ }
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
+ 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);
+ }
- cmSystemTools::ExpandListArgument(ge.Parse(*it)
- ->Evaluate(this->Makefile,
- config, false, this->Target,
- &dagChecker), result);
- }
- for(std::vector<std::string>::iterator li = result.begin();
- li != result.end(); ++li)
- {
- cmSystemTools::ConvertToUnixSlashes(*li);
- }
+ std::for_each(result.begin(), result.end(),
+ cmSystemTools::ConvertToUnixSlashes);
+ std::sort(result.begin(), result.end());
+ result.erase(std::unique(result.begin(), result.end()), result.end());
IncludeCacheType::value_type entry(config_upper, result);
iter = this->SystemIncludesCache.insert(entry).first;
+ }
+
+ return std::binary_search(iter->second.begin(), iter->second.end(), dir);
+}
+
+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)
+{
+ 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);
+ cge->SetEvaluateForBuildsystem(true);
+ entries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(cge, *it));
+ }
}
+ }
+}
- if (std::find(iter->second.begin(),
- iter->second.end(), dir) != iter->second.end())
- {
- return true;
+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)
+{
+ 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()) {
+ contextDependent = true;
}
- return false;
+
+ for (std::vector<std::string>::iterator i = entrySources.begin();
+ i != entrySources.end(); ++i) {
+ std::string& src = *i;
+ cmSourceFile* sf = mf->GetOrCreateSource(src);
+ std::string e;
+ std::string fullPath = sf->GetFullPath(&e);
+ if (fullPath.empty()) {
+ if (!e.empty()) {
+ cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, e, tgt->GetBacktrace());
+ }
+ return contextDependent;
+ }
+
+ if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src.c_str())) {
+ std::ostringstream err;
+ if (!targetName.empty()) {
+ err << "Target \"" << targetName
+ << "\" contains relative "
+ "path in its INTERFACE_SOURCES:\n"
+ " \""
+ << src << "\"";
+ } else {
+ err << "Found relative path while evaluating sources of "
+ "\""
+ << tgt->GetName() << "\":\n \"" << src << "\"\n";
+ }
+ tgt->GetLocalGenerator()->IssueMessage(cmake::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;
+
+ if (uniqueSrcs.insert(src).second) {
+ srcs.push_back(src);
+ if (debugSources) {
+ usedSources += " * " + src + "\n";
+ }
+ }
+ }
+ if (!usedSources.empty()) {
+ tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::LOG, std::string("Used sources for target ") + tgt->GetName() +
+ ":\n" + usedSources,
+ (*it)->ge->GetBacktrace());
+ }
+ }
+ return contextDependent;
}
-//----------------------------------------------------------------------------
-bool cmGeneratorTarget::GetPropertyAsBool(const char *prop)
+void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
+ const std::string& config) const
{
- return this->Target->GetPropertyAsBool(prop);
+ assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
+
+ if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
+ // At configure-time, this method can be called as part of getting the
+ // LOCATION property or to export() a file to be include()d. However
+ // there is no cmGeneratorTarget at configure-time, so search the SOURCES
+ // for TARGET_OBJECTS instead for backwards compatibility with OLD
+ // 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] == '>') {
+ continue;
+ }
+ files.push_back(*li);
+ }
+ }
+ return;
+ }
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugSources = !this->DebugSourcesDone &&
+ std::find(debugProperties.begin(), debugProperties.end(), "SOURCES") !=
+ debugProperties.end();
+
+ 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);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceSourcesEntries;
+
+ AddInterfaceEntries(this, config, "INTERFACE_SOURCES",
+ linkInterfaceSourcesEntries);
+
+ std::vector<std::string>::size_type numFilesBefore = files.size();
+ bool contextDependentInterfaceSources =
+ processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs,
+ &dagChecker, config, debugSources);
+
+ if (!contextDependentDirectSources &&
+ !(contextDependentInterfaceSources && numFilesBefore < files.size())) {
+ this->LinkImplementationLanguageIsContextDependent = false;
+ }
+
+ cmDeleteAll(linkInterfaceSourcesEntries);
}
-//----------------------------------------------------------------------------
-std::vector<cmSourceFile*> const& cmGeneratorTarget::GetSourceFiles()
+void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
+ const std::string& config) const
{
- return this->Target->GetSourceFiles();
+ 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
+ // requires the absolute paths to all sources to be determined.
+ // 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::set<cmSourceFile*> emitted;
+ for (std::vector<std::string>::const_iterator i = srcs.begin();
+ i != srcs.end(); ++i) {
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ if (emitted.insert(sf).second) {
+ files.push_back(sf);
+ }
+ }
+ return;
+ }
+
+ 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);
+ }
}
-//----------------------------------------------------------------------------
-void cmGeneratorTarget::ClassifySources()
+void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+ std::vector<cmSourceFile*>& files, const std::string& config) const
+{
+ 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);
+ }
+ }
+}
+
+cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
+ std::string const& config) const
+{
+ // If we already processed one configuration and found no dependenc
+ // on configuration then always use the one result.
+ if (!this->LinkImplementationLanguageIsContextDependent) {
+ return this->KindedSourcesMap.begin()->second;
+ }
+
+ // Lookup any existing link implementation for this configuration.
+ std::string const key = cmSystemTools::UpperCase(config);
+ KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key);
+ if (it != this->KindedSourcesMap.end()) {
+ if (!it->second.Initialized) {
+ std::ostringstream e;
+ e << "The SOURCES of \"" << this->GetName()
+ << "\" use a generator expression that depends on the "
+ "SOURCES themselves.";
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+ static KindedSources empty;
+ return empty;
+ }
+ return it->second;
+ }
+
+ // Add an entry to the map for this configuration.
+ KindedSources& files = this->KindedSourcesMap[key];
+ this->ComputeKindedSources(files, config);
+ files.Initialized = true;
+ return files;
+}
+
+void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
+ std::string const& config) const
{
- cmsys::RegularExpression header(CM_HEADER_REGEX);
- bool isObjLib = this->Target->GetType() == cmTarget::OBJECT_LIBRARY;
+ // Get the source file paths by string.
+ std::vector<std::string> srcs;
+ this->GetSourceFiles(srcs, config);
+
+ cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
std::vector<cmSourceFile*> badObjLib;
- std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); ++si)
- {
- cmSourceFile* sf = *si;
+
+ std::set<cmSourceFile*> emitted;
+ for (std::vector<std::string>::const_iterator i = srcs.begin();
+ i != srcs.end(); ++i) {
+ // Create each source at most once.
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ if (!emitted.insert(sf).second) {
+ continue;
+ }
+
+ // Compute the kind (classification) of this source file.
+ SourceKind kind;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- if(sf->GetCustomCommand())
- {
- this->CustomCommands.push_back(sf);
- }
- else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY"))
- {
- this->HeaderSources.push_back(sf);
- }
- else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
- {
- this->ExternalObjects.push_back(sf);
- if(isObjLib) { badObjLib.push_back(sf); }
- }
- else if(sf->GetLanguage())
- {
- this->ObjectSources.push_back(sf);
- }
- else if(ext == "def")
- {
- this->ModuleDefinitionFile = sf->GetFullPath();
- if(isObjLib) { badObjLib.push_back(sf); }
- }
- else if(ext == "idl")
- {
- this->IDLSources.push_back(sf);
- if(isObjLib) { badObjLib.push_back(sf); }
- }
- else if(ext == "resx")
- {
+ if (sf->GetCustomCommand()) {
+ kind = SourceKindCustomCommand;
+ } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
+ kind = SourceKindExtra;
+ } 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()) {
+ kind = SourceKindObjectSource;
+ } else if (ext == "def") {
+ kind = SourceKindModuleDefinition;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (ext == "idl") {
+ kind = SourceKindIDL;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (ext == "resx") {
+ kind = SourceKindResx;
// Build and save the name of the corresponding .h file
// This relationship will be used later when building the project 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 hFileName = resx.substr(0, resx.find_last_of(".")) + ".h";
- this->ExpectedResxHeaders.insert(hFileName);
- this->ResxSources.push_back(sf);
- }
- else if(header.find(sf->GetFullPath().c_str()))
- {
- this->HeaderSources.push_back(sf);
- }
- else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str()))
- {
- // We only get here if a source file is not an external object
- // and has an extension that is listed as an ignored file type.
- // No message or diagnosis should be given.
- this->ExtraSources.push_back(sf);
- }
- else
- {
- this->ExtraSources.push_back(sf);
- if(isObjLib && ext != "txt")
- {
- badObjLib.push_back(sf);
+ std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
+ files.ExpectedResxHeaders.insert(hFileName);
+ } else if (ext == "appxmanifest") {
+ kind = SourceKindAppManifest;
+ } else if (ext == "manifest") {
+ kind = SourceKindManifest;
+ } else if (ext == "pfx") {
+ kind = SourceKindCertificate;
+ } else if (ext == "xaml") {
+ kind = SourceKindXaml;
+ // Build and save the name of the corresponding .h and .cpp file
+ // This relationship will be used later when building the project 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 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())) {
+ kind = SourceKindHeader;
+ } else {
+ kind = SourceKindExtra;
+ }
+
+ // Save this classified source file in the result vector.
+ SourceAndKind entry = { sf, kind };
+ files.Sources.push_back(entry);
+ }
+
+ 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";
+ }
+ 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());
+ }
+}
+
+std::vector<cmGeneratorTarget::AllConfigSource> const&
+cmGeneratorTarget::GetAllConfigSources() const
+{
+ if (this->AllConfigSources.empty()) {
+ this->ComputeAllConfigSources();
+ }
+ return this->AllConfigSources;
+}
+
+void cmGeneratorTarget::ComputeAllConfigSources() const
+{
+ std::vector<std::string> configs;
+ this->Makefile->GetConfigurations(configs);
+
+ std::map<cmSourceFile const*, size_t> index;
+
+ 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);
+ if (mi == index.end()) {
+ AllConfigSource acs;
+ acs.Source = si->Source;
+ acs.Kind = si->Kind;
+ this->AllConfigSources.push_back(acs);
+ std::map<cmSourceFile const*, size_t>::value_type entry(
+ si->Source, this->AllConfigSources.size() - 1);
+ mi = index.insert(entry).first;
+ }
+ this->AllConfigSources[mi->second].Configs.push_back(ci);
+ }
+ }
+}
+
+std::string cmGeneratorTarget::GetCompilePDBName(
+ const std::string& config) const
+{
+ std::string prefix;
+ std::string base;
+ std::string suffix;
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
+
+ // Check for a per-configuration output directory target property.
+ std::string configUpper = cmSystemTools::UpperCase(config);
+ std::string configProp = "COMPILE_PDB_NAME_";
+ configProp += configUpper;
+ const char* config_name = this->GetProperty(configProp);
+ if (config_name && *config_name) {
+ return prefix + config_name + ".pdb";
+ }
+
+ const char* name = this->GetProperty("COMPILE_PDB_NAME");
+ if (name && *name) {
+ return prefix + name + ".pdb";
+ }
+
+ return "";
+}
+
+std::string cmGeneratorTarget::GetCompilePDBPath(
+ const std::string& config) const
+{
+ std::string dir = this->GetCompilePDBDirectory(config);
+ std::string name = this->GetCompilePDBName(config);
+ if (dir.empty() && !name.empty() && this->HaveWellDefinedOutputFiles()) {
+ dir = this->GetPDBDirectory(config);
+ }
+ if (!dir.empty()) {
+ dir += "/";
+ }
+ return dir + name;
+}
+
+bool cmGeneratorTarget::HasSOName(const std::string& config) const
+{
+ // soname is supported only for shared libraries and modules,
+ // and then only when the platform supports an soname flag.
+ return ((this->GetType() == cmStateEnums::SHARED_LIBRARY) &&
+ !this->GetPropertyAsBool("NO_SONAME") &&
+ this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config)));
+}
+
+bool cmGeneratorTarget::NeedRelinkBeforeInstall(
+ const std::string& config) const
+{
+ // Only executables and shared libraries can have an rpath and may
+ // need relinking.
+ if (this->GetType() != cmStateEnums::EXECUTABLE &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ return false;
+ }
+
+ // If there is no install location this target will not be installed
+ // and therefore does not need relinking.
+ if (!this->Target->GetHaveInstallRule()) {
+ return false;
+ }
+
+ // If skipping all rpaths completely then no relinking is needed.
+ if (this->Makefile->IsOn("CMAKE_SKIP_RPATH")) {
+ return false;
+ }
+
+ // If building with the install-tree rpath no relinking is needed.
+ if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
+ return false;
+ }
+
+ // If chrpath is going to be used no relinking is needed.
+ if (this->IsChrpathUsed(config)) {
+ return false;
+ }
+
+ // 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";
+ if (!this->Makefile->IsSet(flagVar)) {
+ // There is no rpath support on this platform so nothing needs
+ // relinking.
+ return false;
+ }
+ } else {
+ // No linker language is known. This error will be reported by
+ // other code.
+ return false;
+ }
+
+ // If either a build or install tree rpath is set then the rpath
+ // will likely change between the build tree and install tree and
+ // this target must be relinked.
+ bool have_rpath =
+ this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
+ bool is_ninja =
+ this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
+
+ if (have_rpath && is_ninja) {
+ std::ostringstream w;
+ /* clang-format off */
+ w <<
+ "The install of the " << this->GetName() << " target requires "
+ "changing an RPATH from the build tree, but this is not supported "
+ "with the Ninja generator unless on an ELF-based platform. The "
+ "CMAKE_BUILD_WITH_INSTALL_RPATH variable may be set to avoid this "
+ "relinking step."
+ ;
+ /* clang-format on */
+
+ cmake* cm = this->LocalGenerator->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
+ }
+
+ return have_rpath;
+}
+
+bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
+{
+ // Only certain target types have an rpath.
+ if (!(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->GetType() == cmStateEnums::EXECUTABLE)) {
+ return false;
+ }
+
+ // If the target will not be installed we do not need to change its
+ // rpath.
+ if (!this->Target->GetHaveInstallRule()) {
+ return false;
+ }
+
+ // Skip chrpath if skipping rpath altogether.
+ if (this->Makefile->IsOn("CMAKE_SKIP_RPATH")) {
+ return false;
+ }
+
+ // Skip chrpath if it does not need to be changed at install time.
+ if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
+ return false;
+ }
+
+ // Allow the user to disable builtin chrpath explicitly.
+ if (this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH")) {
+ return false;
+ }
+
+ if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+ return true;
+ }
+
+#if defined(CMAKE_USE_ELF_PARSER)
+ // Enable if the rpath flag uses a separator and the target uses ELF
+ // binaries.
+ std::string ll = this->GetLinkerLanguage(config);
+ if (!ll.empty()) {
+ std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
+ sepVar += ll;
+ sepVar += "_FLAG_SEP";
+ const char* sep = this->Makefile->GetDefinition(sepVar);
+ if (sep && *sep) {
+ // TODO: Add ELF check to ABI detection and get rid of
+ // CMAKE_EXECUTABLE_FORMAT.
+ if (const char* fmt =
+ this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) {
+ return strcmp(fmt, "ELF") == 0;
+ }
+ }
+ }
+#endif
+ static_cast<void>(config);
+ return false;
+}
+
+bool cmGeneratorTarget::IsImportedSharedLibWithoutSOName(
+ const std::string& config) const
+{
+ if (this->IsImported() && this->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ if (cmGeneratorTarget::ImportInfo const* info =
+ this->GetImportInfo(config)) {
+ return info->NoSOName;
+ }
+ }
+ return false;
+}
+
+bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
+ const std::string& config) const
+{
+ bool install_name_is_rpath = false;
+ bool macosx_rpath = false;
+
+ if (!this->IsImported()) {
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY) {
+ return false;
+ }
+ const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
+ bool use_install_name = this->MacOSXUseInstallNameDir();
+ if (install_name && use_install_name &&
+ std::string(install_name) == "@rpath") {
+ install_name_is_rpath = true;
+ } else if (install_name && use_install_name) {
+ return false;
+ }
+ if (!install_name_is_rpath) {
+ macosx_rpath = this->MacOSXRpathInstallNameDirDefault();
+ }
+ } else {
+ // Lookup the imported soname.
+ if (cmGeneratorTarget::ImportInfo const* info =
+ this->GetImportInfo(config)) {
+ if (!info->NoSOName && !info->SOName.empty()) {
+ if (info->SOName.find("@rpath/") == 0) {
+ install_name_is_rpath = true;
+ }
+ } else {
+ std::string install_name;
+ cmSystemTools::GuessLibraryInstallName(info->Location, install_name);
+ if (install_name.find("@rpath") != std::string::npos) {
+ install_name_is_rpath = true;
}
}
}
+ }
- if(!badObjLib.empty())
- {
- cmOStringStream e;
- e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n";
- for(std::vector<cmSourceFile*>::iterator i = badObjLib.begin();
- i != badObjLib.end(); ++i)
- {
- e << " " << (*i)->GetLocation().GetName() << "\n";
+ if (!install_name_is_rpath && !macosx_rpath) {
+ return false;
+ }
+
+ if (!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) {
+ std::ostringstream w;
+ w << "Attempting to use ";
+ if (macosx_rpath) {
+ w << "MACOSX_RPATH";
+ } else {
+ w << "@rpath";
+ }
+ w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
+ w << " This could be because you are using a Mac OS X version";
+ 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());
+ }
+
+ return true;
+}
+
+bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
+{
+ // we can't do rpaths when unsupported
+ if (!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) {
+ return false;
+ }
+
+ const char* macosx_rpath_str = this->GetProperty("MACOSX_RPATH");
+ if (macosx_rpath_str) {
+ return this->GetPropertyAsBool("MACOSX_RPATH");
+ }
+
+ cmPolicies::PolicyStatus cmp0042 = this->GetPolicyStatusCMP0042();
+
+ if (cmp0042 == cmPolicies::WARN) {
+ this->LocalGenerator->GetGlobalGenerator()->AddCMP0042WarnTarget(
+ this->GetName());
+ }
+
+ return cmp0042 == cmPolicies::NEW;
+}
+
+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);
+ }
+
+ cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+ if (cmp0068 == cmPolicies::NEW) {
+ return false;
+ }
+
+ bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+
+ if (use_install_name && cmp0068 == cmPolicies::WARN) {
+ this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+ this->GetName());
+ }
+
+ return use_install_name;
+}
+
+bool cmGeneratorTarget::CanGenerateInstallNameDir(
+ InstallNameType name_type) const
+{
+ cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+
+ if (cmp0068 == cmPolicies::NEW) {
+ return true;
+ }
+
+ bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH");
+ if (name_type == INSTALL_NAME_FOR_INSTALL) {
+ skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
+ } else {
+ skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
+ }
+
+ if (skip && cmp0068 == cmPolicies::WARN) {
+ this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+ this->GetName());
+ }
+
+ return !skip;
+}
+
+std::string cmGeneratorTarget::GetSOName(const std::string& config) const
+{
+ if (this->IsImported()) {
+ // Lookup the imported soname.
+ if (cmGeneratorTarget::ImportInfo const* info =
+ this->GetImportInfo(config)) {
+ if (info->NoSOName) {
+ // The imported library has no builtin soname so the name
+ // searched at runtime will be just the filename.
+ return cmSystemTools::GetFilenameName(info->Location);
}
- e << "but may contain only headers and sources that compile.";
- this->GlobalGenerator->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str(),
- this->Target->GetBacktrace());
+ // Use the soname given if any.
+ if (info->SOName.find("@rpath/") == 0) {
+ return info->SOName.substr(6);
+ }
+ return info->SOName;
}
+ 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;
}
-//----------------------------------------------------------------------------
-void cmGeneratorTarget::LookupObjectLibraries()
-{
- std::vector<std::string> const& objLibs =
- this->Target->GetObjectLibraries();
- for(std::vector<std::string>::const_iterator oli = objLibs.begin();
- oli != objLibs.end(); ++oli)
- {
- std::string const& objLibName = *oli;
- if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName.c_str()))
- {
- if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- if(this->Target->GetType() != cmTarget::EXECUTABLE &&
- this->Target->GetType() != cmTarget::STATIC_LIBRARY &&
- this->Target->GetType() != cmTarget::SHARED_LIBRARY &&
- this->Target->GetType() != cmTarget::MODULE_LIBRARY)
- {
- this->GlobalGenerator->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR,
- "Only executables and non-OBJECT libraries may "
- "reference target objects.",
- this->Target->GetBacktrace());
- return;
- }
- this->Target->AddUtility(objLib->GetName());
- this->ObjectLibraries.push_back(objLib);
+static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
+{
+ return level == cmGeneratorTarget::FullLevel;
+}
+
+static 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 += ".";
+ const char* ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext) {
+ ext = "app";
+ }
+ fpath += ext;
+ if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ fpath += "/Contents";
+ if (shouldAddFullLevel(level)) {
+ fpath += "/MacOS";
+ }
+ }
+ return fpath;
+}
+
+bool cmGeneratorTarget::IsBundleOnApple() const
+{
+ return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
+ this->IsCFBundleOnApple();
+}
+
+std::string cmGeneratorTarget::GetCFBundleDirectory(
+ const std::string& config, BundleDirectoryLevel level) const
+{
+ std::string fpath;
+ fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
+ fpath += ".";
+ const char* ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext) {
+ if (this->IsXCTestOnApple()) {
+ ext = "xctest";
+ } else {
+ ext = "bundle";
+ }
+ }
+ fpath += ext;
+ if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ fpath += "/Contents";
+ if (shouldAddFullLevel(level)) {
+ fpath += "/MacOS";
+ }
+ }
+ return fpath;
+}
+
+std::string cmGeneratorTarget::GetFrameworkDirectory(
+ const std::string& config, BundleDirectoryLevel level) const
+{
+ std::string fpath;
+ fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
+ fpath += ".";
+ const char* ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext) {
+ ext = "framework";
+ }
+ fpath += ext;
+ if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ fpath += "/Versions/";
+ fpath += this->GetFrameworkVersion();
+ }
+ return fpath;
+}
+
+std::string cmGeneratorTarget::GetFullName(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ if (this->IsImported()) {
+ return this->GetFullNameImported(config, artifact);
+ }
+ return this->GetFullNameInternal(config, artifact);
+}
+
+std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
+ const std::string& config) const
+{
+ if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+
+ // If building directly for installation then the build tree install_name
+ // is the same as the install tree.
+ if (this->MacOSXUseInstallNameDir()) {
+ return this->GetInstallNameDirForInstallTree();
+ }
+
+ // Use the build tree directory for the target.
+ if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) {
+ std::string dir;
+ if (this->MacOSXRpathInstallNameDirDefault()) {
+ dir = "@rpath";
+ } else {
+ dir = this->GetDirectory(config);
+ }
+ dir += "/";
+ return dir;
+ }
+ }
+ return "";
+}
+
+std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
+{
+ if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
+ std::string dir;
+ const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
+
+ if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
+ if (install_name_dir && *install_name_dir) {
+ dir = install_name_dir;
+ dir += "/";
+ }
+ }
+ if (!install_name_dir) {
+ if (this->MacOSXRpathInstallNameDirDefault()) {
+ dir = "@rpath/";
+ }
+ }
+ return dir;
+ }
+ return "";
+}
+
+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
+{
+ 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::EXECUTABLE;
+}
+
+const char* cmGeneratorTarget::GetExportMacro() const
+{
+ // Define the symbol for targets that export symbols.
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->IsExecutableWithExports()) {
+ if (const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
+ this->ExportMacro = custom_export_name;
+ } else {
+ std::string in = this->GetName();
+ in += "_EXPORTS";
+ this->ExportMacro = cmSystemTools::MakeCidentifier(in);
+ }
+ return this->ExportMacro.c_str();
+ }
+ return CM_NULLPTR;
+}
+
+class cmTargetCollectLinkLanguages
+{
+public:
+ cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
+ const std::string& config,
+ CM_UNORDERED_SET<std::string>& languages,
+ cmGeneratorTarget const* head)
+ : Config(config)
+ , Languages(languages)
+ , HeadTarget(head)
+ , Target(target)
+ {
+ this->Visited.insert(target);
+ }
+
+ void Visit(cmLinkItem const& item)
+ {
+ if (!item.Target) {
+ if (item.find("::") != std::string::npos) {
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::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;
+ } break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
}
- else
- {
- cmOStringStream e;
- e << "Objects of target \"" << objLibName
- << "\" referenced but is not an OBJECT library.";
- this->GlobalGenerator->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str(),
- this->Target->GetBacktrace());
- return;
+
+ if (!noMessage) {
+ e << "Target \"" << this->Target->GetName()
+ << "\" links to target \"" << item
+ << "\" but the target was not found. Perhaps a find_package() "
+ "call is missing for an IMPORTED target, or an ALIAS target is "
+ "missing?";
+ this->Target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ messageType, e.str(), this->Target->GetBacktrace());
}
}
- else
- {
- cmOStringStream e;
- e << "Objects of target \"" << objLibName
- << "\" referenced but no such target exists.";
- this->GlobalGenerator->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str(),
- this->Target->GetBacktrace());
return;
+ }
+ if (!this->Visited.insert(item.Target).second) {
+ return;
+ }
+ cmLinkInterface const* iface =
+ item.Target->GetLinkInterface(this->Config, this->HeadTarget);
+ if (!iface) {
+ return;
+ }
+
+ for (std::vector<std::string>::const_iterator li =
+ iface->Languages.begin();
+ li != iface->Languages.end(); ++li) {
+ this->Languages.insert(*li);
+ }
+
+ for (std::vector<cmLinkItem>::const_iterator li = iface->Libraries.begin();
+ li != iface->Libraries.end(); ++li) {
+ this->Visit(*li);
+ }
+ }
+
+private:
+ std::string Config;
+ CM_UNORDERED_SET<std::string>& Languages;
+ cmGeneratorTarget const* HeadTarget;
+ const cmGeneratorTarget* Target;
+ std::set<cmGeneratorTarget const*> Visited;
+};
+
+cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
+ const std::string& config) const
+{
+ std::string key(cmSystemTools::UpperCase(config));
+ LinkClosureMapType::iterator i = this->LinkClosureMap.find(key);
+ if (i == this->LinkClosureMap.end()) {
+ LinkClosure lc;
+ this->ComputeLinkClosure(config, lc);
+ LinkClosureMapType::value_type entry(key, lc);
+ i = this->LinkClosureMap.insert(entry).first;
+ }
+ return &i->second;
+}
+
+class cmTargetSelectLinker
+{
+ int Preference;
+ cmGeneratorTarget const* Target;
+ cmGlobalGenerator* GG;
+ std::set<std::string> Preferred;
+
+public:
+ cmTargetSelectLinker(cmGeneratorTarget const* target)
+ : Preference(0)
+ , Target(target)
+ {
+ this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator();
+ }
+ void Consider(const char* lang)
+ {
+ int preference = this->GG->GetLinkerPreference(lang);
+ if (preference > this->Preference) {
+ this->Preference = preference;
+ this->Preferred.clear();
+ }
+ if (preference == this->Preference) {
+ this->Preferred.insert(lang);
+ }
+ }
+ std::string Choose()
+ {
+ if (this->Preferred.empty()) {
+ return "";
+ }
+ if (this->Preferred.size() > 1) {
+ std::ostringstream e;
+ 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";
}
+ e << "Set the LINKER_LANGUAGE property for this target.";
+ cmake* cm = this->Target->GetLocalGenerator()->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Target->GetBacktrace());
}
+ return *this->Preferred.begin();
+ }
+};
+
+void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
+ LinkClosure& lc) const
+{
+ // Get languages built in this target.
+ CM_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);
+ }
+
+ // 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);
+ }
+
+ // 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);
+ }
+
+ // Choose the language whose linker should be used.
+ if (this->GetProperty("HAS_CXX")) {
+ lc.LinkerLanguage = "CXX";
+ } else if (const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) {
+ lc.LinkerLanguage = linkerLang;
+ } else {
+ // Find the language with the highest preference value.
+ 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());
+ }
+
+ // Now consider languages that propagate from linked targets.
+ for (CM_UNORDERED_SET<std::string>::const_iterator sit = languages.begin();
+ sit != languages.end(); ++sit) {
+ std::string propagates =
+ "CMAKE_" + *sit + "_LINKER_PREFERENCE_PROPAGATES";
+ if (this->Makefile->IsOn(propagates)) {
+ tsl.Consider(sit->c_str());
+ }
+ }
+
+ lc.LinkerLanguage = tsl.Choose();
+ }
}
-//----------------------------------------------------------------------------
-void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs)
+void cmGeneratorTarget::GetFullNameComponents(
+ std::string& prefix, std::string& base, std::string& suffix,
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
- for(std::vector<cmTarget*>::const_iterator
- ti = this->ObjectLibraries.begin();
- ti != this->ObjectLibraries.end(); ++ti)
- {
- cmTarget* objLib = *ti;
- cmGeneratorTarget* ogt =
- this->GlobalGenerator->GetGeneratorTarget(objLib);
- for(std::vector<cmSourceFile*>::const_iterator
- si = ogt->ObjectSources.begin();
- si != ogt->ObjectSources.end(); ++si)
- {
- std::string obj = ogt->ObjectDirectory;
- obj += ogt->Objects[*si];
- objs.push_back(obj);
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
+}
+
+std::string cmGeneratorTarget::BuildBundleDirectory(
+ const std::string& base, const std::string& config,
+ BundleDirectoryLevel level) const
+{
+ std::string fpath = base;
+ if (this->IsAppBundleOnApple()) {
+ fpath += this->GetAppBundleDirectory(config, level);
+ }
+ if (this->IsFrameworkOnApple()) {
+ fpath += this->GetFrameworkDirectory(config, level);
+ }
+ if (this->IsCFBundleOnApple()) {
+ fpath += this->GetCFBundleDirectory(config, level);
+ }
+ return fpath;
+}
+
+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 += "/";
+ BundleDirectoryLevel level = ContentLevel;
+ if (this->IsFrameworkOnApple()) {
+ // additional files with a framework go into the version specific
+ // directory
+ level = FullLevel;
+ }
+ fpath = this->BuildBundleDirectory(fpath, config, level);
+ return fpath;
+}
+
+std::string cmGeneratorTarget::GetEffectiveFolderName() const
+{
+ std::string effectiveFolder;
+
+ if (!this->GlobalGenerator->UseFolderProperty()) {
+ return effectiveFolder;
+ }
+
+ const char* targetFolder = this->GetProperty("FOLDER");
+ if (targetFolder) {
+ effectiveFolder += targetFolder;
+ }
+
+ return effectiveFolder;
+}
+
+cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
+ const std::string& config) const
+{
+ // There is no compile information for imported targets.
+ if (this->IsImported()) {
+ return CM_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;
+ }
+
+ // Lookup/compute/cache the compile information for this configuration.
+ std::string config_upper;
+ if (!config.empty()) {
+ config_upper = cmSystemTools::UpperCase(config);
+ }
+ CompileInfoMapType::const_iterator i =
+ this->CompileInfoMap.find(config_upper);
+ if (i == this->CompileInfoMap.end()) {
+ CompileInfo info;
+ this->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir);
+ CompileInfoMapType::value_type entry(config_upper, info);
+ i = this->CompileInfoMap.insert(entry).first;
+ }
+ return &i->second;
+}
+
+cmGeneratorTarget::ModuleDefinitionInfo const*
+cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
+{
+ // A module definition file only makes sense on certain target types.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ !this->IsExecutableWithExports()) {
+ return CM_NULLPTR;
+ }
+
+ // Lookup/compute/cache the compile information for this configuration.
+ std::string config_upper;
+ if (!config.empty()) {
+ config_upper = cmSystemTools::UpperCase(config);
+ }
+ ModuleDefinitionInfoMapType::const_iterator i =
+ this->ModuleDefinitionInfoMap.find(config_upper);
+ if (i == this->ModuleDefinitionInfoMap.end()) {
+ ModuleDefinitionInfo info;
+ this->ComputeModuleDefinitionInfo(config, info);
+ ModuleDefinitionInfoMapType::value_type entry(config_upper, info);
+ i = this->ModuleDefinitionInfoMap.insert(entry).first;
+ }
+ return &i->second;
+}
+
+void cmGeneratorTarget::ComputeModuleDefinitionInfo(
+ std::string const& config, ModuleDefinitionInfo& info) const
+{
+ this->GetModuleDefinitionSources(info.Sources, config);
+ info.WindowsExportAllSymbols =
+ this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
+ this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+ info.DefFileGenerated =
+ info.WindowsExportAllSymbols || info.Sources.size() > 1;
+ if (info.DefFileGenerated) {
+ info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
+ } else if (!info.Sources.empty()) {
+ info.DefFile = info.Sources.front()->GetFullPath();
+ }
+}
+
+bool cmGeneratorTarget::IsDLLPlatform() const
+{
+ return this->DLLPlatform;
+}
+
+void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
+ const std::string& config) const
+{
+ const char* prop =
+ this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS", config);
+ 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);
+}
+
+void processILibs(const std::string& config,
+ cmGeneratorTarget const* headTarget, cmLinkItem const& item,
+ cmGlobalGenerator* gg,
+ std::vector<cmGeneratorTarget const*>& tgts,
+ std::set<cmGeneratorTarget const*>& emitted)
+{
+ if (item.Target && emitted.insert(item.Target).second) {
+ 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);
}
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGeneratorTarget::GetAppleArchs(const char* config,
- std::vector<std::string>& archVec)
+const std::vector<const cmGeneratorTarget*>&
+cmGeneratorTarget::GetLinkImplementationClosure(
+ const std::string& config) const
{
- const char* archs = 0;
- if(config && *config)
- {
- std::string defVarName = "OSX_ARCHITECTURES_";
- defVarName += cmSystemTools::UpperCase(config);
- archs = this->Target->GetProperty(defVarName.c_str());
+ LinkImplClosure& tgts = this->LinkImplClosureMap[config];
+ if (!tgts.Done) {
+ tgts.Done = true;
+ std::set<cmGeneratorTarget const*> emitted;
+
+ 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,
+ this->LocalGenerator->GetGlobalGenerator(), tgts, emitted);
+ }
+ }
+ return tgts;
+}
+
+class cmTargetTraceDependencies
+{
+public:
+ cmTargetTraceDependencies(cmGeneratorTarget* target);
+ void Trace();
+
+private:
+ cmGeneratorTarget* GeneratorTarget;
+ cmMakefile* Makefile;
+ cmLocalGenerator* LocalGenerator;
+ cmGlobalGenerator const* GlobalGenerator;
+ typedef cmGeneratorTarget::SourceEntry SourceEntry;
+ SourceEntry* CurrentEntry;
+ std::queue<cmSourceFile*> SourceQueue;
+ std::set<cmSourceFile*> SourcesQueued;
+ typedef std::map<std::string, cmSourceFile*> NameMapType;
+ NameMapType NameMap;
+ std::vector<std::string> NewSources;
+
+ void QueueSource(cmSourceFile* sf);
+ void FollowName(std::string const& name);
+ void FollowNames(std::vector<std::string> const& names);
+ bool IsUtility(std::string const& dep);
+ void CheckCustomCommand(cmCustomCommand const& cc);
+ void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
+ void FollowCommandDepends(cmCustomCommand const& cc,
+ const std::string& config,
+ std::set<std::string>& emitted);
+};
+
+cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
+ : GeneratorTarget(target)
+{
+ // Convenience.
+ this->Makefile = target->Target->GetMakefile();
+ this->LocalGenerator = target->GetLocalGenerator();
+ this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
+ this->CurrentEntry = CM_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<cmSourceFile*> sources;
+ this->GeneratorTarget->GetSourceFiles(sources, *ci);
+ for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
+ si != sources.end(); ++si) {
+ cmSourceFile* sf = *si;
+ const std::set<cmGeneratorTarget const*> tgts =
+ this->GlobalGenerator->GetFilenameTargetDepends(sf);
+ if (tgts.find(this->GeneratorTarget) != tgts.end()) {
+ std::ostringstream e;
+ e << "Evaluation output file\n \"" << sf->GetFullPath()
+ << "\"\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());
+ return;
+ }
+ if (emitted.insert(sf).second &&
+ this->SourcesQueued.insert(sf).second) {
+ this->SourceQueue.push(sf);
+ }
+ }
+ }
+ }
+
+ // Queue pre-build, pre-link, and post-build rule dependencies.
+ this->CheckCustomCommands(this->GeneratorTarget->GetPreBuildCommands());
+ this->CheckCustomCommands(this->GeneratorTarget->GetPreLinkCommands());
+ this->CheckCustomCommands(this->GeneratorTarget->GetPostBuildCommands());
+}
+
+void cmTargetTraceDependencies::Trace()
+{
+ // Process one dependency at a time until the queue is empty.
+ while (!this->SourceQueue.empty()) {
+ // Get the next source from the queue.
+ cmSourceFile* sf = this->SourceQueue.front();
+ this->SourceQueue.pop();
+ this->CurrentEntry = &this->GeneratorTarget->SourceDepends[sf];
+
+ // 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);
+ }
+ }
+ this->FollowNames(objDeps);
}
- if(!archs)
- {
- archs = this->Target->GetProperty("OSX_ARCHITECTURES");
+
+ // Queue the source needed to generate this file, if any.
+ this->FollowName(sf->GetFullPath());
+
+ // Queue dependencies added programatically by commands.
+ this->FollowNames(sf->GetDepends());
+
+ // Queue custom command dependencies.
+ if (cmCustomCommand const* cc = sf->GetCustomCommand()) {
+ this->CheckCustomCommand(*cc);
}
- if(archs)
- {
+ }
+ this->CurrentEntry = CM_NULLPTR;
+
+ this->GeneratorTarget->AddTracedSources(this->NewSources);
+}
+
+void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
+{
+ if (this->SourcesQueued.insert(sf).second) {
+ this->SourceQueue.push(sf);
+
+ // Make sure this file is in the target at the end.
+ this->NewSources.push_back(sf->GetFullPath());
+ }
+}
+
+void cmTargetTraceDependencies::FollowName(std::string const& name)
+{
+ NameMapType::iterator i = this->NameMap.find(name);
+ if (i == this->NameMap.end()) {
+ // 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);
+ }
+ 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);
+ }
+}
+
+bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
+{
+ // Dependencies on targets (utilities) are supposed to be named by
+ // just the target name. However for compatibility we support
+ // naming the output file generated by the target (assuming there is
+ // no output-name property which old code would not have set). In
+ // that case the target name will be the file basename of the
+ // dependency.
+ std::string util = cmSystemTools::GetFilenameName(dep);
+ if (cmSystemTools::GetFilenameLastExtension(util) == ".exe") {
+ util = cmSystemTools::GetFilenameWithoutLastExtension(util);
+ }
+
+ // Check for a target with this name.
+ if (cmGeneratorTarget* t =
+ this->GeneratorTarget->GetLocalGenerator()->FindGeneratorTargetToUse(
+ util)) {
+ // 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 (t->GetType() >= cmStateEnums::EXECUTABLE &&
+ t->GetType() <= cmStateEnums::MODULE_LIBRARY) {
+ // This is really only for compatibility so we do not need to
+ // worry about configuration names and output names.
+ std::string tLocation = t->GetLocationForBuild();
+ tLocation = cmSystemTools::GetFilenamePath(tLocation);
+ std::string depLocation = cmSystemTools::GetFilenamePath(dep);
+ depLocation = cmSystemTools::CollapseFullPath(depLocation);
+ tLocation = cmSystemTools::CollapseFullPath(tLocation);
+ if (depLocation == tLocation) {
+ this->GeneratorTarget->Target->AddUtility(util);
+ return true;
+ }
+ }
+ } else {
+ // The original name of the dependency was not a full path. It
+ // must name a target, so add the target-level dependency.
+ this->GeneratorTarget->Target->AddUtility(util);
+ return true;
+ }
+ }
+
+ // The dependency does not name a target built in this project.
+ return false;
+}
+
+void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
+{
+ // Transform command names that reference targets built in this
+ // project to corresponding target-level dependencies.
+ cmGeneratorExpression ge(cc.GetBacktrace());
+
+ // 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();
+ // Check for a target with this name.
+ if (cmGeneratorTarget* t =
+ this->LocalGenerator->FindGeneratorTargetToUse(command)) {
+ if (t->GetType() == cmStateEnums::EXECUTABLE) {
+ // The command refers to an executable target built in
+ // this project. Add the target-level dependency to make
+ // sure the executable is up to date before this custom
+ // command possibly runs.
+ this->GeneratorTarget->Target->AddUtility(command);
+ }
+ }
+
+ // 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);
+ 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());
+ }
+
+ // 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);
+ }
+}
+
+void cmTargetTraceDependencies::FollowCommandDepends(
+ cmCustomCommand const& cc, const std::string& config,
+ std::set<std::string>& emitted)
+{
+ cmCustomCommandGenerator ccg(cc, config,
+ this->GeneratorTarget->LocalGenerator);
+
+ 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;
+ if (emitted.insert(dep).second) {
+ if (!this->IsUtility(dep)) {
+ // The dependency does not name a target and may be a file we
+ // know how to generate. Queue it.
+ this->FollowName(dep);
+ }
+ }
+ }
+}
+
+void cmTargetTraceDependencies::CheckCustomCommands(
+ const std::vector<cmCustomCommand>& commands)
+{
+ for (std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
+ cli != commands.end(); ++cli) {
+ this->CheckCustomCommand(*cli);
+ }
+}
+
+void cmGeneratorTarget::TraceDependencies()
+{
+ // CMake-generated targets have no dependencies to trace. Normally tracing
+ // would find nothing anyway, but when building CMake itself the "install"
+ // target command ends up referencing the "cmake" target but we do not
+ // really want the dependency because "install" depend on "all" anyway.
+ if (this->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ return;
+ }
+
+ // Use a helper object to trace the dependencies.
+ cmTargetTraceDependencies tracer(this);
+ tracer.Trace();
+}
+
+std::string cmGeneratorTarget::GetCompilePDBDirectory(
+ const std::string& config) const
+{
+ if (CompileInfo const* info = this->GetCompileInfo(config)) {
+ return info->CompilePdbDir;
+ }
+ return "";
+}
+
+void cmGeneratorTarget::GetAppleArchs(const std::string& config,
+ std::vector<std::string>& archVec) const
+{
+ const char* archs = CM_NULLPTR;
+ if (!config.empty()) {
+ std::string defVarName = "OSX_ARCHITECTURES_";
+ defVarName += cmSystemTools::UpperCase(config);
+ archs = this->GetProperty(defVarName);
+ }
+ if (!archs) {
+ archs = this->GetProperty("OSX_ARCHITECTURES");
+ }
+ if (archs) {
cmSystemTools::ExpandListArgument(std::string(archs), archVec);
+ }
+}
+
+//----------------------------------------------------------------------------
+std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable(
+ std::string const& var, std::string const& lang,
+ std::string const& config) const
+{
+ if (this->IsIPOEnabled(lang, config)) {
+ std::string varIPO = var + "_IPO";
+ if (this->Makefile->IsDefinitionSet(varIPO)) {
+ return varIPO;
}
+ }
+
+ return var;
}
//----------------------------------------------------------------------------
-const char* cmGeneratorTarget::GetCreateRuleVariable()
-{
- switch(this->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- return "_CREATE_STATIC_LIBRARY";
- case cmTarget::SHARED_LIBRARY:
- return "_CREATE_SHARED_LIBRARY";
- case cmTarget::MODULE_LIBRARY:
- return "_CREATE_SHARED_MODULE";
- case cmTarget::EXECUTABLE:
- return "_LINK_EXECUTABLE";
+std::string cmGeneratorTarget::GetCreateRuleVariable(
+ std::string const& lang, std::string const& config) const
+{
+ switch (this->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY: {
+ std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
+ return this->GetFeatureSpecificLinkRuleVariable(var, lang, config);
+ }
+ case cmStateEnums::SHARED_LIBRARY:
+ return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
+ case cmStateEnums::MODULE_LIBRARY:
+ return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
+ case cmStateEnums::EXECUTABLE:
+ return "CMAKE_" + lang + "_LINK_EXECUTABLE";
default:
break;
- }
+ }
return "";
}
+static 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;
+ 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())) {
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::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;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ break;
+ }
+ }
+ /* clang-format off */
+ e << "Imported target \"" << targetName << "\" includes "
+ "non-existent path\n \"" << *li << "\"\nin its "
+ "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
+ "* The path was deleted, renamed, or moved to another "
+ "location.\n"
+ "* An install or uninstall procedure did not complete "
+ "successfully.\n"
+ "* The installation package was faulty and references files it "
+ "does not provide.\n";
+ /* clang-format on */
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ return;
+ }
+
+ if (!cmSystemTools::FileIsFullPath(li->c_str())) {
+ std::ostringstream e;
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
+ if (!targetName.empty()) {
+ /* clang-format off */
+ e << "Target \"" << targetName << "\" contains relative "
+ "path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
+ " \"" << *li << "\"";
+ /* clang-format on */
+ } else {
+ switch (tgt->GetPolicyStatusCMP0021()) {
+ case cmPolicies::WARN: {
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n";
+ messageType = cmake::AUTHOR_WARNING;
+ } break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+ e << "Found relative path while evaluating include directories of "
+ "\""
+ << tgt->GetName() << "\":\n \"" << *li << "\"\n";
+ }
+ if (!noMessage) {
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ if (messageType == cmake::FATAL_ERROR) {
+ return;
+ }
+ }
+ }
+
+ if (!cmSystemTools::IsOff(li->c_str())) {
+ cmSystemTools::ConvertToUnixSlashes(*li);
+ }
+ std::string inc = *li;
+
+ if (uniqueIncludes.insert(inc).second) {
+ includes.push_back(inc);
+ if (debugIncludes) {
+ usedIncludes += " * " + inc + "\n";
+ }
+ }
+ }
+ if (!usedIncludes.empty()) {
+ tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::LOG, std::string("Used includes for target ") + tgt->GetName() +
+ ":\n" + usedIncludes,
+ (*it)->ge->GetBacktrace());
+ }
+ }
+}
-//----------------------------------------------------------------------------
std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
- const char *config)
+ const std::string& config, const std::string& lang) const
+{
+ std::vector<std::string> includes;
+ CM_UNORDERED_SET<std::string> uniqueIncludes;
+
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GetName(), "INCLUDE_DIRECTORIES", CM_NULLPTR, CM_NULLPTR);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugIncludes = !this->DebugIncludesDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "INCLUDE_DIRECTORIES") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugIncludesDone = true;
+ }
+
+ processIncludeDirectories(this, this->IncludeDirectoriesEntries, includes,
+ uniqueIncludes, &dagChecker, config, debugIncludes,
+ lang);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceIncludeDirectoriesEntries;
+ AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES",
+ linkInterfaceIncludeDirectoriesEntries);
+
+ 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);
+
+ static cmsys::RegularExpression frameworkCheck(
+ "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
+ if (!frameworkCheck.find(libDir)) {
+ continue;
+ }
+
+ libDir = frameworkCheck.match(1);
+
+ cmGeneratorExpression ge;
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
+ ge.Parse(libDir.c_str());
+ linkInterfaceIncludeDirectoriesEntries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(cge));
+ }
+ }
+
+ processIncludeDirectories(this, linkInterfaceIncludeDirectoriesEntries,
+ includes, uniqueIncludes, &dagChecker, config,
+ debugIncludes, lang);
+
+ cmDeleteAll(linkInterfaceIncludeDirectoriesEntries);
+
+ 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;
+
+ if (uniqueOptions.insert(opt).second) {
+ options.push_back(opt);
+ if (debugOptions) {
+ usedOptions += " * " + opt + "\n";
+ }
+ }
+ }
+ 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());
+ }
+ }
+}
+
+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;
+
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GetName(), "COMPILE_OPTIONS", CM_NULLPTR, CM_NULLPTR);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugOptions = !this->DebugCompileOptionsDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "COMPILE_OPTIONS") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugCompileOptionsDone = true;
+ }
+
+ processCompileOptions(this, this->CompileOptionsEntries, result,
+ uniqueOptions, &dagChecker, config, debugOptions,
+ language);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceCompileOptionsEntries;
+
+ AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS",
+ linkInterfaceCompileOptionsEntries);
+
+ processCompileOptions(this, linkInterfaceCompileOptionsEntries, result,
+ uniqueOptions, &dagChecker, config, debugOptions,
+ language);
+
+ cmDeleteAll(linkInterfaceCompileOptionsEntries);
+}
+
+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)
+{
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+ dagChecker, config, debugOptions, "features",
+ std::string());
+}
+
+void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
+ const std::string& config) const
+{
+ CM_UNORDERED_SET<std::string> uniqueFeatures;
+
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GetName(), "COMPILE_FEATURES", CM_NULLPTR, CM_NULLPTR);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugFeatures = !this->DebugCompileFeaturesDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "COMPILE_FEATURES") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugCompileFeaturesDone = true;
+ }
+
+ processCompileFeatures(this, this->CompileFeaturesEntries, result,
+ uniqueFeatures, &dagChecker, config, debugFeatures);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceCompileFeaturesEntries;
+ AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES",
+ linkInterfaceCompileFeaturesEntries);
+
+ processCompileFeatures(this, linkInterfaceCompileFeaturesEntries, result,
+ uniqueFeatures, &dagChecker, config, debugFeatures);
+
+ cmDeleteAll(linkInterfaceCompileFeaturesEntries);
+}
+
+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)
+{
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+ dagChecker, config, debugOptions,
+ "definitions", language);
+}
+
+void cmGeneratorTarget::GetCompileDefinitions(
+ std::vector<std::string>& list, const std::string& config,
+ const std::string& language) const
+{
+ CM_UNORDERED_SET<std::string> uniqueOptions;
+
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GetName(), "COMPILE_DEFINITIONS", CM_NULLPTR, CM_NULLPTR);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugDefines = !this->DebugCompileDefinitionsDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "COMPILE_DEFINITIONS") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugCompileDefinitionsDone = true;
+ }
+
+ processCompileDefinitions(this, this->CompileDefinitionsEntries, list,
+ uniqueOptions, &dagChecker, config, debugDefines,
+ language);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceCompileDefinitionsEntries;
+ AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS",
+ linkInterfaceCompileDefinitionsEntries);
+ if (!config.empty()) {
+ std::string configPropName =
+ "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
+ const char* configProp = this->GetProperty(configPropName);
+ 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());
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD: {
+ cmGeneratorExpression ge;
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
+ ge.Parse(configProp);
+ linkInterfaceCompileDefinitionsEntries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(cge));
+ } break;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
+ }
+ }
+ }
+
+ processCompileDefinitions(this, linkInterfaceCompileDefinitionsEntries, list,
+ uniqueOptions, &dagChecker, config, debugDefines,
+ language);
+
+ cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
+}
+
+void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
+{
+ if (this->IsImported()) {
+ return;
+ }
+ cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
+
+ // Get the names.
+ std::string name;
+ std::string soName;
+ std::string realName;
+ std::string impName;
+ std::string pdbName;
+ if (this->GetType() == cmStateEnums::EXECUTABLE) {
+ this->GetExecutableNames(name, realName, impName, pdbName, 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);
+ } else {
+ return;
+ }
+
+ // Get the directory.
+ std::string dir =
+ this->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact);
+
+ // Add each name.
+ std::string f;
+ if (!name.empty()) {
+ f = dir;
+ f += "/";
+ f += name;
+ gg->AddToManifest(f);
+ }
+ if (!soName.empty()) {
+ f = dir;
+ f += "/";
+ f += soName;
+ gg->AddToManifest(f);
+ }
+ if (!realName.empty()) {
+ f = dir;
+ f += "/";
+ f += realName;
+ gg->AddToManifest(f);
+ }
+ if (!pdbName.empty()) {
+ f = dir;
+ f += "/";
+ f += pdbName;
+ gg->AddToManifest(f);
+ }
+ if (!impName.empty()) {
+ f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
+ f += "/";
+ f += impName;
+ 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)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string cmGeneratorTarget::GetImportedLibName(
+ std::string const& config) const
+{
+ if (cmGeneratorTarget::ImportInfo const* info =
+ this->GetImportInfo(config)) {
+ return info->LibName;
+ }
+ return std::string();
+}
+
+std::string cmGeneratorTarget::GetFullPath(const std::string& config,
+ cmStateEnums::ArtifactType artifact,
+ bool realname) const
+{
+ if (this->IsImported()) {
+ return this->Target->ImportedGetFullPath(config, artifact);
+ }
+ return this->NormalGetFullPath(config, artifact, realname);
+}
+
+std::string cmGeneratorTarget::NormalGetFullPath(
+ const std::string& config, cmStateEnums::ArtifactType artifact,
+ bool realname) const
+{
+ std::string fpath = this->GetDirectory(config, artifact);
+ fpath += "/";
+ if (this->IsAppBundleOnApple()) {
+ fpath = this->BuildBundleDirectory(fpath, config, FullLevel);
+ fpath += "/";
+ }
+
+ // Add the full name of the target.
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ if (realname) {
+ fpath += this->NormalGetRealName(config);
+ } else {
+ fpath +=
+ this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
+ }
+ break;
+ case cmStateEnums::ImportLibraryArtifact:
+ fpath += this->GetFullName(config, cmStateEnums::ImportLibraryArtifact);
+ break;
+ }
+ return fpath;
+}
+
+std::string cmGeneratorTarget::NormalGetRealName(
+ const std::string& config) const
+{
+ // 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 = "NormalGetRealName called on imported target: ";
+ msg += this->GetName();
+ this->LocalGenerator->IssueMessage(cmake::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;
+ }
+ // 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
+{
+ // 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;
+ }
+
+ // Check for library version properties.
+ const char* version = this->GetProperty("VERSION");
+ const char* soversion = this->GetProperty("SOVERSION");
+ if (!this->HasSOName(config) ||
+ this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_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;
+ }
+ if (version && !soversion) {
+ // The soversion must be set if the library version is set. Use
+ // the library version as the soversion.
+ soversion = version;
+ }
+ if (!version && soversion) {
+ // Use the soversion as the library version.
+ version = soversion;
+ }
+
+ // Get the components of the library name.
+ std::string prefix;
+ std::string base;
+ std::string suffix;
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
+
+ // The library name.
+ name = prefix + base + suffix;
+
+ if (this->IsFrameworkOnApple()) {
+ realName = prefix;
+ if (!this->Makefile->PlatformIsAppleIos()) {
+ realName += "Versions/";
+ realName += this->GetFrameworkVersion();
+ realName += "/";
+ }
+ realName += base;
+ soName = realName;
+ } else {
+ // The library's soname.
+ this->ComputeVersionedName(soName, prefix, base, suffix, name, soversion);
+
+ // The library's real name on disk.
+ this->ComputeVersionedName(realName, prefix, base, suffix, name, version);
+ }
+
+ // The import library name.
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ impName =
+ this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
+ } else {
+ impName = "";
+ }
+
+ // The program database file name.
+ pdbName = this->GetPDBName(config);
+}
+
+void cmGeneratorTarget::GetExecutableNames(std::string& name,
+ std::string& realName,
+ std::string& impName,
+ std::string& pdbName,
+ const std::string& config) const
+{
+ // 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);
+ }
+
+// This versioning is supported only for executables and then only
+// when the platform supports symbolic links.
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const char* version = 0;
+#else
+ // Check for executable version properties.
+ const char* version = this->GetProperty("VERSION");
+ if (this->GetType() != cmStateEnums::EXECUTABLE ||
+ this->Makefile->IsOn("XCODE")) {
+ version = CM_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);
+
+ // The executable name.
+ name = prefix + base + suffix;
+
+// The executable's real name on disk.
+#if defined(__CYGWIN__)
+ realName = prefix + base;
+#else
+ realName = name;
+#endif
+ if (version) {
+ realName += "-";
+ realName += version;
+ }
+#if defined(__CYGWIN__)
+ realName += suffix;
+#endif
+
+ // The import library name.
+ impName =
+ this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
+
+ // The program database file name.
+ pdbName = this->GetPDBName(config);
+}
+
+std::string cmGeneratorTarget::GetFullNameInternal(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ std::string prefix;
+ std::string base;
+ std::string suffix;
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
+ return prefix + base + suffix;
+}
+
+const char* cmGeneratorTarget::ImportedGetLocation(
+ const std::string& config) const
+{
+ static std::string location;
+ assert(this->IsImported());
+ location = this->Target->ImportedGetFullPath(
+ config, cmStateEnums::RuntimeBinaryArtifact);
+ return location.c_str();
+}
+
+std::string cmGeneratorTarget::GetFullNameImported(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ return cmSystemTools::GetFilenameName(
+ this->Target->ImportedGetFullPath(config, artifact));
+}
+
+void cmGeneratorTarget::GetFullNameInternal(
+ const std::string& config, cmStateEnums::ArtifactType artifact,
+ std::string& outPrefix, std::string& outBase, std::string& outSuffix) const
+{
+ // Use just the target name 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) {
+ outPrefix = "";
+ outBase = this->GetName();
+ outSuffix = "";
+ return;
+ }
+
+ const bool isImportedLibraryArtifact =
+ (artifact == cmStateEnums::ImportLibraryArtifact);
+
+ // 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 = "";
+ return;
+ }
+
+ // 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 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);
+ }
+
+ // frameworks have directory prefix but no suffix
+ std::string fw_prefix;
+ if (this->IsFrameworkOnApple()) {
+ fw_prefix = this->GetFrameworkDirectory(config, ContentLevel);
+ fw_prefix += "/";
+ targetPrefix = fw_prefix.c_str();
+ targetSuffix = CM_NULLPTR;
+ }
+
+ if (this->IsCFBundleOnApple()) {
+ fw_prefix = this->GetCFBundleDirectory(config, FullLevel);
+ fw_prefix += "/";
+ targetPrefix = fw_prefix.c_str();
+ targetSuffix = CM_NULLPTR;
+ }
+
+ // Begin the final name with the prefix.
+ outPrefix = targetPrefix ? targetPrefix : "";
+
+ // Append the target name or property-specified name.
+ outBase += this->GetOutputName(config, artifact);
+
+ // Append the per-configuration postfix.
+ outBase += configPostfix ? configPostfix : "";
+
+ // Name shared libraries with their version number on some platforms.
+ if (const char* soversion = this->GetProperty("SOVERSION")) {
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ !isImportedLibraryArtifact &&
+ this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) {
+ outBase += "-";
+ outBase += soversion;
+ }
+ }
+
+ // Append the suffix.
+ outSuffix = targetSuffix ? targetSuffix : "";
+}
+
+std::string cmGeneratorTarget::GetLinkerLanguage(
+ const std::string& config) const
+{
+ return this->GetLinkClosure(config)->LinkerLanguage;
+}
+
+std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
+{
+ std::string prefix;
+ std::string base;
+ std::string suffix;
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
+
+ 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.push_back("PDB_NAME");
+
+ for (std::vector<std::string>::const_iterator i = props.begin();
+ i != props.end(); ++i) {
+ if (const char* outName = this->GetProperty(*i)) {
+ base = outName;
+ break;
+ }
+ }
+ return prefix + base + ".pdb";
+}
+
+std::string cmGeneratorTarget::GetObjectDirectory(
+ std::string const& config) const
+{
+ std::string obj_dir =
+ this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config);
+#if defined(__APPLE__)
+ // find and replace $(PROJECT_NAME) xcode placeholder
+ const std::string projectName = this->LocalGenerator->GetProjectName();
+ cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
+#endif
+ return obj_dir;
+}
+
+void cmGeneratorTarget::GetTargetObjectNames(
+ std::string const& config, std::vector<std::string>& objects) const
+{
+ std::vector<cmSourceFile const*> objectSources;
+ 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];
+ }
+
+ this->LocalGenerator->ComputeObjectFilenames(mapping, this);
+
+ for (std::vector<cmSourceFile const*>::const_iterator it =
+ objectSources.begin();
+ it != objectSources.end(); ++it) {
+ // 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());
+ objects.push_back(map_it->second);
+ }
+}
+
+bool cmGeneratorTarget::StrictTargetComparison::operator()(
+ cmGeneratorTarget const* t1, cmGeneratorTarget const* t2) const
+{
+ int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
+ if (nameResult == 0) {
+ return strcmp(t1->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+ t2->GetLocalGenerator()->GetCurrentBinaryDirectory()) < 0;
+ }
+ return nameResult < 0;
+}
+
+struct cmGeneratorTarget::SourceFileFlags
+cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
+{
+ struct SourceFileFlags flags;
+ this->ConstructSourceFileFlags();
+ std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
+ this->SourceFlagsMap.find(sf);
+ if (si != this->SourceFlagsMap.end()) {
+ flags = si->second;
+ } else {
+ // Handle the MACOSX_PACKAGE_LOCATION property on source files that
+ // were not listed in one of the other lists.
+ if (const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) {
+ flags.MacFolder = location;
+ const bool stripResources =
+ this->GlobalGenerator->ShouldStripResourcePath(this->Makefile);
+ if (strcmp(location, "Resources") == 0) {
+ flags.Type = cmGeneratorTarget::SourceFileTypeResource;
+ if (stripResources) {
+ flags.MacFolder = "";
+ }
+ } else if (cmSystemTools::StringStartsWith(location, "Resources/")) {
+ flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource;
+ if (stripResources) {
+ flags.MacFolder += strlen("Resources/");
+ }
+ } else {
+ flags.Type = cmGeneratorTarget::SourceFileTypeMacContent;
+ }
+ }
+ }
+ return flags;
+}
+
+void cmGeneratorTarget::ConstructSourceFileFlags() const
+{
+ if (this->SourceFileFlagsConstructed) {
+ return;
+ }
+ this->SourceFileFlagsConstructed = true;
+
+ // 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)) {
+ SourceFileFlags& flags = this->SourceFlagsMap[sf];
+ flags.MacFolder = "Headers";
+ flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader;
+ }
+ }
+ }
+
+ // 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)) {
+ SourceFileFlags& flags = this->SourceFlagsMap[sf];
+ flags.MacFolder = "PrivateHeaders";
+ flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader;
+ }
+ }
+ }
+
+ // 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)) {
+ SourceFileFlags& flags = this->SourceFlagsMap[sf];
+ flags.MacFolder = "";
+ if (!this->GlobalGenerator->ShouldStripResourcePath(this->Makefile)) {
+ flags.MacFolder = "Resources";
+ }
+ flags.Type = cmGeneratorTarget::SourceFileTypeResource;
+ }
+ }
+ }
+}
+
+const cmGeneratorTarget::CompatibleInterfacesBase&
+cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
+{
+ cmGeneratorTarget::CompatibleInterfaces& compat =
+ this->CompatibleInterfacesMap[config];
+ if (!compat.Done) {
+ compat.Done = true;
+ compat.PropsBool.insert("POSITION_INDEPENDENT_CODE");
+ 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) {
+#define CM_READ_COMPATIBLE_INTERFACE(X, x) \
+ if (const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
+ std::vector<std::string> props; \
+ cmSystemTools::ExpandListArgument(prop, props); \
+ compat.Props##x.insert(props.begin(), props.end()); \
+ }
+ CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool)
+ CM_READ_COMPATIBLE_INTERFACE(STRING, String)
+ CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin)
+ CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax)
+#undef CM_READ_COMPATIBLE_INTERFACE
+ }
+ }
+ return compat;
+}
+
+bool cmGeneratorTarget::IsLinkInterfaceDependentBoolProperty(
+ const std::string& p, const std::string& config) const
+{
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return false;
+ }
+ return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0;
+}
+
+bool cmGeneratorTarget::IsLinkInterfaceDependentStringProperty(
+ const std::string& p, const std::string& config) const
+{
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return false;
+ }
+ return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0;
+}
+
+bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMinProperty(
+ const std::string& p, const std::string& config) const
+{
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return false;
+ }
+ return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0;
+}
+
+bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMaxProperty(
+ const std::string& p, const std::string& config) const
+{
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return false;
+ }
+ return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0;
+}
+
+enum CompatibleType
+{
+ BoolType,
+ StringType,
+ NumberMinType,
+ NumberMaxType
+};
+
+template <typename PropertyType>
+PropertyType getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
+ const std::string& prop,
+ const std::string& config,
+ CompatibleType, PropertyType*);
+
+template <>
+bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
+ const std::string& prop,
+ const std::string& config,
+ CompatibleType /*unused*/,
+ bool* /*unused*/)
+{
+ return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
+}
+
+template <>
+const char* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
+ const std::string& prop,
+ const std::string& config,
+ CompatibleType t,
+ const char** /*unused*/)
+{
+ switch (t) {
+ case BoolType:
+ assert(false &&
+ "String compatibility check function called for boolean");
+ return CM_NULLPTR;
+ case StringType:
+ return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
+ case NumberMinType:
+ return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config);
+ case NumberMaxType:
+ return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
+ }
+ assert(false && "Unreachable!");
+ return CM_NULLPTR;
+}
+
+template <typename PropertyType>
+void checkPropertyConsistency(cmGeneratorTarget const* depender,
+ cmGeneratorTarget const* dependee,
+ const std::string& propName,
+ std::set<std::string>& emitted,
+ const std::string& config, CompatibleType t,
+ PropertyType* /*unused*/)
+{
+ const char* prop = dependee->GetProperty(propName);
+ if (!prop) {
+ return;
+ }
+
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(prop, props);
+ std::string pdir = cmSystemTools::GetCMakeRoot();
+ pdir += "/Help/prop_tgt/";
+
+ for (std::vector<std::string>::iterator pi = props.begin();
+ pi != props.end(); ++pi) {
+ std::string pname = cmSystemTools::HelpFileName(*pi);
+ std::string pfile = pdir + pname + ".rst";
+ if (cmSystemTools::FileExists(pfile.c_str(), true)) {
+ std::ostringstream e;
+ e << "Target \"" << dependee->GetName() << "\" has property \"" << *pi
+ << "\" 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());
+ return;
+ }
+ if (emitted.insert(*pi).second) {
+ getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, t,
+ CM_NULLPTR);
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ return;
+ }
+ }
+ }
+}
+
+static 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(),
+ std::inserter(intersect, intersect.begin()));
+ if (!intersect.empty()) {
+ return *intersect.begin();
+ }
+ 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 result;
+ result = intersect(s1, s2);
+ if (!result.empty()) {
+ return result;
+ }
+ result = intersect(s1, s3);
+ if (!result.empty()) {
+ return result;
+ }
+ 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 result;
+ result = intersect(s1, s2);
+ if (!result.empty()) {
+ return result;
+ }
+ result = intersect(s1, s3);
+ if (!result.empty()) {
+ return result;
+ }
+ result = intersect(s1, s4);
+ if (!result.empty()) {
+ return result;
+ }
+ return intersect(s2, s3, s4);
+}
+
+void cmGeneratorTarget::CheckPropertyCompatibility(
+ cmComputeLinkInformation* info, const std::string& config) const
+{
+ const cmComputeLinkInformation::ItemVector& deps = info->GetItems();
+
+ std::set<std::string> emittedBools;
+ static std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
+ std::set<std::string> emittedStrings;
+ static std::string strString = "COMPATIBLE_INTERFACE_STRING";
+ std::set<std::string> emittedMinNumbers;
+ static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN";
+ std::set<std::string> emittedMaxNumbers;
+ static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX";
+
+ for (cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin();
+ li != deps.end(); ++li) {
+ if (!li->Target) {
+ continue;
+ }
+
+ checkPropertyConsistency<bool>(this, li->Target, strBool, emittedBools,
+ config, BoolType, CM_NULLPTR);
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ return;
+ }
+ checkPropertyConsistency<const char*>(this, li->Target, strString,
+ emittedStrings, config, StringType,
+ CM_NULLPTR);
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ return;
+ }
+ checkPropertyConsistency<const char*>(this, li->Target, strNumMin,
+ emittedMinNumbers, config,
+ NumberMinType, CM_NULLPTR);
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ return;
+ }
+ checkPropertyConsistency<const char*>(this, li->Target, strNumMax,
+ emittedMaxNumbers, config,
+ NumberMaxType, CM_NULLPTR);
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ return;
+ }
+ }
+
+ std::string prop = intersect(emittedBools, emittedStrings, emittedMinNumbers,
+ emittedMaxNumbers);
+
+ 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);
+ if (i != emittedBools.end()) {
+ props.push_back(strBool);
+ }
+ i = emittedStrings.find(prop);
+ if (i != emittedStrings.end()) {
+ props.push_back(strString);
+ }
+ i = emittedMinNumbers.find(prop);
+ if (i != emittedMinNumbers.end()) {
+ props.push_back(strNumMin);
+ }
+ i = emittedMaxNumbers.find(prop);
+ if (i != emittedMaxNumbers.end()) {
+ props.push_back(strNumMax);
+ }
+ std::sort(props.begin(), props.end());
+
+ std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", ");
+ propsString += " and the " + props.back();
+
+ std::ostringstream e;
+ e << "Property \"" << prop << "\" appears in both the " << propsString
+ << " property in the dependencies of target \"" << this->GetName()
+ << "\". This is not allowed. A property may only require compatibility "
+ "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());
+ }
+}
+
+std::string compatibilityType(CompatibleType t)
+{
+ switch (t) {
+ case BoolType:
+ return "Boolean compatibility";
+ case StringType:
+ return "String compatibility";
+ case NumberMaxType:
+ return "Numeric maximum compatibility";
+ case NumberMinType:
+ return "Numeric minimum compatibility";
+ }
+ assert(false && "Unreachable!");
+ return "";
+}
+
+std::string compatibilityAgree(CompatibleType t, bool dominant)
+{
+ switch (t) {
+ case BoolType:
+ case StringType:
+ return dominant ? "(Disagree)\n" : "(Agree)\n";
+ case NumberMaxType:
+ case NumberMinType:
+ return dominant ? "(Dominant)\n" : "(Ignored)\n";
+ }
+ assert(false && "Unreachable!");
+ return "";
+}
+
+template <typename PropertyType>
+PropertyType getTypedProperty(cmGeneratorTarget const* tgt,
+ const std::string& prop);
+
+template <>
+bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
+ const std::string& prop)
+{
+ return tgt->GetPropertyAsBool(prop);
+}
+
+template <>
+const char* getTypedProperty<const char*>(cmGeneratorTarget const* tgt,
+ const std::string& prop)
+{
+ return tgt->GetProperty(prop);
+}
+
+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 <typename PropertyType>
+PropertyType impliedValue(PropertyType);
+template <>
+bool impliedValue<bool>(bool /*unused*/)
+{
+ return false;
+}
+template <>
+const char* impliedValue<const char*>(const char* /*unused*/)
+{
+ return "";
+}
+
+template <typename PropertyType>
+std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
+ PropertyType rhs,
+ CompatibleType t);
+
+template <>
+std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
+ CompatibleType /*unused*/)
+{
+ return std::make_pair(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);
+}
+
+std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
+ const char* rhs,
+ CompatibleType t)
+{
+ 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);
+ }
+
+ long rnum = strtol(rhs, &pEnd, 0);
+ if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
+ return std::pair<bool, const char*>(false, null_ptr);
+ }
+
+ if (t == NumberMaxType) {
+ return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs);
+ }
+ return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs);
+}
+
+template <>
+std::pair<bool, const char*> consistentProperty(const char* lhs,
+ const char* rhs,
+ CompatibleType t)
+{
+ if (!lhs && !rhs) {
+ return std::make_pair(true, lhs);
+ }
+ if (!lhs) {
+ return std::make_pair(true, rhs);
+ }
+ if (!rhs) {
+ return std::make_pair(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 StringType:
+ return consistentStringProperty(lhs, rhs);
+ case NumberMinType:
+ case NumberMaxType:
+ return consistentNumberProperty(lhs, rhs, t);
+ }
+ assert(false && "Unreachable!");
+ return std::pair<bool, const char*>(false, null_ptr);
+}
+
+template <typename PropertyType>
+PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
+ const std::string& p,
+ const std::string& config,
+ const char* defaultValue,
+ CompatibleType t,
+ 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 impliedByUse = tgt->IsNullImpliedByLinkLibraries(p);
+ assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet));
+
+ std::vector<cmGeneratorTarget const*> const& deps =
+ tgt->GetLinkImplementationClosure(config);
+
+ if (deps.empty()) {
+ return propContent;
+ }
+ bool propInitialized = explicitlySet;
+
+ std::string report = " * Target \"";
+ report += tgt->GetName();
+ if (explicitlySet) {
+ report += "\" has property content \"";
+ report += valueAsString<PropertyType>(propContent);
+ report += "\"\n";
+ } else if (impliedByUse) {
+ report += "\" property is implied by use.\n";
+ } else {
+ report += "\" property not set.\n";
+ }
+
+ std::string interfaceProperty = "INTERFACE_" + p;
+ for (std::vector<cmGeneratorTarget const*>::const_iterator li = deps.begin();
+ li != deps.end(); ++li) {
+ // 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);
+
+ std::string reportEntry;
+ if (ifaceIsSet) {
+ reportEntry += " * Target \"";
+ reportEntry += theTarget->GetName();
+ reportEntry += "\" property value \"";
+ reportEntry += valueAsString<PropertyType>(ifacePropContent);
+ reportEntry += "\" ";
+ }
+
+ if (explicitlySet) {
+ if (ifaceIsSet) {
+ std::pair<bool, PropertyType> consistent =
+ consistentProperty(propContent, ifacePropContent, t);
+ report += reportEntry;
+ report += compatibilityAgree(t, propContent != consistent.second);
+ if (!consistent.first) {
+ std::ostringstream e;
+ e << "Property " << p << " on target \"" << tgt->GetName()
+ << "\" does\nnot match the "
+ "INTERFACE_"
+ << p << " property requirement\nof "
+ "dependency \""
+ << theTarget->GetName() << "\".\n";
+ cmSystemTools::Error(e.str().c_str());
+ break;
+ }
+ propContent = consistent.second;
+ continue;
+ }
+ // Explicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ if (impliedByUse) {
+ propContent = impliedValue<PropertyType>(propContent);
+
+ if (ifaceIsSet) {
+ std::pair<bool, PropertyType> consistent =
+ consistentProperty(propContent, ifacePropContent, t);
+ report += reportEntry;
+ report += compatibilityAgree(t, propContent != consistent.second);
+ if (!consistent.first) {
+ std::ostringstream e;
+ e << "Property " << p << " on target \"" << tgt->GetName()
+ << "\" is\nimplied to be " << defaultValue
+ << " because it was used to determine the link libraries\n"
+ "already. The INTERFACE_"
+ << p << " property on\ndependency \"" << theTarget->GetName()
+ << "\" is in conflict.\n";
+ cmSystemTools::Error(e.str().c_str());
+ break;
+ }
+ propContent = consistent.second;
+ continue;
+ }
+ // Implicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ if (ifaceIsSet) {
+ if (propInitialized) {
+ std::pair<bool, PropertyType> consistent =
+ consistentProperty(propContent, ifacePropContent, t);
+ report += reportEntry;
+ report += compatibilityAgree(t, propContent != consistent.second);
+ if (!consistent.first) {
+ std::ostringstream e;
+ 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());
+ break;
+ }
+ propContent = consistent.second;
+ continue;
+ }
+ report += reportEntry + "(Interface set)\n";
+ propContent = ifacePropContent;
+ propInitialized = true;
+ } else {
+ // Not set. Nothing to agree on.
+ continue;
+ }
+ }
+
+ tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent),
+ report, compatibilityType(t));
+ return propContent;
+}
+
+bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
+ const std::string& p, const std::string& config) const
+{
+ return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
+ BoolType, CM_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);
+}
+
+const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty(
+ const std::string& p, const std::string& config) const
+{
+ return checkInterfacePropertyCompatibility<const char*>(
+ this, p, config, "empty", NumberMinType, CM_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);
+}
+
+cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
+ const std::string& config) const
+{
+ // Lookup any existing information for this configuration.
+ std::string key(cmSystemTools::UpperCase(config));
+ cmTargetLinkInformationMap::iterator 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;
+ }
+
+ // Store the information for this configuration.
+ cmTargetLinkInformationMap::value_type entry(key, info);
+ i = this->LinkInformation.insert(entry).first;
+
+ if (info) {
+ this->CheckPropertyCompatibility(info, config);
+ }
+ }
+ return i->second;
+}
+
+void cmGeneratorTarget::GetTargetVersion(int& major, int& minor) const
+{
+ int patch;
+ this->GetTargetVersion(false, major, minor, patch);
+}
+
+void cmGeneratorTarget::GetTargetVersion(bool soversion, int& major,
+ int& minor, int& patch) const
+{
+ // Set the default values.
+ major = 0;
+ minor = 0;
+ patch = 0;
+
+ assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
+
+ // Look for a VERSION or SOVERSION property.
+ const char* prop = soversion ? "SOVERSION" : "VERSION";
+ if (const char* version = this->GetProperty(prop)) {
+ // Try to parse the version number and store the results that were
+ // successfully parsed.
+ int parsed_major;
+ int parsed_minor;
+ int parsed_patch;
+ switch (sscanf(version, "%d.%d.%d", &parsed_major, &parsed_minor,
+ &parsed_patch)) {
+ case 3:
+ patch = parsed_patch;
+ CM_FALLTHROUGH;
+ case 2:
+ minor = parsed_minor;
+ CM_FALLTHROUGH;
+ case 1:
+ major = parsed_major;
+ CM_FALLTHROUGH;
+ default:
+ break;
+ }
+ }
+}
+
+std::string cmGeneratorTarget::GetFortranModuleDirectory(
+ std::string const& working_dir) const
+{
+ if (!this->FortranModuleDirectoryCreated) {
+ this->FortranModuleDirectory =
+ this->CreateFortranModuleDirectory(working_dir);
+ this->FortranModuleDirectoryCreated = true;
+ }
+
+ return this->FortranModuleDirectory;
+}
+
+std::string cmGeneratorTarget::CreateFortranModuleDirectory(
+ std::string const& working_dir) const
+{
+ std::string mod_dir;
+ std::string target_mod_dir;
+ if (const char* prop = this->GetProperty("Fortran_MODULE_DIRECTORY")) {
+ target_mod_dir = prop;
+ } else {
+ std::string const& default_mod_dir =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
+ if (default_mod_dir != working_dir) {
+ target_mod_dir = default_mod_dir;
+ }
+ }
+ const char* moddir_flag =
+ this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
+ if (!target_mod_dir.empty() && moddir_flag) {
+ // Compute the full path to the module directory.
+ if (cmSystemTools::FileIsFullPath(target_mod_dir)) {
+ // Already a full path.
+ 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;
+ }
+
+ // Make sure the module output directory exists.
+ cmSystemTools::MakeDirectory(mod_dir);
+ }
+ return mod_dir;
+}
+
+std::string cmGeneratorTarget::GetFrameworkVersion() const
+{
+ assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
+
+ if (const char* fversion = this->GetProperty("FRAMEWORK_VERSION")) {
+ return fversion;
+ }
+ if (const char* tversion = this->GetProperty("VERSION")) {
+ return tversion;
+ }
+ return "A";
+}
+
+void cmGeneratorTarget::ComputeVersionedName(std::string& vName,
+ std::string const& prefix,
+ std::string const& base,
+ std::string const& suffix,
+ std::string const& name,
+ const char* version) const
+{
+ vName = this->Makefile->IsOn("APPLE") ? (prefix + base) : name;
+ if (version) {
+ vName += ".";
+ vName += version;
+ }
+ vName += this->Makefile->IsOn("APPLE") ? suffix : std::string();
+}
+
+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;
+}
+
+void cmGeneratorTarget::ReportPropertyOrigin(
+ const std::string& p, const std::string& result, const std::string& report,
+ const std::string& compatibilityType) const
+{
+ std::vector<std::string> debugProperties;
+ const char* debugProp = this->Target->GetMakefile()->GetDefinition(
+ "CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] &&
+ std::find(debugProperties.begin(), debugProperties.end(), p) !=
+ debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugCompatiblePropertiesDone[p] = true;
+ }
+ if (!debugOrigin) {
+ 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;
+
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(cmake::LOG, areport);
+}
+
+void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
+ 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);
+ if (name == this->GetName() || name.empty()) {
+ continue;
+ }
+ items.push_back(cmLinkItem(name, this->FindTargetToLink(name)));
+ }
+}
+
+void cmGeneratorTarget::ExpandLinkItems(
+ std::string const& prop, std::string const& value, std::string const& config,
+ cmGeneratorTarget const* headTarget, bool usage_requirements_only,
+ std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
+{
+ cmGeneratorExpression ge;
+ cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, CM_NULLPTR,
+ CM_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);
+ hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
+}
+
+cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
+ const std::string& config, cmGeneratorTarget const* head) const
+{
+ // Imported targets have their own link interface.
+ if (this->IsImported()) {
+ return this->GetImportLinkInterface(config, head, false);
+ }
+
+ // Link interfaces are not supported for executables that do not
+ // export symbols.
+ if (this->GetType() == cmStateEnums::EXECUTABLE &&
+ !this->IsExecutableWithExports()) {
+ return CM_NULLPTR;
+ }
+
+ // Lookup any existing link interface for this configuration.
+ cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config);
+
+ // If the link interface does not depend on the head target
+ // then return the one we computed first.
+ if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
+ return &hm.begin()->second;
+ }
+
+ cmOptionalLinkInterface& iface = hm[head];
+ if (!iface.LibrariesDone) {
+ iface.LibrariesDone = true;
+ this->ComputeLinkInterfaceLibraries(config, iface, head, false);
+ }
+ if (!iface.AllDone) {
+ iface.AllDone = true;
+ if (iface.Exists) {
+ this->ComputeLinkInterface(config, iface, head);
+ }
+ }
+
+ return iface.Exists ? &iface : CM_NULLPTR;
+}
+
+void cmGeneratorTarget::ComputeLinkInterface(
+ const std::string& config, cmOptionalLinkInterface& iface,
+ cmGeneratorTarget const* headTarget) const
+{
+ if (iface.ExplicitLibraries) {
+ 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);
+ }
+ 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) {
+ // This is a runtime dependency on another shared library.
+ if (li->Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ iface.SharedDeps.push_back(*li);
+ }
+ } else {
+ // TODO: Recognize shared library file names. Perhaps this
+ // should be moved to cmComputeLinkInformation, but that creates
+ // a chicken-and-egg problem since this list is needed for its
+ // construction.
+ }
+ }
+ }
+ }
+ }
+ } else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN ||
+ this->GetPolicyStatusCMP0022() == cmPolicies::OLD) {
+ // The link implementation is the default link interface.
+ cmLinkImplementationLibraries const* impl =
+ this->GetLinkImplementationLibrariesInternal(config, headTarget);
+ iface.ImplementationIsInterface = true;
+ iface.WrongConfigLibraries = impl->WrongConfigLibraries;
+ }
+
+ if (this->LinkLanguagePropagatesToDependents()) {
+ // Targets using this archive need its language runtime libraries.
+ if (cmLinkImplementation const* impl =
+ this->GetLinkImplementation(config)) {
+ iface.Languages = impl->Languages;
+ }
+ }
+
+ if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ // Construct the property name suffix for this configuration.
+ std::string suffix = "_";
+ if (!config.empty()) {
+ suffix += cmSystemTools::UpperCase(config);
+ } else {
+ suffix += "NOCONFIG";
+ }
+
+ // How many repetitions are needed if this library has cyclic
+ // dependencies?
+ std::string propName = "LINK_INTERFACE_MULTIPLICITY";
+ propName += suffix;
+ if (const char* config_reps = this->GetProperty(propName)) {
+ sscanf(config_reps, "%u", &iface.Multiplicity);
+ } else if (const char* reps =
+ this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) {
+ sscanf(reps, "%u", &iface.Multiplicity);
+ }
+ }
+}
+
+const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
+ const std::string& config, cmGeneratorTarget const* head,
+ bool usage_requirements_only) const
+{
+ // Imported targets have their own link interface.
+ if (this->IsImported()) {
+ return this->GetImportLinkInterface(config, head, usage_requirements_only);
+ }
+
+ // Link interfaces are not supported for executables that do not
+ // export symbols.
+ if (this->GetType() == cmStateEnums::EXECUTABLE &&
+ !this->IsExecutableWithExports()) {
+ return CM_NULLPTR;
+ }
+
+ // Lookup any existing link interface for this configuration.
+ std::string CONFIG = cmSystemTools::UpperCase(config);
+ cmHeadToLinkInterfaceMap& hm =
+ (usage_requirements_only
+ ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
+ : this->GetHeadToLinkInterfaceMap(config));
+
+ // If the link interface does not depend on the head target
+ // then return the one we computed first.
+ if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
+ return &hm.begin()->second;
+ }
+
+ cmOptionalLinkInterface& iface = hm[head];
+ if (!iface.LibrariesDone) {
+ iface.LibrariesDone = true;
+ this->ComputeLinkInterfaceLibraries(config, iface, head,
+ usage_requirements_only);
+ }
+
+ return iface.Exists ? &iface : CM_NULLPTR;
+}
+
+std::string cmGeneratorTarget::GetDirectory(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ if (this->IsImported()) {
+ // Return the directory from which the target is imported.
+ return cmSystemTools::GetFilenamePath(
+ this->Target->ImportedGetFullPath(config, artifact));
+ }
+ if (OutputInfo const* info = this->GetOutputInfo(config)) {
+ // Return the directory in which the target will be built.
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ return info->OutDir;
+ case cmStateEnums::ImportLibraryArtifact:
+ return info->ImpDir;
+ }
+ }
+ return "";
+}
+
+bool cmGeneratorTarget::UsesDefaultOutputDir(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ std::string dir;
+ return this->ComputeOutputDir(config, artifact, dir);
+}
+
+cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
+ const std::string& config) const
+{
+ // There is no output information for imported targets.
+ if (this->IsImported()) {
+ return CM_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;
+ }
+
+ // Lookup/compute/cache the output information for this configuration.
+ std::string config_upper;
+ if (!config.empty()) {
+ config_upper = cmSystemTools::UpperCase(config);
+ }
+ OutputInfoMapType::iterator i = this->OutputInfoMap.find(config_upper);
+ if (i == this->OutputInfoMap.end()) {
+ // Add empty info in map to detect potential recursion.
+ OutputInfo info;
+ OutputInfoMapType::value_type entry(config_upper, info);
+ i = this->OutputInfoMap.insert(entry).first;
+
+ // Compute output directories.
+ this->ComputeOutputDir(config, cmStateEnums::RuntimeBinaryArtifact,
+ info.OutDir);
+ this->ComputeOutputDir(config, cmStateEnums::ImportLibraryArtifact,
+ info.ImpDir);
+ if (!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) {
+ info.PdbDir = info.OutDir;
+ }
+
+ // Now update the previously-prepared map entry.
+ i->second = info;
+ } 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,
+ "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
+ this->GetBacktrace());
+ return CM_NULLPTR;
+ }
+ return &i->second;
+}
+
+bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
+ cmStateEnums::ArtifactType artifact,
+ std::string& out) const
+{
+ bool usesDefaultOutputDir = false;
+ std::string conf = 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;
+ std::string propertyNameStr = targetTypeName;
+ if (!propertyNameStr.empty()) {
+ propertyNameStr += "_OUTPUT_DIRECTORY";
+ propertyName = propertyNameStr.c_str();
+ }
+
+ // Check for a per-configuration output directory target property.
+ std::string configUpper = cmSystemTools::UpperCase(conf);
+ const char* configProp = CM_NULLPTR;
+ std::string configPropStr = targetTypeName;
+ if (!configPropStr.empty()) {
+ configPropStr += "_OUTPUT_DIRECTORY_";
+ configPropStr += configUpper;
+ configProp = configPropStr.c_str();
+ }
+
+ // 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);
+
+ // Skip per-configuration subdirectory.
+ conf = "";
+ } 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);
+
+ // Skip per-configuration subdirectory if the value contained a
+ // generator expression.
+ if (out != outdir) {
+ conf = "";
+ }
+ } else if (this->GetType() == cmStateEnums::EXECUTABLE) {
+ // Lookup the output path for executables.
+ out = this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ } else if (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ // Lookup the output path for libraries.
+ out = this->Makefile->GetSafeDefinition("LIBRARY_OUTPUT_PATH");
+ }
+ if (out.empty()) {
+ // Default to the current output directory.
+ usesDefaultOutputDir = true;
+ out = ".";
+ }
+
+ // Convert the output path to a full path in case it is
+ // specified as a relative path. Treat a relative path as
+ // relative to the current output directory for this makefile.
+ out = (cmSystemTools::CollapseFullPath(
+ out, this->LocalGenerator->GetCurrentBinaryDirectory()));
+
+ // The generator may add the configuration's subdirectory.
+ if (!conf.empty()) {
+ bool useEPN =
+ this->GlobalGenerator->UseEffectivePlatformName(this->Makefile);
+ std::string suffix =
+ usesDefaultOutputDir && useEPN ? "${EFFECTIVE_PLATFORM_NAME}" : "";
+ this->LocalGenerator->GetGlobalGenerator()->AppendDirectoryForConfig(
+ "/", conf, suffix, out);
+ }
+
+ return usesDefaultOutputDir;
+}
+
+bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
+ const std::string& config,
+ std::string& out) const
+{
+ // Look for a target property defining the target output directory
+ // based on the target type.
+ const char* propertyName = CM_NULLPTR;
+ std::string propertyNameStr = kind;
+ if (!propertyNameStr.empty()) {
+ propertyNameStr += "_OUTPUT_DIRECTORY";
+ propertyName = propertyNameStr.c_str();
+ }
+ std::string conf = config;
+
+ // Check for a per-configuration output directory target property.
+ std::string configUpper = cmSystemTools::UpperCase(conf);
+ const char* configProp = CM_NULLPTR;
+ std::string configPropStr = kind;
+ if (!configPropStr.empty()) {
+ configPropStr += "_OUTPUT_DIRECTORY_";
+ configPropStr += configUpper;
+ configProp = configPropStr.c_str();
+ }
+
+ // Select an output directory.
+ if (const char* config_outdir = this->GetProperty(configProp)) {
+ // Use the user-specified per-configuration output directory.
+ out = config_outdir;
+
+ // Skip per-configuration subdirectory.
+ conf = "";
+ } else if (const char* outdir = this->GetProperty(propertyName)) {
+ // Use the user-specified output directory.
+ out = outdir;
+ }
+ if (out.empty()) {
+ return false;
+ }
+
+ // Convert the output path to a full path in case it is
+ // specified as a relative path. Treat a relative path as
+ // relative to the current output directory for this makefile.
+ out = (cmSystemTools::CollapseFullPath(
+ out, this->LocalGenerator->GetCurrentBinaryDirectory()));
+
+ // The generator may add the configuration's subdirectory.
+ if (!conf.empty()) {
+ this->LocalGenerator->GetGlobalGenerator()->AppendDirectoryForConfig(
+ "/", conf, "", out);
+ }
+ return true;
+}
+
+bool cmGeneratorTarget::HaveInstallTreeRPATH() const
+{
+ const char* install_rpath = this->GetProperty("INSTALL_RPATH");
+ return (install_rpath && *install_rpath) &&
+ !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
+}
+
+void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
+ const std::string& config, cmOptionalLinkInterface& iface,
+ cmGeneratorTarget const* headTarget, bool usage_requirements_only) const
+{
+ // Construct the property name suffix for this configuration.
+ std::string suffix = "_";
+ if (!config.empty()) {
+ suffix += cmSystemTools::UpperCase(config);
+ } else {
+ suffix += "NOCONFIG";
+ }
+
+ // An explicit list of interface libraries may be set for shared
+ // libraries and executables that export symbols.
+ const char* explicitLibraries = CM_NULLPTR;
+ std::string linkIfaceProp;
+ if (this->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
+ this->GetPolicyStatusCMP0022() != cmPolicies::WARN) {
+ // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
+ linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+ explicitLibraries = this->GetProperty(linkIfaceProp);
+ } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports()) {
+ // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
+ // shared lib or executable.
+
+ // Lookup the per-configuration property.
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+ linkIfaceProp += suffix;
+ explicitLibraries = this->GetProperty(linkIfaceProp);
+
+ // If not set, try the generic property.
+ if (!explicitLibraries) {
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+ explicitLibraries = this->GetProperty(linkIfaceProp);
+ }
+ }
+
+ if (explicitLibraries &&
+ this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
+ !this->PolicyWarnedCMP0022) {
+ // Compare the explicitly set old link interface properties to the
+ // preferred new link interface property one and warn if different.
+ const char* newExplicitLibraries =
+ this->GetProperty("INTERFACE_LINK_LIBRARIES");
+ if (newExplicitLibraries &&
+ strcmp(newExplicitLibraries, explicitLibraries) != 0) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
+ "Target \"" << this->GetName() << "\" has an "
+ "INTERFACE_LINK_LIBRARIES property which differs from its " <<
+ linkIfaceProp << " properties."
+ "\n"
+ "INTERFACE_LINK_LIBRARIES:\n"
+ " " << newExplicitLibraries << "\n" <<
+ linkIfaceProp << ":\n"
+ " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
+ /* clang-format on */
+ this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->PolicyWarnedCMP0022 = true;
+ }
+ }
+
+ // There is no implicit link interface for executables or modules
+ // so if none was explicitly set then there is no link interface.
+ if (!explicitLibraries &&
+ (this->GetType() == cmStateEnums::EXECUTABLE ||
+ (this->GetType() == cmStateEnums::MODULE_LIBRARY))) {
+ return;
+ }
+ iface.Exists = true;
+ iface.ExplicitLibraries = explicitLibraries;
+
+ 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)
+ // 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
+ // to the link implementation.
+ {
+ // The link implementation is the default link interface.
+ cmLinkImplementationLibraries const* impl =
+ this->GetLinkImplementationLibrariesInternal(config, headTarget);
+ iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(),
+ impl->Libraries.end());
+ if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
+ !this->PolicyWarnedCMP0022 && !usage_requirements_only) {
+ // Compare the link implementation fallback link interface to the
+ // preferred new link interface property and warn if different.
+ std::vector<cmLinkItem> ifaceLibs;
+ static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
+ if (const char* newExplicitLibraries = this->GetProperty(newProp)) {
+ bool hadHeadSensitiveConditionDummy = false;
+ this->ExpandLinkItems(newProp, newExplicitLibraries, config,
+ headTarget, usage_requirements_only, ifaceLibs,
+ hadHeadSensitiveConditionDummy);
+ }
+ if (ifaceLibs != iface.Libraries) {
+ std::string oldLibraries = cmJoin(impl->Libraries, ";");
+ std::string newLibraries = cmJoin(ifaceLibs, ";");
+ if (oldLibraries.empty()) {
+ oldLibraries = "(empty)";
+ }
+ if (newLibraries.empty()) {
+ newLibraries = "(empty)";
+ }
+
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
+ "Target \"" << this->GetName() << "\" has an "
+ "INTERFACE_LINK_LIBRARIES property. "
+ "This should be preferred as the source of the link interface "
+ "for this library but because CMP0022 is not set CMake is "
+ "ignoring the property and using the link implementation "
+ "as the link interface instead."
+ "\n"
+ "INTERFACE_LINK_LIBRARIES:\n"
+ " " << newLibraries << "\n"
+ "Link implementation:\n"
+ " " << oldLibraries << "\n";
+ /* clang-format on */
+ this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->PolicyWarnedCMP0022 = true;
+ }
+ }
+ }
+}
+
+const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
+ const std::string& config, cmGeneratorTarget const* headTarget,
+ bool usage_requirements_only) const
+{
+ cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
+ if (!info) {
+ return CM_NULLPTR;
+ }
+
+ std::string CONFIG = cmSystemTools::UpperCase(config);
+ cmHeadToLinkInterfaceMap& hm =
+ (usage_requirements_only
+ ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
+ : this->GetHeadToLinkInterfaceMap(config));
+
+ // If the link interface does not depend on the head target
+ // then return the one we computed first.
+ if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
+ return &hm.begin()->second;
+ }
+
+ cmOptionalLinkInterface& iface = hm[headTarget];
+ if (!iface.AllDone) {
+ iface.AllDone = true;
+ iface.Multiplicity = info->Multiplicity;
+ cmSystemTools::ExpandListArgument(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);
+ }
+
+ return &iface;
+}
+
+cmGeneratorTarget::ImportInfo const* cmGeneratorTarget::GetImportInfo(
+ const std::string& config) const
+{
+ // There is no imported information for non-imported targets.
+ if (!this->IsImported()) {
+ return CM_NULLPTR;
+ }
+
+ // Lookup/compute/cache the import information for this
+ // configuration.
+ std::string config_upper;
+ if (!config.empty()) {
+ config_upper = cmSystemTools::UpperCase(config);
+ } else {
+ config_upper = "NOCONFIG";
+ }
+
+ ImportInfoMapType::const_iterator i = this->ImportInfoMap.find(config_upper);
+ if (i == this->ImportInfoMap.end()) {
+ ImportInfo info;
+ this->ComputeImportInfo(config_upper, info);
+ ImportInfoMapType::value_type entry(config_upper, info);
+ i = this->ImportInfoMap.insert(entry).first;
+ }
+
+ if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return &i->second;
+ }
+ // 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 the import information.
+ return &i->second;
+}
+
+void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
+ ImportInfo& info) const
+{
+ // This method finds information about an imported target from its
+ // properties. The "IMPORTED_" namespace is reserved for properties
+ // defined by the project exporting the target.
+
+ // Initialize members.
+ info.NoSOName = false;
+
+ const char* loc = CM_NULLPTR;
+ const char* imp = CM_NULLPTR;
+ std::string suffix;
+ if (!this->Target->GetMappedConfig(desired_config, &loc, &imp, suffix)) {
+ return;
+ }
+
+ // Get the link interface.
+ {
+ std::string linkProp = "INTERFACE_LINK_LIBRARIES";
+ const char* propertyLibs = this->GetProperty(linkProp);
+
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (!propertyLibs) {
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ linkProp += suffix;
+ propertyLibs = this->GetProperty(linkProp);
+ }
+
+ if (!propertyLibs) {
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ propertyLibs = this->GetProperty(linkProp);
+ }
+ }
+ if (propertyLibs) {
+ info.LibrariesProp = linkProp;
+ info.Libraries = propertyLibs;
+ }
+ }
+ if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (loc) {
+ info.LibName = loc;
+ }
+ return;
+ }
+
+ // A provided configuration has been chosen. Load the
+ // configuration's properties.
+
+ // Get the location.
+ if (loc) {
+ info.Location = loc;
+ } else {
+ std::string impProp = "IMPORTED_LOCATION";
+ impProp += suffix;
+ if (const char* config_location = this->GetProperty(impProp)) {
+ info.Location = config_location;
+ } else if (const char* location = this->GetProperty("IMPORTED_LOCATION")) {
+ info.Location = location;
+ }
+ }
+
+ // Get the soname.
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ std::string soProp = "IMPORTED_SONAME";
+ soProp += suffix;
+ if (const char* config_soname = this->GetProperty(soProp)) {
+ info.SOName = config_soname;
+ } else if (const char* soname = this->GetProperty("IMPORTED_SONAME")) {
+ info.SOName = soname;
+ }
+ }
+
+ // Get the "no-soname" mark.
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ std::string soProp = "IMPORTED_NO_SONAME";
+ soProp += suffix;
+ if (const char* config_no_soname = this->GetProperty(soProp)) {
+ info.NoSOName = cmSystemTools::IsOn(config_no_soname);
+ } else if (const char* no_soname =
+ this->GetProperty("IMPORTED_NO_SONAME")) {
+ info.NoSOName = cmSystemTools::IsOn(no_soname);
+ }
+ }
+
+ // Get the import library.
+ if (imp) {
+ info.ImportLibrary = imp;
+ } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports()) {
+ std::string impProp = "IMPORTED_IMPLIB";
+ impProp += suffix;
+ if (const char* config_implib = this->GetProperty(impProp)) {
+ info.ImportLibrary = config_implib;
+ } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) {
+ info.ImportLibrary = implib;
+ }
+ }
+
+ // Get the link dependencies.
+ {
+ std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
+ linkProp += suffix;
+ if (const char* config_libs = this->GetProperty(linkProp)) {
+ info.SharedDeps = config_libs;
+ } else if (const char* libs =
+ this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) {
+ info.SharedDeps = libs;
+ }
+ }
+
+ // Get the link languages.
+ if (this->LinkLanguagePropagatesToDependents()) {
+ std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
+ linkProp += suffix;
+ if (const char* config_libs = this->GetProperty(linkProp)) {
+ info.Languages = config_libs;
+ } else if (const char* libs =
+ this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES")) {
+ info.Languages = libs;
+ }
+ }
+
+ // Get the cyclic repetition count.
+ if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
+ linkProp += suffix;
+ if (const char* config_reps = this->GetProperty(linkProp)) {
+ sscanf(config_reps, "%u", &info.Multiplicity);
+ } else if (const char* reps =
+ this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) {
+ sscanf(reps, "%u", &info.Multiplicity);
+ }
+ }
+}
+
+cmHeadToLinkInterfaceMap& cmGeneratorTarget::GetHeadToLinkInterfaceMap(
+ const std::string& config) const
+{
+ std::string CONFIG = cmSystemTools::UpperCase(config);
+ return this->LinkInterfaceMap[CONFIG];
+}
+
+cmHeadToLinkInterfaceMap&
+cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
+ const std::string& config) const
+{
+ std::string CONFIG = cmSystemTools::UpperCase(config);
+ return this->LinkInterfaceUsageRequirementsOnlyMap[CONFIG];
+}
+
+const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
+ const std::string& config) const
+{
+ // There is no link implementation for imported targets.
+ if (this->IsImported()) {
+ return CM_NULLPTR;
+ }
+
+ std::string CONFIG = cmSystemTools::UpperCase(config);
+ cmOptionalLinkImplementation& impl = this->LinkImplMap[CONFIG][this];
+ if (!impl.LibrariesDone) {
+ impl.LibrariesDone = true;
+ this->ComputeLinkImplementationLibraries(config, impl, this);
+ }
+ if (!impl.LanguagesDone) {
+ impl.LanguagesDone = true;
+ this->ComputeLinkImplementationLanguages(config, impl);
+ }
+ return &impl;
+}
+
+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_iterator it = configs.begin();
+ const std::string& firstConfig = *it;
+ this->GetSourceFilesWithoutObjectLibraries(files, firstConfig);
+
+ for (; it != configs.end(); ++it) {
+ std::vector<cmSourceFile*> configFiles;
+ this->GetSourceFilesWithoutObjectLibraries(configFiles, *it);
+ if (configFiles != files) {
+ std::string firstConfigFiles;
+ const char* sep = "";
+ for (std::vector<cmSourceFile*>::const_iterator fi = files.begin();
+ fi != files.end(); ++fi) {
+ firstConfigFiles += sep;
+ firstConfigFiles += (*fi)->GetFullPath();
+ sep = "\n ";
+ }
+
+ std::string thisConfigFiles;
+ sep = "";
+ for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin();
+ fi != configFiles.end(); ++fi) {
+ thisConfigFiles += sep;
+ thisConfigFiles += (*fi)->GetFullPath();
+ sep = "\n ";
+ }
+ std::ostringstream e;
+ /* clang-format off */
+ e << "Target \"" << this->GetName()
+ << "\" has source files which vary by "
+ "configuration. This is not supported by the \""
+ << this->GlobalGenerator->GetName()
+ << "\" generator.\n"
+ "Config \"" << firstConfig << "\":\n"
+ " " << firstConfigFiles << "\n"
+ "Config \"" << *it << "\":\n"
+ " " << thisConfigFiles << "\n";
+ /* clang-format on */
+ this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ }
+ return true;
+}
+
+void cmGeneratorTarget::GetObjectLibrariesCMP0026(
+ std::vector<cmGeneratorTarget*>& objlibs) const
+{
+ // At configure-time, this method can be called as part of getting the
+ // LOCATION property or to export() a file to be include()d. However
+ // there is no cmGeneratorTarget at configure-time, so search the SOURCES
+ // 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);
+
+ if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
+ continue;
+ }
+ cmGeneratorTarget* objLib =
+ this->LocalGenerator->FindGeneratorTargetToUse(objLibName);
+ if (objLib) {
+ objlibs.push_back(objLib);
+ }
+ }
+ }
+ }
+}
+
+std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
+{
+ // Strip whitespace off the library names because we used to do this
+ // in case variables were expanded at generate time. We no longer
+ // do the expansion but users link to libraries like " ${VAR} ".
+ std::string lib = item;
+ std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
+ if (pos != std::string::npos) {
+ lib = lib.substr(pos);
+ }
+ pos = lib.find_last_not_of(" \t\r\n");
+ if (pos != std::string::npos) {
+ lib = lib.substr(0, pos + 1);
+ }
+ if (lib != item) {
+ cmake* cm = this->LocalGenerator->GetCMakeInstance();
+ switch (this->GetPolicyStatusCMP0004()) {
+ case cmPolicies::WARN: {
+ std::ostringstream w;
+ 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());
+ }
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::NEW: {
+ std::ostringstream e;
+ 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());
+ } break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS: {
+ std::ostringstream e;
+ 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());
+ } break;
+ }
+ }
+ return lib;
+}
+
+void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
+ const std::string& config) const
+{
+ 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();
+ if (!lang.empty()) {
+ languages.insert(lang);
+ }
+ }
+
+ std::vector<cmGeneratorTarget*> objectLibraries;
+ std::vector<cmSourceFile const*> externalObjects;
+ if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ 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);
+ }
+ } else {
+ this->GetExternalObjects(externalObjects, config);
+ for (std::vector<cmSourceFile const*>::const_iterator i =
+ externalObjects.begin();
+ i != externalObjects.end(); ++i) {
+ std::string objLib = (*i)->GetObjectLibrary();
+ if (cmGeneratorTarget* tgt =
+ this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
+ objectLibraries.push_back(tgt);
+ }
+ }
+ }
+ for (std::vector<cmGeneratorTarget*>::const_iterator i =
+ objectLibraries.begin();
+ i != objectLibraries.end(); ++i) {
+ (*i)->GetLanguages(languages, config);
+ }
+}
+
+void cmGeneratorTarget::ComputeLinkImplementationLanguages(
+ const std::string& config, cmOptionalLinkImplementation& impl) const
+{
+ // This target needs runtime libraries for its source languages.
+ 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.
+ impl.Languages.insert(impl.Languages.begin(), languages.begin(),
+ languages.end());
+}
+
+bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
+{
+ if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
+ return false;
+ }
+ if (this->GetProperty("BUILD_RPATH")) {
+ return true;
+ }
+ if (cmLinkImplementationLibraries const* impl =
+ this->GetLinkImplementationLibraries(config)) {
+ return !impl->Libraries.empty();
+ }
+ return false;
+}
+
+cmLinkImplementationLibraries const*
+cmGeneratorTarget::GetLinkImplementationLibraries(
+ const std::string& config) const
+{
+ return this->GetLinkImplementationLibrariesInternal(config, this);
+}
+
+cmLinkImplementationLibraries const*
+cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
+ const std::string& config, cmGeneratorTarget const* head) const
+{
+ // There is no link implementation for imported targets.
+ if (this->IsImported()) {
+ return CM_NULLPTR;
+ }
+
+ // Populate the link implementation libraries for this configuration.
+ std::string CONFIG = cmSystemTools::UpperCase(config);
+ HeadToLinkImplementationMap& hm = this->LinkImplMap[CONFIG];
+
+ // If the link implementation does not depend on the head target
+ // then return the one we computed first.
+ if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
+ return &hm.begin()->second;
+ }
+
+ cmOptionalLinkImplementation& impl = hm[head];
+ if (!impl.LibrariesDone) {
+ impl.LibrariesDone = true;
+ this->ComputeLinkImplementationLibraries(config, impl, head);
+ }
+ return &impl;
+}
+
+bool cmGeneratorTarget::IsNullImpliedByLinkLibraries(
+ const std::string& p) const
+{
+ return this->LinkImplicitNullProperties.find(p) !=
+ this->LinkImplicitNullProperties.end();
+}
+
+void cmGeneratorTarget::ComputeLinkImplementationLibraries(
+ const std::string& config, cmOptionalLinkImplementation& impl,
+ cmGeneratorTarget const* head) const
+{
+ cmStringRange entryRange = this->Target->GetLinkImplementationEntries();
+ cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces();
+ cmBacktraceRange::const_iterator btIt = btRange.begin();
+ // Collect libraries directly linked in this configuration.
+ for (cmStringRange::const_iterator le = entryRange.begin(),
+ end = entryRange.end();
+ le != end; ++le, ++btIt) {
+ std::vector<std::string> llibs;
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->GetName(), "LINK_LIBRARIES", CM_NULLPTR, CM_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);
+ if (cge->GetHadHeadSensitiveCondition()) {
+ impl.HadHeadSensitiveCondition = true;
+ }
+
+ for (std::vector<std::string>::const_iterator li = llibs.begin();
+ li != llibs.end(); ++li) {
+ // Skip entries that resolve to the target itself or are empty.
+ std::string name = this->CheckCMP0004(*li);
+ if (name == this->GetName() || name.empty()) {
+ if (name == this->GetName()) {
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
+ std::ostringstream e;
+ switch (this->GetPolicyStatusCMP0038()) {
+ case cmPolicies::WARN: {
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n";
+ messageType = cmake::AUTHOR_WARNING;
+ } break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+
+ if (!noMessage) {
+ e << "Target \"" << this->GetName() << "\" links to itself.";
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ messageType, e.str(), this->GetBacktrace());
+ if (messageType == cmake::FATAL_ERROR) {
+ return;
+ }
+ }
+ }
+ continue;
+ }
+
+ // The entry is meant for this configuration.
+ impl.Libraries.push_back(cmLinkImplItem(
+ name, this->FindTargetToLink(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);
+ }
+ }
+ cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
+ }
+
+ // Get the list of configurations considered to be DEBUG.
+ std::vector<std::string> debugConfigs =
+ this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+
+ cmTargetLinkLibraryType linkType =
+ 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);
+ if (name == this->GetName() || name.empty()) {
+ continue;
+ }
+ // Support OLD behavior for CMP0003.
+ impl.WrongConfigLibraries.push_back(
+ cmLinkItem(name, this->FindTargetToLink(name)));
+ }
+ }
+}
+
+cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
+ std::string const& name) const
+{
+ cmGeneratorTarget* tgt =
+ this->LocalGenerator->FindGeneratorTargetToUse(name);
+
+ // 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;
+ }
+
+ return tgt;
+}
+
+std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
+{
+ if (OutputInfo const* info = this->GetOutputInfo(config)) {
+ // Return the directory in which the target will be built.
+ return info->PdbDir;
+ }
+ return "";
+}
+
+bool cmGeneratorTarget::HasImplibGNUtoMS() const
+{
+ return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS");
+}
+
+bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& gnuName,
+ std::string& out,
+ const char* newExt) const
+{
+ if (this->HasImplibGNUtoMS() && gnuName.size() > 6 &&
+ gnuName.substr(gnuName.size() - 6) == ".dll.a") {
+ out = gnuName.substr(0, gnuName.size() - 6);
+ out += newExt ? newExt : ".lib";
+ return true;
+ }
+ return false;
+}
+
+bool cmGeneratorTarget::IsExecutableWithExports() const
+{
+ return (this->GetType() == cmStateEnums::EXECUTABLE &&
+ this->GetPropertyAsBool("ENABLE_EXPORTS"));
+}
+
+bool cmGeneratorTarget::HasImportLibrary() const
+{
+ return (this->IsDLLPlatform() &&
+ (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports()));
+}
+
+std::string cmGeneratorTarget::GetSupportDirectory() const
+{
+ std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
+ dir += cmake::GetCMakeFilesDirectory();
+ dir += "/";
+ dir += this->GetName();
+#if defined(__VMS)
+ dir += "_dir";
+#else
+ dir += ".dir";
+#endif
+ return dir;
+}
+
+bool cmGeneratorTarget::IsLinkable() const
+{
+ return (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
+ this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ this->IsExecutableWithExports());
+}
+
+bool cmGeneratorTarget::IsFrameworkOnApple() const
+{
+ return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
+ this->Makefile->IsOn("APPLE") &&
+ this->GetPropertyAsBool("FRAMEWORK"));
+}
+
+bool cmGeneratorTarget::IsAppBundleOnApple() const
+{
+ return (this->GetType() == cmStateEnums::EXECUTABLE &&
+ this->Makefile->IsOn("APPLE") &&
+ this->GetPropertyAsBool("MACOSX_BUNDLE"));
+}
+
+bool cmGeneratorTarget::IsXCTestOnApple() const
+{
+ return (this->IsCFBundleOnApple() && this->GetPropertyAsBool("XCTEST"));
+}
+
+bool cmGeneratorTarget::IsCFBundleOnApple() const
{
- return this->Target->GetIncludeDirectories(config);
+ return (this->GetType() == cmStateEnums::MODULE_LIBRARY &&
+ this->Makefile->IsOn("APPLE") && this->GetPropertyAsBool("BUNDLE"));
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index dedfa60aa..52147e319 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -1,19 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGeneratorTarget_h
#define cmGeneratorTarget_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+#include <map>
+#include <set>
+#include <stddef.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+class cmComputeLinkInformation;
class cmCustomCommand;
class cmGlobalGenerator;
class cmLocalGenerator;
@@ -23,67 +27,826 @@ class cmTarget;
class cmGeneratorTarget
{
+ CM_DISABLE_COPY(cmGeneratorTarget)
+
public:
- cmGeneratorTarget(cmTarget*);
+ cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg);
+ ~cmGeneratorTarget();
+
+ cmLocalGenerator* GetLocalGenerator() const;
+
+ cmGlobalGenerator* GetGlobalGenerator() const;
+
+ bool IsImported() const;
+ bool IsImportedGloballyVisible() const;
+ const char* GetLocation(const std::string& config) const;
+
+ std::vector<cmCustomCommand> const& GetPreBuildCommands() const;
+ std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
+ std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
+
+#define DECLARE_TARGET_POLICY(POLICY) \
+ cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \
+ { \
+ return this->PolicyMap.Get(cmPolicies::POLICY); \
+ }
+
+ CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY)
+
+#undef DECLARE_TARGET_POLICY
+
+ /** Get the location of the target in the build tree with a placeholder
+ referencing the configuration in the native build system. This
+ location is suitable for use as the LOCATION target property. */
+ const char* GetLocationForBuild() const;
+
+ cmComputeLinkInformation* GetLinkInformation(
+ const std::string& config) const;
+
+ cmStateEnums::TargetType GetType() const;
+ const std::string& GetName() const;
+ std::string GetExportName() const;
+
+ std::vector<std::string> GetPropertyKeys() const;
+ const char* GetProperty(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;
+
+ /** Source file kinds (classifications).
+ Generators use this to decide how to treat a source file. */
+ enum SourceKind
+ {
+ SourceKindAppManifest,
+ SourceKindCertificate,
+ SourceKindCustomCommand,
+ SourceKindExternalObject,
+ SourceKindExtra,
+ SourceKindHeader,
+ SourceKindIDL,
+ SourceKindManifest,
+ SourceKindModuleDefinition,
+ SourceKindObjectSource,
+ SourceKindResx,
+ SourceKindXaml
+ };
+
+ /** A source file paired with a kind (classification). */
+ struct SourceAndKind
+ {
+ cmSourceFile* Source;
+ SourceKind Kind;
+ };
+
+ /** All sources needed for a configuration with kinds assigned. */
+ struct KindedSources
+ {
+ std::vector<SourceAndKind> Sources;
+ std::set<std::string> ExpectedResxHeaders;
+ std::set<std::string> ExpectedXamlHeaders;
+ std::set<std::string> ExpectedXamlSources;
+ bool Initialized;
+ KindedSources()
+ : Initialized(false)
+ {
+ }
+ };
+
+ /** Get all sources needed for a configuration with kinds assigned. */
+ KindedSources const& GetKindedSources(std::string const& config) const;
+
+ struct AllConfigSource
+ {
+ cmSourceFile const* Source;
+ cmGeneratorTarget::SourceKind Kind;
+ std::vector<size_t> Configs;
+ };
+
+ /** Get all sources needed for all configurations with kinds and
+ per-source configurations assigned. */
+ std::vector<AllConfigSource> const& GetAllConfigSources() const;
+
+ void GetObjectSources(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ const std::string& GetObjectName(cmSourceFile const* file);
+ const char* GetCustomObjectExtension() const;
+
+ bool HasExplicitObjectName(cmSourceFile const* file) const;
+ void AddExplicitObjectName(cmSourceFile const* sf);
+
+ void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetResxSources(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetExternalObjects(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetHeaderSources(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetExtraSources(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetCustomCommands(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetExpectedResxHeaders(std::set<std::string>&,
+ const std::string& config) const;
+ void GetAppManifest(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetManifests(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetCertificates(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetXamlSources(std::vector<cmSourceFile const*>&,
+ const std::string& config) const;
+ void GetExpectedXamlHeaders(std::set<std::string>&,
+ const std::string& config) const;
+ void GetExpectedXamlSources(std::set<std::string>&,
+ const std::string& config) const;
+
+ std::set<cmLinkItem> const& GetUtilityItems() const;
+
+ void ComputeObjectMapping();
+
+ const char* GetFeature(const std::string& feature,
+ const std::string& config) const;
+
+ bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
+
+ bool IsLinkInterfaceDependentBoolProperty(const std::string& p,
+ const std::string& config) const;
+ bool IsLinkInterfaceDependentStringProperty(const std::string& p,
+ const std::string& config) const;
+ bool IsLinkInterfaceDependentNumberMinProperty(
+ const std::string& p, const std::string& config) const;
+ bool IsLinkInterfaceDependentNumberMaxProperty(
+ const std::string& p, const std::string& config) const;
+
+ bool GetLinkInterfaceDependentBoolProperty(const std::string& p,
+ const std::string& config) const;
+
+ const char* GetLinkInterfaceDependentStringProperty(
+ const std::string& p, const std::string& config) const;
+ const char* GetLinkInterfaceDependentNumberMinProperty(
+ const std::string& p, const std::string& config) const;
+ const char* GetLinkInterfaceDependentNumberMaxProperty(
+ const std::string& p, const std::string& config) const;
+
+ cmLinkInterface const* GetLinkInterface(
+ const std::string& config, const cmGeneratorTarget* headTarget) const;
+ void ComputeLinkInterface(const std::string& config,
+ cmOptionalLinkInterface& iface,
+ const cmGeneratorTarget* head) const;
+
+ cmLinkInterfaceLibraries const* GetLinkInterfaceLibraries(
+ const std::string& config, const cmGeneratorTarget* headTarget,
+ bool usage_requirements_only) const;
+
+ void ComputeLinkInterfaceLibraries(const std::string& config,
+ cmOptionalLinkInterface& iface,
+ const cmGeneratorTarget* head,
+ bool usage_requirements_only) const;
+
+ /** Get the library name for an imported interface library. */
+ std::string GetImportedLibName(std::string const& config) const;
+
+ /** Get the full path to the target according to the settings in its
+ makefile and the configuration type. */
+ std::string GetFullPath(
+ const std::string& config = "",
+ cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact,
+ bool realname = false) const;
+ std::string NormalGetFullPath(const std::string& config,
+ cmStateEnums::ArtifactType artifact,
+ bool realname) const;
+ std::string NormalGetRealName(const std::string& config) const;
+
+ /** Get the names of an object library's object files underneath
+ its object file directory. */
+ void GetTargetObjectNames(std::string const& config,
+ std::vector<std::string>& objects) const;
+
+ /** What hierarchy level should the reported directory contain */
+ enum BundleDirectoryLevel
+ {
+ BundleDirLevel,
+ ContentLevel,
+ FullLevel
+ };
+
+ /** @return the Mac App directory without the base */
+ std::string GetAppBundleDirectory(const std::string& config,
+ BundleDirectoryLevel level) const;
- int GetType() const;
- const char *GetName() const;
- const char *GetProperty(const char *prop);
- bool GetPropertyAsBool(const char *prop);
- std::vector<cmSourceFile*> const& GetSourceFiles();
+ /** Return whether this target is an executable Bundle, a framework
+ or CFBundle on Apple. */
+ bool IsBundleOnApple() const;
+
+ /** Get the full name of the target according to the settings in its
+ makefile. */
+ std::string GetFullName(const std::string& config = "",
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+
+ /** @return the Mac framework directory without the base. */
+ std::string GetFrameworkDirectory(const std::string& config,
+ BundleDirectoryLevel level) const;
+
+ /** Return the framework version string. Undefined if
+ IsFrameworkOnApple returns false. */
+ std::string GetFrameworkVersion() const;
+
+ /** @return the Mac CFBundle directory without the base */
+ std::string GetCFBundleDirectory(const std::string& config,
+ 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". */
+ 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/". */
+ 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;
+
+ bool LinkLanguagePropagatesToDependents() const
+ {
+ return this->GetType() == cmStateEnums::STATIC_LIBRARY;
+ }
+
+ /** Get the macro to define when building sources in this target.
+ If no macro should be defined null is returned. */
+ const char* GetExportMacro() const;
+
+ /** Get the soname of the target. Allowed only for a shared library. */
+ std::string GetSOName(const std::string& config) const;
+
+ void GetFullNameComponents(std::string& prefix, std::string& base,
+ std::string& suffix,
+ const std::string& config = "",
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+
+ /** Append to @a base the bundle directory hierarchy up to a certain @a level
+ * and return it. */
+ std::string BuildBundleDirectory(const std::string& base,
+ const std::string& config,
+ BundleDirectoryLevel level) const;
+
+ /** @return the mac content directory for this target. */
+ std::string GetMacContentDirectory(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const;
+
+ /** @return folder prefix for IDEs. */
+ std::string GetEffectiveFolderName() const;
cmTarget* Target;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
- cmGlobalGenerator* GlobalGenerator;
+ cmGlobalGenerator const* GlobalGenerator;
- /** Sources classified by purpose. */
- std::vector<cmSourceFile*> CustomCommands;
- std::vector<cmSourceFile*> ExtraSources;
- std::vector<cmSourceFile*> HeaderSources;
- std::vector<cmSourceFile*> ObjectSources;
- std::vector<cmSourceFile*> ExternalObjects;
- std::vector<cmSourceFile*> IDLSources;
- std::vector<cmSourceFile*> ResxSources;
+ struct ModuleDefinitionInfo
+ {
+ std::string DefFile;
+ bool DefFileGenerated;
+ bool WindowsExportAllSymbols;
+ std::vector<cmSourceFile const*> Sources;
+ };
+ ModuleDefinitionInfo const* GetModuleDefinitionInfo(
+ std::string const& config) const;
- std::string ModuleDefinitionFile;
+ /** Return whether or not the target is for a DLL platform. */
+ bool IsDLLPlatform() const;
- std::map<cmSourceFile const*, std::string> Objects;
- std::set<cmSourceFile const*> ExplicitObjectName;
+ /** @return whether this target have a well defined output file name. */
+ bool HaveWellDefinedOutputFiles() const;
+
+ /** Link information from the transitive closure of the link
+ implementation and the interfaces of its dependencies. */
+ struct LinkClosure
+ {
+ // The preferred linker language.
+ std::string LinkerLanguage;
+
+ // Languages whose runtime libraries must be linked.
+ std::vector<std::string> Languages;
+ };
+
+ LinkClosure const* GetLinkClosure(const std::string& config) const;
+ void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
- std::set<std::string> ExpectedResxHeaders;
+ cmLinkImplementation const* GetLinkImplementation(
+ const std::string& config) const;
+
+ void ComputeLinkImplementationLanguages(
+ const std::string& config, cmOptionalLinkImplementation& impl) const;
+
+ cmLinkImplementationLibraries const* GetLinkImplementationLibraries(
+ const std::string& config) const;
+
+ void ComputeLinkImplementationLibraries(const std::string& config,
+ cmOptionalLinkImplementation& impl,
+ const cmGeneratorTarget* head) const;
+
+ cmGeneratorTarget* FindTargetToLink(std::string const& name) const;
+
+ // Compute the set of languages compiled by the target. This is
+ // computed every time it is called because the languages can change
+ // when source file properties are changed and we do not have enough
+ // information to forward these property changes to the targets
+ // until we have per-target object file properties.
+ void GetLanguages(std::set<std::string>& languages,
+ std::string const& config) const;
+
+ void GetObjectLibrariesCMP0026(
+ std::vector<cmGeneratorTarget*>& objlibs) const;
+
+ std::string GetFullNameImported(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
+
+ /** Get source files common to all configurations and diagnose cases
+ with per-config sources. Excludes sources added by a TARGET_OBJECTS
+ generator expression. */
+ bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
+
+ bool HaveBuildTreeRPATH(const std::string& config) const;
/** Full path with trailing slash to the top-level directory
holding object files for this target. Includes the build
time config name placeholder if needed for the generator. */
std::string ObjectDirectory;
- std::vector<cmTarget*> ObjectLibraries;
+ /** Full path with trailing slash to the top-level directory
+ holding object files for the given configuration. */
+ std::string GetObjectDirectory(std::string const& config) const;
- void UseObjectLibraries(std::vector<std::string>& objs);
+ void GetAppleArchs(const std::string& config,
+ std::vector<std::string>& archVec) const;
- void GetAppleArchs(const char* config,
- std::vector<std::string>& archVec);
+ std::string GetFeatureSpecificLinkRuleVariable(
+ std::string const& var, std::string const& lang,
+ std::string const& config) const;
- ///! Return the rule variable used to create this type of target,
- // need to add CMAKE_(LANG) for full name.
- const char* GetCreateRuleVariable();
+ /** Return the rule variable used to create this type of target. */
+ std::string GetCreateRuleVariable(std::string const& lang,
+ std::string const& config) const;
/** Get the include directories for this target. */
- std::vector<std::string> GetIncludeDirectories(const char *config);
+ std::vector<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;
+
+ void GetCompileFeatures(std::vector<std::string>& features,
+ const std::string& config) const;
+
+ void GetCompileDefinitions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+
+ bool IsSystemIncludeDirectory(const std::string& dir,
+ const std::string& config) const;
+
+ /** Add the target output files to the global generator manifest. */
+ void ComputeTargetManifest(const std::string& config) const;
+
+ bool ComputeCompileFeatures(std::string const& config) const;
+
+ /**
+ * Trace through the source files in this target and add al source files
+ * that they depend on, used by all generators
+ */
+ void TraceDependencies();
+
+ /** Get the directory in which this target will be built. If the
+ configuration name is given then the generator will add its
+ subdirectory for that configuration. Otherwise just the canonical
+ output directory is given. */
+ std::string GetDirectory(const std::string& config = "",
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+
+ /** Get the directory in which to place the target compiler .pdb file.
+ If the configuration name is given then the generator will add its
+ subdirectory for that configuration. Otherwise just the canonical
+ compiler pdb output directory is given. */
+ std::string GetCompilePDBDirectory(const std::string& config = "") const;
- bool IsSystemIncludeDirectory(const char *dir, const char *config);
+ /** Get sources that must be built before the given source. */
+ std::vector<cmSourceFile*> const* GetSourceDepends(
+ cmSourceFile const* sf) const;
+
+ /** Return whether this target uses the default value for its output
+ directory. */
+ bool UsesDefaultOutputDir(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
+
+ // Cache target output paths for each configuration.
+ struct OutputInfo
+ {
+ std::string OutDir;
+ std::string ImpDir;
+ std::string PdbDir;
+ bool empty() const
+ {
+ return OutDir.empty() && ImpDir.empty() && PdbDir.empty();
+ }
+ };
+
+ OutputInfo const* GetOutputInfo(const std::string& config) const;
+
+ /** Get the name of the pdb file for the target. */
+ std::string GetPDBName(const std::string& config = "") const;
+
+ /** Whether this library has soname enabled and platform supports it. */
+ bool HasSOName(const std::string& config) const;
+
+ struct CompileInfo
+ {
+ std::string CompilePdbDir;
+ };
+
+ CompileInfo const* GetCompileInfo(const std::string& config) const;
+
+ typedef std::map<std::string, CompileInfo> CompileInfoMapType;
+ mutable CompileInfoMapType CompileInfoMap;
+
+ bool IsNullImpliedByLinkLibraries(const std::string& p) const;
+
+ /** Get the name of the compiler pdb file for the target. */
+ std::string GetCompilePDBName(const std::string& config = "") const;
+
+ /** Get the path for the MSVC /Fd option for this target. */
+ std::string GetCompilePDBPath(const std::string& config = "") const;
+
+ // Get the target base name.
+ std::string GetOutputName(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
+
+ void AddSource(const std::string& src);
+ void AddTracedSources(std::vector<std::string> const& srcs);
+
+ /**
+ * Adds an entry to the INCLUDE_DIRECTORIES list.
+ * If before is true the entry is pushed at the front.
+ */
+ void AddIncludeDirectory(const std::string& src, bool before = false);
+
+ /**
+ * Flags for a given source file as used in this target. Typically assigned
+ * via SET_TARGET_PROPERTIES when the property is a list of source files.
+ */
+ enum SourceFileType
+ {
+ SourceFileTypeNormal,
+ SourceFileTypePrivateHeader, // is in "PRIVATE_HEADER" target property
+ SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property
+ SourceFileTypeResource, // is in "RESOURCE" target property *or*
+ // has MACOSX_PACKAGE_LOCATION=="Resources"
+ SourceFileTypeDeepResource, // MACOSX_PACKAGE_LOCATION starts with
+ // "Resources/"
+ SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources[/]"
+ };
+ struct SourceFileFlags
+ {
+ SourceFileFlags()
+ : Type(SourceFileTypeNormal)
+ , MacFolder(CM_NULLPTR)
+ {
+ }
+ SourceFileType Type;
+ const char* MacFolder; // location inside Mac content folders
+ };
+ void GetAutoUicOptions(std::vector<std::string>& result,
+ const std::string& config) const;
+
+ /** 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;
+
+ /** 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;
+
+ /**
+ * Compute whether this target must be relinked before installing.
+ */
+ bool NeedRelinkBeforeInstall(const std::string& config) const;
+
+ /** Return true if builtin chrpath will work for this target */
+ bool IsChrpathUsed(const std::string& config) const;
+
+ /** Get the directory in which this targets .pdb files will be placed.
+ If the configuration name is given then the generator will add its
+ subdirectory for that configuration. Otherwise just the canonical
+ pdb output directory is given. */
+ std::string GetPDBDirectory(const std::string& config) const;
+
+ ///! 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;
+
+ /** 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 IsExecutableWithExports() const;
+
+ /** Return whether or not the target has a DLL import library. */
+ bool HasImportLibrary() const;
+
+ /** Get a build-tree directory in which to place target support files. */
+ std::string GetSupportDirectory() const;
+
+ /** Return whether this target may be used to link another target. */
+ bool IsLinkable() const;
+
+ /** Return whether this target is a shared library Framework on
+ Apple. */
+ bool IsFrameworkOnApple() const;
+
+ /** Return whether this target is an executable Bundle on Apple. */
+ bool IsAppBundleOnApple() const;
+
+ /** Return whether this target is a XCTest on Apple. */
+ bool IsXCTestOnApple() const;
+
+ /** Return whether this target is a CFBundle (plugin) on Apple. */
+ bool IsCFBundleOnApple() const;
+
+ struct SourceFileFlags GetTargetSourceFileFlags(
+ const cmSourceFile* sf) const;
+
+ void ReportPropertyOrigin(const std::string& p, const std::string& result,
+ const std::string& report,
+ const std::string& compatibilityType) const;
+
+ class TargetPropertyEntry;
+
+ bool HaveInstallTreeRPATH() const;
+
+ /** Whether this library has \@rpath and platform supports it. */
+ bool HasMacOSXRpathInstallNameDir(const std::string& config) const;
+
+ /** Whether this library defaults to \@rpath. */
+ bool MacOSXRpathInstallNameDirDefault() const;
+
+ enum InstallNameType
+ {
+ INSTALL_NAME_FOR_BUILD,
+ INSTALL_NAME_FOR_INSTALL
+ };
+ /** Whether to use INSTALL_NAME_DIR. */
+ bool MacOSXUseInstallNameDir() const;
+ /** Whether to generate an install_name. */
+ bool CanGenerateInstallNameDir(InstallNameType t) const;
+
+ /** Test for special case of a third-party shared library that has
+ no soname at all. */
+ bool IsImportedSharedLibWithoutSOName(const std::string& config) const;
+
+ const char* 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
+ not set or cannot be parsed. */
+ void GetTargetVersion(int& major, int& minor) const;
+
+ /** Get the target major, minor, and patch version numbers
+ interpreted from the VERSION or SOVERSION property. Version 0
+ is returned if the property is not set or cannot be parsed. */
+ void GetTargetVersion(bool soversion, int& major, int& minor,
+ int& patch) const;
+
+ std::string GetFortranModuleDirectory(std::string const& working_dir) const;
+
+ const char* GetSourcesProperty() const;
private:
- void ClassifySources();
- void LookupObjectLibraries();
+ void AddSourceCommon(const std::string& src);
- std::map<std::string, std::vector<std::string> > SystemIncludesCache;
+ std::string CreateFortranModuleDirectory(
+ std::string const& working_dir) const;
+ mutable bool FortranModuleDirectoryCreated;
+ mutable std::string FortranModuleDirectory;
- cmGeneratorTarget(cmGeneratorTarget const&);
- void operator=(cmGeneratorTarget const&);
-};
+ friend class cmTargetTraceDependencies;
+ struct SourceEntry
+ {
+ std::vector<cmSourceFile*> Depends;
+ };
+ typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType;
+ 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::string ExportMacro;
+
+ void ConstructSourceFileFlags() const;
+ mutable bool SourceFileFlagsConstructed;
+ mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
+
+ mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
+
+ std::string GetFullNameInternal(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
+ void GetFullNameInternal(const std::string& config,
+ cmStateEnums::ArtifactType artifact,
+ std::string& outPrefix, std::string& outBase,
+ std::string& outSuffix) const;
+
+ typedef std::map<std::string, LinkClosure> LinkClosureMapType;
+ mutable LinkClosureMapType LinkClosureMap;
+
+ // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
+ const char* GetOutputTargetType(cmStateEnums::ArtifactType artifact) const;
+
+ void ComputeVersionedName(std::string& vName, std::string const& prefix,
+ std::string const& base, std::string const& suffix,
+ std::string const& name,
+ const char* version) const;
+
+ struct CompatibleInterfacesBase
+ {
+ std::set<std::string> PropsBool;
+ std::set<std::string> PropsString;
+ std::set<std::string> PropsNumberMax;
+ std::set<std::string> PropsNumberMin;
+ };
+ CompatibleInterfacesBase const& GetCompatibleInterfaces(
+ std::string const& config) const;
+
+ struct CompatibleInterfaces : public CompatibleInterfacesBase
+ {
+ CompatibleInterfaces()
+ : Done(false)
+ {
+ }
+ bool Done;
+ };
+ mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap;
+
+ typedef std::map<std::string, cmComputeLinkInformation*>
+ cmTargetLinkInformationMap;
+ mutable cmTargetLinkInformationMap LinkInformation;
+
+ void CheckPropertyCompatibility(cmComputeLinkInformation* info,
+ const std::string& config) const;
+
+ struct LinkImplClosure : public std::vector<cmGeneratorTarget const*>
+ {
+ LinkImplClosure()
+ : Done(false)
+ {
+ }
+ bool Done;
+ };
+ mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap;
+
+ typedef std::map<std::string, cmHeadToLinkInterfaceMap> LinkInterfaceMapType;
+ mutable LinkInterfaceMapType LinkInterfaceMap;
+ mutable LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap;
+
+ cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceMap(
+ std::string const& config) const;
+ cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap(
+ std::string const& config) const;
-typedef std::map<cmTarget*, cmGeneratorTarget*> cmGeneratorTargetsType;
+ // Cache import information from properties for each configuration.
+ struct ImportInfo
+ {
+ ImportInfo()
+ : NoSOName(false)
+ , Multiplicity(0)
+ {
+ }
+ bool NoSOName;
+ unsigned int Multiplicity;
+ std::string Location;
+ std::string SOName;
+ std::string ImportLibrary;
+ std::string LibName;
+ std::string Languages;
+ std::string Libraries;
+ std::string LibrariesProp;
+ std::string SharedDeps;
+ };
+
+ typedef std::map<std::string, ImportInfo> ImportInfoMapType;
+ mutable ImportInfoMapType ImportInfoMap;
+ void ComputeImportInfo(std::string const& desired_config,
+ ImportInfo& info) const;
+ ImportInfo const* GetImportInfo(const std::string& config) const;
+
+ /** Strip off leading and trailing whitespace from an item named in
+ the link dependencies of this target. */
+ std::string CheckCMP0004(std::string const& item) const;
+
+ cmLinkInterface const* GetImportLinkInterface(
+ const std::string& config, const cmGeneratorTarget* head,
+ bool usage_requirements_only) const;
+
+ typedef std::map<std::string, KindedSources> KindedSourcesMapType;
+ mutable KindedSourcesMapType KindedSourcesMap;
+ void ComputeKindedSources(KindedSources& files,
+ std::string const& config) const;
+
+ mutable std::vector<AllConfigSource> AllConfigSources;
+ void ComputeAllConfigSources() const;
+
+ std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> CompileOptionsEntries;
+ std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
+ std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
+ std::vector<TargetPropertyEntry*> SourceEntries;
+ mutable std::set<std::string> LinkImplicitNullProperties;
+
+ void ExpandLinkItems(std::string const& prop, std::string const& value,
+ std::string const& config,
+ const cmGeneratorTarget* headTarget,
+ bool usage_requirements_only,
+ std::vector<cmLinkItem>& items,
+ bool& hadHeadSensitiveCondition) const;
+ void LookupLinkItems(std::vector<std::string> const& names,
+ std::vector<cmLinkItem>& items) const;
+
+ void GetSourceFiles(std::vector<std::string>& files,
+ const std::string& config) const;
+
+ struct HeadToLinkImplementationMap
+ : public std::map<cmGeneratorTarget const*, cmOptionalLinkImplementation>
+ {
+ };
+ typedef std::map<std::string, HeadToLinkImplementationMap> LinkImplMapType;
+ mutable LinkImplMapType LinkImplMap;
+
+ cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(
+ const std::string& config, const cmGeneratorTarget* head) const;
+ bool ComputeOutputDir(const std::string& config,
+ cmStateEnums::ArtifactType artifact,
+ std::string& out) const;
+
+ typedef std::map<std::string, OutputInfo> OutputInfoMapType;
+ mutable OutputInfoMapType OutputInfoMap;
+
+ typedef std::map<std::string, ModuleDefinitionInfo>
+ ModuleDefinitionInfoMapType;
+ 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;
+ mutable OutputNameMapType OutputNameMap;
+ mutable std::set<cmLinkItem> UtilityItems;
+ cmPolicies::PolicyMap PolicyMap;
+ mutable bool PolicyWarnedCMP0022;
+ mutable bool PolicyReportedCMP0069;
+ mutable bool DebugIncludesDone;
+ mutable bool DebugCompileOptionsDone;
+ mutable bool DebugCompileFeaturesDone;
+ mutable bool DebugCompileDefinitionsDone;
+ 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;
+
+public:
+ const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
+ const std::string& config) const;
+
+ mutable std::map<std::string, std::string> MaxLanguageStandards;
+ std::map<std::string, std::string> const& GetMaxLanguageStandards() const
+ {
+ return this->MaxLanguageStandards;
+ }
+
+ struct StrictTargetComparison
+ {
+ bool operator()(cmGeneratorTarget const* t1,
+ cmGeneratorTarget const* t2) const;
+ };
+};
#endif
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index e7ad91a36..5ba3326cb 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -1,79 +1,52 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetCMakePropertyCommand.h"
+#include <set>
+
+#include "cmAlgorithms.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmake.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+
+class cmExecutionStatus;
// cmGetCMakePropertyCommand
-bool cmGetCMakePropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmGetCMakePropertyCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- std::vector<std::string>::size_type cc;
- std::string variable = args[0];
+ std::string const& variable = args[0];
std::string output = "NOTFOUND";
- if ( args[1] == "VARIABLES" )
- {
- int cacheonly = 0;
- std::vector<std::string> vars = this->Makefile->GetDefinitions(cacheonly);
- if (vars.size()>0)
- {
- output = vars[0];
- }
- for ( cc = 1; cc < vars.size(); ++cc )
- {
- output += ";";
- output += vars[cc];
- }
+ if (args[1] == "VARIABLES") {
+ if (const char* varsProp = this->Makefile->GetProperty("VARIABLES")) {
+ output = varsProp;
}
- else if ( args[1] == "MACROS" )
- {
- this->Makefile->GetListOfMacros(output);
+ } else if (args[1] == "MACROS") {
+ output.clear();
+ if (const char* macrosProp = this->Makefile->GetProperty("MACROS")) {
+ output = macrosProp;
}
- else if ( args[1] == "COMPONENTS" )
- {
- const std::set<cmStdString>* components
- = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->GetInstallComponents();
- std::set<cmStdString>::const_iterator compIt;
- output = "";
- for (compIt = components->begin(); compIt != components->end(); ++compIt)
- {
- if (compIt != components->begin())
- {
- output += ";";
- }
- output += *compIt;
- }
+ } else if (args[1] == "COMPONENTS") {
+ const std::set<std::string>* components =
+ this->Makefile->GetGlobalGenerator()->GetInstallComponents();
+ output = cmJoin(*components, ";");
+ } else {
+ const char* prop = CM_NULLPTR;
+ if (!args[1].empty()) {
+ prop = this->Makefile->GetState()->GetGlobalProperty(args[1]);
}
- else
- {
- const char *prop =
- this->Makefile->GetCMakeInstance()->GetProperty(args[1].c_str());
- if (prop)
- {
+ if (prop) {
output = prop;
- }
}
+ }
- this->Makefile->AddDefinition(variable.c_str(), output.c_str());
+ this->Makefile->AddDefinition(variable, output.c_str());
return true;
}
diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h
index b77eaae04..9dfc40fda 100644
--- a/Source/cmGetCMakePropertyCommand.h
+++ b/Source/cmGetCMakePropertyCommand.h
@@ -1,72 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetCMakePropertyCommand_h
#define cmGetCMakePropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmGetCMakePropertyCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmGetCMakePropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetCMakePropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_cmake_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a property of the CMake instance.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_cmake_property(VAR property)\n"
- "Get a property from the CMake instance. "
- "The value of the property is stored in the variable VAR. "
- "If the property is not found, VAR will be set to \"NOTFOUND\". "
- "Some supported properties "
- "include: VARIABLES, CACHE_VARIABLES, COMMANDS, MACROS, and "
- "COMPONENTS."
- "\n"
- "See also the more general get_property() command.";
- }
-
- cmTypeMacro(cmGetCMakePropertyCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index 9e76e1bc3..1005b1543 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -1,96 +1,105 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetDirectoryPropertyCommand.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSystemTools.h"
#include "cmake.h"
+class cmExecutionStatus;
+
// cmGetDirectoryPropertyCommand
-bool cmGetDirectoryPropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmGetDirectoryPropertyCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::vector<std::string>::const_iterator i = args.begin();
- std::string variable = *i;
+ std::string const& variable = *i;
++i;
- std::string output = "";
// get the directory argument if there is one
- cmMakefile *dir = this->Makefile;
- if (*i == "DIRECTORY")
- {
+ cmMakefile* dir = this->Makefile;
+ if (*i == "DIRECTORY") {
++i;
- if (i == args.end())
- {
- this->SetError
- ("DIRECTORY argument provided without subsequent arguments");
+ if (i == args.end()) {
+ this->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->GetStartDirectory();
+ if (!cmSystemTools::FileIsFullPath(sd.c_str())) {
+ sd = this->Makefile->GetCurrentSourceDirectory();
sd += "/";
sd += *i;
- }
+ }
// The local generators are associated with collapsed paths.
- sd = cmSystemTools::CollapseFullPath(sd.c_str());
+ sd = cmSystemTools::CollapseFullPath(sd);
// lookup the makefile from the directory name
- cmLocalGenerator *lg =
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
- FindLocalGenerator(sd.c_str());
- if (!lg)
- {
- this->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.");
+ dir = this->Makefile->GetGlobalGenerator()->FindMakefile(sd);
+ if (!dir) {
+ this->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.");
return false;
- }
- dir = lg->GetMakefile();
- ++i;
}
+ ++i;
+ }
// OK, now we have the directory to process, we just get the requested
// information out of it
- if ( *i == "DEFINITION" )
- {
+ if (*i == "DEFINITION") {
++i;
- if (i == args.end())
- {
+ if (i == args.end()) {
this->SetError("A request for a variable definition was made without "
"providing the name of the variable to get.");
return false;
- }
- output = dir->GetSafeDefinition(i->c_str());
- this->Makefile->AddDefinition(variable.c_str(), output.c_str());
- return true;
}
-
- const char *prop = dir->GetProperty(i->c_str());
- if (prop)
- {
- this->Makefile->AddDefinition(variable.c_str(), prop);
+ std::string output = dir->GetSafeDefinition(*i);
+ this->Makefile->AddDefinition(variable, output.c_str());
return true;
+ }
+
+ const char* prop = CM_NULLPTR;
+ if (!i->empty()) {
+ if (*i == "DEFINITIONS") {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0059)) {
+ case cmPolicies::WARN:
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ this->StoreResult(variable, this->Makefile->GetDefineFlagsCMP0059());
+ return true;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
+ }
}
- this->Makefile->AddDefinition(variable.c_str(), "");
+ prop = dir->GetProperty(*i);
+ }
+ this->StoreResult(variable, prop);
return true;
}
+void cmGetDirectoryPropertyCommand::StoreResult(std::string const& variable,
+ const char* prop)
+{
+ if (prop) {
+ this->Makefile->AddDefinition(variable, prop);
+ return;
+ }
+ this->Makefile->AddDefinition(variable, "");
+}
diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h
index d0d582028..7d9795065 100644
--- a/Source/cmGetDirectoryPropertyCommand.h
+++ b/Source/cmGetDirectoryPropertyCommand.h
@@ -1,78 +1,31 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetDirectoryPropertyCommand_h
#define cmGetDirectoryPropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmGetDirectoryPropertyCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmGetDirectoryPropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetDirectoryPropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_directory_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a property of DIRECTORY scope.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_directory_property(<variable> [DIRECTORY <dir>] <prop-name>)\n"
- "Store a property of directory scope in the named variable. "
- "If the property is not defined the empty-string is returned. "
- "The DIRECTORY argument specifies another directory from which "
- "to retrieve the property value. "
- "The specified directory must have already been traversed by "
- "CMake."
- "\n"
- " get_directory_property(<variable> [DIRECTORY <dir>]\n"
- " DEFINITION <var-name>)\n"
- "Get a variable definition from a directory. "
- "This form is useful to get a variable definition from another "
- "directory."
- "\n"
- "See also the more general get_property() command.";
- }
-
- cmTypeMacro(cmGetDirectoryPropertyCommand, cmCommand);
+private:
+ void StoreResult(const std::string& variable, const char* prop);
};
-
-
#endif
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index 1d7fefcee..c23684c22 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -1,139 +1,110 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetFilenameComponentCommand.h"
+
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
+class cmExecutionStatus;
+
// cmGetFilenameComponentCommand
-bool cmGetFilenameComponentCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmGetFilenameComponentCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->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[3] == "CACHE")
- {
- const char* cacheValue = this->Makefile->GetDefinition(args[0].c_str());
- if(cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue))
- {
+ if (args.size() >= 4 && args[args.size() - 1] == "CACHE") {
+ const char* cacheValue = this->Makefile->GetDefinition(args[0]);
+ if (cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue)) {
return true;
- }
}
+ }
std::string result;
std::string filename = args[1];
- if(filename.find("[HKEY") != filename.npos)
- {
+ if (filename.find("[HKEY") != std::string::npos) {
// 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 (this->Makefile->PlatformIs64Bit()) {
view = cmSystemTools::KeyWOW64_64;
other_view = cmSystemTools::KeyWOW64_32;
- }
+ }
cmSystemTools::ExpandRegistryValues(filename, view);
- if(filename.find("/registry") != filename.npos)
- {
+ if (filename.find("/registry") != std::string::npos) {
std::string other = args[1];
cmSystemTools::ExpandRegistryValues(other, other_view);
- if(other.find("/registry") == other.npos)
- {
+ if (other.find("/registry") == std::string::npos) {
filename = other;
- }
}
}
+ }
std::string storeArgs;
std::string programArgs;
- if (args[2] == "DIRECTORY" || args[2] == "PATH")
- {
+ if (args[2] == "DIRECTORY" || args[2] == "PATH") {
result = cmSystemTools::GetFilenamePath(filename);
- }
- else if (args[2] == "NAME")
- {
+ } else if (args[2] == "NAME") {
result = cmSystemTools::GetFilenameName(filename);
- }
- else if (args[2] == "PROGRAM")
- {
- for(unsigned int i=2; i < args.size(); ++i)
- {
- if(args[i] == "PROGRAM_ARGS")
- {
+ } else if (args[2] == "PROGRAM") {
+ for (unsigned int i = 2; i < args.size(); ++i) {
+ if (args[i] == "PROGRAM_ARGS") {
i++;
- if(i < args.size())
- {
+ if (i < args.size()) {
storeArgs = args[i];
- }
}
}
- cmSystemTools::SplitProgramFromArgs(filename.c_str(),
- result, programArgs);
}
- else if (args[2] == "EXT")
- {
+ cmSystemTools::SplitProgramFromArgs(filename, result, programArgs);
+ } else if (args[2] == "EXT") {
result = cmSystemTools::GetFilenameExtension(filename);
- }
- else if (args[2] == "NAME_WE")
- {
+ } else if (args[2] == "NAME_WE") {
result = cmSystemTools::GetFilenameWithoutExtension(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();
+ for (unsigned int i = 3; i < args.size(); ++i) {
+ if (args[i] == "BASE_DIR") {
+ ++i;
+ if (i < args.size()) {
+ baseDir = args[i];
+ }
+ }
}
- else if (args[2] == "ABSOLUTE" ||
- args[2] == "REALPATH")
- {
// Collapse the path to its simplest form.
- // If the path given is relative evaluate it relative to the
- // current source directory.
- result = cmSystemTools::CollapseFullPath(
- filename.c_str(), this->Makefile->GetCurrentDirectory());
- if(args[2] == "REALPATH")
- {
+ result = cmSystemTools::CollapseFullPath(filename, baseDir);
+ if (args[2] == "REALPATH") {
// Resolve symlinks if possible
- result = cmSystemTools::GetRealPath(result.c_str());
- }
+ result = cmSystemTools::GetRealPath(result);
}
- else
- {
+ } else {
std::string err = "unknown component " + args[2];
- this->SetError(err.c_str());
+ this->SetError(err);
return false;
- }
+ }
- if(args.size() == 4 && args[3] == "CACHE")
- {
- if(programArgs.size() && storeArgs.size())
- {
- this->Makefile->AddCacheDefinition
- (storeArgs.c_str(), programArgs.c_str(),
- "", args[2] == "PATH" ? cmCacheManager::FILEPATH
- : cmCacheManager::STRING);
- }
- this->Makefile->AddCacheDefinition
- (args[0].c_str(), result.c_str(), "",
- args[2] == "PATH" ? cmCacheManager::FILEPATH
- : cmCacheManager::STRING);
+ if (args.size() >= 4 && args[args.size() - 1] == "CACHE") {
+ if (!programArgs.empty() && !storeArgs.empty()) {
+ this->Makefile->AddCacheDefinition(
+ storeArgs, programArgs.c_str(), "",
+ args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
}
- else
- {
- if(programArgs.size() && storeArgs.size())
- {
- this->Makefile->AddDefinition(storeArgs.c_str(), programArgs.c_str());
- }
- this->Makefile->AddDefinition(args[0].c_str(), result.c_str());
+ this->Makefile->AddCacheDefinition(
+ args[0], result.c_str(), "",
+ args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
+ } else {
+ if (!programArgs.empty() && !storeArgs.empty()) {
+ this->Makefile->AddDefinition(storeArgs, programArgs.c_str());
}
+ this->Makefile->AddDefinition(args[0], result.c_str());
+ }
return true;
}
-
diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h
index 09af3325a..c8a23c70e 100644
--- a/Source/cmGetFilenameComponentCommand.h
+++ b/Source/cmGetFilenameComponentCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetFilenameComponentCommand_h
#define cmGetFilenameComponentCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmGetFilenameComponentCommand
* \brief Get a specific component of a filename.
*
@@ -26,68 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmGetFilenameComponentCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetFilenameComponentCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_filename_component";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a specific component of a full filename.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_filename_component(<VAR> <FileName> <COMP> [CACHE])\n"
- "Set <VAR> to a component of <FileName>, where <COMP> is one of:\n"
- " DIRECTORY = Directory without file name\n"
- " NAME = File name without directory\n"
- " EXT = File name longest extension (.b.c from d/a.b.c)\n"
- " NAME_WE = File name without directory or longest extension\n"
- " ABSOLUTE = Full path to file\n"
- " REALPATH = Full path to existing file with symlinks resolved\n"
- " PATH = Legacy alias for DIRECTORY (use for CMake <= 2.8.11)\n"
- "Paths are returned with forward slashes and have no trailing slahes. "
- "The longest file extension is always considered. "
- "If the optional CACHE argument is specified, the result variable is "
- "added to the cache.\n"
- " get_filename_component(<VAR> FileName\n"
- " PROGRAM [PROGRAM_ARGS <ARG_VAR>]\n"
- " [CACHE])\n"
- "The program in FileName will be found in the system search path or "
- "left as a full path. If PROGRAM_ARGS is present with PROGRAM, then "
- "any command-line arguments present in the FileName string are split "
- "from the program name and stored in <ARG_VAR>. This is used to "
- "separate a program name from its arguments in a command line string.";
- }
-
- cmTypeMacro(cmGetFilenameComponentCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index faba7cd35..ddecdf621 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -1,396 +1,366 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetPropertyCommand.h"
-#include "cmake.h"
-#include "cmTest.h"
+#include <sstream>
+
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmSourceFile.h"
+#include "cmInstalledFile.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmPropertyDefinition.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetPropertyComputer.h"
+#include "cmTest.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+class cmMessenger;
-//----------------------------------------------------------------------------
cmGetPropertyCommand::cmGetPropertyCommand()
{
this->InfoType = OutValue;
}
-//----------------------------------------------------------------------------
-bool cmGetPropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// The cmake variable in which to store the result.
this->Variable = args[0];
// Get the scope from which to get the property.
cmProperty::ScopeType scope;
- if(args[1] == "GLOBAL")
- {
+ if (args[1] == "GLOBAL") {
scope = cmProperty::GLOBAL;
- }
- else if(args[1] == "DIRECTORY")
- {
+ } else if (args[1] == "DIRECTORY") {
scope = cmProperty::DIRECTORY;
- }
- else if(args[1] == "TARGET")
- {
+ } else if (args[1] == "TARGET") {
scope = cmProperty::TARGET;
- }
- else if(args[1] == "SOURCE")
- {
+ } else if (args[1] == "SOURCE") {
scope = cmProperty::SOURCE_FILE;
- }
- else if(args[1] == "TEST")
- {
+ } else if (args[1] == "TEST") {
scope = cmProperty::TEST;
- }
- else if(args[1] == "VARIABLE")
- {
+ } else if (args[1] == "VARIABLE") {
scope = cmProperty::VARIABLE;
- }
- else if(args[1] == "CACHE")
- {
+ } else if (args[1] == "CACHE") {
scope = cmProperty::CACHE;
- }
- else
- {
- cmOStringStream e;
+ } 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.";
- this->SetError(e.str().c_str());
+ << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL.";
+ this->SetError(e.str());
return false;
- }
+ }
// Parse remaining arguments.
- enum Doing { DoingNone, DoingName, DoingProperty, DoingType };
+ enum Doing
+ {
+ DoingNone,
+ DoingName,
+ DoingProperty,
+ DoingType
+ };
Doing doing = DoingName;
- for(unsigned int i=2; i < args.size(); ++i)
- {
- if(args[i] == "PROPERTY")
- {
+ for (unsigned int i = 2; i < args.size(); ++i) {
+ if (args[i] == "PROPERTY") {
doing = DoingProperty;
- }
- else if(args[i] == "BRIEF_DOCS")
- {
+ } else if (args[i] == "BRIEF_DOCS") {
doing = DoingNone;
this->InfoType = OutBriefDoc;
- }
- else if(args[i] == "FULL_DOCS")
- {
+ } else if (args[i] == "FULL_DOCS") {
doing = DoingNone;
this->InfoType = OutFullDoc;
- }
- else if(args[i] == "SET")
- {
+ } else if (args[i] == "SET") {
doing = DoingNone;
this->InfoType = OutSet;
- }
- else if(args[i] == "DEFINED")
- {
+ } else if (args[i] == "DEFINED") {
doing = DoingNone;
this->InfoType = OutDefined;
- }
- else if(doing == DoingName)
- {
+ } else if (doing == DoingName) {
doing = DoingNone;
this->Name = args[i];
- }
- else if(doing == DoingProperty)
- {
+ } else if (doing == DoingProperty) {
doing = DoingNone;
this->PropertyName = args[i];
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "given invalid argument \"" << args[i] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Make sure a property name was found.
- if(this->PropertyName.empty())
- {
+ if (this->PropertyName.empty()) {
this->SetError("not given a PROPERTY <name> argument.");
return false;
- }
+ }
// Compute requested output.
- if(this->InfoType == OutBriefDoc)
- {
+ if (this->InfoType == OutBriefDoc) {
// Lookup brief documentation.
std::string output;
- if(cmPropertyDefinition* def =
- this->Makefile->GetCMakeInstance()->
- GetPropertyDefinition(this->PropertyName.c_str(), scope))
- {
+ if (cmPropertyDefinition const* def =
+ this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
+ scope)) {
output = def->GetShortDescription();
- }
- else
- {
+ } else {
output = "NOTFOUND";
- }
- this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
}
- else if(this->InfoType == OutFullDoc)
- {
+ this->Makefile->AddDefinition(this->Variable, output.c_str());
+ } else if (this->InfoType == OutFullDoc) {
// Lookup full documentation.
std::string output;
- if(cmPropertyDefinition* def =
- this->Makefile->GetCMakeInstance()->
- GetPropertyDefinition(this->PropertyName.c_str(), scope))
- {
+ if (cmPropertyDefinition const* def =
+ this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
+ scope)) {
output = def->GetFullDescription();
- }
- else
- {
+ } else {
output = "NOTFOUND";
- }
- this->Makefile->AddDefinition(this->Variable.c_str(), output.c_str());
}
- else if(this->InfoType == OutDefined)
- {
+ this->Makefile->AddDefinition(this->Variable, output.c_str());
+ } else if (this->InfoType == OutDefined) {
// Lookup if the property is defined
- if(this->Makefile->GetCMakeInstance()->
- GetPropertyDefinition(this->PropertyName.c_str(), scope))
- {
- this->Makefile->AddDefinition(this->Variable.c_str(), "1");
- }
- else
- {
- this->Makefile->AddDefinition(this->Variable.c_str(), "0");
- }
+ if (this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
+ scope)) {
+ this->Makefile->AddDefinition(this->Variable, "1");
+ } else {
+ this->Makefile->AddDefinition(this->Variable, "0");
}
- else
- {
+ } else {
// Dispatch property getting.
- switch(scope)
- {
- case cmProperty::GLOBAL: return this->HandleGlobalMode();
- case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
- case cmProperty::TARGET: return this->HandleTargetMode();
- case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
- case cmProperty::TEST: return this->HandleTestMode();
- case cmProperty::VARIABLE: return this->HandleVariableMode();
- case cmProperty::CACHE: return this->HandleCacheMode();
+ switch (scope) {
+ case cmProperty::GLOBAL:
+ return this->HandleGlobalMode();
+ case cmProperty::DIRECTORY:
+ return this->HandleDirectoryMode();
+ case cmProperty::TARGET:
+ return this->HandleTargetMode();
+ case cmProperty::SOURCE_FILE:
+ return this->HandleSourceMode();
+ case cmProperty::TEST:
+ return this->HandleTestMode();
+ case cmProperty::VARIABLE:
+ return this->HandleVariableMode();
+ case cmProperty::CACHE:
+ return this->HandleCacheMode();
+ case cmProperty::INSTALL:
+ return this->HandleInstallMode();
case cmProperty::CACHED_VARIABLE:
break; // should never happen
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::StoreResult(const char* value)
{
- if(this->InfoType == OutSet)
- {
- this->Makefile->AddDefinition(this->Variable.c_str(), value? "1":"0");
- }
- else // if(this->InfoType == OutValue)
- {
- if(value)
- {
- this->Makefile->AddDefinition(this->Variable.c_str(), value);
- }
- else
- {
- this->Makefile->RemoveDefinition(this->Variable.c_str());
- }
+ if (this->InfoType == OutSet) {
+ this->Makefile->AddDefinition(this->Variable, value ? "1" : "0");
+ } else // if(this->InfoType == OutValue)
+ {
+ if (value) {
+ this->Makefile->AddDefinition(this->Variable, value);
+ } else {
+ this->Makefile->RemoveDefinition(this->Variable);
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleGlobalMode()
{
- if(!this->Name.empty())
- {
+ if (!this->Name.empty()) {
this->SetError("given name for GLOBAL scope.");
return false;
- }
+ }
// Get the property.
cmake* cm = this->Makefile->GetCMakeInstance();
- return this->StoreResult(cm->GetProperty(this->PropertyName.c_str()));
+ return this->StoreResult(
+ cm->GetState()->GetGlobalProperty(this->PropertyName));
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleDirectoryMode()
{
// Default to the current directory.
cmMakefile* mf = this->Makefile;
// Lookup the directory if given.
- if(!this->Name.empty())
- {
+ if (!this->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->GetCurrentDirectory();
+ if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
+ dir = this->Makefile->GetCurrentSourceDirectory();
dir += "/";
dir += this->Name;
- }
+ }
// The local generators are associated with collapsed paths.
- dir = cmSystemTools::CollapseFullPath(dir.c_str());
+ dir = cmSystemTools::CollapseFullPath(dir);
// Lookup the generator.
- if(cmLocalGenerator* lg =
- (this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
- {
- // Use the makefile for the directory found.
- mf = lg->GetMakefile();
- }
- else
- {
+ mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
+ if (!mf) {
// Could not find the directory.
- this->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.");
+ this->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.");
return false;
- }
}
+ }
+
+ if (this->PropertyName == "DEFINITIONS") {
+ switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) {
+ case cmPolicies::WARN:
+ mf->IssueMessage(cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ return this->StoreResult(mf->GetDefineFlagsCMP0059());
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
+ }
+ }
// Get the property.
- return this->StoreResult(mf->GetProperty(this->PropertyName.c_str()));
+ return this->StoreResult(mf->GetProperty(this->PropertyName));
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleTargetMode()
{
- if(this->Name.empty())
- {
+ if (this->Name.empty()) {
this->SetError("not given name for TARGET scope.");
return false;
- }
+ }
- if(this->PropertyName == "ALIASED_TARGET")
- {
- if(this->Makefile->IsAlias(this->Name.c_str()))
- {
- if(cmTarget* target =
- this->Makefile->FindTargetToUse(this->Name.c_str()))
- {
- return this->StoreResult(target->GetName());
- }
+ 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());
}
- return false;
+ return this->StoreResult(CM_NULLPTR);
}
- if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
- {
- return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
- }
- else
- {
- cmOStringStream e;
- e << "could not find TARGET " << this->Name
- << ". Perhaps it has not yet been created.";
- this->SetError(e.str().c_str());
- return false;
+ const char* prop_cstr = CM_NULLPTR;
+ cmListFileBacktrace bt = this->Makefile->GetBacktrace();
+ cmMessenger* messenger = this->Makefile->GetMessenger();
+ if (cmTargetPropertyComputer::PassesWhitelist(
+ target->GetType(), this->PropertyName, messenger, bt)) {
+ prop_cstr =
+ target->GetComputedProperty(this->PropertyName, messenger, bt);
+ if (!prop_cstr) {
+ prop_cstr = target->GetProperty(this->PropertyName);
+ }
}
+ return this->StoreResult(prop_cstr);
+ }
+ std::ostringstream e;
+ e << "could not find TARGET " << this->Name
+ << ". Perhaps it has not yet been created.";
+ this->SetError(e.str());
+ return false;
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleSourceMode()
{
- if(this->Name.empty())
- {
+ if (this->Name.empty()) {
this->SetError("not given name for SOURCE scope.");
return false;
- }
+ }
// Get the source file.
- if(cmSourceFile* sf =
- this->Makefile->GetOrCreateSource(this->Name.c_str()))
- {
- return
- this->StoreResult(sf->GetPropertyForUser(this->PropertyName.c_str()));
- }
- else
- {
- cmOStringStream e;
- e << "given SOURCE name that could not be found or created: "
- << this->Name;
- this->SetError(e.str().c_str());
- return false;
- }
+ if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(this->Name)) {
+ return this->StoreResult(sf->GetPropertyForUser(this->PropertyName));
+ }
+ std::ostringstream e;
+ e << "given SOURCE name that could not be found or created: " << this->Name;
+ this->SetError(e.str());
+ return false;
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleTestMode()
{
- if(this->Name.empty())
- {
+ if (this->Name.empty()) {
this->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.c_str()))
- {
- return this->StoreResult(test->GetProperty(this->PropertyName.c_str()));
- }
+ if (cmTest* test = this->Makefile->GetTest(this->Name)) {
+ return this->StoreResult(test->GetProperty(this->PropertyName));
+ }
// If not found it is an error.
- cmOStringStream e;
+ std::ostringstream e;
e << "given TEST name that does not exist: " << this->Name;
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleVariableMode()
{
- if(!this->Name.empty())
- {
+ if (!this->Name.empty()) {
this->SetError("given name for VARIABLE scope.");
return false;
- }
+ }
- return this->StoreResult
- (this->Makefile->GetDefinition(this->PropertyName.c_str()));
+ return this->StoreResult(this->Makefile->GetDefinition(this->PropertyName));
}
-//----------------------------------------------------------------------------
bool cmGetPropertyCommand::HandleCacheMode()
{
- if(this->Name.empty())
- {
+ if (this->Name.empty()) {
this->SetError("not given name for CACHE scope.");
return false;
- }
+ }
- const char* value = 0;
- cmCacheManager::CacheIterator it =
- this->Makefile->GetCacheManager()->GetCacheIterator(this->Name.c_str());
- if(!it.IsAtEnd())
- {
- value = it.GetProperty(this->PropertyName.c_str());
- }
+ const char* value = CM_NULLPTR;
+ if (this->Makefile->GetState()->GetCacheEntryValue(this->Name)) {
+ value = this->Makefile->GetState()->GetCacheEntryProperty(
+ this->Name, this->PropertyName);
+ }
this->StoreResult(value);
return true;
}
+
+bool cmGetPropertyCommand::HandleInstallMode()
+{
+ if (this->Name.empty()) {
+ this->SetError("not given name for INSTALL scope.");
+ return false;
+ }
+
+ // Get the installed file.
+ cmake* cm = this->Makefile->GetCMakeInstance();
+
+ if (cmInstalledFile* file =
+ cm->GetOrCreateInstalledFile(this->Makefile, this->Name)) {
+ std::string value;
+ bool isSet = file->GetProperty(this->PropertyName, value);
+
+ return this->StoreResult(isSet ? value.c_str() : CM_NULLPTR);
+ }
+ std::ostringstream e;
+ e << "given INSTALL name that could not be found or created: " << this->Name;
+ this->SetError(e.str());
+ return false;
+}
diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h
index 3c597fdcf..649780168 100644
--- a/Source/cmGetPropertyCommand.h
+++ b/Source/cmGetPropertyCommand.h
@@ -1,101 +1,40 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetPropertyCommand_h
#define cmGetPropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmGetPropertyCommand : public cmCommand
{
public:
cmGetPropertyCommand();
- virtual cmCommand* Clone()
- {
- return new cmGetPropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetPropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a property.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_property(<variable>\n"
- " <GLOBAL |\n"
- " DIRECTORY [dir] |\n"
- " TARGET <target> |\n"
- " SOURCE <source> |\n"
- " TEST <test> |\n"
- " CACHE <entry> |\n"
- " VARIABLE>\n"
- " PROPERTY <name>\n"
- " [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])\n"
- "Get one property from one object in a scope. "
- "The first argument specifies the variable in which to store the "
- "result. "
- "The second argument determines the scope from which to get the "
- "property. It must be one of the following:\n"
- "GLOBAL scope is unique and does not accept a name.\n"
- "DIRECTORY scope defaults to the current directory but another "
- "directory (already processed by CMake) may be named by full or "
- "relative path.\n"
- "TARGET scope must name one existing target.\n"
- "SOURCE scope must name one source file.\n"
- "TEST scope must name one existing test.\n"
- "CACHE scope must name one cache entry.\n"
- "VARIABLE scope is unique and does not accept a name.\n"
- "The required PROPERTY option is immediately followed by the name "
- "of the property to get. "
- "If the property is not set an empty value is returned. "
- "If the SET option is given the variable is set to a boolean "
- "value indicating whether the property has been set. "
- "If the DEFINED option is given the variable is set to a boolean "
- "value indicating whether the property has been defined "
- "such as with define_property. "
- "If BRIEF_DOCS or FULL_DOCS is given then the variable is set to "
- "a string containing documentation for the requested property. "
- "If documentation is requested for a property that has not been "
- "defined NOTFOUND is returned.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- cmTypeMacro(cmGetPropertyCommand, cmCommand);
private:
- enum OutType { OutValue, OutDefined, OutBriefDoc, OutFullDoc, OutSet };
+ enum OutType
+ {
+ OutValue,
+ OutDefined,
+ OutBriefDoc,
+ OutFullDoc,
+ OutSet
+ };
std::string Variable;
std::string Name;
std::string PropertyName;
@@ -112,6 +51,7 @@ private:
bool HandleTestMode();
bool HandleVariableMode();
bool HandleCacheMode();
+ bool HandleInstallMode();
};
#endif
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index 3d85e6d7d..1a5f08ef8 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -1,52 +1,43 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetSourceFilePropertyCommand.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
+class cmExecutionStatus;
+
// cmSetSourceFilePropertyCommand
-bool cmGetSourceFilePropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmGetSourceFilePropertyCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() != 3 )
- {
+ if (args.size() != 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- const char* var = args[0].c_str();
- const char* file = args[1].c_str();
+ }
+ std::string const& var = args[0];
+ std::string const& file = args[1];
cmSourceFile* sf = this->Makefile->GetSource(file);
// for the location we must create a source file first
- if (!sf && args[2] == "LOCATION")
- {
- sf = this->Makefile->GetOrCreateSource(file);
- }
- if(sf)
- {
- if(args[2] == "LANGUAGE")
- {
- this->Makefile->AddDefinition(var, sf->GetLanguage());
+ if (!sf && args[2] == "LOCATION") {
+ sf = this->Makefile->CreateSource(file);
+ }
+ if (sf) {
+ if (args[2] == "LANGUAGE") {
+ this->Makefile->AddDefinition(var, sf->GetLanguage().c_str());
return true;
- }
- const char *prop = sf->GetPropertyForUser(args[2].c_str());
- if (prop)
- {
+ }
+ const char* prop = CM_NULLPTR;
+ if (!args[2].empty()) {
+ prop = sf->GetPropertyForUser(args[2]);
+ }
+ if (prop) {
this->Makefile->AddDefinition(var, prop);
return true;
- }
}
+ }
this->Makefile->AddDefinition(var, "NOTFOUND");
return true;
}
-
diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h
index 2ba81037f..e96bb29ed 100644
--- a/Source/cmGetSourceFilePropertyCommand.h
+++ b/Source/cmGetSourceFilePropertyCommand.h
@@ -1,66 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetSourceFilePropertyCommand_h
#define cmGetSourceFilePropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmGetSourceFilePropertyCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmGetSourceFilePropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetSourceFilePropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_source_file_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a property for a source file.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_source_file_property(VAR file property)\n"
- "Get a property from a source file. The value of the property is "
- "stored in the variable VAR. If the property is not found, VAR "
- "will be set to \"NOTFOUND\". Use set_source_files_properties to set "
- "property values. Source file properties usually control how the "
- "file is built. One property that is always there is LOCATION"
- "\n"
- "See also the more general get_property() command.";
- }
-
- cmTypeMacro(cmGetSourceFilePropertyCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 02f00a508..0910a5324 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -1,52 +1,83 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGetTargetPropertyCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmGetTargetPropertyCommand.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.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::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() != 3 )
- {
+ if (args.size() != 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- std::string var = args[0].c_str();
- const char* targetName = args[1].c_str();
- const char *prop = 0;
+ }
+ std::string const& var = args[0];
+ std::string const& targetName = args[1];
+ std::string prop;
+ bool prop_exists = false;
- if(args[2] == "ALIASED_TARGET")
- {
- if(this->Makefile->IsAlias(targetName))
- {
- if(cmTarget* target =
- this->Makefile->FindTargetToUse(targetName))
- {
- prop = target->GetName();
+ if (cmTarget* tgt = this->Makefile->FindTargetToUse(targetName)) {
+ if (args[2] == "ALIASED_TARGET") {
+ if (this->Makefile->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();
+ if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2],
+ messenger, bt)) {
+ prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
+ if (!prop_cstr) {
+ prop_cstr = tgt->GetProperty(args[2]);
}
}
+ if (prop_cstr) {
+ prop = prop_cstr;
+ prop_exists = true;
+ }
}
- else if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
- {
- cmTarget& target = *tgt;
- prop = target.GetProperty(args[2].c_str());
+ } else {
+ bool issueMessage = false;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0045)) {
+ case cmPolicies::WARN:
+ issueMessage = true;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0045) << "\n";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ issueMessage = true;
+ messageType = cmake::FATAL_ERROR;
}
-
- if (prop)
- {
- this->Makefile->AddDefinition(var.c_str(), prop);
- return true;
+ if (issueMessage) {
+ e << "get_target_property() called with non-existent target \""
+ << targetName << "\".";
+ this->Makefile->IssueMessage(messageType, e.str());
+ if (messageType == cmake::FATAL_ERROR) {
+ return false;
+ }
}
- this->Makefile->AddDefinition(var.c_str(), (var+"-NOTFOUND").c_str());
+ }
+ if (prop_exists) {
+ this->Makefile->AddDefinition(var, prop.c_str());
+ return true;
+ }
+ this->Makefile->AddDefinition(var, (var + "-NOTFOUND").c_str());
return true;
}
-
diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h
index f5e1aa729..5de322563 100644
--- a/Source/cmGetTargetPropertyCommand.h
+++ b/Source/cmGetTargetPropertyCommand.h
@@ -1,68 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetTargetPropertyCommand_h
#define cmGetTargetPropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmGetTargetPropertyCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmGetTargetPropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetTargetPropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_target_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a property from a target.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_target_property(VAR target property)\n"
- "Get a property from a target. The value of the property is "
- "stored in the variable VAR. If the property is not found, VAR "
- "will be set to \"NOTFOUND\". Use set_target_properties to set "
- "property values. Properties are usually used to control how "
- "a target is built, but some query the target instead. "
- "This command can get properties for any target so far created. "
- "The targets do not need to be in the current CMakeLists.txt file."
- "\n"
- "See also the more general get_property() command.";
- }
-
- cmTypeMacro(cmGetTargetPropertyCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index 0e0e2c09b..6424515ec 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -1,42 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetTestPropertyCommand.h"
-#include "cmake.h"
+#include "cmMakefile.h"
#include "cmTest.h"
+class cmExecutionStatus;
+
// cmGetTestPropertyCommand
-bool cmGetTestPropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmGetTestPropertyCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- std::string testName = args[0];
- std::string var = args[2];
- cmTest *test = this->Makefile->GetTest(testName.c_str());
- if (test)
- {
- const char *prop = test->GetProperty(args[1].c_str());
- if (prop)
- {
- this->Makefile->AddDefinition(var.c_str(), prop);
+ std::string const& testName = args[0];
+ std::string const& var = args[2];
+ cmTest* test = this->Makefile->GetTest(testName);
+ if (test) {
+ const char* prop = CM_NULLPTR;
+ if (!args[1].empty()) {
+ prop = test->GetProperty(args[1]);
+ }
+ if (prop) {
+ this->Makefile->AddDefinition(var, prop);
return true;
- }
}
- this->Makefile->AddDefinition(var.c_str(), "NOTFOUND");
+ }
+ this->Makefile->AddDefinition(var, "NOTFOUND");
return true;
}
-
diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h
index 01f54d951..b17e7a1cc 100644
--- a/Source/cmGetTestPropertyCommand.h
+++ b/Source/cmGetTestPropertyCommand.h
@@ -1,65 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGetTestPropertyCommand_h
#define cmGetTestPropertyCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
class cmGetTestPropertyCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmGetTestPropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmGetTestPropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "get_test_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Get a property of the test.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " get_test_property(test property VAR)\n"
- "Get a property from the Test. The value of the property is "
- "stored in the variable VAR. If the property is not found, VAR "
- "will be set to \"NOTFOUND\". For a list of standard properties "
- "you can type cmake --help-property-list"
- "\n"
- "See also the more general get_property() command.";
- }
-
- cmTypeMacro(cmGetTestPropertyCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx
new file mode 100644
index 000000000..f58cfc1e5
--- /dev/null
+++ b/Source/cmGhsMultiGpj.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 "cmGhsMultiGpj.h"
+
+#include "cmGeneratedFileStream.h"
+
+void GhsMultiGpj::WriteGpjTag(Types const gpjType,
+ cmGeneratedFileStream* const filestream)
+{
+ 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";
+ break;
+ default:
+ tag = "";
+ }
+ *filestream << "[" << tag << "]" << std::endl;
+}
diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h
new file mode 100644
index 000000000..7bc7bfc46
--- /dev/null
+++ b/Source/cmGhsMultiGpj.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 cmGhsMultiGpj_h
+#define cmGhsMultiGpj_h
+
+#include "cmConfigure.h"
+
+class cmGeneratedFileStream;
+
+class GhsMultiGpj
+{
+public:
+ enum Types
+ {
+ INTERGRITY_APPLICATION,
+ LIBRARY,
+ PROJECT,
+ PROGRAM,
+ REFERENCE,
+ SUBPROJECT
+ };
+
+ static void WriteGpjTag(Types const gpjType,
+ cmGeneratedFileStream* filestream);
+};
+
+#endif // ! cmGhsMultiGpjType_h
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
new file mode 100644
index 000000000..7032cd582
--- /dev/null
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -0,0 +1,661 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGhsMultiTargetGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGhsMultiGenerator.h"
+#include "cmLinkLineComputer.h"
+#include "cmLocalGhsMultiGenerator.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.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 += "/";
+ }
+ 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;
+}
+
+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());
+ }
+ 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";
+ }
+ 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;
+ }
+ 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);
+ }
+ this->WriteCustomCommands();
+
+ std::map<const cmSourceFile*, std::string> objectNames =
+ cmGhsMultiTargetGenerator::GetObjectNames(
+ &objectSources, this->LocalGenerator, this->GeneratorTarget);
+
+ this->WriteSources(objectSources, objectNames);
+ }
+}
+
+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;
+}
+
+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;
+}
+
+GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const
+{
+ return cmGhsMultiTargetGenerator::GetGpjTag(this->GeneratorTarget);
+}
+
+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;
+ }
+ return output;
+}
+
+cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator()
+ const
+{
+ return static_cast<cmGlobalGhsMultiGenerator*>(
+ this->LocalGenerator->GetGlobalGenerator());
+}
+
+void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string& config,
+ bool const notKernel)
+{
+ 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;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
+ const std::string& language,
+ bool const notKernel)
+{
+ std::map<std::string, std::string>::iterator 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->AddCMP0018Flags(flags, this->GeneratorTarget, lang,
+ config);
+ this->LocalGenerator->AddVisibilityPresetFlags(
+ flags, this->GeneratorTarget, lang);
+
+ // Append old-style preprocessor definition flags.
+ if (this->Makefile->GetDefineFlags() != " ") {
+ this->LocalGenerator->AppendFlags(flags,
+ this->Makefile->GetDefineFlags());
+ }
+
+ // Add target-specific flags.
+ this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, lang,
+ config);
+
+ std::map<std::string, std::string>::value_type entry(language, flags);
+ i = this->FlagsByLanguage.insert(entry).first;
+ }
+}
+
+std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language,
+ std::string const& config)
+{
+ std::map<std::string, std::string>::iterator 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);
+
+ std::string definesString;
+ this->LocalGenerator->JoinDefines(defines, definesString, lang);
+
+ std::map<std::string, std::string>::value_type entry(language,
+ definesString);
+ i = this->DefinesByLanguage.insert(entry).first;
+ }
+ return i->second;
+}
+
+void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const&,
+ const std::string& language)
+{
+ std::map<std::string, std::string>::iterator flagsByLangI =
+ this->FlagsByLanguage.find(language);
+ if (flagsByLangI != this->FlagsByLanguage.end()) {
+ if (!flagsByLangI->second.empty()) {
+ *this->GetFolderBuildStreams() << " " << flagsByLangI->second
+ << std::endl;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
+ 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;
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteIncludes(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;
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries(
+ std::string const& config, std::string const& language)
+{
+ // 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->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;
+ }
+
+ if (!linkFlags.empty()) {
+ *this->GetFolderBuildStreams() << " " << linkFlags << std::endl;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteCustomCommands()
+{
+ WriteCustomCommandsHelper(this->GeneratorTarget->GetPreBuildCommands(),
+ cmTarget::PRE_BUILD);
+ WriteCustomCommandsHelper(this->GeneratorTarget->GetPostBuildCommands(),
+ cmTarget::POST_BUILD);
+}
+
+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::map<const cmSourceFile*, std::string>
+cmGhsMultiTargetGenerator::GetObjectNames(
+ std::vector<cmSourceFile*>* const objectSources,
+ cmLocalGhsMultiGenerator* const localGhsMultiGenerator,
+ cmGeneratorTarget* const generatorTarget)
+{
+ 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;
+
+ 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;
+ }
+
+ return objectNamesCorrected;
+}
+
+void cmGhsMultiTargetGenerator::WriteSources(
+ std::vector<cmSourceFile*> const& objectSources,
+ std::map<const cmSourceFile*, std::string> const& objectNames)
+{
+ 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;
+ }
+
+ 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;
+ }
+
+ this->WriteObjectDir(this->FolderBuildStreams[sgPath],
+ this->AbsBuildFilePath + sgPath);
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
+ cmGeneratedFileStream* fileStream, cmSourceFile* sourceFile)
+{
+ 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;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteObjectDir(
+ cmGeneratedFileStream* fileStream, std::string const& dir)
+{
+ std::string workingDir(dir);
+ cmSystemTools::ConvertToUnixSlashes(workingDir);
+ if (!workingDir.empty()) {
+ workingDir += "/";
+ }
+ workingDir += "Objs";
+ *fileStream << " -object_dir=\"" << workingDir << "\"" << std::endl;
+}
+
+std::string cmGhsMultiTargetGenerator::GetOutputDirectory(
+ const std::string& config) const
+{
+ std::string outputDir(AbsBuildFilePath);
+
+ const char* runtimeOutputProp =
+ this->GeneratorTarget->GetProperty("RUNTIME_OUTPUT_DIRECTORY");
+ if (NULL != runtimeOutputProp) {
+ outputDir = runtimeOutputProp;
+ }
+
+ std::string configCapped(cmSystemTools::UpperCase(config));
+ const char* runtimeOutputSProp = this->GeneratorTarget->GetProperty(
+ "RUNTIME_OUTPUT_DIRECTORY_" + configCapped);
+ if (NULL != runtimeOutputSProp) {
+ outputDir = runtimeOutputSProp;
+ }
+ cmSystemTools::ConvertToUnixSlashes(outputDir);
+
+ if (!outputDir.empty()) {
+ outputDir += "/";
+ }
+
+ return outputDir;
+}
+
+std::string cmGhsMultiTargetGenerator::GetOutputFilename(
+ const std::string& config) const
+{
+ std::string outputFilename(this->GeneratorTarget->GetName());
+
+ const char* outputNameProp =
+ this->GeneratorTarget->GetProperty("OUTPUT_NAME");
+ if (NULL != outputNameProp) {
+ outputFilename = outputNameProp;
+ }
+
+ std::string configCapped(cmSystemTools::UpperCase(config));
+ const char* outputNameSProp =
+ this->GeneratorTarget->GetProperty(configCapped + "_OUTPUT_NAME");
+ if (NULL != outputNameSProp) {
+ outputFilename = outputNameSProp;
+ }
+
+ return outputFilename;
+}
+
+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;
+}
+
+bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const& config,
+ const std::string& language)
+{
+ 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;
+}
+
+bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup(
+ const cmGeneratorTarget* target)
+{
+ bool output = false;
+ 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;
+ }
+ }
+ return output;
+}
+
+bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload(
+ std::string const& config, const std::string& language)
+{
+ 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;
+ }
+ }
+ return output;
+}
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
new file mode 100644
index 000000000..2cdf68e11
--- /dev/null
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -0,0 +1,120 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGhsMultiTargetGenerator_h
+#define cmGhsMultiTargetGenerator_h
+
+#include "cmGhsMultiGpj.h"
+
+#include "cmTarget.h"
+
+class cmCustomCommand;
+class cmGeneratedFileStream;
+class cmGeneratorTarget;
+class cmGlobalGhsMultiGenerator;
+class cmLocalGhsMultiGenerator;
+class cmMakefile;
+class cmSourceFile;
+
+class cmGhsMultiTargetGenerator
+{
+public:
+ cmGhsMultiTargetGenerator(cmGeneratorTarget* target);
+
+ virtual ~cmGhsMultiTargetGenerator();
+
+ 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,
+ const std::string& language);
+ void WriteCompilerDefinitions(const std::string& config,
+ const std::string& language);
+
+ void SetCompilerFlags(std::string const& config, const std::string& language,
+ bool const notKernel);
+ 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);
+
+ 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;
+};
+
+#endif // ! cmGhsMultiTargetGenerator_h
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 2a7d61d6a..d2372a766 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -1,35 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalBorlandMakefileGenerator.h"
+
+#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmState.h"
#include "cmake.h"
-cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator()
+cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator(cmake* cm)
+ : cmGlobalUnixMakefileGenerator3(cm)
{
this->EmptyRuleHackDepends = "NUL";
this->FindMakeProgramFile = "CMakeBorlandFindMake.cmake";
this->ForceUnixPaths = false;
this->ToolSupportsColor = true;
this->UseLinkScript = false;
+ cm->GetState()->SetWindowsShell(true);
+ this->IncludeDirective = "!include";
+ this->DefineWindowsNULL = true;
+ this->PassMakeflags = true;
+ this->UnixCD = false;
}
-
-void cmGlobalBorlandMakefileGenerator
-::EnableLanguage(std::vector<std::string>const& l,
- cmMakefile *mf,
- bool optional)
+void cmGlobalBorlandMakefileGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
- std::string outdir = this->CMakeInstance->GetStartOutputDirectory();
+ std::string outdir = this->CMakeInstance->GetHomeOutputDirectory();
mf->AddDefinition("BORLAND", "1");
mf->AddDefinition("CMAKE_GENERATOR_CC", "bcc32");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "bcc32");
@@ -37,27 +34,20 @@ void cmGlobalBorlandMakefileGenerator
}
///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(
+ cmMakefile* mf)
{
- cmLocalUnixMakefileGenerator3* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetIncludeDirective("!include");
- lg->SetWindowsShell(true);
- lg->SetDefineWindowsNULL(true);
+ cmLocalUnixMakefileGenerator3* lg =
+ new cmLocalUnixMakefileGenerator3(this, mf);
lg->SetMakefileVariableSize(32);
- lg->SetPassMakeflags(true);
- lg->SetGlobalGenerator(this);
- lg->SetUnixCD(false);
lg->SetMakeCommandEscapeTargetTwice(true);
lg->SetBorlandMakeCurlyHack(true);
return lg;
}
-
-//----------------------------------------------------------------------------
-void cmGlobalBorlandMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalBorlandMakefileGenerator::GetDocumentation(
+ cmDocumentationEntry& entry)
{
entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName();
entry.Brief = "Generates Borland makefiles.";
- entry.Full = "";
}
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index bd3db3eae..5578d7646 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalBorlandMakefileGenerator_h
#define cmGlobalBorlandMakefileGenerator_h
@@ -19,31 +10,38 @@
*
* cmGlobalBorlandMakefileGenerator manages nmake build process for a tree
*/
-class cmGlobalBorlandMakefileGenerator : public cmGlobalNMakeMakefileGenerator
+class cmGlobalBorlandMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
- cmGlobalBorlandMakefileGenerator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalBorlandMakefileGenerator>(); }
+ cmGlobalBorlandMakefileGenerator(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<
+ cmGlobalBorlandMakefileGenerator>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalBorlandMakefileGenerator::GetActualName();}
- static const char* GetActualName() {return "Borland Makefiles";}
+ virtual std::string GetName() const
+ {
+ return cmGlobalBorlandMakefileGenerator::GetActualName();
+ }
+ static std::string GetActualName() { return "Borland Makefiles"; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
+
+ virtual bool AllowNotParallel() const { return false; }
+ virtual bool AllowDeleteOnError() const { return false; }
};
#endif
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
new file mode 100644
index 000000000..3b7de4b9c
--- /dev/null
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalCommonGenerator.h"
+
+class cmake;
+
+cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
+ : cmGlobalGenerator(cm)
+{
+}
+
+cmGlobalCommonGenerator::~cmGlobalCommonGenerator()
+{
+}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
new file mode 100644
index 000000000..f2ad059de
--- /dev/null
+++ b/Source/cmGlobalCommonGenerator.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 cmGlobalCommonGenerator_h
+#define cmGlobalCommonGenerator_h
+
+#include "cmConfigure.h"
+
+#include "cmGlobalGenerator.h"
+
+class cmake;
+
+/** \class cmGlobalCommonGenerator
+ * \brief Common infrastructure for Makefile and Ninja global generators.
+ */
+class cmGlobalCommonGenerator : public cmGlobalGenerator
+{
+public:
+ cmGlobalCommonGenerator(cmake* cm);
+ ~cmGlobalCommonGenerator() CM_OVERRIDE;
+};
+
+#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index f297c4abb..099f705f4 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1,44 +1,75 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "windows.h" // this must be first to define GetCurrentDirectory
+#include <windows.h>
#endif
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
+#include "cmAlgorithms.h"
+#include "cmCPackPropertiesGenerator.h"
+#include "cmComputeTargetDepends.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
+#include "cmExportBuildFileGenerator.h"
#include "cmExternalMakefileProjectGenerator.h"
-#include "cmake.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmInstallGenerator.h"
+#include "cmLinkLineComputer.h"
+#include "cmLocalGenerator.h"
+#include "cmMSVC60LinkLineComputer.h"
#include "cmMakefile.h"
-#include "cmQtAutomoc.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmQtAutoGeneratorInitializer.h"
#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateTypes.h"
#include "cmVersion.h"
-#include "cmTargetExport.h"
-#include "cmComputeTargetDepends.h"
-#include "cmGeneratedFileStream.h"
-#include "cmGeneratorTarget.h"
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorExpressionEvaluationFile.h"
-
-#include <cmsys/Directory.hxx>
+#include "cmWorkingDirectory.h"
+#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <cmsys/MD5.h>
+#include "cmCryptoHash.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
-#include <stdlib.h> // required for atof
+const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
+ "CMAKE_PLATFORM_INFO_INITIALIZED";
-#include <assert.h>
+class cmInstalledFile;
+
+bool cmTarget::StrictTargetComparison::operator()(cmTarget const* t1,
+ cmTarget const* t2) const
+{
+ int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
+ if (nameResult == 0) {
+ return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory(),
+ t2->GetMakefile()->GetCurrentBinaryDirectory()) < 0;
+ }
+ return nameResult < 0;
+}
-cmGlobalGenerator::cmGlobalGenerator()
+cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
+ : CMakeInstance(cm)
{
// By default the .SYMBOLIC dependency is not needed on symbolic rules.
this->NeedSymbolicMark = false;
@@ -58,193 +89,243 @@ cmGlobalGenerator::cmGlobalGenerator()
// how long to let try compiles run
this->TryCompileTimeout = 0;
- this->ExtraGenerator = 0;
- this->CurrentLocalGenerator = 0;
- this->TryCompileOuterMakefile = 0;
+ this->ExtraGenerator = CM_NULLPTR;
+ this->CurrentMakefile = CM_NULLPTR;
+ this->TryCompileOuterMakefile = CM_NULLPTR;
+
+ this->ConfigureDoneCMP0026AndCMP0024 = false;
+ this->FirstTimeProgress = 0.0f;
+
+ cm->GetState()->SetIsGeneratorMultiConfig(false);
+ cm->GetState()->SetMinGWMake(false);
+ cm->GetState()->SetMSYSShell(false);
+ cm->GetState()->SetNMake(false);
+ cm->GetState()->SetWatcomWMake(false);
+ cm->GetState()->SetWindowsShell(false);
+ cm->GetState()->SetWindowsVSIDE(false);
}
cmGlobalGenerator::~cmGlobalGenerator()
{
- // Delete any existing cmLocalGenerators
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
- {
- delete this->LocalGenerators[i];
- }
- for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
- li = this->EvaluationFiles.begin();
- li != this->EvaluationFiles.end();
- ++li)
- {
- delete *li;
- }
- this->LocalGenerators.clear();
+ this->ClearGeneratorMembers();
+ delete this->ExtraGenerator;
+}
- if (this->ExtraGenerator)
- {
- delete this->ExtraGenerator;
- }
+bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
+ cmMakefile* mf)
+{
+ if (p.empty()) {
+ return true;
+ }
- this->ClearGeneratorTargets();
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "does not support platform specification, but platform\n"
+ " " << p << "\n"
+ "was specified.";
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
}
-bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts)
+bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts,
+ cmMakefile* mf)
{
- cmOStringStream e;
+ if (ts.empty()) {
+ return true;
+ }
+ std::ostringstream e;
+ /* clang-format off */
e <<
"Generator\n"
" " << this->GetName() << "\n"
"does not support toolset specification, but toolset\n"
" " << ts << "\n"
"was specified.";
- this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
- cmListFileBacktrace());
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
-void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
- cmMakefile *mf,
- bool optional)
+std::string cmGlobalGenerator::SelectMakeProgram(
+ const std::string& inMakeProgram, const std::string& makeDefault) const
+{
+ std::string makeProgram = inMakeProgram;
+ if (cmSystemTools::IsOff(makeProgram.c_str())) {
+ const char* makeProgramCSTR =
+ this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
+ if (cmSystemTools::IsOff(makeProgramCSTR)) {
+ makeProgram = makeDefault;
+ } else {
+ makeProgram = makeProgramCSTR;
+ }
+ if (cmSystemTools::IsOff(makeProgram.c_str()) && !makeProgram.empty()) {
+ makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND";
+ }
+ }
+ return makeProgram;
+}
+
+void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
+ cmMakefile* mf,
+ bool optional) const
{
std::string langComp = "CMAKE_";
langComp += lang;
langComp += "_COMPILER";
- if(!mf->GetDefinition(langComp.c_str()))
- {
- if(!optional)
- {
- cmSystemTools::Error(langComp.c_str(),
- " not set, after EnableLanguage");
- }
- return;
+ if (!mf->GetDefinition(langComp)) {
+ if (!optional) {
+ cmSystemTools::Error(langComp.c_str(), " not set, after EnableLanguage");
}
- const char* name = mf->GetRequiredDefinition(langComp.c_str());
+ return;
+ }
+ const char* name = mf->GetRequiredDefinition(langComp);
std::string path;
- if(!cmSystemTools::FileIsFullPath(name))
- {
+ if (!cmSystemTools::FileIsFullPath(name)) {
path = cmSystemTools::FindProgram(name);
- }
- else
- {
+ } else {
path = name;
- }
- if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
- && (optional==false))
- {
- std::string message = "your ";
- message += lang;
- message += " compiler: \"";
- message += name;
- message += "\" was not found. Please set ";
- message += langComp;
- message += " to a valid compiler path or name.";
- cmSystemTools::Error(message.c_str());
- path = name;
- }
- std::string doc = lang;
- doc += " compiler.";
- const char* cname = this->GetCMakeInstance()->
- GetCacheManager()->GetCacheValue(langComp.c_str());
+ }
+ if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) {
+ return;
+ }
+ const char* cname =
+ this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
std::string changeVars;
- if(cname && (path != cname) && (optional==false))
- {
- std::string cnameString = cname;
+ if (cname && !optional) {
+ std::string cnameString;
+ if (!cmSystemTools::FileIsFullPath(cname)) {
+ cnameString = cmSystemTools::FindProgram(cname);
+ } else {
+ cnameString = cname;
+ }
std::string pathString = path;
// get rid of potentially multiple slashes:
cmSystemTools::ConvertToUnixSlashes(cnameString);
cmSystemTools::ConvertToUnixSlashes(pathString);
- if (cnameString != pathString)
- {
+ if (cnameString != pathString) {
const char* cvars =
- this->GetCMakeInstance()->GetProperty(
+ this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"__CMAKE_DELETE_CACHE_CHANGE_VARS_");
- if(cvars)
- {
+ if (cvars) {
changeVars += cvars;
changeVars += ";";
- }
+ }
changeVars += langComp;
changeVars += ";";
changeVars += cname;
- this->GetCMakeInstance()->SetProperty(
- "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
- changeVars.c_str());
+ this->GetCMakeInstance()->GetState()->SetGlobalProperty(
+ "__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars.c_str());
+ }
+ }
+}
+
+void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen)
+{
+ this->BuildExportSets[gen->GetMainExportFileName()] = gen;
+}
+
+void cmGlobalGenerator::AddBuildExportExportSet(
+ cmExportBuildFileGenerator* gen)
+{
+ this->BuildExportSets[gen->GetMainExportFileName()] = gen;
+ this->BuildExportExportSets[gen->GetMainExportFileName()] = gen;
+}
+
+bool cmGlobalGenerator::GenerateImportFile(const std::string& file)
+{
+ std::map<std::string, cmExportBuildFileGenerator*>::iterator 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);
}
}
- mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
- doc.c_str(), cmCacheManager::FILEPATH);
+
+ delete it->second;
+ it->second = CM_NULLPTR;
+ this->BuildExportSets.erase(it);
+ return result;
+ }
+ return false;
+}
+
+void cmGlobalGenerator::ForceLinkerLanguages()
+{
+}
+
+bool cmGlobalGenerator::IsExportedTargetsFile(
+ const std::string& filename) const
+{
+ const std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it =
+ this->BuildExportSets.find(filename);
+ if (it == this->BuildExportSets.end()) {
+ return false;
+ }
+ return this->BuildExportExportSets.find(filename) ==
+ this->BuildExportExportSets.end();
}
// Find the make program for the generator, required for try compiles
-void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
+bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
{
- if(this->FindMakeProgramFile.size() == 0)
- {
+ if (this->FindMakeProgramFile.empty()) {
cmSystemTools::Error(
"Generator implementation error, "
"all generators must specify this->FindMakeProgramFile");
- }
- if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
- || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
- {
+ return false;
+ }
+ if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") ||
+ cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
std::string setMakeProgram =
mf->GetModulesFile(this->FindMakeProgramFile.c_str());
- if(setMakeProgram.size())
- {
- mf->ReadListFile(0, setMakeProgram.c_str());
- }
+ if (!setMakeProgram.empty()) {
+ mf->ReadListFile(setMakeProgram.c_str());
}
- if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
- || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
- {
- cmOStringStream err;
+ }
+ if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") ||
+ cmSystemTools::IsOff(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::SetFatalErrorOccured();
- return;
- }
+ return false;
+ }
std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
// if there are spaces in the make program use short path
// but do not short path the actual program name, as
// this can cause trouble with VSExpress
- if(makeProgram.find(' ') != makeProgram.npos)
- {
+ if (makeProgram.find(' ') != std::string::npos) {
std::string dir;
std::string file;
- cmSystemTools::SplitProgramPath(makeProgram.c_str(),
- dir, file);
+ cmSystemTools::SplitProgramPath(makeProgram, dir, file);
std::string saveFile = file;
- cmSystemTools::GetShortPath(makeProgram.c_str(), makeProgram);
- cmSystemTools::SplitProgramPath(makeProgram.c_str(),
- dir, file);
+ cmSystemTools::GetShortPath(makeProgram, makeProgram);
+ cmSystemTools::SplitProgramPath(makeProgram, dir, file);
makeProgram = dir;
makeProgram += "/";
makeProgram += saveFile;
mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
- "make program",
- cmCacheManager::FILEPATH);
- }
-
- if(makeProgram.find("xcodebuild") != makeProgram.npos)
- {
- // due to the text file busy /bin/sh problem with xcodebuild
- // use the cmakexbuild wrapper instead. This program
- // will run xcodebuild and if it sees the error text file busy
- // it will stop forwarding output, and let the build finish.
- // Then it will retry the build. It will continue this
- // untill no text file busy errors occur.
- std::string cmakexbuild =
- this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND");
- cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5);
- cmakexbuild += "cmakexbuild";
+ "make program", cmStateEnums::FILEPATH);
+ }
+ return true;
+}
- mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM",
- cmakexbuild.c_str(),
- "make program",
- cmCacheManager::FILEPATH);
- }
+bool cmGlobalGenerator::CheckLanguages(
+ std::vector<std::string> const& /* languages */, cmMakefile* /* mf */) const
+{
+ return true;
}
// enable the given language
@@ -260,6 +341,9 @@ void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
// CMakeSystem.cmake - configured file created by
// CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
+// CMakeSystemSpecificInitialize.cmake
+// - includes Platform/${CMAKE_SYSTEM_NAME}-Initialize.cmake
+
// Next try and enable all languages found in the languages vector
//
// FOREACH LANG in languages
@@ -289,120 +373,187 @@ void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
//
//
-void
-cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *mf, bool)
+void cmGlobalGenerator::EnableLanguage(
+ std::vector<std::string> const& languages, cmMakefile* mf, bool optional)
{
- if(languages.size() == 0)
- {
+ if (languages.empty()) {
cmSystemTools::Error("EnableLanguage must have a lang specified!");
cmSystemTools::SetFatalErrorOccured();
return;
+ }
+
+ 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) {
+ std::ostringstream e;
+ e << "Language '" << *li << "' is currently being enabled. "
+ "Recursive call not allowed.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return;
}
+ }
- if(this->TryCompileOuterMakefile)
- {
+ 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::vector<std::string>::const_iterator li = languages.begin();
+ li != languages.end(); ++li) {
+ if (*li == "NONE") {
this->SetLanguageEnabled("NONE", mf);
- }
- else
- {
+ } else {
const char* lang = li->c_str();
- if(this->LanguagesReady.find(lang) == this->LanguagesReady.end())
- {
- cmOStringStream e;
- e << "The test project needs language "
- << lang << " which is not enabled.";
- this->TryCompileOuterMakefile
- ->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (this->LanguagesReady.find(lang) == this->LanguagesReady.end()) {
+ std::ostringstream e;
+ e << "The test project needs language " << lang
+ << " which is not enabled.";
+ this->TryCompileOuterMakefile->IssueMessage(cmake::FATAL_ERROR,
+ e.str());
cmSystemTools::SetFatalErrorOccured();
return;
- }
}
}
}
+ }
+
+ bool fatalError = false;
mf->AddDefinition("RUN_CONFIGURE", true);
- std::string rootBin = mf->GetHomeOutputDirectory();
+ std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory();
rootBin += cmake::GetCMakeFilesDirectory();
// If the configuration files path has been set,
// then we are in a try compile and need to copy the enable language
// files from the parent cmake bin dir, into the try compile bin dir
- if(this->ConfiguredFilesPath.size())
- {
+ if (!this->ConfiguredFilesPath.empty()) {
rootBin = this->ConfiguredFilesPath;
- }
+ }
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.c_str());
+
+ if (!this->CMakeInstance->GetIsInTryCompile()) {
+ // Keep a mark in the cache to indicate that we've initialized the
+ // platform information directory. If the platform information
+ // directory exists but the mark is missing then CMakeCache.txt
+ // has been removed or replaced without also removing the CMakeFiles/
+ // directory. In this case remove the platform information directory
+ // so that it will be re-initialized and the relevant information
+ // restored in the cache.
+ if (cmSystemTools::FileIsDirectory(rootBin) &&
+ !mf->IsOn(kCMAKE_PLATFORM_INFO_INITIALIZED)) {
+ cmSystemTools::RemoveADirectory(rootBin);
+ }
+ this->GetCMakeInstance()->AddCacheEntry(
+ kCMAKE_PLATFORM_INFO_INITIALIZED, "1",
+ "Platform information initialized", cmStateEnums::INTERNAL);
+ }
// find and make sure CMAKE_MAKE_PROGRAM is defined
- this->FindMakeProgram(mf);
+ 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;
- if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
- {
+ bool const readCMakeSystem = !mf->GetDefinition("CMAKE_SYSTEM_LOADED");
+ if (readCMakeSystem) {
fpath += "/CMakeSystem.cmake";
- if(cmSystemTools::FileExists(fpath.c_str()))
- {
- mf->ReadListFile(0,fpath.c_str());
- }
+ if (cmSystemTools::FileExists(fpath.c_str())) {
+ mf->ReadListFile(fpath.c_str());
}
+ }
// Load the CMakeDetermineSystem.cmake file and find out
// what platform we are running on
- if (!mf->GetDefinition("CMAKE_SYSTEM"))
- {
+ if (!mf->GetDefinition("CMAKE_SYSTEM")) {
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Windows version number data. */
- OSVERSIONINFO osvi;
- ZeroMemory(&osvi, sizeof(osvi));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx (&osvi);
- cmOStringStream windowsVersionString;
- windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
+ OSVERSIONINFOEXW osviex;
+ ZeroMemory(&osviex, sizeof(osviex));
+ osviex.dwOSVersionInfoSize = sizeof(osviex);
+
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(push)
+#pragma warning(disable : 4996)
+#endif
+ GetVersionExW((OSVERSIONINFOW*)&osviex);
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(pop)
+#endif
+ std::ostringstream windowsVersionString;
+ windowsVersionString << osviex.dwMajorVersion << "."
+ << osviex.dwMinorVersion << "."
+ << osviex.dwBuildNumber;
windowsVersionString.str();
mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
windowsVersionString.str().c_str());
#endif
// Read the DetermineSystem file
std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
- mf->ReadListFile(0, systemFile.c_str());
+ mf->ReadListFile(systemFile.c_str());
// load the CMakeSystem.cmake from the binary directory
// this file is configured by the CMakeDetermineSystem.cmake file
fpath = rootBin;
fpath += "/CMakeSystem.cmake";
- mf->ReadListFile(0,fpath.c_str());
+ mf->ReadListFile(fpath.c_str());
+ }
+
+ if (readCMakeSystem) {
+ // Tell the generator about the target system.
+ std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
+ if (!this->SetSystemName(system, mf)) {
+ cmSystemTools::SetFatalErrorOccured();
+ return;
+ }
+
+ // Tell the generator about the platform, if any.
+ std::string platform = mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM");
+ if (!this->SetGeneratorPlatform(platform, mf)) {
+ cmSystemTools::SetFatalErrorOccured();
+ return;
+ }
+
+ // Tell the generator about the toolset, if any.
+ std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");
+ if (!this->SetGeneratorToolset(toolset, mf)) {
+ cmSystemTools::SetFatalErrorOccured();
+ return;
}
- std::map<cmStdString, bool> needTestLanguage;
- std::map<cmStdString, bool> needSetLanguageEnabledMaps;
+ }
+
+ // **** 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())) {
+ cmSystemTools::Error("Could not find cmake module file: "
+ "CMakeSystemSpecificInitialize.cmake");
+ }
+ }
+
+ std::map<std::string, bool> needTestLanguage;
+ std::map<std::string, bool> needSetLanguageEnabledMaps;
// foreach language
// 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)
- {
+ for (std::vector<std::string>::const_iterator l = languages.begin();
+ l != languages.end(); ++l) {
const char* lang = l->c_str();
needSetLanguageEnabledMaps[lang] = false;
- if(*l == "NONE")
- {
+ if (*l == "NONE") {
this->SetLanguageEnabled("NONE", mf);
continue;
- }
+ }
std::string loadedLang = "CMAKE_";
- loadedLang += lang;
+ loadedLang += lang;
loadedLang += "_COMPILER_LOADED";
- if(!mf->GetDefinition(loadedLang.c_str()))
- {
+ if (!mf->GetDefinition(loadedLang)) {
fpath = rootBin;
fpath += "/CMake";
fpath += lang;
@@ -411,31 +562,27 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
// 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(0,fpath.c_str()))
- {
+ if (cmSystemTools::FileExists(fpath.c_str())) {
+ if (!mf->ReadListFile(fpath.c_str())) {
cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
- }
+ }
// if this file was found then the language was already determined
// to be working
needTestLanguage[lang] = false;
this->SetLanguageEnabledFlag(lang, mf);
needSetLanguageEnabledMaps[lang] = true;
// this can only be called after loading CMake(LANG)Compiler.cmake
- }
}
+ }
- if(!this->GetLanguageEnabled(lang) )
- {
- if (this->CMakeInstance->GetIsInTryCompile())
- {
+ if (!this->GetLanguageEnabled(lang)) {
+ if (this->CMakeInstance->GetIsInTryCompile()) {
cmSystemTools::Error("This should not have happened. "
"If you see this message, you are probably "
"using a broken CMakeLists.txt file or a "
"problematic release of CMake");
- }
+ }
// if the CMake(LANG)Compiler.cmake file was not found then
// load CMakeDetermine(LANG)Compiler.cmake
std::string determineCompiler = "CMakeDetermine";
@@ -443,16 +590,17 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
determineCompiler += "Compiler.cmake";
std::string determineFile =
mf->GetModulesFile(determineCompiler.c_str());
- if(!mf->ReadListFile(0,determineFile.c_str()))
- {
+ if (!mf->ReadListFile(determineFile.c_str())) {
cmSystemTools::Error("Could not find cmake module file: ",
- determineFile.c_str());
- }
+ determineCompiler.c_str());
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return;
+ }
needTestLanguage[lang] = true;
// Some generators like visual studio should not use the env variables
// So the global generator can specify that in this variable
- if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
- {
+ if (!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV")) {
// put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
// into the environment, in case user scripts want to run
// configure, or sub cmakes
@@ -462,14 +610,13 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
std::string compilerEnv = "CMAKE_";
compilerEnv += lang;
compilerEnv += "_COMPILER_ENV_VAR";
- std::string envVar = mf->GetRequiredDefinition(compilerEnv.c_str());
- std::string envVarValue =
- mf->GetRequiredDefinition(compilerName.c_str());
+ std::string envVar = mf->GetRequiredDefinition(compilerEnv);
+ std::string envVarValue = mf->GetRequiredDefinition(compilerName);
std::string env = envVar;
env += "=";
env += envVarValue;
- cmSystemTools::PutEnv(env.c_str());
- }
+ cmSystemTools::PutEnv(env);
+ }
// if determineLanguage was called then load the file it
// configures CMake(LANG)Compiler.cmake
@@ -477,11 +624,10 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
fpath += "/CMake";
fpath += lang;
fpath += "Compiler.cmake";
- if(!mf->ReadListFile(0,fpath.c_str()))
- {
+ if (!mf->ReadListFile(fpath.c_str())) {
cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
- }
+ }
this->SetLanguageEnabledFlag(lang, mf);
needSetLanguageEnabledMaps[lang] = true;
// this can only be called after loading CMake(LANG)Compiler.cmake
@@ -489,190 +635,300 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
// not know if it is a working compiler yet so set the test language
// flag
needTestLanguage[lang] = true;
- } // end if(!this->GetLanguageEnabled(lang) )
- } // end loop over languages
+ } // end if(!this->GetLanguageEnabled(lang) )
+ } // end loop over languages
// **** Load the system specific information if not yet loaded
- if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
- {
+ if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED")) {
fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
- if(!mf->ReadListFile(0,fpath.c_str()))
- {
- cmSystemTools::Error("Could not find cmake module file: ",
- fpath.c_str());
- }
+ if (!mf->ReadListFile(fpath.c_str())) {
+ 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)
- {
+ for (std::vector<std::string>::const_iterator l = languages.begin();
+ l != languages.end(); ++l) {
const char* lang = l->c_str();
- if(*l == "NONE")
- {
+ if (*l == "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::ostringstream noCompiler;
+ const char* compilerFile = mf->GetDefinition(compilerName);
+ if (!compilerFile || !*compilerFile ||
+ cmSystemTools::IsNOTFOUND(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) {
+ if (!cmSystemTools::FileIsFullPath(compilerFile)) {
+ /* clang-format off */
+ noCompiler <<
+ "The " << compilerName << ":\n"
+ " " << compilerFile << "\n"
+ "is not a full path and was not found in the PATH.\n"
+ ;
+ /* clang-format on */
+ } else if (!cmSystemTools::FileExists(compilerFile)) {
+ /* clang-format off */
+ noCompiler <<
+ "The " << compilerName << ":\n"
+ " " << compilerFile << "\n"
+ "is not a full path to an existing compiler tool.\n"
+ ;
+ /* clang-format on */
+ }
+ }
+ if (!noCompiler.str().empty()) {
+ // Skip testing this language since the compiler is not found.
+ needTestLanguage[lang] = false;
+ 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";
+ cmSystemTools::RemoveFile(compilerLangFile);
+ if (!this->CMakeInstance->GetIsInTryCompile()) {
+ this->PrintCompilerAdvice(noCompiler, lang,
+ mf->GetDefinition(compilerEnv));
+ mf->IssueMessage(cmake::FATAL_ERROR, noCompiler.str());
+ fatalError = true;
+ }
}
+ }
+
std::string langLoadedVar = "CMAKE_";
langLoadedVar += lang;
langLoadedVar += "_INFORMATION_LOADED";
- if (!mf->GetDefinition(langLoadedVar.c_str()))
- {
+ if (!mf->GetDefinition(langLoadedVar)) {
fpath = "CMake";
- fpath += lang;
+ fpath += lang;
fpath += "Information.cmake";
std::string informationFile = mf->GetModulesFile(fpath.c_str());
- if (informationFile.empty())
- {
+ if (informationFile.empty()) {
cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
- }
- else if(!mf->ReadListFile(0, informationFile.c_str()))
- {
+ } else if (!mf->ReadListFile(informationFile.c_str())) {
cmSystemTools::Error("Could not process cmake module file: ",
informationFile.c_str());
- }
}
- if (needSetLanguageEnabledMaps[lang])
- {
+ }
+ if (needSetLanguageEnabledMaps[lang]) {
this->SetLanguageEnabledMaps(lang, mf);
- }
+ }
this->LanguagesReady.insert(lang);
- std::string compilerName = "CMAKE_";
- compilerName += lang;
- compilerName += "_COMPILER";
- std::string compilerLangFile = rootBin;
- compilerLangFile += "/CMake";
- compilerLangFile += lang;
- compilerLangFile += "Compiler.cmake";
// Test the compiler for the language just setup
// (but only if a compiler has been actually found)
// At this point we should have enough info for a try compile
// which is used in the backward stuff
// If the language is untested then test it now with a try compile.
- if (!mf->IsSet(compilerName.c_str()))
- {
- // 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
- cmSystemTools::RemoveFile(compilerLangFile.c_str());
- }
- else if(needTestLanguage[lang])
- {
- if (!this->CMakeInstance->GetIsInTryCompile())
- {
+ 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(0,ifpath.c_str()))
- {
+ if (!mf->ReadListFile(ifpath.c_str())) {
cmSystemTools::Error("Could not find cmake module file: ",
- ifpath.c_str());
- }
+ testLang.c_str());
+ }
std::string compilerWorks = "CMAKE_";
compilerWorks += lang;
compilerWorks += "_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.c_str()))
- {
- cmSystemTools::RemoveFile(compilerLangFile.c_str());
- }
- else
- {
- // load backwards compatibility stuff for C and CXX
- // for old versions of CMake ListFiles C and CXX had some
- // backwards compatibility files they have to load
- // These files have a bunch of try compiles in them so
- // should only be done
- if (mf->NeedBackwardsCompatibility(1,4))
- {
- if(strcmp(lang, "C") == 0)
- {
- ifpath =
- mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
- mf->ReadListFile(0,ifpath.c_str());
- }
- if(strcmp(lang, "CXX") == 0)
- {
- ifpath =
- mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
- mf->ReadListFile(0,ifpath.c_str());
- }
- }
- }
- } // end if in try compile
- } // end need test language
+ if (!mf->IsOn(compilerWorks)) {
+ std::string compilerLangFile = rootBin;
+ compilerLangFile += "/CMake";
+ compilerLangFile += lang;
+ compilerLangFile += "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.c_str());
- if (sharedLibFlags)
- {
+ const char* sharedLibFlags = mf->GetSafeDefinition(sharedLibFlagsVar);
+ if (sharedLibFlags) {
this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags;
- }
- } // end for each language
+ }
+
+ // Translate compiler ids for compatibility.
+ this->CheckCompilerIdCompatibility(mf, lang);
+ } // end for each language
// 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 = mf->GetDefinition("CMAKE_ROOT");
+ std::string projectCompatibility = cmSystemTools::GetCMakeRoot();
projectCompatibility += "/Modules/";
projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
projectCompatibility += "Compatibility.cmake";
- if(cmSystemTools::FileExists(projectCompatibility.c_str()))
- {
- mf->ReadListFile(0,projectCompatibility.c_str());
+ if (cmSystemTools::FileExists(projectCompatibility.c_str())) {
+ mf->ReadListFile(projectCompatibility.c_str());
+ }
+ // Inform any extra generator of the new language.
+ if (this->ExtraGenerator) {
+ this->ExtraGenerator->EnableLanguage(languages, mf, false);
+ }
+
+ if (fatalError) {
+ cmSystemTools::SetFatalErrorOccured();
+ }
+
+ for (std::set<std::string>::iterator li = cur_languages.begin();
+ li != cur_languages.end(); ++li) {
+ this->LanguagesInProgress.erase(*li);
+ }
+}
+
+void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os,
+ std::string const& lang,
+ const char* envVar) const
+{
+ // Subclasses override this method if they do not support this advice.
+ os << "Tell CMake where to find the compiler by setting ";
+ if (envVar) {
+ os << "either the environment variable \"" << envVar << "\" or ";
+ }
+ os << "the CMake cache entry CMAKE_" << lang
+ << "_COMPILER "
+ "to the full path to the compiler, or to the compiler name "
+ "if it is in the PATH.";
+}
+
+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;
+ }
+
+ if (strcmp(compilerId, "AppleClang") == 0) {
+ switch (mf->GetPolicyStatus(cmPolicies::CMP0025)) {
+ case cmPolicies::WARN:
+ if (!this->CMakeInstance->GetIsInTryCompile() &&
+ mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0025")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n"
+ "Converting " << lang <<
+ " compiler id \"AppleClang\" to \"Clang\" for compatibility."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to convert AppleClang to Clang.
+ mf->AddDefinition(compilerIdVar, "Clang");
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ mf->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025));
+ case cmPolicies::NEW:
+ // NEW behavior is to keep AppleClang.
+ break;
+ }
+ }
+
+ if (strcmp(compilerId, "QCC") == 0) {
+ switch (mf->GetPolicyStatus(cmPolicies::CMP0047)) {
+ case cmPolicies::WARN:
+ if (!this->CMakeInstance->GetIsInTryCompile() &&
+ mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0047")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0047) << "\n"
+ "Converting " << lang <<
+ " compiler id \"QCC\" to \"GNU\" for compatibility."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to convert QCC to GNU.
+ mf->AddDefinition(compilerIdVar, "GNU");
+ if (lang == "C") {
+ mf->AddDefinition("CMAKE_COMPILER_IS_GNUCC", "1");
+ } else if (lang == "CXX") {
+ mf->AddDefinition("CMAKE_COMPILER_IS_GNUCXX", "1");
+ }
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ mf->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047));
+ CM_FALLTHROUGH;
+ case cmPolicies::NEW:
+ // NEW behavior is to keep QCC.
+ break;
}
+ }
}
-//----------------------------------------------------------------------------
-const char*
-cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source)
+std::string cmGlobalGenerator::GetLanguageOutputExtension(
+ cmSourceFile const& source) const
{
- if(const char* lang = source.GetLanguage())
- {
- if(this->LanguageToOutputExtension.count(lang) > 0)
- {
- return this->LanguageToOutputExtension[lang].c_str();
- }
+ const std::string& lang = source.GetLanguage();
+ if (!lang.empty()) {
+ std::map<std::string, std::string>::const_iterator it =
+ this->LanguageToOutputExtension.find(lang);
+
+ if (it != this->LanguageToOutputExtension.end()) {
+ return it->second;
}
- else
- {
+ } 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
// and in this map, so it will not be compiled but will just be used.
std::string const& ext = source.GetExtension();
- if(!ext.empty())
- {
- if(this->OutputExtensions.count(ext))
- {
- return ext.c_str();
- }
+ if (!ext.empty()) {
+ if (this->OutputExtensions.count(ext)) {
+ return ext;
}
}
+ }
return "";
}
-
-const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
+std::string cmGlobalGenerator::GetLanguageFromExtension(const char* ext) const
{
// if there is an extension and it starts with . then move past the
// . because the extensions are not stored with a . in the map
- if(ext && *ext == '.')
- {
+ if (ext && *ext == '.') {
++ext;
- }
- if(this->ExtensionToLanguage.count(ext) > 0)
- {
- return this->ExtensionToLanguage[ext].c_str();
- }
- return 0;
+ }
+ std::map<std::string, std::string>::const_iterator it =
+ this->ExtensionToLanguage.find(ext);
+ if (it != this->ExtensionToLanguage.end()) {
+ return it->second;
+ }
+ return "";
}
/* SetLanguageEnabled() is now split in two parts:
@@ -687,15 +943,17 @@ files could change the object file extension
(CMAKE_<LANG>_OUTPUT_EXTENSION) before the CMake variables were copied
to the C++ maps.
*/
-void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
+void cmGlobalGenerator::SetLanguageEnabled(const std::string& l,
+ cmMakefile* mf)
{
this->SetLanguageEnabledFlag(l, mf);
this->SetLanguageEnabledMaps(l, mf);
}
-void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile* mf)
+void cmGlobalGenerator::SetLanguageEnabledFlag(const std::string& l,
+ cmMakefile* mf)
{
- this->LanguageEnabled[l] = true;
+ this->CMakeInstance->GetState()->SetLanguageEnabled(l);
// Fill the language-to-extension map with the current variable
// settings to make sure it is available for the try_compile()
@@ -705,237 +963,258 @@ void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile* mf)
this->FillExtensionToLanguageMap(l, mf);
}
-void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
+void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
+ cmMakefile* mf)
{
// use LanguageToLinkerPreference to detect whether this functions has
// run before
if (this->LanguageToLinkerPreference.find(l) !=
- this->LanguageToLinkerPreference.end())
- {
+ this->LanguageToLinkerPreference.end()) {
return;
- }
+ }
- std::string linkerPrefVar = std::string("CMAKE_") +
- std::string(l) + std::string("_LINKER_PREFERENCE");
- const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
+ std::string linkerPrefVar =
+ std::string("CMAKE_") + std::string(l) + std::string("_LINKER_PREFERENCE");
+ const char* linkerPref = mf->GetDefinition(linkerPrefVar);
int preference = 0;
- if(linkerPref)
- {
- if (sscanf(linkerPref, "%d", &preference)!=1)
- {
+ if (linkerPref) {
+ if (sscanf(linkerPref, "%d", &preference) != 1) {
// backward compatibility: before 2.6 LINKER_PREFERENCE
- // was either "None" or "Prefered", and only the first character was
+ // was either "None" or "Preferred", and only the first character was
// tested. So if there is a custom language out there and it is
- // "Prefered", set its preference high
- if (linkerPref[0]=='P')
- {
+ // "Preferred", set its preference high
+ if (linkerPref[0] == 'P') {
preference = 100;
- }
- else
- {
+ } else {
preference = 0;
- }
}
}
+ }
- if (preference < 0)
- {
+ if (preference < 0) {
std::string msg = linkerPrefVar;
msg += " is negative, adjusting it to 0";
cmSystemTools::Message(msg.c_str(), "Warning");
preference = 0;
- }
+ }
this->LanguageToLinkerPreference[l] = preference;
- std::string outputExtensionVar = std::string("CMAKE_") +
- std::string(l) + std::string("_OUTPUT_EXTENSION");
- const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
- if(outputExtension)
- {
+ std::string outputExtensionVar =
+ std::string("CMAKE_") + std::string(l) + std::string("_OUTPUT_EXTENSION");
+ const char* outputExtension = mf->GetDefinition(outputExtensionVar);
+ if (outputExtension) {
this->LanguageToOutputExtension[l] = outputExtension;
this->OutputExtensions[outputExtension] = outputExtension;
- if(outputExtension[0] == '.')
- {
- this->OutputExtensions[outputExtension+1] = outputExtension+1;
- }
+ if (outputExtension[0] == '.') {
+ this->OutputExtensions[outputExtension + 1] = outputExtension + 1;
}
+ }
// The map was originally filled by SetLanguageEnabledFlag, but
// since then the compiler- and platform-specific files have been
// loaded which might have added more entries.
this->FillExtensionToLanguageMap(l, mf);
- std::string ignoreExtensionsVar = std::string("CMAKE_") +
- std::string(l) + std::string("_IGNORE_EXTENSIONS");
- std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
+ 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)
- {
+ for (std::vector<std::string>::iterator i = extensionList.begin();
+ i != extensionList.end(); ++i) {
this->IgnoreExtensions[*i] = true;
- }
-
+ }
}
-void cmGlobalGenerator::FillExtensionToLanguageMap(const char* l,
+void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l,
cmMakefile* mf)
{
- std::string extensionsVar = std::string("CMAKE_") +
- std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
- std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
+ 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)
- {
+ for (std::vector<std::string>::iterator i = extensionList.begin();
+ i != extensionList.end(); ++i) {
this->ExtensionToLanguage[*i] = l;
- }
+ }
}
-bool cmGlobalGenerator::IgnoreFile(const char* l)
+const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
{
- if(this->GetLanguageFromExtension(l))
- {
+ assert(!this->Makefiles.empty());
+ return this->Makefiles[0]->GetDefinition(name);
+}
+
+bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const
+{
+ assert(!this->Makefiles.empty());
+ return this->Makefiles[0]->IsOn(name);
+}
+
+const char* cmGlobalGenerator::GetSafeGlobalSetting(
+ std::string const& name) const
+{
+ assert(!this->Makefiles.empty());
+ return this->Makefiles[0]->GetSafeDefinition(name);
+}
+
+bool cmGlobalGenerator::IgnoreFile(const char* ext) const
+{
+ if (!this->GetLanguageFromExtension(ext).empty()) {
return false;
- }
- return (this->IgnoreExtensions.count(l) > 0);
+ }
+ return (this->IgnoreExtensions.count(ext) > 0);
}
-bool cmGlobalGenerator::GetLanguageEnabled(const char* l) const
+bool cmGlobalGenerator::GetLanguageEnabled(const std::string& l) const
{
- return (this->LanguageEnabled.find(l)!= this->LanguageEnabled.end());
+ return this->CMakeInstance->GetState()->GetLanguageEnabled(l);
}
void cmGlobalGenerator::ClearEnabledLanguages()
{
- this->LanguageEnabled.clear();
+ return this->CMakeInstance->GetState()->ClearEnabledLanguages();
}
-bool cmGlobalGenerator::IsDependedOn(const char* project,
- cmTarget* targetIn)
+void cmGlobalGenerator::CreateLocalGenerators()
{
- // Get all local gens for this project
- std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
- // loop over local gens and get the targets for each one
- for(unsigned int i = 0; i < gens->size(); ++i)
- {
- cmTargets& targets = (*gens)[i]->GetMakefile()->GetTargets();
- for (cmTargets::iterator l = targets.begin();
- l != targets.end(); l++)
- {
- cmTarget& target = l->second;
- TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target);
- if(tgtdeps.count(targetIn))
- {
- return true;
- }
- }
- }
- return false;
+ 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));
+ }
}
void cmGlobalGenerator::Configure()
{
this->FirstTimeProgress = 0.0f;
- this->ClearGeneratorTargets();
- this->ExportSets.clear();
- // Delete any existing cmLocalGenerators
- unsigned int i;
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- delete this->LocalGenerators[i];
- }
- this->LocalGenerators.clear();
- for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
- li = this->EvaluationFiles.begin();
- li != this->EvaluationFiles.end();
- ++li)
- {
- delete *li;
- }
- this->EvaluationFiles.clear();
- this->TargetDependencies.clear();
- this->TotalTargets.clear();
- this->ImportedTargets.clear();
- this->LocalGeneratorToTargetMap.clear();
- this->ProjectMap.clear();
- this->RuleHashes.clear();
- this->DirectoryContentMap.clear();
- this->BinaryDirectories.clear();
+ this->ClearGeneratorMembers();
- // start with this directory
- cmLocalGenerator *lg = this->CreateLocalGenerator();
- this->LocalGenerators.push_back(lg);
+ cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
- // set the Start directories
- cmMakefile* mf = lg->GetMakefile();
- lg->GetMakefile()->SetStartDirectory
- (this->CMakeInstance->GetStartDirectory());
- lg->GetMakefile()->SetStartOutputDirectory
- (this->CMakeInstance->GetStartOutputDirectory());
- lg->GetMakefile()->MakeStartDirectoriesCurrent();
+ snapshot.GetDirectory().SetCurrentSource(
+ this->CMakeInstance->GetHomeDirectory());
+ snapshot.GetDirectory().SetCurrentBinary(
+ this->CMakeInstance->GetHomeOutputDirectory());
- this->BinaryDirectories.insert(mf->GetStartOutputDirectory());
+ cmMakefile* dirMf = new cmMakefile(this, snapshot);
+ this->Makefiles.push_back(dirMf);
+ this->IndexMakefile(dirMf);
+
+ this->BinaryDirectories.insert(
+ this->CMakeInstance->GetHomeOutputDirectory());
// now do it
- lg->Configure();
+ this->ConfigureDoneCMP0026AndCMP0024 = false;
+ dirMf->Configure();
+ dirMf->EnforceDirectoryLevelRules();
+
+ 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)));
+ }
+ }
// update the cache entry for the number of local generators, this is used
// for progress
char num[100];
- sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
- this->GetCMakeInstance()->AddCacheEntry
- ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
- "number of local generators", cmCacheManager::INTERNAL);
+ sprintf(num, "%d", static_cast<int>(this->Makefiles.size()));
+ this->GetCMakeInstance()->AddCacheEntry("CMAKE_NUMBER_OF_MAKEFILES", num,
+ "number of local generators",
+ cmStateEnums::INTERNAL);
// check for link libraries and include directories containing "NOTFOUND"
// and for infinite loops
- this->CheckLocalGenerators();
-
- // at this point this->LocalGenerators has been filled,
- // so create the map from project name to vector of local generators
- this->FillProjectMap();
+ this->CheckTargetProperties();
- if ( this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE)
- {
- cmOStringStream msg;
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) {
+ std::ostringstream msg;
+ if (cmSystemTools::GetErrorOccuredFlag()) {
msg << "Configuring incomplete, errors occurred!";
- const char* logs[] = {"CMakeOutput.log", "CMakeError.log", 0};
- for(const char** log = logs; *log; ++log)
- {
+ const char* logs[] = { "CMakeOutput.log", "CMakeError.log", CM_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()))
- {
+ if (cmSystemTools::FileExists(f.c_str())) {
msg << "\nSee also \"" << f << "\".";
- }
}
}
- else
- {
+ } else {
msg << "Configuring done";
- }
+ }
this->CMakeInstance->UpdateProgress(msg.str().c_str(), -1);
+ }
+}
+
+void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes)
+{
+ this->CreateLocalGenerators();
+ this->CreateGeneratorTargets(targetTypes);
+ this->ComputeBuildFileGenerators();
+}
+
+void cmGlobalGenerator::CreateImportedGenerationObjects(
+ cmMakefile* mf, const std::vector<std::string>& targets,
+ std::vector<const cmGeneratorTarget*>& exports)
+{
+ this->CreateGenerationObjects(ImportedOnly);
+ std::vector<cmMakefile*>::iterator 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);
+ if (gt) {
+ exports.push_back(gt);
}
+ }
+}
+
+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;
}
-bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
+void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target)
+{
+ this->CMP0042WarnTargets.insert(target);
+}
+
+void cmGlobalGenerator::AddCMP0068WarnTarget(const std::string& target)
+{
+ this->CMP0068WarnTargets.insert(target);
+}
+
+bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
{
// If the property is not enabled then okay.
- if(!this->CMakeInstance
- ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
- {
+ if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(
+ "ALLOW_DUPLICATE_CUSTOM_TARGETS")) {
return true;
- }
+ }
// This generator does not support duplicate custom targets.
- cmOStringStream e;
+ std::ostringstream e;
e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
<< "global property. "
<< "The \"" << this->GetName() << "\" generator does not support "
@@ -946,447 +1225,521 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
return false;
}
-void cmGlobalGenerator::Generate()
+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]);
+ }
+ }
+}
+
+bool cmGlobalGenerator::Compute()
{
// Some generators track files replaced during the Generate.
// Start with an empty vector:
this->FilesReplacedDuringGenerate.clear();
+ // clear targets to issue warning CMP0042 for
+ this->CMP0042WarnTargets.clear();
+ // clear targets to issue warning CMP0068 for
+ this->CMP0068WarnTargets.clear();
+
// Check whether this generator is allowed to run.
- if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
- {
- return;
- }
+ if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) {
+ return false;
+ }
+ this->FinalizeTargetCompileInfo();
- // Check that all targets are valid.
- if(!this->CheckTargets())
- {
- return;
- }
+ this->CreateGenerationObjects();
- this->FinalizeTargetCompileDefinitions();
+ // at this point this->LocalGenerators has been filled,
+ // 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 property set
- this->CreateAutomocTargets();
+ // the AUTOMOC, AUTOUIC or AUTORCC property set
+ std::vector<cmGeneratorTarget const*> autogenTargets =
+ this->CreateQtAutoGeneratorsTargets();
+#endif
- // For each existing cmLocalGenerator
unsigned int i;
- // Put a copy of each global target in every directory.
- cmTargets globalTargets;
- this->CreateDefaultGlobalTargets(&globalTargets);
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
- cmTargets* targets = &(mf->GetTargets());
- cmTargets::iterator tit;
- for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
- {
- (*targets)[tit->first] = tit->second;
- (*targets)[tit->first].SetMakefile(mf);
- }
+ // Add generator specific helper commands
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ this->LocalGenerators[i]->AddHelperCommands();
+ }
- for ( tit = targets->begin(); tit != targets->end(); ++ tit )
- {
- tit->second.AppendBuildInterfaceIncludes();
- }
+ // Finalize the set of compile features for each target.
+ // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature
+ // which actually modifies the <lang>_STANDARD target property
+ // 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()) {
+ return false;
}
+ }
- // Add generator specific helper commands
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- this->LocalGenerators[i]->AddHelperCommands();
+#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]);
}
+ }
+
+ this->AddExtraIDETargets();
// 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)
- {
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
this->LocalGenerators[i]->TraceDependencies();
- }
+ }
+
+ this->ForceLinkerLanguages();
// Compute the manifest of main targets generated.
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- this->LocalGenerators[i]->GenerateTargetManifest();
- }
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ this->LocalGenerators[i]->ComputeTargetManifest();
+ }
- // Create per-target generator information.
- this->CreateGeneratorTargets();
+ // Compute the inter-target dependencies.
+ if (!this->ComputeTargetDepends()) {
+ return false;
+ }
- this->ProcessEvaluationFiles();
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ this->LocalGenerators[i]->ComputeHomeRelativeOutputPath();
+ }
- // Compute the inter-target dependencies.
- if(!this->ComputeTargetDepends())
- {
- return;
- }
+ return true;
+}
+void cmGlobalGenerator::Generate()
+{
// Create a map from local generator to the complete set of targets
// it builds by default.
- this->FillLocalGeneratorToTargetMap();
+ this->InitializeProgressMarks();
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
- cmTargets* targets = &(mf->GetTargets());
- for ( cmTargets::iterator it = targets->begin();
- it != targets->end(); ++ it )
- {
- it->second.FinalizeSystemIncludeDirectories();
- }
- }
+ this->ProcessEvaluationFiles();
// Generate project files
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem();
- this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
+ for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
+ this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile());
this->LocalGenerators[i]->Generate();
- this->LocalGenerators[i]->GenerateInstallRules();
- this->LocalGenerators[i]->GenerateTestFiles();
- this->CMakeInstance->UpdateProgress("Generating",
- (static_cast<float>(i)+1.0f)/
- static_cast<float>(this->LocalGenerators.size()));
+ if (!this->LocalGenerators[i]->GetMakefile()->IsOn(
+ "CMAKE_SKIP_INSTALL_RULES")) {
+ this->LocalGenerators[i]->GenerateInstallRules();
}
- this->SetCurrentLocalGenerator(0);
+ this->LocalGenerators[i]->GenerateTestFiles();
+ this->CMakeInstance->UpdateProgress(
+ "Generating", (static_cast<float>(i) + 1.0f) /
+ static_cast<float>(this->LocalGenerators.size()));
+ }
+ this->SetCurrentMakefile(CM_NULLPTR);
+ if (!this->GenerateCPackPropertiesFile()) {
+ this->GetCMakeInstance()->IssueMessage(
+ cmake::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()) {
+ if (!cmSystemTools::GetErrorOccuredFlag()) {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR,
+ "Could not write export file.");
+ }
+ return;
+ }
+ }
// Update rule hashes.
this->CheckRuleHashes();
this->WriteSummary();
- if (this->ExtraGenerator != 0)
- {
+ if (this->ExtraGenerator != CM_NULLPTR) {
this->ExtraGenerator->Generate();
- }
+ }
+
+ if (!this->CMP0042WarnTargets.empty()) {
+ std::ostringstream w;
+ 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";
+ }
+ this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+
+ if (!this->CMP0068WarnTargets.empty()) {
+ std::ostringstream w;
+ /* clang-format off */
+ w <<
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0068) << "\n"
+ "For compatibility with older versions of CMake, the install_name "
+ "fields for the following targets are still affected by RPATH "
+ "settings:\n"
+ ;
+ /* clang-format on */
+ for (std::set<std::string>::iterator iter =
+ this->CMP0068WarnTargets.begin();
+ iter != this->CMP0068WarnTargets.end(); ++iter) {
+ w << " " << *iter << "\n";
+ }
+ this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
this->CMakeInstance->UpdateProgress("Generating done", -1);
}
-//----------------------------------------------------------------------------
bool cmGlobalGenerator::ComputeTargetDepends()
{
cmComputeTargetDepends ctd(this);
- if(!ctd.Compute())
- {
+ if (!ctd.Compute()) {
return false;
- }
- std::vector<cmTarget*> const& targets = ctd.GetTargets();
- for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
+ }
+ 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]);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmGlobalGenerator::CheckTargets()
+std::vector<const cmGeneratorTarget*>
+cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
{
- // Make sure all targets can find their source files.
- for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
- {
- cmTargets& targets =
- this->LocalGenerators[i]->GetMakefile()->GetTargets();
- for(cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
- cmTarget& target = ti->second;
- if(target.GetType() == cmTarget::EXECUTABLE ||
- target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY ||
- target.GetType() == cmTarget::OBJECT_LIBRARY ||
- target.GetType() == cmTarget::UTILITY)
- {
- if(!target.FindSourceFiles())
- {
- return false;
- }
- }
- }
- }
- return true;
-}
+ std::vector<const cmGeneratorTarget*> autogenTargets;
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::CreateAutomocTargets()
-{
#ifdef CMAKE_BUILD_WITH_CMAKE
- typedef std::vector<std::pair<cmQtAutomoc, cmTarget*> > Automocs;
- Automocs automocs;
- for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
- {
- cmTargets& targets =
- this->LocalGenerators[i]->GetMakefile()->GetTargets();
- for(cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
- cmTarget& target = ti->second;
- if(target.GetType() == cmTarget::EXECUTABLE ||
- target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY ||
- target.GetType() == cmTarget::OBJECT_LIBRARY)
- {
- if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported())
- {
- cmQtAutomoc automoc;
- if(automoc.InitializeMocSourceFile(&target))
- {
- automocs.push_back(std::make_pair(automoc, &target));
- }
- }
- }
+ 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") {
+ continue;
}
+
+ cmGeneratorTarget* gt = *ti;
+
+ cmQtAutoGeneratorInitializer::InitializeAutogenSources(gt);
+ filteredTargets.push_back(gt);
}
- for (Automocs::iterator it = automocs.begin(); it != automocs.end();
- ++it)
- {
- it->first.SetupAutomocTarget(it->second);
+ for (std::vector<cmGeneratorTarget*>::iterator ti =
+ filteredTargets.begin();
+ ti != filteredTargets.end(); ++ti) {
+ cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
+ this->LocalGenerators[i], *ti);
+ autogenTargets.push_back(*ti);
}
+ }
#endif
+ return autogenTargets;
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::FinalizeTargetCompileDefinitions()
+cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
{
- // Construct per-target generator information.
- for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
- {
- cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
+ return new cmLinkLineComputer(outputConverter, stateDir);
+}
- const std::vector<cmValueWithOrigin> noconfig_compile_definitions =
- mf->GetCompileDefinitionsEntries();
+cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
+{
+ return new cmMSVC60LinkLineComputer(outputConverter, stateDir);
+}
- std::vector<std::string> configs;
- mf->GetConfigurations(configs);
+void cmGlobalGenerator::FinalizeTargetCompileInfo()
+{
+ std::vector<std::string> const langs =
+ this->CMakeInstance->GetState()->GetEnabledLanguages();
+
+ // Construct per-target generator information.
+ for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
+ cmMakefile* mf = this->Makefiles[i];
+
+ 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)
- {
+ for (cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) {
cmTarget* t = &ti->second;
+ if (t->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ continue;
+ }
- for (std::vector<cmValueWithOrigin>::const_iterator it
- = noconfig_compile_definitions.begin();
- it != noconfig_compile_definitions.end(); ++it)
- {
- t->InsertCompileDefinition(*it);
- }
+ t->AppendBuildInterfaceIncludes();
+
+ if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ 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);
+ }
- for(std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci)
- {
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += cmSystemTools::UpperCase(*ci);
- t->AppendProperty(defPropName.c_str(),
- mf->GetProperty(defPropName.c_str()));
+ cmPolicies::PolicyStatus polSt =
+ mf->GetPolicyStatus(cmPolicies::CMP0043);
+ if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
+ 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);
+ t->AppendProperty(defPropName, mf->GetProperty(defPropName));
}
}
}
+
+ // 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) {
+ std::string const standardIncludesVar =
+ "CMAKE_" + *li + "_STANDARD_INCLUDE_DIRECTORIES";
+ std::string const standardIncludesStr =
+ mf->GetSafeDefinition(standardIncludesVar);
+ std::vector<std::string> standardIncludesVec;
+ cmSystemTools::ExpandListArgument(standardIncludesStr,
+ standardIncludesVec);
+ standardIncludesSet.insert(standardIncludesVec.begin(),
+ standardIncludesVec.end());
+ }
+ mf->AddSystemIncludeDirectories(standardIncludesSet);
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::CreateGeneratorTargets()
+void cmGlobalGenerator::CreateGeneratorTargets(
+ TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
+ std::map<cmTarget*, cmGeneratorTarget*> const& importedMap)
{
- // Construct per-target generator information.
- for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
- {
- cmGeneratorTargetsType generatorTargets;
-
- cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
-
+ if (targetTypes == AllTargets) {
cmTargets& targets = mf->GetTargets();
- for(cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
+ for (cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) {
cmTarget* t = &ti->second;
- cmGeneratorTarget* gt = new cmGeneratorTarget(t);
- this->GeneratorTargets[t] = gt;
- this->ComputeTargetObjects(gt);
- generatorTargets[t] = gt;
- }
+ cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg);
+ lg->AddGeneratorTarget(gt);
+ }
+ }
- for(std::vector<cmTarget*>::const_iterator
- j = mf->GetOwnedImportedTargets().begin();
- j != mf->GetOwnedImportedTargets().end(); ++j)
- {
- cmGeneratorTarget* gt = new cmGeneratorTarget(*j);
- this->GeneratorTargets[*j] = gt;
- generatorTargets[*j] = gt;
- }
+ std::vector<cmTarget*> itgts = mf->GetImportedTargets();
- mf->SetGeneratorTargets(generatorTargets);
- }
+ for (std::vector<cmTarget*>::const_iterator j = itgts.begin();
+ j != itgts.end(); ++j) {
+ lg->AddImportedGeneratorTarget(importedMap.find(*j)->second);
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::ClearGeneratorTargets()
+void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes)
{
- for(cmGeneratorTargetsType::iterator i = this->GeneratorTargets.begin();
- i != this->GeneratorTargets.end(); ++i)
- {
- delete i->second;
+ 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) {
+ cmLocalGenerator* lg = this->LocalGenerators[i];
+ cmGeneratorTarget* gt = new cmGeneratorTarget(*j, lg);
+ lg->AddOwnedImportedGeneratorTarget(gt);
+ importedMap[*j] = gt;
}
- this->GeneratorTargets.clear();
+ }
+
+ // Construct per-target generator information.
+ for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
+ this->CreateGeneratorTargets(targetTypes, this->Makefiles[i],
+ this->LocalGenerators[i], importedMap);
+ }
}
-//----------------------------------------------------------------------------
-cmGeneratorTarget* cmGlobalGenerator::GetGeneratorTarget(cmTarget* t) const
+void cmGlobalGenerator::ClearGeneratorMembers()
{
- cmGeneratorTargetsType::const_iterator ti = this->GeneratorTargets.find(t);
- if(ti == this->GeneratorTargets.end())
- {
- this->CMakeInstance->IssueMessage(
- cmake::INTERNAL_ERROR, "Missing cmGeneratorTarget instance!",
- cmListFileBacktrace());
- return 0;
- }
- return ti->second;
+ cmDeleteAll(this->BuildExportSets);
+ this->BuildExportSets.clear();
+
+ cmDeleteAll(this->Makefiles);
+ this->Makefiles.clear();
+
+ cmDeleteAll(this->LocalGenerators);
+ this->LocalGenerators.clear();
+
+ this->ExportSets.clear();
+ this->TargetDependencies.clear();
+ this->TargetSearchIndex.clear();
+ this->GeneratorTargetSearchIndex.clear();
+ this->MakefileSearchIndex.clear();
+ this->ProjectMap.clear();
+ this->RuleHashes.clear();
+ this->DirectoryContentMap.clear();
+ this->BinaryDirectories.clear();
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::ComputeTargetObjects(cmGeneratorTarget*) const
+void cmGlobalGenerator::ComputeTargetObjectDirectory(
+ cmGeneratorTarget* /*unused*/) const
{
- // Implemented in generator subclasses that need this.
}
-void cmGlobalGenerator::CheckLocalGenerators()
+void cmGlobalGenerator::CheckTargetProperties()
{
- std::map<cmStdString, cmStdString> notFoundMap;
-// std::set<cmStdString> notFoundMap;
+ std::map<std::string, std::string> notFoundMap;
+ // std::set<std::string> notFoundMap;
// after it is all done do a ConfigureFinalPass
- cmCacheManager* manager = 0;
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
- {
- manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
- this->LocalGenerators[i]->ConfigureFinalPass();
- cmTargets &targets =
- this->LocalGenerators[i]->GetMakefile()->GetTargets();
- for (cmTargets::iterator l = targets.begin();
- l != targets.end(); l++)
- {
+ 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) {
+ 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);
- cmCacheManager::CacheIterator it =
- manager->GetCacheIterator(varName.c_str());
- if(it.GetPropertyAsBool("ADVANCED"))
- {
+ 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);
+ 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->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
+ text += this->Makefiles[i]->GetCurrentSourceDirectory();
notFoundMap[varName] = text;
- }
}
+ }
std::vector<std::string> incs;
- const char *incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
- if (!incDirProp)
- {
+ const char* incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
+ if (!incDirProp) {
continue;
- }
+ }
+
+ std::string incDirs = cmGeneratorExpression::Preprocess(
+ incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
- std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp,
- cmGeneratorExpression::StripAllGeneratorExpressions);
-
- cmSystemTools::ExpandListArgument(incDirs.c_str(), 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);
- cmCacheManager::CacheIterator it =
- manager->GetCacheIterator(varName.c_str());
- if(it.GetPropertyAsBool("ADVANCED"))
- {
+ cmSystemTools::ExpandListArgument(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);
+ if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
varName += " (ADVANCED)";
- }
+ }
std::string text = notFoundMap[varName];
text += "\n used as include directory in directory ";
- text += this->LocalGenerators[i]
- ->GetMakefile()->GetCurrentDirectory();
+ text += this->Makefiles[i]->GetCurrentSourceDirectory();
notFoundMap[varName] = text;
- }
}
}
- this->CMakeInstance->UpdateProgress
- ("Configuring", 0.9f+0.1f*(static_cast<float>(i)+1.0f)/
- static_cast<float>(this->LocalGenerators.size()));
}
+ this->CMakeInstance->UpdateProgress(
+ "Configuring", 0.9f +
+ 0.1f * (static_cast<float>(i) + 1.0f) /
+ static_cast<float>(this->Makefiles.size()));
+ }
- if(notFoundMap.size())
- {
+ if (!notFoundMap.empty()) {
std::string notFoundVars;
- for(std::map<cmStdString, cmStdString>::const_iterator
- ii = notFoundMap.begin();
- ii != notFoundMap.end();
- ++ii)
- {
+ for (std::map<std::string, std::string>::const_iterator ii =
+ notFoundMap.begin();
+ ii != notFoundMap.end(); ++ii) {
notFoundVars += ii->first;
notFoundVars += ii->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());
- }
+ }
}
-int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
- const char *projectName,
- const char *target, bool fast,
- std::string *output, cmMakefile *mf)
+int cmGlobalGenerator::TryCompile(const std::string& srcdir,
+ const std::string& bindir,
+ const std::string& projectName,
+ const std::string& target, bool fast,
+ std::string& output, cmMakefile* mf)
{
// if this is not set, then this is a first time configure
// and there is a good chance that the try compile stuff will
// take the bulk of the time, so try and guess some progress
// by getting closer and closer to 100 without actually getting there.
- if (!this->CMakeInstance->GetCacheManager()->GetCacheValue
- ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
- {
- // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
+ if (!this->CMakeInstance->GetState()->GetInitializedCacheValue(
+ "CMAKE_NUMBER_OF_MAKEFILES")) {
+ // If CMAKE_NUMBER_OF_MAKEFILES is not set
// we are in the first time progress and we have no
// idea how long it will be. So, just move 1/10th of the way
// there each time, and don't go over 95%
- this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
- if(this->FirstTimeProgress > 0.95f)
- {
+ this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) / 30.0f);
+ if (this->FirstTimeProgress > 0.95f) {
this->FirstTimeProgress = 0.95f;
- }
+ }
this->CMakeInstance->UpdateProgress("Configuring",
this->FirstTimeProgress);
- }
-
- std::string makeCommand = this->CMakeInstance->
- GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
- if(makeCommand.size() == 0)
- {
- cmSystemTools::Error(
- "Generator cannot find the appropriate make command.");
- return 1;
- }
+ }
std::string newTarget;
- if (target && strlen(target))
- {
+ if (!target.empty()) {
newTarget += target;
#if 0
#if defined(_WIN32) || defined(__CYGWIN__)
@@ -1399,217 +1752,185 @@ int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
}
#endif // WIN32
#endif
- }
- const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
- return this->Build(srcdir,bindir,projectName,
- newTarget.c_str(),
- output,makeCommand.c_str(),config,false,fast,
- this->TryCompileTimeout);
+ }
+ std::string config =
+ mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
+ return this->Build(srcdir, bindir, projectName, newTarget, output, "",
+ config, false, fast, false, this->TryCompileTimeout);
}
-std::string cmGlobalGenerator
-::GenerateBuildCommand(const char* makeProgram, const char *projectName,
- const char *projectDir, const char* additionalOptions,
- const char *targetName, const char* config,
- bool ignoreErrors, bool)
+void cmGlobalGenerator::GenerateBuildCommand(
+ std::vector<std::string>& makeCommand, const std::string& /*unused*/,
+ const std::string& /*unused*/, const std::string& /*unused*/,
+ const std::string& /*unused*/, const std::string& /*unused*/,
+ bool /*unused*/, bool /*unused*/, std::vector<std::string> const& /*unused*/)
{
- // Project name & dir and config are not used yet.
- (void)projectName;
- (void)projectDir;
- (void)config;
-
- std::string makeCommand =
- cmSystemTools::ConvertToUnixOutputPath(makeProgram);
-
- // Since we have full control over the invocation of nmake, let us
- // make it quiet.
- if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
- {
- makeCommand += " /NOLOGO ";
- }
- if ( ignoreErrors )
- {
- makeCommand += " -i";
- }
- if ( additionalOptions )
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
- }
- if ( targetName )
- {
- makeCommand += " ";
- makeCommand += targetName;
- }
- return makeCommand;
+ makeCommand.push_back(
+ "cmGlobalGenerator::GenerateBuildCommand not implemented");
}
-int cmGlobalGenerator::Build(
- const char *, const char *bindir,
- const char *projectName, const char *target,
- std::string *output,
- const char *makeCommandCSTR,
- const char *config,
- bool clean, bool fast,
- double timeout,
- cmSystemTools::OutputOption outputflag,
- const char* extraOptions,
- std::vector<std::string> const& nativeOptions)
+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)
{
/**
* Run an executable command and put the stdout in output.
*/
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(bindir);
- if(output)
- {
- *output += "Change Dir: ";
- *output += bindir;
- *output += "\n";
- }
+ cmWorkingDirectory workdir(bindir);
+ output += "Change Dir: ";
+ output += bindir;
+ output += "\n";
int retVal;
bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
cmSystemTools::SetRunCommandHideConsole(true);
std::string outputBuffer;
- std::string* outputPtr = 0;
- if(output)
- {
- outputPtr = &outputBuffer;
- }
+ std::string* outputPtr = &outputBuffer;
+
+ std::vector<std::string> makeCommand;
+ this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir,
+ target, config, fast, verbose, nativeOptions);
+
+ // Workaround to convince VCExpress.exe to produce output.
+ if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
+ !makeCommand.empty() &&
+ cmSystemTools::LowerCase(
+ cmSystemTools::GetFilenameName(makeCommand[0])) == "vcexpress.exe") {
+ outputflag = cmSystemTools::OUTPUT_FORWARD;
+ }
// should we do a clean first?
- if (clean)
- {
- std::string cleanCommand =
- this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
- 0, "clean", config, false, fast);
- if(output)
- {
- *output += "\nRun Clean Command:";
- *output += cleanCommand;
- *output += "\n";
- }
-
- if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr,
- &retVal, 0, outputflag, timeout))
- {
+ if (clean) {
+ std::vector<std::string> cleanCommand;
+ this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName,
+ bindir, "clean", config, fast, verbose);
+ output += "\nRun Clean Command:";
+ output += cmSystemTools::PrintSingleCommand(cleanCommand);
+ output += "\n";
+
+ if (!cmSystemTools::RunSingleCommand(cleanCommand, outputPtr, outputPtr,
+ &retVal, CM_NULLPTR, outputflag,
+ timeout)) {
cmSystemTools::SetRunCommandHideConsole(hideconsole);
cmSystemTools::Error("Generator: execution of make clean failed.");
- if (output)
- {
- *output += *outputPtr;
- *output += "\nGenerator: execution of make clean failed.\n";
- }
+ output += *outputPtr;
+ output += "\nGenerator: execution of make clean failed.\n";
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
return 1;
- }
- if (output)
- {
- *output += *outputPtr;
- }
}
+ output += *outputPtr;
+ }
// now build
- std::string makeCommand =
- this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
- extraOptions, target,
- config, false, fast);
- if(output)
- {
- *output += "\nRun Build Command:";
- *output += makeCommand;
- *output += "\n";
- }
-
- std::vector<cmStdString> command =
- cmSystemTools::ParseArguments(makeCommand.c_str());
- for(std::vector<std::string>::const_iterator ni = nativeOptions.begin();
- ni != nativeOptions.end(); ++ni)
- {
- command.push_back(*ni);
- }
-
- if (!cmSystemTools::RunSingleCommand(command, outputPtr,
- &retVal, 0, outputflag, timeout))
- {
+ std::string makeCommandStr = cmSystemTools::PrintSingleCommand(makeCommand);
+ output += "\nRun Build Command:";
+ output += makeCommandStr;
+ output += "\n";
+
+ if (!cmSystemTools::RunSingleCommand(makeCommand, outputPtr, outputPtr,
+ &retVal, CM_NULLPTR, outputflag,
+ timeout)) {
cmSystemTools::SetRunCommandHideConsole(hideconsole);
- cmSystemTools::Error
- ("Generator: execution of make failed. Make command was: ",
- makeCommand.c_str());
- if (output)
- {
- *output += *outputPtr;
- *output += "\nGenerator: execution of make failed. Make command was: "
- + makeCommand + "\n";
- }
+ 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";
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
return 1;
- }
- if (output)
- {
- *output += *outputPtr;
- }
+ }
+ output += *outputPtr;
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))
- {
+ if ((retVal == 0) && (output.find("#error") != std::string::npos)) {
retVal = 1;
- }
+ }
- cmSystemTools::ChangeDirectory(cwd.c_str());
return retVal;
}
-void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
+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 .";
+ if (!config.empty()) {
+ makeCommand += " --config \"";
+ makeCommand += config;
+ makeCommand += "\"";
+ }
+ if (!target.empty()) {
+ makeCommand += " --target \"";
+ makeCommand += target;
+ makeCommand += "\"";
+ }
+ const char* sep = " -- ";
+ if (ignoreErrors) {
+ const char* iflag = this->GetBuildIgnoreErrorsFlag();
+ if (iflag && *iflag) {
+ makeCommand += sep;
+ makeCommand += iflag;
+ sep = " ";
+ }
+ }
+ if (!native.empty()) {
+ makeCommand += sep;
+ makeCommand += native;
+ }
+ return makeCommand;
+}
+
+void cmGlobalGenerator::AddMakefile(cmMakefile* mf)
{
- this->LocalGenerators.push_back(lg);
+ this->Makefiles.push_back(mf);
+ this->IndexMakefile(mf);
// update progress
// estimate how many lg there will be
- const char *numGenC =
- this->CMakeInstance->GetCacheManager()->GetCacheValue
- ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
+ const char* numGenC =
+ this->CMakeInstance->GetState()->GetInitializedCacheValue(
+ "CMAKE_NUMBER_OF_MAKEFILES");
- if (!numGenC)
- {
- // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
+ if (!numGenC) {
+ // If CMAKE_NUMBER_OF_MAKEFILES is not set
// we are in the first time progress and we have no
// idea how long it will be. So, just move half way
// there each time, and don't go over 95%
- this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
- if(this->FirstTimeProgress > 0.95f)
- {
+ this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) / 30.0f);
+ if (this->FirstTimeProgress > 0.95f) {
this->FirstTimeProgress = 0.95f;
- }
+ }
this->CMakeInstance->UpdateProgress("Configuring",
this->FirstTimeProgress);
return;
- }
+ }
int numGen = atoi(numGenC);
- float prog = 0.9f*static_cast<float>(this->LocalGenerators.size())/
+ float prog = 0.9f * static_cast<float>(this->Makefiles.size()) /
static_cast<float>(numGen);
- if (prog > 0.9f)
- {
+ if (prog > 0.9f) {
prog = 0.9f;
- }
+ }
this->CMakeInstance->UpdateProgress("Configuring", prog);
}
void cmGlobalGenerator::AddInstallComponent(const char* component)
{
- if(component && *component)
- {
+ if (component && *component) {
this->InstallComponents.insert(component);
- }
+ }
}
void cmGlobalGenerator::EnableInstallTarget()
@@ -1617,25 +1938,23 @@ void cmGlobalGenerator::EnableInstallTarget()
this->InstallTargetEnabled = true;
}
-cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalGenerator::CreateLocalGenerator(cmMakefile* mf)
{
- cmLocalGenerator *lg = new cmLocalGenerator;
- lg->SetGlobalGenerator(this);
- return lg;
+ return new cmLocalGenerator(this, mf);
}
-void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen,
+void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen,
cmMakefile* mf)
{
this->SetConfiguredFilesPath(gen);
this->TryCompileOuterMakefile = mf;
const char* make =
gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
- this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
- "make program",
- cmCacheManager::FILEPATH);
+ this->GetCMakeInstance()->AddCacheEntry(
+ "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH);
// copy the enabled languages
- this->LanguageEnabled = gen->LanguageEnabled;
+ this->GetCMakeInstance()->GetState()->SetEnabledLanguages(
+ gen->GetCMakeInstance()->GetState()->GetEnabledLanguages());
this->LanguagesReady = gen->LanguagesReady;
this->ExtensionToLanguage = gen->ExtensionToLanguage;
this->IgnoreExtensions = gen->IgnoreExtensions;
@@ -1644,73 +1963,72 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen,
this->OutputExtensions = gen->OutputExtensions;
}
-//----------------------------------------------------------------------------
void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
{
- if(!gen->ConfiguredFilesPath.empty())
- {
+ if (!gen->ConfiguredFilesPath.empty()) {
this->ConfiguredFilesPath = gen->ConfiguredFilesPath;
- }
- else
- {
+ } else {
this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory();
this->ConfiguredFilesPath += cmake::GetCMakeFilesDirectory();
- }
+ }
}
-bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
- cmLocalGenerator* gen)
+bool cmGlobalGenerator::IsExcluded(cmStateSnapshot const& rootSnp,
+ cmStateSnapshot const& snp_) const
{
- if(!gen || gen == root)
- {
- // No directory excludes itself.
- return false;
+ cmStateSnapshot snp = snp_;
+ while (snp.IsValid()) {
+ if (snp == rootSnp) {
+ // No directory excludes itself.
+ return false;
}
- if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
- {
- // This directory is excluded from its parent.
- return true;
+ if (snp.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ // This directory is excluded from its parent.
+ return true;
}
+ snp = snp.GetBuildsystemDirectoryParent();
+ }
+ return false;
+}
+
+bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
+ cmLocalGenerator* gen) const
+{
+ assert(gen);
- // This directory is included in its parent. Check whether the
- // parent is excluded.
- return this->IsExcluded(root, gen->GetParent());
+ cmStateSnapshot rootSnp = root->GetStateSnapshot();
+ cmStateSnapshot snp = gen->GetStateSnapshot();
+
+ return this->IsExcluded(rootSnp, snp);
}
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
- cmTarget& target)
+ cmGeneratorTarget* target) const
{
- if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
- {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
// This target is excluded from its directory.
return true;
- }
- else
- {
- // This target is included in its directory. Check whether the
- // directory is excluded.
- return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
- }
+ }
+ // This target is included in its directory. Check whether the
+ // directory is excluded.
+ return this->IsExcluded(root, target->GetLocalGenerator());
}
-void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
+void cmGlobalGenerator::GetEnabledLanguages(
+ std::vector<std::string>& lang) const
{
- for(std::map<cmStdString, bool>::iterator i =
- this->LanguageEnabled.begin(); i != this->LanguageEnabled.end(); ++i)
- {
- lang.push_back(i->first);
- }
+ lang = this->CMakeInstance->GetState()->GetEnabledLanguages();
}
-int cmGlobalGenerator::GetLinkerPreference(const char* lang)
+int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const
{
- std::map<cmStdString, int>::const_iterator it =
- this->LanguageToLinkerPreference.find(lang);
- if (it != this->LanguageToLinkerPreference.end())
- {
+ std::map<std::string, int>::const_iterator it =
+ this->LanguageToLinkerPreference.find(lang);
+ if (it != this->LanguageToLinkerPreference.end()) {
return it->second;
- }
+ }
return 0;
}
@@ -1718,457 +2036,421 @@ 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 (i = 0; i < this->LocalGenerators.size(); ++i) {
// for each local generator add all projects
- cmLocalGenerator *lg = this->LocalGenerators[i];
+ cmStateSnapshot snp = this->LocalGenerators[i]->GetStateSnapshot();
std::string name;
- do
- {
- if (name != lg->GetMakefile()->GetProjectName())
- {
- name = lg->GetMakefile()->GetProjectName();
+ do {
+ std::string snpProjName = snp.GetProjectName();
+ if (name != snpProjName) {
+ name = snpProjName;
this->ProjectMap[name].push_back(this->LocalGenerators[i]);
- }
- lg = lg->GetParent();
}
- while (lg);
- }
+ snp = snp.GetBuildsystemDirectoryParent();
+ } while (snp.IsValid());
+ }
}
-
-// Build a map that contains a the set of targets used by each local
-// generator directory level.
-void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
+cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const
{
- this->LocalGeneratorToTargetMap.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;
- cmMakefile* mf = lg->GetMakefile();
- cmTargets& targets = mf->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- cmTarget& target = t->second;
-
- // Consider the directory containing the target and all its
- // parents until something excludes the target.
- for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
- clg = clg->GetParent())
- {
- // This local generator includes the target.
- std::set<cmTarget*>& targetSet =
- this->LocalGeneratorToTargetMap[clg];
- targetSet.insert(&target);
-
- // 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(target);
- for(TargetDependSet::const_iterator ti = tgtdeps.begin();
- ti != tgtdeps.end(); ++ti)
- {
- targetSet.insert(*ti);
- }
- }
- }
- }
+ MakefileMap::const_iterator i = this->MakefileSearchIndex.find(start_dir);
+ if (i != this->MakefileSearchIndex.end()) {
+ return i->second;
+ }
+ return CM_NULLPTR;
}
-
///! Find a local generator by its startdirectory
-cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
+cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(
+ const std::string& start_dir) const
{
- std::vector<cmLocalGenerator*>* gens = &this->LocalGenerators;
- for(unsigned int i = 0; i < gens->size(); ++i)
- {
- std::string sd = (*gens)[i]->GetMakefile()->GetStartDirectory();
- if (sd == start_dir)
- {
- return (*gens)[i];
- }
+ 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;
}
- return 0;
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt)
+void cmGlobalGenerator::AddAlias(const std::string& name,
+ std::string const& tgtName)
{
- this->AliasTargets[name] = tgt;
+ this->AliasTargets[name] = tgtName;
}
-//----------------------------------------------------------------------------
-bool cmGlobalGenerator::IsAlias(const char *name)
+bool cmGlobalGenerator::IsAlias(const std::string& name) const
{
return this->AliasTargets.find(name) != this->AliasTargets.end();
}
-//----------------------------------------------------------------------------
-cmTarget*
-cmGlobalGenerator::FindTarget(const char* project, const char* name,
- bool excludeAliases)
+void cmGlobalGenerator::IndexTarget(cmTarget* t)
{
- // if project specific
- if(project)
- {
- std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
- for(unsigned int i = 0; i < gens->size(); ++i)
- {
- cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
- excludeAliases);
- if(ret)
- {
- return ret;
- }
- }
- }
- // if all projects/directories
- else
- {
- if (!excludeAliases)
- {
- std::map<cmStdString, cmTarget*>::iterator ai
- = this->AliasTargets.find(name);
- if (ai != this->AliasTargets.end())
- {
- return ai->second;
- }
- }
- std::map<cmStdString,cmTarget *>::iterator i =
- this->TotalTargets.find ( name );
- if ( i != this->TotalTargets.end() )
- {
- return i->second;
- }
- i = this->ImportedTargets.find(name);
- if ( i != this->ImportedTargets.end() )
- {
- return i->second;
- }
+ if (!t->IsImported() || t->IsImportedGloballyVisible()) {
+ this->TargetSearchIndex[t->GetName()] = t;
+ }
+}
+
+void cmGlobalGenerator::IndexGeneratorTarget(cmGeneratorTarget* gt)
+{
+ if (!gt->IsImported() || gt->IsImportedGloballyVisible()) {
+ this->GeneratorTargetSearchIndex[gt->GetName()] = gt;
+ }
+}
+
+void cmGlobalGenerator::IndexMakefile(cmMakefile* mf)
+{
+ // FIXME: add_subdirectory supports multiple build directories
+ // sharing the same source directory. We currently index only the
+ // first one, because that is what FindMakefile has always returned.
+ // All of its callers will need to be modified to support looking
+ // up directories by build directory path.
+ this->MakefileSearchIndex.insert(
+ MakefileMap::value_type(mf->GetCurrentSourceDirectory(), mf));
+}
+
+cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const
+{
+ TargetMap::const_iterator i = this->TargetSearchIndex.find(name);
+ if (i != this->TargetSearchIndex.end()) {
+ return i->second;
+ }
+ return CM_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;
+ }
+ return CM_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);
+ if (ai != this->AliasTargets.end()) {
+ return this->FindTargetImpl(ai->second);
}
- return 0;
+ }
+ return this->FindTargetImpl(name);
}
-//----------------------------------------------------------------------------
-bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
+cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget(
+ const std::string& name) const
{
- if(cmSystemTools::IsPathToFramework(libname.c_str()))
- {
+ std::map<std::string, std::string>::const_iterator ai =
+ this->AliasTargets.find(name);
+ if (ai != this->AliasTargets.end()) {
+ return this->FindGeneratorTargetImpl(ai->second);
+ }
+ return this->FindGeneratorTargetImpl(name);
+}
+
+bool cmGlobalGenerator::NameResolvesToFramework(
+ const std::string& libname) const
+{
+ if (cmSystemTools::IsPathToFramework(libname.c_str())) {
return true;
- }
+ }
- if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
- {
- if(tgt->IsFrameworkOnApple())
- {
- return true;
- }
+ if (cmTarget* tgt = this->FindTarget(libname)) {
+ if (tgt->IsFrameworkOnApple()) {
+ return true;
}
+ }
return false;
}
-//----------------------------------------------------------------------------
inline std::string removeQuotes(const std::string& s)
{
- if(s[0] == '\"' && s[s.size()-1] == '\"')
- {
- return s.substr(1, s.size()-2);
- }
+ if (s[0] == '\"' && s[s.size() - 1] == '\"') {
+ return s.substr(1, s.size() - 2);
+ }
return s;
}
-void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
+void cmGlobalGenerator::CreateDefaultGlobalTargets(
+ std::vector<GlobalTargetInfo>& targets)
{
- // Store a pointer to the cmake object instance.
- this->CMakeInstance = cm;
+ this->AddGlobalTarget_Package(targets);
+ this->AddGlobalTarget_PackageSource(targets);
+ this->AddGlobalTarget_Test(targets);
+ this->AddGlobalTarget_EditCache(targets);
+ this->AddGlobalTarget_RebuildCache(targets);
+ this->AddGlobalTarget_Install(targets);
}
-void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
+void cmGlobalGenerator::AddGlobalTarget_Package(
+ std::vector<GlobalTargetInfo>& targets)
{
- cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
+ cmMakefile* mf = this->Makefiles[0];
const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
- const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
-
- // CPack
- std::string workingDir = mf->GetStartOutputDirectory();
- cmCustomCommandLines cpackCommandLines;
- std::vector<std::string> depends;
+ GlobalTargetInfo gti;
+ gti.Name = this->GetPackageTargetName();
+ gti.Message = "Run CPack packaging tool...";
+ gti.UsesTerminal = true;
+ gti.WorkingDir = mf->GetCurrentBinaryDirectory();
cmCustomCommandLine singleLine;
- singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
- if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
- {
+ singleLine.push_back(cmSystemTools::GetCPackCommand());
+ if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
singleLine.push_back("-C");
singleLine.push_back(cmakeCfgIntDir);
- }
+ }
singleLine.push_back("--config");
- std::string configFile = mf->GetStartOutputDirectory();;
+ std::string configFile = mf->GetCurrentBinaryDirectory();
configFile += "/CPackConfig.cmake";
std::string relConfigFile = "./CPackConfig.cmake";
singleLine.push_back(relConfigFile);
- cpackCommandLines.push_back(singleLine);
- if ( this->GetPreinstallTargetName() )
- {
- depends.push_back(this->GetPreinstallTargetName());
- }
- else
- {
+ gti.CommandLines.push_back(singleLine);
+ if (this->GetPreinstallTargetName()) {
+ gti.Depends.push_back(this->GetPreinstallTargetName());
+ } else {
const char* noPackageAll =
mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
- if(!noPackageAll || cmSystemTools::IsOff(noPackageAll))
- {
- depends.push_back(this->GetAllTargetName());
- }
- }
- if(cmSystemTools::FileExists(configFile.c_str()))
- {
- (*targets)[this->GetPackageTargetName()]
- = this->CreateGlobalTarget(this->GetPackageTargetName(),
- "Run CPack packaging tool...",
- &cpackCommandLines, depends,
- workingDir.c_str());
+ if (!noPackageAll || cmSystemTools::IsOff(noPackageAll)) {
+ gti.Depends.push_back(this->GetAllTargetName());
}
- // CPack source
+ }
+ if (cmSystemTools::FileExists(configFile.c_str())) {
+ targets.push_back(gti);
+ }
+}
+
+void cmGlobalGenerator::AddGlobalTarget_PackageSource(
+ std::vector<GlobalTargetInfo>& targets)
+{
+ cmMakefile* mf = this->Makefiles[0];
const char* packageSourceTargetName = this->GetPackageSourceTargetName();
- if ( packageSourceTargetName )
- {
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- singleLine.erase(singleLine.begin(), singleLine.end());
- depends.erase(depends.begin(), depends.end());
- singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
+ 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");
- configFile = mf->GetStartOutputDirectory();;
+ std::string configFile = mf->GetCurrentBinaryDirectory();
configFile += "/CPackSourceConfig.cmake";
- relConfigFile = "./CPackSourceConfig.cmake";
+ std::string relConfigFile = "./CPackSourceConfig.cmake";
singleLine.push_back(relConfigFile);
- if(cmSystemTools::FileExists(configFile.c_str()))
- {
+ if (cmSystemTools::FileExists(configFile.c_str())) {
singleLine.push_back(configFile);
- cpackCommandLines.push_back(singleLine);
- (*targets)[packageSourceTargetName]
- = this->CreateGlobalTarget(packageSourceTargetName,
- "Run CPack packaging tool for source...",
- &cpackCommandLines, depends,
- workingDir.c_str()
- );
- }
+ gti.CommandLines.push_back(singleLine);
+ targets.push_back(gti);
}
+ }
+}
- // Test
- if(mf->IsOn("CMAKE_TESTING_ENABLED"))
- {
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- singleLine.erase(singleLine.begin(), singleLine.end());
- depends.erase(depends.begin(), depends.end());
- singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand());
+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] != '.')
- {
+ 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
- {
+ } else // TODO: This is a hack. Should be something to do with the
+ // generator
+ {
singleLine.push_back("$(ARGS)");
- }
- cpackCommandLines.push_back(singleLine);
- (*targets)[this->GetTestTargetName()]
- = this->CreateGlobalTarget(this->GetTestTargetName(),
- "Running tests...", &cpackCommandLines, depends, 0);
}
+ gti.CommandLines.push_back(singleLine);
+ targets.push_back(gti);
+ }
+}
- //Edit Cache
+void cmGlobalGenerator::AddGlobalTarget_EditCache(
+ std::vector<GlobalTargetInfo>& targets)
+{
const char* editCacheTargetName = this->GetEditCacheTargetName();
- if ( editCacheTargetName )
- {
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- singleLine.erase(singleLine.begin(), singleLine.end());
- depends.erase(depends.begin(), depends.end());
-
- // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
- // Otherwise default to the interactive command-line interface.
- if(mf->GetDefinition("CMAKE_EDIT_COMMAND"))
- {
- singleLine.push_back(mf->GetDefinition("CMAKE_EDIT_COMMAND"));
+ 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)");
- cpackCommandLines.push_back(singleLine);
- (*targets)[editCacheTargetName] =
- this->CreateGlobalTarget(
- editCacheTargetName, "Running CMake cache editor...",
- &cpackCommandLines, depends, 0);
- }
- else
- {
- singleLine.push_back(cmakeCommand);
- singleLine.push_back("-i");
- singleLine.push_back(".");
- cpackCommandLines.push_back(singleLine);
- (*targets)[editCacheTargetName] =
- this->CreateGlobalTarget(
- editCacheTargetName,
- "Running interactive CMake command-line interface...",
- &cpackCommandLines, depends, 0);
- }
- }
+ 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);
+ }
+
+ targets.push_back(gti);
+ }
+}
- //Rebuild Cache
+void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
+ std::vector<GlobalTargetInfo>& targets)
+{
const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
- if ( rebuildCacheTargetName )
- {
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- singleLine.erase(singleLine.begin(), singleLine.end());
- depends.erase(depends.begin(), depends.end());
- singleLine.push_back(cmakeCommand);
+ 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)");
- cpackCommandLines.push_back(singleLine);
- (*targets)[rebuildCacheTargetName] =
- this->CreateGlobalTarget(
- rebuildCacheTargetName, "Running CMake to regenerate build system...",
- &cpackCommandLines, depends, 0);
- }
+ gti.CommandLines.push_back(singleLine);
+ targets.push_back(gti);
+ }
+}
- //Install
- if(this->InstallTargetEnabled)
- {
- if(!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.')
- {
- std::set<cmStdString>* componentsSet = &this->InstallComponents;
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- depends.erase(depends.begin(), depends.end());
- cmOStringStream ostr;
- if ( componentsSet->size() > 0 )
- {
- ostr << "Available install components are:";
- std::set<cmStdString>::iterator it;
- for (
- it = componentsSet->begin();
- it != componentsSet->end();
- ++ it )
- {
- ostr << " \"" << it->c_str() << "\"";
- }
- }
- else
- {
+void cmGlobalGenerator::AddGlobalTarget_Install(
+ std::vector<GlobalTargetInfo>& targets)
+{
+ cmMakefile* mf = this->Makefiles[0];
+ const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
+ 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",
+ mf->GetBacktrace());
+ } else if (this->InstallTargetEnabled && !skipInstallRules) {
+ if (!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.') {
+ std::set<std::string>* componentsSet = &this->InstallComponents;
+ std::ostringstream ostr;
+ if (!componentsSet->empty()) {
+ ostr << "Available install components are: ";
+ ostr << cmWrap('"', *componentsSet, '"', " ");
+ } else {
ostr << "Only default component available";
- }
- singleLine.push_back(ostr.str().c_str());
- (*targets)["list_install_components"]
- = this->CreateGlobalTarget("list_install_components",
- ostr.str().c_str(),
- &cpackCommandLines, depends, 0);
- }
- std::string cmd = cmakeCommand;
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- singleLine.erase(singleLine.begin(), singleLine.end());
- depends.erase(depends.begin(), depends.end());
- if ( this->GetPreinstallTargetName() )
- {
- depends.push_back(this->GetPreinstallTargetName());
}
- else
- {
+ GlobalTargetInfo gti;
+ gti.Name = "list_install_components";
+ gti.Message = ostr.str();
+ gti.UsesTerminal = false;
+ targets.push_back(gti);
+ }
+ std::string cmd = cmSystemTools::GetCMakeCommand();
+ GlobalTargetInfo gti;
+ gti.Name = this->GetInstallTargetName();
+ gti.Message = "Install the project...";
+ gti.UsesTerminal = true;
+ cmCustomCommandLine singleLine;
+ if (this->GetPreinstallTargetName()) {
+ gti.Depends.push_back(this->GetPreinstallTargetName());
+ } else {
const char* noall =
mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
- if(!noall || cmSystemTools::IsOff(noall))
- {
- depends.push_back(this->GetAllTargetName());
- }
+ if (!noall || cmSystemTools::IsOff(noall)) {
+ gti.Depends.push_back(this->GetAllTargetName());
}
- if(mf->GetDefinition("CMake_BINARY_DIR"))
- {
+ }
+ if (mf->GetDefinition("CMake_BINARY_DIR") &&
+ !mf->IsOn("CMAKE_CROSSCOMPILING")) {
// We are building CMake itself. We cannot use the original
// executable to install over itself. The generator will
// automatically convert this name to the build-time location.
cmd = "cmake";
- }
- singleLine.push_back(cmd.c_str());
- if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
- {
+ }
+ singleLine.push_back(cmd);
+ if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
std::string cfgArg = "-DBUILD_TYPE=";
- cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
- singleLine.push_back(cfgArg);
+ bool useEPN = this->UseEffectivePlatformName(mf);
+ if (useEPN) {
+ cfgArg += "$(CONFIGURATION)";
+ singleLine.push_back(cfgArg);
+ cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)";
+ } else {
+ cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
}
+ singleLine.push_back(cfgArg);
+ }
singleLine.push_back("-P");
singleLine.push_back("cmake_install.cmake");
- cpackCommandLines.push_back(singleLine);
- (*targets)[this->GetInstallTargetName()] =
- this->CreateGlobalTarget(
- this->GetInstallTargetName(), "Install the project...",
- &cpackCommandLines, depends, 0);
+ gti.CommandLines.push_back(singleLine);
+ targets.push_back(gti);
// install_local
- if(const char* install_local = this->GetInstallLocalTargetName())
- {
+ if (const char* install_local = this->GetInstallLocalTargetName()) {
+ gti.Name = install_local;
+ gti.Message = "Installing only the local directory...";
+ gti.UsesTerminal = true;
+ gti.CommandLines.clear();
+
cmCustomCommandLine localCmdLine = singleLine;
- localCmdLine.insert(localCmdLine.begin()+1,
- "-DCMAKE_INSTALL_LOCAL_ONLY=1");
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- cpackCommandLines.push_back(localCmdLine);
+ localCmdLine.insert(localCmdLine.begin() + 1,
+ "-DCMAKE_INSTALL_LOCAL_ONLY=1");
- (*targets)[install_local] =
- this->CreateGlobalTarget(
- install_local, "Installing only the local directory...",
- &cpackCommandLines, depends, 0);
- }
+ gti.CommandLines.push_back(localCmdLine);
+ targets.push_back(gti);
+ }
// install_strip
const char* install_strip = this->GetInstallStripTargetName();
- if((install_strip !=0) && (mf->IsSet("CMAKE_STRIP")))
- {
- cmCustomCommandLine stripCmdLine = singleLine;
+ if ((install_strip != CM_NULLPTR) && (mf->IsSet("CMAKE_STRIP"))) {
+ gti.Name = install_strip;
+ gti.Message = "Installing the project stripped...";
+ gti.UsesTerminal = true;
+ gti.CommandLines.clear();
- stripCmdLine.insert(stripCmdLine.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
- cpackCommandLines.erase(cpackCommandLines.begin(),
- cpackCommandLines.end());
- cpackCommandLines.push_back(stripCmdLine);
+ cmCustomCommandLine stripCmdLine = singleLine;
- (*targets)[install_strip] =
- this->CreateGlobalTarget(
- install_strip, "Installing the project stripped...",
- &cpackCommandLines, depends, 0);
- }
+ stripCmdLine.insert(stripCmdLine.begin() + 1,
+ "-DCMAKE_INSTALL_DO_STRIP=1");
+ gti.CommandLines.push_back(stripCmdLine);
+ targets.push_back(gti);
}
+ }
}
-//----------------------------------------------------------------------------
const char* cmGlobalGenerator::GetPredefinedTargetsFolder()
{
- const char* prop =
- this->GetCMakeInstance()->GetProperty("PREDEFINED_TARGETS_FOLDER");
+ const char* prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
+ "PREDEFINED_TARGETS_FOLDER");
- if (prop)
- {
+ if (prop) {
return prop;
- }
+ }
return "CMakePredefinedTargets";
}
-//----------------------------------------------------------------------------
-bool cmGlobalGenerator::UseFolderProperty()
+bool cmGlobalGenerator::UseFolderProperty() const
{
- const char* prop = this->GetCMakeInstance()->GetProperty("USE_FOLDERS");
+ const char* prop =
+ this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS");
// If this property is defined, let the setter turn this on or off...
//
- if (prop)
- {
+ if (prop) {
return cmSystemTools::IsOn(prop);
- }
+ }
// By default, this feature is OFF, since it is not supported in the
// Visual Studio Express editions until VS11:
@@ -2176,141 +2458,113 @@ bool cmGlobalGenerator::UseFolderProperty()
return false;
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::EnableMinGWLanguage(cmMakefile *mf)
-{
- this->FindMakeProgram(mf);
- std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- std::vector<std::string> locations;
- locations.push_back(cmSystemTools::GetProgramPath(makeProgram.c_str()));
- locations.push_back("/mingw/bin");
- locations.push_back("c:/mingw/bin");
- std::string tgcc = cmSystemTools::FindProgram("gcc", locations);
- std::string gcc = "gcc.exe";
- if(tgcc.size())
- {
- gcc = tgcc;
- }
- std::string tgxx = cmSystemTools::FindProgram("g++", locations);
- std::string gxx = "g++.exe";
- if(tgxx.size())
- {
- gxx = tgxx;
- }
- std::string trc = cmSystemTools::FindProgram("windres", locations);
- std::string rc = "windres.exe";
- if(trc.size())
- {
- 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());
-}
-
-//----------------------------------------------------------------------------
-cmTarget cmGlobalGenerator::CreateGlobalTarget(
- const char* name, const char* message,
- const cmCustomCommandLines* commandLines,
- std::vector<std::string> depends,
- const char* workingDirectory)
+cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
+ cmMakefile* mf)
{
// Package
- cmTarget target;
- target.GetProperties().SetCMakeInstance(this->CMakeInstance);
- target.SetType(cmTarget::GLOBAL_TARGET, name);
- target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
+ cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET,
+ cmTarget::VisibilityNormal, mf);
+ target.SetProperty("EXCLUDE_FROM_ALL", "TRUE");
std::vector<std::string> no_outputs;
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
// Store the custom command in the target.
- cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0,
- workingDirectory);
- target.GetPostBuildCommands().push_back(cc);
- target.SetProperty("EchoString", message);
- std::vector<std::string>::iterator dit;
- for ( dit = depends.begin(); dit != depends.end(); ++ dit )
- {
- target.AddUtility(dit->c_str());
- }
+ cmCustomCommand cc(CM_NULLPTR, no_outputs, no_byproducts, no_depends,
+ gti.CommandLines, CM_NULLPTR, gti.WorkingDir.c_str());
+ cc.SetUsesTerminal(gti.UsesTerminal);
+ target.AddPostBuildCommand(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);
+ }
// Organize in the "predefined targets" folder:
//
- if (this->UseFolderProperty())
- {
+ if (this->UseFolderProperty()) {
target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
- }
+ }
return target;
}
-//----------------------------------------------------------------------------
-std::string
-cmGlobalGenerator::GenerateRuleFile(std::string const& output) const
+std::string cmGlobalGenerator::GenerateRuleFile(
+ std::string const& output) const
{
std::string ruleFile = output;
ruleFile += ".rule";
const char* dir = this->GetCMakeCFGIntDir();
- if(dir && dir[0] == '$')
- {
+ if (dir && dir[0] == '$') {
cmSystemTools::ReplaceString(ruleFile, dir,
cmake::GetCMakeFilesDirectory());
- }
+ }
return ruleFile;
}
-//----------------------------------------------------------------------------
+bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
+{
+ return mf->PlatformIsAppleIos();
+}
+
std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
- std::string const& l)
+ std::string const& l) const
{
- if(this->LanguageToOriginalSharedLibFlags.count(l) > 0)
- {
- return this->LanguageToOriginalSharedLibFlags[l];
- }
+ std::map<std::string, std::string>::const_iterator it =
+ this->LanguageToOriginalSharedLibFlags.find(l);
+ if (it != this->LanguageToOriginalSharedLibFlags.end()) {
+ return it->second;
+ }
return "";
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
- const char*, std::string&)
+void cmGlobalGenerator::AppendDirectoryForConfig(const std::string& /*unused*/,
+ const std::string& /*unused*/,
+ const std::string& /*unused*/,
+ std::string& /*unused*/)
{
// Subclasses that support multiple configurations should implement
// this method to append the subdirectory for the given build
// configuration.
}
-//----------------------------------------------------------------------------
cmGlobalGenerator::TargetDependSet const&
-cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
+cmGlobalGenerator::GetTargetDirectDepends(cmGeneratorTarget const* target)
{
- return this->TargetDependencies[&target];
+ return this->TargetDependencies[target];
}
-void cmGlobalGenerator::AddTarget(cmTarget* t)
+bool cmGlobalGenerator::IsReservedTarget(std::string const& name)
{
- if(t->IsImported())
- {
- this->ImportedTargets[t->GetName()] = t;
- }
- else
- {
- this->TotalTargets[t->GetName()] = t;
- }
+ // The following is a list of targets reserved
+ // 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"
+ };
+
+ return std::find(cmArrayBegin(reservedTargets), cmArrayEnd(reservedTargets),
+ name) != cmArrayEnd(reservedTargets);
}
void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
- cmExternalMakefileProjectGenerator *extraGenerator)
+ cmExternalMakefileProjectGenerator* extraGenerator)
{
this->ExtraGenerator = extraGenerator;
- if (this->ExtraGenerator!=0)
- {
+ if (this->ExtraGenerator != CM_NULLPTR) {
this->ExtraGenerator->SetGlobalGenerator(this);
- }
+ }
}
-const char* cmGlobalGenerator::GetExtraGeneratorName() const
+std::string cmGlobalGenerator::GetExtraGeneratorName() const
{
- return this->ExtraGenerator==0 ? 0 : this->ExtraGenerator->GetName();
+ return this->ExtraGenerator ? this->ExtraGenerator->GetName()
+ : std::string();
}
void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
@@ -2318,146 +2572,123 @@ void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
this->FilesReplacedDuringGenerate.push_back(filename);
}
-void
-cmGlobalGenerator
-::GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames)
+void cmGlobalGenerator::GetFilesReplacedDuringGenerate(
+ std::vector<std::string>& filenames)
{
filenames.clear();
- std::copy(
- this->FilesReplacedDuringGenerate.begin(),
- this->FilesReplacedDuringGenerate.end(),
- std::back_inserter(filenames));
+ std::copy(this->FilesReplacedDuringGenerate.begin(),
+ this->FilesReplacedDuringGenerate.end(),
+ std::back_inserter(filenames));
}
-//----------------------------------------------------------------------------
void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets,
TargetDependSet& originalTargets,
cmLocalGenerator* root,
GeneratorVector const& generators)
{
// loop over all local generators
- for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
- i != generators.end(); ++i)
- {
+ for (std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
+ i != generators.end(); ++i) {
// check to make sure generator is not excluded
- if(this->IsExcluded(root, *i))
- {
+ if (this->IsExcluded(root, *i)) {
continue;
- }
- cmMakefile* mf = (*i)->GetMakefile();
+ }
// Get the targets in the makefile
- cmTargets &tgts = mf->GetTargets();
+ std::vector<cmGeneratorTarget*> tgts = (*i)->GetGeneratorTargets();
// loop over all the targets
- for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
- {
- cmTarget* target = &l->second;
- if(this->IsRootOnlyTarget(target) &&
- target->GetMakefile() != root->GetMakefile())
- {
+ for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
+ l != tgts.end(); ++l) {
+ cmGeneratorTarget* target = *l;
+ if (this->IsRootOnlyTarget(target) &&
+ target->GetLocalGenerator() != root) {
continue;
- }
+ }
// put the target in the set of original targets
originalTargets.insert(target);
// Get the set of targets that depend on target
this->AddTargetDepends(target, projectTargets);
- }
}
+ }
}
-//----------------------------------------------------------------------------
-bool cmGlobalGenerator::IsRootOnlyTarget(cmTarget* target)
+bool cmGlobalGenerator::IsRootOnlyTarget(cmGeneratorTarget* target) const
{
- return (target->GetType() == cmTarget::GLOBAL_TARGET ||
- strcmp(target->GetName(), this->GetAllTargetName()) == 0);
+ return (target->GetType() == cmStateEnums::GLOBAL_TARGET ||
+ target->GetName() == this->GetAllTargetName());
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::AddTargetDepends(cmTarget* target,
+void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target,
TargetDependSet& projectTargets)
{
// add the target itself
- if(projectTargets.insert(target).second)
- {
+ 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)
- {
- cmTarget* dtarget = *i;
- this->AddTargetDepends(dtarget, projectTargets);
- }
+ TargetDependSet const& ts = this->GetTargetDirectDepends(target);
+ for (TargetDependSet::const_iterator i = ts.begin(); i != ts.end(); ++i) {
+ this->AddTargetDepends(*i, projectTargets);
}
+ }
}
-
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::AddToManifest(const char* config,
- std::string const& f)
+void cmGlobalGenerator::AddToManifest(std::string const& f)
{
- // Add to the main manifest for this configuration.
- this->TargetManifest[config].insert(f);
-
// Add to the content listing for the file's directory.
std::string dir = cmSystemTools::GetFilenamePath(f);
std::string file = cmSystemTools::GetFilenameName(f);
- this->DirectoryContentMap[dir].insert(file);
+ DirectoryContent& dc = this->DirectoryContentMap[dir];
+ dc.Generated.insert(file);
+ dc.All.insert(file);
}
-//----------------------------------------------------------------------------
-std::set<cmStdString> const&
-cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
+std::set<std::string> const& cmGlobalGenerator::GetDirectoryContent(
+ std::string const& dir, bool needDisk)
{
DirectoryContent& dc = this->DirectoryContentMap[dir];
- if(needDisk && !dc.LoadedFromDisk)
- {
- // Load the directory content from disk.
- cmsys::Directory d;
- if(d.Load(dir.c_str()))
- {
- unsigned long n = d.GetNumberOfFiles();
- for(unsigned long i = 0; i < n; ++i)
- {
- const char* f = d.GetFile(i);
- if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
- {
- dc.insert(f);
+ if (needDisk) {
+ long mt = cmSystemTools::ModifiedTime(dir);
+ if (mt != dc.LastDiskTime) {
+ // Reset to non-loaded directory content.
+ dc.All = dc.Generated;
+
+ // Load the directory content from disk.
+ cmsys::Directory d;
+ if (d.Load(dir)) {
+ unsigned long n = d.GetNumberOfFiles();
+ for (unsigned long i = 0; i < n; ++i) {
+ const char* f = d.GetFile(i);
+ if (strcmp(f, ".") != 0 && strcmp(f, "..") != 0) {
+ dc.All.insert(f);
}
}
}
- dc.LoadedFromDisk = true;
+ dc.LastDiskTime = mt;
}
- return dc;
+ }
+ return dc.All;
}
-//----------------------------------------------------------------------------
-void
-cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
- std::string const& content)
+void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
+ std::string const& content)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
// Ignore if there are no outputs.
- if(outputs.empty())
- {
+ if (outputs.empty()) {
return;
- }
+ }
// Compute a hash of the rule.
RuleHash hash;
{
- unsigned char const* data =
- reinterpret_cast<unsigned char const*>(content.c_str());
- int length = static_cast<int>(content.length());
- cmsysMD5* sum = cmsysMD5_New();
- cmsysMD5_Initialize(sum);
- cmsysMD5_Append(sum, data, length);
- cmsysMD5_FinalizeHex(sum, hash.Data);
- cmsysMD5_Delete(sum);
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
+ std::string const md5_hex = md5.HashString(content);
+ memcpy(hash.Data, md5_hex.c_str(), 32);
}
// Shorten the output name (in expected use case).
- cmLocalGenerator* lg = this->GetLocalGenerators()[0];
- std::string fname = lg->Convert(outputs[0].c_str(),
- cmLocalGenerator::HOME_OUTPUT);
+ cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot());
+ std::string fname = converter.ConvertToRelativePath(
+ this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]);
// Associate the hash with this output.
this->RuleHashes[fname] = hash;
@@ -2467,7 +2698,6 @@ cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
#endif
}
-//----------------------------------------------------------------------------
void cmGlobalGenerator::CheckRuleHashes()
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -2480,122 +2710,115 @@ void cmGlobalGenerator::CheckRuleHashes()
#endif
}
-//----------------------------------------------------------------------------
void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
std::string const& home)
{
#if defined(_WIN32) || defined(__CYGWIN__)
- std::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
#else
- std::ifstream fin(pfile.c_str(), std::ios::in);
+ cmsys::ifstream fin(pfile.c_str());
#endif
- if(!fin)
- {
+ if (!fin) {
return;
- }
+ }
std::string line;
std::string fname;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
// Line format is a 32-byte hex string followed by a space
// followed by a file name (with no escaping).
// Skip blank and comment lines.
- if(line.size() < 34 || line[0] == '#')
- {
+ if (line.size() < 34 || line[0] == '#') {
continue;
- }
+ }
// Get the filename.
- fname = line.substr(33, line.npos);
+ fname = line.substr(33);
// Look for a hash for this file's rule.
- std::map<cmStdString, RuleHash>::const_iterator rhi =
+ std::map<std::string, RuleHash>::const_iterator rhi =
this->RuleHashes.find(fname);
- if(rhi != this->RuleHashes.end())
- {
+ 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)
- {
+ 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.c_str(), home.c_str());
- cmSystemTools::RemoveFile(fname.c_str());
- }
+ fname = cmSystemTools::CollapseFullPath(fname, home.c_str());
+ cmSystemTools::RemoveFile(fname);
}
- else
- {
+ } else {
// We have no hash for a rule previously listed. This may be a
// case where a user has turned off a build option and might
// want to turn it back on later, so do not delete the file.
// 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.c_str(), home.c_str());
- if(cmSystemTools::FileExists(fpath.c_str()))
- {
+ std::string fpath = cmSystemTools::CollapseFullPath(fname, home.c_str());
+ if (cmSystemTools::FileExists(fpath.c_str())) {
RuleHash hash;
strncpy(hash.Data, line.c_str(), 32);
this->RuleHashes[fname] = hash;
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
{
// Now generate a new persistence file with the current hashes.
- if(this->RuleHashes.empty())
- {
- cmSystemTools::RemoveFile(pfile.c_str());
- }
- else
- {
+ if (this->RuleHashes.empty()) {
+ cmSystemTools::RemoveFile(pfile);
+ } else {
cmGeneratedFileStream fout(pfile.c_str());
fout << "# Hashes of file build rules.\n";
- for(std::map<cmStdString, RuleHash>::const_iterator
- rhi = this->RuleHashes.begin(); rhi != this->RuleHashes.end(); ++rhi)
- {
+ 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";
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalGenerator::WriteSummary()
{
- cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
-
// Record all target directories in a central location.
- std::string fname = mf->GetHomeOutputDirectory();
+ std::string fname = this->CMakeInstance->GetHomeOutputDirectory();
fname += cmake::GetCMakeFilesDirectory();
fname += "/TargetDirectories.txt";
cmGeneratedFileStream fout(fname.c_str());
- // Generate summary information files for each target.
- std::string dir;
- for(std::map<cmStdString,cmTarget *>::const_iterator ti =
- this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
- {
- this->WriteSummary(ti->second);
- fout << ti->second->GetSupportDirectory() << "\n";
+ 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) {
+ continue;
+ }
+ this->WriteSummary(*it);
+ fout << (*it)->GetSupportDirectory() << "\n";
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::WriteSummary(cmTarget* target)
+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 json_file = dir + "/Labels.json";
+#ifdef CMAKE_BUILD_WITH_CMAKE
// Check whether labels are enabled for this target.
- if(const char* value = target->GetProperty("LABELS"))
- {
+ if (const char* value = target->GetProperty("LABELS")) {
+ 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());
@@ -2603,45 +2826,60 @@ void cmGlobalGenerator::WriteSummary(cmTarget* target)
// these labels.
std::vector<std::string> labels;
cmSystemTools::ExpandListArgument(value, labels);
- if(!labels.empty())
- {
+ if (!labels.empty()) {
fout << "# Target labels\n";
- for(std::vector<std::string>::const_iterator li = labels.begin();
- li != labels.end(); ++li)
- {
+ for (std::vector<std::string>::const_iterator li = labels.begin();
+ li != labels.end(); ++li) {
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*> const& sources = target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); ++si)
- {
+ 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) {
+ Json::Value& lj_source = lj_sources.append(Json::objectValue);
cmSourceFile* sf = *si;
- fout << sf->GetFullPath() << "\n";
- if(const char* svalue = sf->GetProperty("LABELS"))
- {
+ std::string const& sfp = sf->GetFullPath();
+ 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)
- {
+ for (std::vector<std::string>::const_iterator li = labels.begin();
+ li != labels.end(); ++li) {
fout << " " << *li << "\n";
- }
+ lj_source_labels.append(*li);
}
}
}
- else
- {
- cmSystemTools::RemoveFile(file.c_str());
- }
+ cmGeneratedFileStream json_fout(json_file.c_str());
+ json_fout << lj_root;
+ } else
+#endif
+ {
+ cmSystemTools::RemoveFile(file);
+ cmSystemTools::RemoveFile(json_file);
+ }
}
-//----------------------------------------------------------------------------
// static
-std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
+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] == '\\') {
@@ -2652,43 +2890,72 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
return result;
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
- cmMakefile *makefile,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent)
+void cmGlobalGenerator::SetFilenameTargetDepends(
+ cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts)
+{
+ this->FilenameTargetDepends[sf] = tgts;
+}
+
+std::set<cmGeneratorTarget const*> const&
+cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const
{
- this->EvaluationFiles.push_back(
- new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr,
- makefile, condition,
- inputIsContent));
+ 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::set<std::string> generatedFiles;
- for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
- li = this->EvaluationFiles.begin();
- li != this->EvaluationFiles.end();
- ++li)
- {
- (*li)->Generate();
- if (cmSystemTools::GetFatalErrorOccured())
- {
- return;
- }
- std::vector<std::string> files = (*li)->GetFiles();
- for(std::vector<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi)
- {
- if (!generatedFiles.insert(*fi).second)
- {
- cmSystemTools::Error("File to be generated by multiple different "
- "commands: ", fi->c_str());
- return;
- }
- }
- }
+ std::vector<std::string> generatedFiles;
+ unsigned int i;
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ this->LocalGenerators[i]->ProcessEvaluationFiles(generatedFiles);
+ }
+}
+
+std::string cmGlobalGenerator::ExpandCFGIntDir(
+ const std::string& str, const std::string& /*config*/) const
+{
+ return str;
+}
+
+bool cmGlobalGenerator::GenerateCPackPropertiesFile()
+{
+ cmake::InstalledFilesMap const& installedFiles =
+ this->CMakeInstance->GetInstalledFiles();
+
+ cmLocalGenerator* lg = this->LocalGenerators[0];
+ cmMakefile* mf = lg->GetMakefile();
+
+ std::vector<std::string> configs;
+ std::string config = mf->GetConfigurations(configs, false);
+
+ std::string path = this->CMakeInstance->GetHomeOutputDirectory();
+ path += "/CPackProperties.cmake";
+
+ if (!cmSystemTools::FileExists(path.c_str()) && installedFiles.empty()) {
+ return true;
+ }
+
+ cmGeneratedFileStream file(path.c_str());
+ file << "# CPack properties\n";
+
+ for (cmake::InstalledFilesMap::const_iterator i = installedFiles.begin();
+ i != installedFiles.end(); ++i) {
+ cmInstalledFile const& installedFile = i->second;
+
+ cmCPackPropertiesGenerator cpackPropertiesGenerator(lg, installedFile,
+ configs);
+
+ cpackPropertiesGenerator.Generate(file, config, configs);
+ }
+
+ return true;
}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 80916ae59..871178be1 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -1,39 +1,43 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalGenerator_h
#define cmGlobalGenerator_h
-#include "cmStandardIncludes.h"
-
-#include "cmTarget.h" // For cmTargets
-#include "cmTargetDepend.h" // For cmTargetDependSet
-#include "cmSystemTools.h" // for cmSystemTools::OutputOption
-#include "cmExportSetMap.h" // For cmExportSetMap
-#include "cmGeneratorTarget.h"
-#include "cmGeneratorExpression.h"
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmCustomCommandLines.h"
+#include "cmExportSetMap.h"
+#include "cmStateSnapshot.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"
+#endif
-class cmake;
+class cmExportBuildFileGenerator;
+class cmExternalMakefileProjectGenerator;
class cmGeneratorTarget;
-class cmGeneratorExpressionEvaluationFile;
-class cmMakefile;
+class cmLinkLineComputer;
class cmLocalGenerator;
-class cmExternalMakefileProjectGenerator;
-class cmTarget;
-class cmInstallTargetGenerator;
-class cmInstallFilesGenerator;
+class cmMakefile;
+class cmOutputConverter;
+class cmSourceFile;
+class cmStateDirectory;
+class cmake;
/** \class cmGlobalGenerator
- * \brief Responable for overseeing the generation process for the entire tree
+ * \brief Responsible for overseeing the generation process for the entire tree
*
* Subclasses of this class generate makefiles for various
* platforms.
@@ -42,18 +46,36 @@ class cmGlobalGenerator
{
public:
///! Free any memory allocated with the GlobalGenerator
- cmGlobalGenerator();
+ cmGlobalGenerator(cmake* cm);
virtual ~cmGlobalGenerator();
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
///! Get the name for this generator
- virtual const char *GetName() const { return "Generic"; };
+ virtual std::string GetName() const { return "Generic"; }
+
+ /** Check whether the given name matches the current generator. */
+ virtual bool MatchesGeneratorName(const std::string& name) const
+ {
+ return this->GetName() == name;
+ }
+
+ /** Get encoding used by generator for makefile files */
+ virtual codecvt::Encoding GetMakefileEncoding() const
+ {
+ return codecvt::None;
+ }
+
+ /** Tell the generator about the target system. */
+ virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }
+
+ /** Set the generator-specific platform name. Returns true if platform
+ is supported and false otherwise. */
+ virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
/** Set the generator-specific toolset name. Returns true if toolset
is supported and false otherwise. */
- virtual bool SetGeneratorToolset(std::string const& ts);
+ virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
/**
* Create LocalGenerators and process the CMakeLists files. This does not
@@ -61,6 +83,20 @@ public:
*/
virtual void Configure();
+ bool Compute();
+ virtual void AddExtraIDETargets() {}
+
+ enum TargetTypes
+ {
+ AllTargets,
+ ImportedOnly
+ };
+
+ void CreateImportedGenerationObjects(
+ cmMakefile* mf, std::vector<std::string> const& targets,
+ std::vector<cmGeneratorTarget const*>& exports);
+ void CreateGenerationObjects(TargetTypes targetTypes = AllTargets);
+
/**
* Generate the all required files for building this project/tree. This
* basically creates a series of LocalGenerators for each directory and
@@ -68,41 +104,47 @@ public:
*/
virtual void Generate();
+ virtual cmLinkLineComputer* CreateLinkLineComputer(
+ cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir) const;
+
+ cmLinkLineComputer* CreateMSVC60LinkLineComputer(
+ cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir) const;
+
/**
* Set/Get and Clear the enabled languages.
*/
- void SetLanguageEnabled(const char*, cmMakefile* mf);
- bool GetLanguageEnabled(const char*) const;
+ void SetLanguageEnabled(const std::string&, cmMakefile* mf);
+ bool GetLanguageEnabled(const std::string&) const;
void ClearEnabledLanguages();
- void GetEnabledLanguages(std::vector<std::string>& lang);
+ void GetEnabledLanguages(std::vector<std::string>& lang) const;
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
/**
* Resolve the CMAKE_<lang>_COMPILER setting for the given language.
* Intended to be called from EnableLanguage.
*/
- void ResolveLanguageCompiler(const std::string &lang, cmMakefile *mf,
- bool optional);
+ void ResolveLanguageCompiler(const std::string& lang, cmMakefile* mf,
+ bool optional) const;
/**
- * Try to determine system infomation, get it from another generator
+ * Try to determine system information, get it from another generator
*/
- virtual void EnableLanguagesFromGenerator(cmGlobalGenerator *gen,
- cmMakefile* mf);
+ void EnableLanguagesFromGenerator(cmGlobalGenerator* gen, cmMakefile* mf);
/**
* Try running cmake and building a file. This is used for dynamically
* loaded commands, not as part of the usual build process.
*/
- virtual int TryCompile(const char *srcdir, const char *bindir,
- const char *projectName, const char *targetName,
- bool fast, std::string *output, cmMakefile* mf);
-
+ 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);
/**
* Build a file given the following information. This is a more direct call
@@ -110,59 +152,68 @@ public:
* empty then all is assumed. clean indicates if a "make clean" should be
* done first.
*/
- int Build(const char *srcdir, const char *bindir,
- const char *projectName, const char *targetName,
- std::string *output,
- const char *makeProgram, const char *config,
- bool clean, bool fast,
- double timeout,
- cmSystemTools::OutputOption outputflag=cmSystemTools::OUTPUT_NONE,
- const char* extraOptions = 0,
+ 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 std::string GenerateBuildCommand(
- const char* makeProgram,
- const char *projectName, const char *projectDir,
- const char* additionalOptions,
- const char *targetName, const char* config,
- bool ignoreErrors, bool fast);
+ 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,
+ std::vector<std::string> const& makeOptions = std::vector<std::string>());
- ///! Set the CMake instance
- void SetCMakeInstance(cmake *cm);
+ /** 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
- cmake *GetCMakeInstance() { return this->CMakeInstance; }
- const cmake *GetCMakeInstance() const { return this->CMakeInstance; }
+ cmake* GetCMakeInstance() const { return this->CMakeInstance; }
void SetConfiguredFilesPath(cmGlobalGenerator* gen);
- const std::vector<cmLocalGenerator *>& GetLocalGenerators() const {
- return this->LocalGenerators;}
+ const std::vector<cmMakefile*>& GetMakefiles() const
+ {
+ return this->Makefiles;
+ }
+ const std::vector<cmLocalGenerator*>& GetLocalGenerators() const
+ {
+ return this->LocalGenerators;
+ }
- cmLocalGenerator* GetCurrentLocalGenerator()
- {return this->CurrentLocalGenerator;}
+ cmMakefile* GetCurrentMakefile() const { return this->CurrentMakefile; }
- void SetCurrentLocalGenerator(cmLocalGenerator* lg)
- {this->CurrentLocalGenerator = lg;}
+ void SetCurrentMakefile(cmMakefile* mf) { this->CurrentMakefile = mf; }
- void AddLocalGenerator(cmLocalGenerator *lg);
+ void AddMakefile(cmMakefile* mf);
///! Set an generator for an "external makefile based project"
void SetExternalMakefileProjectGenerator(
- cmExternalMakefileProjectGenerator *extraGenerator);
+ cmExternalMakefileProjectGenerator* extraGenerator);
- const char* GetExtraGeneratorName() const;
+ std::string GetExtraGeneratorName() const;
void AddInstallComponent(const char* component);
- const std::set<cmStdString>* GetInstallComponents() const
- { return &this->InstallComponents; }
+ const std::set<std::string>* GetInstallComponents() const
+ {
+ return &this->InstallComponents;
+ }
+
+ cmExportSetMap& GetExportSets() { return this->ExportSets; }
- cmExportSetMap& GetExportSets() {return this->ExportSets;}
+ const char* GetGlobalSetting(std::string const& name) const;
+ bool GlobalSettingIsOn(std::string const& name) const;
+ const char* GetSafeGlobalSetting(std::string const& name) const;
/** Add a file to the manifest of generated targets for a configuration. */
- void AddToManifest(const char* config, std::string const& f);
+ void AddToManifest(std::string const& f);
void EnableInstallTarget();
@@ -172,17 +223,21 @@ public:
bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
///! return the language for the given extension
- const char* GetLanguageFromExtension(const char* ext);
+ std::string GetLanguageFromExtension(const char* ext) const;
///! is an extension to be ignored
- bool IgnoreFile(const char* ext);
- ///! What is the preference for linkers and this language (None or Prefered)
- int GetLinkerPreference(const char* lang);
+ bool IgnoreFile(const char* ext) const;
+ ///! 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?
- const char* GetLanguageOutputExtension(cmSourceFile const&);
+ std::string GetLanguageOutputExtension(cmSourceFile const&) const;
///! What is the configurations directory variable called?
virtual const char* GetCMakeCFGIntDir() const { return "."; }
+ ///! expand CFGIntDir for a configuration
+ virtual std::string ExpandCFGIntDir(const std::string& str,
+ const std::string& config) const;
+
/** Get whether the generator should use a script for link commands. */
bool GetUseLinkScript() const { return this->UseLinkScript; }
@@ -193,71 +248,73 @@ public:
/*
* Determine what program to use for building the project.
*/
- void FindMakeProgram(cmMakefile*);
+ virtual bool FindMakeProgram(cmMakefile*);
///! Find a target by name by searching the local generators.
- cmTarget* FindTarget(const char* project, const char* name,
- bool excludeAliases = false);
+ cmTarget* FindTarget(const std::string& name,
+ bool excludeAliases = false) const;
+
+ cmGeneratorTarget* FindGeneratorTarget(const std::string& name) const;
- void AddAlias(const char *name, cmTarget *tgt);
- bool IsAlias(const char *name);
+ void AddAlias(const std::string& name, const std::string& tgtName);
+ bool IsAlias(const std::string& name) const;
/** Determine if a name resolves to a framework on disk or a built target
that is a framework. */
- bool NameResolvesToFramework(const std::string& libname);
+ bool NameResolvesToFramework(const std::string& libname) const;
- /** If check to see if the target is linked to by any other
- target in the project */
- bool IsDependedOn(const char* project, cmTarget* target);
+ cmMakefile* FindMakefile(const std::string& start_dir) const;
///! Find a local generator by its startdirectory
- cmLocalGenerator* FindLocalGenerator(const char* start_dir);
+ cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const;
/** Append the subdirectory for the given configuration. If anything is
appended the given prefix and suffix will be appended around it, which
is useful for leading or trailing slashes. */
- virtual void AppendDirectoryForConfig(const char* prefix,
- const char* config,
- const char* suffix,
+ virtual void AppendDirectoryForConfig(const std::string& prefix,
+ const std::string& config,
+ const std::string& suffix,
std::string& dir);
- /** Get the manifest of all targets that will be built for each
- configuration. This is valid during generation only. */
- cmTargetManifest const& GetTargetManifest() const
- { return this->TargetManifest; }
-
- /** Get the content of a directory. Directory listings are loaded
- from disk at most once and cached. During the generation step
- the content will include the target files to be built even if
+ /** Get the content of a directory. Directory listings are cached
+ and re-loaded from disk only when modified. During the generation
+ step the content will include the target files to be built even if
they do not yet exist. */
- std::set<cmStdString> const& GetDirectoryContent(std::string const& dir,
+ std::set<std::string> const& GetDirectoryContent(std::string const& dir,
bool needDisk = true);
- void AddTarget(cmTarget* t);
+ void IndexTarget(cmTarget* t);
+ void IndexGeneratorTarget(cmGeneratorTarget* 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* 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* GetAllTargetName() const { return "ALL_BUILD"; }
- virtual const char* GetInstallTargetName() const { return "INSTALL"; }
- virtual const char* GetInstallLocalTargetName() const { return 0; }
- virtual const char* GetInstallStripTargetName() const { return 0; }
- virtual const char* GetPreinstallTargetName() const { return 0; }
- virtual const char* GetTestTargetName() const { return "RUN_TESTS"; }
- virtual const char* GetPackageTargetName() const { return "PACKAGE"; }
- virtual const char* GetPackageSourceTargetName() const { return 0; }
- virtual const char* GetEditCacheTargetName() const { return 0; }
- virtual const char* GetRebuildCacheTargetName() const { return 0; }
- virtual const char* GetCleanTargetName() const { return 0; }
+ // 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;
// what targets does the specified target depend on directly
// via a target_link_libraries or add_dependencies
- TargetDependSet const& GetTargetDirectDepends(cmTarget & target);
+ TargetDependSet const& GetTargetDirectDepends(
+ const cmGeneratorTarget* target);
- /** Get per-target generator information. */
- cmGeneratorTarget* GetGeneratorTarget(cmTarget*) const;
-
- const std::map<cmStdString, std::vector<cmLocalGenerator*> >& GetProjectMap()
- const {return this->ProjectMap;}
+ const std::map<std::string, std::vector<cmLocalGenerator*> >& GetProjectMap()
+ const
+ {
+ return this->ProjectMap;
+ }
// track files replaced during a Generate
void FileReplacedDuringGenerate(const std::string& filename);
@@ -267,122 +324,212 @@ public:
std::string const& content);
/** Return whether the given binary directory is unused. */
- bool BinaryDirectoryIsNew(const char* dir)
- {
+ bool BinaryDirectoryIsNew(const std::string& dir)
+ {
return this->BinaryDirectories.insert(dir).second;
- }
- /** Supported systems creates a GUID for the given name */
- virtual void CreateGUID(const char*) {}
+ }
/** 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() { return false; }
+ virtual bool IsMultiConfig() 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. */
+ virtual bool HasKnownObjectFileLocation(std::string*) const { return true; }
+
+ virtual bool UseFolderProperty() const;
+
+ virtual bool IsIPOSupported() const { return false; }
- std::string GetSharedLibFlagsForLanguage(std::string const& lang);
+ /** 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; }
+
+ /** Return whether the "Resources" folder prefix should be stripped from
+ MacFolder. */
+ virtual bool ShouldStripResourcePath(cmMakefile*) const;
+
+ std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
/** Generate an <output>.rule file path for a given command output. */
virtual std::string GenerateRuleFile(std::string const& output) const;
static std::string EscapeJSON(const std::string& s);
- void AddEvaluationFile(const std::string &inputFile,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName,
- cmMakefile *makefile,
- cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent);
-
void ProcessEvaluationFiles();
+ std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
+ {
+ return this->BuildExportSets;
+ }
+ void AddBuildExportSet(cmExportBuildFileGenerator*);
+ void AddBuildExportExportSet(cmExportBuildFileGenerator*);
+ bool IsExportedTargetsFile(const std::string& filename) const;
+ bool GenerateImportFile(const std::string& file);
+ cmExportBuildFileGenerator* GetExportedTargetsFile(
+ const std::string& filename) const;
+ void AddCMP0042WarnTarget(const std::string& target);
+ void AddCMP0068WarnTarget(const std::string& target);
+
+ virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
+
+ 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)
+ cmFileLockPool& GetFileLockPool() { return FileLockPool; }
+#endif
+
+ bool GetConfigureDoneCMP0026() const
+ {
+ return this->ConfigureDoneCMP0026AndCMP0024;
+ }
+
+ std::string MakeSilentFlag;
+
protected:
typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend
// information, and also collect all the targets
- virtual void GetTargetSets(TargetDependSet& projectTargets,
- TargetDependSet& originalTargets,
- cmLocalGenerator* root, GeneratorVector const&);
- virtual bool IsRootOnlyTarget(cmTarget* target);
- void AddTargetDepends(cmTarget* target, TargetDependSet& projectTargets);
- void SetLanguageEnabledFlag(const char* l, cmMakefile* mf);
- void SetLanguageEnabledMaps(const char* l, cmMakefile* mf);
- void FillExtensionToLanguageMap(const char* l, cmMakefile* mf);
+ void GetTargetSets(TargetDependSet& projectTargets,
+ TargetDependSet& originalTargets, cmLocalGenerator* root,
+ GeneratorVector const&);
+ bool IsRootOnlyTarget(cmGeneratorTarget* target) const;
+ void AddTargetDepends(const cmGeneratorTarget* target,
+ TargetDependSet& projectTargets);
+ void SetLanguageEnabledFlag(const std::string& l, cmMakefile* mf);
+ void SetLanguageEnabledMaps(const std::string& l, cmMakefile* mf);
+ void FillExtensionToLanguageMap(const std::string& l, cmMakefile* mf);
+ virtual bool CheckLanguages(std::vector<std::string> const& languages,
+ cmMakefile* mf) const;
+ virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
+ const char* envVar) const;
virtual bool ComputeTargetDepends();
- virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS();
+ virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
- bool CheckTargets();
- void CreateAutomocTargets();
+ std::vector<const cmGeneratorTarget*> CreateQtAutoGeneratorsTargets();
+ std::string SelectMakeProgram(const std::string& makeProgram,
+ const std::string& makeDefault = "") const;
// Fill the ProjectMap, this must be called after LocalGenerators
// has been populated.
void FillProjectMap();
- void CheckLocalGenerators();
- bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen);
- bool IsExcluded(cmLocalGenerator* root, cmTarget& target);
- void FillLocalGeneratorToTargetMap();
- void CreateDefaultGlobalTargets(cmTargets* targets);
- cmTarget CreateGlobalTarget(const char* name, const char* message,
- const cmCustomCommandLines* commandLines,
- std::vector<std::string> depends, const char* workingDir);
+ void CheckTargetProperties();
+ bool IsExcluded(cmStateSnapshot const& root,
+ cmStateSnapshot const& snp) const;
+ bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
+ bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
+ virtual void InitializeProgressMarks() {}
+
+ struct GlobalTargetInfo
+ {
+ std::string Name;
+ std::string Message;
+ cmCustomCommandLines CommandLines;
+ std::vector<std::string> Depends;
+ std::string WorkingDir;
+ bool UsesTerminal;
+ GlobalTargetInfo()
+ : UsesTerminal(false)
+ {
+ }
+ };
- bool NeedSymbolicMark;
- bool UseLinkScript;
- bool ForceUnixPaths;
- bool ToolSupportsColor;
- cmStdString FindMakeProgramFile;
- cmStdString ConfiguredFilesPath;
- cmake *CMakeInstance;
- std::vector<cmLocalGenerator *> LocalGenerators;
- cmLocalGenerator* CurrentLocalGenerator;
+ void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
+
+ void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
+ void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
+ void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
+ void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets);
+ void AddGlobalTarget_RebuildCache(std::vector<GlobalTargetInfo>& targets);
+ void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
+ cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
+
+ std::string FindMakeProgramFile;
+ std::string ConfiguredFilesPath;
+ cmake* CMakeInstance;
+ std::vector<cmMakefile*> Makefiles;
+ std::vector<cmLocalGenerator*> LocalGenerators;
+ cmMakefile* CurrentMakefile;
// map from project name to vector of local generators in that project
- std::map<cmStdString, std::vector<cmLocalGenerator*> > ProjectMap;
- std::map<cmLocalGenerator*, std::set<cmTarget *> > LocalGeneratorToTargetMap;
+ std::map<std::string, std::vector<cmLocalGenerator*> > ProjectMap;
// Set of named installation components requested by the project.
- std::set<cmStdString> InstallComponents;
- bool InstallTargetEnabled;
+ std::set<std::string> InstallComponents;
// Sets of named target exports
cmExportSetMap ExportSets;
+ std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
+ std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
+
+ std::map<std::string, std::string> AliasTargets;
- // Manifest of all targets that will be built for each configuration.
- // This is computed just before local generators generate.
- cmTargetManifest TargetManifest;
+ cmTarget* FindTargetImpl(std::string const& name) const;
- // All targets in the entire project.
- std::map<cmStdString,cmTarget *> TotalTargets;
- std::map<cmStdString,cmTarget *> AliasTargets;
- std::map<cmStdString,cmTarget *> ImportedTargets;
- std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
+ cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
+ cmGeneratorTarget* FindImportedGeneratorTargetImpl(
+ std::string const& name) const;
- virtual const char* GetPredefinedTargetsFolder();
- virtual bool UseFolderProperty();
- void EnableMinGWLanguage(cmMakefile *mf);
+ 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;
+ // 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.
+ TargetMap TargetSearchIndex;
+ GeneratorTargetMap GeneratorTargetSearchIndex;
+
+ // Map efficiently from source directory path to cmMakefile instance.
+ // Do not use this structure for looping over all directories.
+ // It may not contain all of them (see note in IndexMakefile method).
+ MakefileMap MakefileSearchIndex;
+
cmMakefile* TryCompileOuterMakefile;
- float FirstTimeProgress;
// If you add a new map here, make sure it is copied
// in EnableLanguagesFromGenerator
- std::map<cmStdString, bool> IgnoreExtensions;
- std::map<cmStdString, bool> LanguageEnabled;
- std::set<cmStdString> LanguagesReady; // Ready for try_compile
- std::map<cmStdString, cmStdString> OutputExtensions;
- std::map<cmStdString, cmStdString> LanguageToOutputExtension;
- std::map<cmStdString, cmStdString> ExtensionToLanguage;
- std::map<cmStdString, int> LanguageToLinkerPreference;
- std::map<cmStdString, cmStdString> LanguageToOriginalSharedLibFlags;
+ std::map<std::string, bool> IgnoreExtensions;
+ std::set<std::string> LanguagesReady; // Ready for try_compile
+ std::set<std::string> LanguagesInProgress;
+ std::map<std::string, std::string> OutputExtensions;
+ std::map<std::string, std::string> LanguageToOutputExtension;
+ std::map<std::string, std::string> ExtensionToLanguage;
+ std::map<std::string, int> LanguageToLinkerPreference;
+ std::map<std::string, std::string> LanguageToOriginalSharedLibFlags;
// Record hashes for rules and outputs.
- struct RuleHash { char Data[32]; };
- std::map<cmStdString, RuleHash> RuleHashes;
+ struct RuleHash
+ {
+ char Data[32];
+ };
+ std::map<std::string, RuleHash> RuleHashes;
void CheckRuleHashes();
void CheckRuleHashes(std::string const& pfile, std::string const& home);
void WriteRuleHashes(std::string const& pfile);
void WriteSummary();
- void WriteSummary(cmTarget* target);
- void FinalizeTargetCompileDefinitions();
+ void WriteSummary(cmGeneratorTarget* target);
+ void FinalizeTargetCompileInfo();
+
+ virtual void ForceLinkerLanguages();
+
+ void CreateLocalGenerators();
+
+ void CheckCompilerIdCompatibility(cmMakefile* mf,
+ std::string const& lang) const;
+
+ void ComputeBuildFileGenerators();
cmExternalMakefileProjectGenerator* ExtraGenerator;
@@ -390,28 +537,58 @@ private:
std::vector<std::string> FilesReplacedDuringGenerate;
// Store computed inter-target dependencies.
- typedef std::map<cmTarget *, TargetDependSet> TargetDependMap;
+ typedef std::map<cmGeneratorTarget const*, TargetDependSet> TargetDependMap;
TargetDependMap TargetDependencies;
- // Per-target generator information.
- cmGeneratorTargetsType GeneratorTargets;
- void CreateGeneratorTargets();
- void ClearGeneratorTargets();
- virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+ friend class cmake;
+ void CreateGeneratorTargets(
+ TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
+ std::map<cmTarget*, cmGeneratorTarget*> const& importedMap);
+ void CreateGeneratorTargets(TargetTypes targetTypes);
+
+ void ClearGeneratorMembers();
+
+ void IndexMakefile(cmMakefile* mf);
+
+ virtual const char* GetBuildIgnoreErrorsFlag() const { return CM_NULLPTR; }
// Cache directory content and target files to be built.
- struct DirectoryContent: public std::set<cmStdString>
+ struct DirectoryContent
{
- typedef std::set<cmStdString> derived;
- bool LoadedFromDisk;
- DirectoryContent(): LoadedFromDisk(false) {}
- DirectoryContent(DirectoryContent const& dc):
- derived(dc), LoadedFromDisk(dc.LoadedFromDisk) {}
+ long LastDiskTime;
+ std::set<std::string> All;
+ std::set<std::string> Generated;
+ DirectoryContent()
+ : LastDiskTime(-1)
+ {
+ }
};
- std::map<cmStdString, DirectoryContent> DirectoryContentMap;
+ std::map<std::string, DirectoryContent> DirectoryContentMap;
// Set of binary directories on disk.
- std::set<cmStdString> BinaryDirectories;
+ std::set<std::string> BinaryDirectories;
+
+ // track targets to issue CMP0042 warning for.
+ std::set<std::string> CMP0042WarnTargets;
+ // track targets to issue CMP0068 warning for.
+ std::set<std::string> CMP0068WarnTargets;
+
+ mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*> >
+ FilenameTargetDepends;
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ // Pool of file locks
+ cmFileLockPool FileLockPool;
+#endif
+
+protected:
+ float FirstTimeProgress;
+ bool NeedSymbolicMark;
+ bool UseLinkScript;
+ bool ForceUnixPaths;
+ bool ToolSupportsColor;
+ bool InstallTargetEnabled;
+ bool ConfigureDoneCMP0026AndCMP0024;
};
#endif
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
index fd1d65fb5..d5a6db06e 100644
--- a/Source/cmGlobalGeneratorFactory.h
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -1,21 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalGeneratorFactory_h
#define cmGlobalGeneratorFactory_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
class cmGlobalGenerator;
+class cmake;
struct cmDocumentationEntry;
/** \class cmGlobalGeneratorFactory
@@ -29,31 +23,53 @@ public:
virtual ~cmGlobalGeneratorFactory() {}
/** Create a GlobalGenerator */
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* n) const = 0;
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& n,
+ cmake* cm) const = 0;
/** Get the documentation entry for this factory */
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;
+
+ /** 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;
};
-template<class T>
+template <class T>
class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory
{
public:
/** Create a GlobalGenerator */
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if (strcmp(name, T::GetActualName())) return 0;
- return new T; }
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE
+ {
+ if (name != T::GetActualName()) {
+ return CM_NULLPTR;
+ }
+ return new T(cm);
+ }
/** Get the documentation entry for this factory */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- T::GetDocumentation(entry); }
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ {
+ T::GetDocumentation(entry);
+ }
/** Get the names of the current registered generators */
- virtual void GetGenerators(std::vector<std::string>& names) const {
- names.push_back(T::GetActualName()); }
+ void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ {
+ names.push_back(T::GetActualName());
+ }
+
+ /** Determine whether or not this generator supports toolsets */
+ bool SupportsToolset() const CM_OVERRIDE { return T::SupportsToolset(); }
+
+ /** Determine whether or not this generator supports platforms */
+ bool SupportsPlatform() const CM_OVERRIDE { return T::SupportsPlatform(); }
};
#endif
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
new file mode 100644
index 000000000..42ab4d98a
--- /dev/null
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -0,0 +1,490 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalGhsMultiGenerator.h"
+
+#include "cmsys/SystemTools.hxx"
+
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGhsMultiTargetGenerator.h"
+#include "cmLocalGhsMultiGenerator.h"
+#include "cmMakefile.h"
+#include "cmVersion.h"
+
+const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
+const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
+
+cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm)
+ : cmGlobalGenerator(cm)
+ , OSDirRelative(false)
+{
+ this->GhsBuildCommandInitialized = false;
+}
+
+cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
+{
+ cmDeleteAll(TargetFolderBuildStreams);
+}
+
+cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator(
+ cmMakefile* mf)
+{
+ return new cmLocalGhsMultiGenerator(this, mf);
+}
+
+void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
+{
+ entry.Name = GetActualName();
+ entry.Brief =
+ "Generates Green Hills MULTI files (experimental, work-in-progress).";
+}
+
+void cmGlobalGhsMultiGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
+{
+ 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);
+}
+
+bool cmGlobalGhsMultiGenerator::FindMakeProgram(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());
+ }
+ return true;
+}
+
+std::string const& cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
+{
+ if (!this->GhsBuildCommandInitialized) {
+ this->GhsBuildCommandInitialized = true;
+ this->GhsBuildCommand = this->FindGhsBuildCommand();
+ }
+ return this->GhsBuildCommand;
+}
+
+std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
+{
+ 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;
+ }
+ return makeProgram;
+}
+
+std::string cmGlobalGhsMultiGenerator::GetCompRoot()
+{
+ 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;
+ }
+ }
+
+ return output;
+}
+
+std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths()
+{
+ 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;
+ }
+ return output;
+}
+
+std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
+{
+ 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;
+}
+
+void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
+ std::string const& filepath, cmGeneratedFileStream** filestream)
+{
+ // Get a stream where to generate things.
+ if (NULL == *filestream) {
+ *filestream = new cmGeneratedFileStream(filepath.c_str());
+ if (NULL != *filestream) {
+ OpenBuildFileStream(*filestream);
+ }
+ }
+}
+
+void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
+ cmGeneratedFileStream* filestream)
+{
+ *filestream << "#!gbuild" << std::endl;
+}
+
+void cmGlobalGhsMultiGenerator::OpenBuildFileStream()
+{
+ // 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;
+ }
+
+ char const* 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");
+ }
+ 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;
+ }
+ this->WriteCompilerOptions(fOSDir);
+}
+
+void cmGlobalGhsMultiGenerator::CloseBuildFileStream(
+ cmGeneratedFileStream** filestream)
+{
+ if (filestream) {
+ delete *filestream;
+ *filestream = NULL;
+ } else {
+ cmSystemTools::Error("Build file stream was not open.");
+ }
+}
+
+void cmGlobalGhsMultiGenerator::Generate()
+{
+ 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);
+ }
+ }
+
+ cmDeleteAll(TargetFolderBuildStreams);
+ this->TargetFolderBuildStreams.clear();
+}
+
+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)
+{
+ 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");
+ } else {
+ makeCommand.push_back(targetName);
+ }
+ }
+}
+
+void cmGlobalGhsMultiGenerator::WriteMacros()
+{
+ 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;
+ }
+ }
+}
+
+void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
+{
+ *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");
+ }
+}
+
+void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir)
+{
+ *this->GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\""
+ << std::endl;
+}
+
+void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os)
+{
+ (*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;
+}
+
+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::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 += "/";
+ }
+ 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);
+ }
+ AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo,
+ splitPathI, splitPath.end(), projType);
+ pathUpTo += "/";
+ }
+}
+
+void cmGlobalGhsMultiGenerator::Open(
+ std::string const& mapKeyName, std::string const& fileName,
+ std::map<std::string, cmGeneratedFileStream*>* fileMap)
+{
+ if (fileMap->end() == fileMap->find(fileName)) {
+ cmGeneratedFileStream* temp(new cmGeneratedFileStream);
+ temp->open(fileName.c_str());
+ (*fileMap)[mapKeyName] = temp;
+ }
+}
+
+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)
+{
+ // 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());
+ }
+
+ // 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);
+ }
+}
+
+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::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 cmGlobalGhsMultiGenerator::GetFileNameFromPath(
+ std::string const& path)
+{
+ std::string output(path);
+ if (!path.empty()) {
+ cmSystemTools::ConvertToUnixSlashes(output);
+ std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output);
+ output += "/" + splitPath.back() + FILE_EXTENSION;
+ }
+ return output;
+}
+
+void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
+ std::vector<cmGeneratorTarget*> tgts)
+{
+ 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]);
+ }
+ }
+}
+
+bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmGeneratorTarget* tgt)
+{
+ 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;
+ }
+ return !tgtSources.empty() && tgtInBuild;
+}
+
+std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str)
+{
+ std::string result;
+ result.reserve(str.size());
+ for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
+ if (*ch != '"') {
+ result += *ch;
+ }
+ }
+ return result;
+}
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
new file mode 100644
index 000000000..7b3eebbdf
--- /dev/null
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -0,0 +1,133 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGhsMultiGenerator_h
+#define cmGhsMultiGenerator_h
+
+#include "cmGlobalGenerator.h"
+
+#include "cmGhsMultiGpj.h"
+#include "cmGlobalGeneratorFactory.h"
+
+class cmGeneratedFileStream;
+
+class cmGlobalGhsMultiGenerator : public cmGlobalGenerator
+{
+public:
+ /// The default name of GHS MULTI's build file. Typically: monolith.gpj.
+ static const char* FILE_EXTENSION;
+
+ cmGlobalGhsMultiGenerator(cmake* cm);
+ ~cmGlobalGhsMultiGenerator();
+
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>();
+ }
+
+ ///! create the correct local generator
+ virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+
+ /// @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(); }
+
+ /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
+ static void GetDocumentation(cmDocumentationEntry& entry);
+
+ /**
+ * Utilized by the generator factory to determine if this generator
+ * supports toolsets.
+ */
+ static bool SupportsToolset() { return false; }
+
+ /**
+ * Utilized by the generator factory to determine if this generator
+ * supports platforms.
+ */
+ static bool SupportsPlatform() { return false; }
+
+ /**
+ * 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);
+ /*
+ * Determine what program to use for building the project.
+ */
+ bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+
+ cmGeneratedFileStream* GetBuildFileStream()
+ {
+ return this->TargetFolderBuildStreams[""];
+ }
+
+ 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; }
+
+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>());
+
+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;
+};
+
+#endif
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 4af06076f..18c45e0d8 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -1,69 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalJOMMakefileGenerator.h"
+
+#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmState.h"
-cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator()
+cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator(cmake* cm)
+ : cmGlobalUnixMakefileGenerator3(cm)
{
this->FindMakeProgramFile = "CMakeJOMFindMake.cmake";
this->ForceUnixPaths = false;
this->ToolSupportsColor = true;
this->UseLinkScript = false;
+ cm->GetState()->SetWindowsShell(true);
+ cm->GetState()->SetNMake(true);
+ this->DefineWindowsNULL = true;
+ this->PassMakeflags = true;
+ this->UnixCD = false;
+ this->MakeSilentFlag = "/nologo";
}
-void cmGlobalJOMMakefileGenerator
-::EnableLanguage(std::vector<std::string>const& l,
- cmMakefile *mf,
- bool optional)
+void cmGlobalJOMMakefileGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
// pick a default
mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
- if(!(cmSystemTools::GetEnv("INCLUDE") &&
- cmSystemTools::GetEnv("LIB"))
- )
- {
- std::string message = "To use the JOM generator, cmake must be run "
- "from a shell that can use the compiler cl from the command line. "
- "This environment does not contain INCLUDE, LIB, or LIBPATH, and "
- "these must be set for the cl compiler to work. ";
- mf->IssueMessage(cmake::WARNING,
- message);
- }
-
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalJOMMakefileGenerator::CreateLocalGenerator()
+void cmGlobalJOMMakefileGenerator::GetDocumentation(
+ cmDocumentationEntry& entry)
{
- cmLocalUnixMakefileGenerator3* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetDefineWindowsNULL(true);
- lg->SetWindowsShell(true);
- lg->SetMakeSilentFlag("/nologo");
- lg->SetGlobalGenerator(this);
- lg->SetIgnoreLibPrefix(true);
- lg->SetPassMakeflags(true);
- lg->SetNMake(true);
- lg->SetUnixCD(false);
- return lg;
+ entry.Name = cmGlobalJOMMakefileGenerator::GetActualName();
+ entry.Brief = "Generates JOM makefiles.";
}
-//----------------------------------------------------------------------------
-void cmGlobalJOMMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(
+ std::ostream& os, std::string const& lang, const char* envVar) const
{
- entry.Name = cmGlobalJOMMakefileGenerator::GetActualName();
- entry.Brief = "Generates JOM makefiles.";
- entry.Full = "";
+ if (lang == "CXX" || lang == "C") {
+ /* clang-format off */
+ os <<
+ "To use the JOM generator with Visual C++, cmake must be run from a "
+ "shell that can use the compiler cl from the command line. This "
+ "environment is unable to invoke the cl compiler. To fix this problem, "
+ "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
+ /* clang-format on */
+ }
+ this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 28893bf27..2e8ee2939 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalJOMMakefileGenerator_h
#define cmGlobalJOMMakefileGenerator_h
@@ -22,29 +13,33 @@
class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
- cmGlobalJOMMakefileGenerator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalJOMMakefileGenerator>(); }
+ cmGlobalJOMMakefileGenerator(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalJOMMakefileGenerator::GetActualName();}
+ virtual std::string GetName() const
+ {
+ return cmGlobalJOMMakefileGenerator::GetActualName();
+ }
// use NMake Makefiles in the name so that scripts/tests that depend on the
// name NMake Makefiles will work
- static const char* GetActualName() {return "NMake Makefiles JOM";}
+ static std::string GetActualName() { return "NMake Makefiles JOM"; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
+
+private:
+ void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
+ const char* envVar) const;
};
#endif
diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx
index a81c26c0f..e72c6e384 100644
--- a/Source/cmGlobalKdevelopGenerator.cxx
+++ b/Source/cmGlobalKdevelopGenerator.cxx
@@ -1,619 +1,606 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 "cmGlobalUnixMakefileGenerator3.h"
-#include "cmLocalUnixMakefileGenerator3.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmake.h"
#include "cmSourceFile.h"
-#include "cmGeneratedFileStream.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmXMLWriter.h"
+#include "cmake.h"
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Directory.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include <map>
+#include <set>
+#include <string.h>
+#include <utility>
-//----------------------------------------------------------------------------
-void cmGlobalKdevelopGenerator
-::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+cmGlobalKdevelopGenerator::cmGlobalKdevelopGenerator()
+ : cmExternalMakefileProjectGenerator()
{
- entry.Name = this->GetName();
- entry.Brief = "Generates KDevelop 3 project files.";
- entry.Full =
- "Project files for KDevelop 3 will be created in the top directory "
- "and in every subdirectory which features a CMakeLists.txt file "
- "containing a PROJECT() call. "
- "If you change the settings using KDevelop cmake will try its best "
- "to keep your changes when regenerating the project files. "
- "Additionally a hierarchy of UNIX makefiles is generated into the "
- "build tree. Any "
- "standard UNIX-style make program can build the project through the "
- "default make target. A \"make install\" target is also provided.";
}
-cmGlobalKdevelopGenerator::cmGlobalKdevelopGenerator()
-:cmExternalMakefileProjectGenerator()
+cmExternalMakefileProjectGeneratorFactory*
+cmGlobalKdevelopGenerator::GetFactory()
{
- this->SupportedGlobalGenerators.push_back("Unix Makefiles");
+ static cmExternalMakefileProjectGeneratorSimpleFactory<
+ cmGlobalKdevelopGenerator>
+ factory("KDevelop3", "Generates KDevelop 3 project files.");
+
+ if (factory.GetSupportedGlobalGenerators().empty()) {
+ factory.AddSupportedGlobalGenerator("Unix Makefiles");
#ifdef CMAKE_USE_NINJA
- this->SupportedGlobalGenerators.push_back("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<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it!= this->GlobalGenerator->GetProjectMap().end();
- ++it)
- {
- cmMakefile* mf = it->second[0]->GetMakefile();
- std::string outputDir=mf->GetStartOutputDirectory();
- std::string projectDir=mf->GetHomeDirectory();
- std::string projectName=mf->GetProjectName();
+ 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;
+ const std::vector<cmLocalGenerator*>& lgs = it->second;
// create the project.kdevelop.filelist file
- if(!this->CreateFilelistFile(lgs, outputDir, projectDir,
- projectName, cmakeFilePattern, fileToOpen))
- {
+ 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
+ }
+ // 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++)
- {
- cmMakefile* makefile=(*lg)->GetMakefile();
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- if (ti->second.GetType()==cmTarget::EXECUTABLE)
- {
- executable = ti->second.GetProperty("LOCATION");
+ 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())
- {
+ }
+ if (!executable.empty()) {
break;
- }
}
+ }
// now create a project file
- this->CreateProjectFile(outputDir, projectDir, projectName,
- executable, cmakeFilePattern, fileToOpen);
- }
+ 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)
+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::string filename = outputDir + "/" + projectname + ".kdevelop.filelist";
- std::set<cmStdString> files;
+ std::set<std::string> files;
std::string tmp;
- 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;
+ 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())==0))
- {
+ 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
+ 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")==0))
- {
- cmakeFilePattern+=tmp+";";
- }
+ if ((tmp != "CMakeLists.txt") &&
+ (strstr(tmp.c_str(), ".cmake") == CM_NULLPTR)) {
+ cmakeFilePattern += tmp + ";";
}
}
+ }
- //get all sources
- cmTargets& targets=makefile->GetTargets();
- for (cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ti++)
- {
- const std::vector<cmSourceFile*>& sources=ti->second.GetSourceFiles();
- 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);
+ // 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())==0) &&
- (cmSystemTools::GetFilenameExtension(tmp)!=".moc"))
- {
+ 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 = makefile->GetHeaderExtensions().begin();
- ext != makefile->GetHeaderExtensions().end(); ++ext)
- {
- std::string hname=headerBasename;
+ 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()))
- {
+ 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;
+ }
+ 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())==0))
- {
- files.insert(tmp.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
- std::ifstream oldFilelist(filename.c_str());
- if (oldFilelist)
- {
- while (cmSystemTools::GetLineFromStream(oldFilelist, tmp))
- {
- if (tmp[0]=='/')
- {
+ }
+
+ // 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()))
- {
+ }
+ std::string completePath = projectDir + tmp;
+ if (cmSystemTools::FileExists(completePath.c_str())) {
files.insert(tmp);
- }
}
- oldFilelist.close();
}
+ oldFilelist.close();
+ }
- //now write the new filename
+ // now write the new filename
cmGeneratedFileStream fout(filename.c_str());
- if(!fout)
- {
+ if (!fout) {
return false;
- }
+ }
- fileToOpen="";
- for (std::set<cmStdString>::const_iterator it=files.begin();
- it!=files.end(); it++)
- {
+ 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->c_str(), projectDir.c_str());
+ 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;
- }
+ 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.size() && tmp[0] != '/')
- {
- fout << tmp.c_str() <<"\n";
- }
+ 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)
+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";
+ 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
- {
+ 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.c_str()))
- {
+ if (d.Load(projectDir)) {
size_t numf = d.GetNumberOfFiles();
- for (unsigned int i = 0; i < numf; i++)
- {
+ for (unsigned int i = 0; i < numf; i++) {
std::string nextFile = d.GetFile(i);
- if ((nextFile!=".") && (nextFile!=".."))
- {
+ if ((nextFile != ".") && (nextFile != "..")) {
std::string tmp = projectDir;
tmp += "/";
tmp += nextFile;
- if (cmSystemTools::FileIsDirectory(tmp.c_str()))
- {
+ if (cmSystemTools::FileIsDirectory(tmp)) {
tmp += "/CMakeCache.txt";
- if ((nextFile == "CMakeFiles")
- || (cmSystemTools::FileExists(tmp.c_str())))
- {
+ if ((nextFile == "CMakeFiles") ||
+ (cmSystemTools::FileExists(tmp.c_str()))) {
this->Blacklist.push_back(nextFile);
- }
}
}
}
}
- this->CreateNewProjectFile(outputDir, projectDir, filename,
- executable, cmakeFilePattern,
- fileToOpen, sessionFilename);
}
-
+ 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)
+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)
{
- std::ifstream oldProjectFile(filename.c_str());
- if (!oldProjectFile)
- {
- this->CreateNewProjectFile(outputDir, projectDir, filename,
- executable, cmakeFilePattern,
- fileToOpen, 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))
- {
+ while (cmSystemTools::GetLineFromStream(oldProjectFile, tmp)) {
lines.push_back(tmp);
- }
+ }
oldProjectFile.close();
cmGeneratedFileStream fout(filename.c_str());
- if(!fout)
- {
+ if (!fout) {
return;
- }
+ }
- for (std::vector<std::string>::const_iterator it=lines.begin();
- it!=lines.end(); it++)
- {
- const char* line=(*it).c_str();
+ 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>")!=0)
- || (strstr(line, "<projectmanagement>")!=0)
- || (strstr(line, "<absoluteprojectpath>")!=0)
- || (strstr(line, "<filelistdirectory>")!=0)
- || (strstr(line, "<buildtool>")!=0)
- || (strstr(line, "<builddir>")!=0))
- {
+ 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";
+ 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.c_str()
- << "</projectdirectory>\n"; //this one is important
- fout<<" <absoluteprojectpath>true</absoluteprojectpath>\n";
- //and this one
- }
+ 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.c_str()
- <<"</filelistdirectory>\n";
- }
+ 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.c_str()<<"</builddir>\n";
- }
+ 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)
+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)
- {
+ 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 enableCxx = (this->GlobalGenerator->GetLanguageEnabled("C") ||
+ this->GlobalGenerator->GetLanguageEnabled("CXX"));
bool enableFortran = this->GlobalGenerator->GetLanguageEnabled("Fortran");
std::string primaryLanguage = "C++";
- if (enableFortran && !enableCxx)
- {
- primaryLanguage="Fortran77";
- }
-
- fout<<"<?xml version = '1.0'?>\n"
- "<kdevelop>\n"
- " <general>\n"
- " <author></author>\n"
- " <email></email>\n"
- " <version>$VERSION$</version>\n"
- " <projectmanagement>KDevCustomProject</projectmanagement>\n"
- " <primarylanguage>" << primaryLanguage << "</primarylanguage>\n"
- " <ignoreparts/>\n"
- " <projectdirectory>" << projectDir.c_str() <<
- "</projectdirectory>\n"; //this one is important
- fout<<" <absoluteprojectpath>true</absoluteprojectpath>\n"; //and this one
+ 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
- fout<<" <secondaryLanguages>\n";
- if (enableFortran && enableCxx)
- {
- fout<<" <language>Fortran</language>\n";
- }
- if (enableCxx)
- {
- fout<<" <language>C</language>\n";
- }
- fout<<" </secondaryLanguages>\n";
-
- if (hasSvn)
- {
- fout << " <versioncontrol>kdevsubversion</versioncontrol>\n";
- }
- else if (hasCvs)
- {
- fout << " <versioncontrol>kdevcvsservice</versioncontrol>\n";
- }
-
- fout<<" </general>\n"
- " <kdevcustomproject>\n"
- " <filelistdirectory>" << outputDir.c_str() <<
- "</filelistdirectory>\n"
- " <run>\n"
- " <mainprogram>" << executable.c_str() << "</mainprogram>\n"
- " <directoryradio>custom</directoryradio>\n"
- " <customdirectory>"<<outputDir.c_str()<<"</customdirectory>\n"
- " <programargs></programargs>\n"
- " <terminal>false</terminal>\n"
- " <autocompile>true</autocompile>\n"
- " <envvars/>\n"
- " </run>\n"
- " <build>\n"
- " <buildtool>make</buildtool>\n"; //this one is important
- fout<<" <builddir>"<<outputDir.c_str()<<"</builddir>\n"; //and this one
- fout<<" </build>\n"
- " <make>\n"
- " <abortonerror>false</abortonerror>\n"
- " <numberofjobs>1</numberofjobs>\n"
- " <dontact>false</dontact>\n"
- " <makebin>" << this->GlobalGenerator->GetLocalGenerators()[0]->
- GetMakefile()->GetRequiredDefinition("CMAKE_BUILD_TOOL")
- << " </makebin>\n"
- " <selectedenvironment>default</selectedenvironment>\n"
- " <environments>\n"
- " <default>\n"
- " <envvar value=\"1\" name=\"VERBOSE\" />\n"
- " <envvar value=\"1\" name=\"CMAKE_NO_VERBOSE\" />\n"
- " </default>\n"
- " </environments>\n"
- " </make>\n";
-
- fout<<" <blacklist>\n";
- for(std::vector<std::string>::const_iterator dirIt=this->Blacklist.begin();
- dirIt != this->Blacklist.end();
- ++dirIt)
- {
- fout<<" <path>" << dirIt->c_str() << "</path>\n";
- }
- fout<<" </blacklist>\n";
-
- fout<<" </kdevcustomproject>\n"
- " <kdevfilecreate>\n"
- " <filetypes/>\n"
- " <useglobaltypes>\n"
- " <type ext=\"ui\" />\n"
- " <type ext=\"cpp\" />\n"
- " <type ext=\"h\" />\n"
- " </useglobaltypes>\n"
- " </kdevfilecreate>\n"
- " <kdevdoctreeview>\n"
- " <projectdoc>\n"
- " <userdocDir>html/</userdocDir>\n"
- " <apidocDir>html/</apidocDir>\n"
- " </projectdoc>\n"
- " <ignoreqt_xml/>\n"
- " <ignoredoxygen/>\n"
- " <ignorekdocs/>\n"
- " <ignoretocs/>\n"
- " <ignoredevhelp/>\n"
- " </kdevdoctreeview>\n";
-
- if (enableCxx)
- {
- fout<<" <cppsupportpart>\n"
- " <filetemplates>\n"
- " <interfacesuffix>.h</interfacesuffix>\n"
- " <implementationsuffix>.cpp</implementationsuffix>\n"
- " </filetemplates>\n"
- " </cppsupportpart>\n"
- " <kdevcppsupport>\n"
- " <codecompletion>\n"
- " <includeGlobalFunctions>true</includeGlobalFunctions>\n"
- " <includeTypes>true</includeTypes>\n"
- " <includeEnums>true</includeEnums>\n"
- " <includeTypedefs>false</includeTypedefs>\n"
- " <automaticCodeCompletion>true</automaticCodeCompletion>\n"
- " <automaticArgumentsHint>true</automaticArgumentsHint>\n"
- " <automaticHeaderCompletion>true</automaticHeaderCompletion>\n"
- " <codeCompletionDelay>250</codeCompletionDelay>\n"
- " <argumentsHintDelay>400</argumentsHintDelay>\n"
- " <headerCompletionDelay>250</headerCompletionDelay>\n"
- " </codecompletion>\n"
- " <references/>\n"
- " </kdevcppsupport>\n";
- }
-
- if (enableFortran)
- {
- fout<<" <kdevfortransupport>\n"
- " <ftnchek>\n"
- " <division>false</division>\n"
- " <extern>false</extern>\n"
- " <declare>false</declare>\n"
- " <pure>false</pure>\n"
- " <argumentsall>false</argumentsall>\n"
- " <commonall>false</commonall>\n"
- " <truncationall>false</truncationall>\n"
- " <usageall>false</usageall>\n"
- " <f77all>false</f77all>\n"
- " <portabilityall>false</portabilityall>\n"
- " <argumentsonly/>\n"
- " <commononly/>\n"
- " <truncationonly/>\n"
- " <usageonly/>\n"
- " <f77only/>\n"
- " <portabilityonly/>\n"
- " </ftnchek>\n"
- " </kdevfortransupport>\n";
- }
+ 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
- fout<<" <kdevfileview>\n"
- " <groups>\n"
- " <group pattern=\"" << cmakeFilePattern.c_str() <<
- "\" name=\"CMake\" />\n";
-
- if (enableCxx)
- {
- fout<<" <group pattern=\"*.h;*.hxx;*.hpp\" name=\"Header\" />\n"
- " <group pattern=\"*.c\" name=\"C Sources\" />\n"
- " <group pattern=\"*.cpp;*.C;*.cxx;*.cc\" name=\"C++ Sources\""
- "/>\n";
- }
-
- if (enableFortran)
- {
- fout<<" <group pattern=\"*.f;*.F;*.f77;*.F77;*.f90;*.F90;*.for;*.f95;"
- "*.F95\" name=\"Fortran Sources\" />\n";
- }
-
- fout<<" <group pattern=\"*.ui\" name=\"Qt Designer files\" />\n"
- " <hidenonprojectfiles>true</hidenonprojectfiles>\n"
- " </groups>\n"
- " <tree>\n"
- " <hidepatterns>*.o,*.lo,CVS,*~,cmake*</hidepatterns>\n"
- " <hidenonprojectfiles>true</hidenonprojectfiles>\n"
- " </tree>\n"
- " </kdevfileview>\n"
- "</kdevelop>\n";
-
- if (sessionFilename.empty())
- {
+ 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)
- {
+ if (!devses) {
return;
- }
- devses<<"<?xml version = '1.0' encoding = \'UTF-8\'?>\n"
- "<!DOCTYPE KDevPrjSession>\n"
- "<KDevPrjSession>\n"
- " <DocsAndViews NumberOfDocuments=\"1\" >\n"
- " <Doc0 NumberOfViews=\"1\" URL=\"file://" << fileToOpen.c_str() <<
- "\" >\n"
- " <View0 line=\"0\" Type=\"Source\" />\n"
- " </Doc0>\n"
- " </DocsAndViews>\n"
- "</KDevPrjSession>\n";
+ }
+ 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
index a1ad39d44..bdcf8a190 100644
--- a/Source/cmGlobalKdevelopGenerator.h
+++ b/Source/cmGlobalKdevelopGenerator.h
@@ -1,20 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2009 Kitware, Inc.
- Copyright 2004 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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
@@ -33,16 +28,10 @@ class cmGlobalKdevelopGenerator : public cmExternalMakefileProjectGenerator
public:
cmGlobalKdevelopGenerator();
- virtual const char* GetName() const
- { return cmGlobalKdevelopGenerator::GetActualName();}
- static const char* GetActualName() { return "KDevelop3";}
- static cmExternalMakefileProjectGenerator* New()
- { return new cmGlobalKdevelopGenerator; }
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry,
- const char* fullName) const;
+ static cmExternalMakefileProjectGeneratorFactory* GetFactory();
+
+ void Generate() CM_OVERRIDE;
- virtual void Generate();
private:
/*** Create the foo.kdevelop.filelist file, return false if it doesn't
succeed. If the file already exists the contents will be merged.
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index d49639bef..3f223824a 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -1,53 +1,47 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalMSYSMakefileGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmGlobalMSYSMakefileGenerator.h"
+#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmState.h"
#include "cmake.h"
-cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator()
+cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm)
+ : cmGlobalUnixMakefileGenerator3(cm)
{
this->FindMakeProgramFile = "CMakeMSYSFindMake.cmake";
this->ForceUnixPaths = true;
this->ToolSupportsColor = true;
this->UseLinkScript = false;
+ cm->GetState()->SetMSYSShell(true);
}
-std::string
-cmGlobalMSYSMakefileGenerator::FindMinGW(std::string const& makeloc)
+std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
+ std::string const& makeloc)
{
std::string fstab = makeloc;
fstab += "/../etc/fstab";
- std::ifstream fin(fstab.c_str());
+ cmsys::ifstream fin(fstab.c_str());
std::string path;
std::string mount;
std::string mingwBin;
- while(fin)
- {
+ while (fin) {
fin >> path;
fin >> mount;
- if(mount == "/mingw")
- {
+ if (mount == "/mingw") {
mingwBin = path;
mingwBin += "/bin";
- }
}
+ }
return mingwBin;
}
-void cmGlobalMSYSMakefileGenerator
-::EnableLanguage(std::vector<std::string>const& l,
- cmMakefile *mf,
- bool optional)
+void cmGlobalMSYSMakefileGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
this->FindMakeProgram(mf);
std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
@@ -59,57 +53,36 @@ void cmGlobalMSYSMakefileGenerator
locations.push_back("c:/mingw/bin");
std::string tgcc = cmSystemTools::FindProgram("gcc", locations);
std::string gcc = "gcc.exe";
- if(tgcc.size())
- {
+ if (!tgcc.empty()) {
gcc = tgcc;
- }
+ }
std::string tgxx = cmSystemTools::FindProgram("g++", locations);
std::string gxx = "g++.exe";
- if(tgxx.size())
- {
+ if (!tgxx.empty()) {
gxx = tgxx;
- }
+ }
std::string trc = cmSystemTools::FindProgram("windres", locations);
std::string rc = "windres.exe";
- if(trc.size())
- {
+ if (!trc.empty()) {
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());
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"));
- }
-}
-
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalMSYSMakefileGenerator::CreateLocalGenerator()
-{
- cmLocalUnixMakefileGenerator3* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetWindowsShell(false);
- lg->SetMSYSShell(true);
- lg->SetGlobalGenerator(this);
- lg->SetIgnoreLibPrefix(true);
- lg->SetPassMakeflags(false);
- lg->SetUnixCD(true);
- return lg;
+ 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"));
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalMSYSMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalMSYSMakefileGenerator::GetDocumentation(
+ cmDocumentationEntry& entry)
{
entry.Name = cmGlobalMSYSMakefileGenerator::GetActualName();
entry.Brief = "Generates MSYS makefiles.";
- entry.Full = "The makefiles use /bin/sh as the shell. "
- "They require msys to be installed on the machine.";
}
diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h
index 659de1186..23dbc5e31 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.h
+++ b/Source/cmGlobalMSYSMakefileGenerator.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalMSYSMakefileGenerator_h
#define cmGlobalMSYSMakefileGenerator_h
@@ -22,28 +13,28 @@
class cmGlobalMSYSMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
- cmGlobalMSYSMakefileGenerator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalMSYSMakefileGenerator>(); }
+ cmGlobalMSYSMakefileGenerator(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalMSYSMakefileGenerator::GetActualName();}
- static const char* GetActualName() {return "MSYS Makefiles";}
+ virtual std::string GetName() const
+ {
+ return cmGlobalMSYSMakefileGenerator::GetActualName();
+ }
+ static std::string GetActualName() { return "MSYS Makefiles"; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
private:
std::string FindMinGW(std::string const& makeloc);
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index 1f374d3b8..3c3a5d1dc 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -1,54 +1,56 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalMinGWMakefileGenerator.h"
+
+#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmState.h"
-cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator()
+cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm)
+ : cmGlobalUnixMakefileGenerator3(cm)
{
this->FindMakeProgramFile = "CMakeMinGWFindMake.cmake";
this->ForceUnixPaths = true;
this->ToolSupportsColor = true;
this->UseLinkScript = true;
+ cm->GetState()->SetWindowsShell(true);
+ cm->GetState()->SetMinGWMake(true);
}
-void cmGlobalMinGWMakefileGenerator
-::EnableLanguage(std::vector<std::string>const& l,
- cmMakefile *mf,
- bool optional)
+void cmGlobalMinGWMakefileGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
- this->EnableMinGWLanguage(mf);
+ this->FindMakeProgram(mf);
+ std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ std::vector<std::string> locations;
+ locations.push_back(cmSystemTools::GetProgramPath(makeProgram));
+ locations.push_back("/mingw/bin");
+ locations.push_back("c:/mingw/bin");
+ std::string tgcc = cmSystemTools::FindProgram("gcc", locations);
+ std::string gcc = "gcc.exe";
+ if (!tgcc.empty()) {
+ gcc = tgcc;
+ }
+ std::string tgxx = cmSystemTools::FindProgram("g++", locations);
+ std::string gxx = "g++.exe";
+ if (!tgxx.empty()) {
+ gxx = tgxx;
+ }
+ std::string trc = cmSystemTools::FindProgram("windres", locations);
+ std::string rc = "windres.exe";
+ 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());
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalMinGWMakefileGenerator::CreateLocalGenerator()
-{
- cmLocalUnixMakefileGenerator3* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetWindowsShell(true);
- lg->SetGlobalGenerator(this);
- lg->SetIgnoreLibPrefix(true);
- lg->SetPassMakeflags(false);
- lg->SetUnixCD(true);
- lg->SetMinGWMake(true);
- return lg;
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalMinGWMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalMinGWMakefileGenerator::GetDocumentation(
+ cmDocumentationEntry& entry)
{
entry.Name = cmGlobalMinGWMakefileGenerator::GetActualName();
entry.Brief = "Generates a make file for use with mingw32-make.";
- entry.Full = "The makefiles generated use cmd.exe as the shell. "
- "They do not require msys or a unix shell.";
}
diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h
index 7951e9886..a994c9295 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.h
+++ b/Source/cmGlobalMinGWMakefileGenerator.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalMinGWMakefileGenerator_h
#define cmGlobalMinGWMakefileGenerator_h
@@ -22,27 +13,28 @@
class cmGlobalMinGWMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
- cmGlobalMinGWMakefileGenerator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalMinGWMakefileGenerator>(); }
+ cmGlobalMinGWMakefileGenerator(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<
+ cmGlobalMinGWMakefileGenerator>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalMinGWMakefileGenerator::GetActualName();}
- static const char* GetActualName() {return "MinGW Makefiles";}
+ virtual std::string GetName() const
+ {
+ return cmGlobalMinGWMakefileGenerator::GetActualName();
+ }
+ static std::string GetActualName() { return "MinGW Makefiles"; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
};
#endif
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index 7af4ee3a8..da683fb39 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -1,69 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalNMakeMakefileGenerator.h"
+
+#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmState.h"
-cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator()
+cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
+ : cmGlobalUnixMakefileGenerator3(cm)
{
this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
this->ForceUnixPaths = false;
this->ToolSupportsColor = true;
this->UseLinkScript = false;
+ cm->GetState()->SetWindowsShell(true);
+ cm->GetState()->SetNMake(true);
+ this->DefineWindowsNULL = true;
+ this->PassMakeflags = true;
+ this->UnixCD = false;
+ this->MakeSilentFlag = "/nologo";
}
-void cmGlobalNMakeMakefileGenerator
-::EnableLanguage(std::vector<std::string>const& l,
- cmMakefile *mf,
- bool optional)
+void cmGlobalNMakeMakefileGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
// pick a default
mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
- if(!(cmSystemTools::GetEnv("INCLUDE") &&
- cmSystemTools::GetEnv("LIB"))
- )
- {
- std::string message = "To use the NMake generator, cmake must be run "
- "from a shell that can use the compiler cl from the command line. "
- "This environment does not contain INCLUDE, LIB, or LIBPATH, and "
- "these must be set for the cl compiler to work. ";
- mf->IssueMessage(cmake::WARNING,
- message);
- }
-
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalNMakeMakefileGenerator::CreateLocalGenerator()
+void cmGlobalNMakeMakefileGenerator::GetDocumentation(
+ cmDocumentationEntry& entry)
{
- cmLocalUnixMakefileGenerator3* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetDefineWindowsNULL(true);
- lg->SetWindowsShell(true);
- lg->SetMakeSilentFlag("/nologo");
- lg->SetGlobalGenerator(this);
- lg->SetIgnoreLibPrefix(true);
- lg->SetPassMakeflags(true);
- lg->SetNMake(true);
- lg->SetUnixCD(false);
- return lg;
+ entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
+ entry.Brief = "Generates NMake makefiles.";
}
-//----------------------------------------------------------------------------
-void cmGlobalNMakeMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
+ std::ostream& os, std::string const& lang, const char* envVar) const
{
- entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
- entry.Brief = "Generates NMake makefiles.";
- entry.Full = "";
+ if (lang == "CXX" || lang == "C") {
+ /* clang-format off */
+ os <<
+ "To use the NMake generator with Visual C++, cmake must be run from a "
+ "shell that can use the compiler cl from the command line. This "
+ "environment is unable to invoke the cl compiler. To fix this problem, "
+ "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
+ /* clang-format on */
+ }
+ this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 5756fbd0d..6eb21249d 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalNMakeMakefileGenerator_h
#define cmGlobalNMakeMakefileGenerator_h
@@ -22,27 +13,38 @@
class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
- cmGlobalNMakeMakefileGenerator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalNMakeMakefileGenerator>(); }
+ cmGlobalNMakeMakefileGenerator(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<
+ cmGlobalNMakeMakefileGenerator>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalNMakeMakefileGenerator::GetActualName();}
- static const char* GetActualName() {return "NMake Makefiles";}
+ virtual std::string GetName() const
+ {
+ return cmGlobalNMakeMakefileGenerator::GetActualName();
+ }
+ static std::string GetActualName() { return "NMake Makefiles"; }
+
+ /** Get encoding used by generator for makefile files */
+ codecvt::Encoding GetMakefileEncoding() const CM_OVERRIDE
+ {
+ return codecvt::ANSI;
+ }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
+
+private:
+ void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
+ const char* envVar) const;
};
#endif
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 1953546de..2eef9e492 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1,88 +1,133 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 <iterator>
+#include <sstream>
+#include <stdio.h>
+
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+#include "cmFortranParser.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
-#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
+#include "cmNinjaLinkLineComputer.h"
+#include "cmOutputConverter.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetDepend.h"
#include "cmVersion.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-#include <algorithm>
+class cmLinkLineComputer;
const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
const char* cmGlobalNinjaGenerator::INDENT = " ";
+#ifdef _WIN32
+std::string const cmGlobalNinjaGenerator::SHELL_NOOP = "cd .";
+#else
+std::string const cmGlobalNinjaGenerator::SHELL_NOOP = ":";
+#endif
void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
{
- for(int i = 0; i < count; ++i)
+ for (int i = 0; i < count; ++i) {
os << cmGlobalNinjaGenerator::INDENT;
+ }
}
void cmGlobalNinjaGenerator::WriteDivider(std::ostream& os)
{
- os
- << "# ======================================"
- << "=======================================\n";
+ os << "# ======================================"
+ "=======================================\n";
}
void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
const std::string& comment)
{
- if (comment.empty())
+ if (comment.empty()) {
return;
+ }
- std::string replace = comment;
std::string::size_type lpos = 0;
std::string::size_type rpos;
os << "\n#############################################\n";
- while((rpos = replace.find('\n', lpos)) != std::string::npos)
- {
- os << "# " << replace.substr(lpos, rpos - lpos) << "\n";
+ while ((rpos = comment.find('\n', lpos)) != std::string::npos) {
+ os << "# " << comment.substr(lpos, rpos - lpos) << "\n";
lpos = rpos + 1;
+ }
+ os << "# " << comment.substr(lpos) << "\n\n";
+}
+
+cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer(
+ cmOutputConverter* outputConverter,
+ cmStateDirectory const& /* stateDir */) const
+{
+ return new cmNinjaLinkLineComputer(
+ outputConverter,
+ this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this);
+}
+
+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;
+ } else {
+ char buf[16];
+ sprintf(buf, ".%02x", static_cast<unsigned int>(*i));
+ encoded += buf;
}
- os << "# " << replace.substr(lpos) << "\n\n";
+ }
+ return encoded;
}
static bool IsIdentChar(char c)
{
- return
- ('a' <= c && c <= 'z') ||
- ('+' <= c && c <= '9') || // +,-./ and numbers
- ('A' <= c && c <= 'Z') ||
- (c == '_') || (c == '$') || (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) {
+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;
- cmOStringStream names;
+ std::ostringstream names;
names << "ident" << VarNum++;
vars << names.str() << " = " << ident << "\n";
return "$" + names.str();
- } else {
- std::string result = ident;
- cmSystemTools::ReplaceString(result, " ", "$ ");
- cmSystemTools::ReplaceString(result, ":", "$:");
- return result;
}
+ std::string result = ident;
+ cmSystemTools::ReplaceString(result, " ", "$ ");
+ cmSystemTools::ReplaceString(result, ":", "$:");
+ return result;
}
-std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
+std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
{
std::string result = lit;
cmSystemTools::ReplaceString(result, "$", "$$");
@@ -90,170 +135,159 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
return result;
}
-std::string cmGlobalNinjaGenerator::EncodePath(const std::string &path)
+std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
{
- std::string result = path;
+ std::string result = path; // NOLINT(clang-tidy)
#ifdef _WIN32
- if(UsingMinGW)
- cmSystemTools::ReplaceString(result, "\\", "/");
+ if (this->IsGCCOnWindows())
+ std::replace(result.begin(), result.end(), '\\', '/');
else
- cmSystemTools::ReplaceString(result, "/", "\\");
+ std::replace(result.begin(), result.end(), '/', '\\');
#endif
return EncodeLiteral(result);
}
-void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
- const std::string& comment,
- const std::string& rule,
- const cmNinjaDeps& outputs,
- const cmNinjaDeps& explicitDeps,
- const cmNinjaDeps& implicitDeps,
- const cmNinjaDeps& orderOnlyDeps,
- const cmNinjaVars& variables,
- const std::string& rspfile,
- int cmdLineLimit)
+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)
{
// Make sure there is a rule.
- if(rule.empty())
- {
+ if (rule.empty()) {
cmSystemTools::Error("No rule for WriteBuildStatement! called "
"with comment: ",
comment.c_str());
return;
- }
+ }
// Make sure there is at least one output file.
- if(outputs.empty())
- {
+ if (outputs.empty()) {
cmSystemTools::Error("No output files for WriteBuildStatement! called "
"with comment: ",
comment.c_str());
return;
- }
+ }
cmGlobalNinjaGenerator::WriteComment(os, comment);
- cmOStringStream arguments;
+ std::string arguments;
// TODO: Better formatting for when there are multiple input/output files.
// Write explicit dependencies.
- for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
- i != explicitDeps.end();
- ++i)
- {
- arguments << " " << EncodeIdent(EncodePath(*i), os);
-
- //we need to track every dependency that comes in, since we are trying
- //to find dependencies that are side effects of build commands
- //
- this->CombinedBuildExplicitDependencies.insert( EncodePath(*i) );
- }
+ 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);
+ if (!implicitDeps.empty()) {
+ arguments += " |";
+ for (cmNinjaDeps::const_iterator i = implicitDeps.begin();
+ i != implicitDeps.end(); ++i) {
+ arguments += " " + EncodeIdent(EncodePath(*i), os);
}
+ }
// Write order-only dependencies.
- if(!orderOnlyDeps.empty())
- {
- arguments << " ||";
- for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
- i != orderOnlyDeps.end();
- ++i)
- arguments << " " << EncodeIdent(EncodePath(*i), os);
+ if (!orderOnlyDeps.empty()) {
+ arguments += " ||";
+ for (cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
+ i != orderOnlyDeps.end(); ++i) {
+ arguments += " " + EncodeIdent(EncodePath(*i), os);
}
+ }
- arguments << "\n";
+ arguments += "\n";
- cmOStringStream build;
+ std::string build;
// Write outputs files.
- build << "build";
- for(cmNinjaDeps::const_iterator i = outputs.begin();
- i != outputs.end(); ++i)
- {
- build << " " << EncodeIdent(EncodePath(*i), os);
- this->CombinedBuildOutputs.insert( EncodePath(*i) );
+ 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);
}
- build << ":";
+ }
+ if (!implicitOuts.empty()) {
+ build += " |";
+ for (cmNinjaDeps::const_iterator i = implicitOuts.begin();
+ i != implicitOuts.end(); ++i) {
+ build += " " + EncodeIdent(EncodePath(*i), os);
+ }
+ }
+ build += ":";
// Write the rule.
- build << " " << rule;
+ build += " " + rule;
// Write the variables bound to this build statement.
- cmOStringStream variable_assignments;
- for(cmNinjaVars::const_iterator i = variables.begin();
- i != variables.end(); ++i)
- cmGlobalNinjaGenerator::WriteVariable(variable_assignments,
- i->first, i->second, "", 1);
+ std::ostringstream variable_assignments;
+ for (cmNinjaVars::const_iterator i = variables.begin(); i != variables.end();
+ ++i) {
+ cmGlobalNinjaGenerator::WriteVariable(variable_assignments, i->first,
+ i->second, "", 1);
+ }
// check if a response file rule should be used
- std::string buildstr = build.str();
+ std::string buildstr = build;
std::string assignments = variable_assignments.str();
- const std::string args = arguments.str();
- if (cmdLineLimit > 0
- && args.size() + buildstr.size() + assignments.size()
- > (size_t) cmdLineLimit) {
- buildstr += "_RSP_FILE";
- variable_assignments.clear();
- cmGlobalNinjaGenerator::WriteVariable(variable_assignments,
- "RSP_FILE", rspfile, "", 1);
+ 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;
}
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)
+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,
- explicitDeps,
- implicitDeps,
- orderOnlyDeps,
- variables);
+ this->WriteBuild(os, comment, "phony", outputs,
+ /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps,
+ orderOnlyDeps, variables);
}
void cmGlobalNinjaGenerator::AddCustomCommandRule()
{
- this->AddRule("CUSTOM_COMMAND",
- "$COMMAND",
- "$DESC",
+ this->AddRule("CUSTOM_COMMAND", "$COMMAND", "$DESC",
"Rule for running custom commands.",
/*depfile*/ "",
+ /*deptype*/ "",
/*rspfile*/ "",
/*rspcontent*/ "",
- /*restat*/ true);
+ /*restat*/ "", // bound on each build statement as needed
+ /*generator*/ false);
}
-void
-cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
- const std::string& description,
- const std::string& comment,
- const cmNinjaDeps& outputs,
- const cmNinjaDeps& deps,
- const cmNinjaDeps& orderOnlyDeps)
+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)
{
- std::string cmd = command;
+ 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";
+ if (cmd.empty())
+ // TODO Shouldn't an empty command be handled by ninja?
+ cmd = "cmd.exe /c";
#endif
this->AddCustomCommandRule();
@@ -261,40 +295,49 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
cmNinjaVars vars;
vars["COMMAND"] = cmd;
vars["DESC"] = EncodeLiteral(description);
-
- this->WriteBuild(*this->BuildFileStream,
- comment,
- "CUSTOM_COMMAND",
- outputs,
- deps,
- cmNinjaDeps(),
- orderOnlyDeps,
- vars);
+ if (restat) {
+ vars["restat"] = "1";
+ }
+ if (uses_terminal && SupportsConsolePool()) {
+ vars["pool"] = "console";
+ }
+ if (!depfile.empty()) {
+ vars["depfile"] = depfile;
+ }
+ 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);
+ }
+ }
}
-void
-cmGlobalNinjaGenerator::AddMacOSXContentRule()
+void cmGlobalNinjaGenerator::AddMacOSXContentRule()
{
- cmLocalGenerator *lg = this->LocalGenerators[0];
- cmMakefile* mfRoot = lg->GetMakefile();
+ cmLocalGenerator* lg = this->LocalGenerators[0];
- cmOStringStream cmd;
- cmd << lg->ConvertToOutputFormat(
- mfRoot->GetRequiredDefinition("CMAKE_COMMAND"),
- cmLocalGenerator::SHELL)
+ 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."
+ this->AddRule("COPY_OSX_CONTENT", cmd.str(), "Copying OS X Content $out",
+ "Rule for copying OS X bundle content file.",
/*depfile*/ "",
- /*rspfile*/ "");
+ /*deptype*/ "",
+ /*rspfile*/ "",
+ /*rspcontent*/ "",
+ /*restat*/ "",
+ /*generator*/ false);
}
-void
-cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input,
- const std::string& output)
+void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input,
+ const std::string& output)
{
this->AddMacOSXContentRule();
@@ -304,44 +347,33 @@ cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input,
deps.push_back(input);
cmNinjaVars vars;
- this->WriteBuild(*this->BuildFileStream,
- "",
- "COPY_OSX_CONTENT",
- outputs,
- deps,
- cmNinjaDeps(),
- cmNinjaDeps(),
- cmNinjaVars());
-}
-
-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& rspfile,
- const std::string& rspcontent,
- bool restat,
- bool generator)
+ this->WriteBuild(*this->BuildFileStream, "", "COPY_OSX_CONTENT", outputs,
+ /*implicitOuts=*/cmNinjaDeps(), deps, cmNinjaDeps(),
+ cmNinjaDeps(), cmNinjaVars());
+}
+
+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)
{
// Make sure the rule has a name.
- if(name.empty())
- {
+ if (name.empty()) {
cmSystemTools::Error("No name given for WriteRuleStatement! called "
"with comment: ",
comment.c_str());
return;
- }
+ }
// Make sure a command is given.
- if(command.empty())
- {
+ if (command.empty()) {
cmSystemTools::Error("No command given for WriteRuleStatement! called "
"with comment: ",
comment.c_str());
return;
- }
+ }
cmGlobalNinjaGenerator::WriteComment(os, comment);
@@ -349,47 +381,47 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
os << "rule " << name << "\n";
// Write the depfile if any.
- if(!depfile.empty())
- {
+ 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";
+ }
// Write the command.
cmGlobalNinjaGenerator::Indent(os, 1);
os << "command = " << command << "\n";
// Write the description if any.
- if(!description.empty())
- {
+ if (!description.empty()) {
cmGlobalNinjaGenerator::Indent(os, 1);
os << "description = " << description << "\n";
- }
+ }
- if(!rspfile.empty())
- {
- if (rspcontent.empty())
- {
+ if (!rspfile.empty()) {
+ if (rspcontent.empty()) {
cmSystemTools::Error("No rspfile_content given!", comment.c_str());
return;
- }
+ }
cmGlobalNinjaGenerator::Indent(os, 1);
os << "rspfile = " << rspfile << "\n";
cmGlobalNinjaGenerator::Indent(os, 1);
os << "rspfile_content = " << rspcontent << "\n";
- }
+ }
- if(restat)
- {
+ if (!restat.empty()) {
cmGlobalNinjaGenerator::Indent(os, 1);
- os << "restat = 1\n";
- }
+ os << "restat = " << restat << "\n";
+ }
- if(generator)
- {
+ if (generator) {
cmGlobalNinjaGenerator::Indent(os, 1);
os << "generator = 1\n";
- }
+ }
os << "\n";
}
@@ -401,20 +433,18 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
int indent)
{
// Make sure we have a name.
- if(name.empty())
- {
+ if (name.empty()) {
cmSystemTools::Error("No name given for WriteVariable! called "
"with comment: ",
comment.c_str());
return;
- }
+ }
// Do not add a variable if the value is empty.
std::string val = cmSystemTools::TrimWhitespace(value);
- if(val.empty())
- {
+ if (val.empty()) {
return;
- }
+ }
cmGlobalNinjaGenerator::WriteComment(os, comment);
cmGlobalNinjaGenerator::Indent(os, indent);
@@ -435,45 +465,58 @@ void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os,
{
cmGlobalNinjaGenerator::WriteComment(os, comment);
os << "default";
- for(cmNinjaDeps::const_iterator i = targets.begin(); i != targets.end(); ++i)
+ for (cmNinjaDeps::const_iterator i = targets.begin(); i != targets.end();
+ ++i) {
os << " " << *i;
+ }
os << "\n";
}
-
-cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
- : cmGlobalGenerator()
- , BuildFileStream(0)
- , RulesFileStream(0)
- , CompileCommandsStream(0)
+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);
+#endif
// // Ninja is not ported to non-Unix OS yet.
// this->ForceUnixPaths = true;
this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
}
-
-//----------------------------------------------------------------------------
// Virtual public methods.
-cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator(cmMakefile* mf)
+{
+ return new cmLocalNinjaGenerator(this, mf);
+}
+
+codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const
{
- cmLocalGenerator* lg = new cmLocalNinjaGenerator;
- lg->SetGlobalGenerator(this);
- return lg;
+#ifdef _WIN32
+ // Ninja on Windows does not support non-ANSI characters.
+ // https://github.com/ninja-build/ninja/issues/1195
+ return codecvt::ANSI;
+#else
+ // No encoding conversion needed on other platforms.
+ return codecvt::None;
+#endif
}
-void cmGlobalNinjaGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry)
{
entry.Name = cmGlobalNinjaGenerator::GetActualName();
- entry.Brief = "Generates build.ninja files (experimental).";
- entry.Full =
- "A build.ninja file is generated into the build tree. Recent "
- "versions of the ninja program can build the project through the "
- "\"all\" target. An \"install\" target is also provided.";
+ entry.Brief = "Generates build.ninja files.";
}
// Implemented in all cmGlobaleGenerator sub-classes.
@@ -482,19 +525,44 @@ void cmGlobalNinjaGenerator
// Source/cmake.cxx
void cmGlobalNinjaGenerator::Generate()
{
+ // Check minimum Ninja version.
+ if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+ this->NinjaVersion.c_str(),
+ RequiredNinjaVersion().c_str())) {
+ 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());
+ return;
+ }
this->OpenBuildFileStream();
this->OpenRulesFileStream();
+ this->TargetDependsClosures.clear();
+
+ this->InitOutputPathPrefix();
+ this->TargetAll = this->NinjaOutputPath("all");
+ this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt");
+
+ this->PolicyCMP0058 =
+ this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus(
+ cmPolicies::CMP0058);
+ this->ComputingUnknownDependencies =
+ (this->PolicyCMP0058 == cmPolicies::OLD ||
+ this->PolicyCMP0058 == cmPolicies::WARN);
+
this->cmGlobalGenerator::Generate();
this->WriteAssumedSourceDependencies();
this->WriteTargetAliases(*this->BuildFileStream);
+ this->WriteFolderTargets(*this->BuildFileStream);
this->WriteUnknownExplicitDependencies(*this->BuildFileStream);
this->WriteBuiltinTargets(*this->BuildFileStream);
if (cmSystemTools::GetErrorOccuredFlag()) {
- this->RulesFileStream->setstate(std::ios_base::failbit);
- this->BuildFileStream->setstate(std::ios_base::failbit);
+ this->RulesFileStream->setstate(std::ios::failbit);
+ this->BuildFileStream->setstate(std::ios::failbit);
}
this->CloseCompileCommandsStream();
@@ -502,148 +570,207 @@ void cmGlobalNinjaGenerator::Generate()
this->CloseBuildFileStream();
}
-// Implemented in all cmGlobaleGenerator sub-classes.
-// Used in:
-// Source/cmMakefile.cxx:
-void cmGlobalNinjaGenerator
-::EnableLanguage(std::vector<std::string>const& langs,
- cmMakefile* makefile,
- bool optional)
+bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
{
- if (makefile->IsOn("CMAKE_COMPILER_IS_MINGW"))
- {
- UsingMinGW = true;
- this->EnableMinGWLanguage(makefile);
+ if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
+ return false;
+ }
+ if (const char* ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
+ this->NinjaCommand = ninjaCommand;
+ std::vector<std::string> command;
+ command.push_back(this->NinjaCommand);
+ command.push_back("--version");
+ std::string version;
+ std::string error;
+ if (!cmSystemTools::RunSingleCommand(command, &version, &error, CM_NULLPTR,
+ CM_NULLPTR,
+ cmSystemTools::OUTPUT_NONE)) {
+ mf->IssueMessage(cmake::FATAL_ERROR, "Running\n '" +
+ cmJoin(command, "' '") + "'\n"
+ "failed with:\n " +
+ error);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
}
- if (std::find(langs.begin(), langs.end(), "Fortran") != langs.end())
- {
- cmSystemTools::Error("The Ninja generator does not support Fortran yet.");
+ this->NinjaVersion = cmSystemTools::TrimWhitespace(version);
+ this->CheckNinjaFeatures();
+ }
+ return true;
+}
+
+void cmGlobalNinjaGenerator::CheckNinjaFeatures()
+{
+ this->NinjaSupportsConsolePool = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForConsolePool().c_str());
+ this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ this->RequiredNinjaVersionForImplicitOuts().c_str());
+ {
+ // 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);
}
- this->cmGlobalGenerator::EnableLanguage(langs, makefile, optional);
+ }
}
-bool cmGlobalNinjaGenerator::UsingMinGW = false;
+bool cmGlobalNinjaGenerator::CheckLanguages(
+ std::vector<std::string> const& languages, cmMakefile* mf) const
+{
+ if (std::find(languages.begin(), languages.end(), "Fortran") !=
+ languages.end()) {
+ return this->CheckFortran(mf);
+ }
+ return true;
+}
+
+bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
+{
+ if (this->NinjaSupportsDyndeps == 1) {
+ 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());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+}
+
+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") {
+ continue;
+ }
+ 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)) {
+ this->UsingGCCOnWindows = true;
+ }
+#endif
+}
// Implemented by:
// cmGlobalUnixMakefileGenerator3
+// cmGlobalGhsMultiGenerator
// cmGlobalVisualStudio10Generator
-// cmGlobalVisualStudio6Generator
// cmGlobalVisualStudio7Generator
// cmGlobalXCodeGenerator
// Called by:
// cmGlobalGenerator::Build()
-std::string cmGlobalNinjaGenerator
-::GenerateBuildCommand(const char* makeProgram,
- const char* projectName,
- const char* projectDir,
- const char* additionalOptions,
- const char* targetName,
- const char* config,
- bool ignoreErrors,
- bool fast)
-{
- // Project name & dir and config are not used yet.
- (void)projectName;
- (void)projectDir;
- (void)config;
- // Ninja does not have -i equivalent option yet.
- (void)ignoreErrors;
- // We do not handle fast build yet.
- (void)fast;
-
- std::string makeCommand =
- cmSystemTools::ConvertToUnixOutputPath(makeProgram);
-
- if(additionalOptions)
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
- }
- if(targetName)
- {
- if(strcmp(targetName, "clean") == 0)
- {
- makeCommand += " -t clean";
- }
- else
- {
- makeCommand += " ";
- makeCommand += targetName;
- }
- }
+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)
+{
+ makeCommand.push_back(this->SelectMakeProgram(makeProgram));
- return makeCommand;
+ if (verbose) {
+ makeCommand.push_back("-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);
+ }
+ }
}
-//----------------------------------------------------------------------------
// 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& rspfile,
- const std::string& rspcontent,
- bool restat,
- bool generator)
+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)
{
// Do not add the same rule twice.
- if (this->HasRule(name))
- {
+ if (this->HasRule(name)) {
return;
- }
+ }
this->Rules.insert(name);
- cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream,
- name,
- command,
- description,
- comment,
- depfile,
- rspfile,
- rspcontent,
- restat,
- generator);
+ cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream, name, command,
+ description, comment, depfile, deptype,
+ rspfile, rspcontent, restat, generator);
- this->RuleCmdLength[name] = (int) command.size();
+ this->RuleCmdLength[name] = (int)command.size();
}
-bool cmGlobalNinjaGenerator::HasRule(const std::string &name)
+bool cmGlobalNinjaGenerator::HasRule(const std::string& name)
{
RulesSetType::const_iterator rule = this->Rules.find(name);
return (rule != this->Rules.end());
}
-//----------------------------------------------------------------------------
// Private virtual overrides
-// TODO: Refactor to combine with cmGlobalUnixMakefileGenerator3 impl.
-void cmGlobalNinjaGenerator::ComputeTargetObjects(cmGeneratorTarget* gt) const
+std::string cmGlobalNinjaGenerator::GetEditCacheCommand() const
{
- cmTarget* target = gt->Target;
+ // Ninja by design does not run interactive tools in the terminal,
+ // so our only choice is cmake-gui.
+ return cmSystemTools::GetCMakeGUICommand();
+}
+void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
+ cmGeneratorTarget* gt) const
+{
// Compute full path to object file directory for this target.
- std::string dir_max;
- dir_max += gt->Makefile->GetCurrentOutputDirectory();
- dir_max += "/";
- dir_max += gt->LocalGenerator->GetTargetDirectory(*target);
- dir_max += "/";
- gt->ObjectDirectory = dir_max;
-
- // Compute the name of each object file.
- for(std::vector<cmSourceFile*>::iterator
- si = gt->ObjectSources.begin();
- si != gt->ObjectSources.end(); ++si)
- {
- cmSourceFile* sf = *si;
- std::string objectName = gt->LocalGenerator
- ->GetObjectFileNameWithoutTarget(*sf, dir_max);
- gt->Objects[sf] = objectName;
- }
+ std::string dir;
+ dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
+ dir += "/";
+ dir += gt->LocalGenerator->GetTargetDirectory(gt);
+ dir += "/";
+ gt->ObjectDirectory = dir;
}
-//----------------------------------------------------------------------------
// Private methods
void cmGlobalNinjaGenerator::OpenBuildFileStream()
@@ -655,16 +782,15 @@ void cmGlobalNinjaGenerator::OpenBuildFileStream()
buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;
// Get a stream where to generate things.
- if (!this->BuildFileStream)
- {
- this->BuildFileStream = new cmGeneratedFileStream(buildFilePath.c_str());
- if (!this->BuildFileStream)
- {
+ if (!this->BuildFileStream) {
+ this->BuildFileStream = new cmGeneratedFileStream(
+ buildFilePath.c_str(), false, this->GetMakefileEncoding());
+ if (!this->BuildFileStream) {
// An error message is generated by the constructor if it cannot
// open the file.
return;
- }
}
+ }
// Write the do not edit header.
this->WriteDisclaimer(*this->BuildFileStream);
@@ -672,21 +798,17 @@ void cmGlobalNinjaGenerator::OpenBuildFileStream()
// Write a comment about this file.
*this->BuildFileStream
<< "# This file contains all the build statements describing the\n"
- << "# compilation DAG.\n\n"
- ;
+ << "# compilation DAG.\n\n";
}
void cmGlobalNinjaGenerator::CloseBuildFileStream()
{
- if (this->BuildFileStream)
- {
+ if (this->BuildFileStream) {
delete this->BuildFileStream;
- this->BuildFileStream = 0;
- }
- else
- {
+ this->BuildFileStream = CM_NULLPTR;
+ } else {
cmSystemTools::Error("Build file stream was not open.");
- }
+ }
}
void cmGlobalNinjaGenerator::OpenRulesFileStream()
@@ -698,69 +820,98 @@ void cmGlobalNinjaGenerator::OpenRulesFileStream()
rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;
// Get a stream where to generate things.
- if (!this->RulesFileStream)
- {
- this->RulesFileStream = new cmGeneratedFileStream(rulesFilePath.c_str());
- if (!this->RulesFileStream)
- {
+ if (!this->RulesFileStream) {
+ this->RulesFileStream = new cmGeneratedFileStream(
+ rulesFilePath.c_str(), false, this->GetMakefileEncoding());
+ if (!this->RulesFileStream) {
// An error message is generated by the constructor if it cannot
// open the file.
return;
- }
}
+ }
// Write the do not edit header.
this->WriteDisclaimer(*this->RulesFileStream);
// Write comment about this file.
+ /* clang-format off */
*this->RulesFileStream
<< "# This file contains all the rules used to get the outputs files\n"
<< "# built from the input files.\n"
<< "# It is included in the main '" << NINJA_BUILD_FILE << "'.\n\n"
;
+ /* clang-format on */
}
void cmGlobalNinjaGenerator::CloseRulesFileStream()
{
- if (this->RulesFileStream)
- {
+ if (this->RulesFileStream) {
delete this->RulesFileStream;
- this->RulesFileStream = 0;
- }
- else
- {
+ this->RulesFileStream = CM_NULLPTR;
+ } else {
cmSystemTools::Error("Rules file stream was not open.");
- }
+ }
+}
+
+static void EnsureTrailingSlash(std::string& path)
+{
+ if (path.empty()) {
+ return;
+ }
+ std::string::value_type last = path[path.size() - 1];
+#ifdef _WIN32
+ if (last != '\\') {
+ path += '\\';
+ }
+#else
+ if (last != '/') {
+ path += '/';
+ }
+#endif
+}
+
+std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(
+ const std::string& path) const
+{
+ cmLocalNinjaGenerator* ng =
+ static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
+ std::string convPath = ng->ConvertToRelativePath(
+ this->LocalGenerators[0]->GetState()->GetBinaryDirectory(), path);
+ convPath = this->NinjaOutputPath(convPath);
+#ifdef _WIN32
+ std::replace(convPath.begin(), convPath.end(), '/', '\\');
+#endif
+ return convPath;
}
void cmGlobalNinjaGenerator::AddCXXCompileCommand(
- const std::string &commandLine,
- const std::string &sourceFile)
+ const std::string& commandLine, const std::string& sourceFile)
{
// Compute Ninja's build file path.
std::string buildFileDir =
this->GetCMakeInstance()->GetHomeOutputDirectory();
- if (!this->CompileCommandsStream)
- {
+ if (!this->CompileCommandsStream) {
std::string buildFilePath = buildFileDir + "/compile_commands.json";
+ if (this->ComputingUnknownDependencies) {
+ this->CombinedBuildOutputs.insert(
+ this->NinjaOutputPath("compile_commands.json"));
+ }
// Get a stream where to generate things.
this->CompileCommandsStream =
new cmGeneratedFileStream(buildFilePath.c_str());
*this->CompileCommandsStream << "[";
- } else {
+ } else {
*this->CompileCommandsStream << "," << std::endl;
- }
+ }
std::string sourceFileName = sourceFile;
- if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str()))
- {
+ if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) {
sourceFileName = cmSystemTools::CollapseFullPath(
- sourceFileName.c_str(),
- this->GetCMakeInstance()->GetHomeOutputDirectory());
- }
-
+ sourceFileName, this->GetCMakeInstance()->GetHomeOutputDirectory());
+ }
+ /* clang-format off */
*this->CompileCommandsStream << "\n{\n"
<< " \"directory\": \""
<< cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n"
@@ -769,30 +920,27 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
<< " \"file\": \""
<< cmGlobalGenerator::EscapeJSON(sourceFileName) << "\"\n"
<< "}";
+ /* clang-format on */
}
void cmGlobalNinjaGenerator::CloseCompileCommandsStream()
{
- if (this->CompileCommandsStream)
- {
+ if (this->CompileCommandsStream) {
*this->CompileCommandsStream << "\n]";
delete this->CompileCommandsStream;
- this->CompileCommandsStream = 0;
- }
-
+ this->CompileCommandsStream = CM_NULLPTR;
+ }
}
void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
{
- os
- << "# CMAKE generated file: DO NOT EDIT!\n"
- << "# Generated by \"" << this->GetName() << "\""
- << " Generator, CMake Version "
- << cmVersion::GetMajorVersion() << "."
- << cmVersion::GetMinorVersion() << "\n\n";
+ os << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Generated by \"" << this->GetName() << "\""
+ << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << "\n\n";
}
-void cmGlobalNinjaGenerator::AddDependencyToAll(cmTarget* target)
+void cmGlobalNinjaGenerator::AddDependencyToAll(cmGeneratorTarget* target)
{
this->AppendTargetOutputs(target, this->AllDependencies);
}
@@ -804,25 +952,29 @@ void cmGlobalNinjaGenerator::AddDependencyToAll(const std::string& input)
void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
- for (std::map<std::string, std::set<std::string> >::iterator
- i = this->AssumedSourceDependencies.begin();
+ 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));
WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
"Assume dependencies for generated source file.",
- cmNinjaDeps(1, i->first), deps);
+ /*depfile*/ "", /*uses_terminal*/ false,
+ /*restat*/ true, cmNinjaDeps(1, i->first), deps);
}
}
-void
-cmGlobalNinjaGenerator
-::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
+std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target)
{
- const char* configName =
- target->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE");
- cmLocalNinjaGenerator *ng =
- static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+ return "cmake_object_order_depends_target_" + target->GetName();
+}
+
+void cmGlobalNinjaGenerator::AppendTargetOutputs(
+ cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+ cmNinjaTargetDepends depends)
+{
+ std::string configName =
+ target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
// for frameworks, we want the real name, not smple name
// frameworks always appear versioned, and the build.ninja
@@ -831,73 +983,125 @@ cmGlobalNinjaGenerator
bool realname = target->IsFrameworkOnApple();
switch (target->GetType()) {
- case cmTarget::EXECUTABLE:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- outputs.push_back(ng->ConvertToNinjaPath(
- target->GetFullPath(configName, false, realname).c_str()));
- break;
-
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::UTILITY: {
- std::string path = ng->ConvertToNinjaPath(
- target->GetMakefile()->GetStartOutputDirectory());
- if (path.empty() || path == ".")
- outputs.push_back(target->GetName());
- else {
- path += "/";
- path += target->GetName();
- outputs.push_back(path);
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY: {
+ if (depends == DependOnTargetOrdering) {
+ outputs.push_back(OrderDependsTargetForTarget(target));
+ break;
+ }
+ }
+ // FALLTHROUGH
+ case cmStateEnums::EXECUTABLE: {
+ outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
+ configName, cmStateEnums::RuntimeBinaryArtifact, realname)));
+ break;
+ }
+ case cmStateEnums::OBJECT_LIBRARY: {
+ if (depends == DependOnTargetOrdering) {
+ outputs.push_back(OrderDependsTargetForTarget(target));
+ break;
+ }
+ }
+ // FALLTHROUGH
+ case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::UTILITY: {
+ std::string path =
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
+ std::string("/") + target->GetName();
+ outputs.push_back(this->ConvertToNinjaPath(path));
+ break;
}
- break;
- }
-
- case cmTarget::GLOBAL_TARGET:
- // Always use the target in HOME instead of an unused duplicate in a
- // subdirectory.
- outputs.push_back(target->GetName());
- break;
- default:
- return;
+ default:
+ return;
}
}
-void
-cmGlobalNinjaGenerator
-::AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs)
+void cmGlobalNinjaGenerator::AppendTargetDepends(
+ cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+ cmNinjaTargetDepends depends)
{
- if (target->GetType() == cmTarget::GLOBAL_TARGET) {
- // Global targets only depend on other utilities, which may not appear in
- // the TargetDepends set (e.g. "all").
- std::set<cmStdString> const& utils = target->GetUtilities();
- std::copy(utils.begin(), utils.end(), std::back_inserter(outputs));
+ 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) {
+ std::string d =
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
+ std::string("/") + *i;
+ outputs.push_back(this->ConvertToNinjaPath(d));
+ }
} else {
- cmTargetDependSet const& targetDeps =
- this->GetTargetDirectDepends(*target);
+ cmNinjaDeps outs;
+ cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target);
for (cmTargetDependSet::const_iterator i = targetDeps.begin();
i != targetDeps.end(); ++i) {
- this->AppendTargetOutputs(*i, outputs);
+ if ((*i)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+ this->AppendTargetOutputs(*i, outs, depends);
+ }
+ std::sort(outs.begin(), outs.end());
+ outputs.insert(outputs.end(), outs.begin(), outs.end());
+ }
+}
+
+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());
+}
+
+void cmGlobalNinjaGenerator::ComputeTargetDependsClosure(
+ cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& depends)
+{
+ 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);
}
}
}
void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
- cmTarget* target) {
+ cmGeneratorTarget* target)
+{
+ std::string buildAlias = this->NinjaOutputPath(alias);
cmNinjaDeps outputs;
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] = 0;
+ for (cmNinjaDeps::iterator i = outputs.begin(); i != outputs.end(); ++i) {
+ TargetAliases[*i] = CM_NULLPTR;
+ }
// Insert the alias into the map. If the alias was already present in the
// map and referred to another target, mark it as ambiguous.
std::pair<TargetAliasMap::iterator, bool> newAlias =
- TargetAliases.insert(std::make_pair(alias, target));
- if (newAlias.second && newAlias.first->second != target)
- newAlias.first->second = 0;
+ TargetAliases.insert(std::make_pair(buildAlias, target));
+ if (newAlias.second && newAlias.first->second != target) {
+ newAlias.first->second = CM_NULLPTR;
+ }
}
void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
@@ -908,132 +1112,216 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
for (TargetAliasMap::const_iterator i = TargetAliases.begin();
i != TargetAliases.end(); ++i) {
// Don't write ambiguous aliases.
- if (!i->second)
+ if (!i->second) {
continue;
+ }
cmNinjaDeps deps;
this->AppendTargetOutputs(i->second, deps);
- this->WritePhonyBuild(os,
- "",
- cmNinjaDeps(1, i->first),
- deps);
+ this->WritePhonyBuild(os, "", cmNinjaDeps(1, i->first), deps);
+ }
+}
+
+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());
+ }
+ }
+
+ // 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) {
+ 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 comment = "Folder: " + currentBinaryDir;
+ cmNinjaDeps output(1);
+ output.push_back(this->ConvertToNinjaPath(currentBinaryDir + "/all"));
+
+ this->WritePhonyBuild(os, comment, output, it->second);
}
}
void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
{
- //now write out the unknown explicit dependencies.
+ if (!this->ComputingUnknownDependencies) {
+ return;
+ }
+
+ // We need to collect the set of known build outputs.
+ // Start with those generated by WriteBuild calls.
+ // No other method needs this so we can take ownership
+ // of the set locally and throw it out when we are done.
+ std::set<std::string> knownDependencies;
+ knownDependencies.swap(this->CombinedBuildOutputs);
+
+ // now write out the unknown explicit dependencies.
- //union the configured files, evaluations files and the CombinedBuildOutputs,
- //and then difference with CombinedExplicitDependencies to find the explicit
- //dependencies that we have no rule for
+ // union the configured files, evaluations files and the
+ // CombinedBuildOutputs,
+ // and then difference with CombinedExplicitDependencies to find the explicit
+ // dependencies that we have no rule for
cmGlobalNinjaGenerator::WriteDivider(os);
+ /* clang-format off */
os << "# Unknown Build Time Dependencies.\n"
<< "# Tell Ninja that they may appear as side effects of build rules\n"
<< "# otherwise ordered by order-only dependencies.\n\n";
+ /* clang-format on */
- //get the list of files that cmake itself has generated as a
- //product of configuration.
- cmLocalNinjaGenerator *ng =
- static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+ // get the list of files that cmake itself has generated as a
+ // product of configuration.
- std::set<std::string> knownDependencies;
- for (std::vector<cmLocalGenerator *>::const_iterator i =
- this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i)
- {
- //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
+ for (std::vector<cmLocalGenerator*>::const_iterator i =
+ this->LocalGenerators.begin();
+ i != this->LocalGenerators.end(); ++i) {
+ // 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();
+ (*i)->GetMakefile()->GetOutputFiles();
typedef std::vector<std::string>::const_iterator vect_it;
- for(vect_it j = files.begin(); j != files.end(); ++j)
- {
- knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) );
- }
+ for (vect_it j = files.begin(); j != files.end(); ++j) {
+ knownDependencies.insert(this->ConvertToNinjaPath(*j));
}
-
- for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
- li = this->EvaluationFiles.begin();
- li != this->EvaluationFiles.end();
- ++li)
- {
- //get all the files created by generator expressions and convert them
- //to ninja paths
- std::vector<std::string> files = (*li)->GetFiles();
+ // 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 = files.begin(); j != files.end(); ++j)
- {
- knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) );
+ for (vect_it j = lf.begin(); j != lf.end(); ++j) {
+ 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) {
+ // 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));
}
}
+ }
+ knownDependencies.insert(this->CMakeCacheFile);
- for(TargetAliasMap::const_iterator i= this->TargetAliases.begin();
- i != this->TargetAliases.end();
- ++i)
- {
- knownDependencies.insert( ng->ConvertToNinjaPath(i->first.c_str()) );
- }
+ for (TargetAliasMap::const_iterator i = this->TargetAliases.begin();
+ i != this->TargetAliases.end(); ++i) {
+ knownDependencies.insert(this->ConvertToNinjaPath(i->first));
+ }
- //remove all source files we know will exist.
+ // 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( ng->ConvertToNinjaPath(i->first.c_str()) );
- }
-
- //insert outputs from all WirteBuild commands
- for(std::set<std::string>::iterator i = this->CombinedBuildOutputs.begin();
- i != this->CombinedBuildOutputs.end(); ++i)
- {
- //these paths have already be encoded when added to CombinedBuildOutputs
- knownDependencies.insert(*i);
- }
-
- //after we have combined the data into knownDependencies we have no need
- //to keep this data around
- this->CombinedBuildOutputs.clear();
-
- //now we difference with CombinedBuildExplicitDependencies to find
- //the list of items we know nothing about.
- //We have encoded all the paths in CombinedBuildExplicitDependencies
- //and knownDependencies so no matter if unix or windows paths they
- //should all match now.
+ for (map_it i = this->AssumedSourceDependencies.begin();
+ i != this->AssumedSourceDependencies.end(); ++i) {
+ knownDependencies.insert(this->ConvertToNinjaPath(i->first));
+ }
- std::vector<std::string> unkownExplicitDepends;
- this->CombinedBuildExplicitDependencies.erase("all");
+ // now we difference with CombinedCustomCommandExplicitDependencies to find
+ // the list of items we know nothing about.
+ // We have encoded all the paths in CombinedCustomCommandExplicitDependencies
+ // and knownDependencies so no matter if unix or windows paths they
+ // should all match now.
- std::set_difference(this->CombinedBuildExplicitDependencies.begin(),
- this->CombinedBuildExplicitDependencies.end(),
- knownDependencies.begin(),
- knownDependencies.end(),
- std::back_inserter(unkownExplicitDepends));
+ std::vector<std::string> unknownExplicitDepends;
+ this->CombinedCustomCommandExplicitDependencies.erase(this->TargetAll);
+ std::set_difference(this->CombinedCustomCommandExplicitDependencies.begin(),
+ this->CombinedCustomCommandExplicitDependencies.end(),
+ knownDependencies.begin(), knownDependencies.end(),
+ std::back_inserter(unknownExplicitDepends));
std::string const rootBuildDirectory =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- for (std::vector<std::string>::const_iterator
- i = unkownExplicitDepends.begin();
- i != unkownExplicitDepends.end();
- ++i)
- {
- //verify the file is in the build directory
- std::string const absDepPath = cmSystemTools::CollapseFullPath(
- i->c_str(), rootBuildDirectory.c_str());
- bool const inBuildDir = cmSystemTools::IsSubDirectory(absDepPath.c_str(),
- rootBuildDirectory.c_str());
- if(inBuildDir)
- {
- cmNinjaDeps deps(1,*i);
- this->WritePhonyBuild(os,
- "",
- deps,
- deps);
+ 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 (!warnExplicitDepends.empty()) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0058) << "\n"
+ "This project specifies custom command DEPENDS on files "
+ "in the build tree that are not specified as the OUTPUT or "
+ "BYPRODUCTS of any add_custom_command or add_custom_target:\n"
+ " " << cmJoin(warnExplicitDepends, "\n ") <<
+ "\n"
+ "For compatibility with versions of CMake that did not have "
+ "the BYPRODUCTS option, CMake is generating phony rules for "
+ "such files to convince 'ninja' to build."
+ "\n"
+ "Project authors should add the missing BYPRODUCTS or OUTPUT "
+ "options to the custom commands that produce these files."
+ ;
+ /* clang-format on */
+ this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
}
void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
@@ -1051,121 +1339,578 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
{
cmNinjaDeps outputs;
- outputs.push_back("all");
+ outputs.push_back(this->TargetAll);
- this->WritePhonyBuild(os,
- "The main all target.",
- outputs,
+ this->WritePhonyBuild(os, "The main all target.", outputs,
this->AllDependencies);
- cmGlobalNinjaGenerator::WriteDefault(os,
- outputs,
- "Make the all target the default.");
+ if (!this->HasOutputPathPrefix()) {
+ cmGlobalNinjaGenerator::WriteDefault(os, outputs,
+ "Make the all target the default.");
+ }
}
void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
- cmLocalGenerator *lg = this->LocalGenerators[0];
- cmMakefile* mfRoot = lg->GetMakefile();
+ cmLocalGenerator* lg = this->LocalGenerators[0];
- cmOStringStream cmd;
- cmd << lg->ConvertToOutputFormat(
- mfRoot->GetRequiredDefinition("CMAKE_COMMAND"),
- cmLocalGenerator::SHELL)
+ std::ostringstream cmd;
+ cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
+ cmOutputConverter::SHELL)
<< " -H"
- << lg->ConvertToOutputFormat(mfRoot->GetHomeDirectory(),
- cmLocalGenerator::SHELL)
+ << lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
+ cmOutputConverter::SHELL)
<< " -B"
- << lg->ConvertToOutputFormat(mfRoot->GetHomeOutputDirectory(),
- cmLocalGenerator::SHELL);
- WriteRule(*this->RulesFileStream,
- "RERUN_CMAKE",
- cmd.str(),
- "Re-running CMake...",
- "Rule for re-running cmake.",
- /*depfile=*/ "",
- /*rspfile=*/ "",
+ << 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=*/ false,
- /*generator=*/ true);
+ /*restat=*/"",
+ /*generator=*/true);
cmNinjaDeps implicitDeps;
- for (std::vector<cmLocalGenerator *>::const_iterator i =
- this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) {
- const std::vector<std::string>& lf = (*i)->GetMakefile()->GetListFiles();
- implicitDeps.insert(implicitDeps.end(), lf.begin(), lf.end());
+ 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));
+ }
}
+ implicitDeps.push_back(this->CMakeCacheFile);
+
std::sort(implicitDeps.begin(), implicitDeps.end());
implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
implicitDeps.end());
- implicitDeps.push_back("CMakeCache.txt");
- this->WriteBuild(os,
- "Re-run CMake if any of its inputs changed.",
+ 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";
+ }
+
+ 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, NINJA_BUILD_FILE),
- /*explicitDeps=*/ cmNinjaDeps(),
- implicitDeps,
- /*orderOnlyDeps=*/ cmNinjaDeps(),
- /*variables=*/ cmNinjaVars());
+ /*outputs=*/cmNinjaDeps(1, ninjaBuildFile),
+ /*implicitOuts=*/cmNinjaDeps(),
+ /*explicitDeps=*/cmNinjaDeps(), implicitDeps,
+ /*orderOnlyDeps=*/cmNinjaDeps(), variables);
- this->WritePhonyBuild(os,
- "A missing CMake input file is not an error.",
- implicitDeps,
- cmNinjaDeps());
+ this->WritePhonyBuild(os, "A missing CMake input file is not an error.",
+ implicitDeps, cmNinjaDeps());
}
std::string cmGlobalNinjaGenerator::ninjaCmd() const
{
cmLocalGenerator* lgen = this->LocalGenerators[0];
if (lgen) {
- return lgen->ConvertToOutputFormat(
- lgen->GetMakefile()->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"),
- cmLocalGenerator::SHELL);
+ return lgen->ConvertToOutputFormat(this->NinjaCommand,
+ cmOutputConverter::SHELL);
}
return "ninja";
}
+bool cmGlobalNinjaGenerator::SupportsConsolePool() const
+{
+ return this->NinjaSupportsConsolePool;
+}
+
+bool cmGlobalNinjaGenerator::SupportsImplicitOuts() const
+{
+ return this->NinjaSupportsImplicitOuts;
+}
+
void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
- WriteRule(*this->RulesFileStream,
- "CLEAN",
- (ninjaCmd() + " -t clean").c_str(),
+ WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean",
"Cleaning all built files...",
"Rule for cleaning all built files.",
- /*depfile=*/ "",
- /*rspfile=*/ "",
+ /*depfile=*/"",
+ /*deptype=*/"",
+ /*rspfile=*/"",
/*rspcontent*/ "",
- /*restat=*/ false,
- /*generator=*/ false);
- WriteBuild(os,
- "Clean all the built files.",
- "CLEAN",
- /*outputs=*/ cmNinjaDeps(1, "clean"),
- /*explicitDeps=*/ cmNinjaDeps(),
- /*implicitDeps=*/ cmNinjaDeps(),
- /*orderOnlyDeps=*/ cmNinjaDeps(),
- /*variables=*/ cmNinjaVars());
+ /*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());
}
void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
{
- WriteRule(*this->RulesFileStream,
- "HELP",
- (ninjaCmd() + " -t targets").c_str(),
+ WriteRule(*this->RulesFileStream, "HELP", ninjaCmd() + " -t targets",
"All primary targets available:",
"Rule for printing all primary targets available.",
- /*depfile=*/ "",
- /*rspfile=*/ "",
+ /*depfile=*/"",
+ /*deptype=*/"",
+ /*rspfile=*/"",
/*rspcontent*/ "",
- /*restat=*/ false,
- /*generator=*/ false);
- WriteBuild(os,
- "Print all primary targets available.",
- "HELP",
- /*outputs=*/ cmNinjaDeps(1, "help"),
- /*explicitDeps=*/ cmNinjaDeps(),
- /*implicitDeps=*/ cmNinjaDeps(),
- /*orderOnlyDeps=*/ cmNinjaDeps(),
- /*variables=*/ cmNinjaVars());
+ /*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());
+}
+
+void cmGlobalNinjaGenerator::InitOutputPathPrefix()
+{
+ this->OutputPathPrefix =
+ this->LocalGenerators[0]->GetMakefile()->GetSafeDefinition(
+ "CMAKE_NINJA_OUTPUT_PATH_PREFIX");
+ EnsureTrailingSlash(this->OutputPathPrefix);
+}
+
+std::string cmGlobalNinjaGenerator::NinjaOutputPath(
+ std::string const& path) const
+{
+ if (!this->HasOutputPathPrefix() || cmSystemTools::FileIsFullPath(path)) {
+ return path;
+ }
+ return this->OutputPathPrefix + path;
+}
+
+void cmGlobalNinjaGenerator::StripNinjaOutputPathPrefixAsSuffix(
+ std::string& path)
+{
+ if (path.empty()) {
+ return;
+ }
+ EnsureTrailingSlash(path);
+ cmStripSuffixIfExists(path, this->OutputPathPrefix);
+}
+
+/*
+
+We use the following approach to support Fortran. Each target already
+has a <target>.dir/ directory used to hold intermediate files for CMake.
+For each target, a FortranDependInfo.json file is generated by CMake with
+information about include directories, module directories, and the locations
+the per-target directories for target dependencies.
+
+Compilation of source files within a target is split into the following steps:
+
+1. Preprocess all sources, scan preprocessed output for module dependencies.
+ This step is done with independent build statements for each source,
+ and can therefore be done in parallel.
+
+ rule Fortran_PREPROCESS
+ depfile = $DEP_FILE
+ 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
+
+ build src.f90-pp.f90 | src.f90-pp.f90.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
+
+ The ``cmake -E cmake_ninja_depends`` tool reads the preprocessed output
+ and generates the ninja depfile for preprocessor dependencies. It also
+ generates a "ddi" file (in a format private to CMake) that lists the
+ object file that compilation will produce along with the module names
+ it provides and/or requires. The "ddi" file is an implicit output
+ because it should not appear in "$out" but is generated by the rule.
+
+2. Consolidate the per-source module dependencies saved in the "ddi"
+ files from all sources to produce a ninja "dyndep" file, ``Fortran.dd``.
+
+ rule Fortran_DYNDEP
+ command = cmake -E cmake_ninja_dyndep \
+ --tdi=FortranDependInfo.json --dd=$out $in
+
+ build Fortran.dd: Fortran_DYNDEP src1.f90-pp.f90.ddi src2.f90-pp.f90.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
+ on which the target depends. It computes dependency edges on compilations
+ that require modules to those that provide the modules. This information
+ is placed in the ``Fortran.dd`` file for ninja to load later. It also
+ writes the expected location of modules provided by this target into
+ ``FortranModules.json`` for use by dependent targets.
+
+3. Compile all sources after loading dynamically discovered dependencies
+ of the compilation build statements from their ``dyndep`` bindings.
+
+ rule Fortran_COMPILE
+ command = gfortran $INCLUDES $FLAGS -c $in -o $out
+
+ build src1.f90.o: Fortran_COMPILE src1.f90-pp.f90 || Fortran.dd
+ dyndep = Fortran.dd
+
+ The "dyndep" binding tells ninja to load dynamically discovered
+ dependency information from ``Fortran.dd``. This adds information
+ such as:
+
+ build src1.f90.o | mod1.mod: dyndep
+ restat = 1
+
+ This tells ninja that ``mod1.mod`` is an implicit output of compiling
+ the object file ``src1.f90.o``. The ``restat`` binding tells it that
+ the timestamp of the output may not always change. Additionally:
+
+ build src2.f90.o: dyndep | mod1.mod
+
+ This tells ninja that ``mod1.mod`` is a dependency of compiling the
+ object file ``src2.f90.o``. This ensures that ``src1.f90.o`` and
+ ``mod1.mod`` will always be up to date before ``src2.f90.o`` is built
+ (because the latter consumes the module).
+*/
+
+int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd)
+{
+ std::string arg_tdi;
+ std::string arg_pp;
+ 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;
+ if (cmHasLiteralPrefix(arg, "--tdi=")) {
+ arg_tdi = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--pp=")) {
+ arg_pp = arg.substr(5);
+ } else if (cmHasLiteralPrefix(arg, "--dep=")) {
+ arg_dep = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--obj=")) {
+ arg_obj = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--ddi=")) {
+ arg_ddi = arg.substr(6);
+ } else {
+ cmSystemTools::Error("-E cmake_ninja_depends unknown argument: ",
+ arg.c_str());
+ return 1;
+ }
+ }
+ if (arg_tdi.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_depends requires value for --tdi=");
+ return 1;
+ }
+ if (arg_pp.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_depends requires value for --pp=");
+ return 1;
+ }
+ if (arg_dep.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_depends requires value for --dep=");
+ return 1;
+ }
+ if (arg_obj.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_depends requires value for --obj=");
+ return 1;
+ }
+ if (arg_ddi.empty()) {
+ 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());
+ }
+ }
+ }
+
+ 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());
+ return 1;
+ }
+ if (cmFortran_yyparse(parser.Scanner) != 0) {
+ // Failed to parse the file.
+ return 1;
+ }
+
+ {
+ cmGeneratedFileStream depfile(arg_dep.c_str());
+ 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);
+ }
+ depfile << "\n";
+ }
+
+ Json::Value ddi(Json::objectValue);
+ 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);
+ }
+ Json::Value& ddi_requires = ddi["requires"] = Json::arrayValue;
+ for (std::set<std::string>::iterator i = info.Requires.begin();
+ i != info.Requires.end(); ++i) {
+ // Require modules not provided in the same source.
+ if (!info.Provides.count(*i)) {
+ ddi_requires.append(*i);
+ }
+ }
+
+ cmGeneratedFileStream ddif(arg_ddi.c_str());
+ ddif << ddi;
+ if (!ddif) {
+ cmSystemTools::Error("-E cmake_ninja_depends failed to write ",
+ arg_ddi.c_str());
+ return 1;
+ }
+ return 0;
+}
+
+struct cmFortranObjectInfo
+{
+ std::string Object;
+ std::vector<std::string> Provides;
+ std::vector<std::string> Requires;
+};
+
+bool cmGlobalNinjaGenerator::WriteDyndepFile(
+ std::string const& dir_top_src, std::string const& dir_top_bld,
+ 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)
+{
+ // Setup path conversions.
+ {
+ cmStateSnapshot snapshot = this->GetCMakeInstance()->GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentSource(dir_cur_src);
+ 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())));
+ 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) {
+ // 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);
+ 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());
+ return false;
+ }
+
+ cmFortranObjectInfo 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());
+ }
+ }
+ 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());
+ }
+ }
+ objects.push_back(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";
+ 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());
+ return false;
+ }
+ if (ltm.isObject()) {
+ for (Json::Value::iterator i = ltm.begin(); i != ltm.end(); ++i) {
+ mod_files[i.key().asString()] = i->asString();
+ }
+ }
+ }
+
+ // Extend the module map with those provided by this target.
+ // 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;
+ }
+ }
+
+ cmGeneratedFileStream ddf(arg_dd.c_str());
+ 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));
+ }
+ }
+ if (!oi->Provides.empty()) {
+ ddVars["restat"] = "1";
+ }
+
+ this->WriteBuild(ddf, ddComment, ddRule, ddOutputs, ddImplicitOuts,
+ ddExplicitDeps, ddImplicitDeps, ddOrderOnlyDeps, ddVars);
+ }
+
+ // 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());
+ tmf << tm;
+
+ return true;
+}
+
+int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd)
+{
+ std::vector<std::string> arg_full =
+ cmSystemTools::HandleResponseFile(argBeg, argEnd);
+
+ std::string arg_dd;
+ 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;
+ if (cmHasLiteralPrefix(arg, "--tdi=")) {
+ arg_tdi = arg.substr(6);
+ } 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());
+ return 1;
+ }
+ }
+ if (arg_tdi.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --tdi=");
+ return 1;
+ }
+ if (arg_dd.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --dd=");
+ return 1;
+ }
+
+ 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_dyndep failed to parse ",
+ arg_tdi.c_str(),
+ reader.getFormattedErrorMessages().c_str());
+ return 1;
+ }
+ }
+
+ std::string const dir_cur_bld = tdi["dir-cur-bld"].asString();
+ std::string const dir_cur_src = tdi["dir-cur-src"].asString();
+ 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()) {
+ 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());
+ }
+ }
+
+ cmake cm(cmake::RoleInternal);
+ cm.SetHomeDirectory(dir_top_src);
+ cm.SetHomeOutputDirectory(dir_top_bld);
+ CM_AUTO_PTR<cmGlobalNinjaGenerator> ggd(
+ static_cast<cmGlobalNinjaGenerator*>(cm.CreateGlobalGenerator("Ninja")));
+ if (!ggd.get() ||
+ !ggd->WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld,
+ arg_dd, arg_ddis, module_dir,
+ linked_target_dirs)) {
+ return 1;
+ }
+ return 0;
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index e046c7c96..b0008f74a 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -1,27 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalNinjaGenerator_h
-# define cmGlobalNinjaGenerator_h
+#define cmGlobalNinjaGenerator_h
-# include "cmGlobalGenerator.h"
-# include "cmGlobalGeneratorFactory.h"
-# include "cmNinjaTypes.h"
+#include "cmConfigure.h"
-//#define NINJA_GEN_VERBOSE_FILES
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
-class cmLocalGenerator;
+#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;
+class cmMakefile;
+class cmOutputConverter;
+class cmStateDirectory;
+class cmake;
+struct cmDocumentationEntry;
/**
* \class cmGlobalNinjaGenerator
@@ -42,7 +49,7 @@ class cmGeneratorTarget;
* - We extensively use Ninja variable overloading system to minimize the
* number of generated rules.
*/
-class cmGlobalNinjaGenerator : public cmGlobalGenerator
+class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator
{
public:
/// The default name of Ninja's build file. Typically: build.ninja.
@@ -55,15 +62,23 @@ public:
/// The indentation string used when generating Ninja's build file.
static const char* INDENT;
+ /// The shell command used for a no-op.
+ static std::string const SHELL_NOOP;
+
/// Write @a count times INDENT level to output stream @a os.
static void Indent(std::ostream& os, int count);
/// Write a divider in the given output stream @a os.
static void WriteDivider(std::ostream& os);
- static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
- static std::string EncodeLiteral(const std::string &lit);
- static std::string EncodePath(const std::string &path);
+ 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;
/**
* Write the given @a comment to the output stream @a os. It
@@ -72,27 +87,39 @@ public:
static void WriteComment(std::ostream& os, const std::string& comment);
/**
+ * Utilized by the generator factory to determine if this generator
+ * supports toolsets.
+ */
+ static bool SupportsToolset() { return false; }
+
+ /**
+ * Utilized by the generator factory to determine if this generator
+ * supports platforms.
+ */
+ static bool SupportsPlatform() { return false; }
+
+ bool IsIPOSupported() const CM_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.
* @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,
+ 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 = -1);
+ int cmdLineLimit = 0, bool* usedResponseFile = CM_NULLPTR);
/**
* Helper to write a build statement with the special 'phony' rule.
*/
- void WritePhonyBuild(std::ostream& os,
- const std::string& comment,
+ void WritePhonyBuild(std::ostream& os, const std::string& comment,
const cmNinjaDeps& outputs,
const cmNinjaDeps& explicitDeps,
const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
@@ -102,9 +129,10 @@ public:
void WriteCustomCommandBuild(const std::string& command,
const std::string& description,
const std::string& comment,
- const cmNinjaDeps& outputs,
+ const std::string& depfile, bool uses_terminal,
+ bool restat, const cmNinjaDeps& outputs,
const cmNinjaDeps& deps = cmNinjaDeps(),
- const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
+ const cmNinjaDeps& orderOnly = cmNinjaDeps());
void WriteMacOSXContentBuild(const std::string& input,
const std::string& output);
@@ -114,198 +142,238 @@ public:
* It also writes the variables bound to this rule statement.
* @warning no escaping of any kind is done here.
*/
- static void WriteRule(std::ostream& os,
- const std::string& name,
+ 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& rspfile,
+ const std::string& comment, const std::string& depfile,
+ const std::string& deptype, const std::string& rspfile,
const std::string& rspcontent,
- bool restat,
- bool generator);
+ const std::string& restat, bool generator);
/**
* Write a variable named @a name to @a os with value @a value and an
* optional @a comment. An @a indent level can be specified.
* @warning no escaping of any kind is done here.
*/
- static void WriteVariable(std::ostream& os,
- const std::string& name,
+ static void WriteVariable(std::ostream& os, const std::string& name,
const std::string& value,
- const std::string& comment = "",
- int indent = 0);
+ const std::string& comment = "", int indent = 0);
/**
* Write an include statement including @a filename with an optional
* @a comment to the @a os stream.
*/
- static void WriteInclude(std::ostream& os,
- const std::string& filename,
+ static void WriteInclude(std::ostream& os, const std::string& filename,
const std::string& comment = "");
/**
* Write a default target statement specifying @a targets as
* the default targets.
*/
- static void WriteDefault(std::ostream& os,
- const cmNinjaDeps& targets,
+ static void WriteDefault(std::ostream& os, const cmNinjaDeps& targets,
const std::string& comment = "");
-
- static bool IsMinGW() { return UsingMinGW; }
-
+ bool IsGCCOnWindows() const { return UsingGCCOnWindows; }
public:
- /// Default constructor.
- cmGlobalNinjaGenerator();
+ cmGlobalNinjaGenerator(cmake* cm);
- /// Convenience method for creating an instance of this class.
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); }
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>();
+ }
+
+ ~cmGlobalNinjaGenerator() CM_OVERRIDE {}
- /// Destructor.
- virtual ~cmGlobalNinjaGenerator() { }
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE;
- /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator()
- virtual cmLocalGenerator* CreateLocalGenerator();
+ std::string GetName() const CM_OVERRIDE
+ {
+ return cmGlobalNinjaGenerator::GetActualName();
+ }
- /// Overloaded methods. @see cmGlobalGenerator::GetName().
- virtual const char* GetName() const {
- return cmGlobalNinjaGenerator::GetActualName(); }
+ static std::string GetActualName() { return "Ninja"; }
- /// @return the name of this generator.
- static const char* GetActualName() { return "Ninja"; }
+ /** Get encoding used by generator for ninja files */
+ codecvt::Encoding GetMakefileEncoding() const CM_OVERRIDE;
- /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
static void GetDocumentation(cmDocumentationEntry& entry);
- /// Overloaded methods. @see cmGlobalGenerator::Generate()
- virtual void Generate();
-
- /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage()
- virtual void EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile* mf,
- bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile* mf, bool optional) CM_OVERRIDE;
- /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand()
- virtual std::string GenerateBuildCommand(const char* makeProgram,
- const char* projectName,
- const char* projectDir,
- const char* additionalOptions,
- const char* targetName,
- const char* config,
- bool ignoreErrors,
- bool fast);
+ 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;
// Setup target names
- virtual const char* GetAllTargetName() const { return "all"; }
- virtual const char* GetInstallTargetName() const { return "install"; }
- virtual const char* GetInstallLocalTargetName() const {
+ const char* GetAllTargetName() const CM_OVERRIDE { return "all"; }
+ const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; }
+ const char* GetInstallLocalTargetName() const CM_OVERRIDE
+ {
return "install/local";
}
- virtual const char* GetInstallStripTargetName() const {
+ const char* GetInstallStripTargetName() const CM_OVERRIDE
+ {
return "install/strip";
}
- virtual const char* GetTestTargetName() const { return "test"; }
- virtual const char* GetPackageTargetName() const { return "package"; }
- virtual const char* GetPackageSourceTargetName() const {
+ const char* GetTestTargetName() const CM_OVERRIDE { return "test"; }
+ const char* GetPackageTargetName() const CM_OVERRIDE { return "package"; }
+ const char* GetPackageSourceTargetName() const CM_OVERRIDE
+ {
return "package_source";
}
- virtual const char* GetEditCacheTargetName() const {
+ const char* GetEditCacheTargetName() const CM_OVERRIDE
+ {
return "edit_cache";
}
- virtual const char* GetRebuildCacheTargetName() const {
+ const char* GetRebuildCacheTargetName() const CM_OVERRIDE
+ {
return "rebuild_cache";
}
- virtual const char* GetCleanTargetName() const { return "clean"; }
+ const char* GetCleanTargetName() const CM_OVERRIDE { return "clean"; }
+ cmGeneratedFileStream* GetBuildFileStream() const
+ {
+ return this->BuildFileStream;
+ }
- cmGeneratedFileStream* GetBuildFileStream() const {
- return this->BuildFileStream; }
-
- cmGeneratedFileStream* GetRulesFileStream() const {
- return this->RulesFileStream; }
+ cmGeneratedFileStream* GetRulesFileStream() const
+ {
+ return this->RulesFileStream;
+ }
- void AddCXXCompileCommand(const std::string &commandLine,
- const std::string &sourceFile);
+ std::string ConvertToNinjaPath(const std::string& path) const;
+
+ struct MapToNinjaPathImpl
+ {
+ cmGlobalNinjaGenerator* GG;
+ MapToNinjaPathImpl(cmGlobalNinjaGenerator* gg)
+ : GG(gg)
+ {
+ }
+ std::string operator()(std::string const& path)
+ {
+ return this->GG->ConvertToNinjaPath(path);
+ }
+ };
+ MapToNinjaPathImpl MapToNinjaPath() { return MapToNinjaPathImpl(this); }
+
+ void AddCXXCompileCommand(const std::string& commandLine,
+ const std::string& sourceFile);
/**
* Add a rule to the generated build system.
* 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& rspfile = "",
- const std::string& rspcontent = "",
- bool restat = false,
- bool generator = false);
+ 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);
bool HasRule(const std::string& name);
void AddCustomCommandRule();
void AddMacOSXContentRule();
- bool HasCustomCommandOutput(const std::string &output) {
+ bool HasCustomCommandOutput(const std::string& output)
+ {
return this->CustomCommandOutputs.find(output) !=
- this->CustomCommandOutputs.end();
+ this->CustomCommandOutputs.end();
}
/// Called when we have seen the given custom command. Returns true
/// if we has seen it before.
- bool SeenCustomCommand(cmCustomCommand const *cc) {
+ bool SeenCustomCommand(cmCustomCommand const* cc)
+ {
return !this->CustomCommands.insert(cc).second;
}
/// Called when we have seen the given custom command output.
- void SeenCustomCommandOutput(const std::string &output) {
+ void SeenCustomCommandOutput(const std::string& output)
+ {
this->CustomCommandOutputs.insert(output);
// We don't need the assumed dependencies anymore, because we have
// an output.
this->AssumedSourceDependencies.erase(output);
}
- void AddAssumedSourceDependencies(const std::string &source,
- const cmNinjaDeps &deps) {
- std::set<std::string> &ASD = this->AssumedSourceDependencies[source];
+ void AddAssumedSourceDependencies(const std::string& source,
+ const cmNinjaDeps& deps)
+ {
+ std::set<std::string>& ASD = this->AssumedSourceDependencies[source];
// Because we may see the same source file multiple times (same source
// specified in multiple targets), compute the union of any assumed
// dependencies.
ASD.insert(deps.begin(), deps.end());
}
- void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
- void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
- void AddDependencyToAll(cmTarget* target);
+ void AppendTargetOutputs(
+ cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+ cmNinjaTargetDepends depends = DependOnTargetArtifact);
+ void AppendTargetDepends(
+ cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+ cmNinjaTargetDepends depends = DependOnTargetArtifact);
+ void AppendTargetDependsClosure(cmGeneratorTarget const* target,
+ cmNinjaDeps& outputs);
+ void AddDependencyToAll(cmGeneratorTarget* target);
void AddDependencyToAll(const std::string& input);
- const std::vector<cmLocalGenerator*>& GetLocalGenerators() const {
- return LocalGenerators; }
+ const std::vector<cmLocalGenerator*>& GetLocalGenerators() const
+ {
+ return LocalGenerators;
+ }
- bool IsExcluded(cmLocalGenerator* root, cmTarget& target) {
- return cmGlobalGenerator::IsExcluded(root, target); }
+ bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target)
+ {
+ return cmGlobalGenerator::IsExcluded(root, target);
+ }
- int GetRuleCmdLength(const std::string& name) {
- return RuleCmdLength[name]; }
+ int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
- void AddTargetAlias(const std::string& alias, cmTarget* target);
+ void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target);
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
-protected:
+ // 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"; }
+ bool SupportsConsolePool() const;
+ bool SupportsImplicitOuts() const;
- /// Overloaded methods.
- /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
- virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
+ std::string NinjaOutputPath(std::string const& path) const;
+ bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
+ void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
+ bool WriteDyndepFile(std::string const& dir_top_src,
+ std::string const& dir_top_bld,
+ 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);
-private:
+protected:
+ void Generate() CM_OVERRIDE;
- /// @see cmGlobalGenerator::ComputeTargetObjects
- virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+ bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const CM_OVERRIDE { return true; }
+
+private:
+ std::string GetEditCacheCommand() const CM_OVERRIDE;
+ bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+ void CheckNinjaFeatures();
+ bool CheckLanguages(std::vector<std::string> const& languages,
+ cmMakefile* mf) const CM_OVERRIDE;
+ bool CheckFortran(cmMakefile* mf) const;
void OpenBuildFileStream();
void CloseBuildFileStream();
@@ -321,6 +389,7 @@ private:
void WriteAssumedSourceDependencies();
void WriteTargetAliases(std::ostream& os);
+ void WriteFolderTargets(std::ostream& os);
void WriteUnknownExplicitDependencies(std::ostream& os);
void WriteBuiltinTargets(std::ostream& os);
@@ -329,10 +398,13 @@ private:
void WriteTargetClean(std::ostream& os);
void WriteTargetHelp(std::ostream& os);
- std::string ninjaCmd() const;
+ void ComputeTargetDependsClosure(
+ cmGeneratorTarget const* target,
+ std::set<cmGeneratorTarget const*>& depends);
+ std::string ninjaCmd() const;
- /// The file containing the build statement. (the relation ship of the
+ /// The file containing the build statement. (the relationship of the
/// compilation DAG).
cmGeneratedFileStream* BuildFileStream;
/// The file containing the rule statements. (The action attached to each
@@ -353,28 +425,49 @@ private:
/// The set of dependencies to add to the "all" target.
cmNinjaDeps AllDependencies;
+ bool UsingGCCOnWindows;
+
/// The set of custom commands we have seen.
std::set<cmCustomCommand const*> CustomCommands;
/// The set of custom command outputs we have seen.
std::set<std::string> CustomCommandOutputs;
- //The combined explicit dependencies of all build commands that the global
- //generator has issued. When combined with CombinedBuildOutputs it allows
- //us to detect the set of explicit dependencies that have
- std::set<std::string> CombinedBuildExplicitDependencies;
+ /// Whether we are collecting known build outputs and needed
+ /// dependencies to determine unknown dependencies.
+ bool ComputingUnknownDependencies;
+ cmPolicies::PolicyStatus PolicyCMP0058;
+
+ /// The combined explicit dependencies of custom build commands
+ std::set<std::string> CombinedCustomCommandExplicitDependencies;
+
+ /// When combined with CombinedCustomCommandExplicitDependencies it allows
+ /// us to detect the set of explicit dependencies that have
std::set<std::string> CombinedBuildOutputs;
/// The mapping from source file to assumed dependencies.
std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
- typedef std::map<std::string, cmTarget*> TargetAliasMap;
+ typedef std::map<std::string, cmGeneratorTarget*> TargetAliasMap;
TargetAliasMap TargetAliases;
- static cmLocalGenerator* LocalGenerator;
+ typedef std::map<cmGeneratorTarget const*,
+ std::set<cmGeneratorTarget const*> >
+ TargetDependsClosureMap;
+ TargetDependsClosureMap TargetDependsClosures;
- static bool UsingMinGW;
+ std::string NinjaCommand;
+ std::string NinjaVersion;
+ bool NinjaSupportsConsolePool;
+ bool NinjaSupportsImplicitOuts;
+ unsigned long NinjaSupportsDyndeps;
+
+private:
+ void InitOutputPathPrefix();
+ std::string OutputPathPrefix;
+ std::string TargetAll;
+ std::string CMakeCacheFile;
};
#endif // ! cmGlobalNinjaGenerator_h
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 88cd6e5f8..23b3718dc 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -1,25 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalUnixMakefileGenerator3.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <algorithm>
+#include <functional>
+#include <sstream>
+#include <utility>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
-#include "cmMakefileTargetGenerator.h"
#include "cmMakefile.h"
-#include "cmake.h"
-#include "cmGeneratedFileStream.h"
-#include "cmSourceFile.h"
+#include "cmMakefileTargetGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmGeneratorTarget.h"
+#include "cmTargetDepend.h"
+#include "cmake.h"
-cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
+cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm)
+ : cmGlobalCommonGenerator(cm)
{
// This type of makefile always requires unix style paths
this->ForceUnixPaths = true;
@@ -31,76 +38,89 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
#else
this->UseLinkScript = true;
#endif
- this->CommandDatabase = NULL;
+ this->CommandDatabase = CM_NULLPTR;
+
+ this->IncludeDirective = "include";
+ this->DefineWindowsNULL = false;
+ this->PassMakeflags = false;
+ this->UnixCD = true;
}
-void cmGlobalUnixMakefileGenerator3
-::EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *mf,
- bool optional)
+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::vector<std::string>::const_iterator l = languages.begin();
+ l != languages.end(); ++l) {
+ if (*l == "NONE") {
continue;
- }
- this->ResolveLanguageCompiler(*l, mf, optional);
}
+ this->ResolveLanguageCompiler(*l, mf, optional);
+ }
}
///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(
+ cmMakefile* mf)
{
- cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetGlobalGenerator(this);
- return lg;
+ return new cmLocalUnixMakefileGenerator3(this, mf);
}
-//----------------------------------------------------------------------------
-void cmGlobalUnixMakefileGenerator3
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalUnixMakefileGenerator3::GetDocumentation(
+ cmDocumentationEntry& entry)
{
entry.Name = cmGlobalUnixMakefileGenerator3::GetActualName();
entry.Brief = "Generates standard UNIX makefiles.";
- entry.Full =
- "A hierarchy of UNIX makefiles is generated into the build tree. Any "
- "standard UNIX-style make program can build the project through the "
- "default make target. A \"make install\" target is also provided.";
}
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3
-::ComputeTargetObjects(cmGeneratorTarget* gt) const
+std::string cmGlobalUnixMakefileGenerator3::GetEditCacheCommand() const
{
- cmTarget* target = gt->Target;
- cmLocalUnixMakefileGenerator3* lg =
- static_cast<cmLocalUnixMakefileGenerator3*>(gt->LocalGenerator);
+ // If generating for an extra IDE, the edit_cache target cannot
+ // launch a terminal-interactive tool, so always use cmake-gui.
+ if (!this->GetExtraGeneratorName().empty()) {
+ return cmSystemTools::GetCMakeGUICommand();
+ }
- // Compute full path to object file directory for this target.
- std::string dir_max;
- dir_max += gt->Makefile->GetCurrentOutputDirectory();
- dir_max += "/";
- dir_max += gt->LocalGenerator->GetTargetDirectory(*target);
- dir_max += "/";
- gt->ObjectDirectory = dir_max;
-
- // Compute the name of each object file.
- for(std::vector<cmSourceFile*>::iterator
- si = gt->ObjectSources.begin();
- si != gt->ObjectSources.end(); ++si)
- {
- cmSourceFile* sf = *si;
- bool hasSourceExtension = true;
- std::string objectName = gt->LocalGenerator
- ->GetObjectFileNameWithoutTarget(*sf, dir_max,
- &hasSourceExtension);
- gt->Objects[sf] = objectName;
- lg->AddLocalObjectFile(target, sf, objectName, hasSourceExtension);
+ // Use an internal cache entry to track the latest dialog used
+ // to edit the cache, and use that for the edit_cache target.
+ cmake* cm = this->GetCMakeInstance();
+ std::string editCacheCommand = cm->GetCMakeEditCommand();
+ if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
+ !editCacheCommand.empty()) {
+ if (editCacheCommand.empty()) {
+ editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
+ }
+ if (editCacheCommand.empty()) {
+ editCacheCommand = cmSystemTools::GetCMakeGUICommand();
+ }
+ if (!editCacheCommand.empty()) {
+ cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
+ "Path to cache edit program executable.",
+ cmStateEnums::INTERNAL);
}
+ }
+ const char* edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
+ return edit_cmd ? edit_cmd : "";
+}
+
+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 += "/";
+ gt->ObjectDirectory = dir;
+}
+
+void cmGlobalUnixMakefileGenerator3::Configure()
+{
+ // Initialize CMAKE_EDIT_COMMAND cache entry.
+ this->GetEditCacheCommand();
+
+ this->cmGlobalGenerator::Configure();
}
void cmGlobalUnixMakefileGenerator3::Generate()
@@ -110,11 +130,10 @@ void cmGlobalUnixMakefileGenerator3::Generate()
// initialize progress
unsigned long total = 0;
- for(ProgressMapType::const_iterator pmi = this->ProgressMap.begin();
- pmi != this->ProgressMap.end(); ++pmi)
- {
+ for (ProgressMapType::const_iterator pmi = this->ProgressMap.begin();
+ pmi != this->ProgressMap.end(); ++pmi) {
total += pmi->second.NumberOfActions;
- }
+ }
// write each target's progress.make this loop is done twice. Bascially the
// Generate pass counts all the actions, the first loop below determines
@@ -124,58 +143,56 @@ 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)
- {
+ 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)
- {
- cmLocalUnixMakefileGenerator3 *lg =
- static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
- std::string markFileName = lg->GetMakefile()->GetStartOutputDirectory();
+ }
+ 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());
markFile << this->CountProgressMarksInAll(lg) << "\n";
- }
+ }
// write the main makefile
this->WriteMainMakefile2();
this->WriteMainCMakefile();
- if (this->CommandDatabase != NULL) {
+ if (this->CommandDatabase != CM_NULLPTR) {
*this->CommandDatabase << std::endl << "]";
delete this->CommandDatabase;
- this->CommandDatabase = NULL;
+ this->CommandDatabase = CM_NULLPTR;
}
}
void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
- const std::string &sourceFile, const std::string &workingDirectory,
- const std::string &compileCommand) {
- if (this->CommandDatabase == NULL)
- {
+ const std::string& sourceFile, const std::string& workingDirectory,
+ const std::string& compileCommand)
+{
+ if (this->CommandDatabase == CM_NULLPTR) {
std::string commandDatabaseName =
- std::string(this->GetCMakeInstance()->GetHomeOutputDirectory())
- + "/compile_commands.json";
+ std::string(this->GetCMakeInstance()->GetHomeOutputDirectory()) +
+ "/compile_commands.json";
this->CommandDatabase =
new cmGeneratedFileStream(commandDatabaseName.c_str());
*this->CommandDatabase << "[" << std::endl;
- } else {
+ } else {
*this->CommandDatabase << "," << std::endl;
- }
+ }
*this->CommandDatabase << "{" << std::endl
- << " \"directory\": \""
- << cmGlobalGenerator::EscapeJSON(workingDirectory) << "\","
- << std::endl
- << " \"command\": \"" <<
- cmGlobalGenerator::EscapeJSON(compileCommand) << "\","
- << std::endl
- << " \"file\": \"" <<
- cmGlobalGenerator::EscapeJSON(sourceFile) << "\""
- << std::endl << "}";
+ << " \"directory\": \""
+ << cmGlobalGenerator::EscapeJSON(workingDirectory)
+ << "\"," << std::endl
+ << " \"command\": \""
+ << cmGlobalGenerator::EscapeJSON(compileCommand)
+ << "\"," << std::endl
+ << " \"file\": \""
+ << cmGlobalGenerator::EscapeJSON(sourceFile) << "\""
+ << std::endl
+ << "}";
}
void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
@@ -187,15 +204,15 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
this->GetCMakeInstance()->GetHomeOutputDirectory();
makefileName += cmake::GetCMakeFilesDirectory();
makefileName += "/Makefile2";
- cmGeneratedFileStream makefileStream(makefileName.c_str());
- if(!makefileStream)
- {
+ cmGeneratedFileStream makefileStream(makefileName.c_str(), false,
+ this->GetMakefileEncoding());
+ if (!makefileStream) {
return;
- }
+ }
// get a local generator for some useful methods
- cmLocalUnixMakefileGenerator3 *lg =
- static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
+ cmLocalUnixMakefileGenerator3* lg =
+ static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
// Write the do not edit header.
lg->WriteDisclaimer(makefileStream);
@@ -211,47 +228,38 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
lg->WriteMakeRule(makefileStream,
"Default target executed when no arguments are "
"given to make.",
- "default_target",
- depends,
- no_commands, true);
+ "default_target", depends, no_commands, true);
depends.clear();
// The all and preinstall rules might never have any dependencies
// added to them.
- if(this->EmptyRuleHackDepends != "")
- {
+ if (this->EmptyRuleHackDepends != "") {
depends.push_back(this->EmptyRuleHackDepends);
- }
+ }
// Write and empty all:
- lg->WriteMakeRule(makefileStream,
- "The main recursive all target", "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);
+ 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);
- }
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
+ this->WriteConvenienceRules2(makefileStream, lg);
+ }
- lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
lg->WriteSpecialTargetsBottom(makefileStream);
}
-
-//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
// Open the output file. This should not be copy-if-different
@@ -262,70 +270,58 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
cmakefileName += cmake::GetCMakeFilesDirectory();
cmakefileName += "/Makefile.cmake";
cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
- if(!cmakefileStream)
- {
+ if (!cmakefileStream) {
return;
- }
+ }
std::string makefileName =
this->GetCMakeInstance()->GetHomeOutputDirectory();
makefileName += "/Makefile";
// get a local generator for some useful methods
- cmLocalUnixMakefileGenerator3 *lg =
- static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
+ cmLocalUnixMakefileGenerator3* lg =
+ static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
// Write the do not edit header.
lg->WriteDisclaimer(cmakefileStream);
// Save the generator name
- cmakefileStream
- << "# The generator used is:\n"
- << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
+ cmakefileStream << "# The generator used is:\n"
+ << "set(CMAKE_DEPENDS_GENERATOR \"" << this->GetName()
+ << "\")\n\n";
// 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 (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
// Get the list of files contributing to this generation step.
- lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
+ lfiles.insert(lfiles.end(), lg->GetMakefile()->GetListFiles().begin(),
lg->GetMakefile()->GetListFiles().end());
- }
+ }
// 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());
+ std::unique(lfiles.begin(), lfiles.end());
lfiles.erase(new_end, lfiles.end());
#endif
// reset lg to the first makefile
- lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
-
- // Build the path to the cache file.
- std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
- cache += "/CMakeCache.txt";
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
+ std::string currentBinDir = lg->GetCurrentBinaryDirectory();
// Save the list to the cmake file.
cmakefileStream
<< "# The top level Makefile was generated from the following files:\n"
- << "SET(CMAKE_MAKEFILE_DEPENDS\n"
- << " \""
- << lg->Convert(cache.c_str(),
- cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
- for(std::vector<std::string>::const_iterator i = lfiles.begin();
- i != lfiles.end(); ++i)
- {
- cmakefileStream
- << " \""
- << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
- << "\"\n";
- }
- cmakefileStream
- << " )\n\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)
+ << "\"\n";
+ }
+ cmakefileStream << " )\n\n";
// Build the path to the cache check file.
std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
@@ -333,176 +329,155 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
check += "/cmake.check_cache";
// Set the corresponding makefile in the cmake file.
- cmakefileStream
- << "# The corresponding makefile is:\n"
- << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
- << " \""
- << lg->Convert(makefileName.c_str(),
- cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
- << " \""
- << lg->Convert(check.c_str(),
- cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
+ cmakefileStream << "# The corresponding makefile is:\n"
+ << "set(CMAKE_MAKEFILE_OUTPUTS\n"
+ << " \""
+ << lg->ConvertToRelativePath(currentBinDir, makefileName)
+ << "\"\n"
+ << " \"" << lg->ConvertToRelativePath(currentBinDir, check)
+ << "\"\n";
cmakefileStream << " )\n\n";
+ const std::string binDir = lg->GetBinaryDirectory();
+
// CMake must rerun if a byproduct is missing.
{
- 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->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
- << "\"\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->GetMakefile()->GetStartOutputDirectory();
- tmpStr += cmake::GetCMakeFilesDirectory();
- tmpStr += "/CMakeDirectoryInformation.cmake";
- cmakefileStream << " \"" <<
- lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
- << "\"\n";
- }
- cmakefileStream << " )\n\n";
+ 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)
+ << "\"\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)
+ << "\"\n";
+ }
+ cmakefileStream << " )\n\n";
}
this->WriteMainCMakefileLanguageRules(cmakefileStream,
this->LocalGenerators);
}
-void cmGlobalUnixMakefileGenerator3
-::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
- std::vector<cmLocalGenerator *> &lGenerators
- )
+void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
+ cmGeneratedFileStream& cmakefileStream,
+ std::vector<cmLocalGenerator*>& lGenerators)
{
- cmLocalUnixMakefileGenerator3 *lg;
+ cmLocalUnixMakefileGenerator3* lg;
// 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]);
+ 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 all of out targets
- for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
- l != lg->GetMakefile()->GetTargets().end(); l++)
- {
- if((l->second.GetType() == cmTarget::EXECUTABLE) ||
- (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
- (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
- (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
- (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
- (l->second.GetType() == cmTarget::UTILITY))
- {
- std::string tname = lg->GetRelativeTargetDirectory(l->second);
+ 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";
cmSystemTools::ConvertToUnixSlashes(tname);
- cmakefileStream << " \"" << tname.c_str() << "\"\n";
- }
+ cmakefileStream << " \"" << tname << "\"\n";
}
}
+ }
cmakefileStream << " )\n";
}
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3
-::WriteDirectoryRule2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg,
- const char* pass, bool check_all,
- bool check_relink)
+void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
+ std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg,
+ const char* pass, bool check_all, bool check_relink)
{
// Get the relative path to the subdirectory from the top.
- std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
+ std::string makeTarget = lg->GetCurrentBinaryDirectory();
makeTarget += "/";
makeTarget += pass;
// The directory-level rule should depend on the target-level rules
// for all targets in the directory.
std::vector<std::string> depends;
- for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
- l != lg->GetMakefile()->GetTargets().end(); ++l)
- {
- if((l->second.GetType() == cmTarget::EXECUTABLE) ||
- (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
- (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
- (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
- (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
- (l->second.GetType() == cmTarget::UTILITY))
- {
+ 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 || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
- (!check_relink ||
- l->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())))
- {
- std::string tname = lg->GetRelativeTargetDirectory(l->second);
+ 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);
- }
}
}
+ }
// The directory-level rule should depend on the directory-level
// rules of the subdirectories.
- for(std::vector<cmLocalGenerator*>::iterator sdi =
- lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
- {
- cmLocalUnixMakefileGenerator3* slg =
- static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
- std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
+ 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);
- }
+ }
// Work-around for makes that drop rules that have no dependencies
// or commands.
- if(depends.empty() && this->EmptyRuleHackDepends != "")
- {
+ if (depends.empty() && this->EmptyRuleHackDepends != "") {
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.c_str(), depends, no_commands, true);
+ lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends,
+ no_commands, true);
}
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3
-::WriteDirectoryRules2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg)
+void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
+ std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
{
// Only subdirectories need these rules.
- if(!lg->GetParent())
- {
+ if (lg->IsRootMakefile()) {
return;
- }
+ }
// Begin the directory-level rules section.
- std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
- dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
+ 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";
+ ruleFileStream << "# Directory level rules for directory " << dir << "\n\n";
// Write directory-level rules for "all".
this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
@@ -514,79 +489,52 @@ cmGlobalUnixMakefileGenerator3
this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
}
-
-std::string cmGlobalUnixMakefileGenerator3
-::GenerateBuildCommand(const char* makeProgram, const char *projectName,
- const char *projectDir, const char* additionalOptions,
- const char *targetName, const char* config,
- bool ignoreErrors, bool fast)
+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)
{
- // Project name & dir and config are not used yet.
- (void)projectName;
- (void)projectDir;
- (void)config;
-
- std::string makeCommand =
- cmSystemTools::ConvertToUnixOutputPath(makeProgram);
+ makeCommand.push_back(this->SelectMakeProgram(makeProgram));
// Since we have full control over the invocation of nmake, let us
// make it quiet.
- if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
- {
- makeCommand += " /NOLOGO ";
- }
- if ( ignoreErrors )
- {
- makeCommand += " -i";
- }
- if ( additionalOptions )
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
+ 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);
}
- if ( targetName && strlen(targetName))
- {
- cmLocalUnixMakefileGenerator3 *lg;
- if (this->LocalGenerators.size())
- {
- lg = static_cast<cmLocalUnixMakefileGenerator3 *>
- (this->LocalGenerators[0]);
- }
- else
- {
- lg = static_cast<cmLocalUnixMakefileGenerator3 *>
- (this->CreateLocalGenerator());
- // set the Start directories
- lg->GetMakefile()->SetStartDirectory
- (this->CMakeInstance->GetStartDirectory());
- lg->GetMakefile()->SetStartOutputDirectory
- (this->CMakeInstance->GetStartOutputDirectory());
- lg->GetMakefile()->MakeStartDirectoriesCurrent();
- }
- makeCommand += " \"";
std::string tname = targetName;
- if(fast)
- {
+ if (fast) {
tname += "/fast";
- }
- tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeCommand += tname.c_str();
- makeCommand += "\"";
- if (!this->LocalGenerators.size())
- {
- delete lg;
- }
}
- return makeCommand;
+ cmOutputConverter conv(mf->GetStateSnapshot());
+ tname =
+ conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
+ cmSystemTools::ConvertToOutputSlashes(tname);
+ makeCommand.push_back(tname);
+ if (this->Makefiles.empty()) {
+ delete mf;
+ }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3
-::WriteConvenienceRules(std::ostream& ruleFileStream,
- std::set<cmStdString> &emitted)
+void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
+ std::ostream& ruleFileStream, std::set<std::string>& emitted)
{
std::vector<std::string> depends;
std::vector<std::string> commands;
@@ -595,50 +543,44 @@ cmGlobalUnixMakefileGenerator3
// 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]);
+ cmLocalUnixMakefileGenerator3* lg;
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
// for each target Generate the rule files for each target.
- cmTargets& targets = lg->GetMakefile()->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
+ std::vector<cmGeneratorTarget*> targets = lg->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+ t != targets.end(); ++t) {
+ cmGeneratorTarget* gtarget = *t;
// Don't emit the same rule twice (e.g. two targets with the same
// simple name)
- if(t->second.GetName() &&
- strlen(t->second.GetName()) &&
- emitted.insert(t->second.GetName()).second &&
- // Handle user targets here. Global targets are handled in
- // the local generator on a per-directory basis.
- ((t->second.GetType() == cmTarget::EXECUTABLE) ||
- (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
- (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
- (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
- (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
- (t->second.GetType() == cmTarget::UTILITY)))
- {
+ int type = gtarget->GetType();
+ std::string name = gtarget->GetName();
+ if (!name.empty() && emitted.insert(name).second &&
+ // Handle user targets here. Global targets are handled in
+ // the local generator on a per-directory basis.
+ ((type == cmStateEnums::EXECUTABLE) ||
+ (type == cmStateEnums::STATIC_LIBRARY) ||
+ (type == cmStateEnums::SHARED_LIBRARY) ||
+ (type == cmStateEnums::MODULE_LIBRARY) ||
+ (type == cmStateEnums::OBJECT_LIBRARY) ||
+ (type == cmStateEnums::UTILITY))) {
// Add a rule to build the target by name.
lg->WriteDivider(ruleFileStream);
- ruleFileStream
- << "# Target rules for targets named "
- << t->second.GetName() << "\n\n";
+ ruleFileStream << "# Target rules for targets named " << name
+ << "\n\n";
// Write the rule.
commands.clear();
std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
tmp += "Makefile2";
- commands.push_back(lg->GetRecursiveMakeCall
- (tmp.c_str(),t->second.GetName()));
+ commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name));
depends.clear();
depends.push_back("cmake_check_build_system");
- lg->WriteMakeRule(ruleFileStream,
- "Build rule for target.",
- t->second.GetName(), depends, commands,
- true);
+ lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name,
+ depends, commands, true);
// Add a fast rule to build the target
- std::string localName = lg->GetRelativeTargetDirectory(t->second);
+ std::string localName = lg->GetRelativeTargetDirectory(gtarget);
std::string makefileName;
makefileName = localName;
makefileName += "/build.make";
@@ -646,416 +588,419 @@ cmGlobalUnixMakefileGenerator3
commands.clear();
std::string makeTargetName = localName;
makeTargetName += "/build";
- localName = t->second.GetName();
+ localName = name;
localName += "/fast";
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(), makeTargetName.c_str()));
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
- localName.c_str(), depends, commands, true);
+ localName, depends, commands, true);
// Add a local name for the rule to relink the target before
// installation.
- if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
- {
- makeTargetName = lg->GetRelativeTargetDirectory(t->second);
+ if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
+ makeTargetName = lg->GetRelativeTargetDirectory(gtarget);
makeTargetName += "/preinstall";
- localName = t->second.GetName();
+ localName = name;
localName += "/preinstall";
depends.clear();
commands.clear();
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(), makeTargetName.c_str()));
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
lg->WriteMakeRule(ruleFileStream,
"Manual pre-install relink rule for target.",
- localName.c_str(), depends, commands, true);
- }
+ localName, depends, commands, true);
}
}
}
+ }
}
-
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3
-::WriteConvenienceRules2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3 *lg)
+void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
+ std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
{
std::vector<std::string> depends;
std::vector<std::string> commands;
std::string localName;
std::string makeTargetName;
-
// write the directory level rules for this local gen
- this->WriteDirectoryRules2(ruleFileStream,lg);
+ this->WriteDirectoryRules2(ruleFileStream, lg);
depends.push_back("cmake_check_build_system");
// for each target Generate the rule files for each target.
- cmTargets& targets = lg->GetMakefile()->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- if (t->second.GetName()
- && strlen(t->second.GetName())
- && ((t->second.GetType() == cmTarget::EXECUTABLE)
- || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
- || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
- || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
- || (t->second.GetType() == cmTarget::OBJECT_LIBRARY)
- || (t->second.GetType() == cmTarget::UTILITY)))
- {
+ std::vector<cmGeneratorTarget*> targets = lg->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+ t != targets.end(); ++t) {
+ cmGeneratorTarget* gtarget = *t;
+ 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))) {
std::string makefileName;
// Add a rule to build the target by name.
- localName = lg->GetRelativeTargetDirectory(t->second);
+ localName = lg->GetRelativeTargetDirectory(gtarget);
makefileName = localName;
makefileName += "/build.make";
- bool needRequiresStep = this->NeedRequiresStep(t->second);
+ bool needRequiresStep = this->NeedRequiresStep(gtarget);
lg->WriteDivider(ruleFileStream);
- ruleFileStream
- << "# Target rules for target "
- << localName << "\n\n";
+ ruleFileStream << "# Target rules for target " << localName << "\n\n";
commands.clear();
makeTargetName = localName;
makeTargetName += "/depend";
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(),makeTargetName.c_str()));
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
// add requires if we need it for this generator
- if (needRequiresStep)
- {
+ if (needRequiresStep) {
makeTargetName = localName;
makeTargetName += "/requires";
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(),makeTargetName.c_str()));
- }
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ }
makeTargetName = localName;
makeTargetName += "/build";
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(),makeTargetName.c_str()));
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
// Write the rule.
localName += "/all";
depends.clear();
- std::string progressDir =
- lg->GetMakefile()->GetHomeOutputDirectory();
- progressDir += cmake::GetCMakeFilesDirectory();
- {
- cmOStringStream progCmd;
- progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
- // all target counts
- progCmd << lg->Convert(progressDir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
- progCmd << " ";
+ cmLocalUnixMakefileGenerator3::EchoProgress progress;
+ progress.Dir = lg->GetBinaryDirectory();
+ progress.Dir += cmake::GetCMakeFilesDirectory();
+ {
+ std::ostringstream progressArg;
+ const char* sep = "";
std::vector<unsigned long>& progFiles =
- this->ProgressMap[&t->second].Marks;
+ this->ProgressMap[gtarget].Marks;
for (std::vector<unsigned long>::iterator i = progFiles.begin();
- i != progFiles.end(); ++i)
- {
- progCmd << " " << *i;
- }
- commands.push_back(progCmd.str());
+ i != progFiles.end(); ++i) {
+ progressArg << sep << *i;
+ sep = ",";
}
- progressDir = "Built target ";
- progressDir += t->first;
- lg->AppendEcho(commands,progressDir.c_str());
+ progress.Arg = progressArg.str();
+ }
+
+ bool targetMessages = true;
+ if (const char* tgtMsg =
+ this->GetCMakeInstance()->GetState()->GetGlobalProperty(
+ "TARGET_MESSAGES")) {
+ targetMessages = cmSystemTools::IsOn(tgtMsg);
+ }
+
+ if (targetMessages) {
+ lg->AppendEcho(commands, "Built target " + name,
+ cmLocalUnixMakefileGenerator3::EchoNormal, &progress);
+ }
- this->AppendGlobalTargetDepends(depends,t->second);
+ this->AppendGlobalTargetDepends(depends, gtarget);
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
- localName.c_str(), depends, commands, true);
+ localName, depends, commands, true);
// add the all/all dependency
- if(!this->IsExcluded(this->LocalGenerators[0], t->second))
- {
+ 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);
- }
+ lg->WriteMakeRule(ruleFileStream, "Include target in all.", "all",
+ depends, commands, true);
+ }
// Write the rule.
commands.clear();
- progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
- progressDir += cmake::GetCMakeFilesDirectory();
{
- // TODO: Convert the total progress count to a make variable.
- cmOStringStream progCmd;
- progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
- // # in target
- progCmd << lg->Convert(progressDir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
- //
- std::set<cmTarget *> emitted;
- progCmd << " "
- << this->CountProgressMarksInTarget(&t->second, emitted);
- commands.push_back(progCmd.str());
+ // TODO: Convert the total progress count to a make variable.
+ std::ostringstream progCmd;
+ progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
+ // # in target
+ progCmd << lg->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(progress.Dir),
+ cmOutputConverter::SHELL);
+ //
+ std::set<cmGeneratorTarget const*> emitted;
+ 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.c_str()));
+ commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), localName));
{
- cmOStringStream progCmd;
- progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
- progCmd << lg->Convert(progressDir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
- progCmd << " 0";
- commands.push_back(progCmd.str());
+ std::ostringstream progCmd;
+ progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
+ progCmd << lg->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(progress.Dir),
+ cmOutputConverter::SHELL);
+ progCmd << " 0";
+ commands.push_back(progCmd.str());
}
depends.clear();
depends.push_back("cmake_check_build_system");
- localName = lg->GetRelativeTargetDirectory(t->second);
+ localName = lg->GetRelativeTargetDirectory(gtarget);
localName += "/rule";
lg->WriteMakeRule(ruleFileStream,
"Build rule for subdir invocation for target.",
- localName.c_str(), depends, commands, true);
+ localName, depends, commands, true);
// Add a target with the canonical name (no prefix, suffix or path).
commands.clear();
depends.clear();
depends.push_back(localName);
- lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
- t->second.GetName(), depends, commands, true);
+ lg->WriteMakeRule(ruleFileStream, "Convenience name for target.", name,
+ depends, commands, true);
// Add rules to prepare the target for installation.
- if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
- {
- localName = lg->GetRelativeTargetDirectory(t->second);
+ if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
+ localName = lg->GetRelativeTargetDirectory(gtarget);
localName += "/preinstall";
depends.clear();
commands.clear();
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(), localName.c_str()));
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), localName));
lg->WriteMakeRule(ruleFileStream,
- "Pre-install relink rule for target.",
- localName.c_str(), depends, commands, true);
+ "Pre-install relink rule for target.", localName,
+ depends, commands, true);
- if(!this->IsExcluded(this->LocalGenerators[0], t->second))
- {
+ 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(t->second);
+ localName = lg->GetRelativeTargetDirectory(gtarget);
makeTargetName = localName;
makeTargetName += "/clean";
depends.clear();
commands.clear();
- commands.push_back(lg->GetRecursiveMakeCall
- (makefileName.c_str(), makeTargetName.c_str()));
+ commands.push_back(
+ lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
- makeTargetName.c_str(), depends, commands, true);
+ makeTargetName, depends, commands, true);
commands.clear();
depends.push_back(makeTargetName);
- lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
- "clean", depends, commands, true);
+ 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
+// 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;
+
+ cmLocalGenerator* tlg = gt->GetLocalGenerator();
+
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ gt->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ continue;
+ }
+
+ cmStateSnapshot csnp = lg->GetStateSnapshot();
+ cmStateSnapshot tsnp = tlg->GetStateSnapshot();
+
+ // Consider the directory containing the target and all its
+ // parents until something excludes the target.
+ for (; csnp.IsValid() && !this->IsExcluded(csnp, tsnp);
+ csnp = csnp.GetBuildsystemDirectoryParent()) {
+ // This local generator includes the target.
+ std::set<cmGeneratorTarget const*>& targetSet =
+ this->DirectoryTargetsMap[csnp];
+ targetSet.insert(gt);
+
+ // 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);
+ }
}
}
+ }
}
-//----------------------------------------------------------------------------
-size_t
-cmGlobalUnixMakefileGenerator3
-::CountProgressMarksInTarget(cmTarget* target,
- std::set<cmTarget*>& emitted)
+size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget(
+ cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& emitted)
{
size_t count = 0;
- if(emitted.insert(target).second)
- {
+ 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)
- {
- count += this->CountProgressMarksInTarget(*di, emitted);
+ TargetDependSet const& depends = this->GetTargetDirectDepends(target);
+ for (TargetDependSet::const_iterator di = depends.begin();
+ di != depends.end(); ++di) {
+ if ((*di)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
}
+ count += this->CountProgressMarksInTarget(*di, emitted);
}
+ }
return count;
}
-//----------------------------------------------------------------------------
-size_t
-cmGlobalUnixMakefileGenerator3
-::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg)
+size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInAll(
+ cmLocalGenerator* lg)
{
size_t count = 0;
- std::set<cmTarget*> emitted;
- std::set<cmTarget*> const& targets = this->LocalGeneratorToTargetMap[lg];
- for(std::set<cmTarget*>::const_iterator t = targets.begin();
- t != targets.end(); ++t)
- {
+ 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);
- }
+ }
return count;
}
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
+void cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
cmMakefileTargetGenerator* tg)
{
- TargetProgress& tp = this->ProgressMap[tg->GetTarget()];
+ TargetProgress& tp = this->ProgressMap[tg->GetGeneratorTarget()];
tp.NumberOfActions = tg->GetNumberOfProgressActions();
tp.VariableFile = tg->GetProgressFileNameFull();
}
-//----------------------------------------------------------------------------
-bool
-cmGlobalUnixMakefileGenerator3::ProgressMapCompare
-::operator()(cmTarget* l, cmTarget* r) const
-{
- // Order by target name.
- if(int c = strcmp(l->GetName(), r->GetName()))
- {
- return c < 0;
- }
- // Order duplicate targets by binary directory.
- return strcmp(l->GetMakefile()->GetCurrentOutputDirectory(),
- r->GetMakefile()->GetCurrentOutputDirectory()) < 0;
-}
-
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3::TargetProgress
-::WriteProgressVariables(unsigned long total, unsigned long &current)
+void cmGlobalUnixMakefileGenerator3::TargetProgress::WriteProgressVariables(
+ unsigned long total, unsigned long& current)
{
cmGeneratedFileStream fout(this->VariableFile.c_str());
- for(unsigned long i = 1; i <= this->NumberOfActions; ++i)
- {
+ for (unsigned long i = 1; i <= this->NumberOfActions; ++i) {
fout << "CMAKE_PROGRESS_" << i << " = ";
- if (total <= 100)
- {
+ if (total <= 100) {
unsigned long num = i + current;
fout << num;
this->Marks.push_back(num);
- }
- else if (((i+current)*100)/total > ((i-1+current)*100)/total)
- {
- unsigned long num = ((i+current)*100)/total;
+ } else if (((i + current) * 100) / total >
+ ((i - 1 + current) * 100) / total) {
+ unsigned long num = ((i + current) * 100) / total;
fout << num;
this->Marks.push_back(num);
- }
- fout << "\n";
}
+ fout << "\n";
+ }
fout << "\n";
current += this->NumberOfActions;
}
-//----------------------------------------------------------------------------
-void
-cmGlobalUnixMakefileGenerator3
-::AppendGlobalTargetDepends(std::vector<std::string>& depends,
- cmTarget& target)
+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 (TargetDependSet::const_iterator i = depends_set.begin();
+ i != depends_set.end(); ++i) {
// Create the target-level dependency.
- cmTarget const* dep = *i;
+ cmGeneratorTarget const* dep = *i;
+ if (dep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
cmLocalUnixMakefileGenerator3* lg3 =
- static_cast<cmLocalUnixMakefileGenerator3*>
- (dep->GetMakefile()->GetLocalGenerator());
- std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
+ static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
+ std::string tgtName =
+ lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep));
tgtName += "/all";
depends.push_back(tgtName);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalUnixMakefileGenerator3::WriteHelpRule
-(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
+void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
+ std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
{
// add the help target
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,"... all (the default if no target is provided)");
- lg->AppendEcho(commands,"... clean");
- lg->AppendEcho(commands,"... depend");
+ 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");
// Keep track of targets already listed.
- std::set<cmStdString> emittedTargets;
+ std::set<std::string> emittedTargets;
// for each local generator
unsigned int i;
- cmLocalUnixMakefileGenerator3 *lg2;
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
+ cmLocalUnixMakefileGenerator3* lg2;
+ for (i = 0; i < this->LocalGenerators.size(); ++i) {
lg2 =
- static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
+ static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
// for the passed in makefile or if this is the top Makefile wripte out
// the targets
- if (lg2 == lg || !lg->GetParent())
- {
+ if (lg2 == lg || lg->IsRootMakefile()) {
// for each target Generate the rule files for each target.
- cmTargets& targets = lg2->GetMakefile()->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- if((t->second.GetType() == cmTarget::EXECUTABLE) ||
- (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
- (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
- (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
- (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
- (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
- (t->second.GetType() == cmTarget::UTILITY))
- {
- if(emittedTargets.insert(t->second.GetName()).second)
- {
+ std::vector<cmGeneratorTarget*> targets = lg2->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+ t != targets.end(); ++t) {
+ cmGeneratorTarget* target = *t;
+ cmStateEnums::TargetType type = target->GetType();
+ if ((type == cmStateEnums::EXECUTABLE) ||
+ (type == cmStateEnums::STATIC_LIBRARY) ||
+ (type == cmStateEnums::SHARED_LIBRARY) ||
+ (type == cmStateEnums::MODULE_LIBRARY) ||
+ (type == cmStateEnums::OBJECT_LIBRARY) ||
+ (type == cmStateEnums::GLOBAL_TARGET) ||
+ (type == cmStateEnums::UTILITY)) {
+ std::string const& name = target->GetName();
+ if (emittedTargets.insert(name).second) {
path = "... ";
- path += t->second.GetName();
- lg->AppendEcho(commands,path.c_str());
- }
+ path += name;
+ lg->AppendEcho(commands, path);
}
}
}
}
- std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
- for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
- o != localHelp.end(); ++o)
- {
+ }
+ 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;
- lg->AppendEcho(commands, path.c_str());
- }
- lg->WriteMakeRule(ruleFileStream, "Help Target",
- "help",
- no_depends, commands, true);
+ lg->AppendEcho(commands, path);
+ }
+ lg->WriteMakeRule(ruleFileStream, "Help Target", "help", no_depends,
+ commands, true);
ruleFileStream << "\n\n";
}
-
-bool cmGlobalUnixMakefileGenerator3
-::NeedRequiresStep(cmTarget const& target)
+bool cmGlobalUnixMakefileGenerator3::NeedRequiresStep(
+ const cmGeneratorTarget* target)
{
- std::set<cmStdString> languages;
- target.GetLanguages(languages);
- for(std::set<cmStdString>::const_iterator l = languages.begin();
- l != languages.end(); ++l)
- {
+ 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.GetMakefile()->GetDefinition(var.c_str()))
- {
+ if (target->Target->GetMakefile()->GetDefinition(var)) {
return true;
- }
}
+ }
return false;
}
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 5e9dce3a6..a656102fb 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -1,23 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalUnixMakefileGenerator3_h
#define cmGlobalUnixMakefileGenerator3_h
-#include "cmGlobalGenerator.h"
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+#include "cmGeneratorTarget.h"
+#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
+#include "cmStateSnapshot.h"
class cmGeneratedFileStream;
-class cmMakefileTargetGenerator;
+class cmLocalGenerator;
class cmLocalUnixMakefileGenerator3;
+class cmMakefile;
+class cmMakefileTargetGenerator;
+class cmake;
+struct cmDocumentationEntry;
/** \class cmGlobalUnixMakefileGenerator3
* \brief Write a Unix makefiles.
@@ -51,50 +57,66 @@ class cmLocalUnixMakefileGenerator3;
*/
-class cmGlobalUnixMakefileGenerator3 : public cmGlobalGenerator
+class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator
{
public:
- cmGlobalUnixMakefileGenerator3();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalUnixMakefileGenerator3>(); }
+ cmGlobalUnixMakefileGenerator3(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<
+ cmGlobalUnixMakefileGenerator3>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalUnixMakefileGenerator3::GetActualName();}
- static const char* GetActualName() {return "Unix Makefiles";}
+ std::string GetName() const CM_OVERRIDE
+ {
+ return cmGlobalUnixMakefileGenerator3::GetActualName();
+ }
+ static std::string GetActualName() { return "Unix Makefiles"; }
+
+ /**
+ * Utilized by the generator factory to determine if this generator
+ * supports toolsets.
+ */
+ static bool SupportsToolset() { return false; }
+
+ /**
+ * Utilized by the generator factory to determine if this generator
+ * supports platforms.
+ */
+ static bool SupportsPlatform() { return false; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator3
- virtual cmLocalGenerator *CreateLocalGenerator();
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE;
/**
- * Try to determine system infomation such as shared library
+ * 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) CM_OVERRIDE;
+
+ void Configure() CM_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.
*/
- virtual void Generate();
-
+ void Generate() CM_OVERRIDE;
void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
- std::vector<cmLocalGenerator *> &);
+ std::vector<cmLocalGenerator*>&);
// write out the help rule listing the valid targets
void WriteHelpRule(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3 *);
+ cmLocalUnixMakefileGenerator3*);
// write the top level target rules
void WriteConvenienceRules(std::ostream& ruleFileStream,
- std::set<cmStdString> &emitted);
+ std::set<std::string>& emitted);
/** Get the command to use for a target that has no rule. This is
used for multiple output dependencies and for cmake_force. */
@@ -105,19 +127,36 @@ public:
std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
// change the build command for speed
- virtual std::string GenerateBuildCommand
- (const char* makeProgram,
- const char *projectName, const char *projectDir,
- const char* additionalOptions,
- const char *targetName,
- const char* config, bool ignoreErrors, bool fast);
+ 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;
/** Record per-target progress information. */
void RecordTargetProgress(cmMakefileTargetGenerator* tg);
- void AddCXXCompileCommand(const std::string &sourceFile,
- const std::string &workingDirectory,
- const std::string &compileCommand);
+ void AddCXXCompileCommand(const std::string& sourceFile,
+ const std::string& workingDirectory,
+ const std::string& compileCommand);
+
+ /** Does the make tool tolerate .NOTPARALLEL? */
+ virtual bool AllowNotParallel() const { return true; }
+
+ /** Does the make tool tolerate .DELETE_ON_ERROR? */
+ virtual bool AllowDeleteOnError() const { return true; }
+
+ bool IsIPOSupported() const CM_OVERRIDE { return true; }
+
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
+
+ std::string IncludeDirective;
+ bool DefineWindowsNULL;
+ bool PassMakeflags;
+ bool UnixCD;
protected:
void WriteMainMakefile2();
@@ -127,32 +166,49 @@ protected:
cmLocalUnixMakefileGenerator3*);
void WriteDirectoryRule2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg,
- const char* pass, bool check_all,
- bool check_relink);
+ cmLocalUnixMakefileGenerator3* lg, const char* pass,
+ bool check_all, bool check_relink);
void WriteDirectoryRules2(std::ostream& ruleFileStream,
cmLocalUnixMakefileGenerator3* lg);
void AppendGlobalTargetDepends(std::vector<std::string>& depends,
- cmTarget& target);
+ cmGeneratorTarget* target);
// does this generator need a requires step for any of its targets
- bool NeedRequiresStep(cmTarget const&);
+ bool NeedRequiresStep(cmGeneratorTarget const*);
// Target name hooks for superclass.
- const char* GetAllTargetName() const { return "all"; }
- const char* GetInstallTargetName() const { return "install"; }
- const char* GetInstallLocalTargetName() const { return "install/local"; }
- const char* GetInstallStripTargetName() const { return "install/strip"; }
- const char* GetPreinstallTargetName() const { return "preinstall"; }
- const char* GetTestTargetName() const { return "test"; }
- const char* GetPackageTargetName() const { return "package"; }
- const char* GetPackageSourceTargetName() const { return "package_source"; }
- const char* GetEditCacheTargetName() const { return "edit_cache"; }
- const char* GetRebuildCacheTargetName() const { return "rebuild_cache"; }
- const char* GetCleanTargetName() const { return "clean"; }
-
- virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
+ const char* GetAllTargetName() const CM_OVERRIDE { return "all"; }
+ const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; }
+ const char* GetInstallLocalTargetName() const CM_OVERRIDE
+ {
+ return "install/local";
+ }
+ const char* GetInstallStripTargetName() const CM_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
+ {
+ return "package_source";
+ }
+ const char* GetEditCacheTargetName() const CM_OVERRIDE
+ {
+ return "edit_cache";
+ }
+ const char* GetRebuildCacheTargetName() const CM_OVERRIDE
+ {
+ return "rebuild_cache";
+ }
+ const char* GetCleanTargetName() const CM_OVERRIDE { return "clean"; }
+
+ bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const CM_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
@@ -169,24 +225,35 @@ protected:
// Store per-target progress counters.
struct TargetProgress
{
- TargetProgress(): NumberOfActions(0) {}
+ TargetProgress()
+ : NumberOfActions(0)
+ {
+ }
unsigned long NumberOfActions;
std::string VariableFile;
std::vector<unsigned long> Marks;
void WriteProgressVariables(unsigned long total, unsigned long& current);
};
- struct ProgressMapCompare { bool operator()(cmTarget*,cmTarget*) const; };
- typedef std::map<cmTarget*, TargetProgress,
- ProgressMapCompare> ProgressMapType;
+ typedef std::map<cmGeneratorTarget const*, TargetProgress,
+ cmGeneratorTarget::StrictTargetComparison>
+ ProgressMapType;
ProgressMapType ProgressMap;
- size_t CountProgressMarksInTarget(cmTarget* target,
- std::set<cmTarget*>& emitted);
- size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg);
+ size_t CountProgressMarksInTarget(
+ cmGeneratorTarget const* target,
+ std::set<cmGeneratorTarget const*>& emitted);
+ size_t CountProgressMarksInAll(cmLocalGenerator* lg);
+
+ cmGeneratedFileStream* CommandDatabase;
- cmGeneratedFileStream *CommandDatabase;
private:
- virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+ const char* GetBuildIgnoreErrorsFlag() const CM_OVERRIDE { return "-i"; }
+ std::string GetEditCacheCommand() const CM_OVERRIDE;
+
+ std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
+ cmStateSnapshot::StrictWeakOrder>
+ DirectoryTargetsMap;
+ void InitializeProgressMarks() CM_OVERRIDE;
};
#endif
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index b2a337cc6..4fff11a9f 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -1,139 +1,456 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "windows.h" // this must be first to define GetCurrentDirectory
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio10Generator.h"
+
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.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"
-static const char vs10Win32generatorName[] = "Visual Studio 10";
-static const char vs10Win64generatorName[] = "Visual Studio 10 Win64";
-static const char vs10IA64generatorName[] = "Visual Studio 10 IA64";
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include <algorithm>
+
+static const char vs10generatorName[] = "Visual Studio 10 2010";
+
+// Map generator name without year to name with year.
+static const char* cmVS10GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs10generatorName,
+ sizeof(vs10generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs10generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2010")) {
+ p += 5;
+ }
+ genName = std::string(vs10generatorName) + p;
+ return p;
+}
class cmGlobalVisualStudio10Generator::Factory
: public cmGlobalGeneratorFactory
{
public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(!strcmp(name, vs10Win32generatorName))
- {
- return new cmGlobalVisualStudio10Generator(
- name, NULL, NULL);
- }
- if(!strcmp(name, vs10Win64generatorName))
- {
- return new cmGlobalVisualStudio10Generator(
- name, "x64", "CMAKE_FORCE_WIN64");
- }
- if(!strcmp(name, vs10IA64generatorName))
- {
- return new cmGlobalVisualStudio10Generator(
- name, "Itanium", "CMAKE_FORCE_IA64");
- }
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE
+ {
+ std::string genName;
+ const char* p = cmVS10GenName(name, genName);
+ if (!p) {
+ return 0;
+ }
+ if (!*p) {
+ return new cmGlobalVisualStudio10Generator(cm, genName, "");
+ }
+ if (*p++ != ' ') {
+ return 0;
+ }
+ if (strcmp(p, "Win64") == 0) {
+ return new cmGlobalVisualStudio10Generator(cm, genName, "x64");
+ }
+ if (strcmp(p, "IA64") == 0) {
+ return new cmGlobalVisualStudio10Generator(cm, genName, "Itanium");
+ }
return 0;
}
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- entry.Name = "Visual Studio 10";
- entry.Brief = "Generates Visual Studio 10 (2010) project files.";
- entry.Full =
- "It is possible to append a space followed by the platform name "
- "to create project files for a specific target platform. E.g. "
- "\"Visual Studio 10 Win64\" will create project files for "
- "the x64 processor; \"Visual Studio 10 IA64\" for Itanium.";
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_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
+ {
+ names.push_back(vs10generatorName);
+ names.push_back(vs10generatorName + std::string(" IA64"));
+ names.push_back(vs10generatorName + std::string(" Win64"));
}
- virtual void GetGenerators(std::vector<std::string>& names) const {
- names.push_back(vs10Win32generatorName);
- names.push_back(vs10Win64generatorName);
- names.push_back(vs10IA64generatorName); }
+ bool SupportsToolset() const CM_OVERRIDE { return true; }
+ bool SupportsPlatform() const CM_OVERRIDE { return true; }
};
-//----------------------------------------------------------------------------
cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory()
{
return new Factory;
}
-//----------------------------------------------------------------------------
cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
- const char* name, const char* platformName,
- const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio8Generator(name, platformName,
- additionalPlatformDefinition)
+ cmake* cm, const std::string& name, const std::string& platformName)
+ : cmGlobalVisualStudio8Generator(cm, name, platformName)
{
- this->FindMakeProgramFile = "CMakeVS10FindMake.cmake";
std::string vc10Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;"
- "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32);
- this->MasmEnabled = false;
+ "ProductDir",
+ vc10Express, cmSystemTools::KeyWOW64_32);
+ this->CudaEnabled = false;
+ this->SystemIsWindowsCE = false;
+ this->SystemIsWindowsPhone = false;
+ this->SystemIsWindowsStore = false;
+ this->MSBuildCommandInitialized = false;
+ {
+ std::string envPlatformToolset;
+ if (cmSystemTools::GetEnv("PlatformToolset", envPlatformToolset) &&
+ envPlatformToolset == "Windows7.1SDK") {
+ // We are running from a Windows7.1SDK command prompt.
+ this->DefaultPlatformToolset = "Windows7.1SDK";
+ } else {
+ 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->Version = VS10;
+ this->PlatformToolsetNeedsDebugEnum = false;
+}
+
+bool cmGlobalVisualStudio10Generator::MatchesGeneratorName(
+ const std::string& name) const
+{
+ std::string genName;
+ if (cmVS10GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s,
+ cmMakefile* mf)
+{
+ this->SystemName = s;
+ this->SystemVersion = mf->GetSafeDefinition("CMAKE_SYSTEM_VERSION");
+ if (!this->InitializeSystem(mf)) {
+ return false;
+ }
+ return this->cmGlobalVisualStudio8Generator::SetSystemName(s, mf);
+}
+
+bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform(
+ std::string const& p, cmMakefile* mf)
+{
+ if (!this->cmGlobalVisualStudio8Generator::SetGeneratorPlatform(p, mf)) {
+ return false;
+ }
+ if (this->GetPlatformName() == "Itanium" ||
+ this->GetPlatformName() == "x64") {
+ if (this->IsExpressEdition() && !this->Find64BitTools(mf)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void cmCudaToolVersion(std::string& s)
+{
+ // "CUDA x.y.props" => "x.y"
+ s = s.substr(5);
+ s = s.substr(0, s.size() - 6);
+}
+
+bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
+ std::string const& ts, cmMakefile* mf)
+{
+ if (this->SystemIsWindowsCE && ts.empty() &&
+ this->DefaultPlatformToolset.empty()) {
+ 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());
+ return false;
+ }
+
+ if (!this->ParseGeneratorToolset(ts, mf)) {
+ return false;
+ }
+
+ if (!this->FindVCTargetsPath(mf)) {
+ return false;
+ }
+
+ if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) {
+ // The GenerateDebugInformation link setting for the v140 toolset
+ // in VS 2015 was originally an enum with "No" and "Debug" values,
+ // differing from the "false" and "true" values used in older toolsets.
+ // A VS 2015 update changed it back. Parse the "link.xml" file to
+ // discover which one we need.
+ std::string const link_xml = this->VCTargetsPath + "/1033/link.xml";
+ cmsys::ifstream fin(link_xml.c_str());
+ std::string line;
+ while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
+ if (line.find(" Switch=\"DEBUG\" ") != std::string::npos) {
+ this->PlatformToolsetNeedsDebugEnum =
+ line.find(" Name=\"Debug\" ") != std::string::npos;
+ break;
+ }
+ }
+ }
+
+ 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";
+ cmsys::Glob gl;
+ gl.SetRelative(bcDir.c_str());
+ if (gl.FindFiles(bcDir + "/CUDA *.props")) {
+ cudaTools = gl.GetFiles();
+ }
+ if (!cudaTools.empty()) {
+ std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion);
+ std::sort(cudaTools.begin(), cudaTools.end(),
+ cmSystemTools::VersionCompareGreater);
+ this->GeneratorToolsetCuda = cudaTools.at(0);
+ }
+ }
+
+ if (const char* toolset = this->GetPlatformToolset()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
+ }
+ 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);
+ }
+ return true;
}
-//----------------------------------------------------------------------------
-bool
-cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts)
+bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
+ std::string const& ts, cmMakefile* mf)
{
- this->PlatformToolset = ts;
+ std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ",");
+ std::vector<std::string>::const_iterator fi = fields.begin();
+ if (fi == fields.end()) {
+ return true;
+ }
+
+ // The first field may be the VS platform toolset.
+ if (fi->find('=') == fi->npos) {
+ this->GeneratorToolset = *fi;
+ ++fi;
+ }
+
+ std::set<std::string> handled;
+
+ // The rest of the fields must be key=value pairs.
+ for (; fi != fields.end(); ++fi) {
+ std::string::size_type pos = fi->find('=');
+ if (pos == fi->npos) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset specification\n"
+ " " << ts << "\n"
+ "that contains a field after the first ',' with no '='."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ std::string const key = fi->substr(0, pos);
+ std::string const value = fi->substr(pos + 1);
+ if (!handled.insert(key).second) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset specification\n"
+ " " << ts << "\n"
+ "that contains duplicate field key '" << key << "'."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ if (!this->ProcessGeneratorToolsetField(key, value)) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset specification\n"
+ " " << ts << "\n"
+ "that contains invalid field '" << *fi << "'."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ }
+
return true;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Generator::AddPlatformDefinitions(cmMakefile* mf)
+bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
+ std::string const& key, std::string const& value)
+{
+ if (key == "cuda") {
+ this->GeneratorToolsetCuda = value;
+ return true;
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
{
- cmGlobalVisualStudio8Generator::AddPlatformDefinitions(mf);
- if(!this->PlatformToolset.empty())
- {
- mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET",
- this->PlatformToolset.c_str());
+ if (this->SystemName == "Windows") {
+ if (!this->InitializeWindows(mf)) {
+ return false;
+ }
+ } else if (this->SystemName == "WindowsCE") {
+ this->SystemIsWindowsCE = true;
+ if (!this->InitializeWindowsCE(mf)) {
+ return false;
+ }
+ } else if (this->SystemName == "WindowsPhone") {
+ this->SystemIsWindowsPhone = true;
+ if (!this->InitializeWindowsPhone(mf)) {
+ return false;
}
+ } else if (this->SystemName == "WindowsStore") {
+ this->SystemIsWindowsStore = true;
+ if (!this->InitializeWindowsStore(mf)) {
+ return false;
+ }
+ } else if (this->SystemName == "Android") {
+ if (this->DefaultPlatformName != "Win32") {
+ 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());
+ return false;
+ }
+ std::string v = this->GetInstalledNsightTegraVersion();
+ if (v.empty()) {
+ mf->IssueMessage(cmake::FATAL_ERROR,
+ "CMAKE_SYSTEM_NAME is 'Android' but "
+ "'NVIDIA Nsight Tegra Visual Studio Edition' "
+ "is not installed.");
+ return false;
+ }
+ this->DefaultPlatformName = "Tegra-Android";
+ this->DefaultPlatformToolset = "Default";
+ this->NsightTegraVersion = v;
+ mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v.c_str());
+ }
+
+ return true;
+}
+
+bool cmGlobalVisualStudio10Generator::InitializeWindows(cmMakefile*)
+{
+ return true;
+}
+
+bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf)
+{
+ if (this->DefaultPlatformName != "Win32") {
+ 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());
+ return false;
+ }
+
+ this->DefaultPlatformToolset = this->SelectWindowsCEToolset();
+
+ return true;
+}
+
+bool cmGlobalVisualStudio10Generator::InitializeWindowsPhone(cmMakefile* mf)
+{
+ std::ostringstream e;
+ e << this->GetName() << " does not support Windows Phone.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+}
+
+bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf)
+{
+ std::ostringstream e;
+ e << this->GetName() << " does not support Windows Store.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+}
+
+bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
+ std::string& toolset) const
+{
+ toolset = "";
+ return false;
+}
+
+bool cmGlobalVisualStudio10Generator::SelectWindowsStoreToolset(
+ std::string& toolset) const
+{
+ toolset = "";
+ return false;
+}
+
+std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const
+{
+ if (this->SystemVersion == "8.0") {
+ return "CE800";
+ }
+ return "";
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout)
{
fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n";
- if (this->ExpressEdition)
- {
+ if (this->ExpressEdition) {
fout << "# Visual C++ Express 2010\n";
- }
- else
- {
+ } else {
fout << "# Visual Studio 2010\n";
- }
+ }
}
///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio10Generator::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator(
+ cmMakefile* mf)
{
- cmLocalVisualStudio10Generator* lg =
- new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS10);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetGlobalGenerator(this);
- return lg;
+ return new cmLocalVisualStudio10Generator(this, mf);
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio10Generator::Generate()
{
this->LongestSource = LongestSourcePath();
this->cmGlobalVisualStudio8Generator::Generate();
- if(this->LongestSource.Length > 0)
- {
- cmMakefile* mf = this->LongestSource.Target->GetMakefile();
- cmOStringStream e;
+ if (this->LongestSource.Length > 0) {
+ cmLocalGenerator* lg = this->LongestSource.Target->GetLocalGenerator();
+ std::ostringstream e;
+ /* clang-format off */
e <<
"The binary and/or source directory paths may be too long to generate "
"Visual Studio 10 files for this project. "
@@ -147,223 +464,459 @@ void cmGlobalVisualStudio10Generator::Generate()
" " << this->LongestSource.SourceFile->GetFullPath() << "\n"
"This is because some Visual Studio tools would append the relative "
"path to the end of the referencing directory path, as in:\n"
- " " << mf->GetCurrentOutputDirectory() << "/"
+ " " << lg->GetCurrentBinaryDirectory() << "/"
<< this->LongestSource.SourceRel << "\n"
"and then incorrectly complain that the file does not exist because "
"the path length is too long for some internal buffer or API. "
"To avoid this problem CMake must use a full path for this file "
"which then triggers the VS 10 property dialog bug.";
- mf->IssueMessage(cmake::WARNING, e.str().c_str());
- }
+ /* clang-format on */
+ lg->IssueMessage(cmake::WARNING, e.str().c_str());
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Generator
-::EnableLanguage(std::vector<std::string>const & lang,
- cmMakefile *mf, bool optional)
+void cmGlobalVisualStudio10Generator::EnableLanguage(
+ std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
- if(this->PlatformName == "Itanium" || this->PlatformName == "x64")
- {
- if(this->IsExpressEdition() && !this->Find64BitTools(mf))
- {
- return;
- }
+ for (std::vector<std::string>::const_iterator it = lang.begin();
+ it != lang.end(); ++it) {
+ if (*it == "ASM_NASM") {
+ this->NasmEnabled = true;
}
-
- for(std::vector<std::string>::const_iterator it = lang.begin();
- it != lang.end(); ++it)
- {
- if(*it == "ASM_MASM")
- {
- this->MasmEnabled = true;
- }
+ if (*it == "CUDA") {
+ this->CudaEnabled = true;
}
-
+ }
+ this->AddPlatformDefinitions(mf);
cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}
-//----------------------------------------------------------------------------
-const char* cmGlobalVisualStudio10Generator::GetPlatformToolset()
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const
{
- if(!this->PlatformToolset.empty())
- {
- return this->PlatformToolset.c_str();
- }
- return 0;
+ std::string const& toolset = this->GetPlatformToolsetString();
+ if (toolset.empty()) {
+ return CM_NULLPTR;
+ }
+ return toolset.c_str();
}
-//----------------------------------------------------------------------------
-std::string cmGlobalVisualStudio10Generator::GetUserMacrosDirectory()
+std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString()
+ const
{
- std::string base;
- std::string path;
+ if (!this->GeneratorToolset.empty()) {
+ return this->GeneratorToolset;
+ }
+ if (!this->DefaultPlatformToolset.empty()) {
+ return this->DefaultPlatformToolset;
+ }
+ static std::string const empty;
+ return empty;
+}
- // base begins with the VisualStudioProjectsLocation reg value...
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\10.0;"
- "VisualStudioProjectsLocation",
- base))
- {
- cmSystemTools::ConvertToUnixSlashes(base);
-
- // 9.0 macros folder:
- path = base + "/VSMacros80";
- // *NOT* a typo; right now in Visual Studio 2008 beta the macros
- // folder is VSMacros80... They may change it to 90 before final
- // release of 2008 or they may not... we'll have to keep our eyes
- // on it
- }
+const char*
+cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const
+{
+ if (!this->GeneratorToolsetHostArchitecture.empty()) {
+ return this->GeneratorToolsetHostArchitecture.c_str();
+ }
+ return CM_NULLPTR;
+}
+
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const
+{
+ if (!this->GeneratorToolsetCuda.empty()) {
+ return this->GeneratorToolsetCuda.c_str();
+ }
+ return CM_NULLPTR;
+}
- // path is (correctly) still empty if we did not read the base value from
- // the Registry value
- return path;
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const
+{
+ return this->GeneratorToolsetCuda;
}
-//----------------------------------------------------------------------------
-std::string cmGlobalVisualStudio10Generator::GetUserMacrosRegKeyBase()
+bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
{
- return "Software\\Microsoft\\VisualStudio\\10.0\\vsmacros";
+ if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
+ return false;
+ }
+ mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND",
+ this->GetMSBuildCommand().c_str());
+ return true;
}
+std::string const& cmGlobalVisualStudio10Generator::GetMSBuildCommand()
+{
+ if (!this->MSBuildCommandInitialized) {
+ this->MSBuildCommandInitialized = true;
+ this->MSBuildCommand = this->FindMSBuildCommand();
+ }
+ return this->MSBuildCommand;
+}
-std::string cmGlobalVisualStudio10Generator
-::GenerateBuildCommand(const char* makeProgram,
- const char *projectName, const char *projectDir,
- const char* additionalOptions, const char *targetName,
- const char* config, bool ignoreErrors, bool fast)
+std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand()
{
- // now build the test
- std::string makeCommand
- = cmSystemTools::ConvertToOutputPath(makeProgram);
- std::string lowerCaseCommand = makeCommand;
- cmSystemTools::LowerCase(lowerCaseCommand);
+ std::string msbuild;
+ std::string mskey;
- // If makeProgram is devenv, parent class knows how to generate command:
- if (lowerCaseCommand.find("devenv") != std::string::npos ||
- lowerCaseCommand.find("VCExpress") != std::string::npos)
- {
- return cmGlobalVisualStudio7Generator::GenerateBuildCommand(makeProgram,
- projectName, projectDir, additionalOptions, targetName, config,
- ignoreErrors, fast);
+ // Search in standard location.
+ mskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\";
+ mskey += this->GetToolsVersion();
+ mskey += ";MSBuildToolsPath";
+ if (cmSystemTools::ReadRegistryValue(mskey.c_str(), msbuild,
+ cmSystemTools::KeyWOW64_32)) {
+ cmSystemTools::ConvertToUnixSlashes(msbuild);
+ msbuild += "/MSBuild.exe";
+ if (cmSystemTools::FileExists(msbuild, true)) {
+ return msbuild;
}
+ }
+
+ msbuild = "MSBuild.exe";
+ return msbuild;
+}
- // Otherwise, assume MSBuild command line, and construct accordingly.
+std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand()
+{
+ if (this->ExpressEdition) {
+ // Visual Studio Express >= 10 do not have "devenv.com" or
+ // "VCExpress.exe" that we can use to build reliably.
+ // Tell the caller it needs to use MSBuild instead.
+ return "";
+ }
+ // Skip over the cmGlobalVisualStudio8Generator implementation because
+ // we expect a real devenv and do not want to look for VCExpress.
+ return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand();
+}
- // if there are spaces in the makeCommand, assume a full path
- // and convert it to a path with no spaces in it as the
- // RunSingleCommand does not like spaces
- if(makeCommand.find(' ') != std::string::npos)
- {
- cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
- }
- // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
- if(!targetName || strlen(targetName) == 0)
- {
- targetName = "ALL_BUILD";
+bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
+{
+ // Skip this in special cases within our own test suite.
+ if (this->GetPlatformName() == "Test Platform" ||
+ this->GetPlatformToolsetString() == "Test Toolset") {
+ return true;
+ }
+
+ std::string wd;
+ if (!this->ConfiguredFilesPath.empty()) {
+ // In a try-compile we are given the outer CMakeFiles directory.
+ wd = this->ConfiguredFilesPath;
+ } else {
+ wd = this->GetCMakeInstance()->GetHomeOutputDirectory();
+ wd += cmake::GetCMakeFilesDirectory();
+ }
+ wd += "/";
+ wd += cmVersion::GetCMakeVersion();
+
+ // We record the result persistently in a file.
+ std::string const txt = wd + "/VCTargetsPath.txt";
+
+ // If we have a recorded result, use it.
+ {
+ cmsys::ifstream fin(txt.c_str());
+ if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) &&
+ cmSystemTools::FileIsDirectory(this->VCTargetsPath)) {
+ cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
+ return true;
}
- bool clean = false;
- if ( targetName && strcmp(targetName, "clean") == 0 )
- {
- clean = true;
- makeCommand += " ";
- makeCommand += projectName;
- makeCommand += ".sln ";
- makeCommand += "/t:Clean ";
+ }
+
+ // 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());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ // Generate a project file for MSBuild to tell us the VCTargetsPath value.
+ std::string const vcxproj = "VCTargetsPath.vcxproj";
+ {
+ std::string const vcxprojAbs = wd + "/" + vcxproj;
+ 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
}
- else
- {
- std::string targetProject(targetName);
- targetProject += ".vcxproj";
- if (targetProject.find('/') == std::string::npos)
- {
- // it might be in a subdir
- cmVisualStudioSlnParser parser;
- cmSlnData slnData;
- std::string slnFile;
- if (projectDir && *projectDir)
- {
- slnFile = projectDir;
- slnFile += '/';
- slnFile += projectName;
- }
- else
- {
- slnFile = projectName;
- }
- if (parser.ParseFile(slnFile + ".sln", slnData,
- cmVisualStudioSlnParser::DataGroupProjects))
- {
- if (cmSlnProjectEntry const* proj =
- slnData.GetProjectByName(targetName))
- {
- targetProject = proj->GetRelativePath();
- cmSystemTools::ConvertToUnixSlashes(targetProject);
- }
- }
+ xw.StartElement("PropertyGroup");
+ xw.Attribute("Label", "Configuration");
+ xw.StartElement("ConfigurationType");
+ if (this->IsNsightTegra()) {
+ // Tegra-Android platform does not understand "Utility".
+ xw.Content("StaticLibrary");
+ } else {
+ xw.Content("Utility");
}
- makeCommand += " ";
- makeCommand += targetProject;
- makeCommand += " ";
+ 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 */
+ }
+
+ std::vector<std::string> cmd;
+ cmd.push_back(this->GetMSBuildCommand());
+ cmd.push_back(vcxproj);
+ cmd.push_back("/p:Configuration=Debug");
+ cmd.push_back(std::string("/p:VisualStudioVersion=") +
+ this->GetIDEVersion());
+ std::string out;
+ int ret = 0;
+ cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]");
+ if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(),
+ cmSystemTools::OUTPUT_NONE) ||
+ ret != 0 || !regex.find(out)) {
+ cmSystemTools::ReplaceString(out, "\n", "\n ");
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Failed to run MSBuild command:\n"
+ " " << cmd[0] << "\n"
+ "to get the value of VCTargetsPath:\n"
+ " " << out << "\n"
+ ;
+ /* clang-format on */
+ if (ret != 0) {
+ e << "Exit code: " << ret << "\n";
}
- makeCommand += "/p:Configuration=";
- if(config && strlen(config))
- {
- makeCommand += config;
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ this->VCTargetsPath = regex.match(1);
+ cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
+
+ {
+ cmsys::ofstream fout(txt.c_str());
+ fout << this->VCTargetsPath << "\n";
+ }
+ 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)
+{
+ // Select the caller- or user-preferred make program, else MSBuild.
+ std::string makeProgramSelected =
+ this->SelectMakeProgram(makeProgram, this->GetMSBuildCommand());
+
+ // Check if the caller explicitly requested a devenv tool.
+ std::string makeProgramLower = makeProgramSelected;
+ cmSystemTools::LowerCase(makeProgramLower);
+ bool useDevEnv = (makeProgramLower.find("devenv") != std::string::npos ||
+ 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 += "/";
}
- else
- {
- makeCommand += "Debug";
+ slnFile += projectName;
+ slnFile += ".sln";
+ cmVisualStudioSlnParser parser;
+ 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();
+ if (proj.size() > 7 && proj.substr(proj.size() - 7) == ".vfproj") {
+ useDevEnv = true;
+ }
+ }
}
- makeCommand += " /p:VisualStudioVersion=";
- makeCommand += this->GetIDEVersion();
- if ( additionalOptions )
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
+ }
+ if (useDevEnv) {
+ // Use devenv to build solutions containing Intel Fortran projects.
+ cmGlobalVisualStudio7Generator::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, verbose, makeOptions);
+ return;
+ }
+
+ 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";
+ }
+ 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);
+ }
}
- return makeCommand;
+ makeCommand.push_back(targetProject);
+ }
+ std::string configArg = "/p:Configuration=";
+ if (!config.empty()) {
+ configArg += config;
+ } else {
+ configArg += "Debug";
+ }
+ makeCommand.push_back(configArg);
+ makeCommand.push_back(std::string("/p:VisualStudioVersion=") +
+ this->GetIDEVersion());
+ makeCommand.insert(makeCommand.end(), makeOptions.begin(),
+ makeOptions.end());
}
-//----------------------------------------------------------------------------
bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
{
- if(!this->PlatformToolset.empty())
- {
+ if (this->DefaultPlatformToolset == "v100") {
+ // The v100 64-bit toolset does not exist in the express edition.
+ this->DefaultPlatformToolset.clear();
+ }
+ if (this->GetPlatformToolset()) {
return true;
- }
+ }
// This edition does not come with 64-bit tools. Look for them.
//
// TODO: Detect available tools? x64\v100 exists but does not work?
- // KHLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0;VCTargetsPath
+ // HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0;VCTargetsPath
// c:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/Platforms/
// {Itanium,Win32,x64}/PlatformToolsets/{v100,v90,Windows7.1SDK}
std::string winSDK_7_1;
- if(cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\"
- "Windows\\v7.1;InstallationFolder", winSDK_7_1))
- {
- cmOStringStream m;
+ if (cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\"
+ "Windows\\v7.1;InstallationFolder",
+ winSDK_7_1)) {
+ std::ostringstream m;
m << "Found Windows SDK v7.1: " << winSDK_7_1;
mf->DisplayStatus(m.str().c_str(), -1);
- this->PlatformToolset = "Windows7.1SDK";
+ this->DefaultPlatformToolset = "Windows7.1SDK";
return true;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
+ /* clang-format off */
e << "Cannot enable 64-bit tools with Visual Studio 2010 Express.\n"
<< "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());
cmSystemTools::SetFatalErrorOccured();
return false;
- }
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmGlobalVisualStudio10Generator
-::GenerateRuleFile(std::string const& output) const
+std::string cmGlobalVisualStudio10Generator::GenerateRuleFile(
+ std::string const& output) const
{
// The VS 10 generator needs to create the .rule files on disk.
// Hide them away under the CMakeFiles directory.
@@ -378,23 +931,102 @@ cmGlobalVisualStudio10Generator
return ruleFile;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Generator::PathTooLong(
- cmTarget* target, cmSourceFile* sf, std::string const& sfRel)
+void cmGlobalVisualStudio10Generator::PathTooLong(cmGeneratorTarget* target,
+ cmSourceFile const* sf,
+ std::string const& sfRel)
{
- size_t len = (strlen(target->GetMakefile()->GetCurrentOutputDirectory()) +
- 1 + sfRel.length());
- if(len > this->LongestSource.Length)
- {
+ size_t len =
+ (strlen(target->GetLocalGenerator()->GetCurrentBinaryDirectory()) + 1 +
+ sfRel.length());
+ if (len > this->LongestSource.Length) {
this->LongestSource.Length = len;
this->LongestSource.Target = target;
this->LongestSource.SourceFile = sf;
this->LongestSource.SourceRel = sfRel;
- }
+ }
+}
+
+bool cmGlobalVisualStudio10Generator::IsNsightTegra() const
+{
+ return !this->NsightTegraVersion.empty();
+}
+
+std::string cmGlobalVisualStudio10Generator::GetNsightTegraVersion() const
+{
+ return this->NsightTegraVersion;
+}
+
+std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion()
+{
+ std::string version;
+ cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;"
+ "Version",
+ version, cmSystemTools::KeyWOW64_32);
+ return version;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const
+{
+ cmIDEFlagTable const* table = this->ToolsetOptions.GetClFlagTable(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+
+ return (table != CM_NULLPTR) ? table : this->DefaultClFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable()
+ const
+{
+ cmIDEFlagTable const* table = this->ToolsetOptions.GetCSharpFlagTable(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+
+ return (table != CM_NULLPTR) ? table : this->DefaultCSharpFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const
+{
+ cmIDEFlagTable const* table = this->ToolsetOptions.GetRcFlagTable(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+
+ return (table != CM_NULLPTR) ? table : this->DefaultRcFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const
+{
+ cmIDEFlagTable const* table = this->ToolsetOptions.GetLibFlagTable(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+
+ return (table != CM_NULLPTR) ? table : this->DefaultLibFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
+{
+ cmIDEFlagTable const* table = this->ToolsetOptions.GetLinkFlagTable(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+
+ return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
+{
+ return this->DefaultCudaFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
+ const
+{
+ return this->DefaultCudaHostFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
+{
+ cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+
+ return (table != CM_NULLPTR) ? table : this->DefaultMasmFlagTable;
}
-//----------------------------------------------------------------------------
-bool cmGlobalVisualStudio10Generator::UseFolderProperty()
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
{
- return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty();
+ return this->DefaultNasmFlagTable;
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 31e122efe..4a5c2454b 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -1,108 +1,191 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio10Generator_h
#define cmGlobalVisualStudio10Generator_h
#include "cmGlobalVisualStudio8Generator.h"
-
+#include "cmVisualStudio10ToolsetOptions.h"
/** \class cmGlobalVisualStudio10Generator
* \brief Write a Unix makefiles.
*
* cmGlobalVisualStudio10Generator manages UNIX build process for a tree
*/
-class cmGlobalVisualStudio10Generator :
- public cmGlobalVisualStudio8Generator
+class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator
{
public:
- cmGlobalVisualStudio10Generator(const char* name,
- const char* platformName, const char* additionalPlatformDefinition);
+ cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name,
+ const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool SetGeneratorToolset(std::string const& ts);
+ virtual bool MatchesGeneratorName(const std::string& name) const;
- virtual std::string
- GenerateBuildCommand(const char* makeProgram,
- const char *projectName, const char *projectDir,
- const char* additionalOptions, const char *targetName,
- const char* config, bool ignoreErrors, bool);
+ 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);
- virtual void AddPlatformDefinitions(cmMakefile* mf);
+ 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>());
///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
- virtual void Generate();
+ virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
/**
- * Try to determine system infomation such as shared library
+ * 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 EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
virtual void WriteSLNHeader(std::ostream& fout);
- /** Is the installed VS an Express edition? */
- bool IsExpressEdition() const { return this->ExpressEdition; }
+ bool IsCudaEnabled() const { return this->CudaEnabled; }
- /** Is the Microsoft Assembler enabled? */
- bool IsMasmEnabled() const { return this->MasmEnabled; }
+ /** Generating for Nsight Tegra VS plugin? */
+ bool IsNsightTegra() const;
+ std::string GetNsightTegraVersion() const;
/** The toolset name for the target platform. */
- const char* GetPlatformToolset();
+ const char* GetPlatformToolset() const;
+ std::string const& GetPlatformToolsetString() const;
- /**
- * 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();
+ /** The toolset host architecture name (e.g. x64 for 64-bit host tools). */
+ const char* GetPlatformToolsetHostArchitecture() const;
- /**
- * What is the reg key path to "vsmacros" for this version of Visual
- * Studio?
- */
- virtual std::string GetUserMacrosRegKeyBase();
- virtual const char* GetCMakeCFGIntDir() const
- { return "$(Configuration)";}
+ /** The cuda toolset version. */
+ const char* GetPlatformToolsetCuda() const;
+ std::string const& GetPlatformToolsetCudaString() const;
+
+ /** Return whether we need to use No/Debug instead of false/true
+ for GenerateDebugInformation. */
+ bool GetPlatformToolsetNeedsDebugEnum() const
+ {
+ return this->PlatformToolsetNeedsDebugEnum;
+ }
+
+ /** Return the CMAKE_SYSTEM_NAME. */
+ std::string const& GetSystemName() const { return this->SystemName; }
+
+ /** Return the CMAKE_SYSTEM_VERSION. */
+ std::string const& GetSystemVersion() const { return this->SystemVersion; }
+
+ /** Return the Windows version targeted on VS 2015 and above. */
+ std::string const& GetWindowsTargetPlatformVersion() const
+ {
+ return this->WindowsTargetPlatformVersion;
+ }
+
+ /** Return true if building for WindowsCE */
+ bool TargetsWindowsCE() const { return this->SystemIsWindowsCE; }
+
+ /** Return true if building for WindowsPhone */
+ bool TargetsWindowsPhone() const { return this->SystemIsWindowsPhone; }
+
+ /** Return true if building for WindowsStore */
+ bool TargetsWindowsStore() const { return this->SystemIsWindowsStore; }
+
+ virtual const char* GetCMakeCFGIntDir() const { 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;
- void PathTooLong(cmTarget* target, cmSourceFile* sf,
+ void PathTooLong(cmGeneratorTarget* target, cmSourceFile const* sf,
std::string const& sfRel);
virtual const char* GetToolsVersion() { return "4.0"; }
+ bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+
+ static std::string GetInstalledNsightTegraVersion();
+
+ cmIDEFlagTable const* GetClFlagTable() const;
+ cmIDEFlagTable const* GetCSharpFlagTable() const;
+ cmIDEFlagTable const* GetRcFlagTable() const;
+ cmIDEFlagTable const* GetLibFlagTable() const;
+ cmIDEFlagTable const* GetLinkFlagTable() const;
+ cmIDEFlagTable const* GetCudaFlagTable() const;
+ cmIDEFlagTable const* GetCudaHostFlagTable() const;
+ cmIDEFlagTable const* GetMasmFlagTable() const;
+ cmIDEFlagTable const* GetNasmFlagTable() const;
+
protected:
- virtual const char* GetIDEVersion() { return "10.0"; }
+ virtual void Generate();
+ virtual bool InitializeSystem(cmMakefile* mf);
+ virtual bool InitializeWindows(cmMakefile* mf);
+ virtual bool InitializeWindowsCE(cmMakefile* mf);
+ virtual bool InitializeWindowsPhone(cmMakefile* mf);
+ virtual bool InitializeWindowsStore(cmMakefile* mf);
+
+ virtual bool ProcessGeneratorToolsetField(std::string const& key,
+ std::string const& value);
- std::string PlatformToolset;
- bool ExpressEdition;
- bool MasmEnabled;
+ virtual std::string SelectWindowsCEToolset() const;
+ virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
+ virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
- bool UseFolderProperty();
+ virtual const char* GetIDEVersion() { return "10.0"; }
+
+ std::string const& GetMSBuildCommand();
+
+ std::string GeneratorToolset;
+ std::string GeneratorToolsetHostArchitecture;
+ std::string GeneratorToolsetCuda;
+ std::string DefaultPlatformToolset;
+ 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;
+ bool SystemIsWindowsCE;
+ bool SystemIsWindowsPhone;
+ bool SystemIsWindowsStore;
private:
class Factory;
struct LongestSourcePath
{
- LongestSourcePath(): Length(0), Target(0), SourceFile(0) {}
+ LongestSourcePath()
+ : Length(0)
+ , Target(0)
+ , SourceFile(0)
+ {
+ }
size_t Length;
- cmTarget* Target;
- cmSourceFile* SourceFile;
+ cmGeneratorTarget* Target;
+ cmSourceFile const* SourceFile;
std::string SourceRel;
};
LongestSourcePath LongestSource;
+
+ std::string MSBuildCommand;
+ bool MSBuildCommandInitialized;
+ cmVisualStudio10ToolsetOptions ToolsetOptions;
+ virtual std::string FindMSBuildCommand();
+ virtual std::string FindDevEnvCommand();
+ virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); }
+
+ bool PlatformToolsetNeedsDebugEnum;
+
+ bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
+
+ std::string VCTargetsPath;
+ bool FindVCTargetsPath(cmMakefile* mf);
+
+ bool CudaEnabled;
+
+ // We do not use the reload macros for VS >= 10.
+ virtual std::string GetUserMacrosDirectory() { return ""; }
};
#endif
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 8ae733165..d37d4b095 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -1,150 +1,218 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio11Generator.h"
+
+#include "cmAlgorithms.h"
+#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";
+static const char vs11generatorName[] = "Visual Studio 11 2012";
+
+// Map generator name without year to name with year.
+static const char* cmVS11GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs11generatorName,
+ sizeof(vs11generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs11generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2012")) {
+ p += 5;
+ }
+ genName = std::string(vs11generatorName) + p;
+ return p;
+}
class cmGlobalVisualStudio11Generator::Factory
: public cmGlobalGeneratorFactory
{
public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(strstr(name, vs11generatorName) != name)
- {
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE
+ {
+ std::string genName;
+ const char* p = cmVS11GenName(name, genName);
+ if (!p) {
return 0;
- }
-
- const char* p = name + sizeof(vs11generatorName) - 1;
- if(p[0] == '\0')
- {
- return new cmGlobalVisualStudio11Generator(
- name, NULL, NULL);
- }
-
- if(p[0] != ' ')
- {
+ }
+ if (!*p) {
+ return new cmGlobalVisualStudio11Generator(cm, genName, "");
+ }
+ if (*p++ != ' ') {
return 0;
- }
-
- ++p;
-
- if(!strcmp(p, "ARM"))
- {
- return new cmGlobalVisualStudio11Generator(
- name, "ARM", NULL);
- }
-
- if(!strcmp(p, "Win64"))
- {
- return new cmGlobalVisualStudio11Generator(
- name, "x64", "CMAKE_FORCE_WIN64");
- }
+ }
+ if (strcmp(p, "Win64") == 0) {
+ return new cmGlobalVisualStudio11Generator(cm, genName, "x64");
+ }
+ if (strcmp(p, "ARM") == 0) {
+ return new cmGlobalVisualStudio11Generator(cm, genName, "ARM");
+ }
std::set<std::string> installedSDKs =
cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
- if(installedSDKs.find(p) == installedSDKs.end())
- {
+ if (installedSDKs.find(p) == installedSDKs.end()) {
return 0;
- }
+ }
cmGlobalVisualStudio11Generator* ret =
- new cmGlobalVisualStudio11Generator(name, p, NULL);
+ new cmGlobalVisualStudio11Generator(cm, name, p);
ret->WindowsCEVersion = "8.00";
return ret;
}
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- entry.Name = "Visual Studio 11";
- entry.Brief = "Generates Visual Studio 11 (2012) project files.";
- entry.Full =
- "It is possible to append a space followed by the platform name "
- "to create project files for a specific target platform. E.g. "
- "\"Visual Studio 11 Win64\" will create project files for "
- "the x64 processor; \"Visual Studio 11 ARM\" for ARM.";
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ {
+ entry.Name = std::string(vs11generatorName) + " [arch]";
+ entry.Brief = "Generates Visual Studio 2012 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\".";
}
- virtual void GetGenerators(std::vector<std::string>& names) const {
+ void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ {
names.push_back(vs11generatorName);
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("Visual Studio 11 " + *i);
- }
+ for (std::set<std::string>::const_iterator i = installedSDKs.begin();
+ i != installedSDKs.end(); ++i) {
+ names.push_back(std::string(vs11generatorName) + " " + *i);
+ }
}
+
+ bool SupportsToolset() const CM_OVERRIDE { return true; }
+ bool SupportsPlatform() const CM_OVERRIDE { return true; }
};
-//----------------------------------------------------------------------------
cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory()
{
return new Factory;
}
-//----------------------------------------------------------------------------
cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
- const char* name, const char* platformName,
- const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio10Generator(name, platformName,
- additionalPlatformDefinition)
+ cmake* cm, const std::string& name, const std::string& platformName)
+ : cmGlobalVisualStudio10Generator(cm, name, platformName)
{
- this->FindMakeProgramFile = "CMakeVS11FindMake.cmake";
std::string vc11Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\11.0\\Setup\\VC;"
- "ProductDir", vc11Express, cmSystemTools::KeyWOW64_32);
- this->PlatformToolset = "v110";
+ "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->Version = VS11;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout)
+bool cmGlobalVisualStudio11Generator::MatchesGeneratorName(
+ const std::string& name) const
{
- fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- if (this->ExpressEdition)
- {
- fout << "# Visual Studio Express 2012 for Windows Desktop\n";
+ std::string genName;
+ if (cmVS11GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf)
+{
+ if (!this->SelectWindowsPhoneToolset(this->DefaultPlatformToolset)) {
+ std::ostringstream e;
+ if (this->DefaultPlatformToolset.empty()) {
+ e << this->GetName() << " supports Windows Phone '8.0', 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";
}
- else
- {
- fout << "# Visual Studio 2012\n";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ return true;
+}
+
+bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf)
+{
+ if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
+ std::ostringstream e;
+ if (this->DefaultPlatformToolset.empty()) {
+ e << this->GetName() << " supports Windows Store '8.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());
+ return false;
+ }
+ return true;
+}
+
+bool cmGlobalVisualStudio11Generator::SelectWindowsPhoneToolset(
+ std::string& toolset) const
+{
+ if (this->SystemVersion == "8.0") {
+ if (this->IsWindowsPhoneToolsetInstalled() &&
+ this->IsWindowsDesktopToolsetInstalled()) {
+ toolset = "v110_wp80";
+ return true;
+ } else {
+ return false;
}
+ }
+ return this->cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
+ toolset);
}
-//----------------------------------------------------------------------------
-cmLocalGenerator *cmGlobalVisualStudio11Generator::CreateLocalGenerator()
+bool cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset(
+ std::string& toolset) const
{
- cmLocalVisualStudio10Generator* lg =
- new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS11);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetGlobalGenerator(this);
- return lg;
+ if (this->SystemVersion == "8.0") {
+ if (this->IsWindowsStoreToolsetInstalled() &&
+ this->IsWindowsDesktopToolsetInstalled()) {
+ toolset = "v110";
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return this->cmGlobalVisualStudio10Generator::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()
{
- // Intentionally skip over the parent class implementation and call the
- // grand-parent class's implementation. Folders are not supported by the
- // Express editions in VS10 and earlier, but they are in VS11 Express.
- return cmGlobalVisualStudio8Generator::UseFolderProperty();
+ // Intentionally skip up to the top-level class implementation.
+ // Folders are not supported by the Express editions in VS10 and earlier,
+ // but they are in VS11 Express and above.
+ return cmGlobalGenerator::UseFolderProperty();
}
-//----------------------------------------------------------------------------
std::set<std::string>
cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs()
{
@@ -156,23 +224,68 @@ 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::vector<std::string>::const_iterator i = subkeys.begin();
+ i != subkeys.end(); ++i) {
std::string key = sdksKey;
key += '\\';
key += *i;
key += ';';
std::string path;
- if(cmSystemTools::ReadRegistryValue(key.c_str(),
- path,
- cmSystemTools::KeyWOW64_32) &&
- !path.empty())
- {
+ if (cmSystemTools::ReadRegistryValue(key.c_str(), path,
+ cmSystemTools::KeyWOW64_32) &&
+ !path.empty()) {
ret.insert(*i);
- }
}
+ }
return ret;
}
+
+bool cmGlobalVisualStudio11Generator::NeedsDeploy(
+ cmStateEnums::TargetType type) const
+{
+ if ((type == cmStateEnums::EXECUTABLE ||
+ type == cmStateEnums::SHARED_LIBRARY) &&
+ (this->SystemIsWindowsPhone || this->SystemIsWindowsStore)) {
+ return true;
+ }
+ return cmGlobalVisualStudio10Generator::NeedsDeploy(type);
+}
+
+bool cmGlobalVisualStudio11Generator::IsWindowsDesktopToolsetInstalled() const
+{
+ const char desktop80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "VisualStudio\\11.0\\VC\\Libraries\\Extended";
+ const char VS2012DesktopExpressKey[] =
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "WDExpress\\11.0;InstallDir";
+
+ std::vector<std::string> subkeys;
+ std::string path;
+ return cmSystemTools::ReadRegistryValue(VS2012DesktopExpressKey, path,
+ cmSystemTools::KeyWOW64_32) ||
+ cmSystemTools::GetRegistrySubKeys(desktop80Key, subkeys,
+ cmSystemTools::KeyWOW64_32);
+}
+
+bool cmGlobalVisualStudio11Generator::IsWindowsPhoneToolsetInstalled() const
+{
+ const char wp80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "Microsoft SDKs\\WindowsPhone\\v8.0\\"
+ "Install Path;Install Path";
+
+ std::string path;
+ cmSystemTools::ReadRegistryValue(wp80Key, path, cmSystemTools::KeyWOW64_32);
+ return !path.empty();
+}
+
+bool cmGlobalVisualStudio11Generator::IsWindowsStoreToolsetInstalled() const
+{
+ const char win80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "VisualStudio\\11.0\\VC\\Libraries\\Core\\Arm";
+
+ std::vector<std::string> subkeys;
+ return cmSystemTools::GetRegistrySubKeys(win80Key, subkeys,
+ cmSystemTools::KeyWOW64_32);
+}
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index 7cc7e69d9..b4b327d8a 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -1,40 +1,55 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio11Generator_h
#define cmGlobalVisualStudio11Generator_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <set>
+#include <string>
+
#include "cmGlobalVisualStudio10Generator.h"
+#include "cmStateTypes.h"
+class cmGlobalGeneratorFactory;
+class cmMakefile;
+class cmake;
/** \class cmGlobalVisualStudio11Generator */
-class cmGlobalVisualStudio11Generator:
- public cmGlobalVisualStudio10Generator
+class cmGlobalVisualStudio11Generator : public cmGlobalVisualStudio10Generator
{
public:
- cmGlobalVisualStudio11Generator(const char* name,
- const char* platformName, const char* additionalPlatformDefinition);
+ cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name,
+ const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual void WriteSLNHeader(std::ostream& fout);
+ virtual bool MatchesGeneratorName(const std::string& name) const;
- ///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual void WriteSLNHeader(std::ostream& fout);
- /** TODO: VS 11 user macro support. */
- virtual std::string GetUserMacrosDirectory() { return ""; }
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;
+
+ // 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 IsWindowsPhoneToolsetInstalled() const;
+ bool IsWindowsStoreToolsetInstalled() const;
+
virtual const char* GetIDEVersion() { return "11.0"; }
bool UseFolderProperty();
static std::set<std::string> GetInstalledWindowsCESDKs();
+
+ /** Return true if the configuration needs to be deployed */
+ virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
+
private:
class Factory;
friend class Factory;
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index c56dfff15..de62ff0ac 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -1,102 +1,232 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio12Generator.h"
+
+#include "cmAlgorithms.h"
+#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";
-static const char vs12Win32generatorName[] = "Visual Studio 12";
-static const char vs12Win64generatorName[] = "Visual Studio 12 Win64";
-static const char vs12ARMgeneratorName[] = "Visual Studio 12 ARM";
+// Map generator name without year to name with year.
+static const char* cmVS12GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs12generatorName,
+ sizeof(vs12generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs12generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2013")) {
+ p += 5;
+ }
+ genName = std::string(vs12generatorName) + p;
+ return p;
+}
class cmGlobalVisualStudio12Generator::Factory
: public cmGlobalGeneratorFactory
{
public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(!strcmp(name, vs12Win32generatorName))
- {
- return new cmGlobalVisualStudio12Generator(
- name, NULL, NULL);
- }
- if(!strcmp(name, vs12Win64generatorName))
- {
- return new cmGlobalVisualStudio12Generator(
- name, "x64", "CMAKE_FORCE_WIN64");
- }
- if(!strcmp(name, vs12ARMgeneratorName))
- {
- return new cmGlobalVisualStudio12Generator(
- name, "ARM", NULL);
- }
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE
+ {
+ std::string genName;
+ const char* p = cmVS12GenName(name, genName);
+ if (!p) {
+ return 0;
+ }
+ if (!*p) {
+ return new cmGlobalVisualStudio12Generator(cm, genName, "");
+ }
+ if (*p++ != ' ') {
+ return 0;
+ }
+ if (strcmp(p, "Win64") == 0) {
+ return new cmGlobalVisualStudio12Generator(cm, genName, "x64");
+ }
+ if (strcmp(p, "ARM") == 0) {
+ return new cmGlobalVisualStudio12Generator(cm, genName, "ARM");
+ }
return 0;
}
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- entry.Name = "Visual Studio 12";
- entry.Brief = "Generates Visual Studio 12 (2013) project files.";
- entry.Full =
- "It is possible to append a space followed by the platform name "
- "to create project files for a specific target platform. E.g. "
- "\"Visual Studio 12 Win64\" will create project files for "
- "the x64 processor; \"Visual Studio 12 ARM\" for ARM.";
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ {
+ entry.Name = std::string(vs12generatorName) + " [arch]";
+ entry.Brief = "Generates Visual Studio 2013 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\".";
}
- virtual void GetGenerators(std::vector<std::string>& names) const {
- names.push_back(vs12Win32generatorName);
- names.push_back(vs12Win64generatorName);
- names.push_back(vs12ARMgeneratorName); }
+ void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ {
+ names.push_back(vs12generatorName);
+ names.push_back(vs12generatorName + std::string(" ARM"));
+ names.push_back(vs12generatorName + std::string(" Win64"));
+ }
+
+ bool SupportsToolset() const CM_OVERRIDE { return true; }
+ bool SupportsPlatform() const CM_OVERRIDE { return true; }
};
-//----------------------------------------------------------------------------
cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory()
{
return new Factory;
}
-//----------------------------------------------------------------------------
cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
- const char* name, const char* platformName,
- const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio11Generator(name, platformName,
- additionalPlatformDefinition)
+ cmake* cm, const std::string& name, const std::string& platformName)
+ : cmGlobalVisualStudio11Generator(cm, name, platformName)
{
- this->FindMakeProgramFile = "CMakeVS12FindMake.cmake";
std::string vc12Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\12.0\\Setup\\VC;"
- "ProductDir", vc12Express, cmSystemTools::KeyWOW64_32);
- this->PlatformToolset = "v120";
+ "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->Version = VS12;
+}
+
+bool cmGlobalVisualStudio12Generator::MatchesGeneratorName(
+ const std::string& name) const
+{
+ std::string genName;
+ if (cmVS12GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField(
+ std::string const& key, std::string const& value)
+{
+ if (key == "host" && value == "x64") {
+ this->GeneratorToolsetHostArchitecture = "x64";
+ return true;
+ }
+ return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField(
+ key, value);
+}
+
+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 '"
+ << 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());
+ return false;
+ }
+ return true;
+}
+
+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 '"
+ << 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());
+ return false;
+ }
+ return true;
+}
+
+bool cmGlobalVisualStudio12Generator::SelectWindowsPhoneToolset(
+ std::string& toolset) const
+{
+ if (this->SystemVersion == "8.1") {
+ if (this->IsWindowsPhoneToolsetInstalled() &&
+ this->IsWindowsDesktopToolsetInstalled()) {
+ toolset = "v120_wp81";
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return this->cmGlobalVisualStudio11Generator::SelectWindowsPhoneToolset(
+ toolset);
+}
+
+bool cmGlobalVisualStudio12Generator::SelectWindowsStoreToolset(
+ std::string& toolset) const
+{
+ if (this->SystemVersion == "8.1") {
+ if (this->IsWindowsStoreToolsetInstalled() &&
+ this->IsWindowsDesktopToolsetInstalled()) {
+ toolset = "v120";
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return this->cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset(
+ toolset);
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout)
{
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- if (this->ExpressEdition)
- {
+ if (this->ExpressEdition) {
fout << "# Visual Studio Express 2013 for Windows Desktop\n";
- }
- else
- {
+ } else {
fout << "# Visual Studio 2013\n";
- }
+ }
+}
+
+bool cmGlobalVisualStudio12Generator::IsWindowsDesktopToolsetInstalled() const
+{
+ const char desktop81Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "VisualStudio\\12.0\\VC\\LibraryDesktop";
+
+ std::vector<std::string> subkeys;
+ return cmSystemTools::GetRegistrySubKeys(desktop81Key, subkeys,
+ cmSystemTools::KeyWOW64_32);
}
-//----------------------------------------------------------------------------
-cmLocalGenerator *cmGlobalVisualStudio12Generator::CreateLocalGenerator()
+bool cmGlobalVisualStudio12Generator::IsWindowsPhoneToolsetInstalled() const
{
- cmLocalVisualStudio10Generator* lg =
- new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS12);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetGlobalGenerator(this);
- return lg;
+ const char wp81Key[] =
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "Microsoft SDKs\\WindowsPhone\\v8.1\\Install Path;Install Path";
+
+ std::string path;
+ cmSystemTools::ReadRegistryValue(wp81Key, path, cmSystemTools::KeyWOW64_32);
+ return !path.empty();
+}
+
+bool cmGlobalVisualStudio12Generator::IsWindowsStoreToolsetInstalled() const
+{
+ const char win81Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "VisualStudio\\12.0\\VC\\Libraries\\Core\\Arm";
+
+ std::vector<std::string> subkeys;
+ return cmSystemTools::GetRegistrySubKeys(win81Key, subkeys,
+ cmSystemTools::KeyWOW64_32);
}
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index 8c8aeb1fd..ebc95bb63 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -1,42 +1,52 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio12Generator_h
#define cmGlobalVisualStudio12Generator_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+
#include "cmGlobalVisualStudio11Generator.h"
+class cmGlobalGeneratorFactory;
+class cmMakefile;
+class cmake;
/** \class cmGlobalVisualStudio12Generator */
-class cmGlobalVisualStudio12Generator:
- public cmGlobalVisualStudio11Generator
+class cmGlobalVisualStudio12Generator : public cmGlobalVisualStudio11Generator
{
public:
- cmGlobalVisualStudio12Generator(const char* name,
- const char* platformName, const char* additionalPlatformDefinition);
+ cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name,
+ const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual void WriteSLNHeader(std::ostream& fout);
-
- ///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual bool MatchesGeneratorName(const std::string& name) const;
- /** TODO: VS 12 user macro support. */
- virtual std::string GetUserMacrosDirectory() { return ""; }
+ virtual void WriteSLNHeader(std::ostream& fout);
- //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
+ // 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:
+ bool ProcessGeneratorToolsetField(std::string const& key,
+ std::string const& value) CM_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;
+
+ // 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 IsWindowsPhoneToolsetInstalled() const;
+ bool IsWindowsStoreToolsetInstalled() const;
virtual const char* GetIDEVersion() { return "12.0"; }
private:
class Factory;
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
new file mode 100644
index 000000000..c8cf02cdd
--- /dev/null
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -0,0 +1,287 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalVisualStudio14Generator.h"
+
+#include "cmAlgorithms.h"
+#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";
+
+// Map generator name without year to name with year.
+static const char* cmVS14GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs14generatorName,
+ sizeof(vs14generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs14generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2015")) {
+ p += 5;
+ }
+ genName = std::string(vs14generatorName) + p;
+ return p;
+}
+
+class cmGlobalVisualStudio14Generator::Factory
+ : public cmGlobalGeneratorFactory
+{
+public:
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE
+ {
+ std::string genName;
+ const char* p = cmVS14GenName(name, genName);
+ if (!p) {
+ return 0;
+ }
+ if (!*p) {
+ return new cmGlobalVisualStudio14Generator(cm, genName, "");
+ }
+ if (*p++ != ' ') {
+ return 0;
+ }
+ if (strcmp(p, "Win64") == 0) {
+ return new cmGlobalVisualStudio14Generator(cm, genName, "x64");
+ }
+ if (strcmp(p, "ARM") == 0) {
+ return new cmGlobalVisualStudio14Generator(cm, genName, "ARM");
+ }
+ return 0;
+ }
+
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_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
+ {
+ names.push_back(vs14generatorName);
+ names.push_back(vs14generatorName + std::string(" ARM"));
+ names.push_back(vs14generatorName + std::string(" Win64"));
+ }
+
+ bool SupportsToolset() const CM_OVERRIDE { return true; }
+ bool SupportsPlatform() const CM_OVERRIDE { return true; }
+};
+
+cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory()
+{
+ return new Factory;
+}
+
+cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(
+ cmake* cm, const std::string& name, const std::string& platformName)
+ : cmGlobalVisualStudio12Generator(cm, name, platformName)
+{
+ std::string vc14Express;
+ this->ExpressEdition = cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\14.0\\Setup\\VC;"
+ "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->Version = VS14;
+}
+
+bool cmGlobalVisualStudio14Generator::MatchesGeneratorName(
+ const std::string& name) const
+{
+ std::string genName;
+ if (cmVS14GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudio14Generator::InitializeWindows(cmMakefile* mf)
+{
+ if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
+ return this->SelectWindows10SDK(mf, false);
+ }
+ return true;
+}
+
+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 '"
+ << 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());
+ return false;
+ }
+ if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
+ return this->SelectWindows10SDK(mf, true);
+ }
+ return true;
+}
+
+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::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());
+ return false;
+ }
+ mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION",
+ this->WindowsTargetPlatformVersion.c_str());
+ return true;
+}
+
+bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
+ std::string& toolset) const
+{
+ if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
+ if (this->IsWindowsStoreToolsetInstalled() &&
+ this->IsWindowsDesktopToolsetInstalled()) {
+ toolset = "v140";
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return this->cmGlobalVisualStudio12Generator::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\\"
+ "VisualStudio\\14.0\\VC\\Runtimes";
+
+ std::vector<std::string> vc14;
+ return cmSystemTools::GetRegistrySubKeys(desktop10Key, vc14,
+ cmSystemTools::KeyWOW64_32);
+}
+
+bool cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const
+{
+ const char universal10Key[] =
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "VisualStudio\\14.0\\Setup\\Build Tools for Windows 10;SrcPath";
+
+ std::string win10SDK;
+ return cmSystemTools::ReadRegistryValue(universal10Key, win10SDK,
+ cmSystemTools::KeyWOW64_32);
+}
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+struct NoWindowsH
+{
+ bool operator()(std::string const& p)
+ {
+ return !cmSystemTools::FileExists(p + "/um/windows.h", true);
+ }
+};
+#endif
+
+std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ std::vector<std::string> win10Roots;
+
+ {
+ std::string win10Root;
+ if (cmSystemTools::GetEnv("CMAKE_WINDOWS_KITS_10_DIR", win10Root)) {
+ cmSystemTools::ConvertToUnixSlashes(win10Root);
+ win10Roots.push_back(win10Root);
+ }
+ }
+
+ {
+ // This logic is taken from the vcvarsqueryregistry.bat file from VS2015
+ // Try HKLM and then HKCU.
+ std::string win10Root;
+ if (cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "Windows Kits\\Installed Roots;KitsRoot10",
+ win10Root, cmSystemTools::KeyWOW64_32) ||
+ cmSystemTools::ReadRegistryValue(
+ "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
+ "Windows Kits\\Installed Roots;KitsRoot10",
+ win10Root, cmSystemTools::KeyWOW64_32)) {
+ cmSystemTools::ConvertToUnixSlashes(win10Root);
+ win10Roots.push_back(win10Root);
+ }
+ }
+
+ if (win10Roots.empty()) {
+ return std::string();
+ }
+
+ 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/*";
+ cmSystemTools::GlobDirs(path, sdks);
+ }
+
+ // Skip SDKs that do not contain <um/windows.h> because that indicates that
+ // 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);
+ }
+
+ // 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;
+ }
+ }
+
+ // Use the latest Windows 10 SDK since the exact version is not available.
+ return sdks.at(0);
+ }
+#endif
+ // Return an empty string
+ return std::string();
+}
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
new file mode 100644
index 000000000..0ce9a5641
--- /dev/null
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -0,0 +1,51 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGlobalVisualStudio14Generator_h
+#define cmGlobalVisualStudio14Generator_h
+
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+
+#include "cmGlobalVisualStudio12Generator.h"
+
+class cmGlobalGeneratorFactory;
+class cmMakefile;
+class cmake;
+
+/** \class cmGlobalVisualStudio14Generator */
+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);
+
+ 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;
+
+ // 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"; }
+ virtual bool SelectWindows10SDK(cmMakefile* mf, bool required);
+
+ // Used to verify that the Desktop toolset for the current generator is
+ // installed on the machine.
+ virtual bool IsWindowsDesktopToolsetInstalled() const;
+
+ std::string GetWindows10SDKVersion();
+
+private:
+ class Factory;
+};
+#endif
diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx
new file mode 100644
index 000000000..ce1ba007f
--- /dev/null
+++ b/Source/cmGlobalVisualStudio15Generator.cxx
@@ -0,0 +1,206 @@
+/* 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
new file mode 100644
index 000000000..4be88f44f
--- /dev/null
+++ b/Source/cmGlobalVisualStudio15Generator.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 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/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx
deleted file mode 100644
index b3fabdade..000000000
--- a/Source/cmGlobalVisualStudio6Generator.cxx
+++ /dev/null
@@ -1,421 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmGlobalVisualStudio6Generator.h"
-#include "cmLocalVisualStudio6Generator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-#include "cmGeneratedFileStream.h"
-
-// Utility function to make a valid VS6 *.dsp filename out
-// of a CMake target name:
-//
-std::string GetVS6TargetName(const std::string& targetName)
-{
- std::string name(targetName);
-
- // Eliminate hyphens. VS6 cannot handle hyphens in *.dsp filenames...
- // Replace them with underscores.
- //
- cmSystemTools::ReplaceString(name, "-", "_");
-
- return name;
-}
-
-cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator()
-{
- this->FindMakeProgramFile = "CMakeVS6FindMake.cmake";
-}
-
-void cmGlobalVisualStudio6Generator
-::EnableLanguage(std::vector<std::string>const& lang,
- cmMakefile *mf,
- bool optional)
-{
- cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
- mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- this->GenerateConfigurations(mf);
- this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
-}
-
-void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf)
-{
- std::string fname= mf->GetRequiredDefinition("CMAKE_ROOT");
- const char* def= mf->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
- if(def)
- {
- fname = def;
- }
- else
- {
- fname += "/Templates";
- }
- fname += "/CMakeVisualStudio6Configurations.cmake";
- if(!mf->ReadListFile(mf->GetCurrentListFile(), fname.c_str()))
- {
- cmSystemTools::Error("Cannot open ", fname.c_str(),
- ". Please copy this file from the main "
- "CMake/Templates directory and edit it for "
- "your build configurations.");
- }
- else if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
- {
- cmSystemTools::Error("CMAKE_CONFIGURATION_TYPES not set by ",
- fname.c_str(),
- ". Please copy this file from the main "
- "CMake/Templates directory and edit it for "
- "your build configurations.");
- }
-}
-
-std::string cmGlobalVisualStudio6Generator
-::GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
- const char *projectDir,
- const char* additionalOptions,
- const char *targetName,
- const char* config,
- bool ignoreErrors,
- bool)
-{
- // Visual studio 6 doesn't need project dir
- (void) projectDir;
- // Ingoring errors is not implemented in visual studio 6
- (void) ignoreErrors;
-
- // now build the test
- std::vector<std::string> mp;
- mp.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio"
- "\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
- cmSystemTools::ExpandRegistryValues(mp[0]);
- std::string originalCommand = makeProgram;
- std::string makeCommand =
- cmSystemTools::FindProgram(makeProgram, mp);
- if(makeCommand.size() == 0)
- {
- std::string e = "Generator cannot find Visual Studio 6 msdev program \"";
- e += originalCommand;
- e += "\" specified by CMAKE_MAKE_PROGRAM cache entry. ";
- e += "Please fix the setting.";
- cmSystemTools::Error(e.c_str());
- return "";
- }
- makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand.c_str());
-
- // if there are spaces in the makeCommand, assume a full path
- // and convert it to a path with no spaces in it as the
- // RunSingleCommand does not like spaces
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if(makeCommand.find(' ') != std::string::npos)
- {
- cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
- }
-#endif
- makeCommand += " ";
- makeCommand += projectName;
- makeCommand += ".dsw /MAKE \"";
- bool clean = false;
- if ( targetName && strcmp(targetName, "clean") == 0 )
- {
- clean = true;
- targetName = "ALL_BUILD";
- }
- if (targetName && strlen(targetName))
- {
- makeCommand += targetName;
- }
- else
- {
- makeCommand += "ALL_BUILD";
- }
- makeCommand += " - ";
- if(config && strlen(config))
- {
- makeCommand += config;
- }
- else
- {
- makeCommand += "Debug";
- }
- if(clean)
- {
- makeCommand += "\" /CLEAN";
- }
- else
- {
- makeCommand += "\" /BUILD";
- }
- if ( additionalOptions )
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
- }
- return makeCommand;
-}
-
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio6Generator::CreateLocalGenerator()
-{
- cmLocalGenerator *lg = new cmLocalVisualStudio6Generator;
- lg->SetGlobalGenerator(this);
- return lg;
-}
-
-
-void cmGlobalVisualStudio6Generator::Generate()
-{
- // first do the superclass method
- this->cmGlobalVisualStudioGenerator::Generate();
-
- // Now write out the DSW
- this->OutputDSWFile();
-}
-
-// Write a DSW file to the stream
-void cmGlobalVisualStudio6Generator
-::WriteDSWFile(std::ostream& fout,cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
-{
- // Write out the header for a DSW file
- this->WriteDSWHeader(fout);
-
- // 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 orderedProjectTargets(projectTargets);
-
- for(OrderedTargetDependSet::const_iterator
- tt = orderedProjectTargets.begin();
- tt != orderedProjectTargets.end(); ++tt)
- {
- cmTarget* target = *tt;
- // Write the project into the DSW file
- const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
- if(expath)
- {
- std::string project = target->GetName();
- std::string location = expath;
- this->WriteExternalProject(fout, project.c_str(),
- location.c_str(), target->GetUtilities());
- }
- else
- {
- std::string dspname = GetVS6TargetName(target->GetName());
- std::string dir = target->GetMakefile()->GetStartOutputDirectory();
- dir = root->Convert(dir.c_str(), cmLocalGenerator::START_OUTPUT);
- this->WriteProject(fout, dspname.c_str(), dir.c_str(), *target);
- }
- }
-
- // Write the footer for the DSW file
- this->WriteDSWFooter(fout);
-}
-
-void cmGlobalVisualStudio6Generator
-::OutputDSWFile(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
-{
- if(generators.size() == 0)
- {
- return;
- }
- std::string fname = root->GetMakefile()->GetStartOutputDirectory();
- fname += "/";
- fname += root->GetMakefile()->GetProjectName();
- fname += ".dsw";
- std::ofstream fout(fname.c_str());
- if(!fout)
- {
- cmSystemTools::Error("Error can not open DSW file for write: ",
- fname.c_str());
- cmSystemTools::ReportLastSystemError("");
- return;
- }
- this->WriteDSWFile(fout, root, generators);
-}
-
-// output the DSW file
-void cmGlobalVisualStudio6Generator::OutputDSWFile()
-{
- std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
- for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
- {
- this->OutputDSWFile(it->second[0], it->second);
- }
-}
-
-// Write a dsp file into the DSW file,
-// Note, that dependencies from executables to
-// the libraries it uses are also done here
-void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout,
- const char* dspname,
- const char* dir,
- cmTarget& target)
-{
- fout << "#########################################################"
- "######################\n\n";
- fout << "Project: \"" << dspname << "\"="
- << dir << "\\" << dspname << ".dsp - Package Owner=<4>\n\n";
- fout << "Package=<5>\n{{{\n}}}\n\n";
- fout << "Package=<4>\n";
- fout << "{{{\n";
- VSDependSet const& depends = this->VSTargetDepends[&target];
- for(VSDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di)
- {
- const char* name = di->c_str();
- fout << "Begin Project Dependency\n";
- fout << "Project_Dep_Name " << GetVS6TargetName(name) << "\n";
- fout << "End Project Dependency\n";
- }
- fout << "}}}\n\n";
-
- UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
- if(ui != this->UtilityDepends.end())
- {
- const char* uname = ui->second.c_str();
- fout << "Project: \"" << uname << "\"="
- << dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n";
- fout <<
- "Package=<5>\n{{{\n}}}\n\n"
- "Package=<4>\n"
- "{{{\n"
- "Begin Project Dependency\n"
- "Project_Dep_Name " << dspname << "\n"
- "End Project Dependency\n"
- "}}}\n\n";
- ;
- }
-}
-
-
-// Write a dsp file into the DSW file,
-// Note, that dependencies from executables to
-// the libraries it uses are also done here
-void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream& fout,
- const char* name,
- const char* location,
- const std::set<cmStdString>& dependencies)
-{
- fout << "#########################################################"
- "######################\n\n";
- fout << "Project: \"" << name << "\"="
- << location << " - Package Owner=<4>\n\n";
- fout << "Package=<5>\n{{{\n}}}\n\n";
- fout << "Package=<4>\n";
- fout << "{{{\n";
-
-
- std::set<cmStdString>::const_iterator i, end;
- // write dependencies.
- i = dependencies.begin();
- end = dependencies.end();
- for(;i!= end; ++i)
- {
- fout << "Begin Project Dependency\n";
- fout << "Project_Dep_Name " << GetVS6TargetName(*i) << "\n";
- fout << "End Project Dependency\n";
- }
- fout << "}}}\n\n";
-}
-
-
-
-// Standard end of dsw file
-void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream& fout)
-{
- fout << "######################################################"
- "#########################\n\n";
- fout << "Global:\n\n";
- fout << "Package=<5>\n{{{\n}}}\n\n";
- fout << "Package=<3>\n{{{\n}}}\n\n";
- fout << "#####################################################"
- "##########################\n\n";
-}
-
-
-// ouput standard header for dsw file
-void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream& fout)
-{
- fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
- fout << "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n";
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget* target)
-{
- std::string pname = target->GetName();
- pname += "_UTILITY";
- pname = GetVS6TargetName(pname.c_str());
- std::string fname = target->GetMakefile()->GetStartOutputDirectory();
- fname += "/";
- fname += pname;
- fname += ".dsp";
- cmGeneratedFileStream fout(fname.c_str());
- fout.SetCopyIfDifferent(true);
- fout <<
- "# Microsoft Developer Studio Project File - Name=\""
- << pname << "\" - Package Owner=<4>\n"
- "# Microsoft Developer Studio Generated Build File, Format Version 6.00\n"
- "# ** DO NOT EDIT **\n"
- "\n"
- "# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n"
- "\n"
- "CFG=" << pname << " - Win32 Debug\n"
- "!MESSAGE \"" << pname << " - Win32 Debug\""
- " (based on \"Win32 (x86) Generic Project\")\n"
- "!MESSAGE \"" << pname << " - Win32 Release\" "
- "(based on \"Win32 (x86) Generic Project\")\n"
- "!MESSAGE \"" << pname << " - Win32 MinSizeRel\" "
- "(based on \"Win32 (x86) Generic Project\")\n"
- "!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" "
- "(based on \"Win32 (x86) Generic Project\")\n"
- "\n"
- "# Begin Project\n"
- "# Begin Target\n"
- "# Name \"" << pname << " - Win32 Debug\"\n"
- "# Name \"" << pname << " - Win32 Release\"\n"
- "# Name \"" << pname << " - Win32 MinSizeRel\"\n"
- "# Name \"" << pname << " - Win32 RelWithDebInfo\"\n"
- "# End Target\n"
- "# End Project\n"
- ;
- return pname;
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio6Generator
-::GetDocumentation(cmDocumentationEntry& entry)
-{
- entry.Name = cmGlobalVisualStudio6Generator::GetActualName();
- entry.Brief = "Generates Visual Studio 6 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudio6Generator
-::AppendDirectoryForConfig(const char* prefix,
- const char* config,
- const char* suffix,
- std::string& dir)
-{
- if(config)
- {
- dir += prefix;
- dir += config;
- dir += suffix;
- }
-}
diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h
deleted file mode 100644
index 6bd39ca9a..000000000
--- a/Source/cmGlobalVisualStudio6Generator.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmGlobalVisualStudio6Generator_h
-#define cmGlobalVisualStudio6Generator_h
-
-#include "cmGlobalVisualStudioGenerator.h"
-#include "cmGlobalGeneratorFactory.h"
-
-class cmTarget;
-
-/** \class cmGlobalVisualStudio6Generator
- * \brief Write a Unix makefiles.
- *
- * cmGlobalVisualStudio6Generator manages UNIX build process for a tree
- */
-class cmGlobalVisualStudio6Generator : public cmGlobalVisualStudioGenerator
-{
-public:
- cmGlobalVisualStudio6Generator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalVisualStudio6Generator>(); }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio6Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 6";}
-
- /** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
-
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
- /**
- * Try to determine system infomation such as shared library
- * extension, pthreads, byte order etc.
- */
- virtual void EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *, bool optional);
-
- /**
- * Try running cmake and building a file. This is used for dynalically
- * loaded commands, not as part of the usual build process.
- */
- virtual std::string GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
- const char *projectDir,
- const char* additionalOptions,
- const char *targetName,
- const char* config,
- bool ignoreErrors,
- bool fast);
-
- /**
- * 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.
- */
- virtual void Generate();
-
- /**
- * Generate the DSW workspace file.
- */
- virtual void OutputDSWFile();
- virtual void OutputDSWFile(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators);
- virtual void WriteDSWFile(std::ostream& fout,
- cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators);
-
- /** Append the subdirectory for the given configuration. */
- virtual void AppendDirectoryForConfig(const char* prefix,
- const char* config,
- const char* suffix,
- std::string& dir);
-
- ///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGIntDir() const { return "$(IntDir)"; }
-
-protected:
- virtual const char* GetIDEVersion() { return "6.0"; }
-private:
- void GenerateConfigurations(cmMakefile* mf);
- void WriteDSWFile(std::ostream& fout);
- void WriteDSWHeader(std::ostream& fout);
- void WriteProject(std::ostream& fout,
- const char* name, const char* path, cmTarget &t);
- void WriteExternalProject(std::ostream& fout,
- const char* name, const char* path,
- const std::set<cmStdString>& dependencies);
- void WriteDSWFooter(std::ostream& fout);
- virtual std::string WriteUtilityDepend(cmTarget* target);
-};
-
-#endif
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 51efc466c..3b45c902c 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -1,98 +1,27 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "windows.h" // this must be first to define GetCurrentDirectory
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio71Generator.h"
+
+#include "cmDocumentationEntry.h"
+#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmake.h"
-//----------------------------------------------------------------------------
cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(
- const char* platformName) : cmGlobalVisualStudio7Generator(platformName)
+ cmake* cm, const std::string& platformName)
+ : cmGlobalVisualStudio7Generator(cm, platformName)
{
- this->FindMakeProgramFile = "CMakeVS71FindMake.cmake";
this->ProjectConfigurationSectionName = "ProjectConfiguration";
}
-//----------------------------------------------------------------------------
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio71Generator::CreateLocalGenerator()
-{
- cmLocalVisualStudio7Generator *lg =
- new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS71);
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS7());
- lg->SetGlobalGenerator(this);
- return lg;
-}
-
-//----------------------------------------------------------------------------
-std::string cmGlobalVisualStudio71Generator::GetUserMacrosDirectory()
-{
- // Macros not supported on Visual Studio 7.1 and earlier because
- // they do not appear to work *during* a build when called by an
- // outside agent...
- //
- return "";
-
-#if 0
- //
- // The COM result from calling a Visual Studio macro with 7.1 indicates
- // that the call succeeds, but the macro does not appear to execute...
- //
- // So, I am leaving this code here to show how to do it, but have not
- // yet figured out what the issue is in terms of why the macro does not
- // appear to execute...
- //
- std::string base;
- std::string path;
-
- // base begins with the VisualStudioProjectsLocation reg value...
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\7.1;"
- "VisualStudioProjectsLocation",
- base))
- {
- cmSystemTools::ConvertToUnixSlashes(base);
-
- // 7.1 macros folder:
- path = base + "/VSMacros71";
- }
-
- // path is (correctly) still empty if we did not read the base value from
- // the Registry value
- return path;
-#endif
-}
-
-//----------------------------------------------------------------------------
-std::string cmGlobalVisualStudio71Generator::GetUserMacrosRegKeyBase()
+void cmGlobalVisualStudio71Generator::WriteSLNFile(
+ std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators)
{
- // Macros not supported on Visual Studio 7.1 and earlier because
- // they do not appear to work *during* a build when called by an
- // outside agent...
- //
- return "";
-
-#if 0
- return "Software\\Microsoft\\VisualStudio\\7.1\\vsmacros";
-#endif
-}
+ std::vector<std::string> configs;
+ root->GetMakefile()->GetConfigurations(configs);
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio71Generator
-::WriteSLNFile(std::ostream& fout,
- cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
-{
// Write out the header for a SLN file
this->WriteSLNHeader(fout);
@@ -101,33 +30,40 @@ void cmGlobalVisualStudio71Generator
TargetDependSet projectTargets;
TargetDependSet originalTargets;
this->GetTargetSets(projectTargets, originalTargets, root, generators);
- OrderedTargetDependSet orderedProjectTargets(projectTargets);
+ OrderedTargetDependSet orderedProjectTargets(
+ projectTargets, this->GetStartupProjectName(root));
- this->WriteTargetsToSolution(fout, root, orderedProjectTargets);
+ // Generate the targets specification to a string. We will put this in
+ // the actual .sln file later. As a side effect, this method also
+ // populates the set of folders.
+ std::ostringstream targetsSlnString;
+ this->WriteTargetsToSolution(targetsSlnString, root, orderedProjectTargets);
+ // Generate folder specification.
bool useFolderProperty = this->UseFolderProperty();
- if (useFolderProperty)
- {
+ if (useFolderProperty) {
this->WriteFolders(fout);
- }
+ }
+
+ // Now write the actual target specification content.
+ fout << targetsSlnString.str();
// Write out the configurations information for the solution
fout << "Global\n";
// Write out the configurations for the solution
- this->WriteSolutionConfigurations(fout);
+ this->WriteSolutionConfigurations(fout, configs);
fout << "\tGlobalSection(" << this->ProjectConfigurationSectionName
<< ") = postSolution\n";
// Write out the configurations for all the targets in the project
- this->WriteTargetConfigurations(fout, root, orderedProjectTargets);
+ this->WriteTargetConfigurations(fout, configs, orderedProjectTargets);
fout << "\tEndGlobalSection\n";
- if (useFolderProperty)
- {
+ if (useFolderProperty) {
// Write out project folders
fout << "\tGlobalSection(NestedProjects) = preSolution\n";
this->WriteFoldersContent(fout);
fout << "\tEndGlobalSection\n";
- }
+ }
// Write out global sections
this->WriteSLNGlobalSections(fout, root);
@@ -136,60 +72,56 @@ void cmGlobalVisualStudio71Generator
this->WriteSLNFooter(fout);
}
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudio71Generator
-::WriteSolutionConfigurations(std::ostream& fout)
+void cmGlobalVisualStudio71Generator::WriteSolutionConfigurations(
+ std::ostream& fout, std::vector<std::string> const& configs)
{
fout << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = configs.begin();
+ i != configs.end(); ++i) {
fout << "\t\t" << *i << " = " << *i << "\n";
- }
+ }
fout << "\tEndGlobalSection\n";
}
-//----------------------------------------------------------------------------
// Write a dsp file into the SLN file,
// Note, that dependencies from executables to
// the libraries it uses are also done here
-void
-cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
- const char* dspname,
- const char* dir,
- cmTarget& t)
+void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
+ const std::string& dspname,
+ const char* dir,
+ cmGeneratorTarget const* t)
{
// check to see if this is a fortran build
const char* ext = ".vcproj";
const char* project =
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"";
- if(this->TargetIsFortranOnly(t))
- {
+ if (this->TargetIsFortranOnly(t)) {
ext = ".vfproj";
project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
- }
- const char* targetExt = t.GetProperty("GENERATOR_FILE_NAME_EXT");
- if(targetExt)
- {
+ }
+ if (this->TargetIsCSharpOnly(t)) {
+ ext = ".csproj";
+ project = "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"";
+ }
+ const char* targetExt = t->GetProperty("GENERATOR_FILE_NAME_EXT");
+ if (targetExt) {
ext = targetExt;
- }
+ }
std::string guid = this->GetGUID(dspname);
- fout << project
- << dspname << "\", \""
- << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
- << dspname << ext << "\", \"{" << guid << "}\"\n";
+ fout << project << dspname << "\", \"" << this->ConvertToSolutionPath(dir)
+ << (dir[0] ? "\\" : "") << dspname << ext << "\", \"{" << guid
+ << "}\"\n";
fout << "\tProjectSection(ProjectDependencies) = postProject\n";
this->WriteProjectDepends(fout, dspname, dir, t);
fout << "\tEndProjectSection\n";
- fout <<"EndProject\n";
+ fout << "EndProject\n";
- UtilityDependsMap::iterator ui = this->UtilityDepends.find(&t);
- if(ui != this->UtilityDepends.end())
- {
+ UtilityDependsMap::iterator ui = this->UtilityDepends.find(t);
+ if (ui != this->UtilityDepends.end()) {
const char* uname = ui->second.c_str();
+ /* clang-format off */
fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
<< uname << "\", \""
<< this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
@@ -199,119 +131,99 @@ cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
<< "\t\t{" << guid << "} = {" << guid << "}\n"
<< "\tEndProjectSection\n"
<< "EndProject\n";
- }
+ /* clang-format on */
+ }
}
-//----------------------------------------------------------------------------
// Write a dsp file into the SLN file,
// Note, that dependencies from executables to
// the libraries it uses are also done here
-void
-cmGlobalVisualStudio71Generator
-::WriteProjectDepends(std::ostream& fout,
- const char*,
- const char*, cmTarget& target)
+void cmGlobalVisualStudio71Generator::WriteProjectDepends(
+ std::ostream& fout, const std::string&, const char*,
+ cmGeneratorTarget const* target)
{
- VSDependSet const& depends = this->VSTargetDepends[&target];
- for(VSDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di)
- {
+ VSDependSet const& depends = this->VSTargetDepends[target];
+ for (VSDependSet::const_iterator di = depends.begin(); di != depends.end();
+ ++di) {
const char* name = di->c_str();
std::string guid = this->GetGUID(name);
- if(guid.size() == 0)
- {
+ if (guid.empty()) {
std::string m = "Target: ";
- m += target.GetName();
+ m += target->GetName();
m += " depends on unknown target: ";
m += name;
cmSystemTools::Error(m.c_str());
- }
- fout << "\t\t{" << guid << "} = {" << guid << "}\n";
}
+ fout << "\t\t{" << guid << "} = {" << guid << "}\n";
+ }
}
-//----------------------------------------------------------------------------
// Write a dsp file into the SLN file, Note, that dependencies from
// executables to the libraries it uses are also done here
-void cmGlobalVisualStudio71Generator
-::WriteExternalProject(std::ostream& fout,
- const char* name,
- const char* location,
- const char* typeGuid,
- const std::set<cmStdString>& depends)
+void cmGlobalVisualStudio71Generator::WriteExternalProject(
+ std::ostream& fout, const std::string& name, const char* location,
+ const char* typeGuid, const std::set<std::string>& depends)
{
fout << "Project(\"{"
- << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
- << "}\") = \""
- << name << "\", \""
+ << (typeGuid ? typeGuid : this->ExternalProjectType(location))
+ << "}\") = \"" << name << "\", \""
<< this->ConvertToSolutionPath(location) << "\", \"{"
- << this->GetGUID(name)
- << "}\"\n";
+ << this->GetGUID(name) << "}\"\n";
// write out the dependencies here VS 7.1 includes dependencies with the
// project instead of in the global section
- if(!depends.empty())
- {
+ if (!depends.empty()) {
fout << "\tProjectSection(ProjectDependencies) = postProject\n";
- std::set<cmStdString>::const_iterator it;
- for(it = depends.begin(); it != depends.end(); ++it)
- {
- if(it->size() > 0)
- {
- fout << "\t\t{"
- << this->GetGUID(it->c_str())
- << "} = {"
- << this->GetGUID(it->c_str())
- << "}\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";
}
- fout << "\tEndProjectSection\n";
}
+ fout << "\tEndProjectSection\n";
+ }
fout << "EndProject\n";
-
-
}
-//----------------------------------------------------------------------------
// Write a dsp file into the SLN file, Note, that dependencies from
// executables to the libraries it uses are also done here
-void cmGlobalVisualStudio71Generator
-::WriteProjectConfigurations(
- std::ostream& fout, const char* name, cmTarget::TargetType,
+void cmGlobalVisualStudio71Generator::WriteProjectConfigurations(
+ std::ostream& fout, const std::string& name, cmGeneratorTarget const& target,
+ std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const char* platformMapping)
+ std::string const& platformMapping)
{
- const char* platformName =
- platformMapping ? platformMapping : this->GetPlatformName();
+ const std::string& platformName =
+ !platformMapping.empty() ? platformMapping : this->GetPlatformName();
std::string guid = this->GetGUID(name);
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|" << platformName << std::endl;
- std::set<std::string>::const_iterator
- ci = configsPartOfDefaultBuild.find(*i);
- if(!(ci == configsPartOfDefaultBuild.end()))
- {
- fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|" << platformName << std::endl;
+ for (std::vector<std::string>::const_iterator i = configs.begin();
+ i != configs.end(); ++i) {
+ std::vector<std::string> mapConfig;
+ 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);
+ if (!mapConfig.empty()) {
+ dstConfig = mapConfig[0].c_str();
+ }
}
}
+ fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << dstConfig
+ << "|" << platformName << std::endl;
+ std::set<std::string>::const_iterator ci =
+ configsPartOfDefaultBuild.find(*i);
+ if (!(ci == configsPartOfDefaultBuild.end())) {
+ 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";
}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio71Generator
-::GetDocumentation(cmDocumentationEntry& entry)
-{
- entry.Name = cmGlobalVisualStudio71Generator::GetActualName();
- entry.Brief = "Generates Visual Studio .NET 2003 project files.";
- entry.Full = "";
-}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index e136db7ea..0ce02aa46 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -1,20 +1,10 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio71Generator_h
#define cmGlobalVisualStudio71Generator_h
#include "cmGlobalVisualStudio7Generator.h"
-
/** \class cmGlobalVisualStudio71Generator
* \brief Write a Unix makefiles.
*
@@ -23,56 +13,33 @@
class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator
{
public:
- cmGlobalVisualStudio71Generator(const char* platformName = NULL);
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalVisualStudio71Generator>(); }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio71Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 7 .NET 2003";}
-
- /** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
-
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
- /**
- * 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();
+ cmGlobalVisualStudio71Generator(cmake* cm,
+ const std::string& platformName = "");
protected:
- virtual const char* GetIDEVersion() { return "7.1"; }
- virtual void WriteSLNFile(std::ostream& fout,
- cmLocalGenerator* root,
+ virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
- virtual void WriteSolutionConfigurations(std::ostream& fout);
- virtual void WriteProject(std::ostream& fout,
- const char* name, const char* path, cmTarget &t);
- virtual void WriteProjectDepends(std::ostream& fout,
- const char* name, const char* path, cmTarget &t);
+ 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(
- std::ostream& fout, const char* name, cmTarget::TargetType type,
+ std::ostream& fout, const std::string& name,
+ cmGeneratorTarget const& target, std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const char* platformMapping = NULL);
+ const std::string& platformMapping = "");
virtual void WriteExternalProject(std::ostream& fout,
- const char* name,
- const char* path,
+ const std::string& name, const char* path,
const char* typeGuid,
- const std::set<cmStdString>& depends);
+ const std::set<std::string>& depends);
virtual void WriteSLNHeader(std::ostream& fout);
+ // Folders are not supported by VS 7.1.
+ virtual bool UseFolderProperty() { return false; }
+
std::string ProjectConfigurationSectionName;
};
#endif
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index b47566561..b155f5b55 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -1,57 +1,112 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "windows.h" // this must be first to define GetCurrentDirectory
-#include <assert.h>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio7Generator.h"
+
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmState.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
+ // UsePrecompiledHeader entries are marked as "Continue" so that the
+ // corresponding PrecompiledHeaderThrough entry can be found.
+ { "UsePrecompiledHeader", "YX", "Automatically Generate", "2",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+ { "PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "",
+ cmVS7FlagTable::UserValueRequired },
+ { "UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+ { "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
+ cmVS7FlagTable::UserValueRequired },
+ { "WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true",
+ 0 },
+
+ // Exception handling mode. If no entries match, it will be FALSE.
+ { "ExceptionHandling", "GX", "enable c++ exceptions", "true", 0 },
+ { "ExceptionHandling", "EHsc", "enable c++ exceptions", "true", 0 },
+ // The EHa option does not have an IDE setting. Let it go to false,
+ // and have EHa passed on the command line by leaving out the table
+ // entry.
+
+ { 0, 0, 0, 0, 0 }
+};
cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
- const char* platformName)
-{
- this->FindMakeProgramFile = "CMakeVS7FindMake.cmake";
+ cmake* cm, const std::string& platformName)
+ : cmGlobalVisualStudioGenerator(cm)
+{
+ 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;
+}
- if (!platformName)
- {
- platformName = "Win32";
- }
- this->PlatformName = platformName;
+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()
+{
+ if (!this->IntelProjectVersion) {
+ // 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,
+ cmSystemTools::KeyWOW64_32);
+ unsigned int intelVersionNumber = ~0u;
+ sscanf(intelVersion.c_str(), "%u", &intelVersionNumber);
+ if (intelVersionNumber >= 11) {
+ // Default to latest known project file version.
+ intelVersion = "11.0";
+ } else if (intelVersionNumber == 10) {
+ // Version 10.x actually uses 9.10 in project files!
+ intelVersion = "9.10";
+ } else {
+ // Version <= 9: use ProductVersion from registry.
+ }
+ this->IntelProjectVersion = strdup(intelVersion.c_str());
+ }
+ return this->IntelProjectVersion;
+}
-void cmGlobalVisualStudio7Generator
-::EnableLanguage(std::vector<std::string>const & lang,
- cmMakefile *mf, bool optional)
+void cmGlobalVisualStudio7Generator::EnableLanguage(
+ std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- mf->AddDefinition("CMAKE_GENERATOR_FC", "ifort");
- this->AddPlatformDefinitions(mf);
- if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
- {
+ if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES",
- "Debug;Release;MinSizeRel;RelWithDebInfo",
+ "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
"Semicolon separated list of supported configuration types, "
"only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
"anything else will be ignored.",
- cmCacheManager::STRING);
- }
+ cmStateEnums::STRING);
+ }
// Create list of configurations requested by user's cache, if any.
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
- this->GenerateConfigurations(mf);
// if this environment variable is set, then copy it to
// a static cache entry. It will be used by
@@ -60,146 +115,171 @@ void cmGlobalVisualStudio7Generator
// does not use the environment it is run in, and this allows
// for running commands and using dll's that the IDE environment
// does not know about.
- const char* extraPath = cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH");
- if(extraPath)
- {
- mf->AddCacheDefinition
- ("CMAKE_MSVCIDE_RUN_PATH", extraPath,
- "Saved environment variable CMAKE_MSVCIDE_RUN_PATH",
- cmCacheManager::STATIC);
- }
+ std::string extraPath;
+ if (cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH", extraPath)) {
+ mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath.c_str(),
+ "Saved environment variable CMAKE_MSVCIDE_RUN_PATH",
+ cmStateEnums::STATIC);
+ }
+}
+bool cmGlobalVisualStudio7Generator::FindMakeProgram(cmMakefile* mf)
+{
+ if (!this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf)) {
+ return false;
+ }
+ mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND",
+ this->GetDevEnvCommand().c_str());
+ return true;
}
-std::string cmGlobalVisualStudio7Generator
-::GenerateBuildCommand(const char* makeProgram,
- const char *projectName, const char *projectDir,
- const char* additionalOptions, const char *targetName,
- const char* config, bool ignoreErrors, bool)
+std::string const& cmGlobalVisualStudio7Generator::GetDevEnvCommand()
{
- // Visual studio 7 doesn't need project dir
- (void) projectDir;
- // Ingoring errors is not implemented in visual studio 6
- (void) ignoreErrors;
-
- // now build the test
- std::string makeCommand =
- cmSystemTools::ConvertToOutputPath(makeProgram);
- std::string lowerCaseCommand = makeCommand;
- cmSystemTools::LowerCase(lowerCaseCommand);
-
- // if there are spaces in the makeCommand, assume a full path
- // and convert it to a path with no spaces in it as the
- // RunSingleCommand does not like spaces
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if(makeCommand.find(' ') != std::string::npos)
- {
- cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
- }
-#endif
- makeCommand += " ";
- makeCommand += projectName;
- makeCommand += ".sln ";
- bool clean = false;
- if ( targetName && strcmp(targetName, "clean") == 0 )
- {
- clean = true;
- targetName = "ALL_BUILD";
- }
- if(clean)
- {
- makeCommand += "/clean ";
- }
- else
- {
- makeCommand += "/build ";
- }
+ if (!this->DevEnvCommandInitialized) {
+ this->DevEnvCommandInitialized = true;
+ this->DevEnvCommand = this->FindDevEnvCommand();
+ }
+ return this->DevEnvCommand;
+}
- if(config && strlen(config))
- {
- makeCommand += config;
- }
- else
- {
- makeCommand += "Debug";
- }
- makeCommand += " /project ";
+std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand()
+{
+ std::string vscmd;
+ std::string vskey;
- if (targetName && strlen(targetName))
- {
- makeCommand += targetName;
+ // Search in standard location.
+ vskey = this->GetRegistryBase() + ";InstallDir";
+ if (cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
+ cmSystemTools::KeyWOW64_32)) {
+ cmSystemTools::ConvertToUnixSlashes(vscmd);
+ vscmd += "/devenv.com";
+ if (cmSystemTools::FileExists(vscmd, true)) {
+ return vscmd;
}
- else
- {
- makeCommand += "ALL_BUILD";
- }
- if ( additionalOptions )
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
+ }
+
+ // Search where VS15Preview places it.
+ vskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;";
+ vskey += this->GetIDEVersion();
+ if (cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
+ cmSystemTools::KeyWOW64_32)) {
+ cmSystemTools::ConvertToUnixSlashes(vscmd);
+ vscmd += "/Common7/IDE/devenv.com";
+ if (cmSystemTools::FileExists(vscmd, true)) {
+ return vscmd;
}
- return makeCommand;
+ }
+
+ vscmd = "devenv.com";
+ return vscmd;
+}
+
+const char* cmGlobalVisualStudio7Generator::ExternalProjectType(
+ const char* location)
+{
+ std::string extension = cmSystemTools::GetFilenameLastExtension(location);
+ if (extension == ".vbproj") {
+ return "F184B08F-C81C-45F6-A57F-5ABD9991F28F";
+ } else if (extension == ".csproj") {
+ return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC";
+ } else if (extension == ".fsproj") {
+ return "F2A71F9B-5D33-465A-A702-920D77279786";
+ } else if (extension == ".vdproj") {
+ return "54435603-DBB4-11D2-8724-00A0C9A8B90C";
+ } else if (extension == ".dbproj") {
+ return "C8D11400-126E-41CD-887F-60BD40844F9E";
+ } else if (extension == ".wixproj") {
+ return "930C7802-8A8C-48F9-8165-68863BCCD9DD";
+ } else if (extension == ".pyproj") {
+ return "888888A0-9F3D-457C-B088-3A5042F75D52";
+ }
+ 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)
+{
+ // Select the caller- or user-preferred make program, else devenv.
+ std::string makeProgramSelected =
+ this->SelectMakeProgram(makeProgram, this->GetDevEnvCommand());
+
+ // Ignore the above preference if it is msbuild.
+ // Assume any other value is either a devenv or
+ // command-line compatible with devenv.
+ std::string makeProgramLower = makeProgramSelected;
+ cmSystemTools::LowerCase(makeProgramLower);
+ if (makeProgramLower.find("msbuild") != std::string::npos) {
+ makeProgramSelected = this->GetDevEnvCommand();
+ }
+
+ makeCommand.push_back(makeProgramSelected);
+
+ 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");
+ }
+
+ 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());
}
///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator(
+ cmMakefile* mf)
{
- cmLocalVisualStudio7Generator *lg =
- new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS7);
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS7());
- lg->SetGlobalGenerator(this);
+ cmLocalVisualStudio7Generator* lg =
+ new cmLocalVisualStudio7Generator(this, mf);
return lg;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio7Generator::AddPlatformDefinitions(cmMakefile* mf)
+std::string const& cmGlobalVisualStudio7Generator::GetPlatformName() const
{
- cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
+ if (!this->GeneratorPlatform.empty()) {
+ return this->GeneratorPlatform;
+ }
+ return this->DefaultPlatformName;
}
-void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
+bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s,
+ cmMakefile* mf)
{
- // process the configurations
- const char* ct
- = this->CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES");
- if ( ct )
- {
- std::vector<std::string> argsOut;
- cmSystemTools::ExpandListArgument(ct, argsOut);
- for(std::vector<std::string>::iterator i = argsOut.begin();
- i != argsOut.end(); ++i)
- {
- if(std::find(this->Configurations.begin(),
- this->Configurations.end(),
- *i) == this->Configurations.end())
- {
- this->Configurations.push_back(*i);
- }
- }
- }
- // default to at least Debug and Release
- if(this->Configurations.size() == 0)
- {
- this->Configurations.push_back("Debug");
- this->Configurations.push_back("Release");
- }
-
- // Reset the entry to have a semi-colon separated list.
- std::string configs = this->Configurations[0];
- for(unsigned int i=1; i < this->Configurations.size(); ++i)
- {
- configs += ";";
- configs += this->Configurations[i];
- }
+ mf->AddDefinition("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION",
+ this->GetIntelProjectVersion());
+ return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf);
+}
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES",
- configs.c_str(),
- "Semicolon separated list of supported configuration types, "
- "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
- "anything else will be ignored.",
- cmCacheManager::STRING);
+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()
@@ -211,546 +291,323 @@ void cmGlobalVisualStudio7Generator::Generate()
this->OutputSLNFile();
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
- if(!cmSystemTools::GetErrorOccuredFlag())
- {
+ 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.");
+ }
+ }
}
-void cmGlobalVisualStudio7Generator
-::OutputSLNFile(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
+void cmGlobalVisualStudio7Generator::OutputSLNFile(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
- if(generators.size() == 0)
- {
+ if (generators.empty()) {
return;
- }
- this->CurrentProject = root->GetMakefile()->GetProjectName();
- std::string fname = root->GetMakefile()->GetStartOutputDirectory();
+ }
+ this->CurrentProject = root->GetProjectName();
+ std::string fname = root->GetCurrentBinaryDirectory();
fname += "/";
- fname += root->GetMakefile()->GetProjectName();
+ fname += root->GetProjectName();
fname += ".sln";
cmGeneratedFileStream fout(fname.c_str());
fout.SetCopyIfDifferent(true);
- if(!fout)
- {
+ if (!fout) {
return;
- }
+ }
this->WriteSLNFile(fout, root, generators);
- if (fout.Close())
- {
+ if (fout.Close()) {
this->FileReplacedDuringGenerate(fname);
- }
+ }
}
// output the SLN file
void cmGlobalVisualStudio7Generator::OutputSLNFile()
{
- std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
- for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
- {
+ 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);
- }
+ }
}
-
void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
- std::ostream& fout,
- cmLocalGenerator* root,
+ std::ostream& fout, std::vector<std::string> const& configs,
OrderedTargetDependSet const& projectTargets)
{
// loop over again and write out configurations for each target
// in the solution
- for(OrderedTargetDependSet::const_iterator tt =
- projectTargets.begin(); tt != projectTargets.end(); ++tt)
- {
- cmTarget* target = *tt;
+ for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
+ tt != projectTargets.end(); ++tt) {
+ cmGeneratorTarget const* target = *tt;
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
- if(expath)
- {
- std::set<std::string> allConfigurations(this->Configurations.begin(),
- this->Configurations.end());
- this->WriteProjectConfigurations(
- fout, target->GetName(), target->GetType(),
- allConfigurations, target->GetProperty("VS_PLATFORM_MAPPING"));
- }
- else
- {
+ if (expath) {
+ std::set<std::string> allConfigurations(configs.begin(), configs.end());
+ const char* mapping = target->GetProperty("VS_PLATFORM_MAPPING");
+ this->WriteProjectConfigurations(fout, target->GetName().c_str(),
+ *target, configs, allConfigurations,
+ mapping ? mapping : "");
+ } else {
const std::set<std::string>& configsPartOfDefaultBuild =
- this->IsPartOfDefaultBuild(root->GetMakefile()->GetProjectName(),
- target);
- const char *vcprojName =
- target->GetProperty("GENERATOR_FILE_NAME");
- if (vcprojName)
- {
- this->WriteProjectConfigurations(fout, vcprojName, target->GetType(),
+ this->IsPartOfDefaultBuild(configs, projectTargets, target);
+ const char* vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
+ if (vcprojName) {
+ this->WriteProjectConfigurations(fout, vcprojName, *target, configs,
configsPartOfDefaultBuild);
- }
}
}
+ }
}
-
void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
- std::ostream& fout,
- cmLocalGenerator* root,
- OrderedTargetDependSet const& projectTargets)
+ std::ostream& fout, cmLocalGenerator* root,
+ OrderedTargetDependSet const& projectTargets)
{
VisualStudioFolders.clear();
- for(OrderedTargetDependSet::const_iterator tt =
- projectTargets.begin(); tt != projectTargets.end(); ++tt)
- {
- cmTarget* target = *tt;
+ std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
+ for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
+ tt != projectTargets.end(); ++tt) {
+ cmGeneratorTarget const* target = *tt;
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
bool written = false;
// handle external vc project files
const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
- if(expath)
- {
+ if (expath) {
std::string project = target->GetName();
std::string location = expath;
- this->WriteExternalProject(fout,
- project.c_str(),
- location.c_str(),
+ this->WriteExternalProject(fout, project.c_str(), location.c_str(),
target->GetProperty("VS_PROJECT_TYPE"),
target->GetUtilities());
written = true;
- }
- else
- {
- const char *vcprojName =
- target->GetProperty("GENERATOR_FILE_NAME");
- if(vcprojName)
- {
- cmMakefile* tmf = target->GetMakefile();
- std::string dir = tmf->GetStartOutputDirectory();
- dir = root->Convert(dir.c_str(),
- cmLocalGenerator::START_OUTPUT);
- if(dir == ".")
- {
+ } else {
+ const char* vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
+ if (vcprojName) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::string dir = lg->GetCurrentBinaryDirectory();
+ dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str());
+ if (dir == ".") {
dir = ""; // msbuild cannot handle ".\" prefix
- }
- this->WriteProject(fout, vcprojName, dir.c_str(),
- *target);
- written = true;
}
+ this->WriteProject(fout, vcprojName, dir.c_str(), target);
+ written = true;
}
+ }
// Create "solution folder" information from FOLDER target property
//
- if (written && this->UseFolderProperty())
- {
- const char *targetFolder = target->GetProperty("FOLDER");
- if (targetFolder)
- {
+ if (written && this->UseFolderProperty()) {
+ const std::string targetFolder = target->GetEffectiveFolderName();
+ if (!targetFolder.empty()) {
std::vector<cmsys::String> tokens =
cmSystemTools::SplitString(targetFolder, '/', false);
std::string cumulativePath = "";
- for(std::vector<cmsys::String>::iterator iter = tokens.begin();
- iter != tokens.end(); ++iter)
- {
- if(!iter->size())
- {
+ for (std::vector<cmsys::String>::iterator iter = tokens.begin();
+ iter != tokens.end(); ++iter) {
+ if (!iter->size()) {
continue;
- }
+ }
- if (cumulativePath.empty())
- {
+ if (cumulativePath.empty()) {
cumulativePath = "CMAKE_FOLDER_GUID_" + *iter;
- }
- else
- {
- VisualStudioFolders[cumulativePath].insert(
- cumulativePath + "/" + *iter);
+ } else {
+ VisualStudioFolders[cumulativePath].insert(cumulativePath + "/" +
+ *iter);
cumulativePath = cumulativePath + "/" + *iter;
- }
-
- this->CreateGUID(cumulativePath.c_str());
}
+ }
- if (!cumulativePath.empty())
- {
+ if (!cumulativePath.empty()) {
VisualStudioFolders[cumulativePath].insert(target->GetName());
- }
}
}
}
+ }
}
-
void cmGlobalVisualStudio7Generator::WriteTargetDepends(
- std::ostream& fout,
- OrderedTargetDependSet const& projectTargets
- )
+ std::ostream& fout, OrderedTargetDependSet const& projectTargets)
{
- for(OrderedTargetDependSet::const_iterator tt =
- projectTargets.begin(); tt != projectTargets.end(); ++tt)
- {
- cmTarget* target = *tt;
- cmMakefile* mf = target->GetMakefile();
- const char *vcprojName =
- target->GetProperty("GENERATOR_FILE_NAME");
- if (vcprojName)
- {
- std::string dir = mf->GetStartDirectory();
- this->WriteProjectDepends(fout, vcprojName,
- dir.c_str(), *target);
- }
+ for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
+ tt != projectTargets.end(); ++tt) {
+ cmGeneratorTarget const* target = *tt;
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
}
-}
-
-//----------------------------------------------------------------------------
-// Write a SLN file to the stream
-void cmGlobalVisualStudio7Generator
-::WriteSLNFile(std::ostream& fout,
- cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
-{
- // Write out the header for a SLN file
- this->WriteSLNHeader(fout);
-
- // 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 orderedProjectTargets(projectTargets);
-
- this->WriteTargetsToSolution(fout, root, orderedProjectTargets);
-
- bool useFolderProperty = this->UseFolderProperty();
- if (useFolderProperty)
- {
- this->WriteFolders(fout);
+ const char* vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
+ if (vcprojName) {
+ std::string dir =
+ target->GetLocalGenerator()->GetCurrentSourceDirectory();
+ this->WriteProjectDepends(fout, vcprojName, dir.c_str(), target);
}
-
- // Write out the configurations information for the solution
- fout << "Global\n"
- << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
-
- int c = 0;
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- fout << "\t\tConfigName." << c << " = " << *i << "\n";
- c++;
- }
- fout << "\tEndGlobalSection\n";
- // Write out project(target) depends
- fout << "\tGlobalSection(ProjectDependencies) = postSolution\n";
- this->WriteTargetDepends(fout, orderedProjectTargets);
- fout << "\tEndGlobalSection\n";
-
- if (useFolderProperty)
- {
- // Write out project folders
- fout << "\tGlobalSection(NestedProjects) = preSolution\n";
- this->WriteFoldersContent(fout);
- fout << "\tEndGlobalSection\n";
- }
-
- // Write out the configurations for all the targets in the project
- fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n";
- this->WriteTargetConfigurations(fout, root, orderedProjectTargets);
- fout << "\tEndGlobalSection\n";
-
- // Write out global sections
- this->WriteSLNGlobalSections(fout, root);
-
- // Write the footer for the SLN file
- this->WriteSLNFooter(fout);
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
{
- const char *prefix = "CMAKE_FOLDER_GUID_";
+ const char* prefix = "CMAKE_FOLDER_GUID_";
const std::string::size_type skip_prefix = strlen(prefix);
std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8";
- for(std::map<std::string,std::set<std::string> >::iterator iter =
- VisualStudioFolders.begin(); iter != VisualStudioFolders.end(); ++iter)
- {
+ 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());
- cmSystemTools::ReplaceString(fullName, "/", "\\");
- if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix))
- {
+ std::replace(fullName.begin(), fullName.end(), '/', '\\');
+ if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix)) {
fullName = fullName.substr(skip_prefix);
- }
+ }
std::string nameOnly = cmSystemTools::GetFilenameName(fullName);
- fout << "Project(\"{" <<
- guidProjectTypeFolder << "}\") = \"" <<
- nameOnly << "\", \"" <<
- fullName << "\", \"{" <<
- guid <<
- "}\"\nEndProject\n";
- }
+ fout << "Project(\"{" << guidProjectTypeFolder << "}\") = \"" << nameOnly
+ << "\", \"" << fullName << "\", \"{" << guid << "}\"\nEndProject\n";
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio7Generator::WriteFoldersContent(std::ostream& fout)
{
- for(std::map<std::string,std::set<std::string> >::iterator iter =
- VisualStudioFolders.begin(); iter != VisualStudioFolders.end(); ++iter)
- {
+ 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(std::set<std::string>::iterator it = iter->second.begin();
- it != iter->second.end(); ++it)
- {
+ 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()));
fout << "\t\t{" << guid << "} = {" << guidParent << "}\n";
- }
}
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmGlobalVisualStudio7Generator::ConvertToSolutionPath(const char* path)
+std::string cmGlobalVisualStudio7Generator::ConvertToSolutionPath(
+ const char* path)
{
// Convert to backslashes. Do not use ConvertToOutputPath because
// we will add quoting ourselves, and we know these projects always
// use windows slashes.
std::string d = path;
std::string::size_type pos = 0;
- while((pos = d.find('/', pos)) != d.npos)
- {
+ while ((pos = d.find('/', pos)) != d.npos) {
d[pos++] = '\\';
- }
+ }
return d;
}
-// Write a dsp file into the SLN file,
-// Note, that dependencies from executables to
-// the libraries it uses are also done here
-void cmGlobalVisualStudio7Generator::WriteProject(std::ostream& fout,
- const char* dspname,
- const char* dir, cmTarget& target)
-{
- // check to see if this is a fortran build
- const char* ext = ".vcproj";
- const char* project =
- "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"";
- if(this->TargetIsFortranOnly(target))
- {
- ext = ".vfproj";
- project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
- }
-
- fout << project
- << dspname << "\", \""
- << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
- << dspname << ext << "\", \"{"
- << this->GetGUID(dspname) << "}\"\nEndProject\n";
-
- UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
- if(ui != this->UtilityDepends.end())
- {
- const char* uname = ui->second.c_str();
- fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
- << uname << "\", \""
- << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
- << uname << ".vcproj" << "\", \"{"
- << this->GetGUID(uname) << "}\"\n"
- << "EndProject\n";
- }
-}
-
-
-
-// Write a dsp file into the SLN file,
-// Note, that dependencies from executables to
-// the libraries it uses are also done here
-void
-cmGlobalVisualStudio7Generator
-::WriteProjectDepends(std::ostream& fout,
- const char* dspname,
- const char*, cmTarget& target)
-{
- int depcount = 0;
- std::string dspguid = this->GetGUID(dspname);
- VSDependSet const& depends = this->VSTargetDepends[&target];
- for(VSDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di)
- {
- const char* name = di->c_str();
- std::string guid = this->GetGUID(name);
- if(guid.size() == 0)
- {
- std::string m = "Target: ";
- m += target.GetName();
- m += " depends on unknown target: ";
- m += name;
- cmSystemTools::Error(m.c_str());
- }
- fout << "\t\t{" << dspguid << "}." << depcount << " = {" << guid << "}\n";
- depcount++;
- }
-
- UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
- if(ui != this->UtilityDepends.end())
- {
- const char* uname = ui->second.c_str();
- fout << "\t\t{" << this->GetGUID(uname) << "}.0 = {" << dspguid << "}\n";
- }
-}
-
-
-// Write a dsp file into the SLN file, Note, that dependencies from
-// executables to the libraries it uses are also done here
-void cmGlobalVisualStudio7Generator
-::WriteProjectConfigurations(
- std::ostream& fout, const char* name, cmTarget::TargetType,
- const std::set<std::string>& configsPartOfDefaultBuild,
- const char* platformMapping)
-{
- const char* platformName =
- platformMapping ? platformMapping : this->GetPlatformName();
- std::string guid = this->GetGUID(name);
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|" << platformName << "\n";
- std::set<std::string>::const_iterator
- ci = configsPartOfDefaultBuild.find(*i);
- if(!(ci == configsPartOfDefaultBuild.end()))
- {
- fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|" << platformName << "\n";
- }
- }
-}
-
-
-
-// Write a dsp file into the SLN file,
-// Note, that dependencies from executables to
-// the libraries it uses are also done here
-void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout,
- const char* name,
- const char* location,
- const char* typeGuid,
- const std::set<cmStdString>&)
-{
- std::string d = cmSystemTools::ConvertToOutputPath(location);
- fout << "Project("
- << "\"{"
- << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
- << "}\") = \""
- << name << "\", \""
- << this->ConvertToSolutionPath(location) << "\", \"{"
- << this->GetGUID(name)
- << "}\"\n";
- fout << "EndProject\n";
-}
-
-
-
-void cmGlobalVisualStudio7Generator
-::WriteSLNGlobalSections(std::ostream& fout,
- cmLocalGenerator* root)
+void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
+ std::ostream& fout, cmLocalGenerator* root)
{
+ std::string const guid = this->GetGUID(root->GetProjectName() + ".sln");
bool extensibilityGlobalsOverridden = false;
bool extensibilityAddInsOverridden = false;
- const cmPropertyMap& props = root->GetMakefile()->GetProperties();
- for(cmPropertyMap::const_iterator itProp = props.begin();
- itProp != props.end(); ++itProp)
- {
- if(itProp->first.find("VS_GLOBAL_SECTION_") == 0)
- {
+ 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) {
std::string sectionType;
- std::string name = itProp->first.substr(18);
- if(name.find("PRE_") == 0)
- {
+ std::string name = it->substr(18);
+ if (name.find("PRE_") == 0) {
name = name.substr(4);
sectionType = "preSolution";
- }
- else if(name.find("POST_") == 0)
- {
+ } else if (name.find("POST_") == 0) {
name = name.substr(5);
sectionType = "postSolution";
- }
- else
+ } else
continue;
- if(!name.empty())
- {
- if(name == "ExtensibilityGlobals" && sectionType == "postSolution")
+ if (!name.empty()) {
+ bool addGuid = false;
+ if (name == "ExtensibilityGlobals" && sectionType == "postSolution") {
+ addGuid = true;
extensibilityGlobalsOverridden = true;
- else if(name == "ExtensibilityAddIns" && sectionType == "postSolution")
+ } else if (name == "ExtensibilityAddIns" &&
+ sectionType == "postSolution") {
extensibilityAddInsOverridden = true;
+ }
fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
std::vector<std::string> keyValuePairs;
- cmSystemTools::ExpandListArgument(itProp->second.GetValue(),
- keyValuePairs);
- for(std::vector<std::string>::const_iterator itPair =
- keyValuePairs.begin(); itPair != keyValuePairs.end(); ++itPair)
- {
+ 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('=');
- if(posEqual != std::string::npos)
- {
+ if (posEqual != std::string::npos) {
const std::string key =
cmSystemTools::TrimWhitespace(itPair->substr(0, posEqual));
const std::string value =
cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
fout << "\t\t" << key << " = " << value << "\n";
+ if (key == "SolutionGuid") {
+ addGuid = false;
}
}
- fout << "\tEndGlobalSection\n";
}
+ if (addGuid) {
+ fout << "\t\tSolutionGuid = {" << guid << "}\n";
+ }
+ fout << "\tEndGlobalSection\n";
}
}
- if(!extensibilityGlobalsOverridden)
+ }
+ if (!extensibilityGlobalsOverridden) {
fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
+ << "\t\tSolutionGuid = {" << guid << "}\n"
<< "\tEndGlobalSection\n";
- if(!extensibilityAddInsOverridden)
+ }
+ if (!extensibilityAddInsOverridden)
fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
<< "\tEndGlobalSection\n";
}
-
-
// Standard end of dsw file
void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
{
fout << "EndGlobal\n";
}
-
-// ouput standard header for dsw file
-void cmGlobalVisualStudio7Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 7.00\n";
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget* target)
+std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(
+ cmGeneratorTarget const* target)
{
+ std::vector<std::string> configs;
+ target->Target->GetMakefile()->GetConfigurations(configs);
std::string pname = target->GetName();
pname += "_UTILITY";
- std::string fname = target->GetMakefile()->GetStartOutputDirectory();
+ std::string fname = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
fname += "/";
fname += pname;
fname += ".vcproj";
cmGeneratedFileStream fout(fname.c_str());
fout.SetCopyIfDifferent(true);
- this->CreateGUID(pname.c_str());
std::string guid = this->GetGUID(pname.c_str());
+ /* clang-format off */
fout <<
- "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
+ "<?xml version=\"1.0\" encoding = \""
+ << this->Encoding() << "\"?>\n"
"<VisualStudioProject\n"
"\tProjectType=\"Visual C++\"\n"
"\tVersion=\"" << this->GetIDEVersion() << "0\"\n"
@@ -760,9 +617,10 @@ cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget* target)
"\t<Platforms><Platform Name=\"Win32\"/></Platforms>\n"
"\t<Configurations>\n"
;
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
+ /* clang-format on */
+ for (std::vector<std::string>::iterator i = configs.begin();
+ i != configs.end(); ++i) {
+ /* clang-format off */
fout <<
"\t\t<Configuration\n"
"\t\t\tName=\"" << *i << "|Win32\"\n"
@@ -774,144 +632,123 @@ cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget* target)
"\t\t\tCharacterSet=\"2\">\n"
"\t\t</Configuration>\n"
;
- }
+ /* clang-format on */
+ }
+ /* clang-format off */
fout <<
"\t</Configurations>\n"
"\t<Files></Files>\n"
"\t<Globals></Globals>\n"
"</VisualStudioProject>\n"
;
+ /* clang-format on */
- if(fout.Close())
- {
+ if (fout.Close()) {
this->FileReplacedDuringGenerate(fname);
- }
+ }
return pname;
}
-std::string cmGlobalVisualStudio7Generator::GetGUID(const char* name)
+std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name)
{
- std::string guidStoreName = name;
- guidStoreName += "_GUID_CMAKE";
- const char* storedGUID =
- this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str());
- if(storedGUID)
- {
+ std::string const& guidStoreName = name + "_GUID_CMAKE";
+ if (const char* storedGUID =
+ this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str())) {
return std::string(storedGUID);
- }
- cmSystemTools::Error("Unknown Target referenced : ",
- name);
- return "";
-}
+ }
+ // Compute a GUID that is deterministic but unique to the build tree.
+ std::string input = this->CMakeInstance->GetState()->GetBinaryDirectory();
+ input += "|";
+ input += name;
+ cmUuid uuidGenerator;
-void cmGlobalVisualStudio7Generator::CreateGUID(const char* name)
-{
- std::string guidStoreName = name;
- guidStoreName += "_GUID_CMAKE";
- if(this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str()))
- {
- return;
- }
- std::string ret;
- UUID uid;
- unsigned char *uidstr;
- UuidCreate(&uid);
- UuidToString(&uid,&uidstr);
- ret = reinterpret_cast<char*>(uidstr);
- RpcStringFree(&uidstr);
- ret = cmSystemTools::UpperCase(ret);
- this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(),
- ret.c_str(), "Stored GUID",
- cmCacheManager::INTERNAL);
-}
+ std::vector<unsigned char> uuidNamespace;
+ uuidGenerator.StringToBinary("ee30c4be-5192-4fb0-b335-722a2dffe760",
+ uuidNamespace);
-std::vector<std::string> *cmGlobalVisualStudio7Generator::GetConfigurations()
-{
- return &this->Configurations;
-};
+ std::string guid = uuidGenerator.FromMd5(uuidNamespace, input);
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio7Generator
-::GetDocumentation(cmDocumentationEntry& entry)
-{
- entry.Name = cmGlobalVisualStudio7Generator::GetActualName();
- entry.Brief = "Generates Visual Studio .NET 2002 project files.";
- entry.Full = "";
+ return cmSystemTools::UpperCase(guid);
}
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudio7Generator
-::AppendDirectoryForConfig(const char* prefix,
- const char* config,
- const char* suffix,
- std::string& dir)
+void cmGlobalVisualStudio7Generator::AppendDirectoryForConfig(
+ const std::string& prefix, const std::string& config,
+ const std::string& suffix, std::string& dir)
{
- if(config)
- {
+ if (!config.empty()) {
dir += prefix;
dir += config;
dir += suffix;
- }
+ }
}
-std::set<std::string>
-cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(const char* project,
- cmTarget* target)
+std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
+ std::vector<std::string> const& configs,
+ OrderedTargetDependSet const& projectTargets,
+ cmGeneratorTarget const* target)
{
std::set<std::string> activeConfigs;
// if it is a utilitiy target then only make it part of the
// default build if another target depends on it
int type = target->GetType();
- if (type == cmTarget::GLOBAL_TARGET)
- {
- return activeConfigs;
+ if (type == cmStateEnums::GLOBAL_TARGET) {
+ 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) {
+ 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) {
+ 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(type == cmTarget::UTILITY && !this->IsDependedOn(project, target))
- {
return activeConfigs;
- }
+ }
+ if (type == cmStateEnums::UTILITY &&
+ !this->IsDependedOn(projectTargets, target)) {
+ return activeConfigs;
+ }
// inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = configs.begin();
+ i != configs.end(); ++i) {
const char* propertyValue =
target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str());
- if(cmSystemTools::IsOff(propertyValue))
- {
+ if (cmSystemTools::IsOff(propertyValue)) {
activeConfigs.insert(*i);
- }
}
+ }
return activeConfigs;
}
-//----------------------------------------------------------------------------
-static cmVS7FlagTable cmVS7ExtraFlagTable[] =
+bool cmGlobalVisualStudio7Generator::IsDependedOn(
+ OrderedTargetDependSet const& projectTargets, cmGeneratorTarget const* gtIn)
{
- // Precompiled header and related options. Note that the
- // UsePrecompiledHeader entries are marked as "Continue" so that the
- // corresponding PrecompiledHeaderThrough entry can be found.
- {"UsePrecompiledHeader", "YX", "Automatically Generate", "2",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired},
- {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired},
- {"WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "TRUE", 0},
-
- // Exception handling mode. If no entries match, it will be FALSE.
- {"ExceptionHandling", "GX", "enable c++ exceptions", "TRUE", 0},
- {"ExceptionHandling", "EHsc", "enable c++ exceptions", "TRUE", 0},
- // The EHa option does not have an IDE setting. Let it go to false,
- // and have EHa passed on the command line by leaving out the table
- // entry.
+ for (OrderedTargetDependSet::const_iterator l = projectTargets.begin();
+ l != projectTargets.end(); ++l) {
+ TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(*l);
+ if (tgtdeps.count(gtIn)) {
+ return true;
+ }
+ }
+ return false;
+}
- {0,0,0,0,0}
-};
-cmIDEFlagTable const* cmGlobalVisualStudio7Generator::GetExtraFlagTableVS7()
+std::string cmGlobalVisualStudio7Generator::Encoding()
{
- return cmVS7ExtraFlagTable;
+ return "UTF-8";
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 4d22cff88..32a8d6056 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -1,18 +1,10 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio7Generator_h
#define cmGlobalVisualStudio7Generator_h
#include "cmGlobalVisualStudioGenerator.h"
+
#include "cmGlobalGeneratorFactory.h"
class cmTarget;
@@ -26,139 +18,159 @@ struct cmIDEFlagTable;
class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator
{
public:
- cmGlobalVisualStudio7Generator(const char* platformName = NULL);
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalVisualStudio7Generator>(); }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio7Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 7";}
+ cmGlobalVisualStudio7Generator(cmake* cm,
+ const std::string& platformName = "");
+ ~cmGlobalVisualStudio7Generator();
///! Get the name for the platform.
- const char* GetPlatformName() const { return this->PlatformName.c_str(); }
+ std::string const& GetPlatformName() const;
///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
- virtual void AddPlatformDefinitions(cmMakefile* mf);
+ virtual bool SetSystemName(std::string const& s, cmMakefile* mf);
- /** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
/**
- * Try to determine system infomation such as shared library
- * extension, pthreads, byte order etc.
+ * Utilized by the generator factory to determine if this generator
+ * supports toolsets.
*/
- virtual void EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *, bool optional);
+ static bool SupportsToolset() { return false; }
/**
- * Try running cmake and building a file. This is used for dynamically
- * loaded commands, not as part of the usual build process.
+ * Utilized by the generator factory to determine if this generator
+ * supports platforms.
*/
- virtual std::string GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
- const char *projectDir,
- const char* additionalOptions,
- const char *targetName,
- const char* config,
- bool ignoreErrors,
- bool fast);
+ static bool SupportsPlatform() { return false; }
/**
- * 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.
+ * Try to determine system information such as shared library
+ * extension, pthreads, byte order etc.
*/
- virtual void Generate();
+ virtual void EnableLanguage(std::vector<std::string> const& languages,
+ cmMakefile*, bool optional);
/**
- * Generate the DSW workspace file.
+ * Try running cmake and building a file. This is used for dynamically
+ * loaded commands, not as part of the usual build process.
*/
- virtual void OutputSLNFile();
+ 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>());
/**
- * Get the list of configurations
+ * Generate the DSW workspace file.
*/
- std::vector<std::string> *GetConfigurations();
+ virtual void OutputSLNFile();
- ///! Create a GUID or get an existing one.
- void CreateGUID(const char* name);
- std::string GetGUID(const char* name);
+ ///! 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 char* prefix,
- const char* config,
- const char* suffix,
+ virtual void AppendDirectoryForConfig(const std::string& prefix,
+ const std::string& config,
+ const std::string& suffix,
std::string& dir);
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGIntDir() const { return "$(OutDir)"; }
+ virtual const char* GetCMakeCFGIntDir() const
+ {
+ return "$(ConfigurationName)";
+ }
/** Return true if the target project file should have the option
LinkLibraryDependencies and link to .sln dependencies. */
- virtual bool NeedLinkLibraryDependencies(cmTarget&) { return false; }
+ virtual bool NeedLinkLibraryDependencies(cmGeneratorTarget*)
+ {
+ return false;
+ }
+
+ const char* GetIntelProjectVersion();
+
+ bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+
+ /** Is the Microsoft Assembler enabled? */
+ bool IsMasmEnabled() const { return this->MasmEnabled; }
+ bool IsNasmEnabled() const { return this->NasmEnabled; }
+
+ // Encoding for Visual Studio files
+ virtual std::string Encoding();
+
+ cmIDEFlagTable const* ExtraFlagTable;
protected:
- virtual const char* GetIDEVersion() { return "7.0"; }
+ virtual void Generate();
+ virtual const char* GetIDEVersion() = 0;
+
+ std::string const& GetDevEnvCommand();
+ virtual std::string FindDevEnvCommand();
+
+ static const char* ExternalProjectType(const char* location);
- static cmIDEFlagTable const* GetExtraFlagTableVS7();
virtual void OutputSLNFile(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators);
- virtual void WriteProject(std::ostream& fout,
- const char* name, const char* path, cmTarget &t);
- virtual void WriteProjectDepends(std::ostream& fout,
- const char* name, const char* path, cmTarget &t);
+ std::vector<cmLocalGenerator*>& generators) = 0;
+ virtual void WriteProject(std::ostream& fout, const std::string& name,
+ const char* path, const cmGeneratorTarget* t) = 0;
+ virtual void WriteProjectDepends(std::ostream& fout, const std::string& name,
+ const char* path,
+ cmGeneratorTarget const* t) = 0;
virtual void WriteProjectConfigurations(
- std::ostream& fout, const char* name, cmTarget::TargetType type,
+ std::ostream& fout, const std::string& name,
+ cmGeneratorTarget const& target, std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const char* platformMapping = NULL);
+ const std::string& platformMapping = "") = 0;
virtual void WriteSLNGlobalSections(std::ostream& fout,
cmLocalGenerator* root);
virtual void WriteSLNFooter(std::ostream& fout);
- virtual void WriteSLNHeader(std::ostream& fout);
- virtual std::string WriteUtilityDepend(cmTarget* target);
+ virtual void WriteSLNHeader(std::ostream& fout) = 0;
+ virtual std::string WriteUtilityDepend(const cmGeneratorTarget* target);
virtual void WriteTargetsToSolution(
- std::ostream& fout,
- cmLocalGenerator* root,
+ std::ostream& fout, cmLocalGenerator* root,
OrderedTargetDependSet const& projectTargets);
virtual void WriteTargetDepends(
- std::ostream& fout,
- OrderedTargetDependSet const& projectTargets);
+ std::ostream& fout, OrderedTargetDependSet const& projectTargets);
virtual void WriteTargetConfigurations(
- std::ostream& fout,
- cmLocalGenerator* root,
+ std::ostream& fout, std::vector<std::string> const& configs,
OrderedTargetDependSet const& projectTargets);
- void GenerateConfigurations(cmMakefile* mf);
-
- virtual void WriteExternalProject(std::ostream& fout,
- const char* name,
- const char* path,
- const char* typeGuid,
- const std::set<cmStdString>&
- dependencies);
+ virtual void WriteExternalProject(
+ std::ostream& fout, const std::string& name, const char* path,
+ const char* typeGuid, const std::set<std::string>& dependencies) = 0;
std::string ConvertToSolutionPath(const char* path);
- std::set<std::string> IsPartOfDefaultBuild(const char* project,
- cmTarget* target);
- std::vector<std::string> Configurations;
- std::map<cmStdString, cmStdString> GUIDMap;
+ std::set<std::string> IsPartOfDefaultBuild(
+ std::vector<std::string> const& configs,
+ OrderedTargetDependSet const& projectTargets,
+ cmGeneratorTarget const* target);
+ bool IsDependedOn(OrderedTargetDependSet const& projectTargets,
+ cmGeneratorTarget const* target);
+ std::map<std::string, std::string> GUIDMap;
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 PlatformName;
+ std::string GeneratorPlatform;
+ std::string DefaultPlatformName;
+ bool MasmEnabled;
+ bool NasmEnabled;
+
+private:
+ char* IntelProjectVersion;
+ std::string DevEnvCommand;
+ bool DevEnvCommandInitialized;
+ virtual std::string GetVSMakeProgram() { return this->GetDevEnvCommand(); }
};
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index e4244e062..f06a8a1c6 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -1,139 +1,151 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "windows.h" // this must be first to define GetCurrentDirectory
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio8Generator.h"
+
+#include "cmDocumentationEntry.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmSourceFile.h"
#include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h"
-#include "cmGeneratedFileStream.h"
static const char vs8generatorName[] = "Visual Studio 8 2005";
-class cmGlobalVisualStudio8Generator::Factory
- : public cmGlobalGeneratorFactory
+class cmGlobalVisualStudio8Generator::Factory : public cmGlobalGeneratorFactory
{
public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(strstr(name, vs8generatorName) != name)
- {
+ 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 + sizeof(vs8generatorName) - 1;
- if(p[0] == '\0')
- {
- return new cmGlobalVisualStudio8Generator(
- name, NULL, NULL);
- }
+ const char* p = name.c_str() + sizeof(vs8generatorName) - 1;
+ if (p[0] == '\0') {
+ return new cmGlobalVisualStudio8Generator(cm, name, "");
+ }
- if(p[0] != ' ')
- {
+ if (p[0] != ' ') {
return 0;
- }
+ }
++p;
- if(!strcmp(p, "Win64"))
- {
- return new cmGlobalVisualStudio8Generator(
- name, "x64", "CMAKE_FORCE_WIN64");
- }
+ if (!strcmp(p, "Win64")) {
+ return new cmGlobalVisualStudio8Generator(cm, name, "x64");
+ }
cmVisualStudioWCEPlatformParser parser(p);
parser.ParseVersion("8.0");
- if (!parser.Found())
- {
+ if (!parser.Found()) {
return 0;
- }
+ }
- cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator(
- name, p, NULL);
+ cmGlobalVisualStudio8Generator* ret =
+ new cmGlobalVisualStudio8Generator(cm, name, p);
ret->WindowsCEVersion = parser.GetOSVersion();
return ret;
}
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- entry.Name = vs8generatorName;
- entry.Brief = "Generates Visual Studio 8 2005 project files.";
- entry.Full =
- "It is possible to append a space followed by the platform name "
- "to create project files for a specific target platform. E.g. "
- "\"Visual Studio 8 2005 Win64\" will create project files for "
- "the x64 processor.";
+ 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\".";
}
- virtual void GetGenerators(std::vector<std::string>& names) const {
+ 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)
- {
+ 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(
- const char* name, const char* platformName,
- const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio71Generator(platformName)
+ cmake* cm, const std::string& name, const std::string& platformName)
+ : cmGlobalVisualStudio71Generator(cm, platformName)
{
- this->FindMakeProgramFile = "CMakeVS8FindMake.cmake";
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);
+}
- if (additionalPlatformDefinition)
- {
- this->AdditionalPlatformDefinition = additionalPlatformDefinition;
- }
+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";
+ if (cmSystemTools::ReadRegistryValue(vsxkey.c_str(), vsxcmd,
+ cmSystemTools::KeyWOW64_32)) {
+ cmSystemTools::ConvertToUnixSlashes(vsxcmd);
+ vsxcmd += "/VCExpress.exe";
+ return vsxcmd;
+ }
+ // Now look for devenv.
+ return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand();
}
-//----------------------------------------------------------------------------
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator()
+void cmGlobalVisualStudio8Generator::EnableLanguage(
+ std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
- cmLocalVisualStudio7Generator *lg =
- new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS8);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
- lg->SetGlobalGenerator(this);
- return lg;
+ for (std::vector<std::string>::const_iterator it = lang.begin();
+ it != lang.end(); ++it) {
+ if (*it == "ASM_MASM") {
+ this->MasmEnabled = true;
+ }
+ }
+ this->AddPlatformDefinitions(mf);
+ cmGlobalVisualStudio7Generator::EnableLanguage(lang, mf, optional);
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
{
- cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf);
-
- if(this->TargetsWindowsCE())
- {
+ if (this->TargetsWindowsCE()) {
mf->AddDefinition("CMAKE_VS_WINCE_VERSION",
- this->WindowsCEVersion.c_str());
+ this->WindowsCEVersion.c_str());
+ }
+}
+
+bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
+ cmMakefile* mf)
+{
+ if (this->DefaultPlatformName == "Win32") {
+ this->GeneratorPlatform = p;
+ return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf);
+ } else {
+ return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform(p, mf);
}
}
-//----------------------------------------------------------------------------
// ouput standard header for dsw file
void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
{
@@ -141,23 +153,21 @@ void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio 2005\n";
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio8Generator
-::GetDocumentation(cmDocumentationEntry& entry)
+std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
{
- entry.Name = cmGlobalVisualStudio8Generator::GetActualName();
- entry.Brief = "Generates Visual Studio 8 2005 project files.";
- entry.Full = "";
+ return "generate.stamp.list";
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Generator::Configure()
{
this->cmGlobalVisualStudio7Generator::Configure();
- this->CreateGUID(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
}
-//----------------------------------------------------------------------------
+bool cmGlobalVisualStudio8Generator::UseFolderProperty()
+{
+ return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty();
+}
+
std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory()
{
// Some VS8 sp0 versions cannot run macros.
@@ -170,39 +180,35 @@ std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory()
"InstalledProducts\\KB926748;";
std::string vc8sp1;
if (!cmSystemTools::ReadRegistryValue(vc8sp1Registry, vc8sp1) &&
- !cmSystemTools::ReadRegistryValue(vc8exSP1Registry, 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))
- {
+ "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";
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio8Generator::AddCheckTarget()
+bool cmGlobalVisualStudio8Generator::AddCheckTarget()
{
// Add a special target on which all other targets depend that
// checks the build system and optionally re-runs CMake.
@@ -214,182 +220,183 @@ void cmGlobalVisualStudio8Generator::AddCheckTarget()
cmMakefile* mf = lg->GetMakefile();
// Skip the target if no regeneration is to be done.
- if(mf->IsOn("CMAKE_SUPPRESS_REGENERATION"))
- {
- return;
- }
+ if (mf->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return false;
+ }
- std::string cmake_command = mf->GetRequiredDefinition("CMAKE_COMMAND");
cmCustomCommandLines noCommandLines;
cmTarget* tgt =
mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
- no_working_directory, no_depends,
- noCommandLines);
+ no_working_directory, no_depends, noCommandLines);
+
+ cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg);
+ lg->AddGeneratorTarget(gt);
// Organize in the "predefined targets" folder:
//
- if (this->UseFolderProperty())
- {
+ if (this->UseFolderProperty()) {
tgt->SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
- }
+ }
// Create a list of all stamp files for this project.
std::vector<std::string> stamps;
std::string stampList = cmake::GetCMakeFilesDirectoryPostSlash();
- stampList += "generate.stamp.list";
+ stampList += cmGlobalVisualStudio8Generator::GetGenerateStampList();
{
- std::string stampListFile =
- generators[0]->GetMakefile()->GetCurrentOutputDirectory();
- stampListFile += "/";
- stampListFile += stampList;
- std::string stampFile;
- cmGeneratedFileStream fout(stampListFile.c_str());
- for(std::vector<cmLocalGenerator*>::const_iterator
- gi = generators.begin(); gi != generators.end(); ++gi)
- {
- stampFile = (*gi)->GetMakefile()->GetCurrentOutputDirectory();
- stampFile += "/";
- stampFile += cmake::GetCMakeFilesDirectoryPostSlash();
- stampFile += "generate.stamp";
- fout << stampFile << "\n";
- stamps.push_back(stampFile);
+ std::string stampListFile =
+ generators[0]->GetMakefile()->GetCurrentBinaryDirectory();
+ stampListFile += "/";
+ stampListFile += stampList;
+ std::string stampFile;
+ cmGeneratedFileStream fout(stampListFile.c_str());
+ for (std::vector<cmLocalGenerator*>::const_iterator gi =
+ generators.begin();
+ gi != generators.end(); ++gi) {
+ stampFile = (*gi)->GetMakefile()->GetCurrentBinaryDirectory();
+ stampFile += "/";
+ stampFile += cmake::GetCMakeFilesDirectoryPostSlash();
+ stampFile += "generate.stamp";
+ fout << stampFile << "\n";
+ stamps.push_back(stampFile);
}
}
// Add a custom rule to re-run CMake if any input files changed.
{
- // 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());
+ // 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());
}
- // 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());
-
- // Create a rule to re-run CMake.
- std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash();
- stampName += "generate.stamp";
- const char* dsprule = mf->GetRequiredDefinition("CMAKE_COMMAND");
- cmCustomCommandLine commandLine;
- commandLine.push_back(dsprule);
- std::string argH = "-H";
- argH += lg->Convert(mf->GetHomeDirectory(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED, true);
- commandLine.push_back(argH);
- std::string argB = "-B";
- argB += lg->Convert(mf->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED, true);
- commandLine.push_back(argB);
- commandLine.push_back("--check-stamp-list");
- commandLine.push_back(stampList.c_str());
- commandLine.push_back("--vs-solution-file");
- commandLine.push_back("\"$(SolutionPath)\"");
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
-
- // 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)
- const char* no_main_dependency = 0;
- if(cmSourceFile* file =
- mf->AddCustomCommandToOutput(
- stamps, listFiles,
- no_main_dependency, commandLines, "Checking Build System",
- no_working_directory, true))
- {
- tgt->AddSourceFile(file);
- }
- else
- {
- cmSystemTools::Error("Error adding rule for ", stamps[0].c_str());
+ // 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());
+
+ // 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);
+
+ // 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;
+ 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());
+ } else {
+ cmSystemTools::Error("Error adding rule for ", stamps[0].c_str());
}
}
+
+ return true;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio8Generator::Generate()
+void cmGlobalVisualStudio8Generator::AddExtraIDETargets()
{
- this->AddCheckTarget();
-
- // All targets depend on the build-system check target.
- for(std::map<cmStdString,cmTarget *>::const_iterator
- ti = this->TotalTargets.begin();
- ti != this->TotalTargets.end(); ++ti)
- {
- if(ti->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
- {
- ti->second->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+ cmGlobalVisualStudio7Generator::AddExtraIDETargets();
+ if (this->AddCheckTarget()) {
+ for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
+ 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);
+ }
}
}
-
- // Now perform the main generation.
- this->cmGlobalVisualStudio7Generator::Generate();
+ }
}
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudio8Generator
-::WriteSolutionConfigurations(std::ostream& fout)
+void cmGlobalVisualStudio8Generator::WriteSolutionConfigurations(
+ std::ostream& fout, std::vector<std::string> const& configs)
{
fout << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- fout << "\t\t" << *i << "|" << this->GetPlatformName()
- << " = " << *i << "|" << this->GetPlatformName() << "\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";
+ }
fout << "\tEndGlobalSection\n";
}
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudio8Generator
-::WriteProjectConfigurations(
- std::ostream& fout, const char* name, cmTarget::TargetType type,
+void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
+ std::ostream& fout, const std::string& name, cmGeneratorTarget const& target,
+ std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const char* platformMapping)
+ std::string const& platformMapping)
{
std::string guid = this->GetGUID(name);
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- fout << "\t\t{" << guid << "}." << *i
- << "|" << this->GetPlatformName() << ".ActiveCfg = " << *i << "|"
- << (platformMapping ? platformMapping : this->GetPlatformName())
+ for (std::vector<std::string>::const_iterator i = configs.begin();
+ i != configs.end(); ++i) {
+ std::vector<std::string> mapConfig;
+ 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);
+ if (!mapConfig.empty()) {
+ dstConfig = mapConfig[0].c_str();
+ }
+ }
+ }
+ 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);
- if(!(ci == configsPartOfDefaultBuild.end()))
- {
- fout << "\t\t{" << guid << "}." << *i
- << "|" << this->GetPlatformName() << ".Build.0 = " << *i << "|"
- << (platformMapping ? platformMapping : this->GetPlatformName())
+ std::set<std::string>::const_iterator ci =
+ configsPartOfDefaultBuild.find(*i);
+ if (!(ci == configsPartOfDefaultBuild.end())) {
+ fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
+ << ".Build.0 = " << dstConfig << "|"
+ << (!platformMapping.empty() ? platformMapping
+ : this->GetPlatformName())
<< "\n";
- }
- bool needsDeploy = (type == cmTarget::EXECUTABLE ||
- type == cmTarget::SHARED_LIBRARY);
- if(this->TargetsWindowsCE() && needsDeploy)
- {
- fout << "\t\t{" << guid << "}." << *i
- << "|" << this->GetPlatformName() << ".Deploy.0 = " << *i << "|"
- << (platformMapping ? platformMapping : this->GetPlatformName())
+ }
+ if (this->NeedsDeploy(target.GetType())) {
+ fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
+ << ".Deploy.0 = " << dstConfig << "|"
+ << (!platformMapping.empty() ? platformMapping
+ : this->GetPlatformName())
<< "\n";
- }
}
+ }
+}
+
+bool cmGlobalVisualStudio8Generator::NeedsDeploy(
+ cmStateEnums::TargetType type) const
+{
+ bool needsDeploy =
+ (type == cmStateEnums::EXECUTABLE || type == cmStateEnums::SHARED_LIBRARY);
+ return this->TargetsWindowsCE() && needsDeploy;
}
-//----------------------------------------------------------------------------
bool cmGlobalVisualStudio8Generator::ComputeTargetDepends()
{
// Skip over the cmGlobalVisualStudioGenerator implementation!
@@ -397,78 +404,76 @@ bool cmGlobalVisualStudio8Generator::ComputeTargetDepends()
return this->cmGlobalGenerator::ComputeTargetDepends();
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Generator::WriteProjectDepends(
- std::ostream& fout, const char*, const char*, cmTarget& t)
+ std::ostream& fout, const std::string&, const char*,
+ cmGeneratorTarget const* gt)
{
- TargetDependSet const& unordered = this->GetTargetDirectDepends(t);
- OrderedTargetDependSet depends(unordered);
- for(OrderedTargetDependSet::const_iterator i = depends.begin();
- i != depends.end(); ++i)
- {
- std::string guid = this->GetGUID((*i)->GetName());
- fout << "\t\t{" << guid << "} = {" << guid << "}\n";
+ 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) {
+ continue;
}
+ std::string guid = this->GetGUID((*i)->GetName().c_str());
+ fout << "\t\t{" << guid << "} = {" << guid << "}\n";
+ }
}
-//----------------------------------------------------------------------------
bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies(
- cmTarget& target)
+ cmGeneratorTarget* target)
{
// Look for utility dependencies that magically link.
- for(std::set<cmStdString>::const_iterator ui =
- target.GetUtilities().begin();
- ui != target.GetUtilities().end(); ++ui)
- {
- if(cmTarget* depTarget = this->FindTarget(0, ui->c_str()))
- {
- if(depTarget->GetProperty("EXTERNAL_MSPROJECT"))
- {
+ for (std::set<std::string>::const_iterator ui =
+ target->GetUtilities().begin();
+ ui != target->GetUtilities().end(); ++ui) {
+ if (cmGeneratorTarget* depTarget =
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(ui->c_str())) {
+ if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ depTarget->GetProperty("EXTERNAL_MSPROJECT")) {
// This utility dependency names an external .vcproj target.
// We use LinkLibraryDependencies="true" to link to it without
// predicting the .lib file location or name.
return true;
- }
}
}
+ }
return false;
}
-//----------------------------------------------------------------------------
-static cmVS7FlagTable cmVS8ExtraFlagTable[] =
-{
- {"CallingConvention", "Gd", "cdecl", "0", 0 },
- {"CallingConvention", "Gr", "fastcall", "1", 0 },
- {"CallingConvention", "Gz", "stdcall", "2", 0 },
-
- {"Detect64BitPortabilityProblems", "Wp64",
- "Detect 64Bit Portability Problems", "true", 0 },
- {"ErrorReporting", "errorReport:prompt", "Report immediately", "1", 0 },
- {"ErrorReporting", "errorReport:queue", "Queue for next login", "2", 0 },
+static cmVS7FlagTable cmVS8ExtraFlagTable[] = {
+ { "CallingConvention", "Gd", "cdecl", "0", 0 },
+ { "CallingConvention", "Gr", "fastcall", "1", 0 },
+ { "CallingConvention", "Gz", "stdcall", "2", 0 },
+
+ { "Detect64BitPortabilityProblems", "Wp64",
+ "Detect 64Bit Portability Problems", "true", 0 },
+ { "ErrorReporting", "errorReport:prompt", "Report immediately", "1", 0 },
+ { "ErrorReporting", "errorReport:queue", "Queue for next login", "2", 0 },
// Precompiled header and related options. Note that the
// UsePrecompiledHeader entries are marked as "Continue" so that the
// corresponding PrecompiledHeaderThrough entry can be found.
- {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "2",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired},
+ { "UsePrecompiledHeader", "Yu", "Use Precompiled Header", "2",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+ { "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
+ cmVS7FlagTable::UserValueRequired },
// There is no YX option in the VS8 IDE.
// Exception handling mode. If no entries match, it will be FALSE.
- {"ExceptionHandling", "GX", "enable c++ exceptions", "1", 0},
- {"ExceptionHandling", "EHsc", "enable c++ exceptions", "1", 0},
- {"ExceptionHandling", "EHa", "enable SEH exceptions", "2", 0},
+ { "ExceptionHandling", "GX", "enable c++ exceptions", "1", 0 },
+ { "ExceptionHandling", "EHsc", "enable c++ exceptions", "1", 0 },
+ { "ExceptionHandling", "EHa", "enable SEH exceptions", "2", 0 },
- {"EnablePREfast", "analyze", "", "true", 0},
- {"EnablePREfast", "analyze-", "", "false", 0},
+ { "EnablePREfast", "analyze", "", "true", 0 },
+ { "EnablePREfast", "analyze-", "", "false", 0 },
// Language options
- {"TreatWChar_tAsBuiltInType", "Zc:wchar_t",
- "wchar_t is a built-in type", "true", 0},
- {"TreatWChar_tAsBuiltInType", "Zc:wchar_t-",
- "wchar_t is not a built-in type", "false", 0},
+ { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "wchar_t is a built-in type",
+ "true", 0 },
+ { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-",
+ "wchar_t is not a built-in type", "false", 0 },
- {0,0,0,0,0}
+ { 0, 0, 0, 0, 0 }
};
cmIDEFlagTable const* cmGlobalVisualStudio8Generator::GetExtraFlagTableVS8()
{
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index d18174275..4723b83ba 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -1,20 +1,10 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio8Generator_h
#define cmGlobalVisualStudio8Generator_h
#include "cmGlobalVisualStudio71Generator.h"
-
/** \class cmGlobalVisualStudio8Generator
* \brief Write a Unix makefiles.
*
@@ -23,27 +13,27 @@
class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
{
public:
- cmGlobalVisualStudio8Generator(const char* name,
- const char* platformName, const char* additionalPlatformDefinition);
+ cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name,
+ const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
- virtual const char* GetName() const {return this->Name.c_str();}
+ virtual std::string GetName() const { return this->Name; }
- /** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
-
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ /** 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);
virtual void AddPlatformDefinitions(cmMakefile* mf);
+ virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
+
/**
* Override Configure and Generate to add the build-system check
* target.
*/
virtual void Configure();
- virtual void Generate();
/**
* Where does this version of Visual Studio look for macros for the
@@ -60,32 +50,49 @@ public:
/** Return true if the target project file should have the option
LinkLibraryDependencies and link to .sln dependencies. */
- virtual bool NeedLinkLibraryDependencies(cmTarget& target);
+ virtual bool NeedLinkLibraryDependencies(cmGeneratorTarget* target);
/** Return true if building for Windows CE */
- virtual bool TargetsWindowsCE() const {
- return !this->WindowsCEVersion.empty(); }
+ virtual bool TargetsWindowsCE() const
+ {
+ 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"; }
+ virtual std::string FindDevEnvCommand();
+
virtual bool VSLinksDependencies() const { return false; }
- void AddCheckTarget();
+ bool AddCheckTarget();
+
+ /** Return true if the configuration needs to be deployed */
+ virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
static cmIDEFlagTable const* GetExtraFlagTableVS8();
virtual void WriteSLNHeader(std::ostream& fout);
- virtual void WriteSolutionConfigurations(std::ostream& fout);
+ virtual void WriteSolutionConfigurations(
+ std::ostream& fout, std::vector<std::string> const& configs);
virtual void WriteProjectConfigurations(
- std::ostream& fout, const char* name, cmTarget::TargetType type,
+ std::ostream& fout, const std::string& name,
+ cmGeneratorTarget const& target, std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const char* platformMapping = NULL);
+ const std::string& platformMapping = "");
virtual bool ComputeTargetDepends();
- virtual void WriteProjectDepends(std::ostream& fout, const char* name,
- const char* path, cmTarget &t);
+ virtual void WriteProjectDepends(std::ostream& fout, const std::string& name,
+ const char* path,
+ const cmGeneratorTarget* t);
+
+ bool UseFolderProperty();
std::string Name;
std::string WindowsCEVersion;
+ bool ExpressEdition;
private:
class Factory;
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index fba6ed1ee..b1634e2ca 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -1,16 +1,8 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "windows.h" // this must be first to define GetCurrentDirectory
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio9Generator.h"
+
+#include "cmDocumentationEntry.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmVisualStudioWCEPlatformParser.h"
@@ -18,66 +10,57 @@
static const char vs9generatorName[] = "Visual Studio 9 2008";
-class cmGlobalVisualStudio9Generator::Factory
- : public cmGlobalGeneratorFactory
+class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory
{
public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(strstr(name, vs9generatorName) != name)
- {
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE
+ {
+ if (strncmp(name.c_str(), vs9generatorName,
+ sizeof(vs9generatorName) - 1) != 0) {
return 0;
- }
+ }
- const char* p = name + sizeof(vs9generatorName) - 1;
- if(p[0] == '\0')
- {
- return new cmGlobalVisualStudio9Generator(
- name, NULL, NULL);
- }
+ const char* p = name.c_str() + sizeof(vs9generatorName) - 1;
+ if (p[0] == '\0') {
+ return new cmGlobalVisualStudio9Generator(cm, name, "");
+ }
- if(p[0] != ' ')
- {
+ if (p[0] != ' ') {
return 0;
- }
+ }
++p;
- if(!strcmp(p, "IA64"))
- {
- return new cmGlobalVisualStudio9Generator(
- name, "Itanium", "CMAKE_FORCE_IA64");
- }
+ if (!strcmp(p, "IA64")) {
+ return new cmGlobalVisualStudio9Generator(cm, name, "Itanium");
+ }
- if(!strcmp(p, "Win64"))
- {
- return new cmGlobalVisualStudio9Generator(
- name, "x64", "CMAKE_FORCE_WIN64");
- }
+ if (!strcmp(p, "Win64")) {
+ return new cmGlobalVisualStudio9Generator(cm, name, "x64");
+ }
cmVisualStudioWCEPlatformParser parser(p);
parser.ParseVersion("9.0");
- if (!parser.Found())
- {
+ if (!parser.Found()) {
return 0;
- }
+ }
- cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator(
- name, p, NULL);
+ cmGlobalVisualStudio9Generator* ret =
+ new cmGlobalVisualStudio9Generator(cm, name, p);
ret->WindowsCEVersion = parser.GetOSVersion();
return ret;
}
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- entry.Name = vs9generatorName;
- entry.Brief = "Generates Visual Studio 9 2008 project files.";
- entry.Full =
- "It is possible to append a space followed by the platform name "
- "to create project files for a specific target platform. E.g. "
- "\"Visual Studio 9 2008 Win64\" will create project files for "
- "the x64 processor; \"Visual Studio 9 2008 IA64\" for Itanium.";
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ {
+ entry.Name = std::string(vs9generatorName) + " [arch]";
+ entry.Brief = "Generates Visual Studio 2008 project files. "
+ "Optional [arch] can be \"Win64\" or \"IA64\".";
}
- virtual void GetGenerators(std::vector<std::string>& names) const {
+ void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ {
names.push_back(vs9generatorName);
names.push_back(vs9generatorName + std::string(" Win64"));
names.push_back(vs9generatorName + std::string(" IA64"));
@@ -85,57 +68,40 @@ public:
parser.ParseVersion("9.0");
const std::vector<std::string>& availablePlatforms =
parser.GetAvailablePlatforms();
- for(std::vector<std::string>::const_iterator i =
- availablePlatforms.begin(); i != availablePlatforms.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i =
+ availablePlatforms.begin();
+ i != availablePlatforms.end(); ++i) {
names.push_back("Visual Studio 9 2008 " + *i);
- }
+ }
}
+
+ bool SupportsToolset() const CM_OVERRIDE { return false; }
+ bool SupportsPlatform() const CM_OVERRIDE { return true; }
};
-//----------------------------------------------------------------------------
cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory()
{
return new Factory;
}
-//----------------------------------------------------------------------------
cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
- const char* name, const char* platformName,
- const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio8Generator(name, platformName,
- additionalPlatformDefinition)
+ cmake* cm, const std::string& name, const std::string& platformName)
+ : cmGlobalVisualStudio8Generator(cm, name, platformName)
{
- this->FindMakeProgramFile = "CMakeVS9FindMake.cmake";
+ this->Version = VS9;
+ std::string vc9Express;
+ this->ExpressEdition = cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\9.0\\Setup\\VC;"
+ "ProductDir",
+ 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";
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio9Generator::CreateLocalGenerator()
-{
- cmLocalVisualStudio7Generator *lg
- = new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS9);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
- lg->SetGlobalGenerator(this);
- return lg;
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio9Generator
-::EnableLanguage(std::vector<std::string>const & lang,
- cmMakefile *mf, bool optional)
-{
- cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
-}
-
-//----------------------------------------------------------------------------
std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory()
{
std::string base;
@@ -143,26 +109,24 @@ std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory()
// base begins with the VisualStudioProjectsLocation reg value...
if (cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\9.0;"
- "VisualStudioProjectsLocation",
- base))
- {
+ "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\9.0;"
+ "VisualStudioProjectsLocation",
+ base)) {
cmSystemTools::ConvertToUnixSlashes(base);
// 9.0 macros folder:
path = base + "/VSMacros80";
- // *NOT* a typo; right now in Visual Studio 2008 beta the macros
- // folder is VSMacros80... They may change it to 90 before final
- // release of 2008 or they may not... we'll have to keep our eyes
- // on it
- }
+ // *NOT* a typo; right now in Visual Studio 2008 beta the macros
+ // folder is VSMacros80... They may change it to 90 before final
+ // release of 2008 or they may not... we'll have to keep our eyes
+ // on it
+ }
// path is (correctly) still empty if we did not read the base value from
// the Registry value
return path;
}
-//----------------------------------------------------------------------------
std::string cmGlobalVisualStudio9Generator::GetUserMacrosRegKeyBase()
{
return "Software\\Microsoft\\VisualStudio\\9.0\\vsmacros";
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index 202aa8d12..fbc1f5d07 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -1,42 +1,26 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudio9Generator_h
#define cmGlobalVisualStudio9Generator_h
#include "cmGlobalVisualStudio8Generator.h"
-
/** \class cmGlobalVisualStudio9Generator
* \brief Write a Unix makefiles.
*
* cmGlobalVisualStudio9Generator manages UNIX build process for a tree
*/
-class cmGlobalVisualStudio9Generator :
- public cmGlobalVisualStudio8Generator
+class cmGlobalVisualStudio9Generator : public cmGlobalVisualStudio8Generator
{
public:
- cmGlobalVisualStudio9Generator(const char* name,
- const char* platformName, const char* additionalPlatformDefinition);
+ cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name,
+ const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- ///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
- * Try to determine system infomation such as shared library
+ * 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);
/**
@@ -51,6 +35,7 @@ public:
* Studio?
*/
virtual std::string GetUserMacrosRegKeyBase();
+
protected:
virtual const char* GetIDEVersion() { return "9.0"; }
private:
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 59310162c..bbff48eb6 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -1,206 +1,155 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudioGenerator.h"
+#include "cmsys/Encoding.hxx"
+#include <iostream>
+#include <windows.h>
+
+#include "cmAlgorithms.h"
#include "cmCallVisualStudioMacro.h"
+#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudioGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmState.h"
#include "cmTarget.h"
-//----------------------------------------------------------------------------
-cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
+cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm)
+ : cmGlobalGenerator(cm)
{
- this->AdditionalPlatformDefinition = NULL;
+ cm->GetState()->SetIsGeneratorMultiConfig(true);
+ cm->GetState()->SetWindowsShell(true);
+ cm->GetState()->SetWindowsVSIDE(true);
}
-//----------------------------------------------------------------------------
cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
{
}
-//----------------------------------------------------------------------------
+cmGlobalVisualStudioGenerator::VSVersion
+cmGlobalVisualStudioGenerator::GetVersion() const
+{
+ return this->Version;
+}
+
+void cmGlobalVisualStudioGenerator::SetVersion(VSVersion v)
+{
+ this->Version = v;
+}
+
std::string cmGlobalVisualStudioGenerator::GetRegistryBase()
{
- return cmGlobalVisualStudioGenerator::GetRegistryBase(
- this->GetIDEVersion());
+ return cmGlobalVisualStudioGenerator::GetRegistryBase(this->GetIDEVersion());
}
-//----------------------------------------------------------------------------
-std::string cmGlobalVisualStudioGenerator::GetRegistryBase(
- const char* version)
+std::string cmGlobalVisualStudioGenerator::GetRegistryBase(const char* version)
{
std::string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\";
return key + version;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudioGenerator::Generate()
+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;
std::vector<std::string> no_depends;
cmCustomCommandLines no_commands;
- std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
- for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
- {
+ 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;
// add the ALL_BUILD to the first local generator of each project
- if(gen.size())
- {
+ 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");
-
-#if 0
- // Can't activate this code because we want ALL_BUILD
- // selected as the default "startup project" when first
- // opened in Visual Studio... And if it's nested in a
- // folder, then that doesn't happen.
+ cmTarget* allBuild = gen[0]->GetMakefile()->AddUtilityCommand(
+ "ALL_BUILD", true, no_working_dir, no_depends, no_commands, false,
+ "Build all projects");
+
+ cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]);
+ gen[0]->AddGeneratorTarget(gt);
+
//
// Organize in the "predefined targets" folder:
//
- if (this->UseFolderProperty())
- {
+ if (this->UseFolderProperty()) {
allBuild->SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
- }
-#endif
+ }
// Now make all targets depend on the ALL_BUILD target
- for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
- i != gen.end(); ++i)
- {
- cmTargets& targets = (*i)->GetMakefile()->GetTargets();
- for(cmTargets::iterator t = targets.begin();
- t != targets.end(); ++t)
- {
- if(!this->IsExcluded(gen[0], t->second))
- {
- allBuild->AddUtility(t->second.GetName());
- }
+ 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;
+ if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET ||
+ tgt->IsImported()) {
+ continue;
+ }
+ if (!this->IsExcluded(gen[0], tgt)) {
+ allBuild->AddUtility(tgt->GetName());
}
}
}
}
+ }
// 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)
- {
+ for (std::vector<cmLocalGenerator*>::const_iterator lgi =
+ this->LocalGenerators.begin();
+ lgi != this->LocalGenerators.end(); ++lgi) {
cmLocalVisualStudioGenerator* lg =
static_cast<cmLocalVisualStudioGenerator*>(*lgi);
lg->AddCMakeListsRules();
- }
-
- // Run all the local generators.
- this->cmGlobalGenerator::Generate();
-}
-
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudioGenerator
-::ComputeTargetObjects(cmGeneratorTarget* gt) const
-{
- cmLocalVisualStudioGenerator* lg =
- static_cast<cmLocalVisualStudioGenerator*>(gt->LocalGenerator);
- std::string dir_max = lg->ComputeLongestObjectDirectory(*gt->Target);
-
- // Count the number of object files with each name. Note that
- // windows file names are not case sensitive.
- std::map<cmStdString, int> counts;
- for(std::vector<cmSourceFile*>::const_iterator
- si = gt->ObjectSources.begin();
- si != gt->ObjectSources.end(); ++si)
- {
- cmSourceFile* sf = *si;
- std::string objectNameLower = cmSystemTools::LowerCase(
- cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
- objectNameLower += ".obj";
- counts[objectNameLower] += 1;
- }
-
- // For all source files producing duplicate names we need unique
- // object name computation.
- for(std::vector<cmSourceFile*>::const_iterator
- si = gt->ObjectSources.begin();
- si != gt->ObjectSources.end(); ++si)
- {
- cmSourceFile* sf = *si;
- std::string objectName =
- cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
- objectName += ".obj";
- if(counts[cmSystemTools::LowerCase(objectName)] > 1)
- {
- gt->ExplicitObjectName.insert(sf);
- objectName = lg->GetObjectFileNameWithoutTarget(*sf, dir_max);
- }
- gt->Objects[sf] = objectName;
- }
+ }
+}
- std::string dir = gt->Makefile->GetCurrentOutputDirectory();
+void cmGlobalVisualStudioGenerator::ComputeTargetObjectDirectory(
+ cmGeneratorTarget* gt) const
+{
+ std::string dir = gt->LocalGenerator->GetCurrentBinaryDirectory();
dir += "/";
- std::string tgtDir = lg->GetTargetDirectory(*gt->Target);
- if(!tgtDir.empty())
- {
+ std::string tgtDir = gt->LocalGenerator->GetTargetDirectory(gt);
+ if (!tgtDir.empty()) {
dir += tgtDir;
dir += "/";
- }
+ }
const char* cd = this->GetCMakeCFGIntDir();
- if(cd && *cd)
- {
+ if (cd && *cd) {
dir += cd;
dir += "/";
- }
+ }
gt->ObjectDirectory = dir;
}
-//----------------------------------------------------------------------------
bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
- const std::string& regKeyBase,
- std::string& nextAvailableSubKeyName);
+ const std::string& regKeyBase,
+ std::string& nextAvailableSubKeyName);
void RegisterVisualStudioMacros(const std::string& macrosFile,
- const std::string& regKeyBase);
+ const std::string& regKeyBase);
-//----------------------------------------------------------------------------
-#define CMAKE_VSMACROS_FILENAME \
- "CMakeVSMacros2.vsmacros"
+#define CMAKE_VSMACROS_FILENAME "CMakeVSMacros2.vsmacros"
-#define CMAKE_VSMACROS_RELOAD_MACRONAME \
+#define CMAKE_VSMACROS_RELOAD_MACRONAME \
"Macros.CMakeVSMacros2.Macros.ReloadProjects"
-#define CMAKE_VSMACROS_STOP_MACRONAME \
- "Macros.CMakeVSMacros2.Macros.StopBuild"
+#define CMAKE_VSMACROS_STOP_MACRONAME "Macros.CMakeVSMacros2.Macros.StopBuild"
-//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
{
- cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
std::string dir = this->GetUserMacrosDirectory();
- if (mf != 0 && dir != "")
- {
- std::string src = mf->GetRequiredDefinition("CMAKE_ROOT");
+ if (dir != "") {
+ std::string src = cmSystemTools::GetCMakeRoot();
src += "/Templates/" CMAKE_VSMACROS_FILENAME;
std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
@@ -211,27 +160,22 @@ 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.c_str(), dst.c_str(), &res) ||
+ res > 0) {
+ if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str())) {
std::ostringstream oss;
oss << "Could not copy from: " << src << std::endl;
oss << " to: " << dst << std::endl;
cmSystemTools::Message(oss.str().c_str(), "Warning");
- }
}
+ }
RegisterVisualStudioMacros(dst, this->GetUserMacrosRegKeyBase());
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmGlobalVisualStudioGenerator
-::CallVisualStudioMacro(MacroName m,
- const char* vsSolutionFile)
+void cmGlobalVisualStudioGenerator::CallVisualStudioMacro(
+ MacroName m, const char* vsSolutionFile)
{
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
@@ -239,172 +183,143 @@ cmGlobalVisualStudioGenerator
std::string dir = this->GetUserMacrosDirectory();
// Only really try to call the macro if:
- // - mf is non-NULL
// - there is a UserMacrosDirectory
// - the CMake vsmacros file exists
// - the CMake vsmacros file is registered
// - there were .sln/.vcproj files changed during generation
//
- if (mf != 0 && dir != "")
- {
+ if (dir != "") {
std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
std::string nextSubkeyName;
if (cmSystemTools::FileExists(macrosFile.c_str()) &&
- IsVisualStudioMacrosFileRegistered(macrosFile,
- this->GetUserMacrosRegKeyBase(), nextSubkeyName)
- )
- {
+ IsVisualStudioMacrosFileRegistered(
+ macrosFile, this->GetUserMacrosRegKeyBase(), nextSubkeyName)) {
std::string topLevelSlnName;
- if(vsSolutionFile)
- {
+ if (vsSolutionFile) {
topLevelSlnName = vsSolutionFile;
- }
- else
- {
- topLevelSlnName = mf->GetStartOutputDirectory();
+ } else {
+ topLevelSlnName = mf->GetCurrentBinaryDirectory();
topLevelSlnName += "/";
- topLevelSlnName += mf->GetProjectName();
+ topLevelSlnName += this->LocalGenerators[0]->GetProjectName();
topLevelSlnName += ".sln";
- }
+ }
- if(m == MacroReload)
- {
+ if (m == MacroReload) {
std::vector<std::string> filenames;
this->GetFilesReplacedDuringGenerate(filenames);
- if (filenames.size() > 0)
- {
+ 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())
- {
+ if (it != filenames.end()) {
projects = *it;
++it;
- }
- for (; it != filenames.end(); ++it)
- {
+ }
+ for (; it != filenames.end(); ++it) {
projects += ";";
projects += *it;
- }
- cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
- CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
- this->GetCMakeInstance()->GetDebugOutput());
}
+ cmCallVisualStudioMacro::CallMacro(
+ topLevelSlnName, CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
+ this->GetCMakeInstance()->GetDebugOutput());
}
- else if(m == MacroStop)
- {
- cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
- CMAKE_VSMACROS_STOP_MACRONAME, "",
+ } else if (m == MacroStop) {
+ cmCallVisualStudioMacro::CallMacro(
+ topLevelSlnName, CMAKE_VSMACROS_STOP_MACRONAME, "",
this->GetCMakeInstance()->GetDebugOutput());
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory()
{
return "";
}
-//----------------------------------------------------------------------------
std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase()
{
return "";
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudioGenerator::FillLinkClosure(cmTarget* target,
- TargetSet& linked)
+void cmGlobalVisualStudioGenerator::FillLinkClosure(
+ const cmGeneratorTarget* target, TargetSet& linked)
{
- 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())
- {
+ 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);
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
cmGlobalVisualStudioGenerator::TargetSet const&
-cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmTarget* target)
+cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmGeneratorTarget* target)
{
TargetSetMap::iterator i = this->TargetLinkClosure.find(target);
- if(i == this->TargetLinkClosure.end())
- {
+ if (i == this->TargetLinkClosure.end()) {
TargetSetMap::value_type entry(target, TargetSet());
i = this->TargetLinkClosure.insert(entry).first;
this->FillLinkClosure(target, i->second);
- }
+ }
return i->second;
}
-//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::FollowLinkDepends(
- cmTarget* target, std::set<cmTarget*>& linked)
+ const cmGeneratorTarget* target, std::set<const cmGeneratorTarget*>& linked)
{
- if(linked.insert(target).second &&
- target->GetType() == cmTarget::STATIC_LIBRARY)
- {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
+ if (linked.insert(target).second &&
+ target->GetType() == cmStateEnums::STATIC_LIBRARY) {
// 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())
- {
+ TargetDependSet const& depends = this->GetTargetDirectDepends(target);
+ for (TargetDependSet::const_iterator di = depends.begin();
+ di != depends.end(); ++di) {
+ if (di->IsLink()) {
this->FollowLinkDepends(*di, linked);
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
bool cmGlobalVisualStudioGenerator::ComputeTargetDepends()
{
- if(!this->cmGlobalGenerator::ComputeTargetDepends())
- {
+ if (!this->cmGlobalGenerator::ComputeTargetDepends()) {
return false;
- }
- std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
- for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
- {
+ }
+ 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)
- {
- cmTargets& targets = (*i)->GetMakefile()->GetTargets();
- for(cmTargets::iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
- this->ComputeVSTargetDepends(ti->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);
}
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-static bool VSLinkable(cmTarget* t)
+static bool VSLinkable(cmGeneratorTarget const* t)
{
- return t->IsLinkable() || t->GetType() == cmTarget::OBJECT_LIBRARY;
+ return t->IsLinkable() || t->GetType() == cmStateEnums::OBJECT_LIBRARY;
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
+void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(
+ cmGeneratorTarget* target)
{
- if(this->VSTargetDepends.find(&target) != this->VSTargetDepends.end())
- {
+ if (this->VSTargetDepends.find(target) != this->VSTargetDepends.end()) {
return;
- }
- VSDependSet& vsTargetDepend = this->VSTargetDepends[&target];
+ }
+ VSDependSet& vsTargetDepend = this->VSTargetDepends[target];
// VS <= 7.1 has two behaviors that affect solution dependencies.
//
// (1) Solution-level dependencies between a linkable target and a
@@ -424,106 +339,113 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
// leaving them out for the static library itself but following them
// transitively for other targets.
- bool allowLinkable = (target.GetType() != cmTarget::STATIC_LIBRARY &&
- target.GetType() != cmTarget::SHARED_LIBRARY &&
- target.GetType() != cmTarget::MODULE_LIBRARY &&
- target.GetType() != cmTarget::EXECUTABLE);
+ bool allowLinkable = (target->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ target->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ target->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ target->GetType() != cmStateEnums::EXECUTABLE);
TargetDependSet const& depends = this->GetTargetDirectDepends(target);
// Collect implicit link dependencies (target_link_libraries).
// Static libraries cannot depend on their link implementation
// due to behavior (2), but they do not really need to.
- std::set<cmTarget*> linkDepends;
- if(target.GetType() != cmTarget::STATIC_LIBRARY)
- {
- for(TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di)
- {
+ 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(dep, linkDepends);
- }
+ if (dep.IsLink()) {
+ this->FollowLinkDepends(*di, linkDepends);
}
}
+ }
// Collect explicit util dependencies (add_dependencies).
- std::set<cmTarget*> utilDepends;
- for(TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di)
- {
+ std::set<cmGeneratorTarget const*> utilDepends;
+ for (TargetDependSet::const_iterator di = depends.begin();
+ di != depends.end(); ++di) {
cmTargetDepend dep = *di;
- if(dep.IsUtil())
- {
- this->FollowLinkDepends(dep, utilDepends);
- }
+ if (dep.IsUtil()) {
+ this->FollowLinkDepends(*di, utilDepends);
}
+ }
// Collect all targets linked by this target so we can avoid
// intermediate targets below.
TargetSet linked;
- if(target.GetType() != cmTarget::STATIC_LIBRARY)
- {
- linked = this->GetTargetLinkClosure(&target);
- }
+ if (target->GetType() != cmStateEnums::STATIC_LIBRARY) {
+ linked = this->GetTargetLinkClosure(target);
+ }
// Emit link dependencies.
- for(std::set<cmTarget*>::iterator di = linkDepends.begin();
- di != linkDepends.end(); ++di)
- {
- cmTarget* dep = *di;
+ for (std::set<cmGeneratorTarget const*>::iterator di = linkDepends.begin();
+ di != linkDepends.end(); ++di) {
+ cmGeneratorTarget const* dep = *di;
vsTargetDepend.insert(dep->GetName());
- }
+ }
// Emit util dependencies. Possibly use intermediate targets.
- for(std::set<cmTarget*>::iterator di = utilDepends.begin();
- di != utilDepends.end(); ++di)
- {
- cmTarget* dep = *di;
- if(allowLinkable || !VSLinkable(dep) || linked.count(dep))
- {
+ for (std::set<cmGeneratorTarget const*>::iterator di = utilDepends.begin();
+ di != utilDepends.end(); ++di) {
+ cmGeneratorTarget const* dgt = *di;
+ if (allowLinkable || !VSLinkable(dgt) || linked.count(dgt)) {
// Direct dependency allowed.
- vsTargetDepend.insert(dep->GetName());
- }
- else
- {
+ vsTargetDepend.insert(dgt->GetName());
+ } else {
// Direct dependency on linkable target not allowed.
// Use an intermediate utility target.
- vsTargetDepend.insert(this->GetUtilityDepend(dep));
- }
+ vsTargetDepend.insert(this->GetUtilityDepend(dgt));
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf)
+bool cmGlobalVisualStudioGenerator::FindMakeProgram(cmMakefile* mf)
{
- if(this->AdditionalPlatformDefinition)
- {
- mf->AddDefinition(this->AdditionalPlatformDefinition, "TRUE");
- }
+ // 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());
+ }
+ return true;
}
-//----------------------------------------------------------------------------
-std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(cmTarget* target)
+std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(
+ cmGeneratorTarget const* target)
{
UtilityDependsMap::iterator i = this->UtilityDepends.find(target);
- if(i == this->UtilityDepends.end())
- {
+ if (i == this->UtilityDepends.end()) {
std::string name = this->WriteUtilityDepend(target);
UtilityDependsMap::value_type entry(target, name);
i = this->UtilityDepends.insert(entry).first;
- }
+ }
return i->second;
}
-//----------------------------------------------------------------------------
-#include <windows.h>
+std::string cmGlobalVisualStudioGenerator::GetStartupProjectName(
+ cmLocalGenerator const* root) const
+{
+ const char* n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT");
+ if (n && *n) {
+ std::string startup = n;
+ if (this->FindTarget(startup)) {
+ return startup;
+ } else {
+ root->GetMakefile()->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ "Directory property VS_STARTUP_PROJECT specifies target "
+ "'" +
+ startup + "' that does not exist. Ignoring.");
+ }
+ }
+
+ // default, if not specified
+ return this->GetAllTargetName();
+}
-//----------------------------------------------------------------------------
bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
- const std::string& regKeyBase,
- std::string& nextAvailableSubKeyName)
+ const std::string& regKeyBase,
+ std::string& nextAvailableSubKeyName)
{
bool macrosRegistered = false;
@@ -542,97 +464,88 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
keyname = regKeyBase + "\\OtherProjects7";
hkey = NULL;
- result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
- 0, KEY_READ, &hkey);
- if (ERROR_SUCCESS == result)
- {
+ result =
+ RegOpenKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(keyname).c_str(),
+ 0, KEY_READ, &hkey);
+ if (ERROR_SUCCESS == result) {
// Iterate the subkeys and look for the values of interest in each subkey:
- CHAR subkeyname[256];
- DWORD cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
- CHAR keyclass[256];
- DWORD cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
+ wchar_t subkeyname[256];
+ DWORD cch_subkeyname = sizeof(subkeyname) * sizeof(subkeyname[0]);
+ wchar_t keyclass[256];
+ DWORD cch_keyclass = sizeof(keyclass) * sizeof(keyclass[0]);
FILETIME lastWriteTime;
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
- while (ERROR_SUCCESS == RegEnumKeyEx(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 = RegOpenKeyEx(hkey, subkeyname, 0, KEY_READ, &hsubkey);
- if (ERROR_SUCCESS == result)
- {
+ result = RegOpenKeyExW(hkey, subkeyname, 0, KEY_READ, &hsubkey);
+ if (ERROR_SUCCESS == result) {
DWORD valueType = REG_SZ;
- CHAR data1[256];
- DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
- RegQueryValueEx(hsubkey, "Path", 0, &valueType,
- (LPBYTE) &data1[0], &cch_data1);
+ wchar_t data1[256];
+ DWORD cch_data1 = sizeof(data1) * sizeof(data1[0]);
+ RegQueryValueExW(hsubkey, L"Path", 0, &valueType, (LPBYTE)&data1[0],
+ &cch_data1);
DWORD data2 = 0;
DWORD cch_data2 = sizeof(data2);
- RegQueryValueEx(hsubkey, "Security", 0, &valueType,
- (LPBYTE) &data2, &cch_data2);
+ RegQueryValueExW(hsubkey, L"Security", 0, &valueType, (LPBYTE)&data2,
+ &cch_data2);
DWORD data3 = 0;
DWORD cch_data3 = sizeof(data3);
- RegQueryValueEx(hsubkey, "StorageFormat", 0, &valueType,
- (LPBYTE) &data3, &cch_data3);
+ RegQueryValueExW(hsubkey, L"StorageFormat", 0, &valueType,
+ (LPBYTE)&data3, &cch_data3);
- s2 = cmSystemTools::LowerCase(data1);
+ s2 = cmSystemTools::LowerCase(cmsys::Encoding::ToNarrow(data1));
cmSystemTools::ConvertToUnixSlashes(s2);
- if (s2 == s1)
- {
+ if (s2 == s1) {
macrosRegistered = true;
- }
+ }
- std::string fullname(data1);
+ std::string fullname = cmsys::Encoding::ToNarrow(data1);
std::string filename;
std::string filepath;
std::string filepathname;
std::string filepathpath;
- if (cmSystemTools::FileExists(fullname.c_str()))
- {
+ if (cmSystemTools::FileExists(fullname.c_str())) {
filename = cmSystemTools::GetFilenameName(fullname);
filepath = cmSystemTools::GetFilenamePath(fullname);
filepathname = cmSystemTools::GetFilenameName(filepath);
filepathpath = cmSystemTools::GetFilenamePath(filepath);
- }
+ }
- //std::cout << keyname << "\\" << subkeyname << ":" << std::endl;
- //std::cout << " Path: " << data1 << std::endl;
- //std::cout << " Security: " << data2 << std::endl;
- //std::cout << " StorageFormat: " << data3 << std::endl;
- //std::cout << " filename: " << filename << std::endl;
- //std::cout << " filepath: " << filepath << std::endl;
- //std::cout << " filepathname: " << filepathname << std::endl;
- //std::cout << " filepathpath: " << filepathpath << std::endl;
- //std::cout << std::endl;
+ // std::cout << keyname << "\\" << subkeyname << ":" << std::endl;
+ // std::cout << " Path: " << data1 << std::endl;
+ // std::cout << " Security: " << data2 << std::endl;
+ // std::cout << " StorageFormat: " << data3 << std::endl;
+ // std::cout << " filename: " << filename << std::endl;
+ // std::cout << " filepath: " << filepath << std::endl;
+ // std::cout << " filepathname: " << filepathname << std::endl;
+ // std::cout << " filepathpath: " << filepathpath << std::endl;
+ // std::cout << std::endl;
RegCloseKey(hsubkey);
- }
- else
- {
+ } else {
std::cout << "error opening subkey: " << subkeyname << std::endl;
std::cout << std::endl;
- }
+ }
++index;
- cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
- cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
+ cch_subkeyname = sizeof(subkeyname) * sizeof(subkeyname[0]);
+ cch_keyclass = sizeof(keyclass) * sizeof(keyclass[0]);
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
- }
+ }
RegCloseKey(hkey);
- }
- else
- {
+ } else {
std::cout << "error opening key: " << keyname << std::endl;
std::cout << std::endl;
- }
-
+ }
// Pass back next available sub key name, assuming sub keys always
// follow the expected naming scheme. Expected naming scheme is that
@@ -642,137 +555,124 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
ossNext << index;
nextAvailableSubKeyName = ossNext.str();
-
keyname = regKeyBase + "\\RecordingProject7";
hkey = NULL;
- result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
- 0, KEY_READ, &hkey);
- if (ERROR_SUCCESS == result)
- {
+ result =
+ RegOpenKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(keyname).c_str(),
+ 0, KEY_READ, &hkey);
+ if (ERROR_SUCCESS == result) {
DWORD valueType = REG_SZ;
- CHAR data1[256];
- DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
- RegQueryValueEx(hkey, "Path", 0, &valueType,
- (LPBYTE) &data1[0], &cch_data1);
+ wchar_t data1[256];
+ DWORD cch_data1 = sizeof(data1) * sizeof(data1[0]);
+ RegQueryValueExW(hkey, L"Path", 0, &valueType, (LPBYTE)&data1[0],
+ &cch_data1);
DWORD data2 = 0;
DWORD cch_data2 = sizeof(data2);
- RegQueryValueEx(hkey, "Security", 0, &valueType,
- (LPBYTE) &data2, &cch_data2);
+ RegQueryValueExW(hkey, L"Security", 0, &valueType, (LPBYTE)&data2,
+ &cch_data2);
DWORD data3 = 0;
DWORD cch_data3 = sizeof(data3);
- RegQueryValueEx(hkey, "StorageFormat", 0, &valueType,
- (LPBYTE) &data3, &cch_data3);
+ RegQueryValueExW(hkey, L"StorageFormat", 0, &valueType, (LPBYTE)&data3,
+ &cch_data3);
- s2 = cmSystemTools::LowerCase(data1);
+ s2 = cmSystemTools::LowerCase(cmsys::Encoding::ToNarrow(data1));
cmSystemTools::ConvertToUnixSlashes(s2);
- if (s2 == s1)
- {
+ if (s2 == s1) {
macrosRegistered = true;
- }
+ }
- //std::cout << keyname << ":" << std::endl;
- //std::cout << " Path: " << data1 << std::endl;
- //std::cout << " Security: " << data2 << std::endl;
- //std::cout << " StorageFormat: " << data3 << std::endl;
- //std::cout << std::endl;
+ // std::cout << keyname << ":" << std::endl;
+ // std::cout << " Path: " << data1 << std::endl;
+ // std::cout << " Security: " << data2 << std::endl;
+ // std::cout << " StorageFormat: " << data3 << std::endl;
+ // std::cout << std::endl;
RegCloseKey(hkey);
- }
- else
- {
+ } else {
std::cout << "error opening key: " << keyname << std::endl;
std::cout << std::endl;
- }
+ }
return macrosRegistered;
}
-//----------------------------------------------------------------------------
-void WriteVSMacrosFileRegistryEntry(
- const std::string& nextAvailableSubKeyName,
- const std::string& macrosFile,
- const std::string& regKeyBase)
+void WriteVSMacrosFileRegistryEntry(const std::string& nextAvailableSubKeyName,
+ const std::string& macrosFile,
+ const std::string& regKeyBase)
{
std::string keyname = regKeyBase + "\\OtherProjects7";
HKEY hkey = NULL;
- LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0,
- KEY_READ|KEY_WRITE, &hkey);
- if (ERROR_SUCCESS == result)
- {
+ LONG result =
+ RegOpenKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(keyname).c_str(),
+ 0, KEY_READ | KEY_WRITE, &hkey);
+ if (ERROR_SUCCESS == result) {
// Create the subkey and set the values of interest:
HKEY hsubkey = NULL;
- char lpClass[] = "";
- result = RegCreateKeyEx(hkey, nextAvailableSubKeyName.c_str(), 0,
- lpClass, 0, KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
- if (ERROR_SUCCESS == result)
- {
+ wchar_t lpClass[] = L"";
+ result = RegCreateKeyExW(
+ hkey, cmsys::Encoding::ToWide(nextAvailableSubKeyName).c_str(), 0,
+ lpClass, 0, KEY_READ | KEY_WRITE, 0, &hsubkey, 0);
+ if (ERROR_SUCCESS == result) {
DWORD dw = 0;
std::string s(macrosFile);
- cmSystemTools::ReplaceString(s, "/", "\\");
+ std::replace(s.begin(), s.end(), '/', '\\');
+ std::wstring ws = cmsys::Encoding::ToWide(s);
- result = RegSetValueEx(hsubkey, "Path", 0, REG_SZ, (LPBYTE) s.c_str(),
- static_cast<DWORD>(strlen(s.c_str()) + 1));
- if (ERROR_SUCCESS != result)
- {
+ result =
+ RegSetValueExW(hsubkey, L"Path", 0, REG_SZ, (LPBYTE)ws.c_str(),
+ static_cast<DWORD>(ws.size() + 1) * sizeof(wchar_t));
+ if (ERROR_SUCCESS != result) {
std::cout << "error result 1: " << result << std::endl;
std::cout << std::endl;
- }
+ }
// Security value is always "1" for sample macros files (seems to be "2"
// if you put the file somewhere outside the standard VSMacros folder)
dw = 1;
- result = RegSetValueEx(hsubkey, "Security",
- 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
- if (ERROR_SUCCESS != result)
- {
+ result = RegSetValueExW(hsubkey, L"Security", 0, REG_DWORD, (LPBYTE)&dw,
+ sizeof(DWORD));
+ if (ERROR_SUCCESS != result) {
std::cout << "error result 2: " << result << std::endl;
std::cout << std::endl;
- }
+ }
// StorageFormat value is always "0" for sample macros files
dw = 0;
- result = RegSetValueEx(hsubkey, "StorageFormat",
- 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
- if (ERROR_SUCCESS != result)
- {
+ result = RegSetValueExW(hsubkey, L"StorageFormat", 0, REG_DWORD,
+ (LPBYTE)&dw, sizeof(DWORD));
+ if (ERROR_SUCCESS != result) {
std::cout << "error result 3: " << result << std::endl;
std::cout << std::endl;
- }
+ }
RegCloseKey(hsubkey);
- }
- else
- {
- std::cout << "error creating subkey: "
- << nextAvailableSubKeyName << std::endl;
+ } else {
+ std::cout << "error creating subkey: " << nextAvailableSubKeyName
+ << std::endl;
std::cout << std::endl;
- }
- RegCloseKey(hkey);
}
- else
- {
+ RegCloseKey(hkey);
+ } else {
std::cout << "error opening key: " << keyname << std::endl;
std::cout << std::endl;
- }
+ }
}
-//----------------------------------------------------------------------------
void RegisterVisualStudioMacros(const std::string& macrosFile,
- const std::string& regKeyBase)
+ const std::string& regKeyBase)
{
bool macrosRegistered;
std::string nextAvailableSubKeyName;
- macrosRegistered = IsVisualStudioMacrosFileRegistered(macrosFile,
- regKeyBase, nextAvailableSubKeyName);
+ macrosRegistered = IsVisualStudioMacrosFileRegistered(
+ macrosFile, regKeyBase, nextAvailableSubKeyName);
- if (!macrosRegistered)
- {
- int count = cmCallVisualStudioMacro::
- GetNumberOfRunningVisualStudioInstances("ALL");
+ if (!macrosRegistered) {
+ int count =
+ cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances("ALL");
// Only register the macros file if there are *no* instances of Visual
// Studio running. If we register it while one is running, first, it has
@@ -781,18 +681,16 @@ void RegisterVisualStudioMacros(const std::string& macrosFile,
// emit a warning asking the user to exit all running Visual Studio
// instances...
//
- if (0 != count)
- {
+ if (0 != count) {
std::ostringstream oss;
oss << "Could not register CMake's Visual Studio macros file '"
- << CMAKE_VSMACROS_FILENAME "' while Visual Studio is running."
- << " Please exit all running instances of Visual Studio before"
- << " continuing." << std::endl
- << std::endl
- << "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;
+ << CMAKE_VSMACROS_FILENAME "' while Visual Studio is running."
+ << " Please exit all running instances of Visual Studio before"
+ << " continuing." << std::endl
+ << std::endl
+ << "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");
// Count them again now that the warning is over. In the case of a GUI
@@ -800,78 +698,229 @@ void RegisterVisualStudioMacros(const std::string& macrosFile,
// back to the CMake GUI and clicked ok on the above warning. If so,
// then register the macros *now* if the count is *now* 0...
//
- count = cmCallVisualStudioMacro::
- GetNumberOfRunningVisualStudioInstances("ALL");
+ count = cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances(
+ "ALL");
// Also re-get the nextAvailableSubKeyName in case Visual Studio
// wrote out new registered macros information as it was exiting:
//
- if (0 == count)
- {
+ if (0 == count) {
IsVisualStudioMacrosFileRegistered(macrosFile, regKeyBase,
- nextAvailableSubKeyName);
- }
+ nextAvailableSubKeyName);
}
+ }
// Do another if check - 'count' may have changed inside the above if:
//
- if (0 == count)
- {
+ if (0 == count) {
WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile,
- regKeyBase);
- }
+ regKeyBase);
}
+ }
}
-bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget& target)
+bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
+ cmGeneratorTarget const* gt)
{
// check to see if this is a fortran build
- std::set<cmStdString> languages;
- target.GetLanguages(languages);
- if(languages.size() == 1)
- {
- if(*languages.begin() == "Fortran")
- {
+ 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;
+ }
+ }
+ // 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::TargetCompare
-::operator()(cmTarget const* l, cmTarget const* r) const
+bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
+ cmGeneratorTarget const* gt)
{
- // Make sure ALL_BUILD is first so it is the default active project.
- if(strcmp(r->GetName(), "ALL_BUILD") == 0)
- {
- return false;
+ // 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;
}
- if(strcmp(l->GetName(), "ALL_BUILD") == 0)
- {
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
+ cmGeneratorTarget const* gt)
+{
+ if (this->TargetIsCSharpOnly(gt)) {
return true;
- }
- return strcmp(l->GetName(), r->GetName()) < 0;
+ }
+ if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ gt->GetType() != cmStateEnums::EXECUTABLE) {
+ return false;
+ }
+ return true;
}
-//----------------------------------------------------------------------------
-cmGlobalVisualStudioGenerator::OrderedTargetDependSet
-::OrderedTargetDependSet(TargetDependSet const& targets)
+bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
+ cmGeneratorTarget const* l, cmGeneratorTarget const* r) const
{
- for(TargetDependSet::const_iterator ti =
- targets.begin(); ti != targets.end(); ++ti)
- {
- this->insert(*ti);
- }
+ // 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 l->GetName() < r->GetName();
}
-//----------------------------------------------------------------------------
-cmGlobalVisualStudioGenerator::OrderedTargetDependSet
-::OrderedTargetDependSet(TargetSet const& targets)
+cmGlobalVisualStudioGenerator::OrderedTargetDependSet::OrderedTargetDependSet(
+ TargetDependSet const& targets, std::string const& first)
+ : derived(TargetCompare(first))
{
- for(TargetSet::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
- this->insert(*ti);
+ this->insert(targets.begin(), targets.end());
+}
+
+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);
+ }
+}
+
+std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir(
+ const std::string& str, const std::string& config) const
+{
+ std::string replace = GetCMakeCFGIntDir();
+
+ std::string tmp = str;
+ for (std::string::size_type i = tmp.find(replace); i != std::string::npos;
+ i = tmp.find(replace, i)) {
+ tmp.replace(i, replace.size(), config);
+ i += config.size();
+ }
+ return tmp;
+}
+
+void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
+ cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands,
+ std::string const& configName)
+{
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ gt->GetModuleDefinitionInfo(configName);
+ if (!mdi || !mdi->DefFileGenerated) {
+ return;
+ }
+
+ std::vector<std::string> outputs;
+ outputs.push_back(mdi->DefFile);
+ std::vector<std::string> empty;
+ 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];
+ }
+ 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());
+ return;
+ }
+
+ if (mdi->WindowsExportAllSymbols) {
+ std::vector<std::string> objs;
+ for (std::vector<cmSourceFile const*>::const_iterator it =
+ objectSources.begin();
+ it != objectSources.end(); ++it) {
+ // 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;
+ 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 (std::vector<std::string>::iterator it = objs.begin();
+ it != objs.end(); ++it) {
+ std::string objFile = *it;
+ // replace $(ConfigurationName) in the object names
+ cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
+ configName.c_str());
+ if (cmHasLiteralSuffix(objFile, ".obj")) {
+ fout << objFile << "\n";
+ }
}
+ }
+
+ for (std::vector<cmSourceFile const*>::const_iterator i =
+ mdi->Sources.begin();
+ i != mdi->Sources.end(); ++i) {
+ fout << (*i)->GetFullPath() << "\n";
+ }
+
+ cmCustomCommandLines commandLines;
+ commandLines.push_back(cmdl);
+ cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty,
+ commandLines, "Auto build dll exports", ".");
+ commands.push_back(command);
}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index b665158c6..3c43ccdd2 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -1,18 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalVisualStudioGenerator_h
#define cmGlobalVisualStudioGenerator_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmGlobalGenerator.h"
+#include "cmTargetDepend.h"
+
+class cmCustomCommand;
+class cmGeneratorTarget;
+class cmLocalGenerator;
+class cmMakefile;
+class cmake;
/** \class cmGlobalVisualStudioGenerator
* \brief Base class for global Visual Studio generators.
@@ -23,13 +29,24 @@
class cmGlobalVisualStudioGenerator : public cmGlobalGenerator
{
public:
- cmGlobalVisualStudioGenerator();
+ /** 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
+ };
+
+ cmGlobalVisualStudioGenerator(cmake* cm);
virtual ~cmGlobalVisualStudioGenerator();
- /**
- * Basic generate implementation for all VS generators.
- */
- virtual void Generate();
+ VSVersion GetVersion() const;
+ void SetVersion(VSVersion v);
/**
* Configure CMake's Visual Studio macros file into the user's Visual
@@ -50,17 +67,26 @@ public:
*/
virtual std::string GetUserMacrosRegKeyBase();
- enum MacroName {MacroReload, MacroStop};
+ enum MacroName
+ {
+ MacroReload,
+ MacroStop
+ };
/**
* Call the ReloadProjects macro if necessary based on
* GetFilesReplacedDuringGenerate results.
*/
- virtual void CallVisualStudioMacro(MacroName m,
- const char* vsSolutionFile = 0);
+ void CallVisualStudioMacro(MacroName m, const char* vsSolutionFile = 0);
// return true if target is fortran only
- bool TargetIsFortranOnly(cmTarget& t);
+ 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();
@@ -70,19 +96,44 @@ 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() { return true; }
+ virtual bool IsMultiConfig() const { return true; }
/** Return true if building for Windows CE */
virtual bool TargetsWindowsCE() const { return false; }
- class TargetSet: public std::set<cmTarget*> {};
- struct TargetCompare
+ class TargetSet : public std::set<cmGeneratorTarget const*>
+ {
+ };
+ class TargetCompare
{
- bool operator()(cmTarget const* l, cmTarget const* r) const;
+ std::string First;
+
+ public:
+ TargetCompare(std::string const& first)
+ : First(first)
+ {
+ }
+ bool operator()(cmGeneratorTarget const* l,
+ cmGeneratorTarget const* r) const;
};
class OrderedTargetDependSet;
+ bool FindMakeProgram(cmMakefile*) CM_OVERRIDE;
+
+ virtual std::string ExpandCFGIntDir(const std::string& str,
+ const std::string& config) const;
+
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
+
+ std::string GetStartupProjectName(cmLocalGenerator const* root) const;
+
+ void AddSymbolExportCommand(cmGeneratorTarget*,
+ std::vector<cmCustomCommand>& commands,
+ std::string const& configName);
+
protected:
+ virtual void AddExtraIDETargets();
+
// 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.
@@ -90,42 +141,58 @@ protected:
virtual const char* GetIDEVersion() = 0;
- virtual void AddPlatformDefinitions(cmMakefile* mf);
-
virtual bool ComputeTargetDepends();
- class VSDependSet: public std::set<cmStdString> {};
- class VSDependMap: public std::map<cmTarget*, VSDependSet> {};
+ class VSDependSet : public std::set<std::string>
+ {
+ };
+ class VSDependMap : public std::map<cmGeneratorTarget const*, VSDependSet>
+ {
+ };
VSDependMap VSTargetDepends;
- void ComputeVSTargetDepends(cmTarget&);
-
- bool CheckTargetLinks(cmTarget& target, const char* name);
- std::string GetUtilityForTarget(cmTarget& target, const char*);
- virtual std::string WriteUtilityDepend(cmTarget*) = 0;
- std::string GetUtilityDepend(cmTarget* target);
- typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
+ void ComputeVSTargetDepends(cmGeneratorTarget*);
+
+ bool CheckTargetLinks(cmGeneratorTarget& target, const std::string& name);
+ std::string GetUtilityForTarget(cmGeneratorTarget& target,
+ const std::string&);
+ virtual std::string WriteUtilityDepend(cmGeneratorTarget const*) = 0;
+ std::string GetUtilityDepend(const cmGeneratorTarget* target);
+ typedef std::map<cmGeneratorTarget const*, std::string> UtilityDependsMap;
UtilityDependsMap UtilityDepends;
- const char* AdditionalPlatformDefinition;
+
+protected:
+ VSVersion Version;
private:
- void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+ virtual std::string GetVSMakeProgram() = 0;
+ void PrintCompilerAdvice(std::ostream&, std::string const&,
+ const char*) const
+ {
+ }
- void FollowLinkDepends(cmTarget* target, std::set<cmTarget*>& linked);
+ void FollowLinkDepends(cmGeneratorTarget const* target,
+ std::set<cmGeneratorTarget const*>& linked);
- class TargetSetMap: public std::map<cmTarget*, TargetSet> {};
+ class TargetSetMap : public std::map<cmGeneratorTarget*, TargetSet>
+ {
+ };
TargetSetMap TargetLinkClosure;
- void FillLinkClosure(cmTarget* target, TargetSet& linked);
- TargetSet const& GetTargetLinkClosure(cmTarget* target);
+ void FillLinkClosure(const cmGeneratorTarget* target, TargetSet& linked);
+ TargetSet const& GetTargetLinkClosure(cmGeneratorTarget* target);
};
-class cmGlobalVisualStudioGenerator::OrderedTargetDependSet:
- public std::multiset<cmTargetDepend,
- cmGlobalVisualStudioGenerator::TargetCompare>
+class cmGlobalVisualStudioGenerator::OrderedTargetDependSet
+ : public std::multiset<cmTargetDepend,
+ cmGlobalVisualStudioGenerator::TargetCompare>
{
+ typedef std::multiset<cmTargetDepend,
+ cmGlobalVisualStudioGenerator::TargetCompare>
+ derived;
+
public:
typedef cmGlobalGenerator::TargetDependSet TargetDependSet;
typedef cmGlobalVisualStudioGenerator::TargetSet TargetSet;
- OrderedTargetDependSet(TargetDependSet const&);
- OrderedTargetDependSet(TargetSet const&);
+ OrderedTargetDependSet(TargetDependSet const&, std::string const& first);
+ OrderedTargetDependSet(TargetSet const&, std::string const& first);
};
#endif
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index e3cebc4ac..94cdb3848 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -1,31 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalWatcomWMakeGenerator.h"
-#include "cmLocalUnixMakefileGenerator3.h"
+
+#include "cmDocumentationEntry.h"
#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmake.h"
-cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator()
+cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator(cmake* cm)
+ : cmGlobalUnixMakefileGenerator3(cm)
{
this->FindMakeProgramFile = "CMakeFindWMake.cmake";
+#ifdef _WIN32
this->ForceUnixPaths = false;
+#endif
this->ToolSupportsColor = true;
this->NeedSymbolicMark = true;
this->EmptyRuleHackCommand = "@cd .";
+#ifdef _WIN32
+ cm->GetState()->SetWindowsShell(true);
+#endif
+ cm->GetState()->SetWatcomWMake(true);
+ this->IncludeDirective = "!include";
+ this->DefineWindowsNULL = true;
+ this->UnixCD = false;
+ this->MakeSilentFlag = "-h";
}
-void cmGlobalWatcomWMakeGenerator
-::EnableLanguage(std::vector<std::string>const& l,
- cmMakefile *mf,
- bool optional)
+void cmGlobalWatcomWMakeGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
// pick a default
mf->AddDefinition("WATCOM", "1");
@@ -33,34 +36,14 @@ void cmGlobalWatcomWMakeGenerator
mf->AddDefinition("CMAKE_MANGLE_OBJECT_FILE_NAMES", "1");
mf->AddDefinition("CMAKE_MAKE_LINE_CONTINUE", "&");
mf->AddDefinition("CMAKE_MAKE_SYMBOLIC_RULE", ".SYMBOLIC");
- mf->AddDefinition("CMAKE_NO_QUOTED_OBJECTS", "1");
mf->AddDefinition("CMAKE_GENERATOR_CC", "wcl386");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "wcl386");
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalWatcomWMakeGenerator::CreateLocalGenerator()
-{
- cmLocalUnixMakefileGenerator3* lg = new cmLocalUnixMakefileGenerator3;
- lg->SetSilentNoColon(true);
- lg->SetDefineWindowsNULL(true);
- lg->SetWindowsShell(true);
- lg->SetWatcomWMake(true);
- lg->SetMakeSilentFlag("-s -h");
- lg->SetGlobalGenerator(this);
- lg->SetIgnoreLibPrefix(true);
- lg->SetPassMakeflags(false);
- lg->SetUnixCD(false);
- lg->SetIncludeDirective("!include");
- return lg;
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalWatcomWMakeGenerator
-::GetDocumentation(cmDocumentationEntry& entry)
+void cmGlobalWatcomWMakeGenerator::GetDocumentation(
+ cmDocumentationEntry& entry)
{
entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName();
entry.Brief = "Generates Watcom WMake makefiles.";
- entry.Full = "";
}
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index 23e60a1fc..b2d6d5d71 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -1,19 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalWatcomWMakeGenerator_h
#define cmGlobalWatcomWMakeGenerator_h
+#include "cmConfigure.h"
+
+#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <string>
+#include <vector>
+
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
+
/** \class cmGlobalWatcomWMakeGenerator
* \brief Write a NMake makefiles.
*
@@ -22,27 +23,30 @@
class cmGlobalWatcomWMakeGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
- cmGlobalWatcomWMakeGenerator();
- static cmGlobalGeneratorFactory* NewFactory() {
- return new cmGlobalGeneratorSimpleFactory
- <cmGlobalWatcomWMakeGenerator>(); }
+ cmGlobalWatcomWMakeGenerator(cmake* cm);
+ static cmGlobalGeneratorFactory* NewFactory()
+ {
+ return new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>();
+ }
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalWatcomWMakeGenerator::GetActualName();}
- static const char* GetActualName() {return "Watcom WMake";}
+ std::string GetName() const CM_OVERRIDE
+ {
+ return cmGlobalWatcomWMakeGenerator::GetActualName();
+ }
+ static std::string GetActualName() { return "Watcom WMake"; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
- * Try to determine system infomation such as shared library
+ * 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) CM_OVERRIDE;
+
+ bool AllowNotParallel() const CM_OVERRIDE { return false; }
+ bool AllowDeleteOnError() const CM_OVERRIDE { return false; }
};
#endif
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index c181c5926..903796123 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1,30 +1,39 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalXCodeGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
+#include <assert.h>
+#include <iomanip>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmGlobalXCodeGenerator.h"
-#include "cmLocalXCodeGenerator.h"
-#include "cmMakefile.h"
-#include "cmXCodeObject.h"
-#include "cmXCode21Object.h"
-#include "cmake.h"
-#include "cmGeneratedFileStream.h"
#include "cmComputeLinkInformation.h"
-#include "cmSourceFile.h"
#include "cmCustomCommandGenerator.h"
+#include "cmDocumentationEntry.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGeneratorFactory.h"
+#include "cmLocalGenerator.h"
+#include "cmLocalXCodeGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmSourceFile.h"
+#include "cmSourceGroup.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmXCode21Object.h"
+#include "cmXCodeObject.h"
+#include "cmXCodeScheme.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-#include <cmsys/auto_ptr.hxx>
+struct cmLinkImplementation;
-//----------------------------------------------------------------------------
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmXMLParser.h"
@@ -33,29 +42,25 @@
class cmXcodeVersionParser : public cmXMLParser
{
public:
- cmXcodeVersionParser(): Version("1.5") {}
- void StartElement(const char* , const char** )
- {
- this->Data = "";
- }
- void EndElement(const char* name)
- {
- if(strcmp(name, "key") == 0)
- {
- this->Key = this->Data;
- }
- else if(strcmp(name, "string") == 0)
- {
- if(this->Key == "CFBundleShortVersionString")
- {
- this->Version = this->Data;
- }
- }
+ cmXcodeVersionParser()
+ : Version("1.5")
+ {
+ }
+ void StartElement(const std::string&, const char**) { this->Data = ""; }
+ void EndElement(const std::string& name)
+ {
+ if (name == "key") {
+ this->Key = this->Data;
+ } else if (name == "string") {
+ if (this->Key == "CFBundleShortVersionString") {
+ this->Version = this->Data;
+ }
}
+ }
void CharacterDataHandler(const char* data, int length)
- {
- this->Data.append(data, length);
- }
+ {
+ this->Data.append(data, length);
+ }
std::string Version;
std::string Key;
std::string Data;
@@ -66,609 +71,576 @@ public:
// given inputs.
class cmGlobalXCodeGenerator::BuildObjectListOrString
{
- cmGlobalXCodeGenerator *Generator;
- cmXCodeObject *Group;
+ cmGlobalXCodeGenerator* Generator;
+ cmXCodeObject* Group;
bool Empty;
std::string String;
public:
- BuildObjectListOrString(cmGlobalXCodeGenerator *gen, bool buildObjectList)
- : Generator(gen), Group(0), Empty(true)
- {
- if (buildObjectList)
- {
+ BuildObjectListOrString(cmGlobalXCodeGenerator* gen, bool buildObjectList)
+ : Generator(gen)
+ , Group(0)
+ , Empty(true)
+ {
+ if (buildObjectList) {
this->Group = this->Generator->CreateObject(cmXCodeObject::OBJECT_LIST);
- }
}
+ }
bool IsEmpty() const { return this->Empty; }
- void Add(const char *newString)
- {
+ void Add(const std::string& newString)
+ {
this->Empty = false;
- if (this->Group)
- {
+ if (this->Group) {
this->Group->AddObject(this->Generator->CreateString(newString));
- }
- else
- {
+ } else {
this->String += newString;
this->String += ' ';
- }
}
+ }
- const std::string &GetString() const { return this->String; }
+ const std::string& GetString() const { return this->String; }
- cmXCodeObject *CreateList()
- {
- if (this->Group)
- {
+ cmXCodeObject* CreateList()
+ {
+ if (this->Group) {
return this->Group;
- }
- else
- {
- return this->Generator->CreateString(this->String.c_str());
- }
+ } else {
+ return this->Generator->CreateString(this->String);
}
+ }
};
class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory
{
public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const;
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const CM_OVERRIDE;
- virtual void GetDocumentation(cmDocumentationEntry& entry) const {
- cmGlobalXCodeGenerator::GetDocumentation(entry); }
+ void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ {
+ cmGlobalXCodeGenerator::GetDocumentation(entry);
+ }
- virtual void GetGenerators(std::vector<std::string>& names) const {
- names.push_back(cmGlobalXCodeGenerator::GetActualName()); }
+ void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ {
+ names.push_back(cmGlobalXCodeGenerator::GetActualName());
+ }
+
+ bool SupportsToolset() const CM_OVERRIDE { return true; }
+ bool SupportsPlatform() const CM_OVERRIDE { return false; }
};
-//----------------------------------------------------------------------------
-cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(std::string const& version)
+cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
+ cmake* cm, std::string const& version_string, unsigned int version_number)
+ : cmGlobalGenerator(cm)
{
- this->VersionString = version;
+ this->VersionString = version_string;
+ this->XcodeVersion = version_number;
- // Compute an integer form of the version number.
- unsigned int v[2] = {0,0};
- sscanf(this->VersionString.c_str(), "%u.%u", &v[0], &v[1]);
- this->XcodeVersion = 10*v[0] + v[1];
-
- this->FindMakeProgramFile = "CMakeFindXCode.cmake";
this->RootObject = 0;
this->MainGroupChildren = 0;
- this->SourcesGroupChildren = 0;
- this->ResourcesGroupChildren = 0;
this->CurrentMakefile = 0;
this->CurrentLocalGenerator = 0;
+ this->XcodeBuildCommandInitialized = false;
+
+ this->ObjectDirArchDefault = "$(CURRENT_ARCH)";
+ this->ObjectDirArch = this->ObjectDirArchDefault;
+
+ cm->GetState()->SetIsGeneratorMultiConfig(true);
}
-//----------------------------------------------------------------------------
cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory()
{
return new Factory;
}
-//----------------------------------------------------------------------------
-cmGlobalGenerator* cmGlobalXCodeGenerator::Factory
-::CreateGlobalGenerator(const char* name) const
+cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
+ const std::string& name, cmake* cm) const
{
- if (strcmp(name, GetActualName()))
+ if (name != GetActualName())
return 0;
#if defined(CMAKE_BUILD_WITH_CMAKE)
cmXcodeVersionParser parser;
std::string versionFile;
{
- std::string out;
- std::string::size_type pos;
- if(cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, 0, 0,
- cmSystemTools::OUTPUT_NONE) &&
- (pos = out.find(".app/"), pos != out.npos))
- {
- versionFile = out.substr(0, pos+5)+"Contents/version.plist";
+ 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";
}
}
- if(!versionFile.empty() && cmSystemTools::FileExists(versionFile.c_str()))
- {
+ if (!versionFile.empty() && cmSystemTools::FileExists(versionFile.c_str())) {
parser.ParseFile(versionFile.c_str());
- }
- else if (cmSystemTools::FileExists(
- "/Applications/Xcode.app/Contents/version.plist"))
- {
- parser.ParseFile
- ("/Applications/Xcode.app/Contents/version.plist");
- }
- else
- {
- parser.ParseFile
- ("/Developer/Applications/Xcode.app/Contents/version.plist");
- }
- cmsys::auto_ptr<cmGlobalXCodeGenerator>
- gg(new cmGlobalXCodeGenerator(parser.Version));
- if (gg->XcodeVersion == 20)
- {
- cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
- "using Xcode 15 generator\n");
- gg->XcodeVersion = 15;
- }
+ } else if (cmSystemTools::FileExists(
+ "/Applications/Xcode.app/Contents/version.plist")) {
+ parser.ParseFile("/Applications/Xcode.app/Contents/version.plist");
+ } else {
+ parser.ParseFile(
+ "/Developer/Applications/Xcode.app/Contents/version.plist");
+ }
+ std::string const& version_string = parser.Version;
+
+ // Compute an integer form of the version number.
+ unsigned int v[2] = { 0, 0 };
+ 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,
+ "Xcode " + version_string + " not supported.");
+ return CM_NULLPTR;
+ }
+
+ CM_AUTO_PTR<cmGlobalXCodeGenerator> gg(
+ new cmGlobalXCodeGenerator(cm, version_string, version_number));
return gg.release();
#else
std::cerr << "CMake should be built with cmake to use Xcode, "
- "default to Xcode 1.5\n";
- return new cmGlobalXCodeGenerator;
+ "default to Xcode 1.5\n";
+ return new cmGlobalXCodeGenerator(cm);
#endif
}
-//----------------------------------------------------------------------------
-bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts)
+bool cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf)
{
- if(this->XcodeVersion >= 30)
- {
- this->PlatformToolset = ts;
- return true;
- }
- else
- {
- return cmGlobalGenerator::SetGeneratorToolset(ts);
+ // 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());
+ }
+ return true;
+}
+
+std::string const& cmGlobalXCodeGenerator::GetXcodeBuildCommand()
+{
+ if (!this->XcodeBuildCommandInitialized) {
+ this->XcodeBuildCommandInitialized = true;
+ this->XcodeBuildCommand = this->FindXcodeBuildCommand();
+ }
+ return this->XcodeBuildCommand;
+}
+
+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";
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
- lang,
- cmMakefile * mf, bool optional)
+bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
+ cmMakefile* mf)
+{
+ if (ts.find_first_of(",=") != std::string::npos) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "does not recognize the toolset\n"
+ " " << ts << "\n"
+ "that was specified.";
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ this->GeneratorToolset = ts;
+ if (!this->GeneratorToolset.empty()) {
+ mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
+ this->GeneratorToolset.c_str());
+ }
+ return true;
+}
+
+void cmGlobalXCodeGenerator::EnableLanguage(
+ std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
- mf->AddDefinition("XCODE","1");
+ mf->AddDefinition("XCODE", "1");
mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str());
- if(this->XcodeVersion == 15)
- {
- }
- else
- {
- if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
- {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES",
- "Debug;Release;MinSizeRel;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, "
- "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
- "anything else will be ignored.",
- cmCacheManager::STRING);
- }
- }
+ if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
+ mf->AddCacheDefinition(
+ "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
+ "Semicolon separated list of supported configuration types, "
+ "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
+ "anything else will be ignored.",
+ cmStateEnums::STRING);
+ }
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- if(!this->PlatformToolset.empty())
- {
- mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
- this->PlatformToolset.c_str());
- }
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
- const char* osxArch =
- mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
- const char* sysroot =
- mf->GetDefinition("CMAKE_OSX_SYSROOT");
- if(osxArch && sysroot)
- {
- this->Architectures.clear();
- cmSystemTools::ExpandListArgument(std::string(osxArch),
- this->Architectures);
- }
+ this->ComputeArchitectures(mf);
}
-//----------------------------------------------------------------------------
-std::string cmGlobalXCodeGenerator
-::GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
- const char *projectDir,
- const char* additionalOptions,
- const char *targetName,
- const char* config,
- bool ignoreErrors,
- bool)
-{
- // Config is not used yet
- (void) ignoreErrors;
- (void) projectDir;
-
+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)
+{
// now build the test
- if(makeProgram == 0 || !strlen(makeProgram))
- {
- cmSystemTools::Error(
- "Generator cannot find the appropriate make command.");
- return "";
- }
- std::string makeCommand =
- cmSystemTools::ConvertToOutputPath(makeProgram);
- std::string lowerCaseCommand = makeCommand;
- cmSystemTools::LowerCase(lowerCaseCommand);
-
- makeCommand += " -project ";
- makeCommand += projectName;
- makeCommand += ".xcode";
- if(this->XcodeVersion > 20)
- {
- makeCommand += "proj";
- }
+ makeCommand.push_back(
+ this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
+
+ makeCommand.push_back("-project");
+ std::string projectArg = projectName;
+ projectArg += ".xcode";
+ projectArg += "proj";
+ makeCommand.push_back(projectArg);
bool clean = false;
- if ( targetName && strcmp(targetName, "clean") == 0 )
- {
+ std::string realTarget = targetName;
+ if (realTarget == "clean") {
clean = true;
- targetName = "ALL_BUILD";
- }
- if(clean)
- {
- makeCommand += " clean";
- }
- else
- {
- makeCommand += " build";
- }
- makeCommand += " -target ";
- // if it is a null string for config don't use it
- if(config && *config == 0)
- {
- config = 0;
- }
- if (targetName && strlen(targetName))
- {
- makeCommand += targetName;
- }
- else
- {
- makeCommand += "ALL_BUILD";
- }
- if(this->XcodeVersion == 15)
- {
- makeCommand += " -buildstyle Development ";
- }
- else
- {
- makeCommand += " -configuration ";
- makeCommand += config?config:"Debug";
- }
- if ( additionalOptions )
- {
- makeCommand += " ";
- makeCommand += additionalOptions;
- }
- return makeCommand;
+ realTarget = "ALL_BUILD";
+ }
+ if (clean) {
+ makeCommand.push_back("clean");
+ } else {
+ makeCommand.push_back("build");
+ }
+ makeCommand.push_back("-target");
+ if (!realTarget.empty()) {
+ makeCommand.push_back(realTarget);
+ } else {
+ makeCommand.push_back("ALL_BUILD");
+ }
+ makeCommand.push_back("-configuration");
+ makeCommand.push_back(!config.empty() ? config : "Debug");
+ makeCommand.insert(makeCommand.end(), makeOptions.begin(),
+ makeOptions.end());
}
-//----------------------------------------------------------------------------
///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalXCodeGenerator::CreateLocalGenerator()
+cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
{
- cmLocalGenerator *lg = new cmLocalXCodeGenerator;
- lg->SetGlobalGenerator(this);
- return lg;
+ return new cmLocalXCodeGenerator(this, mf);
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::Generate()
+void cmGlobalXCodeGenerator::AddExtraIDETargets()
{
- std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
+ 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)
- {
+ for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
cmLocalGenerator* root = it->second[0];
this->SetGenerationRoot(root);
// add ALL_BUILD, INSTALL, etc
this->AddExtraTargets(root, it->second);
- }
- this->ForceLinkerLanguages();
+ }
+}
+
+void cmGlobalXCodeGenerator::Generate()
+{
this->cmGlobalGenerator::Generate();
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return;
- }
- for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
- {
+ }
+ 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->SetGenerationRoot(root);
// now create the project
this->OutputXCodeProject(root, it->second);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
{
- this->CurrentProject = root->GetMakefile()->GetProjectName();
+ this->CurrentProject = root->GetProjectName();
this->SetCurrentLocalGenerator(root);
- cmSystemTools::SplitPath(this->CurrentMakefile->GetCurrentDirectory(),
- this->ProjectSourceDirectoryComponents);
- cmSystemTools::SplitPath(this->CurrentMakefile->GetCurrentOutputDirectory(),
- this->ProjectOutputDirectoryComponents);
-
- this->CurrentXCodeHackMakefile =
- root->GetMakefile()->GetCurrentOutputDirectory();
+ cmSystemTools::SplitPath(
+ this->CurrentLocalGenerator->GetCurrentSourceDirectory(),
+ this->ProjectSourceDirectoryComponents);
+ cmSystemTools::SplitPath(
+ this->CurrentLocalGenerator->GetCurrentBinaryDirectory(),
+ this->ProjectOutputDirectoryComponents);
+
+ this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory();
this->CurrentXCodeHackMakefile += "/CMakeScripts";
cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile.c_str());
this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
}
-//----------------------------------------------------------------------------
-std::string
-cmGlobalXCodeGenerator::PostBuildMakeTarget(std::string const& tName,
- std::string const& configName)
+std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
+ std::string const& tName, std::string const& configName)
{
std::string target = tName;
- cmSystemTools::ReplaceString(target, " ", "_");
+ std::replace(target.begin(), target.end(), ' ', '_');
std::string out = "PostBuild." + target;
- if(this->XcodeVersion > 20)
- {
- out += "." + configName;
- }
+ out += "." + configName;
return out;
}
-//----------------------------------------------------------------------------
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& gens)
+void cmGlobalXCodeGenerator::AddExtraTargets(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens)
{
cmMakefile* mf = root->GetMakefile();
// Add ALL_BUILD
const char* no_working_directory = 0;
std::vector<std::string> no_depends;
- mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
- no_working_directory,
- "echo", "Build all projects");
- cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
+ cmTarget* allbuild =
+ mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory,
+ "echo", "Build all projects");
+
+ cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root);
+ root->AddGeneratorTarget(allBuildGt);
// Refer to the main build configuration file for easy editing.
- std::string listfile = mf->GetStartDirectory();
+ std::string listfile = root->GetCurrentSourceDirectory();
listfile += "/";
listfile += "CMakeLists.txt";
- allbuild->AddSource(listfile.c_str());
+ allBuildGt->AddSource(listfile);
// Add XCODE depend helper
- std::string dir = mf->GetCurrentOutputDirectory();
+ std::string dir = root->GetCurrentBinaryDirectory();
cmCustomCommandLine makeHelper;
- if(this->XcodeVersion < 50)
- {
- makeHelper.push_back("make");
- makeHelper.push_back("-C");
- makeHelper.push_back(dir.c_str());
- makeHelper.push_back("-f");
- makeHelper.push_back(this->CurrentXCodeHackMakefile.c_str());
- makeHelper.push_back(""); // placeholder, see below
- }
+ 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
// Add ZERO_CHECK
bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
- if (regenerate)
- {
+ if (regenerate) {
this->CreateReRunCMakeFile(root, gens);
- std::string file = this->ConvertToRelativeForMake(
- this->CurrentReRunCMakeMakefile.c_str());
+ std::string file =
+ this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
cmSystemTools::ReplaceString(file, "\\ ", " ");
- 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, true, no_depends,
+ no_working_directory, "make", "-f", file.c_str());
+
+ cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root);
+ root->AddGeneratorTarget(checkGt);
+ }
// 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)
- {
+ for (std::vector<cmLocalGenerator*>::iterator i = gens.begin();
+ i != gens.end(); ++i) {
cmLocalGenerator* lg = *i;
- if(this->IsExcluded(root, *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;
+
+ if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ continue;
}
- cmTargets& tgts = lg->GetMakefile()->GetTargets();
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
- {
- cmTarget& target = l->second;
+ std::string targetName = target->GetName();
- if (regenerate && (l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET))
- {
- target.AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
- }
+ if (regenerate && (targetName != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) {
+ target->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+ }
// make all exe, shared libs and modules
// 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(!makeHelper.empty() &&
- (target.GetType() == cmTarget::EXECUTABLE ||
-// Nope - no post-build for OBJECT_LIRBRARY
-// target.GetType() == cmTarget::OBJECT_LIBRARY ||
- target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY))
- {
- makeHelper[makeHelper.size()-1] = // fill placeholder
- this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)");
+ 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
+ this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
cmCustomCommandLines commandLines;
commandLines.push_back(makeHelper);
- lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(),
- no_depends,
- commandLines,
- cmTarget::POST_BUILD,
- "Depend check for xcode",
- dir.c_str());
- }
+ std::vector<std::string> no_byproducts;
+ lg->GetMakefile()->AddCustomCommandToTarget(
+ target->GetName(), no_byproducts, no_depends, commandLines,
+ cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
+ false, "", false, cmMakefile::AcceptObjectLibraryCommands);
+ }
- if(!target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
- {
- allbuild->AddUtility(target.GetName());
- }
+ if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ allbuild->AddUtility(target->GetName());
+ }
// Refer to the build configuration file for easy editing.
- listfile = lg->GetMakefile()->GetStartDirectory();
+ listfile = lg->GetCurrentSourceDirectory();
listfile += "/";
listfile += "CMakeLists.txt";
- target.AddSource(listfile.c_str());
- }
+ target->AddSource(listfile);
}
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
cmLocalGenerator* root, std::vector<cmLocalGenerator*> const& gens)
{
- cmMakefile* mf = root->GetMakefile();
std::vector<std::string> lfiles;
- for(std::vector<cmLocalGenerator*>::const_iterator gi = gens.begin();
- gi != gens.end(); ++gi)
- {
+ 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());
- }
+ }
// 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 = mf->GetStartOutputDirectory();
+ this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory();
this->CurrentReRunCMakeMakefile += "/CMakeScripts";
cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str());
this->CurrentReRunCMakeMakefile += "/ReRunCMake.make";
- cmGeneratedFileStream makefileStream
- (this->CurrentReRunCMakeMakefile.c_str());
+ cmGeneratedFileStream makefileStream(
+ this->CurrentReRunCMakeMakefile.c_str());
makefileStream.SetCopyIfDifferent(true);
- makefileStream << "# Generated by CMake, DO NOT EDIT\n";
- std::string checkCache = mf->GetHomeOutputDirectory();
+ makefileStream << "# Generated by CMake, DO NOT EDIT\n\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) {
+ makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
+ << this->ConvertToRelativeForMake(i->c_str()) << "))\n";
+ }
+
+ std::string checkCache = root->GetBinaryDirectory();
checkCache += "/";
checkCache += cmake::GetCMakeFilesDirectoryPostSlash();
checkCache += "cmake.check_cache";
- makefileStream << this->ConvertToRelativeForMake(checkCache.c_str())
- << ": ";
- for(std::vector<std::string>::const_iterator i = lfiles.begin();
- i != lfiles.end(); ++i)
- {
- makefileStream << "\\\n" << this->ConvertToRelativeForMake(i->c_str());
- }
- std::string cmake = mf->GetRequiredDefinition("CMAKE_COMMAND");
- makefileStream << "\n\t" << this->ConvertToRelativeForMake(cmake.c_str())
- << " -H" << this->ConvertToRelativeForMake(
- mf->GetHomeDirectory())
- << " -B" << this->ConvertToRelativeForMake(
- mf->GetHomeOutputDirectory()) << "\n";
+
+ makefileStream << "\n"
+ << this->ConvertToRelativeForMake(checkCache.c_str())
+ << ": $(TARGETS)\n";
+ makefileStream << "\t"
+ << this->ConvertToRelativeForMake(
+ cmSystemTools::GetCMakeCommand().c_str())
+ << " -H"
+ << this->ConvertToRelativeForMake(root->GetSourceDirectory())
+ << " -B"
+ << this->ConvertToRelativeForMake(root->GetBinaryDirectory())
+ << "\n";
+}
+
+static bool objectIdLessThan(cmXCodeObject* l, cmXCodeObject* r)
+{
+ return l->GetId() < r->GetId();
+}
+
+void cmGlobalXCodeGenerator::SortXCodeObjects()
+{
+ std::sort(this->XCodeObjects.begin(), this->XCodeObjects.end(),
+ objectIdLessThan);
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::ClearXCodeObjects()
{
this->TargetDoneSet.clear();
- for(unsigned int i = 0; i < this->XCodeObjects.size(); ++i)
- {
+ for (unsigned int i = 0; i < this->XCodeObjects.size(); ++i) {
delete this->XCodeObjects[i];
- }
+ }
this->XCodeObjects.clear();
this->XCodeObjectIDs.clear();
+ this->XCodeObjectMap.clear();
this->GroupMap.clear();
this->GroupNameMap.clear();
this->TargetGroup.clear();
this->FileRefs.clear();
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::addObject(cmXCodeObject *obj)
+void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj)
{
- if(obj->GetType() == cmXCodeObject::OBJECT)
- {
- cmStdString id = obj->GetId();
+ if (obj->GetType() == cmXCodeObject::OBJECT) {
+ std::string id = obj->GetId();
// If this is a duplicate id, it's an error:
//
- if(this->XCodeObjectIDs.count(id))
- {
+ if (this->XCodeObjectIDs.count(id)) {
cmSystemTools::Error(
"Xcode generator: duplicate object ids not allowed");
- }
+ }
this->XCodeObjectIDs.insert(id);
- }
+ }
this->XCodeObjects.push_back(obj);
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(
+ cmXCodeObject::PBXType ptype)
{
- cmXCodeObject* obj;
- if(this->XcodeVersion == 15)
- {
- obj = new cmXCodeObject(ptype, cmXCodeObject::OBJECT);
- }
- else
- {
- obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT);
- }
+ cmXCodeObject* obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT);
this->addObject(obj);
return obj;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type)
{
cmXCodeObject* obj = new cmXCodeObject(cmXCodeObject::None, type);
this->addObject(obj);
return obj;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateString(const char* s)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateString(const std::string& s)
{
cmXCodeObject* obj = this->CreateObject(cmXCodeObject::STRING);
obj->SetString(s);
return obj;
}
-//----------------------------------------------------------------------------
-cmXCodeObject* cmGlobalXCodeGenerator
-::CreateObjectReference(cmXCodeObject* ref)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateObjectReference(
+ cmXCodeObject* ref)
{
cmXCodeObject* obj = this->CreateObject(cmXCodeObject::OBJECT_REF);
obj->SetObject(ref);
return obj;
}
-//----------------------------------------------------------------------------
-cmStdString
-GetGroupMapKeyFromPath(cmTarget& cmtarget, const std::string& fullpath)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateFlatClone(cmXCodeObject* orig)
{
- cmStdString key(cmtarget.GetName());
- key += "-";
- key += fullpath;
- return key;
+ cmXCodeObject* obj = this->CreateObject(orig->GetType());
+ obj->CopyAttributes(orig);
+ return obj;
}
-//----------------------------------------------------------------------------
-cmStdString
-GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
+std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target,
+ const std::string& fullpath)
{
- return GetGroupMapKeyFromPath(cmtarget, sf->GetFullPath());
+ std::string key(target->GetName());
+ key += "-";
+ key += fullpath;
+ return key;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
- const std::string &fullpath,
- cmTarget& cmtarget,
- const std::string &lang)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
+ const std::string& fullpath, cmGeneratorTarget* target,
+ const std::string& lang, cmSourceFile* sf)
{
// Using a map and the full path guarantees that we will always get the same
// fileRef object for any given full path.
//
cmXCodeObject* fileRef =
- this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang);
+ this->CreateXCodeFileReferenceFromPath(fullpath, target, lang, sf);
cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
buildFile->SetComment(fileRef->GetComment());
@@ -677,160 +649,146 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
return buildFile;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
- cmSourceFile* sf,
- cmTarget& cmtarget)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
+ cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt)
{
// Add flags from target and source file properties.
std::string flags;
const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
- switch(this->CurrentLocalGenerator->GetFortranFormat(srcfmt))
- {
- case cmLocalGenerator::FortranFormatFixed: flags="-fixed "+flags; break;
- case cmLocalGenerator::FortranFormatFree: flags="-free "+flags; break;
- default: break;
- }
- lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS"));
+ switch (cmOutputConverter::GetFortranFormat(srcfmt)) {
+ case cmOutputConverter::FortranFormatFixed:
+ flags = "-fixed " + flags;
+ break;
+ case cmOutputConverter::FortranFormatFree:
+ flags = "-free " + flags;
+ break;
+ 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);
+ }
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
- this->AppendDefines(flagsBuild,
- sf->GetProperty("COMPILE_DEFINITIONS"), true);
- if (!flagsBuild.IsEmpty())
- {
- if (flags.size())
- {
+ this->AppendDefines(flagsBuild, sf->GetProperty("COMPILE_DEFINITIONS"),
+ true);
+ if (!flagsBuild.IsEmpty()) {
+ if (!flags.empty()) {
flags += ' ';
- }
- flags += flagsBuild.GetString();
}
+ flags += flagsBuild.GetString();
+ }
- const char* lang =
- this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
- if (!lang)
- {
- lang = "";
- }
+ std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
cmXCodeObject* buildFile =
- this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang);
- cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject();
+ this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf);
- cmXCodeObject* settings =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- settings->AddAttribute("COMPILER_FLAGS", this->CreateString(flags.c_str()));
+ cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+ settings->AddAttributeIfNotEmpty("COMPILER_FLAGS",
+ this->CreateString(flags));
- // Is this a resource file in this target? Add it to the resources group...
- //
- cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(sf);
- bool isResource = (tsFlags.Type == cmTarget::SourceFileTypeResource);
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sf);
+
+ cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
// Is this a "private" or "public" framework header file?
// Set the ATTRIBUTES attribute appropriately...
//
- if(cmtarget.IsFrameworkOnApple())
- {
- if(tsFlags.Type == cmTarget::SourceFileTypePrivateHeader)
- {
- cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ if (gtgt->IsFrameworkOnApple()) {
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) {
attrs->AddObject(this->CreateString("Private"));
- settings->AddAttribute("ATTRIBUTES", attrs);
- isResource = true;
- }
- else if(tsFlags.Type == cmTarget::SourceFileTypePublicHeader)
- {
- cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader) {
attrs->AddObject(this->CreateString("Public"));
- settings->AddAttribute("ATTRIBUTES", attrs);
- isResource = true;
- }
}
+ }
- // Add the fileRef to the top level Resources group/folder if it is not
- // already there.
- //
- if(isResource && this->ResourcesGroupChildren &&
- !this->ResourcesGroupChildren->HasObject(fileRef))
- {
- this->ResourcesGroupChildren->AddObject(fileRef);
+ // Add user-specified file attributes.
+ const char* extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES");
+ if (extraFileAttributes) {
+ // Expand the list of attributes.
+ std::vector<std::string> attributes;
+ cmSystemTools::ExpandListArgument(extraFileAttributes, attributes);
+
+ // Store the attributes.
+ for (std::vector<std::string>::const_iterator ai = attributes.begin();
+ ai != attributes.end(); ++ai) {
+ attrs->AddObject(this->CreateString(*ai));
}
+ }
+
+ settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs);
- buildFile->AddAttribute("settings", settings);
+ buildFile->AddAttributeIfNotEmpty("settings", settings);
return buildFile;
}
-//----------------------------------------------------------------------------
-std::string
-GetSourcecodeValueFromFileExtension(const std::string& _ext,
- const std::string& lang)
+std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
+ const std::string& lang,
+ bool& keepLastKnownFileType)
{
std::string ext = cmSystemTools::LowerCase(_ext);
std::string sourcecode = "sourcecode";
- if(ext == "o")
- {
+ if (ext == "o") {
sourcecode = "compiled.mach-o.objfile";
- }
- else if(ext == "xib")
- {
+ } else if (ext == "xctest") {
+ sourcecode = "wrapper.cfbundle";
+ } else if (ext == "xib") {
+ keepLastKnownFileType = true;
sourcecode = "file.xib";
- }
- else if(ext == "storyboard")
- {
+ } else if (ext == "storyboard") {
+ keepLastKnownFileType = true;
sourcecode = "file.storyboard";
- }
- else if(ext == "mm")
- {
+ } else if (ext == "mm") {
sourcecode += ".cpp.objcpp";
- }
- else if(ext == "m")
- {
+ } else if (ext == "m") {
sourcecode += ".c.objc";
- }
- else if(ext == "xib")
- {
- sourcecode += ".file.xib";
- }
- else if(ext == "plist")
- {
+ } else if (ext == "swift") {
+ sourcecode += ".swift";
+ } else if (ext == "plist") {
sourcecode += ".text.plist";
- }
- else if(ext == "h")
- {
+ } else if (ext == "h") {
sourcecode += ".c.h";
- }
- else if(ext == "hxx" || ext == "hpp" || ext == "txx"
- || ext == "pch" || ext == "hh")
- {
+ } else if (ext == "hxx" || ext == "hpp" || ext == "txx" || ext == "pch" ||
+ ext == "hh") {
sourcecode += ".cpp.h";
- }
- else if(ext == "png" || ext == "gif" || ext == "jpg")
- {
+ } else if (ext == "png" || ext == "gif" || ext == "jpg") {
+ keepLastKnownFileType = true;
sourcecode = "image";
- }
- else if(ext == "txt")
- {
+ } else if (ext == "txt") {
sourcecode += ".text";
- }
- else if(lang == "CXX")
- {
+ } else if (lang == "CXX") {
sourcecode += ".cpp.cpp";
- }
- else if(lang == "C")
- {
+ } else if (lang == "C") {
sourcecode += ".c.c";
- }
- else if(lang == "Fortran")
- {
+ } else if (lang == "Fortran") {
sourcecode += ".fortran.f90";
- }
- else if(lang == "ASM")
- {
+ } else if (lang == "ASM") {
sourcecode += ".asm";
- }
- //else
+ } else if (ext == "metal") {
+ sourcecode += ".metal";
+ } else if (ext == "mig") {
+ sourcecode += ".mig";
+ }
+ // else
// {
// // Already specialized above or we leave sourcecode == "sourcecode"
// // which is probably the most correct choice. Extensionless headers,
@@ -841,117 +799,106 @@ GetSourcecodeValueFromFileExtension(const std::string& _ext,
return sourcecode;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
- const std::string &fullpath,
- cmTarget& cmtarget,
- const std::string &lang)
-{
- std::string fname = fullpath;
- cmXCodeObject* fileRef = this->FileRefs[fname];
- if(!fileRef)
- {
+cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
+ const std::string& fullpath, cmGeneratorTarget* target,
+ const std::string& lang, cmSourceFile* sf)
+{
+ std::string key = GetGroupMapKeyFromPath(target, fullpath);
+ cmXCodeObject* fileRef = this->FileRefs[key];
+ if (!fileRef) {
fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
- std::string comment = fname;
- fileRef->SetComment(fname.c_str());
- this->FileRefs[fname] = fileRef;
- }
- cmStdString key = GetGroupMapKeyFromPath(cmtarget, fullpath);
+ fileRef->SetComment(fullpath);
+ this->FileRefs[key] = fileRef;
+ }
cmXCodeObject* group = this->GroupMap[key];
cmXCodeObject* children = group->GetObject("children");
- if (!children->HasObject(fileRef))
- {
+ if (!children->HasObject(fileRef)) {
children->AddObject(fileRef);
- }
+ }
fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
- // Compute the extension.
- std::string ext;
- std::string realExt =
- cmSystemTools::GetFilenameLastExtension(fullpath);
- if(!realExt.empty())
- {
- // Extension without the leading '.'.
- ext = realExt.substr(1);
+ bool useLastKnownFileType = false;
+ std::string fileType;
+ if (sf) {
+ if (const char* e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) {
+ fileType = e;
+ } else if (const char* l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) {
+ useLastKnownFileType = true;
+ fileType = l;
}
+ }
+ if (fileType.empty()) {
+ // Compute the extension without leading '.'.
+ std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath);
+ if (!ext.empty()) {
+ ext = ext.substr(1);
+ }
+
+ // If fullpath references a directory, then we need to specify
+ // lastKnownFileType as folder in order for Xcode to be able to
+ // open the contents of the folder.
+ // (Xcode 4.6 does not like explicitFileType=folder).
+ if (cmSystemTools::FileIsDirectory(fullpath)) {
+ fileType = (ext == "xcassets" ? "folder.assetcatalog" : "folder");
+ useLastKnownFileType = true;
+ } else {
+ fileType =
+ GetSourcecodeValueFromFileExtension(ext, lang, useLastKnownFileType);
+ }
+ }
- std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, lang);
- const char* attribute = (sourcecode == "file.storyboard") ?
- "lastKnownFileType" :
- "explicitFileType";
- fileRef->AddAttribute(attribute,
- this->CreateString(sourcecode.c_str()));
+ fileRef->AddAttribute(useLastKnownFileType ? "lastKnownFileType"
+ : "explicitFileType",
+ 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 name = cmSystemTools::GetFilenameName(path.c_str());
- const char* sourceTree = (cmSystemTools::FileIsFullPath(path.c_str())?
- "<absolute>" : "SOURCE_ROOT");
- fileRef->AddAttribute("name", this->CreateString(name.c_str()));
- fileRef->AddAttribute("path", this->CreateString(path.c_str()));
+ std::string name = cmSystemTools::GetFilenameName(path);
+ const char* sourceTree =
+ (cmSystemTools::FileIsFullPath(path.c_str()) ? "<absolute>"
+ : "SOURCE_ROOT");
+ fileRef->AddAttribute("name", this->CreateString(name));
+ fileRef->AddAttribute("path", this->CreateString(path));
fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree));
- if(this->XcodeVersion == 15)
- {
- fileRef->AddAttribute("refType", this->CreateString("4"));
- }
return fileRef;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
- cmTarget& cmtarget)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReference(
+ cmSourceFile* sf, cmGeneratorTarget* target)
{
- const char* lang =
- this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
- if (!lang)
- {
- lang = "";
- }
+ std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
- return this->CreateXCodeFileReferenceFromPath(
- sf->GetFullPath(), cmtarget, lang);
+ return this->CreateXCodeFileReferenceFromPath(sf->GetFullPath(), target,
+ lang, sf);
}
-//----------------------------------------------------------------------------
bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname)
{
- if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" ||
- tname == "install" || tname == "package" || tname == "RUN_TESTS" ||
- tname == CMAKE_CHECK_BUILD_SYSTEM_TARGET )
- {
- if(this->TargetDoneSet.find(tname) != this->TargetDoneSet.end())
- {
+ if (tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" ||
+ tname == "install" || tname == "package" || tname == "RUN_TESTS" ||
+ tname == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ if (this->TargetDoneSet.find(tname) != this->TargetDoneSet.end()) {
return true;
- }
+ }
this->TargetDoneSet.insert(tname);
return false;
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
{
this->CurrentLocalGenerator = gen;
this->CurrentMakefile = gen->GetMakefile();
- std::string outdir =
- cmSystemTools::CollapseFullPath(this->CurrentMakefile->
- GetCurrentOutputDirectory());
- cmSystemTools::SplitPath(outdir.c_str(),
- this->CurrentOutputDirectoryComponents);
// Select the current set of configuration types.
this->CurrentConfigurationTypes.clear();
this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes);
- if(this->CurrentConfigurationTypes.empty())
- {
+ if (this->CurrentConfigurationTypes.empty()) {
this->CurrentConfigurationTypes.push_back("");
- }
+ }
}
-//----------------------------------------------------------------------------
struct cmSourceFilePathCompare
{
bool operator()(cmSourceFile* l, cmSourceFile* r)
@@ -960,225 +907,278 @@ struct cmSourceFilePathCompare
}
};
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
- std::vector<cmXCodeObject*>&
- targets)
+struct cmCompareTargets
+{
+ bool operator()(std::string const& a, std::string const& b) const
+ {
+ if (a == "ALL_BUILD") {
+ return true;
+ }
+ if (b == "ALL_BUILD") {
+ return false;
+ }
+ return strcmp(a.c_str(), b.c_str()) < 0;
+ }
+};
+
+bool cmGlobalXCodeGenerator::CreateXCodeTargets(
+ cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
{
this->SetCurrentLocalGenerator(gen);
- cmTargets &tgts = this->CurrentMakefile->GetTargets();
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
- {
- cmTarget& cmtarget = l->second;
+ std::vector<cmGeneratorTarget*> tgts =
+ 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;
+ }
+ for (cmSortedTargets::iterator l = sortedTargets.begin();
+ l != sortedTargets.end(); l++) {
+ cmGeneratorTarget* gtgt = l->second;
+
+ std::string targetName = gtgt->GetName();
// make sure ALL_BUILD, INSTALL, etc are only done once
- if(this->SpecialTargetEmitted(l->first.c_str()))
- {
+ if (this->SpecialTargetEmitted(targetName)) {
continue;
- }
+ }
- if(cmtarget.GetType() == cmTarget::UTILITY ||
- cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
- {
- targets.push_back(this->CreateUtilityTarget(cmtarget));
+ if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
+ }
+
+ if (gtgt->GetType() == cmStateEnums::UTILITY ||
+ gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
+ if (!t) {
+ return false;
}
+ targets.push_back(t);
+ continue;
+ }
// organize the sources
- std::vector<cmSourceFile*> classes = cmtarget.GetSourceFiles();
+ std::vector<cmSourceFile*> classes;
+ if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ return false;
+ }
std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+ gtgt->ComputeObjectMapping();
+
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)
- {
+ for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
+ i != classes.end(); ++i) {
cmXCodeObject* xsf =
- this->CreateXCodeSourceFile(this->CurrentLocalGenerator,
- *i, cmtarget);
+ this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, gtgt);
cmXCodeObject* fr = xsf->GetObject("fileRef");
- cmXCodeObject* filetype =
- fr->GetObject()->GetObject("explicitFileType");
+ cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
- cmTarget::SourceFileFlags tsFlags =
- cmtarget.GetTargetSourceFileFlags(*i);
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(*i);
- if(strcmp(filetype->GetString(), "compiled.mach-o.objfile") == 0)
- {
- externalObjFiles.push_back(xsf);
+ if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
+ if ((*i)->GetObjectLibrary().empty()) {
+ externalObjFiles.push_back(xsf);
}
- else if(this->IsHeaderFile(*i) ||
- (tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) ||
- (tsFlags.Type == cmTarget::SourceFileTypePublicHeader))
- {
+ } else if (this->IsHeaderFile(*i) ||
+ (tsFlags.Type ==
+ cmGeneratorTarget::SourceFileTypePrivateHeader) ||
+ (tsFlags.Type ==
+ cmGeneratorTarget::SourceFileTypePublicHeader)) {
headerFiles.push_back(xsf);
- }
- else if(tsFlags.Type == cmTarget::SourceFileTypeResource)
- {
+ } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
resourceFiles.push_back(xsf);
- }
- else if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY"))
- {
+ } 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) &&
- !this->IgnoreFile((*i)->GetExtension().c_str()))
- {
+ if (!this->CurrentLocalGenerator->GetSourceFileLanguage(**i).empty() &&
+ !this->IgnoreFile((*i)->GetExtension().c_str())) {
sourceFiles.push_back(xsf);
- }
}
}
+ }
- if(this->XcodeVersion < 50)
- {
+ 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<std::string> objs;
- this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- std::string obj = *oi;
+ 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, cmtarget, "");
+ this->CreateXCodeSourceFileFromPath(obj, gtgt, "", 0);
externalObjFiles.push_back(xsf);
- }
}
+ }
// some build phases only apply to bundles and/or frameworks
- bool isFrameworkTarget = cmtarget.IsFrameworkOnApple();
- bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE");
- bool isCFBundleTarget = cmtarget.IsCFBundleOnApple();
+ bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
+ bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
+ bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
cmXCodeObject* buildFiles = 0;
// create source build phase
cmXCodeObject* sourceBuildPhase = 0;
- if (!sourceFiles.empty())
- {
+ 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)
- {
+ for (std::vector<cmXCodeObject*>::iterator i = sourceFiles.begin();
+ i != sourceFiles.end(); ++i) {
buildFiles->AddObject(*i);
- }
+ }
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)
- {
+ 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(std::vector<cmXCodeObject*>::iterator i = headerFiles.begin();
- i != headerFiles.end(); ++i)
- {
+ 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"));
- }
+ }
// create resource build phase - only for framework or bundle targets
cmXCodeObject* resourceBuildPhase = 0;
if (!resourceFiles.empty() &&
- (isFrameworkTarget || isBundleTarget || isCFBundleTarget))
- {
+ (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)
- {
+ for (std::vector<cmXCodeObject*>::iterator i = resourceFiles.begin();
+ i != resourceFiles.end(); ++i) {
buildFiles->AddObject(*i);
- }
+ }
resourceBuildPhase->AddAttribute("files", buildFiles);
resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- }
+ 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<cmStdString, std::vector<cmSourceFile*> >
+ 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)
- {
- cmTarget::SourceFileFlags tsFlags =
- cmtarget.GetTargetSourceFileFlags(*i);
- if(tsFlags.Type == cmTarget::SourceFileTypeMacContent)
- {
+ 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);
- }
}
+ }
mapOfVectorOfSourceFiles::iterator mit;
- for ( mit = bundleFiles.begin(); mit != bundleFiles.end(); ++ 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"));
+ this->CreateString("2147483647"));
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
- this->CreateString("6"));
- cmOStringStream ostr;
- if (cmtarget.IsFrameworkOnApple())
- {
+ 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;
}
- else if ( mit->first != "MacOS" )
- {
- // dstPath in bundles is relative to Contents/MacOS
- ostr << "../" << mit->first.c_str();
- }
+ }
copyFilesBuildPhase->AddAttribute("dstPath",
- this->CreateString(ostr.str().c_str()));
- copyFilesBuildPhase->AddAttribute(
- "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
+ 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, cmtarget);
+ 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) {
+ 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 framework build phase
cmXCodeObject* frameworkBuildPhase = 0;
- if (!externalObjFiles.empty())
- {
+ if (!externalObjFiles.empty()) {
frameworkBuildPhase =
this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
frameworkBuildPhase->SetComment("Frameworks");
@@ -1186,248 +1186,212 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
this->CreateString("2147483647"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
frameworkBuildPhase->AddAttribute("files", buildFiles);
- for(std::vector<cmXCodeObject*>::iterator i = externalObjFiles.begin();
- i != externalObjFiles.end(); ++i)
- {
+ for (std::vector<cmXCodeObject*>::iterator i = externalObjFiles.begin();
+ i != externalObjFiles.end(); ++i) {
buildFiles->AddObject(*i);
- }
+ }
frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
this->CreateString("0"));
- }
+ }
// create list of build phases and create the Xcode target
cmXCodeObject* buildPhases =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- this->CreateCustomCommands(buildPhases, sourceBuildPhase,
- headerBuildPhase, resourceBuildPhase,
- contentBuildPhases,
- frameworkBuildPhase, cmtarget);
+ this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
+ resourceBuildPhase, contentBuildPhases,
+ frameworkBuildPhase, gtgt);
- targets.push_back(this->CreateXCodeTarget(cmtarget, buildPhases));
- }
+ targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
+ }
+ return true;
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::ForceLinkerLanguages()
{
- // This makes sure all targets link using the proper language.
- for(std::map<cmStdString, cmTarget*>::const_iterator
- ti = this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
- {
- this->ForceLinkerLanguage(*ti->second);
+ for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
+ std::vector<cmGeneratorTarget*> tgts =
+ this->LocalGenerators[i]->GetGeneratorTargets();
+ // All targets depend on the build-system check target.
+ for (std::vector<cmGeneratorTarget*>::const_iterator ti = tgts.begin();
+ ti != tgts.end(); ++ti) {
+ // This makes sure all targets link using the proper language.
+ this->ForceLinkerLanguage(*ti);
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
+void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
{
// This matters only for targets that link.
- if(cmtarget.GetType() != cmTarget::EXECUTABLE &&
- cmtarget.GetType() != cmTarget::SHARED_LIBRARY &&
- cmtarget.GetType() != cmTarget::MODULE_LIBRARY)
- {
+ if (gtgt->GetType() != cmStateEnums::EXECUTABLE &&
+ gtgt->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ gtgt->GetType() != cmStateEnums::MODULE_LIBRARY) {
return;
- }
+ }
- const char* llang = cmtarget.GetLinkerLanguage("NOCONFIG");
- if(!llang) { return; }
+ std::string llang = gtgt->GetLinkerLanguage("NOCONFIG");
+ if (llang.empty()) {
+ return;
+ }
// If the language is compiled as a source trust Xcode to link with it.
- cmTarget::LinkImplementation const* impl =
- cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget);
- for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
- li != impl->Languages.end(); ++li)
- {
- if(*li == llang) { return; }
+ 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) {
+ return;
}
+ }
// Add an empty source file to the target that compiles with the
// linker language. This should convince Xcode to choose the proper
// language.
- cmMakefile* mf = cmtarget.GetMakefile();
- std::string fname = mf->GetCurrentOutputDirectory();
+ cmMakefile* mf = gtgt->Target->GetMakefile();
+ std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory();
fname += cmake::GetCMakeFilesDirectory();
fname += "/";
- fname += cmtarget.GetName();
+ fname += gtgt->GetName();
fname += "-CMakeForceLinker";
fname += ".";
fname += cmSystemTools::LowerCase(llang);
{
- cmGeneratedFileStream fout(fname.c_str());
- fout << "\n";
+ cmGeneratedFileStream fout(fname.c_str());
+ fout << "\n";
+ }
+ if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) {
+ sf->SetProperty("LANGUAGE", llang.c_str());
+ gtgt->AddSource(fname);
}
- if(cmSourceFile* sf = mf->GetOrCreateSource(fname.c_str()))
- {
- sf->SetProperty("LANGUAGE", llang);
- cmtarget.AddSourceFile(sf);
- }
}
-//----------------------------------------------------------------------------
bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf)
{
const std::vector<std::string>& hdrExts =
- this->CurrentMakefile->GetHeaderExtensions();
+ this->CMakeInstance->GetHeaderExtensions();
return (std::find(hdrExts.begin(), hdrExts.end(), sf->GetExtension()) !=
hdrExts.end());
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateBuildPhase(const char* name,
- const char* name2,
- cmTarget& cmtarget,
- const std::vector<cmCustomCommand>&
- commands)
-{
- if(commands.size() == 0 && strcmp(name, "CMake ReRun") != 0)
- {
+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;
- }
+ }
cmXCodeObject* buildPhase =
this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
buildPhase->AddAttribute("buildActionMask",
this->CreateString("2147483647"));
cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
buildPhase->AddAttribute("files", buildFiles);
- buildPhase->AddAttribute("name",
- this->CreateString(name));
+ buildPhase->AddAttribute("name", this->CreateString(name));
buildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
this->CreateString("0"));
- buildPhase->AddAttribute("shellPath",
- this->CreateString("/bin/sh"));
- this->AddCommandsToBuildPhase(buildPhase, cmtarget, commands,
- name2);
+ buildPhase->AddAttribute("shellPath", this->CreateString("/bin/sh"));
+ this->AddCommandsToBuildPhase(buildPhase, target, commands, name2);
return buildPhase;
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
- cmXCodeObject*
- sourceBuildPhase,
- cmXCodeObject*
- headerBuildPhase,
- cmXCodeObject*
- resourceBuildPhase,
- std::vector<cmXCodeObject*>
- contentBuildPhases,
- cmXCodeObject*
- frameworkBuildPhase,
- cmTarget& cmtarget)
-{
- std::vector<cmCustomCommand> const & prebuild
- = cmtarget.GetPreBuildCommands();
- std::vector<cmCustomCommand> const & prelink
- = cmtarget.GetPreLinkCommands();
- std::vector<cmCustomCommand> postbuild
- = cmtarget.GetPostBuildCommands();
-
- if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
- !cmtarget.IsFrameworkOnApple())
- {
+void cmGlobalXCodeGenerator::CreateCustomCommands(
+ cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase,
+ cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase,
+ std::vector<cmXCodeObject*> contentBuildPhases,
+ cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt)
+{
+ std::vector<cmCustomCommand> const& prebuild = gtgt->GetPreBuildCommands();
+ std::vector<cmCustomCommand> const& prelink = gtgt->GetPreLinkCommands();
+ std::vector<cmCustomCommand> postbuild = gtgt->GetPostBuildCommands();
+
+ if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ !gtgt->IsFrameworkOnApple()) {
cmCustomCommandLines cmd;
cmd.resize(1);
- cmd[0].push_back(this->CurrentMakefile->GetDefinition("CMAKE_COMMAND"));
+ 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 += cmtarget.GetName();
+ str_file += gtgt->GetName();
str_file += ">";
std::string str_so_file = "$<TARGET_SONAME_FILE:";
- str_so_file += cmtarget.GetName();
+ str_so_file += gtgt->GetName();
str_so_file += ">";
std::string str_link_file = "$<TARGET_LINKER_FILE:";
- str_link_file += cmtarget.GetName();
+ 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);
- cmCustomCommand command(this->CurrentMakefile,
- std::vector<std::string>(),
- std::vector<std::string>(),
- cmd,
- "Creating symlinks",
- "");
+ cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(),
+ std::vector<std::string>(),
+ std::vector<std::string>(), cmd,
+ "Creating symlinks", "");
postbuild.push_back(command);
- }
+ }
- std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles();
+ std::vector<cmSourceFile*> classes;
+ if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ return;
+ }
// add all the sources
std::vector<cmCustomCommand> commands;
- for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i)
- {
- if((*i)->GetCustomCommand())
- {
+ for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
+ i != classes.end(); ++i) {
+ if ((*i)->GetCustomCommand()) {
commands.push_back(*(*i)->GetCustomCommand());
- }
}
+ }
// create prebuild phase
- cmXCodeObject* cmakeRulesBuildPhase =
- this->CreateBuildPhase("CMake Rules",
- "cmakeRulesBuildPhase",
- cmtarget, commands);
+ cmXCodeObject* cmakeRulesBuildPhase = this->CreateBuildPhase(
+ "CMake Rules", "cmakeRulesBuildPhase", gtgt, commands);
// create prebuild phase
- cmXCodeObject* preBuildPhase =
- this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
- cmtarget, prebuild);
+ cmXCodeObject* preBuildPhase = this->CreateBuildPhase(
+ "CMake PreBuild Rules", "preBuildCommands", gtgt, prebuild);
// create prelink phase
- cmXCodeObject* preLinkPhase =
- this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
- cmtarget, prelink);
+ cmXCodeObject* preLinkPhase = this->CreateBuildPhase(
+ "CMake PreLink Rules", "preLinkCommands", gtgt, prelink);
// create postbuild phase
- cmXCodeObject* postBuildPhase =
- this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
- cmtarget, postbuild);
+ cmXCodeObject* postBuildPhase = this->CreateBuildPhase(
+ "CMake PostBuild Rules", "postBuildPhase", gtgt, postbuild);
// The order here is the order they will be built in.
// The order "headers, resources, sources" mimics a native project generated
// from an xcode template...
//
- if(preBuildPhase)
- {
+ if (preBuildPhase) {
buildPhases->AddObject(preBuildPhase);
- }
- if(cmakeRulesBuildPhase)
- {
+ }
+ if (cmakeRulesBuildPhase) {
buildPhases->AddObject(cmakeRulesBuildPhase);
- }
- if(headerBuildPhase)
- {
+ }
+ if (headerBuildPhase) {
buildPhases->AddObject(headerBuildPhase);
- }
- if(resourceBuildPhase)
- {
+ }
+ if (resourceBuildPhase) {
buildPhases->AddObject(resourceBuildPhase);
- }
+ }
std::vector<cmXCodeObject*>::iterator cit;
for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end();
- ++cit)
- {
+ ++cit) {
buildPhases->AddObject(*cit);
- }
- if(sourceBuildPhase)
- {
+ }
+ if (sourceBuildPhase) {
buildPhases->AddObject(sourceBuildPhase);
- }
- if(preLinkPhase)
- {
+ }
+ if (preLinkPhase) {
buildPhases->AddObject(preLinkPhase);
- }
- if(frameworkBuildPhase)
- {
+ }
+ if (frameworkBuildPhase) {
buildPhases->AddObject(frameworkBuildPhase);
- }
- if(postBuildPhase)
- {
+ }
+ if (postBuildPhase) {
buildPhases->AddObject(postBuildPhase);
- }
+ }
}
-//----------------------------------------------------------------------------
// This function removes each occurrence of the flag and returns the last one
// (i.e., the dominant flag in GCC)
std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
@@ -1436,743 +1400,685 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
std::string retFlag;
std::string::size_type lastOccurancePos = flags.rfind(flag);
bool saved = false;
- while(lastOccurancePos != flags.npos)
- {
- //increment pos, we use lastOccurancePos to reduce search space on next inc
+ while (lastOccurancePos != std::string::npos) {
+ // increment pos, we use lastOccurancePos to reduce search space on next
+ // inc
std::string::size_type pos = lastOccurancePos;
- if(pos == 0 || flags[pos-1]==' ')
- {
- while(pos < flags.size() && flags[pos] != ' ')
- {
- if(!saved)
- {
+ if (pos == 0 || flags[pos - 1] == ' ') {
+ while (pos < flags.size() && flags[pos] != ' ') {
+ if (!saved) {
retFlag += flags[pos];
- }
+ }
flags[pos] = ' ';
pos++;
- }
- saved = true;
}
- //decrement lastOccurancePos while making sure we don't loop around
- //and become a very large positive number since size_type is unsigned
- lastOccurancePos = lastOccurancePos == 0 ? 0 : lastOccurancePos-1;
- lastOccurancePos = flags.rfind(flag,lastOccurancePos);
+ saved = true;
}
+ // decrement lastOccurancePos while making sure we don't loop around
+ // and become a very large positive number since size_type is unsigned
+ lastOccurancePos = lastOccurancePos == 0 ? 0 : lastOccurancePos - 1;
+ lastOccurancePos = flags.rfind(flag, lastOccurancePos);
+ }
+ return retFlag;
+}
+
+// This function removes each matching occurrence of the expression and
+// returns the last one (i.e., the dominant flag in GCC)
+std::string cmGlobalXCodeGenerator::ExtractFlagRegex(const char* exp,
+ int matchIndex,
+ std::string& flags)
+{
+ std::string retFlag;
+
+ cmsys::RegularExpression regex(exp);
+ assert(regex.is_valid());
+ if (!regex.is_valid()) {
+ return retFlag;
+ }
+
+ std::string::size_type offset = 0;
+
+ while (regex.find(flags.c_str() + 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;
+
+ offset = startPos + 1;
+
+ retFlag.assign(flags, startPos, size);
+ flags.replace(startPos, size, size, ' ');
+ }
+
return retFlag;
}
//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
- cmTarget& target,
- std::vector<cmCustomCommand>
- const & commands,
- const char* name)
-{
-
- // collect multiple outputs of custom commands into a set
- // which will be used for every configuration
- std::map<cmStdString, cmStdString> multipleOutputPairs;
- for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
- {
- const std::vector<std::string>& outputs = cc.GetOutputs();
- if(!outputs.empty())
- {
- // If there are more than one outputs treat the
- // first as the primary output and make the rest depend on it.
- std::vector<std::string>::const_iterator o = outputs.begin();
- std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str());
- for(++o; o != outputs.end(); ++o)
- {
- std::string currentOutput=this->ConvertToRelativeForMake(o->c_str());
- multipleOutputPairs[currentOutput] = primaryOutput;
- }
- }
- }
- }
+// This function strips off Xcode attributes that do not target the current
+// configuration
+void cmGlobalXCodeGenerator::FilterConfigurationAttribute(
+ std::string const& configName, std::string& attribute)
+{
+ // Handle [variant=<config>] condition explicitly here.
+ std::string::size_type beginVariant = attribute.find("[variant=");
+ if (beginVariant == std::string::npos) {
+ // There is no variant in this attribute.
+ return;
+ }
+
+ std::string::size_type endVariant = attribute.find("]", beginVariant + 9);
+ if (endVariant == std::string::npos) {
+ // There is no terminating bracket.
+ return;
+ }
+
+ // Compare the variant to the configuration.
+ std::string variant =
+ attribute.substr(beginVariant + 9, endVariant - beginVariant - 9);
+ if (variant == configName) {
+ // The variant matches the configuration so use this
+ // attribute but drop the [variant=<config>] condition.
+ attribute.erase(beginVariant, endVariant - beginVariant + 1);
+ } else {
+ // The variant does not match the configuration so
+ // do not use this attribute.
+ attribute.clear();
+ }
+}
- std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory();
+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 += target->GetName();
makefile += "_";
makefile += name;
makefile += ".make";
- for (std::vector<std::string>::const_iterator currentConfig=
- this->CurrentConfigurationTypes.begin();
- currentConfig!=this->CurrentConfigurationTypes.end();
- currentConfig++ )
- {
- this->CreateCustomRulesMakefile(makefile.c_str(),
- target,
- commands,
- currentConfig->c_str(),
- multipleOutputPairs);
- }
+ for (std::vector<std::string>::const_iterator currentConfig =
+ this->CurrentConfigurationTypes.begin();
+ currentConfig != this->CurrentConfigurationTypes.end();
+ currentConfig++) {
+ this->CreateCustomRulesMakefile(makefile.c_str(), target, commands,
+ *currentConfig);
+ }
- std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory();
- cdir = this->ConvertToRelativeForXCode(cdir.c_str());
+ 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());
- if(!multipleOutputPairs.empty())
- {
- makecmd += " cmake_check_multiple_outputs";
- }
+ makecmd +=
+ this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str());
makecmd += " all";
- cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
- buildphase->AddAttribute("shellScript",
- this->CreateString(makecmd.c_str()));
- buildphase->AddAttribute("showEnvVarsInLog",
- this->CreateString("0"));
+ buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
+ buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator
-::CreateCustomRulesMakefile(const char* makefileBasename,
- cmTarget& target,
- std::vector<cmCustomCommand>
- const & commands,
- const char* configName,
- const std::map<cmStdString,
- cmStdString>& multipleOutputPairs
- )
-{
- std::string makefileName=makefileBasename;
- if(this->XcodeVersion > 20)
- {
- makefileName+=configName;
- }
+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());
- if(!makefileStream)
- {
+ if (!makefileStream) {
return;
- }
+ }
makefileStream.SetCopyIfDifferent(true);
makefileStream << "# Generated by CMake, DO NOT EDIT\n";
- makefileStream << "# Custom rules for " << target.GetName() << "\n";
+ makefileStream << "# Custom rules for " << target->GetName() << "\n";
// disable the implicit rules
- makefileStream << ".SUFFIXES: " << "\n";
+ makefileStream << ".SUFFIXES: "
+ << "\n";
// have all depend on all outputs
makefileStream << "all: ";
- std::map<const cmCustomCommand*, cmStdString> tname;
+ std::map<const cmCustomCommand*, std::string> tname;
int count = 0;
- for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
- {
- const std::vector<std::string>& outputs = cc.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());
- }
- }
- else
- {
- cmOStringStream str;
- str << "_buildpart_" << count++ ;
- tname[&cc] = std::string(target.GetName()) + str.str();
- makefileStream << "\\\n\t" << tname[&cc];
+ for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+ i != commands.end(); ++i) {
+ cmCustomCommandGenerator ccg(*i, 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());
}
+ } else {
+ std::ostringstream str;
+ str << "_buildpart_" << count++;
+ tname[&ccg.GetCC()] = std::string(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)
- {
- cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
- {
- cmCustomCommandGenerator ccg(cc, configName, this->CurrentMakefile);
+ for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+ i != commands.end(); ++i) {
+ cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator);
+ if (ccg.GetNumberOfCommands() > 0) {
makefileStream << "\n";
- const std::vector<std::string>& outputs = cc.GetOutputs();
- if(!outputs.empty())
- {
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ if (!outputs.empty()) {
// There is at least one output, start the rule for it
- std::string primary_output =
- this->ConvertToRelativeForMake(outputs.begin()->c_str());
- makefileStream << primary_output << ": ";
+ const char* sep = "";
+ for (std::vector<std::string>::const_iterator oi = outputs.begin();
+ oi != outputs.end(); ++oi) {
+ makefileStream << sep << this->ConvertToRelativeForMake(oi->c_str());
+ sep = " ";
}
- else
- {
+ makefileStream << ": ";
+ } else {
// There are no outputs. Use the generated force rule name.
- makefileStream << tname[&cc] << ": ";
- }
- for(std::vector<std::string>::const_iterator d =
- cc.GetDepends().begin();
- d != cc.GetDepends().end(); ++d)
- {
+ makefileStream << tname[&ccg.GetCC()] << ": ";
+ }
+ for (std::vector<std::string>::const_iterator d =
+ ccg.GetDepends().begin();
+ d != ccg.GetDepends().end(); ++d) {
std::string dep;
- if(this->CurrentLocalGenerator
- ->GetRealDependency(d->c_str(), configName, dep))
- {
- makefileStream << "\\\n" <<
- this->ConvertToRelativeForMake(dep.c_str());
- }
+ if (this->CurrentLocalGenerator->GetRealDependency(*d, configName,
+ dep)) {
+ makefileStream << "\\\n"
+ << this->ConvertToRelativeForMake(dep.c_str());
}
+ }
makefileStream << "\n";
- if(const char* comment = cc.GetComment())
- {
+ if (const char* comment = ccg.GetComment()) {
std::string echo_cmd = "echo ";
- echo_cmd += (this->CurrentLocalGenerator->
- EscapeForShell(comment, cc.GetEscapeAllowMakeVars()));
- makefileStream << "\t" << echo_cmd.c_str() << "\n";
- }
+ echo_cmd += (this->CurrentLocalGenerator->EscapeForShell(
+ comment, ccg.GetCC().GetEscapeAllowMakeVars()));
+ makefileStream << "\t" << echo_cmd << "\n";
+ }
// Add each command line to the set of commands.
- for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
- {
+ for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
// Build the command line in a single string.
std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
std::string cmd;
- if(cc.GetWorkingDirectory())
- {
+ std::string wd = ccg.GetWorkingDirectory();
+ if (!wd.empty()) {
cmd += "cd ";
- cmd += this->ConvertToRelativeForMake(cc.GetWorkingDirectory());
+ cmd += this->ConvertToRelativeForMake(wd.c_str());
cmd += " && ";
- }
+ }
cmd += cmd2;
ccg.AppendArguments(c, cmd);
- makefileStream << "\t" << cmd.c_str() << "\n";
- }
- }
- }
-
- // Add rules to deal with multiple outputs of custom commands.
- if(!multipleOutputPairs.empty())
- {
- makefileStream <<
- "\n# Dependencies of multiple outputs to their primary outputs \n";
-
- for(std::map<cmStdString, cmStdString>::const_iterator o =
- multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
- {
- makefileStream << o->first << ": " << o->second << "\n";
- }
-
- makefileStream <<
- "\n"
- "cmake_check_multiple_outputs:\n";
- for(std::map<cmStdString, cmStdString>::const_iterator o =
- multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
- {
- makefileStream << "\t@if [ ! -f "
- << o->first << " ]; then rm -f "
- << o->second << "; fi\n";
+ makefileStream << "\t" << cmd << "\n";
}
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
+void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
- const char* configName)
+ const std::string& configName)
{
- std::string flags;
+ if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
+
std::string defFlags;
- bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) ||
- (target.GetType() == cmTarget::MODULE_LIBRARY));
- bool binary = ((target.GetType() == cmTarget::OBJECT_LIBRARY) ||
- (target.GetType() == cmTarget::STATIC_LIBRARY) ||
- (target.GetType() == cmTarget::EXECUTABLE) ||
- shared);
-
- const char* lang = target.GetLinkerLanguage(configName);
- std::string cflags;
- if(lang)
- {
- // for c++ projects get the c flags as well
- if(strcmp(lang, "CXX") == 0)
- {
- this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName);
- this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target,
- "C", configName);
- this->CurrentLocalGenerator->
- AddCompileOptions(cflags, &target, "C", configName);
- }
+ bool shared = ((gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) ||
+ (gtgt->GetType() == cmStateEnums::MODULE_LIBRARY));
+ bool binary = ((gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
+ (gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) ||
+ (gtgt->GetType() == cmStateEnums::EXECUTABLE) || shared);
+
+ // Compute the compilation flags for each language.
+ 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;
+ std::string& flags = cflags[lang];
// Add language-specific flags.
- this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName);
+ this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
+ configName);
// Add shared-library flags if needed.
- this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target,
- lang, configName);
+ this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang,
+ configName);
- this->CurrentLocalGenerator->AddVisibilityPresetFlags(flags, &target,
- lang);
+ this->CurrentLocalGenerator->AddVisibilityPresetFlags(flags, gtgt, lang);
- this->CurrentLocalGenerator->
- AddCompileOptions(flags, &target, lang, configName);
- }
- else if(binary)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- target.GetName());
+ this->CurrentLocalGenerator->AddCompileOptions(flags, gtgt, lang,
+ configName);
+ }
+
+ std::string llang = gtgt->GetLinkerLanguage(configName);
+ if (binary && llang.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: ",
+ gtgt->GetName().c_str());
return;
}
+ if (gtgt->IsIPOEnabled(llang, configName)) {
+ const char* ltoValue =
+ this->CurrentMakefile->IsOn("_CMAKE_LTO_THIN") ? "YES_THIN" : "YES";
+ buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
+ }
+
// Add define flags
- this->CurrentLocalGenerator->
- AppendFlags(defFlags,
- this->CurrentMakefile->GetDefineFlags());
+ this->CurrentLocalGenerator->AppendFlags(
+ defFlags, this->CurrentMakefile->GetDefineFlags());
// Add preprocessor definitions for this target and configuration.
- BuildObjectListOrString ppDefs(this, this->XcodeVersion >= 30);
- if(this->XcodeVersion > 15)
- {
- this->AppendDefines(ppDefs,
- "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
- }
- if(const char* exportMacro = target.GetExportMacro())
- {
+ BuildObjectListOrString ppDefs(this, true);
+ this->AppendDefines(
+ ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
+ if (const char* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects.
this->AppendDefines(ppDefs, exportMacro);
- }
- cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
+ }
std::vector<std::string> targetDefines;
- target.GetCompileDefinitions(targetDefines, configName);
+ gtgt->GetCompileDefinitions(targetDefines, configName, "C");
this->AppendDefines(ppDefs, targetDefines);
- buildSettings->AddAttribute
- ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
+ buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
+ ppDefs.CreateList());
std::string extraLinkOptionsVar;
std::string extraLinkOptions;
- if(target.GetType() == cmTarget::EXECUTABLE)
- {
+ if (gtgt->GetType() == cmStateEnums::EXECUTABLE) {
extraLinkOptionsVar = "CMAKE_EXE_LINKER_FLAGS";
- }
- else if(target.GetType() == cmTarget::SHARED_LIBRARY)
- {
+ } else if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
extraLinkOptionsVar = "CMAKE_SHARED_LINKER_FLAGS";
- }
- else if(target.GetType() == cmTarget::MODULE_LIBRARY)
- {
+ } else if (gtgt->GetType() == cmStateEnums::MODULE_LIBRARY) {
extraLinkOptionsVar = "CMAKE_MODULE_LINKER_FLAGS";
- }
- if(extraLinkOptionsVar.size())
- {
- this->CurrentLocalGenerator
- ->AddConfigVariableFlags(extraLinkOptions,
- extraLinkOptionsVar.c_str(),
- configName);
- }
+ }
+ if (!extraLinkOptionsVar.empty()) {
+ this->CurrentLocalGenerator->AddConfigVariableFlags(
+ extraLinkOptions, extraLinkOptionsVar, configName);
+ }
- if(target.GetType() == cmTarget::OBJECT_LIBRARY ||
- target.GetType() == cmTarget::STATIC_LIBRARY)
- {
- this->CurrentLocalGenerator
- ->GetStaticLibraryFlags(extraLinkOptions,
- cmSystemTools::UpperCase(configName),
- &target);
- }
- else
- {
- const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
- if(targetLinkFlags)
- {
- this->CurrentLocalGenerator->
- AppendFlags(extraLinkOptions, targetLinkFlags);
- }
- if(configName && *configName)
- {
+ if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ this->CurrentLocalGenerator->GetStaticLibraryFlags(
+ extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt);
+ } else {
+ const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
+ if (targetLinkFlags) {
+ this->CurrentLocalGenerator->AppendFlags(extraLinkOptions,
+ targetLinkFlags);
+ }
+ if (!configName.empty()) {
std::string linkFlagsVar = "LINK_FLAGS_";
linkFlagsVar += cmSystemTools::UpperCase(configName);
- if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str()))
- {
- this->CurrentLocalGenerator->
- AppendFlags(extraLinkOptions, linkFlags);
- }
+ if (const char* linkFlags = gtgt->GetProperty(linkFlagsVar)) {
+ this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags);
}
}
+ }
// Set target-specific architectures.
std::vector<std::string> archs;
gtgt->GetAppleArchs(configName, archs);
- if(!archs.empty())
- {
+ if (!archs.empty()) {
// Enable ARCHS attribute.
- buildSettings->AddAttribute("ONLY_ACTIVE_ARCH",
- this->CreateString("NO"));
+ buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("NO"));
// Store ARCHS value.
- if(archs.size() == 1)
- {
- buildSettings->AddAttribute("ARCHS",
- this->CreateString(archs[0].c_str()));
- }
- else
- {
+ if (archs.size() == 1) {
+ buildSettings->AddAttribute("ARCHS", this->CreateString(archs[0]));
+ } 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).c_str()));
- }
- buildSettings->AddAttribute("ARCHS", archObjects);
+ for (std::vector<std::string>::iterator i = archs.begin();
+ i != archs.end(); i++) {
+ archObjects->AddObject(this->CreateString(*i));
}
+ buildSettings->AddAttribute("ARCHS", archObjects);
}
+ }
// Get the product name components.
std::string pnprefix;
std::string pnbase;
std::string pnsuffix;
- target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
+ gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
- const char* version = target.GetProperty("VERSION");
- const char* soversion = target.GetProperty("SOVERSION");
- if(!target.HasSOName(configName) || target.IsFrameworkOnApple())
- {
+ const char* version = gtgt->GetProperty("VERSION");
+ const char* soversion = gtgt->GetProperty("SOVERSION");
+ if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) {
version = 0;
soversion = 0;
- }
- if(version && !soversion)
- {
+ }
+ if (version && !soversion) {
soversion = version;
- }
- if(!version && soversion)
- {
+ }
+ if (!version && soversion) {
version = soversion;
- }
+ }
std::string realName = pnbase;
std::string soName = pnbase;
- if(version && soversion)
- {
+ if (version && soversion) {
realName += ".";
realName += version;
soName += ".";
soName += soversion;
- }
+ }
// Set attributes to specify the proper name for the target.
- std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory();
- if(target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY ||
- target.GetType() == cmTarget::EXECUTABLE)
- {
- if(this->XcodeVersion >= 21)
- {
- if(!target.UsesDefaultOutputDir(configName, false))
- {
- std::string pncdir = target.GetDirectory(configName);
- buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
- this->CreateString(pncdir.c_str()));
- }
- }
- else
- {
- buildSettings->AddAttribute("OBJROOT",
- this->CreateString(pndir.c_str()));
- pndir = target.GetDirectory(configName);
- }
+ std::string pndir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
+ if (gtgt->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ gtgt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ gtgt->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ gtgt->GetType() == cmStateEnums::EXECUTABLE) {
+ if (!gtgt->UsesDefaultOutputDir(configName,
+ cmStateEnums::RuntimeBinaryArtifact)) {
+ std::string pncdir = gtgt->GetDirectory(configName);
+ buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
+ this->CreateString(pncdir));
+ }
- if(target.IsFrameworkOnApple() || target.IsCFBundleOnApple())
- {
+ if (gtgt->IsFrameworkOnApple() || gtgt->IsCFBundleOnApple()) {
pnprefix = "";
- }
+ }
buildSettings->AddAttribute("EXECUTABLE_PREFIX",
- this->CreateString(pnprefix.c_str()));
+ this->CreateString(pnprefix));
buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
- this->CreateString(pnsuffix.c_str()));
- }
- else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
- {
+ this->CreateString(pnsuffix));
+ } else if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
pnprefix = "lib";
- pnbase = target.GetName();
+ pnbase = gtgt->GetName();
pnsuffix = ".a";
- if(this->XcodeVersion >= 21)
- {
- std::string pncdir = this->GetObjectsNormalDirectory(
- this->CurrentProject, configName, &target);
- buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
- this->CreateString(pncdir.c_str()));
- }
- else
- {
- buildSettings->AddAttribute("OBJROOT",
- this->CreateString(pndir.c_str()));
- pndir = this->GetObjectsNormalDirectory(
- this->CurrentProject, configName, &target);
- }
- }
+ std::string pncdir =
+ this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt);
+ buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
+ this->CreateString(pncdir));
+ }
// Store the product name for all target types.
- buildSettings->AddAttribute("PRODUCT_NAME",
- this->CreateString(realName.c_str()));
- buildSettings->AddAttribute("SYMROOT",
- this->CreateString(pndir.c_str()));
+ buildSettings->AddAttribute("PRODUCT_NAME", this->CreateString(realName));
+ buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir));
// Handle settings for each target type.
- switch(target.GetType())
- {
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
- {
- buildSettings->AddAttribute("LIBRARY_STYLE",
- this->CreateString("STATIC"));
- break;
+ switch (gtgt->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
+ if (gtgt->GetPropertyAsBool("FRAMEWORK")) {
+ std::string fw_version = gtgt->GetFrameworkVersion();
+ buildSettings->AddAttribute("FRAMEWORK_VERSION",
+ this->CreateString(fw_version));
+ const char* ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ if (ext) {
+ buildSettings->AddAttribute("WRAPPER_EXTENSION",
+ this->CreateString(ext));
+ }
+
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ // Xcode will create the final version of Info.plist at build time,
+ // 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());
+ buildSettings->AddAttribute("INFOPLIST_FILE",
+ this->CreateString(plist));
+ buildSettings->AddAttribute("MACH_O_TYPE",
+ this->CreateString("staticlib"));
+ } else {
+ buildSettings->AddAttribute("LIBRARY_STYLE",
+ this->CreateString("STATIC"));
+ }
+ break;
+
+ case cmStateEnums::OBJECT_LIBRARY: {
+ buildSettings->AddAttribute("LIBRARY_STYLE",
+ this->CreateString("STATIC"));
+ break;
}
- case cmTarget::MODULE_LIBRARY:
- {
- buildSettings->AddAttribute("LIBRARY_STYLE",
- this->CreateString("BUNDLE"));
- if (target.GetPropertyAsBool("BUNDLE"))
- {
- // It turns out that a BUNDLE is basically the same
- // in many ways as an application bundle, as far as
- // link flags go
- std::string createFlags =
- this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang, "_FLAGS",
- "-bundle");
- if(!createFlags.empty())
- {
- extraLinkOptions += " ";
- extraLinkOptions += createFlags;
+ case cmStateEnums::MODULE_LIBRARY: {
+ buildSettings->AddAttribute("LIBRARY_STYLE",
+ this->CreateString("BUNDLE"));
+ if (gtgt->IsCFBundleOnApple()) {
+ // It turns out that a BUNDLE is basically the same
+ // in many ways as an application bundle, as far as
+ // link flags go
+ std::string createFlags = this->LookupFlags(
+ "CMAKE_SHARED_MODULE_CREATE_", llang, "_FLAGS", "-bundle");
+ if (!createFlags.empty()) {
+ extraLinkOptions += " ";
+ extraLinkOptions += createFlags;
}
- std::string plist = this->ComputeInfoPListLocation(target);
- // Xcode will create the final version of Info.plist at build time,
- // so let it replace the cfbundle name. This avoids creating
- // a per-configuration Info.plist file. The cfbundle plist
- // is very similar to the application bundle plist
- this->CurrentLocalGenerator
- ->GenerateAppleInfoPList(&target, "$(EXECUTABLE_NAME)",
- plist.c_str());
- std::string path =
- this->ConvertToRelativeForXCode(plist.c_str());
- buildSettings->AddAttribute("INFOPLIST_FILE",
- this->CreateString(path.c_str()));
- }
- else if(this->XcodeVersion >= 22)
- {
- buildSettings->AddAttribute("MACH_O_TYPE",
- this->CreateString("mh_bundle"));
- buildSettings->AddAttribute("GCC_DYNAMIC_NO_PIC",
- this->CreateString("NO"));
- // Add the flags to create an executable.
- std::string createFlags =
- this->LookupFlags("CMAKE_", lang, "_LINK_FLAGS", "");
- if(!createFlags.empty())
- {
- extraLinkOptions += " ";
- extraLinkOptions += createFlags;
+ const char* ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ if (ext) {
+ buildSettings->AddAttribute("WRAPPER_EXTENSION",
+ this->CreateString(ext));
}
- }
- else
- {
- // Add the flags to create a module.
- std::string createFlags =
- this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang, "_FLAGS",
- "-bundle");
- if(!createFlags.empty())
- {
- extraLinkOptions += " ";
- extraLinkOptions += createFlags;
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ // Xcode will create the final version of Info.plist at build time,
+ // so let it replace the cfbundle name. This avoids creating
+ // 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());
+ buildSettings->AddAttribute("INFOPLIST_FILE",
+ this->CreateString(plist));
+ } else {
+ buildSettings->AddAttribute("MACH_O_TYPE",
+ this->CreateString("mh_bundle"));
+ buildSettings->AddAttribute("GCC_DYNAMIC_NO_PIC",
+ this->CreateString("NO"));
+ // Add the flags to create an executable.
+ std::string createFlags =
+ this->LookupFlags("CMAKE_", llang, "_LINK_FLAGS", "");
+ if (!createFlags.empty()) {
+ extraLinkOptions += " ";
+ extraLinkOptions += createFlags;
}
}
- break;
+ break;
}
- case cmTarget::SHARED_LIBRARY:
- {
- if(target.GetPropertyAsBool("FRAMEWORK"))
- {
- std::string fw_version = target.GetFrameworkVersion();
- buildSettings->AddAttribute("FRAMEWORK_VERSION",
- this->CreateString(fw_version.c_str()));
-
- std::string plist = this->ComputeInfoPListLocation(target);
- // Xcode will create the final version of Info.plist at build time,
- // so let it replace the framework name. This avoids creating
- // a per-configuration Info.plist file.
- this->CurrentLocalGenerator
- ->GenerateFrameworkInfoPList(&target, "$(EXECUTABLE_NAME)",
- plist.c_str());
- std::string path =
- this->ConvertToRelativeForXCode(plist.c_str());
- buildSettings->AddAttribute("INFOPLIST_FILE",
- this->CreateString(path.c_str()));
- }
- else
- {
- // Add the flags to create a shared library.
- std::string createFlags =
- this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang, "_FLAGS",
- "-dynamiclib");
- if(!createFlags.empty())
- {
- extraLinkOptions += " ";
- extraLinkOptions += createFlags;
+ case cmStateEnums::SHARED_LIBRARY: {
+ if (gtgt->GetPropertyAsBool("FRAMEWORK")) {
+ std::string fw_version = gtgt->GetFrameworkVersion();
+ buildSettings->AddAttribute("FRAMEWORK_VERSION",
+ this->CreateString(fw_version));
+ const char* ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ if (ext) {
+ buildSettings->AddAttribute("WRAPPER_EXTENSION",
+ this->CreateString(ext));
+ }
+
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ // Xcode will create the final version of Info.plist at build time,
+ // 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());
+ buildSettings->AddAttribute("INFOPLIST_FILE",
+ this->CreateString(plist));
+ } else {
+ // Add the flags to create a shared library.
+ std::string createFlags = this->LookupFlags(
+ "CMAKE_SHARED_LIBRARY_CREATE_", llang, "_FLAGS", "-dynamiclib");
+ if (!createFlags.empty()) {
+ extraLinkOptions += " ";
+ extraLinkOptions += createFlags;
}
}
- buildSettings->AddAttribute("LIBRARY_STYLE",
- this->CreateString("DYNAMIC"));
- break;
+ buildSettings->AddAttribute("LIBRARY_STYLE",
+ this->CreateString("DYNAMIC"));
+ break;
}
- case cmTarget::EXECUTABLE:
- {
- // Add the flags to create an executable.
- std::string createFlags =
- this->LookupFlags("CMAKE_", lang, "_LINK_FLAGS", "");
- if(!createFlags.empty())
- {
- extraLinkOptions += " ";
- extraLinkOptions += createFlags;
+ case cmStateEnums::EXECUTABLE: {
+ // Add the flags to create an executable.
+ std::string createFlags =
+ this->LookupFlags("CMAKE_", llang, "_LINK_FLAGS", "");
+ if (!createFlags.empty()) {
+ extraLinkOptions += " ";
+ extraLinkOptions += createFlags;
}
- // Handle bundles and normal executables separately.
- if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
- {
- std::string plist = this->ComputeInfoPListLocation(target);
- // Xcode will create the final version of Info.plist at build time,
- // so let it replace the executable name. This avoids creating
- // a per-configuration Info.plist file.
- this->CurrentLocalGenerator
- ->GenerateAppleInfoPList(&target, "$(EXECUTABLE_NAME)",
- plist.c_str());
- std::string path =
- this->ConvertToRelativeForXCode(plist.c_str());
- buildSettings->AddAttribute("INFOPLIST_FILE",
- this->CreateString(path.c_str()));
-
- }
- }
- break;
+ // Handle bundles and normal executables separately.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ const char* ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ if (ext) {
+ buildSettings->AddAttribute("WRAPPER_EXTENSION",
+ this->CreateString(ext));
+ }
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ // Xcode will create the final version of Info.plist at build time,
+ // 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());
+ buildSettings->AddAttribute("INFOPLIST_FILE",
+ this->CreateString(plist));
+ }
+ } break;
default:
break;
- }
- if(this->XcodeVersion >= 22 && this->XcodeVersion < 40)
- {
- buildSettings->AddAttribute("PREBINDING",
- this->CreateString("NO"));
- }
+ }
+ if (this->XcodeVersion < 40) {
+ buildSettings->AddAttribute("PREBINDING", this->CreateString("NO"));
+ }
+
+ BuildObjectListOrString dirs(this, true);
+ BuildObjectListOrString fdirs(this, true);
+ BuildObjectListOrString sysdirs(this, true);
+ BuildObjectListOrString sysfdirs(this, true);
+ const bool emitSystemIncludes = this->XcodeVersion >= 83;
- BuildObjectListOrString dirs(this, this->XcodeVersion >= 30);
- BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30);
std::vector<std::string> includes;
- this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt,
- "C", configName);
- std::set<cmStdString> emitted;
+ this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C",
+ 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->c_str()))
- {
+
+ for (std::vector<std::string>::iterator i = includes.begin();
+ i != includes.end(); ++i) {
+ if (this->NameResolvesToFramework(*i)) {
std::string frameworkDir = *i;
frameworkDir += "/../";
- frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
- if(emitted.insert(frameworkDir).second)
- {
- fdirs.Add(this->XCodeEscapePath(frameworkDir.c_str()).c_str());
+ frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
+ if (emitted.insert(frameworkDir).second) {
+ std::string incpath = this->XCodeEscapePath(frameworkDir);
+ if (emitSystemIncludes &&
+ gtgt->IsSystemIncludeDirectory(frameworkDir, configName)) {
+ sysfdirs.Add(incpath);
+ } else {
+ fdirs.Add(incpath);
}
}
- else
- {
- std::string incpath =
- this->XCodeEscapePath(i->c_str());
- dirs.Add(incpath.c_str());
+ } else {
+ std::string incpath = this->XCodeEscapePath(*i);
+ if (emitSystemIncludes &&
+ gtgt->IsSystemIncludeDirectory(*i, configName)) {
+ sysdirs.Add(incpath);
+ } else {
+ dirs.Add(incpath);
}
}
+ }
// Add framework search paths needed for linking.
- if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName))
- {
+ 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)
- {
- fdirs.Add(this->XCodeEscapePath(fdi->c_str()).c_str());
+ 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);
+ if (emitSystemIncludes &&
+ gtgt->IsSystemIncludeDirectory(*fdi, configName)) {
+ sysfdirs.Add(incpath);
+ } else {
+ fdirs.Add(incpath);
}
}
}
- if(!fdirs.IsEmpty())
- {
- buildSettings->AddAttribute("FRAMEWORK_SEARCH_PATHS",
- fdirs.CreateList());
- }
- if(!dirs.IsEmpty())
- {
- buildSettings->AddAttribute("HEADER_SEARCH_PATHS",
- dirs.CreateList());
- }
- std::string oflagc = this->ExtractFlag("-O", cflags);
- char optLevel[2];
- optLevel[0] = '0';
- optLevel[1] = 0;
- if(oflagc.size() == 3)
- {
- optLevel[0] = oflagc[2];
- }
- if(oflagc.size() == 2)
- {
- optLevel[0] = '1';
- }
- std::string oflag = this->ExtractFlag("-O", flags);
- if(oflag.size() == 3)
- {
- optLevel[0] = oflag[2];
- }
- if(oflag.size() == 2)
- {
- optLevel[0] = '1';
- }
- std::string gflagc = this->ExtractFlag("-g", cflags);
- // put back gdwarf-2 if used since there is no way
- // to represent it in the gui, but we still want debug yes
- if(gflagc == "-gdwarf-2")
- {
- cflags += " ";
- cflags += gflagc;
- }
- std::string gflag = this->ExtractFlag("-g", flags);
- if(gflag == "-gdwarf-2")
- {
- flags += " ";
- flags += gflag;
+ }
+ if (!fdirs.IsEmpty()) {
+ buildSettings->AddAttribute("FRAMEWORK_SEARCH_PATHS", fdirs.CreateList());
+ }
+ if (!dirs.IsEmpty()) {
+ buildSettings->AddAttribute("HEADER_SEARCH_PATHS", dirs.CreateList());
+ }
+ if (!sysfdirs.IsEmpty()) {
+ buildSettings->AddAttribute("SYSTEM_FRAMEWORK_SEARCH_PATHS",
+ sysfdirs.CreateList());
+ }
+ if (!sysdirs.IsEmpty()) {
+ buildSettings->AddAttribute("SYSTEM_HEADER_SEARCH_PATHS",
+ sysdirs.CreateList());
+ }
+
+ if (this->XcodeVersion >= 60 && !emitSystemIncludes) {
+ // Add those per-language flags in addition to HEADER_SEARCH_PATHS to gain
+ // 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) {
+ std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags(
+ includes, gtgt, *li, true, false, configName);
+
+ if (!includeFlags.empty()) {
+ cflags[*li] += " " + includeFlags;
+ }
}
+ }
+
+ bool same_gflags = true;
+ std::map<std::string, std::string> gflags;
+ std::string const* last_gflag = 0;
+ 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];
+ std::string oflag =
+ this->ExtractFlagRegex("(^| )(-Ofast|-Os|-O[0-9]*)( |$)", 2, flags);
+ if (oflag.size() == 2) {
+ optLevel = "1";
+ } else if (oflag.size() > 2) {
+ optLevel = oflag.substr(2);
+ }
+ gflag = this->ExtractFlag("-g", flags);
+ // put back gdwarf-2 if used since there is no way
+ // to represent it in the gui, but we still want debug yes
+ if (gflag == "-gdwarf-2") {
+ flags += " ";
+ flags += gflag;
+ }
+ if (last_gflag && *last_gflag != gflag) {
+ same_gflags = false;
+ }
+ last_gflag = &gflag;
+ }
+
const char* debugStr = "YES";
- // We can't set the Xcode flag differently depending on the language,
- // so put them back in this case.
- if( (lang && strcmp(lang, "CXX") == 0) && gflag != gflagc )
- {
- cflags += " ";
- cflags += gflagc;
- flags += " ";
- flags += gflag;
- debugStr = "NO";
+ 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];
}
- if( gflag == "-g0" || gflag.size() == 0 )
- {
debugStr = "NO";
- }
+ } else if (last_gflag && (last_gflag->empty() || *last_gflag == "-g0")) {
+ debugStr = "NO";
+ }
buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES",
this->CreateString("YES"));
@@ -2184,200 +2090,161 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->CreateString("NO"));
buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
this->CreateString("NO"));
- if(lang && strcmp(lang, "CXX") == 0)
- {
- flags += " ";
- flags += defFlags;
- buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
- this->CreateString(flags.c_str()));
- cflags += " ";
- cflags += defFlags;
- buildSettings->AddAttribute("OTHER_CFLAGS",
- this->CreateString(cflags.c_str()));
-
- }
- else
- {
- flags += " ";
- flags += defFlags;
- buildSettings->AddAttribute("OTHER_CFLAGS",
- this->CreateString(flags.c_str()));
+ 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") {
+ buildSettings->AddAttribute("IFORT_OTHER_FLAGS",
+ this->CreateString(flags));
+ } else if (*li == "C") {
+ buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags));
+ } else if (*li == "Swift") {
+ buildSettings->AddAttribute("OTHER_SWIFT_FLAGS",
+ this->CreateString(flags));
}
+ }
// Add Fortran source format attribute if property is set.
const char* format = 0;
- const char* tgtfmt = target.GetProperty("Fortran_FORMAT");
- switch(this->CurrentLocalGenerator->GetFortranFormat(tgtfmt))
- {
- case cmLocalGenerator::FortranFormatFixed: format = "fixed"; break;
- case cmLocalGenerator::FortranFormatFree: format = "free"; break;
- default: break;
- }
- if(format)
- {
+ const char* tgtfmt = gtgt->GetProperty("Fortran_FORMAT");
+ switch (cmOutputConverter::GetFortranFormat(tgtfmt)) {
+ case cmOutputConverter::FortranFormatFixed:
+ format = "fixed";
+ break;
+ case cmOutputConverter::FortranFormatFree:
+ format = "free";
+ break;
+ default:
+ break;
+ }
+ if (format) {
buildSettings->AddAttribute("IFORT_LANG_SRCFMT",
this->CreateString(format));
- }
+ }
// Create the INSTALL_PATH attribute.
std::string install_name_dir;
- if(target.GetType() == cmTarget::SHARED_LIBRARY)
- {
+ if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
// Get the install_name directory for the build tree.
- install_name_dir = target.GetInstallNameDirForBuildTree(configName);
+ install_name_dir = gtgt->GetInstallNameDirForBuildTree(configName);
// Xcode doesn't create the correct install_name in some cases.
// That is, if the INSTALL_PATH is empty, or if we have versioning
// of dylib libraries, we want to specify the install_name.
// This is done by adding a link flag to create an install_name
// with just the library soname.
std::string install_name;
- if(!install_name_dir.empty())
- {
+ if (!install_name_dir.empty()) {
// Convert to a path for the native build tool.
cmSystemTools::ConvertToUnixSlashes(install_name_dir);
install_name += install_name_dir;
install_name += "/";
- }
- install_name += target.GetSOName(configName);
+ }
+ install_name += gtgt->GetSOName(configName);
- if((realName != soName) || install_name_dir.empty())
- {
+ if ((realName != soName) || install_name_dir.empty()) {
install_name_dir = "";
extraLinkOptions += " -install_name ";
- extraLinkOptions += XCodeEscapePath(install_name.c_str());
- }
+ extraLinkOptions += XCodeEscapePath(install_name);
}
+ }
buildSettings->AddAttribute("INSTALL_PATH",
- this->CreateString(install_name_dir.c_str()));
+ this->CreateString(install_name_dir));
// Create the LD_RUNPATH_SEARCH_PATHS
- cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
- if(pcli)
- {
+ cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName);
+ if (pcli) {
std::string search_paths;
std::vector<std::string> runtimeDirs;
pcli->GetRPath(runtimeDirs, false);
- for(std::vector<std::string>::const_iterator i = runtimeDirs.begin();
- i != runtimeDirs.end(); ++i)
- {
- if(!search_paths.empty())
- {
- search_paths += " ";
+ // 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;
+ runpath = this->ExpandCFGIntDir(runpath, configName);
+
+ if (unique_dirs.find(runpath) == unique_dirs.end()) {
+ unique_dirs.insert(runpath);
+ if (!search_paths.empty()) {
+ search_paths += " ";
}
- search_paths += this->XCodeEscapePath((*i).c_str());
+ search_paths += this->XCodeEscapePath(runpath);
}
- if(!search_paths.empty())
- {
+ }
+ if (!search_paths.empty()) {
buildSettings->AddAttribute("LD_RUNPATH_SEARCH_PATHS",
- this->CreateString(search_paths.c_str()));
- }
+ this->CreateString(search_paths));
}
+ }
- buildSettings->AddAttribute("OTHER_LDFLAGS",
- this->CreateString(extraLinkOptions.c_str()));
- buildSettings->AddAttribute("OTHER_REZFLAGS",
- this->CreateString(""));
- buildSettings->AddAttribute("SECTORDER_FLAGS",
- this->CreateString(""));
- buildSettings->AddAttribute("USE_HEADERMAP",
- this->CreateString("NO"));
- if (this->XcodeVersion >= 30)
- {
- cmXCodeObject *group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- group->AddObject(this->CreateString("-Wmost"));
- group->AddObject(this->CreateString("-Wno-four-char-constants"));
- group->AddObject(this->CreateString("-Wno-unknown-pragmas"));
- buildSettings->AddAttribute("WARNING_CFLAGS", group);
- }
- else
- {
- buildSettings->AddAttribute("WARNING_CFLAGS",
- this->CreateString(
- "-Wmost -Wno-four-char-constants"
- " -Wno-unknown-pragmas"));
- }
+ buildSettings->AddAttribute(this->GetTargetLinkFlagsVar(gtgt),
+ this->CreateString(extraLinkOptions));
+ buildSettings->AddAttribute("OTHER_REZFLAGS", this->CreateString(""));
+ buildSettings->AddAttribute("SECTORDER_FLAGS", this->CreateString(""));
+ buildSettings->AddAttribute("USE_HEADERMAP", this->CreateString("NO"));
+ cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ group->AddObject(this->CreateString("-Wmost"));
+ group->AddObject(this->CreateString("-Wno-four-char-constants"));
+ group->AddObject(this->CreateString("-Wno-unknown-pragmas"));
+ group->AddObject(this->CreateString("$(inherited)"));
+ buildSettings->AddAttribute("WARNING_CFLAGS", group);
// Runtime version information.
- if(target.GetType() == cmTarget::SHARED_LIBRARY)
- {
+ if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
int major;
int minor;
int patch;
// VERSION -> current_version
- target.GetTargetVersion(false, major, minor, patch);
- cmOStringStream v;
+ gtgt->GetTargetVersion(false, major, minor, patch);
+ std::ostringstream v;
// Xcode always wants at least 1.0.0 or nothing
- if(!(major == 0 && minor == 0 && patch == 0))
- {
+ if (!(major == 0 && minor == 0 && patch == 0)) {
v << major << "." << minor << "." << patch;
- }
+ }
buildSettings->AddAttribute("DYLIB_CURRENT_VERSION",
- this->CreateString(v.str().c_str()));
+ this->CreateString(v.str()));
// SOVERSION -> compatibility_version
- target.GetTargetVersion(true, major, minor, patch);
- cmOStringStream vso;
+ gtgt->GetTargetVersion(true, major, minor, patch);
+ std::ostringstream vso;
// Xcode always wants at least 1.0.0 or nothing
- if(!(major == 0 && minor == 0 && patch == 0))
- {
+ if (!(major == 0 && minor == 0 && patch == 0)) {
vso << major << "." << minor << "." << patch;
- }
- buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
- this->CreateString(vso.str().c_str()));
}
+ buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
+ this->CreateString(vso.str()));
+ }
// put this last so it can override existing settings
// Convert "XCODE_ATTRIBUTE_*" properties directly.
{
- cmPropertyMap const& props = target.GetProperties();
- for(cmPropertyMap::const_iterator i = props.begin();
- i != props.end(); ++i)
- {
- if(i->first.find("XCODE_ATTRIBUTE_") == 0)
- {
- cmStdString attribute = i->first.substr(16);
- // Handle [variant=<config>] condition explicitly here.
- cmStdString::size_type beginVariant =
- attribute.find("[variant=");
- if (beginVariant != cmStdString::npos)
- {
- cmStdString::size_type endVariant =
- attribute.find("]", beginVariant+9);
- if (endVariant != cmStdString::npos)
- {
- // Compare the variant to the configuration.
- cmStdString variant =
- attribute.substr(beginVariant+9, endVariant-beginVariant-9);
- if (variant == configName)
- {
- // The variant matches the configuration so use this
- // attribute but drop the [variant=<config>] condition.
- attribute.erase(beginVariant, endVariant-beginVariant+1);
- }
- else
- {
- // The variant does not match the configuration so
- // do not use this attribute.
- attribute.clear();
- }
- }
- }
-
- if (!attribute.empty())
- {
- buildSettings->AddAttribute(attribute.c_str(),
- this->CreateString(i->second.GetValue()));
+ 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);
+ this->FilterConfigurationAttribute(configName, attribute);
+ if (!attribute.empty()) {
+ cmGeneratorExpression ge;
+ std::string processed =
+ ge.Parse(gtgt->GetProperty(*i))
+ ->Evaluate(this->CurrentLocalGenerator, configName);
+ buildSettings->AddAttribute(attribute,
+ this->CreateString(processed));
}
}
}
}
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
+ cmGeneratorTarget* gtgt)
{
cmXCodeObject* shellBuildPhase =
this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
@@ -2391,66 +2258,49 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
shellBuildPhase->AddAttribute("outputPaths", outputPaths);
shellBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
this->CreateString("0"));
- shellBuildPhase->AddAttribute("shellPath",
- this->CreateString("/bin/sh"));
- shellBuildPhase->AddAttribute("shellScript",
- this->CreateString(
- "# shell script goes here\nexit 0"));
- shellBuildPhase->AddAttribute("showEnvVarsInLog",
- this->CreateString("0"));
+ shellBuildPhase->AddAttribute("shellPath", this->CreateString("/bin/sh"));
+ shellBuildPhase->AddAttribute(
+ "shellScript", this->CreateString("# shell script goes here\nexit 0"));
+ shellBuildPhase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
cmXCodeObject* target =
this->CreateObject(cmXCodeObject::PBXAggregateTarget);
- target->SetComment(cmtarget.GetName());
- cmXCodeObject* buildPhases =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ target->SetComment(gtgt->GetName());
+ cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
std::vector<cmXCodeObject*> emptyContentVector;
this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0,
- cmtarget);
+ gtgt);
target->AddAttribute("buildPhases", buildPhases);
- if(this->XcodeVersion > 20)
- {
- this->AddConfigurations(target, cmtarget);
- }
- else
- {
- const char* theConfig =
- this->CurrentMakefile->GetDefinition("CMAKE_BUILD_TYPE");
- cmXCodeObject* buildSettings =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- this->CreateBuildSettings(cmtarget, buildSettings, theConfig);
- target->AddAttribute("buildSettings", buildSettings);
- }
- cmXCodeObject* dependencies =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ this->AddConfigurations(target, gtgt);
+ cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
target->AddAttribute("dependencies", dependencies);
- target->AddAttribute("name", this->CreateString(cmtarget.GetName()));
- target->AddAttribute("productName",this->CreateString(cmtarget.GetName()));
- target->SetTarget(&cmtarget);
+ target->AddAttribute("name", this->CreateString(gtgt->GetName()));
+ target->AddAttribute("productName", this->CreateString(gtgt->GetName()));
+ target->SetTarget(gtgt);
+ this->XCodeObjectMap[gtgt] = target;
// Add source files without build rules for editing convenience.
- if(cmtarget.GetType() == cmTarget::UTILITY)
- {
- std::vector<cmSourceFile*> const& sources = cmtarget.GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
- i != sources.end(); ++i)
- {
- if(!(*i)->GetPropertyAsBool("GENERATED"))
- {
- this->CreateXCodeFileReference(*i, cmtarget);
- }
+ if (gtgt->GetType() == cmStateEnums::UTILITY) {
+ std::vector<cmSourceFile*> sources;
+ if (!gtgt->GetConfigCommonSourceFiles(sources)) {
+ return 0;
+ }
+
+ for (std::vector<cmSourceFile*>::const_iterator i = sources.begin();
+ i != sources.end(); ++i) {
+ if (!(*i)->GetPropertyAsBool("GENERATED")) {
+ this->CreateXCodeFileReference(*i, gtgt);
}
}
+ }
- target->SetId(this->GetOrCreateId(
- cmtarget.GetName(), target->GetId()).c_str());
+ target->SetId(this->GetOrCreateId(gtgt->GetName(), target->GetId()));
return target;
}
-//----------------------------------------------------------------------------
std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
- cmTarget& cmtarget)
+ cmGeneratorTarget* gtgt)
{
std::string configTypes =
this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
@@ -2466,190 +2316,189 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
std::string comment = "Build configuration list for ";
comment += cmXCodeObject::PBXTypeNames[target->GetIsA()];
comment += " \"";
- comment += cmtarget.GetName();
+ comment += gtgt->GetName();
comment += "\"";
- configlist->SetComment(comment.c_str());
+ configlist->SetComment(comment);
target->AddAttribute("buildConfigurationList",
this->CreateObjectReference(configlist));
- for(unsigned int i = 0; i < configVector.size(); ++i)
- {
+ for (unsigned int i = 0; i < configVector.size(); ++i) {
cmXCodeObject* config =
this->CreateObject(cmXCodeObject::XCBuildConfiguration);
buildConfigurations->AddObject(config);
cmXCodeObject* buildSettings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- this->CreateBuildSettings(cmtarget, buildSettings,
- configVector[i].c_str());
- config->AddAttribute("name", this->CreateString(configVector[i].c_str()));
- config->SetComment(configVector[i].c_str());
+ this->CreateBuildSettings(gtgt, buildSettings, configVector[i]);
+ config->AddAttribute("name", this->CreateString(configVector[i]));
+ config->SetComment(configVector[i]);
config->AddAttribute("buildSettings", buildSettings);
- }
- if(configVector.size())
- {
+ }
+ if (!configVector.empty()) {
configlist->AddAttribute("defaultConfigurationName",
- this->CreateString(configVector[0].c_str()));
+ this->CreateString(configVector[0]));
configlist->AddAttribute("defaultConfigurationIsVisible",
this->CreateString("0"));
return configVector[0];
- }
+ }
return "";
}
-//----------------------------------------------------------------------------
-const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget)
+const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar(
+ cmGeneratorTarget const* target) const
{
- switch(cmtarget.GetType())
- {
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
+ if (this->XcodeVersion >= 60 &&
+ (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ target->GetType() == cmStateEnums::OBJECT_LIBRARY)) {
+ return "OTHER_LIBTOOLFLAGS";
+ } else {
+ return "OTHER_LDFLAGS";
+ }
+}
+
+const char* cmGlobalXCodeGenerator::GetTargetFileType(
+ cmGeneratorTarget* target)
+{
+ if (const char* e = target->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) {
+ return e;
+ }
+
+ switch (target->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
return "archive.ar";
- case cmTarget::MODULE_LIBRARY:
- if (cmtarget.IsCFBundleOnApple())
+ case cmStateEnums::STATIC_LIBRARY:
+ return (target->GetPropertyAsBool("FRAMEWORK") ? "wrapper.framework"
+ : "archive.ar");
+ case cmStateEnums::MODULE_LIBRARY:
+ if (target->IsXCTestOnApple())
+ return "wrapper.cfbundle";
+ else if (target->IsCFBundleOnApple())
return "wrapper.plug-in";
else
- return ((this->XcodeVersion >= 22)?
- "compiled.mach-o.executable" : "compiled.mach-o.dylib");
- case cmTarget::SHARED_LIBRARY:
- return (cmtarget.GetPropertyAsBool("FRAMEWORK")?
- "wrapper.framework" : "compiled.mach-o.dylib");
- case cmTarget::EXECUTABLE:
+ return "compiled.mach-o.executable";
+ case cmStateEnums::SHARED_LIBRARY:
+ return (target->GetPropertyAsBool("FRAMEWORK")
+ ? "wrapper.framework"
+ : "compiled.mach-o.dylib");
+ case cmStateEnums::EXECUTABLE:
return "compiled.mach-o.executable";
- default: break;
- }
+ default:
+ break;
+ }
return 0;
}
-//----------------------------------------------------------------------------
-const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget& cmtarget)
+const char* cmGlobalXCodeGenerator::GetTargetProductType(
+ cmGeneratorTarget* target)
{
- switch(cmtarget.GetType())
- {
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
+ if (const char* e = target->GetProperty("XCODE_PRODUCT_TYPE")) {
+ return e;
+ }
+
+ switch (target->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
return "com.apple.product-type.library.static";
- case cmTarget::MODULE_LIBRARY:
- if (cmtarget.IsCFBundleOnApple())
+ case cmStateEnums::STATIC_LIBRARY:
+ return (target->GetPropertyAsBool("FRAMEWORK")
+ ? "com.apple.product-type.framework"
+ : "com.apple.product-type.library.static");
+ case cmStateEnums::MODULE_LIBRARY:
+ if (target->IsXCTestOnApple())
+ return "com.apple.product-type.bundle.unit-test";
+ else if (target->IsCFBundleOnApple())
return "com.apple.product-type.bundle";
else
- return ((this->XcodeVersion >= 22)?
- "com.apple.product-type.tool" :
- "com.apple.product-type.library.dynamic");
- case cmTarget::SHARED_LIBRARY:
- return (cmtarget.GetPropertyAsBool("FRAMEWORK")?
- "com.apple.product-type.framework" :
- "com.apple.product-type.library.dynamic");
- case cmTarget::EXECUTABLE:
- return (cmtarget.GetPropertyAsBool("MACOSX_BUNDLE")?
- "com.apple.product-type.application" :
- "com.apple.product-type.tool");
- default: break;
- }
+ return "com.apple.product-type.tool";
+ case cmStateEnums::SHARED_LIBRARY:
+ return (target->GetPropertyAsBool("FRAMEWORK")
+ ? "com.apple.product-type.framework"
+ : "com.apple.product-type.library.dynamic");
+ case cmStateEnums::EXECUTABLE:
+ return (target->GetPropertyAsBool("MACOSX_BUNDLE")
+ ? "com.apple.product-type.application"
+ : "com.apple.product-type.tool");
+ default:
+ break;
+ }
return 0;
}
-//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
- cmXCodeObject* buildPhases)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
+ cmGeneratorTarget* gtgt, cmXCodeObject* buildPhases)
{
- cmXCodeObject* target =
- this->CreateObject(cmXCodeObject::PBXNativeTarget);
+ if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return 0;
+ }
+ cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXNativeTarget);
target->AddAttribute("buildPhases", buildPhases);
cmXCodeObject* buildRules = this->CreateObject(cmXCodeObject::OBJECT_LIST);
target->AddAttribute("buildRules", buildRules);
std::string defConfig;
- if(this->XcodeVersion > 20)
- {
- defConfig = this->AddConfigurations(target, cmtarget);
- }
- else
- {
- cmXCodeObject* buildSettings =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- defConfig = this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- this->CreateBuildSettings(cmtarget, buildSettings, defConfig.c_str());
- target->AddAttribute("buildSettings", buildSettings);
- }
- cmXCodeObject* dependencies =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ defConfig = this->AddConfigurations(target, gtgt);
+ cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
target->AddAttribute("dependencies", dependencies);
- target->AddAttribute("name", this->CreateString(cmtarget.GetName()));
- target->AddAttribute("productName",this->CreateString(cmtarget.GetName()));
+ target->AddAttribute("name", this->CreateString(gtgt->GetName()));
+ target->AddAttribute("productName", this->CreateString(gtgt->GetName()));
- cmXCodeObject* fileRef =
- this->CreateObject(cmXCodeObject::PBXFileReference);
- if(const char* fileType = this->GetTargetFileType(cmtarget))
- {
+ cmXCodeObject* fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
+ if (const char* fileType = this->GetTargetFileType(gtgt)) {
fileRef->AddAttribute("explicitFileType", this->CreateString(fileType));
- }
+ }
std::string fullName;
- if(cmtarget.GetType() == cmTarget::OBJECT_LIBRARY)
- {
+ if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
fullName = "lib";
- fullName += cmtarget.GetName();
+ fullName += gtgt->GetName();
fullName += ".a";
- }
- else
- {
- fullName = cmtarget.GetFullName(defConfig.c_str());
- }
- fileRef->AddAttribute("path", this->CreateString(fullName.c_str()));
- fileRef->AddAttribute("refType", this->CreateString("0"));
+ } else {
+ fullName = gtgt->GetFullName(defConfig);
+ }
+ fileRef->AddAttribute("path", this->CreateString(fullName));
fileRef->AddAttribute("sourceTree",
this->CreateString("BUILT_PRODUCTS_DIR"));
- fileRef->SetComment(cmtarget.GetName());
+ fileRef->SetComment(gtgt->GetName());
target->AddAttribute("productReference",
this->CreateObjectReference(fileRef));
- if(const char* productType = this->GetTargetProductType(cmtarget))
- {
+ if (const char* productType = this->GetTargetProductType(gtgt)) {
target->AddAttribute("productType", this->CreateString(productType));
- }
- target->SetTarget(&cmtarget);
- target->SetId(this->GetOrCreateId(
- cmtarget.GetName(), target->GetId()).c_str());
+ }
+ target->SetTarget(gtgt);
+ this->XCodeObjectMap[gtgt] = target;
+ target->SetId(this->GetOrCreateId(gtgt->GetName(), target->GetId()));
return target;
}
-//----------------------------------------------------------------------------
-cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
+cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
+ cmGeneratorTarget const* t)
{
- if(!t)
- {
+ if (!t) {
return 0;
- }
- for(std::vector<cmXCodeObject*>::iterator i = this->XCodeObjects.begin();
- i != this->XCodeObjects.end(); ++i)
- {
- cmXCodeObject* o = *i;
- if(o->GetTarget() == t)
- {
- return o;
- }
- }
- return 0;
+ }
+
+ std::map<cmGeneratorTarget const*, cmXCodeObject*>::const_iterator const i =
+ this->XCodeObjectMap.find(t);
+ if (i == this->XCodeObjectMap.end()) {
+ return 0;
+ }
+ return i->second;
}
-//----------------------------------------------------------------------------
-std::string cmGlobalXCodeGenerator::GetOrCreateId(const char* name,
- const char* id)
+std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
+ const std::string& id)
{
std::string guidStoreName = name;
guidStoreName += "_GUID_CMAKE";
const char* storedGUID =
- this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str());
+ this->CMakeInstance->GetCacheDefinition(guidStoreName);
- if(storedGUID)
- {
+ if (storedGUID) {
return storedGUID;
- }
+ }
- this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(),
- id, "Stored Xcode object GUID", cmCacheManager::INTERNAL);
+ this->CMakeInstance->AddCacheEntry(guidStoreName, id.c_str(),
+ "Stored Xcode object GUID",
+ cmStateEnums::INTERNAL);
return id;
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
cmXCodeObject* dependTarget)
{
@@ -2662,739 +2511,553 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
container->AddAttribute("proxyType", this->CreateString("1"));
container->AddAttribute("remoteGlobalIDString",
this->CreateObjectReference(dependTarget));
- container->AddAttribute("remoteInfo",
- this->CreateString(
- dependTarget->GetTarget()->GetName()));
+ container->AddAttribute(
+ "remoteInfo", this->CreateString(dependTarget->GetTarget()->GetName()));
cmXCodeObject* targetdep =
this->CreateObject(cmXCodeObject::PBXTargetDependency);
targetdep->SetComment("PBXTargetDependency");
- targetdep->AddAttribute("target",
- this->CreateObjectReference(dependTarget));
+ targetdep->AddAttribute("target", this->CreateObjectReference(dependTarget));
targetdep->AddAttribute("targetProxy",
this->CreateObjectReference(container));
cmXCodeObject* depends = target->GetObject("dependencies");
- if(!depends)
- {
- cmSystemTools::
- Error("target does not have dependencies attribute error..");
+ if (!depends) {
+ cmSystemTools::Error(
+ "target does not have dependencies attribute error..");
- }
- else
- {
+ } else {
depends->AddUniqueObject(targetdep);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
const char* attribute,
const char* value)
{
- if(settings)
- {
+ if (settings) {
cmXCodeObject* attr = settings->GetObject(attribute);
- if(!attr)
- {
+ if (!attr) {
settings->AddAttribute(attribute, this->CreateString(value));
- }
- else
- {
+ } else {
std::string oldValue = attr->GetString();
oldValue += " ";
oldValue += value;
- attr->SetString(oldValue.c_str());
- }
+ attr->SetString(oldValue);
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator
-::AppendBuildSettingAttribute(cmXCodeObject* target,
- const char* attribute,
- const char* value,
- const char* configName)
-{
- if(this->XcodeVersion < 21)
- {
- // There is only one configuration. Add the setting to the buildSettings
- // of the target.
- this->AppendOrAddBuildSetting(target->GetObject("buildSettings"),
- attribute, value);
- }
- else
- {
- // There are multiple configurations. Add the setting to the
- // buildSettings of the configuration name given.
- cmXCodeObject* configurationList =
- 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)
- {
- if(strcmp((*i)->GetObject("name")->GetString(), configName) == 0)
- {
- cmXCodeObject* settings = (*i)->GetObject("buildSettings");
- this->AppendOrAddBuildSetting(settings, attribute, value);
- }
- }
- else
- {
+void cmGlobalXCodeGenerator::AppendBuildSettingAttribute(
+ cmXCodeObject* target, const char* attribute, const char* value,
+ const std::string& configName)
+{
+ // There are multiple configurations. Add the setting to the
+ // buildSettings of the configuration name given.
+ cmXCodeObject* configurationList =
+ 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");
+ this->AppendOrAddBuildSetting(settings, attribute, value);
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator
-::AddDependAndLinkInformation(cmXCodeObject* target)
+void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
{
- cmTarget* cmtarget = target->GetTarget();
- if(!cmtarget)
- {
+ cmGeneratorTarget* gt = target->GetTarget();
+ if (!gt) {
cmSystemTools::Error("Error no target on xobject\n");
return;
- }
+ }
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
// Add dependencies on other CMake targets.
- TargetDependSet const& deps = this->GetTargetDirectDepends(*cmtarget);
- for(TargetDependSet::const_iterator i = deps.begin(); i != deps.end(); ++i)
- {
- if(cmXCodeObject* dptarget = this->FindXCodeTarget(*i))
- {
+ TargetDependSet const& deps = this->GetTargetDirectDepends(gt);
+ for (TargetDependSet::const_iterator i = deps.begin(); i != deps.end();
+ ++i) {
+ if (cmXCodeObject* dptarget = this->FindXCodeTarget(*i)) {
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)
- {
+ for (std::vector<std::string>::iterator i =
+ this->CurrentConfigurationTypes.begin();
+ i != this->CurrentConfigurationTypes.end(); ++i) {
// Get the current configuration name.
- const char* configName = i->c_str();
- if(!*configName)
- {
- configName = 0;
- }
+ std::string configName = *i;
- if(this->XcodeVersion >= 50)
- {
+ if (this->XcodeVersion >= 50) {
// Add object library contents as link flags.
std::string linkObjs;
const char* sep = "";
- std::vector<std::string> objs;
- this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
+ 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()) {
+ continue;
+ }
linkObjs += sep;
sep = " ";
- linkObjs += this->XCodeEscapePath(oi->c_str());
- }
- this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
- linkObjs.c_str(), configName);
+ linkObjs += this->XCodeEscapePath((*oi)->GetFullPath());
}
+ this->AppendBuildSettingAttribute(
+ target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName);
+ }
// Skip link information for object libraries.
- if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY ||
- cmtarget->GetType() == cmTarget::STATIC_LIBRARY)
- {
+ if (gt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ gt->GetType() == cmStateEnums::STATIC_LIBRARY) {
continue;
- }
+ }
// Compute the link library and directory information.
- cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
- if(!pcli)
- {
+ cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
+ if (!pcli) {
continue;
- }
+ }
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->c_str());
+ 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);
}
}
// 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")
- {
- if(this->XcodeVersion > 15)
- {
+ 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") {
// Now add the same one but append
// $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
linkDirs += " ";
linkDirs += this->XCodeEscapePath(
- (*libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)").c_str());
- }
- linkDirs += " ";
- linkDirs += this->XCodeEscapePath(libDir->c_str());
+ *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
+ linkDirs += " ";
+ linkDirs += this->XCodeEscapePath(*libDir);
}
}
- this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
- linkDirs.c_str(), configName);
+ this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
+ linkDirs.c_str(), configName);
}
// now add the link libraries
{
- 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)
- {
- linkLibs += sep;
- sep = " ";
- if(li->IsPath)
- {
- linkLibs += this->XCodeEscapePath(li->Value.c_str());
- }
- else
- {
- linkLibs += li->Value;
+ 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) {
+ 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(li->Target && !li->Target->IsImported())
- {
- target->AddDependTarget(configName, li->Target->GetName());
+ if (li->Target && !li->Target->IsImported()) {
+ target->AddDependTarget(configName, li->Target->GetName());
}
}
- this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
- linkLibs.c_str(), configName);
- }
+ this->AppendBuildSettingAttribute(
+ target, this->GetTargetLinkFlagsVar(gt), linkLibs.c_str(), configName);
}
+ }
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>&
- generators)
+bool cmGlobalXCodeGenerator::CreateGroups(
+ std::vector<cmLocalGenerator*>& generators)
{
- for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
- i != generators.end(); ++i)
- {
- if(this->IsExcluded(root, *i))
- {
- continue;
- }
+ for (std::vector<cmLocalGenerator*>::iterator i = generators.begin();
+ i != generators.end(); ++i) {
cmMakefile* mf = (*i)->GetMakefile();
std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
- cmTargets &tgts = mf->GetTargets();
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
- {
- cmTarget& cmtarget = l->second;
+ std::vector<cmGeneratorTarget*> tgts = (*i)->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
+ l != tgts.end(); l++) {
+ cmGeneratorTarget* gtgt = *l;
// Same skipping logic here as in CreateXCodeTargets so that we do not
// end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
// groups:
//
- if(cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
- {
+ if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
- }
+ }
+ 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(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE"))
- {
- std::string plist = this->ComputeInfoPListLocation(cmtarget);
- cmSourceFile* sf = mf->GetOrCreateSource(plist.c_str(), true);
- cmtarget.AddSourceFile(sf);
- }
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ mf->GetOrCreateSource(plist, true);
+ gtgt->AddSource(plist);
+ }
- std::vector<cmSourceFile*> classes = cmtarget.GetSourceFiles();
+ std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+ gtgt->GetAllConfigSources();
// Put cmSourceFile instances in proper groups:
- for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
- s != classes.end(); s++)
- {
- cmSourceFile* sf = *s;
+ 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()) {
+ // 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(cmtarget, &sourceGroup);
- cmStdString key = GetGroupMapKey(cmtarget, sf);
- this->GroupMap[key] = pbxgroup;
- }
-
- // Put OBJECT_LIBRARY objects in proper groups:
- std::vector<std::string> objs;
- this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- std::string const& source = *oi;
- cmSourceGroup& sourceGroup =
+ cmSourceGroup* sourceGroup =
mf->FindSourceGroup(source.c_str(), sourceGroups);
- cmXCodeObject* pbxgroup =
- this->CreateOrGetPBXGroup(cmtarget, &sourceGroup);
- cmStdString key = GetGroupMapKeyFromPath(cmtarget, source);
+ cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
+ std::string key = GetGroupMapKeyFromPath(gtgt, source);
this->GroupMap[key] = pbxgroup;
- }
}
}
+ }
+ return true;
}
-cmXCodeObject *cmGlobalXCodeGenerator
-::CreatePBXGroup(cmXCodeObject *parent, cmStdString name)
+cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent,
+ std::string name)
{
cmXCodeObject* parentChildren = NULL;
- if(parent)
+ 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.c_str()));
+ this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ group->AddAttribute("name", this->CreateString(name));
group->AddAttribute("children", groupChildren);
- if(this->XcodeVersion == 15)
- {
- group->AddAttribute("refType", this->CreateString("4"));
- }
group->AddAttribute("sourceTree", this->CreateString("<group>"));
- if(parentChildren)
+ if (parentChildren)
parentChildren->AddObject(group);
return group;
}
-//----------------------------------------------------------------------------
-cmXCodeObject* cmGlobalXCodeGenerator
-::CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg)
+cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
+ cmGeneratorTarget* gtgt, cmSourceGroup* sg)
{
- cmStdString s;
- cmStdString target;
- const char *targetFolder= cmtarget.GetProperty("FOLDER");
- if(targetFolder) {
+ std::string s;
+ std::string target;
+ const std::string targetFolder = gtgt->GetEffectiveFolderName();
+ if (!targetFolder.empty()) {
target = targetFolder;
target += "/";
}
- target += cmtarget.GetName();
+ target += gtgt->GetName();
s = target + "/";
s += sg->GetFullName();
- std::map<cmStdString, cmXCodeObject* >::iterator it =
+ std::map<std::string, cmXCodeObject*>::iterator it =
this->GroupNameMap.find(s);
- if(it != this->GroupNameMap.end())
- {
+ if (it != this->GroupNameMap.end()) {
return it->second;
- }
+ }
it = this->TargetGroup.find(target);
cmXCodeObject* tgroup = 0;
- if(it != this->TargetGroup.end())
- {
+ if (it != this->TargetGroup.end()) {
tgroup = it->second;
- }
- else
- {
+ } else {
std::vector<std::string> tgt_folders =
cmSystemTools::tokenize(target, "/");
- cmStdString curr_tgt_folder;
- for(std::vector<std::string>::size_type i = 0; i < tgt_folders.size();i++)
- {
+ std::string curr_tgt_folder;
+ for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size();
+ i++) {
+ if (i != 0) {
+ curr_tgt_folder += "/";
+ }
curr_tgt_folder += tgt_folders[i];
it = this->TargetGroup.find(curr_tgt_folder);
- if(it == this->TargetGroup.end())
- {
- tgroup = this->CreatePBXGroup(tgroup,tgt_folders[i]);
- this->TargetGroup[curr_tgt_folder] = tgroup;
- }
- else
- {
+ if (it != this->TargetGroup.end()) {
tgroup = it->second;
continue;
- }
- if(i == 0)
- {
- this->SourcesGroupChildren->AddObject(tgroup);
- }
- curr_tgt_folder += "/";
+ }
+ tgroup = this->CreatePBXGroup(tgroup, tgt_folders[i]);
+ this->TargetGroup[curr_tgt_folder] = tgroup;
+ if (i == 0) {
+ this->MainGroupChildren->AddObject(tgroup);
}
}
+ }
this->TargetGroup[target] = tgroup;
// If it's the default source group (empty name) then put the source file
// directly in the tgroup...
//
- if (cmStdString(sg->GetFullName()) == "")
- {
+ if (std::string(sg->GetFullName()) == "") {
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()))
- {
+ // 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(), "\\");
- cmStdString curr_folder = target;
+ std::string curr_folder = target;
curr_folder += "/";
- for(std::vector<std::string>::size_type i = 0; i < folders.size();i++)
- {
+ for (std::vector<std::string>::size_type i = 0; i < folders.size(); i++) {
curr_folder += folders[i];
- std::map<cmStdString, cmXCodeObject* >::iterator i_folder =
+ std::map<std::string, cmXCodeObject*>::iterator i_folder =
this->GroupNameMap.find(curr_folder);
- //Create new folder
- if(i_folder == this->GroupNameMap.end())
- {
- cmXCodeObject *group = this->CreatePBXGroup(tgroup,folders[i]);
+ // Create new folder
+ if (i_folder == this->GroupNameMap.end()) {
+ cmXCodeObject* group = this->CreatePBXGroup(tgroup, folders[i]);
this->GroupNameMap[curr_folder] = group;
tgroup = group;
- }
- else
- {
+ } else {
tgroup = i_folder->second;
- }
- curr_folder = curr_folder + "\\";
}
- return tgroup;
+ curr_folder = curr_folder + "\\";
}
- cmXCodeObject *group = this->CreatePBXGroup(tgroup,sg->GetName());
+ return tgroup;
+ }
+ cmXCodeObject* group = this->CreatePBXGroup(tgroup, sg->GetName());
this->GroupNameMap[s] = group;
return group;
}
-//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator
-::CreateXCodeObjects(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>&
- generators)
+bool cmGlobalXCodeGenerator::CreateXCodeObjects(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
this->ClearXCodeObjects();
this->RootObject = 0;
- this->SourcesGroupChildren = 0;
- this->ResourcesGroupChildren = 0;
this->MainGroupChildren = 0;
cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
- cmXCodeObject* developBuildStyle =
- this->CreateObject(cmXCodeObject::PBXBuildStyle);
cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- if(this->XcodeVersion == 15)
- {
- developBuildStyle->AddAttribute("name",
- this->CreateString("Development"));
- developBuildStyle->AddAttribute("buildSettings", group);
- listObjs->AddObject(developBuildStyle);
- group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
- cmXCodeObject* deployBuildStyle =
- this->CreateObject(cmXCodeObject::PBXBuildStyle);
- deployBuildStyle->AddAttribute("name", this->CreateString("Deployment"));
- deployBuildStyle->AddAttribute("buildSettings", group);
- listObjs->AddObject(deployBuildStyle);
- }
- else
- {
- for(unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i)
- {
- cmXCodeObject* buildStyle =
- this->CreateObject(cmXCodeObject::PBXBuildStyle);
- const char* name = this->CurrentConfigurationTypes[i].c_str();
- buildStyle->AddAttribute("name", this->CreateString(name));
- buildStyle->SetComment(name);
- cmXCodeObject* sgroup =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
- buildStyle->AddAttribute("buildSettings", sgroup);
- listObjs->AddObject(buildStyle);
- }
- }
+ for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
+ cmXCodeObject* buildStyle =
+ this->CreateObject(cmXCodeObject::PBXBuildStyle);
+ const char* name = this->CurrentConfigurationTypes[i].c_str();
+ buildStyle->AddAttribute("name", this->CreateString(name));
+ buildStyle->SetComment(name);
+ cmXCodeObject* sgroup = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+ sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
+ buildStyle->AddAttribute("buildSettings", sgroup);
+ listObjs->AddObject(buildStyle);
+ }
cmXCodeObject* mainGroup = this->CreateObject(cmXCodeObject::PBXGroup);
- this->MainGroupChildren =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ this->MainGroupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST);
mainGroup->AddAttribute("children", this->MainGroupChildren);
- if(this->XcodeVersion == 15)
- {
- mainGroup->AddAttribute("refType", this->CreateString("4"));
- }
mainGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
- cmXCodeObject* sourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
- this->SourcesGroupChildren =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
- sourcesGroup->AddAttribute("name", this->CreateString("Sources"));
- sourcesGroup->AddAttribute("children", this->SourcesGroupChildren);
- if(this->XcodeVersion == 15)
- {
- sourcesGroup->AddAttribute("refType", this->CreateString("4"));
- }
- sourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
- this->MainGroupChildren->AddObject(sourcesGroup);
-
- cmXCodeObject* resourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
- this->ResourcesGroupChildren =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
- resourcesGroup->AddAttribute("name", this->CreateString("Resources"));
- resourcesGroup->AddAttribute("children", this->ResourcesGroupChildren);
- if(this->XcodeVersion == 15)
- {
- resourcesGroup->AddAttribute("refType", this->CreateString("4"));
- }
- resourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
- this->MainGroupChildren->AddObject(resourcesGroup);
-
// now create the cmake groups
- this->CreateGroups(root, generators);
+ if (!this->CreateGroups(generators)) {
+ return false;
+ }
cmXCodeObject* productGroup = this->CreateObject(cmXCodeObject::PBXGroup);
productGroup->AddAttribute("name", this->CreateString("Products"));
- if(this->XcodeVersion == 15)
- {
- productGroup->AddAttribute("refType", this->CreateString("4"));
- }
productGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
cmXCodeObject* productGroupChildren =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
productGroup->AddAttribute("children", productGroupChildren);
this->MainGroupChildren->AddObject(productGroup);
-
this->RootObject = this->CreateObject(cmXCodeObject::PBXProject);
this->RootObject->SetComment("Project object");
std::string project_id = "PROJECT_";
- project_id += root->GetMakefile()->GetProjectName();
- this->RootObject->SetId(this->GetOrCreateId(
- project_id.c_str(), this->RootObject->GetId()).c_str());
+ project_id += root->GetProjectName();
+ this->RootObject->SetId(
+ this->GetOrCreateId(project_id.c_str(), this->RootObject->GetId()));
group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
this->RootObject->AddAttribute("mainGroup",
- this->CreateObjectReference(mainGroup));
+ this->CreateObjectReference(mainGroup));
this->RootObject->AddAttribute("buildSettings", group);
this->RootObject->AddAttribute("buildStyles", listObjs);
this->RootObject->AddAttribute("hasScannedForEncodings",
- this->CreateString("0"));
- if (this->XcodeVersion >= 30)
- {
- group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- group->AddAttribute("BuildIndependentTargetsInParallel",
- this->CreateString("YES"));
- 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->CreateString("0"));
+ group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+ group->AddAttribute("BuildIndependentTargetsInParallel",
+ this->CreateString("YES"));
+ std::ostringstream v;
+ 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"));
// Point Xcode at the top of the source tree.
{
- std::string pdir =
- this->RelativeToBinary(root->GetMakefile()->GetCurrentDirectory());
- this->RootObject->AddAttribute("projectDirPath",
- this->CreateString(pdir.c_str()));
- this->RootObject->AddAttribute("projectRoot", this->CreateString(""));
+ std::string pdir =
+ this->RelativeToBinary(root->GetCurrentSourceDirectory());
+ this->RootObject->AddAttribute("projectDirPath", this->CreateString(pdir));
+ this->RootObject->AddAttribute("projectRoot", this->CreateString(""));
}
cmXCodeObject* configlist =
this->CreateObject(cmXCodeObject::XCConfigurationList);
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- std::vector<cmXCodeObject*> configs;
- const char *defaultConfigName = "Debug";
- if(this->XcodeVersion == 15)
- {
- cmXCodeObject* configDebug =
- this->CreateObject(cmXCodeObject::XCBuildConfiguration);
- configDebug->AddAttribute("name", this->CreateString("Debug"));
- configs.push_back(configDebug);
- cmXCodeObject* configRelease =
- this->CreateObject(cmXCodeObject::XCBuildConfiguration);
- configRelease->AddAttribute("name", this->CreateString("Release"));
- configs.push_back(configRelease);
- }
- else
- {
- for(unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i)
- {
- const char* name = this->CurrentConfigurationTypes[i].c_str();
- if (0 == i)
- {
- defaultConfigName = name;
- }
- cmXCodeObject* config =
- this->CreateObject(cmXCodeObject::XCBuildConfiguration);
- config->AddAttribute("name", this->CreateString(name));
- configs.push_back(config);
- }
- }
- for(std::vector<cmXCodeObject*>::iterator c = configs.begin();
- c != configs.end(); ++c)
- {
- buildConfigurations->AddObject(*c);
+ typedef std::vector<std::pair<std::string, cmXCodeObject*> > Configs;
+ Configs configs;
+ const char* defaultConfigName = "Debug";
+ for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
+ const char* name = this->CurrentConfigurationTypes[i].c_str();
+ if (0 == i) {
+ defaultConfigName = name;
}
+ cmXCodeObject* config =
+ this->CreateObject(cmXCodeObject::XCBuildConfiguration);
+ 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);
+ }
configlist->AddAttribute("buildConfigurations", buildConfigurations);
- std::string comment = "Build configuration list for PBXProject ";
+ std::string comment = "Build configuration list for PBXProject";
comment += " \"";
comment += this->CurrentProject;
comment += "\"";
- configlist->SetComment(comment.c_str());
+ configlist->SetComment(comment);
configlist->AddAttribute("defaultConfigurationIsVisible",
this->CreateString("0"));
configlist->AddAttribute("defaultConfigurationName",
this->CreateString(defaultConfigName));
cmXCodeObject* buildSettings =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- const char* osxArch =
- this->CurrentMakefile->GetDefinition("CMAKE_OSX_ARCHITECTURES");
- if(!osxArch || strlen(osxArch) == 0)
- {
- if(this->XcodeVersion >= 32)
- {
- osxArch = "$(ARCHS_STANDARD_32_64_BIT)";
- }
- else if(this->XcodeVersion == 31)
- {
- osxArch = "$(ARCHS_STANDARD_32_BIT)";
- }
- else if(this->XcodeVersion <= 30)
- {
-#ifdef __ppc__
- osxArch = "ppc";
-#endif
-#ifdef __i386
- osxArch = "i386";
-#endif
- }
- buildSettings->AddAttribute("ONLY_ACTIVE_ARCH",
- this->CreateString("YES"));
- }
-
+ this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
const char* sysroot =
- this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT");
+ this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT");
const char* deploymentTarget =
this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
- if(osxArch && sysroot)
- {
- // recompute this as it may have been changed since enable language
- this->Architectures.clear();
- cmSystemTools::ExpandListArgument(std::string(osxArch),
- this->Architectures);
- buildSettings->AddAttribute("SDKROOT",
- this->CreateString(sysroot));
- std::string archString;
- const char* sep = "";
- for( std::vector<std::string>::iterator i =
- this->Architectures.begin();
- i != this->Architectures.end(); ++i)
- {
- archString += sep;
- archString += *i;
- sep = " ";
- }
- buildSettings->AddAttribute("ARCHS",
- this->CreateString(archString.c_str()));
- }
- if(deploymentTarget && *deploymentTarget)
- {
+ if (sysroot) {
+ buildSettings->AddAttribute("SDKROOT", this->CreateString(sysroot));
+ }
+ // recompute this as it may have been changed since enable language
+ this->ComputeArchitectures(this->CurrentMakefile);
+ std::string const archs = cmJoin(this->Architectures, " ");
+ if (archs.empty()) {
+ // Tell Xcode to use NATIVE_ARCH instead of ARCHS.
+ buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("YES"));
+ } else {
+ // Tell Xcode to use ARCHS (ONLY_ACTIVE_ARCH defaults to NO).
+ buildSettings->AddAttribute("ARCHS", this->CreateString(archs));
+ }
+ if (deploymentTarget && *deploymentTarget) {
buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
this->CreateString(deploymentTarget));
- }
- if(!this->PlatformToolset.empty())
- {
+ }
+ if (!this->GeneratorToolset.empty()) {
buildSettings->AddAttribute("GCC_VERSION",
- this->CreateString(this->PlatformToolset.c_str()));
- }
-
- // 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 i = vars.begin();
- i != vars.end(); ++i)
- {
- if(i->find("CMAKE_XCODE_ATTRIBUTE_") == 0)
- {
- buildSettings->AddAttribute(i->substr(22).c_str(),
- this->CreateString(
- this->CurrentMakefile->GetDefinition(i->c_str())));
- }
- }
+ this->CreateString(this->GeneratorToolset));
+ }
+ if (this->GetLanguageEnabled("Swift")) {
+ std::string swiftVersion;
+ if (const char* vers = this->CurrentMakefile->GetDefinition(
+ "CMAKE_Swift_LANGUAGE_VERSION")) {
+ swiftVersion = vers;
+ } else if (this->XcodeVersion >= 83) {
+ swiftVersion = "3.0";
+ } else {
+ swiftVersion = "2.3";
+ }
+ buildSettings->AddAttribute("SWIFT_VERSION",
+ this->CreateString(swiftVersion));
}
- std::string symroot = root->GetMakefile()->GetCurrentOutputDirectory();
+ std::string symroot = root->GetCurrentBinaryDirectory();
symroot += "/build";
- buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot.c_str()));
+ buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot));
- for( std::vector<cmXCodeObject*>::iterator i = configs.begin();
- i != configs.end(); ++i)
- {
- (*i)->AddAttribute("buildSettings", buildSettings);
+ for (Configs::iterator i = configs.begin(); i != configs.end(); ++i) {
+ 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);
+ if (!attribute.empty()) {
+ cmGeneratorExpression ge;
+ std::string processed =
+ ge.Parse(this->CurrentMakefile->GetDefinition(*d))
+ ->Evaluate(this->CurrentLocalGenerator, i->first);
+ buildSettingsForCfg->AddAttribute(attribute,
+ this->CreateString(processed));
+ }
+ }
}
+ // store per-config buildSettings into configuration object
+ i->second->AddAttribute("buildSettings", buildSettingsForCfg);
+ }
this->RootObject->AddAttribute("buildConfigurationList",
- this->CreateObjectReference(configlist));
+ this->CreateObjectReference(configlist));
std::vector<cmXCodeObject*> targets;
- for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
- i != generators.end(); ++i)
- {
- if(!this->IsExcluded(root, *i))
- {
- this->CreateXCodeTargets(*i, targets);
- }
+ for (std::vector<cmLocalGenerator*>::iterator i = generators.begin();
+ i != generators.end(); ++i) {
+ if (!this->CreateXCodeTargets(*i, 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)
- {
+ for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
+ i != targets.end(); ++i) {
cmXCodeObject* t = *i;
this->AddDependAndLinkInformation(t);
- }
- if(this->XcodeVersion < 50)
- {
- // now create xcode depend hack makefile
- this->CreateXCodeDependHackTarget(targets);
- }
+ }
+ 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)
- {
+ for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
+ i != targets.end(); ++i) {
cmXCodeObject* t = *i;
allTargets->AddObject(t);
cmXCodeObject* productRef = t->GetObject("productReference");
- if(productRef)
- {
+ if (productRef) {
productGroupChildren->AddObject(productRef->GetObject());
- }
}
+ }
this->RootObject->AddAttribute("targets", allTargets);
+ return true;
}
-//----------------------------------------------------------------------------
-std::string
-cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
- const std::string &projName,
- const std::string &configName,
- const cmTarget *t) const
+std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
+ const std::string& projName, const std::string& configName,
+ const cmGeneratorTarget* t) const
{
- std::string dir =
- t->GetMakefile()->GetCurrentOutputDirectory();
+ std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory();
dir += "/";
dir += projName;
dir += ".build/";
@@ -3406,123 +3069,147 @@ cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
return dir;
}
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
+void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
+{
+ this->Architectures.clear();
+ 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);
+ }
+
+ 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")) {
+ this->ObjectDirArchDefault = arch;
+ }
+ }
+
+ this->ComputeObjectDirArch(mf);
+}
+
+void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf)
+{
+ if (this->Architectures.size() > 1 || this->UseEffectivePlatformName(mf)) {
+ this->ObjectDirArch = "$(CURRENT_ARCH)";
+ } else if (!this->Architectures.empty()) {
+ this->ObjectDirArch = this->Architectures[0];
+ } else {
+ this->ObjectDirArch = this->ObjectDirArchDefault;
+ }
+}
+
+void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
std::vector<cmXCodeObject*>& targets)
{
- cmGeneratedFileStream
- makefileStream(this->CurrentXCodeHackMakefile.c_str());
- if(!makefileStream)
- {
+ cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile.c_str());
+ if (!makefileStream) {
cmSystemTools::Error("Could not create",
this->CurrentXCodeHackMakefile.c_str());
return;
- }
+ }
makefileStream.SetCopyIfDifferent(true);
// one more pass for external depend information not handled
// correctly by xcode
+ /* clang-format off */
makefileStream << "# DO NOT EDIT\n";
makefileStream << "# This makefile makes sure all linkable targets are\n";
makefileStream << "# up-to-date with anything they link to\n"
"default:\n"
"\techo \"Do not invoke directly\"\n"
"\n";
- makefileStream
- << "# For each target create a dummy rule "
- "so the target does not have to exist\n";
- std::set<cmStdString> emitted;
- for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i)
- {
- cmXCodeObject* target = *i;
- std::map<cmStdString, cmXCodeObject::StringVec> const& deplibs =
- target->GetDependLibraries();
- for(std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator ci
- = deplibs.begin(); ci != deplibs.end(); ++ci)
- {
- for(cmXCodeObject::StringVec::const_iterator d = ci->second.begin();
- d != ci->second.end(); ++d)
- {
- if(emitted.insert(*d).second)
- {
- makefileStream <<
- this->ConvertToRelativeForMake(d->c_str()) << ":\n";
- }
- }
- }
- }
- makefileStream << "\n\n";
+ /* clang-format on */
+
+ std::set<std::string> dummyRules;
// Write rules to help Xcode relink things at the right time.
+ /* clang-format off */
makefileStream <<
"# Rules to remove targets that are older than anything to which they\n"
"# link. This forces Xcode to relink the targets from scratch. It\n"
"# does not seem to check these dependencies itself.\n";
- for(std::vector<std::string>::const_iterator
- ct = this->CurrentConfigurationTypes.begin();
- ct != this->CurrentConfigurationTypes.end(); ++ct)
- {
- const char* configName = 0;
- if(!ct->empty())
- {
- configName = ct->c_str();
- }
- for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i)
- {
+ /* 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;
- cmTarget* t =target->GetTarget();
-
- if(t->GetType() == cmTarget::EXECUTABLE ||
-// Nope - no post-build for OBJECT_LIRBRARY
-// t->GetType() == cmTarget::OBJECT_LIBRARY ||
- t->GetType() == cmTarget::STATIC_LIBRARY ||
- t->GetType() == cmTarget::SHARED_LIBRARY ||
- t->GetType() == cmTarget::MODULE_LIBRARY)
- {
+ cmGeneratorTarget* gt = target->GetTarget();
+
+ if (gt->GetType() == cmStateEnums::EXECUTABLE ||
+ gt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+ gt->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
// Declare an entry point for the target post-build phase.
- makefileStream << this->PostBuildMakeTarget(t->GetName(), *ct)
+ makefileStream << this->PostBuildMakeTarget(gt->GetName(), *ct)
<< ":\n";
- }
+ }
- if(t->GetType() == cmTarget::EXECUTABLE ||
- t->GetType() == cmTarget::SHARED_LIBRARY ||
- t->GetType() == cmTarget::MODULE_LIBRARY)
- {
- std::string tfull = t->GetFullPath(configName);
+ if (gt->GetType() == cmStateEnums::EXECUTABLE ||
+ gt->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ std::string tfull = gt->GetFullPath(configName);
std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
// Add this target to the post-build phases of its dependencies.
- std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator
- y = target->GetDependTargets().find(*ct);
- if(y != target->GetDependTargets().end())
- {
- std::vector<cmStdString> const& deptgts = y->second;
- for(std::vector<cmStdString>::const_iterator d = deptgts.begin();
- d != deptgts.end(); ++d)
- {
+ std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
+ target->GetDependTargets().find(*ct);
+ 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";
- }
}
+ }
+
+ 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)
+ << ": " << trel << "\n";
+ }
// Create a rule for this target.
makefileStream << trel << ":";
// List dependencies if any exist.
- std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator
- x = target->GetDependLibraries().find(*ct);
- if(x != target->GetDependLibraries().end())
- {
- std::vector<cmStdString> const& deplibs = x->second;
- for(std::vector<cmStdString>::const_iterator d = deplibs.begin();
- d != deplibs.end(); ++d)
- {
- makefileStream << "\\\n\t" <<
- this->ConvertToRelativeForMake(d->c_str());
- }
+ std::map<std::string, cmXCodeObject::StringVec>::const_iterator x =
+ target->GetDependLibraries().find(*ct);
+ 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());
+ makefileStream << "\\\n\t" << file;
+ dummyRules.insert(file);
}
+ }
+
+ for (std::vector<cmGeneratorTarget*>::const_iterator it =
+ objlibs.begin();
+ it != objlibs.end(); ++it) {
+
+ const std::string objLibName = (*it)->GetName();
+ std::string d = this->GetObjectsNormalDirectory(this->CurrentProject,
+ configName, *it);
+ d += "lib";
+ d += objLibName;
+ d += ".a";
+
+ std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+ makefileStream << "\\\n\t" << dependency;
+ dummyRules.insert(dependency);
+ }
+
// Write the action to remove the target if it is out of date.
makefileStream << "\n";
makefileStream << "\t/bin/rm -f "
@@ -3530,83 +3217,138 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
<< "\n";
// if building for more than one architecture
// then remove those exectuables as well
- if(this->Architectures.size() > 1)
- {
+ if (this->Architectures.size() > 1) {
std::string universal = this->GetObjectsNormalDirectory(
- this->CurrentProject, configName, t);
- for( std::vector<std::string>::iterator arch =
+ this->CurrentProject, configName, gt);
+ for (std::vector<std::string>::iterator arch =
this->Architectures.begin();
- arch != this->Architectures.end(); ++arch)
- {
+ arch != this->Architectures.end(); ++arch) {
std::string universalFile = universal;
universalFile += *arch;
universalFile += "/";
- universalFile += t->GetFullName(configName);
+ universalFile += gt->GetFullName(configName);
makefileStream << "\t/bin/rm -f "
- <<
- this->ConvertToRelativeForMake(universalFile.c_str())
+ << this->ConvertToRelativeForMake(
+ universalFile.c_str())
<< "\n";
- }
}
- makefileStream << "\n\n";
}
+ makefileStream << "\n\n";
}
}
+ }
+
+ 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";
+ }
}
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>&
- generators)
+void cmGlobalXCodeGenerator::OutputXCodeProject(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
- if(generators.size() == 0)
- {
+ if (generators.size() == 0) {
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))
- {
+ for (std::vector<cmLocalGenerator*>::iterator g = generators.begin();
+ g != generators.end(); ++g) {
+ if (this->IsExcluded(root, *g)) {
continue;
- }
}
+ }
- this->CreateXCodeObjects(root,
- generators);
- std::string xcodeDir = root->GetMakefile()->GetStartOutputDirectory();
+ if (!this->CreateXCodeObjects(root, generators)) {
+ return;
+ }
+ std::string xcodeDir = root->GetCurrentBinaryDirectory();
xcodeDir += "/";
- xcodeDir += root->GetMakefile()->GetProjectName();
- xcodeDir += ".xcode";
- if(this->XcodeVersion > 20)
- {
- xcodeDir += "proj";
- }
+ xcodeDir += root->GetProjectName();
+ xcodeDir += ".xcodeproj";
cmSystemTools::MakeDirectory(xcodeDir.c_str());
std::string xcodeProjFile = xcodeDir + "/project.pbxproj";
cmGeneratedFileStream fout(xcodeProjFile.c_str());
fout.SetCopyIfDifferent(true);
- if(!fout)
- {
+ 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);
+ }
+ }
+
this->ClearXCodeObjects();
// Since this call may have created new cache entries, save the cache:
//
- root->GetMakefile()->GetCacheManager()->SaveCache(
- root->GetMakefile()->GetHomeOutputDirectory());
+ root->GetMakefile()->GetCMakeInstance()->SaveCache(
+ root->GetBinaryDirectory());
}
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
- cmLocalGenerator* ,
- std::vector<cmLocalGenerator*>& )
+void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
+ const std::string& xcProjDir)
+{
+ 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()));
+ }
+ }
+}
+
+void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
+ const std::string& xcProjDir)
+{
+ std::string xcodeSharedDataDir = xcProjDir;
+ xcodeSharedDataDir += "/project.xcworkspace/xcshareddata";
+ cmSystemTools::MakeDirectory(xcodeSharedDataDir);
+
+ std::string workspaceSettingsFile = xcodeSharedDataDir;
+ workspaceSettingsFile += "/WorkspaceSettings.xcsettings";
+
+ cmGeneratedFileStream fout(workspaceSettingsFile.c_str());
+ fout.SetCopyIfDifferent(true);
+ if (!fout) {
+ return;
+ }
+
+ cmXMLWriter xout(fout);
+ xout.StartDocument();
+ xout.Doctype("plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\""
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"");
+ xout.StartElement("plist");
+ xout.Attribute("version", "1.0");
+ xout.StartElement("dict");
+ xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
+ xout.Element("false");
+ xout.EndElement(); // dict
+ xout.EndElement(); // plist
+ xout.EndDocument();
+}
+
+void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
+ cmLocalGenerator*,
+ std::vector<cmLocalGenerator*>&)
{
+ SortXCodeObjects();
+
fout << "// !$*UTF8*$!\n";
fout << "{\n";
cmXCodeObject::Indent(1, fout);
@@ -3616,157 +3358,116 @@ cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
cmXCodeObject::Indent(1, fout);
fout << "};\n";
cmXCodeObject::Indent(1, fout);
- if(this->XcodeVersion >= 21)
- {
- if (this->XcodeVersion >= 32)
- fout << "objectVersion = 46;\n";
- else if (this->XcodeVersion >= 31)
- fout << "objectVersion = 45;\n";
- else if (this->XcodeVersion >= 30)
- fout << "objectVersion = 44;\n";
- else
- fout << "objectVersion = 42;\n";
- cmXCode21Object::PrintList(this->XCodeObjects, fout);
- }
+ if (this->XcodeVersion >= 32)
+ fout << "objectVersion = 46;\n";
+ else if (this->XcodeVersion >= 31)
+ fout << "objectVersion = 45;\n";
else
- {
- fout << "objectVersion = 39;\n";
- cmXCodeObject::PrintList(this->XCodeObjects, fout);
- }
+ fout << "objectVersion = 44;\n";
+ cmXCode21Object::PrintList(this->XCodeObjects, fout);
cmXCodeObject::Indent(1, fout);
- fout << "rootObject = " << this->RootObject->GetId() << ";\n";
+ fout << "rootObject = " << this->RootObject->GetId()
+ << " /* Project object */;\n";
fout << "}\n";
}
-//----------------------------------------------------------------------------
const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
{
- return this->XcodeVersion >= 21 ?
- "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : ".";
+ return "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+}
+
+std::string cmGlobalXCodeGenerator::ExpandCFGIntDir(
+ const std::string& str, const std::string& config) const
+{
+ std::string replace1 = "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+ std::string replace2 = "$(CONFIGURATION)";
+
+ std::string tmp = str;
+ for (std::string::size_type i = tmp.find(replace1); i != std::string::npos;
+ i = tmp.find(replace1, i)) {
+ tmp.replace(i, replace1.size(), config);
+ i += config.size();
+ }
+ for (std::string::size_type i = tmp.find(replace2); i != std::string::npos;
+ i = tmp.find(replace2, i)) {
+ tmp.replace(i, replace2.size(), config);
+ i += config.size();
+ }
+ return tmp;
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
{
entry.Name = cmGlobalXCodeGenerator::GetActualName();
entry.Brief = "Generate Xcode project files.";
- entry.Full = "";
}
-//----------------------------------------------------------------------------
std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p)
{
- if ( !this->CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
- {
- return cmSystemTools::ConvertToOutputPath(p);
- }
- else
- {
- std::string ret =
- this->CurrentLocalGenerator->
- ConvertToRelativePath(this->CurrentOutputDirectoryComponents, p);
- return cmSystemTools::ConvertToOutputPath(ret.c_str());
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p)
-{
- if ( !this->CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
- {
- return cmSystemTools::ConvertToOutputPath(p);
- }
- else
- {
- std::string ret =
- this->CurrentLocalGenerator->
- ConvertToRelativePath(this->ProjectOutputDirectoryComponents, p);
- return cmSystemTools::ConvertToOutputPath(ret.c_str());
- }
+ return cmSystemTools::ConvertToOutputPath(p);
}
-//----------------------------------------------------------------------------
std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
{
// We force conversion because Xcode breakpoints do not work unless
// they are in a file named relative to the source tree.
- return this->CurrentLocalGenerator->
- ConvertToRelativePath(this->ProjectSourceDirectoryComponents, p, true);
+ return cmOutputConverter::ForceToRelativePath(
+ cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p);
}
-//----------------------------------------------------------------------------
std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
{
- return this->CurrentLocalGenerator->
- ConvertToRelativePath(this->ProjectOutputDirectoryComponents, p);
+ return this->CurrentLocalGenerator->ConvertToRelativePath(
+ cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
}
-//----------------------------------------------------------------------------
-std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p)
+std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
{
- std::string ret = p;
- if(ret.find(' ') != ret.npos)
- {
- std::string t = ret;
- ret = "\"";
- ret += t;
- ret += "\"";
- }
- return ret;
+ if (p.find(' ') != std::string::npos) {
+ std::string t = "\"";
+ t += p;
+ t += "\"";
+ return t;
+ }
+ return p;
}
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator
-::AppendDirectoryForConfig(const char* prefix,
- const char* config,
- const char* suffix,
- std::string& dir)
-{
- if(this->XcodeVersion > 20)
- {
- if(config)
- {
- dir += prefix;
- dir += config;
- dir += suffix;
- }
- }
+void cmGlobalXCodeGenerator::AppendDirectoryForConfig(
+ const std::string& prefix, const std::string& config,
+ const std::string& suffix, std::string& dir)
+{
+ if (!config.empty()) {
+ dir += prefix;
+ dir += config;
+ dir += suffix;
+ }
}
-//----------------------------------------------------------------------------
-std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix,
- const char* varNameLang,
- const char* varNameSuffix,
- const char* default_flags)
+std::string cmGlobalXCodeGenerator::LookupFlags(
+ const std::string& varNamePrefix, const std::string& varNameLang,
+ const std::string& varNameSuffix, const std::string& default_flags)
{
- if(varNameLang)
- {
+ if (!varNameLang.empty()) {
std::string varName = varNamePrefix;
varName += varNameLang;
varName += varNameSuffix;
- if(const char* varValue =
- this->CurrentMakefile->GetDefinition(varName.c_str()))
- {
- if(*varValue)
- {
+ if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) {
+ if (*varValue) {
return varValue;
- }
}
}
+ }
return default_flags;
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
const char* defines_list,
bool dflag)
{
// Skip this if there are no definitions.
- if(!defines_list)
- {
+ if (!defines_list) {
return;
- }
+ }
// Expand the list of definitions.
std::vector<std::string> defines;
@@ -3776,166 +3477,135 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
this->AppendDefines(defs, defines, dflag);
}
-//----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
- std::vector<std::string> const& defines,
- bool dflag)
+void cmGlobalXCodeGenerator::AppendDefines(
+ BuildObjectListOrString& defs, std::vector<std::string> const& defines,
+ bool dflag)
{
// 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 (std::vector<std::string>::const_iterator di = defines.begin();
+ di != defines.end(); ++di) {
// Start with -D if requested.
- def = dflag? "-D": "";
+ def = dflag ? "-D" : "";
def += *di;
// Append the flag with needed escapes.
std::string tmp;
this->AppendFlag(tmp, def);
- defs.Add(tmp.c_str());
- }
+ defs.Add(tmp);
+ }
}
-//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
std::string const& flag)
{
// Short-circuit for an empty flag.
- if(flag.empty())
- {
+ if (flag.empty()) {
return;
- }
+ }
// Separate from previous flags.
- if(!flags.empty())
- {
+ if (!flags.empty()) {
flags += " ";
- }
+ }
// Check if the flag needs quoting.
bool quoteFlag =
- flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag.npos;
+ flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != std::string::npos;
// We escape a flag as follows:
// - Place each flag in single quotes ''
- // - Escape a single quote as \\'
- // - Escape a backslash as \\\\ since it itself is an escape
+ // - Escape a single quote as \'
+ // - Escape a backslash as \\ since it itself is an escape
// Note that in the code below we need one more level of escapes for
// C string syntax in this source file.
//
// The final level of escaping is done when the string is stored
// into the project file by cmXCodeObject::PrintString.
- if(quoteFlag)
- {
+ if (quoteFlag) {
// Open single quote.
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 == '\\')
- {
- flags += "\\\\\\\\";
- }
- else
- {
+ for (const char* c = flag.c_str(); *c; ++c) {
+ if (*c == '\'') {
+ if (this->XcodeVersion >= 40) {
+ flags += "'\\''";
+ } else {
+ flags += "\\'";
+ }
+ } else if (*c == '\\') {
+ flags += "\\\\";
+ } else {
flags += *c;
- }
}
+ }
- if(quoteFlag)
- {
+ if (quoteFlag) {
// Close single quote.
flags += "'";
- }
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget& target)
+std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation(
+ cmGeneratorTarget* target)
{
- std::string plist = target.GetMakefile()->GetCurrentOutputDirectory();
+ std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
plist += cmake::GetCMakeFilesDirectory();
plist += "/";
- plist += target.GetName();
+ plist += target->GetName();
plist += ".dir/Info.plist";
return plist;
}
-//----------------------------------------------------------------------------
// Return true if the generated build tree may contain multiple builds.
// i.e. "Can I build Debug and Release in the same tree?"
-bool cmGlobalXCodeGenerator::IsMultiConfig()
+bool cmGlobalXCodeGenerator::IsMultiConfig() const
{
- // Old Xcode 1.5 is single config:
- if(this->XcodeVersion == 15)
- {
- return false;
- }
-
// Newer Xcode versions are multi config:
return true;
}
- //----------------------------------------------------------------------------
-void
-cmGlobalXCodeGenerator
-::ComputeTargetObjects(cmGeneratorTarget* gt) const
+bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation(
+ std::string* reason) const
{
- // Count the number of object files with each name. Warn about duplicate
- // names since Xcode names them uniquely automatically with a numeric suffix
- // to avoid exact duplicate file names. Note that Mac file names are not
- // typically case sensitive, hence the LowerCase.
- std::map<cmStdString, int> counts;
- for(std::vector<cmSourceFile*>::const_iterator
- si = gt->ObjectSources.begin();
- si != gt->ObjectSources.end(); ++si)
- {
- cmSourceFile* sf = *si;
- std::string objectName =
- cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
- objectName += ".o";
-
- std::string objectNameLower = cmSystemTools::LowerCase(objectName);
- counts[objectNameLower] += 1;
- if (2 == counts[objectNameLower])
- {
- // TODO: emit warning about duplicate name?
- }
-
- gt->Objects[sf] = objectName;
+ if (this->ObjectDirArch.find('$') != std::string::npos) {
+ if (reason != CM_NULLPTR) {
+ *reason = " under Xcode with multiple architectures";
}
+ return false;
+ }
+ return true;
+}
- const char* configName = this->GetCMakeCFGIntDir();
- std::string dir = this->GetObjectsNormalDirectory(
- "$(PROJECT_NAME)", configName, gt->Target);
- if(this->XcodeVersion >= 21)
- {
- dir += "$(CURRENT_ARCH)/";
- }
- else
- {
-#ifdef __ppc__
- dir += "ppc/";
-#endif
-#ifdef __i386
- dir += "i386/";
-#endif
- }
+bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
+{
+ const char* epnValue =
+ this->GetCMakeInstance()->GetState()->GetGlobalProperty(
+ "XCODE_EMIT_EFFECTIVE_PLATFORM_NAME");
+
+ if (!epnValue) {
+ return mf->PlatformIsAppleIos();
+ }
+
+ return cmSystemTools::IsOn(epnValue);
+}
+
+bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const
+{
+ // Xcode determines Resource location itself
+ return true;
+}
+
+void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
+ cmGeneratorTarget* gt) const
+{
+ std::string configName = this->GetCMakeCFGIntDir();
+ std::string dir =
+ this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt);
+ dir += this->ObjectDirArch;
+ dir += "/";
gt->ObjectDirectory = dir;
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index c05394346..e69793bcc 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -1,25 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGlobalXCodeGenerator_h
#define cmGlobalXCodeGenerator_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmGlobalGenerator.h"
#include "cmXCodeObject.h"
-#include "cmCustomCommand.h"
+
+class cmCustomCommand;
+class cmGeneratorTarget;
class cmGlobalGeneratorFactory;
-class cmTarget;
+class cmLocalGenerator;
+class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
-
+class cmake;
+struct cmDocumentationEntry;
/** \class cmGlobalXCodeGenerator
* \brief Write a Unix makefiles.
@@ -29,75 +32,85 @@ class cmSourceGroup;
class cmGlobalXCodeGenerator : public cmGlobalGenerator
{
public:
- cmGlobalXCodeGenerator(std::string const& version);
+ cmGlobalXCodeGenerator(cmake* cm, std::string const& version_string,
+ unsigned int version_number);
static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalXCodeGenerator::GetActualName();}
- static const char* GetActualName() {return "Xcode";}
+ std::string GetName() const CM_OVERRIDE
+ {
+ return cmGlobalXCodeGenerator::GetActualName();
+ }
+ static std::string GetActualName() { return "Xcode"; }
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator *CreateLocalGenerator();
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE;
/**
- * Try to determine system infomation such as shared library
+ * 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) CM_OVERRIDE;
/**
* Try running cmake and building a file. This is used for dynalically
* loaded commands, not as part of the usual build process.
*/
- virtual std::string GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
- const char *projectDir,
- const char* additionalOptions,
- const char *targetName,
- const char* config,
- bool ignoreErrors,
- bool fast);
-
- /**
- * 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.
- */
- virtual void Generate();
+ 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;
/** Append the subdirectory for the given configuration. */
- virtual void AppendDirectoryForConfig(const char* prefix,
- const char* config,
- const char* suffix,
- std::string& dir);
+ void AppendDirectoryForConfig(const std::string& prefix,
+ const std::string& config,
+ const std::string& suffix,
+ std::string& dir) CM_OVERRIDE;
+
+ bool FindMakeProgram(cmMakefile*) CM_OVERRIDE;
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGIntDir() const;
+ const char* GetCMakeCFGIntDir() const CM_OVERRIDE;
+ ///! expand CFGIntDir
+ std::string ExpandCFGIntDir(const std::string& str,
+ const std::string& config) const CM_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?" */
- virtual bool IsMultiConfig();
+ bool IsMultiConfig() const CM_OVERRIDE;
+
+ bool HasKnownObjectFileLocation(std::string* reason) const CM_OVERRIDE;
- virtual bool SetGeneratorToolset(std::string const& ts);
+ bool IsIPOSupported() const CM_OVERRIDE { return true; }
+
+ bool UseEffectivePlatformName(cmMakefile* mf) const CM_OVERRIDE;
+
+ bool ShouldStripResourcePath(cmMakefile*) const CM_OVERRIDE;
+
+ bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) CM_OVERRIDE;
void AppendFlag(std::string& flags, std::string const& flag);
+
+protected:
+ void AddExtraIDETargets() CM_OVERRIDE;
+ void Generate() CM_OVERRIDE;
+
private:
- cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget,
+ cmXCodeObject* CreateOrGetPBXGroup(cmGeneratorTarget* gtgt,
cmSourceGroup* sg);
- cmXCodeObject* CreatePBXGroup(cmXCodeObject *parent,
- cmStdString name);
- void CreateGroups(cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>&
- generators);
- std::string XCodeEscapePath(const char* p);
+ cmXCodeObject* CreatePBXGroup(cmXCodeObject* parent, 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 ConvertToRelativeForXCode(const char* p);
std::string ConvertToRelativeForMake(const char* p);
void CreateCustomCommands(cmXCodeObject* buildPhases,
cmXCodeObject* sourceBuildPhase,
@@ -105,90 +118,96 @@ private:
cmXCodeObject* resourceBuildPhase,
std::vector<cmXCodeObject*> contentBuildPhases,
cmXCodeObject* frameworkBuildPhase,
- cmTarget& cmtarget);
+ cmGeneratorTarget* gtgt);
- std::string ComputeInfoPListLocation(cmTarget& target);
+ std::string ComputeInfoPListLocation(cmGeneratorTarget* target);
void AddCommandsToBuildPhase(cmXCodeObject* buildphase,
- cmTarget& target,
- std::vector<cmCustomCommand>
- const & commands,
+ cmGeneratorTarget* target,
+ std::vector<cmCustomCommand> const& commands,
const char* commandFileName);
void CreateCustomRulesMakefile(const char* makefileBasename,
- cmTarget& target,
- std::vector<cmCustomCommand> const & commands,
- const char* configName,
- const std::map<cmStdString, cmStdString>&
- multipleOutputPairs
- );
+ cmGeneratorTarget* target,
+ std::vector<cmCustomCommand> const& commands,
+ const std::string& configName);
- cmXCodeObject* FindXCodeTarget(cmTarget*);
- std::string GetOrCreateId(const char* name, const char* id);
+ cmXCodeObject* FindXCodeTarget(const cmGeneratorTarget*);
+ std::string GetOrCreateId(const std::string& name, const std::string& id);
// create cmXCodeObject from these functions so that memory can be managed
// correctly. All objects created are stored in this->XCodeObjects.
cmXCodeObject* CreateObject(cmXCodeObject::PBXType ptype);
cmXCodeObject* CreateObject(cmXCodeObject::Type type);
- cmXCodeObject* CreateString(const char* s);
+ cmXCodeObject* CreateString(const std::string& s);
cmXCodeObject* CreateObjectReference(cmXCodeObject*);
- cmXCodeObject* CreateXCodeTarget(cmTarget& target,
+ cmXCodeObject* CreateFlatClone(cmXCodeObject*);
+ cmXCodeObject* CreateXCodeTarget(cmGeneratorTarget* gtgt,
cmXCodeObject* buildPhases);
- void ForceLinkerLanguages();
- void ForceLinkerLanguage(cmTarget& cmtarget);
- const char* GetTargetFileType(cmTarget& cmtarget);
- const char* GetTargetProductType(cmTarget& cmtarget);
- std::string AddConfigurations(cmXCodeObject* target, cmTarget& cmtarget);
+ void ForceLinkerLanguages() CM_OVERRIDE;
+ void ForceLinkerLanguage(cmGeneratorTarget* gtgt);
+ const char* GetTargetLinkFlagsVar(const cmGeneratorTarget* target) const;
+ const char* GetTargetFileType(cmGeneratorTarget* target);
+ const char* GetTargetProductType(cmGeneratorTarget* target);
+ std::string AddConfigurations(cmXCodeObject* target,
+ cmGeneratorTarget* gtgt);
void AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attr,
const char* value);
void AppendBuildSettingAttribute(cmXCodeObject* target, const char* attr,
- const char* value, const char* configName);
- cmXCodeObject* CreateUtilityTarget(cmTarget& target);
+ const char* value,
+ const std::string& configName);
+ cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
void AddDependAndLinkInformation(cmXCodeObject* target);
- void CreateBuildSettings(cmTarget& target,
+ void CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
- const char* buildType);
+ const std::string& buildType);
std::string ExtractFlag(const char* flag, std::string& flags);
+ std::string ExtractFlagRegex(const char* exp, int matchIndex,
+ std::string& flags);
+ void FilterConfigurationAttribute(std::string const& configName,
+ std::string& attribute);
+ void SortXCodeObjects();
// delete all objects in the this->XCodeObjects vector.
void ClearXCodeObjects();
- void CreateXCodeObjects(cmLocalGenerator* root,
+ bool CreateXCodeObjects(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
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);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
- cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string &fullpath,
- cmTarget& cmtarget,
- const std::string &lang);
- cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string &fullpath,
- cmTarget& cmtarget,
- const std::string &lang);
+ cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,
+ cmGeneratorTarget* target,
+ const std::string& lang,
+ cmSourceFile* sf);
+ cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string& fullpath,
+ cmGeneratorTarget* target,
+ const std::string& lang,
+ cmSourceFile* sf);
cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf,
- cmTarget& cmtarget);
- cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen,
- cmSourceFile* sf,
- cmTarget& cmtarget);
- void CreateXCodeTargets(cmLocalGenerator* gen,
- std::vector<cmXCodeObject*>&);
+ cmGeneratorTarget* target);
+ cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
+ cmGeneratorTarget* gtgt);
+ bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
bool IsHeaderFile(cmSourceFile*);
- void AddDependTarget(cmXCodeObject* target,
- cmXCodeObject* dependTarget);
+ void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
bool SpecialTargetEmitted(std::string const& tname);
void SetGenerationRoot(cmLocalGenerator* root);
void AddExtraTargets(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& gens);
- cmXCodeObject* CreateBuildPhase(const char* name,
- const char* name2,
- cmTarget& cmtarget,
+ cmXCodeObject* CreateBuildPhase(const char* name, const char* name2,
+ cmGeneratorTarget* target,
const std::vector<cmCustomCommand>&);
void CreateReRunCMakeFile(cmLocalGenerator* root,
std::vector<cmLocalGenerator*> const& gens);
- std::string LookupFlags(const char* varNamePrefix,
- const char* varNameLang,
- const char* varNameSuffix,
- const char* default_flags);
+ std::string LookupFlags(const std::string& varNamePrefix,
+ const std::string& varNameLang,
+ const std::string& varNameSuffix,
+ const std::string& default_flags);
class Factory;
class BuildObjectListOrString;
@@ -200,45 +219,58 @@ private:
std::vector<std::string> const& defines,
bool dflag = false);
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
+
protected:
- virtual const char* GetInstallTargetName() const { return "install"; }
- virtual const char* GetPackageTargetName() const { return "package"; }
+ const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; }
+ const char* GetPackageTargetName() const CM_OVERRIDE { return "package"; }
unsigned int XcodeVersion;
std::string VersionString;
- std::set<cmStdString> XCodeObjectIDs;
+ std::set<std::string> XCodeObjectIDs;
std::vector<cmXCodeObject*> XCodeObjects;
cmXCodeObject* RootObject;
+
private:
- void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+ std::string const& GetXcodeBuildCommand();
+ std::string FindXcodeBuildCommand();
+ std::string XcodeBuildCommand;
+ bool XcodeBuildCommandInitialized;
+
+ void PrintCompilerAdvice(std::ostream&, std::string const&,
+ const char*) const CM_OVERRIDE
+ {
+ }
+
+ std::string GetObjectsNormalDirectory(const std::string& projName,
+ const std::string& configName,
+ const cmGeneratorTarget* t) const;
- std::string GetObjectsNormalDirectory(
- const std::string &projName,
- const std::string &configName,
- const cmTarget *t) const;
+ void ComputeArchitectures(cmMakefile* mf);
+ void ComputeObjectDirArch(cmMakefile* mf);
- void addObject(cmXCodeObject *obj);
+ void addObject(cmXCodeObject* obj);
std::string PostBuildMakeTarget(std::string const& tName,
std::string const& configName);
cmXCodeObject* MainGroupChildren;
- cmXCodeObject* SourcesGroupChildren;
- cmXCodeObject* ResourcesGroupChildren;
cmMakefile* CurrentMakefile;
cmLocalGenerator* CurrentLocalGenerator;
std::vector<std::string> CurrentConfigurationTypes;
std::string CurrentReRunCMakeMakefile;
std::string CurrentXCodeHackMakefile;
std::string CurrentProject;
- std::set<cmStdString> TargetDoneSet;
- std::vector<std::string> CurrentOutputDirectoryComponents;
+ std::set<std::string> TargetDoneSet;
std::vector<std::string> ProjectSourceDirectoryComponents;
std::vector<std::string> ProjectOutputDirectoryComponents;
- std::map<cmStdString, cmXCodeObject* > GroupMap;
- std::map<cmStdString, cmXCodeObject* > GroupNameMap;
- std::map<cmStdString, cmXCodeObject* > TargetGroup;
- std::map<cmStdString, cmXCodeObject* > FileRefs;
+ std::map<std::string, cmXCodeObject*> GroupMap;
+ std::map<std::string, cmXCodeObject*> GroupNameMap;
+ std::map<std::string, cmXCodeObject*> TargetGroup;
+ std::map<std::string, cmXCodeObject*> FileRefs;
+ std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
std::vector<std::string> Architectures;
- std::string PlatformToolset;
+ std::string ObjectDirArchDefault;
+ std::string ObjectDirArch;
+ std::string GeneratorToolset;
};
#endif
diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h
index 0149d33bd..46cf87871 100644
--- a/Source/cmGraphAdjacencyList.h
+++ b/Source/cmGraphAdjacencyList.h
@@ -1,18 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGraphAdjacencyList_h
#define cmGraphAdjacencyList_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <vector>
/**
* Graph edge representation. Most use cases just need the
@@ -22,10 +15,11 @@
class cmGraphEdge
{
public:
- cmGraphEdge(): Dest(0), Strong(true) {}
- cmGraphEdge(int n): Dest(n), Strong(true) {}
- cmGraphEdge(int n, bool s): Dest(n), Strong(s) {}
- cmGraphEdge(cmGraphEdge const& r): Dest(r.Dest), Strong(r.Strong) {}
+ cmGraphEdge(int n = 0, bool s = true)
+ : Dest(n)
+ , Strong(s)
+ {
+ }
operator int() const { return this->Dest; }
bool IsStrong() const { return this->Strong; }
@@ -33,8 +27,14 @@ private:
int Dest;
bool Strong;
};
-struct cmGraphEdgeList: public std::vector<cmGraphEdge> {};
-struct cmGraphNodeList: public std::vector<int> {};
-struct cmGraphAdjacencyList: public std::vector<cmGraphEdgeList> {};
+struct cmGraphEdgeList : public std::vector<cmGraphEdge>
+{
+};
+struct cmGraphNodeList : public std::vector<int>
+{
+};
+struct cmGraphAdjacencyList : public std::vector<cmGraphEdgeList>
+{
+};
#endif
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index 4816da9ea..7e953cef1 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -1,100 +1,97 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGraphVizWriter.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-#include "cmGeneratedFileStream.h"
+#include "cmConfigure.h"
+#include <iostream>
+#include <sstream>
+#include <utility>
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-static const char* getShapeForTarget(const cmTarget* target)
+static const char* getShapeForTarget(const cmGeneratorTarget* target)
{
- if (!target)
- {
+ if (!target) {
return "ellipse";
- }
+ }
- switch ( target->GetType() )
- {
- case cmTarget::EXECUTABLE:
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
return "house";
- case cmTarget::STATIC_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
return "diamond";
- case cmTarget::SHARED_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
return "polygon";
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
return "octagon";
default:
break;
- }
+ }
return "box";
}
-
-cmGraphVizWriter::cmGraphVizWriter(const std::vector<cmLocalGenerator*>&
- localGenerators)
-:GraphType("digraph")
-,GraphName("GG")
-,GraphHeader("node [\n fontsize = \"12\"\n];")
-,GraphNodePrefix("node")
-,GenerateForExecutables(true)
-,GenerateForStaticLibs(true)
-,GenerateForSharedLibs(true)
-,GenerateForModuleLibs(true)
-,GenerateForExternals(true)
-,LocalGenerators(localGenerators)
-,HaveTargetsAndLibs(false)
+cmGraphVizWriter::cmGraphVizWriter(
+ const std::vector<cmLocalGenerator*>& localGenerators)
+ : GraphType("digraph")
+ , GraphName("GG")
+ , GraphHeader("node [\n fontsize = \"12\"\n];")
+ , GraphNodePrefix("node")
+ , LocalGenerators(localGenerators)
+ , GenerateForExecutables(true)
+ , GenerateForStaticLibs(true)
+ , GenerateForSharedLibs(true)
+ , GenerateForModuleLibs(true)
+ , GenerateForExternals(true)
+ , GeneratePerTarget(true)
+ , GenerateDependers(true)
+ , HaveTargetsAndLibs(false)
{
}
-
void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
const char* fallbackSettingsFileName)
{
- cmake cm;
- cmGlobalGenerator ggi;
- ggi.SetCMakeInstance(&cm);
- cmsys::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator());
- cmMakefile *mf = lg->GetMakefile();
+ cmake cm(cmake::RoleScript);
+ 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;
- if ( !cmSystemTools::FileExists(inFileName) )
- {
+ if (!cmSystemTools::FileExists(inFileName)) {
inFileName = fallbackSettingsFileName;
- if ( !cmSystemTools::FileExists(inFileName) )
- {
+ if (!cmSystemTools::FileExists(inFileName)) {
return;
- }
}
+ }
- if ( !mf->ReadListFile(0, inFileName) )
- {
+ if (!mf->ReadListFile(inFileName)) {
cmSystemTools::Error("Problem opening GraphViz options file: ",
inFileName);
return;
- }
+ }
std::cout << "Reading GraphViz options file: " << inFileName << std::endl;
-#define __set_if_set(var, cmakeDefinition) \
- { \
- const char* value = mf->GetDefinition(cmakeDefinition); \
- if ( value ) \
- { \
- var = value; \
- } \
+#define __set_if_set(var, cmakeDefinition) \
+ { \
+ const char* value = mf->GetDefinition(cmakeDefinition); \
+ if (value) { \
+ (var) = value; \
+ } \
}
__set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE");
@@ -102,13 +99,12 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
__set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER");
__set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");
-#define __set_bool_if_set(var, cmakeDefinition) \
- { \
- const char* value = mf->GetDefinition(cmakeDefinition); \
- if ( value ) \
- { \
- var = mf->IsOn(cmakeDefinition); \
- } \
+#define __set_bool_if_set(var, cmakeDefinition) \
+ { \
+ const char* value = mf->GetDefinition(cmakeDefinition); \
+ if (value) { \
+ (var) = mf->IsOn(cmakeDefinition); \
+ } \
}
__set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES");
@@ -116,55 +112,51 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
__set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
__set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
__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");
- cmStdString ignoreTargetsRegexes;
+ std::string ignoreTargetsRegexes;
__set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS");
this->TargetsToIgnoreRegex.clear();
- if (ignoreTargetsRegexes.size() > 0)
- {
+ 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 )
- {
- cmStdString currentRegexString(*itvIt);
+ for (std::vector<std::string>::const_iterator itvIt =
+ ignoreTargetsRegExVector.begin();
+ itvIt != ignoreTargetsRegExVector.end(); ++itvIt) {
+ std::string currentRegexString(*itvIt);
cmsys::RegularExpression currentRegex;
- if (!currentRegex.compile(currentRegexString.c_str()))
- {
+ if (!currentRegex.compile(currentRegexString.c_str())) {
std::cerr << "Could not compile bad regex \"" << currentRegexString
<< "\"" << std::endl;
- }
- this->TargetsToIgnoreRegex.push_back(currentRegex);
}
+ this->TargetsToIgnoreRegex.push_back(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)
{
+ if (!this->GenerateDependers) {
+ return;
+ }
+
this->CollectTargetsAndLibs();
- for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
- this->TargetPtrs.begin();
- ptrIt != this->TargetPtrs.end();
- ++ptrIt)
- {
- if (ptrIt->second == NULL)
- {
+ for (std::map<std::string, const cmGeneratorTarget*>::const_iterator ptrIt =
+ this->TargetPtrs.begin();
+ ptrIt != this->TargetPtrs.end(); ++ptrIt) {
+ if (ptrIt->second == CM_NULLPTR) {
continue;
- }
+ }
- if (this->GenerateForTargetType(ptrIt->second->GetType()) == false)
- {
+ if (!this->GenerateForTargetType(ptrIt->second->GetType())) {
continue;
- }
+ }
std::string currentFilename = fileName;
currentFilename += ".";
@@ -172,10 +164,9 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
currentFilename += ".dependers";
cmGeneratedFileStream str(currentFilename.c_str());
- if ( !str )
- {
+ if (!str) {
return;
- }
+ }
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
@@ -183,34 +174,33 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
std::cout << "Writing " << currentFilename << "..." << std::endl;
this->WriteHeader(str);
- this->WriteDependerConnections(ptrIt->first.c_str(),
- insertedNodes, insertedConnections, str);
+ this->WriteDependerConnections(ptrIt->first, insertedNodes,
+ insertedConnections, str);
this->WriteFooter(str);
- }
+ }
}
-
// Iterate over all targets and write for each one a graph which shows
// on which targets it depends.
void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
{
+ if (!this->GeneratePerTarget) {
+ return;
+ }
+
this->CollectTargetsAndLibs();
- for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
- this->TargetPtrs.begin();
- ptrIt != this->TargetPtrs.end();
- ++ptrIt)
- {
- if (ptrIt->second == NULL)
- {
+ for (std::map<std::string, const cmGeneratorTarget*>::const_iterator ptrIt =
+ this->TargetPtrs.begin();
+ ptrIt != this->TargetPtrs.end(); ++ptrIt) {
+ if (ptrIt->second == CM_NULLPTR) {
continue;
- }
+ }
- if (this->GenerateForTargetType(ptrIt->second->GetType()) == false)
- {
+ if (!this->GenerateForTargetType(ptrIt->second->GetType())) {
continue;
- }
+ }
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
@@ -219,31 +209,27 @@ void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
currentFilename += ".";
currentFilename += ptrIt->first;
cmGeneratedFileStream str(currentFilename.c_str());
- if ( !str )
- {
+ if (!str) {
return;
- }
+ }
std::cout << "Writing " << currentFilename << "..." << std::endl;
this->WriteHeader(str);
- this->WriteConnections(ptrIt->first.c_str(),
- insertedNodes, insertedConnections, str);
+ this->WriteConnections(ptrIt->first, insertedNodes, insertedConnections,
+ str);
this->WriteFooter(str);
- }
-
+ }
}
-
void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
{
this->CollectTargetsAndLibs();
cmGeneratedFileStream str(fileName);
- if ( !str )
- {
+ if (!str) {
return;
- }
+ }
this->WriteHeader(str);
std::cout << "Writing " << fileName << "..." << std::endl;
@@ -251,332 +237,275 @@ void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
- for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
- this->TargetPtrs.begin();
- ptrIt != this->TargetPtrs.end();
- ++ptrIt)
- {
- if (ptrIt->second == NULL)
- {
+ for (std::map<std::string, const cmGeneratorTarget*>::const_iterator ptrIt =
+ this->TargetPtrs.begin();
+ ptrIt != this->TargetPtrs.end(); ++ptrIt) {
+ if (ptrIt->second == CM_NULLPTR) {
continue;
- }
+ }
- if (this->GenerateForTargetType(ptrIt->second->GetType()) == false)
- {
+ if (!this->GenerateForTargetType(ptrIt->second->GetType())) {
continue;
- }
-
- this->WriteConnections(ptrIt->first.c_str(),
- insertedNodes, insertedConnections, str);
}
+
+ this->WriteConnections(ptrIt->first, insertedNodes, insertedConnections,
+ str);
+ }
this->WriteFooter(str);
}
-
void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const
{
- str << this->GraphType << " " << this->GraphName << " {" << std::endl;
+ str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl;
str << this->GraphHeader << std::endl;
}
-
void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const
{
str << "}" << std::endl;
}
-
-void cmGraphVizWriter::WriteConnections(const char* targetName,
- std::set<std::string>& insertedNodes,
- std::set<std::string>& insertedConnections,
- cmGeneratedFileStream& str) const
+void cmGraphVizWriter::WriteConnections(
+ const std::string& targetName, std::set<std::string>& insertedNodes,
+ std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
{
- std::map<cmStdString, const cmTarget* >::const_iterator targetPtrIt =
- this->TargetPtrs.find(targetName);
+ std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
+ this->TargetPtrs.find(targetName);
- if (targetPtrIt == this->TargetPtrs.end()) // not found at all
- {
+ if (targetPtrIt == this->TargetPtrs.end()) // not found at all
+ {
return;
- }
+ }
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
- if (targetPtrIt->second == NULL) // it's an external library
- {
+ if (targetPtrIt->second == CM_NULLPTR) // it's an external library
+ {
return;
- }
-
+ }
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
const cmTarget::LinkLibraryVectorType* ll =
- &(targetPtrIt->second->GetOriginalLinkLibraries());
+ &(targetPtrIt->second->Target->GetOriginalLinkLibraries());
for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
- llit != ll->end();
- ++ llit )
- {
+ llit != ll->end(); ++llit) {
const char* libName = llit->first.c_str();
- std::map<cmStdString, cmStdString>::const_iterator libNameIt =
- this->TargetNamesNodes.find(libName);
+ std::map<std::string, std::string>::const_iterator libNameIt =
+ this->TargetNamesNodes.find(libName);
// can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used
- if(libNameIt == this->TargetNamesNodes.end())
- {
+ if (libNameIt == this->TargetNamesNodes.end()) {
continue;
- }
+ }
std::string connectionName = myNodeName;
connectionName += "-";
connectionName += libNameIt->second;
- if (insertedConnections.find(connectionName) == insertedConnections.end())
- {
+ if (insertedConnections.find(connectionName) ==
+ insertedConnections.end()) {
insertedConnections.insert(connectionName);
this->WriteNode(libName, this->TargetPtrs.find(libName)->second,
insertedNodes, str);
- str << " \"" << myNodeName.c_str() << "\" -> \""
- << libNameIt->second.c_str() << "\"";
+ str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\"";
str << " // " << targetName << " -> " << libName << std::endl;
this->WriteConnections(libName, insertedNodes, insertedConnections, str);
- }
}
-
+ }
}
-
-void cmGraphVizWriter::WriteDependerConnections(const char* targetName,
- std::set<std::string>& insertedNodes,
- std::set<std::string>& insertedConnections,
- cmGeneratedFileStream& str) const
+void cmGraphVizWriter::WriteDependerConnections(
+ const std::string& targetName, std::set<std::string>& insertedNodes,
+ std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
{
- std::map<cmStdString, const cmTarget* >::const_iterator targetPtrIt =
- this->TargetPtrs.find(targetName);
+ std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
+ this->TargetPtrs.find(targetName);
- if (targetPtrIt == this->TargetPtrs.end()) // not found at all
- {
+ if (targetPtrIt == this->TargetPtrs.end()) // not found at all
+ {
return;
- }
+ }
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
- if (targetPtrIt->second == NULL) // it's an external library
- {
+ if (targetPtrIt->second == CM_NULLPTR) // it's an external library
+ {
return;
- }
-
+ }
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
// now search who links against me
- for(std::map<cmStdString, const cmTarget*>::const_iterator dependerIt =
- this->TargetPtrs.begin();
- dependerIt != this->TargetPtrs.end();
- ++dependerIt)
- {
- if (dependerIt->second == NULL)
- {
+ for (std::map<std::string, const cmGeneratorTarget*>::const_iterator
+ dependerIt = this->TargetPtrs.begin();
+ dependerIt != this->TargetPtrs.end(); ++dependerIt) {
+ if (dependerIt->second == CM_NULLPTR) {
continue;
- }
+ }
- if (this->GenerateForTargetType(dependerIt->second->GetType()) == false)
- {
+ if (!this->GenerateForTargetType(dependerIt->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->GetOriginalLinkLibraries());
+ &(dependerIt->second->Target->GetOriginalLinkLibraries());
for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
- llit != ll->end();
- ++ llit )
- {
- std::string libName = llit->first.c_str();
- if (libName == targetName)
- {
+ llit != ll->end(); ++llit) {
+ std::string libName = llit->first;
+ if (libName == targetName) {
// So this target links against targetName.
- std::map<cmStdString, cmStdString>::const_iterator dependerNodeNameIt =
- this->TargetNamesNodes.find(dependerIt->first);
+ std::map<std::string, std::string>::const_iterator dependerNodeNameIt =
+ this->TargetNamesNodes.find(dependerIt->first);
- if(dependerNodeNameIt != this->TargetNamesNodes.end())
- {
+ if (dependerNodeNameIt != this->TargetNamesNodes.end()) {
std::string connectionName = dependerNodeNameIt->second;
connectionName += "-";
connectionName += myNodeName;
if (insertedConnections.find(connectionName) ==
- insertedConnections.end())
- {
+ insertedConnections.end()) {
insertedConnections.insert(connectionName);
- this->WriteNode(dependerIt->first.c_str(), dependerIt->second,
+ this->WriteNode(dependerIt->first, dependerIt->second,
insertedNodes, str);
str << " \"" << dependerNodeNameIt->second << "\" -> \""
<< myNodeName << "\"";
- str << " // " <<targetName<< " -> " <<dependerIt->first<<std::endl;
- this->WriteDependerConnections(dependerIt->first.c_str(),
- insertedNodes, insertedConnections, str);
- }
-
-
+ str << " // " << targetName << " -> " << dependerIt->first
+ << std::endl;
+ this->WriteDependerConnections(dependerIt->first, insertedNodes,
+ insertedConnections, str);
}
- break;
}
+ break;
}
}
-
+ }
}
-
-void cmGraphVizWriter::WriteNode(const char* targetName,
- const cmTarget* target,
+void cmGraphVizWriter::WriteNode(const std::string& targetName,
+ const cmGeneratorTarget* target,
std::set<std::string>& insertedNodes,
cmGeneratedFileStream& str) const
{
- if (insertedNodes.find(targetName) == insertedNodes.end())
- {
+ if (insertedNodes.find(targetName) == insertedNodes.end()) {
insertedNodes.insert(targetName);
- std::map<cmStdString, cmStdString>::const_iterator nameIt =
- this->TargetNamesNodes.find(targetName);
+ std::map<std::string, std::string>::const_iterator nameIt =
+ this->TargetNamesNodes.find(targetName);
- str << " \"" << nameIt->second.c_str() << "\" [ label=\""
- << targetName << "\" shape=\"" << getShapeForTarget(target)
- << "\"];" << std::endl;
+ str << " \"" << nameIt->second << "\" [ label=\"" << targetName
+ << "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl;
}
}
-
void cmGraphVizWriter::CollectTargetsAndLibs()
{
- if (this->HaveTargetsAndLibs == false)
- {
+ if (!this->HaveTargetsAndLibs) {
this->HaveTargetsAndLibs = true;
int cnt = this->CollectAllTargets();
- if (this->GenerateForExternals)
- {
+ if (this->GenerateForExternals) {
this->CollectAllExternalLibs(cnt);
- }
}
+ }
}
-
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 )
- {
- const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
- for ( cmTargets::const_iterator tit = targets->begin();
- tit != targets->end();
- ++ tit )
- {
- const char* realTargetName = tit->first.c_str();
- if(this->IgnoreThisTarget(realTargetName))
- {
+ 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();
+ if (this->IgnoreThisTarget(realTargetName)) {
// Skip ignored targets
continue;
- }
- //std::cout << "Found target: " << tit->first.c_str() << std::endl;
- cmOStringStream ostr;
+ }
+ // std::cout << "Found target: " << tit->first << std::endl;
+ std::ostringstream ostr;
ostr << this->GraphNodePrefix << cnt++;
this->TargetNamesNodes[realTargetName] = ostr.str();
- this->TargetPtrs[realTargetName] = &tit->second;
- }
+ this->TargetPtrs[realTargetName] = *it;
}
+ }
return cnt;
}
-
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 )
- {
- const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
- for ( cmTargets::const_iterator tit = targets->begin();
- tit != targets->end();
- ++ tit )
- {
- const char* realTargetName = tit->first.c_str();
- if (this->IgnoreThisTarget(realTargetName))
- {
+ 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();
+ if (this->IgnoreThisTarget(realTargetName)) {
// Skip ignored targets
continue;
- }
+ }
const cmTarget::LinkLibraryVectorType* ll =
- &(tit->second.GetOriginalLinkLibraries());
+ &((*it)->Target->GetOriginalLinkLibraries());
for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
- llit != ll->end();
- ++ llit )
- {
+ llit != ll->end(); ++llit) {
const char* libName = llit->first.c_str();
- if (this->IgnoreThisTarget(libName))
- {
+ if (this->IgnoreThisTarget(libName)) {
// Skip ignored targets
continue;
- }
+ }
- std::map<cmStdString, const cmTarget*>::const_iterator tarIt =
- this->TargetPtrs.find(libName);
- if ( tarIt == this->TargetPtrs.end() )
- {
- cmOStringStream ostr;
+ std::map<std::string, const cmGeneratorTarget*>::const_iterator 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] = NULL;
- //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
- //<< "\" shape=\"ellipse\"];" << std::endl;
- }
+ this->TargetPtrs[libName] = CM_NULLPTR;
+ // str << " \"" << ostr << "\" [ label=\"" << libName
+ // << "\" shape=\"ellipse\"];" << std::endl;
}
}
}
- return cnt;
+ }
+ return cnt;
}
-
-bool cmGraphVizWriter::IgnoreThisTarget(const char* name)
+bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name)
{
- for(std::vector<cmsys::RegularExpression>::iterator itvIt
- = this->TargetsToIgnoreRegex.begin();
- itvIt != this->TargetsToIgnoreRegex.end();
- ++ itvIt )
- {
+ for (std::vector<cmsys::RegularExpression>::iterator itvIt =
+ this->TargetsToIgnoreRegex.begin();
+ itvIt != this->TargetsToIgnoreRegex.end(); ++itvIt) {
cmsys::RegularExpression& regEx = *itvIt;
- if (regEx.is_valid())
- {
- if (regEx.find(name))
- {
+ if (regEx.is_valid()) {
+ if (regEx.find(name)) {
return true;
- }
}
}
+ }
return false;
}
-
-bool cmGraphVizWriter::GenerateForTargetType(cmTarget::TargetType targetType)
- const
+bool cmGraphVizWriter::GenerateForTargetType(
+ cmStateEnums::TargetType targetType) const
{
- switch (targetType)
- {
- case cmTarget::EXECUTABLE:
+ switch (targetType) {
+ case cmStateEnums::EXECUTABLE:
return this->GenerateForExecutables;
- case cmTarget::STATIC_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
return this->GenerateForStaticLibs;
- case cmTarget::SHARED_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
return this->GenerateForSharedLibs;
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
return this->GenerateForModuleLibs;
default:
break;
diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h
index f784aa0a1..824999b96 100644
--- a/Source/cmGraphVizWriter.h
+++ b/Source/cmGraphVizWriter.h
@@ -1,29 +1,27 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef CMGRAPHVIZWRITER_H
#define CMGRAPHVIZWRITER_H
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h" // IWYU pragma: keep
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmStandardIncludes.h"
-#include "cmLocalGenerator.h"
-#include "cmGeneratedFileStream.h"
-#include "cmTarget.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmStateTypes.h"
+#include "cmsys/RegularExpression.hxx"
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmGeneratedFileStream;
+class cmGeneratorTarget;
+class cmLocalGenerator;
/** 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);
void ReadSettings(const char* settingsFileName,
@@ -35,7 +33,6 @@ public:
void WriteGlobalFile(const char* fileName);
protected:
-
void CollectTargetsAndLibs();
int CollectAllTargets();
@@ -44,45 +41,47 @@ protected:
void WriteHeader(cmGeneratedFileStream& str) const;
- void WriteConnections(const char* targetName,
+ void WriteConnections(const std::string& targetName,
std::set<std::string>& insertedNodes,
std::set<std::string>& insertedConnections,
cmGeneratedFileStream& str) const;
- void WriteDependerConnections(const char* targetName,
+ void WriteDependerConnections(const std::string& targetName,
std::set<std::string>& insertedNodes,
std::set<std::string>& insertedConnections,
cmGeneratedFileStream& str) const;
- void WriteNode(const char* targetName, const cmTarget* target,
+ void WriteNode(const std::string& targetName,
+ const cmGeneratorTarget* target,
std::set<std::string>& insertedNodes,
cmGeneratedFileStream& str) const;
void WriteFooter(cmGeneratedFileStream& str) const;
- bool IgnoreThisTarget(const char* name);
-
- bool GenerateForTargetType(cmTarget::TargetType targetType) const;
+ bool IgnoreThisTarget(const std::string& name);
- cmStdString GraphType;
- cmStdString GraphName;
- cmStdString GraphHeader;
- cmStdString GraphNodePrefix;
+ bool GenerateForTargetType(cmStateEnums::TargetType targetType) const;
- bool GenerateForExecutables;
- bool GenerateForStaticLibs;
- bool GenerateForSharedLibs;
- bool GenerateForModuleLibs;
- bool GenerateForExternals;
+ std::string GraphType;
+ std::string GraphName;
+ std::string GraphHeader;
+ std::string GraphNodePrefix;
std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex;
const std::vector<cmLocalGenerator*>& LocalGenerators;
- std::map<cmStdString, const cmTarget*> TargetPtrs;
+ std::map<std::string, const cmGeneratorTarget*> TargetPtrs;
// maps from the actual target names to node names in dot:
- std::map<cmStdString, cmStdString> TargetNamesNodes;
+ std::map<std::string, std::string> TargetNamesNodes;
+ bool GenerateForExecutables;
+ bool GenerateForStaticLibs;
+ bool GenerateForSharedLibs;
+ bool GenerateForModuleLibs;
+ bool GenerateForExternals;
+ bool GeneratePerTarget;
+ bool GenerateDependers;
bool HaveTargetsAndLibs;
};
diff --git a/Source/cmHexFileConverter.cxx b/Source/cmHexFileConverter.cxx
index a540825ff..78dceb794 100644
--- a/Source/cmHexFileConverter.cxx
+++ b/Source/cmHexFileConverter.cxx
@@ -1,75 +1,62 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmHexFileConverter.h"
+#include "cmConfigure.h"
#include <stdio.h>
#include <string.h>
-#define INTEL_HEX_MIN_LINE_LENGTH (1+8 +2)
-#define INTEL_HEX_MAX_LINE_LENGTH (1+8+(256*2)+2)
-#define MOTOROLA_SREC_MIN_LINE_LENGTH (2+2+4 +2)
-#define MOTOROLA_SREC_MAX_LINE_LENGTH (2+2+8+(256*2)+2)
+#include "cmSystemTools.h"
+
+#define INTEL_HEX_MIN_LINE_LENGTH (1 + 8 + 2)
+#define INTEL_HEX_MAX_LINE_LENGTH (1 + 8 + (256 * 2) + 2)
+#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')));
+ return (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
+ ((c >= 'A') && (c <= 'F')));
}
static unsigned int ChompStrlen(const char* line)
{
- if (line == 0)
- {
+ if (line == CM_NULLPTR) {
return 0;
- }
- unsigned int length = static_cast<unsigned int>(strlen(line));
- if ((line[length-1] == '\n') || (line[length-1] == '\r'))
- {
+ }
+ unsigned int length = static_cast<unsigned int>(strlen(line));
+ if ((line[length - 1] == '\n') || (line[length - 1] == '\r')) {
length--;
- }
- if ((line[length-1] == '\n') || (line[length-1] == '\r'))
- {
+ }
+ if ((line[length - 1] == '\n') || (line[length - 1] == '\r')) {
length--;
- }
+ }
return length;
}
-static bool OutputBin(FILE* file, const char * buf,
- unsigned int startIndex, unsigned int stopIndex)
+static bool OutputBin(FILE* file, const char* buf, unsigned int startIndex,
+ unsigned int stopIndex)
{
bool success = true;
char hexNumber[3];
hexNumber[2] = '\0';
char outBuf[256];
unsigned int outBufCount = 0;
- for (unsigned int i = startIndex; i < stopIndex; i += 2)
- {
+ for (unsigned int i = startIndex; i < stopIndex; i += 2) {
hexNumber[0] = buf[i];
- hexNumber[1] = buf[i+1];
+ hexNumber[1] = buf[i + 1];
unsigned int convertedByte = 0;
- if (sscanf(hexNumber, "%x", &convertedByte) != 1)
- {
+ if (sscanf(hexNumber, "%x", &convertedByte) != 1) {
success = false;
break;
- }
+ }
outBuf[outBufCount] = static_cast<char>(convertedByte & 0xff);
outBufCount++;
- }
- if (success)
- {
- success = (fwrite(outBuf, 1, outBufCount, file)==outBufCount);
- }
+ }
+ if (success) {
+ success = (fwrite(outBuf, 1, outBufCount, file) == outBufCount);
+ }
return success;
}
@@ -77,45 +64,36 @@ static bool OutputBin(FILE* file, const char * buf,
static bool ConvertMotorolaSrecLine(const char* buf, FILE* outFile)
{
unsigned int slen = ChompStrlen(buf);
- if ((slen < MOTOROLA_SREC_MIN_LINE_LENGTH)
- || (slen > MOTOROLA_SREC_MAX_LINE_LENGTH))
- {
+ if ((slen < MOTOROLA_SREC_MIN_LINE_LENGTH) ||
+ (slen > MOTOROLA_SREC_MAX_LINE_LENGTH)) {
return false;
- }
+ }
// line length must be even
- if (slen % 2 == 1)
- {
+ if (slen % 2 == 1) {
return false;
- }
+ }
- if (buf[0] != 'S')
- {
+ if (buf[0] != 'S') {
return false;
- }
+ }
unsigned int dataStart = 0;
// ignore extra address records
- if ((buf[1] == '5') || (buf[1] == '7') || (buf[1] == '8') || (buf[1] == '9'))
- {
+ if ((buf[1] == '5') || (buf[1] == '7') || (buf[1] == '8') ||
+ (buf[1] == '9')) {
return true;
- }
- else if (buf[1] == '1')
- {
+ }
+ if (buf[1] == '1') {
dataStart = 8;
- }
- else if (buf[1] == '2')
- {
+ } else if (buf[1] == '2') {
dataStart = 10;
- }
- else if (buf[1] == '3')
- {
+ } else if (buf[1] == '3') {
dataStart = 12;
- }
- else // unknown record type
- {
+ } else // unknown record type
+ {
return false;
- }
+ }
// ignore the last two bytes (checksum)
return OutputBin(outFile, buf, dataStart, slen - 2);
@@ -125,91 +103,77 @@ static bool ConvertMotorolaSrecLine(const char* buf, FILE* outFile)
static bool ConvertIntelHexLine(const char* buf, FILE* outFile)
{
unsigned int slen = ChompStrlen(buf);
- if ((slen < INTEL_HEX_MIN_LINE_LENGTH)
- || (slen > INTEL_HEX_MAX_LINE_LENGTH))
- {
+ if ((slen < INTEL_HEX_MIN_LINE_LENGTH) ||
+ (slen > INTEL_HEX_MAX_LINE_LENGTH)) {
return false;
- }
+ }
// line length must be odd
- if (slen % 2 == 0)
- {
+ if (slen % 2 == 0) {
return false;
- }
+ }
- if ((buf[0] != ':') || (buf[7] != '0'))
- {
+ if ((buf[0] != ':') || (buf[7] != '0')) {
return false;
- }
+ }
unsigned int dataStart = 0;
- if ((buf[8] == '0') || (buf[8] == '1'))
- {
+ if ((buf[8] == '0') || (buf[8] == '1')) {
dataStart = 9;
- }
+ }
// ignore extra address records
- else if ((buf[8] == '2') || (buf[8] == '3') || (buf[8] == '4')
- || (buf[8] == '5'))
- {
+ else if ((buf[8] == '2') || (buf[8] == '3') || (buf[8] == '4') ||
+ (buf[8] == '5')) {
return true;
- }
- else // unknown record type
- {
+ } else // unknown record type
+ {
return false;
- }
+ }
-// ignore the last two bytes (checksum)
+ // ignore the last two bytes (checksum)
return OutputBin(outFile, buf, dataStart, slen - 2);
}
cmHexFileConverter::FileType cmHexFileConverter::DetermineFileType(
- const char* inFileName)
+ const char* inFileName)
{
char buf[1024];
- FILE* inFile = fopen(inFileName, "rb");
- if (inFile == 0)
- {
+ FILE* inFile = cmsys::SystemTools::Fopen(inFileName, "rb");
+ if (inFile == CM_NULLPTR) {
return Binary;
- }
+ }
- if(!fgets(buf, 1024, inFile))
- {
+ if (!fgets(buf, 1024, inFile)) {
buf[0] = 0;
- }
+ }
fclose(inFile);
FileType type = Binary;
unsigned int minLineLength = 0;
unsigned int maxLineLength = 0;
if (buf[0] == ':') // might be an intel hex file
- {
+ {
type = IntelHex;
minLineLength = INTEL_HEX_MIN_LINE_LENGTH;
maxLineLength = INTEL_HEX_MAX_LINE_LENGTH;
- }
- else if (buf[0] == 'S') // might be a motorola srec file
- {
+ } else if (buf[0] == 'S') // might be a motorola srec file
+ {
type = MotorolaSrec;
minLineLength = MOTOROLA_SREC_MIN_LINE_LENGTH;
maxLineLength = MOTOROLA_SREC_MAX_LINE_LENGTH;
- }
- else
- {
+ } else {
return Binary;
- }
+ }
unsigned int slen = ChompStrlen(buf);
- if ((slen < minLineLength) || (slen > maxLineLength))
- {
+ if ((slen < minLineLength) || (slen > maxLineLength)) {
return Binary;
- }
+ }
- for (unsigned int i = 1; i < slen; i++)
- {
- if (!cm_IsHexChar(buf[i]))
- {
+ for (unsigned int i = 1; i < slen; i++) {
+ if (!cm_IsHexChar(buf[i])) {
return Binary;
- }
}
+ }
return type;
}
@@ -217,49 +181,39 @@ bool cmHexFileConverter::TryConvert(const char* inFileName,
const char* outFileName)
{
FileType type = DetermineFileType(inFileName);
- if (type == Binary)
- {
+ if (type == Binary) {
return false;
- }
+ }
// try to open the file
- FILE* inFile = fopen(inFileName, "rb");
- FILE* outFile = fopen(outFileName, "wb");
- if ((inFile == 0) || (outFile == 0))
- {
- if (inFile != 0)
- {
+ 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) {
fclose(inFile);
- }
- if (outFile != 0)
- {
+ }
+ if (outFile != CM_NULLPTR) {
fclose(outFile);
- }
- return false;
}
+ return false;
+ }
// convert them line by line
bool success = false;
char buf[1024];
- while (fgets(buf, 1024, inFile) != 0)
- {
- if (type == MotorolaSrec)
- {
+ while (fgets(buf, 1024, inFile) != CM_NULLPTR) {
+ if (type == MotorolaSrec) {
success = ConvertMotorolaSrecLine(buf, outFile);
- }
- else if (type == IntelHex)
- {
+ } else if (type == IntelHex) {
success = ConvertIntelHexLine(buf, outFile);
- }
- if (success == false)
- {
+ }
+ if (!success) {
break;
- }
}
+ }
// close them again
fclose(inFile);
fclose(outFile);
return success;
}
-
diff --git a/Source/cmHexFileConverter.h b/Source/cmHexFileConverter.h
index e11d74a2f..1050bc1b4 100644
--- a/Source/cmHexFileConverter.h
+++ b/Source/cmHexFileConverter.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmHexFileConverter_h
#define cmHexFileConverter_h
@@ -20,7 +11,12 @@
class cmHexFileConverter
{
public:
- enum FileType {Binary, IntelHex, MotorolaSrec};
+ enum FileType
+ {
+ Binary,
+ IntelHex,
+ MotorolaSrec
+ };
static FileType DetermineFileType(const char* inFileName);
static bool TryConvert(const char* inFileName, const char* outFileName);
};
diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h
index e372c0a15..152e293eb 100644
--- a/Source/cmIDEFlagTable.h
+++ b/Source/cmIDEFlagTable.h
@@ -1,38 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIDEFlagTable_h
#define cmIDEFlagTable_h
// 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* IDEName; // name used in the IDE xml file
const char* commandFlag; // command line flag
const char* comment; // comment
- const char* value; // string value
- unsigned int special; // flags for special handling requests
+ const char* value; // string value
+ unsigned int special; // flags for special handling requests
enum
{
- UserValue = (1<<0), // flag contains a user-specified value
- UserIgnored = (1<<1), // ignore any user value
- UserRequired = (1<<2), // match only when user value is non-empty
- Continue = (1<<3), // continue looking for matching entries
- SemicolonAppendable = (1<<4), // a flag that if specified multiple times
- // should have its value appended to the
- // old value with semicolons (e.g.
- // /NODEFAULTLIB: =>
- // IgnoreDefaultLibraryNames)
+ UserValue = (1 << 0), // flag contains a user-specified value
+ UserIgnored = (1 << 1), // ignore any user value
+ UserRequired = (1 << 2), // match only when user value is non-empty
+ Continue = (1 << 3), // continue looking for matching entries
+ SemicolonAppendable = (1 << 4), // a flag that if specified multiple times
+ // should have its value appended to the
+ // old value with semicolons (e.g.
+ // /NODEFAULTLIB: =>
+ // IgnoreDefaultLibraryNames)
+ UserFollowing = (1 << 5), // expect value in following argument
+ CaseInsensitive = (1 << 6), // flag may be any case
+ SpaceAppendable = (1 << 7), // a flag that if specified multiple times
+ // should have its value appended to the
+ // old value with spaces
- UserValueIgnored = UserValue | UserIgnored,
+ UserValueIgnored = UserValue | UserIgnored,
UserValueRequired = UserValue | UserRequired
};
};
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 34a9c7c78..5e872d2ff 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -1,195 +1,206 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIDEOptions.h"
+#include "cmsys/String.h"
+#include <iterator>
+#include <string.h>
+
+#include "cmIDEFlagTable.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
cmIDEOptions::cmIDEOptions()
{
this->DoingDefine = false;
this->AllowDefine = true;
this->AllowSlash = false;
- for(int i=0; i < FlagTableCount; ++i)
- {
+ this->DoingFollowing = 0;
+ for (int i = 0; i < FlagTableCount; ++i) {
this->FlagTable[i] = 0;
- }
+ }
}
-//----------------------------------------------------------------------------
cmIDEOptions::~cmIDEOptions()
{
}
-//----------------------------------------------------------------------------
void cmIDEOptions::HandleFlag(const char* flag)
{
// If the last option was -D then this option is the definition.
- if(this->DoingDefine)
- {
+ if (this->DoingDefine) {
this->DoingDefine = false;
this->Defines.push_back(flag);
return;
- }
+ }
+
+ // If the last option expected a following value, this is it.
+ if (this->DoingFollowing) {
+ this->FlagMapUpdate(this->DoingFollowing, flag);
+ this->DoingFollowing = 0;
+ return;
+ }
// Look for known arguments.
- if(flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))
- {
+ if (flag[0] == '-' || (this->AllowSlash && flag[0] == '/')) {
// Look for preprocessor definitions.
- if(this->AllowDefine && flag[1] == 'D')
- {
- if(flag[2] == '\0')
- {
+ if (this->AllowDefine && flag[1] == 'D') {
+ if (flag[2] == '\0') {
// The next argument will have the definition.
this->DoingDefine = true;
- }
- else
- {
+ } else {
// Store this definition.
- this->Defines.push_back(flag+2);
- }
- return;
+ this->Defines.push_back(flag + 2);
}
+ return;
+ }
// Look through the available flag tables.
bool flag_handled = false;
- for(int i=0; i < FlagTableCount && this->FlagTable[i]; ++i)
- {
- if(this->CheckFlagTable(this->FlagTable[i], flag, flag_handled))
- {
+ for (int i = 0; i < FlagTableCount && this->FlagTable[i]; ++i) {
+ if (this->CheckFlagTable(this->FlagTable[i], flag, flag_handled)) {
return;
- }
}
+ }
// If any map entry handled the flag we are done.
- if(flag_handled)
- {
+ if (flag_handled) {
return;
- }
}
+ }
// This option is not known. Store it in the output flags.
this->StoreUnknownFlag(flag);
}
-//----------------------------------------------------------------------------
bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
const char* flag, bool& flag_handled)
{
// 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; ++entry) {
bool entry_found = false;
- if(entry->special & cmIDEFlagTable::UserValue)
- {
+ 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 &&
- (!(entry->special & cmIDEFlagTable::UserRequired) ||
- static_cast<int>(strlen(flag+1)) > n))
- {
- if(entry->special & cmIDEFlagTable::UserIgnored)
- {
- // Ignore the user-specified value.
- this->FlagMap[entry->IDEName] = entry->value;
- }
- else if(entry->special & cmIDEFlagTable::SemicolonAppendable)
- {
- const char *new_value = flag+1+n;
-
- std::map<cmStdString,cmStdString>::iterator itr;
- itr = this->FlagMap.find(entry->IDEName);
- if(itr != this->FlagMap.end())
- {
- // Append to old value (if present) with semicolons;
- itr->second += ";";
- itr->second += new_value;
- }
- else
- {
- this->FlagMap[entry->IDEName] = new_value;
- }
- }
- else
- {
- // Use the user-specified value.
- this->FlagMap[entry->IDEName] = flag+1+n;
- }
+ if ((strncmp(flag + 1, entry->commandFlag, n) == 0 ||
+ (entry->special & cmIDEFlagTable::CaseInsensitive &&
+ cmsysString_strncasecmp(flag + 1, entry->commandFlag, n))) &&
+ (!(entry->special & cmIDEFlagTable::UserRequired) ||
+ static_cast<int>(strlen(flag + 1)) > n)) {
+ this->FlagMapUpdate(entry, flag + n + 1);
entry_found = true;
- }
}
- else if(strcmp(flag+1, entry->commandFlag) == 0)
- {
- // This flag table entry provides a fixed value.
- this->FlagMap[entry->IDEName] = entry->value;
- entry_found = true;
+ } else if (strcmp(flag + 1, entry->commandFlag) == 0 ||
+ (entry->special & cmIDEFlagTable::CaseInsensitive &&
+ cmsysString_strcasecmp(flag + 1, entry->commandFlag) == 0)) {
+ if (entry->special & cmIDEFlagTable::UserFollowing) {
+ // This flag expects a value in the following argument.
+ this->DoingFollowing = entry;
+ } else {
+ // This flag table entry provides a fixed value.
+ this->FlagMap[entry->IDEName] = entry->value;
}
+ entry_found = true;
+ }
// If the flag has been handled by an entry not requesting a
// search continuation we are done.
- if(entry_found && !(entry->special & cmIDEFlagTable::Continue))
- {
+ if (entry_found && !(entry->special & cmIDEFlagTable::Continue)) {
return true;
- }
+ }
// If the entry was found the flag has been handled.
flag_handled = flag_handled || entry_found;
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
+void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
+ const char* new_value)
+{
+ if (entry->special & cmIDEFlagTable::UserIgnored) {
+ // Ignore the user-specified value.
+ this->FlagMap[entry->IDEName] = entry->value;
+ } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) {
+ this->FlagMap[entry->IDEName].push_back(new_value);
+ } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
+ this->FlagMap[entry->IDEName].append_with_space(new_value);
+ } else {
+ // Use the user-specified value.
+ this->FlagMap[entry->IDEName] = new_value;
+ }
+}
+
void cmIDEOptions::AddDefine(const std::string& def)
{
this->Defines.push_back(def);
}
-//----------------------------------------------------------------------------
void cmIDEOptions::AddDefines(const char* defines)
{
- if(defines)
- {
+ if (defines) {
// Expand the list of definitions.
cmSystemTools::ExpandListArgument(defines, this->Defines);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmIDEOptions::AddDefines(const std::vector<std::string> &defines)
+void cmIDEOptions::AddDefines(const std::vector<std::string>& defines)
{
this->Defines.insert(this->Defines.end(), defines.begin(), defines.end());
}
-//----------------------------------------------------------------------------
+std::vector<std::string> const& cmIDEOptions::GetDefines() const
+{
+ return this->Defines;
+}
+
void cmIDEOptions::AddFlag(const char* flag, const char* value)
{
this->FlagMap[flag] = value;
}
-//----------------------------------------------------------------------------
+void cmIDEOptions::AddFlag(const char* flag,
+ std::vector<std::string> const& value)
+{
+ this->FlagMap[flag] = value;
+}
+
+void cmIDEOptions::AppendFlag(std::string const& flag,
+ std::string const& value)
+{
+ this->FlagMap[flag].push_back(value);
+}
+
+void cmIDEOptions::AppendFlag(std::string const& flag,
+ std::vector<std::string> const& value)
+{
+ FlagValue& fv = this->FlagMap[flag];
+ std::copy(value.begin(), value.end(), std::back_inserter(fv));
+}
+
+void cmIDEOptions::AppendFlagString(std::string const& flag,
+ std::string const& value)
+{
+ this->FlagMap[flag].append_with_space(value);
+}
+
void cmIDEOptions::RemoveFlag(const char* flag)
{
this->FlagMap.erase(flag);
}
-//----------------------------------------------------------------------------
+bool cmIDEOptions::HasFlag(std::string const& flag) const
+{
+ return this->FlagMap.find(flag) != this->FlagMap.end();
+}
+
const char* cmIDEOptions::GetFlag(const char* flag)
{
- std::map<cmStdString, cmStdString>::iterator i = this->FlagMap.find(flag);
- if(i != this->FlagMap.end())
- {
- return i->second.c_str();
- }
+ // 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) {
+ return i->second[0].c_str();
+ }
return 0;
}
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index e78af3ee4..19e96bd44 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -1,19 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIDEOptions_h
#define cmIDEOptions_h
-#include "cmStandardIncludes.h"
-#include "cmIDEFlagTable.h"
+#include "cmConfigure.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+struct cmIDEFlagTable;
/** \class cmIDEOptions
* \brief Superclass for IDE option processing
@@ -27,9 +23,17 @@ public:
// Store definitions and flags.
void AddDefine(const std::string& define);
void AddDefines(const char* defines);
- void AddDefines(const std::vector<std::string> &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 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);
+ bool HasFlag(std::string const& flag) const;
const char* GetFlag(const char* flag);
protected:
@@ -40,22 +44,51 @@ protected:
// Then parse the command line flags specified in CMAKE_CXX_FLAGS
// and CMAKE_C_FLAGS
// and overwrite or add new values to this map
- std::map<cmStdString, cmStdString> FlagMap;
+ class FlagValue : public std::vector<std::string>
+ {
+ typedef std::vector<std::string> derived;
+
+ public:
+ FlagValue& operator=(std::string const& r)
+ {
+ this->resize(1);
+ this->operator[](0) = r;
+ return *this;
+ }
+ FlagValue& operator=(std::vector<std::string> const& r)
+ {
+ this->derived::operator=(r);
+ return *this;
+ }
+ FlagValue& append_with_space(std::string const& r)
+ {
+ this->resize(1);
+ std::string& l = this->operator[](0);
+ if (!l.empty()) {
+ l += " ";
+ }
+ l += r;
+ return *this;
+ }
+ };
+ std::map<std::string, FlagValue> FlagMap;
// Preprocessor definitions.
std::vector<std::string> Defines;
- // Unrecognized flags that get no special handling.
- cmStdString FlagString;
-
bool DoingDefine;
bool AllowDefine;
bool AllowSlash;
- enum { FlagTableCount = 16 };
+ cmIDEFlagTable const* DoingFollowing;
+ enum
+ {
+ FlagTableCount = 16
+ };
cmIDEFlagTable const* FlagTable[FlagTableCount];
void HandleFlag(const char* flag);
bool CheckFlagTable(cmIDEFlagTable const* table, const char* flag,
bool& flag_handled);
+ void FlagMapUpdate(cmIDEFlagTable const* entry, const char* new_value);
virtual void StoreUnknownFlag(const char* flag) = 0;
};
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 57cec5bbb..0972664a2 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -1,157 +1,158 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIfCommand.h"
-#include "cmStringCommand.h"
-
-#include <stdlib.h> // required for atof
-#include <list>
-#include <cmsys/RegularExpression.hxx>
+#include "cmConditionEvaluator.h"
+#include "cmExecutionStatus.h"
+#include "cmExpandedCommandArgument.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
static std::string cmIfCommandError(
- cmMakefile* mf, std::vector<std::string> const& args)
+ std::vector<cmExpandedCommandArgument> const& args)
{
- cmLocalGenerator* lg = mf->GetLocalGenerator();
std::string err = "given arguments:\n ";
- for(std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
+ for (std::vector<cmExpandedCommandArgument>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
err += " ";
- err += lg->EscapeForCMake(i->c_str());
- }
+ err += cmOutputConverter::EscapeForCMake(i->GetValue());
+ }
err += "\n";
return err;
}
//=========================================================================
-bool cmIfFunctionBlocker::
-IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile &mf,
- cmExecutionStatus &inStatus)
+bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
+ cmMakefile& mf,
+ cmExecutionStatus& inStatus)
{
// we start by recording all the functions
- if (!cmSystemTools::Strucmp(lff.Name.c_str(),"if"))
- {
+ if (!cmSystemTools::Strucmp(lff.Name.c_str(), "if")) {
this->ScopeDepth++;
- }
- if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif"))
- {
+ } 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)
- {
+ if (!this->ScopeDepth) {
// Remove the function blocker for this scope or bail.
- cmsys::auto_ptr<cmFunctionBlocker>
- fb(mf.RemoveFunctionBlocker(this, lff));
- if(!fb.get()) { return false; }
+ CM_AUTO_PTR<cmFunctionBlocker> fb(mf.RemoveFunctionBlocker(this, lff));
+ if (!fb.get()) {
+ return false;
+ }
// 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)
- {
+ 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"))
- {
+ if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(), "if")) {
scopeDepth++;
- }
- if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"endif"))
- {
+ }
+ if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),
+ "endif")) {
scopeDepth--;
- }
+ }
// watch for our state change
if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"else"))
- {
+ !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;
// if trace is enabled, print a (trivially) evaluated "else"
// statement
- if(!this->IsBlocking && mf.GetCMakeInstance()->GetTrace())
- {
+ 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->HasRun)
- {
- this->IsBlocking = true;
- }
- else
- {
- // Place this call on the call stack.
- cmMakefileCall stack_manager(&mf, this->Functions[c], status);
- static_cast<void>(stack_manager);
+ } 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);
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ if (this->HasRun) {
+ this->IsBlocking = true;
+ } else {
// if trace is enabled, print the evaluated "elseif" statement
- if(mf.GetCMakeInstance()->GetTrace())
- {
+ if (mf.GetCMakeInstance()->GetTrace()) {
mf.PrintCommandTrace(this->Functions[c]);
- }
+ }
std::string errorString;
- std::vector<std::string> expandedArguments;
+ std::vector<cmExpandedCommandArgument> expandedArguments;
mf.ExpandArguments(this->Functions[c].Arguments,
expandedArguments);
cmake::MessageType messType;
- bool isTrue =
- cmIfCommand::IsTrue(expandedArguments, errorString,
- &mf, messType);
- if (errorString.size())
- {
- std::string err = cmIfCommandError(&mf, expandedArguments);
+ 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;
- mf.IssueMessage(messType, err);
- if (messType == cmake::FATAL_ERROR)
- {
+ cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]);
+ mf.GetCMakeInstance()->IssueMessage(messType, err, bt);
+ if (messType == cmake::FATAL_ERROR) {
cmSystemTools::SetFatalErrorOccured();
return true;
- }
}
+ }
- if (isTrue)
- {
+ if (isTrue) {
this->IsBlocking = false;
this->HasRun = true;
- }
}
}
+ }
// should we execute?
- else if (!this->IsBlocking)
- {
+ else if (!this->IsBlocking) {
status.Clear();
- mf.ExecuteCommand(this->Functions[c],status);
- if (status.GetReturnInvoked())
- {
- inStatus.SetReturnInvoked(true);
+ mf.ExecuteCommand(this->Functions[c], status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
return true;
- }
- if (status.GetBreakInvoked())
- {
- inStatus.SetBreakInvoked(true);
+ }
+ if (status.GetBreakInvoked()) {
+ inStatus.SetBreakInvoked();
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ inStatus.SetContinueInvoked();
return true;
- }
}
}
- return true;
}
+ return true;
}
+ }
// record the command
this->Functions.push_back(lff);
@@ -164,756 +165,55 @@ IsFunctionBlocked(const cmListFileFunction& lff,
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif"))
- {
+ 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.size() == 0 ||
- lff.Arguments == this->Args)
- {
+ if (lff.Arguments.empty() || lff.Arguments == this->Args) {
return true;
- }
}
+ }
return false;
}
//=========================================================================
-bool cmIfCommand
-::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &)
+bool cmIfCommand::InvokeInitialPass(
+ const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
{
std::string errorString;
- std::vector<std::string> expandedArguments;
+ std::vector<cmExpandedCommandArgument> expandedArguments;
this->Makefile->ExpandArguments(args, expandedArguments);
cmake::MessageType status;
+
+ cmConditionEvaluator conditionEvaluator(
+ *(this->Makefile), this->Makefile->GetExecutionContext(),
+ this->Makefile->GetBacktrace());
+
bool isTrue =
- cmIfCommand::IsTrue(expandedArguments,errorString,
- this->Makefile, status);
+ conditionEvaluator.IsTrue(expandedArguments, errorString, status);
- if (errorString.size())
- {
- std::string err = cmIfCommandError(this->Makefile, expandedArguments);
+ if (!errorString.empty()) {
+ std::string err = "if " + cmIfCommandError(expandedArguments);
err += errorString;
- if (status == cmake::FATAL_ERROR)
- {
- this->SetError(err.c_str());
+ if (status == cmake::FATAL_ERROR) {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, err);
cmSystemTools::SetFatalErrorOccured();
- return false;
- }
- else
- {
- this->Makefile->IssueMessage(status, err);
- }
+ return true;
}
+ this->Makefile->IssueMessage(status, err);
+ }
- cmIfFunctionBlocker *f = new cmIfFunctionBlocker();
+ cmIfFunctionBlocker* f = new cmIfFunctionBlocker();
// if is isn't true block the commands
f->ScopeDepth = 1;
f->IsBlocking = !isTrue;
- if (isTrue)
- {
+ if (isTrue) {
f->HasRun = true;
- }
+ }
f->Args = args;
this->Makefile->AddFunctionBlocker(f);
return true;
}
-
-namespace
-{
- //=========================================================================
- bool GetBooleanValue(std::string& arg, cmMakefile* mf)
- {
- // Check basic constants.
- if (arg == "0")
- {
- return false;
- }
- if (arg == "1")
- {
- return true;
- }
-
- // Check named constants.
- if (cmSystemTools::IsOn(arg.c_str()))
- {
- return true;
- }
- if (cmSystemTools::IsOff(arg.c_str()))
- {
- return false;
- }
-
- // Check for numbers.
- if(!arg.empty())
- {
- char* end;
- double d = strtod(arg.c_str(), &end);
- if(*end == '\0')
- {
- // The whole string is a number. Use C conversion to bool.
- return d? true:false;
- }
- }
-
- // Check definition.
- const char* def = mf->GetDefinition(arg.c_str());
- return !cmSystemTools::IsOff(def);
- }
-
- //=========================================================================
- // Boolean value behavior from CMake 2.6.4 and below.
- bool GetBooleanValueOld(std::string const& arg, cmMakefile* mf, bool one)
- {
- if(one)
- {
- // Old IsTrue behavior for single argument.
- if(arg == "0")
- { return false; }
- else if(arg == "1")
- { return true; }
- else
- { return !cmSystemTools::IsOff(mf->GetDefinition(arg.c_str())); }
- }
- else
- {
- // Old GetVariableOrNumber behavior.
- const char* def = mf->GetDefinition(arg.c_str());
- if(!def && atoi(arg.c_str()))
- {
- def = arg.c_str();
- }
- return !cmSystemTools::IsOff(def);
- }
- }
-
- //=========================================================================
- // returns the resulting boolean value
- bool GetBooleanValueWithAutoDereference(
- std::string &newArg,
- cmMakefile *makefile,
- std::string &errorString,
- cmPolicies::PolicyStatus Policy12Status,
- cmake::MessageType &status,
- bool oneArg = false)
- {
- // Use the policy if it is set.
- if (Policy12Status == cmPolicies::NEW)
- {
- return GetBooleanValue(newArg, makefile);
- }
- else if (Policy12Status == cmPolicies::OLD)
- {
- return GetBooleanValueOld(newArg, makefile, oneArg);
- }
-
- // Check policy only if old and new results differ.
- bool newResult = GetBooleanValue(newArg, makefile);
- bool oldResult = GetBooleanValueOld(newArg, makefile, oneArg);
- if(newResult != oldResult)
- {
- switch(Policy12Status)
- {
- case cmPolicies::WARN:
- {
- cmPolicies* policies = makefile->GetPolicies();
- errorString = "An argument named \"" + newArg
- + "\" appears in a conditional statement. "
- + policies->GetPolicyWarning(cmPolicies::CMP0012);
- status = cmake::AUTHOR_WARNING;
- }
- case cmPolicies::OLD:
- return oldResult;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- {
- cmPolicies* policies = makefile->GetPolicies();
- errorString = "An argument named \"" + newArg
- + "\" appears in a conditional statement. "
- + policies->GetRequiredPolicyError(cmPolicies::CMP0012);
- status = cmake::FATAL_ERROR;
- }
- case cmPolicies::NEW:
- break;
- }
- }
- return newResult;
- }
-
- //=========================================================================
- void IncrementArguments(std::list<std::string> &newArgs,
- std::list<std::string>::iterator &argP1,
- std::list<std::string>::iterator &argP2)
- {
- if (argP1 != newArgs.end())
- {
- argP1++;
- argP2 = argP1;
- if (argP1 != newArgs.end())
- {
- argP2++;
- }
- }
- }
-
- //=========================================================================
- // helper function to reduce code duplication
- void HandlePredicate(bool value, int &reducible,
- std::list<std::string>::iterator &arg,
- std::list<std::string> &newArgs,
- std::list<std::string>::iterator &argP1,
- std::list<std::string>::iterator &argP2)
- {
- if(value)
- {
- *arg = "1";
- }
- else
- {
- *arg = "0";
- }
- newArgs.erase(argP1);
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- reducible = 1;
- }
-
- //=========================================================================
- // helper function to reduce code duplication
- void HandleBinaryOp(bool value, int &reducible,
- std::list<std::string>::iterator &arg,
- std::list<std::string> &newArgs,
- std::list<std::string>::iterator &argP1,
- std::list<std::string>::iterator &argP2)
- {
- if(value)
- {
- *arg = "1";
- }
- else
- {
- *arg = "0";
- }
- newArgs.erase(argP2);
- newArgs.erase(argP1);
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- reducible = 1;
- }
-
- //=========================================================================
- // level 0 processes parenthetical expressions
- bool HandleLevel0(std::list<std::string> &newArgs,
- cmMakefile *makefile,
- std::string &errorString,
- cmake::MessageType &status)
- {
- int reducible;
- do
- {
- reducible = 0;
- std::list<std::string>::iterator arg = newArgs.begin();
- while (arg != newArgs.end())
- {
- if (*arg == "(")
- {
- // search for the closing paren for this opening one
- std::list<std::string>::iterator argClose;
- argClose = arg;
- argClose++;
- unsigned int depth = 1;
- while (argClose != newArgs.end() && depth)
- {
- if (*argClose == "(")
- {
- depth++;
- }
- if (*argClose == ")")
- {
- depth--;
- }
- argClose++;
- }
- if (depth)
- {
- errorString = "mismatched parenthesis in condition";
- status = cmake::FATAL_ERROR;
- return false;
- }
- // store the reduced args in this vector
- std::vector<std::string> newArgs2;
-
- // copy to the list structure
- std::list<std::string>::iterator argP1 = arg;
- argP1++;
- for(; argP1 != argClose; argP1++)
- {
- newArgs2.push_back(*argP1);
- }
- newArgs2.pop_back();
- // now recursively invoke IsTrue to handle the values inside the
- // parenthetical expression
- bool value =
- cmIfCommand::IsTrue(newArgs2, errorString, makefile, status);
- if(value)
- {
- *arg = "1";
- }
- else
- {
- *arg = "0";
- }
- argP1 = arg;
- argP1++;
- // remove the now evaluated parenthetical expression
- newArgs.erase(argP1,argClose);
- }
- ++arg;
- }
- }
- while (reducible);
- return true;
- }
-
- //=========================================================================
- // level one handles most predicates except for NOT
- bool HandleLevel1(std::list<std::string> &newArgs,
- cmMakefile *makefile,
- std::string &, cmake::MessageType &)
- {
- int reducible;
- do
- {
- reducible = 0;
- std::list<std::string>::iterator arg = newArgs.begin();
- std::list<std::string>::iterator argP1;
- std::list<std::string>::iterator argP2;
- while (arg != newArgs.end())
- {
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- // does a file exist
- if (*arg == "EXISTS" && argP1 != newArgs.end())
- {
- HandlePredicate(
- cmSystemTools::FileExists((argP1)->c_str()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a directory with this name exist
- if (*arg == "IS_DIRECTORY" && argP1 != newArgs.end())
- {
- HandlePredicate(
- cmSystemTools::FileIsDirectory((argP1)->c_str()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a symlink with this name exist
- if (*arg == "IS_SYMLINK" && argP1 != newArgs.end())
- {
- HandlePredicate(
- cmSystemTools::FileIsSymlink((argP1)->c_str()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // is the given path an absolute path ?
- if (*arg == "IS_ABSOLUTE" && argP1 != newArgs.end())
- {
- HandlePredicate(
- cmSystemTools::FileIsFullPath((argP1)->c_str()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a command exist
- if (*arg == "COMMAND" && argP1 != newArgs.end())
- {
- HandlePredicate(
- makefile->CommandExists((argP1)->c_str()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a policy exist
- if (*arg == "POLICY" && argP1 != newArgs.end())
- {
- cmPolicies::PolicyID pid;
- HandlePredicate(
- makefile->GetPolicies()->GetPolicyID((argP1)->c_str(), pid),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a target exist
- if (*arg == "TARGET" && argP1 != newArgs.end())
- {
- HandlePredicate(
- makefile->FindTargetToUse((argP1)->c_str())? true:false,
- reducible, arg, newArgs, argP1, argP2);
- }
- // is a variable defined
- if (*arg == "DEFINED" && argP1 != newArgs.end())
- {
- size_t argP1len = argP1->size();
- bool bdef = false;
- if(argP1len > 4 && argP1->substr(0, 4) == "ENV{" &&
- argP1->operator[](argP1len-1) == '}')
- {
- std::string env = argP1->substr(4, argP1len-5);
- bdef = cmSystemTools::GetEnv(env.c_str())?true:false;
- }
- else
- {
- bdef = makefile->IsDefinitionSet((argP1)->c_str());
- }
- HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
- }
- ++arg;
- }
- }
- while (reducible);
- return true;
- }
-
- //=========================================================================
- // level two handles most binary operations except for AND OR
- bool HandleLevel2(std::list<std::string> &newArgs,
- cmMakefile *makefile,
- std::string &errorString,
- cmake::MessageType &status)
- {
- int reducible;
- const char *def;
- const char *def2;
- do
- {
- reducible = 0;
- std::list<std::string>::iterator arg = newArgs.begin();
- std::list<std::string>::iterator argP1;
- std::list<std::string>::iterator argP2;
- while (arg != newArgs.end())
- {
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- *(argP1) == "MATCHES")
- {
- def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
- const char* rex = (argP2)->c_str();
- cmStringCommand::ClearMatches(makefile);
- cmsys::RegularExpression regEntry;
- if ( !regEntry.compile(rex) )
- {
- cmOStringStream error;
- error << "Regular expression \"" << rex << "\" cannot compile";
- errorString = error.str();
- status = cmake::FATAL_ERROR;
- return false;
- }
- if (regEntry.find(def))
- {
- cmStringCommand::StoreMatches(makefile, regEntry);
- *arg = "1";
- }
- else
- {
- *arg = "0";
- }
- newArgs.erase(argP2);
- newArgs.erase(argP1);
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- reducible = 1;
- }
-
- if (argP1 != newArgs.end() && *arg == "MATCHES")
- {
- *arg = "0";
- newArgs.erase(argP1);
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- reducible = 1;
- }
-
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (*(argP1) == "LESS" || *(argP1) == "GREATER" ||
- *(argP1) == "EQUAL"))
- {
- def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
- def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
- double lhs;
- double rhs;
- bool result;
- if(sscanf(def, "%lg", &lhs) != 1 ||
- sscanf(def2, "%lg", &rhs) != 1)
- {
- result = false;
- }
- else if (*(argP1) == "LESS")
- {
- result = (lhs < rhs);
- }
- else if (*(argP1) == "GREATER")
- {
- result = (lhs > rhs);
- }
- else
- {
- result = (lhs == rhs);
- }
- HandleBinaryOp(result,
- reducible, arg, newArgs, argP1, argP2);
- }
-
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (*(argP1) == "STRLESS" ||
- *(argP1) == "STREQUAL" ||
- *(argP1) == "STRGREATER"))
- {
- def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
- def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
- int val = strcmp(def,def2);
- bool result;
- if (*(argP1) == "STRLESS")
- {
- result = (val < 0);
- }
- else if (*(argP1) == "STRGREATER")
- {
- result = (val > 0);
- }
- else // strequal
- {
- result = (val == 0);
- }
- HandleBinaryOp(result,
- reducible, arg, newArgs, argP1, argP2);
- }
-
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (*(argP1) == "VERSION_LESS" || *(argP1) == "VERSION_GREATER" ||
- *(argP1) == "VERSION_EQUAL"))
- {
- def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
- def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
- cmSystemTools::CompareOp op = cmSystemTools::OP_EQUAL;
- if(*argP1 == "VERSION_LESS")
- {
- op = cmSystemTools::OP_LESS;
- }
- else if(*argP1 == "VERSION_GREATER")
- {
- op = cmSystemTools::OP_GREATER;
- }
- bool result = cmSystemTools::VersionCompare(op, def, def2);
- HandleBinaryOp(result,
- reducible, arg, newArgs, argP1, argP2);
- }
-
- // is file A newer than file B
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- *(argP1) == "IS_NEWER_THAN")
- {
- int fileIsNewer=0;
- bool success=cmSystemTools::FileTimeCompare(arg->c_str(),
- (argP2)->c_str(),
- &fileIsNewer);
- HandleBinaryOp(
- (success==false || fileIsNewer==1 || fileIsNewer==0),
- reducible, arg, newArgs, argP1, argP2);
- }
-
- ++arg;
- }
- }
- while (reducible);
- return true;
- }
-
- //=========================================================================
- // level 3 handles NOT
- bool HandleLevel3(std::list<std::string> &newArgs,
- cmMakefile *makefile,
- std::string &errorString,
- cmPolicies::PolicyStatus Policy12Status,
- cmake::MessageType &status)
- {
- int reducible;
- do
- {
- reducible = 0;
- std::list<std::string>::iterator arg = newArgs.begin();
- std::list<std::string>::iterator argP1;
- std::list<std::string>::iterator argP2;
- while (arg != newArgs.end())
- {
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- if (argP1 != newArgs.end() && *arg == "NOT")
- {
- bool rhs = GetBooleanValueWithAutoDereference(*argP1, makefile,
- errorString,
- Policy12Status,
- status);
- HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
- }
- ++arg;
- }
- }
- while (reducible);
- return true;
- }
-
- //=========================================================================
- // level 4 handles AND OR
- bool HandleLevel4(std::list<std::string> &newArgs,
- cmMakefile *makefile,
- std::string &errorString,
- cmPolicies::PolicyStatus Policy12Status,
- cmake::MessageType &status)
- {
- int reducible;
- bool lhs;
- bool rhs;
- do
- {
- reducible = 0;
- std::list<std::string>::iterator arg = newArgs.begin();
- std::list<std::string>::iterator argP1;
- std::list<std::string>::iterator argP2;
- while (arg != newArgs.end())
- {
- argP1 = arg;
- IncrementArguments(newArgs,argP1,argP2);
- if (argP1 != newArgs.end() && *(argP1) == "AND" &&
- argP2 != newArgs.end())
- {
- lhs = GetBooleanValueWithAutoDereference(*arg, makefile,
- errorString,
- Policy12Status,
- status);
- rhs = GetBooleanValueWithAutoDereference(*argP2, makefile,
- errorString,
- Policy12Status,
- status);
- HandleBinaryOp((lhs && rhs),
- reducible, arg, newArgs, argP1, argP2);
- }
-
- if (argP1 != newArgs.end() && *(argP1) == "OR" &&
- argP2 != newArgs.end())
- {
- lhs = GetBooleanValueWithAutoDereference(*arg, makefile,
- errorString,
- Policy12Status,
- status);
- rhs = GetBooleanValueWithAutoDereference(*argP2, makefile,
- errorString,
- Policy12Status,
- status);
- HandleBinaryOp((lhs || rhs),
- reducible, arg, newArgs, argP1, argP2);
- }
- ++arg;
- }
- }
- while (reducible);
- return true;
- }
-}
-
-
-//=========================================================================
-// order of operations,
-// 1. ( ) -- parenthetical groups
-// 2. IS_DIRECTORY EXISTS COMMAND DEFINED etc predicates
-// 3. MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL etc binary ops
-// 4. NOT
-// 5. AND OR
-//
-// There is an issue on whether the arguments should be values of references,
-// for example IF (FOO AND BAR) should that compare the strings FOO and BAR
-// or should it really do IF (${FOO} AND ${BAR}) Currently IS_DIRECTORY
-// EXISTS COMMAND and DEFINED all take values. EQUAL, LESS and GREATER can
-// take numeric values or variable names. STRLESS and STRGREATER take
-// variable names but if the variable name is not found it will use the name
-// directly. AND OR take variables or the values 0 or 1.
-
-
-bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
- std::string &errorString, cmMakefile *makefile,
- cmake::MessageType &status)
-{
- errorString = "";
-
- // handle empty invocation
- if (args.size() < 1)
- {
- return false;
- }
-
- // store the reduced args in this vector
- std::list<std::string> newArgs;
-
- // copy to the list structure
- for(unsigned int i = 0; i < args.size(); ++i)
- {
- newArgs.push_back(args[i]);
- }
-
- // 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
- // parens
- if (!HandleLevel0(newArgs, makefile, errorString, status))
- {
- return false;
- }
- //predicates
- if (!HandleLevel1(newArgs, makefile, errorString, status))
- {
- return false;
- }
- // binary ops
- if (!HandleLevel2(newArgs, makefile, errorString, status))
- {
- return false;
- }
-
- // used to store the value of policy CMP0012 for performance
- cmPolicies::PolicyStatus Policy12Status =
- makefile->GetPolicyStatus(cmPolicies::CMP0012);
-
- // NOT
- if (!HandleLevel3(newArgs, makefile, errorString,
- Policy12Status, status))
- {
- return false;
- }
- // AND OR
- if (!HandleLevel4(newArgs, makefile, errorString,
- Policy12Status, status))
- {
- return false;
- }
-
- // now at the end there should only be one argument left
- if (newArgs.size() != 1)
- {
- errorString = "Unknown arguments specified";
- status = cmake::FATAL_ERROR;
- return false;
- }
-
- return GetBooleanValueWithAutoDereference(*(newArgs.begin()),
- makefile,
- errorString,
- Policy12Status,
- status, true);
-}
-
-//=========================================================================
-const char* cmIfCommand::GetVariableOrString(const char* str,
- const cmMakefile* mf)
-{
- const char* def = mf->GetDefinition(str);
- if(!def)
- {
- def = str;
- }
- return def;
-}
diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h
index f794b78b8..5877a7d12 100644
--- a/Source/cmIfCommand.h
+++ b/Source/cmIfCommand.h
@@ -1,36 +1,40 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIfCommand_h
#define cmIfCommand_h
+#include "cmConfigure.h"
+
+#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->ScopeDepth = 0; }
- virtual ~cmIfFunctionBlocker() {}
- virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile &mf,
- cmExecutionStatus &);
- virtual bool ShouldRemove(const cmListFileFunction& lff,
- cmMakefile &mf);
+ 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;
};
@@ -41,226 +45,28 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmIfCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmIfCommand; }
/**
* This overrides the default InvokeInitialPass implementation.
* It records the arguments before expansion.
*/
- virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &);
+ bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus&) CM_OVERRIDE;
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) { return false;};
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "if";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Conditionally execute a group of commands.";
- }
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " if(expression)\n"
- " # then section.\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " elseif(expression2)\n"
- " # elseif section.\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " else(expression)\n"
- " # else section.\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " endif(expression)\n"
- "Evaluates the given expression. If the result is true, the commands "
- "in the THEN section are invoked. Otherwise, the commands in the "
- "else section are invoked. The elseif and else sections are "
- "optional. You may have multiple elseif clauses. Note that "
- "the expression in the else and endif clause is optional. Long "
- "expressions can be used and there is a traditional order of "
- "precedence. "
- "Parenthetical expressions are evaluated first followed by unary "
- "operators such as EXISTS, COMMAND, and DEFINED. "
- "Then any EQUAL, LESS, GREATER, STRLESS, STRGREATER, STREQUAL, MATCHES "
- "will be evaluated. Then NOT operators and finally AND, OR operators "
- "will be evaluated. Possible expressions are:\n"
- " if(<constant>)\n"
- "True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. "
- "False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, '', "
- "or ends in the suffix '-NOTFOUND'. "
- "Named boolean constants are case-insensitive. "
- "If the argument is not one of these constants, "
- "it is treated as a variable:"
- "\n"
- " if(<variable>)\n"
- "True if the variable is defined to a value that is not a false "
- "constant. False otherwise. "
- "(Note macro arguments are not variables.)"
- "\n"
- " if(NOT <expression>)\n"
- "True if the expression is not true."
- "\n"
- " if(<expr1> AND <expr2>)\n"
- "True if both expressions would be considered true individually."
- "\n"
- " if(<expr1> OR <expr2>)\n"
- "True if either expression would be considered true individually."
- "\n"
- " if(COMMAND command-name)\n"
- "True if the given name is a command, macro or function that can be "
- "invoked.\n"
- " if(POLICY policy-id)\n"
- "True if the given name is an existing policy "
- "(of the form CMP<NNNN>).\n"
- " if(TARGET target-name)\n"
- "True if the given name is an existing target, built or imported.\n"
- " if(EXISTS file-name)\n"
- " if(EXISTS directory-name)\n"
- "True if the named file or directory exists. "
- "Behavior is well-defined only for full paths.\n"
- " if(file1 IS_NEWER_THAN file2)\n"
- "True if file1 is newer than file2 or if one of the two files "
- "doesn't exist. "
- "Behavior is well-defined only for full paths. "
- "If the file time stamps are exactly the same, an "
- "IS_NEWER_THAN comparison returns true, so that any dependent "
- "build operations will occur in the event of a tie. "
- "This includes the case of passing the same file name for both "
- "file1 and file2.\n"
- " if(IS_DIRECTORY directory-name)\n"
- "True if the given name is a directory. "
- "Behavior is well-defined only for full paths.\n"
- " if(IS_SYMLINK file-name)\n"
- "True if the given name is a symbolic link. "
- "Behavior is well-defined only for full paths.\n"
- " if(IS_ABSOLUTE path)\n"
- "True if the given path is an absolute path.\n"
- " if(<variable|string> MATCHES regex)\n"
- "True if the given string or variable's value matches the given "
- "regular expression.\n"
- " if(<variable|string> LESS <variable|string>)\n"
- " if(<variable|string> GREATER <variable|string>)\n"
- " if(<variable|string> EQUAL <variable|string>)\n"
- "True if the given string or variable's value is a valid number and "
- "the inequality or equality is true.\n"
- " if(<variable|string> STRLESS <variable|string>)\n"
- " if(<variable|string> STRGREATER <variable|string>)\n"
- " if(<variable|string> STREQUAL <variable|string>)\n"
- "True if the given string or variable's value is lexicographically "
- "less (or greater, or equal) than the string or variable on the right.\n"
- " if(<variable|string> VERSION_LESS <variable|string>)\n"
- " if(<variable|string> VERSION_EQUAL <variable|string>)\n"
- " if(<variable|string> VERSION_GREATER <variable|string>)\n"
- "Component-wise integer version number comparison (version format is "
- "major[.minor[.patch[.tweak]]]).\n"
- " if(DEFINED <variable>)\n"
- "True if the given variable is defined. It does not matter if the "
- "variable is true or false just if it has been set.\n"
- " if((expression) AND (expression OR (expression)))\n"
- "The expressions inside the parenthesis are evaluated first and "
- "then the remaining expression is evaluated as in the previous "
- "examples. Where there are nested parenthesis the innermost are "
- "evaluated as part of evaluating the expression "
- "that contains them."
- "\n"
-
- "The if command was written very early in CMake's history, predating "
- "the ${} variable evaluation syntax, and for convenience evaluates "
- "variables named by its arguments as shown in the above signatures. "
- "Note that normal variable evaluation with ${} applies before the "
- "if command even receives the arguments. "
- "Therefore code like\n"
- " set(var1 OFF)\n"
- " set(var2 \"var1\")\n"
- " if(${var2})\n"
- "appears to the if command as\n"
- " if(var1)\n"
- "and is evaluated according to the if(<variable>) case "
- "documented above. "
- "The result is OFF which is false. "
- "However, if we remove the ${} from the example then the command sees\n"
- " if(var2)\n"
- "which is true because var2 is defined to \"var1\" which is not "
- "a false constant."
- "\n"
- "Automatic evaluation applies in the other cases whenever the "
- "above-documented signature accepts <variable|string>:\n"
-
- "1) The left hand argument to MATCHES is first checked to see "
- "if it is a defined variable, if so the variable's value is "
- "used, otherwise the original value is used. \n"
-
- "2) If the left hand argument to MATCHES is missing it returns "
- "false without error \n"
-
- "3) Both left and right hand arguments to LESS GREATER EQUAL "
- "are independently tested to see if they are defined variables, "
- "if so their defined values are used otherwise the original "
- "value is used. \n"
-
- "4) Both left and right hand arguments to STRLESS STREQUAL "
- "STRGREATER are independently tested to see if they are defined "
- "variables, if so their defined values are used otherwise the "
- "original value is used. \n"
-
- "5) Both left and right hand argumemnts to VERSION_LESS "
- "VERSION_EQUAL VERSION_GREATER are independently tested to see "
- "if they are defined variables, if so their defined values are "
- "used otherwise the original value is used. \n"
-
- "6) The right hand argument to NOT is tested to see if it is a "
- "boolean constant, if so the value is used, otherwise it is "
- "assumed to be a variable and it is dereferenced. \n"
-
- "7) The left and right hand arguments to AND OR are "
- "independently tested to see if they are boolean constants, if "
- "so they are used as such, otherwise they are assumed to be "
- "variables and are dereferenced. \n"
- ;
- }
-
- // 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.
- static bool IsTrue(const std::vector<std::string> &args,
- std::string &errorString, cmMakefile *mf,
- cmake::MessageType &status);
-
- // Get a definition from the makefile. If it doesn't exist,
- // return the original string.
- static const char* GetVariableOrString(const char* str,
- const cmMakefile* mf);
-
- cmTypeMacro(cmIfCommand, cmCommand);
+ 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);
};
-
#endif
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index bb891d6fc..12e0c9ab3 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -1,116 +1,139 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmIncludeCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmIncludeCommand.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+class cmExecutionStatus;
// cmIncludeCommand
-bool cmIncludeCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if (args.size()< 1 || args.size() > 4)
- {
- this->SetError("called with wrong number of arguments. "
- "Include only takes one file.");
- return false;
- }
+ if (args.empty() || args.size() > 4) {
+ this->SetError("called with wrong number of arguments. "
+ "include() only takes one file.");
+ return false;
+ }
bool optional = false;
bool noPolicyScope = false;
std::string fname = args[0];
std::string resultVarName;
- for (unsigned int i=1; i<args.size(); i++)
- {
- if (args[i] == "OPTIONAL")
- {
- if (optional)
- {
+ for (unsigned int i = 1; i < args.size(); i++) {
+ if (args[i] == "OPTIONAL") {
+ if (optional) {
this->SetError("called with invalid arguments: OPTIONAL used twice");
return false;
- }
- optional = true;
}
- else if(args[i] == "RESULT_VARIABLE")
- {
- if (resultVarName.size() > 0)
- {
+ optional = true;
+ } else if (args[i] == "RESULT_VARIABLE") {
+ if (!resultVarName.empty()) {
this->SetError("called with invalid arguments: "
- "only one result variable allowed");
+ "only one result variable allowed");
return false;
- }
- if(++i < args.size())
- {
+ }
+ if (++i < args.size()) {
resultVarName = args[i];
- }
- else
- {
+ } else {
this->SetError("called with no value for RESULT_VARIABLE.");
return false;
- }
}
- else if(args[i] == "NO_POLICY_SCOPE")
- {
+ } else if (args[i] == "NO_POLICY_SCOPE") {
noPolicyScope = true;
- }
- else if(i > 1) // compat.: in previous cmake versions the second
+ } 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.c_str());
- return false;
- }
+ {
+ std::string errorText = "called with invalid argument: ";
+ errorText += args[i];
+ this->SetError(errorText);
+ return false;
}
+ }
- if(fname.empty())
- {
+ if (fname.empty()) {
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
"include() given empty file name (ignored).");
return true;
- }
+ }
- if(!cmSystemTools::FileIsFullPath(fname.c_str()))
- {
+ if (!cmSystemTools::FileIsFullPath(fname.c_str())) {
// Not a path. Maybe module.
std::string module = fname;
module += ".cmake";
std::string mfile = this->Makefile->GetModulesFile(module.c_str());
- if ( mfile.size() )
- {
- fname = mfile.c_str();
+ if (!mfile.empty()) {
+ fname = mfile;
+ }
+ }
+
+ std::string fname_abs = cmSystemTools::CollapseFullPath(
+ fname, this->Makefile->GetCurrentSourceDirectory());
+
+ cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+ if (gg->IsExportedTargetsFile(fname_abs)) {
+ const char* modal = CM_NULLPTR;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0024)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n";
+ modal = "should";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ modal = "may";
+ messageType = cmake::FATAL_ERROR;
+ }
+ if (modal) {
+ 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) {
+ return false;
}
}
- std::string fullFilePath;
+ gg->CreateGenerationObjects();
+ gg->GenerateImportFile(fname_abs);
+ }
+
+ std::string listFile = cmSystemTools::CollapseFullPath(
+ fname, this->Makefile->GetCurrentSourceDirectory());
+ if (optional && !cmSystemTools::FileExists(listFile.c_str())) {
+ if (!resultVarName.empty()) {
+ this->Makefile->AddDefinition(resultVarName, "NOTFOUND");
+ }
+ return true;
+ }
+
bool readit =
- this->Makefile->ReadListFile( this->Makefile->GetCurrentListFile(),
- fname.c_str(), &fullFilePath,
- noPolicyScope);
+ this->Makefile->ReadDependentFile(listFile.c_str(), noPolicyScope);
// add the location of the included file if a result variable was given
- if (resultVarName.size())
- {
- this->Makefile->AddDefinition(resultVarName.c_str(),
- readit?fullFilePath.c_str():"NOTFOUND");
- }
+ if (!resultVarName.empty()) {
+ this->Makefile->AddDefinition(resultVarName,
+ readit ? fname_abs.c_str() : "NOTFOUND");
+ }
- if(!optional && !readit && !cmSystemTools::GetFatalErrorOccured())
- {
- std::string m =
- "could not find load file:\n"
- " ";
+ if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) {
+ std::string m = "could not find load file:\n"
+ " ";
m += fname;
- this->SetError(m.c_str());
+ this->SetError(m);
return false;
- }
+ }
return true;
}
-
-
diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h
index d97b7c3f5..16dda0ef5 100644
--- a/Source/cmIncludeCommand.h
+++ b/Source/cmIncludeCommand.h
@@ -1,23 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIncludeCommand_h
#define cmIncludeCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmIncludeCommand
- * \brief
- *
- * cmIncludeCommand defines a list of distant
+ * \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.
@@ -28,66 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmIncludeCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmIncludeCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "include";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Load and run CMake code from a file or module.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>]\n"
- " [NO_POLICY_SCOPE])\n"
- "Load and run CMake code from the file given. "
- "Variable reads and writes access the scope of the caller "
- "(dynamic scoping). "
- "If OPTIONAL is present, then no error "
- "is raised if the file does not exist. If RESULT_VARIABLE is given "
- "the variable will be set to the full filename which "
- "has been included or NOTFOUND if it failed.\n"
- "If a module is specified instead of a file, the file with name "
- "<modulename>.cmake is searched first in CMAKE_MODULE_PATH, then in the "
- "CMake module directory. There is one exception to this: if the file "
- "which calls include() is located itself in the CMake module directory, "
- "then first the CMake module directory is searched and "
- "CMAKE_MODULE_PATH afterwards. See also policy CMP0017."
- "\n"
- "See the cmake_policy() command documentation for discussion of the "
- "NO_POLICY_SCOPE option."
- ;
- }
-
- cmTypeMacro(cmIncludeCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index 30c174375..b81f7cb2d 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -1,83 +1,65 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmIncludeDirectoryCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <algorithm>
+#include <set>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmIncludeDirectoryCommand.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmIncludeDirectoryCommand
-bool cmIncludeDirectoryCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmIncludeDirectoryCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
std::vector<std::string>::const_iterator i = args.begin();
bool before = this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE");
bool system = false;
- if ((*i) == "BEFORE")
- {
+ if ((*i) == "BEFORE") {
before = true;
++i;
- }
- else if ((*i) == "AFTER")
- {
+ } else if ((*i) == "AFTER") {
before = false;
++i;
- }
+ }
std::vector<std::string> beforeIncludes;
std::vector<std::string> afterIncludes;
- std::set<cmStdString> systemIncludes;
+ std::set<std::string> systemIncludes;
- for(; i != args.end(); ++i)
- {
- if(*i == "SYSTEM")
- {
+ for (; i != args.end(); ++i) {
+ if (*i == "SYSTEM") {
system = true;
continue;
- }
- if(i->size() == 0)
- {
+ }
+ if (i->empty()) {
this->SetError("given empty-string as include directory.");
return false;
- }
+ }
std::vector<std::string> includes;
- GetIncludes(*i, includes);
+ this->GetIncludes(*i, includes);
- if (before)
- {
- beforeIncludes.insert(beforeIncludes.end(),
- includes.begin(),
+ if (before) {
+ beforeIncludes.insert(beforeIncludes.end(), includes.begin(),
includes.end());
- }
- else
- {
- afterIncludes.insert(afterIncludes.end(),
- includes.begin(),
+ } else {
+ afterIncludes.insert(afterIncludes.end(), includes.begin(),
includes.end());
- }
- if (system)
- {
- for (std::vector<std::string>::const_iterator li = includes.begin();
- li != includes.end(); ++li)
- {
- systemIncludes.insert(*li);
- }
- }
}
+ if (system) {
+ systemIncludes.insert(includes.begin(), includes.end());
+ }
+ }
std::reverse(beforeIncludes.begin(), beforeIncludes.end());
this->Makefile->AddIncludeDirectories(afterIncludes);
@@ -87,7 +69,7 @@ bool cmIncludeDirectoryCommand
return true;
}
-static bool StartsWithGeneratorExpression(const std::string &input)
+static bool StartsWithGeneratorExpression(const std::string& input)
{
return input[0] == '$' && input[1] == '<';
}
@@ -104,60 +86,50 @@ 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)
+void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg,
+ std::vector<std::string>& incs)
{
// break apart any line feed arguments
std::string::size_type pos = 0;
std::string::size_type lastPos = 0;
- while((pos = arg.find('\n', lastPos)) != std::string::npos)
- {
- if (pos)
- {
- std::string inc = arg.substr(lastPos,pos);
+ while ((pos = arg.find('\n', lastPos)) != std::string::npos) {
+ if (pos) {
+ std::string inc = arg.substr(lastPos, pos);
this->NormalizeInclude(inc);
- if (!inc.empty())
- {
+ if (!inc.empty()) {
incs.push_back(inc);
- }
}
- lastPos = pos + 1;
}
+ lastPos = pos + 1;
+ }
std::string inc = arg.substr(lastPos);
this->NormalizeInclude(inc);
- if (!inc.empty())
- {
+ if (!inc.empty()) {
incs.push_back(inc);
- }
+ }
}
-void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc)
+void cmIncludeDirectoryCommand::NormalizeInclude(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!=inc.npos) && (e!=inc.npos))
- {
- inc.assign(inc, b, 1+e-b); // copy the remaining substring
- }
- else
- {
+ if ((b != std::string::npos) && (e != std::string::npos)) {
+ inc.assign(inc, b, 1 + e - b); // copy the remaining substring
+ } else {
inc = "";
return;
- }
+ }
- if (!cmSystemTools::IsOff(inc.c_str()))
- {
+ if (!cmSystemTools::IsOff(inc.c_str())) {
cmSystemTools::ConvertToUnixSlashes(inc);
- if(!cmSystemTools::FileIsFullPath(inc.c_str()))
- {
- if(!StartsWithGeneratorExpression(inc))
- {
- std::string tmp = this->Makefile->GetStartDirectory();
+ if (!cmSystemTools::FileIsFullPath(inc.c_str())) {
+ if (!StartsWithGeneratorExpression(inc)) {
+ std::string tmp = this->Makefile->GetCurrentSourceDirectory();
tmp += "/";
tmp += inc;
inc = tmp;
- }
}
}
+ }
}
diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h
index 77a340a64..12de698cb 100644
--- a/Source/cmIncludeDirectoryCommand.h
+++ b/Source/cmIncludeDirectoryCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIncludeDirectoryCommand_h
#define cmIncludeDirectoryCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmIncludeDirectoryCommand
* \brief Add include directories to the build.
*
@@ -26,69 +24,19 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmIncludeDirectoryCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmIncludeDirectoryCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "include_directories";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Add include directories to the build.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)\n"
- "Add the given directories to those the compiler uses to search "
- "for include files. Relative paths are interpreted as relative to "
- "the current source directory. \n"
- "The include directories are added to the directory property "
- "INCLUDE_DIRECTORIES for the current CMakeLists file. "
- "They are also added to the target property INCLUDE_DIRECTORIES "
- "for each target in the current CMakeLists file. "
- "The target property values are the ones used by the generators."
- "\n"
- "By default the directories are appended onto the current list of "
- "directories. "
- "This default behavior can be changed by setting "
- "CMAKE_INCLUDE_DIRECTORIES_BEFORE to ON. "
- "By using AFTER or BEFORE explicitly, you can select between "
- "appending and prepending, independent of the default. "
- "\n"
- "If the SYSTEM option is given, the compiler will be told the "
- "directories are meant as system include directories on some "
- "platforms (signalling this setting might achieve effects such as "
- "the compiler skipping warnings, or these fixed-install system files "
- "not being considered in dependency calculations - see compiler docs).";
- }
-
- cmTypeMacro(cmIncludeDirectoryCommand, cmCommand);
+ 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);
+ void GetIncludes(const std::string& arg, std::vector<std::string>& incs);
+ void NormalizeInclude(std::string& inc);
};
-
-
#endif
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index d40d8fe72..03388c7e9 100644
--- a/Source/cmIncludeExternalMSProjectCommand.cxx
+++ b/Source/cmIncludeExternalMSProjectCommand.cxx
@@ -1,31 +1,35 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmIncludeExternalMSProjectCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#ifdef _WIN32
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#endif
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmIncludeExternalMSProjectCommand.h"
+class cmExecutionStatus;
// cmIncludeExternalMSProjectCommand
-bool cmIncludeExternalMSProjectCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmIncludeExternalMSProjectCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2)
- {
- this->SetError("INCLUDE_EXTERNAL_MSPROJECT called with incorrect "
- "number of arguments");
- return false;
+ if (args.size() < 2) {
+ this->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"))
+ if (this->Makefile->GetDefinition("WIN32")) {
+ enum Doing
{
- enum Doing { DoingNone, DoingType, DoingGuid, DoingPlatform };
+ DoingNone,
+ DoingType,
+ DoingGuid,
+ DoingPlatform
+ };
Doing doing = DoingNone;
@@ -34,32 +38,31 @@ bool cmIncludeExternalMSProjectCommand
std::string platformMapping;
std::vector<std::string> depends;
- for (unsigned int i=2; i<args.size(); ++i)
- {
- if (args[i] == "TYPE")
- {
+ for (unsigned int i = 2; i < args.size(); ++i) {
+ if (args[i] == "TYPE") {
doing = DoingType;
- }
- else if (args[i] == "GUID")
- {
+ } else if (args[i] == "GUID") {
doing = DoingGuid;
- }
- else if (args[i] == "PLATFORM")
- {
+ } else if (args[i] == "PLATFORM") {
doing = DoingPlatform;
+ } else {
+ switch (doing) {
+ case DoingNone:
+ depends.push_back(args[i]);
+ break;
+ case DoingType:
+ customType = args[i];
+ break;
+ case DoingGuid:
+ customGuid = args[i];
+ break;
+ case DoingPlatform:
+ platformMapping = args[i];
+ break;
}
- else
- {
- switch (doing)
- {
- case DoingNone: depends.push_back(args[i]); break;
- case DoingType: customType = args[i]; break;
- case DoingGuid: customGuid = args[i]; break;
- case DoingPlatform: platformMapping = args[i]; break;
- }
doing = DoingNone;
- }
}
+ }
// Hack together a utility target storing enough information
// to reproduce the target inclusion.
@@ -68,34 +71,31 @@ bool cmIncludeExternalMSProjectCommand
std::string path = args[1];
cmSystemTools::ConvertToUnixSlashes(path);
- if (!customGuid.empty())
- {
+ if (!customGuid.empty()) {
std::string guidVariable = utility_name + "_GUID_CMAKE";
this->Makefile->GetCMakeInstance()->AddCacheEntry(
- guidVariable.c_str(), customGuid.c_str(),
- "Stored GUID", cmCacheManager::INTERNAL);
- }
+ guidVariable.c_str(), customGuid.c_str(), "Stored GUID",
+ cmStateEnums::INTERNAL);
+ }
// Create a target instance for this utility.
- cmTarget* target=this->Makefile->AddNewTarget(cmTarget::UTILITY,
- utility_name.c_str());
+ cmTarget* target = this->Makefile->AddNewTarget(cmStateEnums::UTILITY,
+ utility_name.c_str());
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());
+ target->SetProperty("VS_PROJECT_TYPE", customType.c_str());
if (!platformMapping.empty())
- target->SetProperty("VS_PLATFORM_MAPPING",platformMapping.c_str());
+ target->SetProperty("VS_PLATFORM_MAPPING", platformMapping.c_str());
for (std::vector<std::string>::const_iterator it = depends.begin();
- it != depends.end();
- ++it)
- {
+ it != depends.end(); ++it) {
target->AddUtility(it->c_str());
- }
}
+ }
#endif
return true;
}
diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h
index d5cec01eb..375646fa6 100644
--- a/Source/cmIncludeExternalMSProjectCommand.h
+++ b/Source/cmIncludeExternalMSProjectCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIncludeExternalMSProjectCommand_h
#define cmIncludeExternalMSProjectCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmIncludeExternalMSProjectCommand
* \brief Specify an external MS project file for inclusion in the workspace.
*
@@ -27,58 +25,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
return new cmIncludeExternalMSProjectCommand;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "include_external_msproject";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Include an external Microsoft project file in a workspace.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " include_external_msproject(projectname location\n"
- " [TYPE projectTypeGUID]\n"
- " [GUID projectGUID]\n"
- " [PLATFORM platformName]\n"
- " dep1 dep2 ...)\n"
- "Includes an external Microsoft project in the generated workspace "
- "file. Currently does nothing on UNIX. This will create a "
- "target named [projectname]. This can be used in the add_dependencies "
- "command to make things depend on the external project."
- "\n"
- "TYPE, GUID and PLATFORM are optional parameters that allow one "
- "to specify the type of project, id (GUID) of the project and "
- "the name of the target platform. "
- "This is useful for projects requiring values other than the default "
- "(e.g. WIX projects). "
- "These options are not supported by the Visual Studio 6 generator.";
- }
-
- cmTypeMacro(cmIncludeExternalMSProjectCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmIncludeRegularExpressionCommand.cxx b/Source/cmIncludeRegularExpressionCommand.cxx
index ef6e8c6ae..073c95f7d 100644
--- a/Source/cmIncludeRegularExpressionCommand.cxx
+++ b/Source/cmIncludeRegularExpressionCommand.cxx
@@ -1,32 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmIncludeRegularExpressionCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmIncludeRegularExpressionCommand.h"
+class cmExecutionStatus;
// cmIncludeRegularExpressionCommand
-bool cmIncludeRegularExpressionCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmIncludeRegularExpressionCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if((args.size() < 1) || (args.size() > 2))
- {
+ if ((args.empty()) || (args.size() > 2)) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
this->Makefile->SetIncludeRegularExpression(args[0].c_str());
- if(args.size() > 1)
- {
- this->Makefile->SetComplainRegularExpression(args[1].c_str());
- }
+ if (args.size() > 1) {
+ this->Makefile->SetComplainRegularExpression(args[1]);
+ }
return true;
}
-
diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h
index 2e4177548..bac4b8fc3 100644
--- a/Source/cmIncludeRegularExpressionCommand.h
+++ b/Source/cmIncludeRegularExpressionCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmIncludeRegularExpressionCommand_h
#define cmIncludeRegularExpressionCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmIncludeRegularExpressionCommand
* \brief Set the regular expression for following #includes.
*
@@ -26,50 +24,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
return new cmIncludeRegularExpressionCommand;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "include_regular_expression";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set the regular expression used for dependency checking.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " include_regular_expression(regex_match [regex_complain])\n"
- "Set the regular expressions used in dependency checking. Only files "
- "matching regex_match will be traced as dependencies. Only files "
- "matching regex_complain will generate warnings if they cannot be "
- "found "
- "(standard header paths are not searched). The defaults are:\n"
- " regex_match = \"^.*$\" (match everything)\n"
- " regex_complain = \"^$\" (match empty string only)";
- }
-
- cmTypeMacro(cmIncludeRegularExpressionCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 3c76bd638..294fb178d 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -1,202 +1,194 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommand.h"
+#include "cmsys/Glob.hxx"
+#include <sstream>
+#include <stddef.h>
+
+#include "cmAlgorithms.h"
+#include "cmCommandArgumentsHelper.h"
+#include "cmExportSet.h"
+#include "cmExportSetMap.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallCommandArguments.h"
#include "cmInstallDirectoryGenerator.h"
+#include "cmInstallExportGenerator.h"
#include "cmInstallFilesGenerator.h"
+#include "cmInstallGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
-#include "cmInstallExportGenerator.h"
-#include "cmInstallCommandArguments.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmTargetExport.h"
-#include "cmExportSet.h"
+#include "cmake.h"
-#include <cmsys/Glob.hxx>
+class cmExecutionStatus;
-static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
- const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false)
+static cmInstallTargetGenerator* CreateInstallTargetGenerator(
+ cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
+ bool forceOpt = false)
{
- return new cmInstallTargetGenerator(target, args.GetDestination().c_str(),
- impLib, args.GetPermissions().c_str(),
- args.GetConfigurations(), args.GetComponent().c_str(),
- args.GetOptional() || forceOpt);
+ 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);
}
static cmInstallFilesGenerator* CreateInstallFilesGenerator(
- const std::vector<std::string>& absFiles,
- const cmInstallCommandArguments& args, bool programs)
+ cmMakefile* mf, const std::vector<std::string>& absFiles,
+ const cmInstallCommandArguments& args, bool programs)
{
- return new cmInstallFilesGenerator(absFiles, args.GetDestination().c_str(),
- programs, args.GetPermissions().c_str(),
- args.GetConfigurations(), args.GetComponent().c_str(),
- args.GetRename().c_str(), args.GetOptional());
+ 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());
}
-
// cmInstallCommand
bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &)
+ cmExecutionStatus&)
{
// Allow calling with no arguments so that arguments may be built up
// using a variable that may be left empty.
- if(args.empty())
- {
+ if (args.empty()) {
return true;
- }
+ }
// Enable the install target.
- this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->EnableInstallTarget();
+ this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
- this->DefaultComponentName = this->Makefile->GetSafeDefinition(
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
- if (this->DefaultComponentName.empty())
- {
+ 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(args[0] == "SCRIPT")
- {
+ if (mode == "SCRIPT") {
return this->HandleScriptMode(args);
- }
- else if(args[0] == "CODE")
- {
+ }
+ if (mode == "CODE") {
return this->HandleScriptMode(args);
- }
- else if(args[0] == "TARGETS")
- {
+ }
+ if (mode == "TARGETS") {
return this->HandleTargetsMode(args);
- }
- else if(args[0] == "FILES")
- {
+ }
+ if (mode == "FILES") {
return this->HandleFilesMode(args);
- }
- else if(args[0] == "PROGRAMS")
- {
+ }
+ if (mode == "PROGRAMS") {
return this->HandleFilesMode(args);
- }
- else if(args[0] == "DIRECTORY")
- {
+ }
+ if (mode == "DIRECTORY") {
return this->HandleDirectoryMode(args);
- }
- else if(args[0] == "EXPORT")
- {
+ }
+ if (mode == "EXPORT") {
return this->HandleExportMode(args);
- }
+ }
+ if (mode == "EXPORT_ANDROID_MK") {
+ return this->HandleExportAndroidMKMode(args);
+ }
// Unknown mode.
- cmStdString e = "called with unknown mode ";
+ std::string e = "called with unknown mode ";
e += args[0];
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
{
std::string component = this->DefaultComponentName;
int componentCount = 0;
bool doing_script = false;
bool doing_code = false;
+ bool exclude_from_all = false;
// Scan the args once for COMPONENT. Only allow one.
//
- for(size_t i=0; i < args.size(); ++i)
- {
- if(args[i] == "COMPONENT" && i+1 < args.size())
- {
- ++componentCount;
- ++i;
- component = args[i];
- }
+ for (size_t i = 0; i < args.size(); ++i) {
+ if (args[i] == "COMPONENT" && i + 1 < args.size()) {
+ ++componentCount;
+ ++i;
+ component = args[i];
}
+ if (args[i] == "EXCLUDE_FROM_ALL") {
+ exclude_from_all = true;
+ }
+ }
- if(componentCount>1)
- {
+ 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.");
+ "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 (size_t i = 0; i < args.size(); ++i) {
+ if (args[i] == "SCRIPT") {
doing_script = true;
doing_code = false;
- }
- else if(args[i] == "CODE")
- {
+ } else if (args[i] == "CODE") {
doing_script = false;
doing_code = true;
- }
- else if(args[i] == "COMPONENT")
- {
+ } else if (args[i] == "COMPONENT") {
doing_script = false;
doing_code = false;
- }
- else if(doing_script)
- {
+ } else if (doing_script) {
doing_script = false;
std::string script = args[i];
- if(!cmSystemTools::FileIsFullPath(script.c_str()))
- {
- script = this->Makefile->GetCurrentDirectory();
+ if (!cmSystemTools::FileIsFullPath(script.c_str())) {
+ script = this->Makefile->GetCurrentSourceDirectory();
script += "/";
script += args[i];
- }
- if(cmSystemTools::FileIsDirectory(script.c_str()))
- {
+ }
+ if (cmSystemTools::FileIsDirectory(script)) {
this->SetError("given a directory as value of SCRIPT argument.");
return false;
- }
- this->Makefile->AddInstallGenerator(
- new cmInstallScriptGenerator(script.c_str(), false,
- component.c_str()));
}
- else if(doing_code)
- {
+ this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
+ script.c_str(), false, component.c_str(), exclude_from_all));
+ } else if (doing_code) {
doing_code = false;
- std::string code = args[i];
- this->Makefile->AddInstallGenerator(
- new cmInstallScriptGenerator(code.c_str(), true,
- component.c_str()));
- }
+ std::string const& code = args[i];
+ this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
+ code.c_str(), true, component.c_str(), exclude_from_all));
}
+ }
- if(doing_script)
- {
+ if (doing_script) {
this->SetError("given no value for SCRIPT argument.");
return false;
- }
- if(doing_code)
- {
+ }
+ if (doing_code) {
this->SetError("given no value for CODE argument.");
return false;
- }
+ }
- //Tell the global generator about any installation component names specified.
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(component.c_str());
+ // Tell the global generator about any installation component names
+ // specified.
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str());
return true;
}
-
/*struct InstallPart
{
InstallPart(cmCommandArgumentsHelper* helper, const char* key,
@@ -205,7 +197,6 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
cmInstallCommandArguments args;
};*/
-//----------------------------------------------------------------------------
bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
{
// This is the TARGETS mode.
@@ -213,20 +204,22 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmCommandArgumentsHelper argHelper;
cmCommandArgumentGroup group;
- cmCAStringVector genericArgVector (&argHelper,0);
- cmCAStringVector archiveArgVector (&argHelper,"ARCHIVE",&group);
- cmCAStringVector libraryArgVector (&argHelper,"LIBRARY",&group);
- cmCAStringVector runtimeArgVector (&argHelper,"RUNTIME",&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(0);
+ 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, 0);
+ argHelper.Parse(&args, CM_NULLPTR);
// now parse the generic args (i.e. the ones not specialized on LIBRARY/
// ARCHIVE, RUNTIME etc. (see above)
@@ -234,8 +227,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
std::vector<std::string> unknownArgs;
cmInstallCommandArguments genericArgs(this->DefaultComponentName);
cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
- cmCAString exports(&genericArgs.Parser,"EXPORT", &genericArgs.ArgumentGroup);
- targetList.Follows(0);
+ cmCAString exports(&genericArgs.Parser, "EXPORT",
+ &genericArgs.ArgumentGroup);
+ targetList.Follows(CM_NULLPTR);
genericArgs.ArgumentGroup.Follows(&targetList);
genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
bool success = genericArgs.Finalize();
@@ -243,6 +237,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
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);
@@ -252,29 +247,30 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// 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);
- frameworkArgs.Parse (&frameworkArgVector.GetVector(), &unknownArgs);
- bundleArgs.Parse (&bundleArgVector.GetVector(), &unknownArgs);
+ 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);
+ publicHeaderArgs.Parse(&publicHeaderArgVector.GetVector(), &unknownArgs);
+ resourceArgs.Parse(&resourceArgVector.GetVector(), &unknownArgs);
+ includesArgs.Parse(&includesArgVector.GetVector(), &unknownArgs);
- if(!unknownArgs.empty())
- {
+ if (!unknownArgs.empty()) {
// Unknown argument.
- cmOStringStream e;
+ std::ostringstream e;
e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// apply generic args
archiveArgs.SetGenericArguments(&genericArgs);
libraryArgs.SetGenericArguments(&genericArgs);
runtimeArgs.SetGenericArguments(&genericArgs);
+ objectArgs.SetGenericArguments(&genericArgs);
frameworkArgs.SetGenericArguments(&genericArgs);
bundleArgs.SetGenericArguments(&genericArgs);
privateHeaderArgs.SetGenericArguments(&genericArgs);
@@ -284,136 +280,117 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
success = success && runtimeArgs.Finalize();
+ success = success && objectArgs.Finalize();
success = success && frameworkArgs.Finalize();
success = success && bundleArgs.Finalize();
success = success && privateHeaderArgs.Finalize();
success = success && publicHeaderArgs.Finalize();
success = success && resourceArgs.Finalize();
- if(!success)
- {
+ if (!success) {
return false;
- }
+ }
// Enforce argument rules too complex to specify for the
// general-purpose parser.
- if(archiveArgs.GetNamelinkOnly() ||
- runtimeArgs.GetNamelinkOnly() ||
- frameworkArgs.GetNamelinkOnly() ||
- bundleArgs.GetNamelinkOnly() ||
- privateHeaderArgs.GetNamelinkOnly() ||
- publicHeaderArgs.GetNamelinkOnly() ||
- resourceArgs.GetNamelinkOnly())
- {
+ if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
+ objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
+ bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
+ publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
this->SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
- "The NAMELINK_ONLY option may be specified only following LIBRARY."
- );
+ "The NAMELINK_ONLY option may be specified only following LIBRARY.");
return false;
- }
- if(archiveArgs.GetNamelinkSkip() ||
- runtimeArgs.GetNamelinkSkip() ||
- frameworkArgs.GetNamelinkSkip() ||
- bundleArgs.GetNamelinkSkip() ||
- privateHeaderArgs.GetNamelinkSkip() ||
- publicHeaderArgs.GetNamelinkSkip() ||
- resourceArgs.GetNamelinkSkip())
- {
+ }
+ if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
+ objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
+ bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
+ publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
this->SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
- "The NAMELINK_SKIP option may be specified only following LIBRARY."
- );
+ "The NAMELINK_SKIP 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."
- );
+ }
+ if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
+ this->SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
+ "At most one of these two options may be specified.");
return false;
- }
+ }
// Select the mode for installing symlinks to versioned shared libraries.
- cmInstallTargetGenerator::NamelinkModeType
- namelinkMode = cmInstallTargetGenerator::NamelinkModeNone;
- if(libraryArgs.GetNamelinkOnly())
- {
+ cmInstallTargetGenerator::NamelinkModeType namelinkMode =
+ cmInstallTargetGenerator::NamelinkModeNone;
+ if (libraryArgs.GetNamelinkOnly()) {
namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
- }
- else if(libraryArgs.GetNamelinkSkip())
- {
+ } else if (libraryArgs.GetNamelinkSkip()) {
namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
- }
+ }
// Check if there is something to do.
- if(targetList.GetVector().empty())
- {
+ if (targetList.GetVector().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)
- {
-
- if (this->Makefile->IsAlias(targetIt->c_str()))
- {
- cmOStringStream e;
- e << "TARGETS given target \"" << (*targetIt)
- << "\" which is an alias.";
- this->SetError(e.str().c_str());
+ 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) {
+
+ if (this->Makefile->IsAlias(*targetIt)) {
+ std::ostringstream e;
+ e << "TARGETS given target \"" << (*targetIt) << "\" which is an alias.";
+ this->SetError(e.str());
return false;
- }
+ }
// Lookup this target in the current directory.
- if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
- {
+ if (cmTarget* target =
+ this->Makefile->FindLocalNonAliasTarget(*targetIt)) {
// Found the target. Check its type.
- if(target->GetType() != cmTarget::EXECUTABLE &&
- target->GetType() != cmTarget::STATIC_LIBRARY &&
- target->GetType() != cmTarget::SHARED_LIBRARY &&
- target->GetType() != cmTarget::MODULE_LIBRARY &&
- target->GetType() != cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
+ 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::INTERFACE_LIBRARY) {
+ std::ostringstream e;
e << "TARGETS given target \"" << (*targetIt)
<< "\" which is not an executable, library, or module.";
- this->SetError(e.str().c_str());
- return false;
- }
- else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
- e << "TARGETS given OBJECT library \"" << (*targetIt)
- << "\" which may not be installed.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
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
- {
+ } else {
// Did not find the target.
- cmOStringStream e;
+ std::ostringstream e;
e << "TARGETS given target \"" << (*targetIt)
<< "\" which does not exist in this directory.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Keep track of whether we will be performing an installation of
// any files of the given type.
bool installsArchive = false;
bool installsLibrary = false;
bool installsRuntime = false;
+ bool installsObject = false;
bool installsFramework = false;
bool installsBundle = false;
bool installsPrivateHeader = false;
@@ -421,216 +398,217 @@ 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 (std::vector<cmTarget*>::iterator ti = targets.begin();
+ ti != targets.end(); ++ti) {
// Handle each target type.
cmTarget& target = *(*ti);
- cmInstallTargetGenerator* archiveGenerator = 0;
- cmInstallTargetGenerator* libraryGenerator = 0;
- cmInstallTargetGenerator* runtimeGenerator = 0;
- cmInstallTargetGenerator* frameworkGenerator = 0;
- cmInstallTargetGenerator* bundleGenerator = 0;
- cmInstallFilesGenerator* privateHeaderGenerator = 0;
- cmInstallFilesGenerator* publicHeaderGenerator = 0;
- cmInstallFilesGenerator* resourceGenerator = 0;
+ 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;
// Track whether this is a namelink-only rule.
bool namelinkOnly = false;
- switch(target.GetType())
- {
- case cmTarget::SHARED_LIBRARY:
- {
+ switch (target.GetType()) {
+ case cmStateEnums::SHARED_LIBRARY: {
// 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 (dll_platform) {
// When in namelink only mode skip all libraries on Windows.
- if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
- {
+ if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
continue;
- }
+ }
// This is a DLL platform.
- if(!archiveArgs.GetDestination().empty())
- {
+ if (!archiveArgs.GetDestination().empty()) {
// The import library uses the ARCHIVE properties.
- archiveGenerator = CreateInstallTargetGenerator(target,
- archiveArgs, true);
- }
- if(!runtimeArgs.GetDestination().empty())
- {
+ archiveGenerator =
+ CreateInstallTargetGenerator(target, archiveArgs, true);
+ }
+ if (!runtimeArgs.GetDestination().empty()) {
// The DLL uses the RUNTIME properties.
- runtimeGenerator = CreateInstallTargetGenerator(target,
- runtimeArgs, false);
- }
- if ((archiveGenerator==0) && (runtimeGenerator==0))
- {
+ runtimeGenerator =
+ CreateInstallTargetGenerator(target, runtimeArgs, false);
+ }
+ if ((archiveGenerator == CM_NULLPTR) &&
+ (runtimeGenerator == CM_NULLPTR)) {
this->SetError("Library TARGETS given no DESTINATION!");
return false;
- }
}
- else
- {
+ } else {
// This is a non-DLL platform.
// If it is marked with FRAMEWORK property use the FRAMEWORK set of
// INSTALL properties. Otherwise, use the LIBRARY properties.
- if(target.IsFrameworkOnApple())
- {
+ if (target.IsFrameworkOnApple()) {
// When in namelink only mode skip frameworks.
- if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
- {
+ if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
continue;
- }
+ }
// Use the FRAMEWORK properties.
- if (!frameworkArgs.GetDestination().empty())
- {
- frameworkGenerator = CreateInstallTargetGenerator(target,
- frameworkArgs, false);
- }
- else
- {
- cmOStringStream e;
+ if (!frameworkArgs.GetDestination().empty()) {
+ frameworkGenerator =
+ CreateInstallTargetGenerator(target, frameworkArgs, false);
+ } else {
+ std::ostringstream e;
e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
- "FRAMEWORK target \"" << target.GetName() << "\".";
- this->SetError(e.str().c_str());
+ "FRAMEWORK target \""
+ << target.GetName() << "\".";
+ this->SetError(e.str());
return false;
- }
}
- else
- {
+ } else {
// The shared library uses the LIBRARY properties.
- if (!libraryArgs.GetDestination().empty())
- {
- libraryGenerator = CreateInstallTargetGenerator(target,
- libraryArgs, false);
+ if (!libraryArgs.GetDestination().empty()) {
+ libraryGenerator =
+ CreateInstallTargetGenerator(target, libraryArgs, false);
libraryGenerator->SetNamelinkMode(namelinkMode);
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "TARGETS given no LIBRARY DESTINATION for shared library "
- "target \"" << target.GetName() << "\".";
- this->SetError(e.str().c_str());
+ "target \""
+ << target.GetName() << "\".";
+ this->SetError(e.str());
return false;
- }
}
}
}
- break;
- case cmTarget::STATIC_LIBRARY:
- {
- // Static libraries use ARCHIVE properties.
- if (!archiveArgs.GetDestination().empty())
- {
- archiveGenerator = CreateInstallTargetGenerator(target, archiveArgs,
- false);
+ } break;
+ case cmStateEnums::STATIC_LIBRARY: {
+ // If it is marked with FRAMEWORK property use the FRAMEWORK set of
+ // INSTALL properties. Otherwise, use the LIBRARY properties.
+ if (target.IsFrameworkOnApple()) {
+ // When in namelink only mode skip frameworks.
+ if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
+ continue;
}
- else
- {
- cmOStringStream e;
- e << "TARGETS given no ARCHIVE DESTINATION for static library "
- "target \"" << target.GetName() << "\".";
- this->SetError(e.str().c_str());
- return false;
+
+ // Use the FRAMEWORK properties.
+ if (!frameworkArgs.GetDestination().empty()) {
+ frameworkGenerator =
+ CreateInstallTargetGenerator(target, frameworkArgs, false);
+ } else {
+ std::ostringstream e;
+ e << "TARGETS given no FRAMEWORK DESTINATION for static library "
+ "FRAMEWORK target \""
+ << target.GetName() << "\".";
+ this->SetError(e.str());
+ 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;
}
}
- break;
- case cmTarget::MODULE_LIBRARY:
- {
+ } break;
+ case cmStateEnums::MODULE_LIBRARY: {
// Modules use LIBRARY properties.
- if (!libraryArgs.GetDestination().empty())
- {
- libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs,
- false);
+ if (!libraryArgs.GetDestination().empty()) {
+ libraryGenerator =
+ CreateInstallTargetGenerator(target, libraryArgs, false);
libraryGenerator->SetNamelinkMode(namelinkMode);
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "TARGETS given no LIBRARY DESTINATION for module target \""
<< target.GetName() << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
- break;
- case cmTarget::EXECUTABLE:
- {
- if(target.IsAppBundleOnApple())
- {
+ } break;
+ case cmStateEnums::OBJECT_LIBRARY: {
+ // Objects use OBJECT properties.
+ if (!objectArgs.GetDestination().empty()) {
+ objectGenerator =
+ CreateInstallTargetGenerator(target, objectArgs, false);
+ } else {
+ std::ostringstream e;
+ e << "TARGETS given no OBJECTS DESTINATION for object library "
+ "target \""
+ << target.GetName() << "\".";
+ this->SetError(e.str());
+ return false;
+ }
+ } break;
+ case cmStateEnums::EXECUTABLE: {
+ if (target.IsAppBundleOnApple()) {
// Application bundles use the BUNDLE properties.
- if (!bundleArgs.GetDestination().empty())
- {
- bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs,
- false);
- }
- else if(!runtimeArgs.GetDestination().empty())
- {
+ if (!bundleArgs.GetDestination().empty()) {
+ bundleGenerator =
+ CreateInstallTargetGenerator(target, bundleArgs, false);
+ } else if (!runtimeArgs.GetDestination().empty()) {
bool failure = false;
- if(this->CheckCMP0006(failure))
- {
+ if (this->CheckCMP0006(failure)) {
// For CMake 2.4 compatibility fallback to the RUNTIME
// properties.
bundleGenerator =
CreateInstallTargetGenerator(target, runtimeArgs, false);
- }
- else if(failure)
- {
+ } else if (failure) {
return false;
- }
}
- if(!bundleGenerator)
- {
- cmOStringStream e;
+ }
+ if (!bundleGenerator) {
+ std::ostringstream e;
e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
- "executable target \"" << target.GetName() << "\".";
- this->SetError(e.str().c_str());
+ "executable target \""
+ << target.GetName() << "\".";
+ this->SetError(e.str());
return false;
- }
}
- else
- {
+ } else {
// Executables use the RUNTIME properties.
- if (!runtimeArgs.GetDestination().empty())
- {
- runtimeGenerator = CreateInstallTargetGenerator(target,
- runtimeArgs, false);
- }
- else
- {
- cmOStringStream e;
+ 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().c_str());
+ "target \""
+ << target.GetName() << "\".";
+ this->SetError(e.str());
return false;
- }
}
+ }
// 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() &&
- target.IsExecutableWithExports())
- {
+ if (dll_platform && !archiveArgs.GetDestination().empty() &&
+ target.IsExecutableWithExports()) {
// The import library uses the ARCHIVE properties.
- archiveGenerator = CreateInstallTargetGenerator(target,
- archiveArgs, true, true);
- }
+ archiveGenerator =
+ CreateInstallTargetGenerator(target, archiveArgs, true, true);
}
+ } break;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ // Nothing to do. An INTERFACE_LIBRARY can be installed, but the
+ // only effect of that is to make it exportable. It installs no
+ // other files itself.
break;
default:
// This should never happen due to the above type check.
// Ignore the case.
break;
- }
+ }
// These well-known sets of files are installed *automatically* for
// FRAMEWORK SHARED library targets on the Mac as part of installing the
@@ -639,106 +617,93 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// generators for them.
bool createInstallGeneratorsForTargetFileSets = true;
- if(target.IsFrameworkOnApple())
- {
+ if (target.IsFrameworkOnApple() ||
+ target.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
createInstallGeneratorsForTargetFileSets = false;
- }
+ }
- if(createInstallGeneratorsForTargetFileSets && !namelinkOnly)
- {
+ if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
const char* files = target.GetProperty("PRIVATE_HEADER");
- if ((files) && (*files))
- {
+ if ((files) && (*files)) {
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
- {
+ if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
return false;
- }
+ }
// Create the files install generator.
- if (!privateHeaderArgs.GetDestination().empty())
- {
- privateHeaderGenerator =
- CreateInstallFilesGenerator(absFiles, privateHeaderArgs, false);
- }
- else
- {
- cmOStringStream e;
+ 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");
- }
}
+ }
files = target.GetProperty("PUBLIC_HEADER");
- if ((files) && (*files))
- {
+ if ((files) && (*files)) {
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
- {
+ if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
return false;
- }
+ }
// Create the files install generator.
- if (!publicHeaderArgs.GetDestination().empty())
- {
- publicHeaderGenerator =
- CreateInstallFilesGenerator(absFiles, publicHeaderArgs, false);
- }
- else
- {
- cmOStringStream e;
+ 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");
- }
}
+ }
files = target.GetProperty("RESOURCE");
- if ((files) && (*files))
- {
+ if ((files) && (*files)) {
std::vector<std::string> relFiles;
cmSystemTools::ExpandListArgument(files, relFiles);
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
- {
+ if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
return false;
- }
+ }
// Create the files install generator.
- if (!resourceArgs.GetDestination().empty())
- {
- resourceGenerator = CreateInstallFilesGenerator(absFiles,
- resourceArgs, false);
- }
- else
- {
- cmOStringStream e;
+ if (!resourceArgs.GetDestination().empty()) {
+ resourceGenerator = CreateInstallFilesGenerator(
+ this->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");
- }
}
}
+ }
// Keep track of whether we're installing anything in each category
- installsArchive = installsArchive || archiveGenerator != 0;
- installsLibrary = installsLibrary || libraryGenerator != 0;
- installsRuntime = installsRuntime || runtimeGenerator != 0;
- installsFramework = installsFramework || frameworkGenerator != 0;
- installsBundle = installsBundle || bundleGenerator != 0;
- installsPrivateHeader = installsPrivateHeader
- || privateHeaderGenerator != 0;
- installsPublicHeader = installsPublicHeader || publicHeaderGenerator != 0;
+ 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;
+ installsPrivateHeader =
+ installsPrivateHeader || privateHeaderGenerator != CM_NULLPTR;
+ installsPublicHeader =
+ installsPublicHeader || publicHeaderGenerator != CM_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);
@@ -747,360 +712,368 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// 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;
- te->Target = &target;
+ if (!exports.GetString().empty() && !namelinkOnly) {
+ cmTargetExport* te = new cmTargetExport;
+ te->TargetName = target.GetName();
te->ArchiveGenerator = archiveGenerator;
te->BundleGenerator = bundleGenerator;
te->FrameworkGenerator = frameworkGenerator;
te->HeaderGenerator = publicHeaderGenerator;
te->LibraryGenerator = libraryGenerator;
te->RuntimeGenerator = runtimeGenerator;
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->GetExportSets()[exports.GetString()]->AddTargetExport(te);
-
- std::vector<std::string> dirs = includesArgs.GetIncludeDirs();
- if(!dirs.empty())
- {
- std::string dirString;
- const char *sep = "";
- for (std::vector<std::string>::const_iterator it = dirs.begin();
- it != dirs.end(); ++it)
- {
- te->InterfaceIncludeDirectories += sep;
- te->InterfaceIncludeDirectories += *it;
- sep = ";";
- }
- }
- }
+ te->ObjectsGenerator = objectGenerator;
+ this->Makefile->GetGlobalGenerator()
+ ->GetExportSets()[exports.GetString()]
+ ->AddTargetExport(te);
+
+ te->InterfaceIncludeDirectories =
+ cmJoin(includesArgs.GetIncludeDirs(), ";");
}
+ }
// Tell the global generator about any installation component names
// specified
- if (installsArchive)
- {
- this->Makefile->GetLocalGenerator()->
- GetGlobalGenerator()
- ->AddInstallComponent(archiveArgs.GetComponent().c_str());
- }
- if (installsLibrary)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(libraryArgs.GetComponent().c_str());
- }
- if (installsRuntime)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(runtimeArgs.GetComponent().c_str());
- }
- if (installsFramework)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(frameworkArgs.GetComponent().c_str());
- }
- if (installsBundle)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(bundleArgs.GetComponent().c_str());
- }
- if (installsPrivateHeader)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
- }
- if (installsPublicHeader)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
- }
- if (installsResource)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(resourceArgs.GetComponent().c_str());
- }
+ if (installsArchive) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ archiveArgs.GetComponent().c_str());
+ }
+ if (installsLibrary) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetComponent().c_str());
+ }
+ if (installsRuntime) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ runtimeArgs.GetComponent().c_str());
+ }
+ if (installsObject) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ objectArgs.GetComponent().c_str());
+ }
+ if (installsFramework) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ frameworkArgs.GetComponent().c_str());
+ }
+ if (installsBundle) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ bundleArgs.GetComponent().c_str());
+ }
+ if (installsPrivateHeader) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ privateHeaderArgs.GetComponent().c_str());
+ }
+ if (installsPublicHeader) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ publicHeaderArgs.GetComponent().c_str());
+ }
+ if (installsResource) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ resourceArgs.GetComponent().c_str());
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
{
// This is the FILES mode.
bool programs = (args[0] == "PROGRAMS");
cmInstallCommandArguments ica(this->DefaultComponentName);
cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
- files.Follows(0);
+ files.Follows(CM_NULLPTR);
ica.ArgumentGroup.Follows(&files);
std::vector<std::string> unknownArgs;
ica.Parse(&args, &unknownArgs);
- if(!unknownArgs.empty())
- {
+ if (!unknownArgs.empty()) {
// Unknown argument.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
+
+ const std::vector<std::string>& filesVector = files.GetVector();
// Check if there is something to do.
- if(files.GetVector().empty())
- {
+ if (filesVector.empty()) {
return true;
- }
+ }
- if(!ica.GetRename().empty() && files.GetVector().size() > 1)
- {
+ if (!ica.GetRename().empty() && filesVector.size() > 1) {
// The rename option works only with one file.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given RENAME option with more than one file.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath(args[0].c_str(), files.GetVector(), absFiles))
- {
+ if (!this->MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) {
return false;
+ }
+
+ cmPolicies::PolicyStatus status =
+ this->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;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+
+ switch (status) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n";
+ modal = "should";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ modal = "may";
+ messageType = cmake::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) {
+ return false;
+ }
+ }
}
+ }
- if (!ica.Finalize())
- {
+ if (!ica.Finalize()) {
return false;
- }
+ }
- if(ica.GetDestination().empty())
- {
+ if (ica.GetDestination().empty()) {
// A destination is required.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given no DESTINATION!";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Create the files install generator.
this->Makefile->AddInstallGenerator(
- CreateInstallFilesGenerator(absFiles, ica, programs));
+ CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs));
- //Tell the global generator about any installation component names specified.
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(ica.GetComponent().c_str());
+ // Tell the global generator about any installation component names
+ // specified.
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ ica.GetComponent().c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
+bool cmInstallCommand::HandleDirectoryMode(
+ std::vector<std::string> const& args)
{
- enum Doing { DoingNone, DoingDirs, DoingDestination, DoingPattern,
- DoingRegex, DoingPermsFile, DoingPermsDir, DoingPermsMatch,
- DoingConfigurations, DoingComponent };
+ enum Doing
+ {
+ DoingNone,
+ DoingDirs,
+ DoingDestination,
+ DoingPattern,
+ DoingRegex,
+ DoingPermsFile,
+ DoingPermsDir,
+ DoingPermsMatch,
+ DoingConfigurations,
+ DoingComponent
+ };
Doing doing = DoingDirs;
bool in_match_mode = false;
bool optional = false;
+ bool exclude_from_all = false;
+ bool message_never = false;
std::vector<std::string> dirs;
- const char* destination = 0;
+ const char* destination = CM_NULLPTR;
std::string permissions_file;
std::string permissions_dir;
std::vector<std::string> configurations;
std::string component = this->DefaultComponentName;
std::string literal_args;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "DESTINATION")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
+ }
// Switch to setting the destination property.
doing = DoingDestination;
- }
- else if(args[i] == "OPTIONAL")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Mark the rule as optional.
optional = true;
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());
+ return false;
}
- else if(args[i] == "PATTERN")
- {
+
+ // Mark the rule as quiet.
+ message_never = true;
+ doing = DoingNone;
+ } else if (args[i] == "PATTERN") {
// Switch to a new pattern match rule.
doing = DoingPattern;
in_match_mode = true;
- }
- else if(args[i] == "REGEX")
- {
+ } else if (args[i] == "REGEX") {
// Switch to a new regex match rule.
doing = DoingRegex;
in_match_mode = true;
- }
- else if(args[i] == "EXCLUDE")
- {
+ } else if (args[i] == "EXCLUDE") {
// Add this property to the current match rule.
- if(!in_match_mode || doing == DoingPattern || doing == DoingRegex)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" before a PATTERN or REGEX is given.";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
+ }
literal_args += " EXCLUDE";
doing = DoingNone;
- }
- else if(args[i] == "PERMISSIONS")
- {
- if(!in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" before a PATTERN or REGEX is given.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Switch to setting the current match permissions property.
literal_args += " PERMISSIONS";
doing = DoingPermsMatch;
- }
- else if(args[i] == "FILE_PERMISSIONS")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Switch to setting the file permissions property.
doing = DoingPermsFile;
- }
- else if(args[i] == "DIRECTORY_PERMISSIONS")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Switch to setting the directory permissions property.
doing = DoingPermsDir;
- }
- else if(args[i] == "USE_SOURCE_PERMISSIONS")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Add this option literally.
literal_args += " USE_SOURCE_PERMISSIONS";
doing = DoingNone;
- }
- else if(args[i] == "FILES_MATCHING")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Add this option literally.
literal_args += " FILES_MATCHING";
doing = DoingNone;
- }
- else if(args[i] == "CONFIGURATIONS")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Switch to setting the configurations property.
doing = DoingConfigurations;
- }
- else if(args[i] == "COMPONENT")
- {
- if(in_match_mode)
- {
- cmOStringStream e;
- e << args[0] << " does not allow \""
- << args[i] << "\" after PATTERN or REGEX.";
- this->SetError(e.str().c_str());
+ } 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());
return false;
- }
+ }
// Switch to setting the component property.
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());
+ return false;
}
- else if(doing == DoingDirs)
- {
+ exclude_from_all = true;
+ doing = DoingNone;
+ } else if (doing == DoingDirs) {
// Convert this directory to a full path.
std::string dir = args[i];
- if(!cmSystemTools::FileIsFullPath(dir.c_str()))
- {
- dir = this->Makefile->GetCurrentDirectory();
+ std::string::size_type gpos = cmGeneratorExpression::Find(dir);
+ if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir.c_str())) {
+ dir = this->Makefile->GetCurrentSourceDirectory();
dir += "/";
dir += args[i];
- }
+ }
// Make sure the name is a directory.
- if(cmSystemTools::FileExists(dir.c_str()) &&
- !cmSystemTools::FileIsDirectory(dir.c_str()))
- {
- cmOStringStream e;
- e << args[0] << " given non-directory \""
- << args[i] << "\" to install.";
- this->SetError(e.str().c_str());
+ if (cmSystemTools::FileExists(dir.c_str()) &&
+ !cmSystemTools::FileIsDirectory(dir)) {
+ std::ostringstream e;
+ e << args[0] << " given non-directory \"" << args[i]
+ << "\" to install.";
+ this->SetError(e.str());
return false;
- }
+ }
// Store the directory for installation.
dirs.push_back(dir);
- }
- else if(doing == DoingConfigurations)
- {
+ } else if (doing == DoingConfigurations) {
configurations.push_back(args[i]);
- }
- else if(doing == DoingDestination)
- {
+ } else if (doing == DoingDestination) {
destination = args[i].c_str();
doing = DoingNone;
- }
- else if(doing == DoingPattern)
- {
+ } else if (doing == 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
@@ -1111,11 +1084,9 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
literal_args += regex;
literal_args += "$\"";
doing = DoingNone;
- }
- else if(doing == DoingRegex)
- {
+ } else if (doing == DoingRegex) {
literal_args += " REGEX \"";
- // Match rules are case-insensitive on some platforms.
+// Match rules are case-insensitive on some platforms.
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
std::string regex = cmSystemTools::LowerCase(args[i]);
#else
@@ -1125,97 +1096,174 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
literal_args += regex;
literal_args += "\"";
doing = DoingNone;
- }
- else if(doing == DoingComponent)
- {
+ } else if (doing == DoingComponent) {
component = args[i];
doing = DoingNone;
- }
- else if(doing == DoingPermsFile)
- {
- // Check the requested permission.
- if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_file))
- {
- cmOStringStream e;
- e << args[0] << " given invalid file permission \""
- << args[i] << "\".";
- this->SetError(e.str().c_str());
+ } else if (doing == DoingPermsFile) {
+ // 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());
return false;
- }
}
- else if(doing == DoingPermsDir)
- {
+ } else if (doing == DoingPermsDir) {
// Check the requested permission.
- if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_dir))
- {
- cmOStringStream e;
- e << args[0] << " given invalid directory permission \""
- << args[i] << "\".";
- this->SetError(e.str().c_str());
+ if (!cmInstallCommandArguments::CheckPermissions(args[i],
+ permissions_dir)) {
+ std::ostringstream e;
+ e << args[0] << " given invalid directory permission \"" << args[i]
+ << "\".";
+ this->SetError(e.str());
return false;
- }
}
- else if(doing == DoingPermsMatch)
- {
+ } else if (doing == DoingPermsMatch) {
// Check the requested permission.
- if(!cmInstallCommandArguments::CheckPermissions(args[i], literal_args))
- {
- cmOStringStream e;
- e << args[0] << " given invalid permission \""
- << args[i] << "\".";
- this->SetError(e.str().c_str());
+ if (!cmInstallCommandArguments::CheckPermissions(args[i],
+ literal_args)) {
+ std::ostringstream e;
+ e << args[0] << " given invalid permission \"" << args[i] << "\".";
+ this->SetError(e.str());
return false;
- }
}
- else
- {
+ } else {
// Unknown argument.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given unknown argument \"" << args[i] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Support installing an empty directory.
- if(dirs.empty() && destination)
- {
+ if (dirs.empty() && destination) {
dirs.push_back("");
- }
+ }
// Check if there is something to do.
- if(dirs.empty())
- {
+ if (dirs.empty()) {
return true;
- }
- if(!destination)
- {
+ }
+ if (!destination) {
// A destination is required.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given no DESTINATION!";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
+
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(this->Makefile, message_never);
// Create the directory install generator.
- this->Makefile->AddInstallGenerator(
- new cmInstallDirectoryGenerator(dirs, destination,
- permissions_file.c_str(),
- permissions_dir.c_str(),
- configurations,
- component.c_str(),
- literal_args.c_str(),
- optional));
+ this->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->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(component.c_str());
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str());
+
+ return true;
+}
+
+bool cmInstallCommand::HandleExportAndroidMKMode(
+ std::vector<std::string> const& args)
+{
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // 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);
+ std::vector<std::string> 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());
+ return false;
+ }
+
+ if (!ica.Finalize()) {
+ return false;
+ }
+
+ // 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());
+ return false;
+ }
+
+ // Check the file name.
+ std::string fname = filename.GetString();
+ 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());
+ 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());
+ 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());
+ return false;
+ }
+ // Use the default name
+ if (fname.empty()) {
+ fname = "Android.mk";
+ }
+
+ cmExportSet* exportSet =
+ this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(this->Makefile);
+
+ // Create the export install generator.
+ cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
+ 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);
return true;
+#else
+ static_cast<void>(args);
+ this->SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
+ return false;
+#endif
}
-//----------------------------------------------------------------------------
bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
{
// This is the EXPORT mode.
@@ -1225,158 +1273,144 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
&ica.ArgumentGroup);
cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
- exp.Follows(0);
+ exp.Follows(CM_NULLPTR);
ica.ArgumentGroup.Follows(&exp);
std::vector<std::string> unknownArgs;
ica.Parse(&args, &unknownArgs);
- if (!unknownArgs.empty())
- {
+ if (!unknownArgs.empty()) {
// Unknown argument.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- if (!ica.Finalize())
- {
+ if (!ica.Finalize()) {
return false;
- }
+ }
// Make sure there is a destination.
- if(ica.GetDestination().empty())
- {
+ if (ica.GetDestination().empty()) {
// A destination is required.
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " given no DESTINATION!";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Check the file name.
std::string fname = filename.GetString();
- if(fname.find_first_of(":/\\") != fname.npos)
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Check the file extension.
- if(!fname.empty() &&
- cmSystemTools::GetFilenameLastExtension(fname) != ".cmake")
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Construct the file name.
- if(fname.empty())
- {
+ if (fname.empty()) {
fname = exp.GetString();
fname += ".cmake";
- if(fname.find_first_of(":/\\") != fname.npos)
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
}
-
- cmExportSet *exportSet = this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
- if (exportOld.IsEnabled())
- {
- for(std::vector<cmTargetExport*>::const_iterator
- tei = exportSet->GetTargetExports()->begin();
- tei != exportSet->GetTargetExports()->end(); ++tei)
- {
+ }
+
+ 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;
+ cmTarget* tgt =
+ this->Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
const bool newCMP0022Behavior =
- te->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN
- && te->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ (tgt && tgt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ tgt->GetPolicyStatusCMP0022() != cmPolicies::OLD);
- if(!newCMP0022Behavior)
- {
- cmOStringStream e;
+ if (!newCMP0022Behavior) {
+ std::ostringstream e;
e << "INSTALL(EXPORT) given keyword \""
- << "EXPORT_LINK_INTERFACE_LIBRARIES" << "\", but target \""
- << te->Target->GetName()
+ << "EXPORT_LINK_INTERFACE_LIBRARIES"
+ << "\", but target \"" << te->TargetName
<< "\" does not have policy CMP0022 set to NEW.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
}
+ }
+
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(this->Makefile);
// Create the export install generator.
- cmInstallExportGenerator* exportGenerator =
- new cmInstallExportGenerator(
- exportSet,
- ica.GetDestination().c_str(),
- ica.GetPermissions().c_str(), ica.GetConfigurations(),
- ica.GetComponent().c_str(), fname.c_str(),
- name_space.GetCString(), exportOld.IsEnabled(), this->Makefile);
+ cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
+ 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);
return true;
}
-bool cmInstallCommand::MakeFilesFullPath(const char* modeName,
- const std::vector<std::string>& relFiles,
- std::vector<std::string>& absFiles)
+bool cmInstallCommand::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)
- {
+ for (std::vector<std::string>::const_iterator fileIt = relFiles.begin();
+ fileIt != relFiles.end(); ++fileIt) {
std::string file = (*fileIt);
- if(!cmSystemTools::FileIsFullPath(file.c_str()))
- {
- file = this->Makefile->GetCurrentDirectory();
+ std::string::size_type gpos = cmGeneratorExpression::Find(file);
+ if (gpos != 0 && !cmSystemTools::FileIsFullPath(file.c_str())) {
+ file = this->Makefile->GetCurrentSourceDirectory();
file += "/";
file += *fileIt;
- }
+ }
// Make sure the file is not a directory.
- if(cmSystemTools::FileIsDirectory(file.c_str()))
- {
- cmOStringStream e;
+ if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) {
+ std::ostringstream e;
e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
// Store the file for installation.
absFiles.push_back(file);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmInstallCommand::CheckCMP0006(bool& failure)
{
- switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0006))
- {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
case cmPolicies::WARN:
- {
this->Makefile->IssueMessage(
cmake::AUTHOR_WARNING,
- this->Makefile->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0006)
- );
- }
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0006));
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to allow compatibility
return true;
@@ -1388,10 +1422,8 @@ bool cmInstallCommand::CheckCMP0006(bool& failure)
failure = true;
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- this->Makefile->GetPolicies()
- ->GetRequiredPolicyError(cmPolicies::CMP0006)
- );
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006));
break;
- }
+ }
return false;
}
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 65095011f..f5d1f9265 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallCommand_h
#define cmInstallCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmInstallCommand
* \brief Specifies where to install some files
*
@@ -26,325 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmInstallCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmInstallCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "install";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Specify rules to run at install time.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "This command generates installation rules for a project. "
- "Rules specified by calls to this command within a source directory "
- "are executed in order during installation. "
- "The order across directories is not defined."
- "\n"
- "There are multiple signatures for this command. Some of them define "
- "installation properties for files and targets. Properties common to "
- "multiple signatures are covered here but they are valid only for "
- "signatures that specify them.\n"
- "DESTINATION arguments specify "
- "the directory on disk to which a file will be installed. "
- "If a full path (with a leading slash or drive letter) is given it "
- "is used directly. If a relative path is given it is interpreted "
- "relative to the value of CMAKE_INSTALL_PREFIX. The prefix can "
- "be relocated at install time using DESTDIR mechanism explained in the "
- "CMAKE_INSTALL_PREFIX variable documentation.\n"
- "PERMISSIONS arguments specify permissions for installed files. "
- "Valid permissions are "
- "OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, "
- "GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, "
- "WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, "
- "SETUID, and SETGID. "
- "Permissions that do not make sense on certain platforms are ignored "
- "on those platforms.\n"
- "The CONFIGURATIONS argument specifies a list of build configurations "
- "for which the install rule applies (Debug, Release, etc.).\n"
- "The COMPONENT argument specifies an installation component name "
- "with which the install rule is associated, such as \"runtime\" or "
- "\"development\". During component-specific installation only "
- "install rules associated with the given component name will be "
- "executed. During a full installation all components are installed."
- " If COMPONENT is not provided a default component \"Unspecified\" is"
- " created. The default component name may be controlled with the "
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME variable.\n"
- "The RENAME argument specifies a name for an installed file that "
- "may be different from the original file. Renaming is allowed only "
- "when a single file is installed by the command.\n"
- "The OPTIONAL argument specifies that it is not an error if the "
- "file to be installed does not exist. "
- "\n"
- "The TARGETS signature:\n"
- " install(TARGETS targets... [EXPORT <export-name>]\n"
- " [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|\n"
- " PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]\n"
- " [DESTINATION <dir>]\n"
- " [INCLUDES DESTINATION [<dir> ...]]\n"
- " [PERMISSIONS permissions...]\n"
- " [CONFIGURATIONS [Debug|Release|...]]\n"
- " [COMPONENT <component>]\n"
- " [OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP]\n"
- " ] [...])\n"
- "The TARGETS form specifies rules for installing targets from a "
- "project. There are five kinds of target files that may be "
- "installed: ARCHIVE, LIBRARY, RUNTIME, FRAMEWORK, and BUNDLE. "
-
- "Executables are treated as RUNTIME targets, except that those "
- "marked with the MACOSX_BUNDLE property are treated as BUNDLE "
- "targets on OS X. "
- "Static libraries are always treated as ARCHIVE targets. "
- "Module libraries are always treated as LIBRARY targets. "
- "For non-DLL platforms shared libraries are treated as LIBRARY "
- "targets, except that those marked with the FRAMEWORK property "
- "are treated as FRAMEWORK targets on OS X. "
- "For DLL platforms the DLL part of a shared library is treated as "
- "a RUNTIME target and the corresponding import library is treated as "
- "an ARCHIVE target. "
- "All Windows-based systems including Cygwin are DLL platforms. "
- "The ARCHIVE, LIBRARY, RUNTIME, and FRAMEWORK "
- "arguments change the type of target to which the subsequent "
- "properties "
- "apply. If none is given the installation properties apply to "
- "all target types. If only one is given then only targets of that "
- "type will be installed (which can be used to install just a DLL or "
- "just an import library)."
- "The INCLUDES DESTINATION specifies a list of directories which will "
- "be added to the INTERFACE_INCLUDE_DIRECTORIES of the <targets> when "
- "exported by install(EXPORT). If a relative path is specified, it is "
- "treated as relative to the $<INSTALL_PREFIX>."
- "\n"
- "The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause "
- "subsequent properties to be applied to installing a FRAMEWORK "
- "shared library target's associated files on non-Apple platforms. "
- "Rules defined by these arguments are ignored on Apple platforms "
- "because the associated files are installed into the appropriate "
- "locations inside the framework folder. "
- "See documentation of the PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE "
- "target properties for details."
- "\n"
- "Either NAMELINK_ONLY or NAMELINK_SKIP may be specified as a LIBRARY "
- "option. "
- "On some platforms a versioned shared library has a symbolic link "
- "such as\n"
- " lib<name>.so -> lib<name>.so.1\n"
- "where \"lib<name>.so.1\" is the soname of the library and "
- "\"lib<name>.so\" is a \"namelink\" allowing linkers to find the "
- "library when given \"-l<name>\". "
- "The NAMELINK_ONLY option causes installation of only the namelink "
- "when a library target is installed. "
- "The NAMELINK_SKIP option causes installation of library files other "
- "than the namelink when a library target is installed. "
- "When neither option is given both portions are installed. "
- "On platforms where versioned shared libraries do not have namelinks "
- "or when a library is not versioned the NAMELINK_SKIP option installs "
- "the library and the NAMELINK_ONLY option installs nothing. "
- "See the VERSION and SOVERSION target properties for details on "
- "creating versioned shared libraries."
- "\n"
- "One or more groups of properties may be specified in a single call "
- "to the TARGETS form of this command. A target may be installed more "
- "than once to different locations. Consider hypothetical "
- "targets \"myExe\", \"mySharedLib\", and \"myStaticLib\". The code\n"
- " install(TARGETS myExe mySharedLib myStaticLib\n"
- " RUNTIME DESTINATION bin\n"
- " LIBRARY DESTINATION lib\n"
- " ARCHIVE DESTINATION lib/static)\n"
- " install(TARGETS mySharedLib DESTINATION /some/full/path)\n"
- "will install myExe to <prefix>/bin and myStaticLib to "
- "<prefix>/lib/static. "
- "On non-DLL platforms mySharedLib will be installed to <prefix>/lib "
- "and /some/full/path. On DLL platforms the mySharedLib DLL will be "
- "installed to <prefix>/bin and /some/full/path and its import library "
- "will be installed to <prefix>/lib/static and /some/full/path."
- "\n"
- "The EXPORT option associates the installed target files with an "
- "export called <export-name>. "
- "It must appear before any RUNTIME, LIBRARY, or ARCHIVE options. "
- "To actually install the export file itself, call install(EXPORT). "
- "See documentation of the install(EXPORT ...) signature below for "
- "details."
- "\n"
- "Installing a target with EXCLUDE_FROM_ALL set to true has "
- "undefined behavior."
- "\n"
- "The FILES signature:\n"
- " install(FILES files... DESTINATION <dir>\n"
- " [PERMISSIONS permissions...]\n"
- " [CONFIGURATIONS [Debug|Release|...]]\n"
- " [COMPONENT <component>]\n"
- " [RENAME <name>] [OPTIONAL])\n"
- "The FILES form specifies rules for installing files for a "
- "project. File names given as relative paths are interpreted with "
- "respect to the current source directory. Files installed by this "
- "form are by default given permissions OWNER_WRITE, OWNER_READ, "
- "GROUP_READ, and WORLD_READ if no PERMISSIONS argument is given."
- "\n"
- "The PROGRAMS signature:\n"
- " install(PROGRAMS files... DESTINATION <dir>\n"
- " [PERMISSIONS permissions...]\n"
- " [CONFIGURATIONS [Debug|Release|...]]\n"
- " [COMPONENT <component>]\n"
- " [RENAME <name>] [OPTIONAL])\n"
- "The PROGRAMS form is identical to the FILES form except that the "
- "default permissions for the installed file also include "
- "OWNER_EXECUTE, GROUP_EXECUTE, and WORLD_EXECUTE. "
- "This form is intended to install programs that are not targets, "
- "such as shell scripts. Use the TARGETS form to install targets "
- "built within the project."
- "\n"
- "The DIRECTORY signature:\n"
- " install(DIRECTORY dirs... DESTINATION <dir>\n"
- " [FILE_PERMISSIONS permissions...]\n"
- " [DIRECTORY_PERMISSIONS permissions...]\n"
- " [USE_SOURCE_PERMISSIONS] [OPTIONAL]\n"
- " [CONFIGURATIONS [Debug|Release|...]]\n"
- " [COMPONENT <component>] [FILES_MATCHING]\n"
- " [[PATTERN <pattern> | REGEX <regex>]\n"
- " [EXCLUDE] [PERMISSIONS permissions...]] [...])\n"
- "The DIRECTORY form installs contents of one or more directories "
- "to a given destination. "
- "The directory structure is copied verbatim to the destination. "
- "The last component of each directory name is appended to the "
- "destination directory but a trailing slash may be used to "
- "avoid this because it leaves the last component empty. "
- "Directory names given as relative paths are interpreted with "
- "respect to the current source directory. "
- "If no input directory names are given the destination directory "
- "will be created but nothing will be installed into it. "
- "The FILE_PERMISSIONS and DIRECTORY_PERMISSIONS options specify "
- "permissions given to files and directories in the destination. "
- "If USE_SOURCE_PERMISSIONS is specified and FILE_PERMISSIONS is not, "
- "file permissions will be copied from the source directory structure. "
- "If no permissions are specified files will be given the default "
- "permissions specified in the FILES form of the command, and the "
- "directories will be given the default permissions specified in the "
- "PROGRAMS form of the command.\n"
-
- "Installation of directories may be controlled with fine granularity "
- "using the PATTERN or REGEX options. These \"match\" options specify a "
- "globbing pattern or regular expression to match directories or files "
- "encountered within input directories. They may be used to apply "
- "certain options (see below) to a subset of the files and directories "
- "encountered. "
- "The full path to each input file or directory "
- "(with forward slashes) is matched against the expression. "
- "A PATTERN will match only complete file names: the portion of the "
- "full path matching the pattern must occur at the end of the file name "
- "and be preceded by a slash. "
- "A REGEX will match any portion of the full path but it may use "
- "'/' and '$' to simulate the PATTERN behavior. "
- "By default all files and directories are installed whether "
- "or not they are matched. "
- "The FILES_MATCHING option may be given before the first match option "
- "to disable installation of files (but not directories) not matched by "
- "any expression. For example, the code\n"
- " install(DIRECTORY src/ DESTINATION include/myproj\n"
- " FILES_MATCHING PATTERN \"*.h\")\n"
- "will extract and install header files from a source tree.\n"
- "Some options may follow a PATTERN or REGEX expression and are "
- "applied only to files or directories matching them. "
- "The EXCLUDE option will skip the matched file or directory. "
- "The PERMISSIONS option overrides the permissions setting for the "
- "matched file or directory. "
- "For example the code\n"
- " install(DIRECTORY icons scripts/ DESTINATION share/myproj\n"
- " PATTERN \"CVS\" EXCLUDE\n"
- " PATTERN \"scripts/*\"\n"
- " PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ\n"
- " GROUP_EXECUTE GROUP_READ)\n"
- "will install the icons directory to share/myproj/icons and the "
- "scripts directory to share/myproj. The icons will get default file "
- "permissions, the scripts will be given specific permissions, and "
- "any CVS directories will be excluded."
- "\n"
- "The SCRIPT and CODE signature:\n"
- " install([[SCRIPT <file>] [CODE <code>]] [...])\n"
- "The SCRIPT form will invoke the given CMake script files during "
- "installation. If the script file name is a relative path "
- "it will be interpreted with respect to the current source directory. "
- "The CODE form will invoke the given CMake code during installation. "
- "Code is specified as a single argument inside a double-quoted string. "
- "For example, the code\n"
- " install(CODE \"MESSAGE(\\\"Sample install message.\\\")\")\n"
- "will print a message during installation.\n"
- ""
- "The EXPORT signature:\n"
- " install(EXPORT <export-name> DESTINATION <dir>\n"
- " [NAMESPACE <namespace>] [FILE <name>.cmake]\n"
- " [PERMISSIONS permissions...]\n"
- " [CONFIGURATIONS [Debug|Release|...]]\n"
- " [EXPORT_LINK_INTERFACE_LIBRARIES]\n"
- " [COMPONENT <component>])\n"
- "The EXPORT form generates and installs a CMake file containing code "
- "to import targets from the installation tree into another project. "
- "Target installations are associated with the export <export-name> "
- "using the EXPORT option of the install(TARGETS ...) signature "
- "documented above. The NAMESPACE option will prepend <namespace> to "
- "the target names as they are written to the import file. "
- "By default the generated file will be called <export-name>.cmake but "
- "the FILE option may be used to specify a different name. The value "
- "given to the FILE option must be a file name with the \".cmake\" "
- "extension. "
- "If a CONFIGURATIONS option is given then the file will only be "
- "installed when one of the named configurations is installed. "
- "Additionally, the generated import file will reference only the "
- "matching target configurations. "
- "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the "
- "contents of the properties matching "
- "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when "
- "policy CMP0022 is NEW. "
- "If a COMPONENT option is specified that does not match that given "
- "to the targets associated with <export-name> the behavior is "
- "undefined. "
- "If a library target is included in the export but "
- "a target to which it links is not included the behavior is "
- "unspecified."
- "\n"
- "The EXPORT form is useful to help outside projects use targets built "
- "and installed by the current project. For example, the code\n"
- " install(TARGETS myexe EXPORT myproj DESTINATION bin)\n"
- " install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)\n"
- "will install the executable myexe to <prefix>/bin and code to import "
- "it in the file \"<prefix>/lib/myproj/myproj.cmake\". "
- "An outside project may load this file with the include command "
- "and reference the myexe executable from the installation tree using "
- "the imported target name mp_myexe as if the target were built "
- "in its own tree."
- "\n"
- "NOTE: This command supercedes the INSTALL_TARGETS command and the "
- "target properties PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT. "
- "It also replaces the FILES forms of the INSTALL_FILES and "
- "INSTALL_PROGRAMS commands. "
- "The processing order of these install rules relative to those "
- "generated by INSTALL_TARGETS, INSTALL_FILES, and INSTALL_PROGRAMS "
- "commands is not defined.\n"
- ;
- }
-
- cmTypeMacro(cmInstallCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
bool HandleScriptMode(std::vector<std::string> const& args);
@@ -352,6 +39,7 @@ private:
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);
@@ -360,5 +48,4 @@ private:
std::string DefaultComponentName;
};
-
#endif
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 91ea861a4..b73414dd0 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -1,162 +1,147 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallCommandArguments.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmInstallCommandArguments.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", 0
+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
};
const std::string cmInstallCommandArguments::EmptyString;
cmInstallCommandArguments::cmInstallCommandArguments(
- const std::string& defaultComponent)
-:Parser()
-,ArgumentGroup()
-,Destination (&Parser, "DESTINATION" , &ArgumentGroup)
-,Component (&Parser, "COMPONENT" , &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(0)
-,DefaultComponentName(defaultComponent)
+ 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)
{
}
const std::string& cmInstallCommandArguments::GetDestination() const
{
- if (!this->DestinationString.empty())
- {
+ if (!this->DestinationString.empty()) {
return this->DestinationString;
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetDestination();
- }
+ }
return this->EmptyString;
}
const std::string& cmInstallCommandArguments::GetComponent() const
{
- if (!this->Component.GetString().empty())
- {
+ if (!this->Component.GetString().empty()) {
return this->Component.GetString();
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetComponent();
- }
- if (!this->DefaultComponentName.empty())
- {
+ }
+ if (!this->DefaultComponentName.empty()) {
return this->DefaultComponentName;
- }
+ }
static std::string unspecifiedComponent = "Unspecified";
return unspecifiedComponent;
}
const std::string& cmInstallCommandArguments::GetRename() const
{
- if (!this->Rename.GetString().empty())
- {
+ if (!this->Rename.GetString().empty()) {
return this->Rename.GetString();
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetRename();
- }
+ }
return this->EmptyString;
}
const std::string& cmInstallCommandArguments::GetPermissions() const
{
- if (!this->PermissionsString.empty())
- {
+ if (!this->PermissionsString.empty()) {
return this->PermissionsString;
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetPermissions();
- }
+ }
return this->EmptyString;
}
bool cmInstallCommandArguments::GetOptional() const
{
- if (this->Optional.IsEnabled())
- {
+ if (this->Optional.IsEnabled()) {
return true;
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetOptional();
- }
+ }
+ return false;
+}
+
+bool cmInstallCommandArguments::GetExcludeFromAll() const
+{
+ if (this->ExcludeFromAll.IsEnabled()) {
+ return true;
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
+ return this->GenericArguments->GetExcludeFromAll();
+ }
return false;
}
bool cmInstallCommandArguments::GetNamelinkOnly() const
{
- if (this->NamelinkOnly.IsEnabled())
- {
+ if (this->NamelinkOnly.IsEnabled()) {
return true;
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetNamelinkOnly();
- }
+ }
return false;
}
bool cmInstallCommandArguments::GetNamelinkSkip() const
{
- if (this->NamelinkSkip.IsEnabled())
- {
+ if (this->NamelinkSkip.IsEnabled()) {
return true;
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetNamelinkSkip();
- }
+ }
return false;
}
-const std::vector<std::string>&
- cmInstallCommandArguments::GetConfigurations() const
+const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
+ const
{
- if (!this->Configurations.GetVector().empty())
- {
+ if (!this->Configurations.GetVector().empty()) {
return this->Configurations.GetVector();
- }
- if (this->GenericArguments!=0)
- {
+ }
+ if (this->GenericArguments != CM_NULLPTR) {
return this->GenericArguments->GetConfigurations();
- }
+ }
return this->Configurations.GetVector();
}
-
bool cmInstallCommandArguments::Finalize()
{
- if (!this->CheckPermissions())
- {
+ if (!this->CheckPermissions()) {
return false;
- }
+ }
this->DestinationString = this->Destination.GetString();
cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
return true;
@@ -168,45 +153,38 @@ void cmInstallCommandArguments::Parse(const std::vector<std::string>* args,
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))
- {
+ for (std::vector<std::string>::const_iterator permIt =
+ this->Permissions.GetVector().begin();
+ permIt != this->Permissions.GetVector().end(); ++permIt) {
+ if (!this->CheckPermissions(*permIt, this->PermissionsString)) {
return false;
- }
}
+ }
return true;
}
bool cmInstallCommandArguments::CheckPermissions(
- const std::string& onePermission, std::string& permissions)
+ const std::string& onePermission, std::string& permissions)
{
// Check the permission against the table.
- for(const char** valid = cmInstallCommandArguments::PermissionsTable;
- *valid; ++valid)
- {
- if(onePermission == *valid)
- {
+ for (const char** valid = cmInstallCommandArguments::PermissionsTable;
+ *valid; ++valid) {
+ if (onePermission == *valid) {
// This is a valid permission.
permissions += " ";
permissions += onePermission;
return true;
- }
}
+ }
// This is not a valid permission.
return false;
}
cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument()
{
-
}
const std::vector<std::string>&
@@ -216,24 +194,16 @@ cmInstallCommandIncludesArgument::GetIncludeDirs() const
}
void cmInstallCommandIncludesArgument::Parse(
- const std::vector<std::string>* args,
- std::vector<std::string>*)
+ const std::vector<std::string>* args, std::vector<std::string>*)
{
- if(args->empty())
- {
+ if (args->empty()) {
return;
- }
+ }
std::vector<std::string>::const_iterator it = args->begin();
++it;
- for ( ; it != args->end(); ++it)
- {
+ for (; it != args->end(); ++it) {
std::string dir = *it;
- if (!cmSystemTools::FileIsFullPath(it->c_str())
- && cmGeneratorExpression::Find(*it) == std::string::npos)
- {
- dir = "$<INSTALL_PREFIX>/" + dir;
- }
cmSystemTools::ConvertToUnixSlashes(dir);
this->IncludeDirs.push_back(dir);
- }
+ }
}
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 90347e668..a576e7202 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -1,81 +1,79 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallCommandArguments_h
#define cmInstallCommandArguments_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
#include "cmCommandArgumentsHelper.h"
class cmInstallCommandArguments
{
- public:
- cmInstallCommandArguments(const std::string& defaultComponent);
- void SetGenericArguments(cmInstallCommandArguments* args)
- {this->GenericArguments = args;}
- void Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs);
+public:
+ cmInstallCommandArguments(const 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();
- // Compute destination path.and check permissions
- bool Finalize();
+ const std::string& GetDestination() const;
+ const std::string& GetComponent() const;
+ bool GetExcludeFromAll() const;
+ const std::string& GetRename() const;
+ const std::string& GetPermissions() const;
+ const std::vector<std::string>& GetConfigurations() const;
+ bool GetOptional() const;
+ bool GetNamelinkOnly() const;
+ bool GetNamelinkSkip() const;
- const std::string& GetDestination() const;
- const std::string& GetComponent() const;
- const std::string& GetRename() const;
- const std::string& GetPermissions() const;
- const std::vector<std::string>& GetConfigurations() const;
- bool GetOptional() const;
- bool GetNamelinkOnly() const;
- bool GetNamelinkSkip() 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;
- // 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;
- cmCAString Rename;
- cmCAStringVector Permissions;
- cmCAStringVector Configurations;
- cmCAEnabler Optional;
- cmCAEnabler NamelinkOnly;
- cmCAEnabler NamelinkSkip;
+private:
+ cmInstallCommandArguments(); // disabled
+ cmCAString Destination;
+ cmCAString Component;
+ cmCAEnabler ExcludeFromAll;
+ cmCAString Rename;
+ cmCAStringVector Permissions;
+ cmCAStringVector Configurations;
+ cmCAEnabler Optional;
+ cmCAEnabler NamelinkOnly;
+ cmCAEnabler NamelinkSkip;
- std::string DestinationString;
- std::string PermissionsString;
+ std::string DestinationString;
+ std::string PermissionsString;
- cmInstallCommandArguments* GenericArguments;
- static const char* PermissionsTable[];
- static const std::string EmptyString;
- std::string DefaultComponentName;
- bool CheckPermissions();
+ cmInstallCommandArguments* GenericArguments;
+ static const char* PermissionsTable[];
+ static const std::string EmptyString;
+ std::string DefaultComponentName;
+ bool CheckPermissions();
};
class cmInstallCommandIncludesArgument
{
- public:
- cmInstallCommandIncludesArgument();
- void Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs);
+public:
+ cmInstallCommandIncludesArgument();
+ void Parse(const std::vector<std::string>* args,
+ std::vector<std::string>* unconsumedArgs);
- const std::vector<std::string>& GetIncludeDirs() const;
+ const std::vector<std::string>& GetIncludeDirs() const;
- private:
- std::vector<std::string> IncludeDirs;
+private:
+ std::vector<std::string> IncludeDirs;
};
#endif
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index ddf7d08cc..54ad85c3b 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -1,52 +1,102 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallDirectoryGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmGeneratorExpression.h"
+#include "cmInstallType.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmInstallDirectoryGenerator.h"
+cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
+ std::vector<std::string> const& dirs, const char* dest,
+ const char* file_permissions, const char* dir_permissions,
+ std::vector<std::string> const& configurations, const char* component,
+ MessageLevel message, bool exclude_from_all, const char* literal_args,
+ bool optional)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all)
+ , LocalGenerator(CM_NULLPTR)
+ , Directories(dirs)
+ , FilePermissions(file_permissions)
+ , DirPermissions(dir_permissions)
+ , LiteralArguments(literal_args)
+ , Optional(optional)
+{
+ // We need per-config actions if destination have generator expressions.
+ if (cmGeneratorExpression::Find(Destination) != std::string::npos) {
+ this->ActionsPerConfig = true;
+ }
+
+ // 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;
+ }
+ }
+}
+
+cmInstallDirectoryGenerator::~cmInstallDirectoryGenerator()
+{
+}
-#include "cmTarget.h"
-
-//----------------------------------------------------------------------------
-cmInstallDirectoryGenerator
-::cmInstallDirectoryGenerator(std::vector<std::string> const& dirs,
- const char* dest,
- const char* file_permissions,
- const char* dir_permissions,
- std::vector<std::string> const& configurations,
- const char* component,
- const char* literal_args,
- bool optional):
- cmInstallGenerator(dest, configurations, component), Directories(dirs),
- FilePermissions(file_permissions), DirPermissions(dir_permissions),
- LiteralArguments(literal_args), Optional(optional)
+void cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg)
{
+ LocalGenerator = lg;
}
-//----------------------------------------------------------------------------
-cmInstallDirectoryGenerator
-::~cmInstallDirectoryGenerator()
+void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
+ Indent indent)
{
+ if (this->ActionsPerConfig) {
+ this->cmInstallGenerator::GenerateScriptActions(os, indent);
+ } else {
+ this->AddDirectoryInstallRule(os, "", indent, this->Directories);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
- Indent const& indent)
+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);
+ }
+
+ // 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;
+ }
+ }
+
+ this->AddDirectoryInstallRule(os, config, indent, dirs);
+}
+
+void cmInstallDirectoryGenerator::AddDirectoryInstallRule(
+ std::ostream& os, const std::string& config, Indent indent,
+ std::vector<std::string> const& dirs)
{
// Write code to install the directories.
- const char* no_rename = 0;
- this->AddInstallRule(os, cmInstallType_DIRECTORY,
- this->Directories,
- this->Optional,
+ const char* no_rename = CM_NULLPTR;
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, dirs, this->Optional,
this->FilePermissions.c_str(),
- this->DirPermissions.c_str(),
- no_rename, this->LiteralArguments.c_str(),
- indent);
+ this->DirPermissions.c_str(), no_rename,
+ this->LiteralArguments.c_str(), indent);
+}
+
+std::string cmInstallDirectoryGenerator::GetDestination(
+ std::string const& config) const
+{
+ cmGeneratorExpression ge;
+ return ge.Parse(this->Destination)->Evaluate(this->LocalGenerator, config);
}
diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h
index d76ef3c4c..aa2cbc690 100644
--- a/Source/cmInstallDirectoryGenerator.h
+++ b/Source/cmInstallDirectoryGenerator.h
@@ -1,37 +1,46 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallDirectoryGenerator_h
#define cmInstallDirectoryGenerator_h
#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
/** \class cmInstallDirectoryGenerator
* \brief Generate directory installation rules.
*/
-class cmInstallDirectoryGenerator: public cmInstallGenerator
+class cmInstallDirectoryGenerator : public cmInstallGenerator
{
public:
cmInstallDirectoryGenerator(std::vector<std::string> const& dirs,
- const char* dest,
- const char* file_permissions,
+ const char* dest, const char* file_permissions,
const char* dir_permissions,
std::vector<std::string> const& configurations,
- const char* component,
- const char* literal_args,
+ const char* component, MessageLevel message,
+ bool exclude_from_all, const char* literal_args,
bool optional = false);
- virtual ~cmInstallDirectoryGenerator();
+ ~cmInstallDirectoryGenerator() CM_OVERRIDE;
+
+ void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+
+ std::string GetDestination(std::string const& config) const;
protected:
- virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+ void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) CM_OVERRIDE;
+ void AddDirectoryInstallRule(std::ostream& os, const std::string& config,
+ Indent indent,
+ std::vector<std::string> const& dirs);
+ cmLocalGenerator* LocalGenerator;
std::vector<std::string> Directories;
std::string FilePermissions;
std::string DirPermissions;
diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx
new file mode 100644
index 000000000..8eeaa9c7c
--- /dev/null
+++ b/Source/cmInstallExportAndroidMKGenerator.cxx
@@ -0,0 +1,140 @@
+
+/* 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
new file mode 100644
index 000000000..189084a1a
--- /dev/null
+++ b/Source/cmInstallExportAndroidMKGenerator.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 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 3e9e6ac02..b176e85c5 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -1,74 +1,68 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallExportGenerator.h"
-#include <stdio.h>
-
-#include "cmake.h"
-#include "cmInstallTargetGenerator.h"
-#include "cmGeneratedFileStream.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
-
-#include "cmInstallFilesGenerator.h"
+#include <algorithm>
+#include <map>
+#include <sstream>
+#include <utility>
+#ifdef CMAKE_BUILD_WITH_CMAKE
+#include "cmExportInstallAndroidMKGenerator.h"
+#endif
#include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h"
+#include "cmInstallType.h"
+#include "cmLocalGenerator.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-//----------------------------------------------------------------------------
cmInstallExportGenerator::cmInstallExportGenerator(
- cmExportSet* exportSet,
- const char* destination,
- const char* file_permissions,
- std::vector<std::string> const& configurations,
- const char* component,
- const char* filename, const char* name_space,
- bool exportOld,
- cmMakefile* mf)
- :cmInstallGenerator(destination, configurations, component)
- ,ExportSet(exportSet)
- ,FilePermissions(file_permissions)
- ,FileName(filename)
- ,Namespace(name_space)
- ,ExportOld(exportOld)
- ,Makefile(mf)
+ 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, bool android)
+ : cmInstallGenerator(destination, configurations, component, message,
+ exclude_from_all)
+ , ExportSet(exportSet)
+ , FilePermissions(file_permissions)
+ , FileName(filename)
+ , Namespace(name_space)
+ , ExportOld(exportOld)
+ , LocalGenerator(CM_NULLPTR)
{
- this->EFGen = new cmExportInstallFileGenerator(this);
+ if (android) {
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ this->EFGen = new cmExportInstallAndroidMKGenerator(this);
+#endif
+ } else {
+ this->EFGen = new cmExportInstallFileGenerator(this);
+ }
exportSet->AddInstallation(this);
}
-//----------------------------------------------------------------------------
cmInstallExportGenerator::~cmInstallExportGenerator()
{
delete this->EFGen;
}
-//----------------------------------------------------------------------------
+void cmInstallExportGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+ this->ExportSet->Compute(lg);
+}
+
void cmInstallExportGenerator::ComputeTempDir()
{
// Choose a temporary directory in which to generate the import
// files to be installed.
- this->TempDir = this->Makefile->GetCurrentOutputDirectory();
+ this->TempDir = this->LocalGenerator->GetCurrentBinaryDirectory();
this->TempDir += cmake::GetCMakeFilesDirectory();
this->TempDir += "/Export";
- if(this->Destination.empty())
- {
+ if (this->Destination.empty()) {
return;
- }
- else
- {
- this->TempDir += "/";
- }
+ }
+ this->TempDir += "/";
// Enforce a maximum length.
bool useMD5 = false;
@@ -77,55 +71,67 @@ void cmInstallExportGenerator::ComputeTempDir()
#else
std::string::size_type const max_total_len = 1000;
#endif
- if(this->TempDir.size() < max_total_len)
- {
+ // Will generate files of the form "<temp-dir>/<base>-<config>.<ext>".
+ std::string::size_type const len = this->TempDir.size() + 1 +
+ this->FileName.size() + 1 + this->GetMaxConfigLength();
+ if (len < max_total_len) {
// Keep the total path length below the limit.
- std::string::size_type max_len = max_total_len - this->TempDir.size();
- if(this->Destination.size() > max_len)
- {
+ std::string::size_type const max_len = max_total_len - len;
+ if (this->Destination.size() > max_len) {
useMD5 = true;
- }
}
- else
- {
+ } else {
useMD5 = true;
- }
- if(useMD5)
- {
+ }
+ if (useMD5) {
// Replace the destination path with a hash to keep it short.
- this->TempDir +=
- cmSystemTools::ComputeStringMD5(this->Destination.c_str());
- }
- else
- {
+ this->TempDir += cmSystemTools::ComputeStringMD5(this->Destination);
+ } else {
std::string dest = this->Destination;
// Avoid unix full paths.
- if(dest[0] == '/')
- {
+ if (dest[0] == '/') {
dest[0] = '_';
- }
+ }
// Avoid windows full paths by removing colons.
- cmSystemTools::ReplaceString(dest, ":", "_");
+ std::replace(dest.begin(), dest.end(), ':', '_');
// Avoid relative paths that go up the tree.
cmSystemTools::ReplaceString(dest, "../", "__/");
// Avoid spaces.
- cmSystemTools::ReplaceString(dest, " ", "_");
+ std::replace(dest.begin(), dest.end(), ' ', '_');
this->TempDir += dest;
+ }
+}
+
+size_t cmInstallExportGenerator::GetMaxConfigLength() const
+{
+ // Always use at least 8 for "noconfig".
+ size_t len = 8;
+ if (this->ConfigurationTypes->empty()) {
+ if (this->ConfigurationName.size() > 8) {
+ 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();
+ }
+ }
+ }
+ return len;
}
-//----------------------------------------------------------------------------
void cmInstallExportGenerator::GenerateScript(std::ostream& os)
{
// Skip empty sets.
- if(ExportSet->GetTargetExports()->empty())
- {
- cmOStringStream e;
- e << "INSTALL(EXPORT) given unknown export \""
- << ExportSet->GetName() << "\"";
+ 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();
@@ -138,38 +144,29 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
// Generate the import file for this export set.
this->EFGen->SetExportFile(this->MainImportFile.c_str());
- this->EFGen->SetNamespace(this->Namespace.c_str());
+ this->EFGen->SetNamespace(this->Namespace);
this->EFGen->SetExportOld(this->ExportOld);
- if(this->ConfigurationTypes->empty())
- {
- if(this->ConfigurationName && *this->ConfigurationName)
- {
+ if (this->ConfigurationTypes->empty()) {
+ if (!this->ConfigurationName.empty()) {
this->EFGen->AddConfiguration(this->ConfigurationName);
- }
- else
- {
+ } 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->c_str());
- }
+ } 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
-cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
- Indent const& indent)
+void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
+ Indent indent)
{
// Create the main install rules first.
this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
@@ -177,52 +174,53 @@ 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<cmStdString, cmStdString>::const_iterator
- i = this->EFGen->GetConfigImportFiles().begin();
- i != this->EFGen->GetConfigImportFiles().end(); ++i)
- {
+ 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.c_str());
- os << indent << "IF(" << config_test << ")\n";
- this->AddInstallRule(os, cmInstallType_FILES, files, false,
- this->FilePermissions.c_str(), 0, 0, 0,
- indent.Next());
- os << indent << "ENDIF(" << config_test << ")\n";
+ 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 cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
- Indent const& indent)
+ Indent indent)
{
// Remove old per-configuration export files if the main changes.
std::string installedDir = "$ENV{DESTDIR}";
- installedDir += this->GetInstallDestination();
+ installedDir += this->ConvertToAbsoluteDestination(this->Destination);
installedDir += "/";
std::string installedFile = installedDir;
installedFile += this->FileName;
- os << indent << "IF(EXISTS \"" << installedFile << "\")\n";
+ os << indent << "if(EXISTS \"" << installedFile << "\")\n";
Indent indentN = indent.Next();
Indent indentNN = indentN.Next();
Indent indentNNN = indentNN.Next();
- os << indentN << "FILE(DIFFERENT EXPORT_FILE_CHANGED FILES\n"
+ /* 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
+ 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
+ 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(OLD_CONFIG_FILES)\n";
- os << indentN << "ENDIF(EXPORT_FILE_CHANGED)\n";
- os << indent << "ENDIF()\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, cmInstallType_FILES, files, false,
- this->FilePermissions.c_str(), 0, 0, 0, indent);
+ this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), CM_NULLPTR,
+ CM_NULLPTR, CM_NULLPTR, indent);
}
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 37b55932f..047e6b3cd 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -1,59 +1,62 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallExportGenerator_h
#define cmInstallExportGenerator_h
+#include "cmConfigure.h"
+
#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
+#include <iosfwd>
+#include <stddef.h>
+#include <string>
+#include <vector>
class cmExportInstallFileGenerator;
-class cmInstallFilesGenerator;
-class cmInstallTargetGenerator;
class cmExportSet;
-class cmMakefile;
+class cmLocalGenerator;
/** \class cmInstallExportGenerator
* \brief Generate rules for creating an export files.
*/
-class cmInstallExportGenerator: public cmInstallGenerator
+class cmInstallExportGenerator : public cmInstallGenerator
{
public:
- cmInstallExportGenerator(cmExportSet* exportSet,
- const char* dest, const char* file_permissions,
+ cmInstallExportGenerator(cmExportSet* exportSet, const char* dest,
+ const char* file_permissions,
const std::vector<std::string>& configurations,
- const char* component,
- const char* filename, const char* name_space,
- bool exportOld, cmMakefile* mf);
- ~cmInstallExportGenerator();
+ const char* component, MessageLevel message,
+ bool exclude_from_all, const char* filename,
+ const char* name_space, bool exportOld,
+ bool android);
+ ~cmInstallExportGenerator() CM_OVERRIDE;
+
+ cmExportSet* GetExportSet() { return this->ExportSet; }
- cmExportSet* GetExportSet() {return this->ExportSet;}
+ void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
- cmMakefile* GetMakefile() const { return this->Makefile; }
+ cmLocalGenerator* GetLocalGenerator() const { return this->LocalGenerator; }
const std::string& GetNamespace() const { return this->Namespace; }
+ std::string const& GetDestination() const { return this->Destination; }
+
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 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 GenerateImportFile(cmExportSet const* exportSet);
void GenerateImportFile(const char* config, cmExportSet const* exportSet);
void ComputeTempDir();
+ size_t GetMaxConfigLength() const;
cmExportSet* ExportSet;
std::string FilePermissions;
std::string FileName;
std::string Namespace;
bool ExportOld;
- cmMakefile* Makefile;
+ cmLocalGenerator* LocalGenerator;
std::string TempDir;
std::string MainImportFile;
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index cc62c4bac..4a3b620af 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -1,62 +1,47 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallFilesCommand.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmExecutableCommand
-bool cmInstallFilesCommand
-::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
+bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(argsIn.size() < 2)
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Enable the install target.
- this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->EnableInstallTarget();
-
- std::vector<std::string> args;
- this->Makefile->ExpandSourceListArguments(argsIn, args, 2);
+ this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
this->Destination = args[0];
- if((args.size() > 1) && (args[1] == "FILES"))
- {
+ 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)
- {
+ for (std::vector<std::string>::const_iterator s = args.begin() + 2;
+ s != args.end(); ++s) {
// Find the source location for each file listed.
std::string f = this->FindInstallSource(s->c_str());
this->Files.push_back(f);
- }
- this->CreateInstallGenerator();
}
- else
- {
+ this->CreateInstallGenerator();
+ } else {
this->IsFilesForm = false;
- std::vector<std::string>::const_iterator s = args.begin();
- for (++s;s != args.end(); ++s)
- {
- this->FinalArgs.push_back(*s);
- }
- }
+ this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1,
+ args.end());
+ }
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(this->Makefile->GetSafeDefinition(
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
return true;
}
@@ -64,53 +49,45 @@ bool cmInstallFilesCommand
void cmInstallFilesCommand::FinalPass()
{
// No final pass for "FILES" form of arguments.
- if(this->IsFilesForm)
- {
+ if (this->IsFilesForm) {
return;
- }
+ }
std::string testf;
- std::string ext = this->FinalArgs[0];
+ std::string const& ext = this->FinalArgs[0];
// two different options
- if (this->FinalArgs.size() > 1)
- {
+ if (this->FinalArgs.size() > 1) {
// now put the files into the list
std::vector<std::string>::iterator s = this->FinalArgs.begin();
++s;
// for each argument, get the files
- for (;s != this->FinalArgs.end(); ++s)
- {
+ for (; s != this->FinalArgs.end(); ++s) {
// replace any variables
- std::string temps = *s;
- if (cmSystemTools::GetFilenamePath(temps).size() > 0)
- {
- testf = cmSystemTools::GetFilenamePath(temps) + "/" +
- cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext;
- }
- else
- {
- testf = cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext;
- }
+ std::string const& temps = *s;
+ if (!cmSystemTools::GetFilenamePath(temps).empty()) {
+ testf = cmSystemTools::GetFilenamePath(temps) + "/" +
+ cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext;
+ } else {
+ testf = cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext;
+ }
// add to the result
this->Files.push_back(this->FindInstallSource(testf.c_str()));
- }
}
- else // reg exp list
- {
+ } else // reg exp list
+ {
std::vector<std::string> files;
- std::string regex = this->FinalArgs[0].c_str();
- cmSystemTools::Glob(this->Makefile->GetCurrentDirectory(),
- regex.c_str(), files);
+ std::string const& regex = this->FinalArgs[0];
+ cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), regex,
+ files);
std::vector<std::string>::iterator s = files.begin();
// for each argument, get the files
- for (;s != files.end(); ++s)
- {
+ for (; s != files.end(); ++s) {
this->Files.push_back(this->FindInstallSource(s->c_str()));
- }
}
+ }
this->CreateInstallGenerator();
}
@@ -121,25 +98,24 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
// the prefix. We skip the leading slash given by the user.
std::string destination = this->Destination.substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
- if(destination.empty())
- {
+ if (destination.empty()) {
destination = ".";
- }
+ }
// Use a file install generator.
const char* no_permissions = "";
const char* no_rename = "";
- std::string no_component = this->Makefile->GetSafeDefinition(
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+ bool no_exclude_from_all = false;
+ std::string no_component =
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
std::vector<std::string> no_configurations;
- this->Makefile->AddInstallGenerator(
- new cmInstallFilesGenerator(this->Files,
- destination.c_str(), false,
- no_permissions, no_configurations,
- no_component.c_str(), no_rename));
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(this->Makefile);
+ this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator(
+ this->Files, destination.c_str(), false, no_permissions, no_configurations,
+ no_component.c_str(), message, no_exclude_from_all, no_rename));
}
-
/**
* Find a file in the build or source tree for installation given a
* relative path from the CMakeLists.txt file. This will favor files
@@ -148,34 +124,29 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
*/
std::string cmInstallFilesCommand::FindInstallSource(const char* name) const
{
- if(cmSystemTools::FileIsFullPath(name))
- {
+ if (cmSystemTools::FileIsFullPath(name) ||
+ cmGeneratorExpression::Find(name) == 0) {
// This is a full path.
return name;
- }
+ }
// This is a relative path.
- std::string tb = this->Makefile->GetCurrentOutputDirectory();
+ std::string tb = this->Makefile->GetCurrentBinaryDirectory();
tb += "/";
tb += name;
- std::string ts = this->Makefile->GetCurrentDirectory();
+ std::string ts = this->Makefile->GetCurrentSourceDirectory();
ts += "/";
ts += name;
- if(cmSystemTools::FileExists(tb.c_str()))
- {
+ if (cmSystemTools::FileExists(tb.c_str())) {
// The file exists in the binary tree. Use it.
return tb;
- }
- else if(cmSystemTools::FileExists(ts.c_str()))
- {
+ }
+ if (cmSystemTools::FileExists(ts.c_str())) {
// The file exists in the source tree. Use it.
return ts;
- }
- else
- {
- // The file doesn't exist. Assume it will be present in the
- // binary tree when the install occurs.
- return tb;
- }
+ }
+ // The file doesn't exist. Assume it will be present in the
+ // binary tree when the install occurs.
+ return tb;
}
diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h
index bb0a6ccaf..b3c27b827 100644
--- a/Source/cmInstallFilesCommand.h
+++ b/Source/cmInstallFilesCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallFilesCommand_h
#define cmInstallFilesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmInstallFilesCommand
* \brief Specifies where to install some files
*
@@ -26,30 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmInstallFilesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmInstallFilesCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "install_files";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the install(FILES ) command instead.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
* This is called at the end after all the information
@@ -57,58 +39,18 @@ public:
* not implement this method. At this point, reading and
* writing to the cache can be done.
*/
- virtual void FinalPass();
- virtual bool HasFinalPass() const { return !this->IsFilesForm; }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "This command has been superceded by the install command. It "
- "is provided for compatibility with older CMake code. "
- "The FILES form is directly replaced by the FILES form of the "
- "install command. The regexp form can be expressed "
- "more clearly using the GLOB form of the file command.\n"
- " install_files(<dir> extension file file ...)\n"
- "Create rules to install the listed files with the given extension "
- "into the given directory. "
- "Only files existing in the current source tree or its corresponding "
- "location in the binary tree may be listed. "
- "If a file specified already has an extension, that extension will be "
- "removed first. This is useful for providing lists of source files "
- "such as foo.cxx when you want the corresponding foo.h to be "
- "installed. A typical extension is '.h'.\n"
- " install_files(<dir> regexp)\n"
- "Any files in the current source directory that match the regular "
- "expression will be installed.\n"
- " install_files(<dir> FILES file file ...)\n"
- "Any files listed after the FILES keyword will be "
- "installed explicitly from the names given. Full paths are allowed in "
- "this form.\n"
- "The directory <dir> is relative to the installation prefix, which "
- "is stored in the variable CMAKE_INSTALL_PREFIX.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmInstallFilesCommand, cmCommand);
+ void FinalPass() CM_OVERRIDE;
+ bool HasFinalPass() const CM_OVERRIDE { return !this->IsFilesForm; }
protected:
void CreateInstallGenerator() const;
std::string FindInstallSource(const char* name) const;
- private:
+private:
std::vector<std::string> FinalArgs;
bool IsFilesForm;
std::string Destination;
std::vector<std::string> Files;
};
-
#endif
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index ec02bc76a..6323a9189 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -1,50 +1,91 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallFilesGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmGeneratorExpression.h"
+#include "cmInstallType.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmInstallFilesGenerator.h"
+class cmLocalGenerator;
-//----------------------------------------------------------------------------
-cmInstallFilesGenerator
-::cmInstallFilesGenerator(std::vector<std::string> const& files,
- const char* dest, bool programs,
- const char* file_permissions,
- std::vector<std::string> const& configurations,
- const char* component,
- const char* rename,
- bool optional):
- cmInstallGenerator(dest, configurations, component),
- Files(files), Programs(programs),
- FilePermissions(file_permissions),
- Rename(rename), Optional(optional)
+cmInstallFilesGenerator::cmInstallFilesGenerator(
+ std::vector<std::string> const& files, const char* dest, bool programs,
+ const char* file_permissions, std::vector<std::string> const& configurations,
+ const char* component, MessageLevel message, bool exclude_from_all,
+ const char* rename, bool optional)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all)
+ , LocalGenerator(CM_NULLPTR)
+ , Files(files)
+ , FilePermissions(file_permissions)
+ , Rename(rename)
+ , Programs(programs)
+ , Optional(optional)
{
+ // We need per-config actions if the destination has generator expressions.
+ if (cmGeneratorExpression::Find(Destination) != std::string::npos) {
+ 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;
+ }
+ }
}
-//----------------------------------------------------------------------------
-cmInstallFilesGenerator
-::~cmInstallFilesGenerator()
+cmInstallFilesGenerator::~cmInstallFilesGenerator()
{
}
-//----------------------------------------------------------------------------
-void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
- Indent const& indent)
+void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+}
+
+std::string cmInstallFilesGenerator::GetDestination(
+ std::string const& config) const
+{
+ cmGeneratorExpression ge;
+ return ge.Parse(this->Destination)->Evaluate(this->LocalGenerator, config);
+}
+
+void cmInstallFilesGenerator::AddFilesInstallRule(
+ std::ostream& os, std::string const& config, Indent indent,
+ std::vector<std::string> const& files)
{
// Write code to install the files.
- const char* no_dir_permissions = 0;
- this->AddInstallRule(os,
- (this->Programs
- ? cmInstallType_PROGRAMS
- : cmInstallType_FILES),
- this->Files,
- this->Optional,
- this->FilePermissions.c_str(), no_dir_permissions,
- this->Rename.c_str(), 0, indent);
+ const char* no_dir_permissions = CM_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);
+}
+
+void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
+ Indent indent)
+{
+ if (this->ActionsPerConfig) {
+ this->cmInstallGenerator::GenerateScriptActions(os, indent);
+ } else {
+ this->AddFilesInstallRule(os, "", indent, this->Files);
+ }
+}
+
+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);
+ }
+ this->AddFilesInstallRule(os, config, indent, files);
}
diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h
index 871335c64..62b57f9c7 100644
--- a/Source/cmInstallFilesGenerator.h
+++ b/Source/cmInstallFilesGenerator.h
@@ -1,40 +1,51 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallFilesGenerator_h
#define cmInstallFilesGenerator_h
+#include "cmConfigure.h"
+
#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
/** \class cmInstallFilesGenerator
* \brief Generate file installation rules.
*/
-class cmInstallFilesGenerator: public cmInstallGenerator
+class cmInstallFilesGenerator : public cmInstallGenerator
{
public:
cmInstallFilesGenerator(std::vector<std::string> const& files,
const char* dest, bool programs,
const char* file_permissions,
std::vector<std::string> const& configurations,
- const char* component,
- const char* rename,
+ const char* component, MessageLevel message,
+ bool exclude_from_all, const char* rename,
bool optional = false);
- virtual ~cmInstallFilesGenerator();
+ ~cmInstallFilesGenerator() CM_OVERRIDE;
+
+ void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+
+ std::string GetDestination(std::string const& config) const;
protected:
- virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+ void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) CM_OVERRIDE;
+ void AddFilesInstallRule(std::ostream& os, std::string const& config,
+ Indent indent,
+ std::vector<std::string> const& files);
+
+ cmLocalGenerator* LocalGenerator;
std::vector<std::string> Files;
- bool Programs;
std::string FilePermissions;
std::string Rename;
+ bool Programs;
bool Optional;
};
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 3be2c2b14..13b588efb 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -1,150 +1,145 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallGenerator.h"
+#include "cmMakefile.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
-cmInstallGenerator
-::cmInstallGenerator(const char* destination,
- std::vector<std::string> const& configurations,
- const char* component):
- cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations),
- Destination(destination? destination:""),
- Component(component? component:"")
+#include <ostream>
+
+cmInstallGenerator::cmInstallGenerator(
+ const char* destination, std::vector<std::string> const& configurations,
+ const char* component, MessageLevel message, bool exclude_from_all)
+ : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
+ , Destination(destination ? destination : "")
+ , Component(component ? component : "")
+ , Message(message)
+ , ExcludeFromAll(exclude_from_all)
{
}
-//----------------------------------------------------------------------------
-cmInstallGenerator
-::~cmInstallGenerator()
+cmInstallGenerator::~cmInstallGenerator()
{
}
-//----------------------------------------------------------------------------
-void cmInstallGenerator
-::AddInstallRule(
- std::ostream& os,
- cmInstallType type,
- std::vector<std::string> const& files,
- bool optional /* = false */,
- const char* permissions_file /* = 0 */,
- const char* permissions_dir /* = 0 */,
- const char* rename /* = 0 */,
- const char* literal_args /* = 0 */,
- Indent const& indent
- )
+void cmInstallGenerator::AddInstallRule(
+ std::ostream& os, std::string const& dest, cmInstallType type,
+ std::vector<std::string> const& files, bool optional /* = false */,
+ const char* permissions_file /* = 0 */,
+ const char* permissions_dir /* = 0 */, const char* rename /* = 0 */,
+ const char* literal_args /* = 0 */, Indent indent)
{
// Use the FILE command to install the file.
std::string stype;
- switch(type)
- {
- case cmInstallType_DIRECTORY: stype = "DIRECTORY"; break;
- case cmInstallType_PROGRAMS: stype = "PROGRAM"; break;
- case cmInstallType_EXECUTABLE: stype = "EXECUTABLE"; break;
- case cmInstallType_STATIC_LIBRARY: stype = "STATIC_LIBRARY"; break;
- case cmInstallType_SHARED_LIBRARY: stype = "SHARED_LIBRARY"; break;
- case cmInstallType_MODULE_LIBRARY: stype = "MODULE"; break;
- case cmInstallType_FILES: stype = "FILE"; break;
- }
+ switch (type) {
+ case cmInstallType_DIRECTORY:
+ stype = "DIRECTORY";
+ break;
+ case cmInstallType_PROGRAMS:
+ stype = "PROGRAM";
+ break;
+ case cmInstallType_EXECUTABLE:
+ stype = "EXECUTABLE";
+ break;
+ case cmInstallType_STATIC_LIBRARY:
+ stype = "STATIC_LIBRARY";
+ break;
+ case cmInstallType_SHARED_LIBRARY:
+ stype = "SHARED_LIBRARY";
+ break;
+ case cmInstallType_MODULE_LIBRARY:
+ stype = "MODULE";
+ break;
+ case cmInstallType_FILES:
+ stype = "FILE";
+ break;
+ }
os << indent;
- std::string dest = this->GetInstallDestination();
- if (cmSystemTools::FileIsFullPath(dest.c_str()))
- {
- 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())
- {
- os << ";";
- }
- os << dest << "/";
- if (rename && *rename)
- {
- os << rename;
- }
- else
- {
- os << cmSystemTools::GetFilenameName(*fi);
- }
- }
- os << "\")\n";
- os << indent << "IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
- os << indent << indent << "message(WARNING \"ABSOLUTE path INSTALL "
- << "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
- os << indent << "ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
+ if (cmSystemTools::FileIsFullPath(dest.c_str())) {
+ 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()) {
+ os << ";";
+ }
+ os << dest << "/";
+ if (rename && *rename) {
+ os << rename;
+ } else {
+ os << cmSystemTools::GetFilenameName(*fi);
+ }
+ }
+ os << "\")\n";
+ os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
+ os << indent << indent << "message(WARNING \"ABSOLUTE path INSTALL "
+ << "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
+ os << indent << "endif()\n";
- os << indent << "IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
- os << indent << indent << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
- << "DESTINATION forbidden (by caller): "
- << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
- os << indent << "ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
- }
- os << "FILE(INSTALL DESTINATION \"" << dest << "\" TYPE " << stype.c_str();
- if(optional)
- {
+ os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
+ os << indent << indent << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
+ << "DESTINATION forbidden (by caller): "
+ << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
+ os << indent << "endif()\n";
+ }
+ std::string absDest = this->ConvertToAbsoluteDestination(dest);
+ os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype;
+ if (optional) {
os << " OPTIONAL";
- }
- if(permissions_file && *permissions_file)
- {
+ }
+ switch (this->Message) {
+ case MessageDefault:
+ break;
+ case MessageAlways:
+ os << " MESSAGE_ALWAYS";
+ break;
+ case MessageLazy:
+ os << " MESSAGE_LAZY";
+ break;
+ case MessageNever:
+ os << " MESSAGE_NEVER";
+ break;
+ }
+ if (permissions_file && *permissions_file) {
os << " PERMISSIONS" << permissions_file;
- }
- if(permissions_dir && *permissions_dir)
- {
+ }
+ if (permissions_dir && *permissions_dir) {
os << " DIR_PERMISSIONS" << permissions_dir;
- }
- if(rename && *rename)
- {
+ }
+ if (rename && *rename) {
os << " RENAME \"" << rename << "\"";
- }
+ }
os << " FILES";
- if(files.size() == 1)
- {
+ if (files.size() == 1) {
os << " \"" << files[0] << "\"";
- }
- else
- {
- for(std::vector<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi)
- {
+ } else {
+ for (std::vector<std::string>::const_iterator fi = files.begin();
+ fi != files.end(); ++fi) {
os << "\n" << indent << " \"" << *fi << "\"";
- }
+ }
os << "\n" << indent << " ";
- if(!(literal_args && *literal_args))
- {
+ if (!(literal_args && *literal_args)) {
os << " ";
- }
}
- if(literal_args && *literal_args)
- {
+ }
+ if (literal_args && *literal_args) {
os << literal_args;
- }
+ }
os << ")\n";
}
-//----------------------------------------------------------------------------
-std::string
-cmInstallGenerator::CreateComponentTest(const char* component)
+std::string cmInstallGenerator::CreateComponentTest(const char* component,
+ bool exclude_from_all)
{
- std::string result = "NOT CMAKE_INSTALL_COMPONENT OR "
- "\"${CMAKE_INSTALL_COMPONENT}\" STREQUAL \"";
+ std::string result = "\"${CMAKE_INSTALL_COMPONENT}\" STREQUAL \"";
result += component;
result += "\"";
+ if (!exclude_from_all) {
+ result += " OR NOT CMAKE_INSTALL_COMPONENT";
+ }
return result;
}
-//----------------------------------------------------------------------------
void cmInstallGenerator::GenerateScript(std::ostream& os)
{
// Track indentation.
@@ -152,31 +147,47 @@ void cmInstallGenerator::GenerateScript(std::ostream& os)
// Begin this block of installation.
std::string component_test =
- this->CreateComponentTest(this->Component.c_str());
- os << indent << "IF(" << component_test << ")\n";
+ this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll);
+ os << indent << "if(" << component_test << ")\n";
// Generate the script possibly with per-configuration code.
this->GenerateScriptConfigs(os, indent.Next());
// End this block of installation.
- os << indent << "ENDIF(" << component_test << ")\n\n";
+ os << indent << "endif()\n\n";
}
-//----------------------------------------------------------------------------
-bool cmInstallGenerator::InstallsForConfig(const char* config)
+bool cmInstallGenerator::InstallsForConfig(const std::string& config)
{
return this->GeneratesForConfig(config);
}
-//----------------------------------------------------------------------------
-std::string cmInstallGenerator::GetInstallDestination() const
+std::string cmInstallGenerator::ConvertToAbsoluteDestination(
+ std::string const& dest) const
{
std::string result;
- if(!this->Destination.empty() &&
- !cmSystemTools::FileIsFullPath(this->Destination.c_str()))
- {
+ if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest.c_str())) {
result = "${CMAKE_INSTALL_PREFIX}/";
- }
- result += this->Destination;
+ }
+ result += dest;
return result;
}
+
+cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel(
+ cmMakefile* mf, bool never)
+{
+ if (never) {
+ return MessageNever;
+ }
+ std::string m = mf->GetSafeDefinition("CMAKE_INSTALL_MESSAGE");
+ if (m == "ALWAYS") {
+ return MessageAlways;
+ }
+ if (m == "LAZY") {
+ return MessageLazy;
+ }
+ if (m == "NEVER") {
+ return MessageNever;
+ }
+ return MessageDefault;
+}
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index c89ab8ac5..8f8701f1a 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -1,63 +1,73 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallGenerator_h
#define cmInstallGenerator_h
+#include "cmConfigure.h"
+
#include "cmInstallType.h"
#include "cmScriptGenerator.h"
+#include <iosfwd>
+#include <string>
+#include <vector>
+
class cmLocalGenerator;
+class cmMakefile;
/** \class cmInstallGenerator
* \brief Support class for generating install scripts.
*
*/
-class cmInstallGenerator: public cmScriptGenerator
+class cmInstallGenerator : public cmScriptGenerator
{
+ CM_DISABLE_COPY(cmInstallGenerator)
+
public:
+ enum MessageLevel
+ {
+ MessageDefault,
+ MessageAlways,
+ MessageLazy,
+ MessageNever
+ };
+
cmInstallGenerator(const char* destination,
std::vector<std::string> const& configurations,
- const char* component);
- virtual ~cmInstallGenerator();
+ const char* component, MessageLevel message,
+ bool exclude_from_all);
+ ~cmInstallGenerator() CM_OVERRIDE;
void AddInstallRule(
- std::ostream& os, cmInstallType type,
- std::vector<std::string> const& files,
- bool optional = false,
- const char* permissions_file = 0,
- const char* permissions_dir = 0,
- const char* rename = 0,
- const char* literal_args = 0,
- Indent const& indent = Indent()
- );
-
- const char* GetDestination() const
- { return this->Destination.c_str(); }
+ 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());
/** Get the install destination as it should appear in the
installation script. */
- std::string GetInstallDestination() const;
+ std::string ConvertToAbsoluteDestination(std::string const& dest) const;
/** Test if this generator installs something for a given configuration. */
- bool InstallsForConfig(const char*);
+ bool InstallsForConfig(const std::string& config);
+
+ /** Select message level from CMAKE_INSTALL_MESSAGE or 'never'. */
+ static MessageLevel SelectMessageLevel(cmMakefile* mf, bool never = false);
+
+ virtual void Compute(cmLocalGenerator*) {}
protected:
- virtual void GenerateScript(std::ostream& os);
+ void GenerateScript(std::ostream& os) CM_OVERRIDE;
- std::string CreateComponentTest(const char* component);
+ std::string CreateComponentTest(const char* component,
+ bool exclude_from_all);
// Information shared by most generator types.
std::string Destination;
std::string Component;
+ MessageLevel Message;
+ bool ExcludeFromAll;
};
#endif
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index 3a0a3223b..5ee81fbf6 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -1,41 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallProgramsCommand.h"
+
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
+
// cmExecutableCommand
-bool cmInstallProgramsCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmInstallProgramsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2)
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Enable the install target.
- this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->EnableInstallTarget();
+ this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
this->Destination = args[0];
- std::vector<std::string>::const_iterator s = args.begin();
- for (++s;s != args.end(); ++s)
- {
- this->FinalArgs.push_back(*s);
- }
+ this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1, args.end());
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(this->Makefile->GetSafeDefinition(
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
return true;
}
@@ -43,61 +36,55 @@ bool cmInstallProgramsCommand
void cmInstallProgramsCommand::FinalPass()
{
bool files_mode = false;
- if(!this->FinalArgs.empty() && this->FinalArgs[0] == "FILES")
- {
+ if (!this->FinalArgs.empty() && this->FinalArgs[0] == "FILES") {
files_mode = true;
- }
+ }
// two different options
- if (this->FinalArgs.size() > 1 || files_mode)
- {
+ if (this->FinalArgs.size() > 1 || files_mode) {
// for each argument, get the programs
std::vector<std::string>::iterator s = this->FinalArgs.begin();
- if(files_mode)
- {
+ if (files_mode) {
// Skip the FILES argument in files mode.
++s;
- }
- for(;s != this->FinalArgs.end(); ++s)
- {
+ }
+ for (; s != this->FinalArgs.end(); ++s) {
// add to the result
this->Files.push_back(this->FindInstallSource(s->c_str()));
- }
}
- else // reg exp list
- {
+ } else // reg exp list
+ {
std::vector<std::string> programs;
- cmSystemTools::Glob(this->Makefile->GetCurrentDirectory(),
- this->FinalArgs[0].c_str(), programs);
+ cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(),
+ this->FinalArgs[0], programs);
std::vector<std::string>::iterator s = programs.begin();
// for each argument, get the programs
- for (;s != programs.end(); ++s)
- {
+ for (; s != programs.end(); ++s) {
this->Files.push_back(this->FindInstallSource(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);
cmSystemTools::ConvertToUnixSlashes(destination);
- if(destination.empty())
- {
+ if (destination.empty()) {
destination = ".";
- }
+ }
// Use a file install generator.
const char* no_permissions = "";
const char* no_rename = "";
- std::string no_component = this->Makefile->GetSafeDefinition(
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+ bool no_exclude_from_all = false;
+ std::string no_component =
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
std::vector<std::string> no_configurations;
- this->Makefile->AddInstallGenerator(
- new cmInstallFilesGenerator(this->Files,
- destination.c_str(), true,
- no_permissions, no_configurations,
- no_component.c_str(), no_rename));
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(this->Makefile);
+ this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator(
+ this->Files, destination.c_str(), true, no_permissions, no_configurations,
+ no_component.c_str(), message, no_exclude_from_all, no_rename));
}
/**
@@ -106,37 +93,31 @@ 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
+std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const
{
- if(cmSystemTools::FileIsFullPath(name))
- {
+ if (cmSystemTools::FileIsFullPath(name) ||
+ cmGeneratorExpression::Find(name) == 0) {
// This is a full path.
return name;
- }
+ }
// This is a relative path.
- std::string tb = this->Makefile->GetCurrentOutputDirectory();
+ std::string tb = this->Makefile->GetCurrentBinaryDirectory();
tb += "/";
tb += name;
- std::string ts = this->Makefile->GetCurrentDirectory();
+ std::string ts = this->Makefile->GetCurrentSourceDirectory();
ts += "/";
ts += name;
- if(cmSystemTools::FileExists(tb.c_str()))
- {
+ if (cmSystemTools::FileExists(tb.c_str())) {
// The file exists in the binary tree. Use it.
return tb;
- }
- else if(cmSystemTools::FileExists(ts.c_str()))
- {
+ }
+ if (cmSystemTools::FileExists(ts.c_str())) {
// The file exists in the source tree. Use it.
return ts;
- }
- else
- {
- // The file doesn't exist. Assume it will be present in the
- // binary tree when the install occurs.
- return tb;
- }
+ }
+ // The file doesn't exist. Assume it will be present in the
+ // binary tree when the install occurs.
+ return tb;
}
diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h
index 27a0498e5..242fb953d 100644
--- a/Source/cmInstallProgramsCommand.h
+++ b/Source/cmInstallProgramsCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallProgramsCommand_h
#define cmInstallProgramsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmInstallProgramsCommand
* \brief Specifies where to install some programs
*
@@ -26,30 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmInstallProgramsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmInstallProgramsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "install_programs";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the install(PROGRAMS ) command instead.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
* This is called at the end after all the information
@@ -57,52 +39,17 @@ public:
* not implement this method. At this point, reading and
* writing to the cache can be done.
*/
- virtual void FinalPass();
-
- virtual bool HasFinalPass() const { return true; }
+ void FinalPass() CM_OVERRIDE;
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "This command has been superceded by the install command. It "
- "is provided for compatibility with older CMake code. "
- "The FILES form is directly replaced by the PROGRAMS form of the "
- "INSTALL command. The regexp form can be expressed more clearly "
- "using the GLOB form of the FILE command.\n"
- " install_programs(<dir> file1 file2 [file3 ...])\n"
- " install_programs(<dir> FILES file1 [file2 ...])\n"
- "Create rules to install the listed programs into the given directory. "
- "Use the FILES argument to guarantee that the file list version of "
- "the command will be used even when there is only one argument.\n"
- " install_programs(<dir> regexp)\n"
- "In the second form any program in the current source directory that "
- "matches the regular expression will be installed.\n"
- "This command is intended to install programs that are not built "
- "by cmake, such as shell scripts. See the TARGETS form of "
- "the INSTALL command to "
- "create installation rules for targets built by cmake.\n"
- "The directory <dir> is relative to the installation prefix, which "
- "is stored in the variable CMAKE_INSTALL_PREFIX.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmInstallProgramsCommand, cmCommand);
+ 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;
};
-
#endif
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index bcfbe63c5..b39a622f5 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -1,47 +1,39 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallScriptGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmScriptGenerator.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmInstallScriptGenerator.h"
+#include <ostream>
+#include <vector>
-//----------------------------------------------------------------------------
-cmInstallScriptGenerator
-::cmInstallScriptGenerator(const char* script, bool code,
- const char* component) :
- cmInstallGenerator(0, std::vector<std::string>(), component),
- Script(script), Code(code)
+cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script,
+ bool code,
+ const char* component,
+ bool exclude_from_all)
+ : cmInstallGenerator(CM_NULLPTR, std::vector<std::string>(), component,
+ MessageDefault, exclude_from_all)
+ , Script(script)
+ , Code(code)
{
}
-//----------------------------------------------------------------------------
-cmInstallScriptGenerator
-::~cmInstallScriptGenerator()
+cmInstallScriptGenerator::~cmInstallScriptGenerator()
{
}
-//----------------------------------------------------------------------------
void cmInstallScriptGenerator::GenerateScript(std::ostream& os)
{
Indent indent;
std::string component_test =
- this->CreateComponentTest(this->Component.c_str());
- os << indent << "IF(" << component_test << ")\n";
+ this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll);
+ os << indent << "if(" << component_test << ")\n";
- if(this->Code)
- {
+ if (this->Code) {
os << indent.Next() << this->Script << "\n";
- }
- else
- {
- os << indent.Next() << "INCLUDE(\"" << this->Script << "\")\n";
- }
+ } else {
+ os << indent.Next() << "include(\"" << this->Script << "\")\n";
+ }
- os << indent << "ENDIF(" << component_test << ")\n\n";
+ os << indent << "endif()\n\n";
}
diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h
index 54a7b2195..e183999d0 100644
--- a/Source/cmInstallScriptGenerator.h
+++ b/Source/cmInstallScriptGenerator.h
@@ -1,31 +1,27 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallScriptGenerator_h
#define cmInstallScriptGenerator_h
+#include "cmConfigure.h"
+
#include "cmInstallGenerator.h"
+#include <iosfwd>
+#include <string>
+
/** \class cmInstallScriptGenerator
* \brief Generate target installation rules.
*/
-class cmInstallScriptGenerator: public cmInstallGenerator
+class cmInstallScriptGenerator : public cmInstallGenerator
{
public:
cmInstallScriptGenerator(const char* script, bool code,
- const char* component);
- virtual ~cmInstallScriptGenerator();
+ const char* component, bool exclude_from_all);
+ ~cmInstallScriptGenerator() CM_OVERRIDE;
protected:
- virtual void GenerateScript(std::ostream& os);
+ void GenerateScript(std::ostream& os) CM_OVERRIDE;
std::string Script;
bool Code;
};
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index c9624c8e0..84d6f7ac9 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -1,105 +1,125 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallTargetGenerator.h"
+#include <assert.h>
+#include <map>
+#include <set>
+#include <sstream>
+#include <utility>
+
#include "cmComputeLinkInformation.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallType.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmake.h"
-#include <assert.h>
-
-//----------------------------------------------------------------------------
-cmInstallTargetGenerator
-::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib,
- const char* file_permissions,
- std::vector<std::string> const& configurations,
- const char* component, bool optional):
- cmInstallGenerator(dest, configurations, component), Target(&t),
- ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional)
+cmInstallTargetGenerator::cmInstallTargetGenerator(
+ const 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)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all)
+ , TargetName(targetName)
+ , Target(CM_NULLPTR)
+ , FilePermissions(file_permissions)
+ , ImportLibrary(implib)
+ , Optional(optional)
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
- this->Target->SetHaveInstallRule(true);
}
-//----------------------------------------------------------------------------
-cmInstallTargetGenerator
-::~cmInstallTargetGenerator()
+cmInstallTargetGenerator::~cmInstallTargetGenerator()
{
}
-//----------------------------------------------------------------------------
void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
{
// Warn if installing an exclude-from-all target.
- if(this->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
- {
- cmOStringStream msg;
+ 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);
}
-//----------------------------------------------------------------------------
-void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
- const char* config,
- Indent const& indent)
+void cmInstallTargetGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
{
+ cmStateEnums::TargetType targetType = this->Target->GetType();
+ cmInstallType type = cmInstallType();
+ switch (targetType) {
+ case cmStateEnums::EXECUTABLE:
+ type = cmInstallType_EXECUTABLE;
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ type = cmInstallType_STATIC_LIBRARY;
+ break;
+ case cmStateEnums::SHARED_LIBRARY:
+ type = cmInstallType_SHARED_LIBRARY;
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ type = cmInstallType_MODULE_LIBRARY;
+ break;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ // Not reachable. We never create a cmInstallTargetGenerator for
+ // an INTERFACE_LIBRARY.
+ assert(false &&
+ "INTERFACE_LIBRARY targets have no installable outputs.");
+ break;
+
+ case cmStateEnums::OBJECT_LIBRARY:
+ this->GenerateScriptForConfigObjectLibrary(os, config, indent);
+ return;
+
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ this->Target->GetLocalGenerator()->IssueMessage(
+ cmake::INTERNAL_ERROR,
+ "cmInstallTargetGenerator created with non-installable target.");
+ return;
+ }
+
// Compute the build tree directory from which to copy the target.
std::string fromDirConfig;
- if(this->Target->NeedRelinkBeforeInstall(config))
- {
- fromDirConfig = this->Target->GetMakefile()->GetStartOutputDirectory();
+ if (this->Target->NeedRelinkBeforeInstall(config)) {
+ fromDirConfig =
+ this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
fromDirConfig += cmake::GetCMakeFilesDirectory();
fromDirConfig += "/CMakeRelink.dir/";
- }
- else
- {
- fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary);
+ } else {
+ cmStateEnums::ArtifactType artifact = this->ImportLibrary
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+ fromDirConfig = this->Target->GetDirectory(config, artifact);
fromDirConfig += "/";
- }
- std::string toDir = this->GetInstallDestination();
+ }
+
+ std::string toDir =
+ this->ConvertToAbsoluteDestination(this->GetDestination(config));
toDir += "/";
// Compute the list of files to install for this target.
std::vector<std::string> filesFrom;
std::vector<std::string> filesTo;
std::string literal_args;
- cmTarget::TargetType targetType = this->Target->GetType();
- cmInstallType type = cmInstallType();
- switch(targetType)
- {
- case cmTarget::EXECUTABLE: type = cmInstallType_EXECUTABLE; break;
- case cmTarget::STATIC_LIBRARY: type = cmInstallType_STATIC_LIBRARY; break;
- case cmTarget::SHARED_LIBRARY: type = cmInstallType_SHARED_LIBRARY; break;
- case cmTarget::MODULE_LIBRARY: type = cmInstallType_MODULE_LIBRARY; break;
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
- case cmTarget::UNKNOWN_LIBRARY:
- this->Target->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR,
- "cmInstallTargetGenerator created with non-installable target.");
- return;
- }
- if(targetType == cmTarget::EXECUTABLE)
- {
+
+ if (targetType == cmStateEnums::EXECUTABLE) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
@@ -108,70 +128,71 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::string targetNameImport;
std::string targetNamePDB;
this->Target->GetExecutableNames(targetName, targetNameReal,
- targetNameImport, targetNamePDB,
- config);
- if(this->ImportLibrary)
- {
+ targetNameImport, targetNamePDB, config);
+ if (this->ImportLibrary) {
std::string from1 = fromDirConfig + targetNameImport;
std::string to1 = toDir + targetNameImport;
filesFrom.push_back(from1);
filesTo.push_back(to1);
std::string targetNameImportLib;
- if(this->Target->GetImplibGNUtoMS(targetNameImport,
- targetNameImportLib))
- {
+ if (this->Target->GetImplibGNUtoMS(targetNameImport,
+ targetNameImportLib)) {
filesFrom.push_back(fromDirConfig + targetNameImportLib);
filesTo.push_back(toDir + targetNameImportLib);
- }
+ }
// An import library looks like a static library.
type = cmInstallType_STATIC_LIBRARY;
- }
- else
- {
+ } else {
std::string from1 = fromDirConfig + targetName;
std::string to1 = toDir + targetName;
// Handle OSX Bundles.
- if(this->Target->IsAppBundleOnApple())
- {
+ if (this->Target->IsAppBundleOnApple()) {
+ cmMakefile const* mf = this->Target->Target->GetMakefile();
+
+ // Get App Bundle Extension
+ const char* ext = this->Target->GetProperty("BUNDLE_EXTENSION");
+ if (!ext) {
+ ext = "app";
+ }
+
// Install the whole app bundle directory.
type = cmInstallType_DIRECTORY;
literal_args += " USE_SOURCE_PERMISSIONS";
- from1 += ".app";
+ from1 += ".";
+ from1 += ext;
// Tweaks apply to the binary inside the bundle.
- to1 += ".app/Contents/MacOS/";
- to1 += targetName;
+ to1 += ".";
+ to1 += ext;
+ to1 += "/";
+ if (!mf->PlatformIsAppleIos()) {
+ to1 += "Contents/MacOS/";
}
- else
- {
+ to1 += targetName;
+ } else {
// Tweaks apply to the real file, so list it first.
- if(targetNameReal != targetName)
- {
+ if (targetNameReal != targetName) {
std::string from2 = fromDirConfig + targetNameReal;
std::string to2 = toDir += targetNameReal;
filesFrom.push_back(from2);
filesTo.push_back(to2);
- }
}
+ }
filesFrom.push_back(from1);
filesTo.push_back(to1);
- }
}
- else
- {
+ } 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);
- if(this->ImportLibrary)
- {
+ targetNameImport, targetNamePDB, config);
+ if (this->ImportLibrary) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
@@ -180,18 +201,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
filesFrom.push_back(from1);
filesTo.push_back(to1);
std::string targetNameImportLib;
- if(this->Target->GetImplibGNUtoMS(targetNameImport,
- targetNameImportLib))
- {
+ if (this->Target->GetImplibGNUtoMS(targetNameImport,
+ targetNameImportLib)) {
filesFrom.push_back(fromDirConfig + targetNameImportLib);
filesTo.push_back(toDir + targetNameImportLib);
- }
+ }
// An import library looks like a static library.
type = cmInstallType_STATIC_LIBRARY;
- }
- else if(this->Target->IsFrameworkOnApple())
- {
+ } else if (this->Target->IsFrameworkOnApple()) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
@@ -207,9 +225,19 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
filesFrom.push_back(from1);
filesTo.push_back(to1);
- }
- else
- {
+ } 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 from1 = fromDirConfig + targetNameBase;
+ std::string to1 = toDir + targetName;
+
+ filesFrom.push_back(from1);
+ filesTo.push_back(to1);
+ } else {
bool haveNamelink = false;
// Library link name.
@@ -219,92 +247,77 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
// Library interface name.
std::string fromSOName;
std::string toSOName;
- if(targetNameSO != targetName)
- {
+ if (targetNameSO != targetName) {
haveNamelink = true;
fromSOName = fromDirConfig + targetNameSO;
toSOName = toDir + targetNameSO;
- }
+ }
// Library implementation name.
std::string fromRealName;
std::string toRealName;
- if(targetNameReal != targetName &&
- targetNameReal != targetNameSO)
- {
+ if (targetNameReal != targetName && targetNameReal != targetNameSO) {
haveNamelink = true;
fromRealName = fromDirConfig + targetNameReal;
toRealName = toDir + targetNameReal;
- }
+ }
// Add the names based on the current namelink mode.
- if(haveNamelink)
- {
+ if (haveNamelink) {
// With a namelink we need to check the mode.
- if(this->NamelinkMode == NamelinkModeOnly)
- {
+ if (this->NamelinkMode == NamelinkModeOnly) {
// Install the namelink only.
filesFrom.push_back(fromName);
filesTo.push_back(toName);
- }
- else
- {
+ } else {
// Install the real file if it has its own name.
- if(!fromRealName.empty())
- {
+ if (!fromRealName.empty()) {
filesFrom.push_back(fromRealName);
filesTo.push_back(toRealName);
- }
+ }
// Install the soname link if it has its own name.
- if(!fromSOName.empty())
- {
+ if (!fromSOName.empty()) {
filesFrom.push_back(fromSOName);
filesTo.push_back(toSOName);
- }
+ }
// Install the namelink if it is not to be skipped.
- if(this->NamelinkMode != NamelinkModeSkip)
- {
+ if (this->NamelinkMode != NamelinkModeSkip) {
filesFrom.push_back(fromName);
filesTo.push_back(toName);
- }
}
}
- else
- {
+ } else {
// Without a namelink there will be only one file. Install it
// if this is not a namelink-only rule.
- if(this->NamelinkMode != NamelinkModeOnly)
- {
+ if (this->NamelinkMode != NamelinkModeOnly) {
filesFrom.push_back(fromName);
filesTo.push_back(toName);
- }
}
}
}
+ }
// If this fails the above code is buggy.
assert(filesFrom.size() == filesTo.size());
// Skip this rule if no files are to be installed for the target.
- if(filesFrom.empty())
- {
+ if (filesFrom.empty()) {
return;
- }
+ }
// Add pre-installation tweaks.
this->AddTweak(os, indent, config, filesTo,
&cmInstallTargetGenerator::PreReplacementTweaks);
// Write code to install the target file.
- const char* no_dir_permissions = 0;
- const char* no_rename = 0;
+ const char* no_dir_permissions = CM_NULLPTR;
+ const char* no_rename = CM_NULLPTR;
bool optional = this->Optional || this->ImportLibrary;
- this->AddInstallRule(os, type, filesFrom,
- optional,
- this->FilePermissions.c_str(), no_dir_permissions,
- no_rename, literal_args.c_str(),
+ this->AddInstallRule(os, this->GetDestination(config), type, filesFrom,
+ optional, this->FilePermissions.c_str(),
+ no_dir_permissions, no_rename, literal_args.c_str(),
indent);
// Add post-installation tweaks.
@@ -312,54 +325,92 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
&cmInstallTargetGenerator::PostReplacementTweaks);
}
-//----------------------------------------------------------------------------
-std::string
-cmInstallTargetGenerator::GetInstallFilename(const char* config) const
+static std::string computeInstallObjectDir(cmGeneratorTarget* gt,
+ std::string const& config)
+{
+ std::string objectDir = "objects";
+ if (!config.empty()) {
+ objectDir += "-";
+ objectDir += config;
+ }
+ objectDir += "/";
+ objectDir += gt->GetName();
+ return objectDir;
+}
+
+void cmInstallTargetGenerator::GenerateScriptForConfigObjectLibrary(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ // Compute all the object files inside this target
+ std::vector<std::string> objects;
+ this->Target->GetTargetObjectNames(config, objects);
+
+ std::string const dest = this->GetDestination(config) + "/" +
+ computeInstallObjectDir(this->Target, config);
+
+ 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;
+ this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional,
+ this->FilePermissions.c_str(), no_dir_permissions,
+ no_rename, literal_args.c_str(), indent);
+}
+
+void cmInstallTargetGenerator::GetInstallObjectNames(
+ std::string const& config, std::vector<std::string>& objects) const
{
- NameType nameType = this->ImportLibrary? NameImplib : NameNormal;
- return
- cmInstallTargetGenerator::GetInstallFilename(this->Target, config,
- nameType);
+ this->Target->GetTargetObjectNames(config, objects);
+ for (std::vector<std::string>::iterator i = objects.begin();
+ i != objects.end(); ++i) {
+ *i = computeInstallObjectDir(this->Target, config) + "/" + *i;
+ }
}
-//----------------------------------------------------------------------------
-std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target,
- const char* config,
- NameType nameType)
+std::string cmInstallTargetGenerator::GetDestination(
+ std::string const& config) const
+{
+ cmGeneratorExpression ge;
+ return ge.Parse(this->Destination)
+ ->Evaluate(this->Target->GetLocalGenerator(), config);
+}
+
+std::string cmInstallTargetGenerator::GetInstallFilename(
+ const std::string& config) const
+{
+ NameType nameType = this->ImportLibrary ? NameImplib : NameNormal;
+ return cmInstallTargetGenerator::GetInstallFilename(this->Target, config,
+ nameType);
+}
+
+std::string cmInstallTargetGenerator::GetInstallFilename(
+ cmGeneratorTarget const* target, const std::string& config,
+ NameType nameType)
{
std::string fname;
// Compute the name of the library.
- if(target->GetType() == cmTarget::EXECUTABLE)
- {
+ if (target->GetType() == cmStateEnums::EXECUTABLE) {
std::string targetName;
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
- target->GetExecutableNames(targetName, targetNameReal,
- targetNameImport, targetNamePDB,
- config);
- if(nameType == NameImplib)
- {
+ target->GetExecutableNames(targetName, targetNameReal, targetNameImport,
+ targetNamePDB, config);
+ if (nameType == NameImplib) {
// Use the import library name.
- if(!target->GetImplibGNUtoMS(targetNameImport, fname,
- "${CMAKE_IMPORT_LIBRARY_SUFFIX}"))
- {
+ if (!target->GetImplibGNUtoMS(targetNameImport, fname,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNameImport;
- }
}
- else if(nameType == NameReal)
- {
+ } else if (nameType == NameReal) {
// Use the canonical name.
fname = targetNameReal;
- }
- else
- {
+ } else {
// Use the canonical name.
fname = targetName;
- }
}
- else
- {
+ } else {
std::string targetName;
std::string targetNameSO;
std::string targetNameReal;
@@ -367,172 +418,153 @@ std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target,
std::string targetNamePDB;
target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
targetNameImport, targetNamePDB, config);
- if(nameType == NameImplib)
- {
+ if (nameType == NameImplib) {
// Use the import library name.
- if(!target->GetImplibGNUtoMS(targetNameImport, fname,
- "${CMAKE_IMPORT_LIBRARY_SUFFIX}"))
- {
+ if (!target->GetImplibGNUtoMS(targetNameImport, fname,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNameImport;
- }
}
- else if(nameType == NameSO)
- {
+ } else if (nameType == NameSO) {
// Use the soname.
fname = targetNameSO;
- }
- else if(nameType == NameReal)
- {
+ } else if (nameType == NameReal) {
// Use the real name.
fname = targetNameReal;
- }
- else
- {
+ } else {
// Use the canonical name.
fname = targetName;
- }
}
+ }
return fname;
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator
-::AddTweak(std::ostream& os, Indent const& indent, const char* config,
- std::string const& file, TweakMethod tweak)
+void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+}
+
+void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& file,
+ TweakMethod tweak)
{
- cmOStringStream tw;
+ std::ostringstream tw;
(this->*tweak)(tw, indent.Next(), config, file);
std::string tws = tw.str();
- if(!tws.empty())
- {
- os << indent << "IF(EXISTS \"" << file << "\" AND\n"
+ if (!tws.empty()) {
+ os << indent << "if(EXISTS \"" << file << "\" AND\n"
<< indent << " NOT IS_SYMLINK \"" << file << "\")\n";
os << tws;
- os << indent << "ENDIF()\n";
- }
+ os << indent << "endif()\n";
+ }
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator
-::AddTweak(std::ostream& os, Indent const& indent, const char* config,
- std::vector<std::string> const& files, TweakMethod tweak)
+void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::vector<std::string> const& files,
+ TweakMethod tweak)
{
- if(files.size() == 1)
- {
+ if (files.size() == 1) {
// Tweak a single file.
this->AddTweak(os, indent, config, this->GetDestDirPath(files[0]), tweak);
- }
- else
- {
+ } else {
// Generate a foreach loop to tweak multiple files.
- cmOStringStream tw;
+ std::ostringstream tw;
this->AddTweak(tw, indent.Next(), config, "${file}", tweak);
std::string tws = tw.str();
- if(!tws.empty())
- {
+ 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 << indent << "foreach(file\n";
+ for (std::vector<std::string>::const_iterator i = files.begin();
+ i != files.end(); ++i) {
os << indent2 << "\"" << this->GetDestDirPath(*i) << "\"\n";
- }
+ }
os << indent2 << ")\n";
os << tws;
- os << indent << "ENDFOREACH()\n";
- }
+ os << indent << "endforeach()\n";
}
+ }
}
-//----------------------------------------------------------------------------
std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file)
{
// Construct the path of the file on disk after installation on
// which tweaks may be performed.
std::string toDestDirPath = "$ENV{DESTDIR}";
- if(file[0] != '/' && file[0] != '$')
- {
+ if (file[0] != '/' && file[0] != '$') {
toDestDirPath += "/";
- }
+ }
toDestDirPath += file;
return toDestDirPath;
}
-//----------------------------------------------------------------------------
void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os,
- Indent const& indent,
- const char* config,
+ Indent indent,
+ const std::string& config,
std::string const& file)
{
this->AddRPathCheckRule(os, indent, config, file);
}
-//----------------------------------------------------------------------------
void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os,
- Indent const& indent,
- const char* config,
+ Indent indent,
+ const std::string& config,
std::string const& file)
{
this->AddInstallNamePatchRule(os, indent, config, file);
this->AddChrpathPatchRule(os, indent, config, file);
+ this->AddUniversalInstallRule(os, indent, file);
this->AddRanlibRule(os, indent, file);
this->AddStripRule(os, indent, file);
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator
-::AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
- const char* config, std::string const& toDestDirPath)
+void cmInstallTargetGenerator::AddInstallNamePatchRule(
+ std::ostream& os, Indent indent, const std::string& config,
+ std::string const& toDestDirPath)
{
- if(this->ImportLibrary ||
- !(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
- this->Target->GetType() == cmTarget::MODULE_LIBRARY ||
- this->Target->GetType() == cmTarget::EXECUTABLE))
- {
+ if (this->ImportLibrary ||
+ !(this->Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->Target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->Target->GetType() == cmStateEnums::EXECUTABLE)) {
return;
- }
+ }
// Fix the install_name settings in installed binaries.
std::string installNameTool =
- this->Target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
+ this->Target->Target->GetMakefile()->GetSafeDefinition(
+ "CMAKE_INSTALL_NAME_TOOL");
- if(!installNameTool.size())
- {
+ if (installNameTool.empty()) {
return;
- }
+ }
// Build a map of build-tree install_name to install-tree install_name for
// shared libraries linked to this target.
- std::map<cmStdString, cmStdString> install_name_remap;
- if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config))
- {
- std::set<cmTarget*> const& sharedLibs = cli->GetSharedLibrariesLinked();
- for(std::set<cmTarget*>::const_iterator j = sharedLibs.begin();
- j != sharedLibs.end(); ++j)
- {
- cmTarget* tgt = *j;
+ std::map<std::string, std::string> install_name_remap;
+ if (cmComputeLinkInformation* cli =
+ 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;
// The install_name of an imported target does not change.
- if(tgt->IsImported())
- {
+ if (tgt->IsImported()) {
continue;
- }
+ }
// If the build tree and install tree use different path
// components of the install_name field then we need to create a
// mapping to be applied after installation.
std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
std::string for_install = tgt->GetInstallNameDirForInstallTree();
- if(for_build != for_install)
- {
+ if (for_build != for_install) {
// The directory portions differ. Append the filename to
// create the mapping.
- std::string fname =
- this->GetInstallFilename(tgt, config, NameSO);
+ std::string fname = this->GetInstallFilename(tgt, config, NameSO);
// Map from the build-tree install_name.
for_build += fname;
@@ -542,83 +574,72 @@ cmInstallTargetGenerator
// Store the mapping entry.
install_name_remap[for_build] = for_install;
- }
}
}
+ }
// Edit the install_name of the target itself if necessary.
std::string new_id;
- if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
- {
+ if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
std::string for_build =
this->Target->GetInstallNameDirForBuildTree(config);
- std::string for_install =
- this->Target->GetInstallNameDirForInstallTree();
+ std::string for_install = this->Target->GetInstallNameDirForInstallTree();
- if(this->Target->IsFrameworkOnApple() && for_install.empty())
- {
+ if (this->Target->IsFrameworkOnApple() && for_install.empty()) {
// Frameworks seem to have an id corresponding to their own full
// path.
// ...
// for_install = fullDestPath_without_DESTDIR_or_name;
- }
+ }
// If the install name will change on installation set the new id
// on the installed file.
- if(for_build != for_install)
- {
+ 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);
- }
}
+ }
// Write a rule to run install_name_tool to set the install-tree
// install_name value and references.
- if(!new_id.empty() || !install_name_remap.empty())
- {
- os << indent << "EXECUTE_PROCESS(COMMAND \"" << installNameTool;
+ if (!new_id.empty() || !install_name_remap.empty()) {
+ os << indent << "execute_process(COMMAND \"" << installNameTool;
os << "\"";
- if(!new_id.empty())
- {
+ if (!new_id.empty()) {
os << "\n" << indent << " -id \"" << new_id << "\"";
- }
- for(std::map<cmStdString, cmStdString>::const_iterator
- i = install_name_remap.begin();
- i != install_name_remap.end(); ++i)
- {
- os << "\n" << indent << " -change \""
- << i->first << "\" \"" << i->second << "\"";
- }
- os << "\n" << indent << " \"" << toDestDirPath << "\")\n";
}
+ for (std::map<std::string, std::string>::const_iterator i =
+ install_name_remap.begin();
+ i != install_name_remap.end(); ++i) {
+ os << "\n"
+ << indent << " -change \"" << i->first << "\" \"" << i->second
+ << "\"";
+ }
+ os << "\n" << indent << " \"" << toDestDirPath << "\")\n";
+ }
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator
-::AddRPathCheckRule(std::ostream& os, Indent const& indent,
- const char* config, std::string const& toDestDirPath)
+void cmInstallTargetGenerator::AddRPathCheckRule(
+ std::ostream& os, Indent indent, const std::string& config,
+ std::string const& toDestDirPath)
{
// Skip the chrpath if the target does not need it.
- if(this->ImportLibrary || !this->Target->IsChrpathUsed(config))
- {
+ if (this->ImportLibrary || !this->Target->IsChrpathUsed(config)) {
return;
- }
-
+ }
// Skip if on Apple
- if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
+ if (this->Target->Target->GetMakefile()->IsOn(
+ "CMAKE_PLATFORM_HAS_INSTALLNAME")) {
return;
- }
+ }
// Get the link information for this target.
// It can provide the RPATH.
cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
- if(!cli)
- {
+ if (!cli) {
return;
- }
+ }
// Get the install RPATH from the link information.
std::string newRpath = cli->GetChrpathString();
@@ -626,62 +647,90 @@ cmInstallTargetGenerator
// 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.
- os << indent << "FILE(RPATH_CHECK\n"
+ /* clang-format off */
+ os << indent << "file(RPATH_CHECK\n"
<< indent << " FILE \"" << toDestDirPath << "\"\n"
<< indent << " RPATH \"" << newRpath << "\")\n";
+ /* clang-format on */
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator
-::AddChrpathPatchRule(std::ostream& os, Indent const& indent,
- const char* config, std::string const& toDestDirPath)
+void cmInstallTargetGenerator::AddChrpathPatchRule(
+ std::ostream& os, Indent indent, const std::string& config,
+ std::string const& toDestDirPath)
{
// Skip the chrpath if the target does not need it.
- if(this->ImportLibrary || !this->Target->IsChrpathUsed(config))
- {
+ if (this->ImportLibrary || !this->Target->IsChrpathUsed(config)) {
return;
- }
+ }
// Get the link information for this target.
// It can provide the RPATH.
cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
- if(!cli)
- {
+ if (!cli) {
return;
- }
+ }
+
+ cmMakefile* mf = this->Target->Target->GetMakefile();
- if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
+ if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
// If using install_name_tool, set up the rules to modify the rpaths.
std::string installNameTool =
- this->Target->GetMakefile()->
- GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
+ mf->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
std::vector<std::string> oldRuntimeDirs, newRuntimeDirs;
cli->GetRPath(oldRuntimeDirs, false);
cli->GetRPath(newRuntimeDirs, true);
- // Note: These are separate commands to avoid install_name_tool
- // corruption on 10.6.
- for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin();
- i != oldRuntimeDirs.end(); ++i)
- {
- os << indent << "execute_process(COMMAND " << installNameTool << "\n";
- os << indent << " -delete_rpath \"" << *i << "\"\n";
- os << indent << " \"" << toDestDirPath << "\")\n";
+ std::string darwin_major_version_s =
+ mf->GetSafeDefinition("DARWIN_MAJOR_VERSION");
+
+ std::istringstream ss(darwin_major_version_s);
+ int darwin_major_version;
+ ss >> darwin_major_version;
+ if (!ss.fail() && darwin_major_version <= 9 &&
+ (!oldRuntimeDirs.empty() || !newRuntimeDirs.empty())) {
+ std::ostringstream msg;
+ msg
+ << "WARNING: Target \"" << this->Target->GetName()
+ << "\" has runtime paths which cannot be changed during install. "
+ << "To change runtime paths, OS X version 10.6 or newer is required. "
+ << "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());
+ } 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) {
+ std::string runpath =
+ mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config);
+
+ if (runpaths.find(runpath) == runpaths.end()) {
+ runpaths.insert(runpath);
+ os << indent << "execute_process(COMMAND " << installNameTool
+ << "\n";
+ os << indent << " -delete_rpath \"" << runpath << "\"\n";
+ os << indent << " \"" << toDestDirPath << "\")\n";
+ }
}
- for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin();
- i != newRuntimeDirs.end(); ++i)
- {
- os << indent << "execute_process(COMMAND " << installNameTool << "\n";
- os << indent << " -add_rpath \"" << *i << "\"\n";
- os << indent << " \"" << toDestDirPath << "\")\n";
+ runpaths.clear();
+ for (std::vector<std::string>::const_iterator i = newRuntimeDirs.begin();
+ i != newRuntimeDirs.end(); ++i) {
+ std::string runpath =
+ mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config);
+
+ if (runpaths.find(runpath) == runpaths.end()) {
+ os << indent << "execute_process(COMMAND " << installNameTool
+ << "\n";
+ os << indent << " -add_rpath \"" << runpath << "\"\n";
+ os << indent << " \"" << toDestDirPath << "\")\n";
+ }
}
}
- else
- {
+ } else {
// Construct the original rpath string to be replaced.
std::string oldRpath = cli->GetRPathString(false);
@@ -689,86 +738,102 @@ cmInstallTargetGenerator
std::string newRpath = cli->GetChrpathString();
// Skip the rule if the paths are identical
- if(oldRpath == newRpath)
- {
+ if (oldRpath == newRpath) {
return;
- }
+ }
// Write a rule to run chrpath to set the install-tree RPATH
- if(newRpath.empty())
- {
- os << indent << "FILE(RPATH_REMOVE\n"
- << indent << " FILE \"" << toDestDirPath << "\")\n";
- }
- else
- {
- os << indent << "FILE(RPATH_CHANGE\n"
- << indent << " FILE \"" << toDestDirPath << "\"\n"
- << indent << " OLD_RPATH \"" << oldRpath << "\"\n"
- << indent << " NEW_RPATH \"" << newRpath << "\")\n";
- }
- }
+ os << indent << "file(RPATH_CHANGE\n"
+ << indent << " FILE \"" << toDestDirPath << "\"\n"
+ << indent << " OLD_RPATH \"" << oldRpath << "\"\n"
+ << indent << " NEW_RPATH \"" << newRpath << "\")\n";
+ }
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator::AddStripRule(std::ostream& os,
- Indent const& indent,
- const std::string& toDestDirPath)
+void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent,
+ const std::string& toDestDirPath)
{
// don't strip static and import libraries, because it removes the only
// symbol table they have so you can't link to them anymore
- if(this->Target->GetType()==cmTarget::STATIC_LIBRARY || this->ImportLibrary)
- {
+ if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->ImportLibrary) {
return;
- }
+ }
// Don't handle OSX Bundles.
- if(this->Target->GetMakefile()->IsOn("APPLE") &&
- this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
- {
+ if (this->Target->Target->GetMakefile()->IsOn("APPLE") &&
+ this->Target->GetPropertyAsBool("MACOSX_BUNDLE")) {
return;
- }
+ }
- if(! this->Target->GetMakefile()->IsSet("CMAKE_STRIP"))
- {
+ if (!this->Target->Target->GetMakefile()->IsSet("CMAKE_STRIP")) {
return;
- }
+ }
- os << indent << "IF(CMAKE_INSTALL_DO_STRIP)\n";
- os << indent << " EXECUTE_PROCESS(COMMAND \""
- << this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
+ os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n";
+ os << indent << " execute_process(COMMAND \""
+ << this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
<< "\" \"" << toDestDirPath << "\")\n";
- os << indent << "ENDIF(CMAKE_INSTALL_DO_STRIP)\n";
+ os << indent << "endif()\n";
}
-//----------------------------------------------------------------------------
-void
-cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
- Indent const& indent,
- const std::string& toDestDirPath)
+void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, Indent indent,
+ const std::string& toDestDirPath)
{
// Static libraries need ranlib on this platform.
- if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
- {
+ if (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) {
return;
- }
+ }
// Perform post-installation processing on the file depending
// on its type.
- if(!this->Target->GetMakefile()->IsOn("APPLE"))
- {
+ if (!this->Target->Target->GetMakefile()->IsOn("APPLE")) {
return;
- }
+ }
std::string ranlib =
- this->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
- if(ranlib.empty())
- {
+ this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
+ if (ranlib.empty()) {
return;
- }
+ }
+
+ os << indent << "execute_process(COMMAND \"" << ranlib << "\" \""
+ << toDestDirPath << "\")\n";
+}
+
+void cmInstallTargetGenerator::AddUniversalInstallRule(
+ std::ostream& os, Indent indent, const std::string& toDestDirPath)
+{
+ cmMakefile const* mf = this->Target->Target->GetMakefile();
+
+ if (!mf->PlatformIsAppleIos() || !mf->IsOn("XCODE")) {
+ return;
+ }
+
+ const char* xcodeVersion = mf->GetDefinition("XCODE_VERSION");
+ if (!xcodeVersion ||
+ cmSystemTools::VersionCompareGreater("6", xcodeVersion)) {
+ return;
+ }
+
+ switch (this->Target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ break;
+
+ default:
+ return;
+ }
+
+ if (!this->Target->Target->GetPropertyAsBool("IOS_INSTALL_COMBINED")) {
+ return;
+ }
- os << indent << "EXECUTE_PROCESS(COMMAND \""
- << ranlib << "\" \"" << toDestDirPath << "\")\n";
+ os << indent << "include(CMakeIOSInstallCombined)\n";
+ os << indent << "ios_install_combined("
+ << "\"" << this->Target->Target->GetName() << "\" "
+ << "\"" << toDestDirPath << "\")\n";
}
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 8cf72f975..cf2de58f9 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -1,36 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallTargetGenerator_h
#define cmInstallTargetGenerator_h
+#include "cmConfigure.h"
+
#include "cmInstallGenerator.h"
-#include "cmTarget.h"
-#include "cmGeneratorTarget.h"
+#include "cmScriptGenerator.h"
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
/** \class cmInstallTargetGenerator
* \brief Generate target installation rules.
*/
-class cmInstallTargetGenerator: public cmInstallGenerator
+class cmInstallTargetGenerator : public cmInstallGenerator
{
public:
- cmInstallTargetGenerator(
- cmTarget& t, const char* dest, bool implib,
- const char* file_permissions = "",
- std::vector<std::string> const& configurations
- = std::vector<std::string>(),
- const char* component = "Unspecified",
- bool optional = false
- );
- virtual ~cmInstallTargetGenerator();
+ 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;
/** Select the policy for installing shared library linkable name
symlinks. */
@@ -43,7 +39,10 @@ public:
void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; }
NamelinkModeType GetNamelinkMode() const { return this->NamelinkMode; }
- std::string GetInstallFilename(const char* config) const;
+ std::string GetInstallFilename(const std::string& config) const;
+
+ void GetInstallObjectNames(std::string const& config,
+ std::vector<std::string>& objects) const;
enum NameType
{
@@ -53,52 +52,62 @@ public:
NameReal
};
- static std::string GetInstallFilename(cmTarget*target, const char* config,
+ static std::string GetInstallFilename(const cmGeneratorTarget* target,
+ const std::string& config,
NameType nameType = NameNormal);
- cmTarget* GetTarget() const { return this->Target; }
+ void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+
+ cmGeneratorTarget* GetTarget() const { return this->Target; }
+
bool IsImportLibrary() const { return this->ImportLibrary; }
+ std::string GetDestination(std::string const& config) const;
+
protected:
- virtual void GenerateScript(std::ostream& os);
- virtual void GenerateScriptForConfig(std::ostream& os,
- const char* config,
- Indent const& indent);
- typedef void (cmInstallTargetGenerator::*TweakMethod)(
- std::ostream&, Indent const&, const char*, std::string const&
- );
- void AddTweak(std::ostream& os, Indent const& indent,
- const char* config, std::string const& file,
- TweakMethod tweak);
- void AddTweak(std::ostream& os, Indent const& indent,
- const char* config, std::vector<std::string> const& files,
- TweakMethod tweak);
+ void GenerateScript(std::ostream& os) CM_OVERRIDE;
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) CM_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&);
+ 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,
+ std::vector<std::string> const& files, TweakMethod tweak);
std::string GetDestDirPath(std::string const& file);
- void PreReplacementTweaks(std::ostream& os, Indent const& indent,
- const char* config, std::string const& file);
- void PostReplacementTweaks(std::ostream& os, Indent const& indent,
- const char* config, std::string const& file);
- void AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
- const char* config,
+ void PreReplacementTweaks(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& file);
+ void PostReplacementTweaks(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& file);
+ void AddInstallNamePatchRule(std::ostream& os, Indent indent,
+ const std::string& config,
const std::string& toDestDirPath);
- void AddChrpathPatchRule(std::ostream& os, Indent const& indent,
- const char* config,
+ void AddChrpathPatchRule(std::ostream& os, Indent indent,
+ const std::string& config,
std::string const& toDestDirPath);
- void AddRPathCheckRule(std::ostream& os, Indent const& indent,
- const char* config,
+ void AddRPathCheckRule(std::ostream& os, Indent indent,
+ const std::string& config,
std::string const& toDestDirPath);
- void AddStripRule(std::ostream& os, Indent const& indent,
+ void AddStripRule(std::ostream& os, Indent indent,
const std::string& toDestDirPath);
- void AddRanlibRule(std::ostream& os, Indent const& indent,
+ void AddRanlibRule(std::ostream& os, Indent indent,
const std::string& toDestDirPath);
+ void AddUniversalInstallRule(std::ostream& os, Indent indent,
+ const std::string& toDestDirPath);
- cmTarget* Target;
- bool ImportLibrary;
+ std::string TargetName;
+ cmGeneratorTarget* Target;
std::string FilePermissions;
- bool Optional;
NamelinkModeType NamelinkMode;
- cmGeneratorTarget* GeneratorTarget;
+ bool ImportLibrary;
+ bool Optional;
};
#endif
diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx
index 277ccea43..e00eba012 100644
--- a/Source/cmInstallTargetsCommand.cxx
+++ b/Source/cmInstallTargetsCommand.cxx
@@ -1,66 +1,58 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallTargetsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <utility>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmInstallTargetsCommand.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::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Enable the install target.
- this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->EnableInstallTarget();
+ this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
- cmTargets &tgts = this->Makefile->GetTargets();
+ cmTargets& tgts = this->Makefile->GetTargets();
std::vector<std::string>::const_iterator s = args.begin();
++s;
std::string runtime_dir = "/bin";
- for (;s != args.end(); ++s)
- {
- if (*s == "RUNTIME_DIRECTORY")
- {
+ for (; s != args.end(); ++s) {
+ if (*s == "RUNTIME_DIRECTORY") {
++s;
- if ( s == args.end() )
- {
+ if (s == args.end()) {
this->SetError("called with RUNTIME_DIRECTORY but no actual "
"directory");
return false;
- }
+ }
runtime_dir = *s;
- }
- else if (tgts.find(*s) != tgts.end())
- {
- tgts[*s].SetInstallPath(args[0].c_str());
- tgts[*s].SetRuntimeInstallPath(runtime_dir.c_str());
- tgts[*s].SetHaveInstallRule(true);
- }
- else
- {
- std::string str = "Cannot find target: \"" + *s + "\" to install.";
- this->SetError(str.c_str());
- return false;
+ } else {
+ cmTargets::iterator ti = tgts.find(*s);
+ if (ti != tgts.end()) {
+ ti->second.SetInstallPath(args[0].c_str());
+ ti->second.SetRuntimeInstallPath(runtime_dir.c_str());
+ ti->second.SetHaveInstallRule(true);
+ } else {
+ std::string str = "Cannot find target: \"" + *s + "\" to install.";
+ this->SetError(str);
+ return false;
}
}
+ }
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddInstallComponent(this->Makefile->GetSafeDefinition(
- "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
return true;
}
-
diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h
index c47b38700..cc8484365 100644
--- a/Source/cmInstallTargetsCommand.h
+++ b/Source/cmInstallTargetsCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallTargetsCommand_h
#define cmInstallTargetsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmInstallTargetsCommand
* \brief Specifies where to install some targets
*
@@ -27,55 +25,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmInstallTargetsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmInstallTargetsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "install_targets";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the install(TARGETS ) command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "This command has been superceded by the install command. It "
- "is provided for compatibility with older CMake code.\n"
- " install_targets(<dir> [RUNTIME_DIRECTORY dir] target target)\n"
- "Create rules to install the listed targets into the given directory. "
- "The directory <dir> is relative to the installation prefix, which "
- "is stored in the variable CMAKE_INSTALL_PREFIX. If RUNTIME_DIRECTORY "
- "is specified, then on systems with special runtime files "
- "(Windows DLL), the files will be copied to that directory.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmInstallTargetsCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmInstallType.h b/Source/cmInstallType.h
index a8373682c..e2602cb01 100644
--- a/Source/cmInstallType.h
+++ b/Source/cmInstallType.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallType_h
#define cmInstallType_h
diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx
new file mode 100644
index 000000000..d51fd8d74
--- /dev/null
+++ b/Source/cmInstalledFile.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 "cmInstalledFile.h"
+
+#include "cmAlgorithms.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include "cmConfigure.h"
+#include <utility>
+
+cmInstalledFile::cmInstalledFile()
+ : NameExpression(CM_NULLPTR)
+{
+}
+
+cmInstalledFile::~cmInstalledFile()
+{
+ if (NameExpression) {
+ delete NameExpression;
+ }
+}
+
+cmInstalledFile::Property::Property()
+{
+}
+
+cmInstalledFile::Property::~Property()
+{
+ cmDeleteAll(this->ValueExpressions);
+}
+
+void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name)
+{
+ cmListFileBacktrace backtrace = mf->GetBacktrace();
+ cmGeneratorExpression ge(backtrace);
+
+ this->Name = name;
+ this->NameExpression = ge.Parse(name).release();
+}
+
+std::string const& cmInstalledFile::GetName() const
+{
+ return this->Name;
+}
+
+cmCompiledGeneratorExpression const& cmInstalledFile::GetNameExpression() const
+{
+ return *(this->NameExpression);
+}
+
+void cmInstalledFile::RemoveProperty(const std::string& prop)
+{
+ this->Properties.erase(prop);
+}
+
+void cmInstalledFile::SetProperty(cmMakefile const* mf,
+ const std::string& prop, const char* value)
+{
+ this->RemoveProperty(prop);
+ this->AppendProperty(mf, prop, value);
+}
+
+void cmInstalledFile::AppendProperty(cmMakefile const* mf,
+ const std::string& prop,
+ const char* value, bool /*asString*/)
+{
+ cmListFileBacktrace backtrace = mf->GetBacktrace();
+ cmGeneratorExpression ge(backtrace);
+
+ Property& property = this->Properties[prop];
+ property.ValueExpressions.push_back(ge.Parse(value).release());
+}
+
+bool cmInstalledFile::HasProperty(const std::string& prop) const
+{
+ return this->Properties.find(prop) != this->Properties.end();
+}
+
+bool cmInstalledFile::GetProperty(const std::string& prop,
+ std::string& value) const
+{
+ PropertyMapType::const_iterator i = this->Properties.find(prop);
+ if (i == this->Properties.end()) {
+ return false;
+ }
+
+ Property const& property = i->second;
+
+ std::string output;
+ std::string separator;
+
+ for (ExpressionVectorType::const_iterator j =
+ property.ValueExpressions.begin();
+ j != property.ValueExpressions.end(); ++j) {
+ output += separator;
+ output += (*j)->GetInput();
+ separator = ";";
+ }
+
+ value = output;
+ return true;
+}
+
+bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const
+{
+ std::string value;
+ bool isSet = this->GetProperty(prop, value);
+ return isSet && cmSystemTools::IsOn(value.c_str());
+}
+
+void cmInstalledFile::GetPropertyAsList(const std::string& prop,
+ std::vector<std::string>& list) const
+{
+ std::string value;
+ this->GetProperty(prop, value);
+
+ list.clear();
+ cmSystemTools::ExpandListArgument(value, list);
+}
diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h
new file mode 100644
index 000000000..fbf754ffd
--- /dev/null
+++ b/Source/cmInstalledFile.h
@@ -0,0 +1,75 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmInstalledFile_h
+#define cmInstalledFile_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmGeneratorExpression.h"
+#include "cm_auto_ptr.hxx"
+
+#include <map>
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+/** \class cmInstalledFile
+ * \brief Represents a file intended for installation.
+ *
+ * cmInstalledFile represents a file intended for installation.
+ */
+class cmInstalledFile
+{
+public:
+ typedef CM_AUTO_PTR<cmCompiledGeneratorExpression>
+ CompiledGeneratorExpressionPtrType;
+
+ typedef std::vector<cmCompiledGeneratorExpression*> ExpressionVectorType;
+
+ struct Property
+ {
+ Property();
+ ~Property();
+
+ ExpressionVectorType ValueExpressions;
+ };
+
+ typedef std::map<std::string, Property> PropertyMapType;
+
+ cmInstalledFile();
+
+ ~cmInstalledFile();
+
+ void RemoveProperty(const std::string& prop);
+
+ void SetProperty(cmMakefile const* mf, const std::string& prop,
+ const char* value);
+
+ void AppendProperty(cmMakefile const* mf, const std::string& prop,
+ const char* value, bool asString = false);
+
+ bool HasProperty(const std::string& prop) const;
+
+ bool GetProperty(const std::string& prop, std::string& value) const;
+
+ bool GetPropertyAsBool(const std::string& prop) const;
+
+ void GetPropertyAsList(const std::string& prop,
+ std::vector<std::string>& list) const;
+
+ void SetName(cmMakefile* mf, const std::string& name);
+
+ std::string const& GetName() const;
+
+ cmCompiledGeneratorExpression const& GetNameExpression() const;
+
+ PropertyMapType const& GetProperties() const { return this->Properties; }
+
+private:
+ std::string Name;
+ cmCompiledGeneratorExpression* NameExpression;
+ PropertyMapType Properties;
+};
+
+#endif
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index 4412414a4..9b0c28817 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -1,70 +1,66 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLinkDirectoriesCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmLinkDirectoriesCommand.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
// cmLinkDirectoriesCommand
-bool cmLinkDirectoriesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmLinkDirectoriesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
- for(std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
this->AddLinkDir(*i);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
{
std::string unixPath = dir;
cmSystemTools::ConvertToUnixSlashes(unixPath);
- if(!cmSystemTools::FileIsFullPath(unixPath.c_str()))
- {
+ if (!cmSystemTools::FileIsFullPath(unixPath.c_str())) {
bool convertToAbsolute = false;
- cmOStringStream e;
+ std::ostringstream e;
+ /* clang-format off */
e << "This command specifies the relative path\n"
<< " " << unixPath << "\n"
<< "as a link directory.\n";
- cmPolicies* policies = this->Makefile->GetPolicies();
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015))
- {
+ /* clang-format on */
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015)) {
case cmPolicies::WARN:
- e << policies->GetPolicyWarning(cmPolicies::CMP0015);
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015);
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
case cmPolicies::OLD:
// OLD behavior does not convert
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
- e << policies->GetRequiredPolicyError(cmPolicies::CMP0015);
+ e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015);
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ CM_FALLTHROUGH;
case cmPolicies::NEW:
// NEW behavior converts
convertToAbsolute = true;
break;
- }
- if (convertToAbsolute)
- {
- std::string tmp = this->Makefile->GetStartDirectory();
+ }
+ if (convertToAbsolute) {
+ std::string tmp = this->Makefile->GetCurrentSourceDirectory();
tmp += "/";
tmp += unixPath;
unixPath = tmp;
- }
}
- this->Makefile->AddLinkDirectory(unixPath.c_str());
+ }
+ this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str());
}
diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h
index 9218f448d..b64e48d70 100644
--- a/Source/cmLinkDirectoriesCommand.h
+++ b/Source/cmLinkDirectoriesCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLinkDirectoriesCommand_h
#define cmLinkDirectoriesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmLinkDirectoriesCommand
* \brief Define a list of directories containing files to link.
*
@@ -28,55 +26,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmLinkDirectoriesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmLinkDirectoriesCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "link_directories";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Specify directories in which the linker will look for libraries.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " link_directories(directory1 directory2 ...)\n"
- "Specify the paths in which the linker should search for libraries. "
- "The command will apply only to targets created after it is called. "
- "Relative paths given to this command are interpreted as relative to "
- "the current source directory, see CMP0015. \n"
- "Note that this command is rarely necessary. Library locations "
- "returned by find_package() and find_library() are absolute paths. "
- "Pass these absolute library file paths directly to the "
- "target_link_libraries() command. CMake will ensure the linker finds "
- "them."
- ;
- }
-
- cmTypeMacro(cmLinkDirectoriesCommand, cmCommand);
private:
void AddLinkDir(std::string const& dir);
};
-
-
#endif
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
new file mode 100644
index 000000000..f0fded21f
--- /dev/null
+++ b/Source/cmLinkItem.h
@@ -0,0 +1,162 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmLinkItem_h
+#define cmLinkItem_h
+
+#include "cmConfigure.h"
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "cmListFileCache.h"
+#include "cmSystemTools.h"
+#include "cmTargetLinkLibraryType.h"
+
+class cmGeneratorTarget;
+
+// Basic information about each link item.
+class cmLinkItem : public std::string
+{
+ typedef std::string std_string;
+
+public:
+ cmLinkItem()
+ : std_string()
+ , Target(CM_NULLPTR)
+ {
+ }
+ cmLinkItem(const std_string& n, cmGeneratorTarget const* t)
+ : std_string(n)
+ , Target(t)
+ {
+ }
+ cmGeneratorTarget const* Target;
+};
+
+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;
+};
+
+/** The link implementation specifies the direct library
+ dependencies needed by the object files of the target. */
+struct cmLinkImplementationLibraries
+{
+ // Libraries linked directly in this configuration.
+ std::vector<cmLinkImplItem> Libraries;
+
+ // Libraries linked directly in other configurations.
+ // Needed only for OLD behavior of CMP0003.
+ std::vector<cmLinkItem> WrongConfigLibraries;
+};
+
+struct cmLinkInterfaceLibraries
+{
+ // Libraries listed in the interface.
+ std::vector<cmLinkItem> Libraries;
+};
+
+struct cmLinkInterface : public cmLinkInterfaceLibraries
+{
+ // Languages whose runtime libraries must be linked.
+ std::vector<std::string> Languages;
+
+ // Shared library dependencies needed for linking on some platforms.
+ std::vector<cmLinkItem> SharedDeps;
+
+ // Number of repetitions of a strongly connected component of two
+ // or more static libraries.
+ unsigned int Multiplicity;
+
+ // Libraries listed for other configurations.
+ // Needed only for OLD behavior of CMP0003.
+ std::vector<cmLinkItem> WrongConfigLibraries;
+
+ bool ImplementationIsInterface;
+
+ cmLinkInterface()
+ : Multiplicity(0)
+ , 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;
+};
+
+struct cmHeadToLinkInterfaceMap
+ : public std::map<cmGeneratorTarget const*, cmOptionalLinkInterface>
+{
+};
+
+struct cmLinkImplementation : public cmLinkImplementationLibraries
+{
+ // Languages whose runtime libraries must be linked.
+ std::vector<std::string> Languages;
+};
+
+// Cache link implementation computation from each configuration.
+struct cmOptionalLinkImplementation : public cmLinkImplementation
+{
+ cmOptionalLinkImplementation()
+ : LibrariesDone(false)
+ , LanguagesDone(false)
+ , HadHeadSensitiveCondition(false)
+ {
+ }
+ bool LibrariesDone;
+ bool LanguagesDone;
+ bool HadHeadSensitiveCondition;
+};
+
+/** Compute the link type to use for the given configuration. */
+inline cmTargetLinkLibraryType CMP0003_ComputeLinkType(
+ const std::string& config, std::vector<std::string> const& debugConfigs)
+{
+ // No configuration is always optimized.
+ if (config.empty()) {
+ return OPTIMIZED_LibraryType;
+ }
+
+ // 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()) {
+ return DEBUG_LibraryType;
+ }
+ // The current configuration is not a debug configuration.
+ return OPTIMIZED_LibraryType;
+}
+
+#endif
diff --git a/Source/cmLinkLibrariesCommand.cxx b/Source/cmLinkLibrariesCommand.cxx
index 2f1db2aa0..708ec8c00 100644
--- a/Source/cmLinkLibrariesCommand.cxx
+++ b/Source/cmLinkLibrariesCommand.cxx
@@ -1,59 +1,41 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLinkLibrariesCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmLinkLibrariesCommand.h"
+class cmExecutionStatus;
// cmLinkLibrariesCommand
-bool cmLinkLibrariesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmLinkLibrariesCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
// add libraries, nothe 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)
- {
- if (*i == "debug")
- {
+ for (std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
+ if (*i == "debug") {
++i;
- if(i == args.end())
- {
+ if (i == args.end()) {
this->SetError("The \"debug\" argument must be followed by "
"a library");
return false;
- }
- this->Makefile->AddLinkLibrary(i->c_str(),
- cmTarget::DEBUG);
}
- else if (*i == "optimized")
- {
+ this->Makefile->AppendProperty("LINK_LIBRARIES", "debug");
+ } else if (*i == "optimized") {
++i;
- if(i == args.end())
- {
+ if (i == args.end()) {
this->SetError("The \"optimized\" argument must be followed by "
"a library");
return false;
- }
- this->Makefile->AddLinkLibrary(i->c_str(),
- cmTarget::OPTIMIZED);
- }
- else
- {
- this->Makefile->AddLinkLibrary(i->c_str());
}
+ this->Makefile->AppendProperty("LINK_LIBRARIES", "optimized");
}
+ this->Makefile->AppendProperty("LINK_LIBRARIES", i->c_str());
+ }
return true;
}
-
diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h
index c450a1cb9..f1b3a6816 100644
--- a/Source/cmLinkLibrariesCommand.h
+++ b/Source/cmLinkLibrariesCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLinkLibrariesCommand_h
#define cmLinkLibrariesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmLinkLibrariesCommand
* \brief Specify a list of libraries to link into executables.
*
@@ -27,57 +25,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmLinkLibrariesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmLinkLibrariesCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "link_libraries";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the target_link_libraries() command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "Link libraries to all targets added later.\n"
- " link_libraries(library1 <debug | optimized> library2 ...)\n"
- "Specify a list of libraries to be linked into "
- "any following targets (typically added with the add_executable "
- "or add_library calls). This command is passed "
- "down to all subdirectories. "
- "The debug and optimized strings may be used to indicate that "
- "the next library listed is to be used only for that specific "
- "type of build.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmLinkLibrariesCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
new file mode 100644
index 000000000..c0f702e25
--- /dev/null
+++ b/Source/cmLinkLineComputer.cxx
@@ -0,0 +1,192 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmLinkLineComputer.h"
+
+#include <sstream>
+#include <vector>
+
+#include "cmComputeLinkInformation.h"
+#include "cmGeneratorTarget.h"
+#include "cmOutputConverter.h"
+#include "cmStateDirectory.h"
+#include "cmStateTypes.h"
+
+cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir)
+ : StateDir(stateDir)
+ , OutputConverter(outputConverter)
+ , ForResponse(false)
+ , UseWatcomQuote(false)
+ , Relink(false)
+{
+}
+
+cmLinkLineComputer::~cmLinkLineComputer()
+{
+}
+
+void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
+{
+ this->UseWatcomQuote = useWatcomQuote;
+}
+
+void cmLinkLineComputer::SetForResponse(bool forResponse)
+{
+ this->ForResponse = forResponse;
+}
+
+void cmLinkLineComputer::SetRelink(bool relink)
+{
+ this->Relink = relink;
+}
+
+std::string cmLinkLineComputer::ConvertToLinkReference(
+ std::string const& lib) const
+{
+ std::string relLib = lib;
+
+ if (cmOutputConverter::ContainedInDirectory(
+ this->StateDir.GetCurrentBinary(), lib, this->StateDir)) {
+ relLib = cmOutputConverter::ForceToRelativePath(
+ this->StateDir.GetCurrentBinary(), lib);
+ }
+ return relLib;
+}
+
+std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
+{
+ std::string linkLibs;
+ typedef cmComputeLinkInformation::ItemVector 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) {
+ continue;
+ }
+ if (li->IsPath) {
+ linkLibs +=
+ this->ConvertToOutputFormat(this->ConvertToLinkReference(li->Value));
+ } else {
+ linkLibs += li->Value;
+ }
+ linkLibs += " ";
+ }
+ return linkLibs;
+}
+
+std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
+{
+ cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
+ ? cmOutputConverter::RESPONSE
+ : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
+ : cmOutputConverter::SHELL);
+
+ return this->OutputConverter->ConvertToOutputFormat(input, shellFormat);
+}
+
+std::string cmLinkLineComputer::ConvertToOutputForExisting(
+ std::string const& input)
+{
+ cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
+ ? cmOutputConverter::RESPONSE
+ : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
+ : cmOutputConverter::SHELL);
+
+ return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat);
+}
+
+std::string cmLinkLineComputer::ComputeLinkPath(
+ cmComputeLinkInformation& cli, std::string const& libPathFlag,
+ 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 += " ";
+ }
+ return linkPath;
+}
+
+std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
+{
+ std::string rpath;
+ // Check what kind of rpath flags to use.
+ if (cli.GetRuntimeSep().empty()) {
+ // Each rpath entry gets its own option ("-R a -R b -R c")
+ std::vector<std::string> runtimeDirs;
+ cli.GetRPath(runtimeDirs, this->Relink);
+
+ for (std::vector<std::string>::iterator ri = runtimeDirs.begin();
+ ri != runtimeDirs.end(); ++ri) {
+ rpath += cli.GetRuntimeFlag();
+ rpath += this->ConvertToOutputFormat(*ri);
+ rpath += " ";
+ }
+ } else {
+ // All rpath entries are combined ("-Wl,-rpath,a:b:c").
+ std::string rpathString = cli.GetRPathString(this->Relink);
+
+ // Store the rpath option in the stream.
+ if (!rpathString.empty()) {
+ rpath += cli.GetRuntimeFlag();
+ rpath +=
+ this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
+ rpath += " ";
+ }
+ }
+ return rpath;
+}
+
+std::string cmLinkLineComputer::ComputeFrameworkPath(
+ cmComputeLinkInformation& cli, std::string const& fwSearchFlag)
+{
+ 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) {
+ frameworkPath += fwSearchFlag;
+ frameworkPath += this->ConvertToOutputFormat(*fdi);
+ frameworkPath += " ";
+ }
+ }
+ return frameworkPath;
+}
+
+std::string cmLinkLineComputer::ComputeLinkLibraries(
+ cmComputeLinkInformation& cli, std::string const& stdLibString)
+{
+ std::ostringstream fout;
+ fout << this->ComputeRPath(cli);
+
+ // Write the library flags to the build rule.
+ fout << this->ComputeLinkLibs(cli);
+
+ // Add the linker runtime search path if any.
+ std::string rpath_link = cli.GetRPathLinkString();
+ if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
+ fout << cli.GetRPathLinkFlag();
+ fout << this->OutputConverter->EscapeForShell(rpath_link,
+ !this->ForResponse);
+ fout << " ";
+ }
+
+ if (!stdLibString.empty()) {
+ fout << stdLibString << " ";
+ }
+
+ return fout.str();
+}
+
+std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
+ std::string const& config)
+{
+ return target->GetLinkerLanguage(config);
+}
diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h
new file mode 100644
index 000000000..d33e8d1ff
--- /dev/null
+++ b/Source/cmLinkLineComputer.h
@@ -0,0 +1,60 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmLinkLineComputer_h
+#define cmLinkLineComputer_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#include "cmStateDirectory.h"
+
+class cmComputeLinkInformation;
+class cmGeneratorTarget;
+class cmOutputConverter;
+
+class cmLinkLineComputer
+{
+ CM_DISABLE_COPY(cmLinkLineComputer)
+
+public:
+ cmLinkLineComputer(cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir);
+ virtual ~cmLinkLineComputer();
+
+ void SetUseWatcomQuote(bool useWatcomQuote);
+ void SetForResponse(bool forResponse);
+ void SetRelink(bool relink);
+
+ virtual std::string ConvertToLinkReference(std::string const& input) const;
+
+ std::string ComputeLinkPath(cmComputeLinkInformation& cli,
+ std::string const& libPathFlag,
+ std::string const& libPathTerminator);
+
+ std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
+ std::string const& fwSearchFlag);
+
+ virtual std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
+ std::string const& stdLibString);
+
+ virtual std::string GetLinkerLanguage(cmGeneratorTarget* target,
+ std::string const& config);
+
+protected:
+ std::string ComputeLinkLibs(cmComputeLinkInformation& cli);
+ std::string ComputeRPath(cmComputeLinkInformation& cli);
+
+ std::string ConvertToOutputFormat(std::string const& input);
+ std::string ConvertToOutputForExisting(std::string const& input);
+
+ cmStateDirectory StateDir;
+ cmOutputConverter* OutputConverter;
+
+ bool ForResponse;
+ bool UseWatcomQuote;
+ bool Relink;
+};
+
+#endif
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
new file mode 100644
index 000000000..942e9b92c
--- /dev/null
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -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. */
+
+#include "cmLinkLineDeviceComputer.h"
+
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include "cmComputeLinkInformation.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmStateTypes.h"
+
+class cmOutputConverter;
+
+cmLinkLineDeviceComputer::cmLinkLineDeviceComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
+ : cmLinkLineComputer(outputConverter, stateDir)
+{
+}
+
+cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer()
+{
+}
+
+std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
+ cmComputeLinkInformation& cli, std::string const& stdLibString)
+{
+ // Write the library flags to the build rule.
+ std::ostringstream fout;
+ typedef cmComputeLinkInformation::ItemVector 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;
+ }
+
+ 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;
+ }
+
+ if (skippable) {
+ continue;
+ }
+
+ std::set<std::string> langs;
+ li->Target->GetLanguages(langs, config);
+ if (langs.count("CUDA") == 0) {
+ continue;
+ }
+
+ if (li->IsPath) {
+ fout << this->ConvertToOutputFormat(
+ this->ConvertToLinkReference(li->Value));
+ } else {
+ fout << li->Value;
+ }
+ fout << " ";
+ }
+
+ if (!stdLibString.empty()) {
+ fout << stdLibString << " ";
+ }
+
+ return fout.str();
+}
+
+std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
+ std::string const&)
+{
+ return "CUDA";
+}
+
+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/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
new file mode 100644
index 000000000..c3fac6182
--- /dev/null
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -0,0 +1,52 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmLinkLineDeviceComputer_h
+#define cmLinkLineDeviceComputer_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#include "cmLinkLineComputer.h"
+
+class cmComputeLinkInformation;
+class cmGeneratorTarget;
+class cmGlobalNinjaGenerator;
+class cmOutputConverter;
+class cmStateDirectory;
+
+class cmLinkLineDeviceComputer : public cmLinkLineComputer
+{
+ CM_DISABLE_COPY(cmLinkLineDeviceComputer)
+
+public:
+ cmLinkLineDeviceComputer(cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir);
+ ~cmLinkLineDeviceComputer() CM_OVERRIDE;
+
+ std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
+ std::string const& stdLibString)
+ CM_OVERRIDE;
+
+ std::string GetLinkerLanguage(cmGeneratorTarget* target,
+ std::string const& config) CM_OVERRIDE;
+};
+
+class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer
+{
+ CM_DISABLE_COPY(cmNinjaLinkLineDeviceComputer)
+
+public:
+ cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir,
+ cmGlobalNinjaGenerator const* gg);
+
+ std::string ConvertToLinkReference(std::string const& input) const
+ CM_OVERRIDE;
+
+private:
+ cmGlobalNinjaGenerator const* GG;
+};
+
+#endif
diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h
new file mode 100644
index 000000000..55592cb35
--- /dev/null
+++ b/Source/cmLinkedTree.h
@@ -0,0 +1,193 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmLinkedTree_h
+#define cmLinkedTree_h
+
+#include "cmConfigure.h"
+
+#include <assert.h>
+#include <iterator>
+#include <vector>
+
+/**
+ @brief A adaptor for traversing a tree structure in a vector
+
+ This class is not intended to be wholly generic like a standard library
+ container adaptor. Mostly it exists to facilitate code sharing for the
+ needs of the cmState. For example, the Truncate() method is a specific
+ requirement of the cmState.
+
+ An empty cmLinkedTree provides a Root() method, and an Push() method,
+ each of which return iterators. A Tree can be built up by extending
+ from the root, and then extending from any other iterator.
+
+ An iterator resulting from this tree construction can be
+ forward-only-iterated toward the root. Extending the tree never
+ invalidates existing iterators.
+ */
+template <typename T>
+class cmLinkedTree
+{
+ typedef typename std::vector<T>::size_type PositionType;
+ typedef T* PointerType;
+ typedef T& ReferenceType;
+
+public:
+ class iterator : public std::iterator<std::forward_iterator_tag, T>
+ {
+ friend class cmLinkedTree;
+ cmLinkedTree* Tree;
+
+ // The Position is always 'one past the end'.
+ PositionType Position;
+
+ iterator(cmLinkedTree* tree, PositionType pos)
+ : Tree(tree)
+ , Position(pos)
+ {
+ }
+
+ public:
+ iterator()
+ : Tree(CM_NULLPTR)
+ , Position(0)
+ {
+ }
+
+ void operator++()
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ assert(this->Position <= this->Tree->Data.size());
+ assert(this->Position > 0);
+ this->Position = this->Tree->UpPositions[this->Position - 1];
+ }
+
+ PointerType operator->() const
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ assert(this->Position <= this->Tree->Data.size());
+ assert(this->Position > 0);
+ return this->Tree->GetPointer(this->Position - 1);
+ }
+
+ PointerType operator->()
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ assert(this->Position <= this->Tree->Data.size());
+ assert(this->Position > 0);
+ return this->Tree->GetPointer(this->Position - 1);
+ }
+
+ ReferenceType operator*() const
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ assert(this->Position <= this->Tree->Data.size());
+ assert(this->Position > 0);
+ return this->Tree->GetReference(this->Position - 1);
+ }
+
+ ReferenceType operator*()
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ assert(this->Position <= this->Tree->Data.size());
+ assert(this->Position > 0);
+ return this->Tree->GetReference(this->Position - 1);
+ }
+
+ bool operator==(iterator other) const
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ assert(this->Tree == other.Tree);
+ return this->Position == other.Position;
+ }
+
+ bool operator!=(iterator other) const
+ {
+ assert(this->Tree);
+ assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+ return !(*this == other);
+ }
+
+ bool IsValid() const
+ {
+ if (!this->Tree) {
+ return false;
+ }
+ return this->Position <= this->Tree->Data.size();
+ }
+
+ bool StrictWeakOrdered(iterator other) const
+ {
+ assert(this->Tree);
+ assert(this->Tree == other.Tree);
+ return this->Position < other.Position;
+ }
+ };
+
+ iterator Root() const
+ {
+ return iterator(const_cast<cmLinkedTree*>(this), 0);
+ }
+
+ iterator Push(iterator it) { return Push_impl(it, T()); }
+
+ iterator Push(iterator it, T t) { return Push_impl(it, t); }
+
+ bool IsLast(iterator it) { return it.Position == this->Data.size(); }
+
+ iterator Pop(iterator it)
+ {
+ assert(!this->Data.empty());
+ assert(this->UpPositions.size() == this->Data.size());
+ bool const isLast = this->IsLast(it);
+ ++it;
+ // If this is the last entry then no other entry can refer
+ // to it so we can drop its storage.
+ if (isLast) {
+ this->Data.pop_back();
+ this->UpPositions.pop_back();
+ }
+ return it;
+ }
+
+ iterator Truncate()
+ {
+ assert(!this->UpPositions.empty());
+ this->UpPositions.erase(this->UpPositions.begin() + 1,
+ this->UpPositions.end());
+ assert(!this->Data.empty());
+ this->Data.erase(this->Data.begin() + 1, this->Data.end());
+ return iterator(this, 1);
+ }
+
+ void Clear()
+ {
+ this->UpPositions.clear();
+ this->Data.clear();
+ }
+
+private:
+ T& GetReference(PositionType pos) { return this->Data[pos]; }
+
+ T* GetPointer(PositionType pos) { return &this->Data[pos]; }
+
+ 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);
+ return iterator(this, this->UpPositions.size());
+ }
+
+ std::vector<T> Data;
+ std::vector<PositionType> UpPositions;
+};
+
+#endif
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index df64695aa..0542c4fce 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -1,147 +1,116 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmListCommand.h"
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/SystemTools.hxx>
-#include <stdlib.h> // required for atoi
-#include <ctype.h>
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
#include <assert.h>
-//----------------------------------------------------------------------------
-bool cmListCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+#include <iterator>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h> // required for atoi
+
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+bool cmListCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2)
- {
+ 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")
- {
+ const std::string& subCommand = args[0];
+ if (subCommand == "LENGTH") {
return this->HandleLengthCommand(args);
- }
- if(subCommand == "GET")
- {
+ }
+ if (subCommand == "GET") {
return this->HandleGetCommand(args);
- }
- if(subCommand == "APPEND")
- {
+ }
+ if (subCommand == "APPEND") {
return this->HandleAppendCommand(args);
- }
- if(subCommand == "FIND")
- {
+ }
+ if (subCommand == "FIND") {
return this->HandleFindCommand(args);
- }
- if(subCommand == "INSERT")
- {
+ }
+ if (subCommand == "INSERT") {
return this->HandleInsertCommand(args);
- }
- if(subCommand == "REMOVE_AT")
- {
+ }
+ if (subCommand == "REMOVE_AT") {
return this->HandleRemoveAtCommand(args);
- }
- if(subCommand == "REMOVE_ITEM")
- {
+ }
+ if (subCommand == "REMOVE_ITEM") {
return this->HandleRemoveItemCommand(args);
- }
- if(subCommand == "REMOVE_DUPLICATES")
- {
+ }
+ if (subCommand == "REMOVE_DUPLICATES") {
return this->HandleRemoveDuplicatesCommand(args);
- }
- if(subCommand == "SORT")
- {
+ }
+ if (subCommand == "SORT") {
return this->HandleSortCommand(args);
- }
- if(subCommand == "REVERSE")
- {
+ }
+ if (subCommand == "REVERSE") {
return this->HandleReverseCommand(args);
- }
+ }
+ if (subCommand == "FILTER") {
+ return this->HandleFilterCommand(args);
+ }
- std::string e = "does not recognize sub-command "+subCommand;
- this->SetError(e.c_str());
+ std::string e = "does not recognize sub-command " + subCommand;
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
-bool cmListCommand::GetListString(std::string& listString, const char* var)
+bool cmListCommand::GetListString(std::string& listString,
+ const std::string& var)
{
- if ( !var )
- {
- return false;
- }
// get the old value
- const char* cacheValue
- = this->Makefile->GetDefinition(var);
- if(!cacheValue)
- {
+ const char* cacheValue = this->Makefile->GetDefinition(var);
+ if (!cacheValue) {
return false;
- }
+ }
listString = cacheValue;
return true;
}
-//----------------------------------------------------------------------------
-bool cmListCommand::GetList(std::vector<std::string>& list, const char* var)
+bool cmListCommand::GetList(std::vector<std::string>& list,
+ const std::string& var)
{
std::string listString;
- if ( !this->GetListString(listString, var) )
- {
+ if (!this->GetListString(listString, var)) {
return false;
- }
+ }
// if the size of the list
- if(listString.size() == 0)
- {
+ if (listString.empty()) {
return true;
- }
+ }
// expand the variable into a list
cmSystemTools::ExpandListArgument(listString, list, true);
- // check the list for empty values
- bool hasEmpty = false;
- for(std::vector<std::string>::iterator i = list.begin();
- i != list.end(); ++i)
- {
- if(i->size() == 0)
- {
- hasEmpty = true;
- break;
- }
- }
// if no empty elements then just return
- if(!hasEmpty)
- {
+ if (std::find(list.begin(), list.end(), std::string()) == list.end()) {
return true;
- }
+ }
// if we have empty elements we need to check policy CMP0007
- switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0007))
- {
- case cmPolicies::WARN:
- {
+ switch (this->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 = this->Makefile->GetPolicies()->
- GetPolicyWarning(cmPolicies::CMP0007);
+ std::string warn = cmPolicies::GetPolicyWarning(cmPolicies::CMP0007);
warn += " List has value = [";
warn += listString;
warn += "].";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
- warn);
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, warn);
return true;
- }
+ }
case cmPolicies::OLD:
// OLD behavior is to allow compatibility, so recall
// ExpandListArgument without the true which will remove
@@ -155,22 +124,18 @@ bool cmListCommand::GetList(std::vector<std::string>& list, const char* var)
case cmPolicies::REQUIRED_ALWAYS:
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- this->Makefile->GetPolicies()
- ->GetRequiredPolicyError(cmPolicies::CMP0007)
- );
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007));
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
this->SetError("sub-command LENGTH requires two arguments.");
return false;
- }
+ }
const std::string& listName = args[1];
const std::string& variableName = args[args.size() - 1];
@@ -178,433 +143,403 @@ bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args)
// 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.c_str());
+ this->GetList(varArgsExpanded, listName);
size_t length = varArgsExpanded.size();
char buffer[1024];
sprintf(buffer, "%d", static_cast<int>(length));
- this->Makefile->AddDefinition(variableName.c_str(), buffer);
+ this->Makefile->AddDefinition(variableName, buffer);
return true;
}
-//----------------------------------------------------------------------------
bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
{
- if(args.size() < 4)
- {
+ if (args.size() < 4) {
this->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];
// expand the variable
std::vector<std::string> varArgsExpanded;
- if ( !this->GetList(varArgsExpanded, listName.c_str()) )
- {
- this->Makefile->AddDefinition(variableName.c_str(), "NOTFOUND");
+ if (!this->GetList(varArgsExpanded, listName)) {
+ this->Makefile->AddDefinition(variableName, "NOTFOUND");
return true;
- }
+ }
// FIXME: Add policy to make non-existing lists an error like empty lists.
- if(varArgsExpanded.empty())
- {
+ if (varArgsExpanded.empty()) {
this->SetError("GET given empty list");
return false;
- }
+ }
std::string value;
size_t cc;
const char* sep = "";
- for ( cc = 2; cc < args.size()-1; cc ++ )
- {
+ size_t nitem = varArgsExpanded.size();
+ for (cc = 2; cc < args.size() - 1; cc++) {
int item = atoi(args[cc].c_str());
value += sep;
sep = ";";
- size_t nitem = varArgsExpanded.size();
- if ( item < 0 )
- {
+ if (item < 0) {
item = (int)nitem + item;
- }
- if ( item < 0 || nitem <= (size_t)item )
- {
- cmOStringStream str;
- str << "index: " << item << " out of range (-"
- << varArgsExpanded.size() << ", "
- << varArgsExpanded.size()-1 << ")";
- this->SetError(str.str().c_str());
+ }
+ if (item < 0 || nitem <= (size_t)item) {
+ std::ostringstream str;
+ str << "index: " << item << " out of range (-" << nitem << ", "
+ << nitem - 1 << ")";
+ this->SetError(str.str());
return false;
- }
- value += varArgsExpanded[item];
}
+ value += varArgsExpanded[item];
+ }
- this->Makefile->AddDefinition(variableName.c_str(), value.c_str());
+ this->Makefile->AddDefinition(variableName, value.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args)
{
assert(args.size() >= 2);
// Skip if nothing to append.
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
return true;
- }
+ }
const std::string& listName = args[1];
// expand the variable
std::string listString;
- this->GetListString(listString, listName.c_str());
- size_t cc;
- for ( cc = 2; cc < args.size(); ++ cc )
- {
- if(listString.size())
- {
- listString += ";";
- }
- listString += args[cc];
- }
+ this->GetListString(listString, listName);
+
+ if (!listString.empty() && !args.empty()) {
+ listString += ";";
+ }
+ listString += cmJoin(cmMakeRange(args).advance(2), ";");
- this->Makefile->AddDefinition(listName.c_str(), listString.c_str());
+ this->Makefile->AddDefinition(listName, listString.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args)
{
- if(args.size() != 4)
- {
+ if (args.size() != 4) {
this->SetError("sub-command FIND requires three arguments.");
return false;
- }
+ }
const std::string& listName = args[1];
const std::string& variableName = args[args.size() - 1];
// expand the variable
std::vector<std::string> varArgsExpanded;
- if ( !this->GetList(varArgsExpanded, listName.c_str()) )
- {
- this->Makefile->AddDefinition(variableName.c_str(), "-1");
+ if (!this->GetList(varArgsExpanded, listName)) {
+ this->Makefile->AddDefinition(variableName, "-1");
return true;
- }
-
- std::vector<std::string>::iterator it;
- unsigned int index = 0;
- for ( it = varArgsExpanded.begin(); it != varArgsExpanded.end(); ++ it )
- {
- if ( *it == args[2] )
- {
- char indexString[32];
- sprintf(indexString, "%d", index);
- this->Makefile->AddDefinition(variableName.c_str(), indexString);
- return true;
- }
- index++;
- }
+ }
+
+ std::vector<std::string>::iterator 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());
+ return true;
+ }
- this->Makefile->AddDefinition(variableName.c_str(), "-1");
+ this->Makefile->AddDefinition(variableName, "-1");
return true;
}
-//----------------------------------------------------------------------------
bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
{
- if(args.size() < 4)
- {
+ if (args.size() < 4) {
this->SetError("sub-command INSERT requires at least three arguments.");
return false;
- }
+ }
const std::string& listName = args[1];
// expand the variable
int item = atoi(args[2].c_str());
std::vector<std::string> varArgsExpanded;
- if((!this->GetList(varArgsExpanded, listName.c_str())
- || varArgsExpanded.empty()) && item != 0)
- {
- cmOStringStream str;
+ if ((!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) &&
+ item != 0) {
+ std::ostringstream str;
str << "index: " << item << " out of range (0, 0)";
- this->SetError(str.str().c_str());
+ this->SetError(str.str());
return false;
- }
+ }
- if ( varArgsExpanded.size() != 0 )
- {
+ if (!varArgsExpanded.empty()) {
size_t nitem = varArgsExpanded.size();
- if ( item < 0 )
- {
+ if (item < 0) {
item = (int)nitem + item;
- }
- if ( item < 0 || nitem <= (size_t)item )
- {
- cmOStringStream str;
- str << "index: " << item << " out of range (-"
- << varArgsExpanded.size() << ", "
- << (varArgsExpanded.size() == 0?0:(varArgsExpanded.size()-1)) << ")";
- this->SetError(str.str().c_str());
- return false;
- }
}
- size_t cc;
- size_t cnt = 0;
- for ( cc = 3; cc < args.size(); ++ cc )
- {
- varArgsExpanded.insert(varArgsExpanded.begin()+item+cnt, args[cc]);
- cnt ++;
+ 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());
+ return false;
}
+ }
- std::string value;
- const char* sep = "";
- for ( cc = 0; cc < varArgsExpanded.size(); cc ++ )
- {
- value += sep;
- value += varArgsExpanded[cc];
- sep = ";";
- }
+ varArgsExpanded.insert(varArgsExpanded.begin() + item, args.begin() + 3,
+ args.end());
- this->Makefile->AddDefinition(listName.c_str(), value.c_str());
+ std::string value = cmJoin(varArgsExpanded, ";");
+ this->Makefile->AddDefinition(listName, value.c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmListCommand
-::HandleRemoveItemCommand(std::vector<std::string> const& args)
+bool cmListCommand::HandleRemoveItemCommand(
+ std::vector<std::string> const& args)
{
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->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 ( !this->GetList(varArgsExpanded, listName.c_str()) )
- {
+ if (!this->GetList(varArgsExpanded, listName)) {
this->SetError("sub-command REMOVE_ITEM requires list to be present.");
return false;
- }
-
- size_t cc;
- for ( cc = 2; cc < args.size(); ++ cc )
- {
- size_t kk = 0;
- while ( kk < varArgsExpanded.size() )
- {
- if ( varArgsExpanded[kk] == args[cc] )
- {
- varArgsExpanded.erase(varArgsExpanded.begin()+kk);
- }
- else
- {
- kk ++;
- }
- }
- }
-
- std::string value;
- const char* sep = "";
- for ( cc = 0; cc < varArgsExpanded.size(); cc ++ )
- {
- value += sep;
- value += varArgsExpanded[cc];
- sep = ";";
- }
-
- this->Makefile->AddDefinition(listName.c_str(), value.c_str());
+ }
+
+ 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();
+
+ std::vector<std::string>::const_iterator argsEnd =
+ cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd));
+ std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
+ std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
+ this->Makefile->AddDefinition(listName, value.c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmListCommand
-::HandleReverseCommand(std::vector<std::string> const& args)
+bool cmListCommand::HandleReverseCommand(std::vector<std::string> const& args)
{
assert(args.size() >= 2);
- if(args.size() > 2)
- {
- this->SetError(
- "sub-command REVERSE only takes one argument.");
+ if (args.size() > 2) {
+ this->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.c_str()) )
- {
+ if (!this->GetList(varArgsExpanded, listName)) {
this->SetError("sub-command REVERSE requires list to be present.");
return false;
- }
+ }
- std::string value;
- std::vector<std::string>::reverse_iterator it;
- const char* sep = "";
- for ( it = varArgsExpanded.rbegin(); it != varArgsExpanded.rend(); ++ it )
- {
- value += sep;
- value += it->c_str();
- sep = ";";
- }
+ std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";");
- this->Makefile->AddDefinition(listName.c_str(), value.c_str());
+ this->Makefile->AddDefinition(listName, value.c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmListCommand
-::HandleRemoveDuplicatesCommand(std::vector<std::string> const& args)
+bool cmListCommand::HandleRemoveDuplicatesCommand(
+ std::vector<std::string> const& args)
{
assert(args.size() >= 2);
- if(args.size() > 2)
- {
- this->SetError(
- "sub-command REMOVE_DUPLICATES only takes one argument.");
+ if (args.size() > 2) {
+ this->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.c_str()) )
- {
+ if (!this->GetList(varArgsExpanded, listName)) {
this->SetError(
"sub-command REMOVE_DUPLICATES requires list to be present.");
return false;
- }
-
- std::string value;
-
-
- std::set<std::string> unique;
- std::vector<std::string>::iterator it;
- const char* sep = "";
- for ( it = varArgsExpanded.begin(); it != varArgsExpanded.end(); ++ it )
- {
- if (unique.find(*it) != unique.end())
- {
- continue;
- }
- unique.insert(*it);
- value += sep;
- value += it->c_str();
- sep = ";";
- }
+ }
+ std::vector<std::string>::const_iterator argsEnd =
+ cmRemoveDuplicates(varArgsExpanded);
+ std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
+ std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
- this->Makefile->AddDefinition(listName.c_str(), value.c_str());
+ this->Makefile->AddDefinition(listName, value.c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmListCommand
-::HandleSortCommand(std::vector<std::string> const& args)
+bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
{
assert(args.size() >= 2);
- if(args.size() > 2)
- {
- this->SetError(
- "sub-command SORT only takes one argument.");
+ if (args.size() > 2) {
+ this->SetError("sub-command SORT 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.c_str()) )
- {
+ if (!this->GetList(varArgsExpanded, listName)) {
this->SetError("sub-command SORT requires list to be present.");
return false;
- }
+ }
std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
- std::string value;
- std::vector<std::string>::iterator it;
- const char* sep = "";
- for ( it = varArgsExpanded.begin(); it != varArgsExpanded.end(); ++ it )
- {
- value += sep;
- value += it->c_str();
- sep = ";";
- }
-
- this->Makefile->AddDefinition(listName.c_str(), value.c_str());
+ std::string value = cmJoin(varArgsExpanded, ";");
+ this->Makefile->AddDefinition(listName, value.c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmListCommand::HandleRemoveAtCommand(
- std::vector<std::string> const& args)
+bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
{
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->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 ( !this->GetList(varArgsExpanded, listName.c_str()) )
- {
+ if (!this->GetList(varArgsExpanded, listName)) {
this->SetError("sub-command REMOVE_AT requires list to be present.");
return false;
- }
+ }
// FIXME: Add policy to make non-existing lists an error like empty lists.
- if(varArgsExpanded.empty())
- {
+ if (varArgsExpanded.empty()) {
this->SetError("REMOVE_AT given empty list");
return false;
- }
+ }
size_t cc;
std::vector<size_t> removed;
- for ( cc = 2; cc < args.size(); ++ cc )
- {
+ size_t nitem = varArgsExpanded.size();
+ for (cc = 2; cc < args.size(); ++cc) {
int item = atoi(args[cc].c_str());
- size_t nitem = varArgsExpanded.size();
- if ( item < 0 )
- {
+ if (item < 0) {
item = (int)nitem + item;
- }
- if ( item < 0 || nitem <= (size_t)item )
- {
- cmOStringStream str;
- str << "index: " << item << " out of range (-"
- << varArgsExpanded.size() << ", "
- << varArgsExpanded.size()-1 << ")";
- this->SetError(str.str().c_str());
+ }
+ if (item < 0 || nitem <= (size_t)item) {
+ std::ostringstream str;
+ str << "index: " << item << " out of range (-" << nitem << ", "
+ << nitem - 1 << ")";
+ this->SetError(str.str());
return false;
- }
- removed.push_back(static_cast<size_t>(item));
}
+ removed.push_back(static_cast<size_t>(item));
+ }
- std::string value;
- const char* sep = "";
- for ( cc = 0; cc < varArgsExpanded.size(); ++ cc )
- {
- size_t kk;
- bool found = false;
- for ( kk = 0; kk < removed.size(); ++ kk )
- {
- if ( cc == removed[kk] )
- {
- found = true;
- }
- }
-
- if ( !found )
- {
- value += sep;
- value += varArgsExpanded[cc];
- sep = ";";
- }
- }
+ 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();
+
+ std::vector<std::string>::const_iterator argsEnd =
+ cmRemoveIndices(varArgsExpanded, cmMakeRange(remBegin, remEnd));
+ std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
+ std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
- this->Makefile->AddDefinition(listName.c_str(), value.c_str());
+ this->Makefile->AddDefinition(listName, value.c_str());
return true;
}
+bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 2) {
+ this->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.");
+ 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.");
+ return false;
+ }
+
+ const std::string& op = args[2];
+ bool includeMatches;
+ if (op == "INCLUDE") {
+ includeMatches = true;
+ } else if (op == "EXCLUDE") {
+ includeMatches = false;
+ } else {
+ this->SetError("sub-command FILTER does not recognize operator " + op);
+ return false;
+ }
+
+ const std::string& mode = args[3];
+ if (mode == "REGEX") {
+ if (args.size() != 5) {
+ this->SetError("sub-command FILTER, mode REGEX "
+ "requires five arguments.");
+ return false;
+ }
+ return this->FilterRegex(args, includeMatches, listName, varArgsExpanded);
+ }
+
+ this->SetError("sub-command FILTER does not recognize mode " + mode);
+ return false;
+}
+
+class MatchesRegex
+{
+public:
+ MatchesRegex(cmsys::RegularExpression& in_regex, bool in_includeMatches)
+ : regex(in_regex)
+ , includeMatches(in_includeMatches)
+ {
+ }
+
+ bool operator()(const std::string& target)
+ {
+ return regex.find(target) ^ includeMatches;
+ }
+
+private:
+ cmsys::RegularExpression& regex;
+ const bool includeMatches;
+};
+
+bool cmListCommand::FilterRegex(std::vector<std::string> const& args,
+ bool includeMatches,
+ std::string const& listName,
+ std::vector<std::string>& varArgsExpanded)
+{
+ 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);
+ return false;
+ }
+
+ std::vector<std::string>::iterator argsBegin = varArgsExpanded.begin();
+ std::vector<std::string>::iterator argsEnd = varArgsExpanded.end();
+ std::vector<std::string>::iterator newArgsEnd =
+ std::remove_if(argsBegin, argsEnd, MatchesRegex(regex, includeMatches));
+
+ std::string value = cmJoin(cmMakeRange(argsBegin, newArgsEnd), ";");
+ this->Makefile->AddDefinition(listName, value.c_str());
+ return true;
+}
diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h
index f20aa8a8f..7789f7df1 100644
--- a/Source/cmListCommand.h
+++ b/Source/cmListCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmListCommand_h
#define cmListCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmListCommand
* \brief Common list operations
*
@@ -24,89 +22,15 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmListCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmListCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "list";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "List operations.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " list(LENGTH <list> <output variable>)\n"
- " list(GET <list> <element index> [<element index> ...]\n"
- " <output variable>)\n"
- " list(APPEND <list> <element> [<element> ...])\n"
- " list(FIND <list> <value> <output variable>)\n"
- " list(INSERT <list> <element_index> <element> [<element> ...])\n"
- " list(REMOVE_ITEM <list> <value> [<value> ...])\n"
- " list(REMOVE_AT <list> <index> [<index> ...])\n"
- " list(REMOVE_DUPLICATES <list>)\n"
- " list(REVERSE <list>)\n"
- " list(SORT <list>)\n"
- "LENGTH will return a given list's length.\n"
- "GET will return list of elements specified by indices from the list.\n"
- "APPEND will append elements to the list.\n"
- "FIND will return the index of the element specified in the list or -1 "
- "if it wasn't found.\n"
- "INSERT will insert elements to the list to the specified location.\n"
- "REMOVE_AT and REMOVE_ITEM will remove items from the list. The "
- "difference is that REMOVE_ITEM will remove the given items, while "
- "REMOVE_AT will remove the items at the given indices.\n"
- "REMOVE_DUPLICATES will remove duplicated items in the list.\n"
- "REVERSE reverses the contents of the list in-place.\n"
- "SORT sorts the list in-place alphabetically.\n"
- "The list subcommands APPEND, INSERT, REMOVE_AT, REMOVE_ITEM, "
- "REMOVE_DUPLICATES, REVERSE and SORT may create new values for "
- "the list within the current CMake variable scope. Similar to "
- "the SET command, the LIST command creates new variable values "
- "in the current scope, even if the list itself is actually "
- "defined in a parent scope. To propagate the results of these "
- "operations upwards, use SET with PARENT_SCOPE, SET with CACHE "
- "INTERNAL, or some other means of value propagation.\n"
- "NOTES: A list in cmake is a ; separated group of strings. "
- "To create a list the set command can be used. For example, "
- "set(var a b c d e) creates a list with a;b;c;d;e, and "
- "set(var \"a b c d e\") creates a string or a list with one "
- "item in it.\n"
- "When specifying index values, if <element index> is 0 or"
- " greater, it is indexed from the "
- "beginning of the list, with 0 representing the first list element. "
- "If <element index> is -1 or lesser, it is indexed from the end of "
- "the list, with -1 representing the last list element. Be careful "
- "when counting with negative indices: they do not start from 0. "
- "-0 is equivalent to 0, the first list element.\n"
- ;
- }
-
- cmTypeMacro(cmListCommand, cmCommand);
protected:
bool HandleLengthCommand(std::vector<std::string> const& args);
bool HandleGetCommand(std::vector<std::string> const& args);
@@ -118,11 +42,13 @@ protected:
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 char* var);
- bool GetListString(std::string& listString, const char* var);
+ bool GetList(std::vector<std::string>& list, const std::string& var);
+ bool GetListString(std::string& listString, const std::string& var);
};
-
#endif
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 898f379ad..0c73cd725 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -1,392 +1,470 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmListFileCache.h"
#include "cmListFileLexer.h"
+#include "cmMessenger.h"
+#include "cmOutputConverter.h"
+#include "cmState.h"
#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmVersion.h"
-
-#include <cmsys/RegularExpression.hxx>
+#include "cmake.h"
-#ifdef __BORLANDC__
-# pragma warn -8060 /* possibly incorrect assignment */
-#endif
+#include "cmConfigure.h"
+#include <algorithm>
+#include <assert.h>
+#include <sstream>
-//----------------------------------------------------------------------------
struct cmListFileParser
{
- cmListFileParser(cmListFile* lf, cmMakefile* mf, const char* filename);
+ cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt,
+ cmMessenger* messenger, const char* filename);
~cmListFileParser();
+ void IssueFileOpenError(std::string const& text) const;
+ void IssueError(std::string const& text) const;
bool ParseFile();
bool ParseFunction(const char* name, long line);
- void AddArgument(cmListFileLexer_Token* token,
+ bool AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim);
cmListFile* ListFile;
- cmMakefile* Makefile;
+ cmListFileBacktrace Backtrace;
+ cmMessenger* Messenger;
const char* FileName;
cmListFileLexer* Lexer;
cmListFileFunction Function;
- enum { SeparationOkay, SeparationWarning } Separation;
+ enum
+ {
+ SeparationOkay,
+ SeparationWarning,
+ SeparationError
+ } Separation;
};
-//----------------------------------------------------------------------------
-cmListFileParser::cmListFileParser(cmListFile* lf, cmMakefile* mf,
- const char* filename):
- ListFile(lf), Makefile(mf), FileName(filename),
- Lexer(cmListFileLexer_New())
+cmListFileParser::cmListFileParser(cmListFile* lf,
+ cmListFileBacktrace const& lfbt,
+ cmMessenger* messenger,
+ const char* filename)
+ : ListFile(lf)
+ , Backtrace(lfbt)
+ , Messenger(messenger)
+ , FileName(filename)
+ , Lexer(cmListFileLexer_New())
{
}
-//----------------------------------------------------------------------------
cmListFileParser::~cmListFileParser()
{
cmListFileLexer_Delete(this->Lexer);
}
-//----------------------------------------------------------------------------
+void cmListFileParser::IssueFileOpenError(const std::string& text) const
+{
+ this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, this->Backtrace);
+}
+
+void cmListFileParser::IssueError(const std::string& text) const
+{
+ cmListFileContext lfc;
+ lfc.FilePath = this->FileName;
+ lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer);
+ cmListFileBacktrace lfbt = this->Backtrace;
+ lfbt = lfbt.Push(lfc);
+ this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, lfbt);
+ cmSystemTools::SetFatalErrorOccured();
+}
+
bool cmListFileParser::ParseFile()
{
// Open the file.
- if(!cmListFileLexer_SetFileName(this->Lexer, this->FileName))
- {
- cmSystemTools::Error("cmListFileCache: error can not open file ",
- this->FileName);
+ cmListFileLexer_BOM bom;
+ if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) {
+ this->IssueFileOpenError("cmListFileCache: error can not open file.");
return false;
- }
+ }
+
+ if (bom == cmListFileLexer_BOM_Broken) {
+ cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR);
+ this->IssueFileOpenError("Error while reading Byte-Order-Mark. "
+ "File not seekable?");
+ return false;
+ }
+
+ // Verify the Byte-Order-Mark, if any.
+ if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) {
+ cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR);
+ this->IssueFileOpenError(
+ "File starts with a Byte-Order-Mark that is not UTF-8.");
+ return false;
+ }
// Use a simple recursive-descent parser to process the token
// stream.
bool haveNewline = true;
- while(cmListFileLexer_Token* token =
- cmListFileLexer_Scan(this->Lexer))
- {
- if(token->type == cmListFileLexer_Token_Space)
- {
- }
- else if(token->type == cmListFileLexer_Token_Newline)
- {
+ while (cmListFileLexer_Token* token = cmListFileLexer_Scan(this->Lexer)) {
+ if (token->type == cmListFileLexer_Token_Space) {
+ } else if (token->type == cmListFileLexer_Token_Newline) {
haveNewline = true;
- }
- else if(token->type == cmListFileLexer_Token_Identifier)
- {
- if(haveNewline)
- {
+ } else if (token->type == cmListFileLexer_Token_CommentBracket) {
+ haveNewline = false;
+ } else if (token->type == cmListFileLexer_Token_Identifier) {
+ if (haveNewline) {
haveNewline = false;
- if(this->ParseFunction(token->text, token->line))
- {
+ if (this->ParseFunction(token->text, token->line)) {
this->ListFile->Functions.push_back(this->Function);
- }
- else
- {
+ } else {
return false;
- }
}
- else
- {
- cmOStringStream error;
- error << "Error in cmake code at\n"
- << this->FileName << ":" << token->line << ":\n"
- << "Parse error. Expected a newline, got "
+ } else {
+ std::ostringstream error;
+ error << "Parse error. Expected a newline, got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
- cmSystemTools::Error(error.str().c_str());
+ this->IssueError(error.str());
return false;
- }
}
- else
- {
- cmOStringStream error;
- error << "Error in cmake code at\n"
- << this->FileName << ":" << token->line << ":\n"
- << "Parse error. Expected a command name, got "
+ } else {
+ std::ostringstream error;
+ error << "Parse error. Expected a command name, got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
- << " with text \""
- << token->text << "\".";
- cmSystemTools::Error(error.str().c_str());
+ << " with text \"" << token->text << "\".";
+ this->IssueError(error.str());
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmListFile::ParseFile(const char* filename,
- bool topLevel,
- cmMakefile *mf)
+bool cmListFile::ParseFile(const char* filename, cmMessenger* messenger,
+ cmListFileBacktrace const& lfbt)
{
- if(!cmSystemTools::FileExists(filename))
- {
+ if (!cmSystemTools::FileExists(filename) ||
+ cmSystemTools::FileIsDirectory(filename)) {
return false;
- }
-
- bool parseError = false;
- this->ModifiedTime = cmSystemTools::ModifiedTime(filename);
-
- {
- cmListFileParser parser(this, mf, filename);
- parseError = !parser.ParseFile();
}
- if(parseError)
- {
- this->ModifiedTime = 0;
- }
+ bool parseError = false;
- // do we need a cmake_policy(VERSION call?
- if(topLevel)
{
- bool hasVersion = false;
- // search for the right policy command
- for(std::vector<cmListFileFunction>::iterator i
- = this->Functions.begin();
- i != this->Functions.end(); ++i)
- {
- if (cmSystemTools::LowerCase(i->Name) == "cmake_minimum_required")
- {
- hasVersion = true;
- break;
- }
- }
- // if no policy command is found this is an error if they use any
- // non advanced functions or a lot of functions
- if(!hasVersion)
- {
- bool isProblem = true;
- if (this->Functions.size() < 30)
- {
- // the list of simple commands DO NOT ADD TO THIS LIST!!!!!
- // these commands must have backwards compatibility forever and
- // and that is a lot longer than your tiny mind can comprehend mortal
- std::set<std::string> allowedCommands;
- allowedCommands.insert("project");
- allowedCommands.insert("set");
- allowedCommands.insert("if");
- allowedCommands.insert("endif");
- allowedCommands.insert("else");
- allowedCommands.insert("elseif");
- allowedCommands.insert("add_executable");
- allowedCommands.insert("add_library");
- allowedCommands.insert("target_link_libraries");
- allowedCommands.insert("option");
- allowedCommands.insert("message");
- isProblem = false;
- for(std::vector<cmListFileFunction>::iterator i
- = this->Functions.begin();
- i != this->Functions.end(); ++i)
- {
- std::string name = cmSystemTools::LowerCase(i->Name);
- if (allowedCommands.find(name) == allowedCommands.end())
- {
- isProblem = true;
- break;
- }
- }
- }
-
- if (isProblem)
- {
- // Tell the top level cmMakefile to diagnose
- // this violation of CMP0000.
- mf->SetCheckCMP0000(true);
-
- // Implicitly set the version for the user.
- mf->SetPolicyVersion("2.4");
- }
- }
+ cmListFileParser parser(this, lfbt, messenger, filename);
+ parseError = !parser.ParseFile();
}
- if(topLevel)
- {
- bool hasProject = false;
- // search for a project command
- for(std::vector<cmListFileFunction>::iterator i
- = this->Functions.begin();
- i != this->Functions.end(); ++i)
- {
- if(cmSystemTools::LowerCase(i->Name) == "project")
- {
- hasProject = true;
- break;
- }
- }
- // if no project command is found, add one
- if(!hasProject)
- {
- cmListFileFunction project;
- project.Name = "PROJECT";
- cmListFileArgument prj("Project", cmListFileArgument::Unquoted,
- filename, 0);
- project.Arguments.push_back(prj);
- this->Functions.insert(this->Functions.begin(),project);
- }
- }
- if(parseError)
- {
- return false;
- }
- return true;
+ return !parseError;
}
-//----------------------------------------------------------------------------
bool cmListFileParser::ParseFunction(const char* name, long line)
{
- // Inintialize a new function call.
+ // Ininitialize a new function call.
this->Function = cmListFileFunction();
- this->Function.FilePath = this->FileName;
this->Function.Name = name;
this->Function.Line = line;
// Command name has already been parsed. Read the left paren.
cmListFileLexer_Token* token;
- while((token = cmListFileLexer_Scan(this->Lexer)) &&
- token->type == cmListFileLexer_Token_Space) {}
- if(!token)
- {
- cmOStringStream error;
- error << "Error in cmake code at\n" << this->FileName << ":"
- << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
+ while ((token = cmListFileLexer_Scan(this->Lexer)) &&
+ token->type == cmListFileLexer_Token_Space) {
+ }
+ if (!token) {
+ std::ostringstream error;
+ /* clang-format off */
+ error << "Unexpected end of file.\n"
<< "Parse error. Function missing opening \"(\".";
- cmSystemTools::Error(error.str().c_str());
+ /* clang-format on */
+ this->IssueError(error.str());
return false;
- }
- if(token->type != cmListFileLexer_Token_ParenLeft)
- {
- cmOStringStream error;
- error << "Error in cmake code at\n" << this->FileName << ":"
- << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
- << "Parse error. Expected \"(\", got "
+ }
+ if (token->type != cmListFileLexer_Token_ParenLeft) {
+ std::ostringstream error;
+ error << "Parse error. Expected \"(\", got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
- cmSystemTools::Error(error.str().c_str());
+ this->IssueError(error.str());
return false;
- }
+ }
// Arguments.
unsigned long lastLine;
unsigned long parenDepth = 0;
this->Separation = SeparationOkay;
- while((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer),
- token = cmListFileLexer_Scan(this->Lexer)))
- {
- if(token->type == cmListFileLexer_Token_Space ||
- token->type == cmListFileLexer_Token_Newline)
- {
+ while ((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer),
+ token = cmListFileLexer_Scan(this->Lexer))) {
+ if (token->type == cmListFileLexer_Token_Space ||
+ token->type == cmListFileLexer_Token_Newline) {
this->Separation = SeparationOkay;
continue;
- }
- if(token->type == cmListFileLexer_Token_ParenLeft)
- {
+ }
+ if (token->type == cmListFileLexer_Token_ParenLeft) {
parenDepth++;
this->Separation = SeparationOkay;
- this->AddArgument(token, cmListFileArgument::Unquoted);
+ if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
+ return false;
}
- else if(token->type == cmListFileLexer_Token_ParenRight)
- {
- if (parenDepth == 0)
- {
+ } else if (token->type == cmListFileLexer_Token_ParenRight) {
+ if (parenDepth == 0) {
return true;
- }
+ }
parenDepth--;
this->Separation = SeparationOkay;
- this->AddArgument(token, cmListFileArgument::Unquoted);
+ if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
+ return false;
+ }
this->Separation = SeparationWarning;
+ } else if (token->type == cmListFileLexer_Token_Identifier ||
+ token->type == cmListFileLexer_Token_ArgumentUnquoted) {
+ if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
+ return false;
}
- else if(token->type == cmListFileLexer_Token_Identifier ||
- token->type == cmListFileLexer_Token_ArgumentUnquoted)
- {
- this->AddArgument(token, cmListFileArgument::Unquoted);
this->Separation = SeparationWarning;
+ } else if (token->type == cmListFileLexer_Token_ArgumentQuoted) {
+ if (!this->AddArgument(token, cmListFileArgument::Quoted)) {
+ return false;
}
- else if(token->type == cmListFileLexer_Token_ArgumentQuoted)
- {
- this->AddArgument(token, cmListFileArgument::Quoted);
this->Separation = SeparationWarning;
+ } else if (token->type == cmListFileLexer_Token_ArgumentBracket) {
+ if (!this->AddArgument(token, cmListFileArgument::Bracket)) {
+ return false;
}
- else
- {
+ this->Separation = SeparationError;
+ } else if (token->type == cmListFileLexer_Token_CommentBracket) {
+ this->Separation = SeparationError;
+ } else {
// Error.
- cmOStringStream error;
- error << "Error in cmake code at\n" << this->FileName << ":"
- << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
- << "Parse error. Function missing ending \")\". "
+ std::ostringstream error;
+ error << "Parse error. Function missing ending \")\". "
<< "Instead found "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
- cmSystemTools::Error(error.str().c_str());
+ this->IssueError(error.str());
return false;
- }
}
+ }
- cmOStringStream error;
- error << "Error in cmake code at\n"
- << this->FileName << ":" << lastLine << ":\n"
- << "Parse error. Function missing ending \")\". "
+ std::ostringstream error;
+ cmListFileContext lfc;
+ lfc.FilePath = this->FileName;
+ lfc.Line = lastLine;
+ cmListFileBacktrace lfbt = this->Backtrace;
+ lfbt = lfbt.Push(lfc);
+ error << "Parse error. Function missing ending \")\". "
<< "End of file reached.";
- cmSystemTools::Error(error.str().c_str());
-
+ this->Messenger->IssueMessage(cmake::FATAL_ERROR, error.str(), lfbt);
return false;
}
-//----------------------------------------------------------------------------
-void cmListFileParser::AddArgument(cmListFileLexer_Token* token,
+bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim)
{
- cmListFileArgument a(token->text, delim, this->FileName, token->line);
+ cmListFileArgument a(token->text, delim, token->line);
this->Function.Arguments.push_back(a);
- if(delim == cmListFileArgument::Unquoted)
- {
- // Warn about a future behavior change.
- const char* c = a.Value.c_str();
- if(*c++ == '[')
- {
- while(*c == '=')
- { ++c; }
- if(*c == '[')
- {
- cmOStringStream m;
- m << "Syntax Warning in cmake code at\n"
- << " " << this->FileName << ":" << token->line << ":"
- << token->column << "\n"
- << "A future version of CMake may treat unquoted argument:\n"
- << " " << a.Value << "\n"
- << "as an opening long bracket. Double-quote the argument.";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str());
- }
- }
+ if (this->Separation == SeparationOkay) {
+ return true;
+ }
+ bool isError = (this->Separation == SeparationError ||
+ delim == cmListFileArgument::Bracket);
+ std::ostringstream m;
+ cmListFileContext lfc;
+ lfc.FilePath = this->FileName;
+ lfc.Line = token->line;
+ cmListFileBacktrace lfbt = this->Backtrace;
+ lfbt = lfbt.Push(lfc);
+
+ m << "Syntax " << (isError ? "Error" : "Warning") << " in cmake code at "
+ << "column " << token->column << "\n"
+ << "Argument not separated from preceding token by whitespace.";
+ /* clang-format on */
+ if (isError) {
+ this->Messenger->IssueMessage(cmake::FATAL_ERROR, m.str(), lfbt);
+ return false;
+ }
+ this->Messenger->IssueMessage(cmake::AUTHOR_WARNING, m.str(), lfbt);
+ return true;
+}
+
+struct cmListFileBacktrace::Entry : public cmListFileContext
+{
+ Entry(cmListFileContext const& lfc, Entry* up)
+ : cmListFileContext(lfc)
+ , Up(up)
+ , RefCount(0)
+ {
+ if (this->Up) {
+ this->Up->Ref();
+ }
+ }
+ ~Entry()
+ {
+ if (this->Up) {
+ this->Up->Unref();
}
- if(this->Separation == SeparationOkay)
- {
+ }
+ void Ref() { ++this->RefCount; }
+ void Unref()
+ {
+ if (--this->RefCount == 0) {
+ delete this;
+ }
+ }
+ 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();
+}
+
+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)
+{
+}
+
+cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot)
+ : Bottom(snapshot.GetCallStackBottom())
+ , Cur(CM_NULLPTR)
+{
+}
+
+cmListFileBacktrace::cmListFileBacktrace(cmListFileBacktrace const& r)
+ : Bottom(r.Bottom)
+ , Cur(r.Cur)
+{
+ if (this->Cur) {
+ assert(this->Bottom.IsValid());
+ this->Cur->Ref();
+ }
+}
+
+cmListFileBacktrace& cmListFileBacktrace::operator=(
+ cmListFileBacktrace const& r)
+{
+ cmListFileBacktrace tmp(r);
+ std::swap(this->Cur, tmp.Cur);
+ std::swap(this->Bottom, tmp.Bottom);
+ return *this;
+}
+
+cmListFileBacktrace::~cmListFileBacktrace()
+{
+ if (this->Cur) {
+ this->Cur->Unref();
+ }
+}
+
+cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
+{
+ // We are entering a file-level scope but have not yet reached
+ // any specific line or command invocation within it. This context
+ // is useful to print when it is at the top but otherwise can be
+ // skipped during call stack printing.
+ cmListFileContext lfc;
+ lfc.FilePath = file;
+ return cmListFileBacktrace(this->Bottom, this->Cur, lfc);
+}
+
+cmListFileBacktrace cmListFileBacktrace::Push(
+ cmListFileContext const& lfc) const
+{
+ return cmListFileBacktrace(this->Bottom, this->Cur, lfc);
+}
+
+cmListFileBacktrace cmListFileBacktrace::Pop() const
+{
+ assert(this->Cur);
+ return cmListFileBacktrace(this->Bottom, this->Cur->Up);
+}
+
+cmListFileContext const& cmListFileBacktrace::Top() const
+{
+ if (this->Cur) {
+ return *this->Cur;
+ }
+ static cmListFileContext const empty;
+ return empty;
+}
+
+void cmListFileBacktrace::PrintTitle(std::ostream& out) const
+{
+ if (!this->Cur) {
return;
+ }
+ cmOutputConverter converter(this->Bottom);
+ cmListFileContext lfc = *this->Cur;
+ if (!this->Bottom.GetState()->GetIsInTryCompile()) {
+ lfc.FilePath = converter.ConvertToRelativePath(
+ this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+ }
+ out << (lfc.Line ? " at " : " in ") << lfc;
+}
+
+void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
+{
+ if (!this->Cur || !this->Cur->Up) {
+ return;
+ }
+
+ bool first = true;
+ cmOutputConverter converter(this->Bottom);
+ for (Entry* i = this->Cur->Up; i; i = i->Up) {
+ if (i->Name.empty()) {
+ // Skip this whole-file scope. When we get here we already will
+ // have printed a more-specific context within the file.
+ continue;
}
- cmOStringStream m;
- m << "Syntax Warning in cmake code at\n"
- << " " << this->FileName << ":" << token->line << ":"
- << token->column << "\n"
- << "Argument not separated from preceding token by whitespace.";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str());
+ if (first) {
+ 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);
+ }
+ out << " " << lfc << "\n";
+ }
}
-//----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
os << lfc.FilePath;
- if(lfc.Line)
- {
+ if (lfc.Line) {
os << ":" << lfc.Line;
- if(!lfc.Name.empty())
- {
+ if (!lfc.Name.empty()) {
os << " (" << lfc.Name << ")";
- }
}
+ }
return os;
}
+
+bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs)
+{
+ if (lhs.Line != rhs.Line) {
+ return lhs.Line < rhs.Line;
+ }
+ return lhs.FilePath < rhs.FilePath;
+}
+
+bool operator==(const cmListFileContext& lhs, const cmListFileContext& rhs)
+{
+ return lhs.Line == rhs.Line && lhs.FilePath == rhs.FilePath;
+}
+
+bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs)
+{
+ return !(lhs == rhs);
+}
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 7bb3b346c..349ddef91 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -1,18 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmListFileCache_h
#define cmListFileCache_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmStateSnapshot.h"
/** \class cmListFileCache
* \brief A class to cache list file contents.
@@ -21,73 +18,142 @@
* cmake list files.
*/
-class cmMakefile;
+class cmMessenger;
+
+struct cmCommandContext
+{
+ std::string Name;
+ long Line;
+ cmCommandContext()
+ : Name()
+ , Line(0)
+ {
+ }
+};
struct cmListFileArgument
{
enum Delimiter
- {
+ {
Unquoted,
- Quoted
- };
- cmListFileArgument(): Value(), Delim(Unquoted), FilePath(0), Line(0) {}
- cmListFileArgument(const cmListFileArgument& r):
- Value(r.Value), Delim(r.Delim), FilePath(r.FilePath), Line(r.Line) {}
- cmListFileArgument(const std::string& v, Delimiter d, const char* file,
- long line): Value(v), Delim(d),
- FilePath(file), Line(line) {}
- bool operator == (const cmListFileArgument& r) const
- {
+ Quoted,
+ Bracket
+ };
+ cmListFileArgument()
+ : Value()
+ , Delim(Unquoted)
+ , Line(0)
+ {
+ }
+ cmListFileArgument(const std::string& v, Delimiter d, long line)
+ : Value(v)
+ , Delim(d)
+ , Line(line)
+ {
+ }
+ bool operator==(const cmListFileArgument& r) const
+ {
return (this->Value == r.Value) && (this->Delim == r.Delim);
- }
- bool operator != (const cmListFileArgument& r) const
- {
- return !(*this == r);
- }
+ }
+ bool operator!=(const cmListFileArgument& r) const { return !(*this == r); }
std::string Value;
Delimiter Delim;
- const char* FilePath;
long Line;
};
-struct cmListFileContext
+class cmListFileContext
{
+public:
std::string Name;
std::string FilePath;
long Line;
- cmListFileContext(): Name(), FilePath(), Line(0) {}
+ cmListFileContext()
+ : Name()
+ , FilePath()
+ , Line(0)
+ {
+ }
+
+ static cmListFileContext FromCommandContext(cmCommandContext const& lfcc,
+ std::string const& fileName)
+ {
+ cmListFileContext lfc;
+ lfc.FilePath = fileName;
+ lfc.Line = lfcc.Line;
+ lfc.Name = lfcc.Name;
+ return lfc;
+ }
};
std::ostream& operator<<(std::ostream&, cmListFileContext const&);
+bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs);
+bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs);
+bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs);
-struct cmListFileFunction: public cmListFileContext
+struct cmListFileFunction : public cmCommandContext
{
std::vector<cmListFileArgument> Arguments;
};
-class cmListFileBacktrace: public std::vector<cmListFileContext> {};
+// Represent a backtrace (call stack). Provide value semantics
+// but use efficient reference-counting underneath to avoid copies.
+class cmListFileBacktrace
+{
+public:
+ // Default-constructed backtrace may not be used until after
+ // set via assignment from a backtrace constructed with a
+ // valid snapshot.
+ cmListFileBacktrace();
+
+ // 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; }
+
+ // Get a backtrace with the given file scope added to the top.
+ // May not be called until after construction with a valid snapshot.
+ cmListFileBacktrace Push(std::string const& file) const;
+
+ // Get a backtrace with the given call context added to the top.
+ // May not be called until after construction with a valid snapshot.
+ cmListFileBacktrace Push(cmListFileContext const& lfc) const;
+
+ // Get a backtrace with the top level removed.
+ // May not be called until after a matching Push.
+ cmListFileBacktrace Pop() const;
+
+ // Get the context at the top of the backtrace.
+ // Returns an empty context if the backtrace is empty.
+ cmListFileContext const& Top() const;
+
+ // Print the top of the backtrace.
+ void PrintTitle(std::ostream& out) const;
+
+ // Print the call stack below the top of the backtrace.
+ void PrintCallStack(std::ostream& out) const;
+
+private:
+ struct Entry;
+
+ cmStateSnapshot Bottom;
+ Entry* Cur;
+ cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* up,
+ cmListFileContext const& lfc);
+ cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* cur);
+};
struct cmListFile
{
- cmListFile()
- :ModifiedTime(0)
- {
- }
- bool ParseFile(const char* path,
- bool topLevel,
- cmMakefile *mf);
-
- long int ModifiedTime;
- std::vector<cmListFileFunction> Functions;
-};
+ bool ParseFile(const char* path, cmMessenger* messenger,
+ cmListFileBacktrace const& lfbt);
-struct cmValueWithOrigin {
- cmValueWithOrigin(const std::string &value,
- const cmListFileBacktrace &bt)
- : Value(value), Backtrace(bt)
- {}
- std::string Value;
- cmListFileBacktrace Backtrace;
+ std::vector<cmListFileFunction> Functions;
};
#endif
diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c
deleted file mode 100644
index 2841fe511..000000000
--- a/Source/cmListFileLexer.c
+++ /dev/null
@@ -1,2417 +0,0 @@
-#line 2 "cmListFileLexer.c"
-
-#line 4 "cmListFileLexer.c"
-
-#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 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#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
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* 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.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned 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 cmListFileLexer_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
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
- /* 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.
- * 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.
- */
- #define YY_LESS_LINENO(n) \
- do { \
- int yyl;\
- for ( yyl = n; yyl < yyleng; ++yyl )\
- if ( yytext[yyl] == '\n' )\
- --yylineno;\
- }while(0)
-
-/* 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 )
-
-#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.
- */
- yy_size_t 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 cmListFileLexer_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 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 );
-
-#define YY_FLUSH_BUFFER cmListFileLexer_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 );
-
-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
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- cmListFileLexer_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmListFileLexer_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); \
- YY_CURRENT_BUFFER_LVALUE = \
- cmListFileLexer_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(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char 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 yy_fatal_error (yyconst 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 = (size_t) (yy_cp - yy_bp); \
- yyg->yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 16
-#define YY_END_OF_BUFFER 17
-/* 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 yyconst flex_int16_t yy_accept[45] =
- { 0,
- 0, 0, 0, 0, 17, 6, 14, 1, 8, 2,
- 6, 3, 4, 6, 15, 9, 11, 12, 13, 6,
- 0, 6, 0, 14, 2, 0, 5, 6, 9, 0,
- 10, 0, 7, 0, 0, 0, 7, 0, 7, 0,
- 0, 0, 0, 0
- } ;
-
-static yyconst flex_int32_t yy_ec[256] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 1, 5, 6, 7, 1, 1, 1, 8,
- 9, 1, 1, 1, 1, 1, 1, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 1, 1, 1,
- 1, 1, 1, 1, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 1, 12, 1, 1, 11, 1, 11, 11, 11, 11,
-
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 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 yyconst flex_int32_t yy_meta[13] =
- { 0,
- 1, 2, 3, 2, 4, 1, 1, 1, 5, 5,
- 5, 1
- } ;
-
-static yyconst flex_int16_t yy_base[56] =
- { 0,
- 0, 0, 10, 20, 38, 32, 0, 109, 109, 0,
- 28, 109, 109, 35, 0, 23, 109, 109, 44, 0,
- 49, 26, 0, 0, 0, 22, 0, 0, 18, 24,
- 109, 0, 61, 20, 0, 18, 0, 17, 16, 0,
- 12, 11, 10, 109, 73, 16, 78, 83, 88, 93,
- 12, 98, 11, 103, 9
- } ;
-
-static yyconst flex_int16_t yy_def[56] =
- { 0,
- 44, 1, 45, 45, 44, 44, 46, 44, 44, 47,
- 6, 44, 44, 6, 48, 49, 44, 44, 49, 6,
- 44, 6, 50, 46, 47, 51, 14, 6, 49, 49,
- 44, 21, 44, 21, 52, 53, 33, 51, 33, 54,
- 55, 53, 55, 0, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44
- } ;
-
-static yyconst flex_int16_t yy_nxt[122] =
- { 0,
- 6, 7, 8, 7, 9, 10, 11, 12, 13, 6,
- 14, 15, 17, 43, 18, 42, 38, 24, 32, 33,
- 32, 19, 17, 36, 18, 37, 33, 41, 29, 30,
- 37, 19, 20, 36, 30, 26, 21, 44, 22, 44,
- 44, 20, 20, 23, 27, 27, 31, 44, 29, 32,
- 32, 44, 44, 33, 44, 34, 44, 44, 32, 32,
- 35, 33, 44, 44, 44, 21, 44, 39, 44, 44,
- 33, 33, 40, 16, 16, 16, 16, 16, 25, 25,
- 44, 25, 25, 28, 28, 44, 28, 28, 29, 29,
- 44, 44, 29, 20, 20, 44, 20, 20, 32, 32,
-
- 44, 32, 32, 33, 33, 44, 33, 33, 5, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44
- } ;
-
-static yyconst flex_int16_t yy_chk[122] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 3, 55, 3, 53, 51, 46, 43, 42,
- 41, 3, 4, 39, 4, 38, 36, 34, 30, 29,
- 26, 4, 6, 22, 16, 11, 6, 5, 6, 0,
- 0, 6, 6, 6, 14, 14, 19, 0, 19, 21,
- 21, 0, 0, 21, 0, 21, 0, 0, 21, 21,
- 21, 33, 0, 0, 0, 33, 0, 33, 0, 0,
- 33, 33, 33, 45, 45, 45, 45, 45, 47, 47,
- 0, 47, 47, 48, 48, 0, 48, 48, 49, 49,
- 0, 0, 49, 50, 50, 0, 50, 50, 52, 52,
-
- 0, 52, 52, 54, 54, 0, 54, 54, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44
- } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[17] =
- { 0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, };
-
-/* 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
-#line 1 "cmListFileLexer.in.l"
-#line 2 "cmListFileLexer.in.l"
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex like this:
-
- flex --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
-
-Modify cmListFileLexer.c:
- - remove TABs
- - remove use of the 'register' storage class specifier
- - remove the yyunput function
- - add a statement "(void)yyscanner;" to the top of these methods:
- yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree
- - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy
- - remove all YY_BREAK lines occurring right after return statements
- - remove the isatty forward declaration
-
-*/
-
-#include "cmStandardLexer.h"
-
-/* Setup the proper cmListFileLexer_yylex declaration. */
-#define YY_EXTRA_TYPE cmListFileLexer*
-#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
-
-#include "cmListFileLexer.h"
-
-/*--------------------------------------------------------------------------*/
-struct cmListFileLexer_s
-{
- cmListFileLexer_Token token;
- int line;
- int column;
- int size;
- FILE* file;
- char* string_buffer;
- char* string_position;
- int string_left;
- yyscan_t scanner;
-};
-
-static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
- int length);
-static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
- int length);
-static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
- size_t bufferSize);
-static void cmListFileLexerInit(cmListFileLexer* lexer);
-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); }
-
-/*--------------------------------------------------------------------------*/
-
-#line 570 "cmListFileLexer.c"
-
-#define INITIAL 0
-#define STRING 1
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#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 cmListFileLexer_yylex_init (yyscan_t* scanner);
-
-int cmListFileLexer_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 cmListFileLexer_yyget_debug (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_in (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_out (FILE * out_str ,yyscan_t yyscanner );
-
-int cmListFileLexer_yyget_leng (yyscan_t yyscanner );
-
-char *cmListFileLexer_yyget_text (yyscan_t yyscanner );
-
-int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-int cmListFileLexer_yyget_column (yyscan_t yyscanner );
-
-void cmListFileLexer_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 cmListFileLexer_yywrap (yyscan_t yyscanner );
-#else
-extern int cmListFileLexer_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst 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, 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 = '*'; \
- size_t 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 = fread(buf, 1, 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 cmListFileLexer_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int cmListFileLexer_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 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;
-
-#line 82 "cmListFileLexer.in.l"
-
-
-#line 804 "cmListFileLexer.c"
-
- 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 ) {
- cmListFileLexer_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmListFileLexer_yy_load_buffer_state(yyscanner );
- }
-
- while ( 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 >= 45 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 109 );
-
-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;
-
- if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
- {
- int yyl;
- for ( yyl = 0; yyl < yyleng; ++yyl )
- if ( yytext[yyl] == '\n' )
-
- do{ yylineno++;
- yycolumn=0;
- }while(0)
-;
- }
-
-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:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 84 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_Newline;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- ++lexer->line;
- lexer->column = 1;
- return 1;
-}
-case 2:
-YY_RULE_SETUP
-#line 92 "cmListFileLexer.in.l"
-{
- lexer->column += yyleng;
-}
- YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 96 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_ParenLeft;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case 4:
-YY_RULE_SETUP
-#line 103 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_ParenRight;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case 5:
-YY_RULE_SETUP
-#line 110 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_Identifier;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case 6:
-YY_RULE_SETUP
-#line 117 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case 7:
-YY_RULE_SETUP
-#line 124 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case 8:
-YY_RULE_SETUP
-#line 131 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
- cmListFileLexerSetToken(lexer, "", 0);
- lexer->column += yyleng;
- BEGIN(STRING);
-}
- YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 138 "cmListFileLexer.in.l"
-{
- cmListFileLexerAppend(lexer, yytext, yyleng);
- lexer->column += yyleng;
-}
- YY_BREAK
-case 10:
-/* rule 10 can match eol */
-YY_RULE_SETUP
-#line 143 "cmListFileLexer.in.l"
-{
- cmListFileLexerAppend(lexer, yytext, yyleng);
- ++lexer->line;
- lexer->column = 1;
-}
- YY_BREAK
-case 11:
-/* rule 11 can match eol */
-YY_RULE_SETUP
-#line 149 "cmListFileLexer.in.l"
-{
- cmListFileLexerAppend(lexer, yytext, yyleng);
- ++lexer->line;
- lexer->column = 1;
-}
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 155 "cmListFileLexer.in.l"
-{
- lexer->column += yyleng;
- BEGIN(INITIAL);
- return 1;
-}
-case 13:
-YY_RULE_SETUP
-#line 161 "cmListFileLexer.in.l"
-{
- cmListFileLexerAppend(lexer, yytext, yyleng);
- lexer->column += yyleng;
-}
- YY_BREAK
-case YY_STATE_EOF(STRING):
-#line 166 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_BadString;
- BEGIN(INITIAL);
- return 1;
-}
-case 14:
-YY_RULE_SETUP
-#line 172 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_Space;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case 15:
-YY_RULE_SETUP
-#line 179 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_BadCharacter;
- cmListFileLexerSetToken(lexer, yytext, yyleng);
- lexer->column += yyleng;
- return 1;
-}
-case YY_STATE_EOF(INITIAL):
-#line 186 "cmListFileLexer.in.l"
-{
- lexer->token.type = cmListFileLexer_Token_None;
- cmListFileLexerSetToken(lexer, 0, 0);
- return 0;
-}
-case 16:
-YY_RULE_SETUP
-#line 192 "cmListFileLexer.in.l"
-ECHO;
- YY_BREAK
-#line 1064 "cmListFileLexer.c"
-
- 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
- * cmListFileLexer_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 ( cmListFileLexer_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 cmListFileLexer_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;
-
- 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. */
- cmListFileLexer_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- 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, (size_t) 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;
- cmListFileLexer_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 ((yy_size_t) (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. */
- yy_size_t 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 );
- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
- }
-
- 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 >= 45 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) 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 >= 45 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 44);
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
-#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 = 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. */
- cmListFileLexer_yyrestart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( cmListFileLexer_yywrap(yyscanner ) )
- return EOF;
-
- 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;
-
- if ( c == '\n' )
-
- do{ yylineno++;
- yycolumn=0;
- }while(0)
-;
-
- 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 cmListFileLexer_yyrestart (FILE * input_file , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! YY_CURRENT_BUFFER ){
- cmListFileLexer_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- cmListFileLexer_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmListFileLexer_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)
-{
- 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);
- */
- cmListFileLexer_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;
- cmListFileLexer_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
- * 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)
-{
- 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 cmListFileLexer_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 );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_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 *) cmListFileLexer_yyalloc(b->yy_buf_size + 2 ,yyscanner );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- cmListFileLexer_yy_init_buffer(b,file ,yyscanner);
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with cmListFileLexer_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
- void cmListFileLexer_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 )
- cmListFileLexer_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
- cmListFileLexer_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.
- */
- static void cmListFileLexer_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);
-
- 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.
- * 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 cmListFileLexer_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 )
- cmListFileLexer_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 cmListFileLexer_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);
-
- /* This block is copied from cmListFileLexer_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 cmListFileLexer_yy_switch_to_buffer. */
- cmListFileLexer_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 cmListFileLexer_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_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 );
- 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 cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
-{
- int 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;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_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()" );
-
- 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. */
- int 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,
- 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()" );
-
- /* 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 cmListFileLexer_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 0;
-
- b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_buffer()" );
-
- b->yy_buf_size = 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 = 0;
- 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;
-
- cmListFileLexer_yy_switch_to_buffer(b ,yyscanner );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_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_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-
- return cmListFileLexer_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_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 b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
- buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_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 = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmListFileLexer_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 yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
- (void)yyscanner;
- (void) 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 cmListFileLexer_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 cmListFileLexer_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 cmListFileLexer_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 *cmListFileLexer_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 *cmListFileLexer_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 cmListFileLexer_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 *cmListFileLexer_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 cmListFileLexer_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
- * @param yyscanner The scanner object.
- */
-void cmListFileLexer_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" , yyscanner);
-
- yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void cmListFileLexer_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" , yyscanner);
-
- 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 cmListFileLexer_yy_switch_to_buffer
- */
-void cmListFileLexer_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)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
-}
-
-int cmListFileLexer_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)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-/* User-visible API */
-
-/* cmListFileLexer_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)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmListFileLexer_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 );
-}
-
-/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_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 yyextra field.
- */
-
-int cmListFileLexer_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);
-
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmListFileLexer_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));
-
- cmListFileLexer_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 cmListFileLexer_yylex_destroy(), so don't allocate here.
- */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- 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 = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * cmListFileLexer_yylex_init()
- */
- return 0;
-}
-
-/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmListFileLexer_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_CURRENT_BUFFER_LVALUE = NULL;
- cmListFileLexer_yypop_buffer_state(yyscanner);
- }
-
- /* Destroy the stack itself. */
- cmListFileLexer_yyfree(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
-
- /* Destroy the start condition stack. */
- cmListFileLexer_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. */
- yy_init_globals( yyscanner);
-
- /* Destroy the main struct (reentrant only). */
- cmListFileLexer_yyfree ( yyscanner , yyscanner );
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
- int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
- int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *cmListFileLexer_yyalloc (yy_size_t size , yyscan_t yyscanner)
-{
- (void)yyscanner;
- return (void *) malloc( size );
-}
-
-void *cmListFileLexer_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
-{
- /* 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.
- */
- (void)yyscanner;
- return (void *) realloc( (char *) ptr, size );
-}
-
-void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner)
-{
- (void)yyscanner;
- free( (char *) ptr ); /* see cmListFileLexer_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 192 "cmListFileLexer.in.l"
-
-
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
- int length)
-{
- /* Set the token line and column number. */
- lexer->token.line = lexer->line;
- lexer->token.column = lexer->column;
-
- /* Use the same buffer if possible. */
- if(lexer->token.text)
- {
- if(text && length < lexer->size)
- {
- strcpy(lexer->token.text, text);
- lexer->token.length = length;
- return;
- }
- free(lexer->token.text);
- lexer->token.text = 0;
- lexer->size = 0;
- }
-
- /* Need to extend the buffer. */
- if(text)
- {
- lexer->token.text = strdup(text);
- lexer->token.length = length;
- lexer->size = length+1;
- }
- else
- {
- lexer->token.length = 0;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
- int length)
-{
- char* temp;
- int newSize;
-
- /* If the appended text will fit in the buffer, do not reallocate. */
- newSize = lexer->token.length + length + 1;
- if(lexer->token.text && newSize <= lexer->size)
- {
- strcpy(lexer->token.text+lexer->token.length, text);
- lexer->token.length += length;
- return;
- }
-
- /* We need to extend the buffer. */
- temp = malloc(newSize);
- if(lexer->token.text)
- {
- memcpy(temp, lexer->token.text, lexer->token.length);
- free(lexer->token.text);
- }
- memcpy(temp+lexer->token.length, text, length);
- temp[lexer->token.length+length] = 0;
- lexer->token.text = temp;
- lexer->token.length += length;
- lexer->size = newSize;
-}
-
-/*--------------------------------------------------------------------------*/
-static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
- size_t bufferSize)
-{
- if(lexer)
- {
- if(lexer->file)
- {
- return (int)fread(buffer, 1, bufferSize, lexer->file);
- }
- else if(lexer->string_left)
- {
- int length = lexer->string_left;
- if((int)bufferSize < length) { length = (int)bufferSize; }
- memcpy(buffer, lexer->string_position, length);
- lexer->string_position += length;
- lexer->string_left -= length;
- return length;
- }
- }
- return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerInit(cmListFileLexer* lexer)
-{
- if(lexer->file || lexer->string_buffer)
- {
- cmListFileLexer_yylex_init(&lexer->scanner);
- cmListFileLexer_yyset_extra(lexer, lexer->scanner);
- }
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerDestroy(cmListFileLexer* lexer)
-{
- if(lexer->file || lexer->string_buffer)
- {
- cmListFileLexer_yylex_destroy(lexer->scanner);
- if(lexer->file)
- {
- fclose(lexer->file);
- lexer->file = 0;
- }
- if(lexer->string_buffer)
- {
- free(lexer->string_buffer);
- lexer->string_buffer = 0;
- lexer->string_left = 0;
- lexer->string_position = 0;
- }
- }
-}
-
-/*--------------------------------------------------------------------------*/
-cmListFileLexer* cmListFileLexer_New()
-{
- cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
- if(!lexer)
- {
- return 0;
- }
- memset(lexer, 0, sizeof(*lexer));
- lexer->line = 1;
- lexer->column = 1;
- return lexer;
-}
-
-/*--------------------------------------------------------------------------*/
-void cmListFileLexer_Delete(cmListFileLexer* lexer)
-{
- cmListFileLexer_SetFileName(lexer, 0);
- free(lexer);
-}
-
-/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name)
-{
- int result = 1;
- cmListFileLexerDestroy(lexer);
- if(name)
- {
- lexer->file = fopen(name, "r");
- if(!lexer->file)
- {
- result = 0;
- }
- }
- cmListFileLexerInit(lexer);
- return result;
-}
-
-/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
-{
- int result = 1;
- cmListFileLexerDestroy(lexer);
- if(text)
- {
- int length = (int)strlen(text);
- lexer->string_buffer = (char*)malloc(length+1);
- if(lexer->string_buffer)
- {
- strcpy(lexer->string_buffer, text);
- lexer->string_position = lexer->string_buffer;
- lexer->string_left = length;
- }
- else
- {
- result = 0;
- }
- }
- cmListFileLexerInit(lexer);
- return result;
-}
-
-/*--------------------------------------------------------------------------*/
-cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
-{
- if(!lexer->file)
- {
- return 0;
- }
- if(cmListFileLexer_yylex(lexer->scanner, lexer))
- {
- return &lexer->token;
- }
- else
- {
- cmListFileLexer_SetFileName(lexer, 0);
- return 0;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
-{
- if(lexer->file)
- {
- return lexer->line;
- }
- else
- {
- return 0;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
-{
- if(lexer->file)
- {
- return lexer->column;
- }
- else
- {
- return 0;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
- cmListFileLexer_Type type)
-{
- (void)lexer;
- switch(type)
- {
- case cmListFileLexer_Token_None: return "nothing";
- case cmListFileLexer_Token_Space: return "space";
- case cmListFileLexer_Token_Newline: return "newline";
- case cmListFileLexer_Token_Identifier: return "identifier";
- case cmListFileLexer_Token_ParenLeft: return "left paren";
- case cmListFileLexer_Token_ParenRight: return "right paren";
- case cmListFileLexer_Token_ArgumentUnquoted: return "unquoted argument";
- case cmListFileLexer_Token_ArgumentQuoted: return "quoted argument";
- case cmListFileLexer_Token_BadCharacter: return "bad character";
- case cmListFileLexer_Token_BadString: return "unterminated string";
- }
- return "unknown token";
-}
diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h
index cc78b5c2f..f243010ad 100644
--- a/Source/cmListFileLexer.h
+++ b/Source/cmListFileLexer.h
@@ -1,19 +1,9 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmListFileLexer_h
#define cmListFileLexer_h
-typedef enum cmListFileLexer_Type_e
-{
+typedef enum cmListFileLexer_Type_e {
cmListFileLexer_Token_None,
cmListFileLexer_Token_Space,
cmListFileLexer_Token_Newline,
@@ -22,7 +12,10 @@ typedef enum cmListFileLexer_Type_e
cmListFileLexer_Token_ParenRight,
cmListFileLexer_Token_ArgumentUnquoted,
cmListFileLexer_Token_ArgumentQuoted,
+ cmListFileLexer_Token_ArgumentBracket,
+ cmListFileLexer_Token_CommentBracket,
cmListFileLexer_Token_BadCharacter,
+ cmListFileLexer_Token_BadBracket,
cmListFileLexer_Token_BadString
} cmListFileLexer_Type;
@@ -36,15 +29,27 @@ struct cmListFileLexer_Token_s
int column;
};
+enum cmListFileLexer_BOM_e
+{
+ cmListFileLexer_BOM_None,
+ cmListFileLexer_BOM_Broken,
+ cmListFileLexer_BOM_UTF8,
+ cmListFileLexer_BOM_UTF16BE,
+ cmListFileLexer_BOM_UTF16LE,
+ cmListFileLexer_BOM_UTF32BE,
+ cmListFileLexer_BOM_UTF32LE
+};
+typedef enum cmListFileLexer_BOM_e cmListFileLexer_BOM;
+
typedef struct cmListFileLexer_s cmListFileLexer;
#ifdef __cplusplus
-extern "C"
-{
+extern "C" {
#endif
-cmListFileLexer* cmListFileLexer_New();
-int cmListFileLexer_SetFileName(cmListFileLexer*, const char*);
+cmListFileLexer* cmListFileLexer_New(void);
+int cmListFileLexer_SetFileName(cmListFileLexer*, const char*,
+ cmListFileLexer_BOM* bom);
int cmListFileLexer_SetString(cmListFileLexer*, const char*);
cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer*);
long cmListFileLexer_GetCurrentLine(cmListFileLexer*);
diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx
index 462e086ef..00a30bf0e 100644
--- a/Source/cmLoadCacheCommand.cxx
+++ b/Source/cmLoadCacheCommand.cxx
@@ -1,121 +1,100 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLoadCacheCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmLoadCacheCommand.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
-#include <cmsys/RegularExpression.hxx>
+class cmExecutionStatus;
// cmLoadCacheCommand
-bool cmLoadCacheCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if (args.size()< 1)
- {
+ if (args.empty()) {
this->SetError("called with wrong number of arguments.");
- }
+ }
- if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX")
- {
+ if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") {
return this->ReadWithPrefix(args);
- }
+ }
// 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;
+ bool excludeFiles = false;
unsigned int i;
- std::set<cmStdString> excludes;
+ std::set<std::string> excludes;
- for(i=0; i<args.size(); i++)
- {
- if (excludeFiles)
- {
+ for (i = 0; i < args.size(); i++) {
+ if (excludeFiles) {
excludes.insert(args[i]);
- }
- if (args[i] == "EXCLUDE")
- {
- excludeFiles=true;
- }
- if (excludeFiles && (args[i] == "INCLUDE_INTERNALS"))
- {
+ }
+ if (args[i] == "EXCLUDE") {
+ excludeFiles = true;
+ }
+ if (excludeFiles && (args[i] == "INCLUDE_INTERNALS")) {
break;
- }
}
+ }
// Internal cache entries to be imported.
// If this set is empty, no internal cache entries are
// brought in.
- bool includeFiles=false;
- std::set<cmStdString> includes;
+ bool includeFiles = false;
+ std::set<std::string> includes;
- for(i=0; i<args.size(); i++)
- {
- if (includeFiles)
- {
+ for (i = 0; i < args.size(); i++) {
+ if (includeFiles) {
includes.insert(args[i]);
- }
- if (args[i] == "INCLUDE_INTERNALS")
- {
- includeFiles=true;
- }
- if (includeFiles && (args[i] == "EXCLUDE"))
- {
+ }
+ if (args[i] == "INCLUDE_INTERNALS") {
+ includeFiles = true;
+ }
+ if (includeFiles && (args[i] == "EXCLUDE")) {
break;
- }
}
+ }
// 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 (i = 0; i < args.size(); i++) {
+ if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS")) {
break;
- }
- this->Makefile->GetCacheManager()->LoadCache(args[i].c_str(), false,
- excludes, includes);
}
-
+ this->Makefile->GetCMakeInstance()->LoadCache(args[i], false, excludes,
+ includes);
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
{
// Make sure we have a prefix.
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->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()))
- {
+ std::string cacheFile = args[0] + "/CMakeCache.txt";
+ if (!cmSystemTools::FileExists(cacheFile.c_str())) {
std::string e = "Cannot load cache file from " + cacheFile;
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
- }
+ }
// Prepare the table of variables to read.
this->Prefix = args[2];
- for(unsigned int i=3; i < args.size(); ++i)
- {
- this->VariablesToRead.insert(args[i]);
- }
+ this->VariablesToRead.insert(args.begin() + 3, args.end());
// Read the cache file.
- std::ifstream fin(cacheFile.c_str());
+ cmsys::ifstream fin(cacheFile.c_str());
// This is a big hack read loop to overcome a buggy ifstream
// implementation on HP-UX. This should work on all platforms even
@@ -123,74 +102,62 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
const int bufferSize = 4096;
char buffer[bufferSize];
std::string line;
- while(fin)
- {
+ while (fin) {
// Read a block of the file.
fin.read(buffer, bufferSize);
- if(fin.gcount())
- {
+ if (fin.gcount()) {
// Parse for newlines directly.
const char* i = buffer;
- const char* end = buffer+fin.gcount();
- while(i != end)
- {
+ const char* end = buffer + fin.gcount();
+ while (i != end) {
const char* begin = i;
- while(i != end && *i != '\n') { ++i; }
- if(i == begin || *(i-1) != '\r')
- {
+ while (i != end && *i != '\n') {
+ ++i;
+ }
+ if (i == begin || *(i - 1) != '\r') {
// Include this portion of the line.
- line += std::string(begin, i-begin);
- }
- else
- {
+ line += std::string(begin, i - begin);
+ } else {
// Include this portion of the line.
// Don't include the \r in a \r\n pair.
- line += std::string(begin, i-1-begin);
- }
- if(i != end)
- {
+ line += std::string(begin, i - 1 - begin);
+ }
+ if (i != end) {
// Completed a line.
this->CheckLine(line.c_str());
line = "";
// Skip the newline character.
++i;
- }
}
}
}
- if(line.length())
- {
+ }
+ if (!line.empty()) {
// Partial last line.
this->CheckLine(line.c_str());
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
void cmLoadCacheCommand::CheckLine(const char* line)
{
// Check one line of the cache file.
std::string var;
std::string value;
- cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
- if(cmCacheManager::ParseEntry(line, var, value, type))
- {
+ 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 (this->VariablesToRead.find(var) != this->VariablesToRead.end()) {
// This was requested. Set this variable locally with the given
// prefix.
var = this->Prefix + var;
- if(value.length())
- {
- this->Makefile->AddDefinition(var.c_str(), value.c_str());
- }
- else
- {
- this->Makefile->RemoveDefinition(var.c_str());
- }
+ if (!value.empty()) {
+ this->Makefile->AddDefinition(var, value.c_str());
+ } else {
+ this->Makefile->RemoveDefinition(var);
}
}
+ }
}
diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h
index f55cbb3c1..1a8a0fc4c 100644
--- a/Source/cmLoadCacheCommand.h
+++ b/Source/cmLoadCacheCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLoadCacheCommand_h
#define cmLoadCacheCommand_h
+#include "cmConfigure.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmLoadCacheCommand
* \brief load a cache file
*
@@ -25,65 +24,21 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmLoadCacheCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmLoadCacheCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "load_cache";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Load in the values from another project's CMake cache.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " load_cache(pathToCacheFile READ_WITH_PREFIX\n"
- " prefix entry1...)\n"
- "Read the cache and store the requested entries in variables with "
- "their name prefixed with the given prefix. "
- "This only reads the values, and does not create entries in the local "
- "project's cache.\n"
- " load_cache(pathToCacheFile [EXCLUDE entry1...]\n"
- " [INCLUDE_INTERNALS entry1...])\n"
- "Load in the values from another cache and store them in the local "
- "project's cache as internal entries. This is useful for a project "
- "that depends on another project built in a different tree. "
- "EXCLUDE option can be used to provide a list of entries to be "
- "excluded. "
- "INCLUDE_INTERNALS can be used to provide a list of internal entries "
- "to be included. Normally, no internal entries are brought in. Use "
- "of this form of the command is strongly discouraged, but it is "
- "provided for backward compatibility.";
- }
-
- cmTypeMacro(cmLoadCacheCommand, cmCommand);
protected:
-
- std::set<cmStdString> VariablesToRead;
+ std::set<std::string> VariablesToRead;
std::string Prefix;
bool ReadWithPrefix(std::vector<std::string> const& args);
void CheckLine(const char* line);
};
-
#endif
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index b2acf06ad..92a32a147 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -1,60 +1,58 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLoadCommandCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <signal.h>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmLoadCommandCommand.h"
-#include "cmCPluginAPI.h"
#include "cmCPluginAPI.cxx"
+#include "cmCPluginAPI.h"
#include "cmDynamicLoader.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
-#include <cmsys/DynamicLoader.hxx>
-
-#include <stdlib.h>
+class cmExecutionStatus;
#ifdef __QNX__
-# include <malloc.h> /* for malloc/free on QNX */
+#include <malloc.h> /* for malloc/free on QNX */
#endif
-#include <signal.h>
extern "C" void TrapsForSignalsCFunction(int sig);
-
// a class for loadabple commands
class cmLoadedCommand : public cmCommand
{
public:
- cmLoadedCommand() {
- memset(&this->info,0,sizeof(this->info));
+ cmLoadedCommand()
+ {
+ memset(&this->info, 0, sizeof(this->info));
this->info.CAPI = &cmStaticCAPI;
}
///! clean up any memory allocated by the plugin
- ~cmLoadedCommand();
+ ~cmLoadedCommand() CM_OVERRIDE;
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- cmLoadedCommand *newC = new cmLoadedCommand;
- // we must copy when we clone
- memcpy(&newC->info,&this->info,sizeof(info));
- return newC;
- }
+ cmCommand* Clone() CM_OVERRIDE
+ {
+ cmLoadedCommand* newC = new cmLoadedCommand;
+ // we must copy when we clone
+ memcpy(&newC->info, &this->info, sizeof(info));
+ return newC;
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&) CM_OVERRIDE;
/**
* This is called at the end after all the information
@@ -62,83 +60,39 @@ public:
* not implement this method. At this point, reading and
* writing to the cache can be done.
*/
- virtual void FinalPass();
- virtual bool HasFinalPass() const
- { return this->info.FinalPass? true:false; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return info.Name; }
+ void FinalPass() CM_OVERRIDE;
+ bool HasFinalPass() const CM_OVERRIDE
+ {
+ return this->info.FinalPass != CM_NULLPTR;
+ }
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- if (this->info.GetTerseDocumentation)
- {
- cmLoadedCommand::InstallSignalHandlers(info.Name);
- const char* ret = info.GetTerseDocumentation();
- cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- return ret;
- }
- else
- {
- return "LoadedCommand without any additional documentation";
- }
- }
static const char* LastName;
static void TrapsForSignals(int sig)
- {
- fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
- cmLoadedCommand::LastName, 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 = "????";
- }
+ {
+ cmLoadedCommand::LastName = name;
+ if (!name) {
+ cmLoadedCommand::LastName = "????";
+ }
- if(!remove)
- {
- signal(SIGSEGV, TrapsForSignalsCFunction);
+ if (!remove) {
+ signal(SIGSEGV, TrapsForSignalsCFunction);
#ifdef SIGBUS
- signal(SIGBUS, TrapsForSignalsCFunction);
+ signal(SIGBUS, TrapsForSignalsCFunction);
#endif
- signal(SIGILL, TrapsForSignalsCFunction);
- }
- else
- {
- signal(SIGSEGV, 0);
+ signal(SIGILL, TrapsForSignalsCFunction);
+ } else {
+ signal(SIGSEGV, CM_NULLPTR);
#ifdef SIGBUS
- signal(SIGBUS, 0);
+ signal(SIGBUS, CM_NULLPTR);
#endif
- signal(SIGILL, 0);
- }
+ signal(SIGILL, CM_NULLPTR);
}
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- if (this->info.GetFullDocumentation)
- {
- cmLoadedCommand::InstallSignalHandlers(info.Name);
- const char* ret = info.GetFullDocumentation();
- cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- return ret;
- }
- else
- {
- return "LoadedCommand without any additional documentation";
- }
- }
-
- cmTypeMacro(cmLoadedCommand, cmCommand);
+ }
cmLoadedCommandInfo info;
};
@@ -148,92 +102,81 @@ extern "C" void TrapsForSignalsCFunction(int sig)
cmLoadedCommand::TrapsForSignals(sig);
}
-
-const char* cmLoadedCommand::LastName = 0;
+const char* cmLoadedCommand::LastName = CM_NULLPTR;
bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &)
+ cmExecutionStatus&)
{
- if (!info.InitialPass)
- {
+ if (!info.InitialPass) {
return true;
- }
+ }
// clear the error string
- if (this->info.Error)
- {
+ if (this->info.Error) {
free(this->info.Error);
- }
+ }
// create argc and argv and then invoke the command
- int argc = static_cast<int> (args.size());
- char **argv = 0;
- if (argc)
- {
- argv = (char **)malloc(argc*sizeof(char *));
- }
+ int argc = static_cast<int>(args.size());
+ char** argv = CM_NULLPTR;
+ if (argc) {
+ argv = (char**)malloc(argc * sizeof(char*));
+ }
int i;
- for (i = 0; i < argc; ++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);
+ int result =
+ info.InitialPass((void*)&info, (void*)this->Makefile, argc, argv);
cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- cmFreeArguments(argc,argv);
+ cmFreeArguments(argc, argv);
- if (result)
- {
+ if (result) {
return true;
- }
+ }
/* Initial Pass must have failed so set the error string */
- if (this->info.Error)
- {
+ if (this->info.Error) {
this->SetError(this->info.Error);
- }
+ }
return false;
}
void cmLoadedCommand::FinalPass()
{
- if (this->info.FinalPass)
- {
+ if (this->info.FinalPass) {
cmLoadedCommand::InstallSignalHandlers(info.Name);
- this->info.FinalPass((void *)&this->info,(void *)this->Makefile);
+ this->info.FinalPass((void*)&this->info, (void*)this->Makefile);
cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- }
+ }
}
cmLoadedCommand::~cmLoadedCommand()
{
- if (this->info.Destructor)
- {
+ if (this->info.Destructor) {
cmLoadedCommand::InstallSignalHandlers(info.Name);
- this->info.Destructor((void *)&this->info);
+ this->info.Destructor((void*)&this->info);
cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- }
- if (this->info.Error)
- {
+ }
+ if (this->info.Error) {
free(this->info.Error);
- }
+ }
}
// cmLoadCommandCommand
-bool cmLoadCommandCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
// 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.c_str());
+ this->Makefile->RemoveDefinition(reportVar);
// the file must exist
std::string moduleName =
@@ -244,72 +187,64 @@ bool cmLoadCommandCommand
// search for the file
std::vector<std::string> path;
- for (unsigned int j = 1; j < args.size(); j++)
- {
+ for (unsigned int j = 1; j < args.size(); j++) {
// expand variables
std::string exp = args[j];
cmSystemTools::ExpandRegistryValues(exp);
// Glob the entry in case of wildcards.
- cmSystemTools::GlobDirs(exp.c_str(), path);
- }
+ cmSystemTools::GlobDirs(exp, path);
+ }
// Try to find the program.
- std::string fullPath = cmSystemTools::FindFile(moduleName.c_str(), path);
- if (fullPath == "")
- {
- cmOStringStream e;
- e << "Attempt to load command failed from file \""
- << moduleName << "\"";
- this->SetError(e.str().c_str());
+ 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());
return false;
- }
+ }
// try loading the shared library / dll
- cmsys::DynamicLoader::LibraryHandle lib
- = cmDynamicLoader::OpenLibrary(fullPath.c_str());
- if(!lib)
- {
+ cmsys::DynamicLoader::LibraryHandle lib =
+ cmDynamicLoader::OpenLibrary(fullPath.c_str());
+ if (!lib) {
std::string err = "Attempt to load the library ";
err += fullPath + " failed.";
const char* error = cmsys::DynamicLoader::LastError();
- if ( error )
- {
+ if (error) {
err += " Additional error info is:\n";
err += error;
- }
- this->SetError(err.c_str());
- return false;
}
+ this->SetError(err);
+ return false;
+ }
// Report what file was loaded for this command.
- this->Makefile->AddDefinition(reportVar.c_str(), fullPath.c_str());
+ this->Makefile->AddDefinition(reportVar, fullPath.c_str());
// find the init function
std::string initFuncName = args[0] + "Init";
- CM_INIT_FUNCTION initFunction
- = (CM_INIT_FUNCTION)
- cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName.c_str());
- if ( !initFunction )
- {
+ CM_INIT_FUNCTION initFunction =
+ (CM_INIT_FUNCTION)cmsys::DynamicLoader::GetSymbolAddress(lib,
+ initFuncName);
+ if (!initFunction) {
initFuncName = "_";
initFuncName += args[0];
initFuncName += "Init";
initFunction = (CM_INIT_FUNCTION)(
- cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName.c_str()));
- }
+ cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
+ }
// if the symbol is found call it to set the name on the
// function blocker
- if(initFunction)
- {
+ if (initFunction) {
// create a function blocker and set it up
- cmLoadedCommand *f = new cmLoadedCommand();
+ cmLoadedCommand* f = new cmLoadedCommand();
(*initFunction)(&f->info);
- this->Makefile->AddCommand(f);
+ this->Makefile->GetState()->AddScriptedCommand(args[0], f);
return true;
- }
+ }
this->SetError("Attempt to load command failed. "
"No init function found.");
return false;
}
-
diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h
index f0b34ee59..030786e3d 100644
--- a/Source/cmLoadCommandCommand.h
+++ b/Source/cmLoadCommandCommand.h
@@ -1,75 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLoadCommandCommand_h
#define cmLoadCommandCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-/** \class cmLoadCommandCommand
- * \brief Load in a Command plugin
- *
- * cmLoadCommandCommand loads a command into CMake
- */
+class cmExecutionStatus;
+
class cmLoadCommandCommand : public cmCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmLoadCommandCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "load_command";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Load a command into a running CMake.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " load_command(COMMAND_NAME <loc1> [loc2 ...])\n"
- "The given locations are searched for a library whose name is "
- "cmCOMMAND_NAME. If found, it is loaded as a module and the command "
- "is added to the set of available CMake commands. Usually, "
- "TRY_COMPILE is used before this command to compile the module. "
- "If the command is successfully loaded a variable named\n"
- " CMAKE_LOADED_COMMAND_<COMMAND_NAME>\n"
- "will be set to the full path of the module that was loaded. "
- "Otherwise the variable will not be set.";
- }
-
- cmTypeMacro(cmLoadCommandCommand, cmCommand);
+ cmCommand* Clone() CM_OVERRIDE { return new cmLoadCommandCommand; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
new file mode 100644
index 000000000..6524db401
--- /dev/null
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -0,0 +1,79 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLocalCommonGenerator.h"
+
+#include <vector>
+
+#include "cmGeneratorTarget.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+
+class cmGlobalGenerator;
+
+cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
+ cmMakefile* mf,
+ std::string const& wd)
+ : cmLocalGenerator(gg, mf)
+ , WorkingDirectory(wd)
+{
+ // Store the configuration name that will be generated.
+ 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 = "";
+ }
+}
+
+cmLocalCommonGenerator::~cmLocalCommonGenerator()
+{
+}
+
+std::string cmLocalCommonGenerator::GetTargetFortranFlags(
+ cmGeneratorTarget const* target, std::string const& config)
+{
+ 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);
+ }
+
+ // 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),
+ 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;
+ this->AppendFlags(flags, modflag);
+ }
+
+ // If there is a separate module path flag then duplicate the
+ // include path with it. This compiler does not search the include
+ // path for modules.
+ if (const char* modpath_flag =
+ 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);
+ this->AppendFlags(flags, flg);
+ }
+ }
+
+ return flags;
+}
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
new file mode 100644
index 000000000..a5afcd87d
--- /dev/null
+++ b/Source/cmLocalCommonGenerator.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 cmLocalCommonGenerator_h
+#define cmLocalCommonGenerator_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#include "cmLocalGenerator.h"
+
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
+
+/** \class cmLocalCommonGenerator
+ * \brief Common infrastructure for Makefile and Ninja local generators.
+ */
+class cmLocalCommonGenerator : public cmLocalGenerator
+{
+public:
+ cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf,
+ std::string const& wd);
+ ~cmLocalCommonGenerator() CM_OVERRIDE;
+
+ std::string const& GetConfigName() { return this->ConfigName; }
+
+ std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
+
+ std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
+ std::string const& config) CM_OVERRIDE;
+
+protected:
+ std::string WorkingDirectory;
+
+ std::string ConfigName;
+
+ friend class cmCommonTargetGenerator;
+};
+
+#endif
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 9c0410965..6ce31c5ea 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1,281 +1,241 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalGenerator.h"
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpressionEvaluationFile.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h"
-#include "cmInstallFilesGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
+#include "cmLinkLineComputer.h"
#include "cmMakefile.h"
+#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmTest.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateTypes.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 <cmsys/MD5.h>
+#define CM_LG_ENCODE_OBJECT_NAMES
+#include "cmCryptoHash.h"
#endif
-#include <cmsys/System.h>
-
-#include <ctype.h> // for isalpha
-
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
#include <assert.h>
+#include <iterator>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <utility>
#if defined(__HAIKU__)
-#include <StorageKit.h>
+#include <FindDirectory.h>
+#include <StorageDefs.h>
#endif
-cmLocalGenerator::cmLocalGenerator()
-{
- this->Makefile = 0; // moved to after set on global
- this->Parent = 0;
- this->WindowsShell = false;
- this->WindowsVSIDE = false;
- this->WatcomWMake = false;
- this->MinGWMake = false;
- this->NMake = false;
- this->MSYSShell = false;
- this->LinkScriptShell = false;
- this->IgnoreLibPrefix = false;
- this->UseRelativePaths = false;
- this->Configured = false;
- this->EmitUniversalBinaryFlags = true;
- this->RelativePathsConfigured = false;
- this->PathConversionsSetup = false;
- this->BackwardsCompatibility = 0;
- this->BackwardsCompatibilityFinal = false;
-}
-
-cmLocalGenerator::~cmLocalGenerator()
-{
- delete this->Makefile;
-}
-
-//----------------------------------------------------------------------------
-class cmLocalGeneratorCurrent
-{
- cmGlobalGenerator* GG;
- cmLocalGenerator* LG;
-public:
- cmLocalGeneratorCurrent(cmLocalGenerator* lg)
- {
- this->GG = lg->GetGlobalGenerator();
- this->LG = this->GG->GetCurrentLocalGenerator();
- this->GG->SetCurrentLocalGenerator(lg);
- }
- ~cmLocalGeneratorCurrent()
- {
- this->GG->SetCurrentLocalGenerator(this->LG);
- }
+// List of variables that are replaced when
+// rules are expanced. These variables are
+// 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"
};
-//----------------------------------------------------------------------------
-void cmLocalGenerator::Configure()
+cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
+ : cmOutputConverter(makefile->GetStateSnapshot())
+ , StateSnapshot(makefile->GetStateSnapshot())
+ , DirectoryBacktrace(makefile->GetBacktrace())
{
- // Manage the global generator's current local generator.
- cmLocalGeneratorCurrent clg(this);
- static_cast<void>(clg);
+ this->GlobalGenerator = gg;
+
+ this->Makefile = makefile;
- // make sure the CMakeFiles dir is there
- std::string filesDir = this->Makefile->GetStartOutputDirectory();
- filesDir += cmake::GetCMakeFilesDirectory();
- cmSystemTools::MakeDirectory(filesDir.c_str());
+ this->AliasTargets = makefile->GetAliasTargets();
- // find & read the list file
- this->ReadInputFile();
+ this->EmitUniversalBinaryFlags = true;
+ this->BackwardsCompatibility = 0;
+ this->BackwardsCompatibilityFinal = false;
- // at the end of the ReadListFile handle any old style subdirs
- // first get all the subdirectories
- std::vector<cmLocalGenerator *> subdirs = this->GetChildren();
+ this->ComputeObjectMaxPath();
- // for each subdir recurse
- std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
- for (; sdi != subdirs.end(); ++sdi)
- {
- if (!(*sdi)->Configured)
- {
- this->Makefile->ConfigureSubDirectory(*sdi);
+ std::vector<std::string> enabledLanguages =
+ this->GetState()->GetEnabledLanguages();
+
+ if (const char* sysrootCompile =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+ this->CompilerSysroot = sysrootCompile;
+ } else {
+ this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+ }
+
+ if (const char* sysrootLink =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
+ this->LinkerSysroot = sysrootLink;
+ } else {
+ 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;
+ if (lang == "NONE") {
+ continue;
+ }
+ this->Compilers["CMAKE_" + lang + "_COMPILER"] = lang;
+
+ this->VariableMappings["CMAKE_" + lang + "_COMPILER"] =
+ this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER");
+
+ std::string const& compilerArg1 = "CMAKE_" + lang + "_COMPILER_ARG1";
+ std::string const& compilerTarget = "CMAKE_" + lang + "_COMPILER_TARGET";
+ std::string const& compilerOptionTarget =
+ "CMAKE_" + lang + "_COMPILE_OPTIONS_TARGET";
+ std::string const& compilerExternalToolchain =
+ "CMAKE_" + lang + "_COMPILER_EXTERNAL_TOOLCHAIN";
+ std::string const& compilerOptionExternalToolchain =
+ "CMAKE_" + lang + "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN";
+ std::string const& compilerOptionSysroot =
+ "CMAKE_" + lang + "_COMPILE_OPTIONS_SYSROOT";
+
+ this->VariableMappings[compilerArg1] =
+ this->Makefile->GetSafeDefinition(compilerArg1);
+ this->VariableMappings[compilerTarget] =
+ this->Makefile->GetSafeDefinition(compilerTarget);
+ this->VariableMappings[compilerOptionTarget] =
+ this->Makefile->GetSafeDefinition(compilerOptionTarget);
+ this->VariableMappings[compilerExternalToolchain] =
+ this->Makefile->GetSafeDefinition(compilerExternalToolchain);
+ this->VariableMappings[compilerOptionExternalToolchain] =
+ this->Makefile->GetSafeDefinition(compilerOptionExternalToolchain);
+ 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);
}
+
+ this->VariableMappings[actualReplace] =
+ this->Makefile->GetSafeDefinition(actualReplace);
}
+ }
+}
- // Check whether relative paths should be used for optionally
- // relative paths.
- this->UseRelativePaths = this->Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
+cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander()
+ const
+{
+ return new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
+ this->CompilerSysroot,
+ this->LinkerSysroot);
+}
- this->ComputeObjectMaxPath();
+cmLocalGenerator::~cmLocalGenerator()
+{
+ cmDeleteAll(this->GeneratorTargets);
+ cmDeleteAll(this->OwnedImportedGeneratorTargets);
+}
- this->Configured = true;
+void cmLocalGenerator::IssueMessage(cmake::MessageType t,
+ std::string const& text) const
+{
+ this->GetCMakeInstance()->IssueMessage(t, text, this->DirectoryBacktrace);
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::ComputeObjectMaxPath()
{
- // Choose a maximum object file name length.
+// Choose a maximum object file name length.
#if defined(_WIN32) || defined(__CYGWIN__)
this->ObjectPathMax = 250;
#else
this->ObjectPathMax = 1000;
#endif
const char* plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX");
- if(plen && *plen)
- {
+ if (plen && *plen) {
unsigned int pmax;
- if(sscanf(plen, "%u", &pmax) == 1)
- {
- if(pmax >= 128)
- {
+ if (sscanf(plen, "%u", &pmax) == 1) {
+ if (pmax >= 128) {
this->ObjectPathMax = pmax;
- }
- else
- {
- cmOStringStream w;
+ } else {
+ std::ostringstream w;
w << "CMAKE_OBJECT_PATH_MAX is set to " << pmax
<< ", which is less than the minimum of 128. "
<< "The value will be ignored.";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
- }
+ this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
- else
- {
- cmOStringStream w;
+ } 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->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
- }
+ this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
+ }
this->ObjectMaxPathViolations.clear();
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::ReadInputFile()
-{
- // Look for the CMakeLists.txt file.
- std::string currentStart = this->Makefile->GetStartDirectory();
- currentStart += "/CMakeLists.txt";
- if(cmSystemTools::FileExists(currentStart.c_str(), true))
- {
- this->Makefile->ReadListFile(currentStart.c_str());
- return;
- }
-
- if(!this->Parent)
- {
- return;
- }
-
- // The file is missing. Check policy CMP0014.
- cmMakefile* mf = this->Parent->GetMakefile();
- cmOStringStream e;
- e << "The source directory\n"
- << " " << this->Makefile->GetStartDirectory() << "\n"
- << "does not contain a CMakeLists.txt file.";
- switch (mf->GetPolicyStatus(cmPolicies::CMP0014))
- {
- case cmPolicies::WARN:
- // Print the warning.
- e << "\n"
- << "CMake does not support this case but it used "
- << "to work accidentally and is being allowed for "
- << "compatibility."
- << "\n"
- << mf->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0014);
- mf->IssueMessage(cmake::AUTHOR_WARNING, e.str());
- case cmPolicies::OLD:
- // OLD behavior does not warn.
- return;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- e << "\n"
- << mf->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0014);
- case cmPolicies::NEW:
- // NEW behavior prints the error.
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
- break;
- }
-}
-
-void cmLocalGenerator::SetupPathConversions()
-{
- // Setup the current output directory components for use by
- // Convert
- std::string outdir;
- outdir =
- cmSystemTools::CollapseFullPath(this->Makefile->GetHomeDirectory());
- cmSystemTools::SplitPath(outdir.c_str(), this->HomeDirectoryComponents);
- outdir =
- cmSystemTools::CollapseFullPath(this->Makefile->GetStartDirectory());
- cmSystemTools::SplitPath(outdir.c_str(), this->StartDirectoryComponents);
-
- outdir = cmSystemTools::CollapseFullPath
- (this->Makefile->GetHomeOutputDirectory());
- cmSystemTools::SplitPath(outdir.c_str(),
- this->HomeOutputDirectoryComponents);
-
- outdir = cmSystemTools::CollapseFullPath
- (this->Makefile->GetStartOutputDirectory());
- cmSystemTools::SplitPath(outdir.c_str(),
- this->StartOutputDirectoryComponents);
-}
-
-
-void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
-{
- this->GlobalGenerator = gg;
- this->Makefile = new cmMakefile;
- this->Makefile->SetLocalGenerator(this);
-
- // setup the home directories
- this->Makefile->GetProperties().SetCMakeInstance(gg->GetCMakeInstance());
- this->Makefile->SetHomeDirectory(
- gg->GetCMakeInstance()->GetHomeDirectory());
- this->Makefile->SetHomeOutputDirectory(
- gg->GetCMakeInstance()->GetHomeOutputDirectory());
-}
-
-void cmLocalGenerator::ConfigureFinalPass()
-{
- this->Makefile->ConfigureFinalPass();
-}
-
void cmLocalGenerator::TraceDependencies()
{
+ 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) {
+ this->GlobalGenerator->CreateEvaluationSourceFiles(*ci);
+ }
// Generate the rule files for each target.
- cmTargets& targets = this->Makefile->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- t->second.TraceDependencies();
+ std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+ t != targets.end(); ++t) {
+ if ((*t)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
}
+ (*t)->TraceDependencies();
+ }
}
void cmLocalGenerator::GenerateTestFiles()
{
- if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") )
- {
+ if (!this->Makefile->IsOn("CMAKE_TESTING_ENABLED")) {
return;
- }
+ }
// Compute the set of configurations.
std::vector<std::string> configurationTypes;
- const char* config =
+ const std::string& config =
this->Makefile->GetConfigurations(configurationTypes, false);
- std::string file = this->Makefile->GetStartOutputDirectory();
+ std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
file += "/";
file += "CTestTestfile.cmake";
@@ -284,9 +244,9 @@ void cmLocalGenerator::GenerateTestFiles()
fout << "# CMake generated Testfile for " << std::endl
<< "# Source directory: "
- << this->Makefile->GetStartDirectory() << std::endl
+ << this->StateSnapshot.GetDirectory().GetCurrentSource() << std::endl
<< "# Build directory: "
- << this->Makefile->GetStartOutputDirectory() << std::endl
+ << this->StateSnapshot.GetDirectory().GetCurrentBinary() << std::endl
<< "# " << std::endl
<< "# This file includes the relevant testing commands "
<< "required for " << std::endl
@@ -295,1095 +255,566 @@ void cmLocalGenerator::GenerateTestFiles()
const char* testIncludeFile =
this->Makefile->GetProperty("TEST_INCLUDE_FILE");
- if ( testIncludeFile )
- {
- fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
- }
+ if (testIncludeFile) {
+ fout << "include(\"" << testIncludeFile << "\")" << 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)
- {
+ 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);
+ }
+ typedef std::vector<cmStateSnapshot> vec_t;
+ 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) {
+ // TODO: Use add_subdirectory instead?
+ std::string outP = i->GetDirectory().GetCurrentBinary();
+ outP = this->ConvertToRelativePath(parentBinDir, outP);
+ outP = cmOutputConverter::EscapeForCMake(outP);
+ fout << "subdirs(" << outP << ")" << std::endl;
+ }
+}
+
+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);
+ }
+}
+
+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);
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return;
}
- if ( this->Children.size())
- {
- size_t i;
- for(i = 0; i < this->Children.size(); ++i)
- {
- fout << "SUBDIRS(";
- std::string outP =
- this->Children[i]->GetMakefile()->GetStartOutputDirectory();
- fout << this->Convert(outP.c_str(),START_OUTPUT);
- fout << ")" << std::endl;
- }
+ std::vector<std::string> files = (*li)->GetFiles();
+ std::sort(files.begin(), files.end());
+
+ std::vector<std::string> intersection;
+ std::set_intersection(files.begin(), files.end(), generatedFiles.begin(),
+ generatedFiles.end(),
+ std::back_inserter(intersection));
+ if (!intersection.empty()) {
+ cmSystemTools::Error("Files to be generated by multiple different "
+ "commands: ",
+ cmWrap('"', intersection, '"', " ").c_str());
+ 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());
+ }
}
-//----------------------------------------------------------------------------
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)
- {
- if(!cmSystemTools::GetEnv("SystemDrive", prefix_win32))
- {
+ if (!prefix) {
+ if (!cmSystemTools::GetEnv("SystemDrive", prefix_win32)) {
prefix_win32 = "C:";
- }
+ }
const char* project_name = this->Makefile->GetDefinition("PROJECT_NAME");
- if(project_name && project_name[0])
- {
+ if (project_name && project_name[0]) {
prefix_win32 += "/Program Files/";
prefix_win32 += project_name;
- }
- else
- {
+ } else {
prefix_win32 += "/InstalledCMakeProject";
- }
- prefix = prefix_win32.c_str();
}
+ prefix = prefix_win32.c_str();
+ }
#elif defined(__HAIKU__)
- if (!prefix)
- {
- BPath dir;
- if (find_directory(B_COMMON_DIRECTORY, &dir) == B_OK)
- {
- prefix = dir.Path();
- }
- else
- {
- prefix = "/boot/common";
- }
- }
+ char dir[B_PATH_NAME_LENGTH];
+ if (!prefix) {
+ if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) ==
+ B_OK) {
+ prefix = dir;
+ } else {
+ prefix = "/boot/system";
+ }
+ }
#else
- if (!prefix)
- {
+ if (!prefix) {
prefix = "/usr/local";
- }
+ }
#endif
+ if (const char* stagingPrefix =
+ this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) {
+ prefix = stagingPrefix;
+ }
// Compute the set of configurations.
std::vector<std::string> configurationTypes;
- const char* config =
+ const std::string& config =
this->Makefile->GetConfigurations(configurationTypes, false);
// Choose a default install configuration.
- const char* default_config = config;
- const char* default_order[] = {"RELEASE", "MINSIZEREL",
- "RELWITHDEBINFO", "DEBUG", 0};
- for(const char** c = default_order; *c && !default_config; ++c)
- {
- for(std::vector<std::string>::iterator i = configurationTypes.begin();
- i != configurationTypes.end(); ++i)
- {
- if(cmSystemTools::UpperCase(*i) == *c)
- {
- default_config = i->c_str();
- }
+ std::string default_config = config;
+ const char* default_order[] = { "RELEASE", "MINSIZEREL", "RELWITHDEBINFO",
+ "DEBUG", CM_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;
}
}
- if(!default_config && !configurationTypes.empty())
- {
- default_config = configurationTypes[0].c_str();
- }
- if(!default_config)
- {
- default_config = "Release";
- }
+ }
+ if (default_config.empty() && !configurationTypes.empty()) {
+ default_config = configurationTypes[0];
+ }
// Create the install script file.
- std::string file = this->Makefile->GetStartOutputDirectory();
- std::string homedir = this->Makefile->GetHomeOutputDirectory();
- std::string currdir = this->Makefile->GetCurrentOutputDirectory();
- cmSystemTools::ConvertToUnixSlashes(file);
- cmSystemTools::ConvertToUnixSlashes(homedir);
- cmSystemTools::ConvertToUnixSlashes(currdir);
+ std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
+ std::string homedir = this->GetState()->GetBinaryDirectory();
int toplevel_install = 0;
- if ( currdir == homedir )
- {
+ if (file == homedir) {
toplevel_install = 1;
- }
+ }
file += "/cmake_install.cmake";
cmGeneratedFileStream fout(file.c_str());
fout.SetCopyIfDifferent(true);
// Write the header.
fout << "# Install script for directory: "
- << this->Makefile->GetCurrentDirectory() << std::endl << std::endl;
+ << this->StateSnapshot.GetDirectory().GetCurrentSource() << std::endl
+ << std::endl;
fout << "# Set the install prefix" << std::endl
- << "IF(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
- << " SET(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
- << "ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
- << "STRING(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
+ << "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
+ << " set(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
+ << "endif()" << std::endl
+ << "string(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
<< "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl
<< std::endl;
// Write support code for generating per-configuration install rules.
+ /* clang-format off */
fout <<
"# Set the install configuration name.\n"
- "IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
- " IF(BUILD_TYPE)\n"
- " STRING(REGEX REPLACE \"^[^A-Za-z0-9_]+\" \"\"\n"
+ "if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
+ " if(BUILD_TYPE)\n"
+ " string(REGEX REPLACE \"^[^A-Za-z0-9_]+\" \"\"\n"
" CMAKE_INSTALL_CONFIG_NAME \"${BUILD_TYPE}\")\n"
- " ELSE(BUILD_TYPE)\n"
- " SET(CMAKE_INSTALL_CONFIG_NAME \"" << default_config << "\")\n"
- " ENDIF(BUILD_TYPE)\n"
- " MESSAGE(STATUS \"Install configuration: "
+ " else()\n"
+ " set(CMAKE_INSTALL_CONFIG_NAME \"" << default_config << "\")\n"
+ " endif()\n"
+ " message(STATUS \"Install configuration: "
"\\\"${CMAKE_INSTALL_CONFIG_NAME}\\\"\")\n"
- "ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
+ "endif()\n"
"\n";
+ /* clang-format on */
// Write support code for dealing with component-specific installs.
+ /* clang-format off */
fout <<
"# Set the component getting installed.\n"
- "IF(NOT CMAKE_INSTALL_COMPONENT)\n"
- " IF(COMPONENT)\n"
- " MESSAGE(STATUS \"Install component: \\\"${COMPONENT}\\\"\")\n"
- " SET(CMAKE_INSTALL_COMPONENT \"${COMPONENT}\")\n"
- " ELSE(COMPONENT)\n"
- " SET(CMAKE_INSTALL_COMPONENT)\n"
- " ENDIF(COMPONENT)\n"
- "ENDIF(NOT CMAKE_INSTALL_COMPONENT)\n"
+ "if(NOT CMAKE_INSTALL_COMPONENT)\n"
+ " if(COMPONENT)\n"
+ " message(STATUS \"Install component: \\\"${COMPONENT}\\\"\")\n"
+ " set(CMAKE_INSTALL_COMPONENT \"${COMPONENT}\")\n"
+ " else()\n"
+ " set(CMAKE_INSTALL_COMPONENT)\n"
+ " endif()\n"
+ "endif()\n"
"\n";
+ /* clang-format on */
// Copy user-specified install options to the install code.
- if(const char* so_no_exe =
- this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE"))
- {
+ if (const char* so_no_exe =
+ this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE")) {
+ /* clang-format off */
fout <<
"# Install shared libraries without execute permission?\n"
- "IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
- " SET(CMAKE_INSTALL_SO_NO_EXE \"" << so_no_exe << "\")\n"
- "ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
+ "if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
+ " set(CMAKE_INSTALL_SO_NO_EXE \"" << so_no_exe << "\")\n"
+ "endif()\n"
"\n";
- }
+ /* clang-format on */
+ }
// Ask each install generator to write its code.
std::vector<cmInstallGenerator*> const& installers =
this->Makefile->GetInstallGenerators();
- for(std::vector<cmInstallGenerator*>::const_iterator
- gi = installers.begin();
- gi != installers.end(); ++gi)
- {
+ for (std::vector<cmInstallGenerator*>::const_iterator gi =
+ installers.begin();
+ gi != installers.end(); ++gi) {
(*gi)->Generate(fout, config, configurationTypes);
- }
+ }
// Write rules from old-style specification stored in targets.
this->GenerateTargetInstallRules(fout, config, configurationTypes);
// Include install scripts from subdirectories.
- if(!this->Children.empty())
- {
- fout << "IF(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
+ 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<cmLocalGenerator*>::const_iterator
- ci = this->Children.begin(); ci != this->Children.end(); ++ci)
- {
- if(!(*ci)->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
- {
- std::string odir = (*ci)->GetMakefile()->GetStartOutputDirectory();
+ 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.c_str()
- << "/cmake_install.cmake\")" << std::endl;
- }
+ fout << " include(\"" << odir << "/cmake_install.cmake\")"
+ << std::endl;
}
- fout << "\n";
- fout << "ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY)\n\n";
}
+ fout << "\n";
+ fout << "endif()\n\n";
+ }
// Record the install manifest.
- if ( toplevel_install )
- {
+ if (toplevel_install) {
+ /* clang-format off */
fout <<
- "IF(CMAKE_INSTALL_COMPONENT)\n"
- " SET(CMAKE_INSTALL_MANIFEST \"install_manifest_"
+ "if(CMAKE_INSTALL_COMPONENT)\n"
+ " set(CMAKE_INSTALL_MANIFEST \"install_manifest_"
"${CMAKE_INSTALL_COMPONENT}.txt\")\n"
- "ELSE(CMAKE_INSTALL_COMPONENT)\n"
- " SET(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n"
- "ENDIF(CMAKE_INSTALL_COMPONENT)\n\n";
- fout
- << "FILE(WRITE \""
- << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" "
- << "\"\")" << std::endl;
- fout
- << "FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})" << std::endl
- << " FILE(APPEND \""
- << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" "
- << "\"${file}\\n\")" << std::endl
- << "ENDFOREACH(file)" << std::endl;
- }
+ "else()\n"
+ " set(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n"
+ "endif()\n"
+ "\n"
+ "string(REPLACE \";\" \"\\n\" CMAKE_INSTALL_MANIFEST_CONTENT\n"
+ " \"${CMAKE_INSTALL_MANIFEST_FILES}\")\n"
+ "file(WRITE \"" << homedir << "/${CMAKE_INSTALL_MANIFEST}\"\n"
+ " \"${CMAKE_INSTALL_MANIFEST_CONTENT}\")\n";
+ /* clang-format on */
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::GenerateTargetManifest()
+void cmLocalGenerator::AddGeneratorTarget(cmGeneratorTarget* gt)
{
- // Collect the set of configuration types.
- std::vector<std::string> configNames;
- this->Makefile->GetConfigurations(configNames);
-
- // Add our targets to the manifest for each configuration.
- cmTargets& targets = this->Makefile->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- cmTarget& target = t->second;
- if(configNames.empty())
- {
- target.GenerateTargetManifest(0);
- }
- else
- {
- for(std::vector<std::string>::iterator ci = configNames.begin();
- ci != configNames.end(); ++ci)
- {
- const char* config = ci->c_str();
- target.GenerateTargetManifest(config);
- }
- }
- }
+ this->GeneratorTargets.push_back(gt);
+ this->GlobalGenerator->IndexGeneratorTarget(gt);
}
-void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
- const char* lang,
- cmSourceFile& source,
- cmGeneratorTarget& target)
-{
- std::string objectDir = cmSystemTools::GetFilenamePath(std::string(ofname));
- objectDir = this->Convert(objectDir.c_str(),START_OUTPUT,SHELL);
- std::string objectFile = this->Convert(ofname,START_OUTPUT,SHELL);
- std::string sourceFile =
- this->Convert(source.GetFullPath().c_str(),START_OUTPUT,SHELL,true);
- std::string varString = "CMAKE_";
- varString += lang;
- varString += "_COMPILE_OBJECT";
- std::vector<std::string> rules;
- rules.push_back(this->Makefile->GetRequiredDefinition(varString.c_str()));
- varString = "CMAKE_";
- varString += lang;
- varString += "_FLAGS";
- std::string flags;
- flags += this->Makefile->GetSafeDefinition(varString.c_str());
- flags += " ";
- {
- std::vector<std::string> includes;
- this->GetIncludeDirectories(includes, &target, lang);
- flags += this->GetIncludeFlags(includes, &target, lang);
- }
- flags += this->Makefile->GetDefineFlags();
-
- // Construct the command lines.
- cmCustomCommandLines commandLines;
- std::vector<std::string> commands;
- cmSystemTools::ExpandList(rules, commands);
- cmLocalGenerator::RuleVariables vars;
- vars.Language = lang;
- vars.Source = sourceFile.c_str();
- vars.Object = objectFile.c_str();
- vars.ObjectDir = objectDir.c_str();
- vars.Flags = flags.c_str();
- for(std::vector<std::string>::iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- // Expand the full command line string.
- this->ExpandRuleVariables(*i, vars);
-
- // Parse the string to get the custom command line.
- cmCustomCommandLine commandLine;
- std::vector<cmStdString> cmd = cmSystemTools::ParseArguments(i->c_str());
- for(std::vector<cmStdString>::iterator a = cmd.begin();
- a != cmd.end(); ++a)
- {
- commandLine.push_back(*a);
- }
-
- // Store this command line.
- commandLines.push_back(commandLine);
- }
-
- // Check for extra object-file dependencies.
- std::vector<std::string> depends;
- const char* additionalDeps = source.GetProperty("OBJECT_DEPENDS");
- if(additionalDeps)
- {
- cmSystemTools::ExpandListArgument(additionalDeps, depends);
- }
-
- // Generate a meaningful comment for the command.
- std::string comment = "Building ";
- comment += lang;
- comment += " object ";
- comment += this->Convert(ofname, START_OUTPUT);
-
- // Add the custom command to build the object file.
- this->Makefile->AddCustomCommandToOutput(
- ofname,
- depends,
- source.GetFullPath().c_str(),
- commandLines,
- comment.c_str(),
- this->Makefile->GetStartOutputDirectory()
- );
-}
-
-void cmLocalGenerator::AddBuildTargetRule(const char* llang,
- cmGeneratorTarget& target)
-{
- cmStdString objs;
- std::vector<std::string> objVector;
- // Add all the sources outputs to the depends of the target
- std::vector<cmSourceFile*> const& classes = target.GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i)
- {
- cmSourceFile* sf = *i;
- if(!sf->GetCustomCommand() &&
- !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
- !sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
- {
- std::string dir_max;
- dir_max += this->Makefile->GetCurrentOutputDirectory();
- dir_max += "/";
- std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_max);
- if(!obj.empty())
- {
- std::string ofname = this->Makefile->GetCurrentOutputDirectory();
- ofname += "/";
- ofname += obj;
- objVector.push_back(ofname);
- this->AddCustomCommandToCreateObject(ofname.c_str(),
- llang, *(*i), target);
- objs += this->Convert(ofname.c_str(),START_OUTPUT,MAKEFILE);
- objs += " ";
- }
- }
- }
- std::string createRule = "CMAKE_";
- createRule += llang;
- createRule += target.GetCreateRuleVariable();
- std::string targetName = target.Target->GetFullName();
- // Executable :
- // Shared Library:
- // Static Library:
- // Shared Module:
- std::string linkLibs; // should be set
- std::string frameworkPath;
- std::string linkPath;
- std::string flags; // should be set
- std::string linkFlags; // should be set
- this->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags,
- &target);
- linkLibs = frameworkPath + linkPath + linkLibs;
- cmLocalGenerator::RuleVariables vars;
- vars.Language = llang;
- vars.Objects = objs.c_str();
- vars.ObjectDir = ".";
- vars.Target = targetName.c_str();
- vars.LinkLibraries = linkLibs.c_str();
- vars.Flags = flags.c_str();
- vars.LinkFlags = linkFlags.c_str();
-
- std::string langFlags;
- this->AddLanguageFlags(langFlags, llang, 0);
- this->AddArchitectureFlags(langFlags, &target, llang, 0);
- vars.LanguageCompileFlags = langFlags.c_str();
-
- cmCustomCommandLines commandLines;
- std::vector<std::string> rules;
- rules.push_back(this->Makefile->GetRequiredDefinition(createRule.c_str()));
- std::vector<std::string> commands;
- cmSystemTools::ExpandList(rules, commands);
- for(std::vector<std::string>::iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- // Expand the full command line string.
- this->ExpandRuleVariables(*i, vars);
- // Parse the string to get the custom command line.
- cmCustomCommandLine commandLine;
- std::vector<cmStdString> cmd = cmSystemTools::ParseArguments(i->c_str());
- for(std::vector<cmStdString>::iterator a = cmd.begin();
- a != cmd.end(); ++a)
- {
- commandLine.push_back(*a);
- }
+void cmLocalGenerator::AddImportedGeneratorTarget(cmGeneratorTarget* gt)
+{
+ this->ImportedGeneratorTargets.push_back(gt);
+ this->GlobalGenerator->IndexGeneratorTarget(gt);
+}
- // Store this command line.
- commandLines.push_back(commandLine);
- }
- std::string targetFullPath = target.Target->GetFullPath();
- // Generate a meaningful comment for the command.
- std::string comment = "Linking ";
- comment += llang;
- comment += " target ";
- comment += this->Convert(targetFullPath.c_str(), START_OUTPUT);
- this->Makefile->AddCustomCommandToOutput(
- targetFullPath.c_str(),
- objVector,
- 0,
- commandLines,
- comment.c_str(),
- this->Makefile->GetStartOutputDirectory()
- );
- target.Target->AddSourceFile
- (this->Makefile->GetSource(targetFullPath.c_str()));
-}
-
-
-void cmLocalGenerator
-::CreateCustomTargetsAndCommands(std::set<cmStdString> const& lang)
-{
- cmGeneratorTargetsType tgts = this->Makefile->GetGeneratorTargets();
- for(cmGeneratorTargetsType::iterator l = tgts.begin();
- l != tgts.end(); l++)
- {
- if (l->first->IsImported())
- {
- continue;
- }
- cmGeneratorTarget& target = *l->second;
- switch(target.GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::EXECUTABLE:
- {
- const char* llang = target.Target->GetLinkerLanguage();
- if(!llang)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- target.Target->GetName());
- return;
- }
- // if the language is not in the set lang then create custom
- // commands to build the target
- if(lang.count(llang) == 0)
- {
- this->AddBuildTargetRule(llang, target);
- }
- }
- break;
- default:
- break;
- }
- }
+void cmLocalGenerator::AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt)
+{
+ this->OwnedImportedGeneratorTargets.push_back(gt);
}
-// List of variables that are replaced when
-// rules are expanced. These variables are
-// replaced in the form <var> with GetSafeDefinition(var).
-// ${LANG} is replaced in the variable first with all enabled
-// languages.
-static const char* ruleReplaceVars[] =
+struct NamedGeneratorTargetFinder
{
- "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",
- 0
+ NamedGeneratorTargetFinder(std::string const& name)
+ : Name(name)
+ {
+ }
+
+ bool operator()(cmGeneratorTarget* tgt)
+ {
+ return tgt->GetName() == this->Name;
+ }
+
+private:
+ std::string Name;
};
-std::string
-cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
- const RuleVariables& replaceValues)
+cmGeneratorTarget* cmLocalGenerator::FindLocalNonAliasGeneratorTarget(
+ const std::string& name) const
{
- if(replaceValues.LinkFlags)
- {
- if(variable == "LINK_FLAGS")
- {
- return replaceValues.LinkFlags;
- }
- }
- if(replaceValues.Flags)
- {
- if(variable == "FLAGS")
- {
- return replaceValues.Flags;
- }
- }
+ std::vector<cmGeneratorTarget*>::const_iterator ti =
+ std::find_if(this->GeneratorTargets.begin(), this->GeneratorTargets.end(),
+ NamedGeneratorTargetFinder(name));
+ if (ti != this->GeneratorTargets.end()) {
+ return *ti;
+ }
+ return CM_NULLPTR;
+}
- if(replaceValues.Source)
- {
- if(variable == "SOURCE")
- {
- return replaceValues.Source;
- }
- }
- if(replaceValues.PreprocessedSource)
- {
- if(variable == "PREPROCESSED_SOURCE")
- {
- return replaceValues.PreprocessedSource;
- }
- }
- if(replaceValues.AssemblySource)
- {
- if(variable == "ASSEMBLY_SOURCE")
- {
- return replaceValues.AssemblySource;
- }
- }
- if(replaceValues.Object)
- {
- if(variable == "OBJECT")
- {
- return replaceValues.Object;
- }
- }
- if(replaceValues.ObjectDir)
- {
- if(variable == "OBJECT_DIR")
- {
- return replaceValues.ObjectDir;
- }
- }
- if(replaceValues.Objects)
- {
- if(variable == "OBJECTS")
- {
- return replaceValues.Objects;
- }
- }
- if(replaceValues.ObjectsQuoted)
- {
- if(variable == "OBJECTS_QUOTED")
- {
- return replaceValues.ObjectsQuoted;
- }
- }
- if(replaceValues.Defines && variable == "DEFINES")
- {
- return replaceValues.Defines;
- }
- if(replaceValues.TargetPDB )
- {
- if(variable == "TARGET_PDB")
- {
- return replaceValues.TargetPDB;
- }
- }
- if(replaceValues.DependencyFile )
- {
- if(variable == "DEP_FILE")
- {
- return replaceValues.DependencyFile;
- }
- }
+void cmLocalGenerator::ComputeTargetManifest()
+{
+ // Collect the set of configuration types.
+ std::vector<std::string> configNames;
+ this->Makefile->GetConfigurations(configNames);
+ if (configNames.empty()) {
+ configNames.push_back("");
+ }
- if(replaceValues.Target)
- {
- if(variable == "TARGET_QUOTED")
- {
- std::string targetQuoted = replaceValues.Target;
- if(targetQuoted.size() && targetQuoted[0] != '\"')
- {
- targetQuoted = '\"';
- targetQuoted += replaceValues.Target;
- targetQuoted += '\"';
- }
- return targetQuoted;
- }
- if(variable == "TARGET_UNQUOTED")
- {
- std::string unquoted = replaceValues.Target;
- std::string::size_type sz = unquoted.size();
- if(sz > 2 && unquoted[0] == '\"' && unquoted[sz-1] == '\"')
- {
- unquoted = unquoted.substr(1, sz-2);
- }
- return unquoted;
- }
- if(replaceValues.LanguageCompileFlags)
- {
- if(variable == "LANGUAGE_COMPILE_FLAGS")
- {
- return replaceValues.LanguageCompileFlags;
- }
- }
- if(replaceValues.Target)
- {
- if(variable == "TARGET")
- {
- return replaceValues.Target;
- }
- }
- if(variable == "TARGET_IMPLIB")
- {
- return this->TargetImplib;
- }
- if(variable == "TARGET_VERSION_MAJOR")
- {
- if(replaceValues.TargetVersionMajor)
- {
- return replaceValues.TargetVersionMajor;
- }
- else
- {
- return "0";
- }
- }
- if(variable == "TARGET_VERSION_MINOR")
- {
- if(replaceValues.TargetVersionMinor)
- {
- return replaceValues.TargetVersionMinor;
- }
- else
- {
- return "0";
- }
- }
- if(replaceValues.Target)
- {
- if(variable == "TARGET_BASE")
- {
- // Strip the last extension off the target name.
- std::string targetBase = replaceValues.Target;
- std::string::size_type pos = targetBase.rfind(".");
- if(pos != targetBase.npos)
- {
- return targetBase.substr(0, pos);
- }
- else
- {
- return targetBase;
- }
- }
- }
- }
- if(variable == "TARGET_SONAME" || variable == "SONAME_FLAG" ||
- variable == "TARGET_INSTALLNAME_DIR")
- {
- // All these variables depend on TargetSOName
- if(replaceValues.TargetSOName)
- {
- if(variable == "TARGET_SONAME")
- {
- return replaceValues.TargetSOName;
- }
- if(variable == "SONAME_FLAG" && replaceValues.SONameFlag)
- {
- return replaceValues.SONameFlag;
- }
- if(replaceValues.TargetInstallNameDir &&
- variable == "TARGET_INSTALLNAME_DIR")
- {
- return replaceValues.TargetInstallNameDir;
- }
- }
- return "";
- }
- if(replaceValues.LinkLibraries)
- {
- if(variable == "LINK_LIBRARIES")
- {
- return replaceValues.LinkLibraries;
- }
- }
- if(replaceValues.Language)
- {
- if(variable == "LANGUAGE")
- {
- return replaceValues.Language;
- }
- }
- if(replaceValues.CMTarget)
- {
- if(variable == "TARGET_NAME")
- {
- return replaceValues.CMTarget->GetName();
- }
- if(variable == "TARGET_TYPE")
- {
- return cmTarget::GetTargetTypeName(replaceValues.CMTarget->GetType());
- }
- }
- if(replaceValues.Output)
- {
- if(variable == "OUTPUT")
- {
- return replaceValues.Output;
- }
+ // 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;
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
}
- if(variable == "CMAKE_COMMAND")
- {
- const char* cmcommand =
- this->GetMakefile()->GetDefinition("CMAKE_COMMAND");
- return this->Convert(cmcommand, FULL, SHELL);
- }
- std::vector<std::string> enabledLanguages;
- this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
- // loop over language specific replace variables
- int pos = 0;
- while(ruleReplaceVars[pos])
- {
- for(std::vector<std::string>::iterator i = enabledLanguages.begin();
- i != enabledLanguages.end(); ++i)
- {
- const char* lang = i->c_str();
- std::string actualReplace = ruleReplaceVars[pos];
- // If this is the compiler then look for the extra variable
- // _COMPILER_ARG1 which must be the first argument to the compiler
- const char* compilerArg1 = 0;
- if(actualReplace == "CMAKE_${LANG}_COMPILER")
- {
- std::string arg1 = actualReplace + "_ARG1";
- cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
- compilerArg1 = this->Makefile->GetDefinition(arg1.c_str());
- }
- if(actualReplace.find("${LANG}") != actualReplace.npos)
- {
- cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
- }
- if(actualReplace == variable)
- {
- std::string replace =
- this->Makefile->GetSafeDefinition(variable.c_str());
- // if the variable is not a FLAG then treat it like a path
- if(variable.find("_FLAG") == variable.npos)
- {
- std::string ret = this->ConvertToOutputForExisting(replace.c_str());
- // if there is a required first argument to the compiler add it
- // to the compiler string
- if(compilerArg1)
- {
- ret += " ";
- ret += compilerArg1;
- }
- return ret;
- }
- return replace;
- }
- }
- pos++;
+ for (std::vector<std::string>::iterator ci = configNames.begin();
+ ci != configNames.end(); ++ci) {
+ const char* config = ci->c_str();
+ target->ComputeTargetManifest(config);
}
- return variable;
+ }
}
-
-void
-cmLocalGenerator::ExpandRuleVariables(std::string& s,
- const RuleVariables& replaceValues)
+bool cmLocalGenerator::ComputeTargetCompileFeatures()
{
- this->InsertRuleLauncher(s, replaceValues.CMTarget,
- replaceValues.RuleLauncher);
- std::string::size_type start = s.find('<');
- // no variables to expand
- if(start == s.npos)
- {
- return;
- }
- std::string::size_type pos = 0;
- std::string expandedInput;
- while(start != s.npos && start < s.size()-2)
- {
- std::string::size_type end = s.find('>', start);
- // if we find a < with no > we are done
- if(end == s.npos)
- {
- return;
- }
- char c = s[start+1];
- // if the next char after the < is not A-Za-z then
- // skip it and try to find the next < in the string
- if(!isalpha(c))
- {
- start = s.find('<', start+1);
- }
- else
- {
- // extract the var
- std::string var = s.substr(start+1, end - start-1);
- std::string replace = this->ExpandRuleVariable(var,
- replaceValues);
- expandedInput += s.substr(pos, start-pos);
- expandedInput += replace;
- // move to next one
- start = s.find('<', start+var.size()+2);
- pos = end+1;
+ // Collect the set of configuration types.
+ std::vector<std::string> configNames;
+ this->Makefile->GetConfigurations(configNames);
+ if (configNames.empty()) {
+ configNames.push_back("");
+ }
+
+ // 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)) {
+ return false;
}
}
- // add the rest of the input
- expandedInput += s.substr(pos, s.size()-pos);
- s = expandedInput;
-}
+ }
-//----------------------------------------------------------------------------
-const char* cmLocalGenerator::GetRuleLauncher(cmTarget* target,
- const char* prop)
-{
- if(target)
- {
- return target->GetProperty(prop);
- }
- else
- {
- return this->Makefile->GetProperty(prop);
- }
+ return true;
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::InsertRuleLauncher(std::string& s, cmTarget* target,
- const char* prop)
+bool cmLocalGenerator::IsRootMakefile() const
{
- if(const char* val = this->GetRuleLauncher(target, prop))
- {
- cmOStringStream wrapped;
- wrapped << val << " " << s;
- s = wrapped.str();
- }
+ return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid();
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOutputForExistingCommon(const char* remote,
- std::string const& result)
+cmState* cmLocalGenerator::GetState() const
{
- // If this is a windows shell, the result has a space, and the path
- // already exists, we can use a short-path to reference it without a
- // space.
- if(this->WindowsShell && result.find(' ') != result.npos &&
- cmSystemTools::FileExists(remote))
- {
- std::string tmp;
- if(cmSystemTools::GetShortPath(remote, tmp))
- {
- return this->Convert(tmp.c_str(), NONE, SHELL, true);
- }
- }
-
- // Otherwise, leave it unchanged.
- return result;
+ return this->GlobalGenerator->GetCMakeInstance()->GetState();
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOutputForExisting(const char* remote,
- RelativeRoot local)
+cmStateSnapshot cmLocalGenerator::GetStateSnapshot() const
{
- // Perform standard conversion.
- std::string result = this->Convert(remote, local, SHELL, true);
-
- // Consider short-path.
- return this->ConvertToOutputForExistingCommon(remote, result);
+ return this->Makefile->GetStateSnapshot();
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote,
- const char* local)
+const char* cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
+ const std::string& prop)
{
- // Perform standard conversion.
- std::string result = this->Convert(remote, local, SHELL, true);
-
- // Consider short-path.
- const char* remotePath = this->GetRelativeRootPath(remote);
- return this->ConvertToOutputForExistingCommon(remotePath, result);
+ if (target) {
+ return target->GetProperty(prop);
+ }
+ return this->Makefile->GetProperty(prop);
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToIncludeReference(std::string const& path)
+std::string cmLocalGenerator::ConvertToIncludeReference(
+ std::string const& path, OutputFormat format, bool forceFullPaths)
{
- return this->ConvertToOutputForExisting(path.c_str());
+ static_cast<void>(forceFullPaths);
+ return this->ConvertToOutputForExisting(path, format);
}
-//----------------------------------------------------------------------------
std::string cmLocalGenerator::GetIncludeFlags(
- const std::vector<std::string> &includes,
- cmGeneratorTarget* target,
- const char* lang, bool forResponseFile,
- const char *config)
+ const std::vector<std::string>& includes, cmGeneratorTarget* target,
+ const std::string& lang, bool forceFullPaths, bool forResponseFile,
+ const std::string& config)
{
- if(!lang)
- {
+ if (lang.empty()) {
return "";
- }
+ }
- cmOStringStream includeFlags;
+ OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL;
+ std::ostringstream includeFlags;
std::string flagVar = "CMAKE_INCLUDE_FLAG_";
flagVar += lang;
- const char* includeFlag =
- this->Makefile->GetSafeDefinition(flagVar.c_str());
+ const char* includeFlag = this->Makefile->GetSafeDefinition(flagVar);
flagVar = "CMAKE_INCLUDE_FLAG_SEP_";
flagVar += lang;
- const char* sep = this->Makefile->GetDefinition(flagVar.c_str());
+ const char* sep = this->Makefile->GetDefinition(flagVar);
bool quotePaths = false;
- if(this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS"))
- {
+ if (this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS")) {
quotePaths = true;
- }
+ }
bool repeatFlag = true;
// should the include flag be repeated like ie. -IA -IB
- if(!sep)
- {
+ if (!sep) {
sep = " ";
- }
- else
- {
+ } else {
// if there is a separator then the flag is not repeated but is only
// given once i.e. -classpath a:b:c
repeatFlag = false;
- }
+ }
// 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 = 0;
- if(repeatFlag)
- {
- sysIncludeFlag = this->Makefile->GetDefinition(sysFlagVar.c_str());
- }
+ const char* sysIncludeFlag = CM_NULLPTR;
+ if (repeatFlag) {
+ sysIncludeFlag = this->Makefile->GetDefinition(sysFlagVar);
+ }
+
+ 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);
bool flagUsed = false;
- std::set<cmStdString> emitted;
+ 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)
- {
- if(this->Makefile->IsOn("APPLE")
- && cmSystemTools::IsPathToFramework(i->c_str()))
- {
+ for (i = includes.begin(); i != includes.end(); ++i) {
+ if (fwSearchFlag && *fwSearchFlag && this->Makefile->IsOn("APPLE") &&
+ cmSystemTools::IsPathToFramework(i->c_str())) {
std::string frameworkDir = *i;
frameworkDir += "/../";
- frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
- if(emitted.insert(frameworkDir).second)
- {
- OutputFormat format = forResponseFile? RESPONSE : SHELL;
- includeFlags
- << "-F" << this->Convert(frameworkDir.c_str(),
- START_OUTPUT, format, true)
- << " ";
+ frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
+ if (emitted.insert(frameworkDir).second) {
+ if (sysFwSearchFlag && target &&
+ target->IsSystemIncludeDirectory(*i, config)) {
+ includeFlags << sysFwSearchFlag;
+ } else {
+ includeFlags << fwSearchFlag;
}
- continue;
+ includeFlags << this->ConvertToOutputFormat(frameworkDir, shellFormat)
+ << " ";
}
+ continue;
+ }
- if(!flagUsed || repeatFlag)
- {
- if(sysIncludeFlag && target &&
- target->IsSystemIncludeDirectory(i->c_str(), config))
- {
+ if (!flagUsed || repeatFlag) {
+ if (sysIncludeFlag && target &&
+ target->IsSystemIncludeDirectory(*i, config)) {
includeFlags << sysIncludeFlag;
- }
- else
- {
+ } else {
includeFlags << includeFlag;
- }
- flagUsed = true;
- }
- std::string includePath;
- if(forResponseFile)
- {
- includePath = this->Convert(i->c_str(), START_OUTPUT,
- RESPONSE, true);
- }
- else
- {
- includePath = this->ConvertToIncludeReference(*i);
}
- if(quotePaths && includePath.size() && includePath[0] != '\"')
- {
+ flagUsed = true;
+ }
+ std::string includePath =
+ this->ConvertToIncludeReference(*i, shellFormat, forceFullPaths);
+ if (quotePaths && !includePath.empty() && includePath[0] != '\"') {
includeFlags << "\"";
- }
+ }
includeFlags << includePath;
- if(quotePaths && includePath.size() && includePath[0] != '\"')
- {
+ if (quotePaths && !includePath.empty() && includePath[0] != '\"') {
includeFlags << "\"";
- }
- includeFlags << sep;
}
+ includeFlags << sep;
+ }
std::string flags = includeFlags.str();
// remove trailing separators
- if((sep[0] != ' ') && flags.size()>0 && flags[flags.size()-1] == sep[0])
- {
- flags[flags.size()-1] = ' ';
- }
+ if ((sep[0] != ' ') && !flags.empty() && flags[flags.size() - 1] == sep[0]) {
+ flags[flags.size() - 1] = ' ';
+ }
return flags;
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
- cmTarget* target,
- const char* config)
+ cmGeneratorTarget const* target,
+ const std::string& config,
+ const std::string& lang) const
{
std::vector<std::string> targetDefines;
- target->GetCompileDefinitions(targetDefines,
- config);
+ target->GetCompileDefinitions(targetDefines, config, lang);
this->AppendDefines(defines, targetDefines);
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::AddCompileOptions(
- std::string& flags, cmTarget* target,
- const char* lang, const char* config
- )
+void cmLocalGenerator::AddCompileOptions(std::string& flags,
+ cmGeneratorTarget* target,
+ const std::string& lang,
+ const std::string& config)
{
- std::string langFlagRegexVar = std::string("CMAKE_")+lang+"_FLAG_REGEX";
- if(const char* langFlagRegexStr =
- this->Makefile->GetDefinition(langFlagRegexVar.c_str()))
- {
+ std::string langFlagRegexVar = std::string("CMAKE_") + lang + "_FLAG_REGEX";
+
+ 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"))
- {
+ if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) {
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
- }
- target->GetCompileOptions(opts, config);
- for(std::vector<std::string>::const_iterator i = opts.begin();
- i != opts.end(); ++i)
- {
- if(r.find(i->c_str()))
- {
+ }
+ 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->c_str());
- }
+ this->AppendFlagEscape(flags, *i);
}
}
- else
- {
+ } else {
// Use all flags.
- if(const char* targetFlags = target->GetProperty("COMPILE_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);
- for(std::vector<std::string>::const_iterator i = opts.begin();
- i != opts.end(); ++i)
- {
+ 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->c_str());
- }
+ this->AppendFlagEscape(flags, *i);
+ }
+ }
+
+ 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");
+ if (!standard) {
+ continue;
+ }
+ 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
+ << "\" for that computation. Computing the "
+ "COMPILE_FEATURES based on the link implementation resulted in a "
+ "higher \""
+ << 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());
+ return;
}
+ }
+ this->AddCompilerRequirementFlag(flags, target, lang);
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
- cmGeneratorTarget* target,
- const char* lang,
- const char *config,
- bool stripImplicitInclDirs
- )
+ cmGeneratorTarget const* target,
+ const std::string& lang,
+ const std::string& config,
+ bool stripImplicitInclDirs) const
{
// Need to decide whether to automatically include the source and
// binary directories at the beginning of the include path.
@@ -1397,333 +828,373 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// file in a subdirectory of the current source directory but we
// cannot fix this because not all native build tools support
// per-source-file include paths.
- if(this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR"))
- {
+ if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR")) {
includeSourceDir = true;
includeBinaryDir = true;
- }
-
- // CMake versions below 2.0 would add the source tree to the -I path
- // automatically. Preserve compatibility.
- if(this->NeedBackwardsCompatibility(1,9))
- {
- includeSourceDir = true;
- }
-
- // Hack for VTK 4.0 - 4.4 which depend on the old behavior but do
- // not set the backwards compatibility level automatically.
- const char* vtkSourceDir =
- this->Makefile->GetDefinition("VTK_SOURCE_DIR");
- if(vtkSourceDir)
- {
- const char* vtk_major =
- this->Makefile->GetDefinition("VTK_MAJOR_VERSION");
- const char* vtk_minor =
- this->Makefile->GetDefinition("VTK_MINOR_VERSION");
- vtk_major = vtk_major? vtk_major : "4";
- vtk_minor = vtk_minor? vtk_minor : "4";
- int vmajor = 0;
- int vminor = 0;
- if(sscanf(vtk_major, "%d", &vmajor) &&
- sscanf(vtk_minor, "%d", &vminor) && vmajor == 4 && vminor <= 4)
- {
- includeSourceDir = true;
- }
- }
+ }
// Do not repeat an include path.
- std::set<cmStdString> emitted;
+ std::set<std::string> emitted;
// Store the automatic include paths.
- if(includeBinaryDir)
- {
- if(emitted.find(
- this->Makefile->GetStartOutputDirectory()) == emitted.end())
- {
- dirs.push_back(this->Makefile->GetStartOutputDirectory());
- emitted.insert(this->Makefile->GetStartOutputDirectory());
- }
- }
- if(includeSourceDir)
- {
- if(emitted.find(this->Makefile->GetStartDirectory()) == emitted.end())
- {
- dirs.push_back(this->Makefile->GetStartDirectory());
- emitted.insert(this->Makefile->GetStartDirectory());
- }
- }
-
- if(!target)
- {
+ 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);
+ }
+ }
+
+ if (!target) {
return;
- }
+ }
+
+ std::string rootPath;
+ if (const char* sysrootCompile =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+ rootPath = sysrootCompile;
+ } else {
+ rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+ }
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.c_str()))
- {
+ 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)
- {
- emitted.insert(*i);
- if (!stripImplicitInclDirs)
- {
+ 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);
- }
}
}
+ }
// Get the target-specific include directories.
std::vector<std::string> includes;
- includes = target->GetIncludeDirectories(config);
+ includes = 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->Makefile->GetHomeDirectory();
- const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
- for(std::vector<std::string>::const_iterator i = includes.begin();
- i != includes.end(); ++i)
- {
+ 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) {
// Emit this directory only if it is a subdirectory of the
// top-level source or binary tree.
- if(cmSystemTools::ComparePath(i->c_str(), topSourceDir) ||
- cmSystemTools::ComparePath(i->c_str(), topBinaryDir) ||
- cmSystemTools::IsSubDirectory(i->c_str(), topSourceDir) ||
- cmSystemTools::IsSubDirectory(i->c_str(), topBinaryDir))
- {
- if(emitted.insert(*i).second)
- {
+ 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);
- }
}
}
}
+ }
// 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)
- {
+ for (std::vector<std::string>::const_iterator i = includes.begin();
+ i != includes.end(); ++i) {
+ if (emitted.insert(*i).second) {
dirs.push_back(*i);
- }
}
-
- for(std::vector<std::string>::const_iterator i = implicitDirs.begin();
- i != implicitDirs.end(); ++i)
- {
- if(std::find(includes.begin(), includes.end(), *i) != includes.end())
- {
+ }
+
+ // 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);
+ }
+
+ 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);
- }
}
+ }
}
void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string const& config,
- cmTarget* target)
+ cmGeneratorTarget* target)
{
- this->AppendFlags(flags,
- this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
- if(!config.empty())
- {
+ 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.c_str()));
- }
+ this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name));
+ }
this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS"));
- if(!config.empty())
- {
+ if (!config.empty()) {
std::string name = "STATIC_LIBRARY_FLAGS_" + config;
- this->AppendFlags(flags, target->GetProperty(name.c_str()));
- }
+ this->AppendFlags(flags, target->GetProperty(name));
+ }
}
-void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
- std::string& flags,
- std::string& linkFlags,
- std::string& frameworkPath,
- std::string& linkPath,
- cmGeneratorTarget* target)
+void cmLocalGenerator::GetTargetFlags(
+ cmLinkLineComputer* linkLineComputer, const std::string& config,
+ std::string& linkLibs, std::string& flags, std::string& linkFlags,
+ std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target)
{
- std::string buildType =
- this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- buildType = cmSystemTools::UpperCase(buildType);
+ const std::string buildType = cmSystemTools::UpperCase(config);
+ cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
const char* libraryLinkVariable =
"CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
- switch(target->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- this->GetStaticLibraryFlags(linkFlags, buildType, target->Target);
+ const std::string linkLanguage =
+ linkLineComputer->GetLinkerLanguage(target, buildType);
+
+ switch (target->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
+ this->GetStaticLibraryFlags(linkFlags, buildType, target);
break;
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
- case cmTarget::SHARED_LIBRARY:
- {
+ CM_FALLTHROUGH;
+ case cmStateEnums::SHARED_LIBRARY: {
linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
linkFlags += " ";
- if(!buildType.empty())
- {
+ if (!buildType.empty()) {
std::string build = libraryLinkVariable;
build += "_";
build += buildType;
- linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
+ linkFlags += this->Makefile->GetSafeDefinition(build);
linkFlags += " ";
- }
- if(this->Makefile->IsOn("WIN32") &&
- !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")))
- {
- const std::vector<cmSourceFile*>& sources = target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
- i != sources.end(); ++i)
- {
+ }
+ 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 +=
- this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
- linkFlags += this->Convert(sf->GetFullPath().c_str(),
- FULL, SHELL);
+ if (sf->GetExtension() == "def") {
+ linkFlags += defFlag;
+ linkFlags += this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(sf->GetFullPath()), SHELL);
linkFlags += " ";
- }
}
}
+ }
const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
- if(targetLinkFlags)
- {
+ if (targetLinkFlags) {
linkFlags += targetLinkFlags;
linkFlags += " ";
- }
- if(!buildType.empty())
- {
+ }
+ if (!buildType.empty()) {
std::string configLinkFlags = "LINK_FLAGS_";
configLinkFlags += buildType;
- targetLinkFlags = target->GetProperty(configLinkFlags.c_str());
- if(targetLinkFlags)
- {
+ targetLinkFlags = target->GetProperty(configLinkFlags);
+ if (targetLinkFlags) {
linkFlags += targetLinkFlags;
linkFlags += " ";
- }
}
- this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
- *target, false);
}
- break;
- case cmTarget::EXECUTABLE:
- {
- linkFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
+ 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())
- {
+ if (!buildType.empty()) {
std::string build = "CMAKE_EXE_LINKER_FLAGS_";
build += buildType;
- linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
+ linkFlags += this->Makefile->GetSafeDefinition(build);
linkFlags += " ";
- }
- const char* linkLanguage = target->Target->GetLinkerLanguage();
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- target->Target->GetName());
+ }
+ if (linkLanguage.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: ",
+ target->GetName().c_str());
return;
- }
- this->AddLanguageFlags(flags, linkLanguage, buildType.c_str());
- this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
- *target, false);
- if(cmSystemTools::IsOn
- (this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
- {
- std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_")
- + linkLanguage + std::string("_FLAGS");
- linkFlags += this->Makefile->GetSafeDefinition(sFlagVar.c_str());
+ }
+ this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType);
+ if (pcli) {
+ this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+ frameworkPath, linkPath);
+ }
+ if (cmSystemTools::IsOn(
+ 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") )
- {
+ }
+ if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
linkFlags +=
this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
linkFlags += " ";
- }
- else
- {
+ } else {
linkFlags +=
this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
linkFlags += " ";
- }
- if (target->Target->IsExecutableWithExports())
- {
+ }
+ if (target->IsExecutableWithExports()) {
std::string exportFlagVar = "CMAKE_EXE_EXPORTS_";
exportFlagVar += linkLanguage;
exportFlagVar += "_FLAG";
- linkFlags +=
- this->Makefile->GetSafeDefinition(exportFlagVar.c_str());
+ linkFlags += this->Makefile->GetSafeDefinition(exportFlagVar);
linkFlags += " ";
- }
+ }
+
+ std::string cmp0065Flags =
+ this->GetLinkLibsCMP0065(linkLanguage, *target);
+ if (!cmp0065Flags.empty()) {
+ linkFlags += cmp0065Flags;
+ linkFlags += " ";
+ }
+
const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
- if(targetLinkFlags)
- {
+ if (targetLinkFlags) {
linkFlags += targetLinkFlags;
linkFlags += " ";
- }
- if(!buildType.empty())
- {
+ }
+ if (!buildType.empty()) {
std::string configLinkFlags = "LINK_FLAGS_";
configLinkFlags += buildType;
- targetLinkFlags = target->GetProperty(configLinkFlags.c_str());
- if(targetLinkFlags)
- {
+ targetLinkFlags = target->GetProperty(configLinkFlags);
+ if (targetLinkFlags) {
linkFlags += targetLinkFlags;
linkFlags += " ";
- }
}
}
- break;
+ } break;
default:
break;
- }
+ }
+
+ this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage);
}
-std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib)
+void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
+ std::string const& config,
+ std::string const& lang,
+ std::string& flags)
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // Work-ardound command line parsing limitations in MSVC 6.0 and
- // Watcom.
- if(this->Makefile->IsOn("MSVC60") || this->Makefile->IsOn("WATCOM"))
- {
- // Search for the last space.
- std::string::size_type pos = lib.rfind(' ');
- if(pos != lib.npos)
- {
- // Find the slash after the last space, if any.
- pos = lib.find('/', pos);
-
- // Convert the portion of the path with a space to a short path.
- std::string sp;
- if(cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp))
- {
- // Append the rest of the path with no space.
- sp += lib.substr(pos);
-
- // Convert to an output path.
- return this->Convert(sp.c_str(), NONE, SHELL);
- }
+ cmMakefile* mf = this->GetMakefile();
+
+ // Add language-specific flags.
+ this->AddLanguageFlags(flags, target, lang, config);
+
+ this->AddArchitectureFlags(flags, target, lang, config);
+
+ if (lang == "Fortran") {
+ this->AppendFlags(flags, 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->AddCompileOptions(flags, target, lang, config);
+}
+
+static std::string GetFrameworkFlags(const std::string& lang,
+ const std::string& config,
+ cmGeneratorTarget* target)
+{
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ cmMakefile* mf = lg->GetMakefile();
+
+ if (!mf->IsOn("APPLE")) {
+ return std::string();
+ }
+
+ std::string fwSearchFlagVar = "CMAKE_" + lang + "_FRAMEWORK_SEARCH_FLAG";
+ const char* fwSearchFlag = mf->GetDefinition(fwSearchFlagVar);
+ if (!(fwSearchFlag && *fwSearchFlag)) {
+ return std::string();
+ }
+
+ std::set<std::string> emitted;
+#ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */
+ emitted.insert("/System/Library/Frameworks");
+#endif
+ std::vector<std::string> includes;
+
+ 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 += "/../";
+ frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
+ emitted.insert(frameworkDir);
+ }
+ }
+
+ 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) {
+ flags += fwSearchFlag;
+ flags += lg->ConvertToOutputFormat(*i, cmOutputConverter::SHELL);
+ flags += " ";
}
}
-#endif
+ }
+ return flags;
+}
+
+std::string cmLocalGenerator::GetFrameworkFlags(std::string const& l,
+ std::string const& config,
+ cmGeneratorTarget* target)
+{
+ return ::GetFrameworkFlags(l, config, target);
+}
+
+void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target,
+ std::string const& config,
+ std::string const& lang,
+ std::set<std::string>& defines) const
+{
+ // Add the export symbol definition for shared library objects.
+ if (const char* exportMacro = target->GetExportMacro()) {
+ this->AppendDefines(defines, exportMacro);
+ }
- // Normal behavior.
- return this->Convert(lib.c_str(), START_OUTPUT, SHELL);
+ // Add preprocessor definitions for this target and configuration.
+ this->AddCompileDefinitions(defines, target, config, lang);
+}
+
+std::string cmLocalGenerator::GetTargetFortranFlags(
+ cmGeneratorTarget const* /*unused*/, std::string const& /*unused*/)
+{
+ // Implemented by specific generators that override this.
+ return std::string();
}
/**
@@ -1731,210 +1202,192 @@ std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib)
* targetLibrary should be a NULL pointer. For libraries, it should point
* to the name of the library. This will not link a library against itself.
*/
-void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
- std::string& frameworkPath,
- std::string& linkPath,
- cmGeneratorTarget &tgt,
- bool relink)
-{
- cmOStringStream fout;
- const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config);
- if(!pcli)
- {
- return;
- }
+void cmLocalGenerator::OutputLinkLibraries(
+ cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer,
+ std::string& linkLibraries, std::string& frameworkPath,
+ std::string& linkPath)
+{
cmComputeLinkInformation& cli = *pcli;
- // Collect library linking flags command line options.
- std::string linkLibs;
-
- const char* linkLanguage = cli.GetLinkLanguage();
+ 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");
- // Flags to link an executable to shared libraries.
- std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
- linkFlagsVar += linkLanguage;
- linkFlagsVar += "_FLAGS";
- if( tgt.GetType() == cmTarget::EXECUTABLE )
- {
- linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar.c_str());
- linkLibs += " ";
- }
-
- // Append the framework search path flags.
- std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
- for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
- fdi != fwDirs.end(); ++fdi)
- {
- frameworkPath += "-F";
- frameworkPath += this->Convert(fdi->c_str(), NONE, SHELL, false);
- frameworkPath += " ";
- }
-
- // Append the library search path flags.
- 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->c_str());
- linkPath += " " + libPathFlag;
- linkPath += libpath;
- linkPath += libPathTerminator;
- linkPath += " ";
- }
-
- // Append the link items.
- typedef cmComputeLinkInformation::ItemVector ItemVector;
- ItemVector const& items = cli.GetItems();
- for(ItemVector::const_iterator li = items.begin(); li != items.end(); ++li)
- {
- if(li->IsPath)
- {
- linkLibs += this->ConvertToLinkReference(li->Value);
- }
- else
- {
- linkLibs += li->Value;
- }
- linkLibs += " ";
- }
-
- // Write the library flags to the build rule.
- fout << linkLibs;
-
- // Get the RPATH entries.
- std::vector<std::string> runtimeDirs;
- cli.GetRPath(runtimeDirs, relink);
-
- // Check what kind of rpath flags to use.
- if(cli.GetRuntimeSep().empty())
- {
- // Each rpath entry gets its own option ("-R a -R b -R c")
- std::string rpath;
- for(std::vector<std::string>::iterator ri = runtimeDirs.begin();
- ri != runtimeDirs.end(); ++ri)
- {
- rpath += cli.GetRuntimeFlag();
- rpath += this->Convert(ri->c_str(), NONE, SHELL, false);
- rpath += " ";
- }
- fout << rpath;
- }
- else
- {
- // All rpath entries are combined ("-Wl,-rpath,a:b:c").
- std::string rpath = cli.GetRPathString(relink);
-
- // Store the rpath option in the stream.
- if(!rpath.empty())
- {
- fout << cli.GetRuntimeFlag();
- fout << this->EscapeForShell(rpath.c_str(), true);
- fout << " ";
- }
- }
-
- // Add the linker runtime search path if any.
- std::string rpath_link = cli.GetRPathLinkString();
- if(!cli.GetRPathLinkFlag().empty() && !rpath_link.empty())
- {
- fout << cli.GetRPathLinkFlag();
- fout << this->EscapeForShell(rpath_link.c_str(), true);
- fout << " ";
- }
-
// Add standard libraries for this language.
std::string standardLibsVar = "CMAKE_";
standardLibsVar += cli.GetLinkLanguage();
standardLibsVar += "_STANDARD_LIBRARIES";
- if(const char* stdLibs =
- this->Makefile->GetDefinition(standardLibsVar.c_str()))
- {
- fout << stdLibs << " ";
- }
+ std::string stdLibString;
+ if (const char* stdLibs = this->Makefile->GetDefinition(standardLibsVar)) {
+ stdLibString = stdLibs;
+ }
+
+ // Append the framework search path flags.
+ std::string fwSearchFlagVar = "CMAKE_";
+ fwSearchFlagVar += linkLanguage;
+ fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG";
+ std::string fwSearchFlag =
+ this->Makefile->GetSafeDefinition(fwSearchFlagVar);
+
+ frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag);
+ linkPath =
+ linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator);
- linkLibraries = fout.str();
+ linkLibraries = linkLineComputer->ComputeLinkLibraries(cli, stdLibString);
}
+std::string cmLocalGenerator::GetLinkLibsCMP0065(
+ std::string const& linkLanguage, cmGeneratorTarget& tgt) const
+{
+ std::string linkFlags;
+
+ // Flags to link an executable to shared libraries.
+ if (tgt.GetType() == cmStateEnums::EXECUTABLE &&
+ this->StateSnapshot.GetState()->GetGlobalPropertyAsBool(
+ "TARGET_SUPPORTS_SHARED_LIBS")) {
+ bool add_shlib_flags = false;
+ switch (tgt.GetPolicyStatusCMP0065()) {
+ case cmPolicies::WARN:
+ if (!tgt.GetPropertyAsBool("ENABLE_EXPORTS") &&
+ this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0065")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0065) << "\n"
+ "For compatibility with older versions of CMake, "
+ "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());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to always add the flags
+ add_shlib_flags = true;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->IssueMessage(
+ cmake::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");
+ break;
+ }
+
+ if (add_shlib_flags) {
+ std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
+ linkFlagsVar += linkLanguage;
+ linkFlagsVar += "_FLAGS";
+ linkFlags = this->Makefile->GetSafeDefinition(linkFlagsVar);
+ }
+ }
+ return linkFlags;
+}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
- cmGeneratorTarget* target,
- const char *lang,
- const char* config)
+ cmGeneratorTarget const* target,
+ const std::string& lang,
+ const std::string& config)
{
// Only add Mac OS X specific flags on Darwin platforms (OSX and iphone):
- if(!this->Makefile->IsOn("APPLE"))
- {
- return;
- }
-
- if(this->EmitUniversalBinaryFlags)
- {
+ 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 = 0; }
+ if (sysroot && sysroot[0] == '/' && !sysroot[1]) {
+ sysroot = CM_NULLPTR;
+ }
std::string sysrootFlagVar =
std::string("CMAKE_") + lang + "_SYSROOT_FLAG";
- const char* sysrootFlag =
- this->Makefile->GetDefinition(sysrootFlagVar.c_str());
+ const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar);
const char* deploymentTarget =
this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
std::string deploymentTargetFlagVar =
std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG";
const char* deploymentTargetFlag =
- this->Makefile->GetDefinition(deploymentTargetFlagVar.c_str());
- if(!archs.empty() && lang && (lang[0] =='C' || lang[0] == 'F'))
- {
- for(std::vector<std::string>::iterator i = archs.begin();
- i != archs.end(); ++i)
- {
+ 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) {
flags += " -arch ";
flags += *i;
- }
}
+ }
- if(sysrootFlag && *sysrootFlag && sysroot && *sysroot)
- {
+ if (sysrootFlag && *sysrootFlag && sysroot && *sysroot) {
flags += " ";
flags += sysrootFlag;
flags += " ";
- flags += sysroot;
- }
+ flags += this->ConvertToOutputFormat(sysroot, SHELL);
+ }
- if (deploymentTargetFlag && *deploymentTargetFlag &&
- deploymentTarget && *deploymentTarget)
- {
+ if (deploymentTargetFlag && *deploymentTargetFlag && deploymentTarget &&
+ *deploymentTarget) {
flags += " ";
flags += deploymentTargetFlag;
flags += deploymentTarget;
- }
}
+ }
}
-
-//----------------------------------------------------------------------------
void cmLocalGenerator::AddLanguageFlags(std::string& flags,
- const char* lang,
- const char* config)
+ cmGeneratorTarget const* target,
+ const std::string& lang,
+ const std::string& config)
{
// Add language-specific flags.
std::string flagsVar = "CMAKE_";
flagsVar += lang;
flagsVar += "_FLAGS";
- this->AddConfigVariableFlags(flags, flagsVar.c_str(), config);
+ this->AddConfigVariableFlags(flags, flagsVar, config);
+
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(flags, lang, "IPO");
+ }
}
-//----------------------------------------------------------------------------
-bool cmLocalGenerator::GetRealDependency(const char* inName,
- const char* config,
+void cmLocalGenerator::AddLanguageFlagsForLinking(
+ std::string& flags, cmGeneratorTarget const* target, const std::string& lang,
+ const std::string& config)
+{
+ if (this->Makefile->IsOn("CMAKE_" + lang +
+ "_LINK_WITH_STANDARD_COMPILE_OPTION")) {
+ // This toolchain requires use of the language standard flag
+ // when linking in order to use the matching standard library.
+ // FIXME: If CMake gains an abstraction for standard library
+ // selection, this will have to be reconciled with it.
+ this->AddCompilerRequirementFlag(flags, target, lang);
+ }
+
+ this->AddLanguageFlags(flags, target, lang, config);
+}
+
+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));
+ if (imported != this->ImportedGeneratorTargets.end()) {
+ return *imported;
+ }
+
+ if (cmGeneratorTarget* t = this->FindLocalNonAliasGeneratorTarget(name)) {
+ return t;
+ }
+
+ return this->GetGlobalGenerator()->FindGeneratorTarget(name);
+}
+
+bool cmLocalGenerator::GetRealDependency(const std::string& inName,
+ const std::string& config,
std::string& dep)
{
// Older CMake code may specify the dependency using the target
@@ -1946,344 +1399,499 @@ bool cmLocalGenerator::GetRealDependency(const char* inName,
// If the input name is the empty string, there is no real
// dependency. Short-circuit the other checks:
- if(name == "")
- {
+ if (name == "") {
return false;
- }
+ }
- if(cmSystemTools::GetFilenameLastExtension(name) == ".exe")
- {
+ if (cmSystemTools::GetFilenameLastExtension(name) == ".exe") {
name = cmSystemTools::GetFilenameWithoutLastExtension(name);
- }
+ }
// Look for a CMake target with the given name.
- if(cmTarget* target = this->Makefile->FindTargetToUse(name.c_str()))
- {
+ 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))
- {
+ if (cmSystemTools::FileIsFullPath(inName.c_str())) {
std::string tLocation;
- if(target->GetType() >= cmTarget::EXECUTABLE &&
- target->GetType() <= cmTarget::MODULE_LIBRARY)
- {
+ if (target->GetType() >= cmStateEnums::EXECUTABLE &&
+ target->GetType() <= cmStateEnums::MODULE_LIBRARY) {
tLocation = target->GetLocation(config);
tLocation = cmSystemTools::GetFilenamePath(tLocation);
- tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
- }
- std::string depLocation = cmSystemTools::GetFilenamePath(
- std::string(inName));
- depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
- if(depLocation != tLocation)
- {
+ tLocation = cmSystemTools::CollapseFullPath(tLocation);
+ }
+ std::string depLocation =
+ cmSystemTools::GetFilenamePath(std::string(inName));
+ depLocation = cmSystemTools::CollapseFullPath(depLocation);
+ if (depLocation != tLocation) {
// it is a full path to a depend that has the same name
// as a target but is in a different location so do not use
// the target as the depend
dep = inName;
return true;
- }
}
- switch (target->GetType())
- {
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::UNKNOWN_LIBRARY:
+ }
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::UNKNOWN_LIBRARY:
dep = target->GetLocation(config);
return true;
- case cmTarget::OBJECT_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
// An object library has no single file on which to depend.
// This was listed to get the target-level dependency.
return false;
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ // An interface library has no file on which to depend.
+ // This was listed to get the target-level dependency.
+ return false;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
// A utility target has no file on which to depend. This was listed
// only to get the target-level dependency.
return false;
- }
}
+ }
// The name was not that of a CMake target. It must name a file.
- if(cmSystemTools::FileIsFullPath(inName))
- {
+ if (cmSystemTools::FileIsFullPath(inName.c_str())) {
// This is a full path. Return it as given.
dep = inName;
return true;
- }
+ }
// Check for a source file in this directory that matches the
// dependency.
- if(cmSourceFile* sf = this->Makefile->GetSource(inName))
- {
+ if (cmSourceFile* sf = this->Makefile->GetSource(inName)) {
dep = sf->GetFullPath();
return true;
- }
+ }
// Treat the name as relative to the source directory in which it
// was given.
- dep = this->Makefile->GetCurrentDirectory();
+ dep = this->StateSnapshot.GetDirectory().GetCurrentSource();
dep += "/";
dep += inName;
return true;
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AddSharedFlags(std::string& flags,
- const char* lang,
- bool shared)
+ const std::string& lang, bool shared)
{
std::string flagsVar;
// Add flags for dealing with shared libraries for this language.
- if(shared)
- {
+ if (shared) {
flagsVar = "CMAKE_SHARED_LIBRARY_";
flagsVar += lang;
flagsVar += "_FLAGS";
- this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
- }
+ this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar));
+ }
}
-static void AddVisibilityCompileOption(std::string &flags, cmTarget* target,
- cmLocalGenerator *lg, const char *lang)
+void cmLocalGenerator::AddCompilerRequirementFlag(
+ std::string& flags, cmGeneratorTarget const* target, const std::string& lang)
{
- std::string l(lang);
- std::string compileOption = "CMAKE_" + l + "_COMPILE_OPTIONS_VISIBILITY";
- const char *opt = lg->GetMakefile()->GetDefinition(compileOption.c_str());
- if (!opt)
- {
+ if (lang.empty()) {
+ return;
+ }
+ const char* defaultStd =
+ this->Makefile->GetDefinition("CMAKE_" + lang + "_STANDARD_DEFAULT");
+ if (!defaultStd || !*defaultStd) {
+ // 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)) {
+ ext = false;
+ type = "STANDARD";
+ }
+ }
+
+ if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) {
+ std::string option_flag =
+ "CMAKE_" + lang + standardProp + "_" + type + "_COMPILE_OPTION";
+
+ const char* opt =
+ target->Target->GetMakefile()->GetDefinition(option_flag);
+ if (!opt) {
+ std::ostringstream e;
+ 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());
+ } 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::string flagDefine = l + "_VISIBILITY_PRESET";
+ return;
+ }
+
+ 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["C"].push_back("11");
+ langStdMap["C"].push_back("99");
+ langStdMap["C"].push_back("90");
+
+ langStdMap["CUDA"].push_back("14");
+ langStdMap["CUDA"].push_back("11");
+ langStdMap["CUDA"].push_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);
+ 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());
+ return;
+ }
+
+ std::vector<std::string>::const_iterator 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);
+ return;
+ }
+
+ // 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 *prop = target->GetProperty(flagDefine.c_str());
- if (!prop)
- {
+ const char* 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]);
+ }
return;
+ }
+
+ for (; stdIt < defaultStdIt; ++stdIt) {
+ std::string option_flag =
+ "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]);
+ }
+ return;
}
- if (strcmp(prop, "hidden") != 0
- && strcmp(prop, "default") != 0
- && strcmp(prop, "protected") != 0
- && strcmp(prop, "internal") != 0 )
- {
- cmOStringStream e;
- e << "Target " << target->GetName() << " uses unsupported value \""
- << prop << "\" for " << flagDefine << ".";
+ }
+}
+
+static void AddVisibilityCompileOption(std::string& flags,
+ cmGeneratorTarget const* target,
+ cmLocalGenerator* lg,
+ const std::string& lang,
+ std::string* warnCMP0063)
+{
+ std::string compileOption = "CMAKE_" + lang + "_COMPILE_OPTIONS_VISIBILITY";
+ const char* opt = lg->GetMakefile()->GetDefinition(compileOption);
+ if (!opt) {
+ return;
+ }
+ std::string flagDefine = lang + "_VISIBILITY_PRESET";
+
+ const char* prop = target->GetProperty(flagDefine);
+ if (!prop) {
+ return;
+ }
+ if (warnCMP0063) {
+ *warnCMP0063 += " " + flagDefine + "\n";
+ return;
+ }
+ if (strcmp(prop, "hidden") != 0 && strcmp(prop, "default") != 0 &&
+ 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());
return;
- }
+ }
std::string option = std::string(opt) + prop;
- lg->AppendFlags(flags, option.c_str());
+ lg->AppendFlags(flags, option);
}
-static void AddInlineVisibilityCompileOption(std::string &flags,
- cmTarget* target,
- cmLocalGenerator *lg)
+static void AddInlineVisibilityCompileOption(std::string& flags,
+ cmGeneratorTarget const* target,
+ cmLocalGenerator* lg,
+ std::string* warnCMP0063)
{
- std::string compileOption
- = "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN";
- const char *opt = lg->GetMakefile()->GetDefinition(compileOption.c_str());
- if (!opt)
- {
+ std::string compileOption =
+ "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN";
+ const char* opt = lg->GetMakefile()->GetDefinition(compileOption);
+ if (!opt) {
return;
- }
+ }
bool prop = target->GetPropertyAsBool("VISIBILITY_INLINES_HIDDEN");
- if (!prop)
- {
+ if (!prop) {
return;
- }
+ }
+ if (warnCMP0063) {
+ *warnCMP0063 += " VISIBILITY_INLINES_HIDDEN\n";
+ return;
+ }
lg->AppendFlags(flags, opt);
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator
-::AddVisibilityPresetFlags(std::string &flags, cmTarget* target,
- const char *lang)
+void cmLocalGenerator::AddVisibilityPresetFlags(
+ std::string& flags, cmGeneratorTarget const* target, const std::string& lang)
{
- int targetType = target->GetType();
- bool suitableTarget = ((targetType == cmTarget::SHARED_LIBRARY)
- || (targetType == cmTarget::MODULE_LIBRARY)
- || (target->IsExecutableWithExports()));
-
- if (!suitableTarget)
- {
+ if (lang.empty()) {
return;
+ }
+
+ std::string warnCMP0063;
+ std::string* pWarnCMP0063 = CM_NULLPTR;
+ if (target->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ target->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ !target->IsExecutableWithExports()) {
+ switch (target->GetPolicyStatusCMP0063()) {
+ case cmPolicies::OLD:
+ return;
+ case cmPolicies::WARN:
+ pWarnCMP0063 = &warnCMP0063;
+ break;
+ default:
+ break;
}
+ }
- if (!lang)
- {
- return;
- }
- AddVisibilityCompileOption(flags, target, this, lang);
- AddInlineVisibilityCompileOption(flags, target, this);
+ AddVisibilityCompileOption(flags, target, this, lang, pWarnCMP0063);
+
+ if (lang == "CXX") {
+ AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063);
+ }
+
+ if (!warnCMP0063.empty() && this->WarnCMP0063.insert(target).second) {
+ std::ostringstream w;
+ /* clang-format off */
+ w <<
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0063) << "\n"
+ "Target \"" << target->GetName() << "\" of "
+ "type \"" << cmState::GetTargetTypeName(target->GetType()) << "\" "
+ "has the following visibility properties set for " << lang << ":\n" <<
+ warnCMP0063 <<
+ "For compatibility CMake is not honoring them for this target.";
+ /* clang-format on */
+ target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::AUTHOR_WARNING, w.str(), target->GetBacktrace());
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
+void cmLocalGenerator::AddCMP0018Flags(std::string& flags,
+ cmGeneratorTarget const* target,
std::string const& lang,
- const char *config)
+ const std::string& config)
{
int targetType = target->GetType();
- bool shared = ((targetType == cmTarget::SHARED_LIBRARY) ||
- (targetType == cmTarget::MODULE_LIBRARY));
+ bool shared = ((targetType == cmStateEnums::SHARED_LIBRARY) ||
+ (targetType == cmStateEnums::MODULE_LIBRARY));
- if (this->GetShouldUseOldFlags(shared, lang))
- {
- this->AddSharedFlags(flags, lang.c_str(), shared);
- }
- else
- {
- if (target->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
- {
+ if (this->GetShouldUseOldFlags(shared, lang)) {
+ this->AddSharedFlags(flags, lang, shared);
+ } else {
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) {
this->AddPositionIndependentFlags(flags, lang, targetType);
- }
- return;
}
+ return;
+ }
if (target->GetLinkInterfaceDependentBoolProperty(
- "POSITION_INDEPENDENT_CODE",
- config))
- {
+ "POSITION_INDEPENDENT_CODE", config)) {
this->AddPositionIndependentFlags(flags, lang, targetType);
- }
- if (shared)
- {
- this->AppendFeatureOptions(flags, lang.c_str(), "DLL");
- }
}
+ if (shared) {
+ this->AppendFeatureOptions(flags, lang, "DLL");
+ }
+ }
}
-//----------------------------------------------------------------------------
bool cmLocalGenerator::GetShouldUseOldFlags(bool shared,
- const std::string &lang) const
+ const std::string& lang) const
{
std::string originalFlags =
this->GlobalGenerator->GetSharedLibFlagsForLanguage(lang);
- if (shared)
- {
+ if (shared) {
std::string flagsVar = "CMAKE_SHARED_LIBRARY_";
flagsVar += lang;
flagsVar += "_FLAGS";
- const char* flags =
- this->Makefile->GetSafeDefinition(flagsVar.c_str());
-
- if (flags && flags != originalFlags)
- {
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0018))
- {
- case cmPolicies::WARN:
- {
- cmOStringStream e;
- e << "Variable " << flagsVar << " has been modified. CMake "
- "will ignore the POSITION_INDEPENDENT_CODE target property for "
- "shared libraries and will use the " << flagsVar << " variable "
- "instead. This may cause errors if the original content of "
+ const char* flags = this->Makefile->GetSafeDefinition(flagsVar);
+
+ if (flags && flags != originalFlags) {
+ switch (this->GetPolicyStatus(cmPolicies::CMP0018)) {
+ case cmPolicies::WARN: {
+ std::ostringstream e;
+ e << "Variable " << flagsVar
+ << " has been modified. CMake "
+ "will ignore the POSITION_INDEPENDENT_CODE target property for "
+ "shared libraries and will use the "
+ << flagsVar
+ << " variable "
+ "instead. This may cause errors if the original content of "
<< flagsVar << " was removed.\n"
- << this->Makefile->GetPolicies()->GetPolicyWarning(
- cmPolicies::CMP0018);
+ << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018);
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
- // fall through to OLD behaviour
+ this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ CM_FALLTHROUGH;
}
case cmPolicies::OLD:
return true;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
- default:
return false;
- }
}
}
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags,
std::string const& lang,
int targetType)
{
- const char* picFlags = 0;
+ const char* picFlags = CM_NULLPTR;
- if(targetType == cmTarget::EXECUTABLE)
- {
+ if (targetType == cmStateEnums::EXECUTABLE) {
std::string flagsVar = "CMAKE_";
flagsVar += lang;
flagsVar += "_COMPILE_OPTIONS_PIE";
- picFlags = this->Makefile->GetSafeDefinition(flagsVar.c_str());
- }
- if (!picFlags)
- {
+ picFlags = this->Makefile->GetSafeDefinition(flagsVar);
+ }
+ if (!picFlags) {
std::string flagsVar = "CMAKE_";
flagsVar += lang;
flagsVar += "_COMPILE_OPTIONS_PIC";
- picFlags = this->Makefile->GetSafeDefinition(flagsVar.c_str());
- }
- if (picFlags)
- {
+ picFlags = this->Makefile->GetSafeDefinition(flagsVar);
+ }
+ 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->c_str());
- }
+ for (std::vector<std::string>::const_iterator oi = options.begin();
+ oi != options.end(); ++oi) {
+ this->AppendFlagEscape(flags, *oi);
}
+ }
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
- const char* var,
- const char* config)
+ const std::string& var,
+ const std::string& config)
{
// Add the flags from the variable itself.
std::string flagsVar = var;
- this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
+ this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar));
// Add the flags from the build-type specific variable.
- if(config && *config)
- {
+ if (!config.empty()) {
flagsVar += "_";
flagsVar += cmSystemTools::UpperCase(config);
- this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
- }
+ this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar));
+ }
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AppendFlags(std::string& flags,
- const char* newFlags)
+ const std::string& newFlags)
{
- if(newFlags && *newFlags)
- {
- std::string newf = newFlags;
- if(flags.size())
- {
+ if (!newFlags.empty()) {
+ if (!flags.empty()) {
flags += " ";
- }
- flags += newFlags;
}
+ flags += newFlags;
+ }
+}
+
+void cmLocalGenerator::AppendFlags(std::string& flags, const char* newFlags)
+{
+ if (newFlags && *newFlags) {
+ this->AppendFlags(flags, std::string(newFlags));
+ }
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AppendFlagEscape(std::string& flags,
- const char* rawFlag)
+ const std::string& rawFlag)
{
- this->AppendFlags(flags, this->EscapeForShell(rawFlag).c_str());
+ this->AppendFlags(flags, this->EscapeForShell(rawFlag));
+}
+
+void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
+ cmGeneratorTarget* target,
+ const std::string& config,
+ const std::string& lang)
+{
+ if (!target->IsIPOEnabled(lang, config)) {
+ return;
+ }
+
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ break;
+ default:
+ return;
+ }
+
+ const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO";
+ const char* rawFlagsList = this->Makefile->GetDefinition(name);
+ if (rawFlagsList == CM_NULLPTR) {
+ 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);
+ }
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
- const char* defines_list)
+ const char* defines_list) const
{
// Short-circuit if there are no definitions.
- if(!defines_list)
- {
+ if (!defines_list) {
return;
- }
+ }
// Expand the list of definitions.
std::vector<std::string> defines_vec;
@@ -2291,50 +1899,43 @@ void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
this->AppendDefines(defines, defines_vec);
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
- const std::vector<std::string> &defines_vec)
+void cmLocalGenerator::AppendDefines(
+ std::set<std::string>& defines,
+ const std::vector<std::string>& defines_vec) const
{
- for(std::vector<std::string>::const_iterator di = defines_vec.begin();
- di != defines_vec.end(); ++di)
- {
+ for (std::vector<std::string>::const_iterator di = defines_vec.begin();
+ di != defines_vec.end(); ++di) {
// Skip unsupported definitions.
- if(!this->CheckDefinition(*di))
- {
+ if (!this->CheckDefinition(*di)) {
continue;
- }
- defines.insert(*di);
}
+ defines.insert(*di);
+ }
}
-//----------------------------------------------------------------------------
void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
- std::string &definesString,
- const char* lang)
+ std::string& definesString,
+ const std::string& lang)
{
// Lookup the define flag for the current language.
std::string dflag = "-D";
- if(lang)
- {
+ if (!lang.empty()) {
std::string defineFlagVar = "CMAKE_";
defineFlagVar += lang;
defineFlagVar += "_DEFINE_FLAG";
- const char* df = this->Makefile->GetDefinition(defineFlagVar.c_str());
- if(df && *df)
- {
+ const char* df = this->Makefile->GetDefinition(defineFlagVar);
+ 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 (; defineIt != defineEnd; ++defineIt) {
// Append the definition with proper escaping.
std::string def = dflag;
- if(this->WatcomWMake)
- {
+ if (this->GetState()->UseWatcomWMake()) {
// The Watcom compiler does its own command line parsing instead
// of using the windows shell rules. Definitions are one of
// -DNAME
@@ -2345,619 +1946,284 @@ 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)
- {
- if(*c == '$' || *c == '#')
- {
+ for (const char* c = defineIt->c_str(); *c; ++c) {
+ if (*c == '$' || *c == '#') {
def += '$';
- }
- def += *c;
}
+ def += *c;
}
- else
- {
+ } else {
// Make the definition appear properly on the command line. Use
- // -DNAME="value" instead of -D"NAME=value" to help VS6 parser.
+ // -DNAME="value" instead of -D"NAME=value" for historical reasons.
std::string::size_type eq = defineIt->find("=");
def += defineIt->substr(0, eq);
- if(eq != defineIt->npos)
- {
+ if (eq != std::string::npos) {
def += "=";
def += this->EscapeForShell(defineIt->c_str() + eq + 1, true);
- }
}
+ }
definesString += itemSeparator;
itemSeparator = " ";
definesString += def;
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::AppendFeatureOptions(
- std::string& flags, const char* lang, const char* feature)
+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.c_str()))
- {
+ 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->c_str());
- }
+ for (std::vector<std::string>::const_iterator oi = options.begin();
+ oi != options.end(); ++oi) {
+ this->AppendFlagEscape(flags, *oi);
}
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConstructComment(const cmCustomCommand& cc,
- const char* default_comment)
+const char* cmLocalGenerator::GetFeature(const std::string& feature,
+ const std::string& config)
{
- // Check for a comment provided with the command.
- if(cc.GetComment())
- {
- return cc.GetComment();
+ std::string featureName = feature;
+ // TODO: Define accumulation policy for features (prepend, append, replace).
+ // Currently we always replace.
+ if (!config.empty()) {
+ featureName += "_";
+ featureName += cmSystemTools::UpperCase(config);
+ }
+ cmStateSnapshot snp = this->StateSnapshot;
+ while (snp.IsValid()) {
+ if (const char* value = snp.GetDirectory().GetProperty(featureName)) {
+ return value;
}
+ snp = snp.GetBuildsystemDirectoryParent();
+ }
+ return CM_NULLPTR;
+}
+
+std::string cmLocalGenerator::GetProjectName() const
+{
+ return this->StateSnapshot.GetProjectName();
+}
+
+std::string cmLocalGenerator::ConstructComment(
+ cmCustomCommandGenerator const& ccg, const char* default_comment)
+{
+ // Check for a comment provided with the command.
+ if (ccg.GetComment()) {
+ return ccg.GetComment();
+ }
// Construct a reasonable default comment if possible.
- if(!cc.GetOutputs().empty())
- {
+ if (!ccg.GetOutputs().empty()) {
std::string comment;
comment = "Generating ";
const char* sep = "";
- for(std::vector<std::string>::const_iterator o = cc.GetOutputs().begin();
- o != cc.GetOutputs().end(); ++o)
- {
+ std::string currentBinaryDir = this->GetCurrentBinaryDirectory();
+ for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
+ o != ccg.GetOutputs().end(); ++o) {
comment += sep;
- comment += this->Convert(o->c_str(), cmLocalGenerator::START_OUTPUT);
+ comment += this->ConvertToRelativePath(currentBinaryDir, *o);
sep = ", ";
- }
- return comment;
}
+ return comment;
+ }
// Otherwise use the provided default.
return default_comment;
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOptionallyRelativeOutputPath(const char* remote)
-{
- return this->Convert(remote, START_OUTPUT, SHELL, true);
-}
-
-//----------------------------------------------------------------------------
-const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot)
+class cmInstallTargetGeneratorLocal : public cmInstallTargetGenerator
{
- switch (relroot)
- {
- case HOME: return this->Makefile->GetHomeDirectory();
- case START: return this->Makefile->GetStartDirectory();
- case HOME_OUTPUT: return this->Makefile->GetHomeOutputDirectory();
- case START_OUTPUT: return this->Makefile->GetStartOutputDirectory();
- default: break;
- }
- return 0;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::Convert(const char* source,
- RelativeRoot relative,
- OutputFormat output,
- bool optional)
-{
- // Make sure the relative path conversion components are set.
- if(!this->PathConversionsSetup)
- {
- this->SetupPathConversions();
- this->PathConversionsSetup = true;
- }
-
- // Convert the path to a relative path.
- std::string result = source;
-
- if (!optional || this->UseRelativePaths)
- {
- switch (relative)
- {
- case HOME:
- //result = cmSystemTools::CollapseFullPath(result.c_str());
- result = this->ConvertToRelativePath(this->HomeDirectoryComponents,
- result.c_str());
- break;
- case START:
- //result = cmSystemTools::CollapseFullPath(result.c_str());
- result = this->ConvertToRelativePath(this->StartDirectoryComponents,
- result.c_str());
- break;
- case HOME_OUTPUT:
- //result = cmSystemTools::CollapseFullPath(result.c_str());
- result =
- this->ConvertToRelativePath(this->HomeOutputDirectoryComponents,
- result.c_str());
- break;
- case START_OUTPUT:
- //result = cmSystemTools::CollapseFullPath(result.c_str());
- result =
- this->ConvertToRelativePath(this->StartOutputDirectoryComponents,
- result.c_str());
- break;
- case FULL:
- result = cmSystemTools::CollapseFullPath(result.c_str());
- break;
- case NONE:
- break;
- }
- }
- return this->ConvertToOutputFormat(result.c_str(), output);
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::ConvertToOutputFormat(const char* source,
- OutputFormat output)
-{
- std::string result = source;
- // Convert it to an output path.
- if (output == MAKEFILE)
- {
- result = cmSystemTools::ConvertToOutputPath(result.c_str());
- }
- else if( output == SHELL)
- {
- // 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.
- if(this->MSYSShell && !this->LinkScriptShell)
- {
- if(result.size() > 2 && result[1] == ':')
- {
- result[1] = result[0];
- result[0] = '/';
- }
- }
- if(this->WindowsShell)
- {
- std::string::size_type pos = 0;
- while((pos = result.find('/', pos)) != std::string::npos)
- {
- result[pos] = '\\';
- pos++;
- }
- }
- result = this->EscapeForShell(result.c_str(), true, false);
- }
- else if(output == RESPONSE)
- {
- result = this->EscapeForShell(result.c_str(), false, false);
- }
- return result;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::Convert(RelativeRoot remote,
- const char* local,
- OutputFormat output,
- bool optional)
-{
- const char* remotePath = this->GetRelativeRootPath(remote);
-
- // The relative root must have a path (i.e. not FULL or NONE)
- assert(remotePath != 0);
-
- if(local && (!optional || this->UseRelativePaths))
- {
- std::vector<std::string> components;
- cmSystemTools::SplitPath(local, components);
- std::string result = this->ConvertToRelativePath(components, remotePath);
- return this->ConvertToOutputFormat(result.c_str(), output);
- }
- else
- {
- return this->ConvertToOutputFormat(remotePath, output);
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::FindRelativePathTopSource()
-{
- // Relative path conversion within a single tree managed by CMake is
- // safe. We can use our parent relative path top if and only if
- // this is a subdirectory of that top.
- if(cmLocalGenerator* parent = this->GetParent())
- {
- std::string parentTop = parent->FindRelativePathTopSource();
- if(cmSystemTools::IsSubDirectory(
- this->Makefile->GetStartDirectory(), parentTop.c_str()))
- {
- return parentTop;
- }
- }
-
- // Otherwise this directory itself is the new top.
- return this->Makefile->GetStartDirectory();
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::FindRelativePathTopBinary()
-{
- // Relative path conversion within a single tree managed by CMake is
- // safe. We can use our parent relative path top if and only if
- // this is a subdirectory of that top.
- if(cmLocalGenerator* parent = this->GetParent())
- {
- std::string parentTop = parent->FindRelativePathTopBinary();
- if(cmSystemTools::IsSubDirectory(
- this->Makefile->GetStartOutputDirectory(), parentTop.c_str()))
- {
- return parentTop;
- }
- }
-
- // Otherwise this directory itself is the new top.
- return this->Makefile->GetStartOutputDirectory();
-}
-
-//----------------------------------------------------------------------------
-void cmLocalGenerator::ConfigureRelativePaths()
-{
- // Relative path conversion inside the source tree is not used to
- // construct relative paths passed to build tools so it is safe to
- // even when the source is a network path.
- std::string source = this->FindRelativePathTopSource();
- this->RelativePathTopSource = source;
-
- // The current working directory on Windows cannot be a network
- // path. Therefore relative paths cannot work when the binary tree
- // is a network path.
- std::string binary = this->FindRelativePathTopBinary();
- if(binary.size() < 2 || binary.substr(0, 2) != "//")
- {
- this->RelativePathTopBinary = binary;
- }
- else
- {
- this->RelativePathTopBinary = "";
- }
-}
-
-//----------------------------------------------------------------------------
-static bool cmLocalGeneratorNotAbove(const char* a, const char* b)
-{
- return (cmSystemTools::ComparePath(a, b) ||
- cmSystemTools::IsSubDirectory(a, b));
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
- const char* in_remote, bool force)
-{
- // The path should never be quoted.
- assert(in_remote[0] != '\"');
-
- // The local path should never have a trailing slash.
- assert(local.size() > 0 && !(local[local.size()-1] == ""));
-
- // If the path is already relative then just return the path.
- if(!cmSystemTools::FileIsFullPath(in_remote))
- {
- return in_remote;
- }
-
- // Make sure relative path conversion is configured.
- if(!this->RelativePathsConfigured)
- {
- this->ConfigureRelativePaths();
- this->RelativePathsConfigured = true;
- }
-
- if(!force)
- {
- // Skip conversion if the path and local are not both in the source
- // or both in the binary tree.
- std::string local_path = cmSystemTools::JoinPath(local);
- if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
- this->RelativePathTopBinary.c_str()) &&
- cmLocalGeneratorNotAbove(in_remote,
- this->RelativePathTopBinary.c_str())) ||
- (cmLocalGeneratorNotAbove(local_path.c_str(),
- this->RelativePathTopSource.c_str()) &&
- cmLocalGeneratorNotAbove(in_remote,
- this->RelativePathTopSource.c_str()))))
- {
- return in_remote;
- }
- }
-
- // Identify the longest shared path component between the remote
- // path and the local path.
- std::vector<std::string> remote;
- cmSystemTools::SplitPath(in_remote, remote);
- unsigned int common=0;
- while(common < remote.size() &&
- common < local.size() &&
- cmSystemTools::ComparePath(remote[common].c_str(),
- local[common].c_str()))
- {
- ++common;
- }
-
- // If no part of the path is in common then return the full path.
- if(common == 0)
- {
- return in_remote;
- }
-
- // 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].size() == 0 &&
- 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.
- for(unsigned int i=common; i < remote.size(); ++i)
- {
- if(relative.size() > 0)
- {
- relative += "/";
- }
- relative += remote[i];
- }
-
- // Finally return the path.
- return relative;
-}
+public:
+ cmInstallTargetGeneratorLocal(cmLocalGenerator* lg, std::string const& t,
+ const char* dest, bool implib)
+ : cmInstallTargetGenerator(
+ t, dest, implib, "", std::vector<std::string>(), "Unspecified",
+ cmInstallGenerator::SelectMessageLevel(lg->GetMakefile()), false,
+ false)
+ {
+ this->Compute(lg);
+ }
+};
-//----------------------------------------------------------------------------
-void
-cmLocalGenerator
-::GenerateTargetInstallRules(
- std::ostream& os, const char* config,
+void cmLocalGenerator::GenerateTargetInstallRules(
+ std::ostream& os, const std::string& config,
std::vector<std::string> const& configurationTypes)
{
// Convert the old-style install specification from each target to
// an install generator and run it.
- cmTargets& tgts = this->Makefile->GetTargets();
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
- {
+ 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;
+ }
+
// Include the user-specified pre-install script for this target.
- if(const char* preinstall = l->second.GetProperty("PRE_INSTALL_SCRIPT"))
- {
- cmInstallScriptGenerator g(preinstall, false, 0);
+ if (const char* preinstall = (*l)->GetProperty("PRE_INSTALL_SCRIPT")) {
+ cmInstallScriptGenerator g(preinstall, false, CM_NULLPTR, false);
g.Generate(os, config, configurationTypes);
- }
+ }
// Install this target if a destination is given.
- if(l->second.GetInstallPath() != "")
- {
+ if ((*l)->Target->GetInstallPath() != "") {
// 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->second.GetInstallPath().substr(1);
+ std::string destination = (*l)->Target->GetInstallPath().substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
- if(destination.empty())
- {
+ if (destination.empty()) {
destination = ".";
- }
+ }
// Generate the proper install generator for this target type.
- switch(l->second.GetType())
- {
- case cmTarget::EXECUTABLE:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- {
+ switch ((*l)->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY: {
// Use a target install generator.
- cmInstallTargetGenerator g(l->second, destination.c_str(), false);
+ cmInstallTargetGeneratorLocal g(this, (*l)->GetName(),
+ destination.c_str(), false);
g.Generate(os, config, configurationTypes);
- }
- break;
- case cmTarget::SHARED_LIBRARY:
- {
+ } break;
+ case cmStateEnums::SHARED_LIBRARY: {
#if defined(_WIN32) || defined(__CYGWIN__)
// Special code to handle DLL. Install the import library
// to the normal destination and the DLL to the runtime
// destination.
- cmInstallTargetGenerator g1(l->second, destination.c_str(), true);
+ 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->second.GetRuntimeInstallPath().substr(1);
+ destination = (*l)->Target->GetRuntimeInstallPath().substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
- cmInstallTargetGenerator g2(l->second, destination.c_str(), false);
+ cmInstallTargetGeneratorLocal g2(this, (*l)->GetName(),
+ destination.c_str(), false);
g2.Generate(os, config, configurationTypes);
#else
// Use a target install generator.
- cmInstallTargetGenerator g(l->second, destination.c_str(), false);
+ cmInstallTargetGeneratorLocal g(this, (*l)->GetName(),
+ destination.c_str(), false);
g.Generate(os, config, configurationTypes);
#endif
- }
- break;
+ } break;
default:
break;
- }
}
+ }
// Include the user-specified post-install script for this target.
- if(const char* postinstall = l->second.GetProperty("POST_INSTALL_SCRIPT"))
- {
- cmInstallScriptGenerator g(postinstall, false, 0);
+ if (const char* postinstall = (*l)->GetProperty("POST_INSTALL_SCRIPT")) {
+ cmInstallScriptGenerator g(postinstall, false, CM_NULLPTR, false);
g.Generate(os, config, configurationTypes);
- }
}
+ }
}
#if defined(CM_LG_ENCODE_OBJECT_NAMES)
-static std::string cmLocalGeneratorMD5(const char* input)
-{
- char md5out[32];
- cmsysMD5* md5 = cmsysMD5_New();
- cmsysMD5_Initialize(md5);
- cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(input), -1);
- cmsysMD5_FinalizeHex(md5, md5out);
- cmsysMD5_Delete(md5);
- return std::string(md5out, 32);
-}
-
-static bool
-cmLocalGeneratorShortenObjectName(std::string& objName,
- std::string::size_type max_len)
+static bool cmLocalGeneratorShortenObjectName(std::string& objName,
+ std::string::size_type max_len)
{
// Replace the beginning of the path portion of the object name with
// its own md5 sum.
- std::string::size_type pos = objName.find('/', objName.size()-max_len+32);
- if(pos != objName.npos)
- {
- std::string md5name = cmLocalGeneratorMD5(objName.substr(0, pos).c_str());
+ std::string::size_type pos =
+ 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);
objName = md5name;
// The object name is now short enough.
return true;
- }
- else
- {
- // The object name could not be shortened enough.
- return false;
- }
+ }
+ // The object name could not be shortened enough.
+ return false;
}
-static
bool cmLocalGeneratorCheckObjectName(std::string& objName,
std::string::size_type dir_len,
std::string::size_type max_total_len)
{
// Enforce the maximum file name length if possible.
std::string::size_type max_obj_len = max_total_len;
- if(dir_len < max_total_len)
- {
+ if (dir_len < max_total_len) {
max_obj_len = max_total_len - dir_len;
- if(objName.size() > max_obj_len)
- {
+ if (objName.size() > max_obj_len) {
// The current object file name is too long. Try to shorten it.
return cmLocalGeneratorShortenObjectName(objName, max_obj_len);
- }
- else
- {
- // The object file name is short enough.
- return true;
- }
- }
- else
- {
- // The build directory in which the object will be stored is
- // already too deep.
- return false;
}
+ // The object file name is short enough.
+ return true;
+ }
+ // The build directory in which the object will be stored is
+ // already too deep.
+ return false;
}
#endif
-//----------------------------------------------------------------------------
-std::string&
-cmLocalGenerator
-::CreateSafeUniqueObjectFileName(const char* sin,
- std::string const& dir_max)
+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<cmStdString,cmStdString>::iterator it =
+ std::map<std::string, std::string>::iterator it =
this->UniqueObjectNamesMap.find(sin);
// If no entry exists create one.
- if(it == this->UniqueObjectNamesMap.end())
- {
+ if (it == this->UniqueObjectNamesMap.end()) {
// Start with the original name.
std::string ssin = sin;
// Avoid full paths by removing leading slashes.
- std::string::size_type pos = 0;
- for(;pos < ssin.size() && ssin[pos] == '/'; ++pos)
- {
- }
- ssin = ssin.substr(pos);
+ ssin.erase(0, ssin.find_first_not_of('/'));
// Avoid full paths by removing colons.
- cmSystemTools::ReplaceString(ssin, ":", "_");
+ std::replace(ssin.begin(), ssin.end(), ':', '_');
// Avoid relative paths that go up the tree.
cmSystemTools::ReplaceString(ssin, "../", "__/");
// Avoid spaces.
- cmSystemTools::ReplaceString(ssin, " ", "_");
+ std::replace(ssin.begin(), ssin.end(), ' ', '_');
// Mangle the name if necessary.
- if(this->Makefile->IsOn("CMAKE_MANGLE_OBJECT_FILE_NAMES"))
- {
+ if (this->Makefile->IsOn("CMAKE_MANGLE_OBJECT_FILE_NAMES")) {
bool done;
int cc = 0;
char rpstr[100];
sprintf(rpstr, "_p_");
cmSystemTools::ReplaceString(ssin, "+", rpstr);
std::string sssin = sin;
- do
- {
+ do {
done = true;
- for ( it = this->UniqueObjectNamesMap.begin();
- it != this->UniqueObjectNamesMap.end();
- ++ it )
- {
- if ( it->second == ssin )
- {
+ for (it = this->UniqueObjectNamesMap.begin();
+ it != this->UniqueObjectNamesMap.end(); ++it) {
+ if (it->second == ssin) {
done = false;
- }
}
- if ( done )
- {
+ }
+ if (done) {
break;
- }
+ }
sssin = ssin;
cmSystemTools::ReplaceString(ssin, "_p_", rpstr);
sprintf(rpstr, "_p%d_", cc++);
- }
- while ( !done );
- }
+ } while (!done);
+ }
#if defined(CM_LG_ENCODE_OBJECT_NAMES)
- if(!cmLocalGeneratorCheckObjectName(ssin, dir_max.size(),
- this->ObjectPathMax))
- {
+ if (!cmLocalGeneratorCheckObjectName(ssin, dir_max.size(),
+ this->ObjectPathMax)) {
// Warn if this is the first time the path has been seen.
- if(this->ObjectMaxPathViolations.insert(dir_max).second)
- {
- cmOStringStream m;
+ if (this->ObjectMaxPathViolations.insert(dir_max).second) {
+ std::ostringstream m;
+ /* clang-format off */
m << "The object file directory\n"
<< " " << dir_max << "\n"
<< "has " << dir_max.size() << " characters. "
@@ -2968,41 +2234,67 @@ cmLocalGenerator
<< " " << ssin << "\n"
<< "cannot be safely placed under this directory. "
<< "The build may not work correctly.";
- this->Makefile->IssueMessage(cmake::WARNING, m.str());
- }
+ /* clang-format on */
+ this->IssueMessage(cmake::WARNING, m.str());
}
+ }
#else
(void)dir_max;
#endif
// Insert the newly mapped object file name.
- std::map<cmStdString, cmStdString>::value_type e(sin, ssin);
+ std::map<std::string, std::string>::value_type e(sin, ssin);
it = this->UniqueObjectNamesMap.insert(e).first;
- }
+ }
// Return the map entry.
return it->second;
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator
-::GetObjectFileNameWithoutTarget(const cmSourceFile& source,
- std::string const& dir_max,
- bool* hasSourceExtension)
+void cmLocalGenerator::ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& /*unused*/,
+ cmGeneratorTarget const* /*unused*/)
+{
+}
+
+bool cmLocalGenerator::IsWindowsShell() const
+{
+ return this->GetState()->UseWindowsShell();
+}
+
+bool cmLocalGenerator::IsWatcomWMake() const
+{
+ return this->GetState()->UseWatcomWMake();
+}
+
+bool cmLocalGenerator::IsMinGWMake() const
+{
+ return this->GetState()->UseMinGWMake();
+}
+
+bool cmLocalGenerator::IsNMake() const
+{
+ return this->GetState()->UseNMake();
+}
+
+std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
+ const cmSourceFile& source, std::string const& dir_max,
+ bool* hasSourceExtension, char const* customOutputExtension)
{
// Construct the object file name using the full path to the source
// file which is its only unique identification.
- const char* fullPath = source.GetFullPath().c_str();
+ std::string const& fullPath = source.GetFullPath();
// Try referencing the source relative to the source tree.
- std::string relFromSource = this->Convert(fullPath, START);
+ std::string relFromSource =
+ this->ConvertToRelativePath(this->GetCurrentSourceDirectory(), fullPath);
assert(!relFromSource.empty());
bool relSource = !cmSystemTools::FileIsFullPath(relFromSource.c_str());
bool subSource = relSource && relFromSource[0] != '.';
// Try referencing the source relative to the binary tree.
- std::string relFromBinary = this->Convert(fullPath, START_OUTPUT);
+ std::string relFromBinary =
+ this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), fullPath);
assert(!relFromBinary.empty());
bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary.c_str());
bool subBinary = relBinary && relFromBinary[0] != '.';
@@ -3010,300 +2302,142 @@ cmLocalGenerator
// Select a nice-looking reference to the source file to construct
// the object file name.
std::string objectName;
- if((relSource && !relBinary) || (subSource && !subBinary))
- {
+ if ((relSource && !relBinary) || (subSource && !subBinary)) {
objectName = relFromSource;
- }
- else if((relBinary && !relSource) || (subBinary && !subSource))
- {
+ } else if ((relBinary && !relSource) || (subBinary && !subSource)) {
objectName = relFromBinary;
- }
- else if(relFromBinary.length() < relFromSource.length())
- {
+ } else if (relFromBinary.length() < relFromSource.length()) {
objectName = relFromBinary;
- }
- else
- {
+ } else {
objectName = relFromSource;
- }
+ }
// 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(this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile())
- {
+ if (cmSystemTools::FileIsFullPath(objectName.c_str())) {
+ if (this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) {
objectName = cmSystemTools::GetFilenameName(source.GetFullPath());
- }
}
+ }
// Replace the original source file extension with the object file
// extension.
bool keptSourceExtension = true;
- if(!source.GetPropertyAsBool("KEEP_EXTENSION"))
- {
+ if (!source.GetPropertyAsBool("KEEP_EXTENSION")) {
// Decide whether this language wants to replace the source
// extension with the object extension. For CMake 2.4
// compatibility do this by default.
- bool replaceExt = this->NeedBackwardsCompatibility(2, 4);
- if(!replaceExt)
- {
- if(const char* lang = source.GetLanguage())
- {
+ bool replaceExt = this->NeedBackwardsCompatibility_2_4();
+ 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.c_str());
- }
+ replaceExt = this->Makefile->IsOn(repVar);
}
+ }
// Remove the source extension if it is to be replaced.
- if(replaceExt)
- {
+ if (replaceExt || customOutputExtension) {
keptSourceExtension = false;
- std::string::size_type dot_pos = objectName.rfind(".");
- if(dot_pos != std::string::npos)
- {
+ std::string::size_type dot_pos = objectName.rfind('.');
+ if (dot_pos != std::string::npos) {
objectName = objectName.substr(0, dot_pos);
- }
}
+ }
// Store the new extension.
- objectName +=
- this->GlobalGenerator->GetLanguageOutputExtension(source);
+ if (customOutputExtension) {
+ objectName += customOutputExtension;
+ } else {
+ objectName += this->GlobalGenerator->GetLanguageOutputExtension(source);
}
- if(hasSourceExtension)
- {
+ }
+ if (hasSourceExtension) {
*hasSourceExtension = keptSourceExtension;
- }
+ }
// Convert to a safe name.
- return this->CreateSafeUniqueObjectFileName(objectName.c_str(), dir_max);
+ return this->CreateSafeUniqueObjectFileName(objectName, dir_max);
}
-//----------------------------------------------------------------------------
-const char*
-cmLocalGenerator
-::GetSourceFileLanguage(const cmSourceFile& source)
+std::string cmLocalGenerator::GetSourceFileLanguage(const cmSourceFile& source)
{
return source.GetLanguage();
}
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::EscapeForShellOldStyle(const char* str)
+cmake* cmLocalGenerator::GetCMakeInstance() const
{
- std::string result;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // if there are spaces
- std::string temp = str;
- if (temp.find(" ") != std::string::npos &&
- temp.find("\"")==std::string::npos)
- {
- result = "\"";
- result += str;
- result += "\"";
- return result;
- }
- return str;
-#else
- for(const char* ch = str; *ch != '\0'; ++ch)
- {
- if(*ch == ' ')
- {
- result += '\\';
- }
- result += *ch;
- }
- return result;
-#endif
+ return this->GlobalGenerator->GetCMakeInstance();
}
-//----------------------------------------------------------------------------
-static bool cmLocalGeneratorIsShellOperator(const char* str)
-{
- if(strcmp(str, "<") == 0 ||
- strcmp(str, ">") == 0 ||
- strcmp(str, "<<") == 0 ||
- strcmp(str, ">>") == 0 ||
- strcmp(str, "|") == 0 ||
- strcmp(str, "||") == 0 ||
- strcmp(str, "&&") == 0 ||
- strcmp(str, "&>") == 0 ||
- strcmp(str, "1>") == 0 ||
- strcmp(str, "2>") == 0 ||
- strcmp(str, "2>&1") == 0 ||
- strcmp(str, "1>&2") == 0)
- {
- return true;
- }
- return false;
+const char* cmLocalGenerator::GetSourceDirectory() const
+{
+ return this->GetCMakeInstance()->GetHomeDirectory();
}
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::EscapeForShell(const char* str, bool makeVars,
- bool forEcho)
+const char* cmLocalGenerator::GetBinaryDirectory() const
{
- // Do not escape shell operators.
- if(cmLocalGeneratorIsShellOperator(str))
- {
- return str;
- }
-
- // Compute the flags for the target shell environment.
- int flags = 0;
- if(this->WindowsVSIDE)
- {
- flags |= cmsysSystem_Shell_Flag_VSIDE;
- }
- else if(!this->LinkScriptShell)
- {
- flags |= cmsysSystem_Shell_Flag_Make;
- }
- if(makeVars)
- {
- flags |= cmsysSystem_Shell_Flag_AllowMakeVariables;
- }
- if(forEcho)
- {
- flags |= cmsysSystem_Shell_Flag_EchoWindows;
- }
- if(this->WatcomWMake)
- {
- flags |= cmsysSystem_Shell_Flag_WatcomWMake;
- }
- if(this->MinGWMake)
- {
- flags |= cmsysSystem_Shell_Flag_MinGWMake;
- }
- if(this->NMake)
- {
- flags |= cmsysSystem_Shell_Flag_NMake;
- }
-
- // Compute the buffer size needed.
- int size = (this->WindowsShell ?
- cmsysSystem_Shell_GetArgumentSizeForWindows(str, flags) :
- cmsysSystem_Shell_GetArgumentSizeForUnix(str, flags));
+ return this->GetCMakeInstance()->GetHomeOutputDirectory();
+}
- // Compute the shell argument itself.
- std::vector<char> arg(size);
- if(this->WindowsShell)
- {
- cmsysSystem_Shell_GetArgumentForWindows(str, &arg[0], flags);
- }
- else
- {
- cmsysSystem_Shell_GetArgumentForUnix(str, &arg[0], flags);
- }
- return std::string(&arg[0]);
+const char* cmLocalGenerator::GetCurrentBinaryDirectory() const
+{
+ return this->StateSnapshot.GetDirectory().GetCurrentBinary();
}
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::EscapeForCMake(const char* str)
+const char* cmLocalGenerator::GetCurrentSourceDirectory() const
{
- // Always double-quote the argument to take care of most escapes.
- std::string result = "\"";
- for(const char* c = str; *c; ++c)
- {
- if(*c == '"')
- {
- // Escape the double quote to avoid ending the argument.
- result += "\\\"";
- }
- else if(*c == '$')
- {
- // Escape the dollar to avoid expanding variables.
- result += "\\$";
- }
- else if(*c == '\\')
- {
- // Escape the backslash to avoid other escapes.
- result += "\\\\";
- }
- else
- {
- // Other characters will be parsed correctly.
- result += *c;
- }
- }
- result += "\"";
- return result;
-}
-
-//----------------------------------------------------------------------------
-cmLocalGenerator::FortranFormat
-cmLocalGenerator::GetFortranFormat(const char* 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")
- {
- format = FortranFormatFixed;
- }
- if(*fi == "FREE")
- {
- format = FortranFormatFree;
- }
- }
- }
- return format;
+ return this->StateSnapshot.GetDirectory().GetCurrentSource();
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::GetTargetDirectory(cmTarget const&) const
+std::string cmLocalGenerator::GetTargetDirectory(
+ const cmGeneratorTarget* /*unused*/) const
{
cmSystemTools::Error("GetTargetDirectory"
" called on cmLocalGenerator");
return "";
}
-//----------------------------------------------------------------------------
-unsigned int cmLocalGenerator::GetBackwardsCompatibility()
+KWIML_INT_uint64_t cmLocalGenerator::GetBackwardsCompatibility()
{
// The computed version may change until the project is fully
// configured.
- if(!this->BackwardsCompatibilityFinal)
- {
+ if (!this->BackwardsCompatibilityFinal) {
unsigned int major = 0;
unsigned int minor = 0;
unsigned int patch = 0;
- if(const char* value
- = this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"))
- {
- switch(sscanf(value, "%u.%u.%u", &major, &minor, &patch))
- {
- case 2: patch = 0; break;
- case 1: minor = 0; patch = 0; break;
- default: break;
- }
+ if (const char* value =
+ this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY")) {
+ switch (sscanf(value, "%u.%u.%u", &major, &minor, &patch)) {
+ case 2:
+ patch = 0;
+ break;
+ case 1:
+ minor = 0;
+ patch = 0;
+ break;
+ default:
+ break;
}
- this->BackwardsCompatibility = CMake_VERSION_ENCODE(major, minor, patch);
- this->BackwardsCompatibilityFinal = this->Configured;
}
+ this->BackwardsCompatibility = CMake_VERSION_ENCODE(major, minor, patch);
+ this->BackwardsCompatibilityFinal = true;
+ }
return this->BackwardsCompatibility;
}
-//----------------------------------------------------------------------------
-bool cmLocalGenerator::NeedBackwardsCompatibility(unsigned int major,
- unsigned int minor,
- unsigned int patch)
+bool cmLocalGenerator::NeedBackwardsCompatibility_2_4()
{
// Check the policy to decide whether to pay attention to this
// variable.
- switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0001))
- {
+ switch (this->GetPolicyStatus(cmPolicies::CMP0001)) {
case cmPolicies::WARN:
- // WARN is just OLD without warning because user code does not
- // always affect whether this check is done.
+ // WARN is just OLD without warning because user code does not
+ // always affect whether this check is done.
case cmPolicies::OLD:
// Old behavior is to check the variable.
break;
@@ -3317,98 +2451,93 @@ bool cmLocalGenerator::NeedBackwardsCompatibility(unsigned int major,
// 2.6 or higher. Once we add that requirement then this whole
// method can be removed anyway.
return false;
- }
+ }
// Compatibility is needed if CMAKE_BACKWARDS_COMPATIBILITY is set
// equal to or lower than the given version.
- unsigned int actual_compat = this->GetBackwardsCompatibility();
- return (actual_compat &&
- actual_compat <= CMake_VERSION_ENCODE(major, minor, patch));
+ KWIML_INT_uint64_t actual_compat = this->GetBackwardsCompatibility();
+ return (actual_compat && actual_compat <= CMake_VERSION_ENCODE(2, 4, 255));
+}
+
+cmPolicies::PolicyStatus cmLocalGenerator::GetPolicyStatus(
+ cmPolicies::PolicyID id) const
+{
+ return this->Makefile->GetPolicyStatus(id);
}
-//----------------------------------------------------------------------------
bool cmLocalGenerator::CheckDefinition(std::string const& define) const
{
// Many compilers do not support -DNAME(arg)=sdf so we disable it.
- bool function_style = false;
- for(const char* c = define.c_str(); *c && *c != '='; ++c)
- {
- if(*c == '(')
- {
- function_style = true;
- break;
- }
- }
- if(function_style)
- {
- cmOStringStream e;
- e << "WARNING: Function-style preprocessor definitions may not be "
- << "passed on the compiler command line because many compilers "
- << "do not support it.\n"
- << "CMake is dropping a preprocessor definition: " << define << "\n"
- << "Consider defining the macro in a (configured) header file.\n";
- cmSystemTools::Message(e.str().c_str());
- return false;
+ std::string::size_type pos = define.find_first_of("(=");
+ if (pos != std::string::npos) {
+ if (define[pos] == '(') {
+ std::ostringstream e;
+ /* clang-format off */
+ e << "WARNING: Function-style preprocessor definitions may not be "
+ << "passed on the compiler command line because many compilers "
+ << "do not support it.\n"
+ << "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());
+ return false;
}
+ }
// Many compilers do not support # in the value so we disable it.
- if(define.find_first_of("#") != define.npos)
- {
- cmOStringStream e;
+ if (define.find_first_of('#') != std::string::npos) {
+ std::ostringstream e;
+ /* clang-format off */
e << "WARNING: Preprocessor definitions containing '#' may not be "
<< "passed on the compiler command line because many compilers "
<< "do not support it.\n"
<< "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());
return false;
- }
+ }
// Assume it is supported.
return true;
}
-//----------------------------------------------------------------------------
-static void cmLGInfoProp(cmMakefile* mf, cmTarget* target, const char* prop)
+static void cmLGInfoProp(cmMakefile* mf, cmGeneratorTarget* target,
+ const std::string& prop)
{
- if(const char* val = target->GetProperty(prop))
- {
+ if (const char* val = target->GetProperty(prop)) {
mf->AddDefinition(prop, val);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::GenerateAppleInfoPList(cmTarget* target,
- const char* targetName,
+void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
+ const std::string& targetName,
const char* 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 inFile = (in && *in) ? in : "MacOSXBundleInfo.plist.in";
+ if (!cmSystemTools::FileIsFullPath(inFile.c_str())) {
std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
- if(!inMod.empty())
- {
+ if (!inMod.empty()) {
inFile = inMod;
- }
}
- if(!cmSystemTools::FileExists(inFile.c_str(), true))
- {
- cmOStringStream e;
- e << "Target " << target->GetName() << " Info.plist template \""
- << inFile << "\" could not be found.";
+ }
+ if (!cmSystemTools::FileExists(inFile.c_str(), true)) {
+ std::ostringstream e;
+ e << "Target " << target->GetName() << " Info.plist template \"" << inFile
+ << "\" could not be found.";
cmSystemTools::Error(e.str().c_str());
return;
- }
+ }
// Convert target properties to variables in an isolated makefile
// scope to configure the file. If properties are set they will
// override user make variables. If not the configuration will fall
// back to the directory-level values set by the user.
cmMakefile* mf = this->Makefile;
- mf->PushScope();
- mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName);
+ cmMakefile::ScopePushPop varScope(mf);
+ mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName.c_str());
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_INFO_STRING");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_ICON_FILE");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_GUI_IDENTIFIER");
@@ -3418,45 +2547,38 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmTarget* target,
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
- mf->PopScope();
}
-//----------------------------------------------------------------------------
-void cmLocalGenerator::GenerateFrameworkInfoPList(cmTarget* target,
- const char* targetName,
- const char* fname)
+void cmLocalGenerator::GenerateFrameworkInfoPList(
+ cmGeneratorTarget* target, const std::string& targetName, const char* 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 inFile = (in && *in) ? in : "MacOSXFrameworkInfo.plist.in";
+ if (!cmSystemTools::FileIsFullPath(inFile.c_str())) {
std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
- if(!inMod.empty())
- {
+ if (!inMod.empty()) {
inFile = inMod;
- }
}
- if(!cmSystemTools::FileExists(inFile.c_str(), true))
- {
- cmOStringStream e;
- e << "Target " << target->GetName() << " Info.plist template \""
- << inFile << "\" could not be found.";
+ }
+ if (!cmSystemTools::FileExists(inFile.c_str(), true)) {
+ std::ostringstream e;
+ e << "Target " << target->GetName() << " Info.plist template \"" << inFile
+ << "\" could not be found.";
cmSystemTools::Error(e.str().c_str());
return;
- }
+ }
// Convert target properties to variables in an isolated makefile
// scope to configure the file. If properties are set they will
// override user make variables. If not the configuration will fall
// back to the directory-level values set by the user.
cmMakefile* mf = this->Makefile;
- mf->PushScope();
- mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName);
+ cmMakefile::ScopePushPop varScope(mf);
+ mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName.c_str());
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->PopScope();
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 10f0b1a6c..9f78be465 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -1,26 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalGenerator_h
#define cmLocalGenerator_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
-class cmMakefile;
-class cmGlobalGenerator;
+#include "cm_kwiml.h"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cmListFileCache.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmStateSnapshot.h"
+#include "cmake.h"
+
+class cmComputeLinkInformation;
+class cmCustomCommandGenerator;
class cmGeneratorTarget;
-class cmTarget;
-class cmTargetManifest;
+class cmGlobalGenerator;
+class cmLinkLineComputer;
+class cmMakefile;
+class cmRulePlaceholderExpander;
class cmSourceFile;
-class cmCustomCommand;
+class cmState;
/** \class cmLocalGenerator
* \brief Create required build files for a directory.
@@ -29,10 +35,10 @@ class cmCustomCommand;
* platforms. This class should never be constructed directly. A
* GlobalGenerator will create it and invoke the appropriate commands on it.
*/
-class cmLocalGenerator
+class cmLocalGenerator : public cmOutputConverter
{
public:
- cmLocalGenerator();
+ cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile);
virtual ~cmLocalGenerator();
/**
@@ -40,11 +46,7 @@ public:
*/
virtual void Generate() {}
- /**
- * Process the CMakeLists files for this directory to fill in the
- * Makefile ivar
- */
- virtual void Configure();
+ virtual void ComputeHomeRelativeOutputPath() {}
/**
* Calls TraceVSDependencies() on all targets of this generator.
@@ -54,11 +56,6 @@ public:
virtual void AddHelperCommands() {}
/**
- * Perform any final calculations prior to generation
- */
- void ConfigureFinalPass();
-
- /**
* Generate the install rules files in this directory.
*/
void GenerateInstallRules();
@@ -71,116 +68,115 @@ public:
/**
* Generate a manifest of target files that will be built.
*/
- void GenerateTargetManifest();
+ void ComputeTargetManifest();
+
+ bool ComputeTargetCompileFeatures();
+
+ bool IsRootMakefile() const;
///! Get the makefile for this generator
- cmMakefile *GetMakefile() {
- return this->Makefile; };
+ cmMakefile* GetMakefile() { return this->Makefile; }
///! Get the makefile for this generator, const version
- const cmMakefile *GetMakefile() const {
- return this->Makefile; };
+ const cmMakefile* GetMakefile() const { return this->Makefile; }
///! Get the GlobalGenerator this is associated with
- cmGlobalGenerator *GetGlobalGenerator() {
- return this->GlobalGenerator; };
- const cmGlobalGenerator *GetGlobalGenerator() const {
- return this->GlobalGenerator; };
-
- ///! Set the Global Generator, done on creation by the GlobalGenerator
- void SetGlobalGenerator(cmGlobalGenerator *gg);
-
- /**
- * Convert something to something else. This is a centralized conversion
- * routine used by the generators to handle relative paths and the like.
- * The flags determine what is actually done.
- *
- * relative: treat the argument as a directory and convert it to make it
- * relative or full or unchanged. If relative (HOME, START etc) then that
- * specifies what it should be relative to.
- *
- * output: make the result suitable for output to a...
- *
- * optional: should any relative path operation be controlled by the rel
- * path setting
- */
- enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT };
- enum OutputFormat { UNCHANGED, MAKEFILE, SHELL, RESPONSE };
- std::string ConvertToOutputFormat(const char* source, OutputFormat output);
- std::string Convert(const char* remote, RelativeRoot local,
- OutputFormat output = UNCHANGED,
- bool optional = false);
- std::string Convert(RelativeRoot remote, const char* local,
- OutputFormat output = UNCHANGED,
- bool optional = false);
-
- /**
- * Get path for the specified relative root.
- */
- const char* GetRelativeRootPath(RelativeRoot relroot);
-
- /**
- * Convert the given path to an output path that is optionally
- * relative based on the cache option CMAKE_USE_RELATIVE_PATHS. The
- * remote path must use forward slashes and not already be escaped
- * or quoted.
- */
- std::string ConvertToOptionallyRelativeOutputPath(const char* remote);
-
- ///! set/get the parent generator
- cmLocalGenerator* GetParent(){return this->Parent;}
- void SetParent(cmLocalGenerator* g) { this->Parent = g; g->AddChild(this); }
-
- ///! set/get the children
- void AddChild(cmLocalGenerator* g) { this->Children.push_back(g); }
- std::vector<cmLocalGenerator*>& GetChildren() { return this->Children; };
-
-
- void AddArchitectureFlags(std::string& flags, cmGeneratorTarget* target,
- const char *lang, const char* config);
+ cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
+ const cmGlobalGenerator* GetGlobalGenerator() const
+ {
+ return this->GlobalGenerator;
+ }
- void AddLanguageFlags(std::string& flags, const char* lang,
- const char* config);
- void AddCMP0018Flags(std::string &flags, cmTarget* target,
- std::string const& lang, const char *config);
- void AddVisibilityPresetFlags(std::string &flags, cmTarget* target,
- const char *lang);
- void AddConfigVariableFlags(std::string& flags, const char* var,
- const char* config);
+ virtual cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const;
+
+ std::string GetLinkLibsCMP0065(std::string const& linkLanguage,
+ cmGeneratorTarget& tgt) const;
+
+ cmState* GetState() const;
+ cmStateSnapshot GetStateSnapshot() const;
+
+ void AddArchitectureFlags(std::string& flags,
+ cmGeneratorTarget const* target,
+ const std::string& lang,
+ const std::string& config);
+
+ void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target,
+ const std::string& lang, const std::string& config);
+ void AddLanguageFlagsForLinking(std::string& flags,
+ cmGeneratorTarget const* target,
+ const std::string& lang,
+ const std::string& config);
+ void AddCMP0018Flags(std::string& flags, cmGeneratorTarget const* target,
+ std::string const& lang, const std::string& config);
+ void AddVisibilityPresetFlags(std::string& flags,
+ cmGeneratorTarget const* target,
+ const std::string& lang);
+ void AddConfigVariableFlags(std::string& flags, const std::string& var,
+ const std::string& config);
+ 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);
- virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
+ virtual void AppendFlagEscape(std::string& flags,
+ const std::string& rawFlag);
+ 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
- std::string GetIncludeFlags(const std::vector<std::string> &includes,
+ std::string GetIncludeFlags(const std::vector<std::string>& includes,
cmGeneratorTarget* target,
- const char* lang, bool forResponseFile = false,
- const char *config = 0);
+ const std::string& lang,
+ bool forceFullPaths = false,
+ bool forResponseFile = false,
+ const std::string& config = "");
+
+ const std::vector<cmGeneratorTarget*>& GetGeneratorTargets() const
+ {
+ return this->GeneratorTargets;
+ }
+
+ const std::vector<cmGeneratorTarget*>& GetImportedGeneratorTargets() const
+ {
+ return this->ImportedGeneratorTargets;
+ }
+
+ void AddGeneratorTarget(cmGeneratorTarget* gt);
+ void AddImportedGeneratorTarget(cmGeneratorTarget* gt);
+ void AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt);
+
+ cmGeneratorTarget* FindLocalNonAliasGeneratorTarget(
+ const std::string& name) const;
+ cmGeneratorTarget* FindGeneratorTargetToUse(const std::string& name) const;
/**
* Encode a list of preprocessor definitions for the compiler
* command line.
*/
void AppendDefines(std::set<std::string>& defines,
- const char* defines_list);
+ const char* defines_list) const;
void AppendDefines(std::set<std::string>& defines,
- std::string defines_list)
+ std::string const& defines_list) const
{
this->AppendDefines(defines, defines_list.c_str());
}
void AppendDefines(std::set<std::string>& defines,
- const std::vector<std::string> &defines_vec);
+ const std::vector<std::string>& defines_vec) const;
/**
* Join a set of defines into a definesString with a space separator.
*/
void JoinDefines(const std::set<std::string>& defines,
- std::string &definesString,
- const char* lang);
+ std::string& definesString, const std::string& lang);
/** Lookup and append options associated with a particular feature. */
- void AppendFeatureOptions(std::string& flags, const char* lang,
+ void AppendFeatureOptions(std::string& flags, const std::string& lang,
const char* feature);
+ const char* GetFeature(const std::string& feature,
+ const std::string& config);
+
/** \brief Get absolute path to dependency \a name
*
* Translate a dependency as given in CMake code to the name to
@@ -193,121 +189,52 @@ public:
* the source directory of this generator. This should only be
* used for dependencies of custom commands.
*/
- bool GetRealDependency(const char* name, const char* config,
+ bool GetRealDependency(const std::string& name, const std::string& config,
std::string& dep);
- ///! for existing files convert to output path and short path if spaces
- std::string ConvertToOutputForExisting(const char* remote,
- RelativeRoot local = START_OUTPUT);
-
- /** For existing path identified by RelativeRoot convert to output
- path and short path if spaces. */
- std::string ConvertToOutputForExisting(RelativeRoot remote,
- const char* local = 0);
-
- virtual std::string ConvertToIncludeReference(std::string const& path);
+ virtual std::string ConvertToIncludeReference(
+ std::string const& path,
+ cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
+ bool forceFullPaths = false);
/** Called from command-line hook to clear dependencies. */
- virtual void ClearDependencies(cmMakefile* /* mf */,
- bool /* verbose */) {}
+ virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {}
/** Called from command-line hook to update dependencies. */
- virtual bool UpdateDependencies(const char* /* tgtInfo */,
- bool /*verbose*/,
+ virtual bool UpdateDependencies(const char* /* tgtInfo */, bool /*verbose*/,
bool /*color*/)
- { return true; }
+ {
+ return true;
+ }
/** Get the include flags for the current makefile and language. */
void GetIncludeDirectories(std::vector<std::string>& dirs,
- cmGeneratorTarget* target,
- const char* lang = "C", const char *config = 0,
- bool stripImplicitInclDirs = true);
- void AddCompileOptions(std::string& flags, cmTarget* target,
- const char* lang, const char* config);
- void AddCompileDefinitions(std::set<std::string>& defines, cmTarget* target,
- const char* config);
+ cmGeneratorTarget const* target,
+ const std::string& lang = "C",
+ const std::string& config = "",
+ bool stripImplicitInclDirs = true) 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;
+
+ std::string GetProjectName() const;
/** Compute the language used to compile the given source file. */
- const char* GetSourceFileLanguage(const cmSourceFile& source);
+ std::string GetSourceFileLanguage(const cmSourceFile& source);
// Fill the vector with the target names for the object files,
// preprocessed files and assembly files.
- virtual void GetIndividualFileTargets(std::vector<std::string>&) {}
-
- // Create a struct to hold the varibles passed into
- // ExpandRuleVariables
- struct RuleVariables
- {
- RuleVariables()
- {
- memset(this, 0, sizeof(*this));
- }
- cmTarget* CMTarget;
- const char* TargetPDB;
- const char* TargetVersionMajor;
- const char* TargetVersionMinor;
- const char* Language;
- const char* Objects;
- const char* Target;
- const char* LinkLibraries;
- const char* Source;
- const char* AssemblySource;
- const char* PreprocessedSource;
- const char* Output;
- const char* Object;
- const char* ObjectDir;
- const char* Flags;
- const char* ObjectsQuoted;
- const char* SONameFlag;
- const char* TargetSOName;
- const char* TargetInstallNameDir;
- const char* LinkFlags;
- const char* LanguageCompileFlags;
- const char* Defines;
- const char* RuleLauncher;
- const char* DependencyFile;
- };
-
- /** Set whether to treat conversions to SHELL as a link script shell. */
- void SetLinkScriptShell(bool b) { this->LinkScriptShell = b; }
-
- /** Escape the given string to be used as a command line argument in
- the native build system shell. Optionally allow the build
- system to replace make variable references. Optionally adjust
- escapes for the special case of passing to the native echo
- command. */
- std::string EscapeForShell(const char* str, bool makeVars = false,
- bool forEcho = false);
-
- /** Backwards-compatibility version of EscapeForShell. */
- std::string EscapeForShellOldStyle(const char* str);
-
- /** Escape the given string as an argument in a CMake script. */
- static std::string EscapeForCMake(const char* str);
-
- enum FortranFormat
- {
- FortranFormatNone,
- FortranFormatFixed,
- FortranFormatFree
- };
- FortranFormat GetFortranFormat(const char* value);
-
- /**
- * Convert the given remote path to a relative path with respect to
- * the given local path. The local path must be given in component
- * form (see SystemTools::SplitPath) without a trailing slash. The
- * remote path must use forward slashes and not already be escaped
- * or quoted.
- */
- std::string ConvertToRelativePath(const std::vector<std::string>& local,
- const char* remote, bool force=false);
+ void GetIndividualFileTargets(std::vector<std::string>&) {}
/**
* Get the relative path from the generator output directory to a
* per-target support directory.
*/
- virtual std::string GetTargetDirectory(cmTarget const& target) const;
+ virtual std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const;
/**
* Get the level of backwards compatibility requested by the project
@@ -319,157 +246,143 @@ public:
*
* and is monotonically increasing with the CMake version.
*/
- unsigned int GetBackwardsCompatibility();
+ KWIML_INT_uint64_t GetBackwardsCompatibility();
/**
* Test whether compatibility is set to a given version or lower.
*/
- bool NeedBackwardsCompatibility(unsigned int major,
- unsigned int minor,
- unsigned int patch = 0xFFu);
+ bool NeedBackwardsCompatibility_2_4();
+
+ cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
+
+ cmake* GetCMakeInstance() const;
+
+ const char* GetSourceDirectory() const;
+ const char* GetBinaryDirectory() const;
+
+ const char* GetCurrentBinaryDirectory() const;
+ const char* GetCurrentSourceDirectory() const;
/**
* Generate a Mac OS X application bundle Info.plist file.
*/
- void GenerateAppleInfoPList(cmTarget* target, const char* targetName,
+ void GenerateAppleInfoPList(cmGeneratorTarget* target,
+ const std::string& targetName,
const char* fname);
/**
* Generate a Mac OS X framework Info.plist file.
*/
- void GenerateFrameworkInfoPList(cmTarget* target,
- const char* targetName,
+ void GenerateFrameworkInfoPList(cmGeneratorTarget* target,
+ const std::string& targetName,
const char* fname);
/** Construct a comment for a custom command. */
- std::string ConstructComment(const cmCustomCommand& cc,
+ 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 = 0);
+ std::string GetObjectFileNameWithoutTarget(
+ const cmSourceFile& source, std::string const& dir_max,
+ bool* hasSourceExtension = CM_NULLPTR,
+ char const* customOutputExtension = CM_NULLPTR);
/** Fill out the static linker flags for the given target. */
- void GetStaticLibraryFlags(std::string& flags,
- std::string const& config,
- cmTarget* target);
+ void GetStaticLibraryFlags(std::string& flags, std::string const& config,
+ cmGeneratorTarget* target);
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
- void GetTargetFlags(std::string& linkLibs,
- std::string& flags,
- std::string& linkFlags,
- std::string& frameworkPath,
- std::string& linkPath,
+ void GetTargetFlags(cmLinkLineComputer* linkLineComputer,
+ const std::string& config, std::string& linkLibs,
+ std::string& flags, std::string& linkFlags,
+ std::string& frameworkPath, std::string& linkPath,
cmGeneratorTarget* target);
+ void GetTargetDefines(cmGeneratorTarget const* target,
+ std::string const& config, std::string const& lang,
+ std::set<std::string>& defines) const;
+ void GetTargetCompileFlags(cmGeneratorTarget* target,
+ std::string const& config,
+ std::string const& lang, std::string& flags);
+
+ std::string GetFrameworkFlags(std::string const& l,
+ std::string const& config,
+ cmGeneratorTarget* target);
+ virtual std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
+ std::string const& config);
+
+ virtual void ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt = CM_NULLPTR);
+
+ bool IsWindowsShell() const;
+ bool IsWatcomWMake() const;
+ bool IsMinGWMake() const;
+ bool IsNMake() const;
+
+ void IssueMessage(cmake::MessageType t, std::string const& text) const;
+
+ void CreateEvaluationFileOutputs(const std::string& config);
+ void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
+
+ const char* GetRuleLauncher(cmGeneratorTarget* target,
+ const std::string& prop);
protected:
///! put all the libraries for a target on into the given stream
- virtual void OutputLinkLibraries(std::string& linkLibraries,
- std::string& frameworkPath,
- std::string& linkPath,
- cmGeneratorTarget &,
- bool relink);
-
- // Expand rule variables in CMake of the type found in language rules
- void ExpandRuleVariables(std::string& string,
- const RuleVariables& replaceValues);
- // Expand rule variables in a single string
- std::string ExpandRuleVariable(std::string const& variable,
- const RuleVariables& replaceValues);
-
- const char* GetRuleLauncher(cmTarget* target, const char* prop);
- void InsertRuleLauncher(std::string& s, cmTarget* target,
- const char* prop);
-
-
- /** Convert a target to a utility target for unsupported
- * languages of a generator */
- void AddBuildTargetRule(const char* llang, cmGeneratorTarget& target);
- ///! add a custom command to build a .o file that is part of a target
- void AddCustomCommandToCreateObject(const char* ofname,
- const char* lang,
- cmSourceFile& source,
- cmGeneratorTarget& target);
- // Create Custom Targets and commands for unsupported languages
- // The set passed in should contain the languages supported by the
- // generator directly. Any targets containing files that are not
- // of the types listed will be compiled as custom commands and added
- // to a custom target.
- void CreateCustomTargetsAndCommands(std::set<cmStdString> const&);
+ void OutputLinkLibraries(cmComputeLinkInformation* pcli,
+ cmLinkLineComputer* linkLineComputer,
+ std::string& linkLibraries,
+ std::string& frameworkPath, std::string& linkPath);
// Handle old-style install rules stored in the targets.
void GenerateTargetInstallRules(
- std::ostream& os, const char* config,
+ std::ostream& os, const std::string& config,
std::vector<std::string> const& configurationTypes);
- std::string& CreateSafeUniqueObjectFileName(const char* sin,
+ std::string& CreateSafeUniqueObjectFileName(const std::string& sin,
std::string const& dir_max);
- void ComputeObjectMaxPath();
-
- void ConfigureRelativePaths();
- std::string FindRelativePathTopSource();
- std::string FindRelativePathTopBinary();
- void SetupPathConversions();
-
- virtual std::string ConvertToLinkReference(std::string const& lib);
/** Check whether the native build system supports the given
definition. Issues a warning. */
virtual bool CheckDefinition(std::string const& define) const;
- /** Read the input CMakeLists.txt file. */
- void ReadInputFile();
-
- cmMakefile *Makefile;
- cmGlobalGenerator *GlobalGenerator;
- // members used for relative path function ConvertToMakefilePath
- std::string RelativePathToSourceDir;
- std::string RelativePathToBinaryDir;
- std::vector<std::string> HomeDirectoryComponents;
- std::vector<std::string> StartDirectoryComponents;
- std::vector<std::string> HomeOutputDirectoryComponents;
- std::vector<std::string> StartOutputDirectoryComponents;
- cmLocalGenerator* Parent;
- std::vector<cmLocalGenerator*> Children;
- std::map<cmStdString, cmStdString> UniqueObjectNamesMap;
+ cmMakefile* Makefile;
+ cmStateSnapshot StateSnapshot;
+ cmListFileBacktrace DirectoryBacktrace;
+ cmGlobalGenerator* GlobalGenerator;
+ std::map<std::string, std::string> UniqueObjectNamesMap;
std::string::size_type ObjectPathMax;
- std::set<cmStdString> ObjectMaxPathViolations;
- bool WindowsShell;
- bool WindowsVSIDE;
- bool WatcomWMake;
- bool MinGWMake;
- bool NMake;
- bool ForceUnixPath;
- bool MSYSShell;
- bool LinkScriptShell;
- bool UseRelativePaths;
- bool IgnoreLibPrefix;
- bool Configured;
+ std::set<std::string> ObjectMaxPathViolations;
+
+ std::set<cmGeneratorTarget const*> WarnCMP0063;
+ std::vector<cmGeneratorTarget*> GeneratorTargets;
+ std::vector<cmGeneratorTarget*> ImportedGeneratorTargets;
+ std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets;
+ std::map<std::string, std::string> AliasTargets;
+
+ std::map<std::string, std::string> Compilers;
+ std::map<std::string, std::string> VariableMappings;
+ std::string CompilerSysroot;
+ std::string LinkerSysroot;
+
bool EmitUniversalBinaryFlags;
- // Hack for ExpandRuleVariable until object-oriented version is
- // committed.
- std::string TargetImplib;
-
- // The top-most directories for relative path conversion. Both the
- // source and destination location of a relative path conversion
- // must be underneath one of these directories (both under source or
- // both under binary) in order for the relative path to be evaluated
- // safely by the build tools.
- std::string RelativePathTopSource;
- std::string RelativePathTopBinary;
- bool RelativePathsConfigured;
- bool PathConversionsSetup;
-
- unsigned int BackwardsCompatibility;
+
+ KWIML_INT_uint64_t BackwardsCompatibility;
bool BackwardsCompatibilityFinal;
-private:
- std::string ConvertToOutputForExistingCommon(const char* remote,
- std::string const& result);
- void AddSharedFlags(std::string& flags, const char* lang, bool shared);
- bool GetShouldUseOldFlags(bool shared, const std::string &lang) const;
+private:
+ void AddSharedFlags(std::string& flags, const std::string& lang,
+ bool shared);
+ bool GetShouldUseOldFlags(bool shared, const std::string& lang) const;
void AddPositionIndependentFlags(std::string& flags, std::string const& l,
int targetType);
+
+ void ComputeObjectMaxPath();
};
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+bool cmLocalGeneratorCheckObjectName(std::string& objName,
+ std::string::size_type dir_len,
+ std::string::size_type max_total_len);
+#endif
+
#endif
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
new file mode 100644
index 000000000..5f37af528
--- /dev/null
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -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. */
+#include "cmLocalGhsMultiGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGhsMultiTargetGenerator.h"
+#include "cmGlobalGhsMultiGenerator.h"
+#include "cmMakefile.h"
+
+cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg,
+ cmMakefile* mf)
+ : cmLocalGenerator(gg, mf)
+{
+}
+
+cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator()
+{
+}
+
+void cmLocalGhsMultiGenerator::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;
+ }
+ cmGhsMultiTargetGenerator tg(*l);
+ tg.Generate();
+ }
+}
diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h
new file mode 100644
index 000000000..aa842d74b
--- /dev/null
+++ b/Source/cmLocalGhsMultiGenerator.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 cmLocalGhsMultiGenerator_h
+#define cmLocalGhsMultiGenerator_h
+
+#include "cmLocalGenerator.h"
+
+class cmGeneratedFileStream;
+
+/** \class cmLocalGhsMultiGenerator
+ * \brief Write Green Hills MULTI project files.
+ *
+ * cmLocalGhsMultiGenerator produces a set of .gpj
+ * file for each target in its mirrored directory.
+ */
+class cmLocalGhsMultiGenerator : public cmLocalGenerator
+{
+public:
+ cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
+
+ virtual ~cmLocalGhsMultiGenerator();
+
+ /**
+ * Generate the makefile for this directory.
+ */
+ virtual void Generate();
+};
+
+#endif
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index a522e37e2..266710cb1 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -1,100 +1,111 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalNinjaGenerator.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+#include <sstream>
+#include <stdio.h>
+#include <utility>
+
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
-#include "cmMakefile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmMakefile.h"
#include "cmNinjaTargetGenerator.h"
-#include "cmGeneratedFileStream.h"
+#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmComputeLinkInformation.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
#include "cmake.h"
-#include <assert.h>
-
-cmLocalNinjaGenerator::cmLocalNinjaGenerator()
- : cmLocalGenerator()
- , ConfigName("")
+cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
+ cmMakefile* mf)
+ : cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory())
, HomeRelativeOutputPath("")
{
-#ifdef _WIN32
- this->WindowsShell = true;
-#endif
- this->TargetImplib = "$TARGET_IMPLIB";
}
-//----------------------------------------------------------------------------
// Virtual public methods.
+cmRulePlaceholderExpander*
+cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const
+{
+ cmRulePlaceholderExpander* ret =
+ new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
+ this->CompilerSysroot, this->LinkerSysroot);
+ ret->SetTargetImpLib("$TARGET_IMPLIB");
+ return ret;
+}
+
cmLocalNinjaGenerator::~cmLocalNinjaGenerator()
{
}
void cmLocalNinjaGenerator::Generate()
{
- this->SetConfigName();
+ // Compute the path to use when referencing the current output
+ // directory from the top output directory.
+ this->HomeRelativeOutputPath = this->ConvertToRelativePath(
+ this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+ if (this->HomeRelativeOutputPath == ".") {
+ this->HomeRelativeOutputPath = "";
+ }
this->WriteProcessedMakefile(this->GetBuildFileStream());
#ifdef NINJA_GEN_VERBOSE_FILES
this->WriteProcessedMakefile(this->GetRulesFileStream());
#endif
- this->WriteBuildFileTop();
+ // We do that only once for the top CMakeLists.txt file.
+ if (this->IsRootMakefile()) {
+ this->WriteBuildFileTop();
+
+ this->WritePools(this->GetRulesFileStream());
+
+ 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";
+ }
+ }
- cmTargets& targets = this->GetMakefile()->GetTargets();
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(&t->second);
- if(tg)
- {
+ std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+ t != targets.end(); ++t) {
+ if ((*t)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+ cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(*t);
+ if (tg) {
tg->Generate();
// Add the target to "all" if required.
if (!this->GetGlobalNinjaGenerator()->IsExcluded(
- this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0],
- t->second))
- this->GetGlobalNinjaGenerator()->AddDependencyToAll(&t->second);
- delete tg;
+ this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0], *t)) {
+ this->GetGlobalNinjaGenerator()->AddDependencyToAll(*t);
}
+ delete tg;
}
+ }
this->WriteCustomCommandBuildStatements();
}
-// Implemented in:
-// cmLocalUnixMakefileGenerator3.
-// Used in:
-// Source/cmMakefile.cxx
-// Source/cmGlobalGenerator.cxx
-void cmLocalNinjaGenerator::Configure()
-{
- // Compute the path to use when referencing the current output
- // directory from the top output directory.
- this->HomeRelativeOutputPath =
- this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT);
- if(this->HomeRelativeOutputPath == ".")
- {
- this->HomeRelativeOutputPath = "";
- }
- this->cmLocalGenerator::Configure();
-
-}
-
// TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it.
-std::string cmLocalNinjaGenerator
-::GetTargetDirectory(cmTarget const& target) const
+std::string cmLocalNinjaGenerator::GetTargetDirectory(
+ cmGeneratorTarget const* target) const
{
std::string dir = cmake::GetCMakeFilesDirectoryPostSlash();
- dir += target.GetName();
+ dir += target->GetName();
#if defined(__VMS)
dir += "_dir";
#else
@@ -103,14 +114,13 @@ std::string cmLocalNinjaGenerator
return dir;
}
-//----------------------------------------------------------------------------
// Non-virtual public methods.
-const cmGlobalNinjaGenerator*
-cmLocalNinjaGenerator::GetGlobalNinjaGenerator() const
+const cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
+ const
{
- return
- static_cast<const cmGlobalNinjaGenerator*>(this->GetGlobalGenerator());
+ return static_cast<const cmGlobalNinjaGenerator*>(
+ this->GetGlobalGenerator());
}
cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
@@ -118,22 +128,20 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
return static_cast<cmGlobalNinjaGenerator*>(this->GetGlobalGenerator());
}
-//----------------------------------------------------------------------------
// Virtual protected methods.
-std::string
-cmLocalNinjaGenerator::ConvertToLinkReference(std::string const& lib)
-{
- return this->Convert(lib.c_str(), HOME_OUTPUT, SHELL);
-}
-
-std::string
-cmLocalNinjaGenerator::ConvertToIncludeReference(std::string const& path)
+std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
+ std::string const& path, cmOutputConverter::OutputFormat format,
+ bool forceFullPaths)
{
- return this->Convert(path.c_str(), HOME_OUTPUT, SHELL);
+ if (forceFullPaths) {
+ return this->ConvertToOutputFormat(cmSystemTools::CollapseFullPath(path),
+ format);
+ }
+ return this->ConvertToOutputFormat(
+ this->ConvertToRelativePath(this->GetBinaryDirectory(), path), format);
}
-//----------------------------------------------------------------------------
// Private methods.
cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const
@@ -156,20 +164,11 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance()
return this->GetGlobalGenerator()->GetCMakeInstance();
}
-bool cmLocalNinjaGenerator::isRootMakefile() const
-{
- return (strcmp(this->Makefile->GetCurrentDirectory(),
- this->GetCMakeInstance()->GetHomeDirectory()) == 0);
-}
-
void cmLocalNinjaGenerator::WriteBuildFileTop()
{
- // We do that only once for the top CMakeLists.txt file.
- if(!this->isRootMakefile())
- return;
-
// For the build file.
this->WriteProjectHeader(this->GetBuildFileStream());
+ this->WriteNinjaRequiredVersion(this->GetBuildFileStream());
this->WriteNinjaFilesInclusion(this->GetBuildFileStream());
// For the rule file.
@@ -179,196 +178,279 @@ void cmLocalNinjaGenerator::WriteBuildFileTop()
void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
- os
- << "# Project: " << this->GetMakefile()->GetProjectName() << std::endl
- << "# Configuration: " << this->ConfigName << std::endl
- ;
+ os << "# Project: " << this->GetProjectName() << std::endl
+ << "# Configuration: " << this->ConfigName << std::endl;
cmGlobalNinjaGenerator::WriteDivider(os);
}
+void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
+{
+ // Default required version
+ std::string requiredVersion =
+ this->GetGlobalNinjaGenerator()->RequiredNinjaVersion();
+
+ // Ninja generator uses the 'console' pool if available (>= 1.5)
+ if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) {
+ requiredVersion =
+ this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool();
+ }
+
+ cmGlobalNinjaGenerator::WriteComment(
+ os, "Minimal version of Ninja required by this file");
+ os << "ninja_required_version = " << requiredVersion << std::endl
+ << std::endl;
+}
+
+void cmLocalNinjaGenerator::WritePools(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+
+ const char* jobpools =
+ this->GetCMakeInstance()->GetState()->GetGlobalProperty("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];
+ const std::string::size_type eq = pool.find('=');
+ unsigned int jobs;
+ if (eq != std::string::npos &&
+ sscanf(pool.c_str() + eq, "=%u", &jobs) == 1) {
+ os << "pool " << pool.substr(0, eq) << std::endl;
+ os << " depth = " << jobs << std::endl;
+ os << std::endl;
+ } else {
+ cmSystemTools::Error("Invalid pool defined by property 'JOB_POOLS': ",
+ pool.c_str());
+ }
+ }
+ }
+}
+
void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
- os
- << "# Include auxiliary files.\n"
- << "\n"
- ;
- cmGlobalNinjaGenerator::WriteInclude(os,
- cmGlobalNinjaGenerator::NINJA_RULES_FILE,
+ os << "# Include auxiliary files.\n"
+ << "\n";
+ cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
+ std::string const ninjaRulesFile =
+ ng->NinjaOutputPath(cmGlobalNinjaGenerator::NINJA_RULES_FILE);
+ std::string const rulesFilePath =
+ ng->EncodeIdent(ng->EncodePath(ninjaRulesFile), os);
+ cmGlobalNinjaGenerator::WriteInclude(os, rulesFilePath,
"Include rules file.");
os << "\n";
}
-void cmLocalNinjaGenerator::SetConfigName()
+void cmLocalNinjaGenerator::ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt)
{
- // Store the configuration name that will be generated.
- if(const char* config =
- this->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE"))
- {
- // Use the build type given by the user.
- this->ConfigName = config;
- }
- else
- {
- // No configuration type given.
- this->ConfigName = "";
- }
+ // 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);
- os
- << "# Write statements declared in CMakeLists.txt:" << std::endl
- << "# " << this->Makefile->GetCurrentListFile() << std::endl
- ;
- if(this->isRootMakefile())
+ os << "# Write statements declared in CMakeLists.txt:" << std::endl
+ << "# " << this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE")
+ << std::endl;
+ if (this->IsRootMakefile()) {
os << "# Which is the root file." << std::endl;
+ }
cmGlobalNinjaGenerator::WriteDivider(os);
os << std::endl;
}
-std::string cmLocalNinjaGenerator::ConvertToNinjaPath(const char *path)
-{
- std::string convPath = this->Convert(path, cmLocalGenerator::HOME_OUTPUT);
-#ifdef _WIN32
- cmSystemTools::ReplaceString(convPath, "/", "\\");
-#endif
- return convPath;
-}
-
-void
-cmLocalNinjaGenerator
-::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
+void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target,
+ cmNinjaDeps& outputs)
{
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs);
}
-void
-cmLocalNinjaGenerator
-::AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs)
+void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target,
+ cmNinjaDeps& outputs,
+ cmNinjaTargetDepends depends)
{
- this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs);
+ this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs,
+ depends);
}
-void cmLocalNinjaGenerator::AppendCustomCommandDeps(const cmCustomCommand *cc,
- cmNinjaDeps &ninjaDeps)
+void cmLocalNinjaGenerator::AppendCustomCommandDeps(
+ cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps)
{
- const std::vector<std::string> &deps = cc->GetDepends();
+ const std::vector<std::string>& deps = ccg.GetDepends();
for (std::vector<std::string>::const_iterator i = deps.begin();
i != deps.end(); ++i) {
std::string dep;
- if (this->GetRealDependency(i->c_str(), this->GetConfigName(), dep))
- ninjaDeps.push_back(ConvertToNinjaPath(dep.c_str()));
+ if (this->GetRealDependency(*i, this->GetConfigName(), dep)) {
+ ninjaDeps.push_back(
+ this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep));
+ }
}
}
std::string cmLocalNinjaGenerator::BuildCommandLine(
- const std::vector<std::string> &cmdLines)
+ const std::vector<std::string>& cmdLines)
{
- // If we have no commands but we need to build a command anyway, use ":".
+ // 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
// don't use POST_BUILD.
- if (cmdLines.empty())
-#ifdef _WIN32
- return "cd .";
-#else
- return ":";
-#endif
+ if (cmdLines.empty()) {
+ return cmGlobalNinjaGenerator::SHELL_NOOP;
+ }
- cmOStringStream cmd;
+ std::ostringstream cmd;
for (std::vector<std::string>::const_iterator li = cmdLines.begin();
- li != cmdLines.end(); ++li) {
+ li != cmdLines.end(); ++li)
+#ifdef _WIN32
+ {
if (li != cmdLines.begin()) {
cmd << " && ";
-#ifdef _WIN32
} else if (cmdLines.size() > 1) {
- cmd << "cmd.exe /c ";
-#endif
+ cmd << "cmd.exe /C \"";
+ }
+ // Put current cmdLine in brackets if it contains "||" because it has
+ // higher precedence than "&&" in cmd.exe
+ if (li->find("||") != std::string::npos) {
+ cmd << "( " << *li << " )";
+ } else {
+ cmd << *li;
+ }
+ }
+ if (cmdLines.size() > 1) {
+ cmd << "\"";
+ }
+#else
+ {
+ if (li != cmdLines.begin()) {
+ cmd << " && ";
}
cmd << *li;
}
+#endif
return cmd.str();
}
-void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
- std::vector<std::string> &cmdLines)
+void cmLocalNinjaGenerator::AppendCustomCommandLines(
+ cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines)
{
- cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
if (ccg.GetNumberOfCommands() > 0) {
- const char* wd = cc->GetWorkingDirectory();
- if (!wd)
- wd = this->GetMakefile()->GetStartOutputDirectory();
+ std::string wd = ccg.GetWorkingDirectory();
+ if (wd.empty()) {
+ wd = this->GetCurrentBinaryDirectory();
+ }
- cmOStringStream cdCmd;
+ std::ostringstream cdCmd;
#ifdef _WIN32
- std::string cdStr = "cd /D ";
+ std::string cdStr = "cd /D ";
#else
- std::string cdStr = "cd ";
+ std::string cdStr = "cd ";
#endif
- cdCmd << cdStr << this->ConvertToOutputFormat(wd, SHELL);
+ cdCmd << cdStr
+ << this->ConvertToOutputFormat(wd, cmOutputConverter::SHELL);
cmdLines.push_back(cdCmd.str());
}
+
+ std::string launcher = this->MakeCustomLauncher(ccg);
+
for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
- cmdLines.push_back(this->ConvertToOutputFormat(ccg.GetCommand(i).c_str(),
- SHELL));
+ cmdLines.push_back(launcher +
+ this->ConvertToOutputFormat(ccg.GetCommand(i),
+ cmOutputConverter::SHELL));
+
std::string& cmd = cmdLines.back();
ccg.AppendArguments(i, cmd);
}
}
-void
-cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
- cmCustomCommand const *cc, const cmNinjaDeps& orderOnlyDeps)
+void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
+ cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps)
{
- if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc))
+ if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc)) {
return;
+ }
+
+ cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this);
- const std::vector<std::string> &outputs = cc->GetOutputs();
- cmNinjaDeps ninjaOutputs(outputs.size()), ninjaDeps;
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ const std::vector<std::string>& byproducts = ccg.GetByproducts();
+ cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size()), ninjaDeps;
- std::transform(outputs.begin(), outputs.end(),
- ninjaOutputs.begin(), MapToNinjaPath());
- this->AppendCustomCommandDeps(cc, 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");
+ }
+ }
+
+#if 0
+#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
+ std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(),
+ this->GetGlobalNinjaGenerator()->MapToNinjaPath());
+ std::transform(byproducts.begin(), byproducts.end(),
+ ninjaOutputs.begin() + outputs.size(),
+ this->GetGlobalNinjaGenerator()->MapToNinjaPath());
+ this->AppendCustomCommandDeps(ccg, ninjaDeps);
for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
- ++i)
+ ++i) {
this->GetGlobalNinjaGenerator()->SeenCustomCommandOutput(*i);
+ }
std::vector<std::string> cmdLines;
- this->AppendCustomCommandLines(cc, cmdLines);
+ this->AppendCustomCommandLines(ccg, cmdLines);
if (cmdLines.empty()) {
this->GetGlobalNinjaGenerator()->WritePhonyBuild(
this->GetBuildFileStream(),
- "Phony custom command for " +
- ninjaOutputs[0],
- ninjaOutputs,
- ninjaDeps,
- cmNinjaDeps(),
- orderOnlyDeps,
- cmNinjaVars());
+ "Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps,
+ cmNinjaDeps(), orderOnlyDeps, cmNinjaVars());
} else {
this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines),
- this->ConstructComment(*cc),
- "Custom command for " + ninjaOutputs[0],
- ninjaOutputs,
- ninjaDeps,
+ this->BuildCommandLine(cmdLines), this->ConstructComment(ccg),
+ "Custom command for " + ninjaOutputs[0], cc->GetDepfile(),
+ cc->GetUsesTerminal(),
+ /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
orderOnlyDeps);
}
}
void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
- cmTarget* target)
+ cmGeneratorTarget* target)
{
- this->CustomCommandTargets[cc].insert(target);
+ CustomCommandTargetMap::value_type v(cc, std::set<cmGeneratorTarget*>());
+ std::pair<CustomCommandTargetMap::iterator, bool> ins =
+ this->CustomCommandTargets.insert(v);
+ if (ins.second) {
+ this->CustomCommands.push_back(cc);
+ }
+ ins.first->second.insert(target);
}
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
{
- for (CustomCommandTargetMap::iterator i = this->CustomCommandTargets.begin();
- i != this->CustomCommandTargets.end(); ++i) {
+ for (std::vector<cmCustomCommand const*>::iterator vi =
+ this->CustomCommands.begin();
+ vi != this->CustomCommands.end(); ++vi) {
+ CustomCommandTargetMap::iterator i = this->CustomCommandTargets.find(*vi);
+ assert(i != this->CustomCommandTargets.end());
+
// A custom command may appear on multiple targets. However, some build
// systems exist where the target dependencies on some of the targets are
// overspecified, leading to a dependency cycle. If we assume all target
@@ -378,16 +460,17 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
//
// FIXME: This won't work in certain obscure scenarios involving indirect
// dependencies.
- std::set<cmTarget*>::iterator j = i->second.begin();
+ std::set<cmGeneratorTarget*>::iterator j = i->second.begin();
assert(j != i->second.end());
std::vector<std::string> ccTargetDeps;
- this->AppendTargetDepends(*j, ccTargetDeps);
+ this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j,
+ ccTargetDeps);
std::sort(ccTargetDeps.begin(), ccTargetDeps.end());
++j;
for (; j != i->second.end(); ++j) {
std::vector<std::string> jDeps, depsIntersection;
- this->AppendTargetDepends(*j, jDeps);
+ this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps);
std::sort(jDeps.begin(), jDeps.end());
std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
jDeps.begin(), jDeps.end(),
@@ -398,3 +481,43 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps);
}
}
+
+std::string cmLocalNinjaGenerator::MakeCustomLauncher(
+ cmCustomCommandGenerator const& ccg)
+{
+ const char* property_value =
+ this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM");
+
+ if (!property_value || !*property_value) {
+ return std::string();
+ }
+
+ // Expand rules in the empty string. It may insert the launcher and
+ // perform replacements.
+ cmRulePlaceholderExpander::RuleVariables vars;
+
+ std::string output;
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ if (!outputs.empty()) {
+ output = outputs[0];
+ if (ccg.GetWorkingDirectory().empty()) {
+ output =
+ this->ConvertToRelativePath(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(
+ this->CreateRulePlaceholderExpander());
+
+ rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
+ if (!launcher.empty()) {
+ launcher += " ";
+ }
+
+ return launcher;
+}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index c450841af..a45e01851 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -1,23 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalNinjaGenerator_h
-# define cmLocalNinjaGenerator_h
+#define cmLocalNinjaGenerator_h
-# include "cmLocalGenerator.h"
-# include "cmNinjaTypes.h"
+#include "cmConfigure.h"
-class cmGlobalNinjaGenerator;
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cmLocalCommonGenerator.h"
+#include "cmNinjaTypes.h"
+#include "cmOutputConverter.h"
+
+class cmCustomCommand;
+class cmCustomCommandGenerator;
class cmGeneratedFileStream;
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmGlobalNinjaGenerator;
+class cmMakefile;
+class cmRulePlaceholderExpander;
+class cmSourceFile;
class cmake;
/**
@@ -27,82 +33,56 @@ class cmake;
* cmLocalNinjaGenerator produces a local build.ninja file from its
* member Makefile.
*/
-class cmLocalNinjaGenerator : public cmLocalGenerator
+class cmLocalNinjaGenerator : public cmLocalCommonGenerator
{
public:
- /// Default constructor.
- cmLocalNinjaGenerator();
+ cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
- /// Destructor.
- virtual ~cmLocalNinjaGenerator();
+ ~cmLocalNinjaGenerator() CM_OVERRIDE;
- /// Overloaded methods. @see cmLocalGenerator::Generate()
- virtual void Generate();
+ void Generate() CM_OVERRIDE;
- /// Overloaded methods. @see cmLocalGenerator::Configure()
- virtual void Configure();
+ cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const CM_OVERRIDE;
- /// Overloaded methods. @see cmLocalGenerator::GetTargetDirectory()
- virtual std::string GetTargetDirectory(cmTarget const& target) const;
+ std::string GetTargetDirectory(cmGeneratorTarget const* target) const
+ CM_OVERRIDE;
const cmGlobalNinjaGenerator* GetGlobalNinjaGenerator() const;
cmGlobalNinjaGenerator* GetGlobalNinjaGenerator();
- /**
- * Shortcut to get the cmake instance throw the global generator.
- * @return an instance of the cmake object.
- */
const cmake* GetCMakeInstance() const;
cmake* GetCMakeInstance();
- const char* GetConfigName() const
- { return this->ConfigName.c_str(); }
-
- /// @return whether we are processing the top CMakeLists.txt file.
- bool isRootMakefile() const;
-
/// @returns the relative path between the HomeOutputDirectory and this
/// local generators StartOutputDirectory.
std::string GetHomeRelativeOutputPath() const
- { return this->HomeRelativeOutputPath; }
-
- std::string ConvertToNinjaPath(const char *path);
-
- struct map_to_ninja_path {
- cmLocalNinjaGenerator *LocalGenerator;
- map_to_ninja_path(cmLocalNinjaGenerator *LocalGen)
- : LocalGenerator(LocalGen) {}
- std::string operator()(const std::string &path) {
- return LocalGenerator->ConvertToNinjaPath(path.c_str());
- }
- };
-
- map_to_ninja_path MapToNinjaPath() {
- return map_to_ninja_path(this);
- }
-
- void ExpandRuleVariables(std::string& string,
- const RuleVariables& replaceValues) {
- cmLocalGenerator::ExpandRuleVariables(string, replaceValues);
+ {
+ return this->HomeRelativeOutputPath;
}
- std::string BuildCommandLine(const std::vector<std::string> &cmdLines);
+ std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
- void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
- void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
+ void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
+ void AppendTargetDepends(
+ cmGeneratorTarget* target, cmNinjaDeps& outputs,
+ cmNinjaTargetDepends depends = DependOnTargetArtifact);
- void AddCustomCommandTarget(cmCustomCommand const* cc, cmTarget* target);
- void AppendCustomCommandLines(const cmCustomCommand *cc,
- std::vector<std::string> &cmdLines);
- void AppendCustomCommandDeps(const cmCustomCommand *cc,
- cmNinjaDeps &ninjaDeps);
-
- virtual std::string ConvertToLinkReference(std::string const& lib);
+ void AddCustomCommandTarget(cmCustomCommand const* cc,
+ cmGeneratorTarget* target);
+ void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg,
+ std::vector<std::string>& cmdLines);
+ void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
+ cmNinjaDeps& ninjaDeps);
+ void ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt = CM_NULLPTR) CM_OVERRIDE;
protected:
- virtual std::string ConvertToIncludeReference(std::string const& path);
-
+ std::string ConvertToIncludeReference(
+ std::string const& path,
+ cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
+ bool forceFullPaths = false) CM_OVERRIDE;
private:
cmGeneratedFileStream& GetBuildFileStream() const;
@@ -110,24 +90,25 @@ private:
void WriteBuildFileTop();
void WriteProjectHeader(std::ostream& os);
+ void WriteNinjaRequiredVersion(std::ostream& os);
void WriteNinjaFilesInclusion(std::ostream& os);
void WriteProcessedMakefile(std::ostream& os);
-
- void SetConfigName();
+ void WritePools(std::ostream& os);
void WriteCustomCommandRule();
- void WriteCustomCommandBuildStatement(cmCustomCommand const *cc,
+ void WriteCustomCommandBuildStatement(cmCustomCommand const* cc,
const cmNinjaDeps& orderOnlyDeps);
void WriteCustomCommandBuildStatements();
+ std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
- std::string ConfigName;
std::string HomeRelativeOutputPath;
- typedef std::map<cmCustomCommand const*, std::set<cmTarget*> >
+ typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*> >
CustomCommandTargetMap;
CustomCommandTargetMap CustomCommandTargets;
+ std::vector<cmCustomCommand const*> CustomCommands;
};
#endif // ! cmLocalNinjaGenerator_h
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 56da1f936..9b9d22cf5 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1,93 +1,97 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 <sstream>
+#include <stdio.h>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandGenerator.h"
+#include "cmFileTimeComparison.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmake.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cmFileTimeComparison.h"
-#include "cmCustomCommandGenerator.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"
-# include <cmsys/Terminal.h>
+#include "cmDependsFortran.h"
+#include "cmDependsJava.h"
#endif
-#include <cmsys/auto_ptr.hxx>
-
-#include <queue>
-
-//----------------------------------------------------------------------------
// Escape special characters in Makefile dependency lines
class cmMakeSafe
{
public:
- cmMakeSafe(const char* s): Data(s) {}
- cmMakeSafe(std::string const& s): Data(s.c_str()) {}
+ cmMakeSafe(const char* s)
+ : Data(s)
+ {
+ }
+ cmMakeSafe(std::string const& s)
+ : Data(s.c_str())
+ {
+ }
+
private:
const char* Data;
- friend std::ostream& operator<<(std::ostream& os,
- cmMakeSafe const& self)
- {
- for(const char* c = self.Data; *c; ++c)
- {
- switch (*c)
- {
- case '=': os << "$(EQUALS)"; break;
- default: os << *c; break;
- }
+ friend std::ostream& operator<<(std::ostream& os, cmMakeSafe const& self)
+ {
+ for (const char* c = self.Data; *c; ++c) {
+ switch (*c) {
+ case '=':
+ os << "$(EQUALS)";
+ break;
+ default:
+ os << *c;
+ break;
}
- return os;
}
+ return os;
+ }
};
-//----------------------------------------------------------------------------
// Helper function used below.
static std::string cmSplitExtension(std::string const& in, std::string& base)
{
std::string ext;
- std::string::size_type dot_pos = in.rfind(".");
- if(dot_pos != std::string::npos)
- {
+ std::string::size_type dot_pos = in.rfind('.');
+ if (dot_pos != std::string::npos) {
// Remove the extension first in case &base == &in.
- ext = in.substr(dot_pos, std::string::npos);
+ ext = in.substr(dot_pos);
base = in.substr(0, dot_pos);
- }
- else
- {
+ } else {
base = in;
- }
+ }
return ext;
}
-//----------------------------------------------------------------------------
-cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
+cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
+ cmGlobalGenerator* gg, cmMakefile* mf)
+ : cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory())
{
- this->SilentNoColon = false;
- this->WindowsShell = false;
- this->IncludeDirective = "include";
this->MakefileVariableSize = 0;
- this->IgnoreLibPrefix = false;
- this->PassMakeflags = false;
- this->DefineWindowsNULL = false;
- this->UnixCD = true;
this->ColorMakefile = false;
this->SkipPreprocessedSourceRules = false;
this->SkipAssemblySourceRules = false;
@@ -95,69 +99,38 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
this->BorlandMakeCurlyHack = false;
}
-//----------------------------------------------------------------------------
cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3()
{
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3::Configure()
-{
- // Compute the path to use when referencing the current output
- // directory from the top output directory.
- this->HomeRelativeOutputPath =
- this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT);
- if(this->HomeRelativeOutputPath == ".")
- {
- this->HomeRelativeOutputPath = "";
- }
- if(!this->HomeRelativeOutputPath.empty())
- {
- this->HomeRelativeOutputPath += "/";
- }
- this->cmLocalGenerator::Configure();
-}
-
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::Generate()
{
- // Store the configuration name that will be generated.
- if(const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"))
- {
- // Use the build type given by the user.
- this->ConfigurationName = config;
- }
- else
- {
- // No configuration type given.
- this->ConfigurationName = "";
- }
-
// Record whether some options are enabled to avoid checking many
// times later.
- if(!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile())
- {
+ if (!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) {
this->ColorMakefile = this->Makefile->IsOn("CMAKE_COLOR_MAKEFILE");
- }
+ }
this->SkipPreprocessedSourceRules =
this->Makefile->IsOn("CMAKE_SKIP_PREPROCESSED_SOURCE_RULES");
this->SkipAssemblySourceRules =
this->Makefile->IsOn("CMAKE_SKIP_ASSEMBLY_SOURCE_RULES");
// Generate the rule files for each target.
- cmTargets& targets = this->Makefile->GetTargets();
+ std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- cmsys::auto_ptr<cmMakefileTargetGenerator> tg(
- cmMakefileTargetGenerator::New(&(t->second)));
- if (tg.get())
- {
+ for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+ t != targets.end(); ++t) {
+ if ((*t)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+ CM_AUTO_PTR<cmMakefileTargetGenerator> tg(
+ cmMakefileTargetGenerator::New(*t));
+ if (tg.get()) {
tg->WriteRuleFiles();
gg->RecordTargetProgress(tg.get());
- }
}
+ }
// write the local Makefile
this->WriteLocalMakefile();
@@ -166,45 +139,94 @@ void cmLocalUnixMakefileGenerator3::Generate()
this->WriteDirectoryInformationFile();
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3::AddLocalObjectFile(
- cmTarget* target, cmSourceFile* sf, std::string objNoTargetDir,
- bool hasSourceExtension)
+void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
+{
+ // Compute the path to use when referencing the current output
+ // directory from the top output directory.
+ this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+ if (this->HomeRelativeOutputPath == ".") {
+ this->HomeRelativeOutputPath = "";
+ }
+ 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)
{
- if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
- {
- objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
+ std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
+ ti != targets.end(); ++ti) {
+ cmGeneratorTarget* gt = *ti;
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+ std::vector<cmSourceFile const*> objectSources;
+ gt->GetObjectSources(
+ objectSources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
+ // Compute full path to object file directory for this target.
+ std::string dir;
+ dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
+ dir += "/";
+ dir += this->GetTargetDirectory(gt);
+ dir += "/";
+ // Compute the name of each object file.
+ for (std::vector<cmSourceFile const*>::iterator si = objectSources.begin();
+ si != objectSources.end(); ++si) {
+ cmSourceFile const* sf = *si;
+ bool hasSourceExtension = true;
+ std::string objectName =
+ this->GetObjectFileNameWithoutTarget(*sf, dir, &hasSourceExtension);
+ if (cmSystemTools::FileIsFullPath(objectName.c_str())) {
+ objectName = cmSystemTools::GetFilenameName(objectName);
+ }
+ LocalObjectInfo& info = localObjectFiles[objectName];
+ info.HasSourceExtension = hasSourceExtension;
+ info.push_back(LocalObjectEntry(gt, sf->GetLanguage()));
}
- LocalObjectInfo& info = this->LocalObjectFiles[objNoTargetDir];
- info.HasSourceExtension = hasSourceExtension;
- info.push_back(LocalObjectEntry(target, sf->GetLanguage()));
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets
- (std::vector<std::string>& targets)
+void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets(
+ std::vector<std::string>& targets)
{
- for (std::map<cmStdString, LocalObjectInfo>::iterator lo =
- this->LocalObjectFiles.begin();
- lo != this->LocalObjectFiles.end(); ++lo)
- {
+ 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)
- {
+ if (lo->second.HasPreprocessRule) {
targets.push_back(base + ".i");
- }
+ }
- if(lo->second.HasAssembleRule)
- {
+ if (lo->second.HasAssembleRule) {
targets.push_back(base + ".s");
- }
}
+ }
}
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
{
// generate the includes
@@ -213,47 +235,44 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
// Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
- cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
- if(!ruleFileStream)
- {
+ cmGeneratedFileStream ruleFileStream(
+ ruleFileNameFull.c_str(), false,
+ this->GlobalGenerator->GetMakefileEncoding());
+ if (!ruleFileStream) {
return;
- }
+ }
// always write the top makefile
- if (this->Parent)
- {
+ if (!this->IsRootMakefile()) {
ruleFileStream.SetCopyIfDifferent(true);
- }
+ }
// write the all rules
this->WriteLocalAllRules(ruleFileStream);
// only write local targets unless at the top Keep track of targets already
// listed.
- std::set<cmStdString> emittedTargets;
- if (this->Parent)
- {
+ std::set<std::string> emittedTargets;
+ if (!this->IsRootMakefile()) {
// write our targets, and while doing it collect up the object
// file rules
- this->WriteLocalMakefileTargets(ruleFileStream,emittedTargets);
- }
- else
- {
- cmGlobalUnixMakefileGenerator3 *gg =
+ this->WriteLocalMakefileTargets(ruleFileStream, emittedTargets);
+ } else {
+ cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
- gg->WriteConvenienceRules(ruleFileStream,emittedTargets);
- }
+ gg->WriteConvenienceRules(ruleFileStream, emittedTargets);
+ }
+
+ bool do_preprocess_rules = this->GetCreatePreprocessedSourceRules();
+ bool do_assembly_rules = this->GetCreateAssemblySourceRules();
- bool do_preprocess_rules =
- this->GetCreatePreprocessedSourceRules();
- bool do_assembly_rules =
- this->GetCreateAssemblySourceRules();
+ std::map<std::string, LocalObjectInfo> localObjectFiles;
+ this->GetLocalObjectFiles(localObjectFiles);
// now write out the object rules
// for each object file name
- for (std::map<cmStdString, LocalObjectInfo>::iterator lo =
- this->LocalObjectFiles.begin();
- lo != this->LocalObjectFiles.end(); ++lo)
- {
+ for (std::map<std::string, LocalObjectInfo>::iterator lo =
+ localObjectFiles.begin();
+ lo != localObjectFiles.end(); ++lo) {
// Add a convenience rule for building the object file.
this->WriteObjectConvenienceRule(ruleFileStream,
"target to build an object file",
@@ -261,63 +280,60 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
// Check whether preprocessing and assembly rules make sense.
// They make sense only for C and C++ sources.
- bool lang_is_c_or_cxx = false;
- for(std::vector<LocalObjectEntry>::const_iterator ei =
- lo->second.begin(); ei != lo->second.end(); ++ei)
- {
- if(ei->Language == "C" || ei->Language == "CXX")
- {
- lang_is_c_or_cxx = true;
+ 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") {
+ // Right now, C, C++, Fortran and CUDA have both a preprocessor and the
+ // ability to generate assembly code
+ lang_has_preprocessor = true;
+ lang_has_assembly = true;
break;
- }
}
+ }
// Add convenience rules for preprocessed and assembly files.
- if(lang_is_c_or_cxx && (do_preprocess_rules || do_assembly_rules))
- {
+ 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);
- if(do_preprocess_rules)
- {
- this->WriteObjectConvenienceRule(
- ruleFileStream, "target to preprocess a source file",
- (base + ".i").c_str(), lo->second);
- lo->second.HasPreprocessRule = true;
- }
- if(do_assembly_rules)
- {
- this->WriteObjectConvenienceRule(
- ruleFileStream, "target to generate assembly for a file",
- (base + ".s").c_str(), lo->second);
- lo->second.HasAssembleRule = true;
- }
- }
+ this->WriteObjectConvenienceRule(ruleFileStream,
+ "target to preprocess a source file",
+ (base + ".i").c_str(), lo->second);
+ lo->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);
+ this->WriteObjectConvenienceRule(
+ ruleFileStream, "target to generate assembly for a file",
+ (base + ".s").c_str(), lo->second);
+ lo->second.HasAssembleRule = true;
+ }
+ }
+
// add a help target as long as there isn;t a real target named help
- if(emittedTargets.insert("help").second)
- {
- cmGlobalUnixMakefileGenerator3 *gg =
+ if (emittedTargets.insert("help").second) {
+ cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
- gg->WriteHelpRule(ruleFileStream,this);
- }
+ gg->WriteHelpRule(ruleFileStream, this);
+ }
this->WriteSpecialTargetsBottom(ruleFileStream);
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteObjectConvenienceRule(std::ostream& ruleFileStream,
- const char* comment, const char* output,
- LocalObjectInfo const& info)
+void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule(
+ std::ostream& ruleFileStream, const char* comment, const char* output,
+ LocalObjectInfo const& info)
{
// If the rule includes the source file extension then create a
// version that has the extension removed. The help should include
// only the version without source extension.
bool inHelp = true;
- if(info.HasSourceExtension)
- {
+ if (info.HasSourceExtension) {
// Remove the last extension. This should be kept.
std::string outBase1 = output;
std::string outExt1 = cmSplitExtension(outBase1, outBase1);
@@ -332,61 +348,54 @@ cmLocalUnixMakefileGenerator3
std::vector<std::string> depends;
depends.push_back(output);
std::vector<std::string> no_commands;
- this->WriteMakeRule(ruleFileStream, 0,
- outNoExt.c_str(), depends, no_commands, true, true);
+ this->WriteMakeRule(ruleFileStream, CM_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 (std::vector<LocalObjectEntry>::const_iterator t = info.begin();
+ t != info.end(); ++t) {
+ 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.c_str())
- );
- }
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
+ this->GetRecursiveMakeCall(tgtMakefileName.c_str(), targetName));
+ }
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
// Write the rule to the makefile.
std::vector<std::string> no_depends;
- this->WriteMakeRule(ruleFileStream, comment,
- output, no_depends, commands, true, inHelp);
+ this->WriteMakeRule(ruleFileStream, comment, output, no_depends, commands,
+ true, inHelp);
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3
-::WriteLocalMakefileTargets(std::ostream& ruleFileStream,
- std::set<cmStdString> &emitted)
+void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
+ std::ostream& ruleFileStream, std::set<std::string>& emitted)
{
std::vector<std::string> depends;
std::vector<std::string> commands;
// for each target we just provide a rule to cd up to the top and do a make
// on the target
- cmTargets& targets = this->Makefile->GetTargets();
+ std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
std::string localName;
- for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
- {
- if((t->second.GetType() == cmTarget::EXECUTABLE) ||
- (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
- (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
- (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
- (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
- (t->second.GetType() == cmTarget::UTILITY))
- {
- emitted.insert(t->second.GetName());
+ 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 subdirs add a rule to build this specific target by name.
- localName = this->GetRelativeTargetDirectory(t->second);
+ localName = this->GetRelativeTargetDirectory(*t);
localName += "/rule";
commands.clear();
depends.clear();
@@ -394,344 +403,300 @@ void cmLocalUnixMakefileGenerator3
// Build the target for this pass.
std::string makefile2 = cmake::GetCMakeFilesDirectoryPostSlash();
makefile2 += "Makefile2";
- commands.push_back(this->GetRecursiveMakeCall
- (makefile2.c_str(),localName.c_str()));
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
+ commands.push_back(
+ this->GetRecursiveMakeCall(makefile2.c_str(), localName));
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
- localName.c_str(), depends, commands, true);
+ localName, depends, commands, true);
// Add a target with the canonical name (no prefix, suffix or path).
- if(localName != t->second.GetName())
- {
+ if (localName != (*t)->GetName()) {
commands.clear();
depends.push_back(localName);
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
- t->second.GetName(), depends, commands, true);
- }
+ (*t)->GetName(), depends, commands, true);
+ }
// Add a fast rule to build the target
- std::string makefileName = this->GetRelativeTargetDirectory(t->second);
+ std::string makefileName = this->GetRelativeTargetDirectory(*t);
makefileName += "/build.make";
// make sure the makefile name is suitable for a makefile
- std::string makeTargetName =
- this->GetRelativeTargetDirectory(t->second);
+ std::string makeTargetName = this->GetRelativeTargetDirectory(*t);
makeTargetName += "/build";
- localName = t->second.GetName();
+ localName = (*t)->GetName();
localName += "/fast";
depends.clear();
commands.clear();
- commands.push_back(this->GetRecursiveMakeCall
- (makefileName.c_str(), makeTargetName.c_str()));
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
+ commands.push_back(
+ this->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "fast build rule for target.",
- localName.c_str(), depends, commands, true);
+ localName, depends, commands, true);
// Add a local name for the rule to relink the target before
// installation.
- if(t->second.NeedRelinkBeforeInstall(this->ConfigurationName.c_str()))
- {
- makeTargetName = this->GetRelativeTargetDirectory(t->second);
+ if ((*t)->NeedRelinkBeforeInstall(this->ConfigName)) {
+ makeTargetName = this->GetRelativeTargetDirectory(*t);
makeTargetName += "/preinstall";
- localName = t->second.GetName();
+ localName = (*t)->GetName();
localName += "/preinstall";
depends.clear();
commands.clear();
- commands.push_back(this->GetRecursiveMakeCall
- (makefile2.c_str(), makeTargetName.c_str()));
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
+ commands.push_back(
+ this->GetRecursiveMakeCall(makefile2.c_str(), makeTargetName));
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream,
"Manual pre-install relink rule for target.",
- localName.c_str(), depends, commands, true);
- }
+ localName, depends, commands, true);
}
}
+ }
}
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
{
- std::string infoFileName = this->Makefile->GetStartOutputDirectory();
+ std::string infoFileName = this->GetCurrentBinaryDirectory();
infoFileName += cmake::GetCMakeFilesDirectory();
infoFileName += "/CMakeDirectoryInformation.cmake";
// Open the output file.
cmGeneratedFileStream infoFileStream(infoFileName.c_str());
- if(!infoFileStream)
- {
+ if (!infoFileStream) {
return;
- }
+ }
infoFileStream.SetCopyIfDifferent(true);
// Write the do not edit header.
this->WriteDisclaimer(infoFileStream);
// Setup relative path conversion tops.
+ /* clang-format off */
infoFileStream
<< "# Relative path conversion top directories.\n"
- << "SET(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" << this->RelativePathTopSource
+ << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \""
+ << this->StateSnapshot.GetDirectory().GetRelativePathTopSource()
<< "\")\n"
- << "SET(CMAKE_RELATIVE_PATH_TOP_BINARY \"" << this->RelativePathTopBinary
+ << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \""
+ << this->StateSnapshot.GetDirectory().GetRelativePathTopBinary()
<< "\")\n"
<< "\n";
+ /* clang-format on */
// Tell the dependency scanner to use unix paths if necessary.
- if(cmSystemTools::GetForceUnixPaths())
- {
+ if (cmSystemTools::GetForceUnixPaths()) {
+ /* clang-format off */
infoFileStream
<< "# Force unix paths in dependencies.\n"
- << "SET(CMAKE_FORCE_UNIX_PATHS 1)\n"
+ << "set(CMAKE_FORCE_UNIX_PATHS 1)\n"
<< "\n";
- }
+ /* clang-format on */
+ }
// Store the include regular expressions for this directory.
- infoFileStream
- << "\n"
- << "# The C and CXX include file regular expressions for "
- << "this directory.\n";
- infoFileStream
- << "SET(CMAKE_C_INCLUDE_REGEX_SCAN ";
+ infoFileStream << "\n"
+ << "# 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());
- infoFileStream
- << ")\n";
- infoFileStream
- << "SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN ";
+ infoFileStream << ")\n";
+ infoFileStream << "set(CMAKE_C_INCLUDE_REGEX_COMPLAIN ";
this->WriteCMakeArgument(infoFileStream,
this->Makefile->GetComplainRegularExpression());
+ infoFileStream << ")\n";
infoFileStream
- << ")\n";
- infoFileStream
- << "SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n";
- infoFileStream
- << "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN "
- "${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
+ << "set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n";
+ infoFileStream << "set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN "
+ "${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::ConvertToFullPath(const std::string& localPath)
+std::string cmLocalUnixMakefileGenerator3::ConvertToFullPath(
+ const std::string& localPath)
{
- std::string dir = this->Makefile->GetStartOutputDirectory();
+ std::string dir = this->GetCurrentBinaryDirectory();
dir += "/";
dir += localPath;
return dir;
}
-
-const std::string &cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
+const std::string& cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
{
return this->HomeRelativeOutputPath;
}
-
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteMakeRule(std::ostream& os,
- const char* comment,
- const char* target,
- const std::vector<std::string>& depends,
- const std::vector<std::string>& commands,
- bool symbolic,
- bool in_help)
+void cmLocalUnixMakefileGenerator3::WriteMakeRule(
+ std::ostream& os, const char* comment, const std::string& target,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands, bool symbolic, bool in_help)
{
// Make sure there is a target.
- if(!target || !*target)
- {
+ if (target.empty()) {
cmSystemTools::Error("No target for WriteMakeRule! called with comment: ",
comment);
return;
- }
+ }
std::string replace;
// Write the comment describing the rule in the makefile.
- if(comment)
- {
+ if (comment) {
replace = comment;
std::string::size_type lpos = 0;
std::string::size_type rpos;
- while((rpos = replace.find('\n', lpos)) != std::string::npos)
- {
- os << "# " << replace.substr(lpos, rpos-lpos) << "\n";
- lpos = rpos+1;
- }
- os << "# " << replace.substr(lpos) << "\n";
+ while ((rpos = replace.find('\n', lpos)) != std::string::npos) {
+ os << "# " << replace.substr(lpos, rpos - lpos) << "\n";
+ lpos = rpos + 1;
}
+ os << "# " << replace.substr(lpos) << "\n";
+ }
// Construct the left hand side of the rule.
- replace = target;
- std::string tgt = this->Convert(replace.c_str(),HOME_OUTPUT,MAKEFILE);
+ std::string tgt = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target)
+ .c_str());
+
const char* space = "";
- if(tgt.size() == 1)
- {
+ if (tgt.size() == 1) {
// Add a space before the ":" to avoid drive letter confusion on
// Windows.
space = " ";
- }
+ }
// Mark the rule as symbolic if requested.
- if(symbolic)
- {
- if(const char* sym =
- this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE"))
- {
+ if (symbolic) {
+ if (const char* sym =
+ this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE")) {
os << cmMakeSafe(tgt) << space << ": " << sym << "\n";
- }
}
+ }
// Write the rule.
- if(depends.empty())
- {
+ if (depends.empty()) {
// No dependencies. The commands will always run.
os << cmMakeSafe(tgt) << space << ":\n";
- }
- else
- {
+ } else {
// Split dependencies into multiple rule lines. This allows for
// very long dependency lists even on older make implementations.
- for(std::vector<std::string>::const_iterator dep = depends.begin();
- dep != depends.end(); ++dep)
- {
+ std::string binDir = this->GetBinaryDirectory();
+ for (std::vector<std::string>::const_iterator dep = depends.begin();
+ dep != depends.end(); ++dep) {
replace = *dep;
- replace = this->Convert(replace.c_str(),HOME_OUTPUT,MAKEFILE);
+ replace = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, replace).c_str());
os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n";
- }
}
+ }
// Write the list of commands.
- for(std::vector<std::string>::const_iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- replace = *i;
- os << "\t" << replace.c_str() << "\n";
- }
- if(symbolic && !this->WatcomWMake)
- {
+ os << cmWrap("\t", commands, "", "\n") << "\n";
+ if (symbolic && !this->IsWatcomWMake()) {
os << ".PHONY : " << cmMakeSafe(tgt) << "\n";
- }
+ }
os << "\n";
// Add the output to the local help if requested.
- if(in_help)
- {
+ if (in_help) {
this->LocalHelp.push_back(target);
- }
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::ConvertShellCommand(std::string const& cmd, RelativeRoot root)
+std::string cmLocalUnixMakefileGenerator3::MaybeConvertWatcomShellCommand(
+ std::string const& cmd)
{
- if(this->WatcomWMake &&
- cmSystemTools::FileIsFullPath(cmd.c_str()) &&
- cmd.find_first_of("( )") != cmd.npos)
- {
+ if (this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd.c_str()) &&
+ 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
// lines with shell redirection operators.
std::string scmd;
- if(cmSystemTools::GetShortPath(cmd.c_str(), scmd))
- {
- return this->Convert(scmd.c_str(), NONE, SHELL);
- }
+ if (cmSystemTools::GetShortPath(cmd, scmd)) {
+ return this->ConvertToOutputFormat(scmd, cmOutputConverter::SHELL);
}
- return this->Convert(cmd.c_str(), root, SHELL);
+ }
+ return std::string();
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteMakeVariables(std::ostream& makefileStream)
+void cmLocalUnixMakefileGenerator3::WriteMakeVariables(
+ std::ostream& makefileStream)
{
this->WriteDivider(makefileStream);
- makefileStream
- << "# Set environment variables for the build.\n"
- << "\n";
- if(this->DefineWindowsNULL)
- {
- makefileStream
- << "!IF \"$(OS)\" == \"Windows_NT\"\n"
- << "NULL=\n"
- << "!ELSE\n"
- << "NULL=nul\n"
- << "!ENDIF\n";
- }
- if(this->WindowsShell)
- {
- makefileStream
- << "SHELL = cmd.exe\n"
- << "\n";
- }
- else
- {
+ makefileStream << "# Set environment variables for the build.\n"
+ << "\n";
+ cmGlobalUnixMakefileGenerator3* gg =
+ static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
+ if (gg->DefineWindowsNULL) {
+ makefileStream << "!IF \"$(OS)\" == \"Windows_NT\"\n"
+ << "NULL=\n"
+ << "!ELSE\n"
+ << "NULL=nul\n"
+ << "!ENDIF\n";
+ }
+ if (this->IsWindowsShell()) {
+ makefileStream << "SHELL = cmd.exe\n"
+ << "\n";
+ } else {
#if !defined(__VMS)
+ /* clang-format off */
makefileStream
<< "# The shell in which to execute make rules.\n"
<< "SHELL = /bin/sh\n"
<< "\n";
+/* clang-format on */
#endif
- }
+ }
+
+ std::string cmakeShellCommand =
+ this->MaybeConvertWatcomShellCommand(cmSystemTools::GetCMakeCommand());
+ if (cmakeShellCommand.empty()) {
+ cmakeShellCommand = this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
+ cmOutputConverter::SHELL);
+ }
- std::string cmakecommand =
- this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
+ /* clang-format off */
makefileStream
<< "# The CMake executable.\n"
<< "CMAKE_COMMAND = "
- << this->ConvertShellCommand(cmakecommand, FULL)
+ << cmakeShellCommand
<< "\n"
<< "\n";
makefileStream
<< "# The command to remove a file.\n"
<< "RM = "
- << this->ConvertShellCommand(cmakecommand, FULL)
+ << cmakeShellCommand
<< " -E remove -f\n"
<< "\n";
makefileStream
<< "# Escaping for special characters.\n"
<< "EQUALS = =\n"
<< "\n";
-
- if(const char* edit_cmd =
- this->Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
- {
- makefileStream
- << "# The program to use to edit the cache.\n"
- << "CMAKE_EDIT_COMMAND = "
- << this->ConvertShellCommand(edit_cmd, FULL) << "\n"
- << "\n";
- }
-
makefileStream
<< "# The top-level source directory on which CMake was run.\n"
<< "CMAKE_SOURCE_DIR = "
- << this->Convert(this->Makefile->GetHomeDirectory(), FULL, SHELL)
+ << this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(this->GetSourceDirectory()),
+ cmOutputConverter::SHELL)
<< "\n"
<< "\n";
makefileStream
<< "# The top-level build directory on which CMake was run.\n"
<< "CMAKE_BINARY_DIR = "
- << this->Convert(this->Makefile->GetHomeOutputDirectory(), FULL, SHELL)
+ << this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(this->GetBinaryDirectory()),
+ cmOutputConverter::SHELL)
<< "\n"
<< "\n";
+ /* clang-format on */
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteSpecialTargetsTop(std::ostream& makefileStream)
+void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop(
+ std::ostream& makefileStream)
{
this->WriteDivider(makefileStream);
- makefileStream
- << "# Special targets provided by cmake.\n"
- << "\n";
+ makefileStream << "# Special targets provided by cmake.\n"
+ << "\n";
std::vector<std::string> no_commands;
std::vector<std::string> no_depends;
@@ -739,129 +704,128 @@ cmLocalUnixMakefileGenerator3
// Special target to cleanup operation of make tool.
// This should be the first target except for the default_target in
// the interface Makefile.
- this->WriteMakeRule(
- makefileStream, "Disable implicit rules so canonical targets will work.",
- ".SUFFIXES", no_depends, no_commands, false);
+ this->WriteMakeRule(makefileStream,
+ "Disable implicit rules so canonical targets will work.",
+ ".SUFFIXES", no_depends, no_commands, false);
- if(!this->NMake && !this->WatcomWMake && !this->BorlandMakeCurlyHack)
- {
+ if (!this->IsNMake() && !this->IsWatcomWMake() &&
+ !this->BorlandMakeCurlyHack) {
// turn off RCS and SCCS automatic stuff from gmake
makefileStream
<< "# Remove some rules from gmake that .SUFFIXES does not remove.\n"
<< "SUFFIXES =\n\n";
- }
+ }
// 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, 0,
- ".SUFFIXES", depends, no_commands, false);
-
- cmGlobalUnixMakefileGenerator3* gg =
- static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
- // Write special target to silence make output. This must be after
- // the default target in case VERBOSE is set (which changes the
- // name). The setting of CMAKE_VERBOSE_MAKEFILE to ON will cause a
- // "VERBOSE=1" to be added as a make variable which will change the
- // name of this special target. This gives a make-time choice to
- // the user.
- if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
- {
+ this->WriteMakeRule(makefileStream, CM_NULLPTR, ".SUFFIXES", depends,
+ no_commands, false);
+ if (this->IsWatcomWMake()) {
+ // Switch on WMake feature, if an error or interrupt occurs during
+ // makefile processing, the current target being made may be deleted
+ // without prompting (the same as command line -e option).
+ /* clang-format off */
+ makefileStream <<
+ "\n"
+ ".ERASE\n"
+ "\n"
+ ;
+ /* clang-format on */
+ }
+ if (this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")) {
+ /* clang-format off */
makefileStream
<< "# Produce verbose output by default.\n"
<< "VERBOSE = 1\n"
<< "\n";
- }
- if(this->SilentNoColon)
- {
- makefileStream << "$(VERBOSE).SILENT\n";
- }
- else
- {
+ /* clang-format on */
+ }
+ if (this->IsWatcomWMake()) {
+ /* clang-format off */
+ makefileStream <<
+ "!ifndef VERBOSE\n"
+ ".SILENT\n"
+ "!endif\n"
+ "\n"
+ ;
+ /* clang-format on */
+ } else {
+ // Write special target to silence make output. This must be after
+ // the default target in case VERBOSE is set (which changes the
+ // name). The setting of CMAKE_VERBOSE_MAKEFILE to ON will cause a
+ // "VERBOSE=1" to be added as a make variable which will change the
+ // name of this special target. This gives a make-time choice to
+ // the user.
this->WriteMakeRule(makefileStream,
"Suppress display of executed commands.",
- "$(VERBOSE).SILENT",
- no_depends,
- no_commands, false);
- }
+ "$(VERBOSE).SILENT", no_depends, no_commands, false);
+ }
// Work-around for makes that drop rules that have no dependencies
// or commands.
+ cmGlobalUnixMakefileGenerator3* gg =
+ static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
std::string hack = gg->GetEmptyRuleHackDepends();
- if(!hack.empty())
- {
+ if (!hack.empty()) {
no_depends.push_back(hack);
- }
+ }
std::string hack_cmd = gg->GetEmptyRuleHackCommand();
- if(!hack_cmd.empty())
- {
+ if (!hack_cmd.empty()) {
no_commands.push_back(hack_cmd);
- }
+ }
// Special symbolic target that never exists to force dependers to
// run their rules.
- this->WriteMakeRule
- (makefileStream,
- "A target that is always out of date.",
- "cmake_force", no_depends, no_commands, true);
+ this->WriteMakeRule(makefileStream, "A target that is always out of date.",
+ "cmake_force", no_depends, no_commands, true);
// Variables for reference by other rules.
this->WriteMakeVariables(makefileStream);
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3
-::WriteSpecialTargetsBottom(std::ostream& makefileStream)
+void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
+ std::ostream& makefileStream)
{
this->WriteDivider(makefileStream);
- makefileStream
- << "# Special targets to cleanup operation of make.\n"
- << "\n";
+ makefileStream << "# Special targets to cleanup operation of make.\n"
+ << "\n";
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
{
- // 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->Convert(cmakefileName.c_str(),NONE,SHELL);
- runRule += " 0";
-
- std::vector<std::string> no_depends;
- std::vector<std::string> commands;
- commands.push_back(runRule);
- if(this->Parent)
- {
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
- }
- this->WriteMakeRule(makefileStream,
- "Special rule to run CMake to check the build system "
+ // 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> no_depends;
+ std::vector<std::string> commands;
+ commands.push_back(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);
+ "cmake_check_build_system", no_depends, commands, true);
}
}
-
-
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteConvenienceRule(std::ostream& ruleFileStream,
- const char* realTarget,
- const char* helpTarget)
+void cmLocalUnixMakefileGenerator3::WriteConvenienceRule(
+ std::ostream& ruleFileStream, const std::string& realTarget,
+ const std::string& helpTarget)
{
// A rule is only needed if the names are different.
- if(strcmp(realTarget, helpTarget) != 0)
- {
+ if (realTarget != helpTarget) {
// The helper target depends on the real target.
std::vector<std::string> depends;
depends.push_back(realTarget);
@@ -872,359 +836,300 @@ cmLocalUnixMakefileGenerator3
// Write the rule.
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
helpTarget, depends, no_commands, true);
- }
+ }
}
-
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::GetRelativeTargetDirectory(cmTarget const& target)
+std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
+ cmGeneratorTarget* target)
{
std::string dir = this->HomeRelativeOutputPath;
dir += this->GetTargetDirectory(target);
- return this->Convert(dir.c_str(),NONE,UNCHANGED);
+ return dir;
}
-
-
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
- const char* newFlags)
+ const std::string& newFlags)
{
- if(this->WatcomWMake && newFlags && *newFlags)
- {
+ if (this->IsWatcomWMake() && !newFlags.empty()) {
std::string newf = newFlags;
- if(newf.find("\\\"") != newf.npos)
- {
+ if (newf.find("\\\"") != std::string::npos) {
cmSystemTools::ReplaceString(newf, "\\\"", "\"");
- this->cmLocalGenerator::AppendFlags(flags, newf.c_str());
+ this->cmLocalGenerator::AppendFlags(flags, newf);
return;
- }
}
+ }
this->cmLocalGenerator::AppendFlags(flags, newFlags);
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendRuleDepend(std::vector<std::string>& depends,
- const char* ruleFileName)
+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)
{
// Add a dependency on the rule file itself unless an option to skip
// it is specifically enabled by the user or project.
const char* nodep =
this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY");
- if(!nodep || cmSystemTools::IsOff(nodep))
- {
+ if (!nodep || cmSystemTools::IsOff(nodep)) {
depends.push_back(ruleFileName);
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendRuleDepends(std::vector<std::string>& depends,
- std::vector<std::string> const& ruleFiles)
+void cmLocalUnixMakefileGenerator3::AppendRuleDepends(
+ std::vector<std::string>& depends, std::vector<std::string> const& ruleFiles)
{
// 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"))
- {
+ if (!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) {
depends.insert(depends.end(), ruleFiles.begin(), ruleFiles.end());
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendCustomDepends(std::vector<std::string>& depends,
- const std::vector<cmCustomCommand>& ccs)
+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)
- {
- this->AppendCustomDepend(depends, *i);
- }
+ for (std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
+ i != ccs.end(); ++i) {
+ cmCustomCommandGenerator ccg(*i, this->ConfigName, this);
+ this->AppendCustomDepend(depends, ccg);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendCustomDepend(std::vector<std::string>& depends,
- const cmCustomCommand& cc)
+void cmLocalUnixMakefileGenerator3::AppendCustomDepend(
+ std::vector<std::string>& depends, cmCustomCommandGenerator const& ccg)
{
- for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
- d != cc.GetDepends().end(); ++d)
- {
+ for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
+ d != ccg.GetDepends().end(); ++d) {
// Lookup the real name of the dependency in case it is a CMake target.
std::string dep;
- if(this->GetRealDependency(d->c_str(), this->ConfigurationName.c_str(),
- dep))
- {
+ if (this->GetRealDependency(*d, this->ConfigName, dep)) {
depends.push_back(dep);
- }
}
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendCustomCommands(std::vector<std::string>& commands,
- const std::vector<cmCustomCommand>& ccs,
- cmTarget* target,
- cmLocalGenerator::RelativeRoot relative)
+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)
- {
- this->AppendCustomCommand(commands, *i, target, true, relative);
- }
+ for (std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
+ i != ccs.end(); ++i) {
+ cmCustomCommandGenerator ccg(*i, this->ConfigName, this);
+ this->AppendCustomCommand(commands, ccg, target, relative, true);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendCustomCommand(std::vector<std::string>& commands,
- const cmCustomCommand& cc,
- cmTarget* target,
- bool echo_comment,
- cmLocalGenerator::RelativeRoot relative,
- std::ostream* content)
+void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
+ std::vector<std::string>& commands, cmCustomCommandGenerator const& ccg,
+ cmGeneratorTarget* target, std::string const& relative, bool echo_comment,
+ std::ostream* content)
{
// Optionally create a command to display the custom command's
// comment text. This is used for pre-build, pre-link, and
// post-build command comments. Custom build step commands have
// their comments generated elsewhere.
- if(echo_comment)
- {
- const char* comment = cc.GetComment();
- if(comment && *comment)
- {
+ if (echo_comment) {
+ const char* comment = ccg.GetComment();
+ if (comment && *comment) {
this->AppendEcho(commands, comment,
cmLocalUnixMakefileGenerator3::EchoGenerate);
- }
}
+ }
// if the command specified a working directory use it.
- const char* dir = this->Makefile->GetStartOutputDirectory();
- const char* workingDir = cc.GetWorkingDirectory();
- if(workingDir)
- {
+ std::string dir = this->GetCurrentBinaryDirectory();
+ std::string workingDir = ccg.GetWorkingDirectory();
+ if (!workingDir.empty()) {
dir = workingDir;
- }
- if(content)
- {
+ }
+ if (content) {
*content << dir;
- }
- cmCustomCommandGenerator ccg(cc, this->ConfigurationName.c_str(),
- this->Makefile);
+ }
+
+ CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ this->CreateRulePlaceholderExpander());
// Add each command line to the set of commands.
std::vector<std::string> commands1;
- for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
- {
+ std::string currentBinDir = this->GetCurrentBinaryDirectory();
+ 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.size())
- {
+ 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->WindowsShell)
- {
+ if (this->IsWindowsShell()) {
std::string suffix;
- if (cmd.size() > 4)
- {
- suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size()-4));
- if (suffix == ".bat" || suffix == ".cmd")
- {
+ if (cmd.size() > 4) {
+ suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4));
+ if (suffix == ".bat" || suffix == ".cmd") {
useCall = true;
- }
}
}
+ }
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("/") != cmd.npos;
- if(!workingDir)
- {
- cmd = this->Convert(cmd.c_str(),START_OUTPUT);
- }
- bool has_slash = cmd.find("/") != cmd.npos;
- if(had_slash && !has_slash)
- {
+ bool had_slash = cmd.find('/') != std::string::npos;
+ if (workingDir.empty()) {
+ cmd = this->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 = "./" + 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.
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = target->GetName().c_str();
+ vars.CMTargetType = cmState::GetTargetTypeName(target->GetType());
+ std::string output;
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ if (!outputs.empty()) {
+ output = outputs[0];
+ if (workingDir.empty()) {
+ output = this->MaybeConvertToRelativePath(
+ this->GetCurrentBinaryDirectory(), output);
+ }
+ output =
+ this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
}
- std::string launcher =
- this->MakeLauncher(cc, target, workingDir? NONE : START_OUTPUT);
- cmd = launcher + this->ConvertShellCommand(cmd, NONE);
+ vars.Output = output.c_str();
+
+ launcher = val;
+ launcher += " ";
+ rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
+ if (!launcher.empty()) {
+ launcher += " ";
+ }
+ }
+
+ std::string shellCommand = this->MaybeConvertWatcomShellCommand(cmd);
+ if (shellCommand.empty()) {
+ shellCommand =
+ this->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
+ }
+ cmd = launcher + shellCommand;
ccg.AppendArguments(c, cmd);
- if(content)
- {
+ if (content) {
// Rule content does not include the launcher.
- *content << (cmd.c_str()+launcher.size());
- }
- if(this->BorlandMakeCurlyHack)
- {
+ *content << (cmd.c_str() + launcher.size());
+ }
+ if (this->BorlandMakeCurlyHack) {
// Borland Make has a very strange bug. If the first curly
// brace anywhere in the command string is a left curly, it
// must be written {{} instead of just {. Otherwise some
// curly braces are removed. The hack can be skipped if the
// first curly brace is the last character.
- std::string::size_type lcurly = cmd.find("{");
- if(lcurly != cmd.npos && lcurly < (cmd.size()-1))
- {
- std::string::size_type rcurly = cmd.find("}");
- if(rcurly == cmd.npos || rcurly > lcurly)
- {
+ std::string::size_type lcurly = cmd.find('{');
+ if (lcurly != std::string::npos && lcurly < (cmd.size() - 1)) {
+ 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);
+ hack_cmd += cmd.substr(lcurly + 1);
cmd = hack_cmd;
- }
}
}
- if (launcher.empty())
- {
- if (useCall)
- {
+ }
+ if (launcher.empty()) {
+ if (useCall) {
cmd = "call " + cmd;
- }
- else if (this->NMake && cmd[0]=='"')
- {
+ } else if (this->IsNMake() && cmd[0] == '"') {
cmd = "echo >nul && " + cmd;
- }
}
- commands1.push_back(cmd);
}
+ commands1.push_back(cmd);
}
+ }
// Setup the proper working directory for the commands.
- this->CreateCDCommand(commands1, dir, relative);
+ this->CreateCDCommand(commands1, dir.c_str(), relative);
// push back the custom commands
commands.insert(commands.end(), commands1.begin(), commands1.end());
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3::MakeLauncher(const cmCustomCommand& cc,
- cmTarget* target,
- RelativeRoot relative)
+void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
+ std::vector<std::string>& commands, const std::vector<std::string>& files,
+ cmGeneratorTarget* target, const char* filename)
{
- // Short-circuit if there is no launcher.
- const char* prop = "RULE_LAUNCH_CUSTOM";
- const char* val = this->GetRuleLauncher(target, prop);
- if(!(val && *val))
- {
- return "";
- }
-
- // Expand rules in the empty string. It may insert the launcher and
- // perform replacements.
- RuleVariables vars;
- vars.RuleLauncher = prop;
- vars.CMTarget = target;
- std::string output;
- const std::vector<std::string>& outputs = cc.GetOutputs();
- if(!outputs.empty())
- {
- output = this->Convert(outputs[0].c_str(), relative, SHELL);
- }
- vars.Output = output.c_str();
-
- std::string launcher;
- this->ExpandRuleVariables(launcher, vars);
- if(!launcher.empty())
- {
- launcher += " ";
+ std::string currentBinDir = this->GetCurrentBinaryDirectory();
+ std::string cleanfile = currentBinDir;
+ cleanfile += "/";
+ cleanfile += this->GetTargetDirectory(target);
+ cleanfile += "/cmake_clean";
+ if (filename) {
+ cleanfile += "_";
+ cleanfile += filename;
+ }
+ cleanfile += ".cmake";
+ std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
+ cmsys::ofstream fout(cleanfilePath.c_str());
+ if (!fout) {
+ cmSystemTools::Error("Could not create ", cleanfilePath.c_str());
+ }
+ 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);
+ fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n";
}
- return launcher;
-}
-
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::AppendCleanCommand(std::vector<std::string>& commands,
- const std::vector<std::string>& files,
- cmTarget& target, const char* filename)
-{
- if(!files.empty())
- {
- std::string cleanfile = this->Makefile->GetCurrentOutputDirectory();
- cleanfile += "/";
- cleanfile += this->GetTargetDirectory(target);
- cleanfile += "/cmake_clean";
- if(filename)
- {
- cleanfile += "_";
- cleanfile += filename;
- }
- cleanfile += ".cmake";
- std::string cleanfilePath = this->Convert(cleanfile.c_str(), FULL);
- std::ofstream fout(cleanfilePath.c_str());
- if(!fout)
- {
- cmSystemTools::Error("Could not create ", cleanfilePath.c_str());
- }
- fout << "FILE(REMOVE_RECURSE\n";
- std::string remove = "$(CMAKE_COMMAND) -P ";
- remove += this->Convert(cleanfile.c_str(), START_OUTPUT, SHELL);
- for(std::vector<std::string>::const_iterator f = files.begin();
- f != files.end(); ++f)
- {
- std::string fc = this->Convert(f->c_str(),START_OUTPUT,UNCHANGED);
- fout << " " << this->EscapeForCMake(fc.c_str()) << "\n";
- }
fout << ")\n";
- commands.push_back(remove);
-
- // For the main clean rule add per-language cleaning.
- if(!filename)
- {
- // Get the set of source languages in the target.
- std::set<cmStdString> languages;
- target.GetLanguages(languages);
- fout << "\n"
- << "# Per-language clean rules from dependency scanning.\n"
- << "FOREACH(lang";
- for(std::set<cmStdString>::const_iterator l = languages.begin();
- l != languages.end(); ++l)
- {
- fout << " " << *l;
- }
- fout << ")\n"
- << " INCLUDE(" << this->GetTargetDirectory(target)
- << "/cmake_clean_${lang}.cmake OPTIONAL)\n"
- << "ENDFOREACH(lang)\n";
- }
- }
+ }
+ std::string remove = "$(CMAKE_COMMAND) -P ";
+ remove += this->ConvertToOutputFormat(
+ this->MaybeConvertToRelativePath(this->GetCurrentBinaryDirectory(),
+ cleanfile),
+ cmOutputConverter::SHELL);
+ commands.push_back(remove);
+
+ // For the main clean rule add per-language cleaning.
+ if (!filename) {
+ // Get the set of source languages in the target.
+ std::set<std::string> languages;
+ target->GetLanguages(
+ languages, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
+ /* clang-format off */
+ fout << "\n"
+ << "# Per-language clean rules from dependency scanning.\n"
+ << "foreach(lang " << cmJoin(languages, " ") << ")\n"
+ << " include(" << this->GetTargetDirectory(target)
+ << "/cmake_clean_${lang}.cmake OPTIONAL)\n"
+ << "endforeach()\n";
+ /* clang-format on */
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3::AppendEcho(std::vector<std::string>& commands,
- const char* text,
- EchoColor color)
+void cmLocalUnixMakefileGenerator3::AppendEcho(
+ std::vector<std::string>& commands, std::string const& text, EchoColor color,
+ EchoProgress const* progress)
{
// Choose the color for the text.
std::string color_name;
-#ifdef CMAKE_BUILD_WITH_CMAKE
- if(this->GlobalGenerator->GetToolSupportsColor() && this->ColorMakefile)
- {
+ if (this->GlobalGenerator->GetToolSupportsColor() && this->ColorMakefile) {
// See cmake::ExecuteEchoColor in cmake.cxx for these options.
// This color set is readable on both black and white backgrounds.
- switch(color)
- {
+ switch (color) {
case EchoNormal:
break;
case EchoDepend:
@@ -1234,7 +1139,7 @@ cmLocalUnixMakefileGenerator3::AppendEcho(std::vector<std::string>& commands,
color_name = "--green ";
break;
case EchoLink:
- color_name = "--red --bold ";
+ color_name = "--green --bold ";
break;
case EchoGenerate:
color_name = "--blue --bold ";
@@ -1242,160 +1147,149 @@ cmLocalUnixMakefileGenerator3::AppendEcho(std::vector<std::string>& commands,
case EchoGlobal:
color_name = "--cyan ";
break;
- }
}
-#else
- (void)color;
-#endif
+ }
// Echo one line at a time.
std::string line;
line.reserve(200);
- for(const char* c = text;; ++c)
- {
- if(*c == '\n' || *c == '\0')
- {
+ for (const char* c = text.c_str();; ++c) {
+ if (*c == '\n' || *c == '\0') {
// Avoid writing a blank last line on end-of-string.
- if(*c != '\0' || !line.empty())
- {
+ if (*c != '\0' || !line.empty()) {
// Add a command to echo this line.
std::string cmd;
- if(color_name.empty())
- {
+ if (color_name.empty() && !progress) {
// Use the native echo command.
cmd = "@echo ";
- cmd += this->EscapeForShell(line.c_str(), false, true);
- }
- else
- {
+ cmd += 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 += this->EscapeForShell(line.c_str());
+ if (progress) {
+ cmd += "--progress-dir=";
+ cmd += this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(progress->Dir),
+ cmOutputConverter::SHELL);
+ cmd += " ";
+ cmd += "--progress-num=";
+ cmd += progress->Arg;
+ cmd += " ";
}
- commands.push_back(cmd);
+ cmd += this->EscapeForShell(line);
}
+ commands.push_back(cmd);
+ }
// Reset the line to emtpy.
line = "";
+ // Progress appears only on first line.
+ progress = CM_NULLPTR;
+
// Terminate on end-of-string.
- if(*c == '\0')
- {
+ if (*c == '\0') {
return;
- }
}
- else if(*c != '\r')
- {
+ } else if (*c != '\r') {
// Append this character to the current line.
line += *c;
- }
}
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::CreateMakeVariable(const char* sin, const char* s2in)
+std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
+ std::string const& s, std::string const& s2)
{
- std::string s = sin;
- std::string s2 = s2in;
std::string unmodified = s;
unmodified += 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.
- if((!this->MakefileVariableSize && unmodified.find('.') == s.npos)
- && (!this->MakefileVariableSize && unmodified.find('+') == s.npos)
- && (!this->MakefileVariableSize && unmodified.find('-') == s.npos))
- {
+ if ((!this->MakefileVariableSize &&
+ unmodified.find('.') == std::string::npos) &&
+ (!this->MakefileVariableSize &&
+ unmodified.find('+') == std::string::npos) &&
+ (!this->MakefileVariableSize &&
+ unmodified.find('-') == std::string::npos)) {
return unmodified;
- }
+ }
// see if the variable has been defined before and return
// the modified version of the variable
- std::map<cmStdString, cmStdString>::iterator i =
+ std::map<std::string, std::string>::iterator i =
this->MakeVariableMap.find(unmodified);
- if(i != this->MakeVariableMap.end())
- {
+ if (i != this->MakeVariableMap.end()) {
return i->second;
- }
+ }
// start with the unmodified variable
std::string ret = unmodified;
// if this there is no value for this->MakefileVariableSize then
// the string must have bad characters in it
- if(!this->MakefileVariableSize)
- {
- cmSystemTools::ReplaceString(ret, ".", "_");
+ if (!this->MakefileVariableSize) {
+ std::replace(ret.begin(), ret.end(), '.', '_');
cmSystemTools::ReplaceString(ret, "-", "__");
cmSystemTools::ReplaceString(ret, "+", "___");
int ni = 0;
char buffer[5];
// make sure the _ version is not already used, if
// it is used then add number to the end of the variable
- while(this->ShortMakeVariableMap.count(ret) && ni < 1000)
- {
+ while (this->ShortMakeVariableMap.count(ret) && ni < 1000) {
++ni;
sprintf(buffer, "%04d", ni);
ret = unmodified + buffer;
- }
+ }
this->ShortMakeVariableMap[ret] = "1";
this->MakeVariableMap[unmodified] = ret;
return ret;
- }
+ }
// if the string is greater than 32 chars it is an invalid variable name
// for borland make
- if(static_cast<int>(ret.size()) > this->MakefileVariableSize)
- {
+ if (static_cast<int>(ret.size()) > this->MakefileVariableSize) {
int keep = this->MakefileVariableSize - 8;
int size = keep + 3;
std::string str1 = s;
std::string str2 = s2;
// we must shorten the combined string by 4 characters
// keep no more than 24 characters from the second string
- if(static_cast<int>(str2.size()) > keep)
- {
+ if (static_cast<int>(str2.size()) > keep) {
str2 = str2.substr(0, keep);
- }
- if(static_cast<int>(str1.size()) + static_cast<int>(str2.size()) > size)
- {
+ }
+ if (static_cast<int>(str1.size()) + static_cast<int>(str2.size()) > size) {
str1 = str1.substr(0, size - str2.size());
- }
+ }
char buffer[5];
int ni = 0;
sprintf(buffer, "%04d", ni);
ret = str1 + str2 + buffer;
- while(this->ShortMakeVariableMap.count(ret) && ni < 1000)
- {
+ while (this->ShortMakeVariableMap.count(ret) && ni < 1000) {
++ni;
sprintf(buffer, "%04d", ni);
ret = str1 + str2 + buffer;
- }
- if(ni == 1000)
- {
+ }
+ if (ni == 1000) {
cmSystemTools::Error("Borland makefile variable length too long");
return unmodified;
- }
+ }
// once an unused variable is found
this->ShortMakeVariableMap[ret] = "1";
- }
+ }
// always make an entry into the unmodified to variable map
this->MakeVariableMap[unmodified] = ret;
return ret;
}
-//----------------------------------------------------------------------------
bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
bool verbose,
bool color)
{
// read in the target info file
- if(!this->Makefile->ReadListFile(0, tgtInfo) ||
- cmSystemTools::GetErrorOccuredFlag())
- {
+ if (!this->Makefile->ReadListFile(tgtInfo) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
cmSystemTools::Error("Target DependInfo.cmake file not found");
- }
+ }
// Check if any multiple output pairs have a missing file.
this->CheckMultipleOutputs(verbose);
@@ -1412,42 +1306,37 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
cmFileTimeComparison* ftc =
this->GlobalGenerator->GetCMakeInstance()->GetFileComparison();
{
- int result;
- if(!ftc->FileTimeCompare(internalDependFile.c_str(), tgtInfo, &result) ||
- result < 0)
- {
- if(verbose)
- {
- cmOStringStream msg;
- msg << "Dependee \"" << tgtInfo
- << "\" is newer than depender \""
- << internalDependFile << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ int result;
+ if (!ftc->FileTimeCompare(internalDependFile.c_str(), 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());
}
- needRescanDependInfo = true;
+ needRescanDependInfo = true;
}
}
// 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->Makefile->GetStartOutputDirectory();
+ std::string dirInfoFile = this->GetCurrentBinaryDirectory();
dirInfoFile += cmake::GetCMakeFilesDirectory();
dirInfoFile += "/CMakeDirectoryInformation.cmake";
{
- int result;
- if(!ftc->FileTimeCompare(internalDependFile.c_str(),
- dirInfoFile.c_str(), &result) || result < 0)
- {
- if(verbose)
- {
- cmOStringStream msg;
- msg << "Dependee \"" << dirInfoFile
- << "\" is newer than depender \""
- << internalDependFile << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ int result;
+ if (!ftc->FileTimeCompare(internalDependFile.c_str(), dirInfoFile.c_str(),
+ &result) ||
+ result < 0) {
+ if (verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dirInfoFile << "\" is newer than depender \""
+ << internalDependFile << "\"." << std::endl;
+ cmSystemTools::Stdout(msg.str().c_str());
}
- needRescanDirInfo = true;
+ needRescanDirInfo = true;
}
}
@@ -1457,8 +1346,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
// not be considered.
std::map<std::string, cmDepends::DependencyVector> validDependencies;
bool needRescanDependencies = false;
- if (needRescanDirInfo == false)
- {
+ if (!needRescanDirInfo) {
cmDependsC checker;
checker.SetVerbose(verbose);
checker.SetFileComparison(ftc);
@@ -1472,81 +1360,65 @@ 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.c_str(), internalDependFile.c_str(), validDependencies);
+ }
- if(needRescanDependInfo || needRescanDirInfo || needRescanDependencies)
- {
+ if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
// The dependencies must be regenerated.
std::string targetName = cmSystemTools::GetFilenameName(dir);
- targetName = targetName.substr(0, targetName.length()-4);
+ targetName = targetName.substr(0, targetName.length() - 4);
std::string message = "Scanning dependencies of target ";
message += targetName;
-#ifdef CMAKE_BUILD_WITH_CMAKE
- cmSystemTools::MakefileColorEcho(
- cmsysTerminal_Color_ForegroundMagenta |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, color);
-#else
- fprintf(stdout, "%s\n", message.c_str());
-#endif
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
return this->ScanDependencies(dir.c_str(), validDependencies);
- }
+ }
// The dependencies are already up-to-date.
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmLocalUnixMakefileGenerator3
-::ScanDependencies(const char* targetDir,
- std::map<std::string, cmDepends::DependencyVector>& validDeps)
+bool cmLocalUnixMakefileGenerator3::ScanDependencies(
+ const char* targetDir,
+ std::map<std::string, cmDepends::DependencyVector>& validDeps)
{
// Read the directory information file.
cmMakefile* mf = this->Makefile;
bool haveDirectoryInfo = false;
- std::string dirInfoFile = this->Makefile->GetStartOutputDirectory();
+ std::string dirInfoFile = this->GetCurrentBinaryDirectory();
dirInfoFile += cmake::GetCMakeFilesDirectory();
dirInfoFile += "/CMakeDirectoryInformation.cmake";
- if(mf->ReadListFile(0, dirInfoFile.c_str()) &&
- !cmSystemTools::GetErrorOccuredFlag())
- {
+ if (mf->ReadListFile(dirInfoFile.c_str()) &&
+ !cmSystemTools::GetErrorOccuredFlag()) {
haveDirectoryInfo = true;
- }
+ }
// Lookup useful directory information.
- if(haveDirectoryInfo)
- {
+ 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 (const char* force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) {
+ if (!cmSystemTools::IsOff(force)) {
cmSystemTools::SetForceUnixPaths(true);
- }
}
+ }
// Setup relative path top directories.
- this->RelativePathsConfigured = true;
- if(const char* relativePathTopSource =
- mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"))
- {
- this->RelativePathTopSource = relativePathTopSource;
- }
- if(const char* relativePathTopBinary =
- mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"))
- {
- this->RelativePathTopBinary = relativePathTopBinary;
- }
+ if (const char* relativePathTopSource =
+ mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) {
+ this->StateSnapshot.GetDirectory().SetRelativePathTopSource(
+ relativePathTopSource);
}
- else
- {
- cmSystemTools::Error("Directory Information file not found");
+ if (const char* relativePathTopBinary =
+ mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) {
+ this->StateSnapshot.GetDirectory().SetRelativePathTopBinary(
+ relativePathTopBinary);
}
+ } else {
+ cmSystemTools::Error("Directory Information file not found");
+ }
// create the file stream for the depends file
std::string dir = targetDir;
@@ -1555,133 +1427,132 @@ cmLocalUnixMakefileGenerator3
// because the make tool may try to reload it needlessly otherwise.
std::string ruleFileNameFull = dir;
ruleFileNameFull += "/depend.make";
- cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
+ cmGeneratedFileStream ruleFileStream(
+ ruleFileNameFull.c_str(), false,
+ this->GlobalGenerator->GetMakefileEncoding());
ruleFileStream.SetCopyIfDifferent(true);
- if(!ruleFileStream)
- {
+ if (!ruleFileStream) {
return false;
- }
+ }
// 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());
- if(!internalRuleFileStream)
- {
+ cmGeneratedFileStream internalRuleFileStream(
+ internalRuleFileNameFull.c_str(), false,
+ this->GlobalGenerator->GetMakefileEncoding());
+ if (!internalRuleFileStream) {
return false;
- }
+ }
this->WriteDisclaimer(ruleFileStream);
this->WriteDisclaimer(internalRuleFileStream);
// for each language we need to scan, scan it
- const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
+ 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)
- {
+ for (std::vector<std::string>::iterator li = langs.begin();
+ li != langs.end(); ++li) {
// construct the checker
- std::string lang = li->c_str();
+ std::string lang = *li;
// Create the scanner for this language
- cmDepends *scanner = 0;
- if(lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM")
- {
+ cmDepends* scanner = CM_NULLPTR;
+ if (lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM" ||
+ lang == "CUDA") {
// TODO: Handle RC (resource files) dependencies correctly.
- scanner = new cmDependsC(this, targetDir, lang.c_str(), &validDeps);
- }
+ scanner = new cmDependsC(this, targetDir, lang, &validDeps);
+ }
#ifdef CMAKE_BUILD_WITH_CMAKE
- else if(lang == "Fortran")
- {
+ else if (lang == "Fortran") {
scanner = new cmDependsFortran(this);
- }
- else if(lang == "Java")
- {
+ } else if (lang == "Java") {
scanner = new cmDependsJava();
- }
+ }
#endif
- if (scanner)
- {
+ if (scanner) {
scanner->SetLocalGenerator(this);
- scanner->SetFileComparison
- (this->GlobalGenerator->GetCMakeInstance()->GetFileComparison());
- scanner->SetLanguage(lang.c_str());
+ scanner->SetFileComparison(
+ this->GlobalGenerator->GetCMakeInstance()->GetFileComparison());
+ scanner->SetLanguage(lang);
scanner->SetTargetDirectory(dir.c_str());
scanner->Write(ruleFileStream, internalRuleFileStream);
// free the scanner for this language
delete scanner;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
{
cmMakefile* mf = this->Makefile;
// Get the string listing the multiple output pairs.
const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
- if(!pairs_string)
- {
+ if (!pairs_string) {
return;
- }
+ }
// 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();)
- {
+ for (std::vector<std::string>::const_iterator 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(verbose)
- {
- cmOStringStream msg;
+ if (cmSystemTools::FileExists(dependee.c_str()) &&
+ !cmSystemTools::FileExists(depender.c_str())) {
+ if (verbose) {
+ std::ostringstream msg;
msg << "Deleting primary custom command output \"" << dependee
- << "\" because another output \""
- << depender << "\" does not exist." << std::endl;
+ << "\" because another output \"" << depender
+ << "\" does not exist." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
- }
- cmSystemTools::RemoveFile(dependee.c_str());
}
+ cmSystemTools::RemoveFile(dependee);
}
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3
-::WriteLocalAllRules(std::ostream& ruleFileStream)
+void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
+ std::ostream& ruleFileStream)
{
this->WriteDisclaimer(ruleFileStream);
// Write the main entry point target. This must be the VERY first
// target so that make with no arguments will run it.
{
- // 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");
+ // 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");
- // Write the rule.
- this->WriteMakeRule(ruleFileStream,
- "Default target executed when no arguments are "
- "given to make.",
- "default_target",
- depends,
- no_commands, true);
+ // Write the rule.
+ this->WriteMakeRule(ruleFileStream,
+ "Default target executed when no arguments are "
+ "given to make.",
+ "default_target", depends, no_commands, true);
+
+ // Help out users that try "gmake target1 target2 -j".
+ cmGlobalUnixMakefileGenerator3* gg =
+ 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.",
+ ".NOTPARALLEL", no_depends, no_commands, false);
+ }
}
this->WriteSpecialTargetsTop(ruleFileStream);
@@ -1689,131 +1560,109 @@ void cmLocalUnixMakefileGenerator3
// Include the progress variables for the target.
// Write all global targets
this->WriteDivider(ruleFileStream);
- ruleFileStream
- << "# Targets provided globally by CMake.\n"
- << "\n";
- cmTargets* targets = &(this->Makefile->GetTargets());
- cmTargets::iterator glIt;
- for ( glIt = targets->begin(); glIt != targets->end(); ++ glIt )
- {
- if ( glIt->second.GetType() == cmTarget::GLOBAL_TARGET )
- {
- std::string targetString = "Special rule for the target " + glIt->first;
+ 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) {
+ std::string targetString =
+ "Special rule for the target " + (*glIt)->GetName();
std::vector<std::string> commands;
std::vector<std::string> depends;
- const char* text = glIt->second.GetProperty("EchoString");
- if ( !text )
- {
+ const char* text = (*glIt)->GetProperty("EchoString");
+ if (!text) {
text = "Running external command ...";
- }
- std::set<cmStdString>::const_iterator dit;
- for ( dit = glIt->second.GetUtilities().begin();
- dit != glIt->second.GetUtilities().end();
- ++ dit )
- {
- depends.push_back(dit->c_str());
- }
+ }
+ depends.insert(depends.end(), (*glIt)->GetUtilities().begin(),
+ (*glIt)->GetUtilities().end());
this->AppendEcho(commands, text,
cmLocalUnixMakefileGenerator3::EchoGlobal);
+ cmGeneratorTarget* gt = *glIt;
+
// Global targets store their rules in pre- and post-build commands.
- this->AppendCustomDepends(depends,
- glIt->second.GetPreBuildCommands());
- this->AppendCustomDepends(depends,
- glIt->second.GetPostBuildCommands());
- this->AppendCustomCommands(commands,
- glIt->second.GetPreBuildCommands(),
- &glIt->second,
- cmLocalGenerator::START_OUTPUT);
- this->AppendCustomCommands(commands,
- glIt->second.GetPostBuildCommands(),
- &glIt->second,
- cmLocalGenerator::START_OUTPUT);
- std::string targetName = glIt->second.GetName();
- this->WriteMakeRule(ruleFileStream, targetString.c_str(),
- targetName.c_str(), depends, commands, true);
+ this->AppendCustomDepends(depends, gt->GetPreBuildCommands());
+ this->AppendCustomDepends(depends, gt->GetPostBuildCommands());
+ this->AppendCustomCommands(commands, gt->GetPreBuildCommands(), gt,
+ this->GetCurrentBinaryDirectory());
+ this->AppendCustomCommands(commands, gt->GetPostBuildCommands(), gt,
+ this->GetCurrentBinaryDirectory());
+ std::string targetName = gt->GetName();
+ this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName,
+ depends, commands, true);
// Provide a "/fast" version of the target.
depends.clear();
- if((targetName == "install")
- || (targetName == "install_local")
- || (targetName == "install_strip"))
- {
+ if ((targetName == "install") || (targetName == "install/local") ||
+ (targetName == "install/strip")) {
// Provide a fast install target that does not depend on all
// but has the same command.
depends.push_back("preinstall/fast");
- }
- else
- {
+ } else {
// Just forward to the real target so at least it will work.
depends.push_back(targetName);
commands.clear();
- }
- targetName += "/fast";
- this->WriteMakeRule(ruleFileStream, targetString.c_str(),
- targetName.c_str(), depends, commands, true);
}
+ targetName += "/fast";
+ this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName,
+ depends, commands, true);
}
+ }
std::vector<std::string> depends;
std::vector<std::string> commands;
// Write the all rule.
- std::string dir;
- std::string recursiveTarget = this->Makefile->GetStartOutputDirectory();
+ std::string recursiveTarget = this->GetCurrentBinaryDirectory();
recursiveTarget += "/all";
depends.push_back("cmake_check_build_system");
- std::string progressDir = this->Makefile->GetHomeOutputDirectory();
+ std::string progressDir = this->GetBinaryDirectory();
progressDir += cmake::GetCMakeFilesDirectory();
- {
- cmOStringStream progCmd;
- progCmd <<
- "$(CMAKE_COMMAND) -E cmake_progress_start ";
- progCmd << this->Convert(progressDir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
+ {
+ 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 progressFileNameFull =
- this->ConvertToFullPath(progressFile.c_str());
- progCmd << " " << this->Convert(progressFileNameFull.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
+ std::string progressFileNameFull = this->ConvertToFullPath(progressFile);
+ progCmd << " "
+ << this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(progressFileNameFull),
+ cmOutputConverter::SHELL);
commands.push_back(progCmd.str());
- }
+ }
std::string mf2Dir = cmake::GetCMakeFilesDirectoryPostSlash();
mf2Dir += "Makefile2";
- commands.push_back(this->GetRecursiveMakeCall(mf2Dir.c_str(),
- recursiveTarget.c_str()));
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
- {
- cmOStringStream progCmd;
+ commands.push_back(
+ this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget));
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
+ {
+ std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
- progCmd << this->Convert(progressDir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
+ progCmd << this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL);
progCmd << " 0";
commands.push_back(progCmd.str());
- }
- this->WriteMakeRule(ruleFileStream, "The main all target", "all",
- depends, commands, true);
+ }
+ this->WriteMakeRule(ruleFileStream, "The main all target", "all", depends,
+ commands, true);
// Write the clean rule.
- recursiveTarget = this->Makefile->GetStartOutputDirectory();
+ recursiveTarget = this->GetCurrentBinaryDirectory();
recursiveTarget += "/clean";
commands.clear();
depends.clear();
- commands.push_back(this->GetRecursiveMakeCall(mf2Dir.c_str(),
- recursiveTarget.c_str()));
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
+ commands.push_back(
+ this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget));
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "The main clean target", "clean",
depends, commands, true);
commands.clear();
@@ -1823,27 +1672,23 @@ void cmLocalUnixMakefileGenerator3
depends, commands, true);
// Write the preinstall rule.
- recursiveTarget = this->Makefile->GetStartOutputDirectory();
+ recursiveTarget = this->GetCurrentBinaryDirectory();
recursiveTarget += "/preinstall";
commands.clear();
depends.clear();
const char* noall =
this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
- if(!noall || cmSystemTools::IsOff(noall))
- {
+ if (!noall || cmSystemTools::IsOff(noall)) {
// Drive the build before installing.
depends.push_back("all");
- }
- else
- {
+ } else {
// At least make sure the build system is up to date.
depends.push_back("cmake_check_build_system");
- }
- commands.push_back
- (this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget.c_str()));
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
+ }
+ commands.push_back(
+ this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget));
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
"preinstall", depends, commands, true);
depends.clear();
@@ -1858,29 +1703,24 @@ void cmLocalUnixMakefileGenerator3
std::string runRule =
"$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
runRule += " --check-build-system ";
- runRule += this->Convert(cmakefileName.c_str(),cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
+ runRule +=
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
runRule += " 1";
commands.push_back(runRule);
- this->CreateCDCommand(commands,
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::START_OUTPUT);
- this->WriteMakeRule(ruleFileStream, "clear depends",
- "depend",
- depends, commands, true);
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
+ this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
+ commands, true);
}
-
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
bool verbose)
{
// Get the list of target files to check
const char* infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES");
- if(!infoDef)
- {
+ if (!infoDef) {
return;
- }
+ }
std::vector<std::string> files;
cmSystemTools::ExpandListArgument(infoDef, files);
@@ -1888,10 +1728,9 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
// 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->c_str());
+ for (std::vector<std::string>::iterator l = files.begin(); l != files.end();
+ ++l) {
+ std::string dir = cmSystemTools::GetFilenamePath(*l);
// Clear the implicit dependency makefile.
std::string dependFile = dir + "/depend.make";
@@ -1900,13 +1739,61 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
// Remove the internal dependency check file to force
// regeneration.
std::string internalDependFile = dir + "/depend.internal";
- cmSystemTools::RemoveFile(internalDependFile.c_str());
- }
+ cmSystemTools::RemoveFile(internalDependFile);
+ }
}
+namespace {
+// Helper predicate for removing absolute paths that don't point to the
+// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
+// is set ON, to only consider in-project dependencies during the build.
+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)
+ {
+ }
+
+ // Operator evaluating the predicate
+ bool operator()(const std::string& path) const
+ {
+ // Keep all relative paths:
+ if (!cmSystemTools::FileIsFullPath(path)) {
+ return false;
+ }
+ // If it's an absolute path, check if it starts with the source
+ // direcotory:
+ return (
+ !(IsInDirectory(SourceDir, path) || IsInDirectory(BinaryDir, path)));
+ }
+
+private:
+ // Helper function used by the predicate
+ static bool IsInDirectory(const std::string& baseDir,
+ const std::string& testDir)
+ {
+ // First check if the test directory "starts with" the base directory:
+ if (testDir.find(baseDir) != 0) {
+ return false;
+ }
+ // If it does, then check that it's either the same string, or that the
+ // next character is a slash:
+ return ((testDir.size() == baseDir.size()) ||
+ (testDir[baseDir.size()] == '/'));
+ }
+
+ // The path to the source directory
+ std::string SourceDir;
+ // The path to the binary directory
+ std::string BinaryDir;
+};
+}
-void cmLocalUnixMakefileGenerator3
-::WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &target)
+void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
+ std::ostream& cmakefileStream, cmGeneratorTarget* target)
{
ImplicitDependLanguageMap const& implicitLangs =
this->GetImplicitDepends(target);
@@ -1914,258 +1801,254 @@ void cmLocalUnixMakefileGenerator3
// list the languages
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.c_str() << "\"\n";
- }
+ cmakefileStream << "set(CMAKE_DEPENDS_LANGUAGES\n";
+ for (ImplicitDependLanguageMap::const_iterator l = implicitLangs.begin();
+ l != implicitLangs.end(); ++l) {
+ cmakefileStream << " \"" << l->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.c_str() << "\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 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)
- {
+ 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";
- }
}
+ }
cmakefileStream << " )\n";
// Tell the dependency scanner what compiler is used.
std::string cidVar = "CMAKE_";
cidVar += l->first;
cidVar += "_COMPILER_ID";
- const char* cid = this->Makefile->GetDefinition(cidVar.c_str());
- if(cid && *cid)
- {
- cmakefileStream
- << "SET(CMAKE_" << l->first.c_str() << "_COMPILER_ID \""
- << cid << "\")\n";
- }
+ const char* cid = this->Makefile->GetDefinition(cidVar);
+ if (cid && *cid) {
+ cmakefileStream << "set(CMAKE_" << l->first << "_COMPILER_ID \"" << cid
+ << "\")\n";
}
- // Build a list of preprocessor definitions for the target.
- std::set<std::string> defines;
- this->AddCompileDefinitions(defines, &target,
- this->ConfigurationName.c_str());
- if(!defines.empty())
- {
- cmakefileStream
- << "\n"
- << "# Preprocessor definitions for this target.\n"
- << "SET(CMAKE_TARGET_DEFINITIONS\n";
- for(std::set<std::string>::const_iterator di = defines.begin();
- di != defines.end(); ++di)
- {
+ // Build a list of preprocessor definitions for the target.
+ std::set<std::string> defines;
+ this->AddCompileDefinitions(defines, target, this->ConfigName, l->first);
+ if (!defines.empty()) {
+ /* clang-format off */
cmakefileStream
- << " " << this->EscapeForCMake(di->c_str()) << "\n";
+ << "\n"
+ << "# Preprocessor definitions for this target.\n"
+ << "set(CMAKE_TARGET_DEFINITIONS_" << l->first << "\n";
+ /* clang-format on */
+ for (std::set<std::string>::const_iterator di = defines.begin();
+ di != defines.end(); ++di) {
+ cmakefileStream << " " << cmOutputConverter::EscapeForCMake(*di)
+ << "\n";
}
- cmakefileStream
- << " )\n";
+ cmakefileStream << " )\n";
}
+ // Target-specific include directories:
+ cmakefileStream << "\n"
+ << "# The include file search paths:\n";
+ cmakefileStream << "set(CMAKE_" << l->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);
+ std::string binaryDir = this->GetState()->GetBinaryDirectory();
+ if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
+ const char* sourceDir = this->GetState()->GetSourceDirectory();
+ cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir));
+ }
+ for (std::vector<std::string>::iterator i = includes.begin();
+ i != includes.end(); ++i) {
+ cmakefileStream << " \""
+ << this->MaybeConvertToRelativePath(binaryDir, *i)
+ << "\"\n";
+ }
+ cmakefileStream << " )\n";
+ }
+
// Store include transform rule properties. Write the directory
// rules first because they may be overridden by later target rules.
std::vector<std::string> transformRules;
- if(const char* xform =
- this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"))
- {
+ if (const char* xform =
+ this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
cmSystemTools::ExpandListArgument(xform, transformRules);
- }
- if(const char* xform =
- target.GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"))
- {
+ }
+ if (const char* xform =
+ target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
cmSystemTools::ExpandListArgument(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";
}
- if(!transformRules.empty())
- {
- cmakefileStream
- << "SET(CMAKE_INCLUDE_TRANSFORMS\n";
- for(std::vector<std::string>::const_iterator tri = transformRules.begin();
- tri != transformRules.end(); ++tri)
- {
- cmakefileStream << " " << this->EscapeForCMake(tri->c_str()) << "\n";
- }
- cmakefileStream
- << " )\n";
- }
+ cmakefileStream << " )\n";
+ }
}
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
{
- os
- << "# CMAKE generated file: DO NOT EDIT!\n"
- << "# Generated by \"" << this->GlobalGenerator->GetName() << "\""
- << " Generator, CMake Version "
- << cmVersion::GetMajorVersion() << "."
- << cmVersion::GetMinorVersion() << "\n\n";
+ os << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Generated by \"" << this->GlobalGenerator->GetName() << "\""
+ << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << "\n\n";
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::GetRecursiveMakeCall(const char *makefile, const char* tgt)
+std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
+ const char* makefile, const std::string& tgt)
{
// Call make on the given file.
std::string cmd;
cmd += "$(MAKE) -f ";
- cmd += this->Convert(makefile,NONE,SHELL);
+ cmd += this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL);
cmd += " ";
+ cmGlobalUnixMakefileGenerator3* gg =
+ static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
// Pass down verbosity level.
- if(this->GetMakeSilentFlag().size())
- {
- cmd += this->GetMakeSilentFlag();
+ if (!gg->MakeSilentFlag.empty()) {
+ cmd += gg->MakeSilentFlag;
cmd += " ";
- }
+ }
// Most unix makes will pass the command line flags to make down to
// sub-invoked makes via an environment variable. However, some
// makes do not support that, so you have to pass the flags
// explicitly.
- if(this->GetPassMakeflags())
- {
+ if (gg->PassMakeflags) {
cmd += "-$(MAKEFLAGS) ";
- }
+ }
// Add the target.
- if (tgt && tgt[0] != '\0')
- {
+ if (!tgt.empty()) {
// The make target is always relative to the top of the build tree.
- std::string tgt2 = this->Convert(tgt, HOME_OUTPUT);
+ std::string tgt2 =
+ this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), tgt);
// The target may have been written with windows paths.
cmSystemTools::ConvertToOutputSlashes(tgt2);
// Escape one extra time if the make tool requires it.
- if(this->MakeCommandEscapeTargetTwice)
- {
- tgt2 = this->EscapeForShell(tgt2.c_str(), true, false);
- }
+ if (this->MakeCommandEscapeTargetTwice) {
+ tgt2 = this->EscapeForShell(tgt2, true, false);
+ }
// The target name is now a string that should be passed verbatim
// on the command line.
- cmd += this->EscapeForShell(tgt2.c_str(), true, false);
- }
+ cmd += this->EscapeForShell(tgt2, true, false);
+ }
return cmd;
}
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream& os)
{
- os
- << "#======================================"
- << "=======================================\n";
+ os << "#======================================"
+ << "=======================================\n";
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteCMakeArgument(std::ostream& os, const char* s)
+void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os,
+ const char* s)
{
// Write the given string to the stream with escaping to get it back
// into CMake through the lexical scanner.
os << "\"";
- for(const char* c = s; *c; ++c)
- {
- if(*c == '\\')
- {
+ for (const char* c = s; *c; ++c) {
+ if (*c == '\\') {
os << "\\\\";
- }
- else if(*c == '"')
- {
+ } else if (*c == '"') {
os << "\\\"";
- }
- else
- {
+ } else {
os << *c;
- }
}
+ }
os << "\"";
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(const char* p)
+std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
+ const char* p, bool useWatcomQuote)
{
-
// Split the path into its components.
std::vector<std::string> components;
cmSystemTools::SplitPath(p, components);
- // Return an empty path if there are no components.
- if(components.empty())
- {
- return "\"\"";
- }
-
- // Choose a slash direction and fix root component.
- const char* slash = "/";
+ // Open the quoted result.
+ std::string result;
+ if (useWatcomQuote) {
#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 = '\\';
- }
- }
- }
+ result = "'";
+#else
+ result = "\"'";
#endif
+ } else {
+ result = "\"";
+ }
- // Begin the quoted result with the root component.
- std::string result = "\"";
- result += components[0];
-
- // Now add the rest of the components separated by the proper slash
- // direction for this platform.
- bool first = true;
- for(unsigned int i=1; i < components.size(); ++i)
- {
- // Only the last component can be empty to avoid double slashes.
- if(components[i].length() > 0 || (i == (components.size()-1)))
- {
- if(!first)
- {
- result += slash;
+ // Return an empty path if there are no components.
+ if (!components.empty()) {
+ // Choose a slash direction and fix root component.
+ const char* slash = "/";
+#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 = '\\';
}
- result += components[i];
- first = false;
}
}
+#endif
+
+ // Begin the quoted result with the root component.
+ result += components[0];
+
+ 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;
+ result += cmJoin(cmMakeRange(compStart, compEnd), slash);
+ // Only the last component can be empty to avoid double slashes.
+ result += slash;
+ result += components.back();
+ }
+ }
// Close the quoted result.
- result += "\"";
+ if (useWatcomQuote) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ result += "'";
+#else
+ result += "'\"";
+#endif
+ } else {
+ result += "\"";
+ }
return result;
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::GetTargetDirectory(cmTarget const& target) const
+std::string cmLocalUnixMakefileGenerator3::GetTargetDirectory(
+ cmGeneratorTarget const* target) const
{
std::string dir = cmake::GetCMakeFilesDirectoryPostSlash();
- dir += target.GetName();
+ dir += target->GetName();
#if defined(__VMS)
dir += "_dir";
#else
@@ -2174,69 +2057,65 @@ cmLocalUnixMakefileGenerator3
return dir;
}
-//----------------------------------------------------------------------------
cmLocalUnixMakefileGenerator3::ImplicitDependLanguageMap const&
-cmLocalUnixMakefileGenerator3::GetImplicitDepends(cmTarget const& tgt)
+cmLocalUnixMakefileGenerator3::GetImplicitDepends(const cmGeneratorTarget* tgt)
{
- return this->ImplicitDepends[tgt.GetName()];
+ return this->ImplicitDepends[tgt->GetName()];
}
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3::AddImplicitDepends(cmTarget const& tgt,
- const char* lang,
- const char* obj,
- const char* src)
+void cmLocalUnixMakefileGenerator3::AddImplicitDepends(
+ const cmGeneratorTarget* tgt, const std::string& lang, const char* obj,
+ const char* src)
{
- this->ImplicitDepends[tgt.GetName()][lang][obj].push_back(src);
+ this->ImplicitDepends[tgt->GetName()][lang][obj].push_back(src);
}
-//----------------------------------------------------------------------------
-void cmLocalUnixMakefileGenerator3
-::CreateCDCommand(std::vector<std::string>& commands, const char *tgtDir,
- cmLocalGenerator::RelativeRoot relRetDir)
+void cmLocalUnixMakefileGenerator3::CreateCDCommand(
+ std::vector<std::string>& commands, const char* tgtDir,
+ std::string const& relDir)
{
- const char* retDir = this->GetRelativeRootPath(relRetDir);
-
// do we need to cd?
- if (!strcmp(tgtDir,retDir))
- {
+ if (tgtDir == relDir) {
return;
- }
+ }
// In a Windows shell we must change drive letter too. The shell
// used by NMake and Borland make does not support "cd /d" so this
// feature simply cannot work with them (Borland make does not even
// support changing the drive letter with just "d:").
- const char* cd_cmd = this->MinGWMake? "cd /d " : "cd ";
+ const char* cd_cmd = this->IsMinGWMake() ? "cd /d " : "cd ";
- if(!this->UnixCD)
- {
+ cmGlobalUnixMakefileGenerator3* gg =
+ static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
+ if (!gg->UnixCD) {
// 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, relRetDir);
- commands.insert(commands.begin(),cmd);
+ cmd += this->ConvertToOutputForExisting(tgtDir);
+ commands.insert(commands.begin(), cmd);
// Change back to the starting directory.
cmd = cd_cmd;
- cmd += this->ConvertToOutputForExisting(relRetDir, tgtDir);
+ cmd += this->ConvertToOutputForExisting(relDir);
commands.push_back(cmd);
- }
- else
- {
+ } else {
// On UNIX we must construct a single shell command to change
// directory and build because make resets the directory between
// each command.
- std::vector<std::string>::iterator i = commands.begin();
- for (; i != commands.end(); ++i)
- {
- std::string cmd = cd_cmd;
- cmd += this->ConvertToOutputForExisting(tgtDir, relRetDir);
- cmd += " && ";
- cmd += *i;
- *i = cmd;
- }
- }
+ 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;
+ }
+ return cmOutputConverter::ForceToRelativePath(base, path);
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 703369e1c..f64409cba 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -1,27 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalUnixMakefileGenerator3_h
#define cmLocalUnixMakefileGenerator3_h
-#include "cmLocalGenerator.h"
+#include "cmConfigure.h"
-// for cmDepends::DependencyVector
#include "cmDepends.h"
+#include "cmLocalCommonGenerator.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
class cmCustomCommand;
-class cmDependInformation;
-class cmDepends;
-class cmMakefileTargetGenerator;
-class cmTarget;
+class cmCustomCommandGenerator;
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
class cmSourceFile;
/** \class cmLocalUnixMakefileGenerator3
@@ -30,133 +27,52 @@ class cmSourceFile;
* cmLocalUnixMakefileGenerator3 produces a LocalUnix makefile from its
* member Makefile.
*/
-class cmLocalUnixMakefileGenerator3 : public cmLocalGenerator
+class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator
{
public:
- cmLocalUnixMakefileGenerator3();
- virtual ~cmLocalUnixMakefileGenerator3();
+ cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf);
+ ~cmLocalUnixMakefileGenerator3() CM_OVERRIDE;
- /**
- * Process the CMakeLists files for this directory to fill in the
- * Makefile ivar
- */
- virtual void Configure();
+ void ComputeHomeRelativeOutputPath() CM_OVERRIDE;
/**
* Generate the makefile for this directory.
*/
- virtual void Generate();
-
+ void Generate() CM_OVERRIDE;
// this returns the relative path between the HomeOutputDirectory and this
// local generators StartOutputDirectory
- const std::string &GetHomeRelativeOutputPath();
+ const std::string& GetHomeRelativeOutputPath();
// Write out a make rule
- void WriteMakeRule(std::ostream& os,
- const char* comment,
- const char* target,
+ void WriteMakeRule(std::ostream& os, const char* comment,
+ const std::string& target,
const std::vector<std::string>& depends,
- const std::vector<std::string>& commands,
- bool symbolic,
+ const std::vector<std::string>& commands, bool symbolic,
bool in_help = false);
// write the main variables used by the makefiles
void WriteMakeVariables(std::ostream& makefileStream);
/**
- * If true, then explicitly pass MAKEFLAGS on the make all target for makes
- * that do not use environment variables.
- *
- */
- void SetPassMakeflags(bool s){this->PassMakeflags = s;}
- bool GetPassMakeflags() { return this->PassMakeflags; }
-
- /**
- * Set the flag used to keep the make program silent.
- */
- void SetMakeSilentFlag(const char* s) { this->MakeSilentFlag = s; }
- std::string &GetMakeSilentFlag() { return this->MakeSilentFlag; }
-
- /**
- * Set to true if the shell being used is the windows shell.
- * This controls if statements in the makefile and the SHELL variable.
- * The default is false.
- */
- void SetWindowsShell(bool v) {this->WindowsShell = v;}
-
- /**
- * Set to true if the make tool being used is Watcom WMake.
- */
- void SetWatcomWMake(bool v) {this->WatcomWMake = v;}
-
- /**
- * Set to true if the make tool being used is MinGW Make.
- */
- void SetMinGWMake(bool v) {this->MinGWMake = v;}
-
- /**
- * Set to true if the make tool being used is NMake.
- */
- void SetNMake(bool v) {this->NMake = v;}
-
- /**
- * Set to true if the shell being used is the MSYS shell.
- * This controls if statements in the makefile and the SHELL variable.
- * The default is false.
- */
- void SetMSYSShell(bool v) {this->MSYSShell = v;}
-
- /**
- * If set to true, then NULL is set to nil for non Windows_NT.
- * This uses make syntax used by nmake and borland.
- * The default is false.
- */
- void SetDefineWindowsNULL(bool v) {this->DefineWindowsNULL = v;}
-
- /**
- * If set to true, cd dir && command is used to
- * run commands in a different directory.
- */
- void SetUnixCD(bool v) {this->UnixCD = v;}
-
- /**
- * Set Support Verbose Variable. If true, then .SILENT will
- * be not end with : i.e. .SILENT: or .SILENT
- */
- void SetSilentNoColon(bool v) {this->SilentNoColon = v;}
-
- /**
- * Set the string used to include one makefile into another default
- * is include.
- */
- void SetIncludeDirective(const char* s) { this->IncludeDirective = s; }
- const char *GetIncludeDirective() { return this->IncludeDirective.c_str(); }
-
- /**
* Set max makefile variable size, default is 0 which means unlimited.
*/
void SetMakefileVariableSize(int s) { this->MakefileVariableSize = s; }
/**
- * If ignore lib prefix is true, then do not strip lib from the name
- * of a library.
- */
- void SetIgnoreLibPrefix(bool s) { this->IgnoreLibPrefix = s; }
-
- /**
* Set whether passing a make target on a command line requires an
* extra level of escapes.
*/
void SetMakeCommandEscapeTargetTwice(bool b)
- { this->MakeCommandEscapeTargetTwice = b; }
+ {
+ this->MakeCommandEscapeTargetTwice = b;
+ }
/**
* Set whether the Borland curly brace command line hack should be
* applied.
*/
- void SetBorlandMakeCurlyHack(bool b)
- { this->BorlandMakeCurlyHack = b; }
+ void SetBorlandMakeCurlyHack(bool b) { this->BorlandMakeCurlyHack = b; }
// used in writing out Cmake files such as WriteDirectoryInformation
static void WriteCMakeArgument(std::ostream& os, const char* s);
@@ -168,101 +84,122 @@ public:
void WriteDivider(std::ostream& os);
/** used to create a recursive make call */
- std::string GetRecursiveMakeCall(const char *makefile, const char* tgt);
+ std::string GetRecursiveMakeCall(const char* makefile,
+ const std::string& tgt);
// append flags to a string
- virtual void AppendFlags(std::string& flags, const char* newFlags);
+ void AppendFlags(std::string& flags,
+ const std::string& newFlags) CM_OVERRIDE;
+ void AppendFlags(std::string& flags, const char* newFlags) CM_OVERRIDE;
// append an echo command
- enum EchoColor { EchoNormal, EchoDepend, EchoBuild, EchoLink,
- EchoGenerate, EchoGlobal };
- void AppendEcho(std::vector<std::string>& commands, const char* text,
- EchoColor color = EchoNormal);
+ enum EchoColor
+ {
+ EchoNormal,
+ EchoDepend,
+ EchoBuild,
+ EchoLink,
+ EchoGenerate,
+ EchoGlobal
+ };
+ struct EchoProgress
+ {
+ std::string Dir;
+ std::string Arg;
+ };
+ void AppendEcho(std::vector<std::string>& commands, std::string const& text,
+ EchoColor color = EchoNormal,
+ EchoProgress const* = CM_NULLPTR);
/** Get whether the makefile is to have color. */
bool GetColorMakefile() const { return this->ColorMakefile; }
- virtual std::string GetTargetDirectory(cmTarget const& target) const;
+ std::string GetTargetDirectory(cmGeneratorTarget const* target) const
+ CM_OVERRIDE;
- // create a command that cds to the start dir then runs the commands
+ // create a command that cds to the start dir then runs the commands
void CreateCDCommand(std::vector<std::string>& commands,
- const char *targetDir,
- cmLocalGenerator::RelativeRoot returnDir);
+ const char* targetDir, std::string const& relDir);
- static std::string ConvertToQuotedOutputPath(const char* p);
+ static std::string ConvertToQuotedOutputPath(const char* p,
+ bool useWatcomQuote);
- std::string CreateMakeVariable(const char* sin, const char* s2in);
+ std::string CreateMakeVariable(const std::string& sin,
+ const std::string& s2in);
/** Called from command-line hook to bring dependencies up to date
for a target. */
- virtual bool UpdateDependencies(const char* tgtInfo,
- bool verbose, bool color);
+ bool UpdateDependencies(const char* tgtInfo, bool verbose,
+ bool color) CM_OVERRIDE;
/** Called from command-line hook to clear dependencies. */
- virtual void ClearDependencies(cmMakefile* mf, bool verbose);
+ void ClearDependencies(cmMakefile* mf, bool verbose) CM_OVERRIDE;
/** write some extra rules such as make test etc */
void WriteSpecialTargetsTop(std::ostream& makefileStream);
void WriteSpecialTargetsBottom(std::ostream& makefileStream);
- std::string GetRelativeTargetDirectory(cmTarget const& target);
+ std::string GetRelativeTargetDirectory(cmGeneratorTarget* target);
// 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<cmStdString, cmDepends::DependencyVector> {};
- struct ImplicitDependLanguageMap:
- public std::map<cmStdString, ImplicitDependFileMap> {};
- struct ImplicitDependTargetMap:
- public std::map<cmStdString, ImplicitDependLanguageMap> {};
- ImplicitDependLanguageMap const& GetImplicitDepends(cmTarget const& tgt);
-
- void AddImplicitDepends(cmTarget const& tgt, const char* lang,
- const char* obj, const char* src);
+ struct ImplicitDependFileMap
+ : public std::map<std::string, cmDepends::DependencyVector>
+ {
+ };
+ struct ImplicitDependLanguageMap
+ : public std::map<std::string, ImplicitDependFileMap>
+ {
+ };
+ struct ImplicitDependTargetMap
+ : public std::map<std::string, ImplicitDependLanguageMap>
+ {
+ };
+ ImplicitDependLanguageMap const& GetImplicitDepends(
+ cmGeneratorTarget const* tgt);
- void AppendGlobalTargetDepends(std::vector<std::string>& depends,
- cmTarget& target);
+ void AddImplicitDepends(cmGeneratorTarget const* tgt,
+ const std::string& lang, const char* obj,
+ const char* src);
// write the target rules for the local Makefile into the stream
void WriteLocalAllRules(std::ostream& ruleFileStream);
- void AddLocalObjectFile(cmTarget* target, cmSourceFile* sf,
- std::string objNoTargetDir,
- bool hasSourceExtension);
-
- std::vector<cmStdString> const& GetLocalHelp() { return this->LocalHelp; }
+ std::vector<std::string> const& GetLocalHelp() { return this->LocalHelp; }
/** Get whether to create rules to generate preprocessed and
assembly sources. This could be converted to a variable lookup
later. */
bool GetCreatePreprocessedSourceRules()
- {
+ {
return !this->SkipPreprocessedSourceRules;
- }
+ }
bool GetCreateAssemblySourceRules()
- {
+ {
return !this->SkipAssemblySourceRules;
- }
+ }
// Fill the vector with the target names for the object files,
// preprocessed files and assembly files. Currently only used by the
// Eclipse generator.
void GetIndividualFileTargets(std::vector<std::string>& targets);
+ std::string MaybeConvertToRelativePath(std::string const& base,
+ std::string const& path);
+
protected:
void WriteLocalMakefile();
-
// write the target rules for the local Makefile into the stream
void WriteLocalMakefileTargets(std::ostream& ruleFileStream,
- std::set<cmStdString> &emitted);
+ std::set<std::string>& emitted);
// this method Writes the Directory information files
void WriteDirectoryInformationFile();
-
// write the depend info
- void WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &tgt);
+ void WriteDependLanguageInfo(std::ostream& cmakefileStream,
+ cmGeneratorTarget* tgt);
// write the local help rule
void WriteHelpRule(std::ostream& ruleFileStream);
@@ -271,18 +208,17 @@ protected:
// into a full path
std::string ConvertToFullPath(const std::string& localPath);
-
void WriteConvenienceRule(std::ostream& ruleFileStream,
- const char* realTarget,
- const char* helpTarget);
+ const std::string& realTarget,
+ const std::string& helpTarget);
void WriteTargetDependRule(std::ostream& ruleFileStream,
- cmTarget& target);
+ cmGeneratorTarget* target);
void WriteTargetCleanRule(std::ostream& ruleFileStream,
- cmTarget& target,
+ cmGeneratorTarget* target,
const std::vector<std::string>& files);
void WriteTargetRequiresRule(std::ostream& ruleFileStream,
- cmTarget& target,
+ cmGeneratorTarget* target,
const std::vector<std::string>& objects);
void AppendRuleDepend(std::vector<std::string>& depends,
@@ -292,32 +228,34 @@ protected:
void AppendCustomDepends(std::vector<std::string>& depends,
const std::vector<cmCustomCommand>& ccs);
void AppendCustomDepend(std::vector<std::string>& depends,
- const cmCustomCommand& cc);
+ cmCustomCommandGenerator const& cc);
void AppendCustomCommands(std::vector<std::string>& commands,
const std::vector<cmCustomCommand>& ccs,
- cmTarget* target,
- cmLocalGenerator::RelativeRoot relative =
- cmLocalGenerator::HOME_OUTPUT);
+ cmGeneratorTarget* target,
+ std::string const& relative);
void AppendCustomCommand(std::vector<std::string>& commands,
- const cmCustomCommand& cc,
- cmTarget* target,
- bool echo_comment=false,
- cmLocalGenerator::RelativeRoot relative =
- cmLocalGenerator::HOME_OUTPUT,
- std::ostream* content = 0);
+ cmCustomCommandGenerator const& ccg,
+ cmGeneratorTarget* target,
+ std::string const& relative,
+ bool echo_comment = false,
+ std::ostream* content = CM_NULLPTR);
void AppendCleanCommand(std::vector<std::string>& commands,
const std::vector<std::string>& files,
- cmTarget& target, const char* filename =0);
+ cmGeneratorTarget* target,
+ const char* filename = CM_NULLPTR);
// Helper methods for dependeny updates.
- bool ScanDependencies(const char* targetDir,
- std::map<std::string, cmDepends::DependencyVector>& validDeps);
+ bool ScanDependencies(
+ const char* targetDir,
+ std::map<std::string, cmDepends::DependencyVector>& validDeps);
void CheckMultipleOutputs(bool verbose);
private:
- std::string ConvertShellCommand(std::string const& cmd, RelativeRoot root);
- std::string MakeLauncher(const cmCustomCommand& cc, cmTarget* target,
- RelativeRoot relative);
+ 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;
@@ -327,58 +265,54 @@ private:
ImplicitDependTargetMap ImplicitDepends;
- //==========================================================================
- // Configuration settings.
- int MakefileVariableSize;
- std::string IncludeDirective;
- std::string MakeSilentFlag;
- std::string ConfigurationName;
- bool DefineWindowsNULL;
- bool UnixCD;
- bool PassMakeflags;
- bool SilentNoColon;
- bool MakeCommandEscapeTargetTwice;
- bool BorlandMakeCurlyHack;
- //==========================================================================
-
std::string HomeRelativeOutputPath;
- /* Copy the setting of CMAKE_COLOR_MAKEFILE from the makefile at the
- beginning of generation to avoid many duplicate lookups. */
- bool ColorMakefile;
-
- /* Copy the setting of CMAKE_SKIP_PREPROCESSED_SOURCE_RULES and
- CMAKE_SKIP_ASSEMBLY_SOURCE_RULES at the beginning of generation to
- avoid many duplicate lookups. */
- bool SkipPreprocessedSourceRules;
- bool SkipAssemblySourceRules;
-
struct LocalObjectEntry
{
- cmTarget* Target;
+ cmGeneratorTarget* Target;
std::string Language;
- LocalObjectEntry(): Target(0), Language() {}
- LocalObjectEntry(cmTarget* t, const char* lang):
- Target(t), Language(lang) {}
+ LocalObjectEntry()
+ : Target(CM_NULLPTR)
+ , Language()
+ {
+ }
+ LocalObjectEntry(cmGeneratorTarget* t, const std::string& lang)
+ : Target(t)
+ , Language(lang)
+ {
+ }
};
- struct LocalObjectInfo: public std::vector<LocalObjectEntry>
+ struct LocalObjectInfo : public std::vector<LocalObjectEntry>
{
bool HasSourceExtension;
bool HasPreprocessRule;
bool HasAssembleRule;
- LocalObjectInfo():HasSourceExtension(false), HasPreprocessRule(false),
- HasAssembleRule(false) {}
+ LocalObjectInfo()
+ : HasSourceExtension(false)
+ , HasPreprocessRule(false)
+ , HasAssembleRule(false)
+ {
+ }
};
- std::map<cmStdString, LocalObjectInfo> LocalObjectFiles;
+ void GetLocalObjectFiles(
+ std::map<std::string, LocalObjectInfo>& localObjectFiles);
+
void WriteObjectConvenienceRule(std::ostream& ruleFileStream,
const char* comment, const char* output,
LocalObjectInfo const& info);
- std::vector<cmStdString> LocalHelp;
+ std::vector<std::string> LocalHelp;
/* does the work for each target */
- std::map<cmStdString, cmStdString> MakeVariableMap;
- std::map<cmStdString, cmStdString> ShortMakeVariableMap;
+ std::map<std::string, std::string> MakeVariableMap;
+ std::map<std::string, std::string> ShortMakeVariableMap;
+
+ int MakefileVariableSize;
+ bool MakeCommandEscapeTargetTwice;
+ bool BorlandMakeCurlyHack;
+ bool ColorMakefile;
+ bool SkipPreprocessedSourceRules;
+ bool SkipAssemblySourceRules;
};
#endif
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index c3789a022..85d4a73b7 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -1,68 +1,55 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudio10Generator.h"
-#include "cmTarget.h"
+
+#include "cmGeneratorTarget.h"
+#include "cmGlobalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmVisualStudio10TargetGenerator.h"
-#include "cmGlobalVisualStudio10Generator.h"
-#include <cm_expat.h>
#include "cmXMLParser.h"
+
+#include "cm_expat.h"
+
class cmVS10XMLParser : public cmXMLParser
{
- public:
- virtual void EndElement(const char* /* name */)
- {
- }
+public:
+ virtual void EndElement(const std::string& /* name */) {}
virtual void CharacterDataHandler(const char* data, int length)
- {
- if(this->DoGUID )
- {
- this->GUID.assign(data+1, length-2);
- this->DoGUID = false;
- }
+ {
+ if (this->DoGUID) {
+ this->GUID.assign(data + 1, length - 2);
+ this->DoGUID = false;
+ }
+ }
+ virtual void StartElement(const std::string& name, const char**)
+ {
+ // once the GUID is found do nothing
+ if (!this->GUID.empty()) {
+ return;
}
- virtual void StartElement(const char* name, const char**)
- {
- // once the GUID is found do nothing
- if(this->GUID.size())
- {
- return;
- }
- if(strcmp("ProjectGUID", name) == 0 || strcmp("ProjectGuid", name) == 0)
- {
- this->DoGUID = true;
- }
+ if ("ProjectGUID" == name || "ProjectGuid" == name) {
+ this->DoGUID = true;
}
+ }
int InitializeParser()
- {
- this->DoGUID = false;
- int ret = cmXMLParser::InitializeParser();
- if(ret == 0)
- {
- return ret;
- }
- // visual studio projects have a strange encoding, but it is
- // really utf-8
- XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8");
- return 1;
+ {
+ this->DoGUID = false;
+ int ret = cmXMLParser::InitializeParser();
+ if (ret == 0) {
+ return ret;
}
+ // visual studio projects have a strange encoding, but it is
+ // really utf-8
+ XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8");
+ return 1;
+ }
std::string GUID;
bool DoGUID;
};
-
-//----------------------------------------------------------------------------
-cmLocalVisualStudio10Generator::cmLocalVisualStudio10Generator(VSVersion v):
- cmLocalVisualStudio7Generator(v)
+cmLocalVisualStudio10Generator::cmLocalVisualStudio10Generator(
+ cmGlobalGenerator* gg, cmMakefile* mf)
+ : cmLocalVisualStudio7Generator(gg, mf)
{
}
@@ -73,51 +60,44 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
void cmLocalVisualStudio10Generator::Generate()
{
- cmTargets &tgts = this->Makefile->GetTargets();
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
- {
- if(static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(l->second))
- {
- this->CreateSingleVCProj(l->first.c_str(),l->second);
- }
- else
- {
+ 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->second, static_cast<cmGlobalVisualStudio10Generator*>(
- this->GetGlobalGenerator()));
+ *l, static_cast<cmGlobalVisualStudio10Generator*>(
+ this->GetGlobalGenerator()));
tg.Generate();
- }
}
+ }
this->WriteStampFiles();
}
-
-void cmLocalVisualStudio10Generator
-::ReadAndStoreExternalGUID(const char* name,
- const char* path)
+void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID(
+ const std::string& name, const char* path)
{
cmVS10XMLParser parser;
parser.ParseFile(path);
- // if we can not find a GUID then create one
- if(parser.GUID.empty())
- {
- this->GlobalGenerator->CreateGUID(name);
+ // if we can not find a GUID then we will generate one later
+ if (parser.GUID.empty()) {
return;
- }
+ }
std::string guidStoreName = name;
guidStoreName += "_GUID_CMAKE";
// save the GUID in the cache
- this->GlobalGenerator->GetCMakeInstance()->
- AddCacheEntry(guidStoreName.c_str(),
- parser.GUID.c_str(),
- "Stored GUID",
- cmCacheManager::INTERNAL);
+ this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
+ guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
+ cmStateEnums::INTERNAL);
}
-//----------------------------------------------------------------------------
const char* cmLocalVisualStudio10Generator::ReportErrorLabel() const
{
return ":VCEnd";
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index 41db735b2..e57dd8f20 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -1,19 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalVisualStudio10Generator_h
#define cmLocalVisualStudio10Generator_h
+#include "cmConfigure.h"
+
+#include <string>
+
#include "cmLocalVisualStudio7Generator.h"
+class cmGlobalGenerator;
+class cmMakefile;
/** \class cmLocalVisualStudio10Generator
* \brief Write Visual Studio 10 project files.
@@ -25,16 +22,15 @@ class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator
{
public:
///! Set cache only and recurse to false by default.
- cmLocalVisualStudio10Generator(VSVersion v);
+ cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudio10Generator();
-
/**
* Generate the makefile for this directory.
*/
virtual void Generate();
- virtual void ReadAndStoreExternalGUID(const char* name,
+ virtual void ReadAndStoreExternalGUID(const std::string& name,
const char* path);
protected:
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
deleted file mode 100644
index e5b4057d2..000000000
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ /dev/null
@@ -1,1956 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmGlobalGenerator.h"
-#include "cmLocalVisualStudio6Generator.h"
-#include "cmMakefile.h"
-#include "cmSystemTools.h"
-#include "cmSourceFile.h"
-#include "cmCacheManager.h"
-#include "cmGeneratorTarget.h"
-#include "cmake.h"
-
-#include "cmComputeLinkInformation.h"
-
-#include <cmsys/RegularExpression.hxx>
-
-cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator():
- cmLocalVisualStudioGenerator(VS6)
-{
-}
-
-cmLocalVisualStudio6Generator::~cmLocalVisualStudio6Generator()
-{
-}
-
-//----------------------------------------------------------------------------
-// Helper class to write build events.
-class cmLocalVisualStudio6Generator::EventWriter
-{
-public:
- EventWriter(cmLocalVisualStudio6Generator* lg,
- const char* config, std::string& code):
- LG(lg), Config(config), Code(code), First(true) {}
- void Start(const char* event)
- {
- this->First = true;
- this->Event = event;
- }
- void Finish()
- {
- this->Code += (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);
- }
- }
- void Write(cmCustomCommand const& cc)
- {
- if(this->First)
- {
- this->Code += this->Event + "_Cmds=";
- this->First = false;
- }
- else
- {
- this->Code += "\\\n\t";
- }
- this->Code += this->LG->ConstructScript(cc, this->Config, "\\\n\t");
- }
-private:
- cmLocalVisualStudio6Generator* LG;
- const char* Config;
- std::string& Code;
- bool First;
- std::string Event;
-};
-
-void cmLocalVisualStudio6Generator::AddHelperCommands()
-{
- std::set<cmStdString> lang;
- lang.insert("C");
- lang.insert("CXX");
- this->CreateCustomTargetsAndCommands(lang);
-}
-
-void cmLocalVisualStudio6Generator::AddCMakeListsRules()
-{
- cmTargets &tgts = this->Makefile->GetTargets();
- for(cmTargets::iterator l = tgts.begin();
- l != tgts.end(); l++)
- {
- // Add a rule to regenerate the build system when the target
- // specification source changes.
- const char* suppRegenRule =
- this->Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
- if (!cmSystemTools::IsOn(suppRegenRule))
- {
- this->AddDSPBuildRule(l->second);
- }
- }
-}
-
-void cmLocalVisualStudio6Generator::Generate()
-{
- this->OutputDSPFile();
-}
-
-void cmLocalVisualStudio6Generator::OutputDSPFile()
-{
- // If not an in source build, then create the output directory
- if(strcmp(this->Makefile->GetStartOutputDirectory(),
- this->Makefile->GetHomeDirectory()) != 0)
- {
- if(!cmSystemTools::MakeDirectory
- (this->Makefile->GetStartOutputDirectory()))
- {
- cmSystemTools::Error("Error creating directory ",
- this->Makefile->GetStartOutputDirectory());
- }
- }
-
- // Create the DSP or set of DSP's for libraries and executables
-
- cmTargets &tgts = this->Makefile->GetTargets();
-
- // build any targets
- for(cmTargets::iterator l = tgts.begin();
- l != tgts.end(); l++)
- {
- switch(l->second.GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
- break;
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- this->SetBuildType(DLL, l->first.c_str(), l->second);
- break;
- case cmTarget::EXECUTABLE:
- this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
- break;
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
- this->SetBuildType(UTILITY, l->first.c_str(), l->second);
- break;
- default:
- cmSystemTools::Error("Bad target type", l->first.c_str());
- break;
- }
- // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
- // so don't build a projectfile for it
- const char* path =
- l->second.GetProperty("EXTERNAL_MSPROJECT");
- if(!path)
- {
- // check to see if the dsp is going into a sub-directory
- std::string::size_type pos = l->first.rfind('/');
- if(pos != std::string::npos)
- {
- std::string dir = this->Makefile->GetStartOutputDirectory();
- dir += "/";
- dir += l->first.substr(0, pos);
- if(!cmSystemTools::MakeDirectory(dir.c_str()))
- {
- cmSystemTools::Error("Error creating directory ", dir.c_str());
- }
- }
- this->CreateSingleDSP(l->first.c_str(),l->second);
- }
- }
-}
-
-// Utility function to make a valid VS6 *.dsp filename out
-// of a CMake target name:
-//
-extern std::string GetVS6TargetName(const std::string& targetName);
-
-void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname,
- cmTarget &target)
-{
- // add to the list of projects
- std::string pname = GetVS6TargetName(lname);
-
- // create the dsp.cmake file
- std::string fname;
- fname = this->Makefile->GetStartOutputDirectory();
- fname += "/";
- fname += pname;
- fname += ".dsp";
- // save the name of the real dsp file
- std::string realDSP = fname;
- fname += ".cmake";
- std::ofstream fout(fname.c_str());
- if(!fout)
- {
- cmSystemTools::Error("Error Writing ", fname.c_str());
- cmSystemTools::ReportLastSystemError("");
- }
- this->WriteDSPFile(fout,pname.c_str(),target);
- fout.close();
- // if the dsp file has changed, then write it.
- cmSystemTools::CopyFileIfDifferent(fname.c_str(), realDSP.c_str());
-}
-
-
-void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt)
-{
- std::string dspname = GetVS6TargetName(tgt.GetName());
- dspname += ".dsp.cmake";
- const char* dsprule =
- this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
- cmCustomCommandLine commandLine;
- commandLine.push_back(dsprule);
- std::string makefileIn = this->Makefile->GetStartDirectory();
- makefileIn += "/";
- makefileIn += "CMakeLists.txt";
- if(!cmSystemTools::FileExists(makefileIn.c_str()))
- {
- return;
- }
- std::string comment = "Building Custom Rule ";
- comment += makefileIn;
- std::string args;
- args = "-H";
- args += this->Convert(this->Makefile->GetHomeDirectory(),
- START_OUTPUT, UNCHANGED, true);
- commandLine.push_back(args);
- args = "-B";
- args +=
- this->Convert(this->Makefile->GetHomeOutputDirectory(),
- START_OUTPUT, UNCHANGED, true);
- commandLine.push_back(args);
-
- std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
-
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
- const char* no_working_directory = 0;
- this->Makefile->AddCustomCommandToOutput(dspname.c_str(), listFiles,
- makefileIn.c_str(), commandLines,
- comment.c_str(),
- no_working_directory, true);
- if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
- {
- tgt.AddSourceFile(file);
- }
- else
- {
- cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
- }
-}
-
-
-void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
- const char *libName,
- cmTarget &target)
-{
- // For utility targets need custom command since pre- and post-
- // build does not do anything in Visual Studio 6. In order for the
- // rules to run in the correct order as custom commands, we need
- // special care for dependencies. The first rule must depend on all
- // the dependencies of all the rules. The later rules must each
- // depend only on the previous rule.
- if ((target.GetType() == cmTarget::UTILITY ||
- target.GetType() == cmTarget::GLOBAL_TARGET) &&
- (!target.GetPreBuildCommands().empty() ||
- !target.GetPostBuildCommands().empty()))
- {
- // Accumulate the dependencies of all the commands.
- std::vector<std::string> depends;
- for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetPreBuildCommands().begin();
- cr != target.GetPreBuildCommands().end(); ++cr)
- {
- depends.insert(depends.end(),
- cr->GetDepends().begin(), cr->GetDepends().end());
- }
- for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetPostBuildCommands().begin();
- cr != target.GetPostBuildCommands().end(); ++cr)
- {
- depends.insert(depends.end(),
- cr->GetDepends().begin(), cr->GetDepends().end());
- }
-
- // Add the pre- and post-build commands in order.
- int count = 1;
- for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetPreBuildCommands().begin();
- cr != target.GetPreBuildCommands().end(); ++cr)
- {
- this->AddUtilityCommandHack(target, count++, depends, *cr);
- }
- for (std::vector<cmCustomCommand>::const_iterator cr =
- target.GetPostBuildCommands().begin();
- cr != target.GetPostBuildCommands().end(); ++cr)
- {
- this->AddUtilityCommandHack(target, count++, depends, *cr);
- }
- }
-
- // We may be modifying the source groups temporarily, so make a copy.
- std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
-
- // get the classes from the source lists then add them to the groups
- std::vector<cmSourceFile*> const & classes = target.GetSourceFiles();
-
- // now all of the source files have been properly assigned to the target
- // now stick them into source groups using the reg expressions
- for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); i++)
- {
- // Add the file to the list of sources.
- std::string source = (*i)->GetFullPath();
- cmSourceGroup& sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
- sourceGroup.AssignSource(*i);
- // while we are at it, if it is a .rule file then for visual studio 6 we
- // must generate it
- if ((*i)->GetPropertyAsBool("__CMAKE_RULE"))
- {
- if(!cmSystemTools::FileExists(source.c_str()))
- {
- cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
- // Make sure the path exists for the file
- std::string path = cmSystemTools::GetFilenamePath(source);
- cmSystemTools::MakeDirectory(path.c_str());
-#if defined(_WIN32) || defined(__CYGWIN__)
- std::ofstream sourceFout(source.c_str(),
- std::ios::binary | std::ios::out
- | std::ios::trunc);
-#else
- std::ofstream sourceFout(source.c_str(),
- std::ios::out | std::ios::trunc);
-#endif
- if(sourceFout)
- {
- sourceFout.write("# generated from CMake",22);
- sourceFout.flush();
- sourceFout.close();
- }
- }
- }
- }
-
- // Write the DSP file's header.
- this->WriteDSPHeader(fout, libName, target, sourceGroups);
-
-
- // Loop through every source group.
- for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
- sg != sourceGroups.end(); ++sg)
- {
- this->WriteGroup(&(*sg), target, fout, libName);
- }
-
- // Write the DSP file's footer.
- this->WriteDSPFooter(fout);
-}
-
-void cmLocalVisualStudio6Generator
-::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
- std::ostream &fout, const char *libName)
-{
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
- const std::vector<const cmSourceFile *> &sourceFiles =
- sg->GetSourceFiles();
- // If the group is empty, don't write it at all.
-
- if(sourceFiles.empty() && sg->GetGroupChildren().empty())
- {
- return;
- }
-
- // If the group has a name, write the header.
- std::string name = sg->GetName();
- if(name != "")
- {
- this->WriteDSPBeginGroup(fout, name.c_str(), "");
- }
-
- // 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();
- const cmCustomCommand *command =
- (*sf)->GetCustomCommand();
- std::string compileFlags;
- std::vector<std::string> depends;
- std::string objectNameDir;
- if(gt->ExplicitObjectName.find(*sf) != gt->ExplicitObjectName.end())
- {
- objectNameDir = cmSystemTools::GetFilenamePath(gt->Objects[*sf]);
- }
-
- // Add per-source file flags.
- if(const char* cflags = (*sf)->GetProperty("COMPILE_FLAGS"))
- {
- compileFlags += cflags;
- }
-
- const char* lang = this->GetSourceFileLanguage(*(*sf));
- if(lang)
- {
- if(strcmp(lang, "CXX") == 0)
- {
- // force a C++ file type
- compileFlags += " /TP ";
- }
- else if(strcmp(lang, "C") == 0)
- {
- // force to c file type
- compileFlags += " /TC ";
- }
- }
-
- // Add per-source and per-configuration preprocessor definitions.
- std::map<cmStdString, cmStdString> cdmap;
-
- {
- std::set<std::string> targetCompileDefinitions;
-
- this->AppendDefines(targetCompileDefinitions,
- (*sf)->GetProperty("COMPILE_DEFINITIONS"));
- this->JoinDefines(targetCompileDefinitions, compileFlags, lang);
- }
-
- if(const char* cdefs = (*sf)->GetProperty("COMPILE_DEFINITIONS_DEBUG"))
- {
- std::set<std::string> debugCompileDefinitions;
- this->AppendDefines(debugCompileDefinitions, cdefs);
- this->JoinDefines(debugCompileDefinitions, cdmap["DEBUG"], lang);
- }
- if(const char* cdefs = (*sf)->GetProperty("COMPILE_DEFINITIONS_RELEASE"))
- {
- std::set<std::string> releaseCompileDefinitions;
- this->AppendDefines(releaseCompileDefinitions, cdefs);
- this->JoinDefines(releaseCompileDefinitions, cdmap["RELEASE"], lang);
- }
- if(const char* cdefs =
- (*sf)->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"))
- {
- std::set<std::string> minsizerelCompileDefinitions;
- this->AppendDefines(minsizerelCompileDefinitions, cdefs);
- this->JoinDefines(minsizerelCompileDefinitions, cdmap["MINSIZEREL"],
- lang);
- }
- if(const char* cdefs =
- (*sf)->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"))
- {
- std::set<std::string> relwithdebinfoCompileDefinitions;
- this->AppendDefines(relwithdebinfoCompileDefinitions, cdefs);
- this->JoinDefines(relwithdebinfoCompileDefinitions,
- cdmap["RELWITHDEBINFO"], lang);
- }
-
- bool excludedFromBuild =
- (lang && (*sf)->GetPropertyAsBool("HEADER_FILE_ONLY"));
-
- // Check for extra object-file dependencies.
- const char* dependsValue = (*sf)->GetProperty("OBJECT_DEPENDS");
- if(dependsValue)
- {
- cmSystemTools::ExpandListArgument(dependsValue, depends);
- }
- if (GetVS6TargetName(source) != libName ||
- target.GetType() == cmTarget::UTILITY ||
- target.GetType() == cmTarget::GLOBAL_TARGET)
- {
- fout << "# Begin Source File\n\n";
-
- // Tell MS-Dev what the source is. If the compiler knows how to
- // build it, then it will.
- fout << "SOURCE=" <<
- this->ConvertToOptionallyRelativeOutputPath(source.c_str()) << "\n\n";
- if(!depends.empty())
- {
- // Write out the dependencies for the rule.
- fout << "USERDEP__HACK=";
- for(std::vector<std::string>::const_iterator d = depends.begin();
- d != depends.end(); ++d)
- {
- fout << "\\\n\t" <<
- this->ConvertToOptionallyRelativeOutputPath(d->c_str());
- }
- fout << "\n";
- }
- if (command)
- {
- const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
- this->WriteCustomRule(fout, source.c_str(), *command, flags);
- }
- else if(!compileFlags.empty() || !objectNameDir.empty() ||
- excludedFromBuild || !cdmap.empty())
- {
- for(std::vector<std::string>::iterator i
- = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- // Strip the subdirectory name out of the configuration name.
- std::string config = this->GetConfigName(*i);
- if (i == this->Configurations.begin())
- {
- fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
- }
- else
- {
- fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
- }
- if(excludedFromBuild)
- {
- fout << "# PROP Exclude_From_Build 1\n";
- }
- if(!compileFlags.empty())
- {
- fout << "\n# ADD CPP " << compileFlags << "\n\n";
- }
- std::map<cmStdString, cmStdString>::iterator cdi =
- cdmap.find(cmSystemTools::UpperCase(config));
- if(cdi != cdmap.end() && !cdi->second.empty())
- {
- fout << "\n# ADD CPP " << cdi->second << "\n\n";
- }
- if(!objectNameDir.empty())
- {
- // Setup an alternate object file directory.
- fout << "\n# PROP Intermediate_Dir \""
- << config << "/" << objectNameDir << "\"\n\n";
- }
- }
- fout << "!ENDIF\n\n";
- }
- fout << "# End Source File\n";
- }
- }
-
- std::vector<cmSourceGroup> const& children = sg->GetGroupChildren();
-
- for(unsigned int i=0;i<children.size();++i)
- {
- this->WriteGroup(&children[i], target, fout, libName);
- }
-
-
-
-
- // If the group has a name, write the footer.
- if(name != "")
- {
- this->WriteDSPEndGroup(fout);
- }
-
-}
-
-
-void
-cmLocalVisualStudio6Generator
-::AddUtilityCommandHack(cmTarget& target, int count,
- std::vector<std::string>& depends,
- const cmCustomCommand& origCommand)
-{
- // Create a fake output that forces the rule to run.
- char* output = new char[(strlen(this->Makefile->GetStartOutputDirectory()) +
- strlen(target.GetName()) + 30)];
- sprintf(output,"%s/%s_force_%i", this->Makefile->GetStartOutputDirectory(),
- target.GetName(), count);
- std::string comment = this->ConstructComment(origCommand, "<hack>");
-
- // Add the rule with the given dependencies and commands.
- const char* no_main_dependency = 0;
- if(cmSourceFile* outsf =
- this->Makefile->AddCustomCommandToOutput(
- output, depends, no_main_dependency,
- origCommand.GetCommandLines(), comment.c_str(),
- origCommand.GetWorkingDirectory()))
- {
- target.AddSourceFile(outsf);
- }
-
- // Replace the dependencies with the output of this rule so that the
- // next rule added will run after this one.
- depends.clear();
- depends.push_back(output);
-
- // Free the fake output name.
- delete [] output;
-}
-
-void
-cmLocalVisualStudio6Generator
-::WriteCustomRule(std::ostream& fout,
- const char* source,
- const cmCustomCommand& command,
- const char* flags)
-{
- std::string comment =
- this->ConstructComment(command, "Building Custom Rule $(InputPath)");
- if(comment == "<hack>")
- {
- comment = "";
- }
-
- // Write the rule for each configuration.
- std::vector<std::string>::iterator i;
- for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
- {
- std::string config = this->GetConfigName(*i);
- std::string script =
- this->ConstructScript(command, config.c_str(), "\\\n\t");
-
- if (i == this->Configurations.begin())
- {
- fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
- }
- else
- {
- fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
- }
- if(flags)
- {
- fout << "\n# ADD CPP " << flags << "\n\n";
- }
- // Write out the dependencies for the rule.
- fout << "USERDEP__HACK=";
- for(std::vector<std::string>::const_iterator d =
- command.GetDepends().begin();
- d != command.GetDepends().end();
- ++d)
- {
- // Lookup the real name of the dependency in case it is a CMake target.
- std::string dep;
- if(this->GetRealDependency(d->c_str(), config.c_str(), dep))
- {
- fout << "\\\n\t" <<
- this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
- }
- }
- fout << "\n";
-
- fout << "# PROP Ignore_Default_Tool 1\n";
- fout << "# Begin Custom Build -";
- if(!comment.empty())
- {
- fout << " " << comment.c_str();
- }
- fout << "\n\n";
- if(command.GetOutputs().empty())
- {
- fout << source
- << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
- fout << script.c_str() << "\n\n";
- }
- else
- {
- for(std::vector<std::string>::const_iterator o =
- command.GetOutputs().begin();
- o != command.GetOutputs().end();
- ++o)
- {
- // Write a rule for every output generated by this command.
- fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str())
- << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
- fout << script.c_str() << "\n\n";
- }
- }
- fout << "# End Custom Build\n\n";
- }
-
- fout << "!ENDIF\n\n";
-}
-
-
-void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream& fout,
- const char* group,
- const char* filter)
-{
- fout << "# Begin Group \"" << group << "\"\n"
- "# PROP Default_Filter \"" << filter << "\"\n";
-}
-
-
-void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
-{
- fout << "# End Group\n";
-}
-
-
-
-
-void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
- const char* libName,
- cmTarget& target)
-{
- std::string root= this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
- const char *def=
- this->Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
-
- if( def)
- {
- root = def;
- }
- else
- {
- root += "/Templates";
- }
-
- switch(b)
- {
- case WIN32_EXECUTABLE:
- break;
- case STATIC_LIBRARY:
- this->DSPHeaderTemplate = root;
- this->DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
- this->DSPFooterTemplate = root;
- this->DSPFooterTemplate += "/staticLibFooter.dsptemplate";
- break;
- case DLL:
- this->DSPHeaderTemplate = root;
- this->DSPHeaderTemplate += "/DLLHeader.dsptemplate";
- this->DSPFooterTemplate = root;
- this->DSPFooterTemplate += "/DLLFooter.dsptemplate";
- break;
- case EXECUTABLE:
- if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
- {
- this->DSPHeaderTemplate = root;
- this->DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
- this->DSPFooterTemplate = root;
- this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
- }
- else
- {
- this->DSPHeaderTemplate = root;
- this->DSPHeaderTemplate += "/EXEHeader.dsptemplate";
- this->DSPFooterTemplate = root;
- this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
- }
- break;
- case UTILITY:
- this->DSPHeaderTemplate = root;
- this->DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
- this->DSPFooterTemplate = root;
- this->DSPFooterTemplate += "/UtilityFooter.dsptemplate";
- break;
- }
-
- // once the build type is set, determine what configurations are
- // possible
- std::ifstream fin(this->DSPHeaderTemplate.c_str());
-
- cmsys::RegularExpression reg("# Name ");
- if(!fin)
- {
- cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
- }
-
- // reset this->Configurations
- this->Configurations.erase(this->Configurations.begin(),
- this->Configurations.end());
-
- // now add all the configurations possible
- std::string vs6name = GetVS6TargetName(libName);
- std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME", vs6name.c_str());
- if (reg.find(line))
- {
- this->Configurations.push_back(line.substr(reg.end()));
- }
- }
-}
-
-//----------------------------------------------------------------------------
-cmsys::auto_ptr<cmCustomCommand>
-cmLocalVisualStudio6Generator::MaybeCreateOutputDir(cmTarget& target,
- const char* config)
-{
- cmsys::auto_ptr<cmCustomCommand> pcc;
-
- // VS6 forgets to create the output directory for archives if it
- // differs from the intermediate directory.
- if(target.GetType() != cmTarget::STATIC_LIBRARY) { return pcc; }
- std::string outDir = target.GetDirectory(config, false);
-
- // Add a pre-link event to create the directory.
- cmCustomCommandLine command;
- command.push_back(this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
- command.push_back("-E");
- command.push_back("make_directory");
- command.push_back(outDir);
- std::vector<std::string> no_output;
- std::vector<std::string> no_depends;
- cmCustomCommandLines commands;
- commands.push_back(command);
- pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
- pcc->SetEscapeOldStyle(false);
- pcc->SetEscapeAllowMakeVars(true);
- return pcc;
-}
-
-// look for custom rules on a target and collect them together
-std::string
-cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
- const char* configName,
- const char * /* libName */)
-{
- if (target.GetType() >= cmTarget::UTILITY )
- {
- return "";
- }
-
- std::string customRuleCode = "# Begin Special Build Tool\n";
- EventWriter event(this, configName, customRuleCode);
-
- // Write the pre-build and pre-link together (VS6 does not support both).
- event.Start("PreLink");
- event.Write(target.GetPreBuildCommands());
- event.Write(target.GetPreLinkCommands());
- cmsys::auto_ptr<cmCustomCommand> pcc(
- this->MaybeCreateImplibDir(target, configName, false));
- if(pcc.get())
- {
- event.Write(*pcc);
- }
- pcc = this->MaybeCreateOutputDir(target, configName);
- if(pcc.get())
- {
- event.Write(*pcc);
- }
- event.Finish();
-
- // Write the post-build rules.
- event.Start("PostBuild");
- event.Write(target.GetPostBuildCommands());
- event.Finish();
-
- customRuleCode += "# End Special Build Tool\n";
- return customRuleCode;
-}
-
-
-inline std::string removeQuotes(const std::string& s)
-{
- if(s[0] == '\"' && s[s.size()-1] == '\"')
- {
- return s.substr(1, s.size()-2);
- }
- return s;
-}
-
-
-std::string
-cmLocalVisualStudio6Generator::GetTargetIncludeOptions(cmTarget &target,
- const char *config)
-{
- std::string includeOptions;
-
- // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
- // truncates long include paths so make it as short as possible if
- // the length threatens this problem.
- unsigned int maxIncludeLength = 3000;
- bool useShortPath = false;
-
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
- for(int j=0; j < 2; ++j)
- {
- std::vector<std::string> includes;
- this->GetIncludeDirectories(includes, gt, "C", config);
-
- std::vector<std::string>::iterator i;
- for(i = includes.begin(); i != includes.end(); ++i)
- {
- std::string tmp =
- this->ConvertToOptionallyRelativeOutputPath(i->c_str());
- if(useShortPath)
- {
- cmSystemTools::GetShortPath(tmp.c_str(), tmp);
- }
- includeOptions += " /I ";
-
- // quote if not already quoted
- if (tmp[0] != '"')
- {
- includeOptions += "\"";
- includeOptions += tmp;
- includeOptions += "\"";
- }
- else
- {
- includeOptions += tmp;
- }
- }
-
- if(j == 0 && includeOptions.size() > maxIncludeLength)
- {
- includeOptions = "";
- useShortPath = true;
- }
- else
- {
- break;
- }
- }
-
- return includeOptions;
-}
-
-
-// Code in blocks surrounded by a test for this definition is needed
-// only for compatibility with user project's replacement DSP
-// templates. The CMake templates no longer use them.
-#define CM_USE_OLD_VS6
-
-void cmLocalVisualStudio6Generator
-::WriteDSPHeader(std::ostream& fout,
- const char *libName, cmTarget &target,
- std::vector<cmSourceGroup> &)
-{
- bool targetBuilds = (target.GetType() >= cmTarget::EXECUTABLE &&
- target.GetType() <= cmTarget::MODULE_LIBRARY);
-#ifdef CM_USE_OLD_VS6
- // Lookup the library and executable output directories.
- std::string libPath;
- if(this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
- {
- libPath = this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
- }
- std::string exePath;
- if(this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
- {
- exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
- }
-
- // Make sure there are trailing slashes.
- if(!libPath.empty())
- {
- if(libPath[libPath.size()-1] != '/')
- {
- libPath += "/";
- }
- }
- if(!exePath.empty())
- {
- if(exePath[exePath.size()-1] != '/')
- {
- exePath += "/";
- }
- }
-
- std::set<std::string> pathEmitted;
-
- // determine the link directories
- std::string libOptions;
- std::string libDebugOptions;
- std::string libOptimizedOptions;
-
- std::string libMultiLineOptions;
- std::string libMultiLineOptionsForDebug;
- std::string libMultiLineDebugOptions;
- std::string libMultiLineOptimizedOptions;
-
- if(libPath.size())
- {
- std::string lpath =
- this->ConvertToOptionallyRelativeOutputPath(libPath.c_str());
- if(lpath.size() == 0)
- {
- lpath = ".";
- }
- std::string lpathIntDir = libPath + "$(INTDIR)";
- lpathIntDir =
- this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
- if(pathEmitted.insert(lpath).second)
- {
- libOptions += " /LIBPATH:";
- libOptions += lpathIntDir;
- libOptions += " ";
- libOptions += " /LIBPATH:";
- libOptions += lpath;
- libOptions += " ";
- libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
- libMultiLineOptions += lpathIntDir;
- libMultiLineOptions += " ";
- libMultiLineOptions += " /LIBPATH:";
- libMultiLineOptions += lpath;
- libMultiLineOptions += " \n";
- libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
- libMultiLineOptionsForDebug += lpathIntDir;
- libMultiLineOptionsForDebug += " ";
- libMultiLineOptionsForDebug += " /LIBPATH:";
- libMultiLineOptionsForDebug += lpath;
- libMultiLineOptionsForDebug += " \n";
- }
- }
- if(exePath.size())
- {
- std::string lpath =
- this->ConvertToOptionallyRelativeOutputPath(exePath.c_str());
- if(lpath.size() == 0)
- {
- lpath = ".";
- }
- std::string lpathIntDir = exePath + "$(INTDIR)";
- lpathIntDir =
- this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
-
- if(pathEmitted.insert(lpath).second)
- {
- libOptions += " /LIBPATH:";
- libOptions += lpathIntDir;
- libOptions += " ";
- libOptions += " /LIBPATH:";
- libOptions += lpath;
- libOptions += " ";
- libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
- libMultiLineOptions += lpathIntDir;
- libMultiLineOptions += " ";
- libMultiLineOptions += " /LIBPATH:";
- libMultiLineOptions += lpath;
- libMultiLineOptions += " \n";
- libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
- libMultiLineOptionsForDebug += lpathIntDir;
- libMultiLineOptionsForDebug += " ";
- libMultiLineOptionsForDebug += " /LIBPATH:";
- libMultiLineOptionsForDebug += lpath;
- libMultiLineOptionsForDebug += " \n";
- }
- }
- std::vector<std::string>::const_iterator i;
- const std::vector<std::string>& libdirs = target.GetLinkDirectories();
- for(i = libdirs.begin(); i != libdirs.end(); ++i)
- {
- std::string path = *i;
- if(path[path.size()-1] != '/')
- {
- path += "/";
- }
- std::string lpath =
- this->ConvertToOptionallyRelativeOutputPath(path.c_str());
- if(lpath.size() == 0)
- {
- lpath = ".";
- }
- std::string lpathIntDir = path + "$(INTDIR)";
- lpathIntDir =
- this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
- if(pathEmitted.insert(lpath).second)
- {
- libOptions += " /LIBPATH:";
- libOptions += lpathIntDir;
- libOptions += " ";
- libOptions += " /LIBPATH:";
- libOptions += lpath;
- libOptions += " ";
-
- libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
- libMultiLineOptions += lpathIntDir;
- libMultiLineOptions += " ";
- libMultiLineOptions += " /LIBPATH:";
- libMultiLineOptions += lpath;
- libMultiLineOptions += " \n";
- libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
- libMultiLineOptionsForDebug += lpathIntDir;
- libMultiLineOptionsForDebug += " ";
- libMultiLineOptionsForDebug += " /LIBPATH:";
- libMultiLineOptionsForDebug += lpath;
- libMultiLineOptionsForDebug += " \n";
- }
- }
- // find link libraries
- const cmTarget::LinkLibraryVectorType& libs = target.GetLinkLibraries();
- cmTarget::LinkLibraryVectorType::const_iterator j;
- for(j = libs.begin(); j != libs.end(); ++j)
- {
- // add libraries to executables and dlls (but never include
- // a library in a library, bad recursion)
- // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
- if ((target.GetType() != cmTarget::SHARED_LIBRARY
- && target.GetType() != cmTarget::STATIC_LIBRARY
- && target.GetType() != cmTarget::MODULE_LIBRARY) ||
- (target.GetType()==cmTarget::SHARED_LIBRARY
- && libName != GetVS6TargetName(j->first)) ||
- (target.GetType()==cmTarget::MODULE_LIBRARY
- && libName != GetVS6TargetName(j->first)))
- {
- // Compute the proper name to use to link this library.
- std::string lib;
- std::string libDebug;
- cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str());
- if(tgt)
- {
- lib = cmSystemTools::GetFilenameWithoutExtension
- (tgt->GetFullName().c_str());
- libDebug = cmSystemTools::GetFilenameWithoutExtension
- (tgt->GetFullName("Debug").c_str());
- lib += ".lib";
- libDebug += ".lib";
- }
- else
- {
- lib = j->first.c_str();
- libDebug = j->first.c_str();
- if(j->first.find(".lib") == std::string::npos)
- {
- lib += ".lib";
- libDebug += ".lib";
- }
- }
- lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str());
- libDebug =
- this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str());
-
- if (j->second == cmTarget::GENERAL)
- {
- libOptions += " ";
- libOptions += lib;
- libMultiLineOptions += "# ADD LINK32 ";
- libMultiLineOptions += lib;
- libMultiLineOptions += "\n";
- libMultiLineOptionsForDebug += "# ADD LINK32 ";
- libMultiLineOptionsForDebug += libDebug;
- libMultiLineOptionsForDebug += "\n";
- }
- if (j->second == cmTarget::DEBUG)
- {
- libDebugOptions += " ";
- libDebugOptions += lib;
-
- libMultiLineDebugOptions += "# ADD LINK32 ";
- libMultiLineDebugOptions += libDebug;
- libMultiLineDebugOptions += "\n";
- }
- if (j->second == cmTarget::OPTIMIZED)
- {
- libOptimizedOptions += " ";
- libOptimizedOptions += lib;
-
- libMultiLineOptimizedOptions += "# ADD LINK32 ";
- libMultiLineOptimizedOptions += lib;
- libMultiLineOptimizedOptions += "\n";
- }
- }
- }
-#endif
-
- // Get include options for this target.
- std::string includeOptionsDebug = this->GetTargetIncludeOptions(target,
- "DEBUG");
- std::string includeOptionsRelease = this->GetTargetIncludeOptions(target,
- "RELEASE");
- std::string includeOptionsRelWithDebInfo = this->GetTargetIncludeOptions(
- target,
- "RELWITHDEBINFO");
- std::string includeOptionsMinSizeRel = this->GetTargetIncludeOptions(target,
- "MINSIZEREL");
-
- // Get extra linker options for this target type.
- std::string extraLinkOptions;
- std::string extraLinkOptionsDebug;
- std::string extraLinkOptionsRelease;
- std::string extraLinkOptionsMinSizeRel;
- std::string extraLinkOptionsRelWithDebInfo;
- if(target.GetType() == cmTarget::EXECUTABLE)
- {
- extraLinkOptions = this->Makefile->
- GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
- extraLinkOptionsDebug = this->Makefile->
- GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_DEBUG");
- extraLinkOptionsRelease = this->Makefile->
- GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELEASE");
- extraLinkOptionsMinSizeRel = this->Makefile->
- GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_MINSIZEREL");
- extraLinkOptionsRelWithDebInfo = this->Makefile->
- GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO");
- }
- if(target.GetType() == cmTarget::SHARED_LIBRARY)
- {
- extraLinkOptions = this->Makefile->
- GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
- extraLinkOptionsDebug = this->Makefile->
- GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_DEBUG");
- extraLinkOptionsRelease = this->Makefile->
- GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELEASE");
- extraLinkOptionsMinSizeRel = this->Makefile->
- GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL");
- extraLinkOptionsRelWithDebInfo = this->Makefile->
- GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO");
- }
- if(target.GetType() == cmTarget::MODULE_LIBRARY)
- {
- extraLinkOptions = this->Makefile->
- GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
- extraLinkOptionsDebug = this->Makefile->
- GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_DEBUG");
- extraLinkOptionsRelease = this->Makefile->
- GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELEASE");
- extraLinkOptionsMinSizeRel = this->Makefile->
- GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL");
- extraLinkOptionsRelWithDebInfo = this->Makefile->
- GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO");
- }
-
- // Get extra linker options for this target.
- if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
- {
- extraLinkOptions += " ";
- extraLinkOptions += targetLinkFlags;
- }
-
- if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS_DEBUG"))
- {
- extraLinkOptionsDebug += " ";
- extraLinkOptionsDebug += targetLinkFlags;
- }
-
- if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS_RELEASE"))
- {
- extraLinkOptionsRelease += " ";
- extraLinkOptionsRelease += targetLinkFlags;
- }
-
- if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS_MINSIZEREL"))
- {
- extraLinkOptionsMinSizeRel += " ";
- extraLinkOptionsMinSizeRel += targetLinkFlags;
- }
-
- if(const char* targetLinkFlags =
- target.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
- {
- extraLinkOptionsRelWithDebInfo += " ";
- extraLinkOptionsRelWithDebInfo += targetLinkFlags;
- }
-
-
-
-
- // Get standard libraries for this language.
- if(targetBuilds)
- {
- // Get the language to use for linking.
- const char* linkLanguage = target.GetLinkerLanguage();
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- target.GetName());
- return;
- }
-
- // Compute the variable name to lookup standard libraries for this
- // language.
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += linkLanguage;
- standardLibsVar += "_STANDARD_LIBRARIES";
-
- // Add standard libraries.
- if(const char* stdLibs =
- this->Makefile->GetDefinition(standardLibsVar.c_str()))
- {
- extraLinkOptions += " ";
- extraLinkOptions += stdLibs;
- }
- }
-
- // Compute version number information.
- std::string targetVersionFlag;
- if(target.GetType() == cmTarget::EXECUTABLE ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY)
- {
- int major;
- int minor;
- target.GetTargetVersion(major, minor);
- cmOStringStream targetVersionStream;
- targetVersionStream << "/version:" << major << "." << minor;
- targetVersionFlag = targetVersionStream.str();
- }
-
- // Compute the real name of the target.
- std::string outputName =
- "(OUTPUT_NAME is for libraries and executables only)";
- std::string outputNameDebug = outputName;
- std::string outputNameRelease = outputName;
- std::string outputNameMinSizeRel = outputName;
- std::string outputNameRelWithDebInfo = outputName;
- if(target.GetType() == cmTarget::EXECUTABLE ||
- target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY)
- {
- outputName = target.GetFullName();
- outputNameDebug = target.GetFullName("Debug");
- outputNameRelease = target.GetFullName("Release");
- outputNameMinSizeRel = target.GetFullName("MinSizeRel");
- outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo");
- }
- else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
- {
- outputName = target.GetName();
- outputName += ".lib";
- outputNameDebug = outputName;
- outputNameRelease = outputName;
- outputNameMinSizeRel = outputName;
- outputNameRelWithDebInfo = outputName;
- }
-
- // Compute the output directory for the target.
- std::string outputDirOld;
- std::string outputDirDebug;
- std::string outputDirRelease;
- std::string outputDirMinSizeRel;
- std::string outputDirRelWithDebInfo;
- if(target.GetType() == cmTarget::EXECUTABLE ||
- target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY)
- {
-#ifdef CM_USE_OLD_VS6
- outputDirOld =
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath
- (target.GetDirectory().c_str()));
-#endif
- outputDirDebug =
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath(
- target.GetDirectory("Debug").c_str()));
- outputDirRelease =
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath(
- target.GetDirectory("Release").c_str()));
- outputDirMinSizeRel =
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath(
- target.GetDirectory("MinSizeRel").c_str()));
- outputDirRelWithDebInfo =
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath(
- target.GetDirectory("RelWithDebInfo").c_str()));
- }
- else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
- {
- std::string outputDir = cmake::GetCMakeFilesDirectoryPostSlash();
- outputDirDebug = outputDir + "Debug";
- outputDirRelease = outputDir + "Release";
- outputDirMinSizeRel = outputDir + "MinSizeRel";
- outputDirRelWithDebInfo = outputDir + "RelWithDebInfo";
- }
-
- // Compute the proper link information for the target.
- std::string optionsDebug;
- std::string optionsRelease;
- std::string optionsMinSizeRel;
- std::string optionsRelWithDebInfo;
- if(target.GetType() == cmTarget::EXECUTABLE ||
- target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY)
- {
- extraLinkOptionsDebug =
- extraLinkOptions + " " + extraLinkOptionsDebug;
- extraLinkOptionsRelease =
- extraLinkOptions + " " + extraLinkOptionsRelease;
- extraLinkOptionsMinSizeRel =
- extraLinkOptions + " " + extraLinkOptionsMinSizeRel;
- extraLinkOptionsRelWithDebInfo =
- extraLinkOptions + " " + extraLinkOptionsRelWithDebInfo;
- this->ComputeLinkOptions(target, "Debug", extraLinkOptionsDebug,
- optionsDebug);
- this->ComputeLinkOptions(target, "Release", extraLinkOptionsRelease,
- optionsRelease);
- this->ComputeLinkOptions(target, "MinSizeRel", extraLinkOptionsMinSizeRel,
- optionsMinSizeRel);
- this->ComputeLinkOptions(target, "RelWithDebInfo",
- extraLinkOptionsRelWithDebInfo,
- optionsRelWithDebInfo);
- }
-
- // Compute the path of the import library.
- std::string targetImplibFlagDebug;
- std::string targetImplibFlagRelease;
- std::string targetImplibFlagMinSizeRel;
- std::string targetImplibFlagRelWithDebInfo;
- if(target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY ||
- target.GetType() == cmTarget::EXECUTABLE)
- {
- std::string fullPathImpDebug = target.GetDirectory("Debug", true);
- std::string fullPathImpRelease = target.GetDirectory("Release", true);
- std::string fullPathImpMinSizeRel =
- target.GetDirectory("MinSizeRel", true);
- std::string fullPathImpRelWithDebInfo =
- target.GetDirectory("RelWithDebInfo", true);
- fullPathImpDebug += "/";
- fullPathImpRelease += "/";
- fullPathImpMinSizeRel += "/";
- fullPathImpRelWithDebInfo += "/";
- fullPathImpDebug += target.GetFullName("Debug", true);
- fullPathImpRelease += target.GetFullName("Release", true);
- fullPathImpMinSizeRel += target.GetFullName("MinSizeRel", true);
- fullPathImpRelWithDebInfo += target.GetFullName("RelWithDebInfo", true);
-
- targetImplibFlagDebug = "/implib:";
- targetImplibFlagRelease = "/implib:";
- targetImplibFlagMinSizeRel = "/implib:";
- targetImplibFlagRelWithDebInfo = "/implib:";
- targetImplibFlagDebug +=
- this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug.c_str());
- targetImplibFlagRelease +=
- this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease.c_str());
- targetImplibFlagMinSizeRel +=
- this->ConvertToOptionallyRelativeOutputPath(
- fullPathImpMinSizeRel.c_str());
- targetImplibFlagRelWithDebInfo +=
- this->ConvertToOptionallyRelativeOutputPath(
- fullPathImpRelWithDebInfo.c_str());
- }
-
-#ifdef CM_USE_OLD_VS6
- // Compute link information for the target.
- if(extraLinkOptions.size())
- {
- libOptions += " ";
- libOptions += extraLinkOptions;
- libOptions += " ";
- libMultiLineOptions += "# ADD LINK32 ";
- libMultiLineOptions += extraLinkOptions;
- libMultiLineOptions += " \n";
- libMultiLineOptionsForDebug += "# ADD LINK32 ";
- libMultiLineOptionsForDebug += extraLinkOptions;
- libMultiLineOptionsForDebug += " \n";
- }
-#endif
-
- // are there any custom rules on the target itself
- // only if the target is a lib or exe
- std::string customRuleCodeRelease
- = this->CreateTargetRules(target, "RELEASE", libName);
- std::string customRuleCodeDebug
- = this->CreateTargetRules(target, "DEBUG", libName);
- std::string customRuleCodeMinSizeRel
- = this->CreateTargetRules(target, "MINSIZEREL", libName);
- std::string customRuleCodeRelWithDebInfo
- = this->CreateTargetRules(target, "RELWITHDEBINFO", libName);
-
- std::ifstream fin(this->DSPHeaderTemplate.c_str());
- if(!fin)
- {
- cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
- }
- std::string staticLibOptions;
- std::string staticLibOptionsDebug;
- std::string staticLibOptionsRelease;
- std::string staticLibOptionsMinSizeRel;
- std::string staticLibOptionsRelWithDebInfo;
- if(target.GetType() == cmTarget::STATIC_LIBRARY )
- {
- const char *libflagsGlobal =
- this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS");
- this->AppendFlags(staticLibOptions, libflagsGlobal);
- this->AppendFlags(staticLibOptionsDebug, libflagsGlobal);
- this->AppendFlags(staticLibOptionsRelease, libflagsGlobal);
- this->AppendFlags(staticLibOptionsMinSizeRel, libflagsGlobal);
- this->AppendFlags(staticLibOptionsRelWithDebInfo, libflagsGlobal);
-
- this->AppendFlags(staticLibOptionsDebug, this->Makefile->
- GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_DEBUG"));
- this->AppendFlags(staticLibOptionsRelease, this->Makefile->
- GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELEASE"));
- this->AppendFlags(staticLibOptionsMinSizeRel, this->Makefile->
- GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL"));
- this->AppendFlags(staticLibOptionsRelWithDebInfo, this->Makefile->
- GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO"));
-
- const char *libflags = target.GetProperty("STATIC_LIBRARY_FLAGS");
- this->AppendFlags(staticLibOptions, libflags);
- this->AppendFlags(staticLibOptionsDebug, libflags);
- this->AppendFlags(staticLibOptionsRelease, libflags);
- this->AppendFlags(staticLibOptionsMinSizeRel, libflags);
- this->AppendFlags(staticLibOptionsRelWithDebInfo, libflags);
-
- this->AppendFlags(staticLibOptionsDebug,
- target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG"));
- this->AppendFlags(staticLibOptionsRelease,
- target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE"));
- this->AppendFlags(staticLibOptionsMinSizeRel,
- target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL"));
- this->AppendFlags(staticLibOptionsRelWithDebInfo,
- target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO"));
-
- std::string objects;
- this->OutputObjects(target, "LIB", objects);
- if(!objects.empty())
- {
- objects = "\n" + objects;
- staticLibOptionsDebug += objects;
- staticLibOptionsRelease += objects;
- staticLibOptionsMinSizeRel += objects;
- staticLibOptionsRelWithDebInfo += objects;
- }
- }
-
- // Add the export symbol definition for shared library objects.
- std::string exportSymbol;
- if(const char* exportMacro = target.GetExportMacro())
- {
- exportSymbol = exportMacro;
- }
-
- std::string line;
- std::string libnameExports;
- if(exportSymbol.size())
- {
- libnameExports = "/D \"";
- libnameExports += exportSymbol;
- libnameExports += "\"";
- }
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
- if(!mfcFlag)
- {
- mfcFlag = "0";
- }
- cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
- libnameExports.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
- mfcFlag);
- if(target.GetType() == cmTarget::STATIC_LIBRARY ||
- target.GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS_DEBUG",
- staticLibOptionsDebug.c_str());
- cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS_RELEASE",
- staticLibOptionsRelease.c_str());
- cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS_MINSIZEREL",
- staticLibOptionsMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS_RELWITHDEBINFO",
- staticLibOptionsRelWithDebInfo.c_str());
- cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS",
- staticLibOptions.c_str());
- }
- if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
- {
- cmSystemTools::ReplaceString(line, "/nologo", "");
- }
-
-#ifdef CM_USE_OLD_VS6
- cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
- libOptions.c_str());
- cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
- libDebugOptions.c_str());
- cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
- libOptimizedOptions.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
- libMultiLineOptionsForDebug.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
- libMultiLineOptions.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
- libMultiLineDebugOptions.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
- libMultiLineOptimizedOptions.c_str());
-#endif
-
- // Substitute the rules for custom command. When specifying just the
- // target name for the command the command can be different for
- // different configs
- cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
- customRuleCodeRelease.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
- customRuleCodeDebug.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
- customRuleCodeMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
- customRuleCodeRelWithDebInfo.c_str());
-
- // Substitute the real output name into the template.
- cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG",
- outputNameDebug.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELEASE",
- outputNameRelease.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_NAME_MINSIZEREL",
- outputNameMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELWITHDEBINFO",
- outputNameRelWithDebInfo.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_NAME", outputName.c_str());
-
- // Substitute the proper link information into the template.
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_DEBUG",
- optionsDebug.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELEASE",
- optionsRelease.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_MINSIZEREL",
- optionsMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
- optionsRelWithDebInfo.c_str());
-
- cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_DEBUG",
- includeOptionsDebug.c_str());
- cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_RELEASE",
- includeOptionsRelease.c_str());
- cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_MINSIZEREL",
- includeOptionsMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_RELWITHDEBINFO",
- includeOptionsRelWithDebInfo.c_str());
-
- cmSystemTools::ReplaceString(line, "TARGET_VERSION_FLAG",
- targetVersionFlag.c_str());
- cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_DEBUG",
- targetImplibFlagDebug.c_str());
- cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_RELEASE",
- targetImplibFlagRelease.c_str());
- cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_MINSIZEREL",
- targetImplibFlagMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
- targetImplibFlagRelWithDebInfo.c_str());
-
- std::string vs6name = GetVS6TargetName(libName);
- cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME", vs6name.c_str());
-
-#ifdef CM_USE_OLD_VS6
- // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
- // are already quoted in the template file,
- // we need to remove the quotes here, we still need
- // to convert to output path for unix to win32 conversion
- cmSystemTools::ReplaceString
- (line, "LIBRARY_OUTPUT_PATH",
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath
- (libPath.c_str())).c_str());
- cmSystemTools::ReplaceString
- (line, "EXECUTABLE_OUTPUT_PATH",
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath
- (exePath.c_str())).c_str());
-#endif
-
- if(targetBuilds || target.GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_DEBUG",
- outputDirDebug.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_RELEASE",
- outputDirRelease.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_MINSIZEREL",
- outputDirMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_RELWITHDEBINFO",
- outputDirRelWithDebInfo.c_str());
- if(!outputDirOld.empty())
- {
- cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY",
- outputDirOld.c_str());
- }
- }
-
- cmSystemTools::ReplaceString(line,
- "EXTRA_DEFINES",
- this->Makefile->GetDefineFlags());
- const char* debugPostfix
- = this->Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
- cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
- debugPostfix?debugPostfix:"");
- // store flags for each configuration
- std::string flags = " ";
- std::string flagsRelease = " ";
- std::string flagsMinSizeRel = " ";
- std::string flagsDebug = " ";
- std::string flagsRelWithDebInfo = " ";
- if(target.GetType() >= cmTarget::EXECUTABLE &&
- target.GetType() <= cmTarget::OBJECT_LIBRARY)
- {
- const char* linkLanguage = target.GetLinkerLanguage();
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- target.GetName());
- return;
- }
- // if CXX is on and the target contains cxx code then add the cxx flags
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += linkLanguage;
- baseFlagVar += "_FLAGS";
- flags = this->Makefile->GetSafeDefinition(baseFlagVar.c_str());
-
- std::string flagVar = baseFlagVar + "_RELEASE";
- flagsRelease = this->Makefile->GetSafeDefinition(flagVar.c_str());
- flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
-
- flagVar = baseFlagVar + "_MINSIZEREL";
- flagsMinSizeRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
- flagsMinSizeRel += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
-
- flagVar = baseFlagVar + "_DEBUG";
- flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str());
- flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
-
- flagVar = baseFlagVar + "_RELWITHDEBINFO";
- flagsRelWithDebInfo = this->Makefile->GetSafeDefinition(flagVar.c_str());
- flagsRelWithDebInfo += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
-
- this->AddCompileOptions(flags, &target, linkLanguage, 0);
- this->AddCompileOptions(flagsDebug, &target, linkLanguage, "Debug");
- this->AddCompileOptions(flagsRelease, &target, linkLanguage, "Release");
- this->AddCompileOptions(flagsMinSizeRel, &target, linkLanguage,
- "MinSizeRel");
- this->AddCompileOptions(flagsRelWithDebInfo, &target, linkLanguage,
- "RelWithDebInfo");
- }
-
- // if _UNICODE and _SBCS are not found, then add -D_MBCS
- std::string defs = this->Makefile->GetDefineFlags();
- if(flags.find("D_UNICODE") == flags.npos &&
- defs.find("D_UNICODE") == flags.npos &&
- flags.find("D_SBCS") == flags.npos &&
- defs.find("D_SBCS") == flags.npos)
- {
- flags += " /D \"_MBCS\"";
- }
-
- // Add per-target and per-configuration preprocessor definitions.
- std::set<std::string> definesSet;
- std::set<std::string> debugDefinesSet;
- std::set<std::string> releaseDefinesSet;
- std::set<std::string> minsizeDefinesSet;
- std::set<std::string> debugrelDefinesSet;
-
- this->AddCompileDefinitions(definesSet, &target, 0);
- this->AddCompileDefinitions(debugDefinesSet, &target, "DEBUG");
- this->AddCompileDefinitions(releaseDefinesSet, &target, "RELEASE");
- this->AddCompileDefinitions(minsizeDefinesSet, &target, "MINSIZEREL");
- this->AddCompileDefinitions(debugrelDefinesSet, &target, "RELWITHDEBINFO");
-
- std::string defines = " ";
- std::string debugDefines = " ";
- std::string releaseDefines = " ";
- std::string minsizeDefines = " ";
- std::string debugrelDefines = " ";
-
- this->JoinDefines(definesSet, defines, 0);
- this->JoinDefines(debugDefinesSet, debugDefines, 0);
- this->JoinDefines(releaseDefinesSet, releaseDefines, 0);
- this->JoinDefines(minsizeDefinesSet, minsizeDefines, 0);
- this->JoinDefines(debugrelDefinesSet, debugrelDefines, 0);
-
- flags += defines;
- flagsDebug += debugDefines;
- flagsRelease += releaseDefines;
- flagsMinSizeRel += minsizeDefines;
- flagsRelWithDebInfo += debugrelDefines;
-
- // The template files have CXX FLAGS in them, that need to be replaced.
- // There are not separate CXX and C template files, so we use the same
- // variable names. The previous code sets up flags* variables to contain
- // the correct C or CXX flags
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
- flagsMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
- flagsDebug.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
- flagsRelWithDebInfo.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
- flagsRelease.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
-
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_MINSIZEREL",
- minsizeDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_DEBUG",
- debugDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
- debugrelDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELEASE",
- releaseDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS", defines.c_str());
-
- fout << line.c_str() << std::endl;
- }
-}
-
-void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
-{
- std::ifstream fin(this->DSPFooterTemplate.c_str());
- if(!fin)
- {
- cmSystemTools::Error("Error Reading ",
- this->DSPFooterTemplate.c_str());
- }
- std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- fout << line << std::endl;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmLocalVisualStudio6Generator
-::ComputeLinkOptions(cmTarget& target,
- const char* configName,
- const std::string extraOptions,
- std::string& options)
-{
- // Compute the link information for this configuration.
- cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
- if(!pcli)
- {
- return;
- }
- cmComputeLinkInformation& cli = *pcli;
- typedef cmComputeLinkInformation::ItemVector ItemVector;
- ItemVector const& linkLibs = cli.GetItems();
- std::vector<std::string> const& linkDirs = cli.GetDirectories();
-
- this->OutputObjects(target, "LINK", options);
-
- // Build the link options code.
- for(std::vector<std::string>::const_iterator d = linkDirs.begin();
- d != linkDirs.end(); ++d)
- {
- std::string dir = *d;
- if(!dir.empty())
- {
- if(dir[dir.size()-1] != '/')
- {
- dir += "/";
- }
- dir += "$(IntDir)";
- options += "# ADD LINK32 /LIBPATH:";
- options += this->ConvertToOptionallyRelativeOutputPath(dir.c_str());
- options += " /LIBPATH:";
- options += this->ConvertToOptionallyRelativeOutputPath(d->c_str());
- options += "\n";
- }
- }
- for(ItemVector::const_iterator l = linkLibs.begin();
- l != linkLibs.end(); ++l)
- {
- options += "# ADD LINK32 ";
- if(l->IsPath)
- {
- options +=
- this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str());
- }
- else
- {
- options += l->Value;
- }
- options += "\n";
- }
-
- // Add extra options if any.
- if(!extraOptions.empty())
- {
- options += "# ADD LINK32 ";
- options += extraOptions;
- options += "\n";
- }
-}
-
-//----------------------------------------------------------------------------
-void cmLocalVisualStudio6Generator
-::OutputObjects(cmTarget& target, const char* tool,
- std::string& options)
-{
- // VS 6 does not support per-config source locations so we
- // list object library content on the link line instead.
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
- std::vector<std::string> objs;
- gt->UseObjectLibraries(objs);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- options += "# ADD ";
- options += tool;
- options += "32 ";
- options += this->ConvertToOptionallyRelativeOutputPath(oi->c_str());
- options += "\n";
- }
-}
-
-std::string
-cmLocalVisualStudio6Generator
-::GetTargetDirectory(cmTarget const&) const
-{
- // No per-target directory for this generator (yet).
- return "";
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmLocalVisualStudio6Generator
-::ComputeLongestObjectDirectory(cmTarget&) const
-{
- // Compute the maximum length configuration name.
- std::string config_max;
- for(std::vector<std::string>::const_iterator
- i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- // Strip the subdirectory name out of the configuration name.
- std::string config = this->GetConfigName(*i);
- if(config.size() > config_max.size())
- {
- config_max = config;
- }
- }
-
- // 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->Makefile->GetCurrentOutputDirectory();
- dir_max += "/";
- dir_max += config_max;
- dir_max += "/";
- return dir_max;
-}
-
-std::string
-cmLocalVisualStudio6Generator
-::GetConfigName(std::string const& configuration) const
-{
- // Strip the subdirectory name out of the configuration name.
- std::string config = configuration;
- std::string::size_type pos = config.find_last_of(" ");
- config = config.substr(pos+1, std::string::npos);
- config = config.substr(0, config.size()-1);
- return config;
-}
-
-//----------------------------------------------------------------------------
-bool
-cmLocalVisualStudio6Generator
-::CheckDefinition(std::string const& define) const
-{
- // Perform the standard check first.
- if(!this->cmLocalGenerator::CheckDefinition(define))
- {
- return false;
- }
-
- // Now do the VS6-specific check.
- if(define.find_first_of(" ") != define.npos &&
- define.find_first_of("\"$;") != define.npos)
- {
- cmOStringStream e;
- e << "WARNING: The VS6 IDE does not support preprocessor definition "
- << "values with spaces and '\"', '$', or ';'.\n"
- << "CMake is dropping a preprocessor definition: " << define << "\n"
- << "Consider defining the macro in a (configured) header file.\n";
- cmSystemTools::Message(e.str().c_str());
- return false;
- }
-
- // Assume it is supported.
- return true;
-}
diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h
deleted file mode 100644
index f45bc1758..000000000
--- a/Source/cmLocalVisualStudio6Generator.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmLocalVisualStudio6Generator_h
-#define cmLocalVisualStudio6Generator_h
-
-#include "cmLocalVisualStudioGenerator.h"
-
-class cmTarget;
-class cmSourceFile;
-class cmSourceGroup;
-class cmCustomCommand;
-
-/** \class cmLocalVisualStudio6Generator
- * \brief Write a LocalUnix makefiles.
- *
- * cmLocalVisualStudio6Generator produces a LocalUnix makefile from its
- * member this->Makefile.
- */
-class cmLocalVisualStudio6Generator : public cmLocalVisualStudioGenerator
-{
-public:
- ///! Set cache only and recurse to false by default.
- cmLocalVisualStudio6Generator();
-
- virtual ~cmLocalVisualStudio6Generator();
-
- virtual void AddHelperCommands();
- virtual void AddCMakeListsRules();
-
- /**
- * Generate the makefile for this directory.
- */
- virtual void Generate();
-
- void OutputDSPFile();
-
- enum BuildType {STATIC_LIBRARY, DLL, EXECUTABLE, WIN32_EXECUTABLE, UTILITY};
-
- /**
- * Specify the type of the build: static, dll, or executable.
- */
- void SetBuildType(BuildType, const char* libName, cmTarget&);
-
- virtual std::string GetTargetDirectory(cmTarget const& target) const;
- virtual std::string ComputeLongestObjectDirectory(cmTarget&) const;
-private:
- std::string DSPHeaderTemplate;
- std::string DSPFooterTemplate;
-
- void CreateSingleDSP(const char *lname, cmTarget &tgt);
- void WriteDSPFile(std::ostream& fout, const char *libName,
- cmTarget &tgt);
- void WriteDSPBeginGroup(std::ostream& fout,
- const char* group,
- const char* filter);
- void WriteDSPEndGroup(std::ostream& fout);
-
- void WriteDSPHeader(std::ostream& fout, const char *libName,
- cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
-
- void WriteDSPFooter(std::ostream& fout);
- void AddDSPBuildRule(cmTarget& tgt);
- void WriteCustomRule(std::ostream& fout,
- const char* source,
- const cmCustomCommand& command,
- const char* flags);
- void AddUtilityCommandHack(cmTarget& target, int count,
- std::vector<std::string>& depends,
- const cmCustomCommand& origCommand);
- void WriteGroup(const cmSourceGroup *sg, cmTarget& target,
- std::ostream &fout, const char *libName);
- class EventWriter;
- friend class EventWriter;
- cmsys::auto_ptr<cmCustomCommand>
- MaybeCreateOutputDir(cmTarget& target, const char* config);
- std::string CreateTargetRules(cmTarget &target,
- const char* configName,
- const char *libName);
- void ComputeLinkOptions(cmTarget& target, const char* configName,
- const std::string extraOptions,
- std::string& options);
- void OutputObjects(cmTarget& target, const char* tool,
- std::string& options);
- std::string GetTargetIncludeOptions(cmTarget &target, const char *config);
- std::vector<std::string> Configurations;
-
- std::string GetConfigName(std::string const& configuration) const;
-
- // Special definition check for VS6.
- virtual bool CheckDefinition(std::string const& define) const;
-};
-
-#endif
-
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 8ffd96eb1..dd08e5bdb 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1,57 +1,56 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLocalVisualStudio7Generator.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "cmCustomCommandGenerator.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio7Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
-#include "cmXMLParser.h"
-#include <cm_expat.h>
#include "cmMakefile.h"
-#include "cmSystemTools.h"
#include "cmSourceFile.h"
-#include "cmCacheManager.h"
-#include "cmGeneratorTarget.h"
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cm_expat.h"
#include "cmake.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratedFileStream.h"
-#include <cmsys/System.h>
-
#include <ctype.h> // for isspace
+#include <windows.h>
-// Package GUID of Intel Visual Fortran plugin to VS IDE
-#define CM_INTEL_PLUGIN_GUID "{B68A201D-CB9B-47AF-A52F-7EEC72E217E4}"
-
-static bool cmLVS6G_IsFAT(const char* dir);
+static bool cmLVS7G_IsFAT(const char* dir);
class cmLocalVisualStudio7GeneratorInternals
{
public:
- cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e):
- LocalGenerator(e) {}
+ cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e)
+ : LocalGenerator(e)
+ {
+ }
typedef cmComputeLinkInformation::ItemVector ItemVector;
void OutputLibraries(std::ostream& fout, ItemVector const& libs);
- void OutputObjects(std::ostream& fout, cmTarget* t, const char* isep = 0);
+ void OutputObjects(std::ostream& fout, cmGeneratorTarget* t,
+ std::string const& config, const char* isep = 0);
+
private:
cmLocalVisualStudio7Generator* LocalGenerator;
};
extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
-//----------------------------------------------------------------------------
-cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(VSVersion v):
- cmLocalVisualStudioGenerator(v)
+static void cmConvertToWindowsSlash(std::string& s)
+{
+ std::string::size_type pos = 0;
+ while ((pos = s.find('/', pos)) != std::string::npos) {
+ s[pos] = '\\';
+ pos++;
+ }
+}
+
+cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(
+ cmGlobalGenerator* gg, cmMakefile* mf)
+ : cmLocalVisualStudioGenerator(gg, mf)
{
- this->PlatformName = "Win32";
- this->ExtraFlagTable = 0;
this->Internal = new cmLocalVisualStudio7GeneratorInternals(this);
}
@@ -62,34 +61,18 @@ cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator()
void cmLocalVisualStudio7Generator::AddHelperCommands()
{
- std::set<cmStdString> lang;
- lang.insert("C");
- lang.insert("CXX");
- lang.insert("RC");
- lang.insert("IDL");
- lang.insert("DEF");
- lang.insert("Fortran");
- this->CreateCustomTargetsAndCommands(lang);
-
// Now create GUIDs for targets
- cmTargets &tgts = this->Makefile->GetTargets();
-
- cmGlobalVisualStudio7Generator* gg =
- static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
- {
- const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT");
- if(path)
- {
- this->ReadAndStoreExternalGUID(
- l->second.GetName(), path);
- }
- else
- {
- gg->CreateGUID(l->first.c_str());
- }
+ 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;
}
-
+ const char* path = (*l)->GetProperty("EXTERNAL_MSPROJECT");
+ if (path) {
+ this->ReadAndStoreExternalGUID((*l)->GetName().c_str(), path);
+ }
+ }
this->FixGlobalTargets();
}
@@ -102,24 +85,24 @@ void cmLocalVisualStudio7Generator::Generate()
void cmLocalVisualStudio7Generator::AddCMakeListsRules()
{
- cmTargets &tgts = this->Makefile->GetTargets();
// Create the regeneration custom rule.
- if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION"))
- {
+ 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())
- {
+ if (cmSourceFile* sf = this->CreateVCProjBuildRule()) {
// Add the rule to targets that need it.
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
- {
- if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
- {
- l->second.AddSourceFile(sf);
- }
+ 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()
@@ -127,34 +110,29 @@ 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.
- cmTargets &tgts = this->Makefile->GetTargets();
- for(cmTargets::iterator l = tgts.begin();
- l != tgts.end(); l++)
- {
- cmTarget& tgt = l->second;
- if(tgt.GetType() == cmTarget::GLOBAL_TARGET)
- {
+ std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
+ for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
+ l != tgts.end(); l++) {
+ 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);
- const char* no_main_dependency = 0;
- std::string force = this->Makefile->GetStartOutputDirectory();
+ std::string no_main_dependency = "";
+ std::string force = this->GetCurrentBinaryDirectory();
force += cmake::GetCMakeFilesDirectory();
force += "/";
- force += tgt.GetName();
+ force += (*l)->GetName();
force += "_force";
- if(cmSourceFile* file =
- this->Makefile->AddCustomCommandToOutput(
- force.c_str(), no_depends, no_main_dependency,
- force_commands, " ", 0, true))
- {
- tgt.AddSourceFile(file);
- }
+ if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput(
+ force.c_str(), no_depends, no_main_dependency, force_commands, " ",
+ 0, true)) {
+ (*l)->AddSource(file->GetFullPath());
}
}
+ }
}
// TODO
@@ -163,44 +141,41 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
void cmLocalVisualStudio7Generator::WriteProjectFiles()
{
// If not an in source build, then create the output directory
- if(strcmp(this->Makefile->GetStartOutputDirectory(),
- this->Makefile->GetHomeDirectory()) != 0)
- {
- if(!cmSystemTools::MakeDirectory
- (this->Makefile->GetStartOutputDirectory()))
- {
+ if (strcmp(this->GetCurrentBinaryDirectory(), this->GetSourceDirectory()) !=
+ 0) {
+ if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) {
cmSystemTools::Error("Error creating directory ",
- this->Makefile->GetStartOutputDirectory());
- }
+ this->GetCurrentBinaryDirectory());
}
+ }
// Get the set of targets in this directory.
- cmTargets &tgts = this->Makefile->GetTargets();
+ std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
// Create the project file for each target.
- for(cmTargets::iterator l = tgts.begin();
- l != tgts.end(); l++)
- {
+ for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
+ l != tgts.end(); l++) {
+ 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->second.GetProperty("EXTERNAL_MSPROJECT"))
- {
- this->CreateSingleVCProj(l->first.c_str(),l->second);
- }
+ if (!(*l)->GetProperty("EXTERNAL_MSPROJECT")) {
+ this->CreateSingleVCProj((*l)->GetName().c_str(), *l);
}
+ }
}
-//----------------------------------------------------------------------------
void cmLocalVisualStudio7Generator::WriteStampFiles()
{
// Touch a timestamp file used to determine when the project file is
// out of date.
- std::string stampName = this->Makefile->GetStartOutputDirectory();
+ std::string stampName = this->GetCurrentBinaryDirectory();
stampName += cmake::GetCMakeFilesDirectory();
cmSystemTools::MakeDirectory(stampName.c_str());
stampName += "/";
stampName += "generate.stamp";
- std::ofstream stamp(stampName.c_str());
+ cmsys::ofstream stamp(stampName.c_str());
stamp << "# CMake generation timestamp file for this directory.\n";
// Create a helper file so CMake can determine when it is run
@@ -211,439 +186,424 @@ void cmLocalVisualStudio7Generator::WriteStampFiles()
// the stamp file can just be touched.
std::string depName = stampName;
depName += ".depend";
- std::ofstream depFile(depName.c_str());
+ 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)
- {
+ for (std::vector<std::string>::const_iterator lf = listFiles.begin();
+ lf != listFiles.end(); ++lf) {
depFile << *lf << std::endl;
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmLocalVisualStudio7Generator
-::CreateSingleVCProj(const char *lname, cmTarget &target)
+void cmLocalVisualStudio7Generator::CreateSingleVCProj(
+ const std::string& lname, cmGeneratorTarget* target)
{
- this->FortranProject =
- static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(target);
- this->WindowsCEProject =
- static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetsWindowsCE();
+ cmGlobalVisualStudioGenerator* gg =
+ static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
+ this->FortranProject = gg->TargetIsFortranOnly(target);
+ this->WindowsCEProject = gg->TargetsWindowsCE();
// Intel Fortran for VS10 uses VS9 format ".vfproj" files.
- VSVersion realVersion = this->Version;
- if(this->FortranProject && this->Version >= VS10)
- {
- this->Version = VS9;
- }
+ cmGlobalVisualStudioGenerator::VSVersion realVersion = gg->GetVersion();
+ if (this->FortranProject &&
+ gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS10) {
+ gg->SetVersion(cmGlobalVisualStudioGenerator::VS9);
+ }
// add to the list of projects
- std::string pname = lname;
- target.SetProperty("GENERATOR_FILE_NAME",lname);
+ target->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str());
// create the dsp.cmake file
std::string fname;
- fname = this->Makefile->GetStartOutputDirectory();
+ fname = this->GetCurrentBinaryDirectory();
fname += "/";
fname += lname;
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
fname += ".vfproj";
- }
- else
- {
+ } else {
fname += ".vcproj";
- }
+ }
// Generate the project file and replace it atomically with
// copy-if-different. We use a separate timestamp so that the IDE
// does not reload project files unnecessarily.
cmGeneratedFileStream fout(fname.c_str());
fout.SetCopyIfDifferent(true);
- this->WriteVCProjFile(fout,lname,target);
- if (fout.Close())
- {
+ this->WriteVCProjFile(fout, lname, target);
+ if (fout.Close()) {
this->GlobalGenerator->FileReplacedDuringGenerate(fname);
- }
+ }
- this->Version = realVersion;
+ gg->SetVersion(realVersion);
}
-//----------------------------------------------------------------------------
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
{
- std::string stampName = this->Makefile->GetCurrentOutputDirectory();
+ std::string stampName = this->GetCurrentBinaryDirectory();
stampName += "/";
stampName += cmake::GetCMakeFilesDirectoryPostSlash();
stampName += "generate.stamp";
- const char* dsprule =
- this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
cmCustomCommandLine commandLine;
- commandLine.push_back(dsprule);
- std::string makefileIn = this->Makefile->GetStartDirectory();
+ 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()))
- {
+ if (!cmSystemTools::FileExists(makefileIn.c_str())) {
return 0;
- }
+ }
std::string comment = "Building Custom Rule ";
comment += makefileIn;
std::string args;
args = "-H";
- args += this->Convert(this->Makefile->GetHomeDirectory(),
- START_OUTPUT, UNCHANGED, true);
+ args += this->GetSourceDirectory();
commandLine.push_back(args);
args = "-B";
- args +=
- this->Convert(this->Makefile->GetHomeOutputDirectory(),
- START_OUTPUT, UNCHANGED, true);
+ args += this->GetBinaryDirectory();
commandLine.push_back(args);
commandLine.push_back("--check-stamp-file");
- std::string stampFilename = this->Convert(stampName.c_str(), FULL,
- SHELL);
- commandLine.push_back(stampFilename.c_str());
+ 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;
- std::string fullpathStampName = this->Convert(stampName.c_str(), FULL,
- UNCHANGED);
- this->Makefile->AddCustomCommandToOutput(fullpathStampName.c_str(),
- listFiles, makefileIn.c_str(),
- commandLines, comment.c_str(),
- no_working_directory, true);
- if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
- {
+ 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);
+ if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) {
return file;
- }
- else
- {
+ } else {
cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
return 0;
- }
+ }
}
-void cmLocalVisualStudio7Generator::WriteConfigurations(std::ostream& fout,
- const char *libName,
- cmTarget &target)
+void cmLocalVisualStudio7Generator::WriteConfigurations(
+ std::ostream& fout, std::vector<std::string> const& configs,
+ const std::string& libName, cmGeneratorTarget* target)
{
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
-
fout << "\t<Configurations>\n";
- for( std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = configs.begin();
+ i != configs.end(); ++i) {
this->WriteConfiguration(fout, i->c_str(), libName, target);
- }
+ }
fout << "\t</Configurations>\n";
}
-cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] =
-{
- {"Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0},
- {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0},
- {"SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0},
- {"SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0},
- {"DebugInformationFormat", "Zi", "full debug", "debugEnabled", 0},
- {"DebugInformationFormat", "debug:full", "full debug", "debugEnabled", 0},
- {"DebugInformationFormat", "Z7", "c7 compat", "debugOldStyleInfo", 0},
- {"DebugInformationFormat", "Zd", "line numbers", "debugLineInfoOnly", 0},
- {"Optimization", "Od", "disable optimization", "optimizeDisabled", 0},
- {"Optimization", "O1", "min space", "optimizeMinSpace", 0},
- {"Optimization", "O3", "full optimize", "optimizeFull", 0},
- {"GlobalOptimizations", "Og", "global optimize", "true", 0},
- {"InlineFunctionExpansion", "Ob0", "", "expandDisable", 0},
- {"InlineFunctionExpansion", "Ob1", "", "expandOnlyInline", 0},
- {"FavorSizeOrSpeed", "Os", "", "favorSize", 0},
- {"OmitFramePointers", "Oy-", "", "false", 0},
- {"OptimizeForProcessor", "GB", "", "procOptimizeBlended", 0},
- {"OptimizeForProcessor", "G5", "", "procOptimizePentium", 0},
- {"OptimizeForProcessor", "G6", "", "procOptimizePentiumProThruIII", 0},
- {"UseProcessorExtensions", "QzxK", "", "codeForStreamingSIMD", 0},
- {"OptimizeForProcessor", "QaxN", "", "codeForPentium4", 0},
- {"OptimizeForProcessor", "QaxB", "", "codeForPentiumM", 0},
- {"OptimizeForProcessor", "QaxP", "", "codeForCodeNamedPrescott", 0},
- {"OptimizeForProcessor", "QaxT", "", "codeForCore2Duo", 0},
- {"OptimizeForProcessor", "QxK", "", "codeExclusivelyStreamingSIMD", 0},
- {"OptimizeForProcessor", "QxN", "", "codeExclusivelyPentium4", 0},
- {"OptimizeForProcessor", "QxB", "", "codeExclusivelyPentiumM", 0},
- {"OptimizeForProcessor", "QxP", "", "codeExclusivelyCodeNamedPrescott", 0},
- {"OptimizeForProcessor", "QxT", "", "codeExclusivelyCore2Duo", 0},
- {"OptimizeForProcessor", "QxO", "", "codeExclusivelyCore2StreamingSIMD", 0},
- {"OptimizeForProcessor", "QxS", "", "codeExclusivelyCore2StreamingSIMD4", 0},
-
- {"ModulePath", "module:", "", "",
- cmVS7FlagTable::UserValueRequired},
- {"LoopUnrolling", "Qunroll:", "", "",
- cmVS7FlagTable::UserValueRequired},
- {"AutoParallelThreshold", "Qpar-threshold:", "", "",
- cmVS7FlagTable::UserValueRequired},
- {"HeapArrays", "heap-arrays:", "", "",
- cmVS7FlagTable::UserValueRequired},
- {"ObjectText", "bintext:", "", "",
- cmVS7FlagTable::UserValueRequired},
- {"Parallelization", "Qparallel", "", "true", 0},
- {"PrefetchInsertion", "Qprefetch-", "", "false", 0},
- {"BufferedIO", "assume:buffered_io", "", "true", 0},
- {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0},
- {"CallingConvention", "iface:cref", "", "callConventionCRef", 0},
- {"CallingConvention", "iface:stdref", "", "callConventionStdRef", 0},
- {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0},
- {"CallingConvention", "iface:cvf", "", "callConventionCVF", 0},
- {"EnableRecursion", "recursive", "", "true", 0},
- {"ReentrantCode", "reentrancy", "", "true", 0},
+cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] = {
+ { "Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0 },
+ { "SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0 },
+ { "SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0 },
+ { "SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0 },
+ { "DebugInformationFormat", "Zi", "full debug", "debugEnabled", 0 },
+ { "DebugInformationFormat", "debug:full", "full debug", "debugEnabled", 0 },
+ { "DebugInformationFormat", "Z7", "c7 compat", "debugOldStyleInfo", 0 },
+ { "DebugInformationFormat", "Zd", "line numbers", "debugLineInfoOnly", 0 },
+ { "Optimization", "Od", "disable optimization", "optimizeDisabled", 0 },
+ { "Optimization", "O1", "min space", "optimizeMinSpace", 0 },
+ { "Optimization", "O3", "full optimize", "optimizeFull", 0 },
+ { "GlobalOptimizations", "Og", "global optimize", "true", 0 },
+ { "InlineFunctionExpansion", "Ob0", "", "expandDisable", 0 },
+ { "InlineFunctionExpansion", "Ob1", "", "expandOnlyInline", 0 },
+ { "FavorSizeOrSpeed", "Os", "", "favorSize", 0 },
+ { "OmitFramePointers", "Oy-", "", "false", 0 },
+ { "OptimizeForProcessor", "GB", "", "procOptimizeBlended", 0 },
+ { "OptimizeForProcessor", "G5", "", "procOptimizePentium", 0 },
+ { "OptimizeForProcessor", "G6", "", "procOptimizePentiumProThruIII", 0 },
+ { "UseProcessorExtensions", "QzxK", "", "codeForStreamingSIMD", 0 },
+ { "OptimizeForProcessor", "QaxN", "", "codeForPentium4", 0 },
+ { "OptimizeForProcessor", "QaxB", "", "codeForPentiumM", 0 },
+ { "OptimizeForProcessor", "QaxP", "", "codeForCodeNamedPrescott", 0 },
+ { "OptimizeForProcessor", "QaxT", "", "codeForCore2Duo", 0 },
+ { "OptimizeForProcessor", "QxK", "", "codeExclusivelyStreamingSIMD", 0 },
+ { "OptimizeForProcessor", "QxN", "", "codeExclusivelyPentium4", 0 },
+ { "OptimizeForProcessor", "QxB", "", "codeExclusivelyPentiumM", 0 },
+ { "OptimizeForProcessor", "QxP", "", "codeExclusivelyCodeNamedPrescott", 0 },
+ { "OptimizeForProcessor", "QxT", "", "codeExclusivelyCore2Duo", 0 },
+ { "OptimizeForProcessor", "QxO", "", "codeExclusivelyCore2StreamingSIMD",
+ 0 },
+ { "OptimizeForProcessor", "QxS", "", "codeExclusivelyCore2StreamingSIMD4",
+ 0 },
+ { "OpenMP", "Qopenmp", "", "OpenMPParallelCode", 0 },
+ { "OpenMP", "Qopenmp-stubs", "", "OpenMPSequentialCode", 0 },
+ { "Traceback", "traceback", "", "true", 0 },
+ { "Traceback", "notraceback", "", "false", 0 },
+ { "FloatingPointExceptionHandling", "fpe:0", "", "fpe0", 0 },
+ { "FloatingPointExceptionHandling", "fpe:1", "", "fpe1", 0 },
+ { "FloatingPointExceptionHandling", "fpe:3", "", "fpe3", 0 },
+
+ { "MultiProcessorCompilation", "MP", "", "true",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+ { "ProcessorNumber", "MP", "Multi-processor Compilation", "",
+ cmVS7FlagTable::UserValueRequired },
+
+ { "ModulePath", "module:", "", "", cmVS7FlagTable::UserValueRequired },
+ { "LoopUnrolling", "Qunroll:", "", "", cmVS7FlagTable::UserValueRequired },
+ { "AutoParallelThreshold", "Qpar-threshold:", "", "",
+ cmVS7FlagTable::UserValueRequired },
+ { "HeapArrays", "heap-arrays:", "", "", cmVS7FlagTable::UserValueRequired },
+ { "ObjectText", "bintext:", "", "", cmVS7FlagTable::UserValueRequired },
+ { "Parallelization", "Qparallel", "", "true", 0 },
+ { "PrefetchInsertion", "Qprefetch-", "", "false", 0 },
+ { "BufferedIO", "assume:buffered_io", "", "true", 0 },
+ { "CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0 },
+ { "CallingConvention", "iface:cref", "", "callConventionCRef", 0 },
+ { "CallingConvention", "iface:stdref", "", "callConventionStdRef", 0 },
+ { "CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0 },
+ { "CallingConvention", "iface:cvf", "", "callConventionCVF", 0 },
+ { "EnableRecursion", "recursive", "", "true", 0 },
+ { "ReentrantCode", "reentrancy", "", "true", 0 },
// done up to Language
- {0,0,0,0,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
// commandFlag comes FIRST!
-cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] =
-{
+cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = {
// option flags (some flags map to the same option)
- {"BasicRuntimeChecks", "GZ", "Stack frame checks", "1", 0},
- {"BasicRuntimeChecks", "RTCsu",
- "Both stack and uninitialized checks", "3", 0},
- {"BasicRuntimeChecks", "RTCs", "Stack frame checks", "1", 0},
- {"BasicRuntimeChecks", "RTCu", "Uninitialized Variables ", "2", 0},
- {"BasicRuntimeChecks", "RTC1",
- "Both stack and uninitialized checks", "3", 0},
- {"DebugInformationFormat", "Z7", "debug format", "1", 0},
- {"DebugInformationFormat", "Zd", "debug format", "2", 0},
- {"DebugInformationFormat", "Zi", "debug format", "3", 0},
- {"DebugInformationFormat", "ZI", "debug format", "4", 0},
- {"EnableEnhancedInstructionSet", "arch:SSE2",
- "Use sse2 instructions", "2", 0},
- {"EnableEnhancedInstructionSet", "arch:SSE",
- "Use sse instructions", "1", 0},
- {"FloatingPointModel", "fp:precise",
- "Use precise floating point model", "0", 0},
- {"FloatingPointModel", "fp:strict",
- "Use strict floating point model", "1", 0},
- {"FloatingPointModel", "fp:fast", "Use fast floating point model", "2", 0},
- {"FavorSizeOrSpeed", "Ot", "Favor fast code", "1", 0},
- {"FavorSizeOrSpeed", "Os", "Favor small code", "2", 0},
- {"CompileAs", "TC", "Compile as c code", "1", 0},
- {"CompileAs", "TP", "Compile as c++ code", "2", 0},
- {"Optimization", "Od", "Non Debug", "0", 0},
- {"Optimization", "O1", "Min Size", "1", 0},
- {"Optimization", "O2", "Max Speed", "2", 0},
- {"Optimization", "Ox", "Max Optimization", "3", 0},
- {"OptimizeForProcessor", "GB", "Blended processor mode", "0", 0},
- {"OptimizeForProcessor", "G5", "Pentium", "1", 0},
- {"OptimizeForProcessor", "G6", "PPro PII PIII", "2", 0},
- {"OptimizeForProcessor", "G7", "Pentium 4 or Athlon", "3", 0},
- {"InlineFunctionExpansion", "Ob0", "no inlines", "0", 0},
- {"InlineFunctionExpansion", "Ob1", "when inline keyword", "1", 0},
- {"InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0},
- {"RuntimeLibrary", "MTd", "Multithreaded debug", "1", 0},
- {"RuntimeLibrary", "MT", "Multithreaded", "0", 0},
- {"RuntimeLibrary", "MDd", "Multithreaded dll debug", "3", 0},
- {"RuntimeLibrary", "MD", "Multithreaded dll", "2", 0},
- {"RuntimeLibrary", "MLd", "Single Thread debug", "5", 0},
- {"RuntimeLibrary", "ML", "Single Thread", "4", 0},
- {"StructMemberAlignment", "Zp16", "struct align 16 byte ", "5", 0},
- {"StructMemberAlignment", "Zp1", "struct align 1 byte ", "1", 0},
- {"StructMemberAlignment", "Zp2", "struct align 2 byte ", "2", 0},
- {"StructMemberAlignment", "Zp4", "struct align 4 byte ", "3", 0},
- {"StructMemberAlignment", "Zp8", "struct align 8 byte ", "4", 0},
- {"WarningLevel", "W0", "Warning level", "0", 0},
- {"WarningLevel", "W1", "Warning level", "1", 0},
- {"WarningLevel", "W2", "Warning level", "2", 0},
- {"WarningLevel", "W3", "Warning level", "3", 0},
- {"WarningLevel", "W4", "Warning level", "4", 0},
- {"DisableSpecificWarnings", "wd", "Disable specific warnings", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ { "BasicRuntimeChecks", "GZ", "Stack frame checks", "1", 0 },
+ { "BasicRuntimeChecks", "RTCsu", "Both stack and uninitialized checks", "3",
+ 0 },
+ { "BasicRuntimeChecks", "RTCs", "Stack frame checks", "1", 0 },
+ { "BasicRuntimeChecks", "RTCu", "Uninitialized Variables ", "2", 0 },
+ { "BasicRuntimeChecks", "RTC1", "Both stack and uninitialized checks", "3",
+ 0 },
+ { "DebugInformationFormat", "Z7", "debug format", "1", 0 },
+ { "DebugInformationFormat", "Zd", "debug format", "2", 0 },
+ { "DebugInformationFormat", "Zi", "debug format", "3", 0 },
+ { "DebugInformationFormat", "ZI", "debug format", "4", 0 },
+ { "EnableEnhancedInstructionSet", "arch:SSE2", "Use sse2 instructions", "2",
+ 0 },
+ { "EnableEnhancedInstructionSet", "arch:SSE", "Use sse instructions", "1",
+ 0 },
+ { "FloatingPointModel", "fp:precise", "Use precise floating point model",
+ "0", 0 },
+ { "FloatingPointModel", "fp:strict", "Use strict floating point model", "1",
+ 0 },
+ { "FloatingPointModel", "fp:fast", "Use fast floating point model", "2", 0 },
+ { "FavorSizeOrSpeed", "Ot", "Favor fast code", "1", 0 },
+ { "FavorSizeOrSpeed", "Os", "Favor small code", "2", 0 },
+ { "CompileAs", "TC", "Compile as c code", "1", 0 },
+ { "CompileAs", "TP", "Compile as c++ code", "2", 0 },
+ { "Optimization", "Od", "Non Debug", "0", 0 },
+ { "Optimization", "O1", "Min Size", "1", 0 },
+ { "Optimization", "O2", "Max Speed", "2", 0 },
+ { "Optimization", "Ox", "Max Optimization", "3", 0 },
+ { "OptimizeForProcessor", "GB", "Blended processor mode", "0", 0 },
+ { "OptimizeForProcessor", "G5", "Pentium", "1", 0 },
+ { "OptimizeForProcessor", "G6", "PPro PII PIII", "2", 0 },
+ { "OptimizeForProcessor", "G7", "Pentium 4 or Athlon", "3", 0 },
+ { "InlineFunctionExpansion", "Ob0", "no inlines", "0", 0 },
+ { "InlineFunctionExpansion", "Ob1", "when inline keyword", "1", 0 },
+ { "InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0 },
+ { "RuntimeLibrary", "MTd", "Multithreaded debug", "1", 0 },
+ { "RuntimeLibrary", "MT", "Multithreaded", "0", 0 },
+ { "RuntimeLibrary", "MDd", "Multithreaded dll debug", "3", 0 },
+ { "RuntimeLibrary", "MD", "Multithreaded dll", "2", 0 },
+ { "RuntimeLibrary", "MLd", "Single Thread debug", "5", 0 },
+ { "RuntimeLibrary", "ML", "Single Thread", "4", 0 },
+ { "StructMemberAlignment", "Zp16", "struct align 16 byte ", "5", 0 },
+ { "StructMemberAlignment", "Zp1", "struct align 1 byte ", "1", 0 },
+ { "StructMemberAlignment", "Zp2", "struct align 2 byte ", "2", 0 },
+ { "StructMemberAlignment", "Zp4", "struct align 4 byte ", "3", 0 },
+ { "StructMemberAlignment", "Zp8", "struct align 8 byte ", "4", 0 },
+ { "WarningLevel", "W0", "Warning level", "0", 0 },
+ { "WarningLevel", "W1", "Warning level", "1", 0 },
+ { "WarningLevel", "W2", "Warning level", "2", 0 },
+ { "WarningLevel", "W3", "Warning level", "3", 0 },
+ { "WarningLevel", "W4", "Warning level", "4", 0 },
+ { "DisableSpecificWarnings", "wd", "Disable specific warnings", "",
+ cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// Precompiled header and related options. Note that the
// UsePrecompiledHeader entries are marked as "Continue" so that the
// corresponding PrecompiledHeaderThrough entry can be found.
- {"UsePrecompiledHeader", "Yc", "Create Precompiled Header", "1",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired},
- {"PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "",
- cmVS7FlagTable::UserValue},
+ { "UsePrecompiledHeader", "Yc", "Create Precompiled Header", "1",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+ { "PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "",
+ cmVS7FlagTable::UserValueRequired },
+ { "PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "",
+ cmVS7FlagTable::UserValue },
// The YX and Yu options are in a per-global-generator table because
// their values differ based on the VS IDE version.
- {"ForcedIncludeFiles", "FI", "Forced include files", "",
- cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SemicolonAppendable},
+ { "ForcedIncludeFiles", "FI", "Forced include files", "",
+ cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SemicolonAppendable },
- {"AssemblerListingLocation", "Fa", "ASM List Location", "",
- cmVS7FlagTable::UserValue},
- {"ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
- cmVS7FlagTable::UserValue},
+ { "AssemblerListingLocation", "Fa", "ASM List Location", "",
+ cmVS7FlagTable::UserValue },
+ { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
+ cmVS7FlagTable::UserValue },
// boolean flags
- {"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0},
- {"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "FALSE", 0},
- {"Detect64BitPortabilityProblems", "Wp64",
- "Detect 64-bit Portability Problems", "TRUE", 0},
- {"EnableFiberSafeOptimizations", "GT", "Enable Fiber-safe Optimizations",
- "TRUE", 0},
- {"EnableFunctionLevelLinking", "Gy",
- "EnableFunctionLevelLinking", "TRUE", 0},
- {"EnableIntrinsicFunctions", "Oi", "EnableIntrinsicFunctions", "TRUE", 0},
- {"GlobalOptimizations", "Og", "Global Optimize", "TRUE", 0},
- {"ImproveFloatingPointConsistency", "Op",
- "ImproveFloatingPointConsistency", "TRUE", 0},
- {"MinimalRebuild", "Gm", "minimal rebuild", "TRUE", 0},
- {"OmitFramePointers", "Oy", "OmitFramePointers", "TRUE", 0},
- {"OptimizeForWindowsApplication", "GA", "Optimize for windows", "TRUE", 0},
- {"RuntimeTypeInfo", "GR",
- "Turn on Run time type information for c++", "TRUE", 0},
- {"RuntimeTypeInfo", "GR-",
- "Turn off Run time type information for c++", "FALSE", 0},
- {"SmallerTypeCheck", "RTCc", "smaller type check", "TRUE", 0},
- {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "TRUE", 0},
- {"WholeProgramOptimization", "GL",
- "Enables whole program optimization", "TRUE", 0},
- {"WholeProgramOptimization", "GL-",
- "Disables whole program optimization", "FALSE", 0},
- {"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}
+ { "BufferSecurityCheck", "GS", "Buffer security check", "true", 0 },
+ { "BufferSecurityCheck", "GS-", "Turn off Buffer security check", "false",
+ 0 },
+ { "Detect64BitPortabilityProblems", "Wp64",
+ "Detect 64-bit Portability Problems", "true", 0 },
+ { "EnableFiberSafeOptimizations", "GT", "Enable Fiber-safe Optimizations",
+ "true", 0 },
+ { "EnableFunctionLevelLinking", "Gy", "EnableFunctionLevelLinking", "true",
+ 0 },
+ { "EnableIntrinsicFunctions", "Oi", "EnableIntrinsicFunctions", "true", 0 },
+ { "GlobalOptimizations", "Og", "Global Optimize", "true", 0 },
+ { "ImproveFloatingPointConsistency", "Op", "ImproveFloatingPointConsistency",
+ "true", 0 },
+ { "MinimalRebuild", "Gm", "minimal rebuild", "true", 0 },
+ { "OmitFramePointers", "Oy", "OmitFramePointers", "true", 0 },
+ { "OptimizeForWindowsApplication", "GA", "Optimize for windows", "true", 0 },
+ { "RuntimeTypeInfo", "GR", "Turn on Run time type information for c++",
+ "true", 0 },
+ { "RuntimeTypeInfo", "GR-", "Turn off Run time type information for c++",
+ "false", 0 },
+ { "SmallerTypeCheck", "RTCc", "smaller type check", "true", 0 },
+ { "SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0 },
+ { "WholeProgramOptimization", "GL", "Enables whole program optimization",
+ "true", 0 },
+ { "WholeProgramOptimization", "GL-", "Disables whole program optimization",
+ "false", 0 },
+ { "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 }
};
-
-
-cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] =
-{
+cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] = {
// option flags (some flags map to the same option)
- {"GenerateManifest", "MANIFEST:NO",
- "disable manifest generation", "FALSE", 0},
- {"GenerateManifest", "MANIFEST", "enable manifest generation", "TRUE", 0},
- {"LinkIncremental", "INCREMENTAL:NO", "link incremental", "1", 0},
- {"LinkIncremental", "INCREMENTAL:YES", "link incremental", "2", 0},
- {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0},
- {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0},
- {"DataExecutionPrevention", "NXCOMPAT:NO",
- "Not known to work with Windows Data Execution Prevention", "1", 0},
- {"DataExecutionPrevention", "NXCOMPAT",
- "Known to work with Windows Data Execution Prevention", "2", 0},
- {"DelaySign", "DELAYSIGN:NO", "", "false", 0},
- {"DelaySign", "DELAYSIGN", "", "true", 0},
- {"EntryPointSymbol", "ENTRY:", "sets the starting address", "",
- cmVS7FlagTable::UserValue},
- {"IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "default libs to ignore", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
- {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "ignore all default libs",
- "TRUE", 0},
- {"FixedBaseAddress", "FIXED:NO", "Generate a relocation section", "1", 0},
- {"FixedBaseAddress", "FIXED", "Image must be loaded at a fixed address",
- "2", 0},
- {"EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs",
- "1", 0},
- {"EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "2", 0},
- {"ResourceOnlyDLL", "NOENTRY", "Create DLL with no entry point", "true", 0},
- {"OptimizeReferences", "OPT:NOREF", "Keep unreferenced data", "1", 0},
- {"OptimizeReferences", "OPT:REF", "Eliminate unreferenced data", "2", 0},
- {"Profile", "PROFILE", "", "true", 0},
- {"RandomizedBaseAddress", "DYNAMICBASE:NO",
- "Image may not be rebased at load-time", "1", 0},
- {"RandomizedBaseAddress", "DYNAMICBASE",
- "Image may be rebased at load-time", "2", 0},
- {"SetChecksum", "RELEASE", "Enable setting checksum in header", "true", 0},
- {"SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0},
- {"TargetMachine", "MACHINE:I386", "Machine x86", "1", 0},
- {"TargetMachine", "MACHINE:X86", "Machine x86", "1", 0},
- {"TargetMachine", "MACHINE:AM33", "Machine AM33", "2", 0},
- {"TargetMachine", "MACHINE:ARM", "Machine ARM", "3", 0},
- {"TargetMachine", "MACHINE:EBC", "Machine EBC", "4", 0},
- {"TargetMachine", "MACHINE:IA64", "Machine IA64", "5", 0},
- {"TargetMachine", "MACHINE:M32R", "Machine M32R", "6", 0},
- {"TargetMachine", "MACHINE:MIPS", "Machine MIPS", "7", 0},
- {"TargetMachine", "MACHINE:MIPS16", "Machine MIPS16", "8", 0},
- {"TargetMachine", "MACHINE:MIPSFPU)", "Machine MIPSFPU", "9", 0},
- {"TargetMachine", "MACHINE:MIPSFPU16", "Machine MIPSFPU16", "10", 0},
- {"TargetMachine", "MACHINE:MIPSR41XX", "Machine MIPSR41XX", "11", 0},
- {"TargetMachine", "MACHINE:SH3", "Machine SH3", "12", 0},
- {"TargetMachine", "MACHINE:SH3DSP", "Machine SH3DSP", "13", 0},
- {"TargetMachine", "MACHINE:SH4", "Machine SH4", "14", 0},
- {"TargetMachine", "MACHINE:SH5", "Machine SH5", "15", 0},
- {"TargetMachine", "MACHINE:THUMB", "Machine THUMB", "16", 0},
- {"TargetMachine", "MACHINE:X64", "Machine x64", "17", 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}
+ { "GenerateManifest", "MANIFEST:NO", "disable manifest generation", "false",
+ 0 },
+ { "GenerateManifest", "MANIFEST", "enable manifest generation", "true", 0 },
+ { "LinkIncremental", "INCREMENTAL:NO", "link incremental", "1", 0 },
+ { "LinkIncremental", "INCREMENTAL:YES", "link incremental", "2", 0 },
+ { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
+ { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
+ { "DataExecutionPrevention", "NXCOMPAT:NO",
+ "Not known to work with Windows Data Execution Prevention", "1", 0 },
+ { "DataExecutionPrevention", "NXCOMPAT",
+ "Known to work with Windows Data Execution Prevention", "2", 0 },
+ { "DelaySign", "DELAYSIGN:NO", "", "false", 0 },
+ { "DelaySign", "DELAYSIGN", "", "true", 0 },
+ { "EntryPointSymbol", "ENTRY:", "sets the starting address", "",
+ cmVS7FlagTable::UserValue },
+ { "IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "default libs to ignore", "",
+ cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+ { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "ignore all default libs",
+ "true", 0 },
+ { "FixedBaseAddress", "FIXED:NO", "Generate a relocation section", "1", 0 },
+ { "FixedBaseAddress", "FIXED", "Image must be loaded at a fixed address",
+ "2", 0 },
+ { "EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs", "1",
+ 0 },
+ { "EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "2", 0 },
+ { "ResourceOnlyDLL", "NOENTRY", "Create DLL with no entry point", "true",
+ 0 },
+ { "OptimizeReferences", "OPT:NOREF", "Keep unreferenced data", "1", 0 },
+ { "OptimizeReferences", "OPT:REF", "Eliminate unreferenced data", "2", 0 },
+ { "Profile", "PROFILE", "", "true", 0 },
+ { "RandomizedBaseAddress", "DYNAMICBASE:NO",
+ "Image may not be rebased at load-time", "1", 0 },
+ { "RandomizedBaseAddress", "DYNAMICBASE",
+ "Image may be rebased at load-time", "2", 0 },
+ { "SetChecksum", "RELEASE", "Enable setting checksum in header", "true", 0 },
+ { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
+ { "TargetMachine", "MACHINE:I386", "Machine x86", "1", 0 },
+ { "TargetMachine", "MACHINE:X86", "Machine x86", "1", 0 },
+ { "TargetMachine", "MACHINE:AM33", "Machine AM33", "2", 0 },
+ { "TargetMachine", "MACHINE:ARM", "Machine ARM", "3", 0 },
+ { "TargetMachine", "MACHINE:EBC", "Machine EBC", "4", 0 },
+ { "TargetMachine", "MACHINE:IA64", "Machine IA64", "5", 0 },
+ { "TargetMachine", "MACHINE:M32R", "Machine M32R", "6", 0 },
+ { "TargetMachine", "MACHINE:MIPS", "Machine MIPS", "7", 0 },
+ { "TargetMachine", "MACHINE:MIPS16", "Machine MIPS16", "8", 0 },
+ { "TargetMachine", "MACHINE:MIPSFPU)", "Machine MIPSFPU", "9", 0 },
+ { "TargetMachine", "MACHINE:MIPSFPU16", "Machine MIPSFPU16", "10", 0 },
+ { "TargetMachine", "MACHINE:MIPSR41XX", "Machine MIPSR41XX", "11", 0 },
+ { "TargetMachine", "MACHINE:SH3", "Machine SH3", "12", 0 },
+ { "TargetMachine", "MACHINE:SH3DSP", "Machine SH3DSP", "13", 0 },
+ { "TargetMachine", "MACHINE:SH4", "Machine SH4", "14", 0 },
+ { "TargetMachine", "MACHINE:SH5", "Machine SH5", "15", 0 },
+ { "TargetMachine", "MACHINE:THUMB", "Machine THUMB", "16", 0 },
+ { "TargetMachine", "MACHINE:X64", "Machine x64", "17", 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 }
+};
+
+cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = {
+ { "LinkIncremental", "INCREMENTAL:NO", "link incremental",
+ "linkIncrementalNo", 0 },
+ { "LinkIncremental", "INCREMENTAL:YES", "link incremental",
+ "linkIncrementalYes", 0 },
+ { 0, 0, 0, 0, 0 }
};
-//----------------------------------------------------------------------------
// Helper class to write build event <Tool .../> elements.
class cmLocalVisualStudio7Generator::EventWriter
{
public:
- EventWriter(cmLocalVisualStudio7Generator* lg,
- const char* config, std::ostream& os):
- LG(lg), Config(config), Stream(os), First(true) {}
+ EventWriter(cmLocalVisualStudio7Generator* lg, const std::string& config,
+ std::ostream& os)
+ : LG(lg)
+ , Config(config)
+ , Stream(os)
+ , First(true)
+ {
+ }
void Start(const char* tool)
- {
+ {
this->First = true;
this->Stream << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"";
- }
- void Finish()
- {
- this->Stream << (this->First? "" : "\"") << "/>\n";
- }
+ }
+ 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)
- {
+ {
+ for (std::vector<cmCustomCommand>::const_iterator ci = ccs.begin();
+ ci != ccs.end(); ++ci) {
this->Write(*ci);
- }
}
+ }
void Write(cmCustomCommand const& cc)
- {
- if(this->First)
- {
- const char* comment = cc.GetComment();
- if(comment && *comment)
- {
- this->Stream << "\nDescription=\""
- << this->LG->EscapeForXML(comment) << "\"";
- }
+ {
+ cmCustomCommandGenerator ccg(cc, this->Config, this->LG);
+ if (this->First) {
+ const char* comment = ccg.GetComment();
+ if (comment && *comment) {
+ this->Stream << "\nDescription=\"" << this->LG->EscapeForXML(comment)
+ << "\"";
+ }
this->Stream << "\nCommandLine=\"";
this->First = false;
- }
- else
- {
+ } else {
this->Stream << this->LG->EscapeForXML("\n");
- }
- std::string script = this->LG->ConstructScript(cc, this->Config);
- this->Stream << this->LG->EscapeForXML(script.c_str());
}
+ std::string script = this->LG->ConstructScript(ccg);
+ this->Stream << this->LG->EscapeForXML(script.c_str());
+ }
+
private:
cmLocalVisualStudio7Generator* LG;
- const char* Config;
+ std::string Config;
std::ostream& Stream;
bool First;
};
-//----------------------------------------------------------------------------
-void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
- const char* configName,
- const char *libName,
- cmTarget &target)
+void cmLocalVisualStudio7Generator::WriteConfiguration(
+ std::ostream& fout, const std::string& configName,
+ const std::string& libName, cmGeneratorTarget* target)
{
const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
- if(!mfcFlag)
- {
+ if (!mfcFlag) {
mfcFlag = "0";
- }
+ }
+ cmGlobalVisualStudio7Generator* gg =
+ static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
fout << "\t\t<Configuration\n"
- << "\t\t\tName=\"" << configName << "|" << this->PlatformName << "\"\n"
- << "\t\t\tOutputDirectory=\"" << configName << "\"\n";
+ << "\t\t\tName=\"" << configName << "|" << gg->GetPlatformName()
+ << "\"\n";
// This is an internal type to Visual Studio, it seems that:
// 4 == static library
// 2 == dll
@@ -652,103 +612,100 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
const char* configType = "10";
const char* projectType = 0;
bool targetBuilds = true;
- switch(target.GetType())
- {
- case cmTarget::OBJECT_LIBRARY:
- targetBuilds = false; // TODO: PDB for object library?
- case cmTarget::STATIC_LIBRARY:
+
+ switch (target->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
+ targetBuilds = false; // no manifest tool for object library
+ case cmStateEnums::STATIC_LIBRARY:
projectType = "typeStaticLibrary";
configType = "4";
break;
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
projectType = "typeDynamicLibrary";
configType = "2";
break;
- case cmTarget::EXECUTABLE:
+ case cmStateEnums::EXECUTABLE:
configType = "1";
break;
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
configType = "10";
default:
targetBuilds = false;
break;
- }
- if(this->FortranProject && projectType)
- {
+ }
+ if (this->FortranProject && projectType) {
configType = projectType;
- }
+ }
std::string flags;
- if(strcmp(configType, "10") != 0)
- {
- const char* linkLanguage = (this->FortranProject? "Fortran":
- target.GetLinkerLanguage(configName));
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- target.GetName());
+ if (strcmp(configType, "10") != 0) {
+ 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());
return;
- }
- if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
- || strcmp(linkLanguage, "Fortran") == 0)
- {
+ }
+ 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);
+ std::string flagVar =
+ baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
flags += " ";
flags += this->Makefile->GetRequiredDefinition(flagVar.c_str());
- }
+ }
// set the correct language
- if(strcmp(linkLanguage, "C") == 0)
- {
+ if (linkLanguage == "C") {
flags += " /TC ";
- }
- if(strcmp(linkLanguage, "CXX") == 0)
- {
+ }
+ if (linkLanguage == "CXX") {
flags += " /TP ";
- }
-
- // Add the target-specific flags.
- this->AddCompileOptions(flags, &target, linkLanguage, configName);
}
- if(this->FortranProject)
- {
- switch(this->GetFortranFormat(target.GetProperty("Fortran_FORMAT")))
- {
- case FortranFormatFixed: flags += " -fixed"; break;
- case FortranFormatFree: flags += " -free"; break;
- default: break;
- }
- }
+ // Add the target-specific flags.
+ this->AddCompileOptions(flags, target, linkLanguage, configName);
+
+ // Check IPO related warning/error.
+ target->IsIPOEnabled(linkLanguage, configName);
+ }
+
+ if (this->FortranProject) {
+ switch (cmOutputConverter::GetFortranFormat(
+ target->GetProperty("Fortran_FORMAT"))) {
+ case cmOutputConverter::FortranFormatFixed:
+ flags += " -fixed";
+ break;
+ case cmOutputConverter::FortranFormatFree:
+ flags += " -free";
+ break;
+ default:
+ break;
+ }
+ }
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
Options::Tool t = Options::Compiler;
cmVS7FlagTable const* table = cmLocalVisualStudio7GeneratorFlagTable;
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
t = Options::FortranCompiler;
table = cmLocalVisualStudio7GeneratorFortranFlagTable;
- }
- Options targetOptions(this, t,
- table,
- this->ExtraFlagTable);
+ }
+ Options targetOptions(this, t, table, gg->ExtraFlagTable);
targetOptions.FixExceptionHandlingDefault();
- std::string asmLocation = std::string(configName) + "/";
+ std::string asmLocation = configName + "/";
targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.ParseFinish();
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
std::vector<std::string> targetDefines;
- target.GetCompileDefinitions(targetDefines, configName);
+ target->GetCompileDefinitions(targetDefines, configName, "CXX");
targetOptions.AddDefines(targetDefines);
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -760,137 +717,178 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.AddDefine(configDefine);
// Add the export symbol definition for shared library objects.
- if(const char* exportMacro = target.GetExportMacro())
- {
+ if (const char* 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;
+
+ if (target->GetType() < cmStateEnums::UTILITY) {
+ std::string const& outDir =
+ target->GetType() == cmStateEnums::OBJECT_LIBRARY
+ ? intermediateDir
+ : target->GetDirectory(configName);
+ /* clang-format off */
+ fout << "\t\t\tOutputDirectory=\""
+ << this->ConvertToXMLOutputPathSingle(outDir.c_str()) << "\"\n";
+ /* clang-format on */
+ }
+
+ /* clang-format off */
fout << "\t\t\tIntermediateDirectory=\""
<< this->ConvertToXMLOutputPath(intermediateDir.c_str())
<< "\"\n"
<< "\t\t\tConfigurationType=\"" << configType << "\"\n"
<< "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n"
- << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n";
+ << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n";
+ /* clang-format on */
+
+ if (this->FortranProject) {
+ // Intel Fortran >= 15.0 uses TargetName property.
+ std::string const targetNameFull = target->GetFullName(configName);
+ std::string const targetName =
+ cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
+ std::string const targetExt =
+ target->GetType() == cmStateEnums::OBJECT_LIBRARY
+ ? ".lib"
+ : cmSystemTools::GetFilenameLastExtension(targetNameFull);
+ /* clang-format off */
+ fout <<
+ "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n"
+ "\t\t\tTargetExt=\"" << this->EscapeForXML(targetExt) << "\"\n"
+ ;
+ /* clang-format on */
+ }
// If unicode is enabled change the character set to unicode, if not
// then default to MBCS.
- if(targetOptions.UsingUnicode())
- {
+ if (targetOptions.UsingUnicode()) {
fout << "\t\t\tCharacterSet=\"1\">\n";
- }
- else if(targetOptions.UsingSBCS())
- {
+ } else if (targetOptions.UsingSBCS()) {
fout << "\t\t\tCharacterSet=\"0\">\n";
- }
- else
- {
+ } else {
fout << "\t\t\tCharacterSet=\"2\">\n";
- }
+ }
const char* tool = "VCCLCompilerTool";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
tool = "VFFortranCompilerTool";
- }
+ }
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"" << tool << "\"\n";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
const char* target_mod_dir =
- target.GetProperty("Fortran_MODULE_DIRECTORY");
+ target->GetProperty("Fortran_MODULE_DIRECTORY");
std::string modDir;
- if(target_mod_dir)
- {
- modDir = this->Convert(target_mod_dir,
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED);
- }
- else
- {
+ if (target_mod_dir) {
+ modDir = this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(),
+ target_mod_dir);
+ } else {
modDir = ".";
- }
+ }
fout << "\t\t\t\tModulePath=\""
<< this->ConvertToXMLOutputPath(modDir.c_str())
<< "\\$(ConfigurationName)\"\n";
- }
- targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
+ }
fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes;
- this->GetIncludeDirectories(includes, gt, "C", configName);
+ this->GetIncludeDirectories(includes, target, "C", configName);
std::vector<std::string>::iterator i = includes.begin();
- for(;i != includes.end(); ++i)
- {
+ 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)
- {
+ 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");
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
- fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool
+ if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
+ // Specify the compiler program database file if configured.
+ std::string pdb = target->GetCompilePDBPath(configName);
+ if (!pdb.empty()) {
+ fout << "\t\t\t\tProgramDataBaseFileName=\""
+ << this->ConvertToXMLOutputPathSingle(pdb.c_str()) << "\"\n";
+ }
+ }
+ fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool
+ if (gg->IsMasmEnabled() && !this->FortranProject) {
+ Options masmOptions(this, Options::MasmCompiler, 0, 0);
+ /* clang-format off */
+ 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";
+ // Use same preprocessor definitions as VCCLCompilerTool.
+ targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
+ "ASM_MASM");
+ masmOptions.OutputFlagMap(fout, "\t\t\t\t");
+ /* clang-format off */
+ fout <<
+ "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"
+ "\t\t\t/>\n";
+ /* clang-format on */
+ }
tool = "VCCustomBuildTool";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
tool = "VFCustomBuildTool";
- }
+ }
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"/>\n";
tool = "VCResourceCompilerTool";
- if(this->FortranProject)
- {
+ 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)
- {
+ for (i = includes.begin(); i != includes.end(); ++i) {
std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
fout << ipath << ";";
- }
+ }
// add the -D flags to the RC tool
fout << "\"";
targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
fout << "/>\n";
tool = "VCMIDLTool";
- if(this->FortranProject)
- {
+ 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)
- {
+ for (i = includes.begin(); i != includes.end(); ++i) {
std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
fout << ipath << ";";
- }
+ }
fout << "\"\n";
- fout << "\t\t\t\tMkTypLibCompatible=\"FALSE\"\n";
- if( this->PlatformName == "x64" )
- {
+ fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
+ if (gg->GetPlatformName() == "x64") {
fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
- }
- else if( this->PlatformName == "ia64" )
- {
+ } else if (gg->GetPlatformName() == "ia64") {
fout << "\t\t\t\tTargetEnvironment=\"2\"\n";
- }
- else
- {
+ } else {
fout << "\t\t\t\tTargetEnvironment=\"1\"\n";
- }
- fout << "\t\t\t\tGenerateStublessProxies=\"TRUE\"\n";
+ }
+ fout << "\t\t\t\tGenerateStublessProxies=\"true\"\n";
fout << "\t\t\t\tTypeLibraryName=\"$(InputName).tlb\"\n";
fout << "\t\t\t\tOutputDirectory=\"$(IntDir)\"\n";
fout << "\t\t\t\tHeaderFileName=\"$(InputName).h\"\n";
@@ -899,532 +897,509 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n";
// end of <Tool Name=VCMIDLTool
- // Check if we need the FAT32 workaround.
- if(targetBuilds && this->Version >= VS8)
- {
+ // Add manifest tool settings.
+ if (targetBuilds) {
+ const char* manifestTool = "VCManifestTool";
+ if (this->FortranProject) {
+ manifestTool = "VFManifestTool";
+ }
+ /* clang-format off */
+ fout <<
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"" << manifestTool << "\"";
+ /* clang-format on */
+
+ std::vector<cmSourceFile const*> manifest_srcs;
+ 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();
+ fout << this->ConvertToXMLOutputPath(m.c_str()) << ";";
+ }
+ fout << "\"";
+ }
+
+ // Check if we need the FAT32 workaround.
// Check the filesystem type where the target will be written.
- if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
- {
+ if (cmLVS7G_IsFAT(target->GetDirectory(configName).c_str())) {
// Add a flag telling the manifest tool to use a workaround
// for FAT32 file systems, which can cause an empty manifest
// to be embedded into the resulting executable. See CMake
// bug #2617.
- const char* manifestTool = "VCManifestTool";
- if(this->FortranProject)
- {
- manifestTool = "VFManifestTool";
- }
- fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << manifestTool << "\"\n"
- << "\t\t\t\tUseFAT32Workaround=\"true\"\n"
- << "\t\t\t/>\n";
- }
+ fout << "\n\t\t\t\tUseFAT32Workaround=\"true\"";
}
+ fout << "/>\n";
+ }
this->OutputTargetRules(fout, configName, target, libName);
this->OutputBuildTool(fout, configName, target, targetOptions);
+ this->OutputDeploymentDebuggerTool(fout, configName, target);
fout << "\t\t</Configuration>\n";
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalVisualStudio7Generator
-::GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const char* configName)
+std::string cmLocalVisualStudio7Generator::GetBuildTypeLinkerFlags(
+ std::string rootLinkerFlags, const std::string& configName)
{
std::string configTypeUpper = cmSystemTools::UpperCase(configName);
std::string extraLinkOptionsBuildTypeDef =
rootLinkerFlags + "_" + configTypeUpper;
std::string extraLinkOptionsBuildType =
- this->Makefile->GetRequiredDefinition
- (extraLinkOptionsBuildTypeDef.c_str());
+ this->Makefile->GetRequiredDefinition(
+ extraLinkOptionsBuildTypeDef.c_str());
return extraLinkOptionsBuildType;
}
-void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
- const char* configName, cmTarget &target, const Options& targetOptions)
+void cmLocalVisualStudio7Generator::OutputBuildTool(
+ std::ostream& fout, const std::string& configName, cmGeneratorTarget* target,
+ const Options& targetOptions)
{
cmGlobalVisualStudio7Generator* gg =
static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
std::string temp;
std::string extraLinkOptions;
- if(target.GetType() == cmTarget::EXECUTABLE)
- {
+ if (target->GetType() == cmStateEnums::EXECUTABLE) {
extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS")
- + std::string(" ")
- + GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName);
- }
- if(target.GetType() == cmTarget::SHARED_LIBRARY)
- {
+ this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") +
+ std::string(" ") +
+ 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);
- }
- if(target.GetType() == cmTarget::MODULE_LIBRARY)
- {
+ this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") +
+ std::string(" ") +
+ 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);
- }
+ this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS") +
+ std::string(" ") +
+ GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
+ }
- const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
- if(targetLinkFlags)
- {
+ const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
+ if (targetLinkFlags) {
extraLinkOptions += " ";
extraLinkOptions += targetLinkFlags;
- }
+ }
std::string configTypeUpper = cmSystemTools::UpperCase(configName);
std::string linkFlagsConfig = "LINK_FLAGS_";
linkFlagsConfig += configTypeUpper;
- targetLinkFlags = target.GetProperty(linkFlagsConfig.c_str());
- if(targetLinkFlags)
- {
+ targetLinkFlags = target->GetProperty(linkFlagsConfig.c_str());
+ if (targetLinkFlags) {
extraLinkOptions += " ";
extraLinkOptions += targetLinkFlags;
- }
- Options linkOptions(this, Options::Linker,
- cmLocalVisualStudio7GeneratorLinkFlagTable);
+ }
+ Options linkOptions(this, Options::Linker);
+ if (this->FortranProject) {
+ linkOptions.AddTable(cmLocalVisualStudio7GeneratorFortranLinkFlagTable);
+ }
+ linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable);
+
linkOptions.Parse(extraLinkOptions.c_str());
- if(!this->ModuleDefinitionFile.empty())
- {
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ target->GetModuleDefinitionInfo(configName);
+ if (mdi && !mdi->DefFile.empty()) {
std::string defFile =
- this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str());
+ this->ConvertToOutputFormat(mdi->DefFile, cmOutputConverter::SHELL);
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
- }
- switch(target.GetType())
- {
- case cmTarget::UNKNOWN_LIBRARY:
+ }
+
+ switch (target->GetType()) {
+ case cmStateEnums::UNKNOWN_LIBRARY:
break;
- case cmTarget::OBJECT_LIBRARY:
- {
+ case cmStateEnums::OBJECT_LIBRARY: {
std::string libpath = this->GetTargetDirectory(target);
libpath += "/";
libpath += configName;
libpath += "/";
- libpath += target.GetName();
+ libpath += target->GetName();
libpath += ".lib";
const char* tool =
- this->FortranProject? "VFLibrarianTool":"VCLibrarianTool";
+ this->FortranProject ? "VFLibrarianTool" : "VCLibrarianTool";
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"" << tool << "\"\n";
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
break;
- }
- case cmTarget::STATIC_LIBRARY:
- {
- std::string targetNameFull = target.GetFullName(configName);
- std::string libpath = target.GetDirectory(configName);
- libpath += "/";
- libpath += targetNameFull;
- const char* tool = "VCLibrarianTool";
- if(this->FortranProject)
- {
- tool = "VFLibrarianTool";
- }
- fout << "\t\t\t<Tool\n"
- << "\t\t\t\tName=\"" << tool << "\"\n";
-
- if(this->GetVersion() < VS8)
- {
- cmOStringStream libdeps;
- this->Internal->OutputObjects(libdeps, &target);
- if(!libdeps.str().empty())
- {
- fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n";
- }
- }
- std::string libflags;
- this->GetStaticLibraryFlags(libflags, configTypeUpper, &target);
- if(!libflags.empty())
- {
- fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
- }
- fout << "\t\t\t\tOutputFile=\""
- << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
- break;
}
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::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);
-
- // Compute the link library and directory information.
- cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
- if(!pcli)
- {
- return;
- }
- cmComputeLinkInformation& cli = *pcli;
- const char* linkLanguage = cli.GetLinkLanguage();
-
- // Compute the variable name to lookup standard libraries for this
- // language.
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += linkLanguage;
- standardLibsVar += "_STANDARD_LIBRARIES";
- const char* tool = "VCLinkerTool";
- if(this->FortranProject)
- {
- tool = "VFLinkerTool";
- }
- fout << "\t\t\t<Tool\n"
- << "\t\t\t\tName=\"" << tool << "\"\n";
- if(!gg->NeedLinkLibraryDependencies(target))
- {
- fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
- }
- linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
- // 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());
- if(this->GetVersion() < VS8)
- {
- this->Internal->OutputObjects(fout, &target, " ");
- }
- fout << " ";
- this->Internal->OutputLibraries(fout, cli.GetItems());
- fout << "\"\n";
- temp = target.GetDirectory(configName);
- temp += "/";
- temp += targetNameFull;
- fout << "\t\t\t\tOutputFile=\""
- << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
- this->WriteTargetVersionAttribute(fout, target);
- linkOptions.OutputFlagMap(fout, "\t\t\t\t");
- fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
- this->OutputLibraryDirectories(fout, cli.GetDirectories());
- fout << "\"\n";
- temp = target.GetPDBDirectory(configName);
- temp += "/";
- temp += targetNamePDB;
- fout << "\t\t\t\tProgramDatabaseFile=\"" <<
- this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
- if(targetOptions.IsDebug())
- {
- fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
+ case cmStateEnums::STATIC_LIBRARY: {
+ std::string targetNameFull = target->GetFullName(configName);
+ std::string libpath = target->GetDirectory(configName);
+ libpath += "/";
+ libpath += targetNameFull;
+ const char* tool = "VCLibrarianTool";
+ if (this->FortranProject) {
+ tool = "VFLibrarianTool";
}
- if(this->WindowsCEProject)
- {
- if(this->GetVersion() < VS9)
- {
- fout << "\t\t\t\tSubSystem=\"9\"\n";
- }
- else
- {
- fout << "\t\t\t\tSubSystem=\"8\"\n";
+ fout << "\t\t\t<Tool\n"
+ << "\t\t\t\tName=\"" << tool << "\"\n";
+
+ if (this->FortranProject) {
+ std::ostringstream libdeps;
+ this->Internal->OutputObjects(libdeps, target, configName);
+ if (!libdeps.str().empty()) {
+ fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str()
+ << "\"\n";
}
}
- std::string stackVar = "CMAKE_";
- stackVar += linkLanguage;
- stackVar += "_STACK_SIZE";
- const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
- if(stackVal)
- {
- fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n";
- }
- temp = target.GetDirectory(configName, true);
- temp += "/";
- temp += targetNameImport;
- fout << "\t\t\t\tImportLibrary=\""
- << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"";
- if(this->FortranProject)
- {
- fout << "\n\t\t\t\tLinkDLL=\"true\"";
+ std::string libflags;
+ this->GetStaticLibraryFlags(libflags, configTypeUpper, target);
+ if (!libflags.empty()) {
+ fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
}
- fout << "/>\n";
+ fout << "\t\t\t\tOutputFile=\""
+ << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
+ break;
}
- break;
- case cmTarget::EXECUTABLE:
- {
- std::string targetName;
- std::string targetNameFull;
- std::string targetNameImport;
- std::string targetNamePDB;
- target.GetExecutableNames(targetName, targetNameFull,
+ 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);
- // Compute the link library and directory information.
- cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
- if(!pcli)
- {
- return;
+ // Compute the link library and directory information.
+ cmComputeLinkInformation* pcli = target->GetLinkInformation(configName);
+ if (!pcli) {
+ return;
}
- cmComputeLinkInformation& cli = *pcli;
- const char* linkLanguage = cli.GetLinkLanguage();
-
- bool isWin32Executable = target.GetPropertyAsBool("WIN32_EXECUTABLE");
-
- // Compute the variable name to lookup standard libraries for this
- // language.
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += linkLanguage;
- standardLibsVar += "_STANDARD_LIBRARIES";
- const char* tool = "VCLinkerTool";
- if(this->FortranProject)
- {
- tool = "VFLinkerTool";
+ cmComputeLinkInformation& cli = *pcli;
+ std::string linkLanguage = cli.GetLinkLanguage();
+
+ // Compute the variable name to lookup standard libraries for this
+ // language.
+ std::string standardLibsVar = "CMAKE_";
+ standardLibsVar += linkLanguage;
+ standardLibsVar += "_STANDARD_LIBRARIES";
+ const char* tool = "VCLinkerTool";
+ if (this->FortranProject) {
+ tool = "VFLinkerTool";
}
- fout << "\t\t\t<Tool\n"
- << "\t\t\t\tName=\"" << tool << "\"\n";
- if(!gg->NeedLinkLibraryDependencies(target))
- {
- fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
+ fout << "\t\t\t<Tool\n"
+ << "\t\t\t\tName=\"" << tool << "\"\n";
+ if (!gg->NeedLinkLibraryDependencies(target)) {
+ fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
+ }
+ // 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());
+ 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;
+ fout << "\t\t\t\tOutputFile=\""
+ << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
+ this->WriteTargetVersionAttribute(fout, target);
+ linkOptions.OutputFlagMap(fout, "\t\t\t\t");
+ fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
+ this->OutputLibraryDirectories(fout, cli.GetDirectories());
+ fout << "\"\n";
+ temp = target->GetPDBDirectory(configName);
+ temp += "/";
+ temp += targetNamePDB;
+ fout << "\t\t\t\tProgramDatabaseFile=\""
+ << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
+ if (targetOptions.IsDebug()) {
+ fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n";
+ }
+ if (this->WindowsCEProject) {
+ if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) {
+ fout << "\t\t\t\tSubSystem=\"9\"\n";
+ } else {
+ fout << "\t\t\t\tSubSystem=\"8\"\n";
+ }
}
- linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
- // 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());
- if(this->GetVersion() < VS8)
- {
- this->Internal->OutputObjects(fout, &target, " ");
+ std::string stackVar = "CMAKE_";
+ stackVar += linkLanguage;
+ stackVar += "_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;
+ fout << "\t\t\t\tImportLibrary=\""
+ << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"";
+ if (this->FortranProject) {
+ fout << "\n\t\t\t\tLinkDLL=\"true\"";
+ }
+ 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);
+
+ // Compute the link library and directory information.
+ cmComputeLinkInformation* pcli = target->GetLinkInformation(configName);
+ if (!pcli) {
+ return;
}
- fout << " ";
- this->Internal->OutputLibraries(fout, cli.GetItems());
- fout << "\"\n";
- temp = target.GetDirectory(configName);
- temp += "/";
- temp += targetNameFull;
- fout << "\t\t\t\tOutputFile=\""
- << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
- this->WriteTargetVersionAttribute(fout, target);
- linkOptions.OutputFlagMap(fout, "\t\t\t\t");
- 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";
- if(targetOptions.IsDebug())
- {
- fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
+ cmComputeLinkInformation& cli = *pcli;
+ std::string linkLanguage = cli.GetLinkLanguage();
+
+ bool isWin32Executable = target->GetPropertyAsBool("WIN32_EXECUTABLE");
+
+ // Compute the variable name to lookup standard libraries for this
+ // language.
+ std::string standardLibsVar = "CMAKE_";
+ standardLibsVar += linkLanguage;
+ standardLibsVar += "_STANDARD_LIBRARIES";
+ const char* tool = "VCLinkerTool";
+ if (this->FortranProject) {
+ tool = "VFLinkerTool";
}
- if ( this->WindowsCEProject )
- {
- if(this->GetVersion() < VS9)
- {
- fout << "\t\t\t\tSubSystem=\"9\"\n";
- }
- else
- {
- fout << "\t\t\t\tSubSystem=\"8\"\n";
+ fout << "\t\t\t<Tool\n"
+ << "\t\t\t\tName=\"" << tool << "\"\n";
+ if (!gg->NeedLinkLibraryDependencies(target)) {
+ fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
+ }
+ // 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());
+ 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;
+ fout << "\t\t\t\tOutputFile=\""
+ << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
+ this->WriteTargetVersionAttribute(fout, target);
+ linkOptions.OutputFlagMap(fout, "\t\t\t\t");
+ 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";
+ if (targetOptions.IsDebug()) {
+ fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n";
+ }
+ if (this->WindowsCEProject) {
+ if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) {
+ fout << "\t\t\t\tSubSystem=\"9\"\n";
+ } else {
+ fout << "\t\t\t\tSubSystem=\"8\"\n";
}
- if(!linkOptions.GetFlag("EntryPointSymbol"))
- {
- const char* entryPointSymbol = targetOptions.UsingUnicode() ?
- (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup") :
- (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup");
- fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n";
+ if (!linkOptions.GetFlag("EntryPointSymbol")) {
+ const char* entryPointSymbol = targetOptions.UsingUnicode()
+ ? (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup")
+ : (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup");
+ fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n";
}
- }
- else if ( this->FortranProject )
- {
- fout << "\t\t\t\tSubSystem=\""
- << (isWin32Executable ? "subSystemWindows" : "subSystemConsole")
- << "\"\n";
- }
- else
- {
- fout << "\t\t\t\tSubSystem=\""
- << (isWin32Executable ? "2" : "1")
- << "\"\n";
- }
- std::string stackVar = "CMAKE_";
- stackVar += linkLanguage;
- stackVar += "_STACK_SIZE";
- const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
- if(stackVal)
- {
- fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"";
- }
- temp = target.GetDirectory(configName, true);
- temp += "/";
- temp += targetNameImport;
- fout << "\t\t\t\tImportLibrary=\""
- << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
- break;
- }
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
+ } else if (this->FortranProject) {
+ fout << "\t\t\t\tSubSystem=\""
+ << (isWin32Executable ? "subSystemWindows" : "subSystemConsole")
+ << "\"\n";
+ } else {
+ fout << "\t\t\t\tSubSystem=\"" << (isWin32Executable ? "2" : "1")
+ << "\"\n";
+ }
+ std::string stackVar = "CMAKE_";
+ stackVar += linkLanguage;
+ stackVar += "_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;
+ fout << "\t\t\t\tImportLibrary=\""
+ << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
break;
}
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalVisualStudio7Generator
-::WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target)
+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 */
+ 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 */
+ }
+ }
+}
+
+void cmLocalVisualStudio7Generator::WriteTargetVersionAttribute(
+ std::ostream& fout, cmGeneratorTarget* gt)
{
int major;
int minor;
- target.GetTargetVersion(major, minor);
+ gt->GetTargetVersion(major, minor);
fout << "\t\t\t\tVersion=\"" << major << "." << minor << "\"\n";
}
-//----------------------------------------------------------------------------
-void
-cmLocalVisualStudio7GeneratorInternals
-::OutputLibraries(std::ostream& fout, ItemVector const& libs)
+void cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
+ std::ostream& fout, ItemVector const& libs)
{
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
- {
- if(l->IsPath)
- {
- std::string rel = lg->Convert(l->Value.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED);
+ std::string currentBinDir = lg->GetCurrentBinaryDirectory();
+ for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
+ if (l->IsPath) {
+ std::string rel =
+ lg->ConvertToRelativePath(currentBinDir, l->Value.c_str());
fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
- }
- else
- {
+ } else if (!l->Target ||
+ l->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
fout << l->Value << " ";
- }
}
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalVisualStudio7GeneratorInternals
-::OutputObjects(std::ostream& fout, cmTarget* t, const char* isep)
+void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
+ std::ostream& fout, cmGeneratorTarget* gt, std::string const& configName,
+ const char* isep)
{
// VS < 8 does not support per-config source locations so we
// list object library content on the link line instead.
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- cmGeneratorTarget* gt =
- lg->GetGlobalGenerator()->GetGeneratorTarget(t);
- std::vector<std::string> objs;
- gt->UseObjectLibraries(objs);
- const char* sep = isep? isep : "";
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- std::string rel = lg->Convert(oi->c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED);
- fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
- sep = " ";
+ std::string currentBinDir = lg->GetCurrentBinaryDirectory();
+
+ std::vector<cmSourceFile const*> objs;
+ 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);
+ fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
+ sep = " ";
}
+ }
}
-//----------------------------------------------------------------------------
-void
-cmLocalVisualStudio7Generator
-::OutputLibraryDirectories(std::ostream& fout,
- std::vector<std::string> const& dirs)
+void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
+ std::ostream& fout, std::vector<std::string> const& dirs)
{
const char* comma = "";
- for(std::vector<std::string>::const_iterator d = dirs.begin();
- d != dirs.end(); ++d)
- {
+ std::string currentBinDir = this->GetCurrentBinaryDirectory();
+ for (std::vector<std::string>::const_iterator d = dirs.begin();
+ d != dirs.end(); ++d) {
// Remove any trailing slash and skip empty paths.
std::string dir = *d;
- if(dir[dir.size()-1] == '/')
- {
- dir = dir.substr(0, dir.size()-1);
- }
- if(dir.empty())
- {
+ if (dir[dir.size() - 1] == '/') {
+ dir = dir.substr(0, dir.size() - 1);
+ }
+ if (dir.empty()) {
continue;
- }
+ }
// Switch to a relative path specification if it is shorter.
- if(cmSystemTools::FileIsFullPath(dir.c_str()))
- {
- std::string rel = this->Convert(dir.c_str(), START_OUTPUT, UNCHANGED);
- if(rel.size() < dir.size())
- {
+ if (cmSystemTools::FileIsFullPath(dir.c_str())) {
+ std::string rel =
+ this->ConvertToRelativePath(currentBinDir, dir.c_str());
+ if (rel.size() < dir.size()) {
dir = rel;
- }
}
+ }
// First search a configuration-specific subdirectory and then the
// original directory.
- fout << comma << this->ConvertToXMLOutputPath((dir+"/$(OutDir)").c_str())
+ fout << comma
+ << this->ConvertToXMLOutputPath(
+ (dir + "/$(ConfigurationName)").c_str())
<< "," << this->ConvertToXMLOutputPath(dir.c_str());
comma = ",";
- }
+ }
}
void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
- const char *libName,
- cmTarget &target)
+ const std::string& libName,
+ cmGeneratorTarget* target)
{
- // get the configurations
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
+ std::vector<std::string> configs;
+ this->Makefile->GetConfigurations(configs);
// We may be modifying the source groups temporarily, so make a copy.
std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
- // get the classes from the source lists then add them to the groups
- this->ModuleDefinitionFile = "";
- std::vector<cmSourceFile*>const & classes = target.GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); i++)
- {
- // Add the file to the list of sources.
- std::string source = (*i)->GetFullPath();
- if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF")
- {
- this->ModuleDefinitionFile = (*i)->GetFullPath();
+ std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+ target->GetAllConfigSources();
+ std::map<cmSourceFile const*, size_t> sourcesIndex;
+
+ for (size_t si = 0; si < sources.size(); ++si) {
+ cmSourceFile const* sf = sources[si].Source;
+ sourcesIndex[sf] = si;
+ if (!sf->GetObjectLibrary().empty()) {
+ if (this->FortranProject) {
+ // Intel Fortran does not support per-config source locations
+ // so we list object library content on the link line instead.
+ // See OutputObjects.
+ continue;
}
- cmSourceGroup& sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
- sourceGroup.AssignSource(*i);
}
+ // Add the file to the list of sources.
+ std::string const source = sf->GetFullPath();
+ cmSourceGroup* sourceGroup =
+ this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ sourceGroup->AssignSource(sf);
+ }
// open the project
this->WriteProjectStart(fout, libName, target, sourceGroups);
// write the configuration information
- this->WriteConfigurations(fout, libName, target);
+ this->WriteConfigurations(fout, configs, libName, target);
fout << "\t<Files>\n";
-
// Loop through every source group.
- for(unsigned int i = 0; i < sourceGroups.size(); ++i)
- {
+ for (unsigned int i = 0; i < sourceGroups.size(); ++i) {
cmSourceGroup sg = sourceGroups[i];
- this->WriteGroup(&sg, target, fout, libName, configs);
- }
-
- if(this->GetVersion() >= VS8)
- {
- // VS >= 8 support per-config source locations so we
- // list object library content as external objects.
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
- std::vector<std::string> objs;
- gt->UseObjectLibraries(objs);
- if(!objs.empty())
- {
- // TODO: Separate sub-filter for each object library used?
- fout << "\t\t<Filter Name=\"Object Libraries\">\n";
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str());
- fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n";
- }
- fout << "\t\t</Filter>\n";
- }
- }
+ this->WriteGroup(&sg, target, fout, libName, configs, sourcesIndex);
+ }
fout << "\t</Files>\n";
@@ -1445,159 +1420,140 @@ struct cmLVS7GFileConfig
class cmLocalVisualStudio7GeneratorFCInfo
{
public:
- cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
- cmTarget& target,
- cmSourceFile const& sf,
- std::vector<std::string>* configs);
- std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
+ cmLocalVisualStudio7GeneratorFCInfo(
+ cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* target,
+ cmGeneratorTarget::AllConfigSource const& acs,
+ std::vector<std::string> const& configs);
+ std::map<std::string, cmLVS7GFileConfig> FileConfigMap;
};
-cmLocalVisualStudio7GeneratorFCInfo
-::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
- cmTarget& target,
- cmSourceFile const& sf,
- std::vector<std::string>* configs)
+cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
+ cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* gt,
+ cmGeneratorTarget::AllConfigSource const& acs,
+ std::vector<std::string> const& configs)
{
- cmGeneratorTarget* gt =
- lg->GetGlobalGenerator()->GetGeneratorTarget(&target);
+ cmSourceFile const& sf = *acs.Source;
std::string objectName;
- if(gt->ExplicitObjectName.find(&sf) != gt->ExplicitObjectName.end())
- {
- objectName = gt->Objects[&sf];
- }
+ if (gt->HasExplicitObjectName(&sf)) {
+ objectName = gt->GetObjectName(&sf);
+ }
// Compute per-source, per-config information.
- for(std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
+ 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);
cmLVS7GFileConfig fc;
bool needfc = false;
- if(!objectName.empty())
- {
+ if (!objectName.empty()) {
fc.ObjectName = objectName;
needfc = true;
- }
- if(const char* cflags = sf.GetProperty("COMPILE_FLAGS"))
- {
- fc.CompileFlags = cflags;
+ }
+ if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
+ cmGeneratorExpression ge;
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
+ fc.CompileFlags = cge->Evaluate(lg, *i);
needfc = true;
- }
- if(lg->FortranProject)
- {
- switch(lg->GetFortranFormat(sf.GetProperty("Fortran_FORMAT")))
- {
- case cmLocalGenerator::FortranFormatFixed:
+ }
+ if (lg->FortranProject) {
+ switch (cmOutputConverter::GetFortranFormat(
+ sf.GetProperty("Fortran_FORMAT"))) {
+ case cmOutputConverter::FortranFormatFixed:
fc.CompileFlags = "-fixed " + fc.CompileFlags;
needfc = true;
break;
- case cmLocalGenerator::FortranFormatFree:
+ case cmOutputConverter::FortranFormatFree:
fc.CompileFlags = "-free " + fc.CompileFlags;
needfc = true;
break;
- default: break;
- }
+ default:
+ break;
}
- if(const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS"))
- {
+ }
+ if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
fc.CompileDefs = cdefs;
needfc = true;
- }
+ }
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
- if(const char* ccdefs = sf.GetProperty(defPropName.c_str()))
- {
+ if (const char* ccdefs = sf.GetProperty(defPropName.c_str())) {
fc.CompileDefsConfig = ccdefs;
needfc = true;
- }
+ }
// Check for extra object-file dependencies.
- if(const char* deps = sf.GetProperty("OBJECT_DEPENDS"))
- {
+ if (const char* deps = sf.GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> depends;
cmSystemTools::ExpandListArgument(deps, depends);
const char* sep = "";
- for(std::vector<std::string>::iterator j = depends.begin();
- j != depends.end(); ++j)
- {
+ for (std::vector<std::string>::iterator j = depends.begin();
+ j != depends.end(); ++j) {
fc.AdditionalDeps += sep;
fc.AdditionalDeps += lg->ConvertToXMLOutputPath(j->c_str());
sep = ";";
needfc = true;
- }
}
+ }
- const char* lang =
- lg->GlobalGenerator->GetLanguageFromExtension
- (sf.GetExtension().c_str());
- const char* sourceLang = lg->GetSourceFileLanguage(sf);
- const char* linkLanguage = target.GetLinkerLanguage(i->c_str());
+ 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 && strcmp(lang, sourceLang) != 0)
- {
+ if (lang != sourceLang) {
needForceLang = true;
lang = sourceLang;
- }
+ }
// If HEADER_FILE_ONLY is set, we must suppress this generation in
// the project file
- fc.ExcludedFromBuild =
- (sf.GetPropertyAsBool("HEADER_FILE_ONLY"));
- if(fc.ExcludedFromBuild)
- {
+ fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") ||
+ std::find(acs.Configs.begin(), acs.Configs.end(), ci) ==
+ acs.Configs.end();
+ if (fc.ExcludedFromBuild) {
needfc = true;
- }
+ }
// if the source file does not match the linker language
// then force c or c++
- if(needForceLang || (linkLanguage && lang
- && strcmp(lang, linkLanguage) != 0))
- {
- if(strcmp(lang, "CXX") == 0)
- {
+ if (needForceLang || (linkLanguage != lang)) {
+ if (lang == "CXX") {
// force a C++ file type
fc.CompileFlags += " /TP ";
needfc = true;
- }
- else if(strcmp(lang, "C") == 0)
- {
+ } else if (lang == "C") {
// force to c
fc.CompileFlags += " /TC ";
needfc = true;
- }
}
+ }
- if(needfc)
- {
+ if (needfc) {
this->FileConfigMap[*i] = fc;
- }
}
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalVisualStudio7Generator
-::ComputeLongestObjectDirectory(cmTarget& target) const
+std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory(
+ cmGeneratorTarget const* target) const
{
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
+ std::vector<std::string> configs;
+ target->Target->GetMakefile()->GetConfigurations(configs);
+
// Compute the maximum length configuration name.
std::string config_max;
- for(std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
- if(i->size() > config_max.size())
- {
+ for (std::vector<std::string>::iterator i = configs.begin();
+ i != configs.end(); ++i) {
+ if (i->size() > config_max.size()) {
config_max = *i;
- }
}
+ }
// 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->Makefile->GetCurrentOutputDirectory();
+ dir_max += this->GetCurrentBinaryDirectory();
dir_max += "/";
dir_max += this->GetTargetDirectory(target);
dir_max += "/";
@@ -1606,206 +1562,194 @@ cmLocalVisualStudio7Generator
return dir_max;
}
-bool cmLocalVisualStudio7Generator
-::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
- std::ostream &fout, const char *libName,
- std::vector<std::string> *configs)
+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)
{
- const std::vector<const cmSourceFile *> &sourceFiles =
- sg->GetSourceFiles();
- std::vector<cmSourceGroup> const& children = sg->GetGroupChildren();
+ cmGlobalVisualStudio7Generator* gg =
+ static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
+ const std::vector<const cmSourceFile*>& sourceFiles = sg->GetSourceFiles();
+ std::vector<cmSourceGroup> const& children = sg->GetGroupChildren();
// Write the children to temporary output.
bool hasChildrenWithSources = false;
- cmOStringStream tmpOut;
- for(unsigned int i=0;i<children.size();++i)
- {
- if(this->WriteGroup(&children[i], target, tmpOut, libName, configs))
- {
+ std::ostringstream tmpOut;
+ for (unsigned int i = 0; i < children.size(); ++i) {
+ if (this->WriteGroup(&children[i], target, tmpOut, libName, configs,
+ sourcesIndex)) {
hasChildrenWithSources = true;
- }
}
+ }
// If the group is empty, don't write it at all.
- if(sourceFiles.empty() && !hasChildrenWithSources)
- {
+ if (sourceFiles.empty() && !hasChildrenWithSources) {
return false;
- }
+ }
// If the group has a name, write the header.
std::string name = sg->GetName();
- if(name != "")
- {
+ if (name != "") {
this->WriteVCProjBeginGroup(fout, name.c_str(), "");
- }
+ }
+
+ std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+ target->GetAllConfigSources();
// Loop through each source in the source group.
- std::string objectName;
- for(std::vector<const cmSourceFile *>::const_iterator sf =
- sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
- {
+ for (std::vector<const cmSourceFile*>::const_iterator sf =
+ sourceFiles.begin();
+ sf != sourceFiles.end(); ++sf) {
std::string source = (*sf)->GetFullPath();
- FCInfo fcinfo(this, target, *(*sf), configs);
- if (source != libName || target.GetType() == cmTarget::UTILITY ||
- target.GetType() == cmTarget::GLOBAL_TARGET )
- {
+ 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);
+ // The map entry must exist because we populated it earlier.
+ assert(map_it != sourcesIndex.end());
+ cmGeneratorTarget::AllConfigSource const& acs = sources[map_it->second];
+
+ FCInfo fcinfo(this, target, acs, configs);
+
fout << "\t\t\t<File\n";
std::string d = this->ConvertToXMLOutputPathSingle(source.c_str());
// 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())
- {
- this->WriteCustomRule(fout, source.c_str(), *command, fcinfo);
- }
- else if(!fcinfo.FileConfigMap.empty())
- {
+ 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* lang = "CXX";
- if(this->FortranProject)
- {
+ const char* ppLang = "CXX";
+ if (this->FortranProject) {
aCompilerTool = "VFFortranCompilerTool";
- }
+ }
+ std::string const& lang = (*sf)->GetLanguage();
std::string ext = (*sf)->GetExtension();
ext = cmSystemTools::LowerCase(ext);
- if(ext == "idl")
- {
+ if (ext == "idl") {
aCompilerTool = "VCMIDLTool";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
aCompilerTool = "VFMIDLTool";
- }
}
- if(ext == "rc")
- {
+ }
+ if (ext == "rc") {
aCompilerTool = "VCResourceCompilerTool";
- lang = "RC";
- if(this->FortranProject)
- {
+ ppLang = "RC";
+ if (this->FortranProject) {
aCompilerTool = "VFResourceCompilerTool";
- }
}
- if(ext == "def")
- {
+ }
+ if (ext == "def") {
aCompilerTool = "VCCustomBuildTool";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
aCompilerTool = "VFCustomBuildTool";
- }
}
- for(std::map<cmStdString, cmLVS7GFileConfig>::const_iterator
- fci = fcinfo.FileConfigMap.begin();
- fci != fcinfo.FileConfigMap.end(); ++fci)
- {
+ }
+ if (gg->IsMasmEnabled() && !this->FortranProject &&
+ lang == "ASM_MASM") {
+ aCompilerTool = "MASM";
+ }
+ 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;
fout << "\t\t\t\t<FileConfiguration\n"
- << "\t\t\t\t\tName=\"" << fci->first
- << "|" << this->PlatformName << "\"";
- if(fc.ExcludedFromBuild)
- {
+ << "\t\t\t\t\tName=\"" << fci->first << "|"
+ << gg->GetPlatformName() << "\"";
+ if (fc.ExcludedFromBuild) {
fout << " ExcludedFromBuild=\"true\"";
- }
+ }
fout << ">\n";
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())
- {
+ if (!fc.CompileFlags.empty() || !fc.CompileDefs.empty() ||
+ !fc.CompileDefsConfig.empty()) {
Options::Tool tool = Options::Compiler;
cmVS7FlagTable const* table =
cmLocalVisualStudio7GeneratorFlagTable;
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
tool = Options::FortranCompiler;
table = cmLocalVisualStudio7GeneratorFortranFlagTable;
- }
- Options fileOptions(this, tool, table,
- this->ExtraFlagTable);
+ }
+ 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.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n");
fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
- fileOptions.OutputPreprocessorDefinitions(fout,
- "\t\t\t\t\t", "\n",
- lang);
- }
- if(!fc.AdditionalDeps.empty())
- {
- fout << "\t\t\t\t\tAdditionalDependencies=\""
- << fc.AdditionalDeps.c_str() << "\"\n";
- }
- if(!fc.ObjectName.empty())
- {
- fout << "\t\t\t\t\tObjectFile=\"$(IntDir)/"
- << fc.ObjectName.c_str() << "\"\n";
- }
+ fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
+ ppLang);
+ }
+ if (!fc.AdditionalDeps.empty()) {
+ fout << "\t\t\t\t\tAdditionalDependencies=\"" << fc.AdditionalDeps
+ << "\"\n";
+ }
+ if (!fc.ObjectName.empty()) {
+ fout << "\t\t\t\t\tObjectFile=\"$(IntDir)/" << fc.ObjectName
+ << "\"\n";
+ }
fout << "\t\t\t\t\t/>\n"
<< "\t\t\t\t</FileConfiguration>\n";
- }
}
- fout << "\t\t\t</File>\n";
}
+ fout << "\t\t\t</File>\n";
}
+ }
// If the group has children with source files, write the children.
- if(hasChildrenWithSources)
- {
+ if (hasChildrenWithSources) {
fout << tmpOut.str();
- }
+ }
// If the group has a name, write the footer.
- if(name != "")
- {
+ if (name != "") {
this->WriteVCProjEndGroup(fout);
- }
+ }
return true;
}
-void cmLocalVisualStudio7Generator::
-WriteCustomRule(std::ostream& fout,
- const char* source,
- const cmCustomCommand& command,
- FCInfo& fcinfo)
+void cmLocalVisualStudio7Generator::WriteCustomRule(
+ std::ostream& fout, std::vector<std::string> const& configs,
+ const char* source, const cmCustomCommand& command, FCInfo& fcinfo)
{
- std::string comment = this->ConstructComment(command);
+ cmGlobalVisualStudio7Generator* gg =
+ static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
// Write the rule for each configuration.
- std::vector<std::string>::iterator i;
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
const char* compileTool = "VCCLCompilerTool";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
compileTool = "VFCLCompilerTool";
- }
+ }
const char* customTool = "VCCustomBuildTool";
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
customTool = "VFCustomBuildTool";
- }
- for(i = configs->begin(); i != configs->end(); ++i)
- {
+ }
+ 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];
fout << "\t\t\t\t<FileConfiguration\n";
- fout << "\t\t\t\t\tName=\"" << *i << "|" << this->PlatformName << "\">\n";
- if(!fc.CompileFlags.empty())
- {
+ fout << "\t\t\t\t\tName=\"" << *i << "|" << gg->GetPlatformName()
+ << "\">\n";
+ if (!fc.CompileFlags.empty()) {
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << compileTool << "\"\n"
<< "\t\t\t\t\tAdditionalOptions=\""
<< this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n";
- }
+ }
- std::string script = this->ConstructScript(command, i->c_str());
- if(this->FortranProject)
- {
+ std::string comment = this->ConstructComment(ccg);
+ std::string script = this->ConstructScript(ccg);
+ if (this->FortranProject) {
cmSystemTools::ReplaceString(script, "$(Configuration)", i->c_str());
- }
+ }
+ /* clang-format off */
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << customTool << "\"\n"
<< "\t\t\t\t\tDescription=\""
@@ -1813,296 +1757,269 @@ WriteCustomRule(std::ostream& fout,
<< "\t\t\t\t\tCommandLine=\""
<< this->EscapeForXML(script.c_str()) << "\"\n"
<< "\t\t\t\t\tAdditionalDependencies=\"";
- if(command.GetDepends().empty())
- {
+ /* clang-format on */
+ if (ccg.GetDepends().empty()) {
// There are no real dependencies. Produce an artificial one to
// make sure the rule runs reliably.
- if(!cmSystemTools::FileExists(source))
- {
- std::ofstream depout(source);
+ if (!cmSystemTools::FileExists(source)) {
+ cmsys::ofstream depout(source);
depout << "Artificial dependency for a custom command.\n";
- }
- fout << this->ConvertToXMLOutputPath(source);
}
- else
- {
+ fout << this->ConvertToXMLOutputPath(source);
+ } else {
// Write out the dependencies for the rule.
- for(std::vector<std::string>::const_iterator d =
- command.GetDepends().begin();
- d != command.GetDepends().end();
- ++d)
- {
+ for (std::vector<std::string>::const_iterator d =
+ ccg.GetDepends().begin();
+ d != ccg.GetDepends().end(); ++d) {
// 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))
- {
- fout << this->ConvertToXMLOutputPath(dep.c_str())
- << ";";
- }
+ if (this->GetRealDependency(d->c_str(), i->c_str(), dep)) {
+ fout << this->ConvertToXMLOutputPath(dep.c_str()) << ";";
}
}
+ }
fout << "\"\n";
fout << "\t\t\t\t\tOutputs=\"";
- if(command.GetOutputs().empty())
- {
+ if (ccg.GetOutputs().empty()) {
fout << source << "_force";
- }
- else
- {
+ } else {
// Write a rule for the output generated by this command.
const char* sep = "";
- for(std::vector<std::string>::const_iterator o =
- command.GetOutputs().begin();
- o != command.GetOutputs().end();
- ++o)
- {
+ for (std::vector<std::string>::const_iterator o =
+ ccg.GetOutputs().begin();
+ o != ccg.GetOutputs().end(); ++o) {
fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
sep = ";";
- }
}
+ }
fout << "\"/>\n";
fout << "\t\t\t\t</FileConfiguration>\n";
- }
+ }
}
-
void cmLocalVisualStudio7Generator::WriteVCProjBeginGroup(std::ostream& fout,
const char* group,
- const char* )
+ const char*)
{
+ /* clang-format off */
fout << "\t\t<Filter\n"
<< "\t\t\tName=\"" << group << "\"\n"
<< "\t\t\tFilter=\"\">\n";
+ /* clang-format on */
}
-
void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout)
{
fout << "\t\t</Filter>\n";
}
-
// look for custom rules on a target and collect them together
-void cmLocalVisualStudio7Generator
-::OutputTargetRules(std::ostream& fout,
- const char* configName,
- cmTarget &target,
- const char * /*libName*/)
+void cmLocalVisualStudio7Generator::OutputTargetRules(
+ std::ostream& fout, const std::string& configName, cmGeneratorTarget* target,
+ const std::string& /*libName*/)
{
- if (target.GetType() > cmTarget::GLOBAL_TARGET)
- {
+ if (target->GetType() > cmStateEnums::GLOBAL_TARGET) {
return;
- }
+ }
EventWriter event(this, configName, fout);
// Add pre-build event.
const char* tool =
- this->FortranProject? "VFPreBuildEventTool":"VCPreBuildEventTool";
+ this->FortranProject ? "VFPreBuildEventTool" : "VCPreBuildEventTool";
event.Start(tool);
- event.Write(target.GetPreBuildCommands());
+ event.Write(target->GetPreBuildCommands());
event.Finish();
// Add pre-link event.
- tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool";
+ tool = this->FortranProject ? "VFPreLinkEventTool" : "VCPreLinkEventTool";
event.Start(tool);
- event.Write(target.GetPreLinkCommands());
- cmsys::auto_ptr<cmCustomCommand> pcc(
+ bool addedPrelink = false;
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ target->GetModuleDefinitionInfo(configName);
+ if (mdi && mdi->DefFileGenerated) {
+ addedPrelink = true;
+ std::vector<cmCustomCommand> commands = target->GetPreLinkCommands();
+ cmGlobalVisualStudioGenerator* gg =
+ static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
+ gg->AddSymbolExportCommand(target, commands, configName);
+ event.Write(commands);
+ }
+ if (!addedPrelink) {
+ event.Write(target->GetPreLinkCommands());
+ }
+ CM_AUTO_PTR<cmCustomCommand> pcc(
this->MaybeCreateImplibDir(target, configName, this->FortranProject));
- if(pcc.get())
- {
+ if (pcc.get()) {
event.Write(*pcc);
- }
+ }
event.Finish();
// Add post-build event.
- tool = this->FortranProject? "VFPostBuildEventTool":"VCPostBuildEventTool";
+ tool =
+ this->FortranProject ? "VFPostBuildEventTool" : "VCPostBuildEventTool";
event.Start(tool);
- event.Write(target.GetPostBuildCommands());
+ event.Write(target->GetPostBuildCommands());
event.Finish();
}
void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout,
- cmTarget& target)
+ cmGeneratorTarget* target)
{
// if we have all the required Source code control tags
// then add that to the project
- const char* vsProjectname = target.GetProperty("VS_SCC_PROJECTNAME");
- const char* vsLocalpath = target.GetProperty("VS_SCC_LOCALPATH");
- const char* vsProvider = target.GetProperty("VS_SCC_PROVIDER");
+ const char* vsProjectname = target->GetProperty("VS_SCC_PROJECTNAME");
+ const char* vsLocalpath = target->GetProperty("VS_SCC_LOCALPATH");
+ const char* vsProvider = target->GetProperty("VS_SCC_PROVIDER");
- if(vsProvider && vsLocalpath && vsProjectname)
- {
+ if (vsProvider && vsLocalpath && vsProjectname) {
+ /* clang-format off */
fout << "\tSccProjectName=\"" << vsProjectname << "\"\n"
<< "\tSccLocalPath=\"" << vsLocalpath << "\"\n"
<< "\tSccProvider=\"" << vsProvider << "\"\n";
+ /* clang-format on */
- const char* vsAuxPath = target.GetProperty("VS_SCC_AUXPATH");
- if(vsAuxPath)
- {
+ const char* vsAuxPath = target->GetProperty("VS_SCC_AUXPATH");
+ if (vsAuxPath) {
fout << "\tSccAuxPath=\"" << vsAuxPath << "\"\n";
- }
}
+ }
}
-void
-cmLocalVisualStudio7Generator
-::WriteProjectStartFortran(std::ostream& fout,
- const char *libName,
- cmTarget & target)
+void cmLocalVisualStudio7Generator::WriteProjectStartFortran(
+ std::ostream& fout, const std::string& libName, cmGeneratorTarget* target)
{
cmGlobalVisualStudio7Generator* gg =
- static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
-
- // 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 = gg->GetRegistryBase();
- vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion";
- cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion,
- cmSystemTools::KeyWOW64_32);
- unsigned int intelVersionNumber = ~0u;
- sscanf(intelVersion.c_str(), "%u", &intelVersionNumber);
- if(intelVersionNumber >= 11)
- {
- // Default to latest known project file version.
- intelVersion = "11.0";
- }
- else if(intelVersionNumber == 10)
- {
- // Version 10.x actually uses 9.10 in project files!
- intelVersion = "9.10";
- }
- else
- {
- // Version <= 9: use ProductVersion from registry.
- }
-
- fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
+ static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
+ /* clang-format off */
+ fout << "<?xml version=\"1.0\" encoding = \""
+ << gg->Encoding() << "\"?>\n"
<< "<VisualStudioProject\n"
<< "\tProjectCreator=\"Intel Fortran\"\n"
- << "\tVersion=\"" << intelVersion << "\"\n";
- const char* keyword = target.GetProperty("VS_KEYWORD");
- if(!keyword)
- {
+ << "\tVersion=\"" << gg->GetIntelProjectVersion() << "\"\n";
+ /* clang-format on */
+ const char* keyword = target->GetProperty("VS_KEYWORD");
+ if (!keyword) {
keyword = "Console Application";
- }
+ }
const char* projectType = 0;
- switch(target.GetType())
- {
- case cmTarget::STATIC_LIBRARY:
+ switch (target->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
projectType = "typeStaticLibrary";
- if(keyword)
- {
+ if (keyword) {
keyword = "Static Library";
- }
+ }
break;
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
projectType = "typeDynamicLibrary";
- if(!keyword)
- {
+ if (!keyword) {
keyword = "Dll";
- }
+ }
break;
- case cmTarget::EXECUTABLE:
- if(!keyword)
- {
+ case cmStateEnums::EXECUTABLE:
+ if (!keyword) {
keyword = "Console Application";
- }
+ }
projectType = 0;
break;
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
default:
break;
- }
- if(projectType)
- {
+ }
+ if (projectType) {
fout << "\tProjectType=\"" << projectType << "\"\n";
- }
+ }
this->WriteProjectSCC(fout, target);
+ /* clang-format off */
fout<< "\tKeyword=\"" << keyword << "\">\n"
- << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\">\n"
+ << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\">\n"
<< "\t<Platforms>\n"
- << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n"
+ << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n"
<< "\t</Platforms>\n";
+ /* clang-format on */
}
-
-void
-cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout,
- const char *libName,
- cmTarget & target,
- std::vector<cmSourceGroup> &)
+void cmLocalVisualStudio7Generator::WriteProjectStart(
+ std::ostream& fout, const std::string& libName, cmGeneratorTarget* target,
+ std::vector<cmSourceGroup>&)
{
- if(this->FortranProject)
- {
+ if (this->FortranProject) {
this->WriteProjectStartFortran(fout, libName, target);
return;
- }
- fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
+ }
+
+ cmGlobalVisualStudio7Generator* gg =
+ static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
+
+ /* clang-format off */
+ fout << "<?xml version=\"1.0\" encoding = \""
+ << gg->Encoding() << "\"?>\n"
<< "<VisualStudioProject\n"
<< "\tProjectType=\"Visual C++\"\n";
- if(this->Version == VS71)
- {
- fout << "\tVersion=\"7.10\"\n";
- }
- else
- {
- fout << "\tVersion=\"" << (this->Version/10) << ".00\"\n";
- }
- const char* projLabel = target.GetProperty("PROJECT_LABEL");
- if(!projLabel)
- {
- projLabel = libName;
- }
- const char* keyword = target.GetProperty("VS_KEYWORD");
- if(!keyword)
- {
+ /* clang-format on */
+ fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n";
+ const char* projLabel = target->GetProperty("PROJECT_LABEL");
+ if (!projLabel) {
+ projLabel = libName.c_str();
+ }
+ const char* keyword = target->GetProperty("VS_KEYWORD");
+ if (!keyword) {
keyword = "Win32Proj";
- }
- cmGlobalVisualStudio7Generator* gg =
- static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
+ }
fout << "\tName=\"" << projLabel << "\"\n";
- if(this->Version >= VS8)
- {
- fout << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\"\n";
- }
+ fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n";
this->WriteProjectSCC(fout, target);
+ if (const char* targetFrameworkVersion =
+ target->GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
+ fout << "\tTargetFrameworkVersion=\"" << targetFrameworkVersion << "\"\n";
+ }
+ /* clang-format off */
fout << "\tKeyword=\"" << keyword << "\">\n"
<< "\t<Platforms>\n"
- << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n"
+ << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n"
<< "\t</Platforms>\n";
+ /* clang-format on */
+ if (gg->IsMasmEnabled()) {
+ /* clang-format off */
+ fout <<
+ "\t<ToolFiles>\n"
+ "\t\t<DefaultToolFile\n"
+ "\t\t\tFileName=\"masm.rules\"\n"
+ "\t\t/>\n"
+ "\t</ToolFiles>\n"
+ ;
+ /* clang-format on */
+ }
}
-
-void cmLocalVisualStudio7Generator::WriteVCProjFooter(std::ostream& fout,
- cmTarget &target)
+void cmLocalVisualStudio7Generator::WriteVCProjFooter(
+ std::ostream& fout, cmGeneratorTarget* target)
{
fout << "\t<Globals>\n";
- cmPropertyMap const& props = target.GetProperties();
- for(cmPropertyMap::const_iterator i = props.begin(); i != props.end(); ++i)
- {
- if(i->first.find("VS_GLOBAL_") == 0)
- {
- std::string name = i->first.substr(10);
- if(name != "")
- {
+ 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 != "") {
+ /* clang-format off */
fout << "\t\t<Global\n"
<< "\t\t\tName=\"" << name << "\"\n"
- << "\t\t\tValue=\"" << i->second.GetValue() << "\"\n"
+ << "\t\t\tValue=\"" << target->GetProperty(*i) << "\"\n"
<< "\t\t/>\n";
- }
+ /* clang-format on */
}
}
+ }
fout << "\t</Globals>\n"
<< "</VisualStudioProject>\n";
}
-std::string cmLocalVisualStudio7GeneratorEscapeForXML(const char* s)
+std::string cmLocalVisualStudio7GeneratorEscapeForXML(const std::string& s)
{
std::string ret = s;
cmSystemTools::ReplaceString(ret, "&", "&amp;");
@@ -2113,15 +2030,16 @@ std::string cmLocalVisualStudio7GeneratorEscapeForXML(const char* s)
return ret;
}
-std::string cmLocalVisualStudio7Generator::EscapeForXML(const char* s)
+std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s)
{
return cmLocalVisualStudio7GeneratorEscapeForXML(s);
}
-std::string cmLocalVisualStudio7Generator
-::ConvertToXMLOutputPath(const char* path)
+std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPath(
+ const char* path)
{
- std::string ret = this->ConvertToOptionallyRelativeOutputPath(path);
+ std::string ret =
+ this->ConvertToOutputFormat(path, cmOutputConverter::SHELL);
cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "\"", "&quot;");
cmSystemTools::ReplaceString(ret, "<", "&lt;");
@@ -2129,10 +2047,11 @@ std::string cmLocalVisualStudio7Generator
return ret;
}
-std::string cmLocalVisualStudio7Generator
-::ConvertToXMLOutputPathSingle(const char* path)
+std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle(
+ const char* path)
{
- std::string ret = this->ConvertToOptionallyRelativeOutputPath(path);
+ std::string ret =
+ this->ConvertToOutputFormat(path, cmOutputConverter::SHELL);
cmSystemTools::ReplaceString(ret, "\"", "");
cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "<", "&lt;");
@@ -2140,108 +2059,84 @@ std::string cmLocalVisualStudio7Generator
return ret;
}
-
// This class is used to parse an existing vs 7 project
// and extract the GUID
class cmVS7XMLParser : public cmXMLParser
{
public:
- virtual void EndElement(const char* /* name */)
- {
+ virtual void EndElement(const std::string& /* name */) {}
+ virtual void StartElement(const std::string& name, const char** atts)
+ {
+ // once the GUID is found do nothing
+ if (!this->GUID.empty()) {
+ return;
}
- virtual void StartElement(const char* name, const char** atts)
- {
- // once the GUID is found do nothing
- if(this->GUID.size())
- {
- return;
- }
- int i =0;
- if(strcmp("VisualStudioProject", name) == 0)
- {
- while(atts[i])
- {
- 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);
- }
- else
- {
- this->GUID = "";
- }
- return;
- }
- ++i;
+ int i = 0;
+ if ("VisualStudioProject" == name) {
+ while (atts[i]) {
+ 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);
+ } else {
+ this->GUID = "";
}
+ return;
}
+ ++i;
+ }
}
+ }
int InitializeParser()
- {
- int ret = cmXMLParser::InitializeParser();
- if(ret == 0)
- {
- return ret;
- }
- // visual studio projects have a strange encoding, but it is
- // really utf-8
- XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8");
- return 1;
- }
+ {
+ int ret = cmXMLParser::InitializeParser();
+ if (ret == 0) {
+ return ret;
+ }
+ // visual studio projects have a strange encoding, but it is
+ // really utf-8
+ XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8");
+ return 1;
+ }
std::string GUID;
};
void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
- const char* name,
- const char* path)
+ const std::string& name, const char* path)
{
cmVS7XMLParser parser;
parser.ParseFile(path);
- // if we can not find a GUID then create one
- if(parser.GUID.size() == 0)
- {
- cmGlobalVisualStudio7Generator* gg =
- static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
- gg->CreateGUID(name);
+ // if we can not find a GUID then we will generate one later
+ if (parser.GUID.empty()) {
return;
- }
+ }
std::string guidStoreName = name;
guidStoreName += "_GUID_CMAKE";
// save the GUID in the cache
- this->GlobalGenerator->GetCMakeInstance()->
- AddCacheEntry(guidStoreName.c_str(),
- parser.GUID.c_str(),
- "Stored GUID",
- cmCacheManager::INTERNAL);
+ this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
+ guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
+ cmStateEnums::INTERNAL);
}
-
-//----------------------------------------------------------------------------
-std::string cmLocalVisualStudio7Generator
-::GetTargetDirectory(cmTarget const& target) const
+std::string cmLocalVisualStudio7Generator::GetTargetDirectory(
+ cmGeneratorTarget const* target) const
{
std::string dir;
- dir += target.GetName();
+ dir += target->GetName();
dir += ".dir";
return dir;
}
-//----------------------------------------------------------------------------
-#include <windows.h>
-static bool cmLVS6G_IsFAT(const char* dir)
+static bool cmLVS7G_IsFAT(const char* dir)
{
- if(dir[0] && dir[1] == ':')
- {
+ if (dir[0] && dir[1] == ':') {
char volRoot[4] = "_:/";
volRoot[0] = dir[0];
char fsName[16];
- if(GetVolumeInformation(volRoot, 0, 0, 0, 0, 0, fsName, 16) &&
- strstr(fsName, "FAT") != 0)
- {
+ if (GetVolumeInformationA(volRoot, 0, 0, 0, 0, 0, fsName, 16) &&
+ strstr(fsName, "FAT") != 0) {
return true;
- }
}
+ }
return false;
}
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 92e4d3c12..89a3ee353 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -1,29 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalVisualStudio7Generator_h
#define cmLocalVisualStudio7Generator_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
#include "cmLocalVisualStudioGenerator.h"
#include "cmVisualStudioGeneratorOptions.h"
-class cmTarget;
-class cmSourceFile;
class cmCustomCommand;
-class cmSourceGroup;
-
-
-class cmLocalVisualStudio7GeneratorOptions;
+class cmGeneratorTarget;
+class cmGlobalGenerator;
class cmLocalVisualStudio7GeneratorFCInfo;
class cmLocalVisualStudio7GeneratorInternals;
+class cmMakefile;
+class cmSourceFile;
+class cmSourceGroup;
/** \class cmLocalVisualStudio7Generator
* \brief Write Visual Studio .NET project files.
@@ -35,7 +31,7 @@ class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator
{
public:
///! Set cache only and recurse to false by default.
- cmLocalVisualStudio7Generator(VSVersion v);
+ cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudio7Generator();
@@ -46,87 +42,96 @@ public:
*/
virtual void Generate();
- enum BuildType {STATIC_LIBRARY, DLL, EXECUTABLE, WIN32_EXECUTABLE, UTILITY};
+ enum BuildType
+ {
+ STATIC_LIBRARY,
+ DLL,
+ EXECUTABLE,
+ WIN32_EXECUTABLE,
+ UTILITY
+ };
/**
* Specify the type of the build: static, dll, or executable.
*/
- void SetBuildType(BuildType,const char *name);
+ void SetBuildType(BuildType, const std::string& name);
- void SetPlatformName(const char* n) { this->PlatformName = n;}
-
- void SetExtraFlagTable(cmVS7FlagTable const* table)
- { this->ExtraFlagTable = table; }
- virtual std::string GetTargetDirectory(cmTarget const&) const;
+ virtual std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const;
cmSourceFile* CreateVCProjBuildRule();
void WriteStampFiles();
- virtual std::string ComputeLongestObjectDirectory(cmTarget&) const;
+ virtual std::string ComputeLongestObjectDirectory(
+ cmGeneratorTarget const*) const;
- virtual void ReadAndStoreExternalGUID(const char* name,
+ virtual void ReadAndStoreExternalGUID(const std::string& name,
const char* path);
virtual void AddCMakeListsRules();
+
protected:
- void CreateSingleVCProj(const char *lname, cmTarget &tgt);
+ void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt);
+
private:
typedef cmVisualStudioGeneratorOptions Options;
typedef cmLocalVisualStudio7GeneratorFCInfo FCInfo;
std::string GetBuildTypeLinkerFlags(std::string rootLinkerFlags,
- const char* configName);
+ const std::string& configName);
void FixGlobalTargets();
void WriteProjectFiles();
- void WriteVCProjHeader(std::ostream& fout, const char *libName,
- cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
- void WriteVCProjFooter(std::ostream& fout, cmTarget &target);
- void WriteVCProjFile(std::ostream& fout, const char *libName,
- cmTarget &tgt);
+ void WriteVCProjHeader(std::ostream& fout, const std::string& libName,
+ cmGeneratorTarget* tgt,
+ std::vector<cmSourceGroup>& sgs);
+ void WriteVCProjFooter(std::ostream& fout, cmGeneratorTarget* target);
+ void WriteVCProjFile(std::ostream& fout, const std::string& libName,
+ cmGeneratorTarget* tgt);
void WriteConfigurations(std::ostream& fout,
- const char *libName, cmTarget &tgt);
- void WriteConfiguration(std::ostream& fout,
- const char* configName,
- const char* libName, cmTarget &tgt);
- std::string EscapeForXML(const char* s);
+ std::vector<std::string> const& configs,
+ const std::string& libName, cmGeneratorTarget* tgt);
+ void WriteConfiguration(std::ostream& fout, const std::string& configName,
+ const std::string& libName, cmGeneratorTarget* tgt);
+ std::string EscapeForXML(const std::string& s);
std::string ConvertToXMLOutputPath(const char* path);
std::string ConvertToXMLOutputPathSingle(const char* path);
- void OutputTargetRules(std::ostream& fout, const char* configName,
- cmTarget &target, const char *libName);
- void OutputBuildTool(std::ostream& fout, const char* configName,
- cmTarget& t, const Options& targetOptions);
+ void OutputTargetRules(std::ostream& fout, const std::string& configName,
+ cmGeneratorTarget* target,
+ const std::string& libName);
+ void OutputBuildTool(std::ostream& fout, const std::string& configName,
+ cmGeneratorTarget* t, const Options& targetOptions);
+ void OutputDeploymentDebuggerTool(std::ostream& fout,
+ std::string const& config,
+ cmGeneratorTarget* target);
void OutputLibraryDirectories(std::ostream& fout,
std::vector<std::string> const& dirs);
- void WriteProjectSCC(std::ostream& fout, cmTarget& target);
- void WriteProjectStart(std::ostream& fout, const char *libName,
- cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
- void WriteProjectStartFortran(std::ostream& fout, const char *libName,
- cmTarget &tgt);
- void WriteVCProjBeginGroup(std::ostream& fout,
- const char* group,
- const char* filter);
+ void WriteProjectSCC(std::ostream& fout, cmGeneratorTarget* target);
+ void WriteProjectStart(std::ostream& fout, const std::string& libName,
+ cmGeneratorTarget* tgt,
+ std::vector<cmSourceGroup>& sgs);
+ void WriteProjectStartFortran(std::ostream& fout, const std::string& libName,
+ cmGeneratorTarget* tgt);
+ void WriteVCProjBeginGroup(std::ostream& fout, const char* group,
+ const char* filter);
void WriteVCProjEndGroup(std::ostream& fout);
void WriteCustomRule(std::ostream& fout,
- const char* source,
- const cmCustomCommand& command,
+ std::vector<std::string> const& configs,
+ const char* source, const cmCustomCommand& command,
FCInfo& fcinfo);
- void WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target);
+ void WriteTargetVersionAttribute(std::ostream& fout, cmGeneratorTarget* gt);
- bool WriteGroup(const cmSourceGroup *sg,
- cmTarget& target, std::ostream &fout,
- const char *libName, std::vector<std::string> *configs);
+ 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);
friend class cmLocalVisualStudio7GeneratorFCInfo;
friend class cmLocalVisualStudio7GeneratorInternals;
class EventWriter;
+
friend class EventWriter;
- cmVS7FlagTable const* ExtraFlagTable;
- std::string ModuleDefinitionFile;
bool FortranProject;
bool WindowsCEProject;
- std::string PlatformName; // Win32 or x64
cmLocalVisualStudio7GeneratorInternals* Internal;
};
-
#endif
-
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index ef2bb1d99..41025af6c 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -1,158 +1,196 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudioGenerator.h"
+
+#include "cmCustomCommandGenerator.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
-#include "cmCustomCommandGenerator.h"
#include "windows.h"
-//----------------------------------------------------------------------------
-cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator(VSVersion v)
+cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator(
+ cmGlobalGenerator* gg, cmMakefile* mf)
+ : cmLocalGenerator(gg, mf)
{
- this->WindowsShell = true;
- this->WindowsVSIDE = true;
- this->Version = v;
}
-//----------------------------------------------------------------------------
cmLocalVisualStudioGenerator::~cmLocalVisualStudioGenerator()
{
}
-//----------------------------------------------------------------------------
-cmsys::auto_ptr<cmCustomCommand>
-cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
- const char* config,
+cmGlobalVisualStudioGenerator::VSVersion
+cmLocalVisualStudioGenerator::GetVersion() const
+{
+ cmGlobalVisualStudioGenerator* gg =
+ static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
+ return gg->GetVersion();
+}
+
+void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt)
+{
+ char const* custom_ext = gt->GetCustomObjectExtension();
+ std::string dir_max = this->ComputeLongestObjectDirectory(gt);
+
+ // Count the number of object files with each name. Note that
+ // 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;
+ std::string objectNameLower = cmSystemTools::LowerCase(
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
+ if (custom_ext) {
+ objectNameLower += custom_ext;
+ } else {
+ objectNameLower +=
+ this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+ }
+ counts[objectNameLower] += 1;
+ }
+
+ // 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;
+ std::string objectName =
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+ if (custom_ext) {
+ objectName += custom_ext;
+ } else {
+ objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+ }
+ if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
+ const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
+ bool keptSourceExtension;
+ objectName = this->GetObjectFileNameWithoutTarget(
+ *sf, dir_max, &keptSourceExtension, custom_ext);
+ }
+ si->second = objectName;
+ }
+}
+
+CM_AUTO_PTR<cmCustomCommand>
+cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
+ const std::string& config,
bool isFortran)
{
- cmsys::auto_ptr<cmCustomCommand> pcc;
+ CM_AUTO_PTR<cmCustomCommand> pcc;
// If an executable exports symbols then VS wants to create an
// import library but forgets to create the output directory.
// The Intel Fortran plugin always forgets to the directory.
- if(target.GetType() != cmTarget::EXECUTABLE &&
- !(isFortran && target.GetType() == cmTarget::SHARED_LIBRARY))
- { return pcc; }
- std::string outDir = target.GetDirectory(config, false);
- std::string impDir = target.GetDirectory(config, true);
- if(impDir == outDir) { return pcc; }
+ if (target->GetType() != cmStateEnums::EXECUTABLE &&
+ !(isFortran && target->GetType() == cmStateEnums::SHARED_LIBRARY)) {
+ return pcc;
+ }
+ std::string outDir =
+ target->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact);
+ std::string impDir =
+ target->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
+ if (impDir == outDir) {
+ return pcc;
+ }
// Add a pre-build event to create the directory.
cmCustomCommandLine command;
- command.push_back(this->Makefile->GetRequiredDefinition("CMAKE_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);
- pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
+ pcc.reset(new cmCustomCommand(0, no_output, no_byproducts, no_depends,
+ commands, 0, 0));
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
}
-//----------------------------------------------------------------------------
const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const
{
return ":VCReportError";
}
-//----------------------------------------------------------------------------
const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const
{
return this->ReportErrorLabel();
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalVisualStudioGenerator
-::ConstructScript(cmCustomCommand const& cc,
- const char* configName,
- const char* newline_text)
+std::string cmLocalVisualStudioGenerator::ConstructScript(
+ cmCustomCommandGenerator const& ccg, const std::string& newline_text)
{
bool useLocal = this->CustomCommandUseLocal();
- const char* workingDirectory = cc.GetWorkingDirectory();
- cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
- RelativeRoot relativeRoot = workingDirectory? NONE : START_OUTPUT;
+ std::string workingDirectory = ccg.GetWorkingDirectory();
// Avoid leading or trailing newlines.
- const char* newline = "";
+ std::string newline = "";
// Line to check for error between commands.
std::string check_error = newline_text;
- if(useLocal)
- {
+ if (useLocal) {
check_error += "if %errorlevel% neq 0 goto :cmEnd";
- }
- else
- {
+ } else {
check_error += "if errorlevel 1 goto ";
check_error += this->GetReportErrorLabel();
- }
+ }
// Store the script in a string.
std::string script;
// Open a local context.
- if(useLocal)
- {
+ if (useLocal) {
script += newline;
newline = newline_text;
script += "setlocal";
- }
+ }
- if(workingDirectory)
- {
+ if (!workingDirectory.empty()) {
// Change the working directory.
script += newline;
newline = newline_text;
script += "cd ";
- script += this->Convert(workingDirectory, FULL, SHELL);
+ script += this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(workingDirectory), SHELL);
script += check_error;
// Change the working drive.
- if(workingDirectory[0] && workingDirectory[1] == ':')
- {
+ if (workingDirectory.size() > 1 && workingDirectory[1] == ':') {
script += newline;
newline = newline_text;
script += workingDirectory[0];
script += workingDirectory[1];
script += check_error;
- }
}
+ }
// for visual studio IDE add extra stuff to the PATH
// if CMAKE_MSVCIDE_RUN_PATH is set.
- if(this->Makefile->GetDefinition("MSVC_IDE"))
- {
+ if (this->Makefile->GetDefinition("MSVC_IDE")) {
const char* extraPath =
this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
- if(extraPath)
- {
+ if (extraPath) {
script += newline;
newline = newline_text;
script += "set PATH=";
script += extraPath;
script += ";%PATH%";
- }
}
+ }
// Write each command on a single line.
- for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
- {
+ for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
// Start a new line.
script += newline;
newline = newline_text;
@@ -164,16 +202,20 @@ cmLocalVisualStudioGenerator
// invoked as custom commands.
//
std::string suffix;
- if (cmd.size() > 4)
- {
- suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size()-4));
- if (suffix == ".bat" || suffix == ".cmd")
- {
+ if (cmd.size() > 4) {
+ suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4));
+ if (suffix == ".bat" || suffix == ".cmd") {
script += "call ";
- }
}
+ }
- script += this->Convert(cmd.c_str(), relativeRoot, SHELL);
+ if (workingDirectory.empty()) {
+ script += this->ConvertToOutputFormat(
+ this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cmd),
+ cmOutputConverter::SHELL);
+ } else {
+ script += this->ConvertToOutputFormat(cmd.c_str(), SHELL);
+ }
ccg.AppendArguments(c, script);
// After each custom command, check for an error result.
@@ -181,11 +223,10 @@ cmLocalVisualStudioGenerator
// skipping the run of any subsequent commands in this
// sequence.
script += check_error;
- }
+ }
// Close the local context.
- if(useLocal)
- {
+ if (useLocal) {
script += newline;
script += ":cmEnd";
script += newline;
@@ -199,7 +240,7 @@ cmLocalVisualStudioGenerator
script += newline;
script += "if %errorlevel% neq 0 goto ";
script += this->GetReportErrorLabel();
- }
+ }
return script;
}
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 1a3499a96..85fb8a511 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -1,24 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalVisualStudioGenerator_h
#define cmLocalVisualStudioGenerator_h
-#include "cmLocalGenerator.h"
+#include "cmConfigure.h"
-#include <cmsys/auto_ptr.hxx>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cm_auto_ptr.hxx"
-class cmSourceFile;
-class cmSourceGroup;
class cmCustomCommand;
+class cmCustomCommandGenerator;
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
+class cmSourceFile;
/** \class cmLocalVisualStudioGenerator
* \brief Base class for Visual Studio generators.
@@ -29,47 +29,36 @@ class cmCustomCommand;
class cmLocalVisualStudioGenerator : public cmLocalGenerator
{
public:
- /** Known versions of Visual Studio. */
- enum VSVersion
- {
- VS6 = 60,
- VS7 = 70,
- VS71 = 71,
- VS8 = 80,
- VS9 = 90,
- VS10 = 100,
- VS11 = 110,
- VS12 = 120
- };
-
- cmLocalVisualStudioGenerator(VSVersion v);
+ cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudioGenerator();
/** Construct a script from the given list of command lines. */
- std::string ConstructScript(cmCustomCommand const& cc,
- const char* configName,
- const char* newline = "\n");
+ std::string ConstructScript(cmCustomCommandGenerator const& ccg,
+ const std::string& newline = "\n");
/** Label to which to jump in a batch file after a failed step in a
sequence of custom commands. */
const char* GetReportErrorLabel() const;
- /** Version of Visual Studio. */
- VSVersion GetVersion() const { return this->Version; }
+ cmGlobalVisualStudioGenerator::VSVersion GetVersion() const;
- virtual std::string ComputeLongestObjectDirectory(cmTarget&) const = 0;
+ virtual std::string ComputeLongestObjectDirectory(
+ cmGeneratorTarget const*) const = 0;
virtual void AddCMakeListsRules() = 0;
+ virtual void ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* = 0);
+
protected:
virtual const char* ReportErrorLabel() const;
virtual bool CustomCommandUseLocal() const { return false; }
/** Construct a custom command to make exe import lib dir. */
- cmsys::auto_ptr<cmCustomCommand>
- MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran);
-
- VSVersion Version;
+ CM_AUTO_PTR<cmCustomCommand> MaybeCreateImplibDir(cmGeneratorTarget* target,
+ const std::string& config,
+ bool isFortran);
};
#endif
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 7c5f69df5..739ef4367 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -1,44 +1,87 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalXCodeGenerator.h"
+
+#include "cmGeneratorTarget.h"
#include "cmGlobalXCodeGenerator.h"
#include "cmSourceFile.h"
-//----------------------------------------------------------------------------
-cmLocalXCodeGenerator::cmLocalXCodeGenerator()
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
+
+cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg,
+ cmMakefile* mf)
+ : cmLocalGenerator(gg, mf)
{
// the global generator does this, so do not
// put these flags into the language flags
this->EmitUniversalBinaryFlags = false;
}
-//----------------------------------------------------------------------------
cmLocalXCodeGenerator::~cmLocalXCodeGenerator()
{
}
-//----------------------------------------------------------------------------
-std::string
-cmLocalXCodeGenerator::GetTargetDirectory(cmTarget const&) const
+std::string cmLocalXCodeGenerator::GetTargetDirectory(
+ cmGeneratorTarget const*) const
{
// No per-target directory for this generator (yet).
return "";
}
-//----------------------------------------------------------------------------
void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags,
- const char* rawFlag)
+ const std::string& rawFlag)
{
cmGlobalXCodeGenerator* gg =
static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator);
gg->AppendFlag(flags, rawFlag);
}
+
+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("");
+ }
+}
+
+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("");
+ }
+}
+
+void cmLocalXCodeGenerator::ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const*)
+{
+ // Count the number of object files with each name. Warn about duplicate
+ // names since Xcode names them uniquely automatically with a numeric suffix
+ // 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";
+
+ std::string objectNameLower = cmSystemTools::LowerCase(objectName);
+ counts[objectNameLower] += 1;
+ if (2 == counts[objectNameLower]) {
+ // TODO: emit warning about duplicate name?
+ }
+ si->second = objectName;
+ }
+}
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index d97a41cea..4ca02a9d0 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -1,19 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLocalXCodeGenerator_h
#define cmLocalXCodeGenerator_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+
#include "cmLocalGenerator.h"
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
+class cmSourceFile;
+
/** \class cmLocalXCodeGenerator
* \brief Write a local Xcode project
*
@@ -24,14 +25,20 @@ class cmLocalXCodeGenerator : public cmLocalGenerator
{
public:
///! Set cache only and recurse to false by default.
- cmLocalXCodeGenerator();
+ cmLocalXCodeGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalXCodeGenerator();
- virtual std::string GetTargetDirectory(cmTarget const& target) const;
- virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
-private:
+ virtual std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const;
+ virtual void AppendFlagEscape(std::string& flags,
+ const std::string& rawFlag);
+ virtual void Generate();
+ virtual void GenerateInstallRules();
+ virtual void ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt = 0);
+private:
};
#endif
-
diff --git a/Source/cmLocale.h b/Source/cmLocale.h
new file mode 100644
index 000000000..9f90a3a99
--- /dev/null
+++ b/Source/cmLocale.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 cmLocale_h
+#define cmLocale_h
+
+#include "cmConfigure.h"
+
+#include <locale.h>
+#include <string>
+
+class cmLocaleRAII
+{
+ CM_DISABLE_COPY(cmLocaleRAII)
+
+public:
+ cmLocaleRAII()
+ : OldLocale(setlocale(LC_CTYPE, CM_NULLPTR))
+ {
+ setlocale(LC_CTYPE, "");
+ }
+ ~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); }
+
+private:
+ std::string OldLocale;
+};
+
+#endif
diff --git a/Source/cmMSVC60LinkLineComputer.cxx b/Source/cmMSVC60LinkLineComputer.cxx
new file mode 100644
index 000000000..5298d1a79
--- /dev/null
+++ b/Source/cmMSVC60LinkLineComputer.cxx
@@ -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. */
+
+#include "cmMSVC60LinkLineComputer.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include "cmSystemTools.h"
+#endif
+
+class cmOutputConverter;
+
+cmMSVC60LinkLineComputer::cmMSVC60LinkLineComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
+ : cmLinkLineComputer(outputConverter, stateDir)
+{
+}
+
+std::string cmMSVC60LinkLineComputer::ConvertToLinkReference(
+ std::string const& lib) const
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Work-ardound command line parsing limitations in MSVC 6.0
+ // Search for the last space.
+ std::string::size_type pos = lib.rfind(' ');
+ if (pos != std::string::npos) {
+ // Find the slash after the last space, if any.
+ pos = lib.find('/', pos);
+
+ // Convert the portion of the path with a space to a short path.
+ std::string sp;
+ if (cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp)) {
+ // Append the rest of the path with no space.
+ sp += lib.substr(pos);
+ return sp;
+ }
+ }
+#endif
+
+ return cmLinkLineComputer::ConvertToLinkReference(lib);
+}
diff --git a/Source/cmMSVC60LinkLineComputer.h b/Source/cmMSVC60LinkLineComputer.h
new file mode 100644
index 000000000..f2892d53f
--- /dev/null
+++ b/Source/cmMSVC60LinkLineComputer.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 cmMSVC60LinkLineComputer_h
+#define cmMSVC60LinkLineComputer_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#include "cmLinkLineComputer.h"
+
+class cmOutputConverter;
+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;
+};
+
+#endif
diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx
new file mode 100644
index 000000000..a4350f7ce
--- /dev/null
+++ b/Source/cmMachO.cxx
@@ -0,0 +1,363 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmMachO.h"
+
+#include "cmsys/FStream.hxx"
+#include <algorithm>
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+// Include the Mach-O format information system header.
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+
+/**
+
+ https://developer.apple.com/library/mac/documentation/
+ DeveloperTools/Conceptual/MachORuntime/index.html
+
+ A Mach-O file has 3 major regions: header, load commands and segments.
+ Data Structures are provided from <mach-o/loader.h> which
+ correspond to the file structure.
+
+ The header can be either a struct mach_header or struct mach_header_64.
+ One can peek at the first 4 bytes to identify the type of header.
+
+ Following is the load command region which starts with
+ struct load_command, and is followed by n number of load commands.
+
+ In the case of a universal binary (an archive of multiple Mach-O files),
+ the file begins with a struct fat_header and is followed by multiple
+ struct fat_arch instances. The struct fat_arch indicates the offset
+ for each Mach-O file.
+
+ */
+
+namespace {
+
+// peek in the file
+template <typename T>
+bool peek(cmsys::ifstream& fin, T& v)
+{
+ std::streampos p = fin.tellg();
+ if (!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) {
+ return false;
+ }
+ fin.seekg(p);
+ return fin.good();
+}
+
+// read from the file and fill a data structure
+template <typename T>
+bool read(cmsys::ifstream& fin, T& v)
+{
+ if (!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) {
+ return false;
+ }
+ return true;
+}
+
+// read from the file and fill multiple data structures where
+// the vector has been resized
+template <typename T>
+bool read(cmsys::ifstream& fin, std::vector<T>& v)
+{
+ // nothing to read
+ if (v.empty()) {
+ return true;
+ }
+ if (!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size())) {
+ return false;
+ }
+ return true;
+}
+}
+
+// Contains header and load commands for a single Mach-O file
+class cmMachOHeaderAndLoadCommands
+{
+public:
+ // A load_command and its associated data
+ struct RawLoadCommand
+ {
+ uint32_t type(const cmMachOHeaderAndLoadCommands* m) const
+ {
+ if (this->LoadCommand.size() < sizeof(load_command)) {
+ return 0;
+ }
+ const load_command* cmd =
+ reinterpret_cast<const load_command*>(&this->LoadCommand[0]);
+ return m->swap(cmd->cmd);
+ }
+ std::vector<char> LoadCommand;
+ };
+
+ cmMachOHeaderAndLoadCommands(bool _swap)
+ : Swap(_swap)
+ {
+ }
+ virtual ~cmMachOHeaderAndLoadCommands() {}
+
+ virtual bool read_mach_o(cmsys::ifstream& fin) = 0;
+
+ const std::vector<RawLoadCommand>& load_commands() const
+ {
+ return this->LoadCommands;
+ }
+
+ uint32_t swap(uint32_t v) const
+ {
+ if (this->Swap) {
+ char* c = reinterpret_cast<char*>(&v);
+ std::swap(c[0], c[3]);
+ std::swap(c[1], c[2]);
+ }
+ return v;
+ }
+
+protected:
+ bool read_load_commands(uint32_t ncmds, uint32_t sizeofcmds,
+ cmsys::ifstream& fin);
+
+ bool Swap;
+ std::vector<RawLoadCommand> LoadCommands;
+};
+
+// Implementation for reading Mach-O header and load commands.
+// This is 32 or 64 bit arch specific.
+template <class T>
+class cmMachOHeaderAndLoadCommandsImpl : public cmMachOHeaderAndLoadCommands
+{
+public:
+ cmMachOHeaderAndLoadCommandsImpl(bool _swap)
+ : cmMachOHeaderAndLoadCommands(_swap)
+ {
+ }
+ bool read_mach_o(cmsys::ifstream& fin)
+ {
+ if (!read(fin, this->Header)) {
+ return false;
+ }
+ this->Header.cputype = swap(this->Header.cputype);
+ this->Header.cpusubtype = swap(this->Header.cpusubtype);
+ this->Header.filetype = swap(this->Header.filetype);
+ this->Header.ncmds = swap(this->Header.ncmds);
+ this->Header.sizeofcmds = swap(this->Header.sizeofcmds);
+ this->Header.flags = swap(this->Header.flags);
+
+ return read_load_commands(this->Header.ncmds, this->Header.sizeofcmds,
+ fin);
+ }
+
+protected:
+ T Header;
+};
+
+bool cmMachOHeaderAndLoadCommands::read_load_commands(uint32_t ncmds,
+ uint32_t sizeofcmds,
+ cmsys::ifstream& fin)
+{
+ uint32_t size_read = 0;
+ this->LoadCommands.resize(ncmds);
+ for (uint32_t i = 0; i < ncmds; i++) {
+ load_command lc;
+ if (!peek(fin, lc)) {
+ return false;
+ }
+ lc.cmd = swap(lc.cmd);
+ lc.cmdsize = swap(lc.cmdsize);
+ size_read += lc.cmdsize;
+
+ RawLoadCommand& c = this->LoadCommands[i];
+ c.LoadCommand.resize(lc.cmdsize);
+ if (!read(fin, c.LoadCommand)) {
+ return false;
+ }
+ }
+
+ if (size_read != sizeofcmds) {
+ this->LoadCommands.clear();
+ return false;
+ }
+
+ return true;
+}
+
+class cmMachOInternal
+{
+public:
+ cmMachOInternal(const char* fname);
+ ~cmMachOInternal();
+
+ // read a Mach-O file
+ bool read_mach_o(uint32_t file_offset);
+
+ // the file we are reading
+ cmsys::ifstream Fin;
+
+ // The archs in the universal binary
+ // If the binary is not a universal binary, this will be empty.
+ std::vector<fat_arch> FatArchs;
+
+ // the error message while parsing
+ std::string ErrorMessage;
+
+ // the list of Mach-O's
+ std::vector<cmMachOHeaderAndLoadCommands*> MachOList;
+};
+
+cmMachOInternal::cmMachOInternal(const char* fname)
+ : Fin(fname)
+{
+ // Quit now if the file could not be opened.
+ if (!this->Fin || !this->Fin.get()) {
+ this->ErrorMessage = "Error opening input file.";
+ return;
+ }
+
+ if (!this->Fin.seekg(0)) {
+ this->ErrorMessage = "Error seeking to beginning of file.";
+ return;
+ }
+
+ // Read the binary identification block.
+ uint32_t magic = 0;
+ if (!peek(this->Fin, magic)) {
+ this->ErrorMessage = "Error reading Mach-O identification.";
+ return;
+ }
+
+ // Verify the binary identification.
+ if (!(magic == MH_CIGAM || magic == MH_MAGIC || magic == MH_CIGAM_64 ||
+ magic == MH_MAGIC_64 || magic == FAT_CIGAM || magic == FAT_MAGIC)) {
+ this->ErrorMessage = "File does not have a valid Mach-O identification.";
+ return;
+ }
+
+ if (magic == FAT_MAGIC || magic == FAT_CIGAM) {
+ // this is a universal binary
+ fat_header header;
+ if (!read(this->Fin, header)) {
+ this->ErrorMessage = "Error reading fat header.";
+ return;
+ }
+
+ // read fat_archs
+ this->FatArchs.resize(OSSwapBigToHostInt32(header.nfat_arch));
+ if (!read(this->Fin, this->FatArchs)) {
+ this->ErrorMessage = "Error reading fat header archs.";
+ return;
+ }
+
+ // parse each Mach-O file
+ for (size_t i = 0; i < this->FatArchs.size(); i++) {
+ const fat_arch& arch = this->FatArchs[i];
+ if (!this->read_mach_o(OSSwapBigToHostInt32(arch.offset))) {
+ return;
+ }
+ }
+ } else {
+ // parse Mach-O file at the beginning of the file
+ this->read_mach_o(0);
+ }
+}
+
+cmMachOInternal::~cmMachOInternal()
+{
+ for (size_t i = 0; i < this->MachOList.size(); i++) {
+ delete this->MachOList[i];
+ }
+}
+
+bool cmMachOInternal::read_mach_o(uint32_t file_offset)
+{
+ if (!this->Fin.seekg(file_offset)) {
+ this->ErrorMessage = "Failed to locate Mach-O content.";
+ return false;
+ }
+
+ uint32_t magic;
+ if (!peek(this->Fin, magic)) {
+ this->ErrorMessage = "Error reading Mach-O identification.";
+ return false;
+ }
+
+ cmMachOHeaderAndLoadCommands* f = NULL;
+ if (magic == MH_CIGAM || magic == MH_MAGIC) {
+ bool swap = false;
+ if (magic == MH_CIGAM) {
+ swap = true;
+ }
+ f = new cmMachOHeaderAndLoadCommandsImpl<mach_header>(swap);
+ } else if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64) {
+ bool swap = false;
+ if (magic == MH_CIGAM_64) {
+ swap = true;
+ }
+ f = new cmMachOHeaderAndLoadCommandsImpl<mach_header_64>(swap);
+ }
+
+ if (f && f->read_mach_o(this->Fin)) {
+ this->MachOList.push_back(f);
+ } else {
+ delete f;
+ this->ErrorMessage = "Failed to read Mach-O header.";
+ return false;
+ }
+
+ return true;
+}
+
+//============================================================================
+// External class implementation.
+
+cmMachO::cmMachO(const char* fname)
+ : Internal(0)
+{
+ this->Internal = new cmMachOInternal(fname);
+}
+
+cmMachO::~cmMachO()
+{
+ delete this->Internal;
+}
+
+std::string const& cmMachO::GetErrorMessage() const
+{
+ return this->Internal->ErrorMessage;
+}
+
+bool cmMachO::Valid() const
+{
+ return !this->Internal->MachOList.empty();
+}
+
+bool cmMachO::GetInstallName(std::string& install_name)
+{
+ if (this->Internal->MachOList.empty()) {
+ return false;
+ }
+
+ // grab the first Mach-O and get the install name from that one
+ cmMachOHeaderAndLoadCommands* macho = this->Internal->MachOList[0];
+ for (size_t i = 0; i < macho->load_commands().size(); i++) {
+ const cmMachOHeaderAndLoadCommands::RawLoadCommand& cmd =
+ macho->load_commands()[i];
+ uint32_t lc_cmd = cmd.type(macho);
+ if (lc_cmd == LC_ID_DYLIB || lc_cmd == LC_LOAD_WEAK_DYLIB ||
+ lc_cmd == LC_LOAD_DYLIB) {
+ if (sizeof(dylib_command) < cmd.LoadCommand.size()) {
+ uint32_t namelen = cmd.LoadCommand.size() - sizeof(dylib_command);
+ install_name.assign(&cmd.LoadCommand[sizeof(dylib_command)], namelen);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void cmMachO::PrintInfo(std::ostream& /*os*/) const
+{
+}
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
new file mode 100644
index 000000000..42745cf60
--- /dev/null
+++ b/Source/cmMachO.h
@@ -0,0 +1,47 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmMachO_h
+#define cmMachO_h
+
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+
+#if !defined(CMAKE_USE_MACH_PARSER)
+#error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
+#endif
+
+class cmMachOInternal;
+
+/** \class cmMachO
+ * \brief Executable and Link Format (Mach-O) parser.
+ */
+class cmMachO
+{
+public:
+ /** Construct with the name of the Mach-O input file to parse. */
+ cmMachO(const char* fname);
+
+ /** Destruct. */
+ ~cmMachO();
+
+ /** Get the error message if any. */
+ std::string const& GetErrorMessage() const;
+
+ /** Boolean conversion. True if the Mach-O file is valid. */
+ operator bool() const { return this->Valid(); }
+
+ /** Get Install name from binary **/
+ bool GetInstallName(std::string& install_name);
+
+ /** Print human-readable information about the Mach-O file. */
+ void PrintInfo(std::ostream& os) const;
+
+private:
+ friend class cmMachOInternal;
+ bool Valid() const;
+ cmMachOInternal* Internal;
+};
+
+#endif
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 8ba612cc9..a6a9ea316 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -1,17 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMacroCommand.h"
-#include "cmake.h"
+#include <sstream>
+#include <stdio.h>
+
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
// define the class for macro commands
class cmMacroHelperCommand : public cmCommand
@@ -20,25 +19,14 @@ public:
cmMacroHelperCommand() {}
///! clean up any memory allocated by the macro
- ~cmMacroHelperCommand() {};
-
- /**
- * This is used to avoid including this command
- * in documentation. This is mainly used by
- * cmMacroHelperCommand and cmFunctionHelperCommand
- * which cannot provide appropriate documentation.
- */
- virtual bool ShouldAppearInDocumentation() const
- {
- return false;
- }
+ ~cmMacroHelperCommand() CM_OVERRIDE {}
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
+ cmCommand* Clone() CM_OVERRIDE
{
- cmMacroHelperCommand *newC = new cmMacroHelperCommand;
+ cmMacroHelperCommand* newC = new cmMacroHelperCommand;
// we must copy when we clone
newC->Args = this->Args;
newC->Functions = this->Functions;
@@ -48,259 +36,152 @@ public:
}
/**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &);
-
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) { return false; };
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return this->Args[0].c_str(); }
+ bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus&) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- std::string docs = "Macro named: ";
- docs += this->GetName();
- return docs.c_str();
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
+ bool InitialPass(std::vector<std::string> const&,
+ cmExecutionStatus&) CM_OVERRIDE
{
- return this->GetTerseDocumentation();
+ return false;
}
- cmTypeMacro(cmMacroHelperCommand, cmCommand);
-
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
cmPolicies::PolicyMap Policies;
std::string FilePath;
};
-
-bool cmMacroHelperCommand::InvokeInitialPass
-(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &inStatus)
+bool cmMacroHelperCommand::InvokeInitialPass(
+ const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
{
// Expand the argument list to the macro.
std::vector<std::string> expandedArgs;
this->Makefile->ExpandArguments(args, expandedArgs);
- std::string tmps;
- cmListFileArgument arg;
- std::string variable;
-
// make sure the number of arguments passed is at least the number
// required by the signature
- if (expandedArgs.size() < this->Args.size() - 1)
- {
+ 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.c_str());
+ this->SetError(errorMsg);
return false;
- }
-
- // Enforce matching logical blocks inside the macro.
- cmMakefile::LexicalPushPop lexScope(this->Makefile);
+ }
- // Push a weak policy scope which restores the policies recorded at
- // macro creation.
- cmMakefile::PolicyPushPop polScope(this->Makefile, true, this->Policies);
+ cmMakefile::MacroPushPop macroScope(this->Makefile, this->FilePath,
+ this->Policies);
// set the value of argc
- cmOStringStream argcDefStream;
+ std::ostringstream argcDefStream;
argcDefStream << expandedArgs.size();
std::string argcDef = argcDefStream.str();
- // declare varuiables for ARGV ARGN but do not compute until needed
- std::string argvDef;
- std::string argnDef;
- bool argnDefInitialized = false;
- bool argvDefInitialized = false;
- if( this->Functions.size())
- {
- this->FilePath = this->Functions[0].FilePath;
- }
+ std::vector<std::string>::const_iterator 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;
+ variables.reserve(this->Args.size() - 1);
+ for (unsigned int j = 1; j < this->Args.size(); ++j) {
+ variables.push_back("${" + this->Args[j] + "}");
+ }
+ std::vector<std::string> argVs;
+ 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);
+ }
// 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 (unsigned int c = 0; c < this->Functions.size(); ++c) {
// 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.FilePath = this->Functions[c].FilePath;
newLFF.Line = this->Functions[c].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)
- {
- // Set the FilePath on the arguments to match the function since it is
- // not stored and the original values may be freed
- k->FilePath = this->FilePath.c_str();
- tmps = k->Value;
- // replace formal arguments
- for (unsigned int j = 1; j < this->Args.size(); ++j)
- {
- variable = "${";
- variable += this->Args[j];
- variable += "}";
- cmSystemTools::ReplaceString(tmps, variable.c_str(),
- expandedArgs[j-1].c_str());
- }
- // replace argc
- cmSystemTools::ReplaceString(tmps, "${ARGC}",argcDef.c_str());
-
- // repleace ARGN
- if (tmps.find("${ARGN}") != std::string::npos)
- {
- if (!argnDefInitialized)
- {
- std::vector<std::string>::const_iterator eit;
- std::vector<std::string>::size_type cnt = 0;
- for ( eit = expandedArgs.begin(); eit != expandedArgs.end(); ++eit )
- {
- if ( cnt >= this->Args.size()-1 )
- {
- if ( argnDef.size() > 0 )
- {
- argnDef += ";";
- }
- argnDef += *eit;
- }
- cnt ++;
- }
- argnDefInitialized = true;
- }
- cmSystemTools::ReplaceString(tmps, "${ARGN}", argnDef.c_str());
+ k != this->Functions[c].Arguments.end(); ++k) {
+ cmListFileArgument arg;
+ 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],
+ expandedArgs[j]);
}
+ // replace argc
+ cmSystemTools::ReplaceString(arg.Value, "${ARGC}", argcDef);
- // if the current argument of the current function has ${ARGV in it
- // then try replacing ARGV values
- if (tmps.find("${ARGV") != std::string::npos)
- {
- char argvName[60];
-
- // repleace ARGV, compute it only once
- if (!argvDefInitialized)
- {
- std::vector<std::string>::const_iterator eit;
- for ( eit = expandedArgs.begin(); eit != expandedArgs.end(); ++eit )
- {
- if ( argvDef.size() > 0 )
- {
- argvDef += ";";
- }
- argvDef += *eit;
- }
- argvDefInitialized = true;
- }
- cmSystemTools::ReplaceString(tmps, "${ARGV}", argvDef.c_str());
+ cmSystemTools::ReplaceString(arg.Value, "${ARGN}", expandedArgn);
+ cmSystemTools::ReplaceString(arg.Value, "${ARGV}", expandedArgv);
- // also replace the ARGV1 ARGV2 ... etc
- for (unsigned int t = 0; t < expandedArgs.size(); ++t)
- {
- sprintf(argvName,"${ARGV%i}",t);
- cmSystemTools::ReplaceString(tmps, argvName,
- expandedArgs[t].c_str());
+ // if the current argument of the current function has ${ARGV in it
+ // then try replacing ARGV values
+ if (arg.Value.find("${ARGV") != std::string::npos) {
+ for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
+ cmSystemTools::ReplaceString(arg.Value, argVs[t], expandedArgs[t]);
}
}
-
- arg.Value = tmps;
+ }
arg.Delim = k->Delim;
- arg.FilePath = k->FilePath;
arg.Line = k->Line;
newLFF.Arguments.push_back(arg);
- }
+ }
cmExecutionStatus status;
- if(!this->Makefile->ExecuteCommand(newLFF, status) ||
- status.GetNestedError())
- {
+ if (!this->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.
- lexScope.Quiet();
- polScope.Quiet();
- inStatus.SetNestedError(true);
+ macroScope.Quiet();
+ inStatus.SetNestedError();
return false;
- }
- if (status.GetReturnInvoked())
- {
- inStatus.SetReturnInvoked(true);
+ }
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
return true;
- }
- if (status.GetBreakInvoked())
- {
- inStatus.SetBreakInvoked(true);
+ }
+ if (status.GetBreakInvoked()) {
+ inStatus.SetBreakInvoked();
return true;
- }
}
+ }
return true;
}
-bool cmMacroFunctionBlocker::
-IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
- cmExecutionStatus &)
+bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
+ cmMakefile& mf,
+ cmExecutionStatus&)
{
// 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"))
- {
+ if (!cmSystemTools::Strucmp(lff.Name.c_str(), "macro")) {
this->Depth++;
- }
- else if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endmacro"))
- {
+ } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
// if this is the endmacro for this macro then execute
- if (!this->Depth)
- {
- std::string name = this->Args[0];
- std::vector<std::string>::size_type cc;
- name += "(";
- for ( cc = 0; cc < this->Args.size(); cc ++ )
- {
- name += " " + this->Args[cc];
- }
- name += " )";
- mf.AddMacro(this->Args[0].c_str(), name.c_str());
+ if (!this->Depth) {
+ mf.AppendProperty("MACROS", this->Args[0].c_str());
// create a new command and add it to cmake
- cmMacroHelperCommand *f = new cmMacroHelperCommand();
+ cmMacroHelperCommand* f = new cmMacroHelperCommand();
f->Args = this->Args;
f->Functions = this->Functions;
+ f->FilePath = this->GetStartingContext().FilePath;
mf.RecordPolicies(f->Policies);
- std::string newName = "_" + this->Args[0];
- mf.GetCMakeInstance()->RenameCommand(this->Args[0].c_str(),
- newName.c_str());
- mf.AddCommand(f);
-
+ mf.GetState()->AddScriptedCommand(this->Args[0], f);
// remove the function blocker now that the macro is defined
mf.RemoveFunctionBlocker(this, lff);
return true;
- }
- else
- {
- // decrement for each nested macro that ends
- this->Depth--;
- }
}
+ // decrement for each nested macro that ends
+ this->Depth--;
+ }
// if it wasn't an endmacro and we are not executing then we must be
// recording
@@ -308,43 +189,35 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
return true;
}
-
-bool cmMacroFunctionBlocker::
-ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf)
+bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
+ cmMakefile& mf)
{
- if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endmacro"))
- {
+ if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
std::vector<std::string> expandedArguments;
- mf.ExpandArguments(lff.Arguments, 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])))
- {
+ (expandedArguments[0] == this->Args[0]))) {
return true;
- }
}
+ }
return false;
}
bool cmMacroCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &)
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// create a function blocker
- cmMacroFunctionBlocker *f = new cmMacroFunctionBlocker();
- for(std::vector<std::string>::const_iterator j = args.begin();
- j != args.end(); ++j)
- {
- f->Args.push_back(*j);
- }
+ cmMacroFunctionBlocker* f = new cmMacroFunctionBlocker();
+ f->Args.insert(f->Args.end(), args.begin(), args.end());
this->Makefile->AddFunctionBlocker(f);
return true;
}
-
diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h
index aedbb4ddc..0d35fe06e 100644
--- a/Source/cmMacroCommand.h
+++ b/Source/cmMacroCommand.h
@@ -1,29 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMacroCommand_h
#define cmMacroCommand_h
+#include "cmConfigure.h"
+
+#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;}
- virtual ~cmMacroFunctionBlocker() {}
- virtual bool IsFunctionBlocked(const cmListFileFunction&,
- cmMakefile &mf,
- cmExecutionStatus &);
- virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile &mf);
+ 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;
@@ -37,74 +36,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmMacroCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmMacroCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "macro";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Start recording a macro for later invocation as a command.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " macro(<name> [arg1 [arg2 [arg3 ...]]])\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " endmacro(<name>)\n"
- "Define a macro named <name> that takes arguments named "
- "arg1 arg2 arg3 (...). Commands listed after macro, "
- "but before the matching endmacro, are not invoked until the macro "
- "is invoked. When it is invoked, the commands recorded in the "
- "macro are first modified by replacing formal parameters (${arg1}) "
- "with the arguments passed, and then invoked as normal commands. In "
- "addition to referencing the formal parameters you can reference "
- "the values ${ARGC} which will be set to the number of arguments "
- "passed into the function as well as ${ARGV0} ${ARGV1} ${ARGV2} "
- "... which "
- "will have the actual values of the arguments passed in. This "
- "facilitates creating macros with optional arguments. Additionally "
- "${ARGV} holds the list of all arguments given to the macro and "
- "${ARGN} "
- "holds the list of arguments past the last expected argument. "
- "Note that the parameters to a macro and values such as ARGN "
- "are not variables in the usual CMake sense. They are string "
- "replacements much like the C preprocessor would do with a macro. "
- "If you want true CMake variables and/or better CMake scope control "
- "you should look at the function command."
- "\n"
- "See the cmake_policy() command documentation for the behavior of "
- "policies inside macros."
- ;
- }
- cmTypeMacro(cmMacroCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx
deleted file mode 100644
index 2ae35ef14..000000000
--- a/Source/cmMakeDepend.cxx
+++ /dev/null
@@ -1,364 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmMakeDepend.h"
-#include "cmSystemTools.h"
-#include "cmGeneratorExpression.h"
-
-#include <cmsys/RegularExpression.hxx>
-
-void cmDependInformation::AddDependencies(cmDependInformation* info)
-{
- if(this != info)
- {
- this->DependencySet.insert(info);
- }
-}
-
-cmMakeDepend::cmMakeDepend()
-{
- this->Verbose = false;
- this->IncludeFileRegularExpression.compile("^.*$");
- this->ComplainFileRegularExpression.compile("^$");
-}
-
-
-cmMakeDepend::~cmMakeDepend()
-{
- for(DependInformationMapType::iterator i =
- this->DependInformationMap.begin();
- i != this->DependInformationMap.end(); ++i)
- {
- delete i->second;
- }
-}
-
-
-// Set the makefile that depends will be made from.
-// The pointer is kept so the cmSourceFile array can
-// be updated with the depend information in the cmMakefile.
-
-void cmMakeDepend::SetMakefile(cmMakefile* makefile)
-{
- this->Makefile = makefile;
-
- // Now extract the include file regular expression from the makefile.
- this->IncludeFileRegularExpression.compile(
- this->Makefile->IncludeFileRegularExpression.c_str());
- this->ComplainFileRegularExpression.compile(
- this->Makefile->ComplainFileRegularExpression.c_str());
-
- // 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");
- if (!incDirProp)
- {
- continue;
- }
-
- std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp,
- cmGeneratorExpression::StripAllGeneratorExpressions);
-
- std::vector<std::string> includes;
- cmSystemTools::ExpandListArgument(incDirs.c_str(), includes);
-
- for(std::vector<std::string>::const_iterator j = includes.begin();
- j != includes.end(); ++j)
- {
- std::string path = *j;
- this->Makefile->ExpandVariablesInString(path);
- if(uniqueIncludes.insert(path).second)
- {
- orderedAndUniqueIncludes.push_back(path);
- }
- }
- }
-
- for(std::vector<std::string>::const_iterator
- it = orderedAndUniqueIncludes.begin();
- it != orderedAndUniqueIncludes.end();
- ++it)
- {
- this->AddSearchPath(it->c_str());
- }
-}
-
-
-const cmDependInformation* cmMakeDepend::FindDependencies(const char* file)
-{
- cmDependInformation* info = this->GetDependInformation(file,0);
- this->GenerateDependInformation(info);
- return info;
-}
-
-void cmMakeDepend::GenerateDependInformation(cmDependInformation* info)
-{
- // If dependencies are already done, stop now.
- if(info->DependDone)
- {
- return;
- }
- else
- {
- // Make sure we don't visit the same file more than once.
- info->DependDone = true;
- }
- const char* path = info->FullPath.c_str();
- if(!path)
- {
- cmSystemTools::Error(
- "Attempt to find dependencies for file without path!");
- return;
- }
-
- bool found = false;
-
- // If the file exists, use it to find dependency information.
- if(cmSystemTools::FileExists(path, true))
- {
- // Use the real file to find its dependencies.
- this->DependWalk(info);
- found = true;
- }
-
-
- // See if the cmSourceFile for it has any files specified as
- // dependency hints.
- if(info->SourceFile != 0)
- {
-
- // Get the cmSourceFile corresponding to this.
- const cmSourceFile& cFile = *(info->SourceFile);
- // See if there are any hints for finding dependencies for the missing
- // file.
- 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());
- }
-
- // Found dependency information. We are done.
- found = true;
- }
- }
-
- if(!found)
- {
- // Try to find the file amongst the sources
- cmSourceFile *srcFile = this->Makefile->GetSource
- (cmSystemTools::GetFilenameWithoutExtension(path).c_str());
- if (srcFile)
- {
- if (srcFile->GetFullPath() == 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.size() && incpath[incpath.size() - 1] != '/')
- {
- incpath = incpath + "/";
- }
- incpath = incpath + path;
- if (srcFile->GetFullPath() == incpath)
- {
- // set the path to the guessed path
- info->FullPath = incpath;
- found=true;
- }
- }
- }
- }
- }
-
- if(!found)
- {
- // Couldn't find any dependency information.
- if(this->ComplainFileRegularExpression.find(info->IncludeName.c_str()))
- {
- 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 = "";
- }
- }
-}
-
-// This function actually reads the file specified and scans it for
-// #include directives
-void cmMakeDepend::DependWalk(cmDependInformation* info)
-{
- cmsys::RegularExpression includeLine
- ("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]");
- std::ifstream fin(info->FullPath.c_str());
- if(!fin)
- {
- cmSystemTools::Error("Cannot open ", info->FullPath.c_str());
- return;
- }
-
- // TODO: Write real read loop (see cmSystemTools::CopyFile).
- std::string line;
- while( cmSystemTools::GetLineFromStream(fin, line) )
- {
- if(includeLine.find(line.c_str()))
- {
- // extract the file being included
- std::string includeFile = includeLine.match(1);
- // 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.c_str();
- cmSystemTools::Error(message.c_str(), 0);
- }
- continue;
- }
-
- // Add this file and all its dependencies.
- this->AddDependency(info, includeFile.c_str());
- }
- }
-}
-
-
-void cmMakeDepend::AddDependency(cmDependInformation* info, const char* file)
-{
- cmDependInformation* dependInfo =
- this->GetDependInformation(file, info->PathOnly.c_str());
- this->GenerateDependInformation(dependInfo);
- info->AddDependencies(dependInfo);
-}
-
-cmDependInformation* cmMakeDepend::GetDependInformation(const char* file,
- const char *extraPath)
-{
- // Get the full path for the file so that lookup is unambiguous.
- std::string fullPath = this->FullPath(file, extraPath);
-
- // Try to find the file's instance of cmDependInformation.
- DependInformationMapType::const_iterator result =
- this->DependInformationMap.find(fullPath);
- if(result != this->DependInformationMap.end())
- {
- // Found an instance, return it.
- return result->second;
- }
- else
- {
- // Didn't find an instance. Create a new one and save it.
- cmDependInformation* info = new cmDependInformation;
- info->FullPath = fullPath;
- info->PathOnly = cmSystemTools::GetFilenamePath(fullPath.c_str());
- info->IncludeName = file;
- this->DependInformationMap[fullPath] = info;
- return info;
- }
-}
-
-
-// find the full path to fname by searching the this->IncludeDirectories array
-std::string cmMakeDepend::FullPath(const char* fname, const char *extraPath)
-{
- DirectoryToFileToPathMapType::iterator m;
- if(extraPath)
- {
- m = this->DirectoryToFileToPathMap.find(extraPath);
- }
- else
- {
- m = this->DirectoryToFileToPathMap.find("");
- }
-
- if(m != this->DirectoryToFileToPathMap.end())
- {
- FileToPathMapType& map = m->second;
- FileToPathMapType::iterator p = map.find(fname);
- if(p != map.end())
- {
- return p->second;
- }
- }
-
- if(cmSystemTools::FileExists(fname, true))
- {
- std::string fp = cmSystemTools::CollapseFullPath(fname);
- this->DirectoryToFileToPathMap[extraPath? extraPath: ""][fname] = fp;
- return fp;
- }
-
- for(std::vector<std::string>::iterator i = this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i)
- {
- std::string path = *i;
- if (path.size() && path[path.size() - 1] != '/')
- {
- path = path + "/";
- }
- path = path + fname;
- if(cmSystemTools::FileExists(path.c_str(), true)
- && !cmSystemTools::FileIsDirectory(path.c_str()))
- {
- std::string fp = cmSystemTools::CollapseFullPath(path.c_str());
- this->DirectoryToFileToPathMap[extraPath? extraPath: ""][fname] = fp;
- return fp;
- }
- }
-
- if (extraPath)
- {
- std::string path = extraPath;
- if (path.size() && path[path.size() - 1] != '/')
- {
- path = path + "/";
- }
- path = path + fname;
- if(cmSystemTools::FileExists(path.c_str(), true)
- && !cmSystemTools::FileIsDirectory(path.c_str()))
- {
- std::string fp = cmSystemTools::CollapseFullPath(path.c_str());
- this->DirectoryToFileToPathMap[extraPath][fname] = fp;
- return fp;
- }
- }
-
- // Couldn't find the file.
- return std::string(fname);
-}
-
-// Add a directory to the search path
-void cmMakeDepend::AddSearchPath(const char* path)
-{
- this->IncludeDirectories.push_back(path);
-}
diff --git a/Source/cmMakeDepend.h b/Source/cmMakeDepend.h
deleted file mode 100644
index b6e3928e9..000000000
--- a/Source/cmMakeDepend.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmMakeDepend_h
-#define cmMakeDepend_h
-
-#include "cmMakefile.h"
-#include "cmSourceFile.h"
-
-#include <cmsys/RegularExpression.hxx>
-
-/** \class cmDependInformation
- * \brief Store dependency information for a single source file.
- *
- * This structure stores the depend information for a single source file.
- */
-class cmDependInformation
-{
-public:
- /**
- * Construct with dependency generation marked not done; instance
- * not placed in cmMakefile's list.
- */
- cmDependInformation(): DependDone(false), SourceFile(0) {}
-
- /**
- * The set of files on which this one depends.
- */
- typedef std::set<cmDependInformation*> DependencySetType;
- DependencySetType DependencySet;
-
- /**
- * This flag indicates whether dependency checking has been
- * performed for this file.
- */
- bool DependDone;
-
- /**
- * If this object corresponds to a cmSourceFile instance, this points
- * to it.
- */
- const cmSourceFile *SourceFile;
-
- /**
- * Full path to this file.
- */
- std::string FullPath;
-
- /**
- * Full path not including file name.
- */
- std::string PathOnly;
-
- /**
- * Name used to #include this file.
- */
- std::string IncludeName;
-
- /**
- * This method adds the dependencies of another file to this one.
- */
- void AddDependencies(cmDependInformation*);
-};
-
-
-// cmMakeDepend is used to generate dependancy information for
-// the classes in a makefile
-class cmMakeDepend
-{
-public:
- /**
- * Construct the object with verbose turned off.
- */
- cmMakeDepend();
-
- /**
- * Destructor.
- */
- virtual ~cmMakeDepend();
-
- /**
- * Set the makefile that is used as a source of classes.
- */
- virtual void SetMakefile(cmMakefile* makefile);
-
- /**
- * Add a directory to the search path for include files.
- */
- virtual void AddSearchPath(const char*);
-
- /**
- * Generate dependencies for the file given. Returns a pointer to
- * the cmDependInformation object for the file.
- */
- const cmDependInformation* FindDependencies(const char* file);
-
-protected:
- /**
- * Compute the depend information for this class.
- */
- virtual void DependWalk(cmDependInformation* info);
-
- /**
- * Add a dependency. Possibly walk it for more dependencies.
- */
- virtual void AddDependency(cmDependInformation* info, const char* file);
-
- /**
- * Fill in the given object with dependency information. If the
- * information is already complete, nothing is done.
- */
- void GenerateDependInformation(cmDependInformation* info);
-
- /**
- * Get an instance of cmDependInformation corresponding to the given file
- * name.
- */
- cmDependInformation* GetDependInformation(const char* file,
- const char *extraPath);
-
- /**
- * Find the full path name for the given file name.
- * This uses the include directories.
- * TODO: Cache path conversions to reduce FileExists calls.
- */
- std::string FullPath(const char *filename, const char *extraPath);
-
- cmMakefile* Makefile;
- bool Verbose;
- cmsys::RegularExpression IncludeFileRegularExpression;
- cmsys::RegularExpression ComplainFileRegularExpression;
- std::vector<std::string> IncludeDirectories;
- typedef std::map<cmStdString, cmStdString> FileToPathMapType;
- typedef std::map<cmStdString, FileToPathMapType>
- DirectoryToFileToPathMapType;
- typedef std::map<cmStdString, cmDependInformation*>
- DependInformationMapType;
- DependInformationMapType DependInformationMap;
- DirectoryToFileToPathMapType DirectoryToFileToPathMap;
-};
-
-#endif
diff --git a/Source/cmMakeDirectoryCommand.cxx b/Source/cmMakeDirectoryCommand.cxx
index 63be62734..06e295bc0 100644
--- a/Source/cmMakeDirectoryCommand.cxx
+++ b/Source/cmMakeDirectoryCommand.cxx
@@ -1,34 +1,27 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmMakeDirectoryCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmMakeDirectoryCommand.h"
+class cmExecutionStatus;
// cmMakeDirectoryCommand
-bool cmMakeDirectoryCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmMakeDirectoryCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() != 1 )
- {
+ if (args.size() != 1) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- if ( !this->Makefile->CanIWriteThisFile(args[0].c_str()) )
- {
- std::string e = "attempted to create a directory: " + args[0]
- + " into a source directory.";
- this->SetError(e.c_str());
- cmSystemTools::SetFatalErrorOccured();
- return false;
- }
+ }
+ if (!this->Makefile->CanIWriteThisFile(args[0].c_str())) {
+ std::string e = "attempted to create a directory: " + args[0] +
+ " into a source directory.";
+ this->SetError(e);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
cmSystemTools::MakeDirectory(args[0].c_str());
return true;
}
-
diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h
index a0f866a5f..af72eab96 100644
--- a/Source/cmMakeDirectoryCommand.h
+++ b/Source/cmMakeDirectoryCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMakeDirectoryCommand_h
#define cmMakeDirectoryCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmMakeDirectoryCommand
* \brief Specify auxiliary source code directories.
*
@@ -29,57 +27,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmMakeDirectoryCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmMakeDirectoryCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "make_directory";}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the file(MAKE_DIRECTORY ) command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " make_directory(directory)\n"
- "Creates the specified directory. Full paths should be given. Any "
- "parent directories that do not exist will also be created. Use with "
- "care.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmMakeDirectoryCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 34541e996..608b18a46 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1,393 +1,263 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmMakefile.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <assert.h>
+#include <ctype.h>
+#include <sstream>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmMakefile.h"
-#include "cmVersion.h"
+#include "cmAlgorithms.h"
#include "cmCommand.h"
+#include "cmCommandArgumentParserHelper.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
+#include "cmExecutionStatus.h"
+#include "cmExpandedCommandArgument.h"
+#include "cmFileLockPool.h"
+#include "cmFunctionBlocker.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionEvaluationFile.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h" // IWYU pragma: keep
+#include "cmListFileCache.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmCommands.h"
-#include "cmCacheManager.h"
-#include "cmFunctionBlocker.h"
-#include "cmListFileCache.h"
-#include "cmDocumentGeneratorExpressions.h"
-#include "cmCommandArgumentParserHelper.h"
-#include "cmDocumentCompileDefinitions.h"
-#include "cmGeneratorExpression.h"
+#include "cmTargetLinkLibraryType.h"
#include "cmTest.h"
-#ifdef CMAKE_BUILD_WITH_CMAKE
-# include "cmVariableWatch.h"
-#endif
-#include "cmInstallGenerator.h"
-#include "cmTestGenerator.h"
-#include "cmDefinitions.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"
-#include <stdlib.h> // required for atoi
-
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/auto_ptr.hxx>
-
-#include <stack>
-#include <ctype.h> // for isspace
-#include <assert.h>
+#ifdef CMAKE_BUILD_WITH_CMAKE
+#include "cmVariableWatch.h"
+#endif
-class cmMakefile::Internals
-{
-public:
- std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack;
- std::stack<std::set<cmStdString> > VarInitStack;
- std::stack<std::set<cmStdString> > VarUsageStack;
- bool IsSourceFileTryCompile;
-};
+class cmMessenger;
// default is not to be building executables
-cmMakefile::cmMakefile(): Internal(new Internals)
+cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
+ cmStateSnapshot const& snapshot)
+ : GlobalGenerator(globalGenerator)
+ , StateSnapshot(snapshot)
+ , Backtrace(snapshot)
{
- const cmDefinitions& defs = cmDefinitions();
- const std::set<cmStdString> globalKeys = defs.LocalKeys();
- this->Internal->VarStack.push(defs);
- this->Internal->VarInitStack.push(globalKeys);
- this->Internal->VarUsageStack.push(globalKeys);
- this->Internal->IsSourceFileTryCompile = false;
+ this->IsSourceFileTryCompile = false;
+
+ this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
+ this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
- // Initialize these first since AddDefaultDefinitions calls AddDefinition
- this->WarnUnused = false;
- this->CheckSystemVars = false;
+ this->SuppressWatches = false;
- // Setup the default include file regular expression (match everything).
- this->IncludeFileRegularExpression = "^.*$";
// Setup the default include complaint regular expression (match nothing).
this->ComplainFileRegularExpression = "^$";
- // Source and header file extensions that we can handle
-
- // 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" );
this->DefineFlags = " ";
- this->LocalGenerator = 0;
-
- this->AddDefaultDefinitions();
- this->Initialize();
- this->PreOrder = false;
- this->GeneratingBuildSystem = false;
-}
-
-cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
-{
- this->Internal->VarStack.push(mf.Internal->VarStack.top().Closure());
- this->Internal->VarInitStack.push(mf.Internal->VarInitStack.top());
- this->Internal->VarUsageStack.push(mf.Internal->VarUsageStack.top());
-
- this->Prefix = mf.Prefix;
- this->AuxSourceDirectories = mf.AuxSourceDirectories;
- this->cmStartDirectory = mf.cmStartDirectory;
- this->StartOutputDirectory = mf.StartOutputDirectory;
- this->cmHomeDirectory = mf.cmHomeDirectory;
- this->HomeOutputDirectory = mf.HomeOutputDirectory;
- this->cmCurrentListFile = mf.cmCurrentListFile;
- this->ProjectName = mf.ProjectName;
- this->Targets = mf.Targets;
- this->SourceFiles = mf.SourceFiles;
- this->Tests = mf.Tests;
- this->LinkDirectories = mf.LinkDirectories;
- this->SystemIncludeDirectories = mf.SystemIncludeDirectories;
- this->ListFiles = mf.ListFiles;
- this->OutputFiles = mf.OutputFiles;
- this->LinkLibraries = mf.LinkLibraries;
- this->InstallGenerators = mf.InstallGenerators;
- this->TestGenerators = mf.TestGenerators;
- this->IncludeFileRegularExpression = mf.IncludeFileRegularExpression;
- this->ComplainFileRegularExpression = mf.ComplainFileRegularExpression;
- this->SourceFileExtensions = mf.SourceFileExtensions;
- this->HeaderFileExtensions = mf.HeaderFileExtensions;
- this->DefineFlags = mf.DefineFlags;
- this->DefineFlagsOrig = mf.DefineFlagsOrig;
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- this->SourceGroups = mf.SourceGroups;
-#endif
-
- this->LocalGenerator = mf.LocalGenerator;
- this->FunctionBlockers = mf.FunctionBlockers;
- this->MacrosMap = mf.MacrosMap;
- this->SubDirectoryOrder = mf.SubDirectoryOrder;
- this->Properties = mf.Properties;
- this->PreOrder = mf.PreOrder;
- this->WarnUnused = mf.WarnUnused;
- this->Initialize();
- this->CheckSystemVars = mf.CheckSystemVars;
- this->ListFileStack = mf.ListFileStack;
- this->OutputToSource = mf.OutputToSource;
-}
-//----------------------------------------------------------------------------
-void cmMakefile::Initialize()
-{
this->cmDefineRegex.compile("#cmakedefine[ \t]+([A-Za-z_0-9]*)");
this->cmDefine01Regex.compile("#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);
// Enter a policy level for this directory.
this->PushPolicy();
- // Protect the directory-level policies.
- this->PushPolicyBarrier();
+ // push empty loop block
+ this->PushLoopBlockBarrier();
// By default the check is not done. It is enabled by
// cmListFileCache in the top level if necessary.
this->CheckCMP0000 = false;
-}
-unsigned int cmMakefile::GetCacheMajorVersion()
-{
- return this->GetCacheManager()->GetCacheMajorVersion();
-}
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ 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("Header Files", CM_HEADER_REGEX);
+ this->AddSourceGroup("CMake Rules", "\\.rule$");
+ this->AddSourceGroup("Resources", "\\.plist$");
+ this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
-unsigned int cmMakefile::GetCacheMinorVersion()
-{
- return this->GetCacheManager()->GetCacheMinorVersion();
+ this->ObjectLibrariesSourceGroupIndex = this->SourceGroups.size();
+ this->SourceGroups.push_back(
+ cmSourceGroup("Object Libraries", "^MATCH_NO_SOURCES$"));
+#endif
}
-bool cmMakefile::NeedCacheCompatibility(int major, int minor)
+cmMakefile::~cmMakefile()
{
- return this->GetCacheManager()->NeedCacheCompatibility(major, minor);
+ cmDeleteAll(this->InstallGenerators);
+ cmDeleteAll(this->TestGenerators);
+ cmDeleteAll(this->SourceFiles);
+ cmDeleteAll(this->Tests);
+ cmDeleteAll(this->ImportedTargetsOwned);
+ cmDeleteAll(this->FinalPassCommands);
+ cmDeleteAll(this->FunctionBlockers);
+ cmDeleteAll(this->EvaluationFiles);
}
-cmMakefile::~cmMakefile()
+void cmMakefile::IssueMessage(cmake::MessageType t,
+ std::string const& text) const
{
- for(std::vector<cmInstallGenerator*>::iterator
- i = this->InstallGenerators.begin();
- i != this->InstallGenerators.end(); ++i)
- {
- delete *i;
- }
- for(std::vector<cmTestGenerator*>::iterator
- i = this->TestGenerators.begin();
- i != this->TestGenerators.end(); ++i)
- {
- delete *i;
- }
- for(std::vector<cmSourceFile*>::iterator i = this->SourceFiles.begin();
- i != this->SourceFiles.end(); ++i)
- {
- delete *i;
+ if (!this->ExecutionStatusStack.empty()) {
+ if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) {
+ this->ExecutionStatusStack.back()->SetNestedError();
}
- for(std::map<cmStdString, cmTest*>::iterator i = this->Tests.begin();
- i != this->Tests.end(); ++i)
- {
- delete i->second;
- }
- for(std::vector<cmTarget*>::iterator
- i = this->ImportedTargetsOwned.begin();
- i != this->ImportedTargetsOwned.end(); ++i)
- {
- delete *i;
- }
- for(unsigned int i=0; i < this->FinalPassCommands.size(); i++)
- {
- delete this->FinalPassCommands[i];
- }
- std::vector<cmFunctionBlocker*>::iterator pos;
- for (pos = this->FunctionBlockers.begin();
- pos != this->FunctionBlockers.end(); ++pos)
- {
- cmFunctionBlocker* b = *pos;
- delete b;
- }
- this->FunctionBlockers.clear();
- if (this->PolicyStack.size() != 1)
- {
- cmSystemTools::Error("Internal CMake Error, Policy Stack has not been"
- " popped properly");
}
+ this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
}
-void cmMakefile::PrintStringVector(const char* s,
- const std::vector<std::string>& v) const
+cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
- std::cout << s << ": ( \n";
- for(std::vector<std::string>::const_iterator i = v.begin();
- i != v.end(); ++i)
- {
- std::cout << (*i).c_str() << " ";
- }
- std::cout << " )\n";
+ return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
}
-void cmMakefile
-::PrintStringVector(const char* s,
- const std::vector<std::pair<cmStdString, bool> >& v) const
+cmBacktraceRange cmMakefile::GetIncludeDirectoriesBacktraces() const
{
- std::cout << s << ": ( \n";
- for(std::vector<std::pair<cmStdString, bool> >::const_iterator i
- = v.begin(); i != v.end(); ++i)
- {
- std::cout << i->first.c_str() << " " << i->second;
- }
- std::cout << " )\n";
+ return this->StateSnapshot.GetDirectory()
+ .GetIncludeDirectoriesEntryBacktraces();
}
-
-// call print on all the classes in the makefile
-void cmMakefile::Print()
+cmStringRange cmMakefile::GetCompileOptionsEntries() const
{
- // print the class lists
- std::cout << "classes:\n";
+ return this->StateSnapshot.GetDirectory().GetCompileOptionsEntries();
+}
- std::cout << " this->Targets: ";
- for (cmTargets::iterator l = this->Targets.begin();
- l != this->Targets.end(); l++)
- {
- std::cout << l->first << std::endl;
- }
+cmBacktraceRange cmMakefile::GetCompileOptionsBacktraces() const
+{
+ return this->StateSnapshot.GetDirectory().GetCompileOptionsEntryBacktraces();
+}
- std::cout << " this->StartOutputDirectory; " <<
- this->StartOutputDirectory.c_str() << std::endl;
- std::cout << " this->HomeOutputDirectory; " <<
- this->HomeOutputDirectory.c_str() << std::endl;
- std::cout << " this->cmStartDirectory; " <<
- this->cmStartDirectory.c_str() << std::endl;
- std::cout << " this->cmHomeDirectory; " <<
- this->cmHomeDirectory.c_str() << std::endl;
- std::cout << " this->ProjectName; "
- << this->ProjectName.c_str() << std::endl;
- this->PrintStringVector("this->LinkDirectories", this->LinkDirectories);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- for( std::vector<cmSourceGroup>::const_iterator i =
- this->SourceGroups.begin(); i != this->SourceGroups.end(); ++i)
- {
- std::cout << "Source Group: " << i->GetName() << std::endl;
- }
-#endif
+cmStringRange cmMakefile::GetCompileDefinitionsEntries() const
+{
+ return this->StateSnapshot.GetDirectory().GetCompileDefinitionsEntries();
}
-bool cmMakefile::CommandExists(const char* name) const
+cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const
{
- return this->GetCMakeInstance()->CommandExists(name);
+ return this->StateSnapshot.GetDirectory()
+ .GetCompileDefinitionsEntryBacktraces();
}
+cmListFileBacktrace cmMakefile::GetBacktrace() const
+{
+ return this->Backtrace;
+}
-//----------------------------------------------------------------------------
-void cmMakefile::IssueMessage(cmake::MessageType t,
- std::string const& text) const
+cmListFileBacktrace cmMakefile::GetBacktrace(cmCommandContext const& cc) const
{
- // Collect context information.
- cmListFileBacktrace backtrace;
- if(!this->CallStack.empty())
- {
- if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
- {
- this->CallStack.back().Status->SetNestedError(true);
- }
- this->GetBacktrace(backtrace);
- }
- else
- {
- cmListFileContext lfc;
- if(this->ListFileStack.empty())
- {
- // We are not processing the project. Add the directory-level context.
- lfc.FilePath = this->GetCurrentDirectory();
- lfc.FilePath += "/CMakeLists.txt";
- }
- else
- {
- // We are processing the project but are not currently executing a
- // command. Add whatever context information we have.
- lfc.FilePath = this->ListFileStack.back();
- }
- lfc.Line = 0;
- if(!this->GetCMakeInstance()->GetIsInTryCompile())
- {
- lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
- cmLocalGenerator::HOME);
- }
- backtrace.push_back(lfc);
- }
+ cmListFileContext lfc;
+ lfc.Name = cc.Name;
+ lfc.Line = cc.Line;
+ lfc.FilePath = this->StateSnapshot.GetExecutionListFile();
+ return this->Backtrace.Push(lfc);
+}
- // Issue the message.
- this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
+cmListFileContext cmMakefile::GetExecutionContext() const
+{
+ cmListFileContext const& cur = this->Backtrace.Top();
+ cmListFileContext lfc;
+ lfc.Name = cur.Name;
+ lfc.Line = cur.Line;
+ lfc.FilePath = this->StateSnapshot.GetExecutionListFile();
+ return lfc;
}
-//----------------------------------------------------------------------------
-bool cmMakefile::GetBacktrace(cmListFileBacktrace& backtrace) const
+void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
{
- if(this->CallStack.empty())
- {
- return false;
+ // Check if current file in the list of requested to trace...
+ std::vector<std::string> const& trace_only_this_files =
+ this->GetCMakeInstance()->GetTraceSources();
+ std::string const& full_path = this->GetExecutionFilePath();
+ 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);
+ trace = (pos != std::string::npos) &&
+ ((pos + i->size()) == full_path.size()) &&
+ (only_filename == cmSystemTools::GetFilenameName(*i));
}
- for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
- i != this->CallStack.rend(); ++i)
- {
- cmListFileContext lfc = *(*i).Context;
- lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
- cmLocalGenerator::HOME);
- backtrace.push_back(lfc);
+ // Do nothing if current file wasn't requested for trace...
+ if (!trace) {
+ return;
}
- return true;
-}
+ }
-//----------------------------------------------------------------------------
-void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff)
-{
- cmOStringStream msg;
- msg << lff.FilePath << "(" << lff.Line << "): ";
+ std::ostringstream msg;
+ msg << full_path << "(" << lff.Line << "): ";
msg << lff.Name << "(";
- for(std::vector<cmListFileArgument>::const_iterator i =
- lff.Arguments.begin(); i != lff.Arguments.end(); ++i)
- {
- msg << i->Value;
- msg << " ";
+ bool expand = this->GetCMakeInstance()->GetTraceExpand();
+ std::string temp;
+ for (std::vector<cmListFileArgument>::const_iterator i =
+ lff.Arguments.begin();
+ i != lff.Arguments.end(); ++i) {
+ if (expand) {
+ temp = i->Value;
+ this->ExpandVariablesInString(temp);
+ msg << temp;
+ } else {
+ msg << i->Value;
}
+ msg << " ";
+ }
msg << ")";
cmSystemTools::Message(msg.str().c_str());
}
-//----------------------------------------------------------------------------
+// Helper class to make sure the call stack is valid.
+class cmMakefileCall
+{
+public:
+ cmMakefileCall(cmMakefile* mf, cmCommandContext const& cc,
+ cmExecutionStatus& status)
+ : Makefile(mf)
+ {
+ cmListFileContext const& lfc = cmListFileContext::FromCommandContext(
+ cc, this->Makefile->StateSnapshot.GetExecutionListFile());
+ this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc);
+ this->Makefile->ExecutionStatusStack.push_back(&status);
+ }
+
+ ~cmMakefileCall()
+ {
+ this->Makefile->ExecutionStatusStack.pop_back();
+ this->Makefile->Backtrace = this->Makefile->Backtrace.Pop();
+ }
+
+private:
+ cmMakefile* Makefile;
+};
+
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
- cmExecutionStatus &status)
+ cmExecutionStatus& status)
{
bool result = true;
// quick return if blocked
- if(this->IsFunctionBlocked(lff,status))
- {
+ if (this->IsFunctionBlocked(lff, status)) {
// No error.
return result;
- }
+ }
std::string name = lff.Name;
@@ -396,98 +266,83 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
static_cast<void>(stack_manager);
// Lookup the command prototype.
- if(cmCommand* proto = this->GetCMakeInstance()->GetCommand(name.c_str()))
- {
+ if (cmCommand* proto = this->GetState()->GetCommand(name)) {
// Clone the prototype.
- cmsys::auto_ptr<cmCommand> pcmd(proto->Clone());
+ CM_AUTO_PTR<cmCommand> pcmd(proto->Clone());
pcmd->SetMakefile(this);
// Decide whether to invoke the command.
- if(pcmd->GetEnabled() && !cmSystemTools::GetFatalErrorOccured() &&
- (this->GetCMakeInstance()->GetWorkingMode() != cmake::SCRIPT_MODE
- || pcmd->IsScriptable()))
-
- {
+ if (!cmSystemTools::GetFatalErrorOccured()) {
// if trace is enabled, print out invoke information
- if(this->GetCMakeInstance()->GetTrace())
- {
+ if (this->GetCMakeInstance()->GetTrace()) {
this->PrintCommandTrace(lff);
- }
+ }
// Try invoking the command.
- if(!pcmd->InvokeInitialPass(lff.Arguments,status) ||
- status.GetNestedError())
- {
- if(!status.GetNestedError())
- {
+ bool invokeSucceeded = pcmd->InvokeInitialPass(lff.Arguments, status);
+ bool hadNestedError = status.GetNestedError();
+ if (!invokeSucceeded || hadNestedError) {
+ if (!hadNestedError) {
// The command invocation requested that we report an error.
- this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
- }
+ std::string const error = name + " " + pcmd->GetError();
+ this->IssueMessage(cmake::FATAL_ERROR, error);
+ }
result = false;
- if ( this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE)
- {
+ if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) {
cmSystemTools::SetFatalErrorOccured();
- }
}
- else if(pcmd->HasFinalPass())
- {
+ } else if (pcmd->HasFinalPass()) {
// use the command
this->FinalPassCommands.push_back(pcmd.release());
- }
- }
- else if ( this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE
- && !pcmd->IsScriptable() )
- {
- std::string error = "Command ";
- error += pcmd->GetName();
- error += "() is not scriptable";
- this->IssueMessage(cmake::FATAL_ERROR, error);
- result = false;
- cmSystemTools::SetFatalErrorOccured();
}
}
- else
- {
- if(!cmSystemTools::GetFatalErrorOccured())
- {
+ } else {
+ if (!cmSystemTools::GetFatalErrorOccured()) {
std::string error = "Unknown CMake command \"";
error += lff.Name;
error += "\".";
this->IssueMessage(cmake::FATAL_ERROR, error);
result = false;
cmSystemTools::SetFatalErrorOccured();
- }
}
+ }
return result;
}
-//----------------------------------------------------------------------------
class cmMakefile::IncludeScope
{
public:
- IncludeScope(cmMakefile* mf, const char* fname, bool noPolicyScope);
+ IncludeScope(cmMakefile* mf, std::string const& filenametoread,
+ bool noPolicyScope);
~IncludeScope();
void Quiet() { this->ReportError = false; }
+
private:
cmMakefile* Makefile;
- const char* File;
bool NoPolicyScope;
bool CheckCMP0011;
bool ReportError;
void EnforceCMP0011();
};
-//----------------------------------------------------------------------------
-cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, const char* fname,
- bool noPolicyScope):
- Makefile(mf), File(fname), NoPolicyScope(noPolicyScope),
- CheckCMP0011(false), ReportError(true)
+cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
+ std::string const& filenametoread,
+ bool noPolicyScope)
+ : Makefile(mf)
+ , NoPolicyScope(noPolicyScope)
+ , CheckCMP0011(false)
+ , ReportError(true)
{
- if(!this->NoPolicyScope)
- {
+ this->Makefile->Backtrace = this->Makefile->Backtrace.Push(filenametoread);
+
+ this->Makefile->PushFunctionBlockerBarrier();
+
+ this->Makefile->StateSnapshot =
+ this->Makefile->GetState()->CreateIncludeFileSnapshot(
+ this->Makefile->StateSnapshot, filenametoread);
+ if (!this->NoPolicyScope) {
// Check CMP0011 to determine the policy scope type.
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
- {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011)) {
case cmPolicies::WARN:
// We need to push a scope to detect whether the script sets
// any policies that would affect the includer and therefore
@@ -505,260 +360,216 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, const char* fname,
// We should never make this policy required, but we handle it
// here just in case.
this->CheckCMP0011 = true;
+ CM_FALLTHROUGH;
case cmPolicies::NEW:
// NEW behavior is to push a (strong) scope.
this->Makefile->PushPolicy();
break;
- }
}
-
- // The included file cannot pop our policy scope.
- this->Makefile->PushPolicyBarrier();
+ }
}
-//----------------------------------------------------------------------------
cmMakefile::IncludeScope::~IncludeScope()
{
- // Enforce matching policy scopes inside the included file.
- this->Makefile->PopPolicyBarrier(this->ReportError);
-
- if(!this->NoPolicyScope)
- {
+ if (!this->NoPolicyScope) {
// If we need to enforce policy CMP0011 then the top entry is the
// one we pushed above. If the entry is empty, then the included
// script did not set any policies that might affect the includer so
// we do not need to enforce the policy.
- if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().empty())
- {
+ if (this->CheckCMP0011 &&
+ !this->Makefile->StateSnapshot.HasDefinedPolicyCMP0011()) {
this->CheckCMP0011 = false;
- }
+ }
// Pop the scope we pushed for the script.
this->Makefile->PopPolicy();
// We enforce the policy after the script's policy stack entry has
// been removed.
- if(this->CheckCMP0011)
- {
+ if (this->CheckCMP0011) {
this->EnforceCMP0011();
- }
}
+ }
+ this->Makefile->PopSnapshot(this->ReportError);
+
+ this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
+
+ this->Makefile->Backtrace = this->Makefile->Backtrace.Pop();
}
-//----------------------------------------------------------------------------
void cmMakefile::IncludeScope::EnforceCMP0011()
{
// We check the setting of this policy again because the included
// script might actually set this policy for its includer.
- cmPolicies* policies = this->Makefile->GetPolicies();
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
- {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011)) {
case cmPolicies::WARN:
// Warn because the user did not set this policy.
{
- cmOStringStream w;
- w << policies->GetPolicyWarning(cmPolicies::CMP0011) << "\n"
- << "The included script\n " << this->File << "\n"
- << "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());
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n"
+ << "The included script\n "
+ << this->Makefile->GetExecutionFilePath() << "\n"
+ << "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());
}
break;
case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- {
- cmOStringStream e;
- e << policies->GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
- << "The included script\n " << this->File << "\n"
+ case cmPolicies::REQUIRED_ALWAYS: {
+ std::ostringstream e;
+ /* clang-format off */
+ e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
+ << "The included script\n "
+ << 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());
- }
- break;
+ } break;
case cmPolicies::OLD:
case cmPolicies::NEW:
// The script set this policy. We assume the purpose of the
// script is to initialize policies for its includer, and since
// the policy is now set for later scripts, we do not warn.
break;
- }
+ }
}
-//----------------------------------------------------------------------------
-// Parse the given CMakeLists.txt file executing all commands
-//
-bool cmMakefile::ReadListFile(const char* filename_in,
- const char *external_in,
- std::string* fullPath,
- bool noPolicyScope)
+bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope)
{
- std::string currentParentFile
- = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
- std::string currentFile
- = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
- this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename_in);
- this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
+ this->AddDefinition("CMAKE_PARENT_LIST_FILE",
+ this->GetDefinition("CMAKE_CURRENT_LIST_FILE"));
+ std::string filenametoread = cmSystemTools::CollapseFullPath(
+ filename, this->GetCurrentSourceDirectory());
- const char* external = 0;
- std::string external_abs;
+ IncludeScope incScope(this, filenametoread, noPolicyScope);
- const char* filename = filename_in;
- std::string filename_abs;
+ cmListFile listFile;
+ if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
+ this->Backtrace)) {
+ return false;
+ }
- if (external_in)
- {
- external_abs =
- cmSystemTools::CollapseFullPath(external_in,
- this->cmStartDirectory.c_str());
- external = external_abs.c_str();
- if (filename_in)
- {
- filename_abs =
- cmSystemTools::CollapseFullPath(filename_in,
- this->cmStartDirectory.c_str());
- filename = filename_abs.c_str();
- }
- }
+ this->ReadListFile(listFile, filenametoread);
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ incScope.Quiet();
+ }
+ return true;
+}
- // keep track of the current file being read
- if (filename)
- {
- if(this->cmCurrentListFile != filename)
- {
- this->cmCurrentListFile = filename;
- }
- }
+class cmMakefile::ListFileScope
+{
+public:
+ ListFileScope(cmMakefile* mf, std::string const& filenametoread)
+ : Makefile(mf)
+ , ReportError(true)
+ {
+ this->Makefile->Backtrace = this->Makefile->Backtrace.Push(filenametoread);
- // Now read the input file
- const char *filenametoread= filename;
+ this->Makefile->StateSnapshot =
+ this->Makefile->GetState()->CreateInlineListFileSnapshot(
+ this->Makefile->StateSnapshot, filenametoread);
+ assert(this->Makefile->StateSnapshot.IsValid());
- if( external)
- {
- filenametoread= external;
- }
+ this->Makefile->PushFunctionBlockerBarrier();
+ }
- this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);
- this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
- this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
- cmSystemTools::GetFilenamePath(filenametoread).c_str());
- this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
+ ~ListFileScope()
+ {
+ this->Makefile->PopSnapshot(this->ReportError);
+ this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
+ this->Makefile->Backtrace = this->Makefile->Backtrace.Pop();
+ }
- // try to see if the list file is the top most
- // list file for a project, and if it is, then it
- // must have a project command. If there is not
- // one, then cmake will provide one via the
- // cmListFileCache class.
- bool requireProjectCommand = false;
- if(!external && this->cmStartDirectory == this->cmHomeDirectory)
- {
- if(cmSystemTools::LowerCase(
- cmSystemTools::GetFilenameName(filename)) == "cmakelists.txt")
- {
- requireProjectCommand = true;
- }
- }
+ void Quiet() { this->ReportError = false; }
- // push the listfile onto the stack
- this->ListFileStack.push_back(filenametoread);
- if(fullPath!=0)
- {
- *fullPath=filenametoread;
- }
- cmListFile cacheFile;
- if( !cacheFile.ParseFile(filenametoread, requireProjectCommand, this) )
- {
- // pop the listfile off the stack
- this->ListFileStack.pop_back();
- if(fullPath!=0)
- {
- *fullPath = "";
- }
- this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
- this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
- this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
- this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
- this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
- cmSystemTools::GetFilenamePath(currentFile).c_str());
- this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
+private:
+ cmMakefile* Makefile;
+ bool ReportError;
+};
+
+bool cmMakefile::ReadListFile(const char* filename)
+{
+ std::string filenametoread = cmSystemTools::CollapseFullPath(
+ filename, this->GetCurrentSourceDirectory());
+
+ ListFileScope scope(this, filenametoread);
+
+ cmListFile listFile;
+ if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
+ this->Backtrace)) {
return false;
- }
+ }
+
+ this->ReadListFile(listFile, filenametoread);
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ scope.Quiet();
+ }
+ return true;
+}
+
+void cmMakefile::ReadListFile(cmListFile const& listFile,
+ std::string const& filenametoread)
+{
// add this list file to the list of dependencies
- this->ListFiles.push_back( filenametoread);
+ this->ListFiles.push_back(filenametoread);
- // Enforce balanced blocks (if/endif, function/endfunction, etc.).
- {
- LexicalPushPop lexScope(this);
- IncludeScope incScope(this, filenametoread, noPolicyScope);
+ std::string currentParentFile =
+ 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_DIR",
+ cmSystemTools::GetFilenamePath(filenametoread).c_str());
+
+ this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
+ this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
+ this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
// Run the parsed commands.
- const size_t numberFunctions = cacheFile.Functions.size();
- for(size_t i =0; i < numberFunctions; ++i)
- {
+ const size_t numberFunctions = listFile.Functions.size();
+ for (size_t i = 0; i < numberFunctions; ++i) {
cmExecutionStatus status;
- this->ExecuteCommand(cacheFile.Functions[i],status);
- if(cmSystemTools::GetFatalErrorOccured())
- {
- // Exit early due to error.
- lexScope.Quiet();
- incScope.Quiet();
+ this->ExecuteCommand(listFile.Functions[i], status);
+ if (cmSystemTools::GetFatalErrorOccured()) {
break;
- }
- if(status.GetReturnInvoked())
- {
+ }
+ if (status.GetReturnInvoked()) {
// Exit early due to return command.
break;
- }
}
}
-
- // If this is the directory-level CMakeLists.txt file then perform
- // some extra checks.
- if(this->ListFileStack.size() == 1)
- {
- this->EnforceDirectoryLevelRules();
- }
+ this->CheckForUnusedVariables();
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
- this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
- this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
cmSystemTools::GetFilenamePath(currentFile).c_str());
+ this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
+ this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
-
- // pop the listfile off the stack
- this->ListFileStack.pop_back();
-
- // Check for unused variables
- this->CheckForUnusedVariables();
-
- return true;
}
-//----------------------------------------------------------------------------
-void cmMakefile::EnforceDirectoryLevelRules()
+void cmMakefile::EnforceDirectoryLevelRules() const
{
// Diagnose a violation of CMP0000 if necessary.
- if(this->CheckCMP0000)
- {
- cmOStringStream msg;
+ if (this->CheckCMP0000) {
+ std::ostringstream msg;
msg << "No cmake_minimum_required command is present. "
<< "A line of code such as\n"
- << " cmake_minimum_required(VERSION "
- << cmVersion::GetMajorVersion() << "."
- << cmVersion::GetMinorVersion()
- << ")\n"
+ << " cmake_minimum_required(VERSION " << cmVersion::GetMajorVersion()
+ << "." << cmVersion::GetMinorVersion() << ")\n"
<< "should be added at the top of the file. "
<< "The version specified may be lower if you wish to "
<< "support older CMake versions for this project. "
<< "For more information run "
<< "\"cmake --help-policy CMP0000\".";
- switch (this->GetPolicyStatus(cmPolicies::CMP0000))
- {
+ switch (this->GetPolicyStatus(cmPolicies::CMP0000)) {
case cmPolicies::WARN:
// Warn because the user did not provide a mimimum required
// version.
- this->IssueMessage(cmake::AUTHOR_WARNING, msg.str().c_str());
+ this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
+ msg.str(), this->Backtrace);
case cmPolicies::OLD:
// OLD behavior is to use policy version 2.4 set in
// cmListFileCache.
@@ -767,66 +578,60 @@ void cmMakefile::EnforceDirectoryLevelRules()
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// NEW behavior is to issue an error.
- this->IssueMessage(cmake::FATAL_ERROR, msg.str().c_str());
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str(),
+ this->Backtrace);
cmSystemTools::SetFatalErrorOccured();
return;
- }
}
+ }
}
-void cmMakefile::AddCommand(cmCommand* wg)
+void cmMakefile::AddEvaluationFile(
+ const std::string& inputFile,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> outputName,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent)
{
- this->GetCMakeInstance()->AddCommand(wg);
+ this->EvaluationFiles.push_back(new cmGeneratorExpressionEvaluationFile(
+ inputFile, outputName, condition, inputIsContent));
}
-// Set the make file
-void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg)
+std::vector<cmGeneratorExpressionEvaluationFile*>
+cmMakefile::GetEvaluationFiles() const
{
- this->LocalGenerator = lg;
- // the source groups need to access the global generator
- // so don't create them until the lg is set
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- 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("Header Files", CM_HEADER_REGEX);
- this->AddSourceGroup("CMake Rules", "\\.rule$");
- this->AddSourceGroup("Resources", "\\.plist$");
- this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
-#endif
+ return this->EvaluationFiles;
+}
- this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
- this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
+std::vector<cmExportBuildFileGenerator*>
+cmMakefile::GetExportBuildFileGenerators() const
+{
+ return this->ExportBuildFileGenerators;
}
-bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
- unsigned int minor,
- unsigned int patch)
+void cmMakefile::RemoveExportBuildFileGeneratorCMP0024(
+ cmExportBuildFileGenerator* gen)
{
- if(this->LocalGenerator)
- {
- return
- this->LocalGenerator->NeedBackwardsCompatibility(major, minor, patch);
- }
- else
- {
- return false;
- }
+ std::vector<cmExportBuildFileGenerator*>::iterator it =
+ std::find(this->ExportBuildFileGenerators.begin(),
+ this->ExportBuildFileGenerators.end(), gen);
+ if (it != this->ExportBuildFileGenerators.end()) {
+ this->ExportBuildFileGenerators.erase(it);
+ }
}
+void cmMakefile::AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen)
+{
+ this->ExportBuildFileGenerators.push_back(gen);
+}
-namespace
+namespace {
+struct file_not_persistent
{
- struct file_not_persistent
+ bool operator()(const std::string& path) const
{
- bool operator()(const std::string& path) const
- {
- return !(path.find("CMakeTmp") == path.npos &&
- cmSystemTools::FileExists(path.c_str()));
- }
- };
+ return !(path.find("CMakeTmp") == std::string::npos &&
+ cmSystemTools::FileExists(path.c_str()));
+ }
+};
}
void cmMakefile::FinalPass()
@@ -836,242 +641,256 @@ 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)
- {
+ for (std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
+ i != this->FinalPassCommands.end(); ++i) {
(*i)->FinalPass();
- }
-
- //go through all configured files and see which ones still exist.
- //we don't want cmake to re-run if a configured file is created and deleted
- //during processing as that would make it a transient file that can't
- //influence the build process
-
- //remove_if will move all items that don't have a valid file name to the
- //back of the vector
- std::vector<std::string>::iterator new_output_files_end = std::remove_if(
- this->OutputFiles.begin(),
- this->OutputFiles.end(),
- file_not_persistent() );
- //we just have to erase all items at the back
- this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end() );
+ }
- //if a configured file is used as input for another configured file,
- //and then deleted it will show up in the input list files so we
- //need to scan those too
- std::vector<std::string>::iterator new_list_files_end = std::remove_if(
- this->ListFiles.begin(),
- this->ListFiles.end(),
- file_not_persistent() );
+ // go through all configured files and see which ones still exist.
+ // we don't want cmake to re-run if a configured file is created and deleted
+ // during processing as that would make it a transient file that can't
+ // influence the build process
+ cmEraseIf(this->OutputFiles, file_not_persistent());
- this->ListFiles.erase(new_list_files_end, this->ListFiles.end() );
+ // if a configured file is used as input for another configured file,
+ // and then deleted it will show up in the input list files so we
+ // need to scan those too
+ cmEraseIf(this->ListFiles, file_not_persistent());
}
// Generate the output file
void cmMakefile::ConfigureFinalPass()
{
this->FinalPass();
- const char* oldValue
- = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
- if (oldValue && atof(oldValue) <= 1.2)
- {
- cmSystemTools::Error("You have requested backwards compatibility "
- "with CMake version 1.2 or earlier. This version "
- "of CMake only supports backwards compatibility "
- "with CMake 1.4 or later. For compatibility with "
- "1.2 or earlier please use CMake 2.0");
- }
- for (cmTargets::iterator l = this->Targets.begin();
- l != this->Targets.end(); l++)
- {
- l->second.FinishConfigure();
- }
+ const char* oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
+ if (oldValue &&
+ cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) {
+ this->GetCMakeInstance()->IssueMessage(
+ cmake::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 "
+ "use any CMake 2.8.x release or lower.",
+ this->Backtrace);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmMakefile::AddCustomCommandToTarget(const char* target,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- cmTarget::CustomCommandType type,
- const char* comment,
- const char* workingDir,
- bool escapeOldStyle)
+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)
{
// Find the target to which to add the custom command.
cmTargets::iterator ti = this->Targets.find(target);
- if(ti != this->Targets.end())
- {
- if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream 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;
- }
- // Add the command to the appropriate build step for the target.
- std::vector<std::string> no_output;
- cmCustomCommand cc(this, no_output, depends,
- commandLines, comment, workingDir);
- cc.SetEscapeOldStyle(escapeOldStyle);
- cc.SetEscapeAllowMakeVars(true);
- switch(type)
- {
- case cmTarget::PRE_BUILD:
- ti->second.GetPreBuildCommands().push_back(cc);
- break;
- case cmTarget::PRE_LINK:
- ti->second.GetPreLinkCommands().push_back(cc);
- break;
- case cmTarget::POST_BUILD:
- ti->second.GetPostBuildCommands().push_back(cc);
+
+ if (ti == this->Targets.end()) {
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ bool issueMessage = false;
+ std::ostringstream e;
+ switch (this->GetPolicyStatus(cmPolicies::CMP0040)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0040) << "\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) {
+ if (cmTarget const* t = this->FindTargetToUse(target)) {
+ if (t->IsImported()) {
+ e << "TARGET '" << target
+ << "' is IMPORTED and does not build here.";
+ } else {
+ e << "TARGET '" << target << "' was not created in this directory.";
+ }
+ } else {
+ e << "No TARGET '" << target
+ << "' has been created in this directory.";
}
+ IssueMessage(messageType, e.str());
}
+
+ return;
+ }
+
+ if (objLibraryCommands == RejectObjectLibraryCommands &&
+ ti->second.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;
+ }
+ if (ti->second.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;
+ }
+
+ // 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");
+ }
+ }
+
+ // 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,
+ comment, workingDir);
+ cc.SetEscapeOldStyle(escapeOldStyle);
+ cc.SetEscapeAllowMakeVars(true);
+ cc.SetUsesTerminal(uses_terminal);
+ cc.SetCommandExpandLists(command_expand_lists);
+ cc.SetDepfile(depfile);
+ switch (type) {
+ case cmTarget::PRE_BUILD:
+ ti->second.AddPreBuildCommand(cc);
+ break;
+ case cmTarget::PRE_LINK:
+ ti->second.AddPreLinkCommand(cc);
+ break;
+ case cmTarget::POST_BUILD:
+ ti->second.AddPostBuildCommand(cc);
+ break;
+ }
}
-//----------------------------------------------------------------------------
-cmSourceFile*
-cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
- const std::vector<std::string>& depends,
- const char* main_dependency,
- const cmCustomCommandLines& commandLines,
- const char* comment,
- const char* workingDir,
- bool replace,
- bool escapeOldStyle)
+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 cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile)
{
// Make sure there is at least one output.
- if(outputs.empty())
- {
+ if (outputs.empty()) {
cmSystemTools::Error("Attempt to add a custom rule with no output!");
- return 0;
- }
+ return CM_NULLPTR;
+ }
// Validate custom commands. TODO: More strict?
- for(cmCustomCommandLines::const_iterator i=commandLines.begin();
- i != commandLines.end(); ++i)
- {
+ for (cmCustomCommandLines::const_iterator i = commandLines.begin();
+ i != commandLines.end(); ++i) {
cmCustomCommandLine const& cl = *i;
- if(!cl.empty() && !cl[0].empty() && cl[0][0] == '"')
- {
- cmOStringStream e;
+ 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 0;
- }
+ return CM_NULLPTR;
}
+ }
// Choose a source file on which to store the custom command.
- cmSourceFile* file = 0;
- if(main_dependency && main_dependency[0])
- {
+ cmSourceFile* file = CM_NULLPTR;
+ if (!commandLines.empty() && !main_dependency.empty()) {
// The main dependency was specified. Use it unless a different
// custom command already used it.
file = this->GetSource(main_dependency);
- if(file && file->GetCustomCommand() && !replace)
- {
+ if (file && file->GetCustomCommand() && !replace) {
// The main dependency already has a custom command.
- if(commandLines == file->GetCustomCommand()->GetCommandLines())
- {
+ if (commandLines == file->GetCustomCommand()->GetCommandLines()) {
// The existing custom command is identical. Silently ignore
// the duplicate.
return file;
- }
- else
- {
- // The existing custom command is different. We need to
- // generate a rule file for this new command.
- file = 0;
- }
- }
- else
- {
- // The main dependency does not have a custom command or we are
- // allowed to replace it. Use it to store the command.
- file = this->GetOrCreateSource(main_dependency);
}
+ // The existing custom command is different. We need to
+ // generate a rule file for this new command.
+ file = CM_NULLPTR;
+ } else if (!file) {
+ file = this->CreateSource(main_dependency);
}
+ }
// Generate a rule file if the main dependency is not available.
- if(!file)
- {
- cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
+ if (!file) {
+ cmGlobalGenerator* gg = this->GetGlobalGenerator();
// Construct a rule file associated with the first output produced.
std::string outName = gg->GenerateRuleFile(outputs[0]);
// Check if the rule file already exists.
- file = this->GetSource(outName.c_str());
- if(file && file->GetCustomCommand() && !replace)
- {
+ file = this->GetSource(outName);
+ if (file && file->GetCustomCommand() && !replace) {
// The rule file already exists.
- if(commandLines != file->GetCustomCommand()->GetCommandLines())
- {
+ if (commandLines != file->GetCustomCommand()->GetCommandLines()) {
cmSystemTools::Error("Attempt to add a custom rule to output \"",
outName.c_str(),
"\" which already has a custom rule.");
- }
- return file;
}
+ return file;
+ }
// Create a cmSourceFile for the rule file.
- file = this->GetOrCreateSource(outName.c_str(), true);
- file->SetProperty("__CMAKE_RULE", "1");
+ if (!file) {
+ file = this->CreateSource(outName, true);
}
+ 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->c_str(), true))
- {
+ 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");
- }
}
-
- // Construct a complete list of dependencies.
- std::vector<std::string> depends2(depends);
- if(main_dependency && main_dependency[0])
- {
- depends2.push_back(main_dependency);
+ }
+ 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)
- {
- cmCustomCommand* cc =
- new cmCustomCommand(this, outputs, depends2, commandLines,
- comment, workingDir);
+ if (file) {
+ // Construct a complete list of dependencies.
+ std::vector<std::string> depends2(depends);
+ if (!main_dependency.empty()) {
+ depends2.push_back(main_dependency);
+ }
+
+ cmCustomCommand* cc = new cmCustomCommand(
+ this, outputs, byproducts, depends2, commandLines, comment, workingDir);
cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
+ cc->SetUsesTerminal(uses_terminal);
+ cc->SetCommandExpandLists(command_expand_lists);
+ cc->SetDepfile(depfile);
file->SetCustomCommand(cc);
this->UpdateOutputToSourceMap(outputs, file);
- }
+ }
return file;
}
-//----------------------------------------------------------------------------
-void
-cmMakefile::UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
- cmSourceFile* source)
+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)
- {
+ for (std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o) {
this->UpdateOutputToSourceMap(*o, source);
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmMakefile::UpdateOutputToSourceMap(std::string const& output,
- cmSourceFile* source)
+void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source)
{
OutputToSourceMap::iterator i = this->OutputToSource.find(output);
- if(i != this->OutputToSource.end())
- {
+ 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,
@@ -1081,197 +900,192 @@ cmMakefile::UpdateOutputToSourceMap(std::string const& output,
// triggers it for separate generate.stamp rules in ZERO_CHECK and
// individual targets.
return;
- }
+ }
this->OutputToSource[output] = source;
}
-//----------------------------------------------------------------------------
-cmSourceFile*
-cmMakefile::AddCustomCommandToOutput(const char* output,
- const std::vector<std::string>& depends,
- const char* main_dependency,
- const cmCustomCommandLines& commandLines,
- const char* comment,
- const char* workingDir,
- bool replace,
- bool escapeOldStyle)
+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);
- return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
- commandLines, comment, workingDir,
- replace, escapeOldStyle);
+ 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);
}
-//----------------------------------------------------------------------------
-void
-cmMakefile::AddCustomCommandOldStyle(const char* target,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& depends,
- const char* source,
- const cmCustomCommandLines& commandLines,
- const char* comment)
+void cmMakefile::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)
{
// Translate the old-style signature to one of the new-style
// signatures.
- if(strcmp(source, target) == 0)
- {
+ if (source == target) {
// In the old-style signature if the source and target were the
// same then it added a post-build rule to the target. Preserve
// this behavior.
- this->AddCustomCommandToTarget(target, depends, commandLines,
- cmTarget::POST_BUILD, comment, 0);
+ std::vector<std::string> no_byproducts;
+ this->AddCustomCommandToTarget(target, no_byproducts, depends,
+ commandLines, cmTarget::POST_BUILD, comment,
+ CM_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)
- {
+ 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))
- {
+ 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, 0);
- }
- else
- {
+ commandLines, comment, CM_NULLPTR);
+ } else {
// The source may not be a real file. Do not use a main dependency.
- const char* no_main_dependency = 0;
+ 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, 0);
- }
+ commandLines, comment, CM_NULLPTR);
+ }
// 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"))
- {
- if (this->Targets.find(target) != this->Targets.end())
- {
- this->Targets[target].AddSourceFile(sf);
- }
- else
- {
+ if (sf && !sf->GetPropertyAsBool("__CMAKE_RULE")) {
+ cmTargets::iterator ti = this->Targets.find(target);
+ if (ti != this->Targets.end()) {
+ ti->second.AddSource(sf->GetFullPath());
+ } else {
cmSystemTools::Error("Attempt to add a custom rule to a target "
- "that does not exist yet for target ", target);
+ "that does not exist yet for target ",
+ target.c_str());
return;
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
-void cmMakefile::AddUtilityCommand(const char* 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)
+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)
{
// Construct the command line for the custom command.
cmCustomCommandLine commandLine;
commandLine.push_back(command);
- if(arg1)
- {
+ if (arg1) {
commandLine.push_back(arg1);
- }
- if(arg2)
- {
+ }
+ if (arg2) {
commandLine.push_back(arg2);
- }
- if(arg3)
- {
+ }
+ if (arg3) {
commandLine.push_back(arg3);
- }
- if(arg4)
- {
+ }
+ if (arg4) {
commandLine.push_back(arg4);
- }
+ }
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
// Call the real signature of this method.
- this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
- depends, commandLines);
+ return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
+ depends, commandLines);
}
-//----------------------------------------------------------------------------
-cmTarget*
-cmMakefile::AddUtilityCommand(const char* utilityName,
- bool excludeFromAll,
- const char* workingDirectory,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- bool escapeOldStyle, const char* comment)
+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)
+{
+ std::vector<std::string> no_byproducts;
+ return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
+ no_byproducts, depends, commandLines,
+ escapeOldStyle, comment, uses_terminal,
+ command_expand_lists);
+}
+
+cmTarget* cmMakefile::AddUtilityCommand(
+ const std::string& utilityName, 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)
{
// Create a target instance for this utility.
- cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
- if (excludeFromAll)
- {
+ cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
+ if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
- }
- if(!comment)
- {
+ }
+ if (!comment) {
// Use an empty comment to avoid generation of default comment.
comment = "";
- }
+ }
// Store the custom command in the target.
- std::string force = this->GetStartOutputDirectory();
- force += cmake::GetCMakeFilesDirectory();
- force += "/";
- force += utilityName;
- const char* no_main_dependency = 0;
- bool no_replace = false;
- this->AddCustomCommandToOutput(force.c_str(), depends,
- no_main_dependency,
- commandLines, comment,
- workingDirectory, no_replace,
- escapeOldStyle);
- cmSourceFile* sf = target->AddSource(force.c_str());
-
- // 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());
+ 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());
+ }
+
+ // 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)
{
- if (!flag)
- {
+ if (!flag) {
return;
- }
+ }
// 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))
- {
+ if (this->ParseDefineFlag(flag, false)) {
return;
- }
+ }
// Add this flag that does not look like a definition.
this->AddDefineFlag(flag, this->DefineFlags);
@@ -1280,67 +1094,48 @@ void cmMakefile::AddDefineFlag(const char* flag)
void cmMakefile::AddDefineFlag(const char* flag, std::string& dflags)
{
// remove any \n\r
- std::string ret = flag;
- std::string::size_type pos = 0;
- while((pos = ret.find('\n', pos)) != std::string::npos)
- {
- ret[pos] = ' ';
- pos++;
- }
- pos = 0;
- while((pos = ret.find('\r', pos)) != std::string::npos)
- {
- ret[pos] = ' ';
- pos++;
- }
-
- dflags += " ";
- dflags += ret;
+ std::string::size_type initSize = dflags.size();
+ dflags += std::string(" ") + 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)
{
// Check the length of the flag to remove.
std::string::size_type len = strlen(flag);
- if(len < 1)
- {
+ if (len < 1) {
return;
- }
+ }
// Update the string used for the old DEFINITIONS property.
this->RemoveDefineFlag(flag, len, this->DefineFlagsOrig);
// If this is really a definition, update COMPILE_DEFINITIONS.
- if(this->ParseDefineFlag(flag, true))
- {
+ if (this->ParseDefineFlag(flag, true)) {
return;
- }
+ }
// Remove this flag that does not look like a definition.
this->RemoveDefineFlag(flag, len, this->DefineFlags);
}
-void cmMakefile::RemoveDefineFlag(const char* flag,
- std::string::size_type len,
+void cmMakefile::RemoveDefineFlag(const char* flag, std::string::size_type len,
std::string& dflags)
{
// 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);
- lpos != std::string::npos; lpos = dflags.find(flag, lpos))
- {
+ for (std::string::size_type lpos = dflags.find(flag, 0);
+ lpos != std::string::npos; lpos = dflags.find(flag, lpos)) {
std::string::size_type rpos = lpos + len;
- if((lpos <= 0 || isspace(dflags[lpos-1])) &&
- (rpos >= dflags.size() || isspace(dflags[rpos])))
- {
+ if ((lpos <= 0 || isspace(dflags[lpos - 1])) &&
+ (rpos >= dflags.size() || isspace(dflags[rpos]))) {
dflags.erase(lpos, len);
- }
- else
- {
+ } else {
++lpos;
- }
}
+ }
}
void cmMakefile::AddCompileOption(const char* option)
@@ -1351,37 +1146,23 @@ void cmMakefile::AddCompileOption(const char* option)
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
{
// Create a regular expression to match valid definitions.
- static cmsys::RegularExpression
- valid("^[-/]D[A-Za-z_][A-Za-z0-9_]*(=.*)?$");
+ static cmsys::RegularExpression valid("^[-/]D[A-Za-z_][A-Za-z0-9_]*(=.*)?$");
// Make sure the definition matches.
- if(!valid.find(def.c_str()))
- {
- return false;
- }
-
- // VS6 IDE does not support definition values with spaces in
- // combination with '"', '$', or ';'.
- if((strcmp(this->LocalGenerator->GetGlobalGenerator()->GetName(),
- "Visual Studio 6") == 0) &&
- (def.find(" ") != def.npos && def.find_first_of("\"$;") != def.npos))
- {
+ if (!valid.find(def.c_str())) {
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()))
- {
+ static cmsys::RegularExpression trivial(
+ "^[-/]D[A-Za-z_][A-Za-z0-9_]*(=[A-Za-z0-9_.]+)?$");
+ if (!trivial.find(def.c_str())) {
// This definition has a non-trivial value.
- switch(this->GetPolicyStatus(cmPolicies::CMP0005))
- {
+ switch (this->GetPolicyStatus(cmPolicies::CMP0005)) {
case cmPolicies::WARN:
- this->IssueMessage(
- cmake::AUTHOR_WARNING,
- this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0005)
- );
+ this->IssueMessage(cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0005));
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to not escape the value. We should not
// convert the definition to use the property.
@@ -1390,1174 +1171,1254 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
case cmPolicies::REQUIRED_ALWAYS:
this->IssueMessage(
cmake::FATAL_ERROR,
- this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0005)
- );
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0005));
return false;
case cmPolicies::NEW:
// NEW behavior is to escape the value. Proceed to convert it
// to an entry in the property.
break;
- }
}
+ }
// Get the definition part after the flag.
const char* define = def.c_str() + 2;
- if(remove)
- {
- if(const char* cdefs = this->GetProperty("COMPILE_DEFINITIONS"))
- {
+ if (remove) {
+ if (const char* cdefs = this->GetProperty("COMPILE_DEFINITIONS")) {
// Expand the list.
std::vector<std::string> defs;
cmSystemTools::ExpandListArgument(cdefs, defs);
// Recompose the list without the definition.
- std::string ndefs;
- const char* sep = "";
- for(std::vector<std::string>::const_iterator di = defs.begin();
- di != defs.end(); ++di)
- {
- if(*di != define)
- {
- ndefs += sep;
- sep = ";";
- ndefs += *di;
- }
- }
+ std::vector<std::string>::const_iterator defEnd =
+ std::remove(defs.begin(), defs.end(), define);
+ std::vector<std::string>::const_iterator defBegin = defs.begin();
+ std::string ndefs = cmJoin(cmMakeRange(defBegin, defEnd), ";");
// Store the new list.
this->SetProperty("COMPILE_DEFINITIONS", ndefs.c_str());
- }
}
- else
- {
+ } else {
// Append the definition to the directory property.
this->AppendProperty("COMPILE_DEFINITIONS", define);
- }
+ }
return true;
}
-void cmMakefile::AddLinkLibrary(const char* lib,
- cmTarget::LinkLibraryType llt)
+void cmMakefile::InitializeFromParent(cmMakefile* parent)
{
- cmTarget::LibraryID tmp;
- tmp.first = lib;
- tmp.second = llt;
- this->LinkLibraries.push_back(tmp);
+ this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
+
+ // define flags
+ this->DefineFlags = parent->DefineFlags;
+ this->DefineFlagsOrig = parent->DefineFlagsOrig;
+
+ // Include transform property. There is no per-config version.
+ {
+ const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM";
+ this->SetProperty(prop, parent->GetProperty(prop));
+ }
+
+ // compile definitions property and per-config versions
+ cmPolicies::PolicyStatus polSt = this->GetPolicyStatus(cmPolicies::CMP0043);
+ if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
+ this->SetProperty("COMPILE_DEFINITIONS",
+ 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);
+ const char* prop = parent->GetProperty(defPropName);
+ this->SetProperty(defPropName, prop);
+ }
+ }
+
+ // 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());
+
+ // Copy include regular expressions.
+ this->ComplainFileRegularExpression = parent->ComplainFileRegularExpression;
+
+ // Imported targets.
+ this->ImportedTargets = parent->ImportedTargets;
}
-void cmMakefile::AddLinkLibraryForTarget(const char *target,
- const char* lib,
- cmTarget::LinkLibraryType llt)
+void cmMakefile::PushFunctionScope(std::string const& fileName,
+ const cmPolicies::PolicyMap& pm)
{
- cmTargets::iterator i = this->Targets.find(target);
- if ( i != this->Targets.end())
- {
- cmTarget* tgt =
- this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(0,lib);
- if(tgt)
- {
- // CMake versions below 2.4 allowed linking to modules.
- bool allowModules = this->NeedBackwardsCompatibility(2,2);
- // if it is not a static or shared library then you can not link to it
- if(!((tgt->GetType() == cmTarget::STATIC_LIBRARY) ||
- (tgt->GetType() == cmTarget::SHARED_LIBRARY) ||
- tgt->IsExecutableWithExports()))
- {
- cmOStringStream e;
- e << "Target \"" << lib << "\" of type "
- << cmTarget::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.";
- // in older versions of cmake linking to modules was allowed
- if( tgt->GetType() == cmTarget::MODULE_LIBRARY )
- {
- e << "\n"
- << "If you are developing a new project, re-organize it to avoid "
- << "linking to modules. "
- << "If you are just trying to build an existing project, "
- << "set CMAKE_BACKWARDS_COMPATIBILITY to 2.2 or lower to allow "
- << "linking to modules.";
- }
- // if no modules are allowed then this is always an error
- if(!allowModules ||
- // if we allow modules but the type is not a module then it is
- // still an error
- (allowModules && tgt->GetType() != cmTarget::MODULE_LIBRARY))
- {
- this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- }
- }
- }
- i->second.AddLinkLibrary( *this, target, lib, llt );
- }
- else
- {
- cmOStringStream e;
- e << "Attempt to add link library \""
- << lib << "\" to target \""
- << target << "\" which is not built in this directory.";
- this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- }
+ this->StateSnapshot = this->GetState()->CreateFunctionCallSnapshot(
+ this->StateSnapshot, fileName);
+ assert(this->StateSnapshot.IsValid());
+
+ this->PushLoopBlockBarrier();
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope();
+#endif
+
+ this->PushFunctionBlockerBarrier();
+
+ this->PushPolicy(true, pm);
}
-void cmMakefile::AddLinkDirectoryForTarget(const char *target,
- const char* d)
+void cmMakefile::PopFunctionScope(bool reportError)
{
- cmTargets::iterator i = this->Targets.find(target);
- if ( i != this->Targets.end())
- {
- if(this->IsAlias(target))
- {
- cmOStringStream e;
- e << "ALIAS target \"" << target << "\" "
- << "may not be linked into another target.";
- this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- return;
- }
- i->second.AddLinkDirectory( d );
- }
- else
- {
- cmSystemTools::Error
- ("Attempt to add link directories to non-existent target: ",
- target, " for directory ", d);
- }
+ this->PopPolicy();
+
+ this->PopSnapshot(reportError);
+
+ this->PopFunctionBlockerBarrier(reportError);
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope();
+#endif
+
+ this->PopLoopBlockBarrier();
+
+ this->CheckForUnusedVariables();
}
-void cmMakefile::AddLinkLibrary(const char* lib)
+void cmMakefile::PushMacroScope(std::string const& fileName,
+ const cmPolicies::PolicyMap& pm)
{
- this->AddLinkLibrary(lib,cmTarget::GENERAL);
+ this->StateSnapshot =
+ this->GetState()->CreateMacroCallSnapshot(this->StateSnapshot, fileName);
+ assert(this->StateSnapshot.IsValid());
+
+ this->PushFunctionBlockerBarrier();
+
+ this->PushPolicy(true, pm);
}
-void cmMakefile::AddLinkDirectory(const char* dir)
+void cmMakefile::PopMacroScope(bool reportError)
{
- // Don't add a link directory that is already present. Yes, this
- // linear search results in n^2 behavior, but n won't be getting
- // much bigger than 20. We cannot use a set because of order
- // dependency of the link search path.
+ this->PopPolicy();
+ this->PopSnapshot(reportError);
- if(!dir)
- {
- return;
- }
- // remove trailing slashes
- if(dir[strlen(dir)-1] == '/')
- {
- std::string newdir = dir;
- newdir = newdir.substr(0, newdir.size()-1);
- if(std::find(this->LinkDirectories.begin(),
- this->LinkDirectories.end(),
- newdir.c_str()) == this->LinkDirectories.end())
- {
- this->LinkDirectories.push_back(newdir);
- }
- }
- else
- {
- if(std::find(this->LinkDirectories.begin(),
- this->LinkDirectories.end(), dir)
- == this->LinkDirectories.end())
- {
- this->LinkDirectories.push_back(dir);
- }
- }
+ this->PopFunctionBlockerBarrier(reportError);
}
-void cmMakefile::InitializeFromParent()
+bool cmMakefile::IsRootMakefile() const
{
- cmMakefile *parent = this->LocalGenerator->GetParent()->GetMakefile();
+ return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid();
+}
- // Initialize definitions with the closure of the parent scope.
- this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure();
+class cmMakefile::BuildsystemFileScope
+{
+public:
+ BuildsystemFileScope(cmMakefile* mf)
+ : Makefile(mf)
+ , ReportError(true)
+ {
+ std::string currentStart =
+ this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource();
+ currentStart += "/CMakeLists.txt";
+ this->Makefile->StateSnapshot.SetListFile(currentStart);
+ this->Makefile->StateSnapshot =
+ this->Makefile->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
+ this->Makefile->StateSnapshot);
+ this->Makefile->PushFunctionBlockerBarrier();
+
+ this->GG = mf->GetGlobalGenerator();
+ this->CurrentMakefile = this->GG->GetCurrentMakefile();
+ this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot();
+ this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot);
+ this->GG->SetCurrentMakefile(mf);
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->GG->GetFileLockPool().PushFileScope();
+#endif
+ }
- const std::vector<cmValueWithOrigin> parentIncludes =
- parent->GetIncludeDirectoriesEntries();
- this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(),
- parentIncludes.begin(),
- parentIncludes.end());
+ ~BuildsystemFileScope()
+ {
+ this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
+ this->Makefile->PopSnapshot(this->ReportError);
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->GG->GetFileLockPool().PopFileScope();
+#endif
+ this->GG->SetCurrentMakefile(this->CurrentMakefile);
+ this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot);
+ }
- const std::vector<cmValueWithOrigin> parentOptions =
- parent->GetCompileOptionsEntries();
- this->CompileOptionsEntries.insert(this->CompileOptionsEntries.end(),
- parentOptions.begin(),
- parentOptions.end());
+ void Quiet() { this->ReportError = false; }
- const std::vector<cmValueWithOrigin> parentDefines =
- parent->GetCompileDefinitionsEntries();
- this->CompileDefinitionsEntries.insert(this->CompileDefinitionsEntries.end(),
- parentDefines.begin(),
- parentDefines.end());
+private:
+ cmMakefile* Makefile;
+ cmGlobalGenerator* GG;
+ cmMakefile* CurrentMakefile;
+ cmStateSnapshot Snapshot;
+ bool ReportError;
+};
- this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
+void cmMakefile::Configure()
+{
+ std::string currentStart =
+ this->StateSnapshot.GetDirectory().GetCurrentSource();
+ currentStart += "/CMakeLists.txt";
- // define flags
- this->DefineFlags = parent->DefineFlags;
- this->DefineFlagsOrig = parent->DefineFlagsOrig;
+ // Add the bottom of all backtraces within this directory.
+ // We will never pop this scope because it should be available
+ // for messages during the generate step too.
+ this->Backtrace = this->Backtrace.Push(currentStart);
- // Include transform property. There is no per-config version.
- {
- const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM";
- this->SetProperty(prop, parent->GetProperty(prop));
+ 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());
+
+ assert(cmSystemTools::FileExists(currentStart.c_str(), true));
+ this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str());
+
+ cmListFile listFile;
+ if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(),
+ this->Backtrace)) {
+ return;
}
+ 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") {
+ hasVersion = true;
+ break;
+ }
+ }
+ // if no policy command is found this is an error if they use any
+ // non advanced functions or a lot of functions
+ if (!hasVersion) {
+ bool isProblem = true;
+ if (listFile.Functions.size() < 30) {
+ // the list of simple commands DO NOT ADD TO THIS LIST!!!!!
+ // these commands must have backwards compatibility forever and
+ // and that is a lot longer than your tiny mind can comprehend mortal
+ std::set<std::string> allowedCommands;
+ allowedCommands.insert("project");
+ allowedCommands.insert("set");
+ allowedCommands.insert("if");
+ allowedCommands.insert("endif");
+ allowedCommands.insert("else");
+ allowedCommands.insert("elseif");
+ allowedCommands.insert("add_executable");
+ allowedCommands.insert("add_library");
+ allowedCommands.insert("target_link_libraries");
+ 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()) {
+ isProblem = true;
+ break;
+ }
+ }
+ }
- // compile definitions property and per-config versions
- {
- this->SetProperty("COMPILE_DEFINITIONS",
- 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);
- this->SetProperty(defPropName.c_str(),
- parent->GetProperty(defPropName.c_str()));
+ if (isProblem) {
+ // Tell the top level cmMakefile to diagnose
+ // this violation of CMP0000.
+ this->SetCheckCMP0000(true);
+
+ // Implicitly set the version for the user.
+ this->SetPolicyVersion("2.4");
+ }
+ }
+ 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") {
+ hasProject = true;
+ break;
+ }
+ }
+ // if no project command is found, add one
+ if (!hasProject) {
+ cmListFileFunction project;
+ project.Name = "PROJECT";
+ cmListFileArgument prj("Project", cmListFileArgument::Unquoted, 0);
+ project.Arguments.push_back(prj);
+ listFile.Functions.insert(listFile.Functions.begin(), project);
}
}
- // link libraries
- this->LinkLibraries = parent->LinkLibraries;
-
- // link directories
- this->LinkDirectories = parent->LinkDirectories;
+ this->ReadListFile(listFile, currentStart);
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ scope.Quiet();
+ }
- // the initial project name
- this->ProjectName = parent->ProjectName;
+ // at the end handle any old style subdirs
+ std::vector<cmMakefile*> subdirs = this->UnConfiguredDirectories;
- // Copy include regular expressions.
- this->IncludeFileRegularExpression = parent->IncludeFileRegularExpression;
- this->ComplainFileRegularExpression = parent->ComplainFileRegularExpression;
+ // for each subdir recurse
+ std::vector<cmMakefile*>::iterator sdi = subdirs.begin();
+ for (; sdi != subdirs.end(); ++sdi) {
+ (*sdi)->StateSnapshot.InitializeFromParent_ForSubdirsCommand();
+ this->ConfigureSubDirectory(*sdi);
+ }
- // Imported targets.
- this->ImportedTargets = parent->ImportedTargets;
+ this->AddCMakeDependFilesFromUser();
}
-void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2)
+void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
{
- // copy our variables from the child makefile
- lg2->GetMakefile()->InitializeFromParent();
- lg2->GetMakefile()->MakeStartDirectoriesCurrent();
- if (this->GetCMakeInstance()->GetDebugOutput())
- {
- std::string msg=" Entering ";
- msg += lg2->GetMakefile()->GetCurrentDirectory();
+ 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 const currentStartFile = currentStart + "/CMakeLists.txt";
+ if (!cmSystemTools::FileExists(currentStartFile, true)) {
+ // The file is missing. Check policy CMP0014.
+ std::ostringstream e;
+ /* clang-format off */
+ e << "The source directory\n"
+ << " " << currentStart << "\n"
+ << "does not contain a CMakeLists.txt file.";
+ /* clang-format on */
+ switch (this->GetPolicyStatus(cmPolicies::CMP0014)) {
+ case cmPolicies::WARN:
+ // Print the warning.
+ /* clang-format off */
+ e << "\n"
+ << "CMake does not support this case but it used "
+ << "to work accidentally and is being allowed for "
+ << "compatibility."
+ << "\n"
+ << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014);
+ /* clang-format on */
+ this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ case cmPolicies::OLD:
+ // OLD behavior does not warn.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014);
+ CM_FALLTHROUGH;
+ case cmPolicies::NEW:
+ // NEW behavior prints the error.
+ this->IssueMessage(cmake::FATAL_ERROR, e.str());
}
+ return;
+ }
// finally configure the subdir
- lg2->Configure();
- if (this->GetCMakeInstance()->GetDebugOutput())
- {
- std::string msg=" Returning to ";
- msg += this->GetCurrentDirectory();
+ mf->Configure();
+
+ if (this->GetCMakeInstance()->GetDebugOutput()) {
+ std::string msg = " Returning to ";
+ msg += this->GetCurrentSourceDirectory();
cmSystemTools::Message(msg.c_str());
- }
+ }
}
-void cmMakefile::AddSubDirectory(const char* sub,
- bool excludeFromAll, bool preorder)
+void cmMakefile::AddSubDirectory(const std::string& srcPath,
+ const std::string& binPath,
+ bool excludeFromAll, bool immediate)
{
- // the source path must be made full if it isn't already
- std::string srcPath = sub;
- if (!cmSystemTools::FileIsFullPath(srcPath.c_str()))
- {
- srcPath = this->GetCurrentDirectory();
- srcPath += "/";
- srcPath += sub;
- }
+ // Make sure the binary directory is unique.
+ if (!this->EnforceUniqueDir(srcPath, binPath)) {
+ return;
+ }
- // binary path must be made full if it isn't already
- std::string binPath = sub;
- if (!cmSystemTools::FileIsFullPath(binPath.c_str()))
- {
- binPath = this->GetCurrentOutputDirectory();
- binPath += "/";
- binPath += sub;
- }
+ cmStateSnapshot newSnapshot =
+ this->GetState()->CreateBuildsystemDirectorySnapshot(this->StateSnapshot);
+ newSnapshot.GetDirectory().SetCurrentSource(srcPath);
+ newSnapshot.GetDirectory().SetCurrentBinary(binPath);
- this->AddSubDirectory(srcPath.c_str(), binPath.c_str(),
- excludeFromAll, preorder, false);
-}
+ cmSystemTools::MakeDirectory(binPath.c_str());
+
+ cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
+ this->GetGlobalGenerator()->AddMakefile(subMf);
+ if (excludeFromAll) {
+ subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
+ }
-void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
- bool excludeFromAll, bool preorder,
- bool immediate)
+ if (immediate) {
+ this->ConfigureSubDirectory(subMf);
+ } else {
+ this->UnConfiguredDirectories.push_back(subMf);
+ }
+}
+
+const char* cmMakefile::GetCurrentSourceDirectory() const
{
- // Make sure the binary directory is unique.
- if(!this->EnforceUniqueDir(srcPath, binPath))
- {
- return;
- }
+ return this->StateSnapshot.GetDirectory().GetCurrentSource();
+}
- // create a new local generator and set its parent
- cmLocalGenerator *lg2 =
- this->LocalGenerator->GetGlobalGenerator()->CreateLocalGenerator();
- lg2->SetParent(this->LocalGenerator);
- this->LocalGenerator->GetGlobalGenerator()->AddLocalGenerator(lg2);
-
- // set the subdirs start dirs
- lg2->GetMakefile()->SetStartDirectory(srcPath);
- lg2->GetMakefile()->SetStartOutputDirectory(binPath);
- if(excludeFromAll)
- {
- lg2->GetMakefile()->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
- }
- lg2->GetMakefile()->SetPreOrder(preorder);
+const char* cmMakefile::GetCurrentBinaryDirectory() const
+{
+ return this->StateSnapshot.GetDirectory().GetCurrentBinary();
+}
- if (immediate)
- {
- this->ConfigureSubDirectory(lg2);
- }
+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);
+ }
+ return tgts;
}
-//----------------------------------------------------------------------------
-void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs,
+void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs,
bool before)
{
- if (incs.empty())
- {
+ if (incs.empty()) {
return;
- }
-
- std::string incString;
- std::string sep;
-
- for(std::vector<std::string>::const_iterator li = incs.begin();
- li != incs.end(); ++li)
- {
- incString += sep + *li;
- sep = ";";
- }
-
- std::vector<cmValueWithOrigin>::iterator position =
- before ? this->IncludeDirectoriesEntries.begin()
- : this->IncludeDirectoriesEntries.end();
+ }
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- cmValueWithOrigin entry(incString, lfbt);
- this->IncludeDirectoriesEntries.insert(position, entry);
+ cmListFileBacktrace lfbt = this->GetBacktrace();
+ std::string entryString = cmJoin(incs, ";");
+ if (before) {
+ this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry(
+ entryString, lfbt);
+ } else {
+ this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry(
+ entryString, lfbt);
+ }
// Property on each target:
- for (cmTargets::iterator l = this->Targets.begin();
- l != this->Targets.end(); ++l)
- {
- cmTarget &t = l->second;
- t.InsertInclude(entry, before);
- }
+ for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end();
+ ++l) {
+ cmTarget& t = l->second;
+ t.InsertInclude(entryString, lfbt, before);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
+void cmMakefile::AddSystemIncludeDirectories(const std::set<std::string>& incs)
{
- for(std::set<cmStdString>::const_iterator li = incs.begin();
- li != incs.end(); ++li)
- {
- this->SystemIncludeDirectories.insert(*li);
- }
+ if (incs.empty()) {
+ return;
+ }
- for (cmTargets::iterator l = this->Targets.begin();
- l != this->Targets.end(); ++l)
- {
- cmTarget &t = l->second;
+ this->SystemIncludeDirectories.insert(incs.begin(), incs.end());
+
+ for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end();
+ ++l) {
+ cmTarget& t = l->second;
t.AddSystemIncludeDirectories(incs);
- }
+ }
}
-void cmMakefile::AddDefinition(const char* name, const char* value)
+void cmMakefile::AddDefinition(const std::string& name, const char* value)
{
- if (!value )
- {
+ if (!value) {
return;
- }
-
-#ifdef CMAKE_STRICT
- if (this->GetCMakeInstance())
- {
- this->GetCMakeInstance()->
- RecordPropertyAccess(name,cmProperty::VARIABLE);
- }
-#endif
+ }
- this->Internal->VarStack.top().Set(name, value);
- if (this->Internal->VarUsageStack.size() &&
- this->VariableInitialized(name))
- {
- this->CheckForUnused("changing definition", name);
- this->Internal->VarUsageStack.top().erase(name);
- }
- this->Internal->VarInitStack.top().insert(name);
+ if (this->VariableInitialized(name)) {
+ this->LogUnused("changing definition", name);
+ }
+ this->StateSnapshot.SetDefinition(name, value);
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch();
- if ( vv )
- {
- vv->VariableAccessed(name,
- cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
- value,
- this);
- }
+ if (vv) {
+ vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
+ value, this);
+ }
#endif
}
-
-void cmMakefile::AddCacheDefinition(const char* name, const char* value,
+void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
const char* doc,
- cmCacheManager::CacheEntryType type,
+ cmStateEnums::CacheEntryType type,
bool force)
{
- const char* val = value;
- cmCacheManager::CacheIterator it =
- this->GetCacheManager()->GetCacheIterator(name);
- if(!it.IsAtEnd() && (it.GetType() == cmCacheManager::UNINITIALIZED) &&
- it.Initialized())
- {
+ const char* 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 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)
- {
- val = it.GetValue();
- }
- if ( type == cmCacheManager::PATH || type == cmCacheManager::FILEPATH )
- {
+ if (!force) {
+ value = existingValue;
+ }
+ if (type == cmStateEnums::PATH || type == cmStateEnums::FILEPATH) {
std::vector<std::string>::size_type cc;
std::vector<std::string> files;
- std::string nvalue = "";
- cmSystemTools::ExpandListArgument(val, files);
- for ( cc = 0; cc < files.size(); cc ++ )
- {
- if(!cmSystemTools::IsOff(files[cc].c_str()))
- {
- files[cc] = cmSystemTools::CollapseFullPath(files[cc].c_str());
- }
- if ( cc > 0 )
- {
+ nvalue = value ? value : "";
+
+ cmSystemTools::ExpandListArgument(nvalue, files);
+ nvalue = "";
+ for (cc = 0; cc < files.size(); cc++) {
+ if (!cmSystemTools::IsOff(files[cc].c_str())) {
+ files[cc] = cmSystemTools::CollapseFullPath(files[cc]);
+ }
+ if (cc > 0) {
nvalue += ";";
- }
- nvalue += files[cc];
}
-
- this->GetCacheManager()->AddCacheEntry(name, nvalue.c_str(), doc, type);
- val = it.GetValue();
+ nvalue += files[cc];
}
+ this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type);
+ nvalue = this->GetState()->GetInitializedCacheValue(name);
+ value = nvalue.c_str();
}
- this->GetCacheManager()->AddCacheEntry(name, val, doc, type);
+ }
+ this->GetCMakeInstance()->AddCacheEntry(name, value, doc, type);
// if there was a definition then remove it
- this->Internal->VarStack.top().Set(name, 0);
+ this->StateSnapshot.RemoveDefinition(name);
}
-
-void cmMakefile::AddDefinition(const char* name, bool value)
+void cmMakefile::AddDefinition(const std::string& name, bool value)
{
- this->Internal->VarStack.top().Set(name, value? "ON" : "OFF");
- if (this->Internal->VarUsageStack.size() &&
- this->VariableInitialized(name))
- {
- this->CheckForUnused("changing definition", name);
- this->Internal->VarUsageStack.top().erase(name);
- }
- this->Internal->VarInitStack.top().insert(name);
+ 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 )
- {
+ if (vv) {
vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
- value?"ON":"OFF", this);
- }
+ value ? "ON" : "OFF", this);
+ }
#endif
}
void cmMakefile::CheckForUnusedVariables() const
{
- if (!this->WarnUnused)
- {
+ if (!this->WarnUnused) {
return;
- }
- const cmDefinitions& defs = this->Internal->VarStack.top();
- const std::set<cmStdString>& locals = defs.LocalKeys();
- std::set<cmStdString>::const_iterator it = locals.begin();
- for (; it != locals.end(); ++it)
- {
- this->CheckForUnused("out of scope", it->c_str());
- }
+ }
+ 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);
+ }
}
-void cmMakefile::MarkVariableAsUsed(const char* var)
+void cmMakefile::MarkVariableAsUsed(const std::string& var)
{
- this->Internal->VarUsageStack.top().insert(var);
+ this->StateSnapshot.GetDefinition(var);
}
-bool cmMakefile::VariableInitialized(const char* var) const
+bool cmMakefile::VariableInitialized(const std::string& var) const
{
- if(this->Internal->VarInitStack.top().find(var) !=
- this->Internal->VarInitStack.top().end())
- {
- return true;
- }
- return false;
+ return this->StateSnapshot.IsInitialized(var);
}
-bool cmMakefile::VariableUsed(const char* var) const
+void cmMakefile::LogUnused(const char* reason, const std::string& name) const
{
- if(this->Internal->VarUsageStack.top().find(var) !=
- this->Internal->VarUsageStack.top().end())
- {
- return true;
+ if (this->WarnUnused) {
+ std::string path;
+ if (!this->ExecutionStatusStack.empty()) {
+ path = this->GetExecutionContext().FilePath;
+ } else {
+ path = this->GetCurrentSourceDirectory();
+ path += "/CMakeLists.txt";
}
- return false;
-}
-void cmMakefile::CheckForUnused(const char* reason, const char* name) const
-{
- if (this->WarnUnused && !this->VariableUsed(name))
- {
- cmStdString path;
- cmListFileBacktrace bt;
- if (this->CallStack.size())
- {
- const cmListFileContext* file = this->CallStack.back().Context;
- bt.push_back(*file);
- path = file->FilePath.c_str();
- }
- else
- {
- path = this->GetStartDirectory();
- path += "/CMakeLists.txt";
- cmListFileContext lfc;
- lfc.FilePath = path;
- lfc.Line = 0;
- bt.push_back(lfc);
- }
if (this->CheckSystemVars ||
- cmSystemTools::IsSubDirectory(path.c_str(),
- this->GetHomeDirectory()) ||
- (cmSystemTools::IsSubDirectory(path.c_str(),
- this->GetHomeOutputDirectory()) &&
- !cmSystemTools::IsSubDirectory(path.c_str(),
- cmake::GetCMakeFilesDirectory())))
- {
- cmOStringStream msg;
+ cmSystemTools::IsSubDirectory(path, this->GetHomeDirectory()) ||
+ (cmSystemTools::IsSubDirectory(path, this->GetHomeOutputDirectory()) &&
+ !cmSystemTools::IsSubDirectory(path,
+ cmake::GetCMakeFilesDirectory()))) {
+ std::ostringstream msg;
msg << "unused variable (" << reason << ") \'" << name << "\'";
- this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
- msg.str().c_str(),
- bt);
- }
+ this->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
}
+ }
}
-void cmMakefile::RemoveDefinition(const char* name)
+void cmMakefile::RemoveDefinition(const std::string& name)
{
- this->Internal->VarStack.top().Set(name, 0);
- if (this->Internal->VarUsageStack.size() &&
- this->VariableInitialized(name))
- {
- this->CheckForUnused("unsetting", name);
- this->Internal->VarUsageStack.top().erase(name);
- }
- this->Internal->VarInitStack.top().insert(name);
+ if (this->VariableInitialized(name)) {
+ this->LogUnused("unsetting", name);
+ }
+ this->StateSnapshot.RemoveDefinition(name);
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch();
- if ( vv )
- {
+ if (vv) {
vv->VariableAccessed(name, cmVariableWatch::VARIABLE_REMOVED_ACCESS,
- 0, this);
- }
+ CM_NULLPTR, this);
+ }
#endif
}
-void cmMakefile::RemoveCacheDefinition(const char* name)
+void cmMakefile::RemoveCacheDefinition(const std::string& name)
{
- this->GetCacheManager()->RemoveCacheEntry(name);
+ this->GetState()->RemoveCacheEntry(name);
}
-void cmMakefile::SetProjectName(const char* p)
+void cmMakefile::SetProjectName(std::string const& p)
{
- this->ProjectName = p;
+ this->StateSnapshot.SetProjectName(p);
}
-
-void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
+void cmMakefile::AddGlobalLinkInformation(cmTarget& target)
{
// for these targets do not add anything
- switch(target.GetType())
- {
- case cmTarget::UTILITY:
- case cmTarget::GLOBAL_TARGET:
+ switch (target.GetType()) {
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::INTERFACE_LIBRARY:
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);
}
- std::vector<std::string>::iterator j;
- for(j = this->LinkDirectories.begin();
- j != this->LinkDirectories.end(); ++j)
- {
- target.AddLinkDirectory(j->c_str());
+ }
+
+ if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
+ std::vector<std::string> linkLibs;
+ cmSystemTools::ExpandListArgument(linkLibsProp, linkLibs);
+
+ for (std::vector<std::string>::iterator j = linkLibs.begin();
+ j != linkLibs.end(); ++j) {
+ std::string libraryName = *j;
+ cmTargetLinkLibraryType libType = GENERAL_LibraryType;
+ if (libraryName == "optimized") {
+ libType = OPTIMIZED_LibraryType;
+ ++j;
+ libraryName = *j;
+ } else if (libraryName == "debug") {
+ libType = DEBUG_LibraryType;
+ ++j;
+ libraryName = *j;
+ }
+ // This is equivalent to the target_link_libraries plain signature.
+ target.AddLinkLibrary(*this, libraryName, libType);
+ target.AppendProperty(
+ "INTERFACE_LINK_LIBRARIES",
+ target.GetDebugGeneratorExpressions(libraryName, libType).c_str());
}
- target.MergeLinkLibraries( *this, name, this->LinkLibraries );
+ }
}
-
-void cmMakefile::AddAlias(const char* lname, cmTarget *tgt)
+void cmMakefile::AddAlias(const std::string& lname, std::string const& tgtName)
{
- this->AliasTargets[lname] = tgt;
- this->LocalGenerator->GetGlobalGenerator()->AddAlias(lname, tgt);
+ this->AliasTargets[lname] = tgtName;
+ this->GetGlobalGenerator()->AddAlias(lname, tgtName);
}
-cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
- const std::vector<std::string> &srcs,
- bool excludeFromAll)
+cmTarget* cmMakefile::AddLibrary(const std::string& lname,
+ cmStateEnums::TargetType type,
+ const std::vector<std::string>& srcs,
+ bool excludeFromAll)
{
- // wrong type ? default to STATIC
- if ( (type != cmTarget::STATIC_LIBRARY)
- && (type != cmTarget::SHARED_LIBRARY)
- && (type != cmTarget::MODULE_LIBRARY)
- && (type != cmTarget::OBJECT_LIBRARY))
- {
- this->IssueMessage(cmake::INTERNAL_ERROR,
- "cmMakefile::AddLibrary given invalid target type.");
- type = cmTarget::STATIC_LIBRARY;
- }
+ assert(type == cmStateEnums::STATIC_LIBRARY ||
+ type == cmStateEnums::SHARED_LIBRARY ||
+ type == cmStateEnums::MODULE_LIBRARY ||
+ type == cmStateEnums::OBJECT_LIBRARY ||
+ type == cmStateEnums::INTERFACE_LIBRARY);
cmTarget* target = this->AddNewTarget(type, lname);
// Clear its dependencies. Otherwise, dependencies might persist
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
- target->ClearDependencyInformation( *this, lname );
- if(excludeFromAll)
- {
+ target->ClearDependencyInformation(*this, lname);
+ if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
- }
+ }
target->AddSources(srcs);
- this->AddGlobalLinkInformation(lname, *target);
+ this->AddGlobalLinkInformation(*target);
return target;
}
-cmTarget* cmMakefile::AddExecutable(const char *exeName,
- const std::vector<std::string> &srcs,
+cmTarget* cmMakefile::AddExecutable(const char* exeName,
+ const std::vector<std::string>& srcs,
bool excludeFromAll)
{
- cmTarget* target = this->AddNewTarget(cmTarget::EXECUTABLE, exeName);
- if(excludeFromAll)
- {
+ cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName);
+ if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
- }
+ }
target->AddSources(srcs);
- this->AddGlobalLinkInformation(exeName, *target);
+ this->AddGlobalLinkInformation(*target);
return target;
}
-//----------------------------------------------------------------------------
-cmTarget*
-cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
+cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
+ const std::string& name)
{
cmTargets::iterator it =
- this->Targets.insert(cmTargets::value_type(name, cmTarget())).first;
- cmTarget& target = it->second;
- target.SetType(type, name);
- target.SetMakefile(this);
- this->LocalGenerator->GetGlobalGenerator()->AddTarget(&it->second);
+ this->Targets
+ .insert(cmTargets::value_type(
+ name, cmTarget(name, type, cmTarget::VisibilityNormal, this)))
+ .first;
+ this->GetGlobalGenerator()->IndexTarget(&it->second);
+ this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name);
return &it->second;
}
-cmSourceFile *cmMakefile::LinearGetSourceFileWithOutput(const char *cname)
+cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
+ const std::string& name) const
{
- std::string name = cname;
std::string out;
// 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)
- {
+ 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())
- {
- // is the output of the custom command match the source files name
+ if ((*i)->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)
- {
+ 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 != out.npos &&
- pos == out.size() - name.size() &&
- (pos ==0 || out[pos-1] == '/'))
- {
+ if (pos != std::string::npos && pos == out.size() - name.size() &&
+ (pos == 0 || out[pos - 1] == '/')) {
return *i;
- }
}
}
}
+ }
// otherwise return NULL
- return 0;
+ return CM_NULLPTR;
}
-cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
+cmSourceFile* cmMakefile::GetSourceFileWithOutput(
+ const std::string& name) const
{
- std::string name = cname;
-
// 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(cname))
- {
- return LinearGetSourceFileWithOutput(cname);
- }
+ if (!cmSystemTools::FileIsFullPath(name.c_str())) {
+ return this->LinearGetSourceFileWithOutput(name);
+ }
// Otherwise we use an efficient lookup map.
- OutputToSourceMap::iterator o = this->OutputToSource.find(name);
- if (o != this->OutputToSource.end())
- {
+ OutputToSourceMap::const_iterator o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end()) {
return (*o).second;
- }
- return 0;
+ }
+ return CM_NULLPTR;
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
-cmSourceGroup* cmMakefile::GetSourceGroup(const std::vector<std::string>&name)
+cmSourceGroup* cmMakefile::GetSourceGroup(
+ const std::vector<std::string>& name) const
{
- cmSourceGroup* sg = 0;
+ cmSourceGroup* sg = CM_NULLPTR;
- // first look for source group starting with the same as the one we wants
- for (std::vector<cmSourceGroup>::iterator sgIt = this->SourceGroups.begin();
- sgIt != this->SourceGroups.end(); ++sgIt)
-
- {
+ // 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();
- if(sgName == name[0])
- {
- sg = &(*sgIt);
+ if (sgName == name[0]) {
+ sg = const_cast<cmSourceGroup*>(&(*sgIt));
break;
- }
}
+ }
- if(sg != 0)
- {
+ if (sg != CM_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 == 0)
- {
+ for (unsigned int i = 1; i < name.size(); ++i) {
+ sg = sg->LookupChild(name[i].c_str());
+ if (sg == CM_NULLPTR) {
break;
- }
}
}
+ }
return sg;
}
- void cmMakefile::AddSourceGroup(const char* name,
- const char* regex)
+void cmMakefile::AddSourceGroup(const std::string& name, const char* regex)
{
- if (name)
- {
- std::vector<std::string> nameVector;
- nameVector.push_back(name);
- AddSourceGroup(nameVector, regex);
- }
+ std::vector<std::string> nameVector;
+ nameVector.push_back(name);
+ this->AddSourceGroup(nameVector, regex);
}
void cmMakefile::AddSourceGroup(const std::vector<std::string>& name,
const char* regex)
{
- cmSourceGroup* sg = 0;
+ cmSourceGroup* sg = CM_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);
+ 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 != 0)
- {
+ if (sg != CM_NULLPTR) {
break;
- }
}
+ }
// i now contains the index of the last found component
- if(i==lastElement)
- {
+ if (i == lastElement) {
// group already exists, replace its regular expression
- if ( regex )
- {
+ if (regex && sg) {
// We only want to set the regular expression. If there are already
// source files in the group, we don't want to remove them.
sg->SetGroupRegex(regex);
- }
- return;
}
- else if(i==-1)
- {
+ return;
+ }
+ 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));
sg = this->GetSourceGroup(currentName);
i = 0; // last component found
- }
-
+ }
+ if (!sg) {
+ cmSystemTools::Error("Could not create source group ");
+ return;
+ }
// build the whole source group path
- const char* fullname = sg->GetFullName();
- cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
- if(strlen(fullname))
- {
- std::string guidName = "SG_Filter_";
- guidName += fullname;
- gg->CreateGUID(guidName.c_str());
- }
- for(++i; i<=lastElement; ++i)
- {
- sg->AddChild(cmSourceGroup(name[i].c_str(), 0, sg->GetFullName()));
- sg = sg->lookupChild(name[i].c_str());
- fullname = sg->GetFullName();
- if(strlen(fullname))
- {
- std::string guidName = "SG_Filter_";
- guidName += fullname;
- gg->CreateGUID(guidName.c_str());
- }
- }
+ for (++i; i <= lastElement; ++i) {
+ sg->AddChild(
+ cmSourceGroup(name[i].c_str(), CM_NULLPTR, sg->GetFullName()));
+ sg = sg->LookupChild(name[i].c_str());
+ }
sg->SetGroupRegex(regex);
}
#endif
-void cmMakefile::AddExtraDirectory(const char* dir)
-{
- this->AuxSourceDirectories.push_back(dir);
-}
-
static bool mightExpandVariablesCMP0019(const char* s)
{
- return s && *s && strstr(s,"${") && strchr(s,'}');
+ return s && *s && strstr(s, "${") && strchr(s, '}');
}
void cmMakefile::ExpandVariablesCMP0019()
{
// Drop this ancient compatibility behavior with a policy.
cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019);
- if(pol != cmPolicies::OLD && pol != cmPolicies::WARN)
- {
+ if (pol != cmPolicies::OLD && pol != cmPolicies::WARN) {
return;
- }
- cmOStringStream w;
+ }
+ std::ostringstream w;
- const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
- if(mightExpandVariablesCMP0019(includeDirs))
- {
+ const char* includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
+ if (mightExpandVariablesCMP0019(includeDirs)) {
std::string dirs = includeDirs;
this->ExpandVariablesInString(dirs, true, true);
- if(pol == cmPolicies::WARN && dirs != includeDirs)
- {
+ if (pol == cmPolicies::WARN && dirs != includeDirs) {
+ /* clang-format off */
w << "Evaluated directory INCLUDE_DIRECTORIES\n"
<< " " << includeDirs << "\n"
<< "as\n"
<< " " << dirs << "\n";
- }
- this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
+ /* clang-format on */
}
+ this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
+ }
// 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 (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end();
+ ++l) {
+ cmTarget& t = l->second;
+ if (t.GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ t.GetType() == cmStateEnums::GLOBAL_TARGET) {
+ continue;
+ }
includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
- if(mightExpandVariablesCMP0019(includeDirs))
- {
+ if (mightExpandVariablesCMP0019(includeDirs)) {
std::string dirs = includeDirs;
this->ExpandVariablesInString(dirs, true, true);
- if(pol == cmPolicies::WARN && dirs != includeDirs)
- {
+ if (pol == cmPolicies::WARN && dirs != includeDirs) {
+ /* clang-format off */
w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n"
<< " " << includeDirs << "\n"
<< "as\n"
<< " " << dirs << "\n";
- }
- t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
+ /* clang-format on */
}
+ t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
}
+ }
- for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
- d != this->LinkDirectories.end(); ++d)
- {
- if(mightExpandVariablesCMP0019(d->c_str()))
- {
- std::string orig = *d;
- this->ExpandVariablesInString(*d, true, true);
- if(pol == cmPolicies::WARN && *d != orig)
- {
- w << "Evaluated link directory\n"
+ if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
+ if (mightExpandVariablesCMP0019(linkDirsProp)) {
+ std::string d = linkDirsProp;
+ std::string orig = linkDirsProp;
+ this->ExpandVariablesInString(d, true, true);
+ if (pol == cmPolicies::WARN && d != orig) {
+ /* clang-format off */
+ w << "Evaluated link directories\n"
<< " " << orig << "\n"
<< "as\n"
- << " " << *d << "\n";
- }
+ << " " << d << "\n";
+ /* clang-format on */
}
}
- for(cmTarget::LinkLibraryVectorType::iterator l =
- this->LinkLibraries.begin();
- l != this->LinkLibraries.end(); ++l)
- {
- if(mightExpandVariablesCMP0019(l->first.c_str()))
- {
- std::string orig = l->first;
- this->ExpandVariablesInString(l->first, true, true);
- if(pol == cmPolicies::WARN && l->first != orig)
- {
+ }
+
+ if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
+ std::vector<std::string> linkLibs;
+ cmSystemTools::ExpandListArgument(linkLibsProp, linkLibs);
+
+ for (std::vector<std::string>::iterator l = linkLibs.begin();
+ l != linkLibs.end(); ++l) {
+ std::string libName = *l;
+ if (libName == "optimized") {
+ ++l;
+ libName = *l;
+ } else if (libName == "debug") {
+ ++l;
+ libName = *l;
+ }
+ if (mightExpandVariablesCMP0019(libName.c_str())) {
+ std::string orig = libName;
+ this->ExpandVariablesInString(libName, true, true);
+ if (pol == cmPolicies::WARN && libName != orig) {
+ /* clang-format off */
w << "Evaluated link library\n"
<< " " << orig << "\n"
<< "as\n"
- << " " << l->first << "\n";
+ << " " << libName << "\n";
+ /* clang-format on */
}
}
}
+ }
- if(!w.str().empty())
- {
- cmOStringStream m;
- m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019)
+ if (!w.str().empty()) {
+ std::ostringstream m;
+ /* clang-format off */
+ m << cmPolicies::GetPolicyWarning(cmPolicies::CMP0019)
<< "\n"
<< "The following variable evaluations were encountered:\n"
<< w.str();
- this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
- }
+ /* clang-format on */
+ this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, m.str(),
+ this->Backtrace);
+ }
}
-bool cmMakefile::IsOn(const char* name) const
+bool cmMakefile::IsOn(const std::string& name) const
{
const char* value = this->GetDefinition(name);
return cmSystemTools::IsOn(value);
}
-bool cmMakefile::IsSet(const char* name) const
+bool cmMakefile::IsSet(const std::string& name) const
{
const char* value = this->GetDefinition(name);
- if ( !value )
- {
+ if (!value) {
return false;
- }
+ }
- if ( ! *value )
- {
+ if (!*value) {
return false;
- }
+ }
- if ( cmSystemTools::IsNOTFOUND(value) )
- {
+ if (cmSystemTools::IsNOTFOUND(value)) {
return false;
- }
+ }
return true;
}
+bool cmMakefile::PlatformIs32Bit() const
+{
+ if (const char* plat_abi =
+ this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
+ if (strcmp(plat_abi, "ELF X32") == 0) {
+ return false;
+ }
+ }
+ if (const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
+ return atoi(sizeof_dptr) == 4;
+ }
+ return false;
+}
+
bool cmMakefile::PlatformIs64Bit() const
{
- if(const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P"))
- {
+ if (const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
return atoi(sizeof_dptr) == 8;
+ }
+ return false;
+}
+
+bool cmMakefile::PlatformIsx32() const
+{
+ if (const char* plat_abi =
+ this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
+ if (strcmp(plat_abi, "ELF X32") == 0) {
+ return true;
}
+ }
return false;
}
-const char* cmMakefile::GetSONameFlag(const char* language) const
+bool cmMakefile::PlatformIsAppleIos() const
+{
+ std::string sdkRoot;
+ sdkRoot = this->GetSafeDefinition("CMAKE_OSX_SYSROOT");
+ sdkRoot = cmSystemTools::LowerCase(sdkRoot);
+
+ const std::string embedded[] = {
+ "appletvos", "appletvsimulator", "iphoneos",
+ "iphonesimulator", "watchos", "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;
+ }
+ }
+
+ return false;
+}
+
+const char* cmMakefile::GetSONameFlag(const std::string& language) const
{
std::string name = "CMAKE_SHARED_LIBRARY_SONAME";
- if(language)
- {
+ if (!language.empty()) {
name += "_";
name += language;
- }
+ }
name += "_FLAG";
- return GetDefinition(name.c_str());
+ return GetDefinition(name);
}
-bool cmMakefile::CanIWriteThisFile(const char* fileName)
+bool cmMakefile::CanIWriteThisFile(const char* fileName) const
{
- if ( !this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES") )
- {
+ if (!this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES")) {
return true;
- }
+ }
// If we are doing an in-source build, then the test will always fail
- if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
- this->GetHomeOutputDirectory()) )
- {
- if ( this->IsOn("CMAKE_DISABLE_IN_SOURCE_BUILD") )
- {
- return false;
- }
- return true;
- }
+ if (cmSystemTools::SameFile(this->GetHomeDirectory(),
+ this->GetHomeOutputDirectory())) {
+ return !this->IsOn("CMAKE_DISABLE_IN_SOURCE_BUILD");
+ }
- // Check if this is a subdirectory of the source tree but not a
- // subdirectory of the build tree
- if ( cmSystemTools::IsSubDirectory(fileName,
- this->GetHomeDirectory()) &&
- !cmSystemTools::IsSubDirectory(fileName,
- this->GetHomeOutputDirectory()) )
- {
- return false;
- }
- return true;
+ return !cmSystemTools::IsSubDirectory(fileName, this->GetHomeDirectory()) ||
+ cmSystemTools::IsSubDirectory(fileName, this->GetHomeOutputDirectory());
}
-const char* cmMakefile::GetRequiredDefinition(const char* name) const
+const char* cmMakefile::GetRequiredDefinition(const std::string& name) const
{
const char* ret = this->GetDefinition(name);
- if(!ret)
- {
+ if (!ret) {
cmSystemTools::Error("Error required internal CMake variable not "
- "set, cmake may be not be built correctly.\n",
- "Missing variable is:\n",
- name);
+ "set, cmake may not be built correctly.\n",
+ "Missing variable is:\n", name.c_str());
return "";
- }
+ }
return ret;
}
-bool cmMakefile::IsDefinitionSet(const char* name) const
+bool cmMakefile::IsDefinitionSet(const std::string& name) const
{
- const char* def = this->Internal->VarStack.top().Get(name);
- this->Internal->VarUsageStack.top().insert(name);
- if(!def)
- {
- def = this->GetCacheManager()->GetCacheValue(name);
- }
+ const char* def = this->StateSnapshot.GetDefinition(name);
+ if (!def) {
+ def = this->GetState()->GetInitializedCacheValue(name);
+ }
#ifdef CMAKE_BUILD_WITH_CMAKE
- if(cmVariableWatch* vv = this->GetVariableWatch())
- {
- if(!def)
- {
- vv->VariableAccessed
- (name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS,
- def, this);
- }
+ if (cmVariableWatch* vv = this->GetVariableWatch()) {
+ if (!def) {
+ vv->VariableAccessed(
+ name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, def, this);
}
+ }
#endif
- return def?true:false;
+ return def != CM_NULLPTR;
}
-const char* cmMakefile::GetDefinition(const char* name) const
+const char* cmMakefile::GetDefinition(const std::string& name) const
{
-#ifdef CMAKE_STRICT
- if (this->GetCMakeInstance())
- {
- this->GetCMakeInstance()->
- RecordPropertyAccess(name,cmProperty::VARIABLE);
- }
-#endif
- if (this->WarnUnused)
- {
- this->Internal->VarUsageStack.top().insert(name);
- }
- const char* def = this->Internal->VarStack.top().Get(name);
- if(!def)
- {
- def = this->GetCacheManager()->GetCacheValue(name);
- }
+ const char* def = this->StateSnapshot.GetDefinition(name);
+ if (!def) {
+ def = this->GetState()->GetInitializedCacheValue(name);
+ }
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch();
- if ( vv )
- {
- if ( def )
- {
- vv->VariableAccessed(name, cmVariableWatch::VARIABLE_READ_ACCESS,
- def, this);
- }
- else
- {
- // are unknown access allowed
- const char* allow = this->Internal->VarStack.top()
- .Get("CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS");
- if(cmSystemTools::IsOn(allow))
- {
- vv->VariableAccessed(name,
- cmVariableWatch::ALLOWED_UNKNOWN_VARIABLE_READ_ACCESS, def, this);
- }
- else
- {
- vv->VariableAccessed(name,
- cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, def, this);
- }
+ 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 (watch_function_executed) {
+ // A callback was executed and may have caused re-allocation of the
+ // variable storage. Look it up again for now.
+ // FIXME: Refactor variable storage to avoid this problem.
+ def = this->StateSnapshot.GetDefinition(name);
+ if (!def) {
+ def = this->GetState()->GetInitializedCacheValue(name);
}
}
+ }
#endif
return def;
}
-const char* cmMakefile::GetSafeDefinition(const char* def) const
+const char* cmMakefile::GetSafeDefinition(const std::string& def) const
{
const char* ret = this->GetDefinition(def);
- if(!ret)
- {
+ if (!ret) {
return "";
- }
+ }
return ret;
}
-std::vector<std::string> cmMakefile
-::GetDefinitions(int cacheonly /* = 0 */) const
+std::vector<std::string> cmMakefile::GetDefinitions() const
{
- std::set<cmStdString> definitions;
- if ( !cacheonly )
- {
- definitions = this->Internal->VarStack.top().ClosureKeys();
- }
- cmCacheManager::CacheIterator cit =
- this->GetCacheManager()->GetCacheIterator();
- for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
- {
- definitions.insert(cit.GetName());
- }
-
- std::vector<std::string> res;
-
- std::set<cmStdString>::iterator fit;
- for ( fit = definitions.begin(); fit != definitions.end(); fit ++ )
- {
- res.push_back(*fit);
- }
+ std::vector<std::string> res = this->StateSnapshot.ClosureKeys();
+ std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys();
+ res.insert(res.end(), cacheKeys.begin(), cacheKeys.end());
+ std::sort(res.begin(), res.end());
return res;
}
-
-const char *cmMakefile::ExpandVariablesInString(std::string& source)
+const char* cmMakefile::ExpandVariablesInString(std::string& source) const
{
return this->ExpandVariablesInString(source, false, false);
}
-const char *cmMakefile::ExpandVariablesInString(std::string& source,
- bool escapeQuotes,
- bool noEscapes,
- bool atOnly,
- const char* filename,
- long line,
- bool removeEmpty,
- bool replaceAt)
+const char* cmMakefile::ExpandVariablesInString(
+ std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly,
+ const char* filename, long line, bool removeEmpty, bool replaceAt) const
{
- if ( source.empty() || source.find_first_of("$@\\") == source.npos)
- {
+ bool compareResults = false;
+ cmake::MessageType mtype = cmake::LOG;
+ std::string errorstr;
+ std::string original;
+
+ // Sanity check the @ONLY mode.
+ 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,
+ "ExpandVariablesInString @ONLY called "
+ "on something with escapes.");
return source.c_str();
+ }
+
+ // Variables used in the WARN case.
+ std::string newResult;
+ std::string newErrorstr;
+ cmake::MessageType newError = cmake::LOG;
+
+ switch (this->GetPolicyStatus(cmPolicies::CMP0053)) {
+ case cmPolicies::WARN: {
+ // Save the original string for the warning.
+ original = source;
+ newResult = source;
+ 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;
+ CM_FALLTHROUGH;
}
+ case cmPolicies::OLD:
+ mtype =
+ ExpandVariablesInStringOld(errorstr, source, escapeQuotes, noEscapes,
+ atOnly, filename, line, removeEmpty, true);
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ // Messaging here would be *very* verbose.
+ case cmPolicies::NEW:
+ mtype = ExpandVariablesInStringNew(errorstr, source, escapeQuotes,
+ noEscapes, atOnly, filename, line,
+ removeEmpty, replaceAt);
+ break;
+ }
- // Special-case the @ONLY mode.
- if(atOnly)
- {
- if(!noEscapes || !removeEmpty || !replaceAt)
- {
- // This case should never be called. At-only is for
- // configure-file/string which always does no escapes.
- this->IssueMessage(cmake::INTERNAL_ERROR,
- "ExpandVariablesInString @ONLY called "
- "on something with escapes.");
- }
+ // If it's an error in either case, just report the error...
+ if (mtype != cmake::LOG) {
+ if (mtype == cmake::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_input = original;
+ cmSystemTools::ReplaceString(msg_input, "\n", "\n ");
+ msg += "For input:\n '";
+ msg += msg_input;
+ msg += "'\n";
+
+ std::string msg_old = source;
+ cmSystemTools::ReplaceString(msg_old, "\n", "\n ");
+ msg += "the old evaluation rules produce:\n '";
+ msg += msg_old;
+ msg += "'\n";
+
+ if (newError == mtype) {
+ std::string msg_new = newResult;
+ cmSystemTools::ReplaceString(msg_new, "\n", "\n ");
+ msg += "but the new evaluation rules produce:\n '";
+ msg += msg_new;
+ msg += "'\n";
+ } else {
+ std::string msg_err = newErrorstr;
+ cmSystemTools::ReplaceString(msg_err, "\n", "\n ");
+ msg += "but the new evaluation rules produce an error:\n ";
+ msg += msg_err;
+ msg += "\n";
+ }
+
+ msg +=
+ "Using the old result for compatibility since the policy is not set.";
+
+ this->IssueMessage(cmake::AUTHOR_WARNING, msg);
+ }
+
+ return source.c_str();
+}
+
+cmake::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;
+ }
+ // Special-case the @ONLY mode.
+ if (atOnly) {
// Store an original copy of the input.
std::string input = source;
@@ -2566,39 +2427,34 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
// Look for one @VAR@ at a time.
const char* in = input.c_str();
- while(this->cmAtVarRegex.find(in))
- {
+ while (this->cmAtVarRegex.find(in)) {
// Get the range of the string to replace.
const char* first = in + this->cmAtVarRegex.start();
- const char* last = in + this->cmAtVarRegex.end();
+ const char* last = in + this->cmAtVarRegex.end();
// Store the unchanged part of the string now.
- source.append(in, first-in);
+ source.append(in, first - in);
// Lookup the definition of VAR.
- std::string var(first+1, last-first-2);
- if(const char* val = this->GetDefinition(var.c_str()))
- {
+ std::string var(first + 1, last - first - 2);
+ if (const char* val = this->GetDefinition(var)) {
// Store the value in the output escaping as requested.
- if(escapeQuotes)
- {
+ if (escapeQuotes) {
source.append(cmSystemTools::EscapeQuotes(val));
- }
- else
- {
+ } else {
source.append(val);
- }
}
+ }
// Continue looking for @VAR@ further along the string.
in = last;
- }
+ }
// Append the rest of the unchanged part of the string.
source.append(in);
- return source.c_str();
- }
+ return cmake::LOG;
+ }
// This method replaces ${VAR} and @VAR@ where VAR is looked up
// with GetDefinition(), if not found in the map, nothing is expanded.
@@ -2614,25 +2470,22 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
parser.SetRemoveEmpty(removeEmpty);
int res = parser.ParseString(source.c_str(), 0);
const char* emsg = parser.GetError();
- if ( res && !emsg[0] )
- {
+ cmake::MessageType mtype = cmake::LOG;
+ if (res && !emsg[0]) {
source = parser.GetResult();
- }
- else
- {
+ } else {
// Construct the main error message.
- cmOStringStream error;
+ std::ostringstream error;
error << "Syntax error in cmake code ";
- if(filename && line > 0)
- {
+ if (filename && line > 0) {
// This filename and line number may be more specific than the
// command context because one command invocation can have
// arguments on multiple lines.
error << "at\n"
<< " " << filename << ":" << line << "\n";
- }
+ }
error << "when parsing string\n"
- << " " << source.c_str() << "\n";
+ << " " << source << "\n";
error << emsg;
// If the parser failed ("res" is false) then this is a real
@@ -2640,17 +2493,14 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
// parser reported an error message without failing because the
// helper implementation is unhappy, which has always reported an
// error.
- cmake::MessageType mtype = cmake::FATAL_ERROR;
- if(!res)
- {
+ mtype = cmake::FATAL_ERROR;
+ if (!res) {
// This is a real argument parsing error. Use policy CMP0010 to
// decide whether it is an error.
- switch(this->GetPolicyStatus(cmPolicies::CMP0010))
- {
+ switch (this->GetPolicyStatus(cmPolicies::CMP0010)) {
case cmPolicies::WARN:
- error << "\n"
- << (this->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0010));
+ error << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0010);
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to just warn and continue.
mtype = cmake::AUTHOR_WARNING;
@@ -2658,121 +2508,313 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
error << "\n"
- << (this->GetPolicies()
- ->GetRequiredPolicyError(cmPolicies::CMP0010));
+ << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0010);
case cmPolicies::NEW:
// NEW behavior is to report the error.
- cmSystemTools::SetFatalErrorOccured();
break;
+ }
+ }
+ errorstr = error.str();
+ }
+ return mtype;
+}
+
+typedef enum { NORMAL, ENVIRONMENT, CACHE } t_domain;
+struct t_lookup
+{
+ t_lookup()
+ : domain(NORMAL)
+ , loc(0)
+ {
+ }
+ t_domain domain;
+ size_t loc;
+};
+
+cmake::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
+{
+ // This method replaces ${VAR} and @VAR@ where VAR is looked up
+ // with GetDefinition(), if not found in the map, nothing is expanded.
+ // It also supports the $ENV{VAR} syntax where VAR is looked up in
+ // the current environment variables.
+
+ const char* in = source.c_str();
+ const char* last = in;
+ std::string result;
+ result.reserve(source.size());
+ std::vector<t_lookup> openstack;
+ bool error = false;
+ bool done = false;
+ cmake::MessageType mtype = cmake::LOG;
+
+ cmState* state = this->GetCMakeInstance()->GetState();
+
+ do {
+ char inc = *in;
+ switch (inc) {
+ case '}':
+ if (!openstack.empty()) {
+ t_lookup var = openstack.back();
+ openstack.pop_back();
+ result.append(last, in - last);
+ std::string const& lookup = result.substr(var.loc);
+ const char* value = CM_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();
+ } else {
+ value = this->GetDefinition(lookup);
+ }
+ break;
+ case ENVIRONMENT:
+ if (cmSystemTools::GetEnv(lookup, svalue)) {
+ value = svalue.c_str();
+ }
+ break;
+ case CACHE:
+ value = state->GetCacheEntryValue(lookup);
+ break;
+ }
+ // Get the string we're meant to append to.
+ if (value) {
+ if (escapeQuotes) {
+ varresult = cmSystemTools::EscapeQuotes(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());
+ }
+ }
+ }
+ result.replace(var.loc, result.size() - var.loc, varresult);
+ // Start looking from here on out.
+ last = in + 1;
+ }
+ break;
+ case '$':
+ if (!atOnly) {
+ t_lookup lookup;
+ const char* next = in + 1;
+ const char* start = CM_NULLPTR;
+ char nextc = *next;
+ if (nextc == '{') {
+ // Looking for a variable.
+ start = in + 2;
+ lookup.domain = NORMAL;
+ } else if (nextc == '<') {
+ } else if (!nextc) {
+ result.append(last, next - last);
+ last = next;
+ } else if (cmHasLiteralPrefix(next, "ENV{")) {
+ // Looking for an environment variable.
+ start = in + 5;
+ lookup.domain = ENVIRONMENT;
+ } else if (cmHasLiteralPrefix(next, "CACHE{")) {
+ // Looking for a cache variable.
+ start = in + 7;
+ lookup.domain = CACHE;
+ } else {
+ if (this->cmNamedCurly.find(next)) {
+ errorstr = "Syntax $" +
+ std::string(next, this->cmNamedCurly.end()) +
+ "{} is not supported. Only ${}, $ENV{}, "
+ "and $CACHE{} are allowed.";
+ mtype = cmake::FATAL_ERROR;
+ error = true;
+ }
+ }
+ if (start) {
+ result.append(last, in - last);
+ last = start;
+ in = start - 1;
+ lookup.loc = result.size();
+ openstack.push_back(lookup);
+ }
+ break;
+ }
+ CM_FALLTHROUGH;
+ case '\\':
+ if (!noEscapes) {
+ const char* next = in + 1;
+ char nextc = *next;
+ if (nextc == 't') {
+ result.append(last, in - last);
+ result.append("\t");
+ last = next + 1;
+ } else if (nextc == 'n') {
+ result.append(last, in - last);
+ result.append("\n");
+ last = next + 1;
+ } else if (nextc == 'r') {
+ result.append(last, in - last);
+ result.append("\r");
+ last = next + 1;
+ } else if (nextc == ';' && openstack.empty()) {
+ // Handled in ExpandListArgument; pass the backslash literally.
+ } else if (isalnum(nextc) || nextc == '\0') {
+ errorstr += "Invalid character escape '\\";
+ if (nextc) {
+ errorstr += nextc;
+ errorstr += "'.";
+ } else {
+ errorstr += "' (at end of input).";
+ }
+ error = true;
+ } else {
+ // Take what we've found so far, skipping the escape character.
+ result.append(last, in - last);
+ // Start tracking from the next character.
+ last = in + 1;
+ }
+ // Skip the next character since it was escaped, but don't read past
+ // the end of the string.
+ if (*last) {
+ ++in;
+ }
}
+ break;
+ case '\n':
+ // Onto the next line.
+ ++line;
+ break;
+ case '\0':
+ done = true;
+ break;
+ case '@':
+ if (replaceAt) {
+ const char* nextAt = strchr(in + 1, '@');
+ if (nextAt && nextAt != in + 1 &&
+ nextAt ==
+ in + 1 + strspn(in + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789/_.+-")) {
+ std::string variable(in + 1, nextAt - in - 1);
+ std::string varresult = this->GetSafeDefinition(variable);
+ if (escapeQuotes) {
+ varresult = cmSystemTools::EscapeQuotes(varresult);
+ }
+ // Skip over the variable.
+ result.append(last, in - last);
+ result.append(varresult);
+ in = nextAt;
+ last = in + 1;
+ break;
+ }
+ }
+ // Failed to find a valid @ expansion; treat it as literal.
+ /* FALLTHROUGH */
+ default: {
+ if (!openstack.empty() &&
+ !(isalnum(inc) || inc == '_' || inc == '/' || inc == '.' ||
+ inc == '+' || inc == '-')) {
+ errorstr += "Invalid character (\'";
+ errorstr += inc;
+ result.append(last, in - last);
+ errorstr += "\') in a variable name: "
+ "'" +
+ result.substr(openstack.back().loc) + "'";
+ mtype = cmake::FATAL_ERROR;
+ error = true;
+ }
+ break;
}
- this->IssueMessage(mtype, error.str());
}
- return source.c_str();
+ // Look at the next character.
+ } while (!error && !done && *++in);
+
+ // Check for open variable references yet.
+ if (!error && !openstack.empty()) {
+ // There's an open variable reference waiting. Policy CMP0010 flags
+ // whether this is an error or not. The new parser now enforces
+ // CMP0010 as well.
+ errorstr += "There is an unterminated variable reference.";
+ error = true;
+ }
+
+ if (error) {
+ std::ostringstream emsg;
+ emsg << "Syntax error in cmake code ";
+ if (filename) {
+ // This filename and line number may be more specific than the
+ // command context because one command invocation can have
+ // arguments on multiple lines.
+ emsg << "at\n"
+ << " " << filename << ":" << line << "\n";
+ }
+ emsg << "when parsing string\n"
+ << " " << source << "\n";
+ emsg << errorstr;
+ mtype = cmake::FATAL_ERROR;
+ errorstr = emsg.str();
+ } else {
+ // Append the rest of the unchanged part of the string.
+ result.append(last);
+
+ source = result;
+ }
+
+ return mtype;
}
void cmMakefile::RemoveVariablesInString(std::string& source,
bool atOnly) const
{
- if(!atOnly)
- {
+ if (!atOnly) {
cmsys::RegularExpression var("(\\${[A-Za-z_0-9]*})");
- while (var.find(source))
- {
- source.erase(var.start(),var.end() - var.start());
- }
+ while (var.find(source)) {
+ source.erase(var.start(), var.end() - var.start());
}
+ }
- if(!atOnly)
- {
+ if (!atOnly) {
cmsys::RegularExpression varb("(\\$ENV{[A-Za-z_0-9]*})");
- while (varb.find(source))
- {
- source.erase(varb.start(),varb.end() - varb.start());
- }
+ while (varb.find(source)) {
+ source.erase(varb.start(), varb.end() - varb.start());
}
+ }
cmsys::RegularExpression var2("(@[A-Za-z_0-9]*@)");
- while (var2.find(source))
- {
- source.erase(var2.start(),var2.end() - var2.start());
- }
+ while (var2.find(source)) {
+ source.erase(var2.start(), var2.end() - var2.start());
+ }
}
-/**
- * Add the default definitions to the makefile. These values must not
- * be dependent on anything that isn't known when this cmMakefile instance
- * is constructed.
- */
-void cmMakefile::AddDefaultDefinitions()
-{
-/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
- With CMake must separate between target and host platform. In most cases
- the tests for WIN32, UNIX and APPLE will be for the target system, so an
- additional set of variables for the host system is required ->
- CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
- WIN32, UNIX and APPLE are now set in the platform files in
- Modules/Platforms/.
- To keep cmake scripts (-P) and custom language and compiler modules
- working, these variables are still also set here in this place, but they
- will be reset in CMakeSystemSpecificInformation.cmake before the platform
- files are executed. */
-#if defined(_WIN32)
- this->AddDefinition("WIN32", "1");
- this->AddDefinition("CMAKE_HOST_WIN32", "1");
-#else
- this->AddDefinition("UNIX", "1");
- this->AddDefinition("CMAKE_HOST_UNIX", "1");
-#endif
-#if defined(__CYGWIN__)
- if(cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32")))
- {
- this->AddDefinition("WIN32", "1");
- this->AddDefinition("CMAKE_HOST_WIN32", "1");
- }
-#endif
-#if defined(__APPLE__)
- this->AddDefinition("APPLE", "1");
- this->AddDefinition("CMAKE_HOST_APPLE", "1");
-#endif
-
- char temp[1024];
- sprintf(temp, "%d", cmVersion::GetMinorVersion());
- this->AddDefinition("CMAKE_MINOR_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetMajorVersion());
- this->AddDefinition("CMAKE_MAJOR_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetPatchVersion());
- this->AddDefinition("CMAKE_PATCH_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetTweakVersion());
- this->AddDefinition("CMAKE_TWEAK_VERSION", temp);
- this->AddDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion());
-
- this->AddDefinition("CMAKE_FILES_DIRECTORY",
- cmake::GetCMakeFilesDirectory());
-}
-
-//----------------------------------------------------------------------------
-const char*
-cmMakefile::GetConfigurations(std::vector<std::string>& configs,
- bool single) const
-{
- if(this->LocalGenerator->GetGlobalGenerator()->IsMultiConfig())
- {
- if(const char* configTypes =
- this->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
- {
+std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs,
+ bool singleConfig) const
+{
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
+ if (const char* configTypes =
+ this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
cmSystemTools::ExpandListArgument(configTypes, configs);
- }
- return 0;
- }
- else
- {
- const char* buildType = this->GetDefinition("CMAKE_BUILD_TYPE");
- if(single && buildType && *buildType)
- {
- configs.push_back(buildType);
- }
- return buildType;
}
+ return "";
+ }
+ const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ if (singleConfig && !buildType.empty()) {
+ configs.push_back(buildType);
+ }
+ return buildType;
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -2783,211 +2825,249 @@ cmMakefile::GetConfigurations(std::vector<std::string>& configs,
* non-inherited SOURCE_GROUP commands will have precedence over
* inherited ones.
*/
-cmSourceGroup&
-cmMakefile::FindSourceGroup(const char* source,
- std::vector<cmSourceGroup> &groups)
+cmSourceGroup* cmMakefile::FindSourceGroup(
+ const char* source, std::vector<cmSourceGroup>& groups) const
{
// First search for a group that lists the file explicitly.
- for(std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
- sg != groups.rend(); ++sg)
- {
- cmSourceGroup *result = sg->MatchChildrenFiles(source);
- if(result)
- {
- return *result;
- }
+ 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;
- }
+ for (std::vector<cmSourceGroup>::reverse_iterator 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.front();
+ return &groups.front();
}
#endif
bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff,
- cmExecutionStatus &status)
+ cmExecutionStatus& status)
{
// if there are no blockers get out of here
- if (this->FunctionBlockers.begin() == this->FunctionBlockers.end())
- {
+ if (this->FunctionBlockers.begin() == this->FunctionBlockers.end()) {
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))
- {
+ pos != this->FunctionBlockers.rend(); ++pos) {
+ if ((*pos)->IsFunctionBlocked(lff, *this, status)) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmMakefile::PushFunctionBlockerBarrier()
{
this->FunctionBlockerBarriers.push_back(this->FunctionBlockers.size());
}
-//----------------------------------------------------------------------------
void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
{
// Remove any extra entries pushed on the barrier.
FunctionBlockersType::size_type barrier =
this->FunctionBlockerBarriers.back();
- while(this->FunctionBlockers.size() > barrier)
- {
- cmsys::auto_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back());
+ while (this->FunctionBlockers.size() > barrier) {
+ CM_AUTO_PTR<cmFunctionBlocker> fb(this->FunctionBlockers.back());
this->FunctionBlockers.pop_back();
- if(reportError)
- {
+ if (reportError) {
// Report the context in which the unclosed block was opened.
cmListFileContext const& lfc = fb->GetStartingContext();
- cmOStringStream e;
+ std::ostringstream e;
+ /* clang-format off */
e << "A logical block opening on the line\n"
<< " " << lfc << "\n"
<< "is not closed.";
+ /* clang-format on */
this->IssueMessage(cmake::FATAL_ERROR, e.str());
reportError = false;
- }
}
+ }
// Remove the barrier.
this->FunctionBlockerBarriers.pop_back();
}
-bool cmMakefile::ExpandArguments(
- std::vector<cmListFileArgument> const& inArgs,
- std::vector<std::string>& outArgs)
+void cmMakefile::PushLoopBlock()
+{
+ assert(!this->LoopBlockCounter.empty());
+ this->LoopBlockCounter.top()++;
+}
+
+void cmMakefile::PopLoopBlock()
+{
+ assert(!this->LoopBlockCounter.empty());
+ assert(this->LoopBlockCounter.top() > 0);
+ this->LoopBlockCounter.top()--;
+}
+
+void cmMakefile::PushLoopBlockBarrier()
+{
+ this->LoopBlockCounter.push(0);
+}
+
+void cmMakefile::PopLoopBlockBarrier()
+{
+ assert(!this->LoopBlockCounter.empty());
+ assert(this->LoopBlockCounter.top() == 0);
+ this->LoopBlockCounter.pop();
+}
+
+bool cmMakefile::IsLoopBlock() const
{
+ assert(!this->LoopBlockCounter.empty());
+ return !this->LoopBlockCounter.empty() && this->LoopBlockCounter.top() > 0;
+}
+
+std::string cmMakefile::GetExecutionFilePath() const
+{
+ assert(this->StateSnapshot.IsValid());
+ return this->StateSnapshot.GetExecutionListFile();
+}
+
+bool cmMakefile::ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
+ std::vector<std::string>& outArgs,
+ const char* filename) const
+{
+ std::string efp = this->GetExecutionFilePath();
+ 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 (i = inArgs.begin(); i != inArgs.end(); ++i) {
+ // No expansion in a bracket argument.
+ 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,
- i->FilePath, i->Line,
- false, true);
+ 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
- {
+ } else {
cmSystemTools::ExpandListArgument(value, outArgs);
+ }
+ }
+ return !cmSystemTools::GetFatalErrorOccured();
+}
+
+bool cmMakefile::ExpandArguments(
+ std::vector<cmListFileArgument> const& inArgs,
+ std::vector<cmExpandedCommandArgument>& outArgs, const char* filename) const
+{
+ std::string efp = this->GetExecutionFilePath();
+ 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) {
+ // No expansion in a bracket argument.
+ if (i->Delim == cmListFileArgument::Bracket) {
+ outArgs.push_back(cmExpandedCommandArgument(i->Value, true));
+ continue;
+ }
+ // Expand the variables in the argument.
+ 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));
+ } 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));
}
}
+ }
return !cmSystemTools::GetFatalErrorOccured();
}
-//----------------------------------------------------------------------------
void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb)
{
- if(!this->CallStack.empty())
- {
+ if (!this->ExecutionStatusStack.empty()) {
// Record the context in which the blocker is created.
- fb->SetStartingContext(*(this->CallStack.back().Context));
- }
+ fb->SetStartingContext(this->GetExecutionContext());
+ }
this->FunctionBlockers.push_back(fb);
}
-cmsys::auto_ptr<cmFunctionBlocker>
-cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb,
- const cmListFileFunction& lff)
+CM_AUTO_PTR<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker(
+ cmFunctionBlocker* fb, const cmListFileFunction& lff)
{
// 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())
- {
+ 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)
- {
+ for (FunctionBlockersType::size_type i = this->FunctionBlockers.size();
+ i > barrier; --i) {
std::vector<cmFunctionBlocker*>::iterator pos =
this->FunctionBlockers.begin() + (i - 1);
- if (*pos == fb)
- {
+ if (*pos == fb) {
// Warn if the arguments do not match, but always remove.
- if(!(*pos)->ShouldRemove(lff, *this))
- {
+ if (!(*pos)->ShouldRemove(lff, *this)) {
cmListFileContext const& lfc = fb->GetStartingContext();
- cmOStringStream e;
+ 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"
- << " " << lff << "\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 cmsys::auto_ptr<cmFunctionBlocker>(b);
- }
+ return CM_AUTO_PTR<cmFunctionBlocker>(b);
}
+ }
- return cmsys::auto_ptr<cmFunctionBlocker>();
-}
-
-//----------------------------------------------------------------------------
-cmMakefile::LexicalPushPop::LexicalPushPop(cmMakefile* mf):
- Makefile(mf), ReportError(true)
-{
- this->Makefile->PushFunctionBlockerBarrier();
+ return CM_AUTO_PTR<cmFunctionBlocker>();
}
-//----------------------------------------------------------------------------
-cmMakefile::LexicalPushPop::~LexicalPushPop()
+const char* cmMakefile::GetHomeDirectory() const
{
- this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
+ return this->GetCMakeInstance()->GetHomeDirectory();
}
-void cmMakefile::SetHomeDirectory(const char* dir)
+const char* cmMakefile::GetHomeOutputDirectory() const
{
- this->cmHomeDirectory = dir;
- cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory);
- this->AddDefinition("CMAKE_SOURCE_DIR", this->GetHomeDirectory());
- if ( !this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR") )
- {
- this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", this->GetHomeDirectory());
- }
-}
-
-void cmMakefile::SetHomeOutputDirectory(const char* lib)
-{
- this->HomeOutputDirectory = lib;
- cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory);
- this->AddDefinition("CMAKE_BINARY_DIR", this->GetHomeOutputDirectory());
- if ( !this->GetDefinition("CMAKE_CURRENT_BINARY_DIR") )
- {
- this->AddDefinition("CMAKE_CURRENT_BINARY_DIR",
- this->GetHomeOutputDirectory());
- }
+ return this->GetCMakeInstance()->GetHomeOutputDirectory();
}
void cmMakefile::SetScriptModeFile(const char* scriptfile)
@@ -2997,140 +3077,144 @@ void cmMakefile::SetScriptModeFile(const char* scriptfile)
void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
{
- cmOStringStream strStream;
+ std::ostringstream strStream;
strStream << args.size();
this->AddDefinition("CMAKE_ARGC", strStream.str().c_str());
- //this->MarkVariableAsUsed("CMAKE_ARGC");
+ // this->MarkVariableAsUsed("CMAKE_ARGC");
- for (unsigned int t = 0; t < args.size(); ++t)
- {
- cmOStringStream tmpStream;
+ for (unsigned int t = 0; t < args.size(); ++t) {
+ std::ostringstream tmpStream;
tmpStream << "CMAKE_ARGV" << t;
- this->AddDefinition(tmpStream.str().c_str(), args[t].c_str());
- //this->MarkVariableAsUsed(tmpStream.str().c_str());
+ this->AddDefinition(tmpStream.str(), args[t].c_str());
+ // this->MarkVariableAsUsed(tmpStream.str().c_str());
}
}
-//----------------------------------------------------------------------------
-cmSourceFile* cmMakefile::GetSource(const char* sourceName)
+cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const
{
cmSourceFileLocation sfl(this, sourceName);
- for(std::vector<cmSourceFile*>::const_iterator
- sfi = this->SourceFiles.begin();
- sfi != this->SourceFiles.end(); ++sfi)
- {
+ for (std::vector<cmSourceFile*>::const_iterator sfi =
+ this->SourceFiles.begin();
+ sfi != this->SourceFiles.end(); ++sfi) {
cmSourceFile* sf = *sfi;
- if(sf->Matches(sfl))
- {
+ if (sf->Matches(sfl)) {
return sf;
- }
}
- return 0;
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName,
+cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName,
+ bool generated)
+{
+ cmSourceFile* sf = new cmSourceFile(this, sourceName);
+ if (generated) {
+ sf->SetProperty("GENERATED", "1");
+ }
+ this->SourceFiles.push_back(sf);
+ return sf;
+}
+
+cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName,
bool generated)
{
- if(cmSourceFile* esf = this->GetSource(sourceName))
- {
+ if (cmSourceFile* esf = this->GetSource(sourceName)) {
return esf;
- }
- else
- {
- cmSourceFile* sf = new cmSourceFile(this, sourceName);
- if(generated)
- {
- sf->SetProperty("GENERATED", "1");
- }
- this->SourceFiles.push_back(sf);
- return sf;
- }
+ }
+ return this->CreateSource(sourceName, generated);
+}
+
+void cmMakefile::AddTargetObject(std::string const& tgtName,
+ std::string const& objFile)
+{
+ cmSourceFile* sf = this->GetOrCreateSource(objFile, true);
+ sf->SetObjectLibrary(tgtName);
+ sf->SetProperty("EXTERNAL_OBJECT", "1");
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->SourceGroups[this->ObjectLibrariesSourceGroupIndex].AddGroupFile(
+ sf->GetFullPath());
+#endif
}
-void cmMakefile::EnableLanguage(std::vector<std::string> const & lang,
- bool optional)
+void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
+ bool optional)
{
this->AddDefinition("CMAKE_CFG_INTDIR",
- this->LocalGenerator->GetGlobalGenerator()
- ->GetCMakeCFGIntDir());
- this->LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this,
- optional);
-}
-
-void cmMakefile::ExpandSourceListArguments(
- std::vector<std::string> const& arguments,
- std::vector<std::string>& newargs, unsigned int /* start */)
-{
- // now expand the args
- unsigned int i;
- for(i = 0; i < arguments.size(); ++i)
- {
- // List expansion will have been done already.
- newargs.push_back(arguments[i]);
+ this->GetGlobalGenerator()->GetCMakeCFGIntDir());
+ // 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);
+ } else {
+ langs.push_back(*i);
}
+ }
+ if (!langs.empty()) {
+ this->GetGlobalGenerator()->EnableLanguage(langs, this, optional);
+ }
+ if (!langsRC.empty()) {
+ this->GetGlobalGenerator()->EnableLanguage(langsRC, this, optional);
+ }
}
-int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
- const char *projectName, const char *targetName,
- bool fast,
- const std::vector<std::string> *cmakeArgs,
- std::string *output)
+int cmMakefile::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,
+ std::string& output)
{
- this->Internal->IsSourceFileTryCompile = fast;
+ this->IsSourceFileTryCompile = fast;
// does the binary directory exist ? If not create it...
- if (!cmSystemTools::FileIsDirectory(bindir))
- {
- cmSystemTools::MakeDirectory(bindir);
- }
+ if (!cmSystemTools::FileIsDirectory(bindir)) {
+ cmSystemTools::MakeDirectory(bindir.c_str());
+ }
// change to the tests directory and run cmake
// use the cmake object instead of calling cmake
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(bindir);
+ cmWorkingDirectory workdir(bindir);
// 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
- std::string cmakeCommand = this->GetDefinition("CMAKE_COMMAND");
- cmake cm;
+ cmake cm(cmake::RoleProject);
cm.SetIsInTryCompile(true);
- cmGlobalGenerator *gg = cm.CreateGlobalGenerator
- (this->LocalGenerator->GetGlobalGenerator()->GetName());
- if (!gg)
- {
- cmSystemTools::Error(
- "Internal CMake error, TryCompile bad GlobalGenerator");
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
- this->Internal->IsSourceFileTryCompile = false;
+ cmGlobalGenerator* gg =
+ cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName());
+ if (!gg) {
+ this->IssueMessage(cmake::INTERNAL_ERROR, "Global generator '" +
+ this->GetGlobalGenerator()->GetName() +
+ "' could not be created.");
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
return 1;
- }
+ }
cm.SetGlobalGenerator(gg);
// do a configure
cm.SetHomeDirectory(srcdir);
cm.SetHomeOutputDirectory(bindir);
- cm.SetStartDirectory(srcdir);
- cm.SetStartOutputDirectory(bindir);
- cm.SetCMakeCommand(cmakeCommand.c_str());
+ cm.SetGeneratorPlatform(this->GetCMakeInstance()->GetGeneratorPlatform());
cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset());
cm.LoadCache();
- if(!gg->IsMultiConfig())
- {
- if(const char* config =
- this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"))
- {
+ if (!gg->IsMultiConfig()) {
+ if (const char* config =
+ this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION")) {
// Tell the single-configuration generator which one to use.
// Add this before the user-provided CMake arguments in case
// one of the arguments is -DCMAKE_BUILD_TYPE=...
- cm.AddCacheEntry("CMAKE_BUILD_TYPE", config,
- "Build configuration", cmCacheManager::STRING);
- }
+ cm.AddCacheEntry("CMAKE_BUILD_TYPE", config, "Build configuration",
+ cmStateEnums::STRING);
}
+ }
// if cmake args were provided then pass them in
- if (cmakeArgs)
- {
+ if (cmakeArgs) {
// FIXME: Workaround to ignore unused CLI variables in try-compile.
//
// Ideally we should use SetArgs to honor options like --warn-unused-vars.
@@ -3154,127 +3238,91 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
// previously built. Instead we work around the issue by never reporting
// unused arguments and ignoring options such as --warn-unused-vars.
cm.SetWarnUnusedCli(false);
- //cm.SetArgs(*cmakeArgs, true);
+ // cm.SetArgs(*cmakeArgs, true);
cm.SetCacheArgs(*cmakeArgs);
- }
+ }
// to save time we pass the EnableLanguage info directly
- gg->EnableLanguagesFromGenerator
- (this->LocalGenerator->GetGlobalGenerator(), this);
- if(this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"))
- {
- cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS",
- "TRUE", "", cmCacheManager::INTERNAL);
- }
- else
- {
- cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS",
- "FALSE", "", cmCacheManager::INTERNAL);
- }
- if (cm.Configure() != 0)
- {
- cmSystemTools::Error(
- "Internal CMake error, TryCompile configure of cmake failed");
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
- this->Internal->IsSourceFileTryCompile = false;
+ gg->EnableLanguagesFromGenerator(this->GetGlobalGenerator(), this);
+ if (this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
+ cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", "",
+ cmStateEnums::INTERNAL);
+ } else {
+ cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE", "",
+ cmStateEnums::INTERNAL);
+ }
+ if (cm.Configure() != 0) {
+ this->IssueMessage(cmake::FATAL_ERROR,
+ "Failed to configure test project build system.");
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
return 1;
- }
+ }
- if (cm.Generate() != 0)
- {
- cmSystemTools::Error(
- "Internal CMake error, TryCompile generation of cmake failed");
- // return to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
- this->Internal->IsSourceFileTryCompile = false;
+ if (cm.Generate() != 0) {
+ this->IssueMessage(cmake::FATAL_ERROR,
+ "Failed to generate test project build system.");
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
return 1;
- }
+ }
// finally call the generator to actually build the resulting project
- int ret =
- this->LocalGenerator->GetGlobalGenerator()->TryCompile(srcdir,bindir,
- projectName,
- targetName,
- fast,
- output,
- this);
-
- cmSystemTools::ChangeDirectory(cwd.c_str());
- this->Internal->IsSourceFileTryCompile = false;
+ int ret = this->GetGlobalGenerator()->TryCompile(
+ srcdir, bindir, projectName, targetName, fast, output, this);
+
+ this->IsSourceFileTryCompile = false;
return ret;
}
bool cmMakefile::GetIsSourceFileTryCompile() const
{
- return this->Internal->IsSourceFileTryCompile;
+ return this->IsSourceFileTryCompile;
}
-cmake *cmMakefile::GetCMakeInstance() const
+cmake* cmMakefile::GetCMakeInstance() const
{
- if ( this->LocalGenerator && this->LocalGenerator->GetGlobalGenerator() )
- {
- return this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance();
- }
- return 0;
+ return this->GlobalGenerator->GetCMakeInstance();
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
-cmVariableWatch *cmMakefile::GetVariableWatch() const
+cmMessenger* cmMakefile::GetMessenger() const
{
- if ( this->GetCMakeInstance() &&
- this->GetCMakeInstance()->GetVariableWatch() )
- {
- return this->GetCMakeInstance()->GetVariableWatch();
- }
- return 0;
+ return this->GetCMakeInstance()->GetMessenger();
}
-#endif
-void cmMakefile::AddMacro(const char* name, const char* signature)
+cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const
{
- if ( !name || !signature )
- {
- return;
- }
- this->MacrosMap[name] = signature;
+ return this->GlobalGenerator;
}
-void cmMakefile::GetListOfMacros(std::string& macros)
+#ifdef CMAKE_BUILD_WITH_CMAKE
+cmVariableWatch* cmMakefile::GetVariableWatch() const
{
- StringStringMap::iterator it;
- macros = "";
- int cc = 0;
- for ( it = this->MacrosMap.begin(); it != this->MacrosMap.end(); ++it )
- {
- if ( cc > 0 )
- {
- macros += ";";
- }
- macros += it->first;
- cc ++;
- }
+ if (this->GetCMakeInstance() &&
+ this->GetCMakeInstance()->GetVariableWatch()) {
+ return this->GetCMakeInstance()->GetVariableWatch();
+ }
+ return CM_NULLPTR;
}
+#endif
-cmCacheManager *cmMakefile::GetCacheManager() const
+cmState* cmMakefile::GetState() const
{
- return this->GetCMakeInstance()->GetCacheManager();
+ return this->GetCMakeInstance()->GetState();
}
-void cmMakefile::DisplayStatus(const char* message, float s)
+void cmMakefile::DisplayStatus(const char* message, float s) const
{
- cmake* cm = this->GetLocalGenerator()->GetGlobalGenerator()
- ->GetCMakeInstance();
- if (cm->GetWorkingMode() == cmake::FIND_PACKAGE_MODE)
- {
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) {
// don't output any STATUS message in FIND_PACKAGE_MODE, since they will
// directly be fed to the compiler, which will be confused.
return;
- }
+ }
cm->UpdateProgress(message, s);
}
-std::string cmMakefile::GetModulesFile(const char* filename)
+std::string cmMakefile::GetModulesFile(const char* filename) const
{
std::string result;
@@ -3293,68 +3341,58 @@ std::string cmMakefile::GetModulesFile(const char* filename)
// Always search in CMAKE_MODULE_PATH:
const char* cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH");
- if(cmakeModulePath)
- {
+ if (cmakeModulePath) {
std::vector<std::string> modulePath;
cmSystemTools::ExpandListArgument(cmakeModulePath, modulePath);
- //Look through the possible module directories.
- for(std::vector<std::string>::iterator i = modulePath.begin();
- i != modulePath.end(); ++i)
- {
+ // Look through the possible module directories.
+ for (std::vector<std::string>::iterator i = modulePath.begin();
+ i != modulePath.end(); ++i) {
std::string itempl = *i;
cmSystemTools::ConvertToUnixSlashes(itempl);
itempl += "/";
itempl += filename;
- if(cmSystemTools::FileExists(itempl.c_str()))
- {
+ if (cmSystemTools::FileExists(itempl.c_str())) {
moduleInCMakeModulePath = itempl;
break;
- }
}
}
+ }
// Always search in the standard modules location.
- const char* cmakeRoot = this->GetDefinition("CMAKE_ROOT");
- if(cmakeRoot)
- {
- moduleInCMakeRoot = cmakeRoot;
- moduleInCMakeRoot += "/Modules/";
- moduleInCMakeRoot += filename;
- cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot);
- if(!cmSystemTools::FileExists(moduleInCMakeRoot.c_str()))
- {
- moduleInCMakeRoot = "";
- }
- }
+ moduleInCMakeRoot = cmSystemTools::GetCMakeRoot();
+ moduleInCMakeRoot += "/Modules/";
+ moduleInCMakeRoot += filename;
+ cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot);
+ if (!cmSystemTools::FileExists(moduleInCMakeRoot.c_str())) {
+ moduleInCMakeRoot = "";
+ }
// 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.
result = moduleInCMakeModulePath;
- if (result.size() == 0)
- {
+ if (result.empty()) {
result = moduleInCMakeRoot;
- }
+ }
- if ((moduleInCMakeModulePath.size()>0) && (moduleInCMakeRoot.size()>0))
- {
+ if (!moduleInCMakeModulePath.empty() && !moduleInCMakeRoot.empty()) {
const char* currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE");
- if (currentFile && (strstr(currentFile, cmakeRoot) == currentFile))
- {
- switch (this->GetPolicyStatus(cmPolicies::CMP0017))
- {
- case cmPolicies::WARN:
- {
- cmOStringStream e;
+ std::string mods = cmSystemTools::GetCMakeRoot() + "/Modules/";
+ if (currentFile && cmSystemTools::IsSubDirectory(currentFile, mods)) {
+ switch (this->GetPolicyStatus(cmPolicies::CMP0017)) {
+ case cmPolicies::WARN: {
+ std::ostringstream e;
+ /* clang-format off */
e << "File " << currentFile << " includes "
<< moduleInCMakeModulePath
<< " (found via CMAKE_MODULE_PATH) which shadows "
<< moduleInCMakeRoot << ". This may cause errors later on .\n"
- << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0017);
+ << cmPolicies::GetPolicyWarning(cmPolicies::CMP0017);
+ /* clang-format on */
this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
- // break; // fall through to OLD behaviour
+ CM_FALLTHROUGH;
}
case cmPolicies::OLD:
result = moduleInCMakeModulePath;
@@ -3362,1087 +3400,465 @@ std::string cmMakefile::GetModulesFile(const char* filename)
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
- default:
result = moduleInCMakeRoot;
break;
- }
}
}
+ }
return result;
}
-void cmMakefile::ConfigureString(const std::string& input,
- std::string& output, bool atOnly,
- bool escapeQuotes)
+void cmMakefile::ConfigureString(const std::string& input, std::string& output,
+ bool atOnly, bool escapeQuotes) const
{
// Split input to handle one line at a time.
std::string::const_iterator lineStart = input.begin();
- while(lineStart != input.end())
- {
+ while (lineStart != input.end()) {
// Find the end of this line.
std::string::const_iterator lineEnd = lineStart;
- while(lineEnd != input.end() && *lineEnd != '\n')
- {
+ while (lineEnd != input.end() && *lineEnd != '\n') {
++lineEnd;
- }
+ }
// Copy the line.
std::string line(lineStart, lineEnd);
// Skip the newline character.
bool haveNewline = (lineEnd != input.end());
- if(haveNewline)
- {
+ if (haveNewline) {
++lineEnd;
- }
+ }
// Replace #cmakedefine instances.
- if(this->cmDefineRegex.find(line))
- {
- const char* def =
- this->GetDefinition(this->cmDefineRegex.match(1).c_str());
- if(!cmSystemTools::IsOff(def))
- {
+ if (this->cmDefineRegex.find(line)) {
+ const char* def = this->GetDefinition(this->cmDefineRegex.match(1));
+ if (!cmSystemTools::IsOff(def)) {
cmSystemTools::ReplaceString(line, "#cmakedefine", "#define");
output += line;
- }
- else
- {
+ } else {
output += "/* #undef ";
output += this->cmDefineRegex.match(1);
output += " */";
- }
}
- else if(this->cmDefine01Regex.find(line))
- {
- const char* def =
- this->GetDefinition(this->cmDefine01Regex.match(1).c_str());
+ } else if (this->cmDefine01Regex.find(line)) {
+ const char* def = this->GetDefinition(this->cmDefine01Regex.match(1));
cmSystemTools::ReplaceString(line, "#cmakedefine01", "#define");
output += line;
- if(!cmSystemTools::IsOff(def))
- {
+ if (!cmSystemTools::IsOff(def)) {
output += " 1";
- }
- else
- {
+ } else {
output += " 0";
- }
}
- else
- {
+ } else {
output += line;
- }
+ }
- if(haveNewline)
- {
+ if (haveNewline) {
output += "\n";
- }
+ }
// Move to the next line.
lineStart = lineEnd;
- }
+ }
// Perform variable replacements.
- this->ExpandVariablesInString(output, escapeQuotes, true,
- atOnly, 0, -1, true);
+ this->ExpandVariablesInString(output, escapeQuotes, true, atOnly, CM_NULLPTR,
+ -1, true, true);
}
int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
bool copyonly, bool atOnly, bool escapeQuotes,
- const cmNewLineStyle& newLine)
+ cmNewLineStyle newLine)
{
int res = 1;
- if ( !this->CanIWriteThisFile(outfile) )
- {
- cmSystemTools::Error("Attempt to write file: ",
- outfile, " into a source directory.");
+ if (!this->CanIWriteThisFile(outfile)) {
+ cmSystemTools::Error("Attempt to write file: ", outfile,
+ " into a source directory.");
return 0;
- }
- if ( !cmSystemTools::FileExists(infile) )
- {
+ }
+ if (!cmSystemTools::FileExists(infile)) {
cmSystemTools::Error("File ", infile, " does not exist.");
return 0;
- }
+ }
std::string soutfile = outfile;
std::string sinfile = infile;
this->AddCMakeDependFile(sinfile);
cmSystemTools::ConvertToUnixSlashes(soutfile);
// Re-generate if non-temporary outputs are missing.
- //when we finalize the configuration we will remove all
- //output files that now don't exist.
+ // when we finalize the configuration we will remove all
+ // output files that now don't exist.
this->AddCMakeOutputFile(soutfile);
mode_t perm = 0;
cmSystemTools::GetPermissions(sinfile.c_str(), perm);
std::string::size_type pos = soutfile.rfind('/');
- if(pos != std::string::npos)
- {
+ if (pos != std::string::npos) {
std::string path = soutfile.substr(0, pos);
cmSystemTools::MakeDirectory(path.c_str());
- }
+ }
- if(copyonly)
- {
- if ( !cmSystemTools::CopyFileIfDifferent(sinfile.c_str(),
- soutfile.c_str()))
- {
+ if (copyonly) {
+ if (!cmSystemTools::CopyFileIfDifferent(sinfile.c_str(),
+ soutfile.c_str())) {
return 0;
- }
}
- else
- {
+ } else {
std::string newLineCharacters;
- std::ios_base::openmode omode = std::ios_base::out | std::ios_base::trunc;
- if (newLine.IsValid())
- {
+ std::ios::openmode omode = std::ios::out | std::ios::trunc;
+ if (newLine.IsValid()) {
newLineCharacters = newLine.GetCharacters();
omode |= std::ios::binary;
- }
- else
- {
+ } else {
newLineCharacters = "\n";
- }
+ }
std::string tempOutputFile = soutfile;
tempOutputFile += ".tmp";
- std::ofstream fout(tempOutputFile.c_str(), omode);
- if(!fout)
- {
- cmSystemTools::Error(
- "Could not open file for write in copy operation ",
- tempOutputFile.c_str());
+ cmsys::ofstream fout(tempOutputFile.c_str(), omode);
+ if (!fout) {
+ cmSystemTools::Error("Could not open file for write in copy operation ",
+ tempOutputFile.c_str());
cmSystemTools::ReportLastSystemError("");
return 0;
- }
- std::ifstream fin(sinfile.c_str());
- if(!fin)
- {
+ }
+ cmsys::ifstream fin(sinfile.c_str());
+ if (!fin) {
cmSystemTools::Error("Could not open file for read in copy operation ",
sinfile.c_str());
return 0;
- }
+ }
+
+ cmsys::FStream::BOM bom = cmsys::FStream::ReadBOM(fin);
+ if (bom != cmsys::FStream::BOM_None && bom != cmsys::FStream::BOM_UTF8) {
+ 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());
+ return 0;
+ }
+ // rewind to copy BOM to output file
+ fin.seekg(0);
// now copy input to output and expand variables in the
// input file at the same time
std::string inLine;
std::string outLine;
- while( cmSystemTools::GetLineFromStream(fin, inLine) )
- {
+ while (cmSystemTools::GetLineFromStream(fin, inLine)) {
outLine = "";
this->ConfigureString(inLine, outLine, atOnly, escapeQuotes);
- fout << outLine.c_str() << newLineCharacters;
- }
+ 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.c_str(),
+ soutfile.c_str())) {
res = 0;
- }
- else
- {
+ } else {
cmSystemTools::SetPermissions(soutfile.c_str(), perm);
- }
- cmSystemTools::RemoveFile(tempOutputFile.c_str());
}
+ cmSystemTools::RemoveFile(tempOutputFile);
+ }
return res;
}
-void cmMakefile::SetProperty(const char* prop, const char* value)
+void cmMakefile::SetProperty(const std::string& prop, const char* value)
{
- if (!prop)
- {
- return;
- }
-
- // handle special props
- std::string propname = prop;
-
- if ( propname == "LINK_DIRECTORIES" )
- {
- std::vector<std::string> varArgsExpanded;
- if(value)
- {
- cmSystemTools::ExpandListArgument(value, varArgsExpanded);
- }
- this->SetLinkDirectories(varArgsExpanded);
- return;
- }
- if (propname == "INCLUDE_DIRECTORIES")
- {
- this->IncludeDirectoriesEntries.clear();
- if (!value)
- {
- return;
- }
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- this->IncludeDirectoriesEntries.push_back(
- cmValueWithOrigin(value, lfbt));
- return;
- }
- if (propname == "COMPILE_OPTIONS")
- {
- this->CompileOptionsEntries.clear();
- if (!value)
- {
- return;
- }
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- this->CompileOptionsEntries.push_back(cmValueWithOrigin(value, lfbt));
- return;
- }
- if (propname == "COMPILE_DEFINITIONS")
- {
- this->CompileDefinitionsEntries.clear();
- if (!value)
- {
- return;
- }
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- cmValueWithOrigin entry(value, lfbt);
- this->CompileDefinitionsEntries.push_back(entry);
- return;
- }
-
- if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
- {
- this->SetIncludeRegularExpression(value);
- return;
- }
-
- if ( propname == "ADDITIONAL_MAKE_CLEAN_FILES" )
- {
- // This property is not inherrited
- if ( strcmp(this->GetCurrentDirectory(),
- this->GetStartDirectory()) != 0 )
- {
- return;
- }
- }
-
- this->Properties.SetProperty(prop,value,cmProperty::DIRECTORY);
+ cmListFileBacktrace lfbt = this->GetBacktrace();
+ this->StateSnapshot.GetDirectory().SetProperty(prop, value, lfbt);
}
-void cmMakefile::AppendProperty(const char* prop, const char* value,
+void cmMakefile::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
- if (!prop)
- {
- return;
- }
-
- // handle special props
- std::string propname = prop;
-
- if (propname == "INCLUDE_DIRECTORIES")
- {
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- this->IncludeDirectoriesEntries.push_back(
- cmValueWithOrigin(value, lfbt));
- return;
- }
- if (propname == "COMPILE_OPTIONS")
- {
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- this->CompileOptionsEntries.push_back(
- cmValueWithOrigin(value, lfbt));
- return;
- }
- if (propname == "COMPILE_DEFINITIONS")
- {
- cmListFileBacktrace lfbt;
- this->GetBacktrace(lfbt);
- this->CompileDefinitionsEntries.push_back(
- cmValueWithOrigin(value, lfbt));
- return;
- }
- if ( propname == "LINK_DIRECTORIES" )
- {
- std::vector<std::string> varArgsExpanded;
- cmSystemTools::ExpandListArgument(value, varArgsExpanded);
- for(std::vector<std::string>::const_iterator vi = varArgsExpanded.begin();
- vi != varArgsExpanded.end(); ++vi)
- {
- this->AddLinkDirectory(vi->c_str());
- }
- return;
- }
-
- this->Properties.AppendProperty(prop,value,cmProperty::DIRECTORY,asString);
+ cmListFileBacktrace lfbt = this->GetBacktrace();
+ this->StateSnapshot.GetDirectory().AppendProperty(prop, value, asString,
+ lfbt);
}
-const char *cmMakefile::GetPropertyOrDefinition(const char* prop)
+const char* cmMakefile::GetProperty(const std::string& prop) const
{
- const char *ret = this->GetProperty(prop, cmProperty::DIRECTORY);
- if (!ret)
- {
- ret = this->GetDefinition(prop);
- }
- return ret;
+ return this->StateSnapshot.GetDirectory().GetProperty(prop);
}
-const char *cmMakefile::GetProperty(const char* prop)
+const char* cmMakefile::GetProperty(const std::string& prop, bool chain) const
{
- return this->GetProperty(prop, cmProperty::DIRECTORY);
+ return this->StateSnapshot.GetDirectory().GetProperty(prop, chain);
}
-const char *cmMakefile::GetProperty(const char* prop,
- cmProperty::ScopeType scope)
-{
- if(!prop)
- {
- return 0;
- }
- // watch for specific properties
- static std::string output;
- output = "";
- if (!strcmp("PARENT_DIRECTORY",prop))
- {
- if(cmLocalGenerator* plg = this->LocalGenerator->GetParent())
- {
- output = plg->GetMakefile()->GetStartDirectory();
- }
- return output.c_str();
- }
- else if (!strcmp("INCLUDE_REGULAR_EXPRESSION",prop) )
- {
- output = this->GetIncludeRegularExpression();
- return output.c_str();
- }
- else if (!strcmp("LISTFILE_STACK",prop))
- {
- for (std::deque<cmStdString>::iterator i = this->ListFileStack.begin();
- i != this->ListFileStack.end(); ++i)
- {
- if (i != this->ListFileStack.begin())
- {
- output += ";";
- }
- output += *i;
- }
- return output.c_str();
- }
- else if (!strcmp("VARIABLES",prop) || !strcmp("CACHE_VARIABLES",prop))
- {
- int cacheonly = 0;
- if ( !strcmp("CACHE_VARIABLES",prop) )
- {
- cacheonly = 1;
- }
- std::vector<std::string> vars = this->GetDefinitions(cacheonly);
- for (unsigned int cc = 0; cc < vars.size(); cc ++ )
- {
- if ( cc > 0 )
- {
- output += ";";
- }
- output += vars[cc];
- }
- return output.c_str();
- }
- else if (!strcmp("MACROS",prop))
- {
- this->GetListOfMacros(output);
- return output.c_str();
- }
- else if (!strcmp("DEFINITIONS",prop))
- {
- output += this->DefineFlagsOrig;
- return output.c_str();
- }
- else if (!strcmp("LINK_DIRECTORIES",prop))
- {
- cmOStringStream str;
- for (std::vector<std::string>::const_iterator
- it = this->GetLinkDirectories().begin();
- it != this->GetLinkDirectories().end();
- ++ it )
- {
- if ( it != this->GetLinkDirectories().begin())
- {
- str << ";";
- }
- str << it->c_str();
- }
- output = str.str();
- return output.c_str();
- }
- else if (!strcmp("INCLUDE_DIRECTORIES",prop))
- {
- std::string sep;
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->IncludeDirectoriesEntries.begin(),
- end = this->IncludeDirectoriesEntries.end();
- it != end; ++it)
- {
- output += sep;
- output += it->Value;
- sep = ";";
- }
- return output.c_str();
- }
- else if (!strcmp("COMPILE_OPTIONS",prop))
- {
- std::string sep;
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->CompileOptionsEntries.begin(),
- end = this->CompileOptionsEntries.end();
- it != end; ++it)
- {
- output += sep;
- output += it->Value;
- sep = ";";
- }
- return output.c_str();
- }
- else if (!strcmp("COMPILE_DEFINITIONS",prop))
- {
- std::string sep;
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->CompileDefinitionsEntries.begin(),
- end = this->CompileDefinitionsEntries.end();
- it != end; ++it)
- {
- output += sep;
- output += it->Value;
- sep = ";";
- }
- return output.c_str();
- }
-
- bool chain = false;
- const char *retVal =
- this->Properties.GetPropertyValue(prop, scope, chain);
- if (chain)
- {
- if(this->LocalGenerator->GetParent())
- {
- return this->LocalGenerator->GetParent()->GetMakefile()->
- GetProperty(prop, scope);
- }
- return this->GetCMakeInstance()->GetProperty(prop,scope);
- }
-
- return retVal;
-}
-
-bool cmMakefile::GetPropertyAsBool(const char* prop)
+bool cmMakefile::GetPropertyAsBool(const std::string& prop) const
{
return cmSystemTools::IsOn(this->GetProperty(prop));
}
-//----------------------------------------------------------------------------
-const char* cmMakefile::GetFeature(const char* feature, const char* config)
+std::vector<std::string> cmMakefile::GetPropertyKeys() const
{
- // TODO: Define accumulation policy for features (prepend, append, replace).
- // Currently we always replace.
- if(config && *config)
- {
- std::string featureConfig = feature;
- featureConfig += "_";
- featureConfig += cmSystemTools::UpperCase(config);
- if(const char* value = this->GetProperty(featureConfig.c_str()))
- {
- return value;
- }
- }
- if(const char* value = this->GetProperty(feature))
- {
- return value;
- }
- if(cmLocalGenerator* parent = this->LocalGenerator->GetParent())
- {
- return parent->GetMakefile()->GetFeature(feature, config);
- }
- return 0;
+ return this->StateSnapshot.GetDirectory().GetPropertyKeys();
}
-cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases)
+cmTarget* cmMakefile::FindLocalNonAliasTarget(const std::string& name) const
{
- if (!excludeAliases)
- {
- std::map<std::string, cmTarget*>::iterator i
- = this->AliasTargets.find(name);
- if (i != this->AliasTargets.end())
- {
- return i->second;
- }
- }
- cmTargets& tgts = this->GetTargets();
-
- cmTargets::iterator i = tgts.find ( name );
- if ( i != tgts.end() )
- {
+ cmTargets::iterator i = this->Targets.find(name);
+ if (i != this->Targets.end()) {
return &i->second;
- }
-
- return 0;
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-cmTest* cmMakefile::CreateTest(const char* testName)
+cmTest* cmMakefile::CreateTest(const std::string& testName)
{
- if ( !testName )
- {
- return 0;
- }
cmTest* test = this->GetTest(testName);
- if ( test )
- {
+ if (test) {
return test;
- }
+ }
test = new cmTest(this);
test->SetName(testName);
this->Tests[testName] = test;
return test;
}
-//----------------------------------------------------------------------------
-cmTest* cmMakefile::GetTest(const char* testName) const
+cmTest* cmMakefile::GetTest(const std::string& testName) const
{
- if(testName)
- {
- std::map<cmStdString, cmTest*>::const_iterator
- mi = this->Tests.find(testName);
- if(mi != this->Tests.end())
- {
- return mi->second;
- }
+ std::map<std::string, cmTest*>::const_iterator mi =
+ this->Tests.find(testName);
+ if (mi != this->Tests.end()) {
+ return mi->second;
+ }
+ return CM_NULLPTR;
+}
+
+void cmMakefile::AddCMakeDependFilesFromUser()
+{
+ std::vector<std::string> deps;
+ if (const char* deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) {
+ cmSystemTools::ExpandListArgument(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);
+ } else {
+ std::string f = this->GetCurrentSourceDirectory();
+ f += "/";
+ f += *i;
+ this->AddCMakeDependFile(f);
}
- return 0;
+ }
}
-std::string cmMakefile::GetListFileStack()
+std::string cmMakefile::FormatListFileStack() const
{
- cmOStringStream tmp;
- size_t depth = this->ListFileStack.size();
- if (depth > 0)
- {
- std::deque<cmStdString>::iterator it = this->ListFileStack.end();
- do
- {
- if (depth != this->ListFileStack.size())
- {
+ std::vector<std::string> listFiles;
+ cmStateSnapshot snp = this->StateSnapshot;
+ while (snp.IsValid()) {
+ listFiles.push_back(snp.GetExecutionListFile());
+ snp = snp.GetCallStackParent();
+ }
+ std::reverse(listFiles.begin(), listFiles.end());
+ std::ostringstream tmp;
+ size_t depth = listFiles.size();
+ if (depth > 0) {
+ std::vector<std::string>::const_iterator it = listFiles.end();
+ do {
+ if (depth != listFiles.size()) {
tmp << "\n ";
- }
+ }
--it;
tmp << "[";
tmp << depth;
tmp << "]\t";
tmp << *it;
depth--;
- }
- while (it != this->ListFileStack.begin());
- }
+ } while (it != listFiles.begin());
+ }
return tmp.str();
}
-
void cmMakefile::PushScope()
{
- cmDefinitions* parent = &this->Internal->VarStack.top();
- const std::set<cmStdString>& init = this->Internal->VarInitStack.top();
- const std::set<cmStdString>& usage = this->Internal->VarUsageStack.top();
- this->Internal->VarStack.push(cmDefinitions(parent));
- this->Internal->VarInitStack.push(init);
- this->Internal->VarUsageStack.push(usage);
+ this->StateSnapshot =
+ this->GetState()->CreateVariableScopeSnapshot(this->StateSnapshot);
+ this->PushLoopBlockBarrier();
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope();
+#endif
}
void cmMakefile::PopScope()
{
- cmDefinitions* current = &this->Internal->VarStack.top();
- std::set<cmStdString> init = this->Internal->VarInitStack.top();
- std::set<cmStdString> usage = this->Internal->VarUsageStack.top();
- const std::set<cmStdString>& locals = current->LocalKeys();
- // Remove initialization and usage information for variables in the local
- // scope.
- std::set<cmStdString>::const_iterator it = locals.begin();
- for (; it != locals.end(); ++it)
- {
- init.erase(*it);
- if (!this->VariableUsed(it->c_str()))
- {
- this->CheckForUnused("out of scope", it->c_str());
- }
- else
- {
- usage.erase(*it);
- }
- }
- this->Internal->VarStack.pop();
- this->Internal->VarInitStack.pop();
- this->Internal->VarUsageStack.pop();
- // Push initialization and usage up to the parent scope.
- it = init.begin();
- for (; it != init.end(); ++it)
- {
- this->Internal->VarInitStack.top().insert(*it);
- }
- it = usage.begin();
- for (; it != usage.end(); ++it)
- {
- this->Internal->VarUsageStack.top().insert(*it);
- }
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope();
+#endif
+
+ this->PopLoopBlockBarrier();
+
+ this->CheckForUnusedVariables();
+
+ this->PopSnapshot();
}
-void cmMakefile::RaiseScope(const char *var, const char *varDef)
+void cmMakefile::RaiseScope(const std::string& var, const char* varDef)
{
- if (!var || !strlen(var))
- {
+ if (var.empty()) {
return;
- }
-
- cmDefinitions& cur = this->Internal->VarStack.top();
- if(cmDefinitions* up = cur.GetParent())
- {
- // First localize the definition in the current scope.
- cur.Get(var);
+ }
- // Now update the definition in the parent scope.
- up->Set(var, varDef);
- }
- else if(cmLocalGenerator* plg = this->LocalGenerator->GetParent())
- {
- // Update the definition in the parent directory top scope. This
- // directory's scope was initialized by the closure of the parent
- // scope, so we do not need to localize the definition first.
- cmMakefile* parent = plg->GetMakefile();
- if (varDef)
- {
- parent->AddDefinition(var, varDef);
- }
- else
- {
- parent->RemoveDefinition(var);
- }
- }
- else
- {
- cmOStringStream m;
+ 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());
- }
+ }
}
-
-// define properties
-void cmMakefile::DefineProperties(cmake *cm)
-{
- cm->DefineProperty
- ("ADDITIONAL_MAKE_CLEAN_FILES", cmProperty::DIRECTORY,
- "Additional files to clean during the make clean stage.",
- "A list of files that will be cleaned as a part of the "
- "\"make clean\" stage. ");
-
- cm->DefineProperty
- ("CLEAN_NO_CUSTOM", cmProperty::DIRECTORY,
- "Should the output of custom commands be left.",
- "If this is true then the outputs of custom commands for this "
- "directory will not be removed during the \"make clean\" stage. ");
-
- cm->DefineProperty
- ("LISTFILE_STACK", cmProperty::DIRECTORY,
- "The current stack of listfiles being processed.",
- "This property is mainly useful when trying to debug errors "
- "in your CMake scripts. It returns a list of what list files "
- "are currently being processed, in order. So if one listfile "
- "does an INCLUDE command then that is effectively pushing "
- "the included listfile onto the stack.", false);
-
- cm->DefineProperty
- ("TEST_INCLUDE_FILE", cmProperty::DIRECTORY,
- "A cmake file that will be included when ctest is run.",
- "If you specify TEST_INCLUDE_FILE, that file will be "
- "included and processed when ctest is run on the directory.");
-
- cm->DefineProperty
- ("COMPILE_DEFINITIONS", cmProperty::DIRECTORY,
- "Preprocessor definitions for compiling a directory's sources.",
- "The COMPILE_DEFINITIONS property may be set to a "
- "semicolon-separated list of preprocessor "
- "definitions using the syntax VAR or VAR=value. Function-style "
- "definitions are not supported. CMake will automatically escape "
- "the value correctly for the native build system (note that CMake "
- "language syntax may require escapes to specify some values). "
- "This property may be set on a per-configuration basis using the name "
- "COMPILE_DEFINITIONS_<CONFIG> where <CONFIG> is an upper-case name "
- "(ex. \"COMPILE_DEFINITIONS_DEBUG\"). "
- "This property will be initialized in each directory by its value "
- "in the directory's parent.\n"
- "CMake will automatically drop some definitions that "
- "are not supported by the native build tool. "
- "The VS6 IDE does not support definition values with spaces "
- "(but NMake does).\n"
- CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
-
- cm->DefineProperty
- ("COMPILE_DEFINITIONS_<CONFIG>", cmProperty::DIRECTORY,
- "Per-configuration preprocessor definitions in a directory.",
- "This is the configuration-specific version of COMPILE_DEFINITIONS. "
- "This property will be initialized in each directory by its value "
- "in the directory's parent.\n");
-
- cm->DefineProperty
- ("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM", cmProperty::DIRECTORY,
- "Specify #include line transforms for dependencies in a directory.",
- "This property specifies rules to transform macro-like #include lines "
- "during implicit dependency scanning of C and C++ source files. "
- "The list of rules must be semicolon-separated with each entry of "
- "the form \"A_MACRO(%)=value-with-%\" (the % must be literal). "
- "During dependency scanning occurrences of A_MACRO(...) on #include "
- "lines will be replaced by the value given with the macro argument "
- "substituted for '%'. For example, the entry\n"
- " MYDIR(%)=<mydir/%>\n"
- "will convert lines of the form\n"
- " #include MYDIR(myheader.h)\n"
- "to\n"
- " #include <mydir/myheader.h>\n"
- "allowing the dependency to be followed.\n"
- "This property applies to sources in all targets within a directory. "
- "The property value is initialized in each directory by its value "
- "in the directory's parent.");
-
- cm->DefineProperty
- ("EXCLUDE_FROM_ALL", cmProperty::DIRECTORY,
- "Exclude the directory from the all target of its parent.",
- "A property on a directory that indicates if its targets are excluded "
- "from the default build target. If it is not, then with a Makefile "
- "for example typing make will cause the targets to be built. "
- "The same concept applies to the default build of other generators.",
- false);
-
- cm->DefineProperty
- ("PARENT_DIRECTORY", cmProperty::DIRECTORY,
- "Source directory that added current subdirectory.",
- "This read-only property specifies the source directory that "
- "added the current source directory as a subdirectory of the build. "
- "In the top-level directory the value is the empty-string.", false);
-
- cm->DefineProperty
- ("INCLUDE_REGULAR_EXPRESSION", cmProperty::DIRECTORY,
- "Include file scanning regular expression.",
- "This read-only property specifies the regular expression used "
- "during dependency scanning to match include files that should "
- "be followed. See the include_regular_expression command.", false);
-
- cm->DefineProperty
- ("INTERPROCEDURAL_OPTIMIZATION", cmProperty::DIRECTORY,
- "Enable interprocedural optimization for targets in a directory.",
- "If set to true, enables interprocedural optimizations "
- "if they are known to be supported by the compiler.");
-
- cm->DefineProperty
- ("INTERPROCEDURAL_OPTIMIZATION_<CONFIG>", cmProperty::DIRECTORY,
- "Per-configuration interprocedural optimization for a directory.",
- "This is a per-configuration version of INTERPROCEDURAL_OPTIMIZATION. "
- "If set, this property overrides the generic property "
- "for the named configuration.");
-
- cm->DefineProperty
- ("VARIABLES", cmProperty::DIRECTORY,
- "List of variables defined in the current directory.",
- "This read-only property specifies the list of CMake variables "
- "currently defined. "
- "It is intended for debugging purposes.", false);
-
- cm->DefineProperty
- ("CACHE_VARIABLES", cmProperty::DIRECTORY,
- "List of cache variables available in the current directory.",
- "This read-only property specifies the list of CMake cache "
- "variables currently defined. "
- "It is intended for debugging purposes.", false);
-
- cm->DefineProperty
- ("MACROS", cmProperty::DIRECTORY,
- "List of macro commands available in the current directory.",
- "This read-only property specifies the list of CMake macros "
- "currently defined. "
- "It is intended for debugging purposes. "
- "See the macro command.", false);
-
- cm->DefineProperty
- ("DEFINITIONS", cmProperty::DIRECTORY,
- "For CMake 2.4 compatibility only. Use COMPILE_DEFINITIONS instead.",
- "This read-only property specifies the list of flags given so far "
- "to the add_definitions command. "
- "It is intended for debugging purposes. "
- "Use the COMPILE_DEFINITIONS instead.", false);
-
- cm->DefineProperty
- ("INCLUDE_DIRECTORIES", cmProperty::DIRECTORY,
- "List of preprocessor include file search directories.",
- "This property specifies the list of directories given "
- "so far to the include_directories command. "
- "This property exists on directories and targets. "
- "In addition to accepting values from the include_directories "
- "command, values may be set directly on any directory or any "
- "target using the set_property command. "
- "A target gets its initial value for this property from the value "
- "of the directory property. "
- "A directory gets its initial value from its parent directory if "
- "it has one. "
- "Both directory and target property values are adjusted by calls "
- "to the include_directories command."
- "\n"
- "The target property values are used by the generators to set "
- "the include paths for the compiler. "
- "See also the include_directories command.");
-
- cm->DefineProperty
- ("COMPILE_OPTIONS", cmProperty::DIRECTORY,
- "List of options to pass to the compiler.",
- "This property specifies the list of directories given "
- "so far for this property. "
- "This property exists on directories and targets."
- "\n"
- "The target property values are used by the generators to set "
- "the options for the compiler.\n"
- "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
- "the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("LINK_DIRECTORIES", cmProperty::DIRECTORY,
- "List of linker search directories.",
- "This read-only property specifies the list of directories given "
- "so far to the link_directories command. "
- "It is intended for debugging purposes.", false);
-
- cm->DefineProperty
- ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY,
- "Specify a launcher for compile rules.",
- "See the global property of the same name for details. "
- "This overrides the global property for a directory.",
- true);
- cm->DefineProperty
- ("RULE_LAUNCH_LINK", cmProperty::DIRECTORY,
- "Specify a launcher for link rules.",
- "See the global property of the same name for details. "
- "This overrides the global property for a directory.",
- true);
- cm->DefineProperty
- ("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY,
- "Specify a launcher for custom rules.",
- "See the global property of the same name for details. "
- "This overrides the global property for a directory.",
- true);
-
- cm->DefineProperty
- ("VS_GLOBAL_SECTION_PRE_<section>", cmProperty::DIRECTORY,
- "Specify a preSolution global section in Visual Studio.",
- "Setting a property like this generates an entry of the following form "
- "in the solution file:\n"
- " GlobalSection(<section>) = preSolution\n"
- " <contents based on property value>\n"
- " EndGlobalSection\n"
- "The property must be set to a semicolon-separated list of key=value "
- "pairs. Each such pair will be transformed into an entry in the solution "
- "global section. Whitespace around key and value is ignored. List "
- "elements which do not contain an equal sign are skipped."
- "\n"
- "This property only works for Visual Studio 7 and above; it is ignored "
- "on other generators. The property only applies when set on a directory "
- "whose CMakeLists.txt contains a project() command.");
- cm->DefineProperty
- ("VS_GLOBAL_SECTION_POST_<section>", cmProperty::DIRECTORY,
- "Specify a postSolution global section in Visual Studio.",
- "Setting a property like this generates an entry of the following form "
- "in the solution file:\n"
- " GlobalSection(<section>) = postSolution\n"
- " <contents based on property value>\n"
- " EndGlobalSection\n"
- "The property must be set to a semicolon-separated list of key=value "
- "pairs. Each such pair will be transformed into an entry in the solution "
- "global section. Whitespace around key and value is ignored. List "
- "elements which do not contain an equal sign are skipped."
- "\n"
- "This property only works for Visual Studio 7 and above; it is ignored "
- "on other generators. The property only applies when set on a directory "
- "whose CMakeLists.txt contains a project() command."
- "\n"
- "Note that CMake generates postSolution sections ExtensibilityGlobals "
- "and ExtensibilityAddIns by default. If you set the corresponding "
- "property, it will override the default section. For example, setting "
- "VS_GLOBAL_SECTION_POST_ExtensibilityGlobals will override the default "
- "contents of the ExtensibilityGlobals section, while keeping "
- "ExtensibilityAddIns on its default.");
-}
-
-//----------------------------------------------------------------------------
-cmTarget*
-cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type,
- bool global)
+cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
+ cmStateEnums::TargetType type,
+ bool global)
{
// Create the target.
- cmsys::auto_ptr<cmTarget> target(new cmTarget);
- target->SetType(type, name);
- target->SetMakefile(this);
- target->MarkAsImported();
+ CM_AUTO_PTR<cmTarget> target(
+ new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally
+ : cmTarget::VisibilityImported,
+ this));
// Add to the set of available imported targets.
this->ImportedTargets[name] = target.get();
- if(global)
- {
- this->LocalGenerator->GetGlobalGenerator()->AddTarget(target.get());
- }
+ this->GetGlobalGenerator()->IndexTarget(target.get());
// Transfer ownership to this cmMakefile object.
this->ImportedTargetsOwned.push_back(target.get());
return target.release();
}
-//----------------------------------------------------------------------------
-cmTarget* cmMakefile::FindTargetToUse(const char* name, bool excludeAliases)
+cmTarget* cmMakefile::FindTargetToUse(const std::string& name,
+ bool excludeAliases) const
{
// Look for an imported target. These take priority because they
// are more local in scope and do not have to be globally unique.
- std::map<cmStdString, cmTarget*>::const_iterator
- imported = this->ImportedTargets.find(name);
- if(imported != this->ImportedTargets.end())
- {
+ TargetMap::const_iterator imported = this->ImportedTargets.find(name);
+ if (imported != this->ImportedTargets.end()) {
return imported->second;
- }
+ }
// Look for a target built in this directory.
- if(cmTarget* t = this->FindTarget(name, excludeAliases))
- {
+ if (cmTarget* t = this->FindLocalNonAliasTarget(name)) {
return t;
- }
+ }
// Look for a target built in this project.
- return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name,
- excludeAliases);
+ return this->GetGlobalGenerator()->FindTarget(name, excludeAliases);
}
-//----------------------------------------------------------------------------
-bool cmMakefile::IsAlias(const char *name)
+bool cmMakefile::IsAlias(const std::string& name) const
{
- if (this->AliasTargets.find(name) != this->AliasTargets.end())
+ if (this->AliasTargets.find(name) != this->AliasTargets.end()) {
return true;
- return this->GetLocalGenerator()->GetGlobalGenerator()->IsAlias(name);
-}
-
-//----------------------------------------------------------------------------
-cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
-{
- cmTarget *t = this->FindTargetToUse(name);
- return this->LocalGenerator->GetGlobalGenerator()->GetGeneratorTarget(t);
+ }
+ return this->GetGlobalGenerator()->IsAlias(name);
}
-//----------------------------------------------------------------------------
bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
- bool isCustom)
+ bool isCustom) const
{
- if(this->IsAlias(name.c_str()))
- {
- cmOStringStream e;
+ if (this->IsAlias(name)) {
+ std::ostringstream e;
e << "cannot create target \"" << name
<< "\" because an alias with the same name already exists.";
msg = e.str();
return false;
- }
- if(cmTarget* existing = this->FindTargetToUse(name.c_str()))
- {
+ }
+ if (cmTarget* existing = this->FindTargetToUse(name)) {
// The name given conflicts with an existing target. Produce an
// error in a compatible way.
- if(existing->IsImported())
- {
+ if (existing->IsImported()) {
// Imported targets were not supported in previous versions.
// This is new code, so we can make it an error.
- cmOStringStream e;
+ std::ostringstream e;
e << "cannot create target \"" << name
<< "\" because an imported target with the same name already exists.";
msg = e.str();
return false;
- }
- else
- {
- // target names must be globally unique
- switch (this->GetPolicyStatus(cmPolicies::CMP0002))
- {
- case cmPolicies::WARN:
- this->IssueMessage(cmake::AUTHOR_WARNING, this->GetPolicies()->
- GetPolicyWarning(cmPolicies::CMP0002));
- case cmPolicies::OLD:
- return true;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- this->IssueMessage(cmake::FATAL_ERROR,
- this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0002)
- );
- return true;
- case cmPolicies::NEW:
- break;
- }
-
- // The conflict is with a non-imported target.
- // Allow this if the user has requested support.
- cmake* cm =
- this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance();
- if(isCustom && existing->GetType() == cmTarget::UTILITY &&
- this != existing->GetMakefile() &&
- cm->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
- {
+ }
+ // target names must be globally unique
+ switch (this->GetPolicyStatus(cmPolicies::CMP0002)) {
+ case cmPolicies::WARN:
+ this->IssueMessage(cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0002));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
return true;
- }
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0002));
+ return true;
+ case cmPolicies::NEW:
+ break;
+ }
- // Produce an error that tells the user how to work around the
- // problem.
- cmOStringStream e;
- e << "cannot create target \"" << name
- << "\" because another target with the same name already exists. "
- << "The existing target is ";
- switch(existing->GetType())
- {
- case cmTarget::EXECUTABLE:
- e << "an executable ";
- break;
- case cmTarget::STATIC_LIBRARY:
- e << "a static library ";
- break;
- case cmTarget::SHARED_LIBRARY:
- e << "a shared library ";
- break;
- case cmTarget::MODULE_LIBRARY:
- e << "a module library ";
- break;
- case cmTarget::UTILITY:
- e << "a custom target ";
- break;
- default: break;
- }
- e << "created in source directory \""
- << existing->GetMakefile()->GetCurrentDirectory() << "\". "
- << "See documentation for policy CMP0002 for more details.";
- msg = e.str();
- return false;
- }
+ // The conflict is with a non-imported target.
+ // Allow this if the user has requested support.
+ cmake* cm = this->GetCMakeInstance();
+ if (isCustom && existing->GetType() == cmStateEnums::UTILITY &&
+ this != existing->GetMakefile() &&
+ cm->GetState()->GetGlobalPropertyAsBool(
+ "ALLOW_DUPLICATE_CUSTOM_TARGETS")) {
+ return true;
}
+
+ // Produce an error that tells the user how to work around the
+ // problem.
+ std::ostringstream e;
+ e << "cannot create target \"" << name
+ << "\" because another target with the same name already exists. "
+ << "The existing target is ";
+ switch (existing->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ e << "an executable ";
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ e << "a static library ";
+ break;
+ case cmStateEnums::SHARED_LIBRARY:
+ e << "a shared library ";
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ e << "a module library ";
+ break;
+ case cmStateEnums::UTILITY:
+ e << "a custom target ";
+ break;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ e << "an interface library ";
+ break;
+ default:
+ break;
+ }
+ e << "created in source directory \""
+ << existing->GetMakefile()->GetCurrentSourceDirectory() << "\". "
+ << "See documentation for policy CMP0002 for more details.";
+ msg = e.str();
+ return false;
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmMakefile::EnforceUniqueDir(const char* srcPath, const char* binPath)
+bool cmMakefile::EnforceUniqueDir(const std::string& srcPath,
+ const std::string& binPath) const
{
// Make sure the binary directory is unique.
- cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
- if(gg->BinaryDirectoryIsNew(binPath))
- {
+ cmGlobalGenerator* gg = this->GetGlobalGenerator();
+ if (gg->BinaryDirectoryIsNew(binPath)) {
return true;
- }
- cmOStringStream e;
- switch (this->GetPolicyStatus(cmPolicies::CMP0013))
- {
+ }
+ std::ostringstream e;
+ switch (this->GetPolicyStatus(cmPolicies::CMP0013)) {
case cmPolicies::WARN:
// Print the warning.
- e << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0013)
+ /* clang-format off */
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0013)
<< "\n"
<< "The binary directory\n"
<< " " << binPath << "\n"
@@ -4453,229 +3869,743 @@ bool cmMakefile::EnforceUniqueDir(const char* srcPath, const char* binPath)
<< "CMake does not support this use case but it used "
<< "to work accidentally and is being allowed for "
<< "compatibility.";
+ /* clang-format on */
this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior does not warn.
return true;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
- e << this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0013)
- << "\n";
+ e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0013) << "\n";
+ CM_FALLTHROUGH;
case cmPolicies::NEW:
// NEW behavior prints the error.
+ /* clang-format off */
e << "The binary directory\n"
<< " " << binPath << "\n"
<< "is already used to build a source directory. "
<< "It cannot be used to build source directory\n"
<< " " << srcPath << "\n"
<< "Specify a unique binary directory name.";
+ /* clang-format on */
this->IssueMessage(cmake::FATAL_ERROR, e.str());
break;
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
-cmPolicies::PolicyStatus
-cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id)
+void cmMakefile::AddQtUiFileWithOptions(cmSourceFile* sf)
{
- // Get the current setting of the policy.
- cmPolicies::PolicyStatus cur = this->GetPolicyStatusInternal(id);
-
- // If the policy is required to be set to NEW but is not, ignore the
- // current setting and tell the caller.
- if(cur != cmPolicies::NEW)
- {
- if(cur == cmPolicies::REQUIRED_ALWAYS ||
- cur == cmPolicies::REQUIRED_IF_USED)
- {
- return cur;
- }
- cmPolicies::PolicyStatus def = this->GetPolicies()->GetPolicyStatus(id);
- if(def == cmPolicies::REQUIRED_ALWAYS ||
- def == cmPolicies::REQUIRED_IF_USED)
- {
- return def;
- }
- }
+ this->QtUiFilesWithOptions.push_back(sf);
+}
- // The current setting is okay.
- return cur;
+std::vector<cmSourceFile*> cmMakefile::GetQtUiFilesWithOptions() const
+{
+ return this->QtUiFilesWithOptions;
}
-//----------------------------------------------------------------------------
-cmPolicies::PolicyStatus
-cmMakefile::GetPolicyStatusInternal(cmPolicies::PolicyID id)
+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",
+ "CMAKE_MATCH_8", "CMAKE_MATCH_9"
+};
+
+static std::string const nMatchesVariable = "CMAKE_MATCH_COUNT";
+
+void cmMakefile::ClearMatches()
{
- // Is the policy set in our stack?
- for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin();
- psi != this->PolicyStack.rend(); ++psi)
- {
- PolicyStackEntry::const_iterator pse = psi->find(id);
- if(pse != psi->end())
- {
- return pse->second;
- }
+ const char* nMatchesStr = this->GetDefinition(nMatchesVariable);
+ if (!nMatchesStr) {
+ return;
+ }
+ int nMatches = atoi(nMatchesStr);
+ for (int i = 0; i <= nMatches; i++) {
+ std::string const& var = matchVariables[i];
+ std::string const& s = this->GetSafeDefinition(var);
+ if (!s.empty()) {
+ this->AddDefinition(var, "");
+ this->MarkVariableAsUsed(var);
}
+ }
+ this->AddDefinition(nMatchesVariable, "0");
+ this->MarkVariableAsUsed(nMatchesVariable);
+}
- // If we have a parent directory, recurse up to it.
- if(this->LocalGenerator->GetParent())
- {
- cmMakefile* parent = this->LocalGenerator->GetParent()->GetMakefile();
- return parent->GetPolicyStatusInternal(id);
+void cmMakefile::StoreMatches(cmsys::RegularExpression& re)
+{
+ char highest = 0;
+ for (int i = 0; i < 10; i++) {
+ std::string const& m = re.match(i);
+ if (!m.empty()) {
+ std::string const& var = matchVariables[i];
+ this->AddDefinition(var, m.c_str());
+ this->MarkVariableAsUsed(var);
+ highest = static_cast<char>('0' + i);
}
+ }
+ char nMatches[] = { highest, '\0' };
+ this->AddDefinition(nMatchesVariable, nMatches);
+ this->MarkVariableAsUsed(nMatchesVariable);
+}
- // The policy is not set. Use the default for this CMake version.
- return this->GetPolicies()->GetPolicyStatus(id);
+cmStateSnapshot cmMakefile::GetStateSnapshot() const
+{
+ return this->StateSnapshot;
}
-bool cmMakefile::SetPolicy(const char *id,
- cmPolicies::PolicyStatus status)
+const char* cmMakefile::GetDefineFlagsCMP0059() const
+{
+ return this->DefineFlagsOrig.c_str();
+}
+
+cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(
+ cmPolicies::PolicyID id) const
+{
+ return this->StateSnapshot.GetPolicy(id);
+}
+
+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);
+ }
+ // Enable optional policy warnings with --debug-output, --trace,
+ // or --trace-expand.
+ cmake* cm = this->GetCMakeInstance();
+ return cm->GetDebugOutput() || cm->GetTrace();
+}
+
+bool cmMakefile::SetPolicy(const char* id, cmPolicies::PolicyStatus status)
{
cmPolicies::PolicyID pid;
- if (!this->GetPolicies()->GetPolicyID(id, /* out */ pid))
- {
- cmOStringStream e;
+ 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());
return false;
- }
- return this->SetPolicy(pid,status);
+ }
+ return this->SetPolicy(pid, status);
}
-//----------------------------------------------------------------------------
bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
cmPolicies::PolicyStatus status)
{
// A REQUIRED_ALWAYS policy may be set only to NEW.
- if(status != cmPolicies::NEW &&
- this->GetPolicies()->GetPolicyStatus(id) ==
- cmPolicies::REQUIRED_ALWAYS)
- {
- std::string msg =
- this->GetPolicies()->GetRequiredAlwaysPolicyError(id);
- this->IssueMessage(cmake::FATAL_ERROR, msg.c_str());
+ if (status != cmPolicies::NEW &&
+ cmPolicies::GetPolicyStatus(id) == cmPolicies::REQUIRED_ALWAYS) {
+ std::string msg = cmPolicies::GetRequiredAlwaysPolicyError(id);
+ this->IssueMessage(cmake::FATAL_ERROR, msg);
return false;
- }
-
- // Update the policy stack from the top to the top-most strong entry.
- bool previous_was_weak = true;
- for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin();
- previous_was_weak && psi != this->PolicyStack.rend(); ++psi)
- {
- (*psi)[id] = status;
- previous_was_weak = psi->Weak;
- }
+ }
- // Special hook for presenting compatibility variable as soon as
- // the user requests it.
- if(id == cmPolicies::CMP0001 &&
- (status == cmPolicies::WARN || status == cmPolicies::OLD))
- {
- if(!(this->GetCacheManager()
- ->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY")))
- {
- // Set it to 2.4 because that is the last version where the
- // variable had meaning.
- this->AddCacheDefinition
- ("CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
- "For backwards compatibility, what version of CMake "
- "commands and "
- "syntax should this version of CMake try to support.",
- cmCacheManager::STRING);
- }
- }
+ // 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,
+ cmPolicies::GetPolicyDeprecatedWarning(id));
+ }
+ this->StateSnapshot.SetPolicy(id, status);
return true;
}
-//----------------------------------------------------------------------------
-cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m, bool weak,
- cmPolicies::PolicyMap const& pm):
- Makefile(m), ReportError(true)
+cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m)
+ : Makefile(m)
{
- this->Makefile->PushPolicy(weak, pm);
- this->Makefile->PushPolicyBarrier();
+ this->Makefile->PushPolicy();
}
-//----------------------------------------------------------------------------
cmMakefile::PolicyPushPop::~PolicyPushPop()
{
- this->Makefile->PopPolicyBarrier(this->ReportError);
this->Makefile->PopPolicy();
}
-//----------------------------------------------------------------------------
void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm)
{
- // Allocate a new stack entry.
- this->PolicyStack.push_back(PolicyStackEntry(pm, weak));
+ this->StateSnapshot.PushPolicy(pm, weak);
}
-//----------------------------------------------------------------------------
void cmMakefile::PopPolicy()
{
- if(this->PolicyStack.size() > this->PolicyBarriers.back())
- {
- this->PolicyStack.pop_back();
- }
- else
- {
+ if (!this->StateSnapshot.PopPolicy()) {
this->IssueMessage(cmake::FATAL_ERROR,
"cmake_policy POP without matching PUSH");
- }
-}
-
-//----------------------------------------------------------------------------
-void cmMakefile::PushPolicyBarrier()
-{
- this->PolicyBarriers.push_back(this->PolicyStack.size());
+ }
}
-//----------------------------------------------------------------------------
-void cmMakefile::PopPolicyBarrier(bool reportError)
+void cmMakefile::PopSnapshot(bool reportError)
{
- // Remove any extra entries pushed on the barrier.
- PolicyStackType::size_type barrier = this->PolicyBarriers.back();
- while(this->PolicyStack.size() > barrier)
- {
- if(reportError)
- {
+ // cmStateSnapshot manages nested policy scopes within it.
+ // Since the scope corresponding to the snapshot is closing,
+ // reject any still-open nested policy scopes with an error.
+ while (!this->StateSnapshot.CanPopPolicyScope()) {
+ if (reportError) {
this->IssueMessage(cmake::FATAL_ERROR,
"cmake_policy PUSH without matching POP");
reportError = false;
- }
- this->PopPolicy();
}
+ this->PopPolicy();
+ }
- // Remove the barrier.
- this->PolicyBarriers.pop_back();
+ this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
+ assert(this->StateSnapshot.IsValid());
}
-bool cmMakefile::SetPolicyVersion(const char *version)
+bool cmMakefile::SetPolicyVersion(const char* version)
{
- return this->GetCMakeInstance()->GetPolicies()->
- ApplyPolicyVersion(this,version);
+ return cmPolicies::ApplyPolicyVersion(this, version);
}
-cmPolicies *cmMakefile::GetPolicies()
+bool cmMakefile::HasCMP0054AlreadyBeenReported(
+ cmListFileContext const& context) const
{
- if (!this->GetCMakeInstance())
- {
- return 0;
- }
- return this->GetCMakeInstance()->GetPolicies();
+ return !this->CMP0054ReportedIds.insert(context).second;
}
-//----------------------------------------------------------------------------
void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
{
/* Record the setting of every policy. */
typedef cmPolicies::PolicyID PolicyID;
- for(PolicyID pid = cmPolicies::CMP0000;
- pid != cmPolicies::CMPCOUNT; pid = PolicyID(pid+1))
- {
- pm[pid] = this->GetPolicyStatus(pid);
+ for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
+ pid = PolicyID(pid + 1)) {
+ pm.Set(pid, this->GetPolicyStatus(pid));
+ }
+}
+
+bool cmMakefile::IgnoreErrorsCMP0061() const
+{
+ bool ignoreErrors = true;
+ switch (this->GetPolicyStatus(cmPolicies::CMP0061)) {
+ case cmPolicies::WARN:
+ // No warning for this policy!
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ ignoreErrors = false;
+ break;
+ }
+ return ignoreErrors;
+}
+
+#define FEATURE_STRING(F) , #F
+static const char* const C_FEATURES[] = { CM_NULLPTR FOR_EACH_C_FEATURE(
+ FEATURE_STRING) };
+
+static const char* const CXX_FEATURES[] = { CM_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" };
+
+bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
+ const std::string& feature,
+ std::string* error) const
+{
+ if (cmGeneratorExpression::Find(feature) != std::string::npos) {
+ target->AppendProperty("COMPILE_FEATURES", feature.c_str());
+ return true;
+ }
+
+ std::string lang;
+ if (!this->CompileFeatureKnown(target, feature, lang, error)) {
+ return false;
+ }
+
+ const char* features = this->CompileFeaturesAvailable(lang, error);
+ if (!features) {
+ return false;
+ }
+
+ std::vector<std::string> availableFeatures;
+ cmSystemTools::ExpandListArgument(features, availableFeatures);
+ if (std::find(availableFeatures.begin(), availableFeatures.end(), feature) ==
+ availableFeatures.end()) {
+ std::ostringstream e;
+ e << "The compiler feature \"" << feature << "\" is not known to " << lang
+ << " compiler\n\""
+ << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID")
+ << "\"\nversion "
+ << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Backtrace);
+ }
+ return false;
+ }
+
+ target->AppendProperty("COMPILE_FEATURES", feature.c_str());
+
+ return lang == "C"
+ ? this->AddRequiredTargetCFeature(target, feature, error)
+ : this->AddRequiredTargetCxxFeature(target, feature, error);
+}
+
+bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
+ const std::string& feature,
+ std::string& lang,
+ std::string* error) const
+{
+ assert(cmGeneratorExpression::Find(feature) == std::string::npos);
+
+ bool isCFeature =
+ std::find_if(cmArrayBegin(C_FEATURES) + 1, cmArrayEnd(C_FEATURES),
+ cmStrCmp(feature)) != cmArrayEnd(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);
+ if (isCxxFeature) {
+ lang = "CXX";
+ return true;
+ }
+ std::ostringstream e;
+ if (error) {
+ e << "specified";
+ } else {
+ e << "Specified";
+ }
+ e << " unknown feature \"" << feature << "\" for "
+ "target \""
+ << target->GetName() << "\".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Backtrace);
+ }
+ return false;
+}
+
+const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
+ std::string* error) const
+{
+ if (!this->GlobalGenerator->GetLanguageEnabled(lang)) {
+ std::ostringstream e;
+ if (error) {
+ e << "cannot";
+ } else {
+ e << "Cannot";
+ }
+ e << " use features from non-enabled language " << lang;
+ if (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Backtrace);
}
+ return CM_NULLPTR;
+ }
+
+ const char* featuresKnown =
+ this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
+
+ if (!featuresKnown || !*featuresKnown) {
+ std::ostringstream e;
+ if (error) {
+ e << "no";
+ } else {
+ e << "No";
+ }
+ e << " known features for " << lang << " compiler\n\""
+ << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID")
+ << "\"\nversion "
+ << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Backtrace);
+ }
+ return CM_NULLPTR;
+ }
+ return featuresKnown;
+}
+
+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);
+}
+
+bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
+ const std::string& feature) const
+{
+ const char* defaultCStandard =
+ this->GetDefinition("CMAKE_C_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());
+ // 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());
+ return false;
+ }
+
+ bool needC90 = false;
+ bool needC99 = false;
+ bool needC11 = false;
+
+ this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+
+ const char* existingCStandard = target->GetProperty("C_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());
+ return false;
+ }
+
+ const char* const* existingCIt = existingCStandard
+ ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+ cmStrCmp(existingCStandard))
+ : cmArrayEnd(C_STANDARDS);
+
+ if (needC11 && existingCStandard &&
+ existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
+ cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) {
+ return false;
+ }
+ if (needC99 && existingCStandard &&
+ existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
+ cmArrayEnd(C_STANDARDS), cmStrCmp("99"))) {
+ return false;
+ }
+ if (needC90 && existingCStandard &&
+ existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
+ cmArrayEnd(C_STANDARDS), cmStrCmp("90"))) {
+ return false;
+ }
+ return true;
+}
+
+bool cmMakefile::IsLaterStandard(std::string const& lang,
+ std::string const& lhs,
+ std::string const& rhs)
+{
+ if (lang == "C") {
+ const char* const* rhsIt = std::find_if(
+ cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), cmStrCmp(rhs));
+
+ return std::find_if(rhsIt, cmArrayEnd(C_STANDARDS), cmStrCmp(lhs)) !=
+ cmArrayEnd(C_STANDARDS);
+ }
+ const char* const* rhsIt = std::find_if(
+ cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), cmStrCmp(rhs));
+
+ return std::find_if(rhsIt, cmArrayEnd(CXX_STANDARDS), cmStrCmp(lhs)) !=
+ cmArrayEnd(CXX_STANDARDS);
+}
+
+bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
+ const std::string& feature) const
+{
+ const char* defaultCxxStandard =
+ this->GetDefinition("CMAKE_CXX_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());
+ // 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());
+ return false;
+ }
+
+ 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");
+ 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());
+ return false;
+ }
+
+ const char* const* existingCxxIt = existingCxxStandard
+ ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
+ cmStrCmp(existingCxxStandard))
+ : cmArrayEnd(CXX_STANDARDS);
+
+ 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;
+}
+
+void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
+ bool& needCxx98, bool& needCxx11,
+ bool& needCxx14, bool& needCxx17) 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();
+ }
+ 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();
+ }
+ 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();
+ }
+ 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();
+ }
+}
+
+bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
+ const std::string& feature,
+ 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");
+ if (existingCxxStandard) {
+ 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 << "\".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::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");
+ }
+ return true;
+}
+
+void cmMakefile::CheckNeededCLanguage(const std::string& feature,
+ 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();
+ }
+ 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();
+ }
+ 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();
+ }
+}
+
+bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
+ const std::string& feature,
+ std::string* error) const
+{
+ bool needC90 = false;
+ bool needC99 = false;
+ bool needC11 = false;
+
+ this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+
+ const char* existingCStandard = target->GetProperty("C_STANDARD");
+ 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 (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Backtrace);
+ }
+ return false;
+ }
+ }
+ const char* const* existingCIt = existingCStandard
+ ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+ cmStrCmp(existingCStandard))
+ : cmArrayEnd(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"))) {
+ setC11 = true;
+ } else if (needC99 && existingCStandard &&
+ existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
+ cmArrayEnd(C_STANDARDS),
+ cmStrCmp("99"))) {
+ setC99 = true;
+ } else if (needC90 && existingCStandard &&
+ existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
+ cmArrayEnd(C_STANDARDS),
+ cmStrCmp("90"))) {
+ setC90 = true;
+ }
+
+ if (setC11) {
+ target->SetProperty("C_STANDARD", "11");
+ } else if (setC99) {
+ target->SetProperty("C_STANDARD", "99");
+ } else if (setC90) {
+ target->SetProperty("C_STANDARD", "90");
+ }
+ return true;
+}
+
+cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf,
+ const std::string& fileName,
+ cmPolicies::PolicyMap const& pm)
+ : Makefile(mf)
+ , ReportError(true)
+{
+ this->Makefile->PushFunctionScope(fileName, pm);
+}
+
+cmMakefile::FunctionPushPop::~FunctionPushPop()
+{
+ this->Makefile->PopFunctionScope(this->ReportError);
+}
+
+cmMakefile::MacroPushPop::MacroPushPop(cmMakefile* mf,
+ const std::string& fileName,
+ const cmPolicies::PolicyMap& pm)
+ : Makefile(mf)
+ , ReportError(true)
+{
+ this->Makefile->PushMacroScope(fileName, pm);
+}
+
+cmMakefile::MacroPushPop::~MacroPushPop()
+{
+ this->Makefile->PopMacroScope(this->ReportError);
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 8bce9fd65..e65ba468f 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1,50 +1,50 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMakefile_h
#define cmMakefile_h
-#include "cmCacheManager.h"
-#include "cmExecutionStatus.h"
+#include "cmConfigure.h"
+
+#include "cmsys/RegularExpression.hxx"
+#include <deque>
+#include <map>
+#include <set>
+#include <stack>
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+#include "cmAlgorithms.h"
#include "cmListFileCache.h"
+#include "cmNewLineStyle.h"
#include "cmPolicies.h"
-#include "cmPropertyMap.h"
-#include "cmSystemTools.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
#include "cmTarget.h"
-#include "cmNewLineStyle.h"
-#include "cmGeneratorTarget.h"
+#include "cm_auto_ptr.hxx"
+#include "cm_unordered_map.hxx"
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmSourceGroup.h"
#endif
-#include <cmsys/auto_ptr.hxx>
-#include <cmsys/RegularExpression.hxx>
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <cmsys/hash_map.hxx>
-#endif
-
-class cmFunctionBlocker;
class cmCommand;
+class cmCompiledGeneratorExpression;
+class cmCustomCommandLines;
+class cmExecutionStatus;
+class cmExpandedCommandArgument;
+class cmExportBuildFileGenerator;
+class cmFunctionBlocker;
+class cmGeneratorExpressionEvaluationFile;
+class cmGlobalGenerator;
class cmInstallGenerator;
-class cmLocalGenerator;
-class cmMakeDepend;
+class cmMessenger;
class cmSourceFile;
+class cmState;
class cmTest;
class cmTestGenerator;
class cmVariableWatch;
-class cmake;
-class cmMakefileCall;
-class cmCMakePolicyCommand;
/** \class cmMakefile
* \brief Process the input CMakeLists.txt file.
@@ -55,108 +55,62 @@ class cmCMakePolicyCommand;
*/
class cmMakefile
{
- class Internals;
- cmsys::auto_ptr<Internals> Internal;
-public:
- /**
- * Return the major and minor version of the cmake that
- * was used to write the currently loaded cache, note
- * this method will not work before the cache is loaded.
- */
- unsigned int GetCacheMajorVersion();
- unsigned int GetCacheMinorVersion();
+ CM_DISABLE_COPY(cmMakefile)
- /* Check for unused variables in this scope */
- void CheckForUnusedVariables() const;
+public:
/* Mark a variable as used */
- void MarkVariableAsUsed(const char* var);
+ void MarkVariableAsUsed(const std::string& var);
/* return true if a variable has been initialized */
- bool VariableInitialized(const char* ) const;
- /* return true if a variable has been used */
- bool VariableUsed(const char* ) const;
- /** Return whether compatibility features needed for a version of
- the cache or lower should be enabled. */
- bool NeedCacheCompatibility(int major, int minor);
+ bool VariableInitialized(const std::string&) const;
/**
* Construct an empty makefile.
*/
- cmMakefile();
- cmMakefile(const cmMakefile& mf);
+ cmMakefile(cmGlobalGenerator* globalGenerator,
+ const cmStateSnapshot& snapshot);
/**
* Destructor.
*/
~cmMakefile();
- /**
- * Read and parse a CMakeLists.txt file.
- */
- bool ReadListFile(const char* listfile,
- const char* external= 0,
- std::string* fullPath= 0,
- bool noPolicyScope = true);
+ bool ReadListFile(const char* filename);
+
+ bool ReadDependentFile(const char* filename, bool noPolicyScope = true);
+
+ bool ProcessBuildsystemFile(const char* filename);
/**
* Add a function blocker to this makefile
*/
void AddFunctionBlocker(cmFunctionBlocker* fb);
+ /// @return whether we are processing the top CMakeLists.txt file.
+ bool IsRootMakefile() const;
+
/**
* Remove the function blocker whose scope ends with the given command.
* This returns ownership of the function blocker object.
*/
- cmsys::auto_ptr<cmFunctionBlocker>
- RemoveFunctionBlocker(cmFunctionBlocker* fb, const cmListFileFunction& lff);
-
- /** Push/pop a lexical (function blocker) barrier automatically. */
- class LexicalPushPop
- {
- public:
- LexicalPushPop(cmMakefile* mf);
- ~LexicalPushPop();
- void Quiet() { this->ReportError = false; }
- private:
- cmMakefile* Makefile;
- bool ReportError;
- };
- friend class LexicalPushPop;
+ CM_AUTO_PTR<cmFunctionBlocker> RemoveFunctionBlocker(
+ cmFunctionBlocker* fb, const cmListFileFunction& lff);
/**
* Try running cmake and building a file. This is used for dynalically
* loaded commands, not as part of the usual build process.
*/
- int TryCompile(const char *srcdir, const char *bindir,
- const char *projectName, const char *targetName,
- bool fast,
- const std::vector<std::string> *cmakeArgs,
- std::string *output);
+ 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,
+ std::string& output);
bool GetIsSourceFileTryCompile() const;
/**
- * Specify the makefile generator. This is platform/compiler
- * dependent, although the interface is through a generic
- * superclass.
- */
- void SetLocalGenerator(cmLocalGenerator*);
-
- ///! Get the current makefile generator.
- cmLocalGenerator* GetLocalGenerator()
- { return this->LocalGenerator;}
-
- /**
- * Test whether compatibility is set to a given version or lower.
- */
- bool NeedBackwardsCompatibility(unsigned int major,
- unsigned int minor,
- unsigned int patch = 0xFFu);
-
- /**
* Help enforce global target name uniqueness.
*/
bool EnforceUniqueName(std::string const& name, std::string& msg,
- bool isCustom = false);
+ bool isCustom = false) const;
/**
* Perform FinalPass, Library dependency analysis etc before output of the
@@ -169,38 +123,42 @@ public:
*/
void FinalPass();
- /**
- * Print the object state to std::cout.
- */
- void Print();
+ /** How to handle custom commands for object libraries */
+ enum ObjectLibraryCommands
+ {
+ RejectObjectLibraryCommands,
+ AcceptObjectLibraryCommands
+ };
/** Add a custom command to the build. */
- void AddCustomCommandToTarget(const char* target,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- cmTarget::CustomCommandType type,
- const char* comment, const char* workingDir,
- bool escapeOldStyle = true);
+ void 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 = true,
+ bool uses_terminal = false, const std::string& depfile = "",
+ bool command_expand_lists = false,
+ ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
cmSourceFile* AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
- const char* main_dependency,
- const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir,
- bool replace = false,
- bool escapeOldStyle = true);
+ 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 = "");
cmSourceFile* AddCustomCommandToOutput(
- const char* output,
- const std::vector<std::string>& depends,
- const char* main_dependency,
- const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir,
- bool replace = false,
- bool escapeOldStyle = true);
- void AddCustomCommandOldStyle(const char* target,
+ 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 = "");
+ void AddCustomCommandOldStyle(const std::string& target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
- const char* source,
+ const std::string& source,
const cmCustomCommandLines& commandLines,
const char* comment);
@@ -212,148 +170,116 @@ public:
void AddCompileOption(const char* option);
/** Create a new imported target with the name and type given. */
- cmTarget* AddImportedTarget(const char* name, cmTarget::TargetType type,
- bool global);
+ cmTarget* AddImportedTarget(const std::string& name,
+ cmStateEnums::TargetType type, bool global);
- cmTarget* AddNewTarget(cmTarget::TargetType type, const char* name);
+ cmTarget* AddNewTarget(cmStateEnums::TargetType type,
+ const std::string& name);
/**
* Add an executable to the build.
*/
- cmTarget* AddExecutable(const char *exename,
- const std::vector<std::string> &srcs,
+ cmTarget* AddExecutable(const char* exename,
+ const std::vector<std::string>& srcs,
bool excludeFromAll = false);
/**
* Add a utility to the build. A utiltity target is a command that
* is run every time the target is built.
*/
- void AddUtilityCommand(const char* utilityName, bool excludeFromAll,
- const std::vector<std::string>& depends,
- const char* workingDirectory,
- const char* command,
- const char* arg1=0,
- const char* arg2=0,
- const char* arg3=0,
- const char* arg4=0);
- cmTarget* AddUtilityCommand(const char* utilityName, bool excludeFromAll,
- const char* workingDirectory,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- bool escapeOldStyle = true,
- const char* comment = 0);
-
- /**
- * Add a link library to the build.
- */
- void AddLinkLibrary(const char*);
- void AddLinkLibrary(const char*, cmTarget::LinkLibraryType type);
- void AddLinkLibraryForTarget(const char *tgt, const char*,
- cmTarget::LinkLibraryType type);
- void AddLinkDirectoryForTarget(const char *tgt, const char* d);
-
- /**
- * Add a link directory to the build.
- */
- void AddLinkDirectory(const char*);
-
- /**
- * Get the list of link directories
- */
- std::vector<std::string>& GetLinkDirectories()
- {
- return this->LinkDirectories;
- }
- const std::vector<std::string>& GetLinkDirectories() const
- {
- return this->LinkDirectories;
- }
- void SetLinkDirectories(const std::vector<std::string>& vec)
- {
- this->LinkDirectories = vec;
- }
+ 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::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
+ const char* comment = CM_NULLPTR, bool uses_terminal = false,
+ bool command_expand_lists = false);
/**
* Add a subdirectory to the build.
*/
- void AddSubDirectory(const char*, bool excludeFromAll=false,
- bool preorder = false);
- void AddSubDirectory(const char* fullSrcDir,const char *fullBinDir,
- bool excludeFromAll, bool preorder,
+ void AddSubDirectory(const std::string& fullSrcDir,
+ const std::string& fullBinDir, bool excludeFromAll,
bool immediate);
+ void Configure();
+
/**
* Configure a subdirectory
*/
- void ConfigureSubDirectory(cmLocalGenerator *);
+ void ConfigureSubDirectory(cmMakefile* mf);
/**
* Add an include directory to the build.
*/
- void AddIncludeDirectories(const std::vector<std::string> &incs,
+ void AddIncludeDirectories(const std::vector<std::string>& incs,
bool before = false);
/**
* Add a variable definition to the build. This variable
* can be used in CMake to refer to lists, directories, etc.
*/
- void AddDefinition(const char* name, const char* value);
+ void AddDefinition(const std::string& name, const char* value);
///! Add a definition to this makefile and the global cmake cache.
- void AddCacheDefinition(const char* name, const char* value,
- const char* doc,
- cmCacheManager::CacheEntryType type,
+ void AddCacheDefinition(const std::string& name, const char* value,
+ const char* doc, cmStateEnums::CacheEntryType type,
bool force = false);
/**
* Add bool variable definition to the build.
*/
- void AddDefinition(const char* name, bool);
+ void AddDefinition(const std::string& name, bool);
/**
* Remove a variable definition from the build. This is not valid
* for cache entries, and will only affect the current makefile.
*/
- void RemoveDefinition(const char* name);
+ void RemoveDefinition(const std::string& name);
///! Remove a definition from the cache.
- void RemoveCacheDefinition(const char* name);
+ void RemoveCacheDefinition(const std::string& name);
/**
* Specify the name of the project for this build.
*/
- void SetProjectName(const char*);
-
- /**
- * Get the name of the project for this build.
- */
- const char* GetProjectName() const
- {
- return this->ProjectName.c_str();
- }
+ void SetProjectName(std::string const& name);
/** Get the configurations to be generated. */
- const char* GetConfigurations(std::vector<std::string>& configs,
+ std::string GetConfigurations(std::vector<std::string>& configs,
bool single = true) const;
/**
* Set the name of the library.
*/
- cmTarget* AddLibrary(const char *libname, cmTarget::TargetType type,
- const std::vector<std::string> &srcs,
- bool excludeFromAll = false);
- void AddAlias(const char *libname, cmTarget *tgt);
+ cmTarget* AddLibrary(const std::string& libname,
+ cmStateEnums::TargetType type,
+ const std::vector<std::string>& srcs,
+ 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 char* name, const char* regex=0);
+ 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=0);
+ const char* regex = CM_NULLPTR);
#endif
@@ -362,9 +288,9 @@ public:
* 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);
- bool SetPolicyVersion(const char *version);
+ bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
+ cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
+ bool SetPolicyVersion(const char* version);
void RecordPolicies(cmPolicies::PolicyMap& pm);
//@}
@@ -372,58 +298,24 @@ public:
class PolicyPushPop
{
public:
- PolicyPushPop(cmMakefile* m,
- bool weak = false,
- cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap());
+ PolicyPushPop(cmMakefile* m);
~PolicyPushPop();
- void Quiet() { this->ReportError = false; }
+
private:
cmMakefile* Makefile;
- bool ReportError;
};
friend class PolicyPushPop;
/**
- * Get the Policies Instance
- */
- cmPolicies *GetPolicies();
-
- /**
- * Add an auxiliary directory to the build.
+ * Determine if the given context, name pair has already been reported
+ * in context of CMP0054.
*/
- void AddExtraDirectory(const char* dir);
+ bool HasCMP0054AlreadyBeenReported(const cmListFileContext& context) const;
+ bool IgnoreErrorsCMP0061() const;
- /**
- * Add an auxiliary directory to the build.
- */
- void MakeStartDirectoriesCurrent()
- {
- this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR",
- this->cmStartDirectory.c_str());
- this->AddDefinition("CMAKE_CURRENT_BINARY_DIR",
- this->StartOutputDirectory.c_str());
- }
-
- //@{
- /**
- * Set/Get the home directory (or output directory) in the project. The
- * home directory is the top directory of the project. It is where
- * CMakeSetup or configure was run. Remember that CMake processes
- * CMakeLists files by recursing up the tree starting at the StartDirectory
- * and going up until it reaches the HomeDirectory.
- */
- void SetHomeDirectory(const char* dir);
- const char* GetHomeDirectory() const
- {
- return this->cmHomeDirectory.c_str();
- }
- void SetHomeOutputDirectory(const char* lib);
- const char* GetHomeOutputDirectory() const
- {
- return this->HomeOutputDirectory.c_str();
- }
- //@}
+ const char* GetHomeDirectory() const;
+ const char* GetHomeOutputDirectory() const;
/**
* Set CMAKE_SCRIPT_MODE_FILE variable when running a -P script.
@@ -435,59 +327,8 @@ public:
*/
void SetArgcArgv(const std::vector<std::string>& args);
- //@{
- /**
- * Set/Get the start directory (or output directory). The start directory
- * is the directory of the CMakeLists.txt file that started the current
- * round of processing. Remember that CMake processes CMakeLists files by
- * recursing up the tree starting at the StartDirectory and going up until
- * it reaches the HomeDirectory.
- */
- void SetStartDirectory(const char* dir)
- {
- this->cmStartDirectory = dir;
- cmSystemTools::ConvertToUnixSlashes(this->cmStartDirectory);
- this->cmStartDirectory =
- cmSystemTools::CollapseFullPath(this->cmStartDirectory.c_str());
- this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR",
- this->cmStartDirectory.c_str());
- }
- const char* GetStartDirectory() const
- {
- return this->cmStartDirectory.c_str();
- }
- void SetStartOutputDirectory(const char* lib)
- {
- this->StartOutputDirectory = lib;
- cmSystemTools::ConvertToUnixSlashes(this->StartOutputDirectory);
- this->StartOutputDirectory =
- cmSystemTools::CollapseFullPath(this->StartOutputDirectory.c_str());
- cmSystemTools::MakeDirectory(this->StartOutputDirectory.c_str());
- this->AddDefinition("CMAKE_CURRENT_BINARY_DIR",
- this->StartOutputDirectory.c_str());
- }
- const char* GetStartOutputDirectory() const
- {
- return this->StartOutputDirectory.c_str();
- }
- //@}
-
- const char* GetCurrentDirectory() const
- {
- return this->cmStartDirectory.c_str();
- }
- const char* GetCurrentOutputDirectory() const
- {
- return this->StartOutputDirectory.c_str();
- }
-
- /* Get the current CMakeLists.txt file that is being processed. This
- * is just used in order to be able to 'branch' from one file to a second
- * transparently */
- const char* GetCurrentListFile() const
- {
- return this->cmCurrentListFile.c_str();
- }
+ const char* GetCurrentSourceDirectory() const;
+ const char* GetCurrentBinaryDirectory() const;
//@}
@@ -496,183 +337,179 @@ public:
* in order to be considered as part of the depend information.
*/
void SetIncludeRegularExpression(const char* regex)
- {
- this->IncludeFileRegularExpression = regex;
- }
- const char* GetIncludeRegularExpression()
- {
- return this->IncludeFileRegularExpression.c_str();
- }
+ {
+ this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex);
+ }
+ const char* GetIncludeRegularExpression() const
+ {
+ return this->GetProperty("INCLUDE_REGULAR_EXPRESSION");
+ }
/**
* Set a regular expression that include files that are not found
* must match in order to be considered a problem.
*/
- void SetComplainRegularExpression(const char* regex)
- {
- this->ComplainFileRegularExpression = regex;
- }
- const char* GetComplainRegularExpression()
- {
- return this->ComplainFileRegularExpression.c_str();
- }
+ void SetComplainRegularExpression(const std::string& regex)
+ {
+ this->ComplainFileRegularExpression = regex;
+ }
+ const char* GetComplainRegularExpression() const
+ {
+ return this->ComplainFileRegularExpression.c_str();
+ }
/**
* Get the list of targets
*/
- cmTargets &GetTargets() { return this->Targets; }
+ cmTargets& GetTargets() { return this->Targets; }
/**
* Get the list of targets, const version
*/
- const cmTargets &GetTargets() const { return this->Targets; }
- const std::vector<cmTarget*> &GetOwnedImportedTargets() const
- {
- return this->ImportedTargetsOwned;
- }
-
- const cmGeneratorTargetsType &GetGeneratorTargets() const
- {
- return this->GeneratorTargets;
- }
-
- void SetGeneratorTargets(const cmGeneratorTargetsType &targets)
- {
- this->GeneratorTargets = targets;
- }
+ const cmTargets& GetTargets() const { return this->Targets; }
+ const std::vector<cmTarget*>& GetOwnedImportedTargets() const
+ {
+ return this->ImportedTargetsOwned;
+ }
+ std::vector<cmTarget*> GetImportedTargets() const;
- cmTarget* FindTarget(const char* name, bool excludeAliases = false);
+ cmTarget* FindLocalNonAliasTarget(const std::string& name) const;
/** Find a target to use in place of the given name. The target
returned may be imported or built within the project. */
- cmTarget* FindTargetToUse(const char* name, bool excludeAliases = false);
- bool IsAlias(const char *name);
- cmGeneratorTarget* FindGeneratorTargetToUse(const char* name);
+ cmTarget* FindTargetToUse(const std::string& name,
+ bool excludeAliases = false) const;
+ bool IsAlias(const std::string& name) const;
+
+ std::map<std::string, std::string> GetAliasTargets() const
+ {
+ return this->AliasTargets;
+ }
/**
* Mark include directories as system directories.
*/
- void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
- bool IsSystemIncludeDirectory(const char* dir, const char *config);
-
- /** Expand out any arguements in the vector that have ; separated
- * strings into multiple arguements. A new vector is created
- * containing the expanded versions of all arguments in argsIn.
- * This method differes from the one in cmSystemTools in that if
- * the CmakeLists file is version 1.2 or earlier it will check for
- * source lists being used without ${} around them
- */
- void ExpandSourceListArguments(std::vector<std::string> const& argsIn,
- std::vector<std::string>& argsOut,
- unsigned int startArgumentIndex);
+ void AddSystemIncludeDirectories(const std::set<std::string>& incs);
/** Get a cmSourceFile pointer for a given source name, if the name is
* not found, then a null pointer is returned.
*/
- cmSourceFile* GetSource(const char* sourceName);
+ cmSourceFile* GetSource(const std::string& sourceName) 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);
/** 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 char* sourceName,
+ cmSourceFile* GetOrCreateSource(const std::string& sourceName,
bool generated = false);
- /**
- * Obtain a list of auxiliary source directories.
- */
- std::vector<std::string>& GetAuxSourceDirectories()
- {return this->AuxSourceDirectories;}
-
- //@{
- /**
- * Return a list of extensions associated with source and header
- * files
- */
- const std::vector<std::string>& GetSourceExtensions() const
- {return this->SourceFileExtensions;}
- const std::vector<std::string>& GetHeaderExtensions() const
- {return this->HeaderFileExtensions;}
- //@}
+ void AddTargetObject(std::string const& tgtName, std::string const& objFile);
/**
* Given a variable name, return its value (as a string).
* If the variable is not found in this makefile instance, the
* cache is then queried.
*/
- const char* GetDefinition(const char*) const;
- const char* GetSafeDefinition(const char*) const;
- const char* GetRequiredDefinition(const char* name) const;
- bool IsDefinitionSet(const char*) const;
+ const char* GetDefinition(const std::string&) const;
+ const char* GetSafeDefinition(const std::string&) const;
+ const char* GetRequiredDefinition(const std::string& name) const;
+ bool IsDefinitionSet(const std::string&) const;
/**
* Get the list of all variables in the current space. If argument
* cacheonly is specified and is greater than 0, then only cache
* variables will be listed.
*/
- std::vector<std::string> GetDefinitions(int cacheonly=0) const;
+ std::vector<std::string> GetDefinitions() const;
- /** Test a boolean cache entry to see if it is true or false,
- * returns false if no entry defined.
+ /**
+ * Test a boolean variable to see if it is true or false.
+ * If the variable is not found in this makefile instance, the
+ * cache is then queried.
+ * Returns false if no entry defined.
*/
- bool IsOn(const char* name) const;
- bool IsSet(const char* name) const;
+ bool IsOn(const std::string& name) const;
+ bool IsSet(const std::string& name) const;
+
+ /** Return whether the target platform is 32-bit. */
+ bool PlatformIs32Bit() const;
/** Return whether the target platform is 64-bit. */
bool PlatformIs64Bit() const;
+ /** Return whether the target platform is x32. */
+ bool PlatformIsx32() const;
+
+ /** Return whether the target platform is Apple iOS. */
+ bool PlatformIsAppleIos() const;
/** Retrieve soname flag for the specified language if supported */
- const char* GetSONameFlag(const char* language) const;
+ const char* GetSONameFlag(const std::string& language) const;
/**
* Get a list of preprocessor define flags.
*/
- const char* GetDefineFlags()
- {return this->DefineFlags.c_str();}
+ std::string GetDefineFlags() const { return this->DefineFlags; }
/**
* Make sure CMake can write this file
*/
- bool CanIWriteThisFile(const char* fileName);
+ bool CanIWriteThisFile(const char* fileName) const;
#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
* Get the vector source groups.
*/
const std::vector<cmSourceGroup>& GetSourceGroups() const
- { return this->SourceGroups; }
+ {
+ return this->SourceGroups;
+ }
/**
* Get the source group
*/
- cmSourceGroup* GetSourceGroup(const std::vector<std::string>&name);
+ cmSourceGroup* GetSourceGroup(const std::vector<std::string>& name) const;
#endif
/**
* Get the vector of list files on which this makefile depends
*/
const std::vector<std::string>& GetListFiles() const
- { return this->ListFiles; }
+ {
+ return this->ListFiles;
+ }
///! When the file changes cmake will be re-run from the build system.
void AddCMakeDependFile(const std::string& file)
- { this->ListFiles.push_back(file);}
+ {
+ this->ListFiles.push_back(file);
+ }
+ void AddCMakeDependFilesFromUser();
- /**
- * Get the list file stack as a string
- */
- std::string GetListFileStack();
+ std::string FormatListFileStack() const;
/**
* Get the current context backtrace.
*/
- bool GetBacktrace(cmListFileBacktrace& backtrace) const;
+ cmListFileBacktrace GetBacktrace() const;
+ cmListFileBacktrace GetBacktrace(cmCommandContext const& lfc) const;
+ cmListFileContext GetExecutionContext() const;
/**
* Get the vector of files created by this makefile
*/
const std::vector<std::string>& GetOutputFiles() const
- { return this->OutputFiles; }
+ {
+ return this->OutputFiles;
+ }
void AddCMakeOutputFile(const std::string& file)
- { this->OutputFiles.push_back(file);}
+ {
+ this->OutputFiles.push_back(file);
+ }
/**
* Expand all defined variables in the string.
@@ -681,21 +518,18 @@ public:
* entry in the this->Definitions map. Also \@var\@ is
* expanded to match autoconf style expansions.
*/
- const char *ExpandVariablesInString(std::string& source);
- const char *ExpandVariablesInString(std::string& source, bool escapeQuotes,
- bool noEscapes,
- bool atOnly = false,
- const char* filename = 0,
- long line = -1,
- bool removeEmpty = false,
- bool replaceAt = true);
+ 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;
/**
* Remove any remaining variables in the string. Anything with ${var} or
* \@var\@ will be removed.
*/
- void RemoveVariablesInString(std::string& source,
- bool atOnly = false) const;
+ void RemoveVariablesInString(std::string& source, bool atOnly = false) const;
/**
* Expand variables in the makefiles ivars such as link directories etc
@@ -707,239 +541,286 @@ public:
* See cmConfigureFileCommand for details.
*/
void ConfigureString(const std::string& input, std::string& output,
- bool atOnly, bool escapeQuotes);
+ bool atOnly, bool escapeQuotes) const;
/**
* Copy file but change lines acording to ConfigureString
*/
- int ConfigureFile(const char* infile, const char* outfile,
- bool copyonly, bool atOnly, bool escapeQuotes,
- const cmNewLineStyle& = cmNewLineStyle());
-
+ int ConfigureFile(const char* infile, const char* outfile, bool copyonly,
+ bool atOnly, bool escapeQuotes,
+ cmNewLineStyle = cmNewLineStyle());
#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
* find what source group this source is in
*/
- cmSourceGroup& FindSourceGroup(const char* source,
- std::vector<cmSourceGroup> &groups);
+ cmSourceGroup* FindSourceGroup(const char* source,
+ std::vector<cmSourceGroup>& groups) const;
#endif
/**
* Print a command's invocation
*/
- void PrintCommandTrace(const cmListFileFunction& lff);
+ void PrintCommandTrace(const cmListFileFunction& lff) const;
/**
* Execute a single CMake command. Returns true if the command
* succeeded or false if it failed.
*/
bool ExecuteCommand(const cmListFileFunction& lff,
- cmExecutionStatus &status);
-
- /** Check if a command exists. */
- bool CommandExists(const char* name) const;
-
- /**
- * Add a command to this cmake instance
- */
- void AddCommand(cmCommand* );
+ cmExecutionStatus& status);
///! Enable support for named language, if nil then all languages are
- ///enabled.
- void EnableLanguage(std::vector<std::string>const& languages, bool optional);
+ /// enabled.
+ void EnableLanguage(std::vector<std::string> const& languages,
+ bool optional);
- /**
- * Set/Get the name of the parent directories CMakeLists file
- * given a current CMakeLists file name
- */
- cmCacheManager *GetCacheManager() const;
+ cmState* GetState() const;
- /**
- * Get the variable watch. This is used to determine when certain variables
- * are accessed.
- */
+/**
+ * Get the variable watch. This is used to determine when certain variables
+ * are accessed.
+ */
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* GetVariableWatch() const;
#endif
///! Display progress or status message.
- void DisplayStatus(const char*, float);
+ void DisplayStatus(const char*, float) const;
/**
* Expand the given list file arguments into the full set after
* variable replacement and list expansion.
*/
bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
- std::vector<std::string>& outArgs);
+ std::vector<std::string>& outArgs,
+ const char* filename = CM_NULLPTR) const;
+
+ bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
+ std::vector<cmExpandedCommandArgument>& outArgs,
+ const char* filename = CM_NULLPTR) const;
+
/**
* Get the instance
*/
- cmake *GetCMakeInstance() const;
+ cmake* GetCMakeInstance() const;
+ cmMessenger* GetMessenger() const;
+ cmGlobalGenerator* GetGlobalGenerator() const;
/**
* Get all the source files this makefile knows about
*/
- const std::vector<cmSourceFile*> &GetSourceFiles() const
- {return this->SourceFiles;}
- std::vector<cmSourceFile*> &GetSourceFiles() {return this->SourceFiles;}
+ const std::vector<cmSourceFile*>& GetSourceFiles() const
+ {
+ 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
*/
- cmSourceFile *GetSourceFileWithOutput(const char *outName);
-
- /**
- * Add a macro to the list of macros. The arguments should be name of the
- * macro and a documentation signature of it
- */
- void AddMacro(const char* name, const char* signature);
+ cmSourceFile* GetSourceFileWithOutput(const std::string& outName) const;
///! Add a new cmTest to the list of tests for this makefile.
- cmTest* CreateTest(const char* testName);
+ cmTest* CreateTest(const std::string& testName);
/** Get a cmTest pointer for a given test name, if the name is
* not found, then a null pointer is returned.
*/
- cmTest* GetTest(const char* testName) const;
-
- /**
- * Get a list of macros as a ; separated string
- */
- void GetListOfMacros(std::string& macros);
+ cmTest* GetTest(const std::string& testName) const;
/**
* Return a location of a file in cmake or custom modules directory
*/
- std::string GetModulesFile(const char* name);
+ std::string GetModulesFile(const char* name) const;
///! Set/Get a property of this directory
- void SetProperty(const char *prop, const char *value);
- void AppendProperty(const char *prop, const char *value,bool asString=false);
- const char *GetProperty(const char *prop);
- const char *GetPropertyOrDefinition(const char *prop);
- const char *GetProperty(const char *prop, cmProperty::ScopeType scope);
- bool GetPropertyAsBool(const char *prop);
-
- const char* GetFeature(const char* feature, const char* config);
-
- // Get the properties
- cmPropertyMap &GetProperties() { return this->Properties; };
+ 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) const;
+ const char* GetProperty(const std::string& prop, bool chain) const;
+ bool GetPropertyAsBool(const std::string& prop) const;
+ std::vector<std::string> GetPropertyKeys() const;
///! Initialize a makefile from its parent
- void InitializeFromParent();
-
- ///! Set/Get the preorder flag
- void SetPreOrder(bool p) { this->PreOrder = p; }
- bool GetPreOrder() const { return this->PreOrder; }
+ void InitializeFromParent(cmMakefile* parent);
void AddInstallGenerator(cmInstallGenerator* g)
- { if(g) this->InstallGenerators.push_back(g); }
+ {
+ if (g) {
+ this->InstallGenerators.push_back(g);
+ }
+ }
std::vector<cmInstallGenerator*>& GetInstallGenerators()
- { return this->InstallGenerators; }
+ {
+ return this->InstallGenerators;
+ }
void AddTestGenerator(cmTestGenerator* g)
- { if(g) this->TestGenerators.push_back(g); }
- std::vector<cmTestGenerator*>& GetTestGenerators()
- { return this->TestGenerators; }
+ {
+ if (g) {
+ this->TestGenerators.push_back(g);
+ }
+ }
+ const std::vector<cmTestGenerator*>& GetTestGenerators() const
+ {
+ return this->TestGenerators;
+ }
- // Define the properties
- static void DefineProperties(cmake *cm);
+ class FunctionPushPop
+ {
+ public:
+ FunctionPushPop(cmMakefile* mf, std::string const& fileName,
+ cmPolicies::PolicyMap const& pm);
+ ~FunctionPushPop();
- // push and pop variable scopes
+ void Quiet() { this->ReportError = false; }
+ private:
+ cmMakefile* Makefile;
+ bool ReportError;
+ };
+
+ class MacroPushPop
+ {
+ public:
+ MacroPushPop(cmMakefile* mf, std::string const& fileName,
+ cmPolicies::PolicyMap const& pm);
+ ~MacroPushPop();
+
+ void Quiet() { this->ReportError = false; }
+ private:
+ cmMakefile* Makefile;
+ bool ReportError;
+ };
+
+ void PushFunctionScope(std::string const& fileName,
+ cmPolicies::PolicyMap const& pm);
+ void PopFunctionScope(bool reportError);
+ void PushMacroScope(std::string const& fileName,
+ cmPolicies::PolicyMap const& pm);
+ void PopMacroScope(bool reportError);
void PushScope();
void PopScope();
- void RaiseScope(const char *var, const char *value);
+ void RaiseScope(const std::string& var, const char* value);
+
+ // push and pop loop scopes
+ void PushLoopBlockBarrier();
+ void PopLoopBlockBarrier();
/** Helper class to push and pop scopes automatically. */
class ScopePushPop
{
+ CM_DISABLE_COPY(ScopePushPop)
public:
- ScopePushPop(cmMakefile* m): Makefile(m) { this->Makefile->PushScope(); }
+ ScopePushPop(cmMakefile* m)
+ : Makefile(m)
+ {
+ this->Makefile->PushScope();
+ }
~ScopePushPop() { this->Makefile->PopScope(); }
private:
cmMakefile* Makefile;
};
- void IssueMessage(cmake::MessageType t,
- std::string const& text) const;
+ void IssueMessage(cmake::MessageType t, std::string const& text) const;
/** Set whether or not to report a CMP0000 violation. */
void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
- std::vector<cmValueWithOrigin> GetIncludeDirectoriesEntries() const
- {
- return this->IncludeDirectoriesEntries;
- }
- std::vector<cmValueWithOrigin> GetCompileOptionsEntries() const
- {
- return this->CompileOptionsEntries;
- }
- std::vector<cmValueWithOrigin> GetCompileDefinitionsEntries() 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;
+
+ std::set<std::string> const& GetSystemIncludeDirectories() const
{
- return this->CompileDefinitionsEntries;
+ return this->SystemIncludeDirectories;
}
- bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
- void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
+ bool PolicyOptionalWarningEnabled(std::string const& var);
+
+ bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
+ std::string* error = CM_NULLPTR) const;
+
+ bool CompileFeatureKnown(cmTarget const* target, const std::string& feature,
+ std::string& lang, std::string* error) const;
+
+ const char* CompileFeaturesAvailable(const std::string& lang,
+ std::string* error) const;
+
+ bool HaveStandardAvailable(cmTarget const* target, std::string const& lang,
+ const std::string& feature) const;
+
+ bool IsLaterStandard(std::string const& lang, std::string const& lhs,
+ std::string const& rhs);
- std::set<cmStdString> const & GetSystemIncludeDirectories() const
- { return this->SystemIncludeDirectories; }
+ void PushLoopBlock();
+ void PopLoopBlock();
+ bool IsLoopBlock() const;
+
+ void ClearMatches();
+ void StoreMatches(cmsys::RegularExpression& re);
+
+ cmStateSnapshot GetStateSnapshot() const;
+
+ const char* GetDefineFlagsCMP0059() const;
+
+ std::string GetExecutionFilePath() const;
+
+ void EnforceDirectoryLevelRules() const;
+
+ void AddEvaluationFile(const std::string& inputFile,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> outputName,
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent);
+ std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const;
+
+ std::vector<cmExportBuildFileGenerator*> GetExportBuildFileGenerators()
+ const;
+ 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;
protected:
// add link libraries and directories to the target
- void AddGlobalLinkInformation(const char* name, cmTarget& target);
+ void AddGlobalLinkInformation(cmTarget& target);
// Check for a an unused variable
- void CheckForUnused(const char* reason, const char* name) const;
-
- std::string Prefix;
- std::vector<std::string> AuxSourceDirectories; //
+ void LogUnused(const char* reason, const std::string& name) const;
- std::string cmStartDirectory;
- std::string StartOutputDirectory;
- std::string cmHomeDirectory;
- std::string HomeOutputDirectory;
- std::string cmCurrentListFile;
-
- std::string ProjectName; // project name
+ mutable std::set<cmListFileContext> CMP0054ReportedIds;
// libraries, classes, and executables
- cmTargets Targets;
- std::map<std::string, cmTarget*> AliasTargets;
- cmGeneratorTargetsType GeneratorTargets;
+ mutable cmTargets Targets;
+ std::map<std::string, std::string> AliasTargets;
std::vector<cmSourceFile*> SourceFiles;
// Tests
- std::map<cmStdString, cmTest*> Tests;
-
- // The link-library paths. Order matters, use std::vector (not std::set).
- std::vector<std::string> LinkDirectories;
+ std::map<std::string, cmTest*> Tests;
// The set of include directories that are marked as system include
// directories.
- std::set<cmStdString> SystemIncludeDirectories;
-
- std::vector<std::string> ListFiles; // list of command files loaded
- std::vector<std::string> OutputFiles; // list of command files loaded
-
+ std::set<std::string> SystemIncludeDirectories;
- cmTarget::LinkLibraryVectorType LinkLibraries;
+ std::vector<std::string> ListFiles;
+ std::vector<std::string> OutputFiles;
std::vector<cmInstallGenerator*> InstallGenerators;
std::vector<cmTestGenerator*> TestGenerators;
- std::string IncludeFileRegularExpression;
std::string ComplainFileRegularExpression;
- std::vector<std::string> SourceFileExtensions;
- std::vector<std::string> HeaderFileExtensions;
std::string DefineFlags;
- std::vector<cmValueWithOrigin> IncludeDirectoriesEntries;
- std::vector<cmValueWithOrigin> CompileOptionsEntries;
- std::vector<cmValueWithOrigin> CompileDefinitionsEntries;
-
// Track the value of the computed DEFINITIONS property.
void AddDefineFlag(const char*, std::string&);
void RemoveDefineFlag(const char*, std::string::size_type, std::string&);
@@ -947,141 +828,123 @@ protected:
#if defined(CMAKE_BUILD_WITH_CMAKE)
std::vector<cmSourceGroup> SourceGroups;
+ size_t ObjectLibrariesSourceGroupIndex;
#endif
std::vector<cmCommand*> FinalPassCommands;
- cmLocalGenerator* LocalGenerator;
+ cmGlobalGenerator* GlobalGenerator;
bool IsFunctionBlocked(const cmListFileFunction& lff,
- cmExecutionStatus &status);
+ cmExecutionStatus& status);
private:
- void Initialize();
+ cmStateSnapshot StateSnapshot;
+ cmListFileBacktrace Backtrace;
- bool ParseDefineFlag(std::string const& definition, bool remove);
+ void ReadListFile(cmListFile const& listFile,
+ const std::string& filenametoread);
- bool EnforceUniqueDir(const char* srcPath, const char* binPath);
+ bool ParseDefineFlag(std::string const& definition, bool remove);
- void ReadSources(std::ifstream& fin, bool t);
- friend class cmMakeDepend; // make depend needs direct access
- // to the Sources array
- void PrintStringVector(const char* s, const
- std::vector<std::pair<cmStdString, bool> >& v) const;
- void PrintStringVector(const char* s,
- const std::vector<std::string>& v) const;
+ bool EnforceUniqueDir(const std::string& srcPath,
+ const std::string& binPath) const;
- void AddDefaultDefinitions();
typedef std::vector<cmFunctionBlocker*> FunctionBlockersType;
FunctionBlockersType FunctionBlockers;
std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers;
void PushFunctionBlockerBarrier();
void PopFunctionBlockerBarrier(bool reportError = true);
- typedef std::map<cmStdString, cmStdString> StringStringMap;
- StringStringMap MacrosMap;
-
- std::map<cmStdString, bool> SubDirectoryOrder;
+ std::stack<int> LoopBlockCounter;
- cmsys::RegularExpression cmDefineRegex;
- cmsys::RegularExpression cmDefine01Regex;
- cmsys::RegularExpression cmAtVarRegex;
+ mutable cmsys::RegularExpression cmDefineRegex;
+ mutable cmsys::RegularExpression cmDefine01Regex;
+ mutable cmsys::RegularExpression cmAtVarRegex;
+ mutable cmsys::RegularExpression cmNamedCurly;
- cmPropertyMap Properties;
+ std::vector<cmMakefile*> UnConfiguredDirectories;
+ std::vector<cmExportBuildFileGenerator*> ExportBuildFileGenerators;
- // should this makefile be processed before or after processing the parent
- bool PreOrder;
+ std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
- // Unused variable flags
- bool WarnUnused;
- bool CheckSystemVars;
-
- // stack of list files being read
- std::deque<cmStdString> ListFileStack;
-
- // stack of commands being invoked.
- struct CallStackEntry
- {
- cmListFileContext const* Context;
- cmExecutionStatus* Status;
- };
- typedef std::deque<CallStackEntry> CallStackType;
- CallStackType CallStack;
+ std::vector<cmExecutionStatus*> ExecutionStatusStack;
friend class cmMakefileCall;
+ friend class cmParseFileScope;
- cmTarget* FindBasicTarget(const char* name);
std::vector<cmTarget*> ImportedTargetsOwned;
- std::map<cmStdString, cmTarget*> ImportedTargets;
+ typedef CM_UNORDERED_MAP<std::string, cmTarget*> TargetMap;
+ TargetMap ImportedTargets;
// Internal policy stack management.
void PushPolicy(bool weak = false,
cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap());
void PopPolicy();
- void PushPolicyBarrier();
- void PopPolicyBarrier(bool reportError = true);
+ void PopSnapshot(bool reportError = true);
friend class cmCMakePolicyCommand;
class IncludeScope;
- friend class IncludeScope;
- // stack of policy settings
- struct PolicyStackEntry: public cmPolicies::PolicyMap
- {
- typedef cmPolicies::PolicyMap derived;
- PolicyStackEntry(bool w = false): derived(), Weak(w) {}
- PolicyStackEntry(derived const& d, bool w = false): derived(d), Weak(w) {}
- PolicyStackEntry(PolicyStackEntry const& r): derived(r), Weak(r.Weak) {}
- bool Weak;
- };
- typedef std::vector<PolicyStackEntry> PolicyStackType;
- PolicyStackType PolicyStack;
- std::vector<PolicyStackType::size_type> PolicyBarriers;
- cmPolicies::PolicyStatus GetPolicyStatusInternal(cmPolicies::PolicyID id);
-
- bool CheckCMP0000;
+ friend class IncludeScope;
+ class ListFileScope;
- // Enforce rules about CMakeLists.txt files.
- void EnforceDirectoryLevelRules();
+ friend class ListFileScope;
+ class BuildsystemFileScope;
- bool GeneratingBuildSystem;
+ 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;
+ // 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;
/**
- * Old version of GetSourceFileWithOutput(const char*) kept for
+ * 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 char*).
+ * GetSourceFileWithOutput(const std::string&).
*/
- cmSourceFile *LinearGetSourceFileWithOutput(const char *cname);
+ cmSourceFile* LinearGetSourceFileWithOutput(const std::string& cname) const;
// A map for fast output to input look up.
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- typedef cmsys::hash_map<std::string, cmSourceFile*> OutputToSourceMap;
-#else
- typedef std::map<std::string, cmSourceFile*> OutputToSourceMap;
-#endif
+ typedef CM_UNORDERED_MAP<std::string, cmSourceFile*> OutputToSourceMap;
OutputToSourceMap OutputToSource;
void UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
cmSourceFile* source);
void UpdateOutputToSourceMap(std::string const& output,
cmSourceFile* source);
-};
-//----------------------------------------------------------------------------
-// Helper class to make sure the call stack is valid.
-class cmMakefileCall
-{
-public:
- cmMakefileCall(cmMakefile* mf,
- cmListFileContext const& lfc,
- cmExecutionStatus& status): Makefile(mf)
- {
- cmMakefile::CallStackEntry entry = {&lfc, &status};
- this->Makefile->CallStack.push_back(entry);
- }
- ~cmMakefileCall()
- {
- this->Makefile->CallStack.pop_back();
- }
-private:
- cmMakefile* Makefile;
+ std::vector<cmSourceFile*> QtUiFilesWithOptions;
+
+ bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
+ std::string* error = CM_NULLPTR) const;
+
+ bool AddRequiredTargetCxxFeature(cmTarget* target,
+ const std::string& feature,
+ std::string* error = CM_NULLPTR) const;
+
+ void CheckNeededCLanguage(const std::string& feature, bool& needC90,
+ bool& needC99, bool& needC11) const;
+ void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
+ bool& needCxx11, bool& needCxx14,
+ bool& needCxx17) const;
+
+ bool HaveCStandardAvailable(cmTarget const* target,
+ const std::string& feature) const;
+ bool HaveCxxStandardAvailable(cmTarget const* target,
+ const std::string& feature) const;
+
+ void CheckForUnusedVariables() const;
+
+ // Unused variable flags
+ bool WarnUnused;
+ bool CheckSystemVars;
+ bool CheckCMP0000;
+ bool IsSourceFileTryCompile;
+ mutable bool SuppressWatches;
};
#endif
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 3a71bd6eb..359b9fdbb 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -1,47 +1,50 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileExecutableTargetGenerator.h"
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLinkLineComputer.h"
+#include "cmLinkLineDeviceComputer.h"
+#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmTarget.h"
+#include "cmOSXBundleGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
#include "cmake.h"
-//----------------------------------------------------------------------------
-cmMakefileExecutableTargetGenerator
-::cmMakefileExecutableTargetGenerator(cmTarget* target):
- cmMakefileTargetGenerator(target)
+cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
+ cmGeneratorTarget* target)
+ : cmMakefileTargetGenerator(target)
{
this->CustomCommandDriver = OnDepends;
- this->Target->GetExecutableNames(
+ this->GeneratorTarget->GetExecutableNames(
this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
this->TargetNamePDB, this->ConfigName);
- this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
- this->ConfigName);
+ this->OSXBundleGenerator =
+ new cmOSXBundleGenerator(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-//----------------------------------------------------------------------------
-cmMakefileExecutableTargetGenerator
-::~cmMakefileExecutableTargetGenerator()
+cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator()
{
delete this->OSXBundleGenerator;
}
-//----------------------------------------------------------------------------
void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
{
// create the build.make file and directory, put in the common blocks
@@ -56,13 +59,15 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// write in rules for object files and custom commands
this->WriteTargetBuildRules();
+ // write the device link rules
+ this->WriteDeviceExecutableRule(false);
+
// write the link rules
this->WriteExecutableRule(false);
- if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
- {
+ if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) {
// Write rules to link an installable version of the target.
this->WriteExecutableRule(true);
- }
+ }
// Write the requires target.
this->WriteTargetRequiresRules();
@@ -78,9 +83,222 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
this->CloseFileStreams();
}
+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) {
+ 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 =
+ this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+
+ // Get the name of the device object to generate.
+ std::string const targetOutputReal =
+ this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt;
+ this->DeviceLinkObject = targetOutputReal;
+
+ this->NumberOfProgressActions++;
+ if (!this->NoRuleMessages) {
+ 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);
+ this->LocalGenerator->AppendEcho(
+ commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
+ }
+
+ // Build a list of compiler flags and linker flags.
+ std::string flags;
+ std::string linkFlags;
+
+ // 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";
+ this->LocalGenerator->AppendFlags(
+ linkFlags, this->Makefile->GetDefinition(export_flag_var));
+ }
+
+ this->LocalGenerator->AppendFlags(linkFlags,
+ this->LocalGenerator->GetLinkLibsCMP0065(
+ linkLanguage, *this->GeneratorTarget));
+
+ // Add language feature flags.
+ this->LocalGenerator->AddLanguageFlagsForLinking(
+ flags, this->GeneratorTarget, linkLanguage, this->ConfigName);
+
+ this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
+ 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));
+
+ // Construct a list of files associated with this executable that
+ // may need to be cleaned.
+ std::vector<std::string> exeCleanFiles;
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal));
+
+ // Determine whether a link script will be used.
+ bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
+
+ // Construct the main link rule.
+ std::vector<std::string> real_link_commands;
+ 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);
+
+ bool useResponseFileForObjects =
+ this->CheckUseResponseFileForObjects(linkLanguage);
+ bool const useResponseFileForLibs =
+ this->CheckUseResponseFileForLibraries(linkLanguage);
+
+ // Expand the rule variables.
+ {
+ bool useWatcomQuote =
+ this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
+
+ // Set path conversion for link script shells.
+ this->LocalGenerator->SetLinkScriptShell(useLinkScript);
+
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ new cmLinkLineDeviceComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+ linkLineComputer->SetForResponse(useResponseFileForLibs);
+ linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+ linkLineComputer->SetRelink(relink);
+
+ // Collect up flags to link in needed libraries.
+ std::string linkLibs;
+ this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+ useResponseFileForLibs, depends);
+
+ // Construct object file lists that may be needed to expand the
+ // rule.
+ std::string buildObjs;
+ this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
+ buildObjs, depends, useWatcomQuote);
+
+ cmRulePlaceholderExpander::RuleVariables vars;
+ std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
+
+ objectDir = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ cmOutputConverter::SHELL);
+
+ cmOutputConverter::OutputFormat output = (useWatcomQuote)
+ ? cmOutputConverter::WATCOMQUOTE
+ : cmOutputConverter::SHELL;
+ std::string target = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal),
+ output);
+
+ std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB();
+ std::string targetOutPathCompilePDB =
+ this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB,
+ cmOutputConverter::SHELL);
+
+ vars.Language = linkLanguage.c_str();
+ vars.Objects = buildObjs.c_str();
+ vars.ObjectDir = objectDir.c_str();
+ vars.Target = target.c_str();
+ vars.LinkLibraries = linkLibs.c_str();
+ vars.Flags = flags.c_str();
+ vars.LinkFlags = linkFlags.c_str();
+ vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
+
+ std::string launcher;
+
+ const char* val = this->LocalGenerator->GetRuleLauncher(
+ this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ CM_AUTO_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);
+ }
+
+ // Restore path conversion to normal shells.
+ this->LocalGenerator->SetLinkScriptShell(false);
+ }
+
+ // Optionally convert the build rule to use a script to avoid long
+ // command lines in the make shell.
+ if (useLinkScript) {
+ // Use a link script.
+ const char* name = (relink ? "drelink.txt" : "dlink.txt");
+ this->CreateLinkScript(name, real_link_commands, commands1, depends);
+ } else {
+ // No link script. Just use the link rule directly.
+ commands1 = real_link_commands;
+ }
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+ commands1.clear();
+
+ // Write the build rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ targetOutputReal, depends, commands,
+ false);
+
+ // Write the main driver rule to build everything in this target.
+ this->WriteTargetDriverRule(targetOutputReal, relink);
+ // Clean all the possible executable names and symlinks.
+ this->CleanFiles.insert(this->CleanFiles.end(), exeCleanFiles.begin(),
+ exeCleanFiles.end());
+#else
+ static_cast<void>(relink);
+#endif
+}
-//----------------------------------------------------------------------------
void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
{
std::vector<std::string> commands;
@@ -88,194 +306,203 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// 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->Target->GetExecutableNames
- (targetName, targetNameReal, targetNameImport, targetNamePDB,
- this->ConfigName);
+ this->GeneratorTarget->GetExecutableNames(targetName, targetNameReal,
+ targetNameImport, targetNamePDB,
+ this->ConfigName);
// Construct the full path version of the names.
- std::string outpath = this->Target->GetDirectory(this->ConfigName);
- if(this->Target->IsAppBundleOnApple())
- {
+ std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
+ if (this->GeneratorTarget->IsAppBundleOnApple()) {
this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
- }
+ }
outpath += "/";
std::string outpathImp;
- if(relink)
- {
- outpath = this->Makefile->GetStartOutputDirectory();
+ if (relink) {
+ outpath = this->Makefile->GetCurrentBinaryDirectory();
outpath += cmake::GetCMakeFilesDirectory();
outpath += "/CMakeRelink.dir";
cmSystemTools::MakeDirectory(outpath.c_str());
outpath += "/";
- if(!targetNameImport.empty())
- {
+ if (!targetNameImport.empty()) {
outpathImp = outpath;
- }
}
- else
- {
+ } else {
cmSystemTools::MakeDirectory(outpath.c_str());
- if(!targetNameImport.empty())
- {
- outpathImp = this->Target->GetDirectory(this->ConfigName, true);
+ if (!targetNameImport.empty()) {
+ outpathImp = this->GeneratorTarget->GetDirectory(
+ this->ConfigName, cmStateEnums::ImportLibraryArtifact);
cmSystemTools::MakeDirectory(outpathImp.c_str());
outpathImp += "/";
- }
}
+ }
+
+ std::string compilePdbOutputPath =
+ this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
+ cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str());
- std::string pdbOutputPath = this->Target->GetPDBDirectory();
+ std::string pdbOutputPath =
+ this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
pdbOutputPath += "/";
std::string targetFullPath = outpath + targetName;
std::string targetFullPathReal = outpath + targetNameReal;
- std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
+ std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
std::string targetFullPathImport = outpathImp + targetNameImport;
- std::string targetOutPathPDB =
- this->Convert(targetFullPathPDB.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
+ std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
+ targetFullPathPDB, cmOutputConverter::SHELL);
// Convert to the output path to use in constructing commands.
- std::string targetOutPath =
- this->Convert(targetFullPath.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- std::string targetOutPathReal =
- this->Convert(targetFullPathReal.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
+ std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
+ cmOutputConverter::SHELL);
+ std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ cmOutputConverter::SHELL);
std::string targetOutPathImport =
- this->Convert(targetFullPathImport.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ targetFullPathImport),
+ cmOutputConverter::SHELL);
// Get the language to use for linking this executable.
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->ConfigName);
+ std::string linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
// Make sure we have a link language.
- if(!linkLanguage)
- {
+ if (linkLanguage.empty()) {
cmSystemTools::Error("Cannot determine link language for target \"",
- this->Target->GetName(), "\".");
+ this->GeneratorTarget->GetName().c_str(), "\".");
return;
- }
+ }
- if(!this->NoRuleMessages)
- {
+ 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;
- this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
- cmLocalUnixMakefileGenerator3::EchoLink);
- }
+ this->LocalGenerator->AppendEcho(
+ commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
+ }
// Build a list of compiler flags and linker flags.
std::string flags;
std::string linkFlags;
// Add flags to create an executable.
- this->LocalGenerator->
- AddConfigVariableFlags(linkFlags, "CMAKE_EXE_LINKER_FLAGS",
- this->ConfigName);
-
-
- if(this->Target->GetPropertyAsBool("WIN32_EXECUTABLE"))
- {
- this->LocalGenerator->AppendFlags
- (linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
- }
- else
- {
- this->LocalGenerator->AppendFlags
- (linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
- }
+ this->LocalGenerator->AddConfigVariableFlags(
+ linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->ConfigName);
+
+ if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+ this->LocalGenerator->AppendFlags(
+ linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
+ } else {
+ this->LocalGenerator->AppendFlags(
+ linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
+ }
// Add symbol export flags if necessary.
- if(this->Target->IsExecutableWithExports())
- {
+ if (this->GeneratorTarget->IsExecutableWithExports()) {
std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
export_flag_var += linkLanguage;
export_flag_var += "_FLAG";
- this->LocalGenerator->AppendFlags
- (linkFlags, this->Makefile->GetDefinition(export_flag_var.c_str()));
- }
+ this->LocalGenerator->AppendFlags(
+ linkFlags, this->Makefile->GetDefinition(export_flag_var));
+ }
+
+ this->LocalGenerator->AppendFlags(linkFlags,
+ this->LocalGenerator->GetLinkLibsCMP0065(
+ linkLanguage, *this->GeneratorTarget));
+
+ if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
+ this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed");
+ }
// Add language feature flags.
- this->AddFeatureFlags(flags, linkLanguage);
+ this->LocalGenerator->AddLanguageFlagsForLinking(
+ flags, this->GeneratorTarget, linkLanguage, this->ConfigName);
this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
linkLanguage, this->ConfigName);
// Add target-specific linker flags.
- this->LocalGenerator->AppendFlags
- (linkFlags, this->Target->GetProperty("LINK_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->Target->GetProperty(linkFlagsConfig.c_str()));
+ this->LocalGenerator->AppendFlags(
+ linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
- this->AddModuleDefinitionFlag(linkFlags);
+ {
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ this->CreateLinkLineComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+
+ this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags);
+ }
+
+ this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
+ this->ConfigName, linkLanguage);
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> exeCleanFiles;
- exeCleanFiles.push_back(this->Convert(targetFullPath.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
#ifdef _WIN32
// There may be a manifest file for this target. Add it to the
// clean set just in case.
- exeCleanFiles.push_back(this->Convert((targetFullPath+".manifest").c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ (targetFullPath + ".manifest").c_str()));
#endif
- if(targetNameReal != targetName)
- {
- exeCleanFiles.push_back(this->Convert(targetFullPathReal.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- if(!targetNameImport.empty())
- {
- exeCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
+ if (targetNameReal != targetName) {
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+ }
+ if (!targetNameImport.empty()) {
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ targetFullPathImport));
std::string implib;
- if(this->Target->GetImplibGNUtoMS(targetFullPathImport, implib))
- {
- exeCleanFiles.push_back(this->Convert(implib.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
+ if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
+ implib)) {
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
+ }
// 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->Convert(targetFullPathPDB.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
+ this->CleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
// Add the pre-build and pre-link rules building but not when relinking.
- if(!relink)
- {
- this->LocalGenerator
- ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands(),
- this->Target);
- this->LocalGenerator
- ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands(),
- this->Target);
- }
+ if (!relink) {
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPreBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPreLinkCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
+ }
// Determine whether a link script will be used.
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
@@ -285,167 +512,201 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string linkRuleVar = "CMAKE_";
linkRuleVar += linkLanguage;
linkRuleVar += "_LINK_EXECUTABLE";
- std::string linkRule = this->GetLinkRule(linkRuleVar.c_str());
+ std::string linkRule = this->GetLinkRule(linkRuleVar);
std::vector<std::string> commands1;
cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
- if(this->Target->IsExecutableWithExports())
- {
+ 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";
- if(const char* rule =
- this->Makefile->GetDefinition(implibRuleVar.c_str()))
- {
+ if (const char* rule = this->Makefile->GetDefinition(implibRuleVar)) {
cmSystemTools::ExpandListArgument(rule, real_link_commands);
- }
- }
-
- // Select whether to use a response file for objects.
- bool useResponseFile = false;
- {
- std::string responseVar = "CMAKE_";
- responseVar += linkLanguage;
- responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
- if(this->Makefile->IsOn(responseVar.c_str()))
- {
- useResponseFile = true;
}
}
+ bool useResponseFileForObjects =
+ this->CheckUseResponseFileForObjects(linkLanguage);
+ bool const useResponseFileForLibs =
+ this->CheckUseResponseFileForLibraries(linkLanguage);
+
// Expand the rule variables.
{
- // Set path conversion for link script shells.
- this->LocalGenerator->SetLinkScriptShell(useLinkScript);
-
- // Collect up flags to link in needed libraries.
- std::string linkLibs;
- std::string frameworkPath;
- std::string linkPath;
- this->LocalGenerator->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
- *this->GeneratorTarget,
- relink);
- linkLibs = frameworkPath + linkPath + linkLibs;
- // Construct object file lists that may be needed to expand the
- // rule.
- std::string buildObjs;
- this->CreateObjectLists(useLinkScript, false, useResponseFile,
- buildObjs, depends);
-
- cmLocalGenerator::RuleVariables vars;
- vars.RuleLauncher = "RULE_LAUNCH_LINK";
- vars.CMTarget = this->Target;
- vars.Language = linkLanguage;
- vars.Objects = buildObjs.c_str();
- std::string objectDir = this->Target->GetSupportDirectory();
- objectDir = this->Convert(objectDir.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- vars.ObjectDir = objectDir.c_str();
- vars.Target = targetOutPathReal.c_str();
- vars.TargetPDB = targetOutPathPDB.c_str();
-
- // Setup the target version.
- std::string targetVersionMajor;
- std::string targetVersionMinor;
- {
- cmOStringStream majorStream;
- cmOStringStream minorStream;
- int major;
- int minor;
- this->Target->GetTargetVersion(major, minor);
- majorStream << major;
- minorStream << minor;
- targetVersionMajor = majorStream.str();
- targetVersionMinor = minorStream.str();
- }
- vars.TargetVersionMajor = targetVersionMajor.c_str();
- vars.TargetVersionMinor = targetVersionMinor.c_str();
-
- vars.LinkLibraries = linkLibs.c_str();
- vars.Flags = flags.c_str();
- vars.LinkFlags = linkFlags.c_str();
- // Expand placeholders in the commands.
- this->LocalGenerator->TargetImplib = targetOutPathImport;
- for(std::vector<std::string>::iterator i = real_link_commands.begin();
- i != real_link_commands.end(); ++i)
+ bool useWatcomQuote =
+ this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
+
+ // Set path conversion for link script shells.
+ this->LocalGenerator->SetLinkScriptShell(useLinkScript);
+
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ this->CreateLinkLineComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+ linkLineComputer->SetForResponse(useResponseFileForLibs);
+ linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+ linkLineComputer->SetRelink(relink);
+
+ // Collect up flags to link in needed libraries.
+ std::string linkLibs;
+ this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+ useResponseFileForLibs, depends);
+
+ // Construct object file lists that may be needed to expand the
+ // rule.
+ std::string buildObjs;
+ this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
+ buildObjs, depends, useWatcomQuote);
+ if (!this->DeviceLinkObject.empty()) {
+ buildObjs += " " +
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->DeviceLinkObject),
+ cmOutputConverter::SHELL);
+ }
+
+ // maybe create .def file from list of objects
+ this->GenDefFile(real_link_commands);
+
+ std::string manifests = this->GetManifests();
+
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
+ vars.Language = linkLanguage.c_str();
+ vars.Objects = buildObjs.c_str();
+ std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
+
+ objectDir = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ cmOutputConverter::SHELL);
+ vars.ObjectDir = objectDir.c_str();
+ cmOutputConverter::OutputFormat output = (useWatcomQuote)
+ ? cmOutputConverter::WATCOMQUOTE
+ : cmOutputConverter::SHELL;
+ std::string target = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ output);
+ vars.Target = target.c_str();
+ vars.TargetPDB = targetOutPathPDB.c_str();
+
+ // Setup the target version.
+ std::string targetVersionMajor;
+ std::string targetVersionMinor;
{
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ std::ostringstream majorStream;
+ std::ostringstream minorStream;
+ int major;
+ int minor;
+ this->GeneratorTarget->GetTargetVersion(major, minor);
+ majorStream << major;
+ minorStream << minor;
+ targetVersionMajor = majorStream.str();
+ targetVersionMinor = minorStream.str();
+ }
+ vars.TargetVersionMajor = targetVersionMajor.c_str();
+ vars.TargetVersionMinor = targetVersionMinor.c_str();
+
+ vars.LinkLibraries = linkLibs.c_str();
+ vars.Flags = flags.c_str();
+ vars.LinkFlags = linkFlags.c_str();
+ 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 launcher;
+
+ const char* val = this->LocalGenerator->GetRuleLauncher(
+ this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ CM_AUTO_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);
}
- this->LocalGenerator->TargetImplib = "";
- // Restore path conversion to normal shells.
- this->LocalGenerator->SetLinkScriptShell(false);
+ // Restore path conversion to normal shells.
+ this->LocalGenerator->SetLinkScriptShell(false);
}
// Optionally convert the build rule to use a script to avoid long
// command lines in the make shell.
- if(useLinkScript)
- {
+ if (useLinkScript) {
// Use a link script.
- const char* name = (relink? "relink.txt" : "link.txt");
+ const char* name = (relink ? "relink.txt" : "link.txt");
this->CreateLinkScript(name, real_link_commands, commands1, depends);
- }
- else
- {
+ } else {
// No link script. Just use the link rule directly.
commands1 = real_link_commands;
- }
- this->LocalGenerator->CreateCDCommand
- (commands1,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
+ }
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
commands1.clear();
// Add a rule to create necessary symlinks for the library.
- if(targetOutPath != targetOutPathReal)
- {
+ if (targetOutPath != targetOutPathReal) {
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
symlink += targetOutPathReal;
symlink += " ";
symlink += targetOutPath;
commands1.push_back(symlink);
- this->LocalGenerator->CreateCDCommand(commands1,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
commands1.clear();
- }
+ }
// Add the post-build rules when building but not when relinking.
- if(!relink)
- {
- this->LocalGenerator->
- AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
- this->Target);
- }
+ if (!relink) {
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPostBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
+ }
// Write the build rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
- 0,
- targetFullPathReal.c_str(),
- depends, commands, false);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ targetFullPathReal, depends, commands,
+ false);
// The symlink name for the target should depend on the real target
// so if the target version changes it rebuilds and recreates the
// symlink.
- if(targetFullPath != targetFullPathReal)
- {
+ if (targetFullPath != targetFullPathReal) {
depends.clear();
commands.clear();
- depends.push_back(targetFullPathReal.c_str());
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- targetFullPath.c_str(),
- depends, commands, false);
- }
+ depends.push_back(targetFullPathReal);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ targetFullPath, depends, commands,
+ false);
+ }
// Write the main driver rule to build everything in this target.
- this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
+ this->WriteTargetDriverRule(targetFullPath, relink);
// Clean all the possible executable names and symlinks.
- this->CleanFiles.insert(this->CleanFiles.end(),
- exeCleanFiles.begin(),
+ this->CleanFiles.insert(this->CleanFiles.end(), exeCleanFiles.begin(),
exeCleanFiles.end());
}
diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h
index 3b18166ff..01aa6270c 100644
--- a/Source/cmMakefileExecutableTargetGenerator.h
+++ b/Source/cmMakefileExecutableTargetGenerator.h
@@ -1,31 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMakefileExecutableTargetGenerator_h
#define cmMakefileExecutableTargetGenerator_h
+#include "cmConfigure.h"
+
+#include <string>
+
#include "cmMakefileTargetGenerator.h"
-class cmMakefileExecutableTargetGenerator: public cmMakefileTargetGenerator
+class cmGeneratorTarget;
+
+class cmMakefileExecutableTargetGenerator : public cmMakefileTargetGenerator
{
public:
- cmMakefileExecutableTargetGenerator(cmTarget* target);
- virtual ~cmMakefileExecutableTargetGenerator();
+ cmMakefileExecutableTargetGenerator(cmGeneratorTarget* target);
+ ~cmMakefileExecutableTargetGenerator() CM_OVERRIDE;
/* the main entry point for this class. Writes the Makefiles associated
with this target */
- virtual void WriteRuleFiles();
+ void WriteRuleFiles() CM_OVERRIDE;
protected:
virtual void WriteExecutableRule(bool relink);
+ virtual void WriteDeviceExecutableRule(bool relink);
+
+private:
+ std::string DeviceLinkObject;
};
#endif
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index ffe68e5b2..3d1594bdb 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -1,47 +1,51 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileLibraryTargetGenerator.h"
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLinkLineComputer.h"
+#include "cmLinkLineDeviceComputer.h"
+#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmTarget.h"
+#include "cmOSXBundleGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
#include "cmake.h"
-//----------------------------------------------------------------------------
-cmMakefileLibraryTargetGenerator
-::cmMakefileLibraryTargetGenerator(cmTarget* target):
- cmMakefileTargetGenerator(target)
+cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
+ cmGeneratorTarget* target)
+ : cmMakefileTargetGenerator(target)
{
this->CustomCommandDriver = OnDepends;
- this->Target->GetLibraryNames(
- this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
- this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
+ if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ this->GeneratorTarget->GetLibraryNames(
+ this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
+ this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
+ }
- this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
- this->ConfigName);
+ this->OSXBundleGenerator =
+ new cmOSXBundleGenerator(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-//----------------------------------------------------------------------------
-cmMakefileLibraryTargetGenerator
-::~cmMakefileLibraryTargetGenerator()
+cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator()
{
delete this->OSXBundleGenerator;
}
-//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
{
// create the build.make file and directory, put in the common blocks
@@ -58,35 +62,32 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
// write the link rules
// Write the rule for this target type.
- switch(this->Target->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
this->WriteStaticLibraryRules();
break;
- case cmTarget::SHARED_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
this->WriteSharedLibraryRules(false);
- if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
- {
+ if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) {
// Write rules to link an installable version of the target.
this->WriteSharedLibraryRules(true);
- }
+ }
break;
- case cmTarget::MODULE_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
this->WriteModuleLibraryRules(false);
- if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
- {
+ if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) {
// Write rules to link an installable version of the target.
this->WriteModuleLibraryRules(true);
- }
+ }
break;
- case cmTarget::OBJECT_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
this->WriteObjectLibraryRules();
break;
default:
// If language is not known, this is an error.
cmSystemTools::Error("Unknown Library Type");
break;
- }
+ }
// Write the requires target.
this->WriteTargetRequiresRules();
@@ -102,140 +103,186 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
this->CloseFileStreams();
}
-//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
{
std::vector<std::string> commands;
std::vector<std::string> depends;
// Add post-build rules.
- this->LocalGenerator->
- AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
- this->Target);
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPostBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
// Depend on the object files.
this->AppendObjectDepends(depends);
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- this->Target->GetName(),
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->GeneratorTarget->GetName(),
depends, commands, true);
// Write the main driver rule to build everything in this target.
- this->WriteTargetDriverRule(this->Target->GetName(), false);
+ this->WriteTargetDriverRule(this->GeneratorTarget->GetName(), false);
}
-//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
{
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->ConfigName);
- std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
- }
- linkRuleVar += "_CREATE_STATIC_LIBRARY";
+ 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) {
+ 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);
+ }
- if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") &&
- this->Makefile->GetDefinition((linkRuleVar+"_IPO").c_str()))
- {
- linkRuleVar += "_IPO";
- }
+ std::string linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
+
+ std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
+ linkLanguage, this->ConfigName);
std::string extraFlags;
- this->LocalGenerator->GetStaticLibraryFlags(extraFlags,
- cmSystemTools::UpperCase(this->ConfigName), this->Target);
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
+ this->LocalGenerator->GetStaticLibraryFlags(
+ extraFlags, cmSystemTools::UpperCase(this->ConfigName),
+ this->GeneratorTarget);
+ this->WriteLibraryRules(linkRuleVar, extraFlags, false);
}
-//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
{
- if(this->Target->IsFrameworkOnApple())
- {
+ if (this->GeneratorTarget->IsFrameworkOnApple()) {
this->WriteFrameworkRules(relink);
return;
+ }
+
+ 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) {
+ 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);
}
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->ConfigName);
+ }
+
+ std::string linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
- }
+ linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_SHARED_LIBRARY";
std::string extraFlags;
- this->LocalGenerator->AppendFlags
- (extraFlags, this->Target->GetProperty("LINK_FLAGS"));
+ this->LocalGenerator->AppendFlags(
+ extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
std::string linkFlagsConfig = "LINK_FLAGS_";
linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags
- (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
+ this->LocalGenerator->AppendFlags(
+ extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+
+ this->LocalGenerator->AddConfigVariableFlags(
+ extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
- this->LocalGenerator->AddConfigVariableFlags
- (extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
- this->AddModuleDefinitionFlag(extraFlags);
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ this->CreateLinkLineComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
+ this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
+
+ if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
+ this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
+ }
+ this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
-//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
{
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->ConfigName);
- std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
+
+ 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) {
+ 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);
}
+ }
+
+ std::string linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
+ std::string linkRuleVar = "CMAKE_";
+ linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_SHARED_MODULE";
std::string extraFlags;
- this->LocalGenerator->AppendFlags(extraFlags,
- this->Target->GetProperty("LINK_FLAGS"));
+ this->LocalGenerator->AppendFlags(
+ extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
std::string linkFlagsConfig = "LINK_FLAGS_";
linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags
- (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
- this->LocalGenerator->AddConfigVariableFlags
- (extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
- this->AddModuleDefinitionFlag(extraFlags);
+ this->LocalGenerator->AppendFlags(
+ extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->LocalGenerator->AddConfigVariableFlags(
+ extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
+
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ this->CreateLinkLineComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
+ this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
+
+ this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
-//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
{
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->ConfigName);
+ std::string linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
- }
+ linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
std::string extraFlags;
- this->LocalGenerator->AppendFlags(extraFlags,
- this->Target->GetProperty("LINK_FLAGS"));
+ this->LocalGenerator->AppendFlags(
+ extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
std::string linkFlagsConfig = "LINK_FLAGS_";
linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags
- (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
- this->LocalGenerator->AddConfigVariableFlags
- (extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
+ this->LocalGenerator->AppendFlags(
+ extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->LocalGenerator->AddConfigVariableFlags(
+ extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
+ this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
-//----------------------------------------------------------------------------
-void cmMakefileLibraryTargetGenerator::WriteLibraryRules
-(const char* linkRuleVar, const char* extraFlags, bool relink)
+void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
+ const std::string& linkRuleVar, const std::string& extraFlags, bool relink)
{
+#ifdef CMAKE_BUILD_WITH_CMAKE
// TODO: Merge the methods that call this method to avoid
// code duplication.
std::vector<std::string> commands;
@@ -245,28 +292,217 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
this->AppendLinkDepends(depends);
// Get the language to use for linking this library.
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->ConfigName);
+ std::string linkLanguage = "CUDA";
+ std::string const objExt =
+ this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+
+ // Create set of linking flags.
+ std::string linkFlags;
+ this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+
+ // Get the name of the device object to generate.
+ std::string const targetOutputReal =
+ this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt;
+ this->DeviceLinkObject = targetOutputReal;
+
+ this->NumberOfProgressActions++;
+ if (!this->NoRuleMessages) {
+ 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);
+ 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(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal));
+
+ // Determine whether a link script will be used.
+ bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
+
+ bool useResponseFileForObjects =
+ this->CheckUseResponseFileForObjects(linkLanguage);
+ bool const useResponseFileForLibs =
+ this->CheckUseResponseFileForLibraries(linkLanguage);
+
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.Language = linkLanguage.c_str();
+
+ // Expand the rule variables.
+ std::vector<std::string> real_link_commands;
+ {
+ bool useWatcomQuote =
+ this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
+
+ // Set path conversion for link script shells.
+ this->LocalGenerator->SetLinkScriptShell(useLinkScript);
+
+ // 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);
+
+ this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+ useResponseFileForLibs, depends);
+ }
+
+ // Construct object file lists that may be needed to expand the
+ // rule.
+ std::string buildObjs;
+ this->CreateObjectLists(useLinkScript, false, // useArchiveRules
+ useResponseFileForObjects, buildObjs, depends,
+ useWatcomQuote);
+
+ cmOutputConverter::OutputFormat output = (useWatcomQuote)
+ ? cmOutputConverter::WATCOMQUOTE
+ : cmOutputConverter::SHELL;
+
+ std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
+ objectDir = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ cmOutputConverter::SHELL);
+
+ std::string target = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal),
+ output);
+
+ std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB();
+ std::string targetOutPathCompilePDB =
+ this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB,
+ cmOutputConverter::SHELL);
+
+ vars.Objects = buildObjs.c_str();
+ vars.ObjectDir = objectDir.c_str();
+ vars.Target = target.c_str();
+ vars.LinkLibraries = linkLibs.c_str();
+ vars.ObjectsQuoted = buildObjs.c_str();
+ vars.LinkFlags = linkFlags.c_str();
+ vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
+
+ // Add language-specific flags.
+ std::string langFlags;
+ this->LocalGenerator->AddLanguageFlagsForLinking(
+ langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
+
+ vars.LanguageCompileFlags = langFlags.c_str();
+
+ std::string launcher;
+ const char* val = this->LocalGenerator->GetRuleLauncher(
+ this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ CM_AUTO_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);
+
+ // 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);
+ }
+ // 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());
+ }
+
+ std::vector<std::string> commands1;
+ // Optionally convert the build rule to use a script to avoid long
+ // command lines in the make shell.
+ if (useLinkScript) {
+ // Use a link script.
+ const char* name = (relink ? "drelink.txt" : "dlink.txt");
+ this->CreateLinkScript(name, real_link_commands, commands1, depends);
+ } else {
+ // No link script. Just use the link rule directly.
+ commands1 = real_link_commands;
+ }
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+ 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,
+ 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
+}
+
+void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
+ const std::string& linkRuleVar, const std::string& extraFlags, bool relink)
+{
+ // 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);
+ 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)
- {
+ if (linkLanguage.empty()) {
cmSystemTools::Error("Cannot determine link language for target \"",
- this->Target->GetName(), "\".");
+ this->GeneratorTarget->GetName().c_str(), "\".");
return;
- }
+ }
// Create set of linking flags.
std::string linkFlags;
this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+ this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
+ this->ConfigName, linkLanguage);
// Add OSX version flags, if any.
- if(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
- this->Target->GetType() == cmTarget::MODULE_LIBRARY)
- {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
this->AppendOSXVerFlag(linkFlags, linkLanguage, "COMPATIBILITY", true);
this->AppendOSXVerFlag(linkFlags, linkLanguage, "CURRENT", false);
- }
+ }
// Construct the name of the library.
std::string targetName;
@@ -274,51 +510,48 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
- this->Target->GetLibraryNames(
- targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB,
- this->ConfigName);
+ this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
+ targetNameReal, targetNameImport,
+ targetNamePDB, this->ConfigName);
// Construct the full path version of the names.
std::string outpath;
std::string outpathImp;
- if(this->Target->IsFrameworkOnApple())
- {
- outpath = this->Target->GetDirectory(this->ConfigName);
+ if (this->GeneratorTarget->IsFrameworkOnApple()) {
+ outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
this->OSXBundleGenerator->CreateFramework(targetName, outpath);
outpath += "/";
- }
- else if(this->Target->IsCFBundleOnApple())
- {
- outpath = this->Target->GetDirectory(this->ConfigName);
+ } else if (this->GeneratorTarget->IsCFBundleOnApple()) {
+ outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
outpath += "/";
- }
- else if(relink)
- {
- outpath = this->Makefile->GetStartOutputDirectory();
+ } else if (relink) {
+ outpath = this->Makefile->GetCurrentBinaryDirectory();
outpath += cmake::GetCMakeFilesDirectory();
outpath += "/CMakeRelink.dir";
cmSystemTools::MakeDirectory(outpath.c_str());
outpath += "/";
- if(!targetNameImport.empty())
- {
+ if (!targetNameImport.empty()) {
outpathImp = outpath;
- }
}
- else
- {
- outpath = this->Target->GetDirectory(this->ConfigName);
+ } else {
+ outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
cmSystemTools::MakeDirectory(outpath.c_str());
outpath += "/";
- if(!targetNameImport.empty())
- {
- outpathImp = this->Target->GetDirectory(this->ConfigName, true);
+ if (!targetNameImport.empty()) {
+ outpathImp = this->GeneratorTarget->GetDirectory(
+ this->ConfigName, cmStateEnums::ImportLibraryArtifact);
cmSystemTools::MakeDirectory(outpathImp.c_str());
outpathImp += "/";
- }
}
+ }
+
+ std::string compilePdbOutputPath =
+ this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
+ cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str());
- std::string pdbOutputPath = this->Target->GetPDBDirectory();
+ std::string pdbOutputPath =
+ this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
pdbOutputPath += "/";
@@ -330,153 +563,128 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
// Construct the output path version of the names for use in command
// arguments.
- std::string targetOutPathPDB =
- this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
- std::string targetOutPath =
- this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- std::string targetOutPathSO =
- this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- std::string targetOutPathReal =
- this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
+ std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
+ targetFullPathPDB, cmOutputConverter::SHELL);
+
+ std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
+ cmOutputConverter::SHELL);
+ std::string targetOutPathSO = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO),
+ cmOutputConverter::SHELL);
+ std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ cmOutputConverter::SHELL);
std::string targetOutPathImport =
- this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
-
- if(!this->NoRuleMessages)
- {
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ targetFullPathImport),
+ cmOutputConverter::SHELL);
+
+ this->NumberOfProgressActions++;
+ if (!this->NoRuleMessages) {
+ cmLocalUnixMakefileGenerator3::EchoProgress progress;
+ this->MakeEchoProgress(progress);
// Add the link message.
std::string buildEcho = "Linking ";
buildEcho += linkLanguage;
- switch(this->Target->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
buildEcho += " static library ";
break;
- case cmTarget::SHARED_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
buildEcho += " shared library ";
break;
- case cmTarget::MODULE_LIBRARY:
- if (this->Target->IsCFBundleOnApple())
- buildEcho += " CFBundle";
+ case cmStateEnums::MODULE_LIBRARY:
+ if (this->GeneratorTarget->IsCFBundleOnApple()) {
+ buildEcho += " CFBundle";
+ }
buildEcho += " shared module ";
break;
default:
buildEcho += " library ";
break;
- }
- buildEcho += targetOutPath.c_str();
- this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
- cmLocalUnixMakefileGenerator3::EchoLink);
- }
-
- const char* forbiddenFlagVar = 0;
- switch(this->Target->GetType())
- {
- case cmTarget::SHARED_LIBRARY:
- forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
- break;
- case cmTarget::MODULE_LIBRARY:
- forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
- break;
- default: break;
}
+ buildEcho += targetOutPath;
+ this->LocalGenerator->AppendEcho(
+ commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
+ }
// Clean files associated with this library.
std::vector<std::string> libCleanFiles;
- libCleanFiles.push_back(this->Convert(targetFullPath.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- if(targetNameReal != targetName)
- {
- libCleanFiles.push_back(this->Convert(targetFullPathReal.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- if(targetNameSO != targetName &&
- targetNameSO != targetNameReal)
- {
- libCleanFiles.push_back(this->Convert(targetFullPathSO.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- if(!targetNameImport.empty())
- {
- libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
+ libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+
+ std::vector<std::string> commands1;
+ // Add a command to remove any existing files for this library.
+ // for static libs only
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
+ this->GeneratorTarget, "target");
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+ commands1.clear();
+ }
+
+ if (targetName != targetNameReal) {
+ libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+ }
+ if (targetNameSO != targetNameReal && targetNameSO != targetName) {
+ libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO));
+ }
+ if (!targetNameImport.empty()) {
+ libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ targetFullPathImport));
std::string implib;
- if(this->Target->GetImplibGNUtoMS(targetFullPathImport, implib))
- {
- libCleanFiles.push_back(this->Convert(implib.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
+ if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
+ implib)) {
+ libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
+ }
// 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->Convert(targetFullPathPDB.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
+ this->CleanFiles.push_back(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->Target->GetType() != cmTarget::STATIC_LIBRARY)
- {
- libCleanFiles.push_back(
- this->Convert((targetFullPath+".manifest").c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
+ if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
+ libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ (targetFullPath + ".manifest").c_str()));
+ }
#endif
- std::vector<std::string> commands1;
- // Add a command to remove any existing files for this library.
- // for static libs only
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
- {
- this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
- *this->Target, "target");
- this->LocalGenerator->CreateCDCommand
- (commands1,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
- commands.insert(commands.end(), commands1.begin(), commands1.end());
- commands1.clear();
- }
-
// Add the pre-build and pre-link rules building but not when relinking.
- if(!relink)
- {
- this->LocalGenerator
- ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands(),
- this->Target);
- this->LocalGenerator
- ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands(),
- this->Target);
- }
+ if (!relink) {
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPreBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPreLinkCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
+ }
// Determine whether a link script will be used.
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
- // Select whether to use a response file for objects.
- bool useResponseFile = false;
- {
- std::string responseVar = "CMAKE_";
- responseVar += linkLanguage;
- responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
- if(this->Makefile->IsOn(responseVar.c_str()))
- {
- useResponseFile = true;
- }
- }
+ bool useResponseFileForObjects =
+ this->CheckUseResponseFileForObjects(linkLanguage);
+ bool const useResponseFileForLibs =
+ this->CheckUseResponseFileForLibraries(linkLanguage);
// For static libraries there might be archiving rules.
bool haveStaticLibraryRule = false;
@@ -484,242 +692,291 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::vector<std::string> archiveAppendCommands;
std::vector<std::string> archiveFinishCommands;
std::string::size_type archiveCommandLimit = std::string::npos;
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
- {
- haveStaticLibraryRule =
- this->Makefile->GetDefinition(linkRuleVar)? true:false;
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ haveStaticLibraryRule = this->Makefile->IsDefinitionSet(linkRuleVar);
std::string arCreateVar = "CMAKE_";
arCreateVar += linkLanguage;
arCreateVar += "_ARCHIVE_CREATE";
- if(const char* rule = this->Makefile->GetDefinition(arCreateVar.c_str()))
- {
+
+ arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+ arCreateVar, linkLanguage, this->ConfigName);
+
+ if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) {
cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
- }
+ }
std::string arAppendVar = "CMAKE_";
arAppendVar += linkLanguage;
arAppendVar += "_ARCHIVE_APPEND";
- if(const char* rule = this->Makefile->GetDefinition(arAppendVar.c_str()))
- {
+
+ arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+ arAppendVar, linkLanguage, this->ConfigName);
+
+ if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) {
cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
- }
+ }
std::string arFinishVar = "CMAKE_";
arFinishVar += linkLanguage;
arFinishVar += "_ARCHIVE_FINISH";
- if(const char* rule = this->Makefile->GetDefinition(arFinishVar.c_str()))
- {
+
+ arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+ arFinishVar, linkLanguage, this->ConfigName);
+
+ if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) {
cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
- }
}
+ }
// Decide whether to use archiving rules.
- bool useArchiveRules =
- !haveStaticLibraryRule &&
+ bool useArchiveRules = !haveStaticLibraryRule &&
!archiveCreateCommands.empty() && !archiveAppendCommands.empty();
- if(useArchiveRules)
- {
+ if (useArchiveRules) {
// Archiving rules are always run with a link script.
useLinkScript = true;
// Archiving rules never use a response file.
- useResponseFile = false;
+ 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;
- }
+ }
// Expand the rule variables.
std::vector<std::string> real_link_commands;
{
- // Set path conversion for link script shells.
- this->LocalGenerator->SetLinkScriptShell(useLinkScript);
-
- // Collect up flags to link in needed libraries.
- std::string linkLibs;
- if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
- {
- std::string frameworkPath;
- std::string linkPath;
- this->LocalGenerator
- ->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
- *this->GeneratorTarget, relink);
- linkLibs = frameworkPath + linkPath + linkLibs;
- }
-
- // Construct object file lists that may be needed to expand the
- // rule.
- std::string buildObjs;
- this->CreateObjectLists(useLinkScript, useArchiveRules, useResponseFile,
- buildObjs, depends);
-
- cmLocalGenerator::RuleVariables vars;
- vars.TargetPDB = targetOutPathPDB.c_str();
-
- // Setup the target version.
- std::string targetVersionMajor;
- std::string targetVersionMinor;
- {
- cmOStringStream majorStream;
- cmOStringStream minorStream;
- int major;
- int minor;
- this->Target->GetTargetVersion(major, minor);
- majorStream << major;
- minorStream << minor;
- targetVersionMajor = majorStream.str();
- targetVersionMinor = minorStream.str();
- }
- vars.TargetVersionMajor = targetVersionMajor.c_str();
- vars.TargetVersionMinor = targetVersionMinor.c_str();
-
- vars.RuleLauncher = "RULE_LAUNCH_LINK";
- vars.CMTarget = this->Target;
- vars.Language = linkLanguage;
- vars.Objects = buildObjs.c_str();
- std::string objectDir = this->Target->GetSupportDirectory();
- objectDir = this->Convert(objectDir.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- vars.ObjectDir = objectDir.c_str();
- vars.Target = targetOutPathReal.c_str();
- vars.LinkLibraries = linkLibs.c_str();
- vars.ObjectsQuoted = buildObjs.c_str();
- if (this->Target->HasSOName(this->ConfigName))
- {
- vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
- vars.TargetSOName= targetNameSO.c_str();
- }
- vars.LinkFlags = linkFlags.c_str();
-
- // Compute the directory portion of the install_name setting.
- std::string install_name_dir;
- if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
- {
- // Get the install_name directory for the build tree.
- install_name_dir =
- this->Target->GetInstallNameDirForBuildTree(this->ConfigName);
-
- // Set the rule variable replacement value.
- if(install_name_dir.empty())
- {
- vars.TargetInstallNameDir = "";
- }
- else
- {
- // Convert to a path for the native build tool.
+ bool useWatcomQuote =
+ this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
+
+ // Set path conversion for link script shells.
+ this->LocalGenerator->SetLinkScriptShell(useLinkScript);
+
+ // Collect up flags to link in needed libraries.
+ std::string linkLibs;
+ if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
+
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ this->CreateLinkLineComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+ linkLineComputer->SetForResponse(useResponseFileForLibs);
+ linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+ linkLineComputer->SetRelink(relink);
+
+ this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+ useResponseFileForLibs, depends);
+ }
+
+ // Construct object file lists that may be needed to expand the
+ // rule.
+ std::string buildObjs;
+ this->CreateObjectLists(useLinkScript, useArchiveRules,
+ useResponseFileForObjects, buildObjs, depends,
+ useWatcomQuote);
+ if (!this->DeviceLinkObject.empty()) {
+ buildObjs += " " +
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->DeviceLinkObject),
+ cmOutputConverter::SHELL);
+ }
+
+ // maybe create .def file from list of objects
+ this->GenDefFile(real_link_commands);
+
+ std::string manifests = this->GetManifests();
+
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.TargetPDB = targetOutPathPDB.c_str();
+
+ // Setup the target version.
+ std::string targetVersionMajor;
+ std::string targetVersionMinor;
+ {
+ std::ostringstream majorStream;
+ std::ostringstream minorStream;
+ int major;
+ int minor;
+ this->GeneratorTarget->GetTargetVersion(major, minor);
+ majorStream << major;
+ minorStream << minor;
+ targetVersionMajor = majorStream.str();
+ targetVersionMinor = minorStream.str();
+ }
+ vars.TargetVersionMajor = targetVersionMajor.c_str();
+ vars.TargetVersionMinor = targetVersionMinor.c_str();
+
+ vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
+ vars.Language = linkLanguage.c_str();
+ vars.Objects = buildObjs.c_str();
+ std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
+
+ objectDir = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ cmOutputConverter::SHELL);
+
+ vars.ObjectDir = objectDir.c_str();
+ cmOutputConverter::OutputFormat output = (useWatcomQuote)
+ ? cmOutputConverter::WATCOMQUOTE
+ : cmOutputConverter::SHELL;
+ std::string target = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ output);
+ vars.Target = target.c_str();
+ vars.LinkLibraries = linkLibs.c_str();
+ vars.ObjectsQuoted = buildObjs.c_str();
+ if (this->GeneratorTarget->HasSOName(this->ConfigName)) {
+ vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
+ vars.TargetSOName = targetNameSO.c_str();
+ }
+ vars.LinkFlags = linkFlags.c_str();
+
+ vars.Manifests = manifests.c_str();
+
+ // Compute the directory portion of the install_name setting.
+ std::string install_name_dir;
+ if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ // Get the install_name directory for the build tree.
install_name_dir =
- this->LocalGenerator->Convert(install_name_dir.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL, false);
- vars.TargetInstallNameDir = install_name_dir.c_str();
+ this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName);
+
+ // Set the rule variable replacement value.
+ if (install_name_dir.empty()) {
+ vars.TargetInstallNameDir = "";
+ } else {
+ // Convert to a path for the native build tool.
+ install_name_dir = this->LocalGenerator->ConvertToOutputFormat(
+ install_name_dir, cmOutputConverter::SHELL);
+ vars.TargetInstallNameDir = install_name_dir.c_str();
}
}
- // Add language feature flags.
- std::string langFlags;
- this->AddFeatureFlags(langFlags, linkLanguage);
-
- this->LocalGenerator->AddArchitectureFlags(langFlags, this->GeneratorTarget,
- linkLanguage, this->ConfigName);
-
- // remove any language flags that might not work with the
- // particular os
- if(forbiddenFlagVar)
- {
- this->RemoveForbiddenFlags(forbiddenFlagVar,
- linkLanguage, langFlags);
- }
- vars.LanguageCompileFlags = langFlags.c_str();
-
- // Construct the main link rule and expand placeholders.
- this->LocalGenerator->TargetImplib = targetOutPathImport;
- if(useArchiveRules)
- {
- // Construct the individual object list strings.
- std::vector<std::string> object_strings;
- this->WriteObjectsStrings(object_strings, archiveCommandLimit);
+ // Add language-specific flags.
+ std::string langFlags;
+ this->LocalGenerator->AddLanguageFlagsForLinking(
+ langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
+
+ this->LocalGenerator->AddArchitectureFlags(
+ langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
+
+ vars.LanguageCompileFlags = langFlags.c_str();
+
+ std::string launcher;
+ const char* val = this->LocalGenerator->GetRuleLauncher(
+ this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ this->LocalGenerator->CreateRulePlaceholderExpander());
+ // Construct the main link rule and expand placeholders.
+ rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
+ if (useArchiveRules) {
+ // Construct the individual object list strings.
+ std::vector<std::string> object_strings;
+ this->WriteObjectsStrings(object_strings, archiveCommandLimit);
+
+ // Add the cuda device object to the list of archive files. This will
+ // only occur on archives which have CUDA_RESOLVE_DEVICE_SYMBOLS enabled
+ if (!this->DeviceLinkObject.empty()) {
+ object_strings.push_back(this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->DeviceLinkObject),
+ cmOutputConverter::SHELL));
+ }
- // Create the archive with the first set of objects.
- std::vector<std::string>::iterator osi = object_strings.begin();
- {
- vars.Objects = osi->c_str();
- for(std::vector<std::string>::const_iterator
- i = archiveCreateCommands.begin();
- i != archiveCreateCommands.end(); ++i)
+ // Create the archive with the first set of objects.
+ std::vector<std::string>::iterator osi = object_strings.begin();
{
- std::string cmd = *i;
- this->LocalGenerator->ExpandRuleVariables(cmd, vars);
- real_link_commands.push_back(cmd);
+ vars.Objects = osi->c_str();
+ for (std::vector<std::string>::const_iterator i =
+ archiveCreateCommands.begin();
+ i != archiveCreateCommands.end(); ++i) {
+ std::string cmd = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ cmd, vars);
+ real_link_commands.push_back(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 = *i;
- this->LocalGenerator->ExpandRuleVariables(cmd, vars);
- real_link_commands.push_back(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;
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ cmd, vars);
+ real_link_commands.push_back(cmd);
}
}
- // Finish the archive.
- vars.Objects = "";
- for(std::vector<std::string>::const_iterator
- i = archiveFinishCommands.begin();
- i != archiveFinishCommands.end(); ++i)
- {
- std::string cmd = *i;
- this->LocalGenerator->ExpandRuleVariables(cmd, vars);
- real_link_commands.push_back(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;
+ 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);
+ }
+ }
+ } else {
+ // Get the set of commands.
+ std::string linkRule = this->GetLinkRule(linkRuleVar);
+ cmSystemTools::ExpandListArgument(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);
}
- }
- else
- {
- // Get the set of commands.
- std::string linkRule = this->GetLinkRule(linkRuleVar);
- cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
- // Expand placeholders.
- for(std::vector<std::string>::iterator i = real_link_commands.begin();
- i != real_link_commands.end(); ++i)
- {
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ // 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);
}
}
- this->LocalGenerator->TargetImplib = "";
- // Restore path conversion to normal shells.
- this->LocalGenerator->SetLinkScriptShell(false);
+ // Restore path conversion to normal shells.
+ this->LocalGenerator->SetLinkScriptShell(false);
}
// Optionally convert the build rule to use a script to avoid long
// command lines in the make shell.
- if(useLinkScript)
- {
+ if (useLinkScript) {
// Use a link script.
- const char* name = (relink? "relink.txt" : "link.txt");
+ const char* name = (relink ? "relink.txt" : "link.txt");
this->CreateLinkScript(name, real_link_commands, commands1, depends);
- }
- else
- {
+ } else {
// No link script. Just use the link rule directly.
commands1 = real_link_commands;
- }
- this->LocalGenerator->CreateCDCommand
- (commands1,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
+ }
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
commands1.clear();
// Add a rule to create necessary symlinks for the library.
// Frameworks are handled by cmOSXBundleGenerator.
- if(targetOutPath != targetOutPathReal && !this->Target->IsFrameworkOnApple())
- {
+ if (targetOutPath != targetOutPathReal &&
+ !this->GeneratorTarget->IsFrameworkOnApple()) {
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
symlink += targetOutPathReal;
symlink += " ";
@@ -727,78 +984,37 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
symlink += " ";
symlink += targetOutPath;
commands1.push_back(symlink);
- this->LocalGenerator->CreateCDCommand(commands1,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
+ this->LocalGenerator->CreateCDCommand(
+ commands1, this->Makefile->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
commands1.clear();
- }
+ }
+
// Add the post-build rules when building but not when relinking.
- if(!relink)
- {
- this->LocalGenerator->
- AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
- this->Target);
- }
+ if (!relink) {
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPostBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
+ }
+
+ // Compute the list of outputs.
+ std::vector<std::string> outputs(1, targetFullPathReal);
+ if (targetNameSO != targetNameReal) {
+ outputs.push_back(targetFullPathSO);
+ }
+ if (targetName != targetNameSO && targetName != targetNameReal) {
+ outputs.push_back(targetFullPath);
+ }
// Write the build rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- targetFullPathReal.c_str(),
- depends, commands, false);
-
- // Some targets have more than one output file. Create rules to
- // drive the build if any extra outputs are missing.
- std::vector<std::string> extraOutputs;
- if(targetNameSO != targetNameReal)
- {
- this->GenerateExtraOutput(targetFullPathSO.c_str(),
- targetFullPathReal.c_str());
- }
- if(targetName != targetNameSO &&
- targetName != targetNameReal)
- {
- this->GenerateExtraOutput(targetFullPath.c_str(),
- targetFullPathReal.c_str());
- }
+ this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, outputs, depends,
+ commands, false);
// Write the main driver rule to build everything in this target.
- this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
+ this->WriteTargetDriverRule(targetFullPath, relink);
// Clean all the possible library names and symlinks.
- this->CleanFiles.insert(this->CleanFiles.end(),
- libCleanFiles.begin(),libCleanFiles.end());
-}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileLibraryTargetGenerator
-::AppendOSXVerFlag(std::string& flags, const char* lang,
- 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";
- const char* flag = this->Makefile->GetDefinition(fvar.c_str());
-
- // Skip if no such flag.
- if(!flag)
- {
- return;
- }
-
- // Lookup the target version information.
- int major;
- int minor;
- int patch;
- this->Target->GetTargetVersion(so, major, minor, patch);
- if(major > 0 || minor > 0 || patch > 0)
- {
- // Append the flag since a non-zero version is specified.
- cmOStringStream vflag;
- vflag << flag << major << "." << minor << "." << patch;
- this->LocalGenerator->AppendFlags(flags, vflag.str().c_str());
- }
+ this->CleanFiles.insert(this->CleanFiles.end(), libCleanFiles.begin(),
+ libCleanFiles.end());
}
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
index 07f828b7d..da1d8b65c 100644
--- a/Source/cmMakefileLibraryTargetGenerator.h
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -1,45 +1,44 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMakefileLibraryTargetGenerator_h
#define cmMakefileLibraryTargetGenerator_h
+#include "cmConfigure.h"
+
#include "cmMakefileTargetGenerator.h"
-class cmMakefileLibraryTargetGenerator:
- public cmMakefileTargetGenerator
+#include <string>
+
+class cmGeneratorTarget;
+
+class cmMakefileLibraryTargetGenerator : public cmMakefileTargetGenerator
{
public:
- cmMakefileLibraryTargetGenerator(cmTarget* target);
- virtual ~cmMakefileLibraryTargetGenerator();
+ cmMakefileLibraryTargetGenerator(cmGeneratorTarget* target);
+ ~cmMakefileLibraryTargetGenerator() CM_OVERRIDE;
/* the main entry point for this class. Writes the Makefiles associated
with this target */
- virtual void WriteRuleFiles();
+ void WriteRuleFiles() CM_OVERRIDE;
protected:
void WriteObjectLibraryRules();
void WriteStaticLibraryRules();
void WriteSharedLibraryRules(bool relink);
void WriteModuleLibraryRules(bool relink);
- void WriteLibraryRules(const char *linkRule, const char *extraFlags,
- bool relink);
+
+ void WriteDeviceLibraryRules(const std::string& linkRule,
+ const std::string& extraFlags, bool relink);
+ void WriteLibraryRules(const std::string& linkRule,
+ const std::string& extraFlags, bool relink);
// MacOSX Framework support methods
void WriteFrameworkRules(bool relink);
// Store the computd framework version for OS X Frameworks.
std::string FrameworkVersion;
- void AppendOSXVerFlag(std::string& flags, const char* lang,
- const char* name, bool so);
+private:
+ std::string DeviceLinkObject;
};
#endif
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 5e6c54822..a4511b63b 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1,57 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileTargetGenerator.h"
-#include "cmGeneratorTarget.h"
+#include <sstream>
+#include <stdio.h>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
-#include "cmGlobalGenerator.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmTarget.h"
-#include "cmake.h"
-#include "cmComputeLinkInformation.h"
-
#include "cmMakefileExecutableTargetGenerator.h"
#include "cmMakefileLibraryTargetGenerator.h"
#include "cmMakefileUtilityTargetGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
-
-cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target)
- : OSXBundleGenerator(0)
- , MacOSXContentGenerator(0)
+cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
+ : cmCommonTargetGenerator(target)
+ , OSXBundleGenerator(CM_NULLPTR)
+ , MacOSXContentGenerator(CM_NULLPTR)
{
- this->BuildFileStream = 0;
- this->InfoFileStream = 0;
- this->FlagFileStream = 0;
+ this->BuildFileStream = CM_NULLPTR;
+ this->InfoFileStream = CM_NULLPTR;
+ this->FlagFileStream = CM_NULLPTR;
this->CustomCommandDriver = OnBuild;
- this->FortranModuleDirectoryComputed = false;
- this->Target = target;
- this->Makefile = this->Target->GetMakefile();
this->LocalGenerator =
- static_cast<cmLocalUnixMakefileGenerator3*>(
- this->Makefile->GetLocalGenerator());
- this->ConfigName = this->LocalGenerator->ConfigurationName.c_str();
- this->GlobalGenerator =
- static_cast<cmGlobalUnixMakefileGenerator3*>(
- this->LocalGenerator->GetGlobalGenerator());
- this->GeneratorTarget = this->GlobalGenerator->GetGeneratorTarget(target);
+ static_cast<cmLocalUnixMakefileGenerator3*>(target->GetLocalGenerator());
+ this->GlobalGenerator = static_cast<cmGlobalUnixMakefileGenerator3*>(
+ this->LocalGenerator->GetGlobalGenerator());
cmake* cm = this->GlobalGenerator->GetCMakeInstance();
this->NoRuleMessages = false;
- if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES"))
- {
+ if (const char* ruleStatus =
+ cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) {
this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus);
- }
+ }
MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
}
@@ -60,38 +57,36 @@ cmMakefileTargetGenerator::~cmMakefileTargetGenerator()
delete MacOSXContentGenerator;
}
-cmMakefileTargetGenerator *
-cmMakefileTargetGenerator::New(cmTarget *tgt)
+cmMakefileTargetGenerator* cmMakefileTargetGenerator::New(
+ cmGeneratorTarget* tgt)
{
- cmMakefileTargetGenerator *result = 0;
+ cmMakefileTargetGenerator* result = CM_NULLPTR;
- switch (tgt->GetType())
- {
- case cmTarget::EXECUTABLE:
+ switch (tgt->GetType()) {
+ case cmStateEnums::EXECUTABLE:
result = new cmMakefileExecutableTargetGenerator(tgt);
break;
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
result = new cmMakefileLibraryTargetGenerator(tgt);
break;
- case cmTarget::UTILITY:
+ case cmStateEnums::UTILITY:
result = new cmMakefileUtilityTargetGenerator(tgt);
break;
default:
return result;
// break; /* unreachable */
- }
+ }
return result;
}
-//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::CreateRuleFile()
{
// Create a directory for this target.
this->TargetBuildDirectory =
- this->LocalGenerator->GetTargetDirectory(*this->Target);
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
this->TargetBuildDirectoryFull =
this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
@@ -112,268 +107,219 @@ 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());
+ new cmGeneratedFileStream(this->BuildFileNameFull.c_str(), false,
+ this->GlobalGenerator->GetMakefileEncoding());
this->BuildFileStream->SetCopyIfDifferent(true);
- if(!this->BuildFileStream)
- {
+ if (!this->BuildFileStream) {
return;
- }
+ }
this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
+ if (this->GlobalGenerator->AllowDeleteOnError()) {
+ std::vector<std::string> no_depends;
+ std::vector<std::string> no_commands;
+ this->LocalGenerator->WriteMakeRule(
+ *this->BuildFileStream, "Delete rule output on recipe failure.",
+ ".DELETE_ON_ERROR", no_depends, no_commands, false);
+ }
this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
}
-//----------------------------------------------------------------------------
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 =
- this->Makefile->GetProperty
- ("ADDITIONAL_MAKE_CLEAN_FILES"))
- {
- cmSystemTools::ExpandListArgument(additional_clean_files,
- this->CleanFiles);
- }
+ if (const char* additional_clean_files =
+ 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);
+ }
// add custom commands to the clean rules?
- const char* clean_no_custom =
- this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
+ const char* clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
bool clean = cmSystemTools::IsOff(clean_no_custom);
// First generate the object rule files. Save a list of all object
// files for this target.
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->CustomCommands.begin();
- si != this->GeneratorTarget->CustomCommands.end(); ++si)
- {
- cmCustomCommand const* cc = (*si)->GetCustomCommand();
- this->GenerateCustomRuleFile(*cc);
- if (clean)
- {
- const std::vector<std::string>& outputs = cc->GetOutputs();
- for(std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o)
- {
- this->CleanFiles.push_back
- (this->Convert(o->c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
+ std::vector<cmSourceFile const*> customCommands;
+ this->GeneratorTarget->GetCustomCommands(customCommands, config);
+ 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,
+ 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));
}
}
+ }
+ std::vector<cmSourceFile const*> headerSources;
+ this->GeneratorTarget->GetHeaderSources(headerSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- this->GeneratorTarget->HeaderSources,
- this->MacOSXContentGenerator);
+ headerSources, this->MacOSXContentGenerator);
+ std::vector<cmSourceFile const*> extraSources;
+ this->GeneratorTarget->GetExtraSources(extraSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- this->GeneratorTarget->ExtraSources,
- this->MacOSXContentGenerator);
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ExternalObjects.begin();
- si != this->GeneratorTarget->ExternalObjects.end(); ++si)
- {
+ 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->ExternalObjects.push_back((*si)->GetFullPath());
- }
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ObjectSources.begin();
- si != this->GeneratorTarget->ObjectSources.end(); ++si)
- {
+ }
+ std::vector<cmSourceFile const*> objectSources;
+ this->GeneratorTarget->GetObjectSources(objectSources, config);
+ for (std::vector<cmSourceFile const*>::const_iterator si =
+ objectSources.begin();
+ si != objectSources.end(); ++si) {
// Generate this object file's rule file.
this->WriteObjectRuleFiles(**si);
- }
-
- // Add object library contents as external objects.
- this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects);
+ }
}
-//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteCommonCodeRules()
{
- const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")?
- "$(CMAKE_BINARY_DIR)/" : "");
+ const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
+ ? "$(CMAKE_BINARY_DIR)/"
+ : "");
// Include the dependencies for the target.
std::string dependFileNameFull = this->TargetBuildDirectoryFull;
dependFileNameFull += "/depend.make";
*this->BuildFileStream
<< "# Include any dependencies generated for this target.\n"
- << this->LocalGenerator->IncludeDirective << " " << root
- << this->Convert(dependFileNameFull.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator
+ ->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull)
+ .c_str())
<< "\n\n";
- if(!this->NoRuleMessages)
- {
+ if (!this->NoRuleMessages) {
// Include the progress variables for the target.
*this->BuildFileStream
<< "# Include the progress variables for this target.\n"
- << this->LocalGenerator->IncludeDirective << " " << root
- << this->Convert(this->ProgressFileNameFull.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator
+ ->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->ProgressFileNameFull)
+ .c_str())
<< "\n\n";
- }
+ }
// make sure the depend file exists
- if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
- {
+ if (!cmSystemTools::FileExists(dependFileNameFull.c_str())) {
// Write an empty dependency file.
- cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
- depFileStream
- << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
- << "# This may be replaced when dependencies are built." << std::endl;
- }
+ cmGeneratedFileStream depFileStream(
+ dependFileNameFull.c_str(), false,
+ this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty dependencies file for "
+ << this->GeneratorTarget->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built."
+ << std::endl;
+ }
// 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->FlagFileStream =
- new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
+ new cmGeneratedFileStream(this->FlagFileNameFull.c_str(), false,
+ this->GlobalGenerator->GetMakefileEncoding());
this->FlagFileStream->SetCopyIfDifferent(true);
- if(!this->FlagFileStream)
- {
+ if (!this->FlagFileStream) {
return;
- }
+ }
this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
// Include the flags for the target.
*this->BuildFileStream
<< "# Include the compile flags for this target's objects.\n"
- << this->LocalGenerator->IncludeDirective << " " << root
- << this->Convert(this->FlagFileNameFull.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator
+ ->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->FlagFileNameFull)
+ .c_str())
<< "\n\n";
}
-//----------------------------------------------------------------------------
-std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
-{
- ByLanguageMap::iterator i = this->FlagsByLanguage.find(l);
- if (i == this->FlagsByLanguage.end())
- {
- std::string flags;
- const char *lang = l.c_str();
-
- // Add language feature flags.
- this->AddFeatureFlags(flags, lang);
-
- this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
- lang, this->ConfigName);
-
- // Fortran-specific flags computed for this target.
- if(l == "Fortran")
- {
- this->AddFortranFlags(flags);
- }
-
- this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
- lang, this->ConfigName);
-
- this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target,
- lang);
-
- // Add include directory flags.
- this->AddIncludeFlags(flags, lang);
-
- // Append old-style preprocessor definition flags.
- this->LocalGenerator->
- AppendFlags(flags, this->Makefile->GetDefineFlags());
-
- // Add include directory flags.
- this->LocalGenerator->
- AppendFlags(flags,this->GetFrameworkFlags().c_str());
-
- // Add target-specific flags.
- this->LocalGenerator->AddCompileOptions(flags, this->Target,
- lang, this->ConfigName);
-
- ByLanguageMap::value_type entry(l, flags);
- i = this->FlagsByLanguage.insert(entry).first;
- }
- return i->second;
-}
-
-std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
-{
- ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
- if (i == this->DefinesByLanguage.end())
- {
- std::set<std::string> defines;
- const char *lang = l.c_str();
- // Add the export symbol definition for shared library objects.
- if(const char* exportMacro = this->Target->GetExportMacro())
- {
- this->LocalGenerator->AppendDefines(defines, exportMacro);
- }
-
- // Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
- this->LocalGenerator->ConfigurationName.c_str());
-
- std::string definesString;
- this->LocalGenerator->JoinDefines(defines, definesString, lang);
-
- ByLanguageMap::value_type entry(l, definesString);
- i = this->DefinesByLanguage.insert(entry).first;
- }
- return i->second;
-}
-
void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
{
// write language flags for target
- std::set<cmStdString> languages;
- this->Target->GetLanguages(languages);
- // put the compiler in the rules.make file so that if it changes
+ std::set<std::string> languages;
+ this->GeneratorTarget->GetLanguages(
+ 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<cmStdString>::const_iterator l = languages.begin();
- l != languages.end(); ++l)
- {
- cmStdString compiler = "CMAKE_";
+ 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->c_str() << " with " <<
- this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
- }
+ *this->FlagFileStream << "# compile " << *l << " with "
+ << this->Makefile->GetSafeDefinition(compiler)
+ << "\n";
+ }
- for(std::set<cmStdString>::const_iterator l = languages.begin();
- l != languages.end(); ++l)
- {
- *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n";
- *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
- "\n\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);
+ // 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";
+ }
}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
- (cmSourceFile& source, const char* pkgloc)
+void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
+ cmSourceFile const& source, const char* pkgloc)
{
// Skip OS X content when not building a Framework or Bundle.
- if(!this->Generator->GetTarget()->IsBundleOnApple())
- {
+ if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) {
return;
- }
+ }
std::string macdir =
this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
// Get the input file location.
- std::string input = source.GetFullPath();
+ 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(
- this->Generator->Convert(output.c_str(),
- cmLocalGenerator::START_OUTPUT));
- output = this->Generator->Convert(output.c_str(),
- cmLocalGenerator::HOME_OUTPUT);
+ this->Generator->LocalGenerator->MaybeConvertToRelativePath(
+ this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output));
+ output = this->Generator->LocalGenerator->MaybeConvertToRelativePath(
+ this->Generator->LocalGenerator->GetBinaryDirectory(), output);
// Create a rule to copy the content into the bundle.
std::vector<std::string> depends;
@@ -382,131 +328,87 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
std::string copyEcho = "Copying OS X content ";
copyEcho += output;
this->Generator->LocalGenerator->AppendEcho(
- commands, copyEcho.c_str(),
- cmLocalUnixMakefileGenerator3::EchoBuild);
+ commands, copyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
- copyCommand += this->Generator->Convert(input.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
+ copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
+ input, cmOutputConverter::SHELL);
copyCommand += " ";
- copyCommand += this->Generator->Convert(output.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
+ copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
+ output, cmOutputConverter::SHELL);
commands.push_back(copyCommand);
this->Generator->LocalGenerator->WriteMakeRule(
- *this->Generator->BuildFileStream, 0,
- output.c_str(),
- depends, commands, false);
+ *this->Generator->BuildFileStream, CM_NULLPTR, output, depends, commands,
+ false);
this->Generator->ExtraFiles.insert(output);
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
+void cmMakefileTargetGenerator::WriteObjectRuleFiles(
+ cmSourceFile const& source)
{
// Identify the language of the source file.
- const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
- if(!lang)
- {
+ const std::string& lang =
+ this->LocalGenerator->GetSourceFileLanguage(source);
+ if (lang.empty()) {
// don't know anything about this file so skip it
return;
- }
+ }
// Get the full path name of the object file.
- std::string const& objectName = this->GeneratorTarget->Objects[&source];
- std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target);
+ std::string const& objectName =
+ this->GeneratorTarget->GetObjectName(&source);
+ std::string obj =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
obj += "/";
obj += objectName;
// Avoid generating duplicate rules.
- if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
- {
+ if (this->ObjectFiles.find(obj) == this->ObjectFiles.end()) {
this->ObjectFiles.insert(obj);
- }
- else
- {
- cmOStringStream err;
- err << "Warning: Source file \""
- << source.GetFullPath()
+ } else {
+ std::ostringstream err;
+ err << "Warning: Source file \"" << source.GetFullPath()
<< "\" is listed multiple times for target \""
- << this->Target->GetName()
- << "\".";
+ << this->GeneratorTarget->GetName() << "\".";
cmSystemTools::Message(err.str().c_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.c_str());
- cmSystemTools::MakeDirectory
- (this->LocalGenerator->ConvertToFullPath(dir).c_str());
+ std::string dir = cmSystemTools::GetFilenamePath(obj);
+ cmSystemTools::MakeDirectory(
+ this->LocalGenerator->ConvertToFullPath(dir).c_str());
// 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
+ // std::string relativeObj
//= this->LocalGenerator->GetHomeRelativeOutputPath();
- //relativeObj += obj;
+ // relativeObj += 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;
- std::string depMakeFile;
// generate the build rule file
this->WriteObjectBuildFile(obj, lang, source, depends);
// The object file should be checked for dependency integrity.
- std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
+ std::string objFullPath = this->LocalGenerator->GetCurrentBinaryDirectory();
objFullPath += "/";
objFullPath += obj;
- objFullPath =
- this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
+ objFullPath = cmSystemTools::CollapseFullPath(objFullPath);
std::string srcFullPath =
- this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
- this->LocalGenerator->
- AddImplicitDepends(*this->Target, lang,
- objFullPath.c_str(),
- srcFullPath.c_str());
+ cmSystemTools::CollapseFullPath(source.GetFullPath());
+ this->LocalGenerator->AddImplicitDepends(
+ this->GeneratorTarget, lang, objFullPath.c_str(), srcFullPath.c_str());
}
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::AppendFortranFormatFlags(std::string& flags, cmSourceFile& source)
-{
- const char* srcfmt = source.GetProperty("Fortran_FORMAT");
- cmLocalGenerator::FortranFormat format =
- this->LocalGenerator->GetFortranFormat(srcfmt);
- if(format == cmLocalGenerator::FortranFormatNone)
- {
- const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT");
- format = this->LocalGenerator->GetFortranFormat(tgtfmt);
- }
- const char* var = 0;
- switch (format)
- {
- case cmLocalGenerator::FortranFormatFixed:
- var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break;
- case cmLocalGenerator::FortranFormatFree:
- var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break;
- default: break;
- }
- if(var)
- {
- this->LocalGenerator->AppendFlags(
- flags, this->Makefile->GetDefinition(var));
- }
-}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::WriteObjectBuildFile(std::string &obj,
- const char *lang,
- cmSourceFile& source,
- std::vector<std::string>& depends)
+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());
@@ -527,122 +429,134 @@ cmMakefileTargetGenerator
std::string langFlags = "$(";
langFlags += lang;
langFlags += "_FLAGS)";
- this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
+ this->LocalGenerator->AppendFlags(flags, langFlags);
- std::string configUpper =
- cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
+ std::string config = this->LocalGenerator->GetConfigName();
+ std::string configUpper = cmSystemTools::UpperCase(config);
// Add Fortran format flags.
- if(strcmp(lang, "Fortran") == 0)
- {
+ if (lang == "Fortran") {
this->AppendFortranFormatFlags(flags, source);
- }
+ }
// Add flags from source file properties.
- if (source.GetProperty("COMPILE_FLAGS"))
- {
- this->LocalGenerator->AppendFlags
- (flags, source.GetProperty("COMPILE_FLAGS"));
- *this->FlagFileStream << "# Custom flags: "
- << relativeObj << "_FLAGS = "
- << source.GetProperty("COMPILE_FLAGS")
- << "\n"
+ 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);
+ this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
+ *this->FlagFileStream << "# Custom flags: " << relativeObj
+ << "_FLAGS = " << evaluatedFlags << "\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"))
- {
+ if (const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS")) {
this->LocalGenerator->AppendDefines(defines, compile_defs);
- *this->FlagFileStream << "# Custom defines: "
- << relativeObj << "_DEFINES = "
- << compile_defs << "\n"
+ *this->FlagFileStream << "# Custom defines: " << relativeObj
+ << "_DEFINES = " << compile_defs << "\n"
<< "\n";
- }
+ }
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
- if(const char* config_compile_defs =
- source.GetProperty(defPropName.c_str()))
- {
+ if (const char* config_compile_defs = source.GetProperty(defPropName)) {
this->LocalGenerator->AppendDefines(defines, config_compile_defs);
- *this->FlagFileStream
- << "# Custom defines: "
- << relativeObj << "_DEFINES_" << configUpper
- << " = " << config_compile_defs << "\n"
- << "\n";
- }
+ *this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_"
+ << configUpper << " = " << config_compile_defs
+ << "\n"
+ << "\n";
+ }
// Get the output paths for source and object files.
- std::string sourceFile = source.GetFullPath();
- if(this->LocalGenerator->UseRelativePaths)
- {
- sourceFile = this->Convert(sourceFile.c_str(),
- cmLocalGenerator::START_OUTPUT);
- }
- sourceFile = this->Convert(sourceFile.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
+ std::string sourceFile = this->LocalGenerator->ConvertToOutputFormat(
+ source.GetFullPath(), cmOutputConverter::SHELL);
// Construct the build message.
std::vector<std::string> no_commands;
std::vector<std::string> commands;
// add in a progress call if needed
- this->AppendProgress(commands);
+ this->NumberOfProgressActions++;
- if(!this->NoRuleMessages)
- {
+ if (!this->NoRuleMessages) {
+ cmLocalUnixMakefileGenerator3::EchoProgress progress;
+ this->MakeEchoProgress(progress);
std::string buildEcho = "Building ";
buildEcho += lang;
buildEcho += " object ";
buildEcho += relativeObj;
- this->LocalGenerator->AppendEcho
- (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
- }
+ this->LocalGenerator->AppendEcho(commands, buildEcho,
+ cmLocalUnixMakefileGenerator3::EchoBuild,
+ &progress);
+ }
std::string targetOutPathReal;
std::string targetOutPathPDB;
+ std::string targetOutPathCompilePDB;
{
- std::string targetFullPathReal;
- std::string targetFullPathPDB;
- if(this->Target->GetType() == cmTarget::EXECUTABLE ||
- this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
- this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
- this->Target->GetType() == cmTarget::MODULE_LIBRARY)
- {
- targetFullPathReal =
- this->Target->GetFullPath(this->ConfigName, false, true);
- targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
- targetFullPathPDB += "/";
- targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
+ std::string targetFullPathReal;
+ std::string targetFullPathPDB;
+ std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB();
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
+ this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ targetFullPathReal = this->GeneratorTarget->GetFullPath(
+ this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true);
+ targetFullPathPDB =
+ this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
+ targetFullPathPDB += "/";
+ targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName);
+ }
+
+ targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ cmOutputConverter::SHELL);
+ targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
+ targetFullPathPDB, cmOutputConverter::SHELL);
+ targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ targetFullPathCompilePDB),
+ cmOutputConverter::SHELL);
+
+ if (this->LocalGenerator->IsMinGWMake() &&
+ cmHasLiteralSuffix(targetOutPathCompilePDB, "\\")) {
+ // 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] = '/';
}
- targetOutPathReal = this->Convert(targetFullPathReal.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- targetOutPathPDB =
- this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
- }
- cmLocalGenerator::RuleVariables vars;
- vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
- vars.CMTarget = this->Target;
- vars.Language = lang;
+ }
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
+ vars.Language = lang.c_str();
vars.Target = targetOutPathReal.c_str();
vars.TargetPDB = targetOutPathPDB.c_str();
+ vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
vars.Source = sourceFile.c_str();
std::string shellObj =
- this->Convert(obj.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL).c_str();
+ this->LocalGenerator->ConvertToOutputFormat(obj, cmOutputConverter::SHELL);
vars.Object = shellObj.c_str();
- std::string objectDir = this->Target->GetSupportDirectory();
- objectDir = this->Convert(objectDir.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
+ std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
+ objectDir = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ cmOutputConverter::SHELL);
vars.ObjectDir = objectDir.c_str();
+ std::string objectFileDir = cmSystemTools::GetFilenamePath(obj);
+ objectFileDir = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objectFileDir),
+ cmOutputConverter::SHELL);
+ vars.ObjectFileDir = objectFileDir.c_str();
vars.Flags = flags.c_str();
std::string definesString = "$(";
@@ -653,91 +567,165 @@ cmMakefileTargetGenerator
vars.Defines = definesString.c_str();
- bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
- (strcmp(lang, "CXX") == 0));
+ std::string const includesString = "$(" + lang + "_INCLUDES)";
+ vars.Includes = includesString.c_str();
+
+ // At the moment, it is assumed that C, C++, Fortran, and CUDA have both
+ // assembly and preprocessor capabilities. The same is true for the
+ // ability to export compile commands
+ bool lang_has_preprocessor = ((lang == "C") || (lang == "CXX") ||
+ (lang == "Fortran") || (lang == "CUDA"));
+ bool const lang_has_assembly = lang_has_preprocessor;
+ bool const lang_can_export_cmds = lang_has_preprocessor;
+
+ CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ this->LocalGenerator->CreateRulePlaceholderExpander());
// Construct the compile rules.
{
- std::string compileRuleVar = "CMAKE_";
- compileRuleVar += lang;
- compileRuleVar += "_COMPILE_OBJECT";
- std::string compileRule =
- this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
- std::vector<std::string> compileCommands;
- cmSystemTools::ExpandListArgument(compileRule, compileCommands);
-
- if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
- lang_is_c_or_cxx && compileCommands.size() == 1)
- {
- std::string compileCommand = compileCommands[0];
- this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
- std::string workingDirectory =
- this->LocalGenerator->Convert(
- this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL);
- compileCommand.replace(compileCommand.find(langFlags),
- langFlags.size(), this->GetFlags(lang));
- std::string langDefines = std::string("$(") + lang + "_DEFINES)";
- compileCommand.replace(compileCommand.find(langDefines),
- langDefines.size(), this->GetDefines(lang));
- this->GlobalGenerator->AddCXXCompileCommand(
- source.GetFullPath(), workingDirectory, compileCommand);
+ std::vector<std::string> compileCommands;
+ if (lang == "CUDA") {
+ std::string cmdVar;
+ if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_SEPARABLE_COMPILATION")) {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_PTX_COMPILATION")) {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+ } else {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+ }
+ std::string compileRule = this->Makefile->GetRequiredDefinition(cmdVar);
+ cmSystemTools::ExpandListArgument(compileRule, compileCommands);
+ } else {
+ const std::string cmdVar =
+ std::string("CMAKE_") + lang + "_COMPILE_OBJECT";
+ std::string compileRule = this->Makefile->GetRequiredDefinition(cmdVar);
+ cmSystemTools::ExpandListArgument(compileRule, compileCommands);
+ }
+
+ if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
+ lang_can_export_cmds && compileCommands.size() == 1) {
+ std::string compileCommand = compileCommands[0];
+
+ // no launcher for CMAKE_EXPORT_COMPILE_COMMANDS
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ compileCommand, vars);
+ std::string workingDirectory = cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetCurrentBinaryDirectory());
+ compileCommand.replace(compileCommand.find(langFlags), langFlags.size(),
+ this->GetFlags(lang));
+ std::string langDefines = std::string("$(") + lang + "_DEFINES)";
+ compileCommand.replace(compileCommand.find(langDefines),
+ langDefines.size(), this->GetDefines(lang));
+ std::string langIncludes = std::string("$(") + lang + "_INCLUDES)";
+ compileCommand.replace(compileCommand.find(langIncludes),
+ langIncludes.size(), this->GetIncludes(lang));
+ this->GlobalGenerator->AddCXXCompileCommand(
+ source.GetFullPath(), workingDirectory, compileCommand);
+ }
+
+ // 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";
+ const char* iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
+ std::string const tidy_prop = lang + "_CLANG_TIDY";
+ 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";
+ if (iwyu && *iwyu) {
+ run_iwyu += " --iwyu=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(iwyu);
+ }
+ if (tidy && *tidy) {
+ run_iwyu += " --tidy=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(tidy);
+ }
+ if (cpplint && *cpplint) {
+ run_iwyu += " --cpplint=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(cpplint);
+ }
+ if ((tidy && *tidy) || (cpplint && *cpplint)) {
+ run_iwyu += " --source=";
+ run_iwyu += sourceFile;
+ }
+ run_iwyu += " -- ";
+ compileCommands.front().insert(0, run_iwyu);
+ }
}
- // Expand placeholders in the commands.
- for(std::vector<std::string>::iterator i = compileCommands.begin();
- i != compileCommands.end(); ++i)
+ // 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);
+ }
+ std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
+ compileCommands.front().insert(0, run_launcher);
+ }
+ }
+
+ std::string launcher;
{
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ const char* val = this->LocalGenerator->GetRuleLauncher(
+ this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
}
- // Change the command working directory to the local build tree.
- this->LocalGenerator->CreateCDCommand
- (compileCommands,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
- commands.insert(commands.end(),
- compileCommands.begin(), compileCommands.end());
- }
+ // 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);
+ }
- // Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- relativeObj.c_str(),
- depends, commands, false);
+ // 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());
+ }
// Check for extra outputs created by the compilation.
- if(const char* extra_outputs_str =
- source.GetProperty("OBJECT_OUTPUTS"))
- {
- std::vector<std::string> extra_outputs;
- cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
- for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
- eoi != extra_outputs.end(); ++eoi)
- {
- // Register this as an extra output for the object file rule.
- // This will cause the object file to be rebuilt if the extra
- // output is missing.
- this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
-
- // Register this as an extra file to clean.
- this->CleanFiles.push_back(eoi->c_str());
- }
- }
+ 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());
+ }
+
+ // Write the rule.
+ this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, outputs, depends,
+ commands);
- bool do_preprocess_rules = lang_is_c_or_cxx &&
+ bool do_preprocess_rules = lang_has_preprocessor &&
this->LocalGenerator->GetCreatePreprocessedSourceRules();
- bool do_assembly_rules = lang_is_c_or_cxx &&
- this->LocalGenerator->GetCreateAssemblySourceRules();
- if(do_preprocess_rules || do_assembly_rules)
- {
+ bool do_assembly_rules =
+ 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");
- std::string::size_type dot_pos = relativeObj.rfind(".");
+ std::string::size_type dot_pos = relativeObj.rfind('.');
std::string relativeObjBase = relativeObj.substr(0, dot_pos);
- dot_pos = obj.rfind(".");
+ dot_pos = obj.rfind('.');
std::string objBase = obj.substr(0, dot_pos);
- if(do_preprocess_rules)
- {
+ if (do_preprocess_rules) {
commands.clear();
std::string relativeObjI = relativeObjBase + ".i";
std::string objI = objBase + ".i";
@@ -747,54 +735,46 @@ cmMakefileTargetGenerator
preprocessEcho += " source to ";
preprocessEcho += objI;
this->LocalGenerator->AppendEcho(
- commands, preprocessEcho.c_str(),
- cmLocalUnixMakefileGenerator3::EchoBuild
- );
+ commands, preprocessEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
std::string preprocessRuleVar = "CMAKE_";
preprocessRuleVar += lang;
preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
- if(const char* preprocessRule =
- this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
- {
+ if (const char* preprocessRule =
+ this->Makefile->GetDefinition(preprocessRuleVar)) {
std::vector<std::string> preprocessCommands;
cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
- std::string shellObjI =
- this->Convert(objI.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL).c_str();
+ 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)
- {
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
- }
-
- this->LocalGenerator->CreateCDCommand
- (preprocessCommands,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
- commands.insert(commands.end(),
- preprocessCommands.begin(),
- preprocessCommands.end());
+ for (std::vector<std::string>::iterator i = preprocessCommands.begin();
+ i != preprocessCommands.end(); ++i) {
+ // no launcher for preprocessor commands
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ *i, vars);
}
- else
- {
+
+ this->LocalGenerator->CreateCDCommand(
+ preprocessCommands,
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
+ commands.insert(commands.end(), preprocessCommands.begin(),
+ preprocessCommands.end());
+ } else {
std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
cmd += preprocessRuleVar;
commands.push_back(cmd);
- }
-
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- relativeObjI.c_str(),
- force_depends, commands, false);
}
- if(do_assembly_rules)
- {
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ relativeObjI, force_depends,
+ commands, false);
+ }
+
+ if (do_assembly_rules) {
commands.clear();
std::string relativeObjS = relativeObjBase + ".s";
std::string objS = objBase + ".s";
@@ -804,52 +784,44 @@ cmMakefileTargetGenerator
assemblyEcho += " source to assembly ";
assemblyEcho += objS;
this->LocalGenerator->AppendEcho(
- commands, assemblyEcho.c_str(),
- cmLocalUnixMakefileGenerator3::EchoBuild
- );
+ commands, assemblyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
std::string assemblyRuleVar = "CMAKE_";
assemblyRuleVar += lang;
assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
- if(const char* assemblyRule =
- this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
- {
+ if (const char* assemblyRule =
+ this->Makefile->GetDefinition(assemblyRuleVar)) {
std::vector<std::string> assemblyCommands;
cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
- std::string shellObjS =
- this->Convert(objS.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL).c_str();
+ 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)
- {
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
- }
-
- this->LocalGenerator->CreateCDCommand
- (assemblyCommands,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
- commands.insert(commands.end(),
- assemblyCommands.begin(),
- assemblyCommands.end());
+ for (std::vector<std::string>::iterator i = assemblyCommands.begin();
+ i != assemblyCommands.end(); ++i) {
+ // no launcher for assembly commands
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ *i, vars);
}
- else
- {
+
+ this->LocalGenerator->CreateCDCommand(
+ assemblyCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
+ commands.insert(commands.end(), assemblyCommands.begin(),
+ assemblyCommands.end());
+ } else {
std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
cmd += assemblyRuleVar;
commands.push_back(cmd);
- }
-
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- relativeObjS.c_str(),
- force_depends, commands, false);
}
+
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ relativeObjS, force_depends,
+ commands, false);
}
+ }
// If the language needs provides-requires mode, create the
// corresponding targets.
@@ -857,9 +829,9 @@ cmMakefileTargetGenerator
objectRequires += ".requires";
std::vector<std::string> p_depends;
// always provide an empty requires target
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- objectRequires.c_str(), p_depends,
- no_commands, true);
+ 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;
@@ -868,27 +840,24 @@ cmMakefileTargetGenerator
temp += ".provides.build";
std::vector<std::string> r_commands;
std::string tgtMakefileName =
- this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
tgtMakefileName += "/build.make";
- r_commands.push_back
- (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
- temp.c_str()));
+ r_commands.push_back(
+ this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(), temp));
p_depends.clear();
p_depends.push_back(objectRequires);
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- objectProvides.c_str(), p_depends,
- r_commands, true);
+ 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, 0,
- temp.c_str(), p_depends, no_commands,
- false);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, temp,
+ p_depends, no_commands, false);
}
-//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetRequiresRules()
{
std::vector<std::string> depends;
@@ -896,28 +865,25 @@ void cmMakefileTargetGenerator::WriteTargetRequiresRules()
// Construct the name of the dependency generation target.
std::string depTarget =
- this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ 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)
- {
+ 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, 0,
- depTarget.c_str(),
- depends, no_commands, true);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ depTarget, depends, no_commands, true);
}
-//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetCleanRules()
{
std::vector<std::string> depends;
@@ -925,29 +891,92 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
// Construct the clean target name.
std::string cleanTarget =
- this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
cleanTarget += "/clean";
// Construct the clean command.
this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
- *this->Target);
- this->LocalGenerator->CreateCDCommand
- (commands,
- this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::HOME_OUTPUT);
+ this->GeneratorTarget);
+ this->LocalGenerator->CreateCDCommand(
+ commands, this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->GetBinaryDirectory());
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- cleanTarget.c_str(),
- depends, commands, true);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ cleanTarget, depends, commands, true);
}
+bool cmMakefileTargetGenerator::WriteMakeRule(
+ std::ostream& os, const char* comment,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands, bool in_help)
+{
+ bool symbolic = false;
+ if (outputs.empty()) {
+ return symbolic;
+ }
+
+ // Check whether we need to bother checking for a symbolic output.
+ bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
+
+ // Check whether the first output is marked as symbolic.
+ if (need_symbolic) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(outputs[0])) {
+ symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+ }
+ }
+
+ // We always attach the actual commands to the first output.
+ this->LocalGenerator->WriteMakeRule(os, comment, outputs[0], depends,
+ commands, symbolic, in_help);
+
+ // For single outputs, we are done.
+ if (outputs.size() == 1) {
+ return symbolic;
+ }
+
+ // 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) {
+ // Touch the extra output so "make" knows that it was updated,
+ // but only if the output was acually created.
+ std::string const out = this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(binDir, *o),
+ cmOutputConverter::SHELL);
+ std::vector<std::string> output_commands;
+
+ bool o_symbolic = false;
+ if (need_symbolic) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(*o)) {
+ o_symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+ }
+ }
+ symbolic = symbolic && o_symbolic;
+
+ if (!o_symbolic) {
+ output_commands.push_back("@$(CMAKE_COMMAND) -E touch_nocreate " + out);
+ }
+ this->LocalGenerator->WriteMakeRule(os, CM_NULLPTR, *o, 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]);
+ this->MultipleOutputPairs.insert(p);
+ }
+ }
+ return symbolic;
+}
-//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetDependRules()
{
// must write the targets depend info file
- std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
+ std::string dir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
this->InfoFileNameFull = dir;
this->InfoFileNameFull += "/DependInfo.cmake";
this->InfoFileNameFull =
@@ -955,104 +984,57 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
this->InfoFileStream =
new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
this->InfoFileStream->SetCopyIfDifferent(true);
- if(!*this->InfoFileStream)
- {
+ if (!*this->InfoFileStream) {
return;
- }
- this->LocalGenerator->
- WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
+ }
+ this->LocalGenerator->WriteDependLanguageInfo(*this->InfoFileStream,
+ this->GeneratorTarget);
// Store multiple output pairs in the depend info file.
- if(!this->MultipleOutputPairs.empty())
- {
+ if (!this->MultipleOutputPairs.empty()) {
+ /* clang-format off */
*this->InfoFileStream
<< "\n"
<< "# Pairs of files generated by the same build rule.\n"
- << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
- for(MultipleOutputPairsType::const_iterator pi =
- this->MultipleOutputPairs.begin();
- pi != this->MultipleOutputPairs.end(); ++pi)
- {
+ << "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
+ /* clang-format on */
+ for (MultipleOutputPairsType::const_iterator pi =
+ this->MultipleOutputPairs.begin();
+ pi != this->MultipleOutputPairs.end(); ++pi) {
*this->InfoFileStream
- << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
- << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
- << "\n";
- }
- *this->InfoFileStream << " )\n\n";
+ << " " << cmOutputConverter::EscapeForCMake(pi->first) << " "
+ << cmOutputConverter::EscapeForCMake(pi->second) << "\n";
}
+ *this->InfoFileStream << " )\n\n";
+ }
// Store list of targets linked directly or transitively.
{
+ /* clang-format off */
*this->InfoFileStream
<< "\n"
<< "# Targets to which this target links.\n"
- << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
- std::set<cmTarget const*> emitted;
- const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
- if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
- {
- cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
- for(cmComputeLinkInformation::ItemVector::const_iterator
- i = items.begin(); i != items.end(); ++i)
- {
- cmTarget const* linkee = i->Target;
- if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
- {
- cmMakefile* mf = linkee->GetMakefile();
- cmLocalGenerator* lg = mf->GetLocalGenerator();
- std::string di = mf->GetStartOutputDirectory();
- di += "/";
- di += lg->GetTargetDirectory(*linkee);
- di += "/DependInfo.cmake";
- *this->InfoFileStream << " \"" << di << "\"\n";
- }
- }
- }
- *this->InfoFileStream
- << " )\n";
+ << "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";
+ }
+ *this->InfoFileStream << " )\n";
}
- // Check for a target-specific module output directory.
- if(const char* mdir = this->GetFortranModuleDirectory())
- {
- *this->InfoFileStream
- << "\n"
- << "# Fortran module output directory.\n"
- << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
- }
+ std::string const& working_dir =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
- // Target-specific include directories:
+ /* clang-format off */
*this->InfoFileStream
<< "\n"
- << "# The include file search paths:\n";
- *this->InfoFileStream
- << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n";
- std::vector<std::string> includes;
-
- const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- this->LocalGenerator->GetIncludeDirectories(includes,
- this->GeneratorTarget,
- "C", config);
- for(std::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i)
- {
- *this->InfoFileStream
- << " \""
- << this->LocalGenerator->Convert(i->c_str(),
- cmLocalGenerator::HOME_OUTPUT)
- << "\"\n";
- }
- *this->InfoFileStream
- << " )\n";
- *this->InfoFileStream
- << "SET(CMAKE_CXX_TARGET_INCLUDE_PATH "
- << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
- *this->InfoFileStream
- << "SET(CMAKE_Fortran_TARGET_INCLUDE_PATH "
- << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
- *this->InfoFileStream
- << "SET(CMAKE_ASM_TARGET_INCLUDE_PATH "
- << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
+ << "# Fortran module output directory.\n"
+ << "set(CMAKE_Fortran_TARGET_MODULE_DIR \""
+ << this->GeneratorTarget->GetFortranModuleDirectory(working_dir)
+ << "\")\n";
+ /* clang-format on */
// and now write the rule to use it
std::vector<std::string> depends;
@@ -1060,23 +1042,23 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
// Construct the name of the dependency generation target.
std::string depTarget =
- this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
depTarget += "/depend";
// Add a command to call CMake to scan dependencies. CMake will
// touch the corresponding depends file after scanning dependencies.
- cmOStringStream depCmd;
- // TODO: Account for source file properties and directory-level
- // definitions when scanning for dependencies.
+ std::ostringstream depCmd;
+// TODO: Account for source file properties and directory-level
+// definitions when scanning for dependencies.
#if !defined(_WIN32) || defined(__CYGWIN__)
// This platform supports symlinks, so cmSystemTools will translate
// 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->Convert(
- this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
+ depCmd << "cd " << (this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetBinaryDirectory()),
+ cmOutputConverter::SHELL))
<< " && ";
#endif
// Generate a call this signature:
@@ -1090,325 +1072,212 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
// the state of our local generator sufficiently for its needs.
depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
<< this->GlobalGenerator->GetName() << "\" "
- << this->Convert(this->Makefile->GetHomeDirectory(),
- cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetSourceDirectory()),
+ cmOutputConverter::SHELL)
<< " "
- << this->Convert(this->Makefile->GetStartDirectory(),
- cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetCurrentSourceDirectory()),
+ cmOutputConverter::SHELL)
<< " "
- << this->Convert(this->Makefile->GetHomeOutputDirectory(),
- cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetBinaryDirectory()),
+ cmOutputConverter::SHELL)
<< " "
- << this->Convert(this->Makefile->GetStartOutputDirectory(),
- cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetCurrentBinaryDirectory()),
+ cmOutputConverter::SHELL)
<< " "
- << this->Convert(this->InfoFileNameFull.c_str(),
- cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
- if(this->LocalGenerator->GetColorMakefile())
- {
+ << this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(this->InfoFileNameFull),
+ cmOutputConverter::SHELL);
+ if (this->LocalGenerator->GetColorMakefile()) {
depCmd << " --color=$(COLOR)";
- }
+ }
commands.push_back(depCmd.str());
// Make sure all custom command outputs in this target are built.
- if(this->CustomCommandDriver == OnDepends)
- {
+ if (this->CustomCommandDriver == OnDepends) {
this->DriveCustomCommands(depends);
- }
+ }
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- depTarget.c_str(),
- depends, commands, true);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ depTarget, depends, commands, true);
}
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::DriveCustomCommands(std::vector<std::string>& depends)
+void cmMakefileTargetGenerator::DriveCustomCommands(
+ std::vector<std::string>& depends)
{
// Depend on all custom command outputs.
- const std::vector<cmSourceFile*>& sources =
- this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
- {
- if(cmCustomCommand* cc = (*source)->GetCustomCommand())
- {
- const std::vector<std::string>& outputs = cc->GetOutputs();
- for(std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o)
- {
- depends.push_back(*o);
- }
- }
+ 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()) {
+ cmCustomCommandGenerator ccg(*cc, this->ConfigName,
+ this->LocalGenerator);
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ depends.insert(depends.end(), outputs.begin(), outputs.end());
}
+ }
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator
-::WriteObjectDependRules(cmSourceFile& source,
- std::vector<std::string>& depends)
+void cmMakefileTargetGenerator::WriteObjectDependRules(
+ cmSourceFile const& source, std::vector<std::string>& depends)
{
// Create the list of dependencies known at cmake time. These are
// shared between the object file and dependency scanning rule.
depends.push_back(source.GetFullPath());
- if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
- {
- std::vector<std::string> deps;
- cmSystemTools::ExpandListArgument(objectDeps, deps);
- for(std::vector<std::string>::iterator i = deps.begin();
- i != deps.end(); ++i)
- {
- depends.push_back(i->c_str());
- }
- }
+ if (const char* objectDeps = source.GetProperty("OBJECT_DEPENDS")) {
+ cmSystemTools::ExpandListArgument(objectDeps, depends);
+ }
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator
-::GenerateCustomRuleFile(const cmCustomCommand& cc)
+void cmMakefileTargetGenerator::GenerateCustomRuleFile(
+ cmCustomCommandGenerator const& ccg)
{
// Collect the commands.
std::vector<std::string> commands;
- std::string comment = this->LocalGenerator->ConstructComment(cc);
- if(!comment.empty())
- {
+ std::string comment = this->LocalGenerator->ConstructComment(ccg);
+ if (!comment.empty()) {
// add in a progress call if needed
- this->AppendProgress(commands);
- if(!this->NoRuleMessages)
- {
- this->LocalGenerator
- ->AppendEcho(commands, comment.c_str(),
- cmLocalUnixMakefileGenerator3::EchoGenerate);
- }
+ this->NumberOfProgressActions++;
+ if (!this->NoRuleMessages) {
+ cmLocalUnixMakefileGenerator3::EchoProgress progress;
+ this->MakeEchoProgress(progress);
+ this->LocalGenerator->AppendEcho(
+ commands, comment, cmLocalUnixMakefileGenerator3::EchoGenerate,
+ &progress);
}
+ }
// Now append the actual user-specified commands.
- cmOStringStream content;
- this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
- cmLocalGenerator::HOME_OUTPUT,
- &content);
+ std::ostringstream content;
+ this->LocalGenerator->AppendCustomCommand(
+ commands, ccg, this->GeneratorTarget,
+ this->LocalGenerator->GetBinaryDirectory(), false, &content);
// Collect the dependencies.
std::vector<std::string> depends;
- this->LocalGenerator->AppendCustomDepend(depends, cc);
-
- // Check whether we need to bother checking for a symbolic output.
- bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
+ this->LocalGenerator->AppendCustomDepend(depends, ccg);
// Write the rule.
- const std::vector<std::string>& outputs = cc.GetOutputs();
- std::vector<std::string>::const_iterator o = outputs.begin();
- {
- bool symbolic = false;
- if(need_symbolic)
- {
- if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
- {
- symbolic = sf->GetPropertyAsBool("SYMBOLIC");
- }
- }
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- o->c_str(), depends, commands,
- symbolic);
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ bool symbolic = this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ outputs, depends, commands);
// If the rule has changed make sure the output is rebuilt.
- if(!symbolic)
- {
- this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
- }
+ if (!symbolic) {
+ this->GlobalGenerator->AddRuleHash(ccg.GetOutputs(), content.str());
}
- // Write rules to drive building any outputs beyond the first.
- const char* in = o->c_str();
- for(++o; o != outputs.end(); ++o)
- {
- bool symbolic = false;
- if(need_symbolic)
- {
- if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
- {
- symbolic = sf->GetPropertyAsBool("SYMBOLIC");
- }
- }
- this->GenerateExtraOutput(o->c_str(), in, symbolic);
- }
-
// Setup implicit dependency scanning.
- for(cmCustomCommand::ImplicitDependsList::const_iterator
- idi = cc.GetImplicitDepends().begin();
- idi != cc.GetImplicitDepends().end(); ++idi)
- {
- std::string objFullPath =
- this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
- std::string srcFullPath =
- this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
- this->LocalGenerator->
- AddImplicitDepends(*this->Target, idi->first.c_str(),
- objFullPath.c_str(),
- srcFullPath.c_str());
- }
-}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
-{
- // Add a rule to build the primary output if the extra output needs
- // to be created.
- std::vector<std::string> commands;
- std::vector<std::string> depends;
- std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
- if(!emptyCommand.empty())
- {
- commands.push_back(emptyCommand);
- }
- depends.push_back(in);
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- out, depends, commands,
- symbolic);
-
- // Register the extra output as paired with the first output so that
- // the check-build-system step will remove the primary output if any
- // extra outputs are missing. This forces the rule to regenerate
- // all outputs.
- this->AddMultipleOutputPair(out, in);
+ for (cmCustomCommand::ImplicitDependsList::const_iterator idi =
+ ccg.GetCC().GetImplicitDepends().begin();
+ idi != ccg.GetCC().GetImplicitDepends().end(); ++idi) {
+ 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());
+ }
}
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
+void cmMakefileTargetGenerator::MakeEchoProgress(
+ cmLocalUnixMakefileGenerator3::EchoProgress& progress) const
{
- this->NumberOfProgressActions++;
- if(this->NoRuleMessages)
- {
- return;
- }
- std::string progressDir = this->Makefile->GetHomeOutputDirectory();
- progressDir += cmake::GetCMakeFilesDirectory();
- cmOStringStream progCmd;
- progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
- progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL);
- progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
- commands.push_back(progCmd.str());
+ progress.Dir = this->LocalGenerator->GetBinaryDirectory();
+ progress.Dir += cmake::GetCMakeFilesDirectory();
+ std::ostringstream progressArg;
+ progressArg << "$(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
+ progress.Arg = progressArg.str();
}
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::WriteObjectsVariable(std::string& variableName,
- std::string& variableNameExternal)
+void cmMakefileTargetGenerator::WriteObjectsVariable(
+ std::string& variableName, std::string& variableNameExternal,
+ bool useWatcomQuote)
{
// Write a make variable assignment that lists all objects for the
// target.
- variableName =
- this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
- "_OBJECTS");
- *this->BuildFileStream
- << "# Object files for target " << this->Target->GetName() << "\n"
- << variableName.c_str() << " =";
+ variableName = this->LocalGenerator->CreateMakeVariable(
+ this->GeneratorTarget->GetName(), "_OBJECTS");
+ *this->BuildFileStream << "# Object files for target "
+ << this->GeneratorTarget->GetName() << "\n"
+ << variableName << " =";
std::string object;
- const char* objName =
- this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
const char* lineContinue =
this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
- if(!lineContinue)
- {
+ if (!lineContinue) {
lineContinue = "\\";
- }
- for(std::vector<std::string>::const_iterator i = this->Objects.begin();
- i != this->Objects.end(); ++i)
- {
+ }
+ for (std::vector<std::string>::const_iterator i = this->Objects.begin();
+ i != this->Objects.end(); ++i) {
*this->BuildFileStream << " " << lineContinue << "\n";
- if(objName)
- {
- *this->BuildFileStream <<
- this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- }
- else
- {
- *this->BuildFileStream <<
- this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
- }
- }
+ *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath(
+ i->c_str(), useWatcomQuote);
+ }
*this->BuildFileStream << "\n";
// Write a make variable assignment that lists all external objects
// for the target.
- variableNameExternal =
- this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
- "_EXTERNAL_OBJECTS");
+ variableNameExternal = this->LocalGenerator->CreateMakeVariable(
+ this->GeneratorTarget->GetName(), "_EXTERNAL_OBJECTS");
+ /* clang-format off */
*this->BuildFileStream
<< "\n"
<< "# External object files for target "
- << this->Target->GetName() << "\n"
- << variableNameExternal.c_str() << " =";
- for(std::vector<std::string>::const_iterator i =
- this->ExternalObjects.begin();
- i != this->ExternalObjects.end(); ++i)
- {
- object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
- *this->BuildFileStream
- << " " << lineContinue << "\n"
- << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
- if(objName)
- {
- *this->BuildFileStream <<
- this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- }
- else
- {
- *this->BuildFileStream <<
- this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
- }
- }
- *this->BuildFileStream << "\n" << "\n";
-}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::WriteObjectsString(std::string& buildObjs)
-{
- std::vector<std::string> objStrings;
- this->WriteObjectsStrings(objStrings);
- buildObjs = objStrings[0];
+ << this->GeneratorTarget->GetName() << "\n"
+ << variableNameExternal << " =";
+ /* 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) {
+ object =
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, *i);
+ *this->BuildFileStream << " " << lineContinue << "\n";
+ *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath(
+ i->c_str(), useWatcomQuote);
+ }
+ *this->BuildFileStream << "\n"
+ << "\n";
}
-//----------------------------------------------------------------------------
class cmMakefileTargetGeneratorObjectStrings
{
public:
cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
- cmLocalUnixMakefileGenerator3* lg,
- std::string::size_type limit):
- Strings(strings), LocalGenerator(lg), LengthLimit(limit)
- {
+ cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir,
+ std::string::size_type limit)
+ : Strings(strings)
+ , OutputConverter(outputConverter)
+ , StateDir(stateDir)
+ , LengthLimit(limit)
+ {
this->Space = "";
- }
+ }
void Feed(std::string const& obj)
- {
+ {
// Construct the name of the next object.
- this->NextObject =
- this->LocalGenerator->Convert(obj.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::RESPONSE);
+ this->NextObject = this->OutputConverter->ConvertToOutputFormat(
+ this->MaybeConvertToRelativePath(obj), cmOutputConverter::RESPONSE);
// Roll over to next string if the limit will be exceeded.
- if(this->LengthLimit != std::string::npos &&
- (this->CurrentString.length() + 1 + this->NextObject.length()
- > this->LengthLimit))
- {
+ if (this->LengthLimit != std::string::npos &&
+ (this->CurrentString.length() + 1 + this->NextObject.length() >
+ this->LengthLimit)) {
this->Strings.push_back(this->CurrentString);
this->CurrentString = "";
this->Space = "";
- }
+ }
// Separate from previous object.
this->CurrentString += this->Space;
@@ -1416,201 +1285,128 @@ public:
// Append this object.
this->CurrentString += this->NextObject;
- }
- void Done()
- {
- this->Strings.push_back(this->CurrentString);
- }
+ }
+ void Done() { this->Strings.push_back(this->CurrentString); }
+
private:
+ std::string MaybeConvertToRelativePath(std::string const& obj)
+ {
+ if (!cmOutputConverter::ContainedInDirectory(
+ this->StateDir.GetCurrentBinary(), obj, this->StateDir)) {
+ return obj;
+ }
+ return cmOutputConverter::ForceToRelativePath(
+ this->StateDir.GetCurrentBinary(), obj);
+ }
+
std::vector<std::string>& Strings;
- cmLocalUnixMakefileGenerator3* LocalGenerator;
+ cmOutputConverter* OutputConverter;
+ cmStateDirectory StateDir;
std::string::size_type LengthLimit;
std::string CurrentString;
std::string NextObject;
const char* Space;
};
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::WriteObjectsStrings(std::vector<std::string>& objStrings,
- std::string::size_type limit)
+void cmMakefileTargetGenerator::WriteObjectsStrings(
+ std::vector<std::string>& objStrings, std::string::size_type limit)
{
- cmMakefileTargetGeneratorObjectStrings
- helper(objStrings, this->LocalGenerator, limit);
- for(std::vector<std::string>::const_iterator i = this->Objects.begin();
- i != this->Objects.end(); ++i)
- {
+ 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::vector<std::string>::const_iterator i =
- this->ExternalObjects.begin();
- i != this->ExternalObjects.end(); ++i)
- {
+ }
+ for (std::vector<std::string>::const_iterator i =
+ this->ExternalObjects.begin();
+ i != this->ExternalObjects.end(); ++i) {
helper.Feed(*i);
- }
+ }
helper.Done();
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
- bool relink)
+void cmMakefileTargetGenerator::WriteTargetDriverRule(
+ const std::string& main_output, bool relink)
{
// Compute the name of the driver target.
std::string dir =
- this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
std::string buildTargetRuleName = dir;
- buildTargetRuleName += relink?"/preinstall":"/build";
- buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::UNCHANGED);
+ buildTargetRuleName += relink ? "/preinstall" : "/build";
+ buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName);
// Build the list of target outputs to drive.
std::vector<std::string> depends;
- if(main_output)
- {
- depends.push_back(main_output);
- }
+ depends.push_back(main_output);
- const char* comment = 0;
- if(relink)
- {
+ const char* comment = CM_NULLPTR;
+ if (relink) {
// Setup the comment for the preinstall driver.
comment = "Rule to relink during preinstall.";
- }
- else
- {
+ } else {
// Setup the comment for the main build driver.
comment = "Rule to build all files generated by this target.";
// Make sure all custom command outputs in this target are built.
- if(this->CustomCommandDriver == OnBuild)
- {
+ if (this->CustomCommandDriver == OnBuild) {
this->DriveCustomCommands(depends);
- }
+ }
// Make sure the extra files are built.
- for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
- i != this->ExtraFiles.end(); ++i)
- {
- depends.push_back(*i);
- }
- }
+ depends.insert(depends.end(), this->ExtraFiles.begin(),
+ this->ExtraFiles.end());
+ }
// Write the driver rule.
std::vector<std::string> no_commands;
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
- buildTargetRuleName.c_str(),
- depends, no_commands, true);
-}
-
-//----------------------------------------------------------------------------
-std::string cmMakefileTargetGenerator::GetFrameworkFlags()
-{
- if(!this->Makefile->IsOn("APPLE"))
- {
- return std::string();
- }
-
- std::set<cmStdString> emitted;
-#ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */
- emitted.insert("/System/Library/Frameworks");
-#endif
- std::vector<std::string> includes;
-
- const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- this->LocalGenerator->GetIncludeDirectories(includes,
- this->GeneratorTarget,
- "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(this->Target->NameResolvesToFramework(i->c_str()))
- {
- std::string frameworkDir = *i;
- frameworkDir += "/../";
- frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
- emitted.insert(frameworkDir);
- }
- }
-
- std::string flags;
- const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
- if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
- {
- 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)
- {
- flags += "-F";
- flags += this->Convert(i->c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL, true);
- flags += " ";
- }
- }
- }
- return flags;
+ buildTargetRuleName, depends,
+ no_commands, true);
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator
-::AppendTargetDepends(std::vector<std::string>& depends)
+void cmMakefileTargetGenerator::AppendTargetDepends(
+ std::vector<std::string>& depends)
{
// Static libraries never depend on anything for linking.
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
- {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
return;
- }
+ }
// Loop over all library dependencies.
- const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
- if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
- {
+ const char* cfg = this->LocalGenerator->GetConfigName().c_str();
+ if (cmComputeLinkInformation* cli =
+ this->GeneratorTarget->GetLinkInformation(cfg)) {
std::vector<std::string> const& libDeps = cli->GetDepends();
- for(std::vector<std::string>::const_iterator j = libDeps.begin();
- j != libDeps.end(); ++j)
- {
- depends.push_back(*j);
- }
- }
+ depends.insert(depends.end(), libDeps.begin(), libDeps.end());
+ }
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator
-::AppendObjectDepends(std::vector<std::string>& depends)
+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)
- {
+ for (std::vector<std::string>::const_iterator obj = this->Objects.begin();
+ obj != this->Objects.end(); ++obj) {
objTarget = relPath;
objTarget += *obj;
depends.push_back(objTarget);
- }
+ }
// Add dependencies on the external object files.
- for(std::vector<std::string>::const_iterator obj
- = this->ExternalObjects.begin();
- obj != this->ExternalObjects.end(); ++obj)
- {
- depends.push_back(*obj);
- }
+ depends.insert(depends.end(), this->ExternalObjects.begin(),
+ this->ExternalObjects.end());
// Add a dependency on the rule file itself.
this->LocalGenerator->AppendRuleDepend(depends,
this->BuildFileNameFull.c_str());
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator
-::AppendLinkDepends(std::vector<std::string>& depends)
+void cmMakefileTargetGenerator::AppendLinkDepends(
+ std::vector<std::string>& depends)
{
this->AppendObjectDepends(depends);
@@ -1618,83 +1414,57 @@ void cmMakefileTargetGenerator
this->AppendTargetDepends(depends);
// Add a dependency on the link definitions file, if any.
- if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
- {
- depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
+ 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());
}
+ }
+
+ // 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());
+ }
// Add user-specified dependencies.
- if(const char* linkDepends =
- this->Target->GetProperty("LINK_DEPENDS"))
- {
+ if (const char* linkDepends =
+ this->GeneratorTarget->GetProperty("LINK_DEPENDS")) {
cmSystemTools::ExpandListArgument(linkDepends, depends);
- }
+ }
}
-//----------------------------------------------------------------------------
-std::string cmMakefileTargetGenerator::GetLinkRule(const char* linkRuleVar)
+std::string cmMakefileTargetGenerator::GetLinkRule(
+ const std::string& linkRuleVar)
{
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
- if(this->Target->HasImplibGNUtoMS())
- {
+ if (this->GeneratorTarget->HasImplibGNUtoMS()) {
std::string ruleVar = "CMAKE_";
- ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
+ ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
ruleVar += "_GNUtoMS_RULE";
- if(const char* rule = this->Makefile->GetDefinition(ruleVar.c_str()))
- {
+ if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
linkRule += rule;
- }
}
+ }
return linkRule;
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator
-::CloseFileStreams()
+void cmMakefileTargetGenerator::CloseFileStreams()
{
delete this->BuildFileStream;
delete this->InfoFileStream;
delete this->FlagFileStream;
}
-void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
- const char* linkLang,
- std::string& linkFlags)
-{
- // check for language flags that are not allowed at link time, and
- // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
- // which fails, there may be more]
-
- std::string removeFlags = "CMAKE_";
- removeFlags += linkLang;
- removeFlags += flagVar;
- std::string removeflags =
- this->Makefile->GetSafeDefinition(removeFlags.c_str());
- std::vector<std::string> removeList;
- cmSystemTools::ExpandListArgument(removeflags, removeList);
- for(std::vector<std::string>::iterator i = removeList.begin();
- i != removeList.end(); ++i)
- {
- cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
- }
-}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::AddMultipleOutputPair(const char* depender, const char* dependee)
-{
- MultipleOutputPairsType::value_type p(depender, dependee);
- this->MultipleOutputPairs.insert(p);
-}
-
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::CreateLinkScript(const char* name,
- std::vector<std::string> const& link_commands,
- std::vector<std::string>& makefile_commands,
- std::vector<std::string>& makefile_depends)
+void cmMakefileTargetGenerator::CreateLinkScript(
+ const char* name, std::vector<std::string> const& link_commands,
+ std::vector<std::string>& makefile_commands,
+ std::vector<std::string>& makefile_depends)
{
// Create the link script file.
std::string linkScriptName = this->TargetBuildDirectoryFull;
@@ -1702,32 +1472,87 @@ cmMakefileTargetGenerator
linkScriptName += name;
cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
linkScriptStream.SetCopyIfDifferent(true);
- for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
- cmd != link_commands.end(); ++cmd)
- {
+ for (std::vector<std::string>::const_iterator cmd = link_commands.begin();
+ cmd != link_commands.end(); ++cmd) {
// Do not write out empty commands or commands beginning in the
// shell no-op ":".
- if(!cmd->empty() && (*cmd)[0] != ':')
- {
+ if (!cmd->empty() && (*cmd)[0] != ':') {
linkScriptStream << *cmd << "\n";
- }
}
+ }
// Create the makefile command to invoke the link script.
std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
- link_command += this->Convert(linkScriptName.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
+ 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
-cmMakefileTargetGenerator
-::CreateResponseFile(const char* name, std::string const& options,
- std::vector<std::string>& makefile_depends)
+bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
+ std::string const& l) const
+{
+ // Check for an explicit setting one way or the other.
+ std::string const responseVar =
+ "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS";
+ if (const char* val = this->Makefile->GetDefinition(responseVar)) {
+ if (*val) {
+ return cmSystemTools::IsOn(val);
+ }
+ }
+
+ // Check for a system limit.
+ if (size_t const limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
+ // Compute the total length of our list of object files with room
+ // for argument separation and quoting. This does not convert paths
+ // relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so the
+ // 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::vector<std::string>::const_iterator i =
+ this->ExternalObjects.begin();
+ i != this->ExternalObjects.end(); ++i) {
+ length += i->size() + 3;
+ }
+
+ // We need to guarantee room for both objects and libraries, so
+ // if the objects take up more than half then use a response file
+ // for them.
+ if (length > (limit / 2)) {
+ return true;
+ }
+ }
+
+ // We do not need a response file for objects.
+ return false;
+}
+
+bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
+ std::string const& l) const
+{
+ // Check for an explicit setting one way or the other.
+ std::string const responseVar =
+ "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES";
+ if (const char* val = this->Makefile->GetDefinition(responseVar)) {
+ if (*val) {
+ return cmSystemTools::IsOn(val);
+ }
+ }
+
+ // We do not need a response file for libraries.
+ return false;
+}
+
+std::string cmMakefileTargetGenerator::CreateResponseFile(
+ const char* name, std::string const& options,
+ std::vector<std::string>& makefile_depends)
{
// Create the response file.
std::string responseFileNameFull = this->TargetBuildDirectoryFull;
@@ -1748,18 +1573,63 @@ cmMakefileTargetGenerator
return responseFileName;
}
-//----------------------------------------------------------------------------
-void
-cmMakefileTargetGenerator
-::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
- bool useResponseFile, std::string& buildObjs,
- std::vector<std::string>& makefile_depends)
+cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
+{
+ if (this->Makefile->IsOn("MSVC60")) {
+ return this->GlobalGenerator->CreateMSVC60LinkLineComputer(outputConverter,
+ stateDir);
+ }
+ return this->GlobalGenerator->CreateLinkLineComputer(outputConverter,
+ stateDir);
+}
+
+void cmMakefileTargetGenerator::CreateLinkLibs(
+ cmLinkLineComputer* linkLineComputer, std::string& linkLibs,
+ bool useResponseFile, std::vector<std::string>& makefile_depends)
+{
+ std::string frameworkPath;
+ std::string linkPath;
+ std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(config);
+ this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+ frameworkPath, linkPath);
+ linkLibs = frameworkPath + linkPath + linkLibs;
+
+ 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";
+ const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
+ if (!responseFlag) {
+ responseFlag = "@";
+ }
+
+ // Create this response file.
+ std::string link_rsp =
+ this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
+
+ // Reference the response file.
+ linkLibs = responseFlag;
+ linkLibs += this->LocalGenerator->ConvertToOutputFormat(
+ link_rsp, cmOutputConverter::SHELL);
+ }
+}
+
+void cmMakefileTargetGenerator::CreateObjectLists(
+ bool useLinkScript, bool useArchiveRules, bool useResponseFile,
+ std::string& buildObjs, std::vector<std::string>& makefile_depends,
+ bool useWatcomQuote)
{
std::string variableName;
std::string variableNameExternal;
- this->WriteObjectsVariable(variableName, variableNameExternal);
- if(useResponseFile)
- {
+ this->WriteObjectsVariable(variableName, variableNameExternal,
+ useWatcomQuote);
+ if (useResponseFile) {
// MSVC response files cannot exceed 128K.
std::string::size_type const responseFileLimit = 131000;
@@ -1769,22 +1639,20 @@ cmMakefileTargetGenerator
// Lookup the response file reference flag.
std::string responseFlagVar = "CMAKE_";
- responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
+ responseFlagVar +=
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
- const char* responseFlag =
- this->Makefile->GetDefinition(responseFlagVar.c_str());
- if(!responseFlag)
- {
+ const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
+ if (!responseFlag) {
responseFlag = "@";
- }
+ }
// Write a response file for each string.
const char* sep = "";
- for(unsigned int i = 0; i < object_strings.size(); ++i)
- {
+ for (unsigned int i = 0; i < object_strings.size(); ++i) {
// Number the response files.
char rsp[32];
- sprintf(rsp, "objects%u.rsp", i+1);
+ sprintf(rsp, "objects%u.rsp", i + 1);
// Create this response file.
std::string objects_rsp =
@@ -1796,208 +1664,100 @@ cmMakefileTargetGenerator
// Reference the response file.
buildObjs += responseFlag;
- buildObjs += this->Convert(objects_rsp.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
- }
+ buildObjs += this->LocalGenerator->ConvertToOutputFormat(
+ objects_rsp, cmOutputConverter::SHELL);
}
- else if(useLinkScript)
- {
- if(!useArchiveRules)
- {
- this->WriteObjectsString(buildObjs);
- }
+ } else if (useLinkScript) {
+ if (!useArchiveRules) {
+ std::vector<std::string> objStrings;
+ this->WriteObjectsStrings(objStrings);
+ buildObjs = objStrings[0];
}
- else
- {
+ } else {
buildObjs = "$(";
buildObjs += variableName;
buildObjs += ") $(";
buildObjs += variableNameExternal;
buildObjs += ")";
- }
+ }
}
-//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
- const char* lang)
+ const std::string& lang)
{
std::string responseVar = "CMAKE_";
responseVar += lang;
responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
- bool useResponseFile = this->Makefile->IsOn(responseVar.c_str());
-
+ bool useResponseFile = this->Makefile->IsOn(responseVar);
std::vector<std::string> includes;
- const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- this->LocalGenerator->GetIncludeDirectories(includes,
- this->GeneratorTarget,
+ const std::string& config =
+ this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
lang, config);
- std::string includeFlags =
- this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget,
- lang, useResponseFile);
- if(includeFlags.empty())
- {
+ std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
+ includes, this->GeneratorTarget, lang, false, useResponseFile, config);
+ if (includeFlags.empty()) {
return;
- }
+ }
- if(useResponseFile)
- {
+ if (useResponseFile) {
std::string name = "includes_";
name += lang;
name += ".rsp";
std::string arg = "@" +
this->CreateResponseFile(name.c_str(), includeFlags,
this->FlagFileDepends[lang]);
- this->LocalGenerator->AppendFlags(flags, arg.c_str());
- }
- else
- {
- this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
-{
- // Compute the module directory.
- if(!this->FortranModuleDirectoryComputed)
- {
- const char* target_mod_dir =
- this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
- const char* moddir_flag =
- this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
- if(target_mod_dir && moddir_flag)
- {
- // Compute the full path to the module directory.
- if(cmSystemTools::FileIsFullPath(target_mod_dir))
- {
- // Already a full path.
- this->FortranModuleDirectory = target_mod_dir;
- }
- else
- {
- // Interpret relative to the current output directory.
- this->FortranModuleDirectory =
- this->Makefile->GetCurrentOutputDirectory();
- this->FortranModuleDirectory += "/";
- this->FortranModuleDirectory += target_mod_dir;
- }
-
- // Make sure the module output directory exists.
- cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
- }
- this->FortranModuleDirectoryComputed = true;
- }
-
- // Return the computed directory.
- if(this->FortranModuleDirectory.empty())
- {
- return 0;
- }
- else
- {
- return this->FortranModuleDirectory.c_str();
- }
-}
-
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
-{
- // Enable module output if necessary.
- if(const char* modout_flag =
- this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG"))
- {
- this->LocalGenerator->AppendFlags(flags, modout_flag);
- }
-
- // Add a module output directory flag if necessary.
- const char* mod_dir = this->GetFortranModuleDirectory();
- if(!mod_dir)
- {
- mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
- }
- if(mod_dir)
- {
- const char* moddir_flag =
- this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
- std::string modflag = moddir_flag;
- modflag += this->Convert(mod_dir,
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- this->LocalGenerator->AppendFlags(flags, modflag.c_str());
- }
-
- // If there is a separate module path flag then duplicate the
- // include path with it. This compiler does not search the include
- // path for modules.
- if(const char* modpath_flag =
- this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
- {
- std::vector<std::string> includes;
- const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- this->LocalGenerator->GetIncludeDirectories(includes,
- this->GeneratorTarget,
- "C", config);
- for(std::vector<std::string>::const_iterator idi = includes.begin();
- idi != includes.end(); ++idi)
- {
- std::string flg = modpath_flag;
- flg += this->Convert(idi->c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL);
- this->LocalGenerator->AppendFlags(flags, flg.c_str());
- }
- }
+ this->LocalGenerator->AppendFlags(flags, arg);
+ } else {
+ this->LocalGenerator->AppendFlags(flags, includeFlags);
+ }
}
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
+void cmMakefileTargetGenerator::GenDefFile(
+ std::vector<std::string>& real_link_commands)
{
- if(this->GeneratorTarget->ModuleDefinitionFile.empty())
- {
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+ if (!mdi || !mdi->DefFileGenerated) {
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 += " ";
+ std::string objlist_file = mdi->DefFile + ".objs";
+ cmd += this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
+ 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());
+
+ 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";
+ }
}
-
- // TODO: Create a per-language flag variable.
- const char* defFileFlag =
- this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
- if(!defFileFlag)
- {
- return;
+ for (std::vector<std::string>::const_iterator i =
+ this->ExternalObjects.begin();
+ i != this->ExternalObjects.end(); ++i) {
+ fout << *i << "\n";
}
+ }
- // 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->ConvertToLinkReference(
- this->GeneratorTarget->ModuleDefinitionFile.c_str()));
- this->LocalGenerator->AppendFlags(flags, flag.c_str());
-}
-
-//----------------------------------------------------------------------------
-const char* cmMakefileTargetGenerator::GetFeature(const char* feature)
-{
- return this->Target->GetFeature(feature, this->ConfigName);
-}
-
-//----------------------------------------------------------------------------
-bool cmMakefileTargetGenerator::GetFeatureAsBool(const char* feature)
-{
- return cmSystemTools::IsOn(this->GetFeature(feature));
-}
-
-//----------------------------------------------------------------------------
-void cmMakefileTargetGenerator::AddFeatureFlags(
- std::string& flags, const char* lang
- )
-{
- // Add language-specific flags.
- this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);
-
- if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
- {
- this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
- }
+ for (std::vector<cmSourceFile const*>::const_iterator i =
+ mdi->Sources.begin();
+ i != mdi->Sources.end(); ++i) {
+ fout << (*i)->GetFullPath() << "\n";
+ }
}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index f7a1e2e56..92c9f60b0 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -1,59 +1,57 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMakefileTargetGenerator_h
#define cmMakefileTargetGenerator_h
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cmCommonTargetGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmOSXBundleGenerator.h"
-class cmCustomCommand;
-class cmDependInformation;
-class cmDepends;
-class cmGeneratorTarget;
+class cmCustomCommandGenerator;
class cmGeneratedFileStream;
+class cmGeneratorTarget;
class cmGlobalUnixMakefileGenerator3;
-class cmLocalUnixMakefileGenerator3;
-class cmMakefile;
-class cmTarget;
+class cmLinkLineComputer;
+class cmOutputConverter;
class cmSourceFile;
+class cmStateDirectory;
/** \class cmMakefileTargetGenerator
* \brief Support Routines for writing makefiles
*
*/
-class cmMakefileTargetGenerator
+class cmMakefileTargetGenerator : public cmCommonTargetGenerator
{
public:
// constructor to set the ivars
- cmMakefileTargetGenerator(cmTarget* target);
- virtual ~cmMakefileTargetGenerator();
+ cmMakefileTargetGenerator(cmGeneratorTarget* target);
+ ~cmMakefileTargetGenerator() CM_OVERRIDE;
// construct using this factory call
- static cmMakefileTargetGenerator *New(cmTarget *tgt);
+ static cmMakefileTargetGenerator* New(cmGeneratorTarget* tgt);
/* the main entry point for this class. Writes the Makefiles associated
with this target */
virtual void WriteRuleFiles() = 0;
/* return the number of actions that have progress reporting on them */
- virtual unsigned long GetNumberOfProgressActions() {
- return this->NumberOfProgressActions;}
- std::string GetProgressFileNameFull()
- { return this->ProgressFileNameFull; }
+ virtual unsigned long GetNumberOfProgressActions()
+ {
+ return this->NumberOfProgressActions;
+ }
+ std::string GetProgressFileNameFull() { return this->ProgressFileNameFull; }
- cmTarget* GetTarget() { return this->Target;}
+ cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
protected:
-
// create the file and directory etc
void CreateRuleFile();
@@ -75,13 +73,16 @@ protected:
void WriteTargetDependRules();
// write rules for Mac OS X Application Bundle content.
- struct MacOSXContentGeneratorType :
- cmOSXBundleGenerator::MacOSXContentGeneratorType
+ struct MacOSXContentGeneratorType
+ : cmOSXBundleGenerator::MacOSXContentGeneratorType
{
- MacOSXContentGeneratorType(cmMakefileTargetGenerator* gen) :
- Generator(gen) {}
+ MacOSXContentGeneratorType(cmMakefileTargetGenerator* gen)
+ : Generator(gen)
+ {
+ }
- void operator()(cmSourceFile& source, const char* pkgloc);
+ void operator()(cmSourceFile const& source,
+ const char* pkgloc) CM_OVERRIDE;
private:
cmMakefileTargetGenerator* Generator;
@@ -89,45 +90,39 @@ protected:
friend struct MacOSXContentGeneratorType;
// write the rules for an object
- void WriteObjectRuleFiles(cmSourceFile& source);
+ void WriteObjectRuleFiles(cmSourceFile const& source);
// write the build rule for an object
- void WriteObjectBuildFile(std::string &obj,
- const char *lang,
- cmSourceFile& source,
+ 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& source,
+ void WriteObjectDependRules(cmSourceFile const& source,
std::vector<std::string>& depends);
// write the build rule for a custom command
- void GenerateCustomRuleFile(const cmCustomCommand& cc);
+ void GenerateCustomRuleFile(cmCustomCommandGenerator const& ccg);
// write a rule to drive building of more than one output from
// another rule
void GenerateExtraOutput(const char* out, const char* in,
bool symbolic = false);
- void AppendProgress(std::vector<std::string>& commands);
+ void MakeEchoProgress(cmLocalUnixMakefileGenerator3::EchoProgress&) const;
// write out the variable that lists the objects for this target
void WriteObjectsVariable(std::string& variableName,
- std::string& variableNameExternal);
- void WriteObjectsString(std::string& buildObjs);
+ std::string& variableNameExternal,
+ bool useWatcomQuote);
void WriteObjectsStrings(std::vector<std::string>& objStrings,
std::string::size_type limit = std::string::npos);
// write the driver rule to build target outputs
- void WriteTargetDriverRule(const char* main_output, bool relink);
+ void WriteTargetDriverRule(const std::string& main_output, bool relink);
void DriveCustomCommands(std::vector<std::string>& depends);
- // Return the a string with -F flags on apple
- std::string GetFrameworkFlags();
-
- void AppendFortranFormatFlags(std::string& flags, cmSourceFile& source);
-
// append intertarget dependencies
void AppendTargetDepends(std::vector<std::string>& depends);
@@ -138,16 +133,7 @@ protected:
void AppendLinkDepends(std::vector<std::string>& depends);
// Lookup the link rule for this target.
- std::string GetLinkRule(const char* linkRuleVar);
-
- /** In order to support parallel builds for custom commands with
- multiple outputs the outputs are given a serial order, and only
- the first output actually has the build rule. Other outputs
- just depend on the first one. The check-build-system step must
- remove a dependee if the depender is missing to make sure both
- are regenerated properly. This method is used by the local
- makefile generators to register such pairs. */
- void AddMultipleOutputPair(const char* depender, const char* dependee);
+ std::string GetLinkRule(const std::string& linkRuleVar);
/** Create a script to hold link rules and a command to invoke the
script at build time. */
@@ -156,31 +142,45 @@ protected:
std::vector<std::string>& makefile_commands,
std::vector<std::string>& makefile_depends);
+ cmLinkLineComputer* CreateLinkLineComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir);
+
/** Create a response file with the given set of options. Returns
the relative path from the target build working directory to the
response file name. */
- std::string CreateResponseFile(const char* name,
- std::string const& options,
+ std::string CreateResponseFile(const char* name, std::string const& options,
std::vector<std::string>& makefile_depends);
+ bool CheckUseResponseFileForObjects(std::string const& l) const;
+ bool CheckUseResponseFileForLibraries(std::string const& l) const;
+
+ /** Create list of flags for link libraries. */
+ void CreateLinkLibs(cmLinkLineComputer* linkLineComputer,
+ std::string& linkLibs, bool useResponseFile,
+ std::vector<std::string>& makefile_depends);
+
/** Create lists of object files for linking and cleaning. */
void CreateObjectLists(bool useLinkScript, bool useArchiveRules,
bool useResponseFile, std::string& buildObjs,
- std::vector<std::string>& makefile_depends);
+ std::vector<std::string>& makefile_depends,
+ bool useWatcomQuote);
+
+ /** Add commands for generate def files */
+ void GenDefFile(std::vector<std::string>& real_link_commands);
- void AddIncludeFlags(std::string& flags, const char* lang);
+ void AddIncludeFlags(std::string& flags,
+ const std::string& lang) CM_OVERRIDE;
virtual void CloseFileStreams();
- void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
- std::string& linkFlags);
- cmTarget *Target;
- cmGeneratorTarget* GeneratorTarget;
- cmLocalUnixMakefileGenerator3 *LocalGenerator;
- cmGlobalUnixMakefileGenerator3 *GlobalGenerator;
- cmMakefile *Makefile;
- const char *ConfigName;
-
- enum CustomCommandDriveType { OnBuild, OnDepends, OnUtility };
+ cmLocalUnixMakefileGenerator3* LocalGenerator;
+ cmGlobalUnixMakefileGenerator3* GlobalGenerator;
+
+ enum CustomCommandDriveType
+ {
+ OnBuild,
+ OnDepends,
+ OnUtility
+ };
CustomCommandDriveType CustomCommandDriver;
// the full path to the build file
@@ -197,17 +197,19 @@ protected:
std::string TargetBuildDirectoryFull;
// the stream for the build file
- cmGeneratedFileStream *BuildFileStream;
+ cmGeneratedFileStream* BuildFileStream;
// the stream for the flag file
std::string FlagFileNameFull;
- cmGeneratedFileStream *FlagFileStream;
- class StringList: public std::vector<std::string> {};
- std::map<cmStdString, StringList> FlagFileDepends;
+ cmGeneratedFileStream* FlagFileStream;
+ class StringList : public std::vector<std::string>
+ {
+ };
+ std::map<std::string, StringList> FlagFileDepends;
// the stream for the info file
std::string InfoFileNameFull;
- cmGeneratedFileStream *InfoFileStream;
+ cmGeneratedFileStream* InfoFileStream;
// files to clean
std::vector<std::string> CleanFiles;
@@ -217,13 +219,18 @@ protected:
std::vector<std::string> ExternalObjects;
// Set of object file names that will be built in this directory.
- std::set<cmStdString> ObjectFiles;
+ std::set<std::string> ObjectFiles;
// Set of extra output files to be driven by the build.
- std::set<cmStdString> ExtraFiles;
+ std::set<std::string> ExtraFiles;
- typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
+ typedef std::map<std::string, std::string> MultipleOutputPairsType;
MultipleOutputPairsType MultipleOutputPairs;
+ bool WriteMakeRule(std::ostream& os, const char* comment,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands,
+ bool in_help = false);
// Target name info.
std::string TargetNameOut;
@@ -233,46 +240,9 @@ protected:
std::string TargetNamePDB;
// Mac OS X content info.
- std::set<cmStdString> MacContentFolders;
+ std::set<std::string> MacContentFolders;
cmOSXBundleGenerator* OSXBundleGenerator;
MacOSXContentGeneratorType* MacOSXContentGenerator;
-
- typedef std::map<cmStdString, cmStdString> ByLanguageMap;
- std::string GetFlags(const std::string &l);
- ByLanguageMap FlagsByLanguage;
- std::string GetDefines(const std::string &l);
- ByLanguageMap DefinesByLanguage;
-
- // Target-wide Fortran module output directory.
- bool FortranModuleDirectoryComputed;
- std::string FortranModuleDirectory;
- const char* GetFortranModuleDirectory();
-
- // Compute target-specific Fortran language flags.
- void AddFortranFlags(std::string& flags);
-
- // Helper to add flag for windows .def file.
- void AddModuleDefinitionFlag(std::string& flags);
-
- // Add language feature flags.
- void AddFeatureFlags(std::string& flags, const char* lang);
-
- // Feature query methods.
- const char* GetFeature(const char* feature);
- bool GetFeatureAsBool(const char* feature);
-
- //==================================================================
- // Convenience routines that do nothing more than forward to
- // implementaitons
- std::string Convert(const char* source,
- cmLocalGenerator::RelativeRoot relative,
- cmLocalGenerator::OutputFormat output =
- cmLocalGenerator::UNCHANGED,
- bool optional = false)
- {
- return this->LocalGenerator->Convert(source, relative, output, optional);
- }
-
};
#endif
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 1fa4e95b6..a7c5d27f2 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -1,62 +1,57 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileUtilityTargetGenerator.h"
+#include <ostream>
+#include <string>
+#include <vector>
+
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmTarget.h"
+#include "cmOSXBundleGenerator.h"
+#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
-cmMakefileUtilityTargetGenerator
-::cmMakefileUtilityTargetGenerator(cmTarget* target):
- cmMakefileTargetGenerator(target)
+cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
+ cmGeneratorTarget* target)
+ : cmMakefileTargetGenerator(target)
{
this->CustomCommandDriver = OnUtility;
- this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
- this->ConfigName);
+ this->OSXBundleGenerator =
+ new cmOSXBundleGenerator(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-//----------------------------------------------------------------------------
-cmMakefileUtilityTargetGenerator
-::~cmMakefileUtilityTargetGenerator()
+cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator()
{
delete this->OSXBundleGenerator;
}
-//----------------------------------------------------------------------------
void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
{
this->CreateRuleFile();
- *this->BuildFileStream
- << "# Utility rule file for " << this->Target->GetName() << ".\n\n";
+ *this->BuildFileStream << "# Utility rule file for "
+ << this->GeneratorTarget->GetName() << ".\n\n";
- if(!this->NoRuleMessages)
- {
- const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")?
- "$(CMAKE_BINARY_DIR)/" : "");
+ if (!this->NoRuleMessages) {
+ const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
+ ? "$(CMAKE_BINARY_DIR)/"
+ : "");
// Include the progress variables for the target.
*this->BuildFileStream
<< "# Include the progress variables for this target.\n"
- << this->LocalGenerator->IncludeDirective << " " << root
- << this->Convert(this->ProgressFileNameFull.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator
+ ->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->ProgressFileNameFull)
+ .c_str())
<< "\n\n";
- }
+ }
// write the custom commands for this target
this->WriteTargetBuildRules();
@@ -66,20 +61,22 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
std::vector<std::string> depends;
// Utility targets store their rules in pre- and post-build commands.
- this->LocalGenerator->AppendCustomDepends
- (depends, this->Target->GetPreBuildCommands());
+ this->LocalGenerator->AppendCustomDepends(
+ depends, this->GeneratorTarget->GetPreBuildCommands());
- this->LocalGenerator->AppendCustomDepends
- (depends, this->Target->GetPostBuildCommands());
+ this->LocalGenerator->AppendCustomDepends(
+ depends, this->GeneratorTarget->GetPostBuildCommands());
- this->LocalGenerator->AppendCustomCommands
- (commands, this->Target->GetPreBuildCommands(), this->Target);
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPreBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
// Depend on all custom command outputs for sources
this->DriveCustomCommands(depends);
- this->LocalGenerator->AppendCustomCommands
- (commands, this->Target->GetPostBuildCommands(), this->Target);
+ this->LocalGenerator->AppendCustomCommands(
+ commands, this->GeneratorTarget->GetPostBuildCommands(),
+ this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
// Add dependencies on targets that must be built first.
this->AppendTargetDepends(depends);
@@ -90,22 +87,20 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
// If the rule is empty add the special empty rule dependency needed
// by some make tools.
- if(depends.empty() && commands.empty())
- {
+ if (depends.empty() && commands.empty()) {
std::string hack = this->GlobalGenerator->GetEmptyRuleHackDepends();
- if(!hack.empty())
- {
+ if (!hack.empty()) {
depends.push_back(hack);
- }
}
+ }
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- this->Target->GetName(),
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->GeneratorTarget->GetName(),
depends, commands, true);
// Write the main driver rule to build everything in this target.
- this->WriteTargetDriverRule(this->Target->GetName(), false);
+ this->WriteTargetDriverRule(this->GeneratorTarget->GetName(), false);
// Write clean target
this->WriteTargetCleanRules();
@@ -117,4 +112,3 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
// close the streams
this->CloseFileStreams();
}
-
diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h
index fc47b3891..8df5dd46f 100644
--- a/Source/cmMakefileUtilityTargetGenerator.h
+++ b/Source/cmMakefileUtilityTargetGenerator.h
@@ -1,32 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMakefileUtilityTargetGenerator_h
#define cmMakefileUtilityTargetGenerator_h
+#include "cmConfigure.h"
+
#include "cmMakefileTargetGenerator.h"
-class cmMakefileUtilityTargetGenerator:
- public cmMakefileTargetGenerator
+class cmGeneratorTarget;
+
+class cmMakefileUtilityTargetGenerator : public cmMakefileTargetGenerator
{
public:
- cmMakefileUtilityTargetGenerator(cmTarget* target);
- virtual ~cmMakefileUtilityTargetGenerator();
+ cmMakefileUtilityTargetGenerator(cmGeneratorTarget* target);
+ ~cmMakefileUtilityTargetGenerator() CM_OVERRIDE;
/* the main entry point for this class. Writes the Makefiles associated
with this target */
- virtual void WriteRuleFiles();
+ void WriteRuleFiles() CM_OVERRIDE;
protected:
-
};
#endif
diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx
index 4236d102c..14fd96f08 100644
--- a/Source/cmMarkAsAdvancedCommand.cxx
+++ b/Source/cmMarkAsAdvancedCommand.cxx
@@ -1,62 +1,49 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmMarkAsAdvancedCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmMarkAsAdvancedCommand.h"
+class cmExecutionStatus;
// cmMarkAsAdvancedCommand
-bool cmMarkAsAdvancedCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- unsigned int i =0;
+ unsigned int i = 0;
const char* value = "1";
bool overwrite = false;
- if(args[0] == "CLEAR" || args[0] == "FORCE")
- {
+ if (args[0] == "CLEAR" || args[0] == "FORCE") {
overwrite = true;
- if(args[0] == "CLEAR")
- {
+ if (args[0] == "CLEAR") {
value = "0";
- }
- i = 1;
}
- for(; i < args.size(); ++i)
- {
- std::string variable = args[i];
- cmCacheManager* manager = this->Makefile->GetCacheManager();
- cmCacheManager::CacheIterator it =
- manager->GetCacheIterator(variable.c_str());
- if ( it.IsAtEnd() )
- {
- this->Makefile->GetCacheManager()
- ->AddCacheEntry(variable.c_str(), 0, 0,
- cmCacheManager::UNINITIALIZED);
+ i = 1;
+ }
+ for (; i < args.size(); ++i) {
+ std::string const& variable = args[i];
+ cmState* state = this->Makefile->GetState();
+ if (!state->GetCacheEntryValue(variable)) {
+ this->Makefile->GetCMakeInstance()->AddCacheEntry(
+ variable, CM_NULLPTR, CM_NULLPTR, cmStateEnums::UNINITIALIZED);
overwrite = true;
- }
- it.Find(variable.c_str());
- if ( it.IsAtEnd() )
- {
+ }
+ if (!state->GetCacheEntryValue(variable)) {
cmSystemTools::Error("This should never happen...");
return false;
- }
- if ( !it.PropertyExists("ADVANCED") || overwrite )
- {
- it.SetProperty("ADVANCED", value);
- }
}
+ if (!state->GetCacheEntryProperty(variable, "ADVANCED") || overwrite) {
+ state->SetCacheEntryProperty(variable, "ADVANCED", value);
+ }
+ }
return true;
}
-
diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h
index 246eb8aa3..a7791a932 100644
--- a/Source/cmMarkAsAdvancedCommand.h
+++ b/Source/cmMarkAsAdvancedCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMarkAsAdvancedCommand_h
#define cmMarkAsAdvancedCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmMarkAsAdvancedCommand
* \brief mark_as_advanced command
*
@@ -25,61 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmMarkAsAdvancedCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmMarkAsAdvancedCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "mark_as_advanced";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Mark cmake cached variables as advanced.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " mark_as_advanced([CLEAR|FORCE] VAR VAR2 VAR...)\n"
- "Mark the named cached variables as advanced. An advanced variable "
- "will not be displayed in any of the cmake GUIs unless the show "
- "advanced option is on. "
- "If CLEAR is the first argument advanced variables are changed back "
- "to unadvanced. "
- "If FORCE is the first argument, then the variable is made advanced. "
- "If neither FORCE nor CLEAR is specified, new values will be marked as "
- "advanced, but if the variable already has an advanced/non-advanced "
- "state, it will not be changed.\n"
- "It does nothing in script mode.";
- }
-
- /**
- * This determines if the command is invoked when in script mode.
- * mark_as_advanced() will have no effect in script mode, but this will
- * make many of the modules usable in cmake/ctest scripts, (among them
- * FindUnixMake.cmake used by the CTEST_BUILD command.
- */
- virtual bool IsScriptable() const { return true; }
-
- cmTypeMacro(cmMarkAsAdvancedCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx
index 9fc42659a..c1cd1b6c2 100644
--- a/Source/cmMathCommand.cxx
+++ b/Source/cmMathCommand.cxx
@@ -1,61 +1,51 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMathCommand.h"
+#include <stdio.h>
+
#include "cmExprParserHelper.h"
+#include "cmMakefile.h"
+
+class cmExecutionStatus;
-//----------------------------------------------------------------------------
-bool cmMathCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmMathCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if ( args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("must be called with at least one argument.");
return false;
- }
- const std::string &subCommand = args[0];
- if(subCommand == "EXPR")
- {
+ }
+ const std::string& subCommand = args[0];
+ if (subCommand == "EXPR") {
return this->HandleExprCommand(args);
- }
- std::string e = "does not recognize sub-command "+subCommand;
- this->SetError(e.c_str());
+ }
+ std::string e = "does not recognize sub-command " + subCommand;
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
{
- if ( args.size() != 3 )
- {
+ if (args.size() != 3) {
this->SetError("EXPR called with incorrect arguments.");
return false;
- }
+ }
const std::string& outputVariable = args[1];
const std::string& expression = args[2];
cmExprParserHelper helper;
- if ( !helper.ParseString(expression.c_str(), 0) )
- {
- std::string e = "cannot parse the expression: \""+expression+"\": ";
+ if (!helper.ParseString(expression.c_str(), 0)) {
+ std::string e = "cannot parse the expression: \"" + expression + "\": ";
e += helper.GetError();
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
- }
+ }
char buffer[1024];
sprintf(buffer, "%d", helper.GetResult());
- this->Makefile->AddDefinition(outputVariable.c_str(), buffer);
+ this->Makefile->AddDefinition(outputVariable, buffer);
return true;
}
diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h
index dc0ceb340..67dbdda37 100644
--- a/Source/cmMathCommand.h
+++ b/Source/cmMathCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMathCommand_h
#define cmMathCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/// Mathematical expressions: math(EXPR ...) command.
class cmMathCommand : public cmCommand
{
@@ -21,56 +19,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmMathCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmMathCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "math";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Mathematical expressions.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " math(EXPR <output variable> <math expression>)\n"
- "EXPR evaluates mathematical expression and returns result in the "
- "output variable. Example mathematical expression is "
- "'5 * ( 10 + 13 )'. Supported operators are "
- "+ - * / % | & ^ ~ << >> * / %. They have the same meaning "
- " as they do in C code.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- cmTypeMacro(cmMathCommand, cmCommand);
protected:
-
bool HandleExprCommand(std::vector<std::string> const& args);
};
-
#endif
-
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index e1dbf349d..43fb5f54c 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -1,82 +1,80 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmMessageCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmMessenger.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmMessageCommand.h"
+class cmExecutionStatus;
// cmLibraryCommand
-bool cmMessageCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
- std::string message;
+ }
std::vector<std::string>::const_iterator i = args.begin();
cmake::MessageType type = cmake::MESSAGE;
bool status = false;
bool fatal = false;
- if (*i == "SEND_ERROR")
- {
+ if (*i == "SEND_ERROR") {
type = cmake::FATAL_ERROR;
++i;
- }
- else if (*i == "FATAL_ERROR")
- {
+ } else if (*i == "FATAL_ERROR") {
fatal = true;
type = cmake::FATAL_ERROR;
++i;
- }
- else if (*i == "WARNING")
- {
+ } else if (*i == "WARNING") {
type = cmake::WARNING;
++i;
+ } else if (*i == "AUTHOR_WARNING") {
+ if (this->Makefile->IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
+ !this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
+ fatal = true;
+ type = cmake::AUTHOR_ERROR;
+ } else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
+ type = cmake::AUTHOR_WARNING;
+ } else {
+ return true;
}
- else if (*i == "AUTHOR_WARNING")
- {
- type = cmake::AUTHOR_WARNING;
++i;
- }
- else if (*i == "STATUS")
- {
+ } else if (*i == "STATUS") {
status = true;
++i;
+ } else if (*i == "DEPRECATION") {
+ if (this->Makefile->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;
+ } else {
+ return true;
}
+ ++i;
+ }
- for(;i != args.end(); ++i)
- {
- message += *i;
- }
+ std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
- if (type != cmake::MESSAGE)
- {
- this->Makefile->IssueMessage(type, message.c_str());
- }
- else
- {
- if (status)
- {
+ 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
- {
+ } else {
cmSystemTools::Message(message.c_str());
- }
}
- if(fatal)
- {
+ }
+ if (fatal) {
cmSystemTools::SetFatalErrorOccured();
- }
+ }
return true;
}
-
diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h
index fc61810c3..96939e514 100644
--- a/Source/cmMessageCommand.h
+++ b/Source/cmMessageCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMessageCommand_h
#define cmMessageCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmMessageCommand
* \brief Displays a message to the user
*
@@ -24,69 +22,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmMessageCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmMessageCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "message";}
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Display a message to the user.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR]\n"
- " \"message to display\" ...)\n"
- "The optional keyword determines the type of message:\n"
- " (none) = Important information\n"
- " STATUS = Incidental information\n"
- " WARNING = CMake Warning, continue processing\n"
- " AUTHOR_WARNING = CMake Warning (dev), continue processing\n"
- " SEND_ERROR = CMake Error, continue processing,\n"
- " but skip generation\n"
- " FATAL_ERROR = CMake Error, stop processing and generation\n"
- "The CMake command-line tool displays STATUS messages on stdout "
- "and all other message types on stderr. "
- "The CMake GUI displays all messages in its log area. "
- "The interactive dialogs (ccmake and CMakeSetup) show STATUS messages "
- "one at a time on a status line and other messages in interactive "
- "pop-up boxes."
- "\n"
- "CMake Warning and Error message text displays using a simple "
- "markup language. "
- "Non-indented text is formatted in line-wrapped paragraphs delimited "
- "by newlines. "
- "Indented text is considered pre-formatted."
- ;
- }
-
- cmTypeMacro(cmMessageCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
new file mode 100644
index 000000000..3ae5bc5c2
--- /dev/null
+++ b/Source/cmMessenger.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 "cmMessenger.h"
+
+#include "cmAlgorithms.h"
+#include "cmDocumentationFormatter.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmsys/SystemInformation.hxx"
+#endif
+
+#include <sstream>
+
+cmake::MessageType cmMessenger::ConvertMessageType(cmake::MessageType t) const
+{
+ bool warningsAsErrors;
+
+ if (t == cmake::AUTHOR_WARNING || t == cmake::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;
+ }
+ } else if (t == cmake::DEPRECATION_WARNING ||
+ t == cmake::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;
+ }
+ }
+
+ return t;
+}
+
+bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const
+{
+ bool isVisible = true;
+
+ if (t == cmake::DEPRECATION_ERROR) {
+ if (!this->GetDeprecatedWarningsAsErrors()) {
+ isVisible = false;
+ }
+ } else if (t == cmake::DEPRECATION_WARNING) {
+ if (this->GetSuppressDeprecatedWarnings()) {
+ isVisible = false;
+ }
+ } else if (t == cmake::AUTHOR_ERROR) {
+ if (!this->GetDevWarningsAsErrors()) {
+ isVisible = false;
+ }
+ } else if (t == cmake::AUTHOR_WARNING) {
+ if (this->GetSuppressDevWarnings()) {
+ isVisible = false;
+ }
+ }
+
+ return isVisible;
+}
+
+static bool printMessagePreamble(cmake::MessageType t, std::ostream& msg)
+{
+ // Construct the message header.
+ if (t == cmake::FATAL_ERROR) {
+ msg << "CMake Error";
+ } else if (t == cmake::INTERNAL_ERROR) {
+ msg << "CMake Internal Error (please report a bug)";
+ } else if (t == cmake::LOG) {
+ msg << "CMake Debug Log";
+ } else if (t == cmake::DEPRECATION_ERROR) {
+ msg << "CMake Deprecation Error";
+ } else if (t == cmake::DEPRECATION_WARNING) {
+ msg << "CMake Deprecation Warning";
+ } else if (t == cmake::AUTHOR_WARNING) {
+ msg << "CMake Warning (dev)";
+ } else if (t == cmake::AUTHOR_ERROR) {
+ msg << "CMake Error (dev)";
+ } else {
+ msg << "CMake Warning";
+ }
+ return true;
+}
+
+void printMessageText(std::ostream& msg, std::string const& text)
+{
+ msg << ":\n";
+ cmDocumentationFormatter formatter;
+ formatter.SetIndent(" ");
+ formatter.PrintFormatted(msg, text.c_str());
+}
+
+void displayMessage(cmake::MessageType t, std::ostringstream& msg)
+{
+ // Add a note about warning suppression.
+ if (t == cmake::AUTHOR_WARNING) {
+ msg << "This warning is for project developers. Use -Wno-dev to suppress "
+ "it.";
+ } else if (t == cmake::AUTHOR_ERROR) {
+ msg << "This error is for project developers. Use -Wno-error=dev to "
+ "suppress "
+ "it.";
+ }
+
+ // Add a terminating blank line.
+ msg << "\n";
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ // Add a C++ stack trace to internal errors.
+ if (t == cmake::INTERNAL_ERROR) {
+ std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
+ if (!stack.empty()) {
+ if (cmHasLiteralPrefix(stack, "WARNING:")) {
+ stack = "Note:" + stack.substr(8);
+ }
+ msg << stack << "\n";
+ }
+ }
+#endif
+
+ // Output the message.
+ if (t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR ||
+ t == cmake::DEPRECATION_ERROR || t == cmake::AUTHOR_ERROR) {
+ cmSystemTools::SetErrorOccured();
+ cmSystemTools::Message(msg.str().c_str(), "Error");
+ } else {
+ cmSystemTools::Message(msg.str().c_str(), "Warning");
+ }
+}
+
+cmMessenger::cmMessenger(cmState* state)
+ : State(state)
+{
+}
+
+void cmMessenger::IssueMessage(cmake::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);
+ if (override != t) {
+ t = override;
+ force = true;
+ }
+ }
+
+ if (!force && !this->IsMessageTypeVisible(t)) {
+ return;
+ }
+ this->DisplayMessage(t, text, backtrace);
+}
+
+void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text,
+ const cmListFileBacktrace& backtrace) const
+{
+ std::ostringstream msg;
+ if (!printMessagePreamble(t, msg)) {
+ return;
+ }
+
+ // Add the immediate context.
+ backtrace.PrintTitle(msg);
+
+ printMessageText(msg, text);
+
+ // Add the rest of the context.
+ backtrace.PrintCallStack(msg);
+
+ 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
new file mode 100644
index 000000000..4aafbd40b
--- /dev/null
+++ b/Source/cmMessenger.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 cmMessenger_h
+#define cmMessenger_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmListFileCache.h"
+#include "cmake.h"
+
+#include <string>
+
+class cmState;
+
+class cmMessenger
+{
+public:
+ cmMessenger(cmState* state);
+
+ void IssueMessage(
+ cmake::MessageType t, std::string const& text,
+ cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
+
+ void DisplayMessage(cmake::MessageType t, std::string const& text,
+ cmListFileBacktrace const& backtrace) const;
+
+ bool GetSuppressDevWarnings() const;
+ bool GetSuppressDeprecatedWarnings() const;
+ bool GetDevWarningsAsErrors() const;
+ bool GetDeprecatedWarningsAsErrors() const;
+
+private:
+ bool IsMessageTypeVisible(cmake::MessageType t) const;
+ cmake::MessageType ConvertMessageType(cmake::MessageType t) const;
+
+ cmState* State;
+};
+
+#endif
diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx
index 6f7b6a949..5500eba65 100644
--- a/Source/cmNewLineStyle.cxx
+++ b/Source/cmNewLineStyle.cxx
@@ -1,94 +1,67 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNewLineStyle.h"
+#include <stddef.h>
-
-cmNewLineStyle::cmNewLineStyle() : NewLineStyle(Invalid)
+cmNewLineStyle::cmNewLineStyle()
+ : NewLineStyle(Invalid)
{
}
-
bool cmNewLineStyle::IsValid() const
{
return NewLineStyle != Invalid;
}
-
bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args,
std::string& errorString)
{
NewLineStyle = Invalid;
- for (size_t i = 0; i< args.size(); i++)
- {
- if (args[i] == "NEWLINE_STYLE")
- {
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == "NEWLINE_STYLE") {
size_t const styleIndex = i + 1;
- if (args.size() > styleIndex)
- {
- const std::string eol = args[styleIndex];
- if (eol == "LF" || eol == "UNIX")
- {
+ if (args.size() > styleIndex) {
+ std::string const& eol = args[styleIndex];
+ if (eol == "LF" || eol == "UNIX") {
NewLineStyle = LF;
return true;
- }
- else if (eol == "CRLF" || eol == "WIN32" || eol == "DOS")
- {
+ }
+ if (eol == "CRLF" || eol == "WIN32" || eol == "DOS") {
NewLineStyle = CRLF;
return true;
- }
- else
- {
- errorString = "NEWLINE_STYLE sets an unknown style, only LF, "
- "CRLF, UNIX, DOS, and WIN32 are supported";
- return false;
- }
}
- else
- {
- errorString = "NEWLINE_STYLE must set a style: "
- "LF, CRLF, UNIX, DOS, or WIN32";
+ errorString = "NEWLINE_STYLE sets an unknown style, only LF, "
+ "CRLF, UNIX, DOS, and WIN32 are supported";
return false;
- }
}
+ errorString = "NEWLINE_STYLE must set a style: "
+ "LF, CRLF, UNIX, DOS, or WIN32";
+ return false;
}
+ }
return true;
}
-
const std::string cmNewLineStyle::GetCharacters() const
{
- switch (NewLineStyle)
- {
+ switch (NewLineStyle) {
case Invalid:
return "";
case LF:
return "\n";
case CRLF:
return "\r\n";
- default:
- ;
- };
+ }
return "";
}
-
void cmNewLineStyle::SetStyle(Style style)
{
NewLineStyle = style;
}
-
cmNewLineStyle::Style cmNewLineStyle::GetStyle() const
{
return NewLineStyle;
diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h
index cae110604..397cd2c50 100644
--- a/Source/cmNewLineStyle.h
+++ b/Source/cmNewLineStyle.h
@@ -1,32 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmNewLineStyle_h
#define cmNewLineStyle_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
class cmNewLineStyle
{
public:
-
cmNewLineStyle();
enum Style
{
Invalid,
- // LF = '\n', 0x0A, 10
- // CR = '\r', 0x0D, 13
- LF, // Unix
- CRLF // Dos
+ // LF = '\n', 0x0A, 10
+ // CR = '\r', 0x0D, 13
+ LF, // Unix
+ CRLF // Dos
};
void SetStyle(Style);
@@ -35,7 +28,7 @@ public:
bool IsValid() const;
bool ReadFromArguments(const std::vector<std::string>& args,
- std::string &errorString);
+ std::string& errorString);
const std::string GetCharacters() const;
diff --git a/Source/cmNinjaLinkLineComputer.cxx b/Source/cmNinjaLinkLineComputer.cxx
new file mode 100644
index 000000000..7fbeeeaa3
--- /dev/null
+++ b/Source/cmNinjaLinkLineComputer.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 "cmNinjaLinkLineComputer.h"
+
+#include "cmGlobalNinjaGenerator.h"
+
+class cmOutputConverter;
+
+cmNinjaLinkLineComputer::cmNinjaLinkLineComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir,
+ cmGlobalNinjaGenerator const* gg)
+ : cmLinkLineComputer(outputConverter, stateDir)
+ , GG(gg)
+{
+}
+
+std::string cmNinjaLinkLineComputer::ConvertToLinkReference(
+ std::string const& lib) const
+{
+ return GG->ConvertToNinjaPath(lib);
+}
diff --git a/Source/cmNinjaLinkLineComputer.h b/Source/cmNinjaLinkLineComputer.h
new file mode 100644
index 000000000..13f05a838
--- /dev/null
+++ b/Source/cmNinjaLinkLineComputer.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 cmNinjaLinkLineComputer_h
+#define cmNinjaLinkLineComputer_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+#include "cmLinkLineComputer.h"
+
+class cmGlobalNinjaGenerator;
+class cmOutputConverter;
+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;
+
+private:
+ cmGlobalNinjaGenerator const* GG;
+};
+
+#endif
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 57adeba23..14a4ef824 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -1,65 +1,69 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNinjaNormalTargetGenerator.h"
-#include "cmLocalNinjaGenerator.h"
-#include "cmGlobalNinjaGenerator.h"
-#include "cmSourceFile.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+#include <map>
+#include <set>
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmLinkLineComputer.h"
+#include "cmLinkLineDeviceComputer.h"
+#include "cmLocalGenerator.h"
+#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
+#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
-
-#include <assert.h>
-#include <algorithm>
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-
-cmNinjaNormalTargetGenerator::
-cmNinjaNormalTargetGenerator(cmTarget* target)
+#include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
+
+cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
+ cmGeneratorTarget* target)
: cmNinjaTargetGenerator(target)
, TargetNameOut()
, TargetNameSO()
, TargetNameReal()
, TargetNameImport()
, TargetNamePDB()
- , TargetLinkLanguage(0)
+ , TargetLinkLanguage("")
+ , DeviceLinkObject()
{
this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
- if (target->GetType() == cmTarget::EXECUTABLE)
- target->GetExecutableNames(this->TargetNameOut,
- this->TargetNameReal,
- this->TargetNameImport,
- this->TargetNamePDB,
- GetLocalGenerator()->GetConfigName());
- else
- target->GetLibraryNames(this->TargetNameOut,
- this->TargetNameSO,
- this->TargetNameReal,
- this->TargetNameImport,
- this->TargetNamePDB,
- GetLocalGenerator()->GetConfigName());
-
- if(target->GetType() != cmTarget::OBJECT_LIBRARY)
- {
+ if (target->GetType() == cmStateEnums::EXECUTABLE) {
+ this->GetGeneratorTarget()->GetExecutableNames(
+ this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
+ this->TargetNamePDB, GetLocalGenerator()->GetConfigName());
+ } else {
+ this->GetGeneratorTarget()->GetLibraryNames(
+ this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
+ this->TargetNameImport, this->TargetNamePDB,
+ GetLocalGenerator()->GetConfigName());
+ }
+
+ if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) {
// on Windows the output dir is already needed at compile time
// ensure the directory exists (OutDir test)
EnsureDirectoryExists(target->GetDirectory(this->GetConfigName()));
- }
+ }
- this->OSXBundleGenerator = new cmOSXBundleGenerator(target,
- this->GetConfigName());
+ this->OSXBundleGenerator =
+ new cmOSXBundleGenerator(target, this->GetConfigName());
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
@@ -70,10 +74,10 @@ cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
void cmNinjaNormalTargetGenerator::Generate()
{
- if (!this->TargetLinkLanguage) {
+ if (this->TargetLinkLanguage.empty()) {
cmSystemTools::Error("CMake can not determine linker language for "
"target: ",
- this->GetTarget()->GetName());
+ this->GetGeneratorTarget()->GetName().c_str());
return;
}
@@ -83,16 +87,14 @@ void cmNinjaNormalTargetGenerator::Generate()
// Write the build statements
this->WriteObjectBuildStatements();
- if(this->GetTarget()->GetType() == cmTarget::OBJECT_LIBRARY)
- {
+ if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
this->WriteObjectLibStatement();
- }
- else
- {
- this->WriteLinkRule(false); // write rule without rspfile support
- this->WriteLinkRule(true); // write rule with rspfile support
+ } else {
+ // If this target has cuda language link inputs, and we need to do
+ // device linking
+ this->WriteDeviceLinkStatement();
this->WriteLinkStatement();
- }
+ }
}
void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
@@ -101,106 +103,230 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream());
this->GetRulesFileStream()
<< "# Rules for each languages for "
- << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
- << " target "
- << this->GetTargetName()
- << "\n\n";
+ << cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
+ << " target " << this->GetTargetName() << "\n\n";
#endif
- std::set<cmStdString> languages;
- this->GetTarget()->GetLanguages(languages);
- for(std::set<cmStdString>::const_iterator l = languages.begin();
- l != languages.end();
- ++l)
+ // Write rules for languages compiled in this target.
+ std::set<std::string> languages;
+ 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();
+ if (!lang.empty()) {
+ languages.insert(lang);
+ }
+ }
+ for (std::set<std::string>::const_iterator l = languages.begin();
+ l != languages.end(); ++l) {
this->WriteLanguageRules(*l);
+ }
}
-const char *cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
+const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
{
- switch (this->GetTarget()->GetType()) {
- case cmTarget::STATIC_LIBRARY:
+ switch (this->GetGeneratorTarget()->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
return "static library";
- case cmTarget::SHARED_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
return "shared library";
- case cmTarget::MODULE_LIBRARY:
- if (this->GetTarget()->IsCFBundleOnApple())
+ case cmStateEnums::MODULE_LIBRARY:
+ if (this->GetGeneratorTarget()->IsCFBundleOnApple()) {
return "CFBundle shared module";
- else
+ } else {
return "shared module";
- case cmTarget::EXECUTABLE:
+ }
+ case cmStateEnums::EXECUTABLE:
return "executable";
default:
- return 0;
+ return CM_NULLPTR;
}
}
-std::string
-cmNinjaNormalTargetGenerator
-::LanguageLinkerRule() const
+std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const
{
- return std::string(this->TargetLinkLanguage)
- + "_"
- + cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
- + "_LINKER";
+ return this->TargetLinkLanguage + "_" +
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
+ "_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());
+}
+
+struct cmNinjaRemoveNoOpCommands
+{
+ bool operator()(std::string const& cmd)
+ {
+ return cmd.empty() || cmd[0] == ':';
+ }
+};
+
+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)) {
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+
+ vars.Language = "CUDA";
+
+ std::string responseFlag;
+ if (!useResponseFile) {
+ vars.Objects = "$in";
+ vars.LinkLibraries = "$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;
+
+ // build response file content
+ if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
+ rspcontent = "$in";
+ } else {
+ rspcontent = "$in_newline";
+ }
+ rspcontent += " $LINK_LIBRARIES";
+ vars.Objects = responseFlag.c_str();
+ vars.LinkLibraries = "";
+ }
+
+ vars.ObjectDir = "$OBJECT_DIR";
+
+ vars.Target = "$TARGET_FILE";
+
+ vars.SONameFlag = "$SONAME_FLAG";
+ vars.TargetSOName = "$SONAME";
+ vars.TargetPDB = "$TARGET_PDB";
+ vars.TargetCompilePDB = "$TARGET_COMPILE_PDB";
+
+ vars.Flags = "$FLAGS";
+ vars.LinkFlags = "$LINK_FLAGS";
+ vars.Manifests = "$MANIFESTS";
+
+ std::string langFlags;
+ if (targetType != cmStateEnums::EXECUTABLE) {
+ langFlags += "$LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS";
+ vars.LanguageCompileFlags = langFlags.c_str();
+ }
+
+ std::string launcher;
+ const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+ this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ CM_AUTO_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;
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+ *i, vars);
+ }
+
+ // If there is no ranlib the command will be ":". Skip it.
+ cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());
+
+ std::string linkCmd =
+ 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);
+ }
}
-void
-cmNinjaNormalTargetGenerator
-::WriteLinkRule(bool useResponseFile)
+void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
{
- cmTarget::TargetType targetType = this->GetTarget()->GetType();
+ cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType();
std::string ruleName = this->LanguageLinkerRule();
- if (useResponseFile)
- ruleName += "_RSP_FILE";
// Select whether to use a response file for objects.
std::string rspfile;
std::string rspcontent;
if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
- cmLocalGenerator::RuleVariables vars;
- vars.RuleLauncher = "RULE_LAUNCH_LINK";
- vars.CMTarget = this->GetTarget();
- vars.Language = this->TargetLinkLanguage;
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+
+ vars.Language = this->TargetLinkLanguage.c_str();
std::string responseFlag;
if (!useResponseFile) {
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.c_str());
- if(flag) {
- responseFlag = flag;
- } else {
- responseFlag = "@";
- }
- rspfile = "$RSP_FILE";
- responseFlag += rspfile;
-
- // build response file content
- std::string linkOptionVar = cmakeVarLang;
- linkOptionVar += "_COMPILER_LINKER_OPTION_FLAG_";
- linkOptionVar += cmTarget::GetTargetTypeName(targetType);
- const std::string linkOption =
- GetMakefile()->GetSafeDefinition(linkOptionVar.c_str());
- rspcontent = "$in_newline "+linkOption+" $LINK_PATH $LINK_LIBRARIES";
- vars.Objects = responseFlag.c_str();
- vars.LinkLibraries = "";
+ 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;
+
+ // build response file content
+ if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
+ rspcontent = "$in";
+ } else {
+ rspcontent = "$in_newline";
+ }
+ rspcontent += " $LINK_PATH $LINK_LIBRARIES";
+ vars.Objects = responseFlag.c_str();
+ vars.LinkLibraries = "";
}
vars.ObjectDir = "$OBJECT_DIR";
- // TODO:
- // Makefile generator expands <TARGET> to the plain target name
- // with suffix. $out expands to a relative path. This difference
- // could make trouble when switching to Ninja generator. Maybe
- // using TARGET_NAME and RuleVariables::TargetName is a fix.
- vars.Target = "$out";
+ vars.Target = "$TARGET_FILE";
vars.SONameFlag = "$SONAME_FLAG";
vars.TargetSOName = "$SONAME";
@@ -211,220 +337,468 @@ cmNinjaNormalTargetGenerator
std::string targetVersionMajor;
std::string targetVersionMinor;
{
- cmOStringStream majorStream;
- cmOStringStream minorStream;
- int major;
- int minor;
- this->GetTarget()->GetTargetVersion(major, minor);
- majorStream << major;
- minorStream << minor;
- targetVersionMajor = majorStream.str();
- targetVersionMinor = minorStream.str();
+ std::ostringstream majorStream;
+ std::ostringstream minorStream;
+ int major;
+ int minor;
+ this->GetGeneratorTarget()->GetTargetVersion(major, minor);
+ majorStream << major;
+ minorStream << minor;
+ targetVersionMajor = majorStream.str();
+ targetVersionMinor = minorStream.str();
}
vars.TargetVersionMajor = targetVersionMajor.c_str();
vars.TargetVersionMinor = targetVersionMinor.c_str();
vars.Flags = "$FLAGS";
vars.LinkFlags = "$LINK_FLAGS";
+ vars.Manifests = "$MANIFESTS";
std::string langFlags;
- if (targetType != cmTarget::EXECUTABLE) {
- this->GetLocalGenerator()->AddLanguageFlags(langFlags,
- this->TargetLinkLanguage,
- this->GetConfigName());
- langFlags += " $ARCH_FLAGS";
+ if (targetType != cmStateEnums::EXECUTABLE) {
+ langFlags += "$LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS";
vars.LanguageCompileFlags = langFlags.c_str();
}
+ std::string launcher;
+ const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+ this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ CM_AUTO_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)
- {
- this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
- }
+ for (std::vector<std::string>::iterator i = linkCmds.begin();
+ i != linkCmds.end(); ++i) {
+ *i = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+ *i, 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);
// Write the linker rule with response file if needed.
- cmOStringStream comment;
+ std::ostringstream comment;
comment << "Rule for linking " << this->TargetLinkLanguage << " "
<< this->GetVisibleTypeName() << ".";
- cmOStringStream description;
+ std::ostringstream description;
description << "Linking " << this->TargetLinkLanguage << " "
- << this->GetVisibleTypeName() << " $out";
- this->GetGlobalGenerator()->AddRule(ruleName,
- linkCmd,
- description.str(),
+ << this->GetVisibleTypeName() << " $TARGET_FILE";
+ this->GetGlobalGenerator()->AddRule(ruleName, linkCmd, description.str(),
comment.str(),
/*depfile*/ "",
- rspfile,
- rspcontent);
+ /*deptype*/ "", rspfile, rspcontent,
+ /*restat*/ "$RESTAT",
+ /*generator*/ false);
}
if (this->TargetNameOut != this->TargetNameReal &&
- !this->GetTarget()->IsFrameworkOnApple()) {
+ !this->GetGeneratorTarget()->IsFrameworkOnApple()) {
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
- this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
- cmLocalGenerator::SHELL);
- if (targetType == cmTarget::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.");
- 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.");
+ 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);
+ } 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);
+ }
}
}
-std::vector<std::string>
-cmNinjaNormalTargetGenerator
-::ComputeLinkCmd()
+std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
{
std::vector<std::string> linkCmds;
- cmTarget::TargetType targetType = this->GetTarget()->GetType();
- switch (targetType) {
- case cmTarget::STATIC_LIBRARY: {
- // Check if you have a non archive way to create the static library.
- {
- std::string linkCmdVar = "CMAKE_";
- linkCmdVar += this->TargetLinkLanguage;
- linkCmdVar += "_CREATE_STATIC_LIBRARY";
- if (const char *linkCmd =
- this->GetMakefile()->GetDefinition(linkCmdVar.c_str()))
- {
- cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
- return linkCmds;
- }
- }
- // We have archive link commands set. First, delete the existing archive.
- std::string cmakeCommand =
- this->GetLocalGenerator()->ConvertToOutputFormat(
- this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
- cmLocalGenerator::SHELL);
- linkCmds.push_back(cmakeCommand + " -E remove $out");
+ // this target requires separable cuda compilation
+ // now build the correct command depending on if the target is
+ // an executable or a dynamic library.
+ std::string linkCmd;
+ switch (this->GetGeneratorTarget()->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY: {
+ const std::string cudaLinkCmd(
+ this->GetMakefile()->GetDefinition("CMAKE_CUDA_DEVICE_LINK_LIBRARY"));
+ cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds);
+ } break;
+ case cmStateEnums::EXECUTABLE: {
+ const std::string cudaLinkCmd(this->GetMakefile()->GetDefinition(
+ "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE"));
+ cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds);
+ } break;
+ default:
+ break;
+ }
+ return linkCmds;
+}
- // TODO: Use ARCHIVE_APPEND for archives over a certain size.
- {
- std::string linkCmdVar = "CMAKE_";
- linkCmdVar += this->TargetLinkLanguage;
- linkCmdVar += "_ARCHIVE_CREATE";
- const char *linkCmd =
- this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
- cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
- }
- {
- std::string linkCmdVar = "CMAKE_";
- linkCmdVar += this->TargetLinkLanguage;
- linkCmdVar += "_ARCHIVE_FINISH";
- const char *linkCmd =
- this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
+{
+ std::vector<std::string> linkCmds;
+ cmMakefile* mf = this->GetMakefile();
+ {
+ // If we have a rule variable prefer it. In the case of static libraries
+ // this occurs when things like IPO is enabled, and we need to use the
+ // CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead.
+ std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable(
+ this->TargetLinkLanguage, this->GetConfigName());
+ const char* linkCmd = mf->GetDefinition(linkCmdVar);
+ if (linkCmd) {
cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
+ std::string cmakeCommand =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
+ cmakeCommand += " -E __run_iwyu --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);
}
return linkCmds;
}
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::EXECUTABLE: {
- std::string linkCmdVar = "CMAKE_";
- linkCmdVar += this->TargetLinkLanguage;
- switch (targetType) {
- case cmTarget::SHARED_LIBRARY:
- linkCmdVar += "_CREATE_SHARED_LIBRARY";
- break;
- case cmTarget::MODULE_LIBRARY:
- linkCmdVar += "_CREATE_SHARED_MODULE";
- break;
- case cmTarget::EXECUTABLE:
- linkCmdVar += "_LINK_EXECUTABLE";
- break;
- default:
- assert(0 && "Unexpected target type");
+ }
+ switch (this->GetGeneratorTarget()->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY: {
+ // We have archive link commands set. First, delete the existing archive.
+ {
+ std::string cmakeCommand =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
+ linkCmds.push_back(cmakeCommand + " -E remove $TARGET_FILE");
}
+ // TODO: Use ARCHIVE_APPEND for archives over a certain size.
+ {
+ std::string linkCmdVar = "CMAKE_";
+ linkCmdVar += this->TargetLinkLanguage;
+ linkCmdVar += "_ARCHIVE_CREATE";
- const char *linkCmd =
- this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
- cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+ linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
+
+ const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
+ cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ }
+ {
+ std::string linkCmdVar = "CMAKE_";
+ linkCmdVar += this->TargetLinkLanguage;
+ linkCmdVar += "_ARCHIVE_FINISH";
+
+ linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+ linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
+
+ const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
+ cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ }
return linkCmds;
}
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::EXECUTABLE:
+ break;
default:
- assert(0 && "Unexpected target type");
+ assert(false && "Unexpected target type");
}
return std::vector<std::string>();
}
-void cmNinjaNormalTargetGenerator::WriteLinkStatement()
+void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
{
- cmTarget::TargetType targetType = this->GetTarget()->GetType();
+ 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;
+ }
+
+ if (!(shouldHaveDeviceLinking && hasCUDA)) {
+ return;
+ }
+
+ // Now we can do device linking
+
+ // 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 =
+ this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+
+ std::string const cfgName = this->GetConfigName();
+ std::string const targetOutputReal = ConvertToNinjaPath(
+ genTarget.ObjectDirectory + "cmake_device_link" + objExt);
+
+ std::string const targetOutputImplib = ConvertToNinjaPath(
+ genTarget.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
+
+ this->DeviceLinkObject = targetOutputReal;
+
+ // Write comments.
+ cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
+ 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;
- std::string targetOutput = ConvertToNinjaPath(
- this->GetTarget()->GetFullPath(this->GetConfigName()).c_str());
+ cmNinjaDeps emptyDeps;
+ cmNinjaVars vars;
+
+ // Compute outputs.
+ cmNinjaDeps outputs;
+ outputs.push_back(targetOutputReal);
+ // Compute specific libraries to link with.
+ cmNinjaDeps explicitDeps = this->GetObjects();
+ cmNinjaDeps implicitDeps = this->ComputeLinkDeps();
+
+ std::string frameworkPath;
+ std::string linkPath;
+
+ std::string createRule = genTarget.GetCreateRuleVariable(
+ this->TargetLinkLanguage, this->GetConfigName());
+ const bool useWatcomQuote =
+ this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE");
+ cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
+
+ vars["TARGET_FILE"] =
+ localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL);
+
+ CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ new cmNinjaLinkLineDeviceComputer(
+ this->GetLocalGenerator(),
+ this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(),
+ this->GetGlobalGenerator()));
+ linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+
+ localGen.GetTargetFlags(
+ linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
+ vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);
+
+ this->addPoolNinjaVariable("JOB_POOL_LINK", &genTarget, vars);
+
+ vars["LINK_FLAGS"] =
+ cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);
+
+ vars["MANIFESTS"] = this->GetManifests();
+
+ vars["LINK_PATH"] = frameworkPath + linkPath;
+
+ // Compute architecture specific link flags. Yes, these go into a different
+ // variable for executables, probably due to a mistake made when duplicating
+ // code between the Makefile executable and library generators.
+ if (targetType == cmStateEnums::EXECUTABLE) {
+ std::string t = vars["FLAGS"];
+ localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
+ vars["FLAGS"] = t;
+ } else {
+ std::string t = vars["ARCH_FLAGS"];
+ localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
+ vars["ARCH_FLAGS"] = t;
+ t = "";
+ localGen.AddLanguageFlagsForLinking(t, &genTarget, cudaLinkLanguage,
+ cfgName);
+ vars["LANGUAGE_COMPILE_FLAGS"] = t;
+ }
+ if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
+ vars["SONAME_FLAG"] =
+ this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage);
+ vars["SONAME"] = this->TargetNameSO;
+ if (targetType == cmStateEnums::SHARED_LIBRARY) {
+ std::string install_dir =
+ this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
+ if (!install_dir.empty()) {
+ vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
+ install_dir, cmOutputConverter::SHELL);
+ }
+ }
+ }
+
+ cmNinjaDeps byproducts;
+
+ if (!this->TargetNameImport.empty()) {
+ const std::string impLibPath = localGen.ConvertToOutputFormat(
+ targetOutputImplib, cmOutputConverter::SHELL);
+ vars["TARGET_IMPLIB"] = impLibPath;
+ EnsureParentDirectoryExists(impLibPath);
+ if (genTarget.HasImportLibrary()) {
+ byproducts.push_back(targetOutputImplib);
+ }
+ }
+
+ const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
+ vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
+ EnsureDirectoryExists(objPath);
+
+ this->SetMsvcTargetPdbVariable(vars);
+
+ if (this->GetGlobalGenerator()->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(), '\\', '/');
+ std::string& link_path = vars["LINK_PATH"];
+ 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());
+
+ const std::string rspfile =
+ std::string(cmake::GetCMakeFilesDirectoryPostSlash()) +
+ genTarget.GetName() + ".rsp";
+
+ // Gather order-only dependencies.
+ cmNinjaDeps orderOnlyDeps;
+ this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
+ 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);
+ this->WriteDeviceLinkRule(usedResponseFile);
+}
+
+void cmNinjaNormalTargetGenerator::WriteLinkStatement()
+{
+ cmGeneratorTarget& gt = *this->GetGeneratorTarget();
+ const std::string cfgName = this->GetConfigName();
+ std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
std::string targetOutputReal = ConvertToNinjaPath(
- this->GetTarget()->GetFullPath(this->GetConfigName(),
- /*implib=*/false,
- /*realpath=*/true).c_str());
+ gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
+ /*realname=*/true));
std::string targetOutputImplib = ConvertToNinjaPath(
- this->GetTarget()->GetFullPath(this->GetConfigName(),
- /*implib=*/true).c_str());
+ gt.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
- if (this->GetTarget()->IsAppBundleOnApple())
- {
+ if (gt.IsAppBundleOnApple()) {
// Create the app bundle
- std::string outpath =
- this->GetTarget()->GetDirectory(this->GetConfigName());
+ std::string outpath = gt.GetDirectory(cfgName);
this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);
// Calculate the output path
targetOutput = outpath;
targetOutput += "/";
targetOutput += this->TargetNameOut;
- targetOutput = this->ConvertToNinjaPath(targetOutput.c_str());
+ targetOutput = this->ConvertToNinjaPath(targetOutput);
targetOutputReal = outpath;
targetOutputReal += "/";
targetOutputReal += this->TargetNameReal;
- targetOutputReal = this->ConvertToNinjaPath(targetOutputReal.c_str());
- }
- else if (this->GetTarget()->IsFrameworkOnApple())
- {
+ targetOutputReal = this->ConvertToNinjaPath(targetOutputReal);
+ } else if (gt.IsFrameworkOnApple()) {
// Create the library framework.
- std::string outpath =
- this->GetTarget()->GetDirectory(this->GetConfigName());
- this->OSXBundleGenerator->CreateFramework(this->TargetNameOut, outpath);
- }
- else if(this->GetTarget()->IsCFBundleOnApple())
- {
+ this->OSXBundleGenerator->CreateFramework(this->TargetNameOut,
+ gt.GetDirectory(cfgName));
+ } else if (gt.IsCFBundleOnApple()) {
// Create the core foundation bundle.
- std::string outpath =
- this->GetTarget()->GetDirectory(this->GetConfigName());
- this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut, outpath);
- }
+ this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut,
+ gt.GetDirectory(cfgName));
+ }
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
- this->GetBuildFileStream()
- << "# Link build statements for "
- << cmTarget::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;
// Compute the comment.
- cmOStringStream comment;
+ std::ostringstream comment;
comment << "Link the " << this->GetVisibleTypeName() << " "
<< targetOutputReal;
@@ -436,184 +810,257 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
cmNinjaDeps explicitDeps = this->GetObjects();
cmNinjaDeps implicitDeps = this->ComputeLinkDeps();
+ if (!this->DeviceLinkObject.empty()) {
+ explicitDeps.push_back(this->DeviceLinkObject);
+ }
+
+ cmMakefile* mf = this->GetMakefile();
+
std::string frameworkPath;
std::string linkPath;
- this->GetLocalGenerator()->GetTargetFlags(vars["LINK_LIBRARIES"],
- vars["FLAGS"],
- vars["LINK_FLAGS"],
- frameworkPath,
- linkPath,
- this->GetGeneratorTarget());
+ cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
+
+ std::string createRule = genTarget.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(
+ 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);
+
+ // Add OS X version flags, if any.
+ if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage,
+ "COMPATIBILITY", true);
+ this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage,
+ "CURRENT", false);
+ }
+
+ this->addPoolNinjaVariable("JOB_POOL_LINK", &gt, vars);
+
+ this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]);
+ vars["LINK_FLAGS"] =
+ cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);
- this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]);
- vars["LINK_FLAGS"] = cmGlobalNinjaGenerator
- ::EncodeLiteral(vars["LINK_FLAGS"]);
+ vars["MANIFESTS"] = this->GetManifests();
vars["LINK_PATH"] = frameworkPath + linkPath;
+ std::string lwyuFlags;
+ if (genTarget.GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
+ lwyuFlags = " -Wl,--no-as-needed";
+ }
// Compute architecture specific link flags. Yes, these go into a different
// variable for executables, probably due to a mistake made when duplicating
// code between the Makefile executable and library generators.
- std::string flags = (targetType == cmTarget::EXECUTABLE
- ? vars["FLAGS"]
- : vars["ARCH_FLAGS"]);
- this->GetLocalGenerator()->AddArchitectureFlags(flags,
- this->GetGeneratorTarget(),
- this->TargetLinkLanguage,
- this->GetConfigName());
- if (targetType == cmTarget::EXECUTABLE) {
- vars["FLAGS"] = flags;
+ if (targetType == cmStateEnums::EXECUTABLE) {
+ std::string t = vars["FLAGS"];
+ localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
+ t += lwyuFlags;
+ vars["FLAGS"] = t;
} else {
- vars["ARCH_FLAGS"] = flags;
+ std::string t = vars["ARCH_FLAGS"];
+ localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
+ vars["ARCH_FLAGS"] = t;
+ t = "";
+ t += lwyuFlags;
+ localGen.AddLanguageFlagsForLinking(t, &genTarget, TargetLinkLanguage,
+ cfgName);
+ vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
- if (this->GetTarget()->HasSOName(this->GetConfigName())) {
- vars["SONAME_FLAG"] =
- this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage);
+ if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
+ vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
vars["SONAME"] = this->TargetNameSO;
- if (targetType == cmTarget::SHARED_LIBRARY) {
- std::string install_name_dir = this->GetTarget()
- ->GetInstallNameDirForBuildTree(this->GetConfigName());
-
- if (!install_name_dir.empty()) {
- vars["INSTALLNAME_DIR"] =
- this->GetLocalGenerator()->Convert(install_name_dir.c_str(),
- cmLocalGenerator::NONE,
- cmLocalGenerator::SHELL, false);
+ if (targetType == cmStateEnums::SHARED_LIBRARY) {
+ std::string install_dir =
+ this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
+ if (!install_dir.empty()) {
+ vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
+ install_dir, cmOutputConverter::SHELL);
}
}
}
+ cmNinjaDeps byproducts;
+
if (!this->TargetNameImport.empty()) {
- const std::string impLibPath = this->GetLocalGenerator()
- ->ConvertToOutputFormat(targetOutputImplib.c_str(),
- cmLocalGenerator::SHELL);
+ const std::string impLibPath = localGen.ConvertToOutputFormat(
+ targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
EnsureParentDirectoryExists(impLibPath);
+ if (genTarget.HasImportLibrary()) {
+ byproducts.push_back(targetOutputImplib);
+ }
}
- cmMakefile* mf = this->GetMakefile();
- if (!this->SetMsvcTargetPdbVariable(vars))
- {
+ if (!this->SetMsvcTargetPdbVariable(vars)) {
// It is common to place debug symbols at a specific place,
// so we need a plain target name in the rule available.
std::string prefix;
std::string base;
std::string suffix;
- this->GetTarget()->GetFullNameComponents(prefix, base, suffix);
+ this->GetGeneratorTarget()->GetFullNameComponents(prefix, base, suffix);
std::string dbg_suffix = ".dbg";
// TODO: Where to document?
- if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX"))
+ if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) {
dbg_suffix = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX");
- vars["TARGET_PDB"] = base + suffix + dbg_suffix;
}
+ vars["TARGET_PDB"] = base + suffix + dbg_suffix;
+ }
- if (mf->IsOn("CMAKE_COMPILER_IS_MINGW"))
- {
- const std::string objPath = GetTarget()->GetSupportDirectory();
- vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath.c_str());
- EnsureDirectoryExists(objPath);
+ const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
+ vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
+ EnsureDirectoryExists(objPath);
+
+ if (this->GetGlobalGenerator()->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(), '\\', '/');
- }
+ std::string& link_path = vars["LINK_PATH"];
+ std::replace(link_path.begin(), link_path.end(), '\\', '/');
+ }
- std::vector<cmCustomCommand> *cmdLists[3] = {
- &this->GetTarget()->GetPreBuildCommands(),
- &this->GetTarget()->GetPreLinkCommands(),
- &this->GetTarget()->GetPostBuildCommands()
+ const std::vector<cmCustomCommand>* cmdLists[3] = {
+ &gt.GetPreBuildCommands(), &gt.GetPreLinkCommands(),
+ &gt.GetPostBuildCommands()
};
std::vector<std::string> preLinkCmdLines, postBuildCmdLines;
- std::vector<std::string> *cmdLineLists[3] = {
- &preLinkCmdLines,
- &preLinkCmdLines,
- &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();
+ for (std::vector<cmCustomCommand>::const_iterator ci =
+ cmdLists[i]->begin();
ci != cmdLists[i]->end(); ++ci) {
- this->GetLocalGenerator()->AppendCustomCommandLines(&*ci,
- *cmdLineLists[i]);
+ 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());
}
}
- // If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
+ // maybe create .def file from list of objects
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ 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 obj_list_file = mdi->DefFile + ".objs";
+ cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
+ obj_list_file, cmOutputConverter::SHELL);
+ preLinkCmdLines.push_back(cmd);
+
+ // create a list of obj files for the -E __create_def to read
+ cmGeneratedFileStream fout(obj_list_file.c_str());
+
+ 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::vector<cmSourceFile const*>::const_iterator i =
+ mdi->Sources.begin();
+ i != mdi->Sources.end(); ++i) {
+ fout << (*i)->GetFullPath() << "\n";
+ }
+ }
+ // If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR
+ // for
// the link commands.
if (!preLinkCmdLines.empty()) {
- const std::string homeOutDir = this->GetLocalGenerator()
- ->ConvertToOutputFormat(this->GetMakefile()->GetHomeOutputDirectory(),
- cmLocalGenerator::SHELL);
+ const std::string homeOutDir = localGen.ConvertToOutputFormat(
+ localGen.GetBinaryDirectory(), cmOutputConverter::SHELL);
preLinkCmdLines.push_back("cd " + homeOutDir);
}
- vars["PRE_LINK"] =
- this->GetLocalGenerator()->BuildCommandLine(preLinkCmdLines);
- std::string postBuildCmdLine =
- this->GetLocalGenerator()->BuildCommandLine(postBuildCmdLines);
+ vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
+ std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines);
cmNinjaVars symlinkVars;
- if (targetOutput == targetOutputReal) {
+ bool const symlinkNeeded =
+ (targetOutput != targetOutputReal && !gt.IsFrameworkOnApple());
+ if (!symlinkNeeded) {
vars["POST_BUILD"] = postBuildCmdLine;
} else {
- vars["POST_BUILD"] = ":";
+ vars["POST_BUILD"] = cmGlobalNinjaGenerator::SHELL_NOOP;
symlinkVars["POST_BUILD"] = postBuildCmdLine;
}
-
- int linkRuleLength = this->GetGlobalGenerator()->
- GetRuleCmdLength(this->LanguageLinkerRule());
-
- int commandLineLengthLimit = 1;
- const char* forceRspFile = "CMAKE_NINJA_FORCE_RESPONSE_FILE";
- if (!this->GetMakefile()->IsDefinitionSet(forceRspFile) &&
- cmSystemTools::GetEnv(forceRspFile) == 0) {
-#ifdef _WIN32
- commandLineLengthLimit = 8000 - linkRuleLength;
-#elif defined(__linux) || defined(__APPLE__)
- // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac
- commandLineLengthLimit = ((int)sysconf(_SC_ARG_MAX))-linkRuleLength-1000;
-#else
- (void)linkRuleLength;
- commandLineLengthLimit = -1;
-#endif
+ cmGlobalNinjaGenerator& globalGen = *this->GetGlobalGenerator();
+
+ bool const lang_supports_response =
+ !(this->TargetLinkLanguage == "RC" || this->TargetLinkLanguage == "CUDA");
+ int commandLineLengthLimit = -1;
+ if (!lang_supports_response || !this->ForceResponseFile()) {
+ commandLineLengthLimit =
+ static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
+ globalGen.GetRuleCmdLength(this->LanguageLinkerRule());
}
- //Get the global generator as we are going to be call WriteBuild numerous
- //times in the following section
- cmGlobalNinjaGenerator* globalGenerator = this->GetGlobalGenerator();
+ const std::string rspfile =
+ std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + gt.GetName() +
+ ".rsp";
+
+ // Gather order-only dependencies.
+ cmNinjaDeps orderOnlyDeps;
+ this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
+ orderOnlyDeps);
+ // Ninja should restat after linking if and only if there are byproducts.
+ vars["RESTAT"] = byproducts.empty() ? "" : "1";
- const std::string rspfile = std::string
- (cmake::GetCMakeFilesDirectoryPostSlash()) +
- this->GetTarget()->GetName() + ".rsp";
+ for (cmNinjaDeps::const_iterator oi = byproducts.begin(),
+ oe = byproducts.end();
+ oi != oe; ++oi) {
+ this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+ outputs.push_back(*oi);
+ }
// Write the build statement for this target.
- globalGenerator->WriteBuild(this->GetBuildFileStream(),
- comment.str(),
- this->LanguageLinkerRule(),
- outputs,
- explicitDeps,
- implicitDeps,
- emptyDeps,
- vars,
- rspfile,
- commandLineLengthLimit);
-
- if (targetOutput != targetOutputReal &&
- !this->GetTarget()->IsFrameworkOnApple()) {
- if (targetType == cmTarget::EXECUTABLE) {
- globalGenerator->WriteBuild(this->GetBuildFileStream(),
- "Create executable symlink " + targetOutput,
- "CMAKE_SYMLINK_EXECUTABLE",
- cmNinjaDeps(1, targetOutput),
- cmNinjaDeps(1, targetOutputReal),
- emptyDeps,
- emptyDeps,
- symlinkVars);
+ bool usedResponseFile = false;
+ globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(),
+ this->LanguageLinkerRule(), outputs,
+ /*implicitOuts=*/cmNinjaDeps(), explicitDeps,
+ implicitDeps, orderOnlyDeps, vars, rspfile,
+ 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);
} else {
cmNinjaDeps symlinks;
- const std::string soName = this->GetTargetFilePath(this->TargetNameSO);
+ std::string const soName =
+ this->ConvertToNinjaPath(this->GetTargetFilePath(this->TargetNameSO));
// If one link has to be created.
if (targetOutputReal == soName || targetOutput == soName) {
symlinkVars["SONAME"] = soName;
@@ -622,47 +1069,31 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
symlinks.push_back(soName);
}
symlinks.push_back(targetOutput);
- globalGenerator->WriteBuild(this->GetBuildFileStream(),
- "Create library symlink " + targetOutput,
- "CMAKE_SYMLINK_LIBRARY",
- symlinks,
- cmNinjaDeps(1, targetOutputReal),
- emptyDeps,
- emptyDeps,
- symlinkVars);
+ globalGen.WriteBuild(
+ this->GetBuildFileStream(), "Create library symlink " + targetOutput,
+ "CMAKE_SYMLINK_LIBRARY", symlinks,
+ /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal),
+ emptyDeps, emptyDeps, symlinkVars);
}
}
- if (!this->TargetNameImport.empty()) {
- // Since using multiple outputs would mess up the $out variable, use an
- // alias for the import library.
- globalGenerator->WritePhonyBuild(this->GetBuildFileStream(),
- "Alias for import library.",
- cmNinjaDeps(1, targetOutputImplib),
- cmNinjaDeps(1, targetOutputReal));
- }
-
// Add aliases for the file name and the target name.
- globalGenerator->AddTargetAlias(this->TargetNameOut,
- this->GetTarget());
- globalGenerator->AddTargetAlias(this->GetTargetName(),
- this->GetTarget());
+ globalGen.AddTargetAlias(this->TargetNameOut, &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->GetTarget(), outputs);
+ this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
+ outputs);
cmNinjaDeps depends = this->GetObjects();
- this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
- "Object library "
- + this->GetTargetName(),
- outputs,
- depends);
+ this->GetGlobalGenerator()->WritePhonyBuild(
+ this->GetBuildFileStream(), "Object library " + this->GetTargetName(),
+ outputs, depends);
// Add aliases for the target name.
this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
- this->GetTarget());
+ this->GetGeneratorTarget());
}
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index 284804b08..677b1c666 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -1,43 +1,42 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmNinjaNormalTargetGenerator_h
-# define cmNinjaNormalTargetGenerator_h
+#define cmNinjaNormalTargetGenerator_h
-# include "cmNinjaTargetGenerator.h"
-# include "cmNinjaTypes.h"
-# include "cmStandardIncludes.h"
+#include "cmConfigure.h"
-# include <set>
+#include "cmNinjaTargetGenerator.h"
-class cmSourceFile;
-class cmOSXBundleGenerator;
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator
{
public:
- cmNinjaNormalTargetGenerator(cmTarget* target);
- ~cmNinjaNormalTargetGenerator();
+ cmNinjaNormalTargetGenerator(cmGeneratorTarget* target);
+ ~cmNinjaNormalTargetGenerator() CM_OVERRIDE;
- void Generate();
+ void Generate() CM_OVERRIDE;
private:
std::string LanguageLinkerRule() const;
+ std::string LanguageLinkerDeviceRule() const;
+
const char* GetVisibleTypeName() const;
void WriteLanguagesRules();
+
void WriteLinkRule(bool useResponseFile);
+ void WriteDeviceLinkRule(bool useResponseFile);
+
void WriteLinkStatement();
+ void WriteDeviceLinkStatement();
+
void WriteObjectLibStatement();
+
std::vector<std::string> ComputeLinkCmd();
+ std::vector<std::string> ComputeDeviceLinkCmd();
private:
// Target name info.
@@ -46,7 +45,8 @@ private:
std::string TargetNameReal;
std::string TargetNameImport;
std::string TargetNamePDB;
- const char *TargetLinkLanguage;
+ std::string TargetLinkLanguage;
+ std::string DeviceLinkObject;
};
#endif // ! cmNinjaNormalTargetGenerator_h
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 9c8b4810b..d38dbcb09 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -1,73 +1,65 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNinjaTargetGenerator.h"
-#include "cmGlobalNinjaGenerator.h"
-#include "cmLocalNinjaGenerator.h"
+
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <string.h>
+
+#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmMakefile.h"
#include "cmNinjaNormalTargetGenerator.h"
#include "cmNinjaUtilityTargetGenerator.h"
-#include "cmSystemTools.h"
-#include "cmMakefile.h"
-#include "cmComputeLinkInformation.h"
+#include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmCustomCommandGenerator.h"
-
-#include <algorithm>
-
-cmNinjaTargetGenerator *
-cmNinjaTargetGenerator::New(cmTarget* target)
-{
- switch (target->GetType())
- {
- case cmTarget::EXECUTABLE:
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- case cmTarget::OBJECT_LIBRARY:
- return new cmNinjaNormalTargetGenerator(target);
-
- case cmTarget::UTILITY:
- return new cmNinjaUtilityTargetGenerator(target);;
-
- case cmTarget::GLOBAL_TARGET: {
- // We only want to process global targets that live in the home
- // (i.e. top-level) directory. CMake creates copies of these targets
- // in every directory, which we don't need.
- cmMakefile *mf = target->GetMakefile();
- if (strcmp(mf->GetStartDirectory(), mf->GetHomeDirectory()) == 0)
- return new cmNinjaUtilityTargetGenerator(target);
- // else fallthrough
- }
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
- default:
- return 0;
- }
+cmNinjaTargetGenerator* cmNinjaTargetGenerator::New(cmGeneratorTarget* target)
+{
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ return new cmNinjaNormalTargetGenerator(target);
+
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ return new cmNinjaUtilityTargetGenerator(target);
+
+ default:
+ return CM_NULLPTR;
+ }
}
-cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target)
- :
- MacOSXContentGenerator(0),
- OSXBundleGenerator(0),
- MacContentFolders(),
- Target(target),
- Makefile(target->GetMakefile()),
- LocalGenerator(
- static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())),
- Objects()
+cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target)
+ : cmCommonTargetGenerator(target)
+ , MacOSXContentGenerator(CM_NULLPTR)
+ , OSXBundleGenerator(CM_NULLPTR)
+ , MacContentFolders()
+ , LocalGenerator(
+ static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator()))
+ , Objects()
{
- this->GeneratorTarget =
- this->GetGlobalGenerator()->GetGeneratorTarget(target);
MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
}
@@ -91,133 +83,112 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const
return this->LocalGenerator->GetGlobalNinjaGenerator();
}
-const char* cmNinjaTargetGenerator::GetConfigName() const
+std::string cmNinjaTargetGenerator::LanguageCompilerRule(
+ const std::string& lang) const
{
- return this->LocalGenerator->GetConfigName();
+ return lang + "_COMPILER__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName());
}
-// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
-const char* cmNinjaTargetGenerator::GetFeature(const char* feature)
+std::string cmNinjaTargetGenerator::LanguagePreprocessRule(
+ std::string const& lang) const
{
- return this->Target->GetFeature(feature, this->GetConfigName());
+ return lang + "_PREPROCESS__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName());
}
-// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
-bool cmNinjaTargetGenerator::GetFeatureAsBool(const char* feature)
+bool cmNinjaTargetGenerator::NeedExplicitPreprocessing(
+ std::string const& lang) const
{
- return cmSystemTools::IsOn(this->GetFeature(feature));
+ return lang == "Fortran";
}
-// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
-void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags,
- const char* lang)
+std::string cmNinjaTargetGenerator::LanguageDyndepRule(
+ const std::string& lang) const
{
- // Add language-specific flags.
- this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName());
+ return lang + "_DYNDEP__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName());
+}
- if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
- {
- this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
- }
+bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const
+{
+ return lang == "Fortran";
+}
+
+std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget()
+{
+ return "cmake_object_order_depends_target_" + this->GetTargetName();
}
// TODO: Most of the code is picked up from
// void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink),
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
// Refactor it.
-std::string
-cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
- const std::string& language)
+std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
+ cmSourceFile const* source, const std::string& language)
{
- std::string flags;
-
- this->AddFeatureFlags(flags, language.c_str());
+ std::string flags = this->GetFlags(language);
- this->GetLocalGenerator()->AddArchitectureFlags(flags,
- this->GeneratorTarget,
- language.c_str(),
- this->GetConfigName());
-
- // TODO: Fortran support.
- // // Fortran-specific flags computed for this target.
- // if(*l == "Fortran")
- // {
- // this->AddFortranFlags(flags);
- // }
+ // Add Fortran format flags.
+ if (language == "Fortran") {
+ this->AppendFortranFormatFlags(flags, *source);
+ }
- // Add shared-library flags if needed.
- this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
- language.c_str(),
- this->GetConfigName());
+ // 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);
+ }
- this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target,
- language.c_str());
+ return flags;
+}
- // Add include directory flags.
- const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- {
+void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
+ std::string const& language)
+{
std::vector<std::string> includes;
- this->LocalGenerator->GetIncludeDirectories(includes,
- this->GeneratorTarget,
- language.c_str(), config);
- std::string includeFlags =
- this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget,
- language.c_str(),
- language == "RC" ? true : false); // full include paths for RC
- // needed by cmcldeps
- if(cmGlobalNinjaGenerator::IsMinGW())
- cmSystemTools::ReplaceString(includeFlags, "\\", "/");
-
- this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
+ this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
+ language, this->GetConfigName());
+ // Add include directory flags.
+ std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
+ includes, this->GeneratorTarget, language,
+ language == "RC", // full include paths for RC needed by cmcldeps
+ false, this->GetConfigName());
+ if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
+ std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
}
- // Append old-style preprocessor definition flags.
- this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
-
- // Add target-specific flags.
- this->LocalGenerator->AddCompileOptions(flags, this->Target,
- language.c_str(), config);
-
- // Add source file specific flags.
- this->LocalGenerator->AppendFlags(flags,
- source->GetProperty("COMPILE_FLAGS"));
-
- // TODO: Handle Apple frameworks.
+ this->LocalGenerator->AppendFlags(languageFlags, includeFlags);
+}
- return flags;
+bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const
+{
+ return strcmp(this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" +
+ lang),
+ "msvc") == 0;
}
// TODO: Refactor with
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
-std::string
-cmNinjaTargetGenerator::
-ComputeDefines(cmSourceFile *source, const std::string& language)
+std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
+ const std::string& language)
{
std::set<std::string> defines;
-
- // Add the export symbol definition for shared library objects.
- if(const char* exportMacro = this->Target->GetExportMacro())
- {
- this->LocalGenerator->AppendDefines(defines, exportMacro);
- }
-
- // Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
- this->GetConfigName());
- this->LocalGenerator->AppendDefines
- (defines,
- source->GetProperty("COMPILE_DEFINITIONS"));
+ 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.c_str()));
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(this->GetConfigName());
+ this->LocalGenerator->AppendDefines(defines,
+ source->GetProperty(defPropName));
}
- std::string definesString;
- this->LocalGenerator->JoinDefines(defines, definesString,
- language.c_str());
+ std::string definesString = this->GetDefines(language);
+ this->LocalGenerator->JoinDefines(defines, definesString, language);
return definesString;
}
@@ -225,62 +196,145 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
{
// Static libraries never depend on other targets for linking.
- if (this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
- this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->GeneratorTarget->GetType() == cmStateEnums::OBJECT_LIBRARY) {
return cmNinjaDeps();
+ }
cmComputeLinkInformation* cli =
- this->Target->GetLinkInformation(this->GetConfigName());
- if(!cli)
+ this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
+ if (!cli) {
return cmNinjaDeps();
+ }
- const std::vector<std::string> &deps = cli->GetDepends();
+ const std::vector<std::string>& deps = cli->GetDepends();
cmNinjaDeps result(deps.size());
std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
// Add a dependency on the link definitions file, if any.
- if(!this->ModuleDefinitionFile.empty())
- {
- result.push_back(this->ModuleDefinitionFile);
+ 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()));
}
+ }
+
+ // 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()));
+ }
+
+ // 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());
+ }
return result;
}
-std::string
-cmNinjaTargetGenerator
-::GetSourceFilePath(cmSourceFile* source) const
+std::string cmNinjaTargetGenerator::GetSourceFilePath(
+ cmSourceFile const* source) const
{
- return ConvertToNinjaPath(source->GetFullPath().c_str());
+ return ConvertToNinjaPath(source->GetFullPath());
}
-std::string
-cmNinjaTargetGenerator
-::GetObjectFilePath(cmSourceFile* source) const
+std::string cmNinjaTargetGenerator::GetObjectFilePath(
+ cmSourceFile const* source) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
- if(!path.empty())
+ if (!path.empty()) {
path += "/";
- std::string const& objectName = this->GeneratorTarget->Objects[source];
- path += this->LocalGenerator->GetTargetDirectory(*this->Target);
+ }
+ std::string const& objectName = this->GeneratorTarget->GetObjectName(source);
+ path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
path += "/";
path += objectName;
return path;
}
+std::string cmNinjaTargetGenerator::GetPreprocessedFilePath(
+ cmSourceFile const* source) const
+{
+ // Choose an extension to compile already-preprocessed source.
+ std::string ppExt = source->GetExtension();
+ if (cmHasLiteralPrefix(ppExt, "F")) {
+ // Some Fortran compilers automatically enable preprocessing for
+ // upper-case extensions. Since the source is already preprocessed,
+ // use a lower-case extension.
+ ppExt = cmSystemTools::LowerCase(ppExt);
+ }
+ if (ppExt == "fpp") {
+ // Some Fortran compilers automatically enable preprocessing for
+ // the ".fpp" extension. Since the source is already preprocessed,
+ // use the ".f" extension.
+ ppExt = "f";
+ }
+
+ // Take the object file name and replace the extension.
+ std::string const& objName = this->GeneratorTarget->GetObjectName(source);
+ std::string const& objExt =
+ this->GetGlobalGenerator()->GetLanguageOutputExtension(*source);
+ assert(objName.size() >= objExt.size());
+ std::string const ppName =
+ objName.substr(0, objName.size() - objExt.size()) + "-pp." + ppExt;
+
+ std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
+ if (!path.empty()) {
+ path += "/";
+ }
+ path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ path += "/";
+ path += ppName;
+ return path;
+}
+
+std::string cmNinjaTargetGenerator::GetDyndepFilePath(
+ std::string const& lang) const
+{
+ std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
+ if (!path.empty()) {
+ path += "/";
+ }
+ path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ path += "/";
+ path += lang;
+ path += ".dd";
+ return path;
+}
+
+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";
+ return path;
+}
+
std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
{
- std::string dir = this->Target->GetDirectory(this->GetConfigName());
- return ConvertToNinjaPath(dir.c_str());
+ std::string dir = this->GeneratorTarget->GetDirectory(this->GetConfigName());
+ return ConvertToNinjaPath(dir);
}
-std::string
-cmNinjaTargetGenerator
-::GetTargetFilePath(const std::string& name) const
+std::string cmNinjaTargetGenerator::GetTargetFilePath(
+ const std::string& name) const
{
std::string path = this->GetTargetOutputDir();
- if (path.empty() || path == ".")
+ if (path.empty() || path == ".") {
return name;
+ }
path += "/";
path += name;
return path;
@@ -288,244 +342,521 @@ cmNinjaTargetGenerator
std::string cmNinjaTargetGenerator::GetTargetName() const
{
- return this->Target->GetName();
+ return this->GeneratorTarget->GetName();
}
-
bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
{
cmMakefile* mf = this->GetMakefile();
if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") ||
- mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID"))
- {
+ mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") ||
+ mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) {
std::string pdbPath;
- if(this->Target->GetType() == cmTarget::EXECUTABLE ||
- this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
- this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
- this->Target->GetType() == cmTarget::MODULE_LIBRARY)
- {
- pdbPath = this->Target->GetPDBDirectory(this->GetConfigName());
+ std::string compilePdbPath = this->ComputeTargetCompilePDB();
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
+ 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->Target->GetPDBName(this->GetConfigName());
- }
+ pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName());
+ }
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- ConvertToNinjaPath(pdbPath.c_str()).c_str(),
- cmLocalGenerator::SHELL);
+ ConvertToNinjaPath(pdbPath), cmOutputConverter::SHELL);
+ vars["TARGET_COMPILE_PDB"] =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ ConvertToNinjaPath(compilePdbPath), cmOutputConverter::SHELL);
+
EnsureParentDirectoryExists(pdbPath);
+ EnsureParentDirectoryExists(compilePdbPath);
return true;
- }
+ }
return false;
}
-void
-cmNinjaTargetGenerator
-::WriteLanguageRules(const std::string& language)
+void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language)
{
#ifdef NINJA_GEN_VERBOSE_FILES
- this->GetRulesFileStream()
- << "# Rules for language " << language << "\n\n";
+ this->GetRulesFileStream() << "# Rules for language " << language << "\n\n";
#endif
this->WriteCompileRule(language);
}
-void
-cmNinjaTargetGenerator
-::WriteCompileRule(const std::string& language)
+void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
{
- cmLocalGenerator::RuleVariables vars;
- vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
- vars.CMTarget = this->GetTarget();
- std::string lang = language;
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
vars.Language = lang.c_str();
vars.Source = "$in";
vars.Object = "$out";
- std::string flags = "$FLAGS";
vars.Defines = "$DEFINES";
+ vars.Includes = "$INCLUDES";
vars.TargetPDB = "$TARGET_PDB";
+ vars.TargetCompilePDB = "$TARGET_COMPILE_PDB";
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 needDyndep = this->NeedDyndep(lang);
- bool useClDeps = false;
- std::string clBinary;
- std::string clDepsBinary;
- std::string clShowPrefix;
- if (lang == "C" || lang == "CXX" || lang == "RC")
- {
- clDepsBinary = mf->GetSafeDefinition("CMAKE_CMCLDEPS_EXECUTABLE");
- if (!clDepsBinary.empty() && !mf->GetIsSourceFileTryCompile())
- {
- clShowPrefix = mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDE_PREFIX");
- clBinary = mf->GetDefinition("CMAKE_C_COMPILER") ?
- mf->GetSafeDefinition("CMAKE_C_COMPILER") :
- mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
- if (!clBinary.empty() && !clShowPrefix.empty())
- {
- useClDeps = true;
- const std::string quote = " \"";
- clBinary = quote + clBinary + "\" ";
- clDepsBinary = quote + clDepsBinary + "\" ";
- clShowPrefix = quote + clShowPrefix + "\" ";
- vars.DependencyFile = "$DEP_FILE";
- }
- }
- }
+ 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");
+ 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 depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
- const char *depfileFlags = mf->GetDefinition(depfileFlagsName.c_str());
- if (depfileFlags || useClDeps) {
- std::string depFlagsStr = depfileFlags ? depfileFlags : "";
+ 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";
- cmSystemTools::ReplaceString(depFlagsStr, "<DEPFILE>", "\"$DEP_FILE\"");
- cmSystemTools::ReplaceString(depFlagsStr, "<OBJECT>", "$out");
- cmSystemTools::ReplaceString(depFlagsStr, "<CMAKE_C_COMPILER>",
- mf->GetDefinition("CMAKE_C_COMPILER"));
- flags += " " + depFlagsStr;
+ 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 = depfile.c_str();
+ CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ this->GetLocalGenerator()->CreateRulePlaceholderExpander());
+
+ std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat(
+ ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)),
+ cmLocalGenerator::SHELL);
+
+ std::string launcher;
+ const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+ this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
+ if (val && *val) {
+ launcher = val;
+ launcher += " ";
+ }
+
+ if (explicitPP) {
+ // Lookup the explicit preprocessing rule.
+ std::string const ppVar = "CMAKE_" + lang + "_PREPROCESS_SOURCE";
+ std::string const ppCmd =
+ this->GetMakefile()->GetRequiredDefinition(ppVar);
+
+ // Explicit preprocessing always uses a depfile.
+ std::string const ppDeptype; // no deps= for multiple outputs
+ std::string const ppDepfile = "$DEP_FILE";
+
+ cmRulePlaceholderExpander::RuleVariables ppVars;
+ ppVars.CMTargetName = vars.CMTargetName;
+ ppVars.CMTargetType = vars.CMTargetType;
+ ppVars.Language = vars.Language;
+ ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
+ ppVars.PreprocessedSource = "$out";
+ ppVars.DependencyFile = ppDepfile.c_str();
+
+ // Preprocessing uses the original source,
+ // compilation uses preprocessed output.
+ ppVars.Source = vars.Source;
+ vars.Source = "$in";
+
+ // Preprocessing and compilation use the same flags.
+ ppVars.Flags = vars.Flags;
+
+ // Move preprocessor definitions to the preprocessor rule.
+ ppVars.Defines = vars.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;
+
+ // Rule for preprocessing source file.
+ std::vector<std::string> ppCmds;
+ cmSystemTools::ExpandListArgument(ppCmd, ppCmds);
+
+ for (std::vector<std::string>::iterator i = ppCmds.begin();
+ i != ppCmds.end(); ++i) {
+ *i = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+ *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);
+
+ // 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);
+ }
+
+ 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
+
+ // 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);
+ }
// Rule for compiling object file.
- std::string compileCmdVar = "CMAKE_";
- compileCmdVar += language;
- compileCmdVar += "_COMPILE_OBJECT";
- std::string compileCmd = mf->GetRequiredDefinition(compileCmdVar.c_str());
std::vector<std::string> compileCmds;
- cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ if (lang == "CUDA") {
+ std::string cmdVar;
+ if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_SEPARABLE_COMPILATION")) {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_PTX_COMPILATION")) {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+ } else {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+ }
+ std::string compileCmd = mf->GetRequiredDefinition(cmdVar);
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ } else {
+ const std::string cmdVar =
+ std::string("CMAKE_") + lang + "_COMPILE_OBJECT";
+ std::string compileCmd = mf->GetRequiredDefinition(cmdVar);
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ }
+
+ // Maybe insert an include-what-you-use runner.
+ if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) {
+ std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
+ const char* iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
+ std::string const tidy_prop = lang + "_CLANG_TIDY";
+ 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";
+ if (iwyu && *iwyu) {
+ run_iwyu += " --iwyu=";
+ run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu);
+ }
+ if (tidy && *tidy) {
+ run_iwyu += " --tidy=";
+ run_iwyu += this->GetLocalGenerator()->EscapeForShell(tidy);
+ }
+ if (cpplint && *cpplint) {
+ run_iwyu += " --cpplint=";
+ run_iwyu += this->GetLocalGenerator()->EscapeForShell(cpplint);
+ }
+ if ((tidy && *tidy) || (cpplint && *cpplint)) {
+ run_iwyu += " --source=$in";
+ }
+ run_iwyu += " -- ";
+ compileCmds.front().insert(0, run_iwyu);
+ }
+ }
- if(useClDeps)
- {
- std::string cmdPrefix = clDepsBinary + lang + " $in \"$DEP_FILE\" $out " +
- clShowPrefix + clBinary;
- compileCmds.front().insert(0, cmdPrefix);
+ // 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);
+ }
+ std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
+ compileCmds.front().insert(0, run_launcher);
}
+ }
+
+ if (!compileCmds.empty()) {
+ compileCmds.front().insert(0, cldeps);
+ }
for (std::vector<std::string>::iterator i = compileCmds.begin();
- i != compileCmds.end(); ++i)
- this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+ i != compileCmds.end(); ++i) {
+ *i = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+ vars);
+ }
std::string cmdLine =
this->GetLocalGenerator()->BuildCommandLine(compileCmds);
-
// Write the rule for compiling file of the given language.
- cmOStringStream comment;
- comment << "Rule for compiling " << language << " files.";
- cmOStringStream description;
- description << "Building " << language << " object $out";
- this->GetGlobalGenerator()->AddRule(this->LanguageCompilerRule(language),
- cmdLine,
- description.str(),
- comment.str(),
- depfile);
+ 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);
}
-void
-cmNinjaTargetGenerator
-::WriteObjectBuildStatements()
+void cmNinjaTargetGenerator::WriteObjectBuildStatements()
{
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
this->GetBuildFileStream()
<< "# Object build statements for "
- << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
- << " target "
- << this->GetTargetName()
- << "\n\n";
-
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->CustomCommands.begin();
- si != this->GeneratorTarget->CustomCommands.end(); ++si)
- {
- cmCustomCommand const* cc = (*si)->GetCustomCommand();
- this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
- }
+ << 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*> headerSources;
+ this->GeneratorTarget->GetHeaderSources(headerSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- this->GeneratorTarget->HeaderSources,
- this->MacOSXContentGenerator);
+ headerSources, this->MacOSXContentGenerator);
+ std::vector<cmSourceFile const*> extraSources;
+ this->GeneratorTarget->GetExtraSources(extraSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- this->GeneratorTarget->ExtraSources,
- this->MacOSXContentGenerator);
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ExternalObjects.begin();
- si != this->GeneratorTarget->ExternalObjects.end(); ++si)
- {
+ 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));
- }
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ObjectSources.begin();
- si != this->GeneratorTarget->ObjectSources.end(); ++si)
- {
- this->WriteObjectBuildStatement(*si);
- }
- if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
- {
- this->ModuleDefinitionFile = this->ConvertToNinjaPath(
- this->GeneratorTarget->ModuleDefinitionFile.c_str());
- }
+ }
+
+ 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::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
+ orderOnlyDeps.erase(std::unique(orderOnlyDeps.begin(), orderOnlyDeps.end()),
+ orderOnlyDeps.end());
{
- // Add object library contents as external objects.
- std::vector<std::string> objs;
- this->GeneratorTarget->UseObjectLibraries(objs);
- for(std::vector<std::string>::iterator oi = objs.begin();
- oi != objs.end(); ++oi)
- {
- this->Objects.push_back(ConvertToNinjaPath(oi->c_str()));
- }
+ cmNinjaDeps orderOnlyTarget;
+ orderOnlyTarget.push_back(this->OrderDependsTargetForTarget());
+ this->GetGlobalGenerator()->WritePhonyBuild(
+ this->GetBuildFileStream(),
+ "Order-only phony target for " + this->GetTargetName(), orderOnlyTarget,
+ cmNinjaDeps(), cmNinjaDeps(), orderOnlyDeps);
+ }
+ 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);
+ }
+
+ 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;
+
+ this->WriteTargetDependInfo("Fortran");
+
+ ddOutputs.push_back(this->GetDyndepFilePath("Fortran"));
+
+ // Make sure dyndep files for all our dependencies have already
+ // been generated so that the 'FortranModules.json' files they
+ // produced as side-effects are available for us to read.
+ // Ideally we should depend on the 'FortranModules.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->GetGlobalGenerator()->WriteBuild(
+ this->GetBuildFileStream(), ddComment, ddRule, ddOutputs, ddImplicitOuts,
+ ddExplicitDeps, ddImplicitDeps, ddOrderOnlyDeps, ddVars);
}
this->GetBuildFileStream() << "\n";
}
-void
-cmNinjaTargetGenerator
-::WriteObjectBuildStatement(cmSourceFile* source)
+void cmNinjaTargetGenerator::WriteObjectBuildStatement(
+ cmSourceFile const* source)
{
+ std::string const language = source->GetLanguage();
+ std::string const sourceFileName =
+ language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source);
+ std::string const objectDir =
+ this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory());
+ std::string const objectFileName =
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source));
+ std::string const objectFileDir =
+ cmSystemTools::GetFilenamePath(objectFileName);
+
+ cmNinjaVars vars;
+ vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
+ vars["DEFINES"] = this->ComputeDefines(source, language);
+ vars["INCLUDES"] = this->GetIncludes(language);
+ if (!this->NeedDepTypeMSVC(language)) {
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".d", cmOutputConverter::SHELL);
+ }
+
+ this->ExportObjectCompileCommand(
+ language, sourceFileName, objectDir, objectFileName, objectFileDir,
+ vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]);
+
std::string comment;
- const std::string language = source->GetLanguage();
std::string rule = this->LanguageCompilerRule(language);
cmNinjaDeps outputs;
- std::string objectFileName = this->GetObjectFilePath(source);
outputs.push_back(objectFileName);
// Add this object to the list of object files.
this->Objects.push_back(objectFileName);
cmNinjaDeps explicitDeps;
- std::string sourceFileName;
- if (language == "RC")
- sourceFileName = source->GetFullPath();
- else
- sourceFileName = this->GetSourceFilePath(source);
explicitDeps.push_back(sourceFileName);
- // Ensure that the target dependencies are built before any source file in
- // the target, using order-only dependencies.
- cmNinjaDeps orderOnlyDeps;
- this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps);
-
cmNinjaDeps implicitDeps;
- if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
+ 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::transform(depList.begin(), depList.end(),
std::back_inserter(implicitDeps), MapToNinjaPath());
}
- // Add order-only dependencies on custom command outputs.
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->CustomCommands.begin();
- si != this->GeneratorTarget->CustomCommands.end(); ++si)
- {
- cmCustomCommand const* cc = (*si)->GetCustomCommand();
- const std::vector<std::string>& ccoutputs = cc->GetOutputs();
- std::transform(ccoutputs.begin(), ccoutputs.end(),
- std::back_inserter(orderOnlyDeps), MapToNinjaPath());
- }
+ cmNinjaDeps orderOnlyDeps;
+ 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
@@ -537,167 +868,305 @@ cmNinjaTargetGenerator
orderOnlyDeps);
}
- cmNinjaVars vars;
- vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
- vars["DEFINES"] = this->ComputeDefines(source, language);
- vars["DEP_FILE"] = objectFileName + ".d";;
- EnsureParentDirectoryExists(objectFileName);
-
- std::string objectDir = this->Target->GetSupportDirectory();
- vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- ConvertToNinjaPath(objectDir.c_str()).c_str(),
- cmLocalGenerator::SHELL);
-
- this->SetMsvcTargetPdbVariable(vars);
-
- if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS"))
- {
- cmLocalGenerator::RuleVariables compileObjectVars;
- std::string lang = language;
- compileObjectVars.Language = lang.c_str();
-
- std::string escapedSourceFileName = sourceFileName;
+ // For some cases we need to generate a ninja dyndep file.
+ bool const needDyndep = this->NeedDyndep(language);
+
+ // 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;
+
+ 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"]);
+
+ // The actual compilation will now use the preprocessed source.
+ explicitDeps.push_back(ppFileName);
+
+ // Preprocessing and compilation use the same flags.
+ ppVars["FLAGS"] = vars["FLAGS"];
+
+ // Move preprocessor definitions to the preprocessor build statement.
+ std::swap(ppVars["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"];
+
+ // 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());
+
+ 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");
+
+ if (needDyndep) {
+ // Tell dependency scanner the object file that will result from
+ // compiling the preprocessed source.
+ ppVars["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);
+ }
- if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str()))
- {
- escapedSourceFileName = cmSystemTools::CollapseFullPath(
- escapedSourceFileName.c_str(),
- this->GetGlobalGenerator()->GetCMakeInstance()->
- GetHomeOutputDirectory());
- }
+ this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
+ ppVars);
- escapedSourceFileName =
- this->LocalGenerator->ConvertToOutputFormat(
- escapedSourceFileName.c_str(), cmLocalGenerator::SHELL);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetBuildFileStream(), ppComment, ppRule, ppOutputs, ppImplicitOuts,
+ ppExplicitDeps, ppImplicitDeps, ppOrderOnlyDeps, ppVars);
+ }
+ if (needDyndep) {
+ std::string const dyndep = this->GetDyndepFilePath(language);
+ orderOnlyDeps.push_back(dyndep);
+ vars["dyndep"] = dyndep;
+ }
- compileObjectVars.Source = escapedSourceFileName.c_str();
- compileObjectVars.Object = objectFileName.c_str();
- compileObjectVars.ObjectDir = objectDir.c_str();
- compileObjectVars.Flags = vars["FLAGS"].c_str();
- compileObjectVars.Defines = vars["DEFINES"].c_str();
+ EnsureParentDirectoryExists(objectFileName);
- // Rule for compiling object file.
- std::string compileCmdVar = "CMAKE_";
- compileCmdVar += language;
- compileCmdVar += "_COMPILE_OBJECT";
- std::string compileCmd =
- this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
- std::vector<std::string> compileCmds;
- cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectDir, cmOutputConverter::SHELL);
+ vars["OBJECT_FILE_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileDir, cmOutputConverter::SHELL);
- for (std::vector<std::string>::iterator i = compileCmds.begin();
- i != compileCmds.end(); ++i)
- this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars);
+ this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
+ vars);
- std::string cmdLine =
- this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+ this->SetMsvcTargetPdbVariable(vars);
- this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine,
- sourceFileName);
- }
+ 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";
- this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(),
- comment,
- rule,
- outputs,
- explicitDeps,
- implicitDeps,
- orderOnlyDeps,
- vars);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetBuildFileStream(), comment, rule, outputs,
+ /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, orderOnlyDeps,
+ vars, rspfile, commandLineLengthLimit);
- if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
+ 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);
+ outputList, outputs);
}
}
-//----------------------------------------------------------------------------
-void
-cmNinjaTargetGenerator
-::AddModuleDefinitionFlag(std::string& flags)
+void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
{
- if(this->ModuleDefinitionFile.empty())
- {
- return;
+ Json::Value tdi(Json::objectValue);
+ tdi["language"] = lang;
+ tdi["compiler-id"] =
+ this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID");
+
+ if (lang == "Fortran") {
+ std::string mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
+ this->Makefile->GetHomeOutputDirectory());
+ if (mod_dir.empty()) {
+ mod_dir = this->Makefile->GetCurrentBinaryDirectory();
}
+ tdi["module-dir"] = mod_dir;
+ }
+
+ tdi["dir-cur-bld"] = this->Makefile->GetCurrentBinaryDirectory();
+ tdi["dir-cur-src"] = this->Makefile->GetCurrentSourceDirectory();
+ tdi["dir-top-bld"] = this->Makefile->GetHomeOutputDirectory();
+ tdi["dir-top-src"] = this->Makefile->GetHomeDirectory();
- // TODO: Create a per-language flag variable.
- const char* defFileFlag =
- this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
- if(!defFileFlag)
- {
+ Json::Value& tdi_include_dirs = tdi["include-dirs"] = Json::arrayValue;
+ 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) {
+ // Convert the include directories the same way we do for -I flags.
+ // See upstream ninja issue 1251.
+ 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);
+ }
+
+ std::string const tdin = this->GetTargetDependInfoPath(lang);
+ cmGeneratedFileStream tdif(tdin.c_str());
+ tdif << tdi;
+}
+
+void cmNinjaTargetGenerator::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)
+{
+ if (!this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) {
return;
+ }
+
+ cmRulePlaceholderExpander::RuleVariables compileObjectVars;
+ compileObjectVars.Language = language.c_str();
+
+ std::string escapedSourceFileName = sourceFileName;
+
+ if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) {
+ escapedSourceFileName = cmSystemTools::CollapseFullPath(
+ escapedSourceFileName, this->GetGlobalGenerator()
+ ->GetCMakeInstance()
+ ->GetHomeOutputDirectory());
+ }
+
+ escapedSourceFileName = this->LocalGenerator->ConvertToOutputFormat(
+ escapedSourceFileName, cmOutputConverter::SHELL);
+
+ compileObjectVars.Source = escapedSourceFileName.c_str();
+ compileObjectVars.Object = objectFileName.c_str();
+ compileObjectVars.ObjectDir = objectDir.c_str();
+ compileObjectVars.ObjectFileDir = objectFileDir.c_str();
+ compileObjectVars.Flags = flags.c_str();
+ compileObjectVars.Defines = defines.c_str();
+ compileObjectVars.Includes = includes.c_str();
+
+ // Rule for compiling object file.
+ std::vector<std::string> compileCmds;
+ if (language == "CUDA") {
+ std::string cmdVar;
+ if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_SEPARABLE_COMPILATION")) {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_PTX_COMPILATION")) {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+ } else {
+ cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
}
+ std::string compileCmd =
+ this->GetMakefile()->GetRequiredDefinition(cmdVar);
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ } else {
+ const std::string cmdVar =
+ std::string("CMAKE_") + language + "_COMPILE_OBJECT";
+ std::string compileCmd =
+ this->GetMakefile()->GetRequiredDefinition(cmdVar);
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ }
+
+ CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ this->GetLocalGenerator()->CreateRulePlaceholderExpander());
- // 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->ConvertToLinkReference(
- this->ModuleDefinitionFile.c_str()));
- this->LocalGenerator->AppendFlags(flags, flag.c_str());
+ for (std::vector<std::string>::iterator i = compileCmds.begin();
+ i != compileCmds.end(); ++i) {
+ // no launcher for CMAKE_EXPORT_COMPILE_COMMANDS
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+ compileObjectVars);
+ }
+
+ std::string cmdLine =
+ this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+
+ this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName);
}
-void
-cmNinjaTargetGenerator
-::EnsureDirectoryExists(const std::string& path) const
+void cmNinjaTargetGenerator::EnsureDirectoryExists(
+ const std::string& path) const
{
- if (cmSystemTools::FileIsFullPath(path.c_str()))
- {
+ if (cmSystemTools::FileIsFullPath(path.c_str())) {
cmSystemTools::MakeDirectory(path.c_str());
- }
- else
- {
- const std::string fullPath = std::string(this->GetGlobalGenerator()->
- GetCMakeInstance()->GetHomeOutputDirectory())
- + "/" + path;
+ } else {
+ cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
+ std::string fullPath =
+ std::string(gg->GetCMakeInstance()->GetHomeOutputDirectory());
+ // Also ensures their is a trailing slash.
+ gg->StripNinjaOutputPathPrefixAsSuffix(fullPath);
+ fullPath += path;
cmSystemTools::MakeDirectory(fullPath.c_str());
- }
+ }
}
-void
-cmNinjaTargetGenerator
-::EnsureParentDirectoryExists(const std::string& path) const
+void cmNinjaTargetGenerator::EnsureParentDirectoryExists(
+ const std::string& path) const
{
- EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path.c_str()));
+ EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path));
}
-
-//----------------------------------------------------------------------------
-void
-cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
- cmSourceFile& source, const char* pkgloc)
+void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
+ cmSourceFile const& source, const char* pkgloc)
{
// Skip OS X content when not building a Framework or Bundle.
- if(!this->Generator->GetTarget()->IsBundleOnApple())
- {
+ if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) {
return;
- }
+ }
std::string macdir =
this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
// Get the input file location.
std::string input = source.GetFullPath();
- input =
- this->Generator->GetLocalGenerator()->ConvertToNinjaPath(input.c_str());
+ input = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(input);
// Get the output file location.
std::string output = macdir;
output += "/";
output += cmSystemTools::GetFilenameName(input);
- output =
- this->Generator->GetLocalGenerator()->ConvertToNinjaPath(output.c_str());
+ output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output);
// Write a build statement to copy the content into the bundle.
this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input,
output);
- // Add as a dependency of all target so that it gets called.
- this->Generator->GetGlobalGenerator()->AddDependencyToAll(output);
+ // Add as a dependency to the target so that it gets called.
+ this->Generator->ExtraFiles.push_back(output);
+}
+
+void cmNinjaTargetGenerator::addPoolNinjaVariable(
+ const std::string& pool_property, cmGeneratorTarget* target,
+ cmNinjaVars& vars)
+{
+ const char* pool = target->GetProperty(pool_property);
+ if (pool) {
+ vars["pool"] = pool;
+ }
+}
+
+bool cmNinjaTargetGenerator::ForceResponseFile()
+{
+ static std::string const forceRspFile = "CMAKE_NINJA_FORCE_RESPONSE_FILE";
+ return (this->GetMakefile()->IsDefinitionSet(forceRspFile) ||
+ cmSystemTools::HasEnv(forceRspFile));
}
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index cf06bfdf5..5eb7a9a49 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -1,103 +1,114 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmNinjaTargetGenerator_h
#define cmNinjaTargetGenerator_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include "cmCommonTargetGenerator.h"
+#include "cmGlobalNinjaGenerator.h"
#include "cmNinjaTypes.h"
-#include "cmLocalNinjaGenerator.h"
#include "cmOSXBundleGenerator.h"
-class cmTarget;
-class cmGlobalNinjaGenerator;
+#include <set>
+#include <string>
+#include <vector>
+
+class cmCustomCommand;
class cmGeneratedFileStream;
class cmGeneratorTarget;
+class cmLocalNinjaGenerator;
class cmMakefile;
class cmSourceFile;
-class cmCustomCommand;
-class cmNinjaTargetGenerator
+class cmNinjaTargetGenerator : public cmCommonTargetGenerator
{
public:
/// Create a cmNinjaTargetGenerator according to the @a target's type.
- static cmNinjaTargetGenerator* New(cmTarget* target);
+ static cmNinjaTargetGenerator* New(cmGeneratorTarget* target);
/// Build a NinjaTargetGenerator.
- cmNinjaTargetGenerator(cmTarget* target);
+ cmNinjaTargetGenerator(cmGeneratorTarget* target);
/// Destructor.
- virtual ~cmNinjaTargetGenerator();
+ ~cmNinjaTargetGenerator() CM_OVERRIDE;
virtual void Generate() = 0;
std::string GetTargetName() const;
-protected:
+ bool NeedDepTypeMSVC(const std::string& lang) const;
+protected:
bool SetMsvcTargetPdbVariable(cmNinjaVars&) const;
cmGeneratedFileStream& GetBuildFileStream() const;
cmGeneratedFileStream& GetRulesFileStream() const;
- cmTarget* GetTarget() const
- { return this->Target; }
-
cmGeneratorTarget* GetGeneratorTarget() const
- { return this->GeneratorTarget; }
+ {
+ return this->GeneratorTarget;
+ }
cmLocalNinjaGenerator* GetLocalGenerator() const
- { return this->LocalGenerator; }
+ {
+ return this->LocalGenerator;
+ }
cmGlobalNinjaGenerator* GetGlobalGenerator() const;
- cmMakefile* GetMakefile() const
- { return this->Makefile; }
+ cmMakefile* GetMakefile() const { return this->Makefile; }
- const char* GetConfigName() const;
+ std::string LanguageCompilerRule(const std::string& lang) const;
+ std::string LanguagePreprocessRule(std::string const& lang) const;
+ bool NeedExplicitPreprocessing(std::string const& lang) const;
+ std::string LanguageDyndepRule(std::string const& lang) const;
+ bool NeedDyndep(std::string const& lang) const;
- std::string LanguageCompilerRule(const std::string& lang) const
- { return lang + "_COMPILER"; }
+ std::string OrderDependsTargetForTarget();
- const char* GetFeature(const char* feature);
- bool GetFeatureAsBool(const char* feature);
- void AddFeatureFlags(std::string& flags, const char* lang);
+ std::string ComputeOrderDependsForTarget();
/**
* Compute the flags for compilation of object files for a given @a language.
* @note Generally it is the value of the variable whose name is computed
* by LanguageFlagsVarName().
*/
- std::string ComputeFlagsForObject(cmSourceFile *source,
+ std::string ComputeFlagsForObject(cmSourceFile const* source,
const std::string& language);
- std::string ComputeDefines(cmSourceFile *source,
+ void AddIncludeFlags(std::string& flags,
+ std::string const& lang) CM_OVERRIDE;
+
+ std::string ComputeDefines(cmSourceFile const* source,
const std::string& language);
- std::string ConvertToNinjaPath(const char *path) const {
- return this->GetLocalGenerator()->ConvertToNinjaPath(path);
+ std::string ConvertToNinjaPath(const std::string& path) const
+ {
+ return this->GetGlobalGenerator()->ConvertToNinjaPath(path);
}
- cmLocalNinjaGenerator::map_to_ninja_path MapToNinjaPath() const {
- return this->GetLocalGenerator()->MapToNinjaPath();
+ cmGlobalNinjaGenerator::MapToNinjaPathImpl MapToNinjaPath() const
+ {
+ return this->GetGlobalGenerator()->MapToNinjaPath();
}
/// @return the list of link dependency for the given target @a target.
cmNinjaDeps ComputeLinkDeps() const;
/// @return the source file path for the given @a source.
- std::string GetSourceFilePath(cmSourceFile* source) const;
+ std::string GetSourceFilePath(cmSourceFile const* source) const;
/// @return the object file path for the given @a source.
- std::string GetObjectFilePath(cmSourceFile* source) const;
+ std::string GetObjectFilePath(cmSourceFile const* source) const;
+
+ /// @return the preprocessed source file path for the given @a source.
+ std::string GetPreprocessedFilePath(cmSourceFile const* source) const;
+
+ /// @return the dyndep file path for this target.
+ std::string GetDyndepFilePath(std::string const& lang) const;
+
+ /// @return the target dependency scanner info file path
+ std::string GetTargetDependInfoPath(std::string const& lang) const;
/// @return the file path where the target named @a name is generated.
std::string GetTargetFilePath(const std::string& name) const;
@@ -108,49 +119,54 @@ protected:
void WriteLanguageRules(const std::string& language);
void WriteCompileRule(const std::string& language);
void WriteObjectBuildStatements();
- void WriteObjectBuildStatement(cmSourceFile* source);
- void WriteCustomCommandBuildStatement(cmCustomCommand *cc);
+ void WriteObjectBuildStatement(cmSourceFile const* source);
+ void WriteTargetDependInfo(std::string const& lang);
- cmNinjaDeps GetObjects() const
- { return this->Objects; }
+ 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);
- // Helper to add flag for windows .def file.
- void AddModuleDefinitionFlag(std::string& flags);
+ 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.
- struct MacOSXContentGeneratorType :
- cmOSXBundleGenerator::MacOSXContentGeneratorType
+ struct MacOSXContentGeneratorType
+ : cmOSXBundleGenerator::MacOSXContentGeneratorType
{
- MacOSXContentGeneratorType(cmNinjaTargetGenerator* g) :
- Generator(g) {}
+ MacOSXContentGeneratorType(cmNinjaTargetGenerator* g)
+ : Generator(g)
+ {
+ }
- void operator()(cmSourceFile& source, const char* pkgloc);
+ void operator()(cmSourceFile const& source,
+ const char* pkgloc) CM_OVERRIDE;
private:
cmNinjaTargetGenerator* Generator;
};
friend struct MacOSXContentGeneratorType;
-protected:
MacOSXContentGeneratorType* MacOSXContentGenerator;
// Properly initialized by sub-classes.
cmOSXBundleGenerator* OSXBundleGenerator;
- std::set<cmStdString> MacContentFolders;
+ std::set<std::string> MacContentFolders;
+ void addPoolNinjaVariable(const std::string& pool_property,
+ cmGeneratorTarget* target, cmNinjaVars& vars);
+
+ bool ForceResponseFile();
private:
- cmTarget* Target;
- cmGeneratorTarget* GeneratorTarget;
- cmMakefile* Makefile;
cmLocalNinjaGenerator* LocalGenerator;
/// List of object files for this target.
cmNinjaDeps Objects;
-
- // The windows module definition source file (.def), if any.
- std::string ModuleDefinitionFile;
+ cmNinjaDeps DDIFiles; // TODO: Make per-language.
+ std::vector<cmCustomCommand const*> CustomCommands;
+ cmNinjaDeps ExtraFiles;
};
#endif // ! cmNinjaTargetGenerator_h
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
index 498f6b639..ec435d9dd 100644
--- a/Source/cmNinjaTypes.h
+++ b/Source/cmNinjaTypes.h
@@ -1,17 +1,19 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmNinjaTypes_h
+#define cmNinjaTypes_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h" // IWYU pragma: keep
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmNinjaTypes_h
-# define cmNinjaTypes_h
+#include <map>
+#include <string>
+#include <vector>
+
+enum cmNinjaTargetDepends
+{
+ DependOnTargetArtifact,
+ DependOnTargetOrdering
+};
typedef std::vector<std::string> cmNinjaDeps;
typedef std::map<std::string, std::string> cmNinjaVars;
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 755ce6edc..500ff4a45 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -1,117 +1,158 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNinjaUtilityTargetGenerator.h"
+
#include "cmCustomCommand.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
+#include "cmNinjaTypes.h"
+#include "cmOutputConverter.h"
#include "cmSourceFile.h"
-#include "cmTarget.h"
-
-cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(cmTarget *target)
- : cmNinjaTargetGenerator(target) {}
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <vector>
+
+cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
+ cmGeneratorTarget* target)
+ : cmNinjaTargetGenerator(target)
+{
+}
-cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}
+cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator()
+{
+}
void cmNinjaUtilityTargetGenerator::Generate()
{
+ std::string utilCommandName =
+ this->GetLocalGenerator()->GetCurrentBinaryDirectory();
+ utilCommandName += cmake::GetCMakeFilesDirectory();
+ utilCommandName += "/";
+ utilCommandName += this->GetTargetName() + ".util";
+ utilCommandName = this->ConvertToNinjaPath(utilCommandName);
+
std::vector<std::string> commands;
- cmNinjaDeps deps, outputs;
+ cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
- const std::vector<cmCustomCommand> *cmdLists[2] = {
- &this->GetTarget()->GetPreBuildCommands(),
- &this->GetTarget()->GetPostBuildCommands()
+ const std::vector<cmCustomCommand>* cmdLists[2] = {
+ &this->GetGeneratorTarget()->GetPreBuildCommands(),
+ &this->GetGeneratorTarget()->GetPostBuildCommands()
};
+ 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) {
- this->GetLocalGenerator()->AppendCustomCommandDeps(&*ci, deps);
- this->GetLocalGenerator()->AppendCustomCommandLines(&*ci, commands);
+ 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;
+ }
}
}
- const std::vector<cmSourceFile*>& sources =
- this->GetTarget()->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
- {
- if(cmCustomCommand* cc = (*source)->GetCustomCommand())
- {
- this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
+ 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 = cc->GetOutputs();
+ 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->GetTarget(), outputs);
- this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps);
+ this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
+ outputs);
+ this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
+ deps);
if (commands.empty()) {
- this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
- "Utility command for "
- + this->GetTargetName(),
- outputs,
- deps);
+ this->GetGlobalGenerator()->WritePhonyBuild(
+ this->GetBuildFileStream(),
+ "Utility command for " + this->GetTargetName(), outputs, deps);
} else {
std::string command =
this->GetLocalGenerator()->BuildCommandLine(commands);
- const char *echoStr = this->GetTarget()->GetProperty("EchoString");
+ const char* echoStr =
+ this->GetGeneratorTarget()->GetProperty("EchoString");
std::string desc;
- if (echoStr)
+ if (echoStr) {
desc = echoStr;
- else
+ } else {
desc = "Running utility command for " + this->GetTargetName();
+ }
// TODO: fix problematic global targets. For now, search and replace the
// makefile vars.
cmSystemTools::ReplaceString(
- command,
- "$(CMAKE_SOURCE_DIR)",
- this->GetLocalGenerator()->ConvertToOutputFormat(
- this->GetTarget()->GetMakefile()->GetHomeDirectory(),
- cmLocalGenerator::SHELL).c_str());
+ command, "$(CMAKE_SOURCE_DIR)",
+ this->GetLocalGenerator()
+ ->ConvertToOutputFormat(
+ this->GetLocalGenerator()->GetSourceDirectory(),
+ cmOutputConverter::SHELL)
+ .c_str());
cmSystemTools::ReplaceString(
- command,
- "$(CMAKE_BINARY_DIR)",
- this->GetLocalGenerator()->ConvertToOutputFormat(
- this->GetTarget()->GetMakefile()->GetHomeOutputDirectory(),
- cmLocalGenerator::SHELL).c_str());
+ command, "$(CMAKE_BINARY_DIR)",
+ this->GetLocalGenerator()
+ ->ConvertToOutputFormat(
+ this->GetLocalGenerator()->GetBinaryDirectory(),
+ cmOutputConverter::SHELL)
+ .c_str());
cmSystemTools::ReplaceString(command, "$(ARGS)", "");
- if (command.find('$') != std::string::npos)
+ if (command.find('$') != std::string::npos) {
return;
+ }
- std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
- utilCommandName += this->GetTargetName() + ".util";
+ for (cmNinjaDeps::const_iterator oi = util_outputs.begin(),
+ oe = util_outputs.end();
+ oi != oe; ++oi) {
+ this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+ }
this->GetGlobalGenerator()->WriteCustomCommandBuild(
- command,
- desc,
- "Utility command for " + this->GetTargetName(),
- cmNinjaDeps(1, utilCommandName),
- deps);
-
- this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
- "",
- outputs,
- cmNinjaDeps(1, utilCommandName)
- );
+ command, desc, "Utility command for " + this->GetTargetName(),
+ /*depfile*/ "", uses_terminal,
+ /*restat*/ true, util_outputs, deps);
+
+ this->GetGlobalGenerator()->WritePhonyBuild(
+ this->GetBuildFileStream(), "", outputs,
+ cmNinjaDeps(1, utilCommandName));
}
- this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
- this->GetTarget());
+ // 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());
+ }
}
diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h
index 8b82ce49a..9256e369c 100644
--- a/Source/cmNinjaUtilityTargetGenerator.h
+++ b/Source/cmNinjaUtilityTargetGenerator.h
@@ -1,30 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
- Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmNinjaUtilityTargetGenerator_h
-# define cmNinjaUtilityTargetGenerator_h
+#define cmNinjaUtilityTargetGenerator_h
+
+#include "cmConfigure.h"
-# include "cmNinjaTargetGenerator.h"
-# include "cmNinjaTypes.h"
+#include "cmNinjaTargetGenerator.h"
-class cmSourceFile;
+class cmGeneratorTarget;
class cmNinjaUtilityTargetGenerator : public cmNinjaTargetGenerator
{
public:
- cmNinjaUtilityTargetGenerator(cmTarget* target);
- ~cmNinjaUtilityTargetGenerator();
+ cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target);
+ ~cmNinjaUtilityTargetGenerator() CM_OVERRIDE;
- void Generate();
+ void Generate() CM_OVERRIDE;
};
#endif // ! cmNinjaUtilityTargetGenerator_h
diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx
index a475c7cfa..beddc6e6d 100644
--- a/Source/cmOSXBundleGenerator.cxx
+++ b/Source/cmOSXBundleGenerator.cxx
@@ -1,105 +1,109 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Nicolas Despres <nicolas.despres@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmOSXBundleGenerator.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmOSXBundleGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmLocalGenerator.h"
#include <cassert>
-//----------------------------------------------------------------------------
-cmOSXBundleGenerator::
-cmOSXBundleGenerator(cmTarget* target,
- const char* configName)
- : Target(target)
- , Makefile(target->GetMakefile())
- , LocalGenerator(Makefile->GetLocalGenerator())
- , ConfigName(configName)
- , MacContentFolders(0)
+class cmSourceFile;
+
+cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
+ const std::string& configName)
+ : GT(target)
+ , Makefile(target->Target->GetMakefile())
+ , LocalGenerator(target->GetLocalGenerator())
+ , ConfigName(configName)
+ , MacContentFolders(CM_NULLPTR)
{
- if (this->MustSkip())
+ if (this->MustSkip()) {
return;
-
+ }
}
-//----------------------------------------------------------------------------
bool cmOSXBundleGenerator::MustSkip()
{
- return !this->Target->HaveWellDefinedOutputFiles();
+ return !this->GT->HaveWellDefinedOutputFiles();
}
-//----------------------------------------------------------------------------
void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
std::string& outpath)
{
- if (this->MustSkip())
+ if (this->MustSkip()) {
return;
+ }
// Compute bundle directory names.
std::string out = outpath;
out += "/";
- out += this->Target->GetAppBundleDirectory(this->ConfigName, false);
+ out += this->GT->GetAppBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::FullLevel);
cmSystemTools::MakeDirectory(out.c_str());
this->Makefile->AddCMakeOutputFile(out);
- std::string newoutpath = out;
-
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
std::string plist = outpath;
plist += "/";
- plist += this->Target->GetAppBundleDirectory(this->ConfigName, true);
+ plist += this->GT->GetAppBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::ContentLevel);
plist += "/Info.plist";
- this->LocalGenerator->GenerateAppleInfoPList(this->Target,
- targetName.c_str(),
+ this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName,
plist.c_str());
this->Makefile->AddCMakeOutputFile(plist);
- outpath = newoutpath;
+ outpath = out;
}
-//----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateFramework(
- const std::string& targetName, const std::string& outpath)
+void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
+ const std::string& outpath)
{
- if (this->MustSkip())
+ if (this->MustSkip()) {
return;
+ }
assert(this->MacContentFolders);
// Compute the location of the top-level foo.framework directory.
std::string contentdir = outpath + "/" +
- this->Target->GetFrameworkDirectory(this->ConfigName, true);
+ this->GT->GetFrameworkDirectory(this->ConfigName,
+ cmGeneratorTarget::ContentLevel);
contentdir += "/";
std::string newoutpath = outpath + "/" +
- this->Target->GetFrameworkDirectory(this->ConfigName, false);
+ this->GT->GetFrameworkDirectory(this->ConfigName,
+ cmGeneratorTarget::FullLevel);
- std::string frameworkVersion = this->Target->GetFrameworkVersion();
+ std::string frameworkVersion = this->GT->GetFrameworkVersion();
- // Configure the Info.plist file into the Resources directory.
- this->MacContentFolders->insert("Resources");
+ // Configure the Info.plist file
std::string plist = newoutpath;
- plist += "/Resources/Info.plist";
+ if (!this->Makefile->PlatformIsAppleIos()) {
+ // 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->Target,
- name.c_str(),
+ this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name,
plist.c_str());
+ // Generate Versions directory only for MacOSX frameworks
+ if (this->Makefile->PlatformIsAppleIos()) {
+ return;
+ }
+
// TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
// drive rules to create these files at build time.
std::string oldName;
std::string newName;
-
// Make foo.framework/Versions
std::string versions = contentdir;
versions += "Versions";
@@ -112,8 +116,8 @@ void cmOSXBundleGenerator::CreateFramework(
oldName = frameworkVersion;
newName = versions;
newName += "/Current";
- cmSystemTools::RemoveFile(newName.c_str());
- cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+ cmSystemTools::RemoveFile(newName);
+ cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
// foo -> Versions/Current/foo
@@ -121,102 +125,95 @@ void cmOSXBundleGenerator::CreateFramework(
oldName += name;
newName = contentdir;
newName += name;
- cmSystemTools::RemoveFile(newName.c_str());
- cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+ cmSystemTools::RemoveFile(newName);
+ cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
// Resources -> Versions/Current/Resources
- if(this->MacContentFolders->find("Resources") !=
- this->MacContentFolders->end())
- {
+ if (this->MacContentFolders->find("Resources") !=
+ this->MacContentFolders->end()) {
oldName = "Versions/Current/Resources";
newName = contentdir;
newName += "Resources";
- cmSystemTools::RemoveFile(newName.c_str());
- cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+ cmSystemTools::RemoveFile(newName);
+ cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
- }
+ }
// Headers -> Versions/Current/Headers
- if(this->MacContentFolders->find("Headers") !=
- this->MacContentFolders->end())
- {
+ if (this->MacContentFolders->find("Headers") !=
+ this->MacContentFolders->end()) {
oldName = "Versions/Current/Headers";
newName = contentdir;
newName += "Headers";
- cmSystemTools::RemoveFile(newName.c_str());
- cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+ cmSystemTools::RemoveFile(newName);
+ cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
- }
+ }
// PrivateHeaders -> Versions/Current/PrivateHeaders
- if(this->MacContentFolders->find("PrivateHeaders") !=
- this->MacContentFolders->end())
- {
+ if (this->MacContentFolders->find("PrivateHeaders") !=
+ this->MacContentFolders->end()) {
oldName = "Versions/Current/PrivateHeaders";
newName = contentdir;
newName += "PrivateHeaders";
- cmSystemTools::RemoveFile(newName.c_str());
- cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
+ cmSystemTools::RemoveFile(newName);
+ cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
const std::string& root)
{
- if (this->MustSkip())
+ if (this->MustSkip()) {
return;
+ }
// Compute bundle directory names.
std::string out = root;
out += "/";
- out += this->Target->GetCFBundleDirectory(this->ConfigName, false);
+ out += this->GT->GetCFBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::FullLevel);
cmSystemTools::MakeDirectory(out.c_str());
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
- std::string plist =
- this->Target->GetCFBundleDirectory(this->ConfigName, true);
+ std::string plist = root + "/" +
+ this->GT->GetCFBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::ContentLevel);
plist += "/Info.plist";
- this->LocalGenerator->GenerateAppleInfoPList(this->Target,
- targetName.c_str(),
- plist.c_str());
+ std::string name = cmSystemTools::GetFilenameName(targetName);
+ this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str());
this->Makefile->AddCMakeOutputFile(plist);
}
-//----------------------------------------------------------------------------
-void
-cmOSXBundleGenerator::
-GenerateMacOSXContentStatements(std::vector<cmSourceFile*> const& sources,
- MacOSXContentGeneratorType* generator)
+void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
+ std::vector<cmSourceFile const*> const& sources,
+ MacOSXContentGeneratorType* generator)
{
- if (this->MustSkip())
+ if (this->MustSkip()) {
return;
+ }
- for(std::vector<cmSourceFile*>::const_iterator
- si = sources.begin(); si != sources.end(); ++si)
- {
- cmTarget::SourceFileFlags tsFlags =
- this->Target->GetTargetSourceFileFlags(*si);
- if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
- {
+ for (std::vector<cmSourceFile const*>::const_iterator si = sources.begin();
+ si != sources.end(); ++si) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ this->GT->GetTargetSourceFileFlags(*si);
+ if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
(*generator)(**si, tsFlags.MacFolder);
- }
}
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
+std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
+ const char* pkgloc)
{
// Construct the full path to the content subdirectory.
- std::string macdir =
- this->Target->GetMacContentDirectory(this->ConfigName,
- /*implib*/ false);
+ std::string macdir = this->GT->GetMacContentDirectory(
+ this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
macdir += "/";
macdir += pkgloc;
cmSystemTools::MakeDirectory(macdir.c_str());
@@ -224,9 +221,9 @@ cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
// Record use of this content location. Only the first level
// directory is needed.
{
- std::string loc = pkgloc;
- loc = loc.substr(0, loc.find('/'));
- this->MacContentFolders->insert(loc);
+ std::string loc = pkgloc;
+ loc = loc.substr(0, loc.find('/'));
+ this->MacContentFolders->insert(loc);
}
return macdir;
diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h
index ec82b9a15..be7e932f9 100644
--- a/Source/cmOSXBundleGenerator.h
+++ b/Source/cmOSXBundleGenerator.h
@@ -1,69 +1,61 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Nicolas Despres <nicolas.despres@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmOSXBundleGenerator_h
#define cmOSXBundleGenerator_h
-#include "cmStandardIncludes.h"
-#include "cmSourceFile.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <string>
#include <set>
+#include <string>
+#include <vector>
-class cmTarget;
-class cmMakefile;
+class cmGeneratorTarget;
class cmLocalGenerator;
+class cmMakefile;
+class cmSourceFile;
class cmOSXBundleGenerator
{
public:
- cmOSXBundleGenerator(cmTarget* target,
- const char* configName);
+ cmOSXBundleGenerator(cmGeneratorTarget* target,
+ const std::string& configName);
// create an app bundle at a given root, and return
// the directory within the bundle that contains the executable
void CreateAppBundle(const std::string& targetName, std::string& root);
// create a framework at a given root
- void CreateFramework(const std::string& targetName,
- const std::string& root);
+ void CreateFramework(const std::string& targetName, const std::string& root);
// create a cf bundle at a given root
- void CreateCFBundle(const std::string& targetName,
- const std::string& root);
+ void CreateCFBundle(const std::string& targetName, const std::string& root);
struct MacOSXContentGeneratorType
{
virtual ~MacOSXContentGeneratorType() {}
- virtual void operator()(cmSourceFile& source, const char* pkgloc) = 0;
+ virtual void operator()(cmSourceFile const& source,
+ const char* pkgloc) = 0;
};
void GenerateMacOSXContentStatements(
- std::vector<cmSourceFile*> const& sources,
+ std::vector<cmSourceFile const*> const& sources,
MacOSXContentGeneratorType* generator);
std::string InitMacOSXContentDirectory(const char* pkgloc);
- void SetMacContentFolders(std::set<cmStdString>* macContentFolders)
- { this->MacContentFolders = macContentFolders; }
+ void SetMacContentFolders(std::set<std::string>* macContentFolders)
+ {
+ this->MacContentFolders = macContentFolders;
+ }
private:
bool MustSkip();
private:
- cmTarget* Target;
+ cmGeneratorTarget* GT;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
- const char* ConfigName;
- std::set<cmStdString>* MacContentFolders;
+ std::string ConfigName;
+ std::set<std::string>* MacContentFolders;
};
-
#endif
diff --git a/Source/cmObject.h b/Source/cmObject.h
deleted file mode 100644
index ca6a54fd0..000000000
--- a/Source/cmObject.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmObject_h
-#define cmObject_h
-
-#include "cmStandardIncludes.h"
-
-/** \class cmObject
- * \brief Superclass for all commands and other classes in CMake.
- *
- * cmObject is the base class for all classes in CMake. It defines some
- * methods such as GetNameOfClass, IsA, SafeDownCast.
- */
-class cmObject
-{
-public:
- /**
- * Need virtual destructor to destroy real command type.
- */
- virtual ~cmObject() {}
-
- /**
- * The class name of the command.
- */
- virtual const char* GetNameOfClass() = 0;
-
- /**
- * Returns true if this class is the given class, or a subclass of it.
- */
- static bool IsTypeOf(const char *type)
- { return !strcmp("cmObject", type); }
-
- /**
- * Returns true if this object is an instance of the given class or
- * a subclass of it.
- */
- virtual bool IsA(const char *type)
- { return cmObject::IsTypeOf(type); }
-};
-
-#endif
-
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index 776a3a443..00a2d2bce 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -1,71 +1,56 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmOptionCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmOptionCommand.h"
+class cmExecutionStatus;
// cmOptionCommand
-bool cmOptionCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmOptionCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
bool argError = false;
- if(args.size() < 2)
- {
+ 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)
- {
+ if (this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
+ if (args.size() > 3) {
argError = true;
- }
}
- if(argError)
- {
+ }
+ if (argError) {
std::string m = "called with incorrect number of arguments: ";
- for(size_t i =0; i < args.size(); ++i)
- {
- m += args[i];
- m += " ";
- }
- this->SetError(m.c_str());
+ m += cmJoin(args, " ");
+ this->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
- cmCacheManager::CacheIterator it =
- this->Makefile->GetCacheManager()->GetCacheIterator(args[0].c_str());
- if(!it.IsAtEnd())
- {
- if ( it.GetType() != cmCacheManager::UNINITIALIZED )
- {
- it.SetProperty("HELPSTRING", args[1].c_str());
+ 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;
- }
- if ( it.GetValue() )
- {
- initialValue = it.GetValue();
- }
}
- if(args.size() == 3)
- {
+ initialValue = existingValue;
+ }
+ if (args.size() == 3) {
initialValue = args[2];
- }
+ }
bool init = cmSystemTools::IsOn(initialValue.c_str());
- this->Makefile->AddCacheDefinition(args[0].c_str(), init? "ON":"OFF",
- args[1].c_str(), cmCacheManager::BOOL);
+ this->Makefile->AddCacheDefinition(args[0], init ? "ON" : "OFF",
+ args[1].c_str(), cmStateEnums::BOOL);
return true;
}
diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h
index 7d0240050..634e3a824 100644
--- a/Source/cmOptionCommand.h
+++ b/Source/cmOptionCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmOptionCommand_h
#define cmOptionCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmOptionCommand
* \brief Provide an option to the user
*
@@ -25,54 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmOptionCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmOptionCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "option";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Provides an option that the user can optionally select.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " option(<option_variable> \"help string describing option\"\n"
- " [initial value])\n"
- "Provide an option for the user to select as ON or OFF. If no "
- "initial value is provided, OFF is used.\n"
- "If you have options that depend on the values of other "
- "options, see the module help for CMakeDependentOption."
- ;
- }
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- cmTypeMacro(cmOptionCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 022082519..333e3134c 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -1,23 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmOrderDirectories.h"
+#include "cmAlgorithms.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include <assert.h>
-
#include <algorithm>
+#include <assert.h>
+#include <functional>
+#include <sstream>
/*
Directory ordering computation.
@@ -27,84 +21,80 @@ Directory ordering computation.
for shared libraries.
*/
-//----------------------------------------------------------------------------
class cmOrderDirectoriesConstraint
{
public:
- cmOrderDirectoriesConstraint(cmOrderDirectories* od,
- std::string const& file):
- OD(od), GlobalGenerator(od->GlobalGenerator)
- {
+ cmOrderDirectoriesConstraint(cmOrderDirectories* od, std::string const& file)
+ : OD(od)
+ , GlobalGenerator(od->GlobalGenerator)
+ {
this->FullPath = file;
- if(file.rfind(".framework") != std::string::npos)
- {
- cmsys::RegularExpression splitFramework;
- splitFramework.compile("^(.*)/(.*).framework/(.*)$");
- if(splitFramework.find(file) &&
- (std::string::npos !=
- splitFramework.match(3).find(splitFramework.match(2))))
- {
+ if (file.rfind(".framework") != std::string::npos) {
+ static cmsys::RegularExpression splitFramework(
+ "^(.*)/(.*).framework/(.*)$");
+ if (splitFramework.find(file) &&
+ (std::string::npos !=
+ splitFramework.match(3).find(splitFramework.match(2)))) {
this->Directory = splitFramework.match(1);
this->FileName =
std::string(file.begin() + this->Directory.size() + 1, file.end());
- }
}
+ }
- if(this->FileName.empty())
- {
+ if (this->FileName.empty()) {
this->Directory = cmSystemTools::GetFilenamePath(file);
this->FileName = cmSystemTools::GetFilenameName(file);
- }
}
+ }
virtual ~cmOrderDirectoriesConstraint() {}
void AddDirectory()
- {
+ {
this->DirectoryIndex = this->OD->AddOriginalDirectory(this->Directory);
- }
+ }
virtual void Report(std::ostream& e) = 0;
void FindConflicts(unsigned int index)
- {
- for(unsigned int i=0; i < this->OD->OriginalDirectories.size(); ++i)
- {
+ {
+ for (unsigned int i = 0; i < this->OD->OriginalDirectories.size(); ++i) {
// Check if this directory conflicts with the entry.
std::string const& dir = this->OD->OriginalDirectories[i];
- if(dir != this->Directory && this->FindConflict(dir))
- {
+ if (!this->OD->IsSameDirectory(dir, this->Directory) &&
+ this->FindConflict(dir)) {
// The library will be found in this directory but this is not
// the directory named for it. Add an entry to make sure the
// desired directory comes before this one.
cmOrderDirectories::ConflictPair p(this->DirectoryIndex, index);
this->OD->ConflictGraph[i].push_back(p);
- }
}
}
+ }
- void FindImplicitConflicts(cmOStringStream& w)
- {
+ void FindImplicitConflicts(std::ostringstream& w)
+ {
bool first = true;
- for(unsigned int i=0; i < this->OD->OriginalDirectories.size(); ++i)
- {
+ for (unsigned int i = 0; i < this->OD->OriginalDirectories.size(); ++i) {
// Check if this directory conflicts with the entry.
std::string const& dir = this->OD->OriginalDirectories[i];
- if(dir != this->Directory && this->FindConflict(dir))
- {
+ if (dir != this->Directory &&
+ cmSystemTools::GetRealPath(dir) !=
+ cmSystemTools::GetRealPath(this->Directory) &&
+ this->FindConflict(dir)) {
// The library will be found in this directory but it is
// supposed to be found in an implicit search directory.
- if(first)
- {
+ if (first) {
first = false;
w << " ";
this->Report(w);
w << " in " << this->Directory << " may be hidden by files in:\n";
- }
- w << " " << dir << "\n";
}
+ w << " " << dir << "\n";
}
}
+ }
+
protected:
virtual bool FindConflict(std::string const& dir) = 0;
@@ -122,7 +112,6 @@ protected:
int DirectoryIndex;
};
-//----------------------------------------------------------------------------
bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
std::string const& name)
{
@@ -130,150 +119,130 @@ bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
std::string file = dir;
file += "/";
file += name;
- if(cmSystemTools::FileExists(file.c_str(), true))
- {
+ if (cmSystemTools::FileExists(file.c_str(), 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.c_str(), file.c_str());
- }
+ return !cmSystemTools::SameFile(this->FullPath, file);
+ }
// Check if the file will be built by cmake.
- std::set<cmStdString> const& files =
+ std::set<std::string> const& files =
(this->GlobalGenerator->GetDirectoryContent(dir, false));
- std::set<cmStdString>::const_iterator fi = files.find(name);
+ std::set<std::string>::const_iterator fi = files.find(name);
return fi != files.end();
}
-//----------------------------------------------------------------------------
-class cmOrderDirectoriesConstraintSOName: public cmOrderDirectoriesConstraint
+class cmOrderDirectoriesConstraintSOName : public cmOrderDirectoriesConstraint
{
public:
cmOrderDirectoriesConstraintSOName(cmOrderDirectories* od,
std::string const& file,
- const char* soname):
- cmOrderDirectoriesConstraint(od, file), SOName(soname? soname : "")
- {
- if(this->SOName.empty())
- {
+ const char* soname)
+ : cmOrderDirectoriesConstraint(od, file)
+ , SOName(soname ? soname : "")
+ {
+ if (this->SOName.empty()) {
// Try to guess the soname.
std::string soguess;
- if(cmSystemTools::GuessLibrarySOName(file, soguess))
- {
+ if (cmSystemTools::GuessLibrarySOName(file, soguess)) {
this->SOName = soguess;
- }
}
}
+ }
- virtual void Report(std::ostream& e)
- {
+ void Report(std::ostream& e) CM_OVERRIDE
+ {
e << "runtime library [";
- if(this->SOName.empty())
- {
+ if (this->SOName.empty()) {
e << this->FileName;
- }
- else
- {
+ } else {
e << this->SOName;
- }
- e << "]";
}
+ e << "]";
+ }
+
+ bool FindConflict(std::string const& dir) CM_OVERRIDE;
- virtual bool FindConflict(std::string const& dir);
private:
// The soname of the shared library if it is known.
std::string SOName;
};
-//----------------------------------------------------------------------------
bool cmOrderDirectoriesConstraintSOName::FindConflict(std::string const& dir)
{
// Determine which type of check to do.
- if(!this->SOName.empty())
- {
+ if (!this->SOName.empty()) {
// We have the library soname. Check if it will be found.
- if(this->FileMayConflict(dir, this->SOName))
- {
+ if (this->FileMayConflict(dir, this->SOName)) {
return true;
- }
}
- else
- {
+ } else {
// We do not have the soname. Look for files in the directory
// that may conflict.
- std::set<cmStdString> const& files =
- (this->GlobalGenerator
- ->GetDirectoryContent(dir, true));
+ std::set<std::string> const& files =
+ (this->GlobalGenerator->GetDirectoryContent(dir, true));
// Get the set of files that might conflict. Since we do not
// 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<cmStdString>::const_iterator first = files.lower_bound(base);
- ++base[base.size()-1];
- std::set<cmStdString>::const_iterator last = files.upper_bound(base);
- if(first != last)
- {
+ 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);
+ if (first != last) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
-class cmOrderDirectoriesConstraintLibrary: public cmOrderDirectoriesConstraint
+class cmOrderDirectoriesConstraintLibrary : public cmOrderDirectoriesConstraint
{
public:
cmOrderDirectoriesConstraintLibrary(cmOrderDirectories* od,
- std::string const& file):
- cmOrderDirectoriesConstraint(od, file)
- {
- }
+ std::string const& file)
+ : cmOrderDirectoriesConstraint(od, file)
+ {
+ }
- virtual void Report(std::ostream& e)
- {
+ void Report(std::ostream& e) CM_OVERRIDE
+ {
e << "link library [" << this->FileName << "]";
- }
+ }
- virtual bool FindConflict(std::string const& dir);
+ bool FindConflict(std::string const& dir) CM_OVERRIDE;
};
-//----------------------------------------------------------------------------
bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir)
{
// We have the library file name. Check if it will be found.
- if(this->FileMayConflict(dir, this->FileName))
- {
+ if (this->FileMayConflict(dir, this->FileName)) {
return true;
- }
+ }
// Now check if the file exists with other extensions the linker
// might consider.
- if(!this->OD->LinkExtensions.empty() &&
- this->OD->RemoveLibraryExtension.find(this->FileName))
- {
- cmStdString lib = this->OD->RemoveLibraryExtension.match(1);
- cmStdString 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)
- {
+ if (!this->OD->LinkExtensions.empty() &&
+ 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;
- if(this->FileMayConflict(dir, fname.c_str()))
- {
+ if (this->FileMayConflict(dir, fname)) {
return true;
- }
}
}
}
+ }
return false;
}
-//----------------------------------------------------------------------------
cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg,
- cmTarget* target,
+ const cmGeneratorTarget* target,
const char* purpose)
{
this->GlobalGenerator = gg;
@@ -282,147 +251,122 @@ cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg,
this->Computed = false;
}
-//----------------------------------------------------------------------------
cmOrderDirectories::~cmOrderDirectories()
{
- for(std::vector<cmOrderDirectoriesConstraint*>::iterator
- i = this->ConstraintEntries.begin();
- i != this->ConstraintEntries.end(); ++i)
- {
- delete *i;
- }
- for(std::vector<cmOrderDirectoriesConstraint*>::iterator
- i = this->ImplicitDirEntries.begin();
- i != this->ImplicitDirEntries.end(); ++i)
- {
- delete *i;
- }
+ cmDeleteAll(this->ConstraintEntries);
+ cmDeleteAll(this->ImplicitDirEntries);
}
-//----------------------------------------------------------------------------
std::vector<std::string> const& cmOrderDirectories::GetOrderedDirectories()
{
- if(!this->Computed)
- {
+ if (!this->Computed) {
this->Computed = true;
this->CollectOriginalDirectories();
this->FindConflicts();
this->OrderDirectories();
- }
+ }
return this->OrderedDirectories;
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath,
const char* soname)
{
// Add the runtime library at most once.
- if(this->EmmittedConstraintSOName.insert(fullPath).second)
- {
+ if (this->EmmittedConstraintSOName.insert(fullPath).second) {
// Implicit link directories need special handling.
- if(!this->ImplicitDirectories.empty())
- {
+ if (!this->ImplicitDirectories.empty()) {
std::string dir = cmSystemTools::GetFilenamePath(fullPath);
- if(fullPath.rfind(".framework") != std::string::npos)
- {
- cmsys::RegularExpression splitFramework;
- splitFramework.compile("^(.*)/(.*).framework/(.*)$");
- if(splitFramework.find(fullPath) &&
- (std::string::npos !=
- splitFramework.match(3).find(splitFramework.match(2))))
- {
+ if (fullPath.rfind(".framework") != std::string::npos) {
+ static cmsys::RegularExpression splitFramework(
+ "^(.*)/(.*).framework/(.*)$");
+ if (splitFramework.find(fullPath) &&
+ (std::string::npos !=
+ splitFramework.match(3).find(splitFramework.match(2)))) {
dir = splitFramework.match(1);
- }
}
+ }
- if(this->ImplicitDirectories.find(dir) !=
- this->ImplicitDirectories.end())
- {
+ if (this->IsImplicitDirectory(dir)) {
this->ImplicitDirEntries.push_back(
new cmOrderDirectoriesConstraintSOName(this, fullPath, soname));
return;
- }
}
+ }
// Construct the runtime information entry for this library.
this->ConstraintEntries.push_back(
new cmOrderDirectoriesConstraintSOName(this, fullPath, soname));
- }
- else
- {
+ } else {
// This can happen if the same library is linked multiple times.
// In that case the runtime information check need be done only
// once anyway. For shared libs we could add a check in AddItem
// to not repeat them.
- }
+ }
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath)
{
// Link extension info is required for library constraints.
assert(!this->LinkExtensions.empty());
// Add the link library at most once.
- if(this->EmmittedConstraintLibrary.insert(fullPath).second)
- {
+ if (this->EmmittedConstraintLibrary.insert(fullPath).second) {
// Implicit link directories need special handling.
- if(!this->ImplicitDirectories.empty())
- {
+ if (!this->ImplicitDirectories.empty()) {
std::string dir = cmSystemTools::GetFilenamePath(fullPath);
- if(this->ImplicitDirectories.find(dir) !=
- this->ImplicitDirectories.end())
- {
+ if (this->IsImplicitDirectory(dir)) {
this->ImplicitDirEntries.push_back(
new cmOrderDirectoriesConstraintLibrary(this, fullPath));
return;
- }
}
+ }
// Construct the link library entry.
this->ConstraintEntries.push_back(
new cmOrderDirectoriesConstraintLibrary(this, fullPath));
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmOrderDirectories
-::AddUserDirectories(std::vector<std::string> const& extra)
+void cmOrderDirectories::AddUserDirectories(
+ std::vector<std::string> const& extra)
{
- this->UserDirectories.insert(this->UserDirectories.end(),
- extra.begin(), extra.end());
+ this->UserDirectories.insert(this->UserDirectories.end(), extra.begin(),
+ extra.end());
}
-//----------------------------------------------------------------------------
-void
-cmOrderDirectories
-::AddLanguageDirectories(std::vector<std::string> const& dirs)
+void cmOrderDirectories::AddLanguageDirectories(
+ std::vector<std::string> const& dirs)
{
this->LanguageDirectories.insert(this->LanguageDirectories.end(),
dirs.begin(), dirs.end());
}
-//----------------------------------------------------------------------------
-void
-cmOrderDirectories
-::SetImplicitDirectories(std::set<cmStdString> const& implicitDirs)
+void cmOrderDirectories::SetImplicitDirectories(
+ std::set<std::string> const& implicitDirs)
{
- this->ImplicitDirectories = implicitDirs;
+ this->ImplicitDirectories.clear();
+ for (std::set<std::string>::const_iterator i = implicitDirs.begin();
+ i != implicitDirs.end(); ++i) {
+ this->ImplicitDirectories.insert(this->GetRealPath(*i));
+ }
}
-//----------------------------------------------------------------------------
-void
-cmOrderDirectories
-::SetLinkExtensionInfo(std::vector<std::string> const& linkExtensions,
- std::string const& removeExtRegex)
+bool cmOrderDirectories::IsImplicitDirectory(std::string const& dir)
+{
+ std::string const& real = this->GetRealPath(dir);
+ return this->ImplicitDirectories.find(real) !=
+ this->ImplicitDirectories.end();
+}
+
+void cmOrderDirectories::SetLinkExtensionInfo(
+ std::vector<std::string> const& linkExtensions,
+ std::string const& removeExtRegex)
{
this->LinkExtensions = linkExtensions;
this->RemoveLibraryExtension.compile(removeExtRegex.c_str());
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::CollectOriginalDirectories()
{
// Add user directories specified for inclusion. These should be
@@ -431,59 +375,48 @@ void cmOrderDirectories::CollectOriginalDirectories()
this->AddOriginalDirectories(this->UserDirectories);
// Add directories containing constraints.
- for(unsigned int i=0; i < this->ConstraintEntries.size(); ++i)
- {
+ for (unsigned int i = 0; i < this->ConstraintEntries.size(); ++i) {
this->ConstraintEntries[i]->AddDirectory();
- }
+ }
// Add language runtime directories last.
this->AddOriginalDirectories(this->LanguageDirectories);
}
-//----------------------------------------------------------------------------
int cmOrderDirectories::AddOriginalDirectory(std::string const& dir)
{
// Add the runtime directory with a unique index.
- std::map<cmStdString, int>::iterator i =
- this->DirectoryIndex.find(dir);
- if(i == this->DirectoryIndex.end())
- {
- std::map<cmStdString, int>::value_type
- entry(dir, static_cast<int>(this->OriginalDirectories.size()));
+ std::map<std::string, int>::iterator 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()));
i = this->DirectoryIndex.insert(entry).first;
this->OriginalDirectories.push_back(dir);
- }
+ }
return i->second;
}
-//----------------------------------------------------------------------------
-void
-cmOrderDirectories
-::AddOriginalDirectories(std::vector<std::string> const& dirs)
+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::vector<std::string>::const_iterator di = dirs.begin();
+ di != dirs.end(); ++di) {
// We never explicitly specify implicit link directories.
- if(this->ImplicitDirectories.find(*di) !=
- this->ImplicitDirectories.end())
- {
+ if (this->IsImplicitDirectory(*di)) {
continue;
- }
+ }
// Skip the empty string.
- if(di->empty())
- {
+ if (di->empty()) {
continue;
- }
+ }
// Add this directory.
this->AddOriginalDirectory(*di);
- }
+ }
}
-//----------------------------------------------------------------------------
struct cmOrderDirectoriesCompare
{
typedef std::pair<int, int> ConflictPair;
@@ -491,14 +424,12 @@ struct cmOrderDirectoriesCompare
// The conflict pair is unique based on just the directory
// (first). The second element is only used for displaying
// information about why the entry is present.
- bool operator()(ConflictPair const& l,
- ConflictPair const& r)
- {
+ bool operator()(ConflictPair l, ConflictPair r)
+ {
return l.first == r.first;
- }
+ }
};
-//----------------------------------------------------------------------------
void cmOrderDirectories::FindConflicts()
{
// Allocate the conflict graph.
@@ -506,16 +437,13 @@ void cmOrderDirectories::FindConflicts()
this->DirectoryVisited.resize(this->OriginalDirectories.size(), 0);
// Find directories conflicting with each entry.
- for(unsigned int i=0; i < this->ConstraintEntries.size(); ++i)
- {
+ for (unsigned int i = 0; i < this->ConstraintEntries.size(); ++i) {
this->ConstraintEntries[i]->FindConflicts(i);
- }
+ }
// Clean up the conflict graph representation.
- for(std::vector<ConflictList>::iterator
- i = this->ConflictGraph.begin();
- i != this->ConflictGraph.end(); ++i)
- {
+ for (std::vector<ConflictList>::iterator i = this->ConflictGraph.begin();
+ i != this->ConflictGraph.end(); ++i) {
// 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());
@@ -524,43 +452,38 @@ void cmOrderDirectories::FindConflicts()
ConflictList::iterator last =
std::unique(i->begin(), i->end(), cmOrderDirectoriesCompare());
i->erase(last, i->end());
- }
+ }
// Check items in implicit link directories.
this->FindImplicitConflicts();
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::FindImplicitConflicts()
{
// Check for items in implicit link directories that have conflicts
// in the explicit directories.
- cmOStringStream conflicts;
- for(unsigned int i=0; i < this->ImplicitDirEntries.size(); ++i)
- {
+ std::ostringstream conflicts;
+ for (unsigned int i = 0; i < this->ImplicitDirEntries.size(); ++i) {
this->ImplicitDirEntries[i]->FindImplicitConflicts(conflicts);
- }
+ }
// Skip warning if there were no conflicts.
std::string text = conflicts.str();
- if(text.empty())
- {
+ if (text.empty()) {
return;
- }
+ }
// Warn about the conflicts.
- cmOStringStream w;
- w << "Cannot generate a safe " << this->Purpose
- << " for target " << this->Target->GetName()
+ 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());
+ << text << "Some of these libraries may not be found correctly.";
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::WARNING, w.str(), this->Target->GetBacktrace());
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::OrderDirectories()
{
// Allow a cycle to be diagnosed once.
@@ -568,75 +491,84 @@ void cmOrderDirectories::OrderDirectories()
this->WalkId = 0;
// Iterate through the directories in the original order.
- for(unsigned int i=0; i < this->OriginalDirectories.size(); ++i)
- {
+ for (unsigned int i = 0; i < this->OriginalDirectories.size(); ++i) {
// Start a new DFS from this node.
++this->WalkId;
this->VisitDirectory(i);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::VisitDirectory(unsigned int i)
{
// Skip nodes already visited.
- if(this->DirectoryVisited[i])
- {
- if(this->DirectoryVisited[i] == this->WalkId)
- {
+ if (this->DirectoryVisited[i]) {
+ if (this->DirectoryVisited[i] == this->WalkId) {
// We have reached a node previously visited on this DFS.
// There is a cycle.
this->DiagnoseCycle();
- }
- return;
}
+ return;
+ }
// We are now visiting this node so mark it.
this->DirectoryVisited[i] = this->WalkId;
// Visit the neighbors of the node first.
ConflictList const& clist = this->ConflictGraph[i];
- for(ConflictList::const_iterator j = clist.begin();
- j != clist.end(); ++j)
- {
+ for (ConflictList::const_iterator j = clist.begin(); j != clist.end(); ++j) {
this->VisitDirectory(j->first);
- }
+ }
// Now that all directories required to come before this one have
// been emmitted, emit this directory.
this->OrderedDirectories.push_back(this->OriginalDirectories[i]);
}
-//----------------------------------------------------------------------------
void cmOrderDirectories::DiagnoseCycle()
{
// Report the cycle at most once.
- if(this->CycleDiagnosed)
- {
+ if (this->CycleDiagnosed) {
return;
- }
+ }
this->CycleDiagnosed = true;
// Construct the message.
- cmOStringStream e;
- e << "Cannot generate a safe " << this->Purpose
- << " for target " << this->Target->GetName()
+ std::ostringstream e;
+ e << "Cannot generate a safe " << this->Purpose << " for target "
+ << this->Target->GetName()
<< " because there is a cycle in the constraint graph:\n";
// Display the conflict graph.
- for(unsigned int i=0; i < this->ConflictGraph.size(); ++i)
- {
+ 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)
- {
+ 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);
e << "\n";
- }
}
+ }
e << "Some of these libraries may not be found correctly.";
- this->GlobalGenerator->GetCMakeInstance()
- ->IssueMessage(cmake::WARNING, e.str(), this->Target->GetBacktrace());
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::WARNING, e.str(), this->Target->GetBacktrace());
+}
+
+bool cmOrderDirectories::IsSameDirectory(std::string const& l,
+ std::string const& r)
+{
+ return this->GetRealPath(l) == this->GetRealPath(r);
+}
+
+std::string const& cmOrderDirectories::GetRealPath(std::string const& dir)
+{
+ std::map<std::string, std::string>::iterator 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;
+ i = this->RealPaths.insert(
+ i, value_type(dir, cmSystemTools::GetRealPath(dir)));
+ }
+ return i->second;
}
diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h
index 96a75de17..3a0637afb 100644
--- a/Source/cmOrderDirectories.h
+++ b/Source/cmOrderDirectories.h
@@ -1,25 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmOrderDirectories_h
#define cmOrderDirectories_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+class cmGeneratorTarget;
class cmGlobalGenerator;
class cmOrderDirectoriesConstraint;
-class cmOrderDirectoriesConstraintLibrary;
-class cmTarget;
/** \class cmOrderDirectories
* \brief Compute a safe runtime path order for a set of shared libraries.
@@ -27,25 +22,25 @@ class cmTarget;
class cmOrderDirectories
{
public:
- cmOrderDirectories(cmGlobalGenerator* gg, cmTarget* target,
+ cmOrderDirectories(cmGlobalGenerator* gg, cmGeneratorTarget const* target,
const char* purpose);
~cmOrderDirectories();
- void AddRuntimeLibrary(std::string const& fullPath, const char* soname = 0);
+ void AddRuntimeLibrary(std::string const& fullPath,
+ const char* soname = CM_NULLPTR);
void AddLinkLibrary(std::string const& fullPath);
void AddUserDirectories(std::vector<std::string> const& extra);
void AddLanguageDirectories(std::vector<std::string> const& dirs);
- void SetImplicitDirectories(std::set<cmStdString> const& implicitDirs);
+ void SetImplicitDirectories(std::set<std::string> const& implicitDirs);
void SetLinkExtensionInfo(std::vector<std::string> const& linkExtensions,
std::string const& removeExtRegex);
std::vector<std::string> const& GetOrderedDirectories();
+
private:
cmGlobalGenerator* GlobalGenerator;
- cmTarget* Target;
+ cmGeneratorTarget const* Target;
std::string Purpose;
- bool Computed;
-
std::vector<std::string> OrderedDirectories;
std::vector<cmOrderDirectoriesConstraint*> ConstraintEntries;
@@ -54,11 +49,11 @@ private:
std::vector<std::string> LanguageDirectories;
cmsys::RegularExpression RemoveLibraryExtension;
std::vector<std::string> LinkExtensions;
- std::set<cmStdString> ImplicitDirectories;
- std::set<cmStdString> EmmittedConstraintSOName;
- std::set<cmStdString> EmmittedConstraintLibrary;
+ std::set<std::string> ImplicitDirectories;
+ std::set<std::string> EmmittedConstraintSOName;
+ std::set<std::string> EmmittedConstraintLibrary;
std::vector<std::string> OriginalDirectories;
- std::map<cmStdString, int> DirectoryIndex;
+ std::map<std::string, int> DirectoryIndex;
std::vector<int> DirectoryVisited;
void CollectOriginalDirectories();
int AddOriginalDirectory(std::string const& dir);
@@ -68,8 +63,9 @@ private:
void OrderDirectories();
void VisitDirectory(unsigned int i);
void DiagnoseCycle();
- bool CycleDiagnosed;
int WalkId;
+ bool CycleDiagnosed;
+ bool Computed;
// Adjacency-list representation of runtime path ordering graph.
// This maps from directory to those that must come *before* it.
@@ -78,9 +74,19 @@ private:
// element is the index of the runtime library that added the
// constraint.
typedef std::pair<int, int> ConflictPair;
- struct ConflictList: public std::vector<ConflictPair> {};
+ struct ConflictList : public std::vector<ConflictPair>
+ {
+ };
std::vector<ConflictList> ConflictGraph;
+ // Compare directories after resolving symlinks.
+ bool IsSameDirectory(std::string const& l, std::string const& r);
+
+ bool IsImplicitDirectory(std::string const& dir);
+
+ std::string const& GetRealPath(std::string const& dir);
+ std::map<std::string, std::string> RealPaths;
+
friend class cmOrderDirectoriesConstraint;
friend class cmOrderDirectoriesConstraintLibrary;
};
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
new file mode 100644
index 000000000..14c986dd8
--- /dev/null
+++ b/Source/cmOutputConverter.cxx
@@ -0,0 +1,636 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmOutputConverter.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <ctype.h>
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include "cmAlgorithms.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmSystemTools.h"
+
+cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
+ : StateSnapshot(snapshot)
+ , LinkScriptShell(false)
+{
+ assert(this->StateSnapshot.IsValid());
+}
+
+std::string cmOutputConverter::ConvertToOutputForExisting(
+ const std::string& remote, OutputFormat format) const
+{
+ // If this is a windows shell, the result has a space, and the path
+ // already exists, we can use a short-path to reference it without a
+ // space.
+ if (this->GetState()->UseWindowsShell() &&
+ remote.find(' ') != std::string::npos &&
+ cmSystemTools::FileExists(remote.c_str())) {
+ std::string tmp;
+ if (cmSystemTools::GetShortPath(remote, tmp)) {
+ return this->ConvertToOutputFormat(tmp, format);
+ }
+ }
+
+ // Otherwise, perform standard conversion.
+ return this->ConvertToOutputFormat(remote, format);
+}
+
+std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
+ OutputFormat output) const
+{
+ std::string result = source;
+ // Convert it to an output path.
+ if (output == SHELL || output == WATCOMQUOTE) {
+ result = this->ConvertDirectorySeparatorsForShell(source);
+ result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE);
+ } else if (output == RESPONSE) {
+ result = this->EscapeForShell(result, false, false, false);
+ }
+ return result;
+}
+
+std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
+ const std::string& source) const
+{
+ 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.
+ if (this->GetState()->UseMSYSShell() && !this->LinkScriptShell) {
+ if (result.size() > 2 && result[1] == ':') {
+ result[1] = result[0];
+ result[0] = '/';
+ }
+ }
+ if (this->GetState()->UseWindowsShell()) {
+ std::replace(result.begin(), result.end(), '/', '\\');
+ }
+ return result;
+}
+
+static bool cmOutputConverterNotAbove(const char* a, const char* b)
+{
+ return (cmSystemTools::ComparePath(a, b) ||
+ cmSystemTools::IsSubDirectory(a, b));
+}
+
+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,
+ bool makeVars, bool forEcho,
+ bool useWatcomQuote) const
+{
+ // Do not escape shell operators.
+ if (cmOutputConverterIsShellOperator(str)) {
+ return str;
+ }
+
+ // Compute the flags for the target shell environment.
+ int flags = 0;
+ if (this->GetState()->UseWindowsVSIDE()) {
+ flags |= Shell_Flag_VSIDE;
+ } else if (!this->LinkScriptShell) {
+ flags |= Shell_Flag_Make;
+ }
+ if (makeVars) {
+ flags |= Shell_Flag_AllowMakeVariables;
+ }
+ if (forEcho) {
+ flags |= Shell_Flag_EchoWindows;
+ }
+ if (useWatcomQuote) {
+ flags |= Shell_Flag_WatcomQuote;
+ }
+ if (this->GetState()->UseWatcomWMake()) {
+ flags |= Shell_Flag_WatcomWMake;
+ }
+ if (this->GetState()->UseMinGWMake()) {
+ flags |= Shell_Flag_MinGWMake;
+ }
+ if (this->GetState()->UseNMake()) {
+ flags |= Shell_Flag_NMake;
+ }
+ if (!this->GetState()->UseWindowsShell()) {
+ flags |= Shell_Flag_IsUnix;
+ }
+
+ return Shell__GetArgument(str.c_str(), flags);
+}
+
+std::string cmOutputConverter::EscapeForCMake(const std::string& 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 == '"') {
+ // Escape the double quote to avoid ending the argument.
+ result += "\\\"";
+ } else if (*c == '$') {
+ // Escape the dollar to avoid expanding variables.
+ result += "\\$";
+ } else if (*c == '\\') {
+ // Escape the backslash to avoid other escapes.
+ result += "\\\\";
+ } else {
+ // Other characters will be parsed correctly.
+ result += *c;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg,
+ int shell_flags)
+{
+ return Shell__GetArgument(arg, shell_flags);
+}
+
+cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
+ const char* 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") {
+ format = FortranFormatFixed;
+ }
+ if (*fi == "FREE") {
+ format = FortranFormatFree;
+ }
+ }
+ }
+ return format;
+}
+
+void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
+{
+ this->LinkScriptShell = linkScriptShell;
+}
+
+cmState* cmOutputConverter::GetState() const
+{
+ return this->StateSnapshot.GetState();
+}
+
+/*
+
+Notes:
+
+Make variable replacements open a can of worms. Sometimes they should
+be quoted and sometimes not. Sometimes their replacement values are
+already quoted.
+
+VS variables cause problems. In order to pass the referenced value
+with spaces the reference must be quoted. If the variable value ends
+in a backslash then it will escape the ending quote! In order to make
+the ending backslash appear we need this:
+
+ "$(InputDir)\"
+
+However if there is not a trailing backslash then this will put a
+quote in the value so we need:
+
+ "$(InputDir)"
+
+Make variable references are platform specific so we should probably
+just NOT quote them and let the listfile author deal with it.
+
+*/
+
+/*
+TODO: For windows echo:
+
+To display a pipe (|) or redirection character (< or >) when using the
+echo command, use a caret character immediately before the pipe or
+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)
+{
+ return ((c == ' ') || (c == '\t'));
+}
+
+int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
+{
+ return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
+ (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
+ (c == '<') || (c == '>') || (c == '|') || (c == '*') || (c == '^') ||
+ (c == '\\'));
+}
+
+int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c)
+{
+ return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
+ (c == '>') || (c == '|') || (c == '^'));
+}
+
+int 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;
+ }
+
+ /* On all platforms quotes are needed to preserve whitespace. */
+ if (Shell__CharIsWhitespace(c)) {
+ return 1;
+ }
+
+ if (flags & Shell_Flag_IsUnix) {
+ /* On UNIX several special characters need quotes to preserve them. */
+ if (Shell__CharNeedsQuotesOnUnix(c)) {
+ return 1;
+ }
+ } else {
+ /* On Windows several special characters need quotes to preserve them. */
+ if (Shell__CharNeedsQuotesOnWindows(c)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int cmOutputConverter::Shell__CharIsMakeVariableName(char c)
+{
+ 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)) {
+ ++skip;
+ }
+ if (*skip == ')') {
+ c = skip + 1;
+ } else {
+ break;
+ }
+ }
+ return c;
+}
+
+/*
+Allowing make variable replacements opens a can of worms. Sometimes
+they should be quoted and sometimes not. Sometimes their replacement
+values are already quoted or contain escapes.
+
+Some Visual Studio variables cause problems. In order to pass the
+referenced value with spaces the reference must be quoted. If the
+variable value ends in a backslash then it will escape the ending
+quote! In order to make the ending backslash appear we need this:
+
+ "$(InputDir)\"
+
+However if there is not a trailing backslash then this will put a
+quote in the value so we need:
+
+ "$(InputDir)"
+
+This macro decides whether we quote an argument just because it
+contains a make variable reference. This should be replaced with a
+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)
+{
+ /* The empty string needs quotes. */
+ if (!*in) {
+ return 1;
+ }
+
+ /* 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) {
+#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;
+ }
+#else
+ /* Skip over the make variable references if any are present. */
+ c = Shell__SkipMakeVariables(c);
+
+ /* Stop if we have reached the end of the string. */
+ if (!*c) {
+ break;
+ }
+#endif
+ }
+
+ /* Check whether this character needs quotes. */
+ if (Shell__CharNeedsQuotes(*c, flags)) {
+ return 1;
+ }
+ }
+ }
+
+ /* On Windows some single character arguments need quotes. */
+ if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) {
+ char c = *in;
+ if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
+{
+ std::ostringstream out;
+
+ /* String iterator. */
+ const char* c;
+
+ /* Keep track of how many backslashes have been encountered in a row. */
+ int windows_backslashes = 0;
+
+ /* Whether the argument must be quoted. */
+ int needQuotes = Shell__ArgumentNeedsQuotes(in, flags);
+ if (needQuotes) {
+ /* Add the opening quote for this argument. */
+ if (flags & Shell_Flag_WatcomQuote) {
+ if (flags & Shell_Flag_IsUnix) {
+ out << '"';
+ }
+ out << '\'';
+ } else {
+ out << '"';
+ }
+ }
+
+ /* Scan the string for characters that require escaping or quoting. */
+ for (c = in; *c; ++c) {
+ /* Look for $(MAKEVAR) syntax if requested. */
+ if (flags & Shell_Flag_AllowMakeVariables) {
+ const char* skip = Shell__SkipMakeVariables(c);
+ if (skip != c) {
+ /* Copy to the end of the make variable references. */
+ while (c != skip) {
+ out << *c++;
+ }
+
+ /* The make variable reference eliminates any escaping needed
+ for preceding backslashes. */
+ windows_backslashes = 0;
+
+ /* Stop if we have reached the end of the string. */
+ if (!*c) {
+ break;
+ }
+ }
+ }
+
+ /* Check whether this character needs escaping for the shell. */
+ if (flags & Shell_Flag_IsUnix) {
+ /* On Unix a few special characters need escaping even inside a
+ quoted argument. */
+ if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
+ /* This character needs a backslash to escape it. */
+ 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 == '\\') {
+ /* Found a backslash. It may need to be escaped later. */
+ ++windows_backslashes;
+ } else if (*c == '"') {
+ /* Found a double-quote. Escape all immediately preceding
+ backslashes. */
+ while (windows_backslashes > 0) {
+ --windows_backslashes;
+ out << '\\';
+ }
+
+ /* Add the backslash to escape the double-quote. */
+ out << '\\';
+ } else {
+ /* We encountered a normal character. This eliminates any
+ escaping needed for preceding backslashes. */
+ windows_backslashes = 0;
+ }
+ }
+
+ /* Check whether this character needs escaping for a make tool. */
+ if (*c == '$') {
+ 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 << "$$";
+ } 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
+ 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 from surrounding
+ text to avoid looking like a variable reference. */
+ out << "\"$\"";
+ } else {
+ /* Otherwise a dollar is written just $. */
+ out << '$';
+ }
+ } else if (*c == '#') {
+ 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 << "$#";
+ } else {
+ /* Otherwise a pound is written just #. */
+ out << '#';
+ }
+ } else if (*c == '%') {
+ 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 << "%%";
+ } else {
+ /* Otherwise a percent is written just %. */
+ out << '%';
+ }
+ } else if (*c == ';') {
+ 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 << "\";\"";
+ } else {
+ /* Otherwise a semicolon is written just ;. */
+ out << ';';
+ }
+ } else {
+ /* Store this character. */
+ out << *c;
+ }
+ }
+
+ if (needQuotes) {
+ /* Add enough backslashes to escape any trailing ones. */
+ while (windows_backslashes > 0) {
+ --windows_backslashes;
+ out << '\\';
+ }
+
+ /* Add the closing quote for this argument. */
+ if (flags & Shell_Flag_WatcomQuote) {
+ out << '\'';
+ if (flags & Shell_Flag_IsUnix) {
+ out << '"';
+ }
+ } else {
+ out << '"';
+ }
+ }
+
+ return out.str();
+}
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
new file mode 100644
index 000000000..ae15055ed
--- /dev/null
+++ b/Source/cmOutputConverter.h
@@ -0,0 +1,135 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmOutputConverter_h
+#define cmOutputConverter_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+#include "cmStateSnapshot.h"
+
+class cmState;
+class cmStateDirectory;
+
+class cmOutputConverter
+{
+public:
+ cmOutputConverter(cmStateSnapshot const& snapshot);
+
+ enum OutputFormat
+ {
+ SHELL,
+ WATCOMQUOTE,
+ RESPONSE
+ };
+ std::string ConvertToOutputFormat(const std::string& source,
+ OutputFormat output) const;
+ std::string ConvertDirectorySeparatorsForShell(
+ const std::string& source) const;
+
+ ///! for existing files convert to output path and short path if spaces
+ std::string ConvertToOutputForExisting(const std::string& remote,
+ OutputFormat format = SHELL) const;
+
+ void SetLinkScriptShell(bool linkScriptShell);
+
+ /**
+ * Flags to pass to Shell_GetArgument. These modify the generated
+ * quoting and escape sequences to work under alternative
+ * environments.
+ */
+ enum Shell_Flag_e
+ {
+ /** The target shell is in a makefile. */
+ Shell_Flag_Make = (1 << 0),
+
+ /** The target shell is in a VS project file. Do not use with
+ Shell_Flag_Make. */
+ Shell_Flag_VSIDE = (1 << 1),
+
+ /** In a windows shell the argument is being passed to "echo". */
+ Shell_Flag_EchoWindows = (1 << 2),
+
+ /** The target shell is in a Watcom WMake makefile. */
+ Shell_Flag_WatcomWMake = (1 << 3),
+
+ /** The target shell is in a MinGW Make makefile. */
+ Shell_Flag_MinGWMake = (1 << 4),
+
+ /** The target shell is in a NMake makefile. */
+ Shell_Flag_NMake = (1 << 5),
+
+ /** Make variable reference syntax $(MAKEVAR) should not be escaped
+ to allow a build tool to replace it. Replacement values
+ containing spaces, quotes, backslashes, or other
+ non-alphanumeric characters that have significance to some makes
+ or shells produce undefined behavior. */
+ Shell_Flag_AllowMakeVariables = (1 << 6),
+
+ /** The target shell quoting uses extra single Quotes for Watcom tools. */
+ Shell_Flag_WatcomQuote = (1 << 7),
+
+ Shell_Flag_IsUnix = (1 << 8)
+ };
+
+ std::string EscapeForShell(const std::string& str, bool makeVars = false,
+ bool forEcho = false,
+ bool useWatcomQuote = false) const;
+
+ static std::string EscapeForCMake(const std::string& str);
+
+ /** Compute an escaped version of the given argument for use in a
+ windows shell. */
+ static std::string EscapeWindowsShellArgument(const char* arg,
+ int shell_flags);
+
+ enum FortranFormat
+ {
+ FortranFormatNone,
+ FortranFormatFixed,
+ FortranFormatFree
+ };
+ 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);
+
+private:
+ cmStateSnapshot StateSnapshot;
+
+ bool LinkScriptShell;
+};
+
+#endif
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 01fc2cf8a..2339d6876 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -1,184 +1,502 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmOutputRequiredFilesCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <map>
+#include <utility>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmOutputRequiredFilesCommand.h"
-#include "cmMakeDepend.h"
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cm_unordered_map.hxx"
+
+class cmExecutionStatus;
-class cmLBDepend : public cmMakeDepend
+/** \class cmDependInformation
+ * \brief Store dependency information for a single source file.
+ *
+ * This structure stores the depend information for a single source file.
+ */
+class cmDependInformation
{
+public:
/**
- * Compute the depend information for this class.
+ * Construct with dependency generation marked not done; instance
+ * not placed in cmMakefile's list.
+ */
+ cmDependInformation()
+ : DependDone(false)
+ , SourceFile(CM_NULLPTR)
+ {
+ }
+
+ /**
+ * The set of files on which this one depends.
+ */
+ typedef std::set<cmDependInformation*> DependencySetType;
+ DependencySetType DependencySet;
+
+ /**
+ * This flag indicates whether dependency checking has been
+ * performed for this file.
+ */
+ bool DependDone;
+
+ /**
+ * If this object corresponds to a cmSourceFile instance, this points
+ * to it.
+ */
+ const cmSourceFile* SourceFile;
+
+ /**
+ * Full path to this file.
+ */
+ std::string FullPath;
+
+ /**
+ * Full path not including file name.
*/
- virtual void DependWalk(cmDependInformation* info);
+ std::string PathOnly;
+
+ /**
+ * Name used to #include this file.
+ */
+ std::string IncludeName;
+
+ /**
+ * This method adds the dependencies of another file to this one.
+ */
+ void AddDependencies(cmDependInformation* info)
+ {
+ if (this != info) {
+ this->DependencySet.insert(info);
+ }
+ }
};
-void cmLBDepend::DependWalk(cmDependInformation* info)
+class cmLBDepend
{
- std::ifstream fin(info->FullPath.c_str());
- if(!fin)
- {
- cmSystemTools::Error("error can not open ", info->FullPath.c_str());
- return;
- }
-
- std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- if(!strncmp(line.c_str(), "#include", 8))
- {
- // if it is an include line then create a string class
- std::string currentline = line;
- size_t qstart = currentline.find('\"', 8);
- size_t qend;
- // if a quote is not found look for a <
- if(qstart == std::string::npos)
- {
- qstart = currentline.find('<', 8);
- // if a < is not found then move on
- if(qstart == std::string::npos)
- {
- cmSystemTools::Error("unknown include directive ",
- currentline.c_str() );
- continue;
- }
- else
- {
- qend = currentline.find('>', qstart+1);
- }
+public:
+ /**
+ * Construct the object with verbose turned off.
+ */
+ cmLBDepend()
+ {
+ this->Verbose = false;
+ this->IncludeFileRegularExpression.compile("^.*$");
+ this->ComplainFileRegularExpression.compile("^$");
+ }
+
+ /**
+ * Destructor.
+ */
+ ~cmLBDepend() { cmDeleteAll(this->DependInformationMap); }
+
+ /**
+ * Set the makefile that is used as a source of classes.
+ */
+ void SetMakefile(cmMakefile* makefile)
+ {
+ this->Makefile = makefile;
+
+ // Now extract the include file regular expression from the makefile.
+ this->IncludeFileRegularExpression.compile(
+ this->Makefile->GetIncludeRegularExpression());
+ this->ComplainFileRegularExpression.compile(
+ this->Makefile->GetComplainRegularExpression());
+
+ // 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");
+ if (!incDirProp) {
+ continue;
+ }
+
+ std::string incDirs = cmGeneratorExpression::Preprocess(
+ incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
+
+ std::vector<std::string> includes;
+ cmSystemTools::ExpandListArgument(incDirs, includes);
+
+ for (std::vector<std::string>::const_iterator j = includes.begin();
+ j != includes.end(); ++j) {
+ std::string path = *j;
+ this->Makefile->ExpandVariablesInString(path);
+ if (uniqueIncludes.insert(path).second) {
+ orderedAndUniqueIncludes.push_back(path);
}
- else
- {
- qend = currentline.find('\"', qstart+1);
+ }
+ }
+
+ for (std::vector<std::string>::const_iterator it =
+ orderedAndUniqueIncludes.begin();
+ it != orderedAndUniqueIncludes.end(); ++it) {
+ this->AddSearchPath(*it);
+ }
+ }
+
+ /**
+ * Add a directory to the search path for include files.
+ */
+ void AddSearchPath(const std::string& path)
+ {
+ this->IncludeDirectories.push_back(path);
+ }
+
+ /**
+ * Generate dependencies for the file given. Returns a pointer to
+ * the cmDependInformation object for the file.
+ */
+ const cmDependInformation* FindDependencies(const char* file)
+ {
+ cmDependInformation* info = this->GetDependInformation(file, CM_NULLPTR);
+ this->GenerateDependInformation(info);
+ return info;
+ }
+
+protected:
+ /**
+ * Compute the depend information for this class.
+ */
+
+ void DependWalk(cmDependInformation* info)
+ {
+ cmsys::ifstream fin(info->FullPath.c_str());
+ if (!fin) {
+ cmSystemTools::Error("error can not open ", info->FullPath.c_str());
+ return;
+ }
+
+ std::string line;
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (cmHasLiteralPrefix(line.c_str(), "#include")) {
+ // if it is an include line then create a string class
+ size_t qstart = line.find('\"', 8);
+ size_t qend;
+ // if a quote is not found look for a <
+ if (qstart == std::string::npos) {
+ 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());
+ continue;
+ }
+ qend = line.find('>', qstart + 1);
+ } else {
+ qend = line.find('\"', qstart + 1);
}
- // extract the file being included
- std::string includeFile = currentline.substr(qstart+1, qend - qstart-1);
- // 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.c_str();
- cmSystemTools::Error(message.c_str(), 0);
+ // extract the file being included
+ std::string includeFile = line.substr(qstart + 1, qend - qstart - 1);
+ // 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);
}
- continue;
+ continue;
}
- // Add this file and all its dependencies.
- this->AddDependency(info, includeFile.c_str());
- /// add the cxx file if it exists
- std::string cxxFile = includeFile;
- std::string::size_type pos = cxxFile.rfind('.');
- if(pos != std::string::npos)
- {
- std::string root = cxxFile.substr(0, pos);
- cxxFile = root + ".cxx";
- bool found = false;
- // try jumping to .cxx .cpp and .c in order
- if(cmSystemTools::FileExists(cxxFile.c_str()))
- {
- 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()))
- {
+ // Add this file and all its dependencies.
+ this->AddDependency(info, includeFile.c_str());
+ /// add the cxx file if it exists
+ std::string cxxFile = includeFile;
+ std::string::size_type pos = cxxFile.rfind('.');
+ if (pos != std::string::npos) {
+ std::string root = cxxFile.substr(0, pos);
+ cxxFile = root + ".cxx";
+ bool found = false;
+ // try jumping to .cxx .cpp and .c in order
+ if (cmSystemTools::FileExists(cxxFile.c_str())) {
found = true;
- }
}
- if (!found)
- {
- cxxFile = root + ".cpp";
- if(cmSystemTools::FileExists(cxxFile.c_str()))
- {
- found = true;
- }
- for(std::vector<std::string>::iterator i =
- this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i)
- {
+ 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()))
- {
+ if (cmSystemTools::FileExists(path.c_str())) {
found = true;
- }
}
}
- if (!found)
- {
- cxxFile = root + ".c";
- if(cmSystemTools::FileExists(cxxFile.c_str()))
- {
- 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()))
- {
+ if (!found) {
+ cxxFile = root + ".cpp";
+ if (cmSystemTools::FileExists(cxxFile.c_str())) {
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())) {
+ found = true;
}
}
}
- if (!found)
- {
- cxxFile = root + ".txx";
- if(cmSystemTools::FileExists(cxxFile.c_str()))
- {
- found = true;
+ if (!found) {
+ cxxFile = root + ".c";
+ if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ 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::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())) {
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ cxxFile = root + ".txx";
+ if (cmSystemTools::FileExists(cxxFile.c_str())) {
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())) {
+ found = true;
}
}
}
- if (found)
- {
- this->AddDependency(info, cxxFile.c_str());
+ if (found) {
+ this->AddDependency(info, cxxFile.c_str());
}
}
}
}
-}
+ }
+
+ /**
+ * Add a dependency. Possibly walk it for more dependencies.
+ */
+ void AddDependency(cmDependInformation* info, const char* file)
+ {
+ cmDependInformation* dependInfo =
+ this->GetDependInformation(file, info->PathOnly.c_str());
+ this->GenerateDependInformation(dependInfo);
+ info->AddDependencies(dependInfo);
+ }
+
+ /**
+ * Fill in the given object with dependency information. If the
+ * information is already complete, nothing is done.
+ */
+ void GenerateDependInformation(cmDependInformation* info)
+ {
+ // If dependencies are already done, stop now.
+ if (info->DependDone) {
+ return;
+ }
+ // Make sure we don't visit the same file more than once.
+ info->DependDone = true;
+
+ const char* path = info->FullPath.c_str();
+ if (!path) {
+ cmSystemTools::Error(
+ "Attempt to find dependencies for file without path!");
+ return;
+ }
+
+ bool found = false;
+
+ // If the file exists, use it to find dependency information.
+ if (cmSystemTools::FileExists(path, true)) {
+ // Use the real file to find its dependencies.
+ this->DependWalk(info);
+ found = true;
+ }
+
+ // See if the cmSourceFile for it has any files specified as
+ // dependency hints.
+ if (info->SourceFile != CM_NULLPTR) {
+
+ // Get the cmSourceFile corresponding to this.
+ const cmSourceFile& cFile = *(info->SourceFile);
+ // See if there are any hints for finding dependencies for the missing
+ // file.
+ 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());
+ }
+
+ // Found dependency information. We are done.
+ found = true;
+ }
+ }
+
+ if (!found) {
+ // Try to find the file amongst the sources
+ cmSourceFile* srcFile = this->Makefile->GetSource(
+ cmSystemTools::GetFilenameWithoutExtension(path));
+ if (srcFile) {
+ if (srcFile->GetFullPath() == 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 + "/";
+ }
+ incpath = incpath + path;
+ if (srcFile->GetFullPath() == incpath) {
+ // set the path to the guessed path
+ info->FullPath = incpath;
+ found = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (!found) {
+ // Couldn't find any dependency information.
+ if (this->ComplainFileRegularExpression.find(
+ info->IncludeName.c_str())) {
+ 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 = "";
+ }
+ }
+ }
+
+ /**
+ * Get an instance of cmDependInformation corresponding to the given file
+ * name.
+ */
+ cmDependInformation* GetDependInformation(const char* file,
+ const char* extraPath)
+ {
+ // Get the full path for the file so that lookup is unambiguous.
+ std::string fullPath = this->FullPath(file, extraPath);
+
+ // Try to find the file's instance of cmDependInformation.
+ DependInformationMapType::const_iterator result =
+ this->DependInformationMap.find(fullPath);
+ if (result != this->DependInformationMap.end()) {
+ // Found an instance, return it.
+ return result->second;
+ }
+ // Didn't find an instance. Create a new one and save it.
+ cmDependInformation* info = new cmDependInformation;
+ info->FullPath = fullPath;
+ info->PathOnly = cmSystemTools::GetFilenamePath(fullPath);
+ info->IncludeName = file;
+ this->DependInformationMap[fullPath] = info;
+ return info;
+ }
+
+ /**
+ * Find the full path name for the given file name.
+ * This uses the include directories.
+ * TODO: Cache path conversions to reduce FileExists calls.
+ */
+ std::string FullPath(const char* fname, const char* extraPath)
+ {
+ DirectoryToFileToPathMapType::iterator m;
+ if (extraPath) {
+ m = this->DirectoryToFileToPathMap.find(extraPath);
+ } else {
+ m = this->DirectoryToFileToPathMap.find("");
+ }
+
+ if (m != this->DirectoryToFileToPathMap.end()) {
+ FileToPathMapType& map = m->second;
+ FileToPathMapType::iterator p = map.find(fname);
+ if (p != map.end()) {
+ return p->second;
+ }
+ }
+
+ if (cmSystemTools::FileExists(fname, true)) {
+ std::string fp = cmSystemTools::CollapseFullPath(fname);
+ this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
+ 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 + "/";
+ }
+ path = path + fname;
+ if (cmSystemTools::FileExists(path.c_str(), true) &&
+ !cmSystemTools::FileIsDirectory(path)) {
+ std::string fp = cmSystemTools::CollapseFullPath(path);
+ this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
+ return fp;
+ }
+ }
+
+ if (extraPath) {
+ std::string path = extraPath;
+ if (!path.empty() && path[path.size() - 1] != '/') {
+ path = path + "/";
+ }
+ path = path + fname;
+ if (cmSystemTools::FileExists(path.c_str(), true) &&
+ !cmSystemTools::FileIsDirectory(path)) {
+ std::string fp = cmSystemTools::CollapseFullPath(path);
+ this->DirectoryToFileToPathMap[extraPath][fname] = fp;
+ return fp;
+ }
+ }
+
+ // Couldn't find the file.
+ return std::string(fname);
+ }
+
+ cmMakefile* Makefile;
+ bool Verbose;
+ 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;
+ DependInformationMapType DependInformationMap;
+ DirectoryToFileToPathMapType DirectoryToFileToPathMap;
+};
// cmOutputRequiredFilesCommand
-bool cmOutputRequiredFilesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmOutputRequiredFilesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() != 2 )
- {
+ if (args.size() != 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// store the arg for final pass
this->File = args[0];
@@ -187,54 +505,46 @@ bool cmOutputRequiredFilesCommand
// compute the list of files
cmLBDepend md;
md.SetMakefile(this->Makefile);
- md.AddSearchPath(this->Makefile->GetStartDirectory());
+ md.AddSearchPath(this->Makefile->GetCurrentSourceDirectory());
// find the depends for a file
- const cmDependInformation *info = md.FindDependencies(this->File.c_str());
- if (info)
- {
+ const cmDependInformation* info = md.FindDependencies(this->File.c_str());
+ if (info) {
// write them out
- FILE *fout = fopen(this->OutputFile.c_str(),"w");
- if(!fout)
- {
+ FILE* fout = cmsys::SystemTools::Fopen(this->OutputFile, "w");
+ if (!fout) {
std::string err = "Can not open output file: ";
err += this->OutputFile;
- this->SetError(err.c_str());
+ this->SetError(err);
return false;
- }
+ }
std::set<cmDependInformation const*> visited;
- this->ListDependencies(info,fout, &visited);
+ this->ListDependencies(info, fout, &visited);
fclose(fout);
- }
+ }
return true;
}
-void cmOutputRequiredFilesCommand::
-ListDependencies(cmDependInformation const *info,
- FILE *fout,
- std::set<cmDependInformation const*> *visited)
+void cmOutputRequiredFilesCommand::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 != "")
- {
+ 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;
std::string::size_type pos = tmp.rfind('.');
- if(pos != std::string::npos && (tmp.substr(pos) != ".h"))
- {
+ 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);
}
+ this->ListDependencies(*d, fout, visited);
}
+ }
}
-
diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h
index 1d7e39457..d20bfbdc1 100644
--- a/Source/cmOutputRequiredFilesCommand.h
+++ b/Source/cmOutputRequiredFilesCommand.h
@@ -1,88 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmOutputRequiredFilesCommand_h
#define cmOutputRequiredFilesCommand_h
+#include "cmConfigure.h"
+
+#include <set>
+#include <stdio.h>
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmMakeDepend.h"
-/** \class cmOutputRequiredFilesCommand
- * \brief Output a list of required files for a source file
- *
- */
+class cmDependInformation;
+class cmExecutionStatus;
+
class cmOutputRequiredFilesCommand : public cmCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmOutputRequiredFilesCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "output_required_files";}
+ cmCommand* Clone() CM_OVERRIDE { return new cmOutputRequiredFilesCommand; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Approximate C preprocessor dependency scanning.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "This command exists only because ancient CMake versions provided it. "
- "CMake handles preprocessor dependency scanning automatically using a "
- "more advanced scanner.\n"
- " output_required_files(srcfile outputfile)\n"
- "Outputs a list of all the source files that are required by the "
- "specified srcfile. This list is written into outputfile. This is "
- "similar to writing out the dependencies for srcfile except that it "
- "jumps from .h files into .cxx, .c and .cpp files if possible.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
-
- cmTypeMacro(cmOutputRequiredFilesCommand, cmCommand);
- void ListDependencies(cmDependInformation const *info,
- FILE *fout,
- std::set<cmDependInformation const*> *visited);
+ void ListDependencies(cmDependInformation const* info, FILE* fout,
+ std::set<cmDependInformation const*>* visited);
private:
std::string File;
std::string OutputFile;
};
-
-
#endif
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
new file mode 100644
index 000000000..d75ee8e86
--- /dev/null
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -0,0 +1,244 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmParseArgumentsCommand.h"
+
+#include <map>
+#include <set>
+#include <sstream>
+#include <stddef.h>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+static std::string escape_arg(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] == ';') {
+ escapedArg += '\\';
+ }
+ escapedArg += arg[i];
+ }
+ return escapedArg;
+}
+
+bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
+{
+ // 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.");
+ return false;
+ }
+
+ std::vector<std::string>::const_iterator argIter = args.begin(),
+ argEnd = args.end();
+ bool parseFromArgV = false;
+ unsigned long argvStart = 0;
+ if (*argIter == "PARSE_ARGV") {
+ if (args.size() != 6) {
+ this->Makefile->IssueMessage(
+ cmake::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");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ argIter++; // move past N
+ }
+ // the first argument is the prefix
+ const std::string prefix = (*argIter++) + "_";
+
+ // 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;
+
+ // 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: ";
+
+ // 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
+ }
+
+ // 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
+ }
+
+ // 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;
+
+ 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);
+ }
+ } else {
+ // in the PARSE_ARGV move read the arguments from ARGC and ARGV#
+ std::string argc = this->Makefile->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");
+ 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());
+ if (!arg) {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "PARSE_ARGV called with " +
+ argName.str() + " not set");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ list.push_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;
+ }
+
+ const multi_map::iterator multiIter = multi.find(*argIter);
+ if (multiIter != multi.end()) {
+ insideValues = MULTI;
+ currentArgName = *argIter;
+ continue;
+ }
+
+ 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");
+ }
+
+ return true;
+}
diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h
new file mode 100644
index 000000000..359fb85b9
--- /dev/null
+++ b/Source/cmParseArgumentsCommand.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 cmParseArgumentsCommand_h
+#define cmParseArgumentsCommand_h
+
+#include "cmConfigure.h"
+
+#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;
+};
+
+#endif
diff --git a/Source/cmPathLabel.cxx b/Source/cmPathLabel.cxx
new file mode 100644
index 000000000..30ba08151
--- /dev/null
+++ b/Source/cmPathLabel.cxx
@@ -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. */
+#include "cmPathLabel.h"
+
+#include <stddef.h>
+
+cmPathLabel::cmPathLabel(const std::string& label)
+ : Label(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];
+ this->Hash += ((this->Hash & 0x003FFFFF) << 10);
+ this->Hash ^= ((this->Hash & 0xFFFFFFC0) >> 6);
+ }
+ this->Hash += ((this->Hash & 0x1FFFFFFF) << 3);
+ this->Hash ^= ((this->Hash & 0xFFFFF800) >> 11);
+ this->Hash += ((this->Hash & 0x0001FFFF) << 15);
+}
+
+bool cmPathLabel::operator<(const cmPathLabel& l) const
+{
+ return this->Hash < l.Hash;
+}
+
+bool cmPathLabel::operator==(const cmPathLabel& l) const
+{
+ return this->Hash == l.Hash;
+}
diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h
new file mode 100644
index 000000000..97551fb46
--- /dev/null
+++ b/Source/cmPathLabel.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 cmPathLabel_h
+#define cmPathLabel_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** \class cmPathLabel
+ * \brief Helper class for text based labels
+ *
+ * cmPathLabel is extended in different classes to act as an inheritable
+ * enum. Comparisons are done on a precomputed Jenkins hash of the string
+ * label for indexing and searchig.
+ */
+class cmPathLabel
+{
+public:
+ cmPathLabel(const std::string& label);
+
+ // The comparison operators are only for quick sorting and searching and
+ // in no way imply any lexicographical order of the label
+ bool operator<(const cmPathLabel& l) const;
+ bool operator==(const cmPathLabel& l) const;
+
+ const std::string& GetLabel() const { return this->Label; }
+ const unsigned int& GetHash() const { return this->Hash; }
+
+protected:
+ cmPathLabel();
+
+ std::string Label;
+ unsigned int Hash;
+};
+
+#endif
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index a823f0595..da3edd427 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -1,658 +1,167 @@
#include "cmPolicies.h"
-#include "cmake.h"
+
+#include "cmAlgorithms.h"
#include "cmMakefile.h"
-#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cmVersionMacros.h"
-#include <map>
-#include <set>
-#include <queue>
-#include <assert.h>
+#include "cmake.h"
-const char* cmPolicies::PolicyStatusNames[] = {
- "OLD", "WARN", "NEW", "REQUIRED_IF_USED", "REQUIRED_ALWAYS"
-};
+#include "cmConfigure.h"
+#include <assert.h>
+#include <ctype.h>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <vector>
-class cmPolicy
+static bool stringToId(const char* input, cmPolicies::PolicyID& pid)
{
-public:
- cmPolicy(cmPolicies::PolicyID iD,
- const char *idString,
- const char *shortDescription,
- const char *longDescription,
- unsigned int majorVersionIntroduced,
- unsigned int minorVersionIntroduced,
- unsigned int patchVersionIntroduced,
- unsigned int tweakVersionIntroduced,
- cmPolicies::PolicyStatus status)
- {
- if (!idString || !shortDescription || ! longDescription)
- {
- cmSystemTools::Error("Attempt to define a policy without "
- "all parameters being specified!");
- return;
+ assert(input);
+ if (strlen(input) != 7) {
+ return false;
+ }
+ if (!cmHasLiteralPrefix(input, "CMP")) {
+ return false;
+ }
+ if (cmHasLiteralSuffix(input, "0000")) {
+ pid = cmPolicies::CMP0000;
+ return true;
+ }
+ for (int i = 3; i < 7; ++i) {
+ if (!isdigit(*(input + i))) {
+ return false;
}
- this->ID = iD;
- this->IDString = idString;
- this->ShortDescription = shortDescription;
- this->LongDescription = longDescription;
- this->MajorVersionIntroduced = majorVersionIntroduced;
- this->MinorVersionIntroduced = minorVersionIntroduced;
- this->PatchVersionIntroduced = patchVersionIntroduced;
- this->TweakVersionIntroduced = tweakVersionIntroduced;
- this->Status = status;
}
+ long id;
+ if (!cmSystemTools::StringToLong(input + 3, &id)) {
+ return false;
+ }
+ if (id >= cmPolicies::CMPCOUNT) {
+ return false;
+ }
+ pid = cmPolicies::PolicyID(id);
+ return true;
+}
- std::string GetVersionString()
- {
- cmOStringStream v;
- v << this->MajorVersionIntroduced << "." << this->MinorVersionIntroduced;
- v << "." << this->PatchVersionIntroduced;
- if(this->TweakVersionIntroduced > 0)
- {
- v << "." << this->TweakVersionIntroduced;
- }
- return v.str();
+#define CM_SELECT_ID_VERSION(F, A1, A2, A3, A4, A5, A6) F(A1, A3, A4, A5)
+#define CM_FOR_EACH_POLICY_ID_VERSION(POLICY) \
+ CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID_VERSION)
+
+#define CM_SELECT_ID_DOC(F, A1, A2, A3, A4, A5, A6) F(A1, A2)
+#define CM_FOR_EACH_POLICY_ID_DOC(POLICY) \
+ CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID_DOC)
+
+static const char* idToString(cmPolicies::PolicyID id)
+{
+ switch (id) {
+#define POLICY_CASE(ID) \
+ case cmPolicies::ID: \
+ return #ID;
+ CM_FOR_EACH_POLICY_ID(POLICY_CASE)
+#undef POLICY_CASE
+ case cmPolicies::CMPCOUNT:
+ return CM_NULLPTR;
}
+ return CM_NULLPTR;
+}
- bool IsPolicyNewerThan(unsigned int majorV,
- unsigned int minorV,
- unsigned int patchV,
- unsigned int tweakV)
- {
- if (majorV < this->MajorVersionIntroduced)
- {
- return true;
- }
- if (majorV > this->MajorVersionIntroduced)
- {
- return false;
- }
- if (minorV < this->MinorVersionIntroduced)
- {
- return true;
- }
- if (minorV > this->MinorVersionIntroduced)
- {
- return false;
- }
- if (patchV < this->PatchVersionIntroduced)
- {
- return true;
- }
- if (patchV > this->PatchVersionIntroduced)
- {
+static const char* idToVersion(cmPolicies::PolicyID id)
+{
+ switch (id) {
+#define POLICY_CASE(ID, V_MAJOR, V_MINOR, V_PATCH) \
+ case cmPolicies::ID: \
+ return #V_MAJOR "." #V_MINOR "." #V_PATCH;
+ CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE)
+#undef POLICY_CASE
+ case cmPolicies::CMPCOUNT:
+ return CM_NULLPTR;
+ }
+ return CM_NULLPTR;
+}
+
+static bool isPolicyNewerThan(cmPolicies::PolicyID id, unsigned int majorV,
+ unsigned int minorV, unsigned int patchV)
+{
+ switch (id) {
+#define POLICY_CASE(ID, V_MAJOR, V_MINOR, V_PATCH) \
+ case cmPolicies::ID: \
+ return (majorV < (V_MAJOR) || \
+ (majorV == (V_MAJOR) && minorV + 1 < (V_MINOR) + 1) || \
+ (majorV == (V_MAJOR) && minorV == (V_MINOR) && \
+ patchV + 1 < (V_PATCH) + 1));
+ CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE)
+#undef POLICY_CASE
+ case cmPolicies::CMPCOUNT:
return false;
- }
- return (tweakV < this->TweakVersionIntroduced);
}
+ return false;
+}
- cmPolicies::PolicyID ID;
- std::string IDString;
- std::string ShortDescription;
- std::string LongDescription;
- unsigned int MajorVersionIntroduced;
- unsigned int MinorVersionIntroduced;
- unsigned int PatchVersionIntroduced;
- unsigned int TweakVersionIntroduced;
- cmPolicies::PolicyStatus Status;
-};
-
-cmPolicies::cmPolicies()
+const char* idToShortDescription(cmPolicies::PolicyID id)
{
- // define all the policies
- this->DefinePolicy(
- CMP0000, "CMP0000",
- "A minimum required CMake version must be specified.",
- "CMake requires that projects specify the version of CMake to which "
- "they have been written. "
- "This policy has been put in place so users trying to build the project "
- "may be told when they need to update their CMake. "
- "Specifying a version also helps the project build with CMake versions "
- "newer than that specified. "
- "Use the cmake_minimum_required command at the top of your main "
- " CMakeLists.txt file:\n"
- " cmake_minimum_required(VERSION <major>.<minor>)\n"
- "where \"<major>.<minor>\" is the version of CMake you want to support "
- "(such as \"2.6\"). "
- "The command will ensure that at least the given version of CMake is "
- "running and help newer versions be compatible with the project. "
- "See documentation of cmake_minimum_required for details.\n"
- "Note that the command invocation must appear in the CMakeLists.txt "
- "file itself; a call in an included file is not sufficient. "
- "However, the cmake_policy command may be called to set policy "
- "CMP0000 to OLD or NEW behavior explicitly. "
- "The OLD behavior is to silently ignore the missing invocation. "
- "The NEW behavior is to issue an error instead of a warning. "
- "An included file may set CMP0000 explicitly to affect how this "
- "policy is enforced for the main CMakeLists.txt file.",
- 2,6,0,0, cmPolicies::WARN
- );
-
- this->DefinePolicy(
- CMP0001, "CMP0001",
- "CMAKE_BACKWARDS_COMPATIBILITY should no longer be used.",
- "The OLD behavior is to check CMAKE_BACKWARDS_COMPATIBILITY and present "
- "it to the user. "
- "The NEW behavior is to ignore CMAKE_BACKWARDS_COMPATIBILITY "
- "completely.\n"
- "In CMake 2.4 and below the variable CMAKE_BACKWARDS_COMPATIBILITY was "
- "used to request compatibility with earlier versions of CMake. "
- "In CMake 2.6 and above all compatibility issues are handled by policies "
- "and the cmake_policy command. "
- "However, CMake must still check CMAKE_BACKWARDS_COMPATIBILITY for "
- "projects written for CMake 2.4 and below.",
- 2,6,0,0, cmPolicies::WARN
- );
-
- this->DefinePolicy(
- CMP0002, "CMP0002",
- "Logical target names must be globally unique.",
- "Targets names created with "
- "add_executable, add_library, or add_custom_target "
- "are logical build target names. "
- "Logical target names must be globally unique because:\n"
- " - Unique names may be referenced unambiguously both in CMake\n"
- " code and on make tool command lines.\n"
- " - Logical names are used by Xcode and VS IDE generators\n"
- " to produce meaningful project names for the targets.\n"
- "The logical name of executable and library targets does not "
- "have to correspond to the physical file names built. "
- "Consider using the OUTPUT_NAME target property to create two "
- "targets with the same physical name while keeping logical "
- "names distinct. "
- "Custom targets must simply have globally unique names (unless one "
- "uses the global property ALLOW_DUPLICATE_CUSTOM_TARGETS with a "
- "Makefiles generator).",
- 2,6,0,0, cmPolicies::WARN
- );
-
- this->DefinePolicy(
- CMP0003, "CMP0003",
- "Libraries linked via full path no longer produce linker search paths.",
- "This policy affects how libraries whose full paths are NOT known "
- "are found at link time, but was created due to a change in how CMake "
- "deals with libraries whose full paths are known. "
- "Consider the code\n"
- " target_link_libraries(myexe /path/to/libA.so)\n"
- "CMake 2.4 and below implemented linking to libraries whose full paths "
- "are known by splitting them on the link line into separate components "
- "consisting of the linker search path and the library name. "
- "The example code might have produced something like\n"
- " ... -L/path/to -lA ...\n"
- "in order to link to library A. "
- "An analysis was performed to order multiple link directories such that "
- "the linker would find library A in the desired location, but there "
- "are cases in which this does not work. "
- "CMake versions 2.6 and above use the more reliable approach of passing "
- "the full path to libraries directly to the linker in most cases. "
- "The example code now produces something like\n"
- " ... /path/to/libA.so ....\n"
- "Unfortunately this change can break code like\n"
- " target_link_libraries(myexe /path/to/libA.so B)\n"
- "where \"B\" is meant to find \"/path/to/libB.so\". "
- "This code is wrong because the user is asking the linker to find "
- "library B but has not provided a linker search path (which may be "
- "added with the link_directories command). "
- "However, with the old linking implementation the code would work "
- "accidentally because the linker search path added for library A "
- "allowed library B to be found."
- "\n"
- "In order to support projects depending on linker search paths "
- "added by linking to libraries with known full paths, the OLD "
- "behavior for this policy will add the linker search paths even "
- "though they are not needed for their own libraries. "
- "When this policy is set to OLD, CMake will produce a link line such as\n"
- " ... -L/path/to /path/to/libA.so -lB ...\n"
- "which will allow library B to be found as it was previously. "
- "When this policy is set to NEW, CMake will produce a link line such as\n"
- " ... /path/to/libA.so -lB ...\n"
- "which more accurately matches what the project specified."
- "\n"
- "The setting for this policy used when generating the link line is that "
- "in effect when the target is created by an add_executable or "
- "add_library command. For the example described above, the code\n"
- " cmake_policy(SET CMP0003 OLD) # or cmake_policy(VERSION 2.4)\n"
- " add_executable(myexe myexe.c)\n"
- " target_link_libraries(myexe /path/to/libA.so B)\n"
- "will work and suppress the warning for this policy. "
- "It may also be updated to work with the corrected linking approach:\n"
- " cmake_policy(SET CMP0003 NEW) # or cmake_policy(VERSION 2.6)\n"
- " link_directories(/path/to) # needed to find library B\n"
- " add_executable(myexe myexe.c)\n"
- " target_link_libraries(myexe /path/to/libA.so B)\n"
- "Even better, library B may be specified with a full path:\n"
- " add_executable(myexe myexe.c)\n"
- " target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)\n"
- "When all items on the link line have known paths CMake does not check "
- "this policy so it has no effect.\n"
- "Note that the warning for this policy will be issued for at most "
- "one target. This avoids flooding users with messages for every "
- "target when setting the policy once will probably fix all targets.",
- 2,6,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0004, "CMP0004",
- "Libraries linked may not have leading or trailing whitespace.",
- "CMake versions 2.4 and below silently removed leading and trailing "
- "whitespace from libraries linked with code like\n"
- " target_link_libraries(myexe \" A \")\n"
- "This could lead to subtle errors in user projects.\n"
- "The OLD behavior for this policy is to silently remove leading and "
- "trailing whitespace. "
- "The NEW behavior for this policy is to diagnose the existence of "
- "such whitespace as an error. "
- "The setting for this policy used when checking the library names is "
- "that in effect when the target is created by an add_executable or "
- "add_library command.",
- 2,6,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0005, "CMP0005",
- "Preprocessor definition values are now escaped automatically.",
- "This policy determines whether or not CMake should generate escaped "
- "preprocessor definition values added via add_definitions. "
- "CMake versions 2.4 and below assumed that only trivial values would "
- "be given for macros in add_definitions calls. "
- "It did not attempt to escape non-trivial values such as string "
- "literals in generated build rules. "
- "CMake versions 2.6 and above support escaping of most values, but "
- "cannot assume the user has not added escapes already in an attempt to "
- "work around limitations in earlier versions.\n"
- "The OLD behavior for this policy is to place definition values given "
- "to add_definitions directly in the generated build rules without "
- "attempting to escape anything. "
- "The NEW behavior for this policy is to generate correct escapes "
- "for all native build tools automatically. "
- "See documentation of the COMPILE_DEFINITIONS target property for "
- "limitations of the escaping implementation.",
- 2,6,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0006, "CMP0006",
- "Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION.",
- "This policy determines whether the install(TARGETS) command must be "
- "given a BUNDLE DESTINATION when asked to install a target with the "
- "MACOSX_BUNDLE property set. "
- "CMake 2.4 and below did not distinguish application bundles from "
- "normal executables when installing targets. "
- "CMake 2.6 provides a BUNDLE option to the install(TARGETS) command "
- "that specifies rules specific to application bundles on the Mac. "
- "Projects should use this option when installing a target with the "
- "MACOSX_BUNDLE property set.\n"
- "The OLD behavior for this policy is to fall back to the RUNTIME "
- "DESTINATION if a BUNDLE DESTINATION is not given. "
- "The NEW behavior for this policy is to produce an error if a bundle "
- "target is installed without a BUNDLE DESTINATION.",
- 2,6,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0007, "CMP0007",
- "list command no longer ignores empty elements.",
- "This policy determines whether the list command will "
- "ignore empty elements in the list. "
- "CMake 2.4 and below list commands ignored all empty elements"
- " in the list. For example, a;b;;c would have length 3 and not 4. "
- "The OLD behavior for this policy is to ignore empty list elements. "
- "The NEW behavior for this policy is to correctly count empty "
- "elements in a list. ",
- 2,6,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0008, "CMP0008",
- "Libraries linked by full-path must have a valid library file name.",
- "In CMake 2.4 and below it is possible to write code like\n"
- " target_link_libraries(myexe /full/path/to/somelib)\n"
- "where \"somelib\" is supposed to be a valid library file name "
- "such as \"libsomelib.a\" or \"somelib.lib\". "
- "For Makefile generators this produces an error at build time "
- "because the dependency on the full path cannot be found. "
- "For VS IDE and Xcode generators this used to work by accident because "
- "CMake would always split off the library directory and ask the "
- "linker to search for the library by name (-lsomelib or somelib.lib). "
- "Despite the failure with Makefiles, some projects have code like this "
- "and build only with VS and/or Xcode. "
- "This version of CMake prefers to pass the full path directly to the "
- "native build tool, which will fail in this case because it does "
- "not name a valid library file."
- "\n"
- "This policy determines what to do with full paths that do not appear "
- "to name a valid library file. "
- "The OLD behavior for this policy is to split the library name from the "
- "path and ask the linker to search for it. "
- "The NEW behavior for this policy is to trust the given path and "
- "pass it directly to the native build tool unchanged.",
- 2,6,1,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0009, "CMP0009",
- "FILE GLOB_RECURSE calls should not follow symlinks by default.",
- "In CMake 2.6.1 and below, FILE GLOB_RECURSE calls would follow "
- "through symlinks, sometimes coming up with unexpectedly large "
- "result sets because of symlinks to top level directories that "
- "contain hundreds of thousands of files."
- "\n"
- "This policy determines whether or not to follow symlinks "
- "encountered during a FILE GLOB_RECURSE call. "
- "The OLD behavior for this policy is to follow the symlinks. "
- "The NEW behavior for this policy is not to follow the symlinks "
- "by default, but only if FOLLOW_SYMLINKS is given as an additional "
- "argument to the FILE command.",
- 2,6,2,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0010, "CMP0010",
- "Bad variable reference syntax is an error.",
- "In CMake 2.6.2 and below, incorrect variable reference syntax such as "
- "a missing close-brace (\"${FOO\") was reported but did not stop "
- "processing of CMake code. "
- "This policy determines whether a bad variable reference is an error. "
- "The OLD behavior for this policy is to warn about the error, leave "
- "the string untouched, and continue. "
- "The NEW behavior for this policy is to report an error.",
- 2,6,3,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0011, "CMP0011",
- "Included scripts do automatic cmake_policy PUSH and POP.",
- "In CMake 2.6.2 and below, CMake Policy settings in scripts loaded by "
- "the include() and find_package() commands would affect the includer. "
- "Explicit invocations of cmake_policy(PUSH) and cmake_policy(POP) were "
- "required to isolate policy changes and protect the includer. "
- "While some scripts intend to affect the policies of their includer, "
- "most do not. "
- "In CMake 2.6.3 and above, include() and find_package() by default PUSH "
- "and POP an entry on the policy stack around an included script, "
- "but provide a NO_POLICY_SCOPE option to disable it. "
- "This policy determines whether or not to imply NO_POLICY_SCOPE for "
- "compatibility. "
- "The OLD behavior for this policy is to imply NO_POLICY_SCOPE for "
- "include() and find_package() commands. "
- "The NEW behavior for this policy is to allow the commands to do their "
- "default cmake_policy PUSH and POP.",
- 2,6,3,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0012, "CMP0012",
- "if() recognizes numbers and boolean constants.",
- "In CMake versions 2.6.4 and lower the if() command implicitly "
- "dereferenced arguments corresponding to variables, even those named "
- "like numbers or boolean constants, except for 0 and 1. "
- "Numbers and boolean constants such as true, false, yes, no, "
- "on, off, y, n, notfound, ignore (all case insensitive) were recognized "
- "in some cases but not all. "
- "For example, the code \"if(TRUE)\" might have evaluated as false. "
- "Numbers such as 2 were recognized only in "
- "boolean expressions like \"if(NOT 2)\" (leading to false) "
- "but not as a single-argument like \"if(2)\" (also leading to false). "
- "Later versions of CMake prefer to treat numbers and boolean constants "
- "literally, so they should not be used as variable names."
- "\n"
- "The OLD behavior for this policy is to implicitly dereference variables "
- "named like numbers and boolean constants. "
- "The NEW behavior for this policy is to recognize numbers and "
- "boolean constants without dereferencing variables with such names.",
- 2,8,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0013, "CMP0013",
- "Duplicate binary directories are not allowed.",
- "CMake 2.6.3 and below silently permitted add_subdirectory() calls "
- "to create the same binary directory multiple times. "
- "During build system generation files would be written and then "
- "overwritten in the build tree and could lead to strange behavior. "
- "CMake 2.6.4 and above explicitly detect duplicate binary directories. "
- "CMake 2.6.4 always considers this case an error. "
- "In CMake 2.8.0 and above this policy determines whether or not "
- "the case is an error. "
- "The OLD behavior for this policy is to allow duplicate binary "
- "directories. "
- "The NEW behavior for this policy is to disallow duplicate binary "
- "directories with an error.",
- 2,8,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0014, "CMP0014",
- "Input directories must have CMakeLists.txt.",
- "CMake versions before 2.8 silently ignored missing CMakeLists.txt "
- "files in directories referenced by add_subdirectory() or subdirs(), "
- "treating them as if present but empty. "
- "In CMake 2.8.0 and above this policy determines whether or not "
- "the case is an error. "
- "The OLD behavior for this policy is to silently ignore the problem. "
- "The NEW behavior for this policy is to report an error.",
- 2,8,0,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0015, "CMP0015",
- "link_directories() treats paths relative to the source dir.",
- "In CMake 2.8.0 and lower the link_directories() command passed relative "
- "paths unchanged to the linker. "
- "In CMake 2.8.1 and above the link_directories() command prefers to "
- "interpret relative paths with respect to CMAKE_CURRENT_SOURCE_DIR, "
- "which is consistent with include_directories() and other commands. "
- "The OLD behavior for this policy is to use relative paths verbatim in "
- "the linker command. "
- "The NEW behavior for this policy is to convert relative paths to "
- "absolute paths by appending the relative path to "
- "CMAKE_CURRENT_SOURCE_DIR.",
- 2,8,1,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0016, "CMP0016",
- "target_link_libraries() reports error if its only argument "
- "is not a target.",
- "In CMake 2.8.2 and lower the target_link_libraries() command silently "
- "ignored if it was called with only one argument, and this argument "
- "wasn't a valid target. "
- "In CMake 2.8.3 and above it reports an error in this case.",
- 2,8,3,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0017, "CMP0017",
- "Prefer files from the CMake module directory when including from there.",
- "Starting with CMake 2.8.4, if a cmake-module shipped with CMake (i.e. "
- "located in the CMake module directory) calls include() or "
- "find_package(), the files located in the CMake module directory are "
- "preferred over the files in CMAKE_MODULE_PATH. "
- "This makes sure that the modules belonging to "
- "CMake always get those files included which they expect, and against "
- "which they were developed and tested. "
- "In all other cases, the files found in "
- "CMAKE_MODULE_PATH still take precedence over the ones in "
- "the CMake module directory. "
- "The OLD behaviour is to always prefer files from CMAKE_MODULE_PATH over "
- "files from the CMake modules directory.",
- 2,8,4,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0018, "CMP0018",
- "Ignore CMAKE_SHARED_LIBRARY_<Lang>_FLAGS variable.",
- "CMake 2.8.8 and lower compiled sources in SHARED and MODULE libraries "
- "using the value of the undocumented CMAKE_SHARED_LIBRARY_<Lang>_FLAGS "
- "platform variable. The variable contained platform-specific flags "
- "needed to compile objects for shared libraries. Typically it included "
- "a flag such as -fPIC for position independent code but also included "
- "other flags needed on certain platforms. CMake 2.8.9 and higher "
- "prefer instead to use the POSITION_INDEPENDENT_CODE target property to "
- "determine what targets should be position independent, and new "
- "undocumented platform variables to select flags while ignoring "
- "CMAKE_SHARED_LIBRARY_<Lang>_FLAGS completely."
- "\n"
- "The default for either approach produces identical compilation flags, "
- "but if a project modifies CMAKE_SHARED_LIBRARY_<Lang>_FLAGS from its "
- "original value this policy determines which approach to use."
- "\n"
- "The OLD behavior for this policy is to ignore the "
- "POSITION_INDEPENDENT_CODE property for all targets and use the modified "
- "value of CMAKE_SHARED_LIBRARY_<Lang>_FLAGS for SHARED and MODULE "
- "libraries."
- "\n"
- "The NEW behavior for this policy is to ignore "
- "CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
- "honor the POSITION_INDEPENDENT_CODE target property.",
- 2,8,9,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0019, "CMP0019",
- "Do not re-expand variables in include and link information.",
- "CMake 2.8.10 and lower re-evaluated values given to the "
- "include_directories, link_directories, and link_libraries "
- "commands to expand any leftover variable references at the "
- "end of the configuration step. "
- "This was for strict compatibility with VERY early CMake versions "
- "because all variable references are now normally evaluated during "
- "CMake language processing. "
- "CMake 2.8.11 and higher prefer to skip the extra evaluation."
- "\n"
- "The OLD behavior for this policy is to re-evaluate the values "
- "for strict compatibility. "
- "The NEW behavior for this policy is to leave the values untouched.",
- 2,8,11,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0020, "CMP0020",
- "Automatically link Qt executables to qtmain target on Windows.",
- "CMake 2.8.10 and lower required users of Qt to always specify a link "
- "dependency to the qtmain.lib static library manually on Windows. CMake "
- "2.8.11 gained the ability to evaluate generator expressions while "
- "determining the link dependencies from IMPORTED targets. This allows "
- "CMake itself to automatically link executables which link to Qt to the "
- "qtmain.lib library when using IMPORTED Qt targets. For applications "
- "already linking to qtmain.lib, this should have little impact. For "
- "applications which supply their own alternative WinMain implementation "
- "and for applications which use the QAxServer library, this automatic "
- "linking will need to be disabled as per the documentation."
- "\n"
- "The OLD behavior for this policy is not to link executables to "
- "qtmain.lib automatically when they link to the QtCore IMPORTED"
- "target. "
- "The NEW behavior for this policy is to link executables to "
- "qtmain.lib automatically when they link to QtCore IMPORTED target.",
- 2,8,11,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0021, "CMP0021",
- "Fatal error on relative paths in INCLUDE_DIRECTORIES target property.",
- "CMake 2.8.10.2 and lower allowed the INCLUDE_DIRECTORIES target "
- "property to contain relative paths. The base path for such relative "
- "entries is not well defined. CMake 2.8.12 issues a FATAL_ERROR if the "
- "INCLUDE_DIRECTORIES property contains a relative path."
- "\n"
- "The OLD behavior for this policy is not to warn about relative paths in "
- "the INCLUDE_DIRECTORIES target property. "
- "The NEW behavior for this policy is to issue a FATAL_ERROR if "
- "INCLUDE_DIRECTORIES contains a relative path.",
- 2,8,12,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0022, "CMP0022",
- "INTERFACE_LINK_LIBRARIES defines the link interface.",
- "CMake 2.8.11 constructed the 'link interface' of a target from "
- "properties matching (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?. "
- "The modern way to specify config-sensitive content is to use generator "
- "expressions and the IMPORTED_ prefix makes uniform processing of the "
- "link interface with generator expressions impossible. The "
- "INTERFACE_LINK_LIBRARIES target property was introduced as a "
- "replacement in CMake 2.8.12. This new property is named consistently "
- "with the INTERFACE_COMPILE_DEFINITIONS, INTERFACE_INCLUDE_DIRECTORIES "
- "and INTERFACE_COMPILE_OPTIONS properties. For in-build targets, CMake "
- "will use the INTERFACE_LINK_LIBRARIES property as the source of the "
- "link interface only if policy CMP0022 is NEW. "
- "When exporting a target which has this policy set to NEW, only the "
- "INTERFACE_LINK_LIBRARIES property will be processed and generated for "
- "the IMPORTED target by default. A new option to the install(EXPORT) "
- "and export commands allows export of the old-style properties for "
- "compatibility with downstream users of CMake versions older than "
- "2.8.12. "
- "The target_link_libraries command will no longer populate the "
- "properties matching LINK_INTERFACE_LIBRARIES(_<CONFIG>)? if this policy "
- "is NEW."
- "\n"
- "The OLD behavior for this policy is to ignore the "
- "INTERFACE_LINK_LIBRARIES property for in-build targets. "
- "The NEW behavior for this policy is to use the INTERFACE_LINK_LIBRARIES "
- "property for in-build targets, and ignore the old properties matching "
- "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.",
- 2,8,12,0, cmPolicies::WARN);
-
- this->DefinePolicy(
- CMP0023, "CMP0023",
- "Plain and keyword target_link_libraries signatures cannot be mixed.",
- "CMake 2.8.12 introduced the target_link_libraries signature using "
- "the PUBLIC, PRIVATE, and INTERFACE keywords to generalize the "
- "LINK_PUBLIC and LINK_PRIVATE keywords introduced in CMake 2.8.7. "
- "Use of signatures with any of these keywords sets the link interface "
- "of a target explicitly, even if empty. "
- "This produces confusing behavior when used in combination with the "
- "historical behavior of the plain target_link_libraries signature. "
- "For example, consider the code:\n"
- " target_link_libraries(mylib A)\n"
- " target_link_libraries(mylib PRIVATE B)\n"
- "After the first line the link interface has not been set explicitly "
- "so CMake would use the link implementation, A, as the link interface. "
- "However, the second line sets the link interface to empty. "
- "In order to avoid this subtle behavior CMake now prefers to disallow "
- "mixing the plain and keyword signatures of target_link_libraries for "
- "a single target."
- "\n"
- "The OLD behavior for this policy is to allow keyword and plain "
- "target_link_libraries signatures to be mixed. "
- "The NEW behavior for this policy is to not to allow mixing of the "
- "keyword and plain signatures.",
- 2,8,12,0, cmPolicies::WARN);
+ switch (id) {
+#define POLICY_CASE(ID, SHORT_DESCRIPTION) \
+ case cmPolicies::ID: \
+ return SHORT_DESCRIPTION;
+ CM_FOR_EACH_POLICY_ID_DOC(POLICY_CASE)
+#undef POLICY_CASE
+ case cmPolicies::CMPCOUNT:
+ return CM_NULLPTR;
+ }
+ return CM_NULLPTR;
}
-cmPolicies::~cmPolicies()
+static void DiagnoseAncientPolicies(
+ std::vector<cmPolicies::PolicyID> const& ancient, unsigned int majorVer,
+ unsigned int minorVer, unsigned int patchVer, cmMakefile* mf)
{
- // free the policies
- std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i
- = this->Policies.begin();
- for (;i != this->Policies.end(); ++i)
- {
- delete i->second;
+ std::ostringstream e;
+ 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";
}
+ 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());
}
-void cmPolicies::DefinePolicy(cmPolicies::PolicyID iD,
- const char *idString,
- const char *shortDescription,
- const char *longDescription,
- unsigned int majorVersionIntroduced,
- unsigned int minorVersionIntroduced,
- unsigned int patchVersionIntroduced,
- unsigned int tweakVersionIntroduced,
- cmPolicies::PolicyStatus status)
+static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
+ cmPolicies::PolicyStatus* defaultSetting)
{
- // a policy must be unique and can only be defined once
- if (this->Policies.find(iD) != this->Policies.end())
- {
- cmSystemTools::Error("Attempt to redefine a CMake policy for policy "
- "ID ", this->GetPolicyIDString(iD).c_str());
- return;
+ std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy;
+ std::string defaultValue = mf->GetSafeDefinition(defaultVar);
+ if (defaultValue == "NEW") {
+ *defaultSetting = cmPolicies::NEW;
+ } else if (defaultValue == "OLD") {
+ *defaultSetting = cmPolicies::OLD;
+ } else if (defaultValue == "") {
+ *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());
+ return false;
}
- this->Policies[iD] = new cmPolicy(iD, idString,
- shortDescription,
- longDescription,
- majorVersionIntroduced,
- minorVersionIntroduced,
- patchVersionIntroduced,
- tweakVersionIntroduced,
- status);
- this->PolicyStringMap[idString] = iD;
+ return true;
}
-//----------------------------------------------------------------------------
-bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf,
- const char *version)
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
{
std::string ver = "2.4.0";
- if (version && strlen(version) > 0)
- {
+ if (version && strlen(version) > 0) {
ver = version;
- }
+ }
unsigned int majorVer = 2;
unsigned int minorVer = 0;
@@ -660,31 +169,24 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf,
unsigned int tweakVer = 0;
// parse the string
- if(sscanf(ver.c_str(), "%u.%u.%u.%u",
- &majorVer, &minorVer, &patchVer, &tweakVer) < 2)
- {
- cmOStringStream e;
+ if (sscanf(ver.c_str(), "%u.%u.%u.%u", &majorVer, &minorVer, &patchVer,
+ &tweakVer) < 2) {
+ std::ostringstream e;
e << "Invalid policy version value \"" << ver << "\". "
<< "A numeric major.minor[.patch[.tweak]] must be given.";
mf->IssueMessage(cmake::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))
- {
- mf->IssueMessage(cmake::FATAL_ERROR,
- "An attempt was made to set the policy version of CMake to something "
- "earlier than \"2.4\". "
- "In CMake 2.4 and below backwards compatibility was handled with the "
- "CMAKE_BACKWARDS_COMPATIBILITY variable. "
- "In order to get compatibility features supporting versions earlier "
- "than 2.4 set policy CMP0001 to OLD to tell CMake to check the "
- "CMAKE_BACKWARDS_COMPATIBILITY variable. "
- "One way to do this is to set the policy version to 2.4 exactly."
- );
+ if (majorVer < 2 || (majorVer == 2 && minorVer < 4)) {
+ mf->IssueMessage(
+ cmake::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.");
return false;
- }
+ }
// It is an error if the policy version is greater than the running
// CMake.
@@ -697,9 +199,8 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf,
(majorVer == cmVersion::GetMajorVersion() &&
minorVer == cmVersion::GetMinorVersion() &&
patchVer == cmVersion::GetPatchVersion() &&
- tweakVer > cmVersion::GetTweakVersion()))
- {
- cmOStringStream e;
+ tweakVer > 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. "
<< "This is not allowed because the greater version may have new "
@@ -707,232 +208,127 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf,
<< "You may need a newer CMake version to build this project.";
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
- }
+ }
// now loop over all the policies and set them as appropriate
std::vector<cmPolicies::PolicyID> ancientPolicies;
- for(std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i
- = this->Policies.begin(); i != this->Policies.end(); ++i)
- {
- if (i->second->IsPolicyNewerThan(majorVer,minorVer,patchVer,tweakVer))
- {
- if(i->second->Status == cmPolicies::REQUIRED_ALWAYS)
- {
- ancientPolicies.push_back(i->first);
- }
- else
- {
+ for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
+ pid = PolicyID(pid + 1)) {
+ if (isPolicyNewerThan(pid, majorVer, minorVer, patchVer)) {
+ if (cmPolicies::GetPolicyStatus(pid) == cmPolicies::REQUIRED_ALWAYS) {
+ ancientPolicies.push_back(pid);
+ } else {
cmPolicies::PolicyStatus status = cmPolicies::WARN;
- if(!this->GetPolicyDefault(mf, i->second->IDString, &status) ||
- !mf->SetPolicy(i->second->ID, status))
- {
+ if (!GetPolicyDefault(mf, idToString(pid), &status) ||
+ !mf->SetPolicy(pid, status)) {
return false;
+ }
+ if (pid == cmPolicies::CMP0001 &&
+ (status == cmPolicies::WARN || status == cmPolicies::OLD)) {
+ if (!(mf->GetState()->GetInitializedCacheValue(
+ "CMAKE_BACKWARDS_COMPATIBILITY"))) {
+ // Set it to 2.4 because that is the last version where the
+ // variable had meaning.
+ mf->AddCacheDefinition(
+ "CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
+ "For backwards compatibility, what version of CMake "
+ "commands and "
+ "syntax should this version of CMake try to support.",
+ cmStateEnums::STRING);
}
}
}
- else
- {
- if (!mf->SetPolicy(i->second->ID, cmPolicies::NEW))
- {
+ } else {
+ if (!mf->SetPolicy(pid, cmPolicies::NEW)) {
return false;
- }
}
}
+ }
// Make sure the project does not use any ancient policies.
- if(!ancientPolicies.empty())
- {
- this->DiagnoseAncientPolicies(ancientPolicies,
- majorVer, minorVer, patchVer, mf);
+ if (!ancientPolicies.empty()) {
+ DiagnoseAncientPolicies(ancientPolicies, majorVer, minorVer, patchVer, mf);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-bool cmPolicies::GetPolicyDefault(cmMakefile* mf, std::string const& policy,
- cmPolicies::PolicyStatus* defaultSetting)
-{
- std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy;
- std::string defaultValue = mf->GetSafeDefinition(defaultVar.c_str());
- if(defaultValue == "NEW")
- {
- *defaultSetting = cmPolicies::NEW;
- }
- else if(defaultValue == "OLD")
- {
- *defaultSetting = cmPolicies::OLD;
- }
- else if(defaultValue == "")
- {
- *defaultSetting = cmPolicies::WARN;
- }
- else
- {
- cmOStringStream e;
- e << defaultVar << " has value \"" << defaultValue
- << "\" but must be \"OLD\", \"NEW\", or \"\" (empty).";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- return false;
- }
-
- return true;
-}
-
-bool cmPolicies::GetPolicyID(const char *id, cmPolicies::PolicyID &pid)
-{
- if (!id || strlen(id) < 1)
- {
- return false;
- }
- std::map<std::string,cmPolicies::PolicyID>::iterator pos =
- this->PolicyStringMap.find(id);
- if (pos == this->PolicyStringMap.end())
- {
- return false;
}
- pid = pos->second;
+
return true;
}
-std::string cmPolicies::GetPolicyIDString(cmPolicies::PolicyID pid)
+bool cmPolicies::GetPolicyID(const char* id, cmPolicies::PolicyID& pid)
{
- std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
- this->Policies.find(pid);
- if (pos == this->Policies.end())
- {
- return "";
- }
- return pos->second->IDString;
+ return stringToId(id, pid);
}
-
///! return a warning string for a given policy
std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
{
- std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
- this->Policies.find(id);
- if (pos == this->Policies.end())
- {
- cmSystemTools::Error(
- "Request for warning text for undefined policy!");
- return "Request for warning text for undefined policy!";
- }
+ 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.";
+ return msg.str();
+}
- cmOStringStream msg;
+std::string cmPolicies::GetPolicyDeprecatedWarning(cmPolicies::PolicyID id)
+{
+ std::ostringstream msg;
+ /* clang-format off */
msg <<
- "Policy " << pos->second->IDString << " is not set: "
- "" << pos->second->ShortDescription << " "
- "Run \"cmake --help-policy " << pos->second->IDString << "\" for "
- "policy details. "
- "Use the cmake_policy command to set the policy "
- "and suppress this warning.";
+ "The OLD behavior for policy " << idToString(id) << " "
+ "will be removed from a future version of CMake.\n"
+ "The cmake-policies(7) manual explains that the OLD behaviors of all "
+ "policies are deprecated and that a policy should be set to OLD only "
+ "under specific short-term circumstances. Projects should be ported "
+ "to the NEW behavior and not rely on setting a policy to OLD."
+ ;
+ /* clang-format on */
return msg.str();
}
-
///! return an error string for when a required policy is unspecified
std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
{
- std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
- this->Policies.find(id);
- if (pos == this->Policies.end())
- {
- cmSystemTools::Error(
- "Request for error text for undefined policy!");
- return "Request for error text for undefined policy!";
- }
-
- cmOStringStream error;
- error <<
- "Policy " << pos->second->IDString << " is not set to NEW: "
- "" << pos->second->ShortDescription << " "
- "Run \"cmake --help-policy " << pos->second->IDString << "\" 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 " << pos->second->IDString << " NEW)\n"
- "or by upgrading all policies with the code\n"
- " cmake_policy(VERSION " << pos->second->GetVersionString() <<
- ") # or later\n"
- "Run \"cmake --help-command cmake_policy\" for more information.";
+ std::ostringstream error;
+ 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 "
+ << idToVersion(id)
+ << ") # or later\n"
+ "Run \"cmake --help-command cmake_policy\" for more information.";
return error.str();
}
///! Get the default status for a policy
-cmPolicies::PolicyStatus
-cmPolicies::GetPolicyStatus(cmPolicies::PolicyID id)
-{
- // if the policy is not know then what?
- std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
- this->Policies.find(id);
- if (pos == this->Policies.end())
- {
- // TODO is this right?
- return cmPolicies::WARN;
- }
-
- return pos->second->Status;
-}
-
-void cmPolicies::GetDocumentation(std::vector<cmDocumentationEntry>& v)
+cmPolicies::PolicyStatus cmPolicies::GetPolicyStatus(
+ cmPolicies::PolicyID /*unused*/)
{
- // now loop over all the policies and set them as appropriate
- std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i
- = this->Policies.begin();
- for (;i != this->Policies.end(); ++i)
- {
- cmOStringStream full;
- full << i->second->LongDescription;
- full << "\nThis policy was introduced in CMake version ";
- full << i->second->GetVersionString() << ".";
- if(i->first != cmPolicies::CMP0000)
- {
- full << " "
- << "CMake version " << cmVersion::GetCMakeVersion() << " ";
- // add in some more text here based on status
- switch (i->second->Status)
- {
- case cmPolicies::WARN:
- full << "warns when the policy is not set and uses OLD behavior. "
- << "Use the cmake_policy command to set it to OLD or NEW "
- << "explicitly.";
- break;
- case cmPolicies::OLD:
- full << "defaults to the OLD behavior for this policy.";
- break;
- case cmPolicies::NEW:
- full << "defaults to the NEW behavior for this policy.";
- break;
- case cmPolicies::REQUIRED_IF_USED:
- full << "requires the policy to be set to NEW if you use it. "
- << "Use the cmake_policy command to set it to NEW.";
- break;
- case cmPolicies::REQUIRED_ALWAYS:
- full << "requires the policy to be set to NEW. "
- << "Use the cmake_policy command to set it to NEW.";
- break;
- }
- }
- cmDocumentationEntry e(i->second->IDString.c_str(),
- i->second->ShortDescription.c_str(),
- full.str().c_str());
- v.push_back(e);
- }
+ return cmPolicies::WARN;
}
-//----------------------------------------------------------------------------
-std::string
-cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id)
+std::string cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id)
{
- std::string pid = this->GetPolicyIDString(id);
- cmOStringStream e;
+ std::string pid = idToString(id);
+ std::ostringstream e;
e << "Policy " << pid << " may not be set to OLD behavior because this "
<< "version of CMake no longer supports it. "
<< "The policy was introduced in "
- << "CMake version " << this->Policies[id]->GetVersionString()
+ << "CMake version " << idToVersion(id)
<< ", and use of NEW behavior is now required."
<< "\n"
<< "Please either update your CMakeLists.txt files to conform to "
@@ -942,28 +338,35 @@ cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id)
return e.str();
}
-//----------------------------------------------------------------------------
-void
-cmPolicies::DiagnoseAncientPolicies(std::vector<PolicyID> const& ancient,
- unsigned int majorVer,
- unsigned int minorVer,
- unsigned int patchVer,
- cmMakefile* mf)
+cmPolicies::PolicyStatus cmPolicies::PolicyMap::Get(
+ cmPolicies::PolicyID id) const
{
- cmOStringStream e;
- e << "The project requests behavior compatible with CMake version \""
- << majorVer << "." << minorVer << "." << patchVer
- << "\", which requires the OLD behavior for some policies:\n";
- for(std::vector<PolicyID>::const_iterator
- i = ancient.begin(); i != ancient.end(); ++i)
- {
- cmPolicy const* policy = this->Policies[*i];
- e << " " << policy->IDString << ": " << policy->ShortDescription << "\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().c_str());
+ PolicyStatus status = cmPolicies::WARN;
+
+ if (this->Status[(POLICY_STATUS_COUNT * id) + OLD]) {
+ status = cmPolicies::OLD;
+ } else if (this->Status[(POLICY_STATUS_COUNT * id) + NEW]) {
+ status = cmPolicies::NEW;
+ }
+ return status;
+}
+
+void cmPolicies::PolicyMap::Set(cmPolicies::PolicyID id,
+ cmPolicies::PolicyStatus status)
+{
+ this->Status[(POLICY_STATUS_COUNT * id) + OLD] = (status == OLD);
+ this->Status[(POLICY_STATUS_COUNT * id) + WARN] = (status == WARN);
+ this->Status[(POLICY_STATUS_COUNT * id) + NEW] = (status == NEW);
+}
+
+bool cmPolicies::PolicyMap::IsDefined(cmPolicies::PolicyID id) const
+{
+ return this->Status[(POLICY_STATUS_COUNT * id) + OLD] ||
+ this->Status[(POLICY_STATUS_COUNT * id) + WARN] ||
+ this->Status[(POLICY_STATUS_COUNT * id) + NEW];
+}
+
+bool cmPolicies::PolicyMap::IsEmpty() const
+{
+ return this->Status.none();
}
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 5b843a9ad..69cbc1844 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -1,79 +1,264 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmPolicies_h
#define cmPolicies_h
-#include "cmCustomCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <bitset>
+#include <string>
-class cmake;
class cmMakefile;
-class cmPolicy;
+
+#define CM_FOR_EACH_POLICY_TABLE(POLICY, SELECT) \
+ SELECT(POLICY, CMP0000, \
+ "A minimum required CMake version must be specified.", 2, 6, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0001, \
+ "CMAKE_BACKWARDS_COMPATIBILITY should no longer be used.", 2, 6, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0002, "Logical target names must be globally unique.", 2, \
+ 6, 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0003, \
+ "Libraries linked via full path no longer produce linker search paths.", \
+ 2, 6, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0004, \
+ "Libraries linked may not have leading or trailing whitespace.", 2, \
+ 6, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0005, \
+ "Preprocessor definition values are now escaped automatically.", 2, \
+ 6, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0006, \
+ "Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION.", \
+ 2, 6, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0007, "list command no longer ignores empty elements.", \
+ 2, 6, 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0008, \
+ "Libraries linked by full-path must have a valid library file name.", 2, \
+ 6, 1, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0009, \
+ "FILE GLOB_RECURSE calls should not follow symlinks by default.", 2, \
+ 6, 2, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0010, "Bad variable reference syntax is an error.", 2, 6, \
+ 3, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0011, \
+ "Included scripts do automatic cmake_policy PUSH and POP.", 2, 6, 3, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0012, "if() recognizes numbers and boolean constants.", \
+ 2, 8, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0013, "Duplicate binary directories are not allowed.", 2, \
+ 8, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0014, "Input directories must have CMakeLists.txt.", 2, \
+ 8, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0015, \
+ "link_directories() treats paths relative to the source dir.", 2, 8, \
+ 1, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0016, \
+ "target_link_libraries() reports error if its only argument " \
+ "is not a target.", \
+ 2, 8, 3, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0017, \
+ "Prefer files from the CMake module directory when including from " \
+ "there.", \
+ 2, 8, 4, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0018, \
+ "Ignore CMAKE_SHARED_LIBRARY_<Lang>_FLAGS variable.", 2, 8, 9, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0019, \
+ "Do not re-expand variables in include and link information.", 2, 8, \
+ 11, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0020, \
+ "Automatically link Qt executables to qtmain target on Windows.", 2, \
+ 8, 11, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0021, \
+ "Fatal error on relative paths in INCLUDE_DIRECTORIES target property.", \
+ 2, 8, 12, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0022, \
+ "INTERFACE_LINK_LIBRARIES defines the link interface.", 2, 8, 12, \
+ cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0023, \
+ "Plain and keyword target_link_libraries signatures cannot be mixed.", 2, \
+ 8, 12, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0024, "Disallow include export result.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0025, "Compiler id for Apple Clang is now AppleClang.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0026, "Disallow use of the LOCATION target property.", 3, \
+ 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0027, \
+ "Conditionally linked imported targets with missing include " \
+ "directories.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0028, \
+ "Double colon in target name means ALIAS or IMPORTED target.", 3, 0, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0029, "The subdir_depends command should not be called.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0030, \
+ "The use_mangled_mesa command should not be called.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0031, "The load_command command should not be called.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0032, \
+ "The output_required_files command should not be called.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0033, \
+ "The export_library_dependencies command should not be called.", 3, \
+ 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0034, "The utility_source command should not be called.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0035, \
+ "The variable_requires command should not be called.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0036, "The build_name command should not be called.", 3, \
+ 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0037, \
+ "Target names should not be reserved and should match a validity " \
+ "pattern.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0038, "Targets may not link directly to themselves.", 3, \
+ 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0039, "Utility targets may not have link dependencies.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0040, \
+ "The target in the TARGET signature of add_custom_command() must " \
+ "exist.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0041, \
+ "Error on relative include with generator expression.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0042, "MACOSX_RPATH is enabled by default.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0043, "Ignore COMPILE_DEFINITIONS_<Config> properties.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0044, \
+ "Case sensitive <LANG>_COMPILER_ID generator expressions.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0045, \
+ "Error on non-existent target in get_target_property.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0046, \
+ "Error on non-existent dependency in add_dependencies.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0047, "Use QCC compiler id for the qcc drivers on QNX.", \
+ 3, 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0048, "project() command manages VERSION variables.", 3, \
+ 0, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0049, \
+ "Do not expand variables in target source entries.", 3, 0, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0050, "Disallow add_custom_command SOURCE signatures.", \
+ 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.", \
+ 3, 1, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0053, \
+ "Simplify variable reference and escape sequence evaluation.", 3, 1, \
+ 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0054, \
+ "Only interpret if() arguments as variables or keywords when unquoted.", \
+ 3, 1, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0055, "Strict checking for break() command.", 3, 2, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0056, \
+ "Honor link flags in try_compile() source-file signature.", 3, 2, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0057, "Support new IN_LIST if() operator.", 3, 3, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0058, \
+ "Ninja requires custom command byproducts to be explicit.", 3, 3, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0059, \
+ "Do not treat DEFINITIONS as a built-in directory property.", 3, 3, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0060, \
+ "Link libraries by full path even in implicit directories.", 3, 3, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0061, \
+ "CTest does not by default tell make to ignore errors (-i).", 3, 3, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0062, "Disallow install() of export() result.", 3, 3, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0063, \
+ "Honor visibility properties for all target types.", 3, 3, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0064, "Support new TEST if() operator.", 3, 4, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0065, \
+ "Do not add flags to export symbols from executables without " \
+ "the ENABLE_EXPORTS target property.", \
+ 3, 4, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0066, \
+ "Honor per-config flags in try_compile() source-file signature.", 3, \
+ 7, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0067, \
+ "Honor language standard in try_compile() source-file signature.", \
+ 3, 8, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0068, \
+ "RPATH settings on macOS do not affect install_name.", 3, 9, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0069, \
+ "INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.", 3, 9, 0, \
+ cmPolicies::WARN)
+
+#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
+#define CM_FOR_EACH_POLICY_ID(POLICY) \
+ CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID)
+
+#define CM_FOR_EACH_TARGET_POLICY(F) \
+ F(CMP0003) \
+ F(CMP0004) \
+ F(CMP0008) \
+ F(CMP0020) \
+ F(CMP0021) \
+ F(CMP0022) \
+ F(CMP0027) \
+ F(CMP0038) \
+ F(CMP0041) \
+ F(CMP0042) \
+ F(CMP0046) \
+ F(CMP0052) \
+ F(CMP0060) \
+ F(CMP0063) \
+ F(CMP0065) \
+ F(CMP0068) \
+ F(CMP0069)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
*
* See the cmake wiki section on
- * <a href="http://www.cmake.org/Wiki/CMake/Policies">policies</a>
+ * <a href="https://cmake.org/Wiki/CMake/Policies">policies</a>
* for an overview of this class's purpose
*/
class cmPolicies
{
public:
- cmPolicies();
- ~cmPolicies();
-
/// Status of a policy
- enum PolicyStatus {
- OLD, ///< Use old behavior
+ enum PolicyStatus
+ {
+ OLD, ///< Use old behavior
WARN, ///< Use old behavior but issue a warning
- NEW, ///< Use new behavior
+ NEW, ///< Use new behavior
/// Issue an error if user doesn't set policy status to NEW and hits the
/// check
REQUIRED_IF_USED,
REQUIRED_ALWAYS ///< Issue an error unless user sets policy status to NEW.
};
- static const char* PolicyStatusNames[];
/// Policy identifiers
enum PolicyID
{
- CMP0000, ///< Policy version specification
- CMP0001, ///< Ignore old compatibility variable
- CMP0002, ///< Target names must be unique
- CMP0003, ///< Linking does not include extra -L paths
- CMP0004, ///< Libraries linked may not have leading or trailing whitespace
- CMP0005, ///< Definition value escaping
- CMP0006, ///< BUNDLE install rules needed for MACOSX_BUNDLE targets
- CMP0007, ///< list command handling of empty elements
- CMP0008, ///< Full-path libraries must be a valid library file name
- CMP0009, ///< GLOB_RECURSE should not follow symlinks by default
- CMP0010, ///< Bad variable reference syntax is an error
- CMP0011, ///< Strong policy scope for include and find_package
- CMP0012, ///< Recognize numbers and boolean constants in if()
- CMP0013, ///< Duplicate binary directories not allowed
- CMP0014, ///< Input directories must have CMakeLists.txt
- CMP0015, ///< link_directories() treats paths relative to source dir
- /// target_link_libraries() fails if only argument is not a target
- CMP0016,
- CMP0017, ///< Prefer files in CMAKE_ROOT when including from CMAKE_ROOT
- CMP0018, ///< Ignore language flags for shared libs, and adhere to
- /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
- /// instead.
- CMP0019, ///< No variable re-expansion in include and link info
- CMP0020, ///< Automatically link Qt executables to qtmain target
- CMP0021, ///< Fatal error on relative paths in INCLUDE_DIRECTORIES
- /// target property
- CMP0022, ///< INTERFACE_LINK_LIBRARIES defines the link interface
- CMP0023, ///< Disallow mixing keyword and plain tll signatures
+#define POLICY_ENUM(POLICY_ID) POLICY_ID,
+ CM_FOR_EACH_POLICY_ID(POLICY_ENUM)
+#undef POLICY_ENUM
/** \brief Always the last entry.
*
@@ -84,53 +269,36 @@ public:
};
///! convert a string policy ID into a number
- bool GetPolicyID(const char *id, /* out */ cmPolicies::PolicyID &pid);
- std::string GetPolicyIDString(cmPolicies::PolicyID pid);
+ static bool GetPolicyID(const char* id, /* out */ cmPolicies::PolicyID& pid);
///! Get the default status for a policy
- cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
-
- ///! Define a Policy for CMake
- void DefinePolicy(cmPolicies::PolicyID id,
- const char *stringID,
- const char *shortDescription,
- const char *longDescription,
- unsigned int majorVersionIntroduced,
- unsigned int minorVersionIntroduced,
- unsigned int patchVersionIntroduced,
- unsigned int tweakVersionIntroduced,
- cmPolicies::PolicyStatus status);
+ static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
///! Set a policy level for this listfile
- bool ApplyPolicyVersion(cmMakefile *mf, const char *version);
+ static bool ApplyPolicyVersion(cmMakefile* mf, const char* version);
///! return a warning string for a given policy
- std::string GetPolicyWarning(cmPolicies::PolicyID id);
+ 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
- std::string GetRequiredPolicyError(cmPolicies::PolicyID id);
+ static std::string GetRequiredPolicyError(cmPolicies::PolicyID id);
///! return an error string for when a required policy is unspecified
- std::string GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id);
-
- ///! Get docs for policies
- void GetDocumentation(std::vector<cmDocumentationEntry>& v);
+ static std::string GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id);
/** Represent a set of policy values. */
- typedef std::map<PolicyID, PolicyStatus> PolicyMap;
+ struct PolicyMap
+ {
+ PolicyStatus Get(PolicyID id) const;
+ void Set(PolicyID id, PolicyStatus status);
+ bool IsDefined(PolicyID id) const;
+ bool IsEmpty() const;
private:
- // might have to make these internal for VS6 not sure yet
- std::map<PolicyID,cmPolicy *> Policies;
- std::map<std::string,PolicyID> PolicyStringMap;
-
- void DiagnoseAncientPolicies(std::vector<PolicyID> const& ancient,
- unsigned int majorVer, unsigned int minorVer,
- unsigned int patchVer, cmMakefile* mf);
-
- bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
- cmPolicies::PolicyStatus* defaultStatus);
-
+#define POLICY_STATUS_COUNT 3
+ std::bitset<cmPolicies::CMPCOUNT * POLICY_STATUS_COUNT> Status;
+ };
};
#endif
diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx
new file mode 100644
index 000000000..617e1ca7d
--- /dev/null
+++ b/Source/cmProcessOutput.cxx
@@ -0,0 +1,173 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmProcessOutput.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+unsigned int cmProcessOutput::defaultCodepage =
+ KWSYS_ENCODING_DEFAULT_CODEPAGE;
+#endif
+
+cmProcessOutput::Encoding cmProcessOutput::FindEncoding(
+ std::string const& name)
+{
+ Encoding encoding = Auto;
+ if (name == "UTF8") {
+ encoding = UTF8;
+ } else if (name == "NONE") {
+ encoding = None;
+ } else if (name == "ANSI") {
+ encoding = ANSI;
+ } else if (name == "OEM") {
+ encoding = OEM;
+ }
+ return encoding;
+}
+
+cmProcessOutput::cmProcessOutput(Encoding encoding, unsigned int maxSize)
+{
+#if defined(_WIN32)
+ codepage = 0;
+ bufferSize = maxSize;
+ if (encoding == None) {
+ codepage = defaultCodepage;
+ } else if (encoding == Auto) {
+ codepage = GetConsoleCP();
+ } else if (encoding == UTF8) {
+ codepage = CP_UTF8;
+ } else if (encoding == OEM) {
+ codepage = GetOEMCP();
+ }
+ if (!codepage || encoding == ANSI) {
+ codepage = GetACP();
+ }
+#else
+ static_cast<void>(encoding);
+ static_cast<void>(maxSize);
+#endif
+}
+
+cmProcessOutput::~cmProcessOutput()
+{
+}
+
+bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded,
+ size_t id)
+{
+#if !defined(_WIN32)
+ static_cast<void>(id);
+ decoded.swap(raw);
+ return true;
+#else
+ bool success = true;
+ decoded = raw;
+ if (id > 0) {
+ if (rawparts.size() < id) {
+ rawparts.reserve(id);
+ while (rawparts.size() < id)
+ rawparts.push_back(std::string());
+ }
+ raw = rawparts[id - 1] + raw;
+ rawparts[id - 1].clear();
+ decoded = raw;
+ }
+ if (raw.size() > 0 && codepage != defaultCodepage) {
+ success = false;
+ CPINFOEXW cpinfo;
+ if (id > 0 && bufferSize > 0 && raw.size() == bufferSize &&
+ GetCPInfoExW(codepage, 0, &cpinfo) == 1 && cpinfo.MaxCharSize > 1) {
+ if (cpinfo.MaxCharSize == 2 && cpinfo.LeadByte[0] != 0) {
+ LPSTR prevChar =
+ CharPrevExA(codepage, raw.c_str(), raw.c_str() + raw.size(), 0);
+ bool isLeadByte =
+ (*(prevChar + 1) == 0) && IsDBCSLeadByteEx(codepage, *prevChar);
+ if (isLeadByte) {
+ rawparts[id - 1] += *(raw.end() - 1);
+ raw.resize(raw.size() - 1);
+ }
+ success = DoDecodeText(raw, decoded, NULL);
+ } else {
+ bool restoreDecoded = false;
+ std::string firstDecoded = decoded;
+ wchar_t lastChar = 0;
+ for (UINT i = 0; i < cpinfo.MaxCharSize; i++) {
+ success = DoDecodeText(raw, decoded, &lastChar);
+ if (success && lastChar != 0) {
+ if (i == 0) {
+ firstDecoded = decoded;
+ }
+ if (lastChar == cpinfo.UnicodeDefaultChar) {
+ restoreDecoded = true;
+ rawparts[id - 1] = *(raw.end() - 1) + rawparts[id - 1];
+ raw.resize(raw.size() - 1);
+ } else {
+ restoreDecoded = false;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (restoreDecoded) {
+ decoded = firstDecoded;
+ rawparts[id - 1].clear();
+ }
+ }
+ } else {
+ success = DoDecodeText(raw, decoded, NULL);
+ }
+ }
+ return success;
+#endif
+}
+
+bool cmProcessOutput::DecodeText(const char* data, size_t length,
+ std::string& decoded, size_t id)
+{
+ return DecodeText(std::string(data, length), decoded, id);
+}
+
+bool cmProcessOutput::DecodeText(std::vector<char> raw,
+ std::vector<char>& decoded, size_t id)
+{
+ std::string str;
+ const bool success =
+ DecodeText(std::string(raw.begin(), raw.end()), str, id);
+ decoded.assign(str.begin(), str.end());
+ return success;
+}
+
+#if defined(_WIN32)
+bool cmProcessOutput::DoDecodeText(std::string raw, std::string& decoded,
+ wchar_t* lastChar)
+{
+ bool success = false;
+ const int wlength =
+ MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), NULL, 0);
+ wchar_t* wdata = new wchar_t[wlength];
+ int r = MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), wdata,
+ wlength);
+ if (r > 0) {
+ if (lastChar) {
+ *lastChar = 0;
+ if ((wlength >= 2 && wdata[wlength - 2] != wdata[wlength - 1]) ||
+ wlength >= 1) {
+ *lastChar = wdata[wlength - 1];
+ }
+ }
+ int length = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, NULL,
+ 0, NULL, NULL);
+ char* data = new char[length];
+ r = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, data, length,
+ NULL, NULL);
+ if (r > 0) {
+ decoded = std::string(data, length);
+ success = true;
+ }
+ delete[] data;
+ }
+ delete[] wdata;
+ return success;
+}
+#endif
diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h
new file mode 100644
index 000000000..b5ec4a8be
--- /dev/null
+++ b/Source/cmProcessOutput.h
@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmProcessOutput_h
+#define cmProcessOutput_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+/** \class cmProcessOutput
+ * \brief Decode text data to internal encoding.
+ *
+ * cmProcessOutput is used to decode text output from external process
+ * using external encoding to our internal encoding.
+ */
+class cmProcessOutput
+{
+public:
+ enum Encoding
+ {
+ None,
+ Auto,
+ UTF8,
+ ANSI,
+ OEM
+ };
+
+ /**
+ * 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.
+ static unsigned int defaultCodepage;
+
+ /**
+ * A class constructor.
+ * \param encoding external process encoding from which we will decode.
+ * \param maxSize a maximal size for process output buffer. It should match
+ * to KWSYSPE_PIPE_BUFFER_SIZE. If text we decode is same size as \a maxSize
+ * then we will check for incomplete character at end of buffer and
+ * we will not return last incomplete character. This character will be
+ * returned with next DecodeText() call. To disable this behavior specify
+ * 0 as \a maxSize.
+ */
+ cmProcessOutput(Encoding encoding = Auto, unsigned int maxSize = 1024);
+ ~cmProcessOutput();
+ /**
+ * Decode \a raw string using external encoding to internal
+ * encoding in \a decoded.
+ * \a id specifies which internal buffer to use. This is important when we
+ * are decoding both stdout and stderr from process output and we need to
+ * keep incomplete characters in separate buffers for each stream.
+ * \return true if successfully decoded \a raw to \a decoded or false if not.
+ */
+ bool DecodeText(std::string raw, std::string& decoded, size_t id = 0);
+ /**
+ * Decode \a data with \a length from external encoding to internal
+ * encoding in \a decoded.
+ * \param data a pointer to process output text data.
+ * \param length a size of data buffer.
+ * \param decoded a string which will contain decoded text.
+ * \param id an internal buffer id to use.
+ * \return true if successfully decoded \a data to \a decoded or false if
+ * not.
+ */
+ bool DecodeText(const char* data, size_t length, std::string& decoded,
+ size_t id = 0);
+ /**
+ * \overload
+ */
+ bool DecodeText(std::vector<char> raw, std::vector<char>& decoded,
+ size_t id = 0);
+
+private:
+#if defined(_WIN32)
+ unsigned int codepage;
+ unsigned int bufferSize;
+ std::vector<std::string> rawparts;
+ bool DoDecodeText(std::string raw, std::string& decoded, wchar_t* lastChar);
+#endif
+};
+
+#endif
diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx
index d2f7bf320..de7b06126 100644
--- a/Source/cmProcessTools.cxx
+++ b/Source/cmProcessTools.cxx
@@ -1,90 +1,87 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 "cmsys/Process.h"
+#include <ostream>
-//----------------------------------------------------------------------------
-void cmProcessTools::RunProcess(struct cmsysProcess_s* cp,
- OutputParser* out, OutputParser* err)
+void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
+ OutputParser* err, Encoding encoding)
{
cmsysProcess_Execute(cp);
- char* data = 0;
+ char* data = CM_NULLPTR;
int length = 0;
int p;
- while((out||err) && (p=cmsysProcess_WaitForData(cp, &data, &length, 0), p))
- {
- if(out && p == cmsysProcess_Pipe_STDOUT)
- {
- if(!out->Process(data, length))
- {
- out = 0;
- }
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
+ while ((out || err) &&
+ (p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
+ if (out && p == cmsysProcess_Pipe_STDOUT) {
+ processOutput.DecodeText(data, length, strdata, 1);
+ if (!out->Process(strdata.c_str(), int(strdata.size()))) {
+ out = CM_NULLPTR;
}
- else if(err && p == cmsysProcess_Pipe_STDERR)
- {
- if(!err->Process(data, length))
- {
- err = 0;
- }
+ } 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;
}
}
- cmsysProcess_WaitForExit(cp, 0);
+ }
+ if (out) {
+ processOutput.DecodeText(std::string(), strdata, 1);
+ if (!strdata.empty()) {
+ out->Process(strdata.c_str(), int(strdata.size()));
+ }
+ }
+ if (err) {
+ processOutput.DecodeText(std::string(), strdata, 2);
+ if (!strdata.empty()) {
+ out->Process(strdata.c_str(), int(strdata.size()));
+ }
+ }
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
}
-
-//----------------------------------------------------------------------------
-cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR):
- Separator(sep), IgnoreCR(ignoreCR), Log(0), Prefix(0), LineEnd('\0')
+cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR)
+ : Log(CM_NULLPTR)
+ , Prefix(CM_NULLPTR)
+ , Separator(sep)
+ , LineEnd('\0')
+ , IgnoreCR(ignoreCR)
{
}
-//----------------------------------------------------------------------------
void cmProcessTools::LineParser::SetLog(std::ostream* log, const char* prefix)
{
this->Log = log;
- this->Prefix = prefix? prefix : "";
+ this->Prefix = prefix ? prefix : "";
}
-//----------------------------------------------------------------------------
bool cmProcessTools::LineParser::ProcessChunk(const char* first, int length)
{
const char* last = first + length;
- for(const char* c = first; c != last; ++c)
- {
- if(*c == this->Separator || *c == '\0')
- {
+ for (const char* c = first; c != last; ++c) {
+ if (*c == this->Separator || *c == '\0') {
this->LineEnd = *c;
// Log this line.
- if(this->Log && this->Prefix)
- {
+ if (this->Log && this->Prefix) {
*this->Log << this->Prefix << this->Line << "\n";
- }
+ }
// Hand this line to the subclass implementation.
- if(!this->ProcessLine())
- {
+ if (!this->ProcessLine()) {
this->Line = "";
return false;
- }
+ }
this->Line = "";
- }
- else if(*c != '\r' || !this->IgnoreCR)
- {
+ } else if (*c != '\r' || !this->IgnoreCR) {
// Append this character to the line under construction.
this->Line.append(1, *c);
- }
}
+ }
return true;
}
diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h
index 439726dd0..e7d9a10eb 100644
--- a/Source/cmProcessTools.h
+++ b/Source/cmProcessTools.h
@@ -1,18 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmProcessTools_h
#define cmProcessTools_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+#include "cmProcessOutput.h"
+
+#include <iosfwd>
+#include <string.h>
+#include <string>
/** \class cmProcessTools
* \brief Helper classes for process output parsing
@@ -21,6 +17,7 @@
class cmProcessTools
{
public:
+ typedef cmProcessOutput::Encoding Encoding;
/** Abstract interface for process output parsers. */
class OutputParser
{
@@ -29,9 +26,13 @@ public:
done incrementally. Returns true if the parser is interested
in any more data and false if it is done. */
bool Process(const char* data, int length)
- { return this->ProcessChunk(data, length); }
+ {
+ return this->ProcessChunk(data, length);
+ }
bool Process(const char* data)
- { return this->Process(data, static_cast<int>(strlen(data))); }
+ {
+ return this->Process(data, static_cast<int>(strlen(data)));
+ }
virtual ~OutputParser() {}
protected:
@@ -41,7 +42,7 @@ public:
};
/** Process output parser that extracts one line at a time. */
- class LineParser: public OutputParser
+ class LineParser : public OutputParser
{
public:
/** Construct with line separation character and choose whether to
@@ -50,14 +51,15 @@ public:
/** Configure logging of lines as they are extracted. */
void SetLog(std::ostream* log, const char* prefix);
+
protected:
- char Separator;
- bool IgnoreCR;
std::ostream* Log;
const char* Prefix;
- char LineEnd;
std::string Line;
- virtual bool ProcessChunk(const char* data, int length);
+ char Separator;
+ char LineEnd;
+ bool IgnoreCR;
+ bool ProcessChunk(const char* data, int length) CM_OVERRIDE;
/** Implement in a subclass to process one line of input. It
should return true only if it is interested in more data. */
@@ -65,18 +67,22 @@ public:
};
/** Trivial line handler for simple logging. */
- class OutputLogger: public LineParser
+ class OutputLogger : public LineParser
{
public:
- OutputLogger(std::ostream& log, const char* prefix = 0)
- { this->SetLog(&log, prefix); }
+ OutputLogger(std::ostream& log, const char* prefix = CM_NULLPTR)
+ {
+ this->SetLog(&log, prefix);
+ }
+
private:
- virtual bool ProcessLine() { return true; }
+ bool ProcessLine() CM_OVERRIDE { return true; }
};
/** Run a process and send output to given parsers. */
- static void RunProcess(struct cmsysProcess_s* cp,
- OutputParser* out, OutputParser* err = 0);
+ static void RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
+ OutputParser* err = CM_NULLPTR,
+ Encoding encoding = cmProcessOutput::Auto);
};
#endif
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 11f9a7621..d72c7909c 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -1,50 +1,53 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmProjectCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
+#include <sstream>
+#include <stdio.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmProjectCommand.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
// cmProjectCommand
-bool cmProjectCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("PROJECT called with incorrect number of arguments");
return false;
- }
- this->Makefile->SetProjectName(args[0].c_str());
+ }
+
+ std::string const& projectName = args[0];
- std::string bindir = args[0];
+ this->Makefile->SetProjectName(projectName);
+
+ std::string bindir = projectName;
bindir += "_BINARY_DIR";
- std::string srcdir = args[0];
+ std::string srcdir = projectName;
srcdir += "_SOURCE_DIR";
- this->Makefile->AddCacheDefinition
- (bindir.c_str(),
- this->Makefile->GetCurrentOutputDirectory(),
- "Value Computed by CMake", cmCacheManager::STATIC);
- this->Makefile->AddCacheDefinition
- (srcdir.c_str(),
- this->Makefile->GetCurrentDirectory(),
- "Value Computed by CMake", cmCacheManager::STATIC);
+ 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);
bindir = "PROJECT_BINARY_DIR";
srcdir = "PROJECT_SOURCE_DIR";
- this->Makefile->AddDefinition(bindir.c_str(),
- this->Makefile->GetCurrentOutputDirectory());
- this->Makefile->AddDefinition(srcdir.c_str(),
- this->Makefile->GetCurrentDirectory());
+ this->Makefile->AddDefinition(bindir,
+ this->Makefile->GetCurrentBinaryDirectory());
+ this->Makefile->AddDefinition(srcdir,
+ this->Makefile->GetCurrentSourceDirectory());
- this->Makefile->AddDefinition("PROJECT_NAME", args[0].c_str());
+ this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str());
// Set the CMAKE_PROJECT_NAME variable to be the highest-level
// project name in the tree. If there are two project commands
@@ -52,49 +55,199 @@ bool cmProjectCommand
// 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->GetLocalGenerator()->GetParent() == 0) )
- {
- this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str());
- this->Makefile->AddCacheDefinition
- ("CMAKE_PROJECT_NAME",
- args[0].c_str(),
- "Value Computed by CMake", cmCacheManager::STATIC);
- }
+ 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);
+ }
+ bool haveVersion = false;
+ bool haveLanguages = false;
+ bool haveDescription = false;
+ std::string version;
+ std::string description;
std::vector<std::string> languages;
- if(args.size() > 1)
+ enum Doing
+ {
+ DoingDescription,
+ DoingLanguages,
+ DoingVersion
+ };
+ Doing doing = DoingLanguages;
+ 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.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveLanguages = true;
+ doing = DoingLanguages;
+ } else if (args[i] == "VERSION") {
+ if (haveVersion) {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "VERSION may be specified at most once.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveVersion = true;
+ doing = DoingVersion;
+ } else if (args[i] == "DESCRIPTION") {
+ if (haveDescription) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "DESCRITPION may be specified at most once.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveDescription = true;
+ doing = DoingDescription;
+ } else if (doing == DoingVersion) {
+ doing = DoingLanguages;
+ version = args[i];
+ } else if (doing == DoingDescription) {
+ doing = DoingLanguages;
+ description = args[i];
+ } else // doing == DoingLanguages
{
- for(size_t i =1; i < args.size(); ++i)
- {
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.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ if (haveLanguages && languages.empty()) {
+ languages.push_back("NONE");
+ }
+
+ cmPolicies::PolicyStatus cmp0048 =
+ this->Makefile->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");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
+ cmsys::RegularExpression vx(
+ "^([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);
+ 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;
}
}
- else
- {
+
+ std::string vv;
+ vv = projectName + "_VERSION";
+ this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str());
+ this->Makefile->AddDefinition(vv, vs.c_str());
+ vv = projectName + "_VERSION_MAJOR";
+ this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]);
+ this->Makefile->AddDefinition(vv, vb[0]);
+ vv = projectName + "_VERSION_MINOR";
+ this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]);
+ this->Makefile->AddDefinition(vv, vb[1]);
+ vv = projectName + "_VERSION_PATCH";
+ this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]);
+ this->Makefile->AddDefinition(vv, vb[2]);
+ vv = projectName + "_VERSION_TWEAK";
+ this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]);
+ this->Makefile->AddDefinition(vv, vb[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::string vw;
+ for (std::vector<std::string>::iterator i = vv.begin(); i != vv.end();
+ ++i) {
+ const char* v = this->Makefile->GetDefinition(*i);
+ if (v && *v) {
+ if (cmp0048 == cmPolicies::WARN) {
+ vw += "\n ";
+ vw += *i;
+ } else {
+ this->Makefile->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());
+ }
+ }
+
+ 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);
+ }
+ }
+
+ if (languages.empty()) {
// if no language is specified do c and c++
languages.push_back("C");
languages.push_back("CXX");
- }
+ }
this->Makefile->EnableLanguage(languages, false);
- std::string extraInclude = "CMAKE_PROJECT_" + args[0] + "_INCLUDE";
- const char* include = this->Makefile->GetDefinition(extraInclude.c_str());
- if(include)
- {
- std::string fullFilePath;
- bool readit =
- this->Makefile->ReadListFile( this->Makefile->GetCurrentListFile(),
- include);
- if(!readit && !cmSystemTools::GetFatalErrorOccured())
- {
- std::string m =
- "could not find file:\n"
- " ";
+ 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.c_str());
+ this->SetError(m);
return false;
- }
}
+ }
return true;
}
-
diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h
index 9547c4c8f..3c579ac9d 100644
--- a/Source/cmProjectCommand.h
+++ b/Source/cmProjectCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmProjectCommand_h
#define cmProjectCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmProjectCommand
* \brief Specify the name for this build project.
*
@@ -28,61 +26,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmProjectCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmProjectCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "project";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set a name for the entire project.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " project(<projectname> [languageName1 languageName2 ... ] )\n"
- "Sets the name of the project. "
- "Additionally this sets the variables <projectName>_BINARY_DIR and "
- "<projectName>_SOURCE_DIR to the respective values.\n"
- "Optionally you can specify which languages your project supports. "
- "Example languages are CXX (i.e. C++), C, Fortran, etc. "
- "By default C and CXX are enabled. E.g. if you do not have a "
- "C++ compiler, you can disable the check for it by explicitly listing "
- "the languages you want to support, e.g. C. By using the special "
- "language \"NONE\" all checks for any language can be disabled. "
- "If a variable exists called CMAKE_PROJECT_<projectName>_INCLUDE, "
- "the file pointed to by that variable will be included as the last step "
- "of the project command."
- "\n"
- "The top-level CMakeLists.txt file for a project must contain a "
- "literal, direct call to the project() command; loading one through "
- "the include() command is not sufficient. "
- "If no such call exists CMake will implicitly add one to the top that "
- "enables the default languages (C and CXX).";
- }
-
- cmTypeMacro(cmProjectCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx
index 3b37cf3b8..222afb497 100644
--- a/Source/cmProperty.cxx
+++ b/Source/cmProperty.cxx
@@ -1,40 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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 "cmSystemTools.h"
-void cmProperty::Set(const char *name, const char *value)
+#include "cmConfigure.h"
+
+void cmProperty::Set(const char* value)
{
- this->Name = name;
this->Value = value;
this->ValueHasBeenSet = true;
}
-void cmProperty::Append(const char *name, const char *value, bool asString)
+void cmProperty::Append(const char* value, bool asString)
{
- this->Name = name;
- if(!this->Value.empty() && *value && !asString)
- {
+ if (!this->Value.empty() && *value && !asString) {
this->Value += ";";
- }
+ }
this->Value += value;
this->ValueHasBeenSet = true;
}
-const char *cmProperty::GetValue() const
+const char* cmProperty::GetValue() const
{
- if (this->ValueHasBeenSet)
- {
+ if (this->ValueHasBeenSet) {
return this->Value.c_str();
- }
- return 0;
+ }
+ return CM_NULLPTR;
}
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index bb75bb0b9..d11c5efbb 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -1,39 +1,41 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmProperty_h
#define cmProperty_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
class cmProperty
{
public:
- enum ScopeType { TARGET, SOURCE_FILE, DIRECTORY, GLOBAL, CACHE,
- TEST, VARIABLE, CACHED_VARIABLE };
+ enum ScopeType
+ {
+ TARGET,
+ SOURCE_FILE,
+ DIRECTORY,
+ GLOBAL,
+ CACHE,
+ TEST,
+ VARIABLE,
+ CACHED_VARIABLE,
+ INSTALL
+ };
// set this property
- void Set(const char *name, const char *value);
+ void Set(const char* value);
// append to this property
- void Append(const char *name, const char *value, bool asString = false);
+ void Append(const char* value, bool asString = false);
// get the value
- const char *GetValue() const;
+ const char* GetValue() const;
// construct with the value not set
- cmProperty() { this->ValueHasBeenSet = false; };
+ cmProperty() { this->ValueHasBeenSet = false; }
protected:
- std::string Name;
std::string Value;
bool ValueHasBeenSet;
};
diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx
index b80c863f1..6a3174c7b 100644
--- a/Source/cmPropertyDefinition.cxx
+++ b/Source/cmPropertyDefinition.cxx
@@ -1,47 +1,20 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPropertyDefinition.h"
-#include "cmSystemTools.h"
-
-cmDocumentationEntry cmPropertyDefinition::GetDocumentation() const
-{
- cmDocumentationEntry e;
- e.Name = this->Name;
- e.Brief = this->ShortDescription;
- e.Full = this->FullDescription;
- return e;
-}
-void cmPropertyDefinition
-::DefineProperty(const char *name, cmProperty::ScopeType scope,
- const char *shortDescription,
- const char *fullDescription,
- const char *sec,
- bool chain)
+void cmPropertyDefinition::DefineProperty(const std::string& name,
+ cmProperty::ScopeType scope,
+ const char* shortDescription,
+ const char* fullDescription,
+ bool chain)
{
this->Name = name;
this->Scope = scope;
this->Chained = chain;
- if (shortDescription)
- {
+ if (shortDescription) {
this->ShortDescription = shortDescription;
- }
- if (fullDescription)
- {
+ }
+ if (fullDescription) {
this->FullDescription = fullDescription;
- }
- if (sec)
- {
- this->DocumentationSection = sec;
- }
+ }
}
-
diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h
index 296366dca..9adff4902 100644
--- a/Source/cmPropertyDefinition.h
+++ b/Source/cmPropertyDefinition.h
@@ -1,19 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmPropertyDefinition_h
#define cmPropertyDefinition_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include "cmProperty.h"
+#include <string>
+
/** \class cmPropertyDefinition
* \brief Property meta-information
*
@@ -27,42 +22,35 @@ class cmPropertyDefinition
{
public:
/// Define this property
- void DefineProperty(const char *name, cmProperty::ScopeType scope,
- const char *ShortDescription,
- const char *FullDescription,
- const char *DocumentationSection,
- bool chained);
-
- /// Get the documentation string
- cmDocumentationEntry GetDocumentation() const;
+ void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
+ const char* ShortDescription,
+ const char* FullDescription, bool chained);
/// Default constructor
- cmPropertyDefinition() { this->Chained = false; };
+ cmPropertyDefinition() { this->Chained = false; }
/// Is the property chained?
- bool IsChained() const { return this->Chained; };
-
- /// Get the section if any
- const std::string &GetDocumentationSection() const {
- return this->DocumentationSection; };
+ bool IsChained() const { return this->Chained; }
/// Get the scope
- cmProperty::ScopeType GetScope() const {
- return this->Scope; };
+ cmProperty::ScopeType GetScope() const { return this->Scope; }
/// Get the documentation (short version)
- const std::string &GetShortDescription() const {
- return this->ShortDescription; };
+ const std::string& GetShortDescription() const
+ {
+ return this->ShortDescription;
+ }
/// Get the documentation (full version)
- const std::string &GetFullDescription() const {
- return this->FullDescription; };
+ const std::string& GetFullDescription() const
+ {
+ return this->FullDescription;
+ }
protected:
std::string Name;
std::string ShortDescription;
std::string FullDescription;
- std::string DocumentationSection;
cmProperty::ScopeType Scope;
bool Chained;
};
diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx
index 20fa07c43..5daaf9ba3 100644
--- a/Source/cmPropertyDefinitionMap.cxx
+++ b/Source/cmPropertyDefinitionMap.cxx
@@ -1,125 +1,35 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPropertyDefinitionMap.h"
-#include "cmSystemTools.h"
-#include "cmDocumentationSection.h"
-void cmPropertyDefinitionMap
-::DefineProperty(const char *name, cmProperty::ScopeType scope,
- const char *ShortDescription,
- const char *FullDescription,
- const char *DocumentationSection,
- bool chain)
-{
- if (!name)
- {
- return;
- }
+#include <utility>
+void cmPropertyDefinitionMap::DefineProperty(const std::string& name,
+ cmProperty::ScopeType scope,
+ const char* ShortDescription,
+ const char* FullDescription,
+ bool chain)
+{
cmPropertyDefinitionMap::iterator it = this->find(name);
- cmPropertyDefinition *prop;
- if (it == this->end())
- {
+ cmPropertyDefinition* prop;
+ if (it == this->end()) {
prop = &(*this)[name];
- prop->DefineProperty(name,scope,ShortDescription, FullDescription,
- DocumentationSection, chain);
- }
+ prop->DefineProperty(name, scope, ShortDescription, FullDescription,
+ chain);
+ }
}
-void cmPropertyDefinitionMap
-::GetPropertiesDocumentation(std::map<std::string,
- cmDocumentationSection *>& v) const
+bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) const
{
- for(cmPropertyDefinitionMap::const_iterator j = this->begin();
- j != this->end(); ++j)
- {
- // add a section if needed
- std::string secName = j->second.GetDocumentationSection();
- // if a section was not specified then use the scope
- if (!secName.size())
- {
- switch (j->second.GetScope())
- {
- case cmProperty::GLOBAL:
- secName = "Properties of Global Scope";
- break;
- case cmProperty::TARGET:
- secName = "Properties on Targets";
- break;
- case cmProperty::SOURCE_FILE:
- secName = "Properties on Source Files";
- break;
- case cmProperty::DIRECTORY:
- secName = "Properties on Directories";
- break;
- case cmProperty::TEST:
- secName = "Properties on Tests";
- break;
- case cmProperty::CACHE:
- secName = "Properties on Cache Entries";
- break;
- case cmProperty::VARIABLE:
- secName = "Variables";
- break;
- case cmProperty::CACHED_VARIABLE:
- secName = "Cached Variables";
- break;
- default:
- secName = "Properties of Unknown Scope";
- break;
- }
- }
- if (!v[secName])
- {
- v[secName] = new
- cmDocumentationSection(secName.c_str(),
- cmSystemTools::UpperCase(secName).c_str());
- }
- cmDocumentationEntry e = j->second.GetDocumentation();
- if (e.Brief.size() || e.Full.size())
- {
- v[secName]->Append(e);
- }
- }
+ return this->find(name) != this->end();
}
-bool cmPropertyDefinitionMap::IsPropertyDefined(const char *name)
+bool cmPropertyDefinitionMap::IsPropertyChained(const std::string& name) const
{
- if (!name)
- {
- return false;
- }
-
- cmPropertyDefinitionMap::iterator it = this->find(name);
- if (it == this->end())
- {
- return false;
- }
-
- return true;
-}
-
-bool cmPropertyDefinitionMap::IsPropertyChained(const char *name)
-{
- if (!name)
- {
- return false;
- }
-
- cmPropertyDefinitionMap::iterator it = this->find(name);
- if (it == this->end())
- {
+ cmPropertyDefinitionMap::const_iterator it = this->find(name);
+ if (it == this->end()) {
return false;
- }
+ }
return it->second.IsChained();
}
diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h
index 007e26515..97ba55391 100644
--- a/Source/cmPropertyDefinitionMap.h
+++ b/Source/cmPropertyDefinitionMap.h
@@ -1,41 +1,30 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmPropertyDefinitionMap_h
#define cmPropertyDefinitionMap_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmProperty.h"
#include "cmPropertyDefinition.h"
-class cmDocumentationSection;
+#include <map>
+#include <string>
-class cmPropertyDefinitionMap :
-public std::map<cmStdString,cmPropertyDefinition>
+class cmPropertyDefinitionMap
+ : public std::map<std::string, cmPropertyDefinition>
{
public:
// define the property
- void DefineProperty(const char *name, cmProperty::ScopeType scope,
- const char *ShortDescription,
- const char *FullDescription,
- const char *DocumentaitonSection,
- bool chain);
+ void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
+ const char* ShortDescription,
+ const char* FullDescription, bool chain);
// has a named property been defined
- bool IsPropertyDefined(const char *name);
+ bool IsPropertyDefined(const std::string& name) const;
// is a named property set to chain
- bool IsPropertyChained(const char *name);
-
- void GetPropertiesDocumentation(std::map<std::string,
- cmDocumentationSection *>&) const;
+ bool IsPropertyChained(const std::string& name) const;
};
#endif
-
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index 78f378ab7..1e089d1c8 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -1,123 +1,65 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPropertyMap.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
-cmProperty *cmPropertyMap::GetOrCreateProperty(const char *name)
+#include "cmConfigure.h"
+#include <algorithm>
+#include <assert.h>
+#include <utility>
+
+cmProperty* cmPropertyMap::GetOrCreateProperty(const std::string& name)
{
cmPropertyMap::iterator it = this->find(name);
- cmProperty *prop;
- if (it == this->end())
- {
+ cmProperty* prop;
+ if (it == this->end()) {
prop = &(*this)[name];
- }
- else
- {
+ } else {
prop = &(it->second);
- }
+ }
return prop;
}
-void cmPropertyMap::SetProperty(const char *name, const char *value,
- cmProperty::ScopeType scope)
+std::vector<std::string> cmPropertyMap::GetPropertyList() const
{
- if (!name)
- {
- return;
- }
- if(!value)
- {
+ 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;
+}
+
+void cmPropertyMap::SetProperty(const std::string& name, const char* value)
+{
+ if (!value) {
this->erase(name);
return;
- }
-#ifdef CMAKE_STRICT
- if (!this->CMakeInstance)
- {
- cmSystemTools::Error("CMakeInstance not set on a property map!");
- abort();
- }
- else
- {
- this->CMakeInstance->RecordPropertyAccess(name,scope);
- }
-#else
- (void)scope;
-#endif
+ }
- cmProperty *prop = this->GetOrCreateProperty(name);
- prop->Set(name,value);
+ cmProperty* prop = this->GetOrCreateProperty(name);
+ prop->Set(value);
}
-void cmPropertyMap::AppendProperty(const char* name, const char* value,
- cmProperty::ScopeType scope, bool asString)
+void cmPropertyMap::AppendProperty(const std::string& name, const char* value,
+ bool asString)
{
// Skip if nothing to append.
- if(!name || !value || !*value)
- {
+ if (!value || !*value) {
return;
- }
-#ifdef CMAKE_STRICT
- if (!this->CMakeInstance)
- {
- cmSystemTools::Error("CMakeInstance not set on a property map!");
- abort();
- }
- else
- {
- this->CMakeInstance->RecordPropertyAccess(name,scope);
- }
-#else
- (void)scope;
-#endif
+ }
- cmProperty *prop = this->GetOrCreateProperty(name);
- prop->Append(name,value,asString);
+ cmProperty* prop = this->GetOrCreateProperty(name);
+ prop->Append(value, asString);
}
-const char *cmPropertyMap
-::GetPropertyValue(const char *name,
- cmProperty::ScopeType scope,
- bool &chain) const
+const char* cmPropertyMap::GetPropertyValue(const std::string& name) const
{
- chain = false;
- if (!name)
- {
- return 0;
- }
-
- // has the property been defined?
-#ifdef CMAKE_STRICT
- if (!this->CMakeInstance)
- {
- cmSystemTools::Error("CMakeInstance not set on a property map!");
- abort();
- }
- else
- {
- this->CMakeInstance->RecordPropertyAccess(name,scope);
- }
-#endif
+ assert(!name.empty());
cmPropertyMap::const_iterator it = this->find(name);
- if (it == this->end())
- {
- // should we chain up?
- if (this->CMakeInstance)
- {
- chain = this->CMakeInstance->IsPropertyChained(name,scope);
- }
- return 0;
- }
+ if (it == this->end()) {
+ return CM_NULLPTR;
+ }
return it->second.GetValue();
}
-
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index 0c3aad461..5a0515076 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -1,43 +1,29 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmPropertyMap_h
#define cmPropertyMap_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include "cmProperty.h"
-class cmake;
+#include <map>
+#include <string>
+#include <vector>
-class cmPropertyMap : public std::map<cmStdString,cmProperty>
+class cmPropertyMap : public std::map<std::string, cmProperty>
{
public:
- cmProperty *GetOrCreateProperty(const char *name);
+ cmProperty* GetOrCreateProperty(const std::string& name);
- void SetProperty(const char *name, const char *value,
- cmProperty::ScopeType scope);
+ std::vector<std::string> GetPropertyList() const;
- void AppendProperty(const char* name, const char* value,
- cmProperty::ScopeType scope, bool asString=false);
+ void SetProperty(const std::string& name, const char* value);
- const char *GetPropertyValue(const char *name,
- cmProperty::ScopeType scope,
- bool &chain) const;
+ void AppendProperty(const std::string& name, const char* value,
+ bool asString = false);
- void SetCMakeInstance(cmake *cm) { this->CMakeInstance = cm; };
-
- cmPropertyMap() { this->CMakeInstance = 0;};
-
-private:
- cmake *CMakeInstance;
+ const char* GetPropertyValue(const std::string& name) const;
};
#endif
-
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index 0d3c9941c..de9e54505 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -1,29 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQTWrapCPPCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmCustomCommandLines.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmQTWrapCPPCommand.h"
+class cmExecutionStatus;
// cmQTWrapCPPCommand
-bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& argsIn,
- cmExecutionStatus &)
+bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(argsIn.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
-
- // This command supports source list inputs for compatibility.
- std::vector<std::string> args;
- this->Makefile->ExpandSourceListArguments(argsIn, args, 2);
+ }
// Get the moc executable to run in the custom command.
const char* moc_exe =
@@ -31,56 +24,43 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& argsIn,
// Get the variable holding the list of sources.
std::string const& sourceList = args[1];
- std::string sourceListValue =
- this->Makefile->GetSafeDefinition(sourceList.c_str());
+ std::string sourceListValue = this->Makefile->GetSafeDefinition(sourceList);
// Create a rule for all sources listed.
- for(std::vector<std::string>::iterator j = (args.begin() + 2);
- j != args.end(); ++j)
- {
- cmSourceFile *curr = this->Makefile->GetSource(j->c_str());
+ for (std::vector<std::string>::const_iterator j = (args.begin() + 2);
+ j != args.end(); ++j) {
+ cmSourceFile* curr = this->Makefile->GetSource(*j);
// if we should wrap the class
- if(!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE")))
- {
+ 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->GetCurrentOutputDirectory();
+ std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(*j);
+ std::string newName = this->Makefile->GetCurrentBinaryDirectory();
newName += "/moc_";
newName += srcName;
newName += ".cxx";
- cmSourceFile* sf =
- this->Makefile->GetOrCreateSource(newName.c_str(), true);
- if (curr)
- {
+ cmSourceFile* sf = this->Makefile->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()))
- {
+ if (cmSystemTools::FileIsFullPath(j->c_str())) {
hname = *j;
+ } else {
+ if (curr && curr->GetPropertyAsBool("GENERATED")) {
+ hname = this->Makefile->GetCurrentBinaryDirectory();
+ } else {
+ hname = this->Makefile->GetCurrentSourceDirectory();
}
- else
- {
- if(curr && curr->GetPropertyAsBool("GENERATED"))
- {
- hname = this->Makefile->GetCurrentOutputDirectory();
- }
- else
- {
- hname = this->Makefile->GetCurrentDirectory();
- }
hname += "/";
hname += *j;
- }
+ }
// Append the generated source file to the list.
- if(!sourceListValue.empty())
- {
+ if (!sourceListValue.empty()) {
sourceListValue += ";";
- }
+ }
sourceListValue += newName;
// Create the custom command to generate the file.
@@ -97,19 +77,15 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& argsIn,
depends.push_back(moc_exe);
depends.push_back(hname);
- const char* no_main_dependency = 0;
- const char* no_working_dir = 0;
- this->Makefile->AddCustomCommandToOutput(newName.c_str(),
- depends,
- no_main_dependency,
- commandLines,
- "Qt Wrapped File",
- no_working_dir);
- }
+ 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);
}
+ }
// Store the final list of source files.
- this->Makefile->AddDefinition(sourceList.c_str(),
- sourceListValue.c_str());
+ this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
return true;
}
diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h
index 4863402e4..ad1ccf38d 100644
--- a/Source/cmQTWrapCPPCommand.h
+++ b/Source/cmQTWrapCPPCommand.h
@@ -1,20 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmQTWrapCPPCommand_h
#define cmQTWrapCPPCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmSourceFile.h"
+class cmExecutionStatus;
/** \class cmQTWrapCPPCommand
* \brief Create moc file rules for Qt classes
@@ -25,50 +21,17 @@
class cmQTWrapCPPCommand : public cmCommand
{
public:
- cmTypeMacro(cmQTWrapCPPCommand, cmCommand);
-
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmQTWrapCPPCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmQTWrapCPPCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "qt_wrap_cpp";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Create Qt Wrappers.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " qt_wrap_cpp(resultingLibraryName DestName\n"
- " SourceLists ...)\n"
- "Produce moc files for all the .h files listed in the SourceLists. "
- "The moc files will be added to the library using the DestName "
- "source list.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index a6a4b5158..d3c663176 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -1,29 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQTWrapUICommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmCustomCommandLines.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmQTWrapUICommand.h"
+class cmExecutionStatus;
// cmQTWrapUICommand
-bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& argsIn,
- cmExecutionStatus &)
+bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(argsIn.size() < 4 )
- {
+ if (args.size() < 4) {
this->SetError("called with incorrect number of arguments");
return false;
- }
-
- // This command supports source list inputs for compatibility.
- std::vector<std::string> args;
- this->Makefile->ExpandSourceListArguments(argsIn, args, 3);
+ }
// Get the uic and moc executables to run in the custom commands.
const char* uic_exe =
@@ -34,67 +27,54 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& argsIn,
// 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.c_str());
- std::string sourceListValue =
- this->Makefile->GetSafeDefinition(sourceList.c_str());
+ std::string headerListValue = this->Makefile->GetSafeDefinition(headerList);
+ std::string sourceListValue = this->Makefile->GetSafeDefinition(sourceList);
// Create rules for all sources listed.
- for(std::vector<std::string>::iterator j = (args.begin() + 3);
- j != args.end(); ++j)
- {
- cmSourceFile *curr = this->Makefile->GetSource(j->c_str());
+ for (std::vector<std::string>::const_iterator j = (args.begin() + 3);
+ j != args.end(); ++j) {
+ cmSourceFile* curr = this->Makefile->GetSource(*j);
// if we should wrap the class
- if(!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE")))
- {
+ 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->GetCurrentOutputDirectory();
+ std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(*j);
+ std::string hName = this->Makefile->GetCurrentBinaryDirectory();
hName += "/";
hName += srcName;
hName += ".h";
- std::string cxxName = this->Makefile->GetCurrentOutputDirectory();
+ std::string cxxName = this->Makefile->GetCurrentBinaryDirectory();
cxxName += "/";
cxxName += srcName;
cxxName += ".cxx";
- std::string mocName = this->Makefile->GetCurrentOutputDirectory();
+ std::string mocName = this->Makefile->GetCurrentBinaryDirectory();
mocName += "/moc_";
mocName += srcName;
mocName += ".cxx";
// Compute the name of the ui file from which to generate others.
std::string uiName;
- if(cmSystemTools::FileIsFullPath(j->c_str()))
- {
+ if (cmSystemTools::FileIsFullPath(j->c_str())) {
uiName = *j;
+ } else {
+ if (curr && curr->GetPropertyAsBool("GENERATED")) {
+ uiName = this->Makefile->GetCurrentBinaryDirectory();
+ } else {
+ uiName = this->Makefile->GetCurrentSourceDirectory();
}
- else
- {
- if(curr && curr->GetPropertyAsBool("GENERATED"))
- {
- uiName = this->Makefile->GetCurrentOutputDirectory();
- }
- else
- {
- uiName = this->Makefile->GetCurrentDirectory();
- }
uiName += "/";
uiName += *j;
- }
+ }
// create the list of headers
- if(!headerListValue.empty())
- {
+ if (!headerListValue.empty()) {
headerListValue += ";";
- }
+ }
headerListValue += hName;
// create the list of sources
- if(!sourceListValue.empty())
- {
+ if (!sourceListValue.empty()) {
sourceListValue += ";";
- }
+ }
sourceListValue += cxxName;
sourceListValue += ";";
sourceListValue += mocName;
@@ -128,39 +108,28 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& argsIn,
std::vector<std::string> depends;
depends.push_back(uiName);
- const char* no_main_dependency = 0;
- const char* no_comment = 0;
- const char* no_working_dir = 0;
- this->Makefile->AddCustomCommandToOutput(hName.c_str(),
- depends,
- no_main_dependency,
- hCommandLines,
- no_comment,
- no_working_dir);
+ 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);
depends.push_back(hName);
- this->Makefile->AddCustomCommandToOutput(cxxName.c_str(),
- depends,
- no_main_dependency,
- cxxCommandLines,
- no_comment,
- no_working_dir);
+ this->Makefile->AddCustomCommandToOutput(
+ cxxName, depends, no_main_dependency, cxxCommandLines, no_comment,
+ no_working_dir);
depends.clear();
depends.push_back(hName);
- this->Makefile->AddCustomCommandToOutput(mocName.c_str(),
- depends,
- no_main_dependency,
- mocCommandLines,
- no_comment,
- no_working_dir);
- }
+ this->Makefile->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.c_str(),
- sourceListValue.c_str());
- this->Makefile->AddDefinition(headerList.c_str(),
- headerListValue.c_str());
+ this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
+ this->Makefile->AddDefinition(headerList, headerListValue.c_str());
return true;
}
diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h
index b15c5cde0..ac7ab01c7 100644
--- a/Source/cmQTWrapUICommand.h
+++ b/Source/cmQTWrapUICommand.h
@@ -1,20 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmQTWrapUICommand_h
#define cmQTWrapUICommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmSourceFile.h"
+class cmExecutionStatus;
/** \class cmQTWrapUICommand
* \brief Create .h and .cxx files rules for Qt user interfaces files
@@ -24,52 +20,17 @@
class cmQTWrapUICommand : public cmCommand
{
public:
- cmTypeMacro(cmQTWrapUICommand, cmCommand);
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmQTWrapUICommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmQTWrapUICommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "qt_wrap_ui";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Create Qt user interfaces Wrappers.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " qt_wrap_ui(resultingLibraryName HeadersDestName\n"
- " SourcesDestName SourceLists ...)\n"
- "Produce .h and .cxx files for all the .ui files listed "
- "in the SourceLists. "
- "The .h files will be added to the library using the HeadersDestName"
- "source list. "
- "The .cxx files will be added to the library using the SourcesDestName"
- "source list.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx
new file mode 100644
index 000000000..3e1b58caa
--- /dev/null
+++ b/Source/cmQtAutoGeneratorCommon.cxx
@@ -0,0 +1,216 @@
+/* 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
new file mode 100644
index 000000000..a131baf20
--- /dev/null
+++ b/Source/cmQtAutoGeneratorCommon.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 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
new file mode 100644
index 000000000..3e3be54d1
--- /dev/null
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -0,0 +1,1131 @@
+/* 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
new file mode 100644
index 000000000..ca806f5a9
--- /dev/null
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -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. */
+#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
new file mode 100644
index 000000000..d12d96dcb
--- /dev/null
+++ b/Source/cmQtAutoGenerators.cxx
@@ -0,0 +1,2066 @@
+/* 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
new file mode 100644
index 000000000..337aa17fd
--- /dev/null
+++ b/Source/cmQtAutoGenerators.h
@@ -0,0 +1,222 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#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/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx
deleted file mode 100644
index 93e39abeb..000000000
--- a/Source/cmQtAutomoc.cxx
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2011 Kitware, Inc.
- Copyright 2011 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmSystemTools.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# include "cmLocalVisualStudioGenerator.h"
-#endif
-
-#include <cmsys/Terminal.h>
-#include <cmsys/ios/sstream>
-
-#include <string.h>
-#if defined(__APPLE__)
-#include <unistd.h>
-#endif
-
-#include "cmQtAutomoc.h"
-
-
-static bool containsQ_OBJECT(const std::string& text)
-{
- // this simple check is much much faster than the regexp
- if (strstr(text.c_str(), "Q_OBJECT") == NULL)
- {
- return false;
- }
-
- cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
- return qObjectRegExp.find(text);
-}
-
-
-static std::string findMatchingHeader(const std::string& absPath,
- const std::string& mocSubDir,
- const std::string& basename,
- const std::vector<std::string>& headerExtensions)
-{
- std::string header;
- for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
- ext != headerExtensions.end();
- ++ext)
- {
- std::string sourceFilePath = absPath + basename + "." + (*ext);
- if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
- {
- header = sourceFilePath;
- break;
- }
- if (!mocSubDir.empty())
- {
- sourceFilePath = mocSubDir + basename + "." + (*ext);
- if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
- {
- header = sourceFilePath;
- break;
- }
- }
- }
-
- return header;
-}
-
-
-static std::string extractSubDir(const std::string& absPath,
- const std::string& currentMoc)
-{
- std::string subDir;
- if (currentMoc.find_first_of('/') != std::string::npos)
- {
- subDir = absPath
- + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/';
- }
- return subDir;
-}
-
-
-static void copyTargetProperty(cmTarget* destinationTarget,
- cmTarget* sourceTarget,
- const char* propertyName)
-{
- const char* propertyValue = sourceTarget->GetProperty(propertyName);
- if (propertyValue)
- {
- destinationTarget->SetProperty(propertyName, propertyValue);
- }
-}
-
-
-cmQtAutomoc::cmQtAutomoc()
-:Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != 0)
-,ColorOutput(true)
-,RunMocFailed(false)
-,GenerateAll(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;
- }
- }
-}
-
-bool cmQtAutomoc::InitializeMocSourceFile(cmTarget* target)
-{
- cmMakefile* makefile = target->GetMakefile();
- // don't do anything if there is no Qt4 or Qt5Core (which contains moc):
- std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion == "")
- {
- qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
- if (qtMajorVersion != "4" && qtMajorVersion != "5")
- {
- return false;
- }
-
- std::string automocTargetName = target->GetName();
- automocTargetName += "_automoc";
- std::string mocCppFile = makefile->GetCurrentOutputDirectory();
- mocCppFile += "/";
- mocCppFile += automocTargetName;
- mocCppFile += ".cpp";
- cmSourceFile* mocCppSource = makefile->GetOrCreateSource(mocCppFile.c_str(),
- true);
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
- mocCppFile.c_str(), false);
-
- target->AddSourceFile(mocCppSource);
- return true;
-}
-
-static void GetCompileDefinitionsAndDirectories(cmTarget *target,
- const char * config,
- std::string &incs,
- std::string &defs)
-{
- cmMakefile* makefile = target->GetMakefile();
- cmLocalGenerator* localGen = makefile->GetLocalGenerator();
- std::vector<std::string> includeDirs;
- cmGeneratorTarget gtgt(target);
- // Get the include dirs for this target, without stripping the implicit
- // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667
- localGen->GetIncludeDirectories(includeDirs, &gtgt, "CXX", config, false);
- const char* sep = "";
- incs = "";
- for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin();
- incDirIt != includeDirs.end();
- ++incDirIt)
- {
- incs += sep;
- sep = ";";
- incs += *incDirIt;
- }
-
- std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, target, config);
-
- sep = "";
- for(std::set<std::string>::const_iterator defIt = defines.begin();
- defIt != defines.end();
- ++defIt)
- {
- defs += sep;
- sep = ";";
- defs += *defIt;
- }
-}
-
-void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
-{
- cmMakefile* makefile = target->GetMakefile();
- const char* targetName = target->GetName();
-
- bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
-
- // create a custom target for running automoc at buildtime:
- std::string automocTargetName = targetName;
- automocTargetName += "_automoc";
-
- std::string targetDir = makefile->GetCurrentOutputDirectory();
- targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
- targetDir += "/";
- targetDir += automocTargetName;
- targetDir += ".dir/";
-
- cmCustomCommandLine currentLine;
- currentLine.push_back(makefile->GetSafeDefinition("CMAKE_COMMAND"));
- currentLine.push_back("-E");
- currentLine.push_back("cmake_automoc");
- currentLine.push_back(targetDir);
- currentLine.push_back("$<CONFIGURATION>");
-
- cmCustomCommandLines commandLines;
- commandLines.push_back(currentLine);
-
- std::string workingDirectory = cmSystemTools::CollapseFullPath(
- "", makefile->GetCurrentOutputDirectory());
-
- std::vector<std::string> depends;
- std::string automocComment = "Automoc for target ";
- automocComment += targetName;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- bool usePRE_BUILD = false;
- cmLocalGenerator* localGen = makefile->GetLocalGenerator();
- cmGlobalGenerator* gg = localGen->GetGlobalGenerator();
- if(strstr(gg->GetName(), "Visual Studio"))
- {
- cmLocalVisualStudioGenerator* vslg =
- static_cast<cmLocalVisualStudioGenerator*>(localGen);
- // Under VS >= 7 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 = vslg->GetVersion() >= cmLocalVisualStudioGenerator::VS7;
- }
- 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;
- cmCustomCommand cc(makefile, no_output, depends,
- commandLines, automocComment.c_str(),
- workingDirectory.c_str());
- cc.SetEscapeOldStyle(false);
- cc.SetEscapeAllowMakeVars(true);
- target->GetPreBuildCommands().push_back(cc);
- }
- else
-#endif
- {
- cmTarget* automocTarget = makefile->AddUtilityCommand(
- automocTargetName.c_str(), true,
- workingDirectory.c_str(), depends,
- commandLines, false, automocComment.c_str());
- // Set target folder
- const char* automocFolder = makefile->GetCMakeInstance()->GetProperty(
- "AUTOMOC_TARGETS_FOLDER");
- if (automocFolder && *automocFolder)
- {
- automocTarget->SetProperty("FOLDER", automocFolder);
- }
- else
- {
- // inherit FOLDER property from target (#13688)
- copyTargetProperty(automocTarget, target, "FOLDER");
- }
-
- target->AddUtility(automocTargetName.c_str());
- }
-
- // configure a file to get all information to automoc at buildtime:
- std::string _moc_files;
- std::string _moc_headers;
- const char* sepFiles = "";
- const char* sepHeaders = "";
-
- const std::vector<cmSourceFile*>& srcFiles = target->GetSourceFiles();
-
- for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end();
- ++fileIt)
- {
- cmSourceFile* sf = *fileIt;
- std::string absFile = cmsys::SystemTools::GetRealPath(
- sf->GetFullPath().c_str());
- bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
- bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"));
-
- if ((skip==false) && (generated == false))
- {
- std::string ext = sf->GetExtension();
- cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat(
- ext.c_str());
- if (fileType == cmSystemTools::CXX_FILE_FORMAT)
- {
- _moc_files += sepFiles;
- _moc_files += absFile;
- sepFiles = ";";
- }
- else if (fileType == cmSystemTools::HEADER_FILE_FORMAT)
- {
- _moc_headers += sepHeaders;
- _moc_headers += absFile;
- sepHeaders = ";";
- }
- }
- }
-
- const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
- std::string _moc_options = (tmp!=0 ? tmp : "");
-
- // forget the variables added here afterwards again:
- cmMakefile::ScopePushPop varScope(makefile);
- static_cast<void>(varScope);
-
- makefile->AddDefinition("_moc_target_name",
- cmLocalGenerator::EscapeForCMake(automocTargetName.c_str()).c_str());
- makefile->AddDefinition("_moc_options",
- cmLocalGenerator::EscapeForCMake(_moc_options.c_str()).c_str());
- makefile->AddDefinition("_moc_files",
- cmLocalGenerator::EscapeForCMake(_moc_files.c_str()).c_str());
- makefile->AddDefinition("_moc_headers",
- cmLocalGenerator::EscapeForCMake(_moc_headers.c_str()).c_str());
- makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
-
- std::string _moc_incs;
- std::string _moc_compile_defs;
- std::vector<std::string> configs;
- const char *config = makefile->GetConfigurations(configs);
- GetCompileDefinitionsAndDirectories(target, config,
- _moc_incs, _moc_compile_defs);
-
- makefile->AddDefinition("_moc_incs",
- cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str());
- makefile->AddDefinition("_moc_compile_defs",
- cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str());
-
- std::map<std::string, std::string> configIncludes;
- std::map<std::string, std::string> configDefines;
-
- for (std::vector<std::string>::const_iterator li = configs.begin();
- li != configs.end(); ++li)
- {
- std::string config_moc_incs;
- std::string config_moc_compile_defs;
- GetCompileDefinitionsAndDirectories(target, li->c_str(),
- config_moc_incs,
- config_moc_compile_defs);
- if (config_moc_incs != _moc_incs)
- {
- configIncludes["_moc_incs_" + *li] =
- cmLocalGenerator::EscapeForCMake(config_moc_incs.c_str());
- if(_moc_incs.empty())
- {
- _moc_incs = config_moc_incs;
- }
- }
- if (config_moc_compile_defs != _moc_compile_defs)
- {
- configDefines["_moc_compile_defs_" + *li] =
- cmLocalGenerator::EscapeForCMake(config_moc_compile_defs.c_str());
- if(_moc_compile_defs.empty())
- {
- _moc_compile_defs = config_moc_compile_defs;
- }
- }
- }
-
- const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR");
- if (!qtVersion)
- {
- qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
- }
- if (const char *targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", 0))
- {
- qtVersion = targetQtVersion;
- }
- if (qtVersion)
- {
- makefile->AddDefinition("_target_qt_version", qtVersion);
- }
-
- {
- const char *qtMoc = makefile->GetSafeDefinition("QT_MOC_EXECUTABLE");
- makefile->AddDefinition("_qt_moc_executable", qtMoc);
- }
-
- if (strcmp(qtVersion, "5") == 0)
- {
- cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc");
- if (!qt5Moc)
- {
- cmSystemTools::Error("Qt5::moc target not found ",
- automocTargetName.c_str());
- return;
- }
- makefile->AddDefinition("_qt_moc_executable", qt5Moc->GetLocation(0));
- }
- else
- {
- if (strcmp(qtVersion, "4") != 0)
- {
- cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and "
- "Qt 5 ", automocTargetName.c_str());
- }
- }
-
- const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT");
- std::string inputFile = cmakeRoot;
- inputFile += "/Modules/AutomocInfo.cmake.in";
- std::string outputFile = targetDir;
- outputFile += "/AutomocInfo.cmake";
- makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
- false, true, false);
-
- if (!configDefines.empty() || !configIncludes.empty())
- {
- std::ofstream infoFile(outputFile.c_str(), std::ios::app);
- if ( !infoFile )
- {
- std::string error = "Internal CMake error when trying to open file: ";
- error += outputFile.c_str();
- error += " for writing.";
- cmSystemTools::Error(error.c_str());
- return;
- }
- if (!configDefines.empty())
- {
- for (std::map<std::string, std::string>::iterator
- it = configDefines.begin(), end = configDefines.end();
- it != end; ++it)
- {
- infoFile << "SET(AM_MOC_COMPILE_DEFINITIONS_" << it->first <<
- " " << it->second << ")\n";
- }
- }
- if (!configIncludes.empty())
- {
- for (std::map<std::string, std::string>::iterator
- it = configIncludes.begin(), end = configIncludes.end();
- it != end; ++it)
- {
- infoFile << "SET(AM_MOC_INCLUDES_" << it->first <<
- " " << it->second << ")\n";
- }
- }
- }
-}
-
-
-bool cmQtAutomoc::Run(const char* targetDirectory, const char *config)
-{
- bool success = true;
- cmake cm;
- cmGlobalGenerator* gg = this->CreateGlobalGenerator(&cm, targetDirectory);
- cmMakefile* makefile = gg->GetCurrentLocalGenerator()->GetMakefile();
-
- this->ReadAutomocInfoFile(makefile, targetDirectory, config);
- this->ReadOldMocDefinitionsFile(makefile, targetDirectory);
-
- this->Init();
-
- if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5")
- {
- success = this->RunAutomoc(makefile);
- }
-
- this->WriteOldMocDefinitionsFile(targetDirectory);
-
- delete gg;
- gg = NULL;
- makefile = NULL;
- return success;
-}
-
-
-cmGlobalGenerator* cmQtAutomoc::CreateGlobalGenerator(cmake* cm,
- const char* targetDirectory)
-{
- cmGlobalGenerator* gg = new cmGlobalGenerator();
- gg->SetCMakeInstance(cm);
-
- cmLocalGenerator* lg = gg->CreateLocalGenerator();
- lg->GetMakefile()->SetHomeOutputDirectory(targetDirectory);
- lg->GetMakefile()->SetStartOutputDirectory(targetDirectory);
- lg->GetMakefile()->SetHomeDirectory(targetDirectory);
- lg->GetMakefile()->SetStartDirectory(targetDirectory);
- gg->SetCurrentLocalGenerator(lg);
-
- return gg;
-}
-
-
-bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
- const char* targetDirectory,
- const char *config)
-{
- std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
- cmSystemTools::ConvertToUnixSlashes(filename);
- filename += "/AutomocInfo.cmake";
-
- if (!makefile->ReadListFile(0, filename.c_str()))
- {
- cmSystemTools::Error("Error processing file: ", filename.c_str());
- return false;
- }
-
- this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR");
- if (this->QtMajorVersion == "")
- {
- this->QtMajorVersion = makefile->GetSafeDefinition(
- "AM_Qt5Core_VERSION_MAJOR");
- }
- this->Sources = makefile->GetSafeDefinition("AM_SOURCES");
- this->Headers = makefile->GetSafeDefinition("AM_HEADERS");
- this->IncludeProjectDirsBefore = makefile->IsOn(
- "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
- this->Srcdir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
- this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR");
- this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
- std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS";
- std::string compileDefsProp = compileDefsPropOrig;
- if(config)
- {
- compileDefsProp += "_";
- compileDefsProp += config;
- }
- const char *compileDefs = makefile->GetDefinition(compileDefsProp.c_str());
- this->MocCompileDefinitionsStr = compileDefs ? compileDefs
- : makefile->GetSafeDefinition(compileDefsPropOrig.c_str());
- std::string includesPropOrig = "AM_MOC_INCLUDES";
- std::string includesProp = includesPropOrig;
- if(config)
- {
- includesProp += "_";
- includesProp += config;
- }
- const char *includes = makefile->GetDefinition(includesProp.c_str());
- this->MocIncludesStr = includes ? includes
- : makefile->GetSafeDefinition(includesPropOrig.c_str());
- this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS");
- this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
- this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
- this->TargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
-
- this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile);
-
- this->RelaxedMode = makefile->IsOn("AM_RELAXED_MODE");
-
- return true;
-}
-
-
-std::string cmQtAutomoc::MakeCompileSettingsString(cmMakefile* makefile)
-{
- std::string s;
- s += makefile->GetSafeDefinition("AM_MOC_COMPILE_DEFINITIONS");
- s += " ~~~ ";
- s += makefile->GetSafeDefinition("AM_MOC_INCLUDES");
- s += " ~~~ ";
- s += makefile->GetSafeDefinition("AM_MOC_OPTIONS");
- s += " ~~~ ";
- s += makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE") ? "TRUE"
- : "FALSE";
- s += " ~~~ ";
-
- return s;
-}
-
-
-bool cmQtAutomoc::ReadOldMocDefinitionsFile(cmMakefile* makefile,
- const char* targetDirectory)
-{
- std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
- cmSystemTools::ConvertToUnixSlashes(filename);
- filename += "/AutomocOldMocDefinitions.cmake";
-
- if (makefile->ReadListFile(0, filename.c_str()))
- {
- this->OldCompileSettingsStr =
- makefile->GetSafeDefinition("AM_OLD_COMPILE_SETTINGS");
- }
- return true;
-}
-
-
-void cmQtAutomoc::WriteOldMocDefinitionsFile(const char* targetDirectory)
-{
- std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
- cmSystemTools::ConvertToUnixSlashes(filename);
- filename += "/AutomocOldMocDefinitions.cmake";
-
- std::fstream outfile;
- outfile.open(filename.c_str(),
- std::ios::out | std::ios::trunc);
- outfile << "set(AM_OLD_COMPILE_SETTINGS "
- << cmLocalGenerator::EscapeForCMake(
- this->CurrentCompileSettingsStr.c_str()) << ")\n";
-
- outfile.close();
-}
-
-
-void cmQtAutomoc::Init()
-{
- this->OutMocCppFilename = this->Builddir;
- this->OutMocCppFilename += this->TargetName;
- this->OutMocCppFilename += ".cpp";
-
- std::vector<std::string> cdefList;
- cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
- for(std::vector<std::string>::const_iterator it = cdefList.begin();
- it != cdefList.end();
- ++it)
- {
- this->MocDefinitions.push_back("-D" + (*it));
- }
-
- cmSystemTools::ExpandListArgument(this->MocOptionsStr, this->MocOptions);
-
- std::vector<std::string> incPaths;
- cmSystemTools::ExpandListArgument(this->MocIncludesStr, incPaths);
-
- std::set<std::string> frameworkPaths;
- for(std::vector<std::string>::const_iterator it = incPaths.begin();
- it != incPaths.end();
- ++it)
- {
- const std::string &path = *it;
- this->MocIncludes.push_back("-I" + path);
- if (this->EndsWith(path, ".framework/Headers"))
- {
- // Go up twice to get to the framework root
- std::vector<std::string> pathComponents;
- cmsys::SystemTools::SplitPath(path.c_str(), pathComponents);
- std::string frameworkPath =cmsys::SystemTools::JoinPath(
- pathComponents.begin(), pathComponents.end() - 2);
- frameworkPaths.insert(frameworkPath);
- }
- }
-
- for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
- it != frameworkPaths.end(); ++it)
- {
- this->MocIncludes.push_back("-F");
- this->MocIncludes.push_back(*it);
- }
-
-
- if (this->IncludeProjectDirsBefore)
- {
- const std::string &binDir = "-I" + this->ProjectBinaryDir;
-
- const std::string srcDir = "-I" + this->ProjectSourceDir;
-
- std::list<std::string> sortedMocIncludes;
- std::list<std::string>::iterator it = this->MocIncludes.begin();
- while (it != this->MocIncludes.end())
- {
- if (this->StartsWith(*it, binDir))
- {
- sortedMocIncludes.push_back(*it);
- it = this->MocIncludes.erase(it);
- }
- else
- {
- ++it;
- }
- }
- it = this->MocIncludes.begin();
- while (it != this->MocIncludes.end())
- {
- if (this->StartsWith(*it, srcDir))
- {
- sortedMocIncludes.push_back(*it);
- it = this->MocIncludes.erase(it);
- }
- else
- {
- ++it;
- }
- }
- sortedMocIncludes.insert(sortedMocIncludes.end(),
- this->MocIncludes.begin(), this->MocIncludes.end());
- this->MocIncludes = sortedMocIncludes;
- }
-
-}
-
-
-bool cmQtAutomoc::RunAutomoc(cmMakefile* makefile)
-{
- if (!cmsys::SystemTools::FileExists(this->OutMocCppFilename.c_str())
- || (this->OldCompileSettingsStr != this->CurrentCompileSettingsStr))
- {
- this->GenerateAll = true;
- }
-
- // 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 _automoc.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 _automoc.cpp file.
-
- // key = moc source filepath, value = moc output filepath
- std::map<std::string, std::string> includedMocs;
- // collect all headers which may need to be mocced
- std::set<std::string> headerFiles;
-
- std::vector<std::string> sourceFiles;
- cmSystemTools::ExpandListArgument(this->Sources, sourceFiles);
-
- const std::vector<std::string>& headerExtensions =
- makefile->GetHeaderExtensions();
-
- for (std::vector<std::string>::const_iterator it = sourceFiles.begin();
- it != sourceFiles.end();
- ++it)
- {
- const std::string &absFilename = *it;
- if (this->Verbose)
- {
- std::cout << "AUTOMOC: Checking " << absFilename << std::endl;
- }
- if (this->RelaxedMode)
- {
- this->ParseCppFile(absFilename, headerExtensions, includedMocs);
- }
- else
- {
- this->StrictParseCppFile(absFilename, headerExtensions, includedMocs);
- }
- this->SearchHeadersForCppFile(absFilename, headerExtensions, headerFiles);
- }
-
- std::vector<std::string> headerFilesVec;
- cmSystemTools::ExpandListArgument(this->Headers, headerFilesVec);
- for (std::vector<std::string>::const_iterator it = headerFilesVec.begin();
- it != headerFilesVec.end();
- ++it)
- {
- headerFiles.insert(*it);
- }
-
- // key = moc source filepath, value = moc output filename
- std::map<std::string, std::string> notIncludedMocs;
- this->ParseHeaders(headerFiles, includedMocs, notIncludedMocs);
-
- // run moc on all the moc's that are #included in source files
- for(std::map<std::string, std::string>::const_iterator
- it = includedMocs.begin();
- it != includedMocs.end();
- ++it)
- {
- this->GenerateMoc(it->first, it->second);
- }
-
- cmsys_ios::stringstream outStream;
- outStream << "/* This file is autogenerated, do not edit*/\n";
-
- bool automocCppChanged = false;
- if (notIncludedMocs.empty())
- {
- outStream << "enum some_compilers { need_more_than_nothing };\n";
- }
- else
- {
- // run moc on the remaining headers and include them in
- // the _automoc.cpp file
- for(std::map<std::string, std::string>::const_iterator
- it = notIncludedMocs.begin();
- it != notIncludedMocs.end();
- ++it)
- {
- bool mocSuccess = this->GenerateMoc(it->first, it->second);
- if (mocSuccess)
- {
- automocCppChanged = true;
- }
- outStream << "#include \"" << it->second << "\"\n";
- }
- }
-
- if (this->RunMocFailed)
- {
- std::cerr << "moc failed..."<< std::endl;
- return false;
- }
- outStream.flush();
- std::string automocSource = outStream.str();
- if (!automocCppChanged)
- {
- // compare contents of the _automoc.cpp file
- const std::string oldContents = this->ReadAll(this->OutMocCppFilename);
- if (oldContents == automocSource)
- {
- // nothing changed: don't touch the _automoc.cpp file
- return true;
- }
- }
-
- // source file that includes all remaining moc files (_automoc.cpp file)
- std::fstream outfile;
- outfile.open(this->OutMocCppFilename.c_str(),
- std::ios::out | std::ios::trunc);
- outfile << automocSource;
- outfile.close();
-
- return true;
-}
-
-
-void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
- const std::vector<std::string>& headerExtensions,
- std::map<std::string, std::string>& includedMocs)
-{
- cmsys::RegularExpression mocIncludeRegExp(
- "[\n][ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
-
- const std::string contentsString = this->ReadAll(absFilename);
- if (contentsString.empty())
- {
- std::cerr << "AUTOMOC: warning: " << absFilename << ": file is empty\n"
- << std::endl;
- return;
- }
- const std::string absPath = cmsys::SystemTools::GetFilenamePath(
- cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
- const std::string scannedFileBasename = cmsys::SystemTools::
- GetFilenameWithoutLastExtension(absFilename);
- const bool cppContainsQ_OBJECT = containsQ_OBJECT(contentsString);
- bool dotMocIncluded = false;
- bool mocUnderscoreIncluded = false;
- std::string ownMocUnderscoreFile;
- std::string ownDotMocFile;
- std::string ownMocHeaderFile;
-
- std::string::size_type matchOffset = 0;
- // 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
- if ((strstr(contentsString.c_str(), "moc") != NULL)
- && (mocIncludeRegExp.find(contentsString)))
- {
- // for every moc include in the file
- do
- {
- const std::string currentMoc = mocIncludeRegExp.match(1);
- //std::cout << "found moc include: " << currentMoc << std::endl;
-
- std::string basename = cmsys::SystemTools::
- GetFilenameWithoutLastExtension(currentMoc);
- const bool moc_style = this->StartsWith(basename, "moc_");
-
- // 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.
- // Q_OBJECT
- if (moc_style)
- {
- // basename should be the part of the moc filename used for
- // finding the correct header, so we need to remove the moc_ part
- basename = basename.substr(4);
- std::string mocSubDir = extractSubDir(absPath, currentMoc);
- std::string headerToMoc = findMatchingHeader(
- absPath, mocSubDir, basename, headerExtensions);
-
- if (!headerToMoc.empty())
- {
- includedMocs[headerToMoc] = currentMoc;
- if (basename == scannedFileBasename)
- {
- mocUnderscoreIncluded = true;
- ownMocUnderscoreFile = currentMoc;
- ownMocHeaderFile = headerToMoc;
- }
- }
- else
- {
- std::cerr << "AUTOMOC: error: " << absFilename << " The file "
- << "includes the moc file \"" << currentMoc << "\", "
- << "but could not find header \"" << basename
- << '{' << this->Join(headerExtensions, ',') << "}\" ";
- if (mocSubDir.empty())
- {
- std::cerr << "in " << absPath << "\n" << std::endl;
- }
- else
- {
- std::cerr << "neither in " << absPath
- << " nor in " << mocSubDir << "\n" << std::endl;
- }
-
- ::exit(EXIT_FAILURE);
- }
- }
- else
- {
- std::string fileToMoc = absFilename;
- if ((basename != scannedFileBasename) || (cppContainsQ_OBJECT==false))
- {
- std::string mocSubDir = extractSubDir(absPath, currentMoc);
- std::string headerToMoc = findMatchingHeader(
- absPath, mocSubDir, basename, headerExtensions);
- if (!headerToMoc.empty())
- {
- // this is for KDE4 compatibility:
- fileToMoc = headerToMoc;
- if ((cppContainsQ_OBJECT==false) &&(basename==scannedFileBasename))
- {
- std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
- "includes the moc file \"" << currentMoc <<
- "\", but does not contain a Q_OBJECT macro. "
- "Running moc on "
- << "\"" << headerToMoc << "\" ! Include \"moc_"
- << basename << ".cpp\" for a compatiblity with "
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
- << std::endl;
- }
- else
- {
- std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
- "includes the moc file \"" << currentMoc <<
- "\" instead of \"moc_" << basename << ".cpp\". "
- "Running moc on "
- << "\"" << headerToMoc << "\" ! Include \"moc_"
- << basename << ".cpp\" for compatiblity with "
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
- << std::endl;
- }
- }
- else
- {
- std::cerr <<"AUTOMOC: error: " << absFilename << ": The file "
- "includes the moc file \"" << currentMoc <<
- "\", which seems to be the moc file from a different "
- "source file. CMake also could not find a matching "
- "header.\n" << std::endl;
- ::exit(EXIT_FAILURE);
- }
- }
- else
- {
- dotMocIncluded = true;
- ownDotMocFile = currentMoc;
- }
- includedMocs[fileToMoc] = currentMoc;
- }
- matchOffset += mocIncludeRegExp.end();
- } while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
- }
-
- // 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 ((dotMocIncluded == false) && (cppContainsQ_OBJECT == true))
- {
- if (mocUnderscoreIncluded == true)
- {
- // this is for KDE4 compatibility:
- std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
- << "contains a Q_OBJECT macro, but does not include "
- << "\"" << scannedFileBasename << ".moc\", but instead "
- "includes "
- << "\"" << ownMocUnderscoreFile << "\". Running moc on "
- << "\"" << absFilename << "\" ! Better include \""
- << scannedFileBasename << ".moc\" for compatiblity with "
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
- << std::endl;
- includedMocs[absFilename] = ownMocUnderscoreFile;
- includedMocs.erase(ownMocHeaderFile);
- }
- else
- {
- // otherwise always error out since it will not compile:
- std::cerr << "AUTOMOC: error: " << absFilename << ": The file "
- << "contains a Q_OBJECT macro, but does not include "
- << "\"" << scannedFileBasename << ".moc\" !\n"
- << std::endl;
- ::exit(EXIT_FAILURE);
- }
- }
-
-}
-
-
-void cmQtAutomoc::StrictParseCppFile(const std::string& absFilename,
- const std::vector<std::string>& headerExtensions,
- std::map<std::string, std::string>& includedMocs)
-{
- cmsys::RegularExpression mocIncludeRegExp(
- "[\n][ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
-
- const std::string contentsString = this->ReadAll(absFilename);
- if (contentsString.empty())
- {
- std::cerr << "AUTOMOC: warning: " << absFilename << ": file is empty\n"
- << std::endl;
- return;
- }
- const std::string absPath = cmsys::SystemTools::GetFilenamePath(
- cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
- const std::string scannedFileBasename = cmsys::SystemTools::
- GetFilenameWithoutLastExtension(absFilename);
-
- bool dotMocIncluded = false;
-
- std::string::size_type matchOffset = 0;
- // 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
- if ((strstr(contentsString.c_str(), "moc") != NULL)
- && (mocIncludeRegExp.find(contentsString)))
- {
- // for every moc include in the file
- do
- {
- const std::string currentMoc = mocIncludeRegExp.match(1);
-
- std::string basename = cmsys::SystemTools::
- GetFilenameWithoutLastExtension(currentMoc);
- const bool mocUnderscoreStyle = this->StartsWith(basename, "moc_");
-
- // 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 (mocUnderscoreStyle)
- {
- // basename should be the part of the moc filename used for
- // finding the correct header, so we need to remove the moc_ part
- basename = basename.substr(4);
- std::string mocSubDir = extractSubDir(absPath, currentMoc);
- std::string headerToMoc = findMatchingHeader(
- absPath, mocSubDir, basename, headerExtensions);
-
- if (!headerToMoc.empty())
- {
- includedMocs[headerToMoc] = currentMoc;
- }
- else
- {
- std::cerr << "AUTOMOC: error: " << absFilename << " The file "
- << "includes the moc file \"" << currentMoc << "\", "
- << "but could not find header \"" << basename
- << '{' << this->Join(headerExtensions, ',') << "}\" ";
- if (mocSubDir.empty())
- {
- std::cerr << "in " << absPath << "\n" << std::endl;
- }
- else
- {
- std::cerr << "neither in " << absPath
- << " nor in " << mocSubDir << "\n" << std::endl;
- }
-
- ::exit(EXIT_FAILURE);
- }
- }
- else
- {
- if (basename != scannedFileBasename)
- {
- std::cerr <<"AUTOMOC: error: " << absFilename << ": The file "
- "includes the moc file \"" << currentMoc <<
- "\", which seems to be the moc file from a different "
- "source file. This is not supported. "
- "Include \"" << scannedFileBasename << ".moc\" to run "
- "moc on this source file.\n" << std::endl;
- ::exit(EXIT_FAILURE);
- }
- dotMocIncluded = true;
- includedMocs[absFilename] = currentMoc;
- }
- matchOffset += mocIncludeRegExp.end();
- } while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
- }
-
- // 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 ((dotMocIncluded == false) && (containsQ_OBJECT(contentsString)))
- {
- // otherwise always error out since it will not compile:
- std::cerr << "AUTOMOC: error: " << absFilename << ": The file "
- << "contains a Q_OBJECT macro, but does not include "
- << "\"" << scannedFileBasename << ".moc\" !\n"
- << std::endl;
- ::exit(EXIT_FAILURE);
- }
-
-}
-
-
-void cmQtAutomoc::SearchHeadersForCppFile(const std::string& absFilename,
- const std::vector<std::string>& headerExtensions,
- std::set<std::string>& absHeaders)
-{
- // search for header files and private header files we may need to moc:
- const std::string basename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
- const std::string absPath = cmsys::SystemTools::GetFilenamePath(
- cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
-
- for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
- ext != headerExtensions.end();
- ++ext)
- {
- const std::string headerName = absPath + basename + "." + (*ext);
- if (cmsys::SystemTools::FileExists(headerName.c_str()))
- {
- absHeaders.insert(headerName);
- break;
- }
- }
- for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
- ext != headerExtensions.end();
- ++ext)
- {
- const std::string privateHeaderName = absPath+basename+"_p."+(*ext);
- if (cmsys::SystemTools::FileExists(privateHeaderName.c_str()))
- {
- absHeaders.insert(privateHeaderName);
- break;
- }
- }
-
-}
-
-
-void cmQtAutomoc::ParseHeaders(const std::set<std::string>& absHeaders,
- const std::map<std::string, std::string>& includedMocs,
- std::map<std::string, std::string>& notIncludedMocs)
-{
- for(std::set<std::string>::const_iterator hIt=absHeaders.begin();
- hIt!=absHeaders.end();
- ++hIt)
- {
- const std::string& headerName = *hIt;
-
- if (includedMocs.find(headerName) == includedMocs.end())
- {
- if (this->Verbose)
- {
- std::cout << "AUTOMOC: Checking " << headerName << std::endl;
- }
-
- const std::string basename = cmsys::SystemTools::
- GetFilenameWithoutLastExtension(headerName);
-
- const std::string currentMoc = "moc_" + basename + ".cpp";
- const std::string contents = this->ReadAll(headerName);
- if (containsQ_OBJECT(contents))
- {
- //std::cout << "header contains Q_OBJECT macro";
- notIncludedMocs[headerName] = currentMoc;
- }
- }
- }
-
-}
-
-
-bool cmQtAutomoc::GenerateMoc(const std::string& sourceFile,
- const std::string& mocFileName)
-{
- const std::string mocFilePath = this->Builddir + mocFileName;
- int sourceNewerThanMoc = 0;
- bool success = cmsys::SystemTools::FileTimeCompare(sourceFile.c_str(),
- mocFilePath.c_str(),
- &sourceNewerThanMoc);
- if (this->GenerateAll || !success || sourceNewerThanMoc >= 0)
- {
- // make sure the directory for the resulting moc file exists
- std::string mocDir = mocFilePath.substr(0, mocFilePath.rfind('/'));
- if (!cmsys::SystemTools::FileExists(mocDir.c_str(), false))
- {
- cmsys::SystemTools::MakeDirectory(mocDir.c_str());
- }
-
- std::string msg = "Generating ";
- msg += mocFileName;
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue
- |cmsysTerminal_Color_ForegroundBold,
- msg.c_str(), true, this->ColorOutput);
-
- std::vector<cmStdString> command;
- command.push_back(this->MocExecutable);
- for (std::list<std::string>::const_iterator it = this->MocIncludes.begin();
- it != this->MocIncludes.end();
- ++it)
- {
- command.push_back(*it);
- }
- for(std::list<std::string>::const_iterator it=this->MocDefinitions.begin();
- it != this->MocDefinitions.end();
- ++it)
- {
- command.push_back(*it);
- }
- for(std::vector<std::string>::const_iterator it=this->MocOptions.begin();
- it != this->MocOptions.end();
- ++it)
- {
- command.push_back(*it);
- }
-#ifdef _WIN32
- command.push_back("-DWIN32");
-#endif
- command.push_back("-o");
- command.push_back(mocFilePath);
- command.push_back(sourceFile);
-
- if (this->Verbose)
- {
- for(std::vector<cmStdString>::const_iterator cmdIt = command.begin();
- cmdIt != command.end();
- ++cmdIt)
- {
- std::cout << *cmdIt << " ";
- }
- std::cout << std::endl;
- }
-
- std::string output;
- int retVal = 0;
- bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal);
- if (!result || retVal)
- {
- std::cerr << "AUTOMOC: error: process for " << mocFilePath <<" failed:\n"
- << output << std::endl;
- this->RunMocFailed = true;
- cmSystemTools::RemoveFile(mocFilePath.c_str());
- }
- return true;
- }
- return false;
-}
-
-
-std::string cmQtAutomoc::Join(const std::vector<std::string>& lst,
- char separator)
-{
- if (lst.empty())
- {
- return "";
- }
-
- std::string result;
- for (std::vector<std::string>::const_iterator it = lst.begin();
- it != lst.end();
- ++it)
- {
- result += "." + (*it) + separator;
- }
- result.erase(result.end() - 1);
- return result;
-}
-
-
-bool cmQtAutomoc::StartsWith(const std::string& str, const std::string& with)
-{
- return (str.substr(0, with.length()) == with);
-}
-
-
-bool cmQtAutomoc::EndsWith(const std::string& str, const std::string& with)
-{
- if (with.length() > (str.length()))
- {
- return false;
- }
- return (str.substr(str.length() - with.length(), with.length()) == with);
-}
-
-
-std::string cmQtAutomoc::ReadAll(const std::string& filename)
-{
- std::ifstream file(filename.c_str());
- cmsys_ios::stringstream stream;
- stream << file.rdbuf();
- file.close();
- return stream.str();
-}
diff --git a/Source/cmQtAutomoc.h b/Source/cmQtAutomoc.h
deleted file mode 100644
index ebeeb0eee..000000000
--- a/Source/cmQtAutomoc.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2004-2011 Kitware, Inc.
- Copyright 2011 Alexander Neundorf (neundorf@kde.org)
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-#ifndef cmQtAutomoc_h
-#define cmQtAutomoc_h
-
-class cmGlobalGenerator;
-class cmMakefile;
-
-class cmQtAutomoc
-{
-public:
- cmQtAutomoc();
- bool Run(const char* targetDirectory, const char *config);
-
- bool InitializeMocSourceFile(cmTarget* target);
- void SetupAutomocTarget(cmTarget* target);
-
-private:
- cmGlobalGenerator* CreateGlobalGenerator(cmake* cm,
- const char* targetDirectory);
-
- bool ReadAutomocInfoFile(cmMakefile* makefile,
- const char* targetDirectory,
- const char *config);
- bool ReadOldMocDefinitionsFile(cmMakefile* makefile,
- const char* targetDirectory);
- void WriteOldMocDefinitionsFile(const char* targetDirectory);
-
- std::string MakeCompileSettingsString(cmMakefile* makefile);
-
- bool RunAutomoc(cmMakefile* makefile);
- bool GenerateMoc(const std::string& sourceFile,
- const std::string& mocFileName);
- void ParseCppFile(const std::string& absFilename,
- const std::vector<std::string>& headerExtensions,
- std::map<std::string, std::string>& includedMocs);
- void StrictParseCppFile(const std::string& absFilename,
- const std::vector<std::string>& headerExtensions,
- std::map<std::string, std::string>& includedMocs);
- void SearchHeadersForCppFile(const std::string& absFilename,
- const std::vector<std::string>& headerExtensions,
- std::set<std::string>& absHeaders);
-
- void ParseHeaders(const std::set<std::string>& absHeaders,
- const std::map<std::string, std::string>& includedMocs,
- std::map<std::string, std::string>& notIncludedMocs);
-
- void Init();
-
- std::string Join(const std::vector<std::string>& lst, char separator);
- bool EndsWith(const std::string& str, const std::string& with);
- bool StartsWith(const std::string& str, const std::string& with);
- std::string ReadAll(const std::string& filename);
-
- std::string QtMajorVersion;
- std::string Sources;
- std::string Headers;
- bool IncludeProjectDirsBefore;
- std::string Srcdir;
- std::string Builddir;
- std::string MocExecutable;
- std::string MocCompileDefinitionsStr;
- std::string MocIncludesStr;
- std::string MocOptionsStr;
- std::string ProjectBinaryDir;
- std::string ProjectSourceDir;
- std::string TargetName;
-
- std::string CurrentCompileSettingsStr;
- std::string OldCompileSettingsStr;
-
- std::string OutMocCppFilename;
- std::list<std::string> MocIncludes;
- std::list<std::string> MocDefinitions;
- std::vector<std::string> MocOptions;
-
- bool Verbose;
- bool ColorOutput;
- bool RunMocFailed;
- bool GenerateAll;
- bool RelaxedMode;
-
-};
-
-#endif
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
new file mode 100644
index 000000000..5364f76f4
--- /dev/null
+++ b/Source/cmRST.cxx
@@ -0,0 +1,420 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 <iterator>
+#include <stddef.h>
+#include <utility>
+
+cmRST::cmRST(std::ostream& os, std::string const& docroot)
+ : OS(os)
+ , DocRoot(docroot)
+ , IncludeDepth(0)
+ , OutputLinePending(false)
+ , LastLineEndedInColonColon(false)
+ , Markup(MarkupNone)
+ , Directive(DirectiveNone)
+ , CMakeDirective("^.. (cmake:)?("
+ "command|variable"
+ ")::[ \t]+([^ \t\n]+)$")
+ , CMakeModuleDirective("^.. cmake-module::[ \t]+([^ \t\n]+)$")
+ , ParsedLiteralDirective("^.. parsed-literal::[ \t]*(.*)$")
+ , CodeBlockDirective("^.. code-block::[ \t]*(.*)$")
+ , ReplaceDirective("^.. (\\|[^|]+\\|) replace::[ \t]*(.*)$")
+ , IncludeDirective("^.. include::[ \t]+([^ \t\n]+)$")
+ , TocTreeDirective("^.. toctree::[ \t]*(.*)$")
+ , ProductionListDirective("^.. productionlist::[ \t]*(.*)$")
+ , NoteDirective("^.. note::[ \t]*(.*)$")
+ , ModuleRST("^#\\[(=*)\\[\\.rst:$")
+ , CMakeRole("(:cmake)?:("
+ "command|generator|variable|module|policy|"
+ "prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
+ "prop_test|prop_tgt|"
+ "manual"
+ "):`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`")
+ , Substitution("(^|[^A-Za-z0-9_])"
+ "((\\|[^| \t\r\n]([^|\r\n]*[^| \t\r\n])?\\|)(__|_|))"
+ "([^A-Za-z0-9_]|$)")
+ , TocTreeLink("^.*[ \t]+<([^>]+)>$")
+{
+ this->Replace["|release|"] = cmVersion::GetCMakeVersion();
+}
+
+bool cmRST::ProcessFile(std::string const& fname, bool isModule)
+{
+ cmsys::ifstream fin(fname.c_str());
+ if (fin) {
+ this->DocDir = cmSystemTools::GetFilenamePath(fname);
+ if (isModule) {
+ this->ProcessModule(fin);
+ } else {
+ this->ProcessRST(fin);
+ }
+ this->OutputLinePending = true;
+ return true;
+ }
+ return false;
+}
+
+void cmRST::ProcessRST(std::istream& is)
+{
+ std::string line;
+ while (cmSystemTools::GetLineFromStream(is, line)) {
+ this->ProcessLine(line);
+ }
+ this->Reset();
+}
+
+void cmRST::ProcessModule(std::istream& is)
+{
+ std::string line;
+ std::string rst;
+ while (cmSystemTools::GetLineFromStream(is, line)) {
+ if (!rst.empty() && rst != "#") {
+ // Bracket mode: check for end bracket
+ std::string::size_type pos = line.find(rst);
+ if (pos == std::string::npos) {
+ this->ProcessLine(line);
+ } else {
+ if (line[0] != '#') {
+ this->ProcessLine(line.substr(0, pos));
+ }
+ rst = "";
+ this->Reset();
+ this->OutputLinePending = true;
+ }
+ } else {
+ // Line mode: check for .rst start (bracket or line)
+ if (rst == "#") {
+ if (line == "#") {
+ this->ProcessLine("");
+ continue;
+ }
+ if (line.substr(0, 2) == "# ") {
+ this->ProcessLine(line.substr(2));
+ continue;
+ }
+ rst = "";
+ this->Reset();
+ this->OutputLinePending = true;
+ }
+ if (line == "#.rst:") {
+ rst = "#";
+ } else if (this->ModuleRST.find(line)) {
+ rst = "]" + this->ModuleRST.match(1) + "]";
+ }
+ }
+ }
+ if (rst == "#") {
+ this->Reset();
+ }
+}
+
+void cmRST::Reset()
+{
+ if (!this->MarkupLines.empty()) {
+ this->UnindentLines(this->MarkupLines);
+ }
+ switch (this->Directive) {
+ case DirectiveNone:
+ break;
+ case DirectiveParsedLiteral:
+ this->ProcessDirectiveParsedLiteral();
+ break;
+ case DirectiveLiteralBlock:
+ this->ProcessDirectiveLiteralBlock();
+ break;
+ case DirectiveCodeBlock:
+ this->ProcessDirectiveCodeBlock();
+ break;
+ case DirectiveReplace:
+ this->ProcessDirectiveReplace();
+ break;
+ case DirectiveTocTree:
+ this->ProcessDirectiveTocTree();
+ break;
+ }
+ this->Markup = MarkupNone;
+ this->Directive = DirectiveNone;
+ this->MarkupLines.clear();
+}
+
+void cmRST::ProcessLine(std::string const& line)
+{
+ bool lastLineEndedInColonColon = this->LastLineEndedInColonColon;
+ this->LastLineEndedInColonColon = false;
+
+ // A line starting in .. is an explicit markup start.
+ 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
+ : MarkupNormal);
+ if (this->CMakeDirective.find(line)) {
+ // Output cmake domain directives and their content normally.
+ this->NormalLine(line);
+ } else if (this->CMakeModuleDirective.find(line)) {
+ // Process cmake-module directive: scan .cmake file comments.
+ std::string file = this->CMakeModuleDirective.match(1);
+ if (file.empty() || !this->ProcessInclude(file, IncludeModule)) {
+ this->NormalLine(line);
+ }
+ } else if (this->ParsedLiteralDirective.find(line)) {
+ // Record the literal lines to output after whole block.
+ this->Directive = DirectiveParsedLiteral;
+ this->MarkupLines.push_back(this->ParsedLiteralDirective.match(1));
+ } else if (this->CodeBlockDirective.find(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("");
+ } else if (this->ReplaceDirective.find(line)) {
+ // Record the replace directive content.
+ this->Directive = DirectiveReplace;
+ this->ReplaceName = this->ReplaceDirective.match(1);
+ this->MarkupLines.push_back(this->ReplaceDirective.match(2));
+ } else if (this->IncludeDirective.find(line)) {
+ // Process the include directive or output the directive and its
+ // content normally if it fails.
+ std::string file = this->IncludeDirective.match(1);
+ if (file.empty() || !this->ProcessInclude(file, IncludeNormal)) {
+ this->NormalLine(line);
+ }
+ } else if (this->TocTreeDirective.find(line)) {
+ // Record the toctree entries to process after whole block.
+ this->Directive = DirectiveTocTree;
+ this->MarkupLines.push_back(this->TocTreeDirective.match(1));
+ } else if (this->ProductionListDirective.find(line)) {
+ // Output productionlist directives and their content normally.
+ this->NormalLine(line);
+ } else if (this->NoteDirective.find(line)) {
+ // Output note directives and their content normally.
+ this->NormalLine(line);
+ }
+ }
+ // An explicit markup start followed nothing but whitespace and a
+ // blank line does not consume any indented text following.
+ else if (this->Markup == MarkupEmpty && line.empty()) {
+ this->NormalLine(line);
+ }
+ // Indented lines following an explicit markup start are explicit markup.
+ else if (this->Markup && (line.empty() || isspace(line[0]))) {
+ this->Markup = MarkupNormal;
+ // Record markup lines if the start line was recorded.
+ if (!this->MarkupLines.empty()) {
+ this->MarkupLines.push_back(line);
+ }
+ }
+ // A blank line following a paragraph ending in "::" starts a literal block.
+ else if (lastLineEndedInColonColon && line.empty()) {
+ // Record the literal lines to output after whole block.
+ this->Markup = MarkupNormal;
+ this->Directive = DirectiveLiteralBlock;
+ this->MarkupLines.push_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] == ':');
+ }
+}
+
+void cmRST::NormalLine(std::string const& line)
+{
+ this->Reset();
+ this->OutputLine(line, true);
+}
+
+void cmRST::OutputLine(std::string const& line_in, bool inlineMarkup)
+{
+ if (this->OutputLinePending) {
+ this->OS << "\n";
+ this->OutputLinePending = false;
+ }
+ 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 += "()";
+ }
+ this->OS << "``" << text << "``";
+ pos += this->CMakeRole.end();
+ }
+ this->OS << line.substr(pos) << "\n";
+ } else {
+ this->OS << line_in << "\n";
+ }
+}
+
+std::string cmRST::ReplaceSubstitutions(std::string const& line)
+{
+ std::string out;
+ std::string::size_type pos = 0;
+ while (this->Substitution.find(line.c_str() + pos)) {
+ 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);
+ if (replace != this->Replace.end()) {
+ std::pair<std::set<std::string>::iterator, bool> replaced =
+ this->Replaced.insert(substitute);
+ if (replaced.second) {
+ substitute = this->ReplaceSubstitutions(replace->second);
+ this->Replaced.erase(replaced.first);
+ }
+ }
+ out += line.substr(pos, start);
+ out += substitute;
+ pos += end;
+ }
+ out += line.substr(pos);
+ return out;
+}
+
+void cmRST::OutputMarkupLines(bool inlineMarkup)
+{
+ for (std::vector<std::string>::iterator i = this->MarkupLines.begin();
+ i != this->MarkupLines.end(); ++i) {
+ std::string line = *i;
+ if (!line.empty()) {
+ line = " " + line;
+ }
+ this->OutputLine(line, inlineMarkup);
+ }
+ this->OutputLinePending = true;
+}
+
+bool cmRST::ProcessInclude(std::string file, IncludeType type)
+{
+ bool found = false;
+ if (this->IncludeDepth < 10) {
+ cmRST r(this->OS, this->DocRoot);
+ r.IncludeDepth = this->IncludeDepth + 1;
+ r.OutputLinePending = this->OutputLinePending;
+ if (type != IncludeTocTree) {
+ r.Replace = this->Replace;
+ }
+ if (file[0] == '/') {
+ file = this->DocRoot + file;
+ } else {
+ file = this->DocDir + "/" + file;
+ }
+ found = r.ProcessFile(file, type == IncludeModule);
+ if (type != IncludeTocTree) {
+ this->Replace = r.Replace;
+ }
+ this->OutputLinePending = r.OutputLinePending;
+ }
+ return found;
+}
+
+void cmRST::ProcessDirectiveParsedLiteral()
+{
+ this->OutputMarkupLines(true);
+}
+
+void cmRST::ProcessDirectiveLiteralBlock()
+{
+ this->OutputMarkupLines(false);
+}
+
+void cmRST::ProcessDirectiveCodeBlock()
+{
+ this->OutputMarkupLines(false);
+}
+
+void cmRST::ProcessDirectiveReplace()
+{
+ // Record markup lines as replacement text.
+ std::string& replacement = this->Replace[this->ReplaceName];
+ replacement += cmJoin(this->MarkupLines, " ");
+ this->ReplaceName = "";
+}
+
+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;
+ if (!line.empty() && line[0] != ':') {
+ if (this->TocTreeLink.find(line)) {
+ std::string const& link = this->TocTreeLink.match(1);
+ this->ProcessInclude(link + ".rst", IncludeTocTree);
+ } else {
+ this->ProcessInclude(line + ".rst", IncludeTocTree);
+ }
+ }
+ }
+}
+
+void cmRST::UnindentLines(std::vector<std::string>& lines)
+{
+ // Remove the common indentation from the second and later lines.
+ std::string indentText;
+ std::string::size_type indentEnd = 0;
+ bool first = true;
+ for (size_t i = 1; i < lines.size(); ++i) {
+ std::string const& line = lines[i];
+
+ // Do not consider empty lines.
+ if (line.empty()) {
+ continue;
+ }
+
+ // Record indentation on first non-empty line.
+ if (first) {
+ first = false;
+ indentEnd = line.find_first_not_of(" \t");
+ indentText = line.substr(0, indentEnd);
+ continue;
+ }
+
+ // Truncate indentation to match that on this line.
+ indentEnd = std::min(indentEnd, line.size());
+ for (std::string::size_type j = 0; j != indentEnd; ++j) {
+ if (line[j] != indentText[j]) {
+ indentEnd = j;
+ break;
+ }
+ }
+ }
+
+ // Update second and later lines.
+ for (size_t i = 1; i < lines.size(); ++i) {
+ std::string& line = lines[i];
+ if (!line.empty()) {
+ line = line.substr(indentEnd);
+ }
+ }
+
+ std::vector<std::string>::const_iterator it = lines.begin();
+ size_t leadingEmpty = std::distance(it, cmFindNot(lines, std::string()));
+
+ std::vector<std::string>::const_reverse_iterator rit = lines.rbegin();
+ 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);
+ lines.erase(contentEnd, lines.end());
+}
diff --git a/Source/cmRST.h b/Source/cmRST.h
new file mode 100644
index 000000000..d1a8e2711
--- /dev/null
+++ b/Source/cmRST.h
@@ -0,0 +1,98 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef _cmRST_h
+#define _cmRST_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmsys/RegularExpression.hxx"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+/** \class cmRST
+ * \brief Perform basic .rst processing for command-line help
+ *
+ * This class implements a subset of reStructuredText and Sphinx
+ * document processing. It is used to print command-line help.
+ *
+ * If you modify the capabilities of this class, be sure to update
+ * the Help/manual/cmake-developer.7.rst documentation and to update
+ * the Tests/CMakeLib/testRST.(rst|expect) test input and output.
+ */
+class cmRST
+{
+public:
+ cmRST(std::ostream& os, std::string const& docroot);
+ bool ProcessFile(std::string const& fname, bool isModule = false);
+
+private:
+ enum IncludeType
+ {
+ IncludeNormal,
+ IncludeModule,
+ IncludeTocTree
+ };
+ enum MarkupType
+ {
+ MarkupNone,
+ MarkupNormal,
+ MarkupEmpty
+ };
+ enum DirectiveType
+ {
+ DirectiveNone,
+ DirectiveParsedLiteral,
+ DirectiveLiteralBlock,
+ DirectiveCodeBlock,
+ DirectiveReplace,
+ DirectiveTocTree
+ };
+
+ void ProcessRST(std::istream& is);
+ void ProcessModule(std::istream& is);
+ void Reset();
+ void ProcessLine(std::string const& line);
+ void NormalLine(std::string const& line);
+ void OutputLine(std::string const& line, bool inlineMarkup);
+ std::string ReplaceSubstitutions(std::string const& line);
+ void OutputMarkupLines(bool inlineMarkup);
+ bool ProcessInclude(std::string file, IncludeType type);
+ void ProcessDirectiveParsedLiteral();
+ void ProcessDirectiveLiteralBlock();
+ void ProcessDirectiveCodeBlock();
+ void ProcessDirectiveReplace();
+ void ProcessDirectiveTocTree();
+ static void UnindentLines(std::vector<std::string>& lines);
+
+ std::ostream& OS;
+ std::string DocRoot;
+ int IncludeDepth;
+ bool OutputLinePending;
+ bool LastLineEndedInColonColon;
+ MarkupType Markup;
+ DirectiveType Directive;
+ cmsys::RegularExpression CMakeDirective;
+ cmsys::RegularExpression CMakeModuleDirective;
+ cmsys::RegularExpression ParsedLiteralDirective;
+ cmsys::RegularExpression CodeBlockDirective;
+ cmsys::RegularExpression ReplaceDirective;
+ cmsys::RegularExpression IncludeDirective;
+ cmsys::RegularExpression TocTreeDirective;
+ cmsys::RegularExpression ProductionListDirective;
+ cmsys::RegularExpression NoteDirective;
+ cmsys::RegularExpression ModuleRST;
+ cmsys::RegularExpression CMakeRole;
+ cmsys::RegularExpression Substitution;
+ cmsys::RegularExpression TocTreeLink;
+
+ std::vector<std::string> MarkupLines;
+ std::string DocDir;
+ std::map<std::string, std::string> Replace;
+ std::set<std::string> Replaced;
+ std::string ReplaceName;
+};
+
+#endif
diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx
index bcb856438..1db84414a 100644
--- a/Source/cmRemoveCommand.cxx
+++ b/Source/cmRemoveCommand.cxx
@@ -1,35 +1,28 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmRemoveCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmRemoveCommand.h"
+class cmExecutionStatus;
// cmRemoveCommand
-bool cmRemoveCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
return true;
- }
+ }
- const char* variable = args[0].c_str(); // VAR is always first
+ std::string const& variable = args[0]; // VAR is always first
// get the old value
- const char* cacheValue
- = this->Makefile->GetDefinition(variable);
+ const char* cacheValue = this->Makefile->GetDefinition(variable);
// if there is no old value then return
- if (!cacheValue)
- {
+ if (!cacheValue) {
return true;
- }
+ }
// expand the variable
std::vector<std::string> varArgsExpanded;
@@ -39,38 +32,29 @@ bool cmRemoveCommand
// check for REMOVE(VAR v1 v2 ... vn)
std::vector<std::string> argsExpanded;
std::vector<std::string> temp;
- for(unsigned int j = 1; j < args.size(); ++j)
- {
- temp.push_back(args[j]);
- }
+ temp.insert(temp.end(), args.begin() + 1, args.end());
cmSystemTools::ExpandList(temp, argsExpanded);
// now create the new value
std::string value;
- for(unsigned int j = 0; j < varArgsExpanded.size(); ++j)
- {
+ for (unsigned int j = 0; j < varArgsExpanded.size(); ++j) {
int found = 0;
- for(unsigned int k = 0; k < argsExpanded.size(); ++k)
- {
- if (varArgsExpanded[j] == argsExpanded[k])
- {
+ for (unsigned int k = 0; k < argsExpanded.size(); ++k) {
+ if (varArgsExpanded[j] == argsExpanded[k]) {
found = 1;
break;
- }
}
- if (!found)
- {
- if (value.size())
- {
+ }
+ if (!found) {
+ if (!value.empty()) {
value += ";";
- }
- value += varArgsExpanded[j];
}
+ value += varArgsExpanded[j];
}
+ }
// add the definition
this->Makefile->AddDefinition(variable, value.c_str());
return true;
}
-
diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h
index 5aedc26e5..f2e89f6e1 100644
--- a/Source/cmRemoveCommand.h
+++ b/Source/cmRemoveCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmRemoveCommand_h
#define cmRemoveCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmRemoveCommand
* \brief remove command
*
@@ -25,57 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmRemoveCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmRemoveCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "remove";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the list(REMOVE_ITEM ) command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " remove(VAR VALUE VALUE ...)\n"
- "Removes VALUE from the variable VAR. "
- "This is typically used to remove entries from a vector "
- "(e.g. semicolon separated list). VALUE is expanded.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmRemoveCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmRemoveDefinitionsCommand.cxx b/Source/cmRemoveDefinitionsCommand.cxx
index b4be0f587..f5fe2dfb7 100644
--- a/Source/cmRemoveDefinitionsCommand.cxx
+++ b/Source/cmRemoveDefinitionsCommand.cxx
@@ -1,31 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmRemoveDefinitionsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmRemoveDefinitionsCommand.h"
+class cmExecutionStatus;
// cmRemoveDefinitionsCommand
-bool cmRemoveDefinitionsCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmRemoveDefinitionsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
// it is OK to have no arguments
- if(args.size() < 1 )
- {
+ if (args.empty()) {
return true;
- }
+ }
- for(std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
this->Makefile->RemoveDefineFlag(i->c_str());
- }
+ }
return true;
}
-
diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h
index 18f617124..9a9a5d535 100644
--- a/Source/cmRemoveDefinitionsCommand.h
+++ b/Source/cmRemoveDefinitionsCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmRemoveDefinitionsCommand_h
#define cmRemoveDefinitionsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmRemoveDefinitionsCommand
* \brief Specify a list of compiler defines
*
@@ -27,45 +25,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmRemoveDefinitionsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmRemoveDefinitionsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "remove_definitions";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Removes -D define flags added by add_definitions.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " remove_definitions(-DFOO -DBAR ...)\n"
- "Removes flags (added by add_definitions) from the compiler command "
- "line for sources in the current directory and below.";
- }
-
- cmTypeMacro(cmRemoveDefinitionsCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx
index 51cc83fcd..ceea8b4d9 100644
--- a/Source/cmReturnCommand.cxx
+++ b/Source/cmReturnCommand.cxx
@@ -1,21 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmReturnCommand.h"
+#include "cmExecutionStatus.h"
+
// cmReturnCommand
bool cmReturnCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &status)
+ cmExecutionStatus& status)
{
- status.SetReturnInvoked(true);
+ status.SetReturnInvoked();
return true;
}
-
diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h
index a6e87eff3..87900e7e9 100644
--- a/Source/cmReturnCommand.h
+++ b/Source/cmReturnCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmReturnCommand_h
#define cmReturnCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmReturnCommand
* \brief Return from a directory or function
*
@@ -25,57 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmReturnCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmReturnCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "return";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Return from a file, directory or function.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " return()\n"
- "Returns from a file, directory or function. When this command is "
- "encountered in an included file (via include() or find_package()), "
- "it causes processing of the current file to stop and control is "
- "returned to the including file. If it is encountered in a file which "
- "is not included by another file, e.g. a CMakeLists.txt, control is "
- "returned to the parent directory if there is one. "
- "If return is called in a function, control is returned to the caller "
- "of the function. Note that a macro "
- "is not a function and does not handle return like a function does.";
- }
-
- cmTypeMacro(cmReturnCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
new file mode 100644
index 000000000..a71861af7
--- /dev/null
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -0,0 +1,318 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmRulePlaceholderExpander.h"
+
+#include <ctype.h>
+#include <string.h>
+#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)
+{
+}
+
+cmRulePlaceholderExpander::RuleVariables::RuleVariables()
+{
+ memset(this, 0, sizeof(*this));
+}
+
+std::string cmRulePlaceholderExpander::ExpandRuleVariable(
+ cmOutputConverter* outputConverter, std::string const& variable,
+ const RuleVariables& replaceValues)
+{
+ if (replaceValues.LinkFlags) {
+ if (variable == "LINK_FLAGS") {
+ return replaceValues.LinkFlags;
+ }
+ }
+ if (replaceValues.Manifests) {
+ if (variable == "MANIFESTS") {
+ return replaceValues.Manifests;
+ }
+ }
+ if (replaceValues.Flags) {
+ if (variable == "FLAGS") {
+ return replaceValues.Flags;
+ }
+ }
+
+ if (replaceValues.Source) {
+ if (variable == "SOURCE") {
+ return replaceValues.Source;
+ }
+ }
+ if (replaceValues.PreprocessedSource) {
+ if (variable == "PREPROCESSED_SOURCE") {
+ return replaceValues.PreprocessedSource;
+ }
+ }
+ if (replaceValues.AssemblySource) {
+ if (variable == "ASSEMBLY_SOURCE") {
+ return replaceValues.AssemblySource;
+ }
+ }
+ if (replaceValues.Object) {
+ if (variable == "OBJECT") {
+ return replaceValues.Object;
+ }
+ }
+ if (replaceValues.ObjectDir) {
+ if (variable == "OBJECT_DIR") {
+ return replaceValues.ObjectDir;
+ }
+ }
+ if (replaceValues.ObjectFileDir) {
+ if (variable == "OBJECT_FILE_DIR") {
+ return replaceValues.ObjectFileDir;
+ }
+ }
+ if (replaceValues.Objects) {
+ if (variable == "OBJECTS") {
+ return replaceValues.Objects;
+ }
+ }
+ if (replaceValues.ObjectsQuoted) {
+ if (variable == "OBJECTS_QUOTED") {
+ return replaceValues.ObjectsQuoted;
+ }
+ }
+ if (replaceValues.Defines && variable == "DEFINES") {
+ return replaceValues.Defines;
+ }
+ if (replaceValues.Includes && variable == "INCLUDES") {
+ return replaceValues.Includes;
+ }
+ if (replaceValues.TargetPDB) {
+ if (variable == "TARGET_PDB") {
+ return replaceValues.TargetPDB;
+ }
+ }
+ if (replaceValues.TargetCompilePDB) {
+ if (variable == "TARGET_COMPILE_PDB") {
+ return replaceValues.TargetCompilePDB;
+ }
+ }
+ if (replaceValues.DependencyFile) {
+ if (variable == "DEP_FILE") {
+ return replaceValues.DependencyFile;
+ }
+ }
+
+ if (replaceValues.Target) {
+ if (variable == "TARGET_QUOTED") {
+ std::string targetQuoted = replaceValues.Target;
+ if (!targetQuoted.empty() && targetQuoted[0] != '\"') {
+ targetQuoted = '\"';
+ targetQuoted += replaceValues.Target;
+ targetQuoted += '\"';
+ }
+ return targetQuoted;
+ }
+ if (variable == "TARGET_UNQUOTED") {
+ std::string unquoted = replaceValues.Target;
+ std::string::size_type sz = unquoted.size();
+ if (sz > 2 && unquoted[0] == '\"' && unquoted[sz - 1] == '\"') {
+ unquoted = unquoted.substr(1, sz - 2);
+ }
+ return unquoted;
+ }
+ if (replaceValues.LanguageCompileFlags) {
+ if (variable == "LANGUAGE_COMPILE_FLAGS") {
+ return replaceValues.LanguageCompileFlags;
+ }
+ }
+ if (replaceValues.Target) {
+ if (variable == "TARGET") {
+ return replaceValues.Target;
+ }
+ }
+ if (variable == "TARGET_IMPLIB") {
+ return this->TargetImpLib;
+ }
+ if (variable == "TARGET_VERSION_MAJOR") {
+ if (replaceValues.TargetVersionMajor) {
+ return replaceValues.TargetVersionMajor;
+ }
+ return "0";
+ }
+ if (variable == "TARGET_VERSION_MINOR") {
+ if (replaceValues.TargetVersionMinor) {
+ return replaceValues.TargetVersionMinor;
+ }
+ return "0";
+ }
+ if (replaceValues.Target) {
+ if (variable == "TARGET_BASE") {
+ // Strip the last extension off the target name.
+ std::string targetBase = replaceValues.Target;
+ std::string::size_type pos = targetBase.rfind('.');
+ if (pos != std::string::npos) {
+ return targetBase.substr(0, pos);
+ }
+ return targetBase;
+ }
+ }
+ }
+ if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" ||
+ variable == "TARGET_INSTALLNAME_DIR") {
+ // All these variables depend on TargetSOName
+ if (replaceValues.TargetSOName) {
+ if (variable == "TARGET_SONAME") {
+ return replaceValues.TargetSOName;
+ }
+ if (variable == "SONAME_FLAG" && replaceValues.SONameFlag) {
+ return replaceValues.SONameFlag;
+ }
+ if (replaceValues.TargetInstallNameDir &&
+ variable == "TARGET_INSTALLNAME_DIR") {
+ return replaceValues.TargetInstallNameDir;
+ }
+ }
+ return "";
+ }
+ if (replaceValues.LinkLibraries) {
+ if (variable == "LINK_LIBRARIES") {
+ return replaceValues.LinkLibraries;
+ }
+ }
+ if (replaceValues.Language) {
+ if (variable == "LANGUAGE") {
+ return replaceValues.Language;
+ }
+ }
+ if (replaceValues.CMTargetName) {
+ if (variable == "TARGET_NAME") {
+ return replaceValues.CMTargetName;
+ }
+ }
+ if (replaceValues.CMTargetType) {
+ if (variable == "TARGET_TYPE") {
+ return replaceValues.CMTargetType;
+ }
+ }
+ if (replaceValues.Output) {
+ if (variable == "OUTPUT") {
+ return replaceValues.Output;
+ }
+ }
+ if (variable == "CMAKE_COMMAND") {
+ return outputConverter->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
+ cmOutputConverter::SHELL);
+ }
+
+ std::map<std::string, std::string>::iterator compIt =
+ this->Compilers.find(variable);
+
+ if (compIt != this->Compilers.end()) {
+ std::string ret = outputConverter->ConvertToOutputForExisting(
+ this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
+ std::string const& compilerArg1 =
+ this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_ARG1"];
+ std::string const& compilerTarget =
+ this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
+ std::string const& compilerOptionTarget =
+ this->VariableMappings["CMAKE_" + compIt->second +
+ "_COMPILE_OPTIONS_TARGET"];
+ std::string const& compilerExternalToolchain =
+ this->VariableMappings["CMAKE_" + compIt->second +
+ "_COMPILER_EXTERNAL_TOOLCHAIN"];
+ std::string const& compilerOptionExternalToolchain =
+ this->VariableMappings["CMAKE_" + compIt->second +
+ "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
+ std::string const& compilerOptionSysroot =
+ this->VariableMappings["CMAKE_" + compIt->second +
+ "_COMPILE_OPTIONS_SYSROOT"];
+
+ // if there is a required first argument to the compiler add it
+ // to the compiler string
+ if (!compilerArg1.empty()) {
+ ret += " ";
+ ret += compilerArg1;
+ }
+ if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
+ ret += " ";
+ ret += compilerOptionTarget;
+ ret += compilerTarget;
+ }
+ if (!compilerExternalToolchain.empty() &&
+ !compilerOptionExternalToolchain.empty()) {
+ ret += " ";
+ ret += compilerOptionExternalToolchain;
+ ret += outputConverter->EscapeForShell(compilerExternalToolchain, true);
+ }
+ std::string sysroot;
+ // Some platforms may use separate sysroots for compiling and linking.
+ // If we detect link flags, then we pass the link sysroot instead.
+ // FIXME: Use a more robust way to detect link line expansion.
+ if (replaceValues.LinkFlags) {
+ sysroot = this->LinkerSysroot;
+ } else {
+ sysroot = this->CompilerSysroot;
+ }
+ if (!sysroot.empty() && !compilerOptionSysroot.empty()) {
+ ret += " ";
+ ret += compilerOptionSysroot;
+ ret += outputConverter->EscapeForShell(sysroot, true);
+ }
+ return ret;
+ }
+
+ std::map<std::string, std::string>::iterator mapIt =
+ this->VariableMappings.find(variable);
+ if (mapIt != this->VariableMappings.end()) {
+ if (variable.find("_FLAG") == std::string::npos) {
+ return outputConverter->ConvertToOutputForExisting(mapIt->second);
+ }
+ return mapIt->second;
+ }
+ return variable;
+}
+
+void cmRulePlaceholderExpander::ExpandRuleVariables(
+ cmOutputConverter* outputConverter, std::string& s,
+ const RuleVariables& replaceValues)
+{
+ std::string::size_type start = s.find('<');
+ // no variables to expand
+ if (start == std::string::npos) {
+ return;
+ }
+ std::string::size_type pos = 0;
+ std::string expandedInput;
+ while (start != std::string::npos && start < s.size() - 2) {
+ std::string::size_type end = s.find('>', start);
+ // if we find a < with no > we are done
+ if (end == std::string::npos) {
+ return;
+ }
+ char c = s[start + 1];
+ // if the next char after the < is not A-Za-z then
+ // skip it and try to find the next < in the string
+ if (!isalpha(c)) {
+ start = s.find('<', start + 1);
+ } else {
+ // extract the var
+ std::string var = s.substr(start + 1, end - start - 1);
+ std::string replace =
+ this->ExpandRuleVariable(outputConverter, var, replaceValues);
+ expandedInput += s.substr(pos, start - pos);
+ expandedInput += replace;
+ // move to next one
+ start = s.find('<', start + var.size() + 2);
+ pos = end + 1;
+ }
+ }
+ // add the rest of the input
+ expandedInput += s.substr(pos, s.size() - pos);
+ s = expandedInput;
+}
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
new file mode 100644
index 000000000..7b19210d3
--- /dev/null
+++ b/Source/cmRulePlaceholderExpander.h
@@ -0,0 +1,82 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmRulePlaceholderExpander_h
+#define cmRulePlaceholderExpander_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+
+class cmOutputConverter;
+
+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);
+
+ void SetTargetImpLib(std::string const& targetImpLib)
+ {
+ this->TargetImpLib = targetImpLib;
+ }
+
+ // Create a struct to hold the varibles passed into
+ // ExpandRuleVariables
+ struct RuleVariables
+ {
+ RuleVariables();
+ const char* CMTargetName;
+ const char* CMTargetType;
+ const char* TargetPDB;
+ const char* TargetCompilePDB;
+ const char* TargetVersionMajor;
+ const char* TargetVersionMinor;
+ const char* Language;
+ const char* Objects;
+ const char* Target;
+ const char* LinkLibraries;
+ const char* Source;
+ const char* AssemblySource;
+ const char* PreprocessedSource;
+ const char* Output;
+ const char* Object;
+ const char* ObjectDir;
+ const char* ObjectFileDir;
+ const char* Flags;
+ const char* ObjectsQuoted;
+ const char* SONameFlag;
+ const char* TargetSOName;
+ const char* TargetInstallNameDir;
+ const char* LinkFlags;
+ const char* Manifests;
+ const char* LanguageCompileFlags;
+ const char* Defines;
+ const char* Includes;
+ const char* DependencyFile;
+ const char* FilterPrefix;
+ };
+
+ // Expand rule variables in CMake of the type found in language rules
+ void ExpandRuleVariables(cmOutputConverter* outputConverter,
+ std::string& string,
+ const RuleVariables& replaceValues);
+
+ // Expand rule variables in a single string
+ std::string ExpandRuleVariable(cmOutputConverter* outputConverter,
+ std::string const& variable,
+ const RuleVariables& replaceValues);
+
+private:
+ std::string TargetImpLib;
+
+ std::map<std::string, std::string> Compilers;
+ std::map<std::string, std::string> VariableMappings;
+ std::string CompilerSysroot;
+ std::string LinkerSysroot;
+};
+
+#endif
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index cabe98a51..753a1ba6f 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -1,111 +1,84 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmScriptGenerator.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
-cmScriptGenerator
-::cmScriptGenerator(const char* config_var,
- std::vector<std::string> const& configurations):
- RuntimeConfigVariable(config_var),
- Configurations(configurations),
- ConfigurationName(0),
- ConfigurationTypes(0),
- ActionsPerConfig(false)
+cmScriptGenerator::cmScriptGenerator(
+ const std::string& config_var,
+ std::vector<std::string> const& configurations)
+ : RuntimeConfigVariable(config_var)
+ , Configurations(configurations)
+ , ConfigurationName("")
+ , ConfigurationTypes(CM_NULLPTR)
+ , ActionsPerConfig(false)
{
}
-//----------------------------------------------------------------------------
-cmScriptGenerator
-::~cmScriptGenerator()
+cmScriptGenerator::~cmScriptGenerator()
{
}
-//----------------------------------------------------------------------------
-void
-cmScriptGenerator
-::Generate(std::ostream& os, const char* config,
- std::vector<std::string> const& configurationTypes)
+void cmScriptGenerator::Generate(
+ std::ostream& os, const std::string& config,
+ std::vector<std::string> const& configurationTypes)
{
this->ConfigurationName = config;
this->ConfigurationTypes = &configurationTypes;
this->GenerateScript(os);
- this->ConfigurationName = 0;
- this->ConfigurationTypes = 0;
+ this->ConfigurationName = "";
+ this->ConfigurationTypes = CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-static void cmScriptGeneratorEncodeConfig(const char* config,
+static void cmScriptGeneratorEncodeConfig(const std::string& config,
std::string& result)
{
- for(const char* c = config; *c; ++c)
- {
- if(*c >= 'a' && *c <= 'z')
- {
+ for (const char* c = config.c_str(); *c; ++c) {
+ if (*c >= 'a' && *c <= 'z') {
result += "[";
result += static_cast<char>(*c + 'A' - 'a');
result += *c;
result += "]";
- }
- else if(*c >= 'A' && *c <= 'Z')
- {
+ } else if (*c >= 'A' && *c <= 'Z') {
result += "[";
result += *c;
result += static_cast<char>(*c + 'a' - 'A');
result += "]";
- }
- else
- {
+ } else {
result += *c;
- }
}
+ }
}
-//----------------------------------------------------------------------------
-std::string
-cmScriptGenerator::CreateConfigTest(const char* config)
+std::string cmScriptGenerator::CreateConfigTest(const std::string& config)
{
std::string result = "\"${";
result += this->RuntimeConfigVariable;
result += "}\" MATCHES \"^(";
- if(config && *config)
- {
+ if (!config.empty()) {
cmScriptGeneratorEncodeConfig(config, result);
- }
+ }
result += ")$\"";
return result;
}
-//----------------------------------------------------------------------------
-std::string
-cmScriptGenerator::CreateConfigTest(std::vector<std::string> const& configs)
+std::string cmScriptGenerator::CreateConfigTest(
+ std::vector<std::string> const& configs)
{
std::string result = "\"${";
result += this->RuntimeConfigVariable;
result += "}\" MATCHES \"^(";
const char* sep = "";
- for(std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci)
- {
+ for (std::vector<std::string>::const_iterator ci = configs.begin();
+ ci != configs.end(); ++ci) {
result += sep;
sep = "|";
- cmScriptGeneratorEncodeConfig(ci->c_str(), result);
- }
+ cmScriptGeneratorEncodeConfig(*ci, result);
+ }
result += ")$\"";
return result;
}
-//----------------------------------------------------------------------------
void cmScriptGenerator::GenerateScript(std::ostream& os)
{
// Track indentation.
@@ -115,123 +88,99 @@ void cmScriptGenerator::GenerateScript(std::ostream& os)
this->GenerateScriptConfigs(os, indent);
}
-//----------------------------------------------------------------------------
-void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os,
- Indent const& indent)
+void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
{
- if(this->ActionsPerConfig)
- {
+ if (this->ActionsPerConfig) {
this->GenerateScriptActionsPerConfig(os, indent);
- }
- else
- {
+ } else {
this->GenerateScriptActionsOnce(os, indent);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmScriptGenerator::GenerateScriptActions(std::ostream& os,
- Indent const& indent)
+void cmScriptGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
{
- if(this->ActionsPerConfig)
- {
+ if (this->ActionsPerConfig) {
// This is reached for single-configuration build generators in a
// per-config script generator.
this->GenerateScriptForConfig(os, this->ConfigurationName, indent);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmScriptGenerator::GenerateScriptForConfig(std::ostream&, const char*,
- Indent const&)
+void cmScriptGenerator::GenerateScriptForConfig(std::ostream& /*unused*/,
+ const std::string& /*unused*/,
+ Indent /*unused*/)
{
// No actions for this generator.
}
-//----------------------------------------------------------------------------
-bool cmScriptGenerator::GeneratesForConfig(const char* config)
+bool cmScriptGenerator::GeneratesForConfig(const std::string& config)
{
// If this is not a configuration-specific rule then we install.
- if(this->Configurations.empty())
- {
+ if (this->Configurations.empty()) {
return true;
- }
+ }
// This is a configuration-specific rule. Check if the config
// matches this rule.
- std::string config_upper = cmSystemTools::UpperCase(config?config:"");
- for(std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- if(cmSystemTools::UpperCase(*i) == config_upper)
- {
+ 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) {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
- Indent const& indent)
+ Indent indent)
{
- if(this->Configurations.empty())
- {
+ if (this->Configurations.empty()) {
// This rule is for all configurations.
this->GenerateScriptActions(os, indent);
- }
- else
- {
+ } else {
// Generate a per-configuration block.
std::string config_test = this->CreateConfigTest(this->Configurations);
- os << indent << "IF(" << config_test << ")\n";
+ os << indent << "if(" << config_test << ")\n";
this->GenerateScriptActions(os, indent.Next());
- os << indent << "ENDIF(" << config_test << ")\n";
- }
+ os << indent << "endif(" << config_test << ")\n";
+ }
}
-//----------------------------------------------------------------------------
void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os,
- Indent const& indent)
+ Indent indent)
{
- if(this->ConfigurationTypes->empty())
- {
+ if (this->ConfigurationTypes->empty()) {
// In a single-configuration generator there is only one action
// and it applies if the runtime-requested configuration is among
// the rule's allowed configurations. The configuration built in
// the tree does not matter for this decision but will be used to
// generate proper target file names into the code.
this->GenerateScriptActionsOnce(os, indent);
- }
- else
- {
+ } else {
// In a multi-configuration generator we produce a separate rule
// 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)
- {
+ 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))
- {
+ if (this->GeneratesForConfig(config)) {
// Generate a per-configuration block.
std::string config_test = this->CreateConfigTest(config);
- os << indent << (first? "IF(" : "ELSEIF(") << config_test << ")\n";
+ os << indent << (first ? "if(" : "elseif(") << config_test << ")\n";
this->GenerateScriptForConfig(os, config, indent.Next());
first = false;
- }
}
- if(!first)
- {
- if(this->NeedsScriptNoConfig())
- {
- os << indent << "ELSE()\n";
+ }
+ if (!first) {
+ if (this->NeedsScriptNoConfig()) {
+ os << indent << "else()\n";
this->GenerateScriptNoConfig(os, indent.Next());
- }
- os << indent << "ENDIF()\n";
}
+ os << indent << "endif()\n";
}
+ }
}
diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h
index 8b2ca335f..d0879c687 100644
--- a/Source/cmScriptGenerator.h
+++ b/Source/cmScriptGenerator.h
@@ -1,40 +1,41 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmScriptGenerator_h
#define cmScriptGenerator_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <ostream>
+#include <string>
+#include <vector>
class cmScriptGeneratorIndent
{
public:
- cmScriptGeneratorIndent(): Level(0) {}
- cmScriptGeneratorIndent(int level): Level(level) {}
+ cmScriptGeneratorIndent()
+ : Level(0)
+ {
+ }
+ cmScriptGeneratorIndent(int level)
+ : Level(level)
+ {
+ }
void Write(std::ostream& os) const
- {
- for(int i=0; i < this->Level; ++i)
- {
+ {
+ for (int i = 0; i < this->Level; ++i) {
os << " ";
- }
}
+ }
cmScriptGeneratorIndent Next(int step = 2) const
- {
+ {
return cmScriptGeneratorIndent(this->Level + step);
- }
+ }
+
private:
int Level;
};
inline std::ostream& operator<<(std::ostream& os,
- cmScriptGeneratorIndent const& indent)
+ cmScriptGeneratorIndent indent)
{
indent.Write(os);
return os;
@@ -46,32 +47,31 @@ inline std::ostream& operator<<(std::ostream& os,
*/
class cmScriptGenerator
{
+ CM_DISABLE_COPY(cmScriptGenerator)
+
public:
- cmScriptGenerator(const char* config_var,
+ cmScriptGenerator(const std::string& config_var,
std::vector<std::string> const& configurations);
virtual ~cmScriptGenerator();
- void Generate(std::ostream& os, const char* config,
+ void Generate(std::ostream& os, const std::string& config,
std::vector<std::string> const& configurationTypes);
- const std::vector<std::string>& GetConfigurations() const
- { return this->Configurations; }
-
protected:
typedef cmScriptGeneratorIndent Indent;
virtual void GenerateScript(std::ostream& os);
- virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
- virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+ virtual void GenerateScriptConfigs(std::ostream& os, Indent indent);
+ virtual void GenerateScriptActions(std::ostream& os, Indent indent);
virtual void GenerateScriptForConfig(std::ostream& os,
- const char* config,
- Indent const& indent);
- virtual void GenerateScriptNoConfig(std::ostream&, Indent const&) {}
+ const std::string& config,
+ Indent indent);
+ virtual void GenerateScriptNoConfig(std::ostream&, Indent) {}
virtual bool NeedsScriptNoConfig() const { return false; }
// Test if this generator does something for a given configuration.
- bool GeneratesForConfig(const char*);
+ bool GeneratesForConfig(const std::string&);
- std::string CreateConfigTest(const char* config);
+ std::string CreateConfigTest(const std::string& config);
std::string CreateConfigTest(std::vector<std::string> const& configs);
std::string CreateComponentTest(const char* component);
@@ -80,7 +80,7 @@ protected:
std::vector<std::string> const Configurations;
// Information used during generation.
- const char* ConfigurationName;
+ std::string ConfigurationName;
std::vector<std::string> const* ConfigurationTypes;
// True if the subclass needs to generate an explicit rule for each
@@ -89,8 +89,8 @@ protected:
bool ActionsPerConfig;
private:
- void GenerateScriptActionsOnce(std::ostream& os, Indent const& indent);
- void GenerateScriptActionsPerConfig(std::ostream& os, Indent const& indent);
+ void GenerateScriptActionsOnce(std::ostream& os, Indent indent);
+ void GenerateScriptActionsPerConfig(std::ostream& os, Indent indent);
};
#endif
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
new file mode 100644
index 000000000..0df6e0c06
--- /dev/null
+++ b/Source/cmSearchPath.cxx
@@ -0,0 +1,224 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSearchPath.h"
+
+#include <algorithm>
+#include <cassert>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmFindCommon.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
+ : FC(findCmd)
+{
+}
+
+cmSearchPath::~cmSearchPath()
+{
+}
+
+void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
+ std::vector<std::string>& outPaths,
+ bool clear) const
+{
+ 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);
+ }
+ }
+}
+
+void cmSearchPath::AddPath(const std::string& path)
+{
+ this->AddPathInternal(path);
+}
+
+void cmSearchPath::AddUserPath(const std::string& path)
+{
+ assert(this->FC != CM_NULLPTR);
+
+ std::vector<std::string> outPaths;
+
+ // 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 (this->FC->Makefile->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, outPaths);
+
+ // Executables can be either 32-bit or 64-bit, so expand using the
+ // alternative view.
+ if (expanded != path && this->FC->CMakePathName == "PROGRAM") {
+ expanded = path;
+ cmSystemTools::ExpandRegistryValues(expanded, other_view);
+ cmSystemTools::GlobDirs(expanded, outPaths);
+ }
+
+ // 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());
+ }
+}
+
+void cmSearchPath::AddCMakePath(const std::string& variable)
+{
+ assert(this->FC != CM_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);
+
+ for (std::vector<std::string>::const_iterator p = expanded.begin();
+ p != expanded.end(); ++p) {
+ this->AddPathInternal(*p,
+ this->FC->Makefile->GetCurrentSourceDirectory());
+ }
+ }
+}
+
+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);
+ }
+}
+
+void cmSearchPath::AddCMakePrefixPath(const std::string& variable)
+{
+ assert(this->FC != CM_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);
+
+ this->AddPrefixPaths(expanded,
+ this->FC->Makefile->GetCurrentSourceDirectory());
+ }
+}
+
+static std::string cmSearchPathStripBin(std::string const& s)
+{
+ // If the path is a PREFIX/bin case then add its parent instead.
+ if ((cmHasLiteralSuffix(s, "/bin")) || (cmHasLiteralSuffix(s, "/sbin"))) {
+ return cmSystemTools::GetFilenamePath(s);
+ }
+ return s;
+}
+
+void cmSearchPath::AddEnvPrefixPath(const std::string& variable, bool stripBin)
+{
+ std::vector<std::string> expanded;
+ cmSystemTools::GetPath(expanded, variable.c_str());
+ if (stripBin) {
+ std::transform(expanded.begin(), expanded.end(), expanded.begin(),
+ cmSearchPathStripBin);
+ }
+ this->AddPrefixPaths(expanded);
+}
+
+void cmSearchPath::AddSuffixes(const std::vector<std::string>& suffixes)
+{
+ std::vector<std::string> inPaths;
+ 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);
+
+ // 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() != '/') {
+ 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);
+ }
+
+ // And now the original w/o any suffix
+ this->Paths.push_back(*ip);
+ }
+}
+
+void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
+ const char* base)
+{
+ assert(this->FC != CM_NULLPTR);
+
+ // default for programs
+ std::string subdir = "bin";
+
+ if (this->FC->CMakePathName == "INCLUDE") {
+ subdir = "include";
+ } else if (this->FC->CMakePathName == "LIBRARY") {
+ subdir = "lib";
+ } else if (this->FC->CMakePathName == "FRAMEWORK") {
+ subdir = ""; // ? 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() != '/') {
+ dir += "/";
+ }
+ if (subdir == "include" || subdir == "lib") {
+ const char* arch =
+ this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
+ if (arch && *arch) {
+ this->AddPathInternal(dir + subdir + "/" + arch, base);
+ }
+ }
+ std::string add = dir + subdir;
+ if (add != "/") {
+ this->AddPathInternal(add, base);
+ }
+ if (subdir == "bin") {
+ this->AddPathInternal(dir + "sbin", base);
+ }
+ if (!subdir.empty() && *p != "/") {
+ this->AddPathInternal(*p, base);
+ }
+ }
+}
+
+void cmSearchPath::AddPathInternal(const std::string& path, const char* base)
+{
+ assert(this->FC != CM_NULLPTR);
+
+ std::string collapsed = cmSystemTools::CollapseFullPath(path, base);
+
+ if (collapsed.empty()) {
+ return;
+ }
+
+ // Insert the path if has not already been emitted.
+ if (this->FC->SearchPathsEmitted.insert(collapsed).second) {
+ this->Paths.push_back(collapsed);
+ }
+}
diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h
new file mode 100644
index 000000000..932022aa1
--- /dev/null
+++ b/Source/cmSearchPath.h
@@ -0,0 +1,52 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmSearchPath_h
+#define cmSearchPath_h
+
+#include "cmConfigure.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+class cmFindCommon;
+
+/** \class cmSearchPath
+ * \brief Container for encapsulating a set of search paths
+ *
+ * cmSearchPath is a container that encapsulates search path construction and
+ * management
+ */
+class cmSearchPath
+{
+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();
+
+ const std::vector<std::string>& GetPaths() const { return this->Paths; }
+
+ void ExtractWithout(const std::set<std::string>& ignore,
+ std::vector<std::string>& outPaths,
+ bool clear = false) const;
+
+ void AddPath(const std::string& path);
+ void AddUserPath(const std::string& path);
+ void AddCMakePath(const std::string& variable);
+ void AddEnvPath(const std::string& variable);
+ void AddCMakePrefixPath(const std::string& variable);
+ void AddEnvPrefixPath(const std::string& variable, bool stripBin = false);
+ void AddSuffixes(const std::vector<std::string>& suffixes);
+
+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);
+
+ cmFindCommon* FC;
+ std::vector<std::string> Paths;
+};
+
+#endif
diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx
index 6f620918b..7b222a041 100644
--- a/Source/cmSeparateArgumentsCommand.cxx
+++ b/Source/cmSeparateArgumentsCommand.cxx
@@ -1,109 +1,106 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSeparateArgumentsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <algorithm>
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSeparateArgumentsCommand.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmSeparateArgumentsCommand
-bool cmSeparateArgumentsCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSeparateArgumentsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.empty())
- {
+ if (args.empty()) {
this->SetError("must be given at least one argument.");
return false;
- }
+ }
std::string var;
std::string command;
- enum Mode { ModeOld, ModeUnix, ModeWindows };
+ enum Mode
+ {
+ ModeOld,
+ ModeUnix,
+ ModeWindows
+ };
Mode mode = ModeOld;
- enum Doing { DoingNone, DoingVariable, DoingMode, DoingCommand };
+ enum Doing
+ {
+ DoingNone,
+ DoingVariable,
+ DoingMode,
+ DoingCommand
+ };
Doing doing = DoingVariable;
- for(unsigned int i=0; i < args.size(); ++i)
- {
- if(doing == DoingVariable)
- {
+ for (unsigned int i = 0; i < args.size(); ++i) {
+ if (doing == DoingVariable) {
var = args[i];
doing = DoingMode;
- }
- else if(doing == DoingMode && args[i] == "UNIX_COMMAND")
- {
+ } else if (doing == DoingMode && args[i] == "NATIVE_COMMAND") {
+#ifdef _WIN32
+ mode = ModeWindows;
+#else
mode = ModeUnix;
+#endif
doing = DoingCommand;
- }
- else if(doing == DoingMode && args[i] == "WINDOWS_COMMAND")
- {
+ } else if (doing == DoingMode && args[i] == "UNIX_COMMAND") {
+ mode = ModeUnix;
+ doing = DoingCommand;
+ } else if (doing == DoingMode && args[i] == "WINDOWS_COMMAND") {
mode = ModeWindows;
doing = DoingCommand;
- }
- else if(doing == DoingCommand)
- {
+ } else if (doing == DoingCommand) {
command = args[i];
doing = DoingNone;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "given unknown argument " << args[i];
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
- if(mode == ModeOld)
- {
+ if (mode == ModeOld) {
// Original space-replacement version of command.
- if(const char* def = this->Makefile->GetDefinition(var.c_str()))
- {
+ if (const char* def = this->Makefile->GetDefinition(var)) {
std::string value = def;
- cmSystemTools::ReplaceString(value, " ", ";");
- this->Makefile->AddDefinition(var.c_str(), value.c_str());
- }
+ std::replace(value.begin(), value.end(), ' ', ';');
+ this->Makefile->AddDefinition(var, value.c_str());
}
- else
- {
+ } else {
// Parse the command line.
std::vector<std::string> vec;
- if(mode == ModeUnix)
- {
+ if (mode == ModeUnix) {
cmSystemTools::ParseUnixCommandLine(command.c_str(), vec);
- }
- else // if(mode == ModeWindows)
- {
+ } else // if(mode == ModeWindows)
+ {
cmSystemTools::ParseWindowsCommandLine(command.c_str(), vec);
- }
+ }
// 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::vector<std::string>::const_iterator vi = vec.begin();
+ vi != vec.end(); ++vi) {
// 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 (std::string::const_iterator si = vi->begin(); si != vi->end();
+ ++si) {
+ if (*si == ';') {
value += '\\';
- }
- value += *si;
}
+ value += *si;
}
- this->Makefile->AddDefinition(var.c_str(), value.c_str());
}
+ this->Makefile->AddDefinition(var, value.c_str());
+ }
return true;
}
diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h
index d62baf787..6bf8549cf 100644
--- a/Source/cmSeparateArgumentsCommand.h
+++ b/Source/cmSeparateArgumentsCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSeparateArgumentsCommand_h
#define cmSeparateArgumentsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmSeparateArgumentsCommand
* \brief separate_arguments command
*
@@ -25,68 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmSeparateArgumentsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSeparateArgumentsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "separate_arguments";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Parse space-separated arguments into a semicolon-separated list.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " separate_arguments(<var> <UNIX|WINDOWS>_COMMAND \"<args>\")\n"
- "Parses a unix- or windows-style command-line string \"<args>\" and "
- "stores a semicolon-separated list of the arguments in <var>. "
- "The entire command line must be given in one \"<args>\" argument."
- "\n"
- "The UNIX_COMMAND mode separates arguments by unquoted whitespace. "
- "It recognizes both single-quote and double-quote pairs. "
- "A backslash escapes the next literal character (\\\" is \"); "
- "there are no special escapes (\\n is just n)."
- "\n"
- "The WINDOWS_COMMAND mode parses a windows command-line using the "
- "same syntax the runtime library uses to construct argv at startup. "
- "It separates arguments by whitespace that is not double-quoted. "
- "Backslashes are literal unless they precede double-quotes. "
- "See the MSDN article \"Parsing C Command-Line Arguments\" for details."
- "\n"
- " separate_arguments(VARIABLE)\n"
- "Convert the value of VARIABLE to a semi-colon separated list. "
- "All spaces are replaced with ';'. This helps with generating "
- "command lines.";
- }
-
- cmTypeMacro(cmSeparateArgumentsCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
new file mode 100644
index 000000000..7fc6ed755
--- /dev/null
+++ b/Source/cmServer.cxx
@@ -0,0 +1,375 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmServer.h"
+
+#include "cmServerConnection.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>
+
+class cmServer::DebugInfo
+{
+public:
+ DebugInfo()
+ : StartTime(uv_hrtime())
+ {
+ }
+
+ bool PrintStatistics = false;
+
+ std::string OutputFile;
+ uint64_t StartTime;
+};
+
+cmServer::cmServer(cmServerConnection* conn, bool supportExperimental)
+ : Connection(conn)
+ , SupportExperimental(supportExperimental)
+{
+ this->Connection->SetServer(this);
+ // Register supported protocols:
+ this->RegisterProtocol(new cmServerProtocol1_0);
+}
+
+cmServer::~cmServer()
+{
+ if (!this->Protocol) { // Server was never fully started!
+ return;
+ }
+
+ for (cmServerProtocol* p : this->SupportedProtocols) {
+ delete p;
+ }
+
+ delete this->Connection;
+}
+
+void cmServer::PopOne()
+{
+ 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.");
+ return;
+ }
+
+ std::unique_ptr<DebugInfo> debug;
+ Json::Value debugValue = value["debug"];
+ if (!debugValue.isNull()) {
+ debug = std::make_unique<DebugInfo>();
+ debug->OutputFile = debugValue["dumpToFile"].asString();
+ debug->PrintStatistics = debugValue["showStats"].asBool();
+ }
+
+ const cmServerRequest request(this, value[kTYPE_KEY].asString(),
+ value[kCOOKIE_KEY].asString(), value);
+
+ if (request.Type == "") {
+ cmServerResponse response(request);
+ response.SetError("No type given in request.");
+ this->WriteResponse(response, nullptr);
+ return;
+ }
+
+ cmSystemTools::SetMessageCallback(reportMessage,
+ const_cast<cmServerRequest*>(&request));
+ if (this->Protocol) {
+ this->Protocol->CMakeInstance()->SetProgressCallback(
+ reportProgress, const_cast<cmServerRequest*>(&request));
+ this->WriteResponse(this->Protocol->Process(request), debug.get());
+ } else {
+ this->WriteResponse(this->SetProtocolVersion(request), debug.get());
+ }
+}
+
+void cmServer::RegisterProtocol(cmServerProtocol* protocol)
+{
+ if (protocol->IsExperimental() && !this->SupportExperimental) {
+ return;
+ }
+ auto version = protocol->ProtocolVersion();
+ assert(version.first >= 0);
+ assert(version.second >= 0);
+ auto it = std::find_if(this->SupportedProtocols.begin(),
+ this->SupportedProtocols.end(),
+ [version](cmServerProtocol* p) {
+ return p->ProtocolVersion() == version;
+ });
+ if (it == this->SupportedProtocols.end()) {
+ this->SupportedProtocols.push_back(protocol);
+ }
+}
+
+void cmServer::PrintHello() const
+{
+ Json::Value hello = Json::objectValue;
+ hello[kTYPE_KEY] = "hello";
+
+ Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] =
+ Json::arrayValue;
+
+ for (auto const& proto : this->SupportedProtocols) {
+ auto version = proto->ProtocolVersion();
+ Json::Value tmp = Json::objectValue;
+ tmp[kMAJOR_KEY] = version.first;
+ tmp[kMINOR_KEY] = version.second;
+ if (proto->IsExperimental()) {
+ tmp[kIS_EXPERIMENTAL_KEY] = true;
+ }
+ protocolVersions.append(tmp);
+ }
+
+ this->WriteJsonObject(hello, nullptr);
+}
+
+void cmServer::QueueRequest(const std::string& request)
+{
+ this->Queue.push_back(request);
+ this->PopOne();
+}
+
+void cmServer::reportProgress(const char* msg, float progress, void* data)
+{
+ const cmServerRequest* request = static_cast<const cmServerRequest*>(data);
+ assert(request);
+ if (progress < 0.0f || progress > 1.0f) {
+ request->ReportMessage(msg, "");
+ } else {
+ request->ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
+ }
+}
+
+void cmServer::reportMessage(const char* msg, const char* title,
+ bool& /* cancel */, void* data)
+{
+ 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);
+}
+
+cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
+{
+ if (request.Type != kHANDSHAKE_TYPE) {
+ return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE +
+ "\".");
+ }
+
+ Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY];
+ if (requestedProtocolVersion.isNull()) {
+ return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
+ "\" is required for \"" + kHANDSHAKE_TYPE +
+ "\".");
+ }
+
+ if (!requestedProtocolVersion.isObject()) {
+ return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
+ "\" must be a JSON object.");
+ }
+
+ Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY];
+ if (!majorValue.isInt()) {
+ return request.ReportError("\"" + kMAJOR_KEY +
+ "\" must be set and an integer.");
+ }
+
+ Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY];
+ if (!minorValue.isNull() && !minorValue.isInt()) {
+ return request.ReportError("\"" + kMINOR_KEY +
+ "\" must be unset or an integer.");
+ }
+
+ const int major = majorValue.asInt();
+ const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
+ if (major < 0) {
+ return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0.");
+ }
+ if (!minorValue.isNull() && minor < 0) {
+ return request.ReportError("\"" + kMINOR_KEY +
+ "\" must be >= 0 when set.");
+ }
+
+ this->Protocol =
+ this->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;
+ return request.ReportError("Failed to activate protocol version: " +
+ errorMessage);
+ }
+ return request.Reply(Json::objectValue);
+}
+
+bool cmServer::Serve(std::string* errorMessage)
+{
+ if (this->SupportedProtocols.empty()) {
+ *errorMessage =
+ "No protocol versions defined. Maybe you need --experimental?";
+ return false;
+ }
+ assert(!this->Protocol);
+
+ return Connection->ProcessEvents(errorMessage);
+}
+
+cmFileMonitor* cmServer::FileMonitor() const
+{
+ return Connection->FileMonitor();
+}
+
+void cmServer::WriteJsonObject(const Json::Value& jsonValue,
+ const DebugInfo* debug) const
+{
+ Json::FastWriter writer;
+
+ auto beforeJson = uv_hrtime();
+ std::string result = writer.write(jsonValue);
+
+ if (debug) {
+ Json::Value copy = jsonValue;
+ if (debug->PrintStatistics) {
+ Json::Value stats = Json::objectValue;
+ auto endTime = uv_hrtime();
+
+ stats["jsonSerialization"] = double(endTime - beforeJson) / 1000000.0;
+ stats["totalTime"] = double(endTime - debug->StartTime) / 1000000.0;
+ stats["size"] = static_cast<int>(result.size());
+ if (!debug->OutputFile.empty()) {
+ stats["dumpFile"] = debug->OutputFile;
+ }
+
+ copy["zzzDebug"] = stats;
+
+ result = writer.write(copy); // Update result to include debug info
+ }
+
+ if (!debug->OutputFile.empty()) {
+ cmsys::ofstream myfile(debug->OutputFile.c_str());
+ myfile << result;
+ }
+ }
+
+ Connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") +
+ result + kEND_MAGIC + std::string("\n"));
+}
+
+cmServerProtocol* cmServer::FindMatchingProtocol(
+ const std::vector<cmServerProtocol*>& protocols, int major, int minor)
+{
+ cmServerProtocol* bestMatch = nullptr;
+ for (auto protocol : protocols) {
+ auto version = protocol->ProtocolVersion();
+ if (major != version.first) {
+ continue;
+ }
+ if (minor == version.second) {
+ return protocol;
+ }
+ if (!bestMatch || bestMatch->ProtocolVersion().second < version.second) {
+ bestMatch = protocol;
+ }
+ }
+ return minor < 0 ? bestMatch : nullptr;
+}
+
+void cmServer::WriteProgress(const cmServerRequest& request, int min,
+ int current, int max,
+ const std::string& message) const
+{
+ assert(min <= current && current <= max);
+ assert(message.length() != 0);
+
+ Json::Value obj = Json::objectValue;
+ obj[kTYPE_KEY] = kPROGRESS_TYPE;
+ obj[kREPLY_TO_KEY] = request.Type;
+ obj[kCOOKIE_KEY] = request.Cookie;
+ obj[kPROGRESS_MESSAGE_KEY] = message;
+ obj[kPROGRESS_MINIMUM_KEY] = min;
+ obj[kPROGRESS_MAXIMUM_KEY] = max;
+ obj[kPROGRESS_CURRENT_KEY] = current;
+
+ this->WriteJsonObject(obj, nullptr);
+}
+
+void cmServer::WriteMessage(const cmServerRequest& request,
+ const std::string& message,
+ const std::string& title) const
+{
+ if (message.empty()) {
+ return;
+ }
+
+ Json::Value obj = Json::objectValue;
+ obj[kTYPE_KEY] = kMESSAGE_TYPE;
+ obj[kREPLY_TO_KEY] = request.Type;
+ obj[kCOOKIE_KEY] = request.Cookie;
+ obj[kMESSAGE_KEY] = message;
+ if (!title.empty()) {
+ obj[kTITLE_KEY] = title;
+ }
+
+ WriteJsonObject(obj, nullptr);
+}
+
+void cmServer::WriteParseError(const std::string& message) const
+{
+ Json::Value obj = Json::objectValue;
+ obj[kTYPE_KEY] = kERROR_TYPE;
+ obj[kERROR_MESSAGE_KEY] = message;
+ obj[kREPLY_TO_KEY] = "";
+ obj[kCOOKIE_KEY] = "";
+
+ this->WriteJsonObject(obj, nullptr);
+}
+
+void cmServer::WriteSignal(const std::string& name,
+ const Json::Value& data) const
+{
+ assert(data.isObject());
+ Json::Value obj = data;
+ obj[kTYPE_KEY] = kSIGNAL_TYPE;
+ obj[kREPLY_TO_KEY] = "";
+ obj[kCOOKIE_KEY] = "";
+ obj[kNAME_KEY] = name;
+
+ WriteJsonObject(obj, nullptr);
+}
+
+void cmServer::WriteResponse(const cmServerResponse& response,
+ const DebugInfo* debug) const
+{
+ assert(response.IsComplete());
+
+ Json::Value obj = response.Data();
+ obj[kCOOKIE_KEY] = response.Cookie;
+ obj[kTYPE_KEY] = response.IsError() ? kERROR_TYPE : kREPLY_TYPE;
+ obj[kREPLY_TO_KEY] = response.Type;
+ if (response.IsError()) {
+ obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
+ }
+
+ this->WriteJsonObject(obj, debug);
+}
diff --git a/Source/cmServer.h b/Source/cmServer.h
new file mode 100644
index 000000000..b8140504c
--- /dev/null
+++ b/Source/cmServer.h
@@ -0,0 +1,93 @@
+/* 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"
+
+#include "cm_jsoncpp_value.h"
+#include "cm_uv.h"
+
+#include <string>
+#include <vector>
+
+class cmFileMonitor;
+class cmServerConnection;
+class cmServerProtocol;
+class cmServerRequest;
+class cmServerResponse;
+
+class cmServer
+{
+ CM_DISABLE_COPY(cmServer)
+
+public:
+ class DebugInfo;
+
+ cmServer(cmServerConnection* conn, bool supportExperimental);
+ ~cmServer();
+
+ bool Serve(std::string* errorMessage);
+
+ cmFileMonitor* FileMonitor() const;
+
+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);
+
+ // Handle requests:
+ cmServerResponse SetProtocolVersion(const cmServerRequest& request);
+
+ void PrintHello() 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,
+ const DebugInfo* debug) const;
+ void WriteParseError(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;
+
+ 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
new file mode 100644
index 000000000..36312edf4
--- /dev/null
+++ b/Source/cmServerConnection.cxx
@@ -0,0 +1,377 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmServerConnection.h"
+
+#include "cmFileMonitor.h"
+#include "cmServer.h"
+#include "cmServerDictionary.h"
+
+#include <assert.h>
+#include <string.h>
+
+namespace {
+
+struct write_req_t
+{
+ 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)
+{
+ auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
+ if (nread >= 0) {
+ conn->ReadData(std::string(buf->base, buf->base + nread));
+ } else {
+ conn->TriggerShutdown();
+ }
+
+ delete[](buf->base);
+}
+
+void on_write(uv_write_t* req, int status)
+{
+ (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();
+}
+
+void on_new_connection(uv_stream_t* stream, int status)
+{
+ (void)(status);
+ auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
+ conn->Connect(stream);
+}
+
+void on_signal(uv_signal_t* signal, int signum)
+{
+ auto conn = reinterpret_cast<cmServerConnection*>(signal->data);
+ (void)(signum);
+ conn->TriggerShutdown();
+}
+
+void on_signal_close(uv_handle_t* handle)
+{
+ delete reinterpret_cast<uv_signal_t*>(handle);
+}
+
+void on_pipe_close(uv_handle_t* handle)
+{
+ delete reinterpret_cast<uv_pipe_t*>(handle);
+}
+
+void on_tty_close(uv_handle_t* handle)
+{
+ delete reinterpret_cast<uv_tty_t*>(handle);
+}
+
+} // namespace
+
+class LoopGuard
+{
+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);
+ }
+
+ ~LoopGuard()
+ {
+ if (!this->Connection->mLoop) {
+ return;
+ }
+
+ if (this->Connection->mFileMonitor) {
+ delete this->Connection->mFileMonitor;
+ }
+ uv_loop_close(this->Connection->mLoop);
+ this->Connection->mLoop = nullptr;
+ }
+
+private:
+ cmServerConnection* Connection;
+};
+
+cmServerConnection::cmServerConnection()
+{
+}
+
+cmServerConnection::~cmServerConnection()
+{
+}
+
+void cmServerConnection::SetServer(cmServer* s)
+{
+ this->Server = s;
+}
+
+bool cmServerConnection::ProcessEvents(std::string* errorMessage)
+{
+ 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;
+}
+
+void cmServerConnection::ReadData(const std::string& data)
+{
+ this->RawReadBuffer += data;
+
+ for (;;) {
+ auto needle = this->RawReadBuffer.find('\n');
+
+ if (needle == std::string::npos) {
+ return;
+ }
+ std::string line = this->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);
+ if (line == kSTART_MAGIC) {
+ this->RequestBuffer.clear();
+ continue;
+ }
+ if (line == kEND_MAGIC) {
+ this->Server->QueueRequest(this->RequestBuffer);
+ this->RequestBuffer.clear();
+ } else {
+ this->RequestBuffer += line;
+ this->RequestBuffer += "\n";
+ }
+ }
+}
+
+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;
+ }
+
+ 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
new file mode 100644
index 000000000..b96bf3c54
--- /dev/null
+++ b/Source/cmServerConnection.h
@@ -0,0 +1,95 @@
+/* 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"
+
+#include "cm_uv.h"
+
+#include <string>
+
+class cmFileMonitor;
+class cmServer;
+
+class cmServerConnection
+{
+ CM_DISABLE_COPY(cmServerConnection)
+
+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();
+
+ 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;
+
+ void SendGreetings();
+
+ uv_loop_t* Loop() const { return mLoop; }
+
+protected:
+ std::string RawReadBuffer;
+ std::string RequestBuffer;
+
+ uv_stream_t* ReadStream = nullptr;
+ uv_stream_t* WriteStream = nullptr;
+
+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;
+};
+
+class cmServerStdIoConnection : public cmServerConnection
+{
+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
+{
+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
new file mode 100644
index 000000000..e6a7ae6ca
--- /dev/null
+++ b/Source/cmServerDictionary.h
@@ -0,0 +1,96 @@
+/* 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 kDIRTY_SIGNAL = "dirty";
+static const std::string kFILE_CHANGE_SIGNAL = "fileChange";
+
+static const std::string kCACHE_TYPE = "cache";
+static const std::string kCMAKE_INPUTS_TYPE = "cmakeInputs";
+static const std::string kCODE_MODEL_TYPE = "codemodel";
+static const std::string kCOMPUTE_TYPE = "compute";
+static const std::string kCONFIGURE_TYPE = "configure";
+static const std::string kERROR_TYPE = "error";
+static const std::string kFILESYSTEM_WATCHERS_TYPE = "fileSystemWatchers";
+static const std::string kGLOBAL_SETTINGS_TYPE = "globalSettings";
+static const std::string kHANDSHAKE_TYPE = "handshake";
+static const std::string kMESSAGE_TYPE = "message";
+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 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";
+static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
+static const std::string kWATCHED_FILES_KEY = "watchedFiles";
+
+static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==[";
+static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]";
+
+static const std::string kRENAME_PROPERTY_VALUE = "rename";
+static const std::string kCHANGE_PROPERTY_VALUE = "change";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
new file mode 100644
index 000000000..c5b7f6064
--- /dev/null
+++ b/Source/cmServerProtocol.cxx
@@ -0,0 +1,1181 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmServerProtocol.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 "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) {
+ 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)
+ , m_Server(server)
+{
+}
+
+void cmServerRequest::ReportProgress(int min, int current, int max,
+ const std::string& message) const
+{
+ this->m_Server->WriteProgress(*this, min, current, max, message);
+}
+
+void cmServerRequest::ReportMessage(const std::string& message,
+ const std::string& title) const
+{
+ m_Server->WriteMessage(*this, message, title);
+}
+
+cmServerResponse cmServerRequest::Reply(const Json::Value& data) const
+{
+ cmServerResponse response(*this);
+ response.SetData(data);
+ return response;
+}
+
+cmServerResponse cmServerRequest::ReportError(const std::string& message) const
+{
+ cmServerResponse response(*this);
+ response.SetError(message);
+ return response;
+}
+
+cmServerResponse::cmServerResponse(const cmServerRequest& request)
+ : Type(request.Type)
+ , Cookie(request.Cookie)
+{
+}
+
+void cmServerResponse::SetData(const Json::Value& data)
+{
+ assert(this->m_Payload == PAYLOAD_UNKNOWN);
+ if (!data[kCOOKIE_KEY].isNull() || !data[kTYPE_KEY].isNull()) {
+ this->SetError("Response contains cookie or type field.");
+ return;
+ }
+ this->m_Payload = PAYLOAD_DATA;
+ this->m_Data = data;
+}
+
+void cmServerResponse::SetError(const std::string& message)
+{
+ assert(this->m_Payload == PAYLOAD_UNKNOWN);
+ this->m_Payload = PAYLOAD_ERROR;
+ this->m_ErrorMessage = message;
+}
+
+bool cmServerResponse::IsComplete() const
+{
+ return this->m_Payload != PAYLOAD_UNKNOWN;
+}
+
+bool cmServerResponse::IsError() const
+{
+ assert(this->m_Payload != PAYLOAD_UNKNOWN);
+ return this->m_Payload == PAYLOAD_ERROR;
+}
+
+std::string cmServerResponse::ErrorMessage() const
+{
+ if (this->m_Payload == PAYLOAD_ERROR) {
+ return this->m_ErrorMessage;
+ }
+ return std::string();
+}
+
+Json::Value cmServerResponse::Data() const
+{
+ assert(this->m_Payload != PAYLOAD_UNKNOWN);
+ return this->m_Data;
+}
+
+bool cmServerProtocol::Activate(cmServer* server,
+ const cmServerRequest& request,
+ std::string* errorMessage)
+{
+ assert(server);
+ this->m_Server = server;
+ this->m_CMakeInstance = std::make_unique<cmake>(cmake::RoleProject);
+ const bool result = this->DoActivate(request, errorMessage);
+ if (!result) {
+ this->m_CMakeInstance = CM_NULLPTR;
+ }
+ return result;
+}
+
+cmFileMonitor* cmServerProtocol::FileMonitor() const
+{
+ return this->m_Server ? this->m_Server->FileMonitor() : nullptr;
+}
+
+void cmServerProtocol::SendSignal(const std::string& name,
+ const Json::Value& data) const
+{
+ if (this->m_Server) {
+ this->m_Server->WriteSignal(name, data);
+ }
+}
+
+cmake* cmServerProtocol::CMakeInstance() const
+{
+ return this->m_CMakeInstance.get();
+}
+
+bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
+ std::string* /*errorMessage*/)
+{
+ return true;
+}
+
+std::pair<int, int> cmServerProtocol1_0::ProtocolVersion() const
+{
+ return std::make_pair(1, 0);
+}
+
+static void setErrorMessage(std::string* errorMessage, const std::string& text)
+{
+ if (errorMessage) {
+ *errorMessage = text;
+ }
+}
+
+static bool testHomeDirectory(cmState* state, std::string& value,
+ std::string* errorMessage)
+{
+ const std::string cachedValue =
+ std::string(state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"));
+ const std::string suffix = "/CMakeLists.txt";
+ const std::string cachedValueCML = cachedValue + suffix;
+ const std::string valueCML = value + suffix;
+ if (!cmSystemTools::SameFile(valueCML, cachedValueCML)) {
+ setErrorMessage(errorMessage,
+ std::string("\"CMAKE_HOME_DIRECTORY\" is set but "
+ "incompatible with configured "
+ "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)
+{
+ 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 +
+ "\" 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)
+{
+ std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString();
+ const 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();
+
+ if (buildDirectory.empty()) {
+ setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY +
+ "\" is missing.");
+ return false;
+ }
+
+ cmake* cm = CMakeInstance();
+ if (cmSystemTools::PathExists(buildDirectory)) {
+ if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
+ setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY +
+ "\" exists but is not a directory.");
+ return false;
+ }
+
+ const std::string cachePath = cm->FindCacheFile(buildDirectory);
+ if (cm->LoadCache(cachePath)) {
+ cmState* state = cm->GetState();
+
+ // Check generator:
+ if (!testValue(state, "CMAKE_GENERATOR", generator, "generator",
+ errorMessage)) {
+ return false;
+ }
+
+ // check extra generator:
+ if (!testValue(state, "CMAKE_EXTRA_GENERATOR", extraGenerator,
+ "extra generator", errorMessage)) {
+ return false;
+ }
+
+ // check sourcedir:
+ if (!testHomeDirectory(state, sourceDirectory, errorMessage)) {
+ return false;
+ }
+
+ // check toolset:
+ if (!testValue(state, "CMAKE_GENERATOR_TOOLSET", toolset, "toolset",
+ errorMessage)) {
+ return false;
+ }
+
+ // check platform:
+ if (!testValue(state, "CMAKE_GENERATOR_PLATFORM", platform, "platform",
+ errorMessage)) {
+ return false;
+ }
+ }
+ }
+
+ if (sourceDirectory.empty()) {
+ setErrorMessage(errorMessage, std::string("\"") + kSOURCE_DIRECTORY_KEY +
+ "\" is unset but required.");
+ return false;
+ }
+ if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
+ setErrorMessage(errorMessage, std::string("\"") + kSOURCE_DIRECTORY_KEY +
+ "\" is not a directory.");
+ return false;
+ }
+ if (generator.empty()) {
+ setErrorMessage(errorMessage, std::string("\"") + kGENERATOR_KEY +
+ "\" is unset but required.");
+ return false;
+ }
+
+ std::vector<cmake::GeneratorInfo> generators;
+ cm->GetRegisteredGenerators(generators);
+ auto baseIt = std::find_if(generators.begin(), generators.end(),
+ [&generator](const cmake::GeneratorInfo& info) {
+ return info.name == generator;
+ });
+ if (baseIt == generators.end()) {
+ setErrorMessage(errorMessage, std::string("Generator \"") + generator +
+ "\" not supported.");
+ return false;
+ }
+ auto extraIt = std::find_if(
+ generators.begin(), generators.end(),
+ [&generator, &extraGenerator](const cmake::GeneratorInfo& info) {
+ return info.baseName == generator && info.extraName == extraGenerator;
+ });
+ if (extraIt == generators.end()) {
+ setErrorMessage(errorMessage,
+ std::string("The combination of generator \"" + generator +
+ "\" and extra generator \"" + extraGenerator +
+ "\" is not supported."));
+ return false;
+ }
+ if (!extraIt->supportsToolset && !toolset.empty()) {
+ setErrorMessage(errorMessage,
+ std::string("Toolset was provided but is not supported by "
+ "the requested generator."));
+ return false;
+ }
+ if (!extraIt->supportsPlatform && !platform.empty()) {
+ setErrorMessage(errorMessage,
+ std::string("Platform was provided but is not supported "
+ "by the requested generator."));
+ return false;
+ }
+
+ this->GeneratorInfo =
+ GeneratorInformation(generator, extraGenerator, toolset, platform,
+ sourceDirectory, buildDirectory);
+
+ this->m_State = STATE_ACTIVE;
+ return true;
+}
+
+void cmServerProtocol1_0::HandleCMakeFileChanges(const std::string& path,
+ int event, int status)
+{
+ assert(status == 0);
+ static_cast<void>(status);
+
+ if (!m_isDirty) {
+ m_isDirty = true;
+ SendSignal(kDIRTY_SIGNAL, Json::objectValue);
+ }
+ Json::Value obj = Json::objectValue;
+ obj[kPATH_KEY] = path;
+ Json::Value properties = Json::arrayValue;
+ if (event & UV_RENAME) {
+ properties.append(kRENAME_PROPERTY_VALUE);
+ }
+ if (event & UV_CHANGE) {
+ properties.append(kCHANGE_PROPERTY_VALUE);
+ }
+
+ obj[kPROPERTIES_KEY] = properties;
+ SendSignal(kFILE_CHANGE_SIGNAL, obj);
+}
+
+const cmServerResponse cmServerProtocol1_0::Process(
+ const cmServerRequest& request)
+{
+ assert(this->m_State >= STATE_ACTIVE);
+
+ if (request.Type == kCACHE_TYPE) {
+ return this->ProcessCache(request);
+ }
+ if (request.Type == kCMAKE_INPUTS_TYPE) {
+ return this->ProcessCMakeInputs(request);
+ }
+ if (request.Type == kCODE_MODEL_TYPE) {
+ return this->ProcessCodeModel(request);
+ }
+ if (request.Type == kCOMPUTE_TYPE) {
+ return this->ProcessCompute(request);
+ }
+ if (request.Type == kCONFIGURE_TYPE) {
+ return this->ProcessConfigure(request);
+ }
+ if (request.Type == kFILESYSTEM_WATCHERS_TYPE) {
+ return this->ProcessFileSystemWatchers(request);
+ }
+ if (request.Type == kGLOBAL_SETTINGS_TYPE) {
+ return this->ProcessGlobalSettings(request);
+ }
+ if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {
+ return this->ProcessSetGlobalSettings(request);
+ }
+
+ return request.ReportError("Unknown command!");
+}
+
+bool cmServerProtocol1_0::IsExperimental() const
+{
+ return true;
+}
+
+cmServerResponse cmServerProtocol1_0::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;
+
+ std::vector<std::string> allKeys = state->GetCacheEntryKeys();
+
+ Json::Value list = Json::arrayValue;
+ std::vector<std::string> keys = toStringList(request.Data[kKEYS_KEY]);
+ if (keys.empty()) {
+ keys = allKeys;
+ } else {
+ for (const auto& i : keys) {
+ if (std::find(allKeys.begin(), allKeys.end(), i) == allKeys.end()) {
+ return request.ReportError("Key \"" + i + "\" not found in cache.");
+ }
+ }
+ }
+ std::sort(keys.begin(), keys.end());
+ for (const auto& key : keys) {
+ Json::Value entry = Json::objectValue;
+ entry[kKEY_KEY] = key;
+ entry[kTYPE_KEY] =
+ cmState::CacheEntryTypeToString(state->GetCacheEntryType(key));
+ entry[kVALUE_KEY] = state->GetCacheEntryValue(key);
+
+ Json::Value props = Json::objectValue;
+ bool haveProperties = false;
+ for (const auto& prop : state->GetCacheEntryPropertyList(key)) {
+ haveProperties = true;
+ props[prop] = state->GetCacheEntryProperty(key, prop);
+ }
+ if (haveProperties) {
+ entry[kPROPERTIES_KEY] = props;
+ }
+
+ list.append(entry);
+ }
+
+ result[kCACHE_KEY] = list;
+ return request.Reply(result);
+}
+
+cmServerResponse cmServerProtocol1_0::ProcessCMakeInputs(
+ const cmServerRequest& request)
+{
+ if (this->m_State < STATE_CONFIGURED) {
+ return request.ReportError("This instance was not yet configured.");
+ }
+
+ 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();
+
+ 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;
+
+ 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(
+ 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);
+}
+
+cmServerResponse cmServerProtocol1_0::ProcessCompute(
+ const cmServerRequest& request)
+{
+ if (this->m_State > STATE_CONFIGURED) {
+ return request.ReportError("This build system was already generated.");
+ }
+ if (this->m_State < STATE_CONFIGURED) {
+ return request.ReportError("This project was not configured yet.");
+ }
+
+ cmake* cm = this->CMakeInstance();
+ int ret = cm->Generate();
+
+ if (ret < 0) {
+ return request.ReportError("Failed to compute build system.");
+ }
+ m_State = STATE_COMPUTED;
+ return request.Reply(Json::Value());
+}
+
+cmServerResponse cmServerProtocol1_0::ProcessConfigure(
+ const cmServerRequest& request)
+{
+ if (this->m_State == STATE_INACTIVE) {
+ return request.ReportError("This instance is inactive.");
+ }
+
+ FileMonitor()->StopMonitoring();
+
+ std::string errorMessage;
+ cmake* cm = this->CMakeInstance();
+ this->GeneratorInfo.SetupGenerator(cm, &errorMessage);
+ if (!errorMessage.empty()) {
+ return request.ReportError(errorMessage);
+ }
+
+ // Make sure the types of cacheArguments matches (if given):
+ std::vector<std::string> cacheArgs = { "unused" };
+ bool cacheArgumentsError = false;
+ const Json::Value passedArgs = request.Data[kCACHE_ARGUMENTS_KEY];
+ if (!passedArgs.isNull()) {
+ if (passedArgs.isString()) {
+ cacheArgs.push_back(passedArgs.asString());
+ } else if (passedArgs.isArray()) {
+ for (auto i = passedArgs.begin(); i != passedArgs.end(); ++i) {
+ if (!i->isString()) {
+ cacheArgumentsError = true;
+ break;
+ }
+ cacheArgs.push_back(i->asString());
+ }
+ } else {
+ cacheArgumentsError = true;
+ }
+ }
+ if (cacheArgumentsError) {
+ request.ReportError(
+ "cacheArguments must be unset, a string or an array of strings.");
+ }
+
+ std::string sourceDir = cm->GetHomeDirectory();
+ const std::string buildDir = cm->GetHomeOutputDirectory();
+
+ cmGlobalGenerator* gg = cm->GetGlobalGenerator();
+
+ if (buildDir.empty()) {
+ return request.ReportError("No build directory set via Handshake.");
+ }
+
+ if (cm->LoadCache(buildDir)) {
+ // build directory has been set up before
+ const char* 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);
+ cm->SetHomeDirectory(sourceDir);
+ }
+
+ const char* cachedGenerator =
+ cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR");
+ if (cachedGenerator) {
+ if (gg && gg->GetName() != cachedGenerator) {
+ return request.ReportError("Configured generator does not match with "
+ "CMAKE_GENERATOR found in cache.");
+ }
+ }
+ } else {
+ // build directory has not been set up before
+ if (sourceDir.empty()) {
+ return request.ReportError("No sourceDirectory set via "
+ "setGlobalSettings and no cache found in "
+ "buildDirectory.");
+ }
+ }
+
+ cmSystemTools::ResetErrorOccuredFlag(); // Reset error state
+
+ if (cm->AddCMakePaths() != 1) {
+ return request.ReportError("Failed to set CMake paths.");
+ }
+
+ if (!cm->SetCacheArgs(cacheArgs)) {
+ return request.ReportError("cacheArguments could not be set.");
+ }
+
+ int ret = cm->Configure();
+ if (ret < 0) {
+ return request.ReportError("Configuration failed.");
+ }
+
+ std::vector<std::string> toWatchList;
+ getCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList, nullptr);
+
+ FileMonitor()->MonitorPaths(toWatchList,
+ [this](const std::string& p, int e, int s) {
+ this->HandleCMakeFileChanges(p, e, s);
+ });
+
+ m_State = STATE_CONFIGURED;
+ m_isDirty = false;
+ return request.Reply(Json::Value());
+}
+
+cmServerResponse cmServerProtocol1_0::ProcessGlobalSettings(
+ const cmServerRequest& request)
+{
+ cmake* cm = this->CMakeInstance();
+ Json::Value obj = Json::objectValue;
+
+ // Capabilities information:
+ obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson(true);
+
+ obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();
+ obj[kTRACE_KEY] = cm->GetTrace();
+ obj[kTRACE_EXPAND_KEY] = cm->GetTraceExpand();
+ obj[kWARN_UNINITIALIZED_KEY] = cm->GetWarnUninitialized();
+ obj[kWARN_UNUSED_KEY] = cm->GetWarnUnused();
+ obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli();
+ obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars();
+
+ obj[kSOURCE_DIRECTORY_KEY] = this->GeneratorInfo.SourceDirectory;
+ obj[kBUILD_DIRECTORY_KEY] = this->GeneratorInfo.BuildDirectory;
+
+ // Currently used generator:
+ obj[kGENERATOR_KEY] = this->GeneratorInfo.GeneratorName;
+ obj[kEXTRA_GENERATOR_KEY] = this->GeneratorInfo.ExtraGeneratorName;
+
+ return request.Reply(obj);
+}
+
+static void setBool(const cmServerRequest& request, const std::string& key,
+ std::function<void(bool)> const& setter)
+{
+ if (request.Data[key].isNull()) {
+ return;
+ }
+ setter(request.Data[key].asBool());
+}
+
+cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings(
+ const cmServerRequest& request)
+{
+ const std::vector<std::string> boolValues = {
+ kDEBUG_OUTPUT_KEY, kTRACE_KEY, kTRACE_EXPAND_KEY,
+ kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY,
+ kCHECK_SYSTEM_VARS_KEY
+ };
+ for (const auto& i : boolValues) {
+ if (!request.Data[i].isNull() && !request.Data[i].isBool()) {
+ return request.ReportError("\"" + i +
+ "\" must be unset or a bool value.");
+ }
+ }
+
+ cmake* cm = this->CMakeInstance();
+
+ setBool(request, kDEBUG_OUTPUT_KEY,
+ [cm](bool e) { cm->SetDebugOutputOn(e); });
+ setBool(request, kTRACE_KEY, [cm](bool e) { cm->SetTrace(e); });
+ setBool(request, kTRACE_EXPAND_KEY, [cm](bool e) { cm->SetTraceExpand(e); });
+ setBool(request, kWARN_UNINITIALIZED_KEY,
+ [cm](bool e) { cm->SetWarnUninitialized(e); });
+ setBool(request, kWARN_UNUSED_KEY, [cm](bool e) { cm->SetWarnUnused(e); });
+ setBool(request, kWARN_UNUSED_CLI_KEY,
+ [cm](bool e) { cm->SetWarnUnusedCli(e); });
+ setBool(request, kCHECK_SYSTEM_VARS_KEY,
+ [cm](bool e) { cm->SetCheckSystemVars(e); });
+
+ return request.Reply(Json::Value());
+}
+
+cmServerResponse cmServerProtocol1_0::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()) {
+ files.append(f);
+ }
+ Json::Value directories = Json::arrayValue;
+ for (const auto& d : fm->WatchedDirectories()) {
+ directories.append(d);
+ }
+ result[kWATCHED_FILES_KEY] = files;
+ result[kWATCHED_DIRECTORIES_KEY] = directories;
+
+ 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)
+{
+}
+
+void cmServerProtocol1_0::GeneratorInformation::SetupGenerator(
+ cmake* cm, std::string* errorMessage)
+{
+ const std::string fullGeneratorName =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ GeneratorName, ExtraGeneratorName);
+
+ cm->SetHomeDirectory(SourceDirectory);
+ cm->SetHomeOutputDirectory(BuildDirectory);
+
+ cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName);
+ if (!gg) {
+ setErrorMessage(
+ errorMessage,
+ std::string("Could not set up the requested combination of \"") +
+ kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\"");
+ return;
+ }
+
+ cm->SetGlobalGenerator(gg);
+
+ cm->SetGeneratorToolset(Toolset);
+ cm->SetGeneratorPlatform(Platform);
+}
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
new file mode 100644
index 000000000..83b3d58de
--- /dev/null
+++ b/Source/cmServerProtocol.h
@@ -0,0 +1,158 @@
+/* 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"
+
+#include "cm_jsoncpp_value.h"
+#include "cmake.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+class cmFileMonitor;
+class cmServer;
+class cmServerRequest;
+
+class cmServerResponse
+{
+public:
+ explicit cmServerResponse(const cmServerRequest& request);
+
+ void SetData(const Json::Value& data);
+ void SetError(const std::string& message);
+
+ bool IsComplete() const;
+ bool IsError() const;
+ std::string ErrorMessage() const;
+ Json::Value Data() const;
+
+ const std::string Type;
+ const std::string Cookie;
+
+private:
+ enum PayLoad
+ {
+ PAYLOAD_UNKNOWN,
+ PAYLOAD_ERROR,
+ PAYLOAD_DATA
+ };
+ PayLoad m_Payload = PAYLOAD_UNKNOWN;
+ std::string m_ErrorMessage;
+ Json::Value m_Data;
+};
+
+class cmServerRequest
+{
+public:
+ cmServerResponse Reply(const Json::Value& data) const;
+ cmServerResponse ReportError(const std::string& message) const;
+
+ const std::string Type;
+ const std::string Cookie;
+ const Json::Value Data;
+
+private:
+ cmServerRequest(cmServer* server, const std::string& t, const std::string& c,
+ const Json::Value& d);
+
+ void ReportProgress(int min, int current, int max,
+ const std::string& message) const;
+ void ReportMessage(const std::string& message,
+ const std::string& title) const;
+
+ cmServer* m_Server;
+
+ friend class cmServer;
+};
+
+class cmServerProtocol
+{
+ CM_DISABLE_COPY(cmServerProtocol)
+
+public:
+ cmServerProtocol() = default;
+ virtual ~cmServerProtocol() = default;
+
+ virtual std::pair<int, int> ProtocolVersion() const = 0;
+ virtual bool IsExperimental() const = 0;
+ virtual const cmServerResponse Process(const cmServerRequest& request) = 0;
+
+ bool Activate(cmServer* server, const cmServerRequest& request,
+ std::string* errorMessage);
+
+ cmFileMonitor* FileMonitor() const;
+ void SendSignal(const std::string& name, const Json::Value& data) const;
+
+protected:
+ cmake* CMakeInstance() const;
+ // Implement protocol specific activation tasks here. Called from Activate().
+ virtual bool DoActivate(const cmServerRequest& request,
+ std::string* errorMessage);
+
+private:
+ std::unique_ptr<cmake> m_CMakeInstance;
+ cmServer* m_Server = nullptr; // not owned!
+
+ friend class cmServer;
+};
+
+class cmServerProtocol1_0 : public cmServerProtocol
+{
+public:
+ std::pair<int, int> ProtocolVersion() const override;
+ bool IsExperimental() const override;
+ const cmServerResponse Process(const cmServerRequest& request) override;
+
+private:
+ bool DoActivate(const cmServerRequest& request,
+ std::string* errorMessage) override;
+
+ void HandleCMakeFileChanges(const std::string& path, int event, int status);
+
+ // Handle requests:
+ cmServerResponse ProcessCache(const cmServerRequest& request);
+ cmServerResponse ProcessCMakeInputs(const cmServerRequest& request);
+ cmServerResponse ProcessCodeModel(const cmServerRequest& request);
+ cmServerResponse ProcessCompute(const cmServerRequest& request);
+ cmServerResponse ProcessConfigure(const cmServerRequest& request);
+ cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
+ cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
+ cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
+
+ enum State
+ {
+ STATE_INACTIVE,
+ STATE_ACTIVE,
+ STATE_CONFIGURED,
+ STATE_COMPUTED
+ };
+ State m_State = STATE_INACTIVE;
+
+ bool m_isDirty = false;
+
+ struct GeneratorInformation
+ {
+ 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);
+
+ void SetupGenerator(cmake* cm, std::string* errorMessage);
+
+ std::string GeneratorName;
+ std::string ExtraGeneratorName;
+ std::string Toolset;
+ std::string Platform;
+
+ std::string SourceDirectory;
+ std::string BuildDirectory;
+ };
+
+ GeneratorInformation GeneratorInfo;
+};
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 20f38be10..820e7f695 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -1,177 +1,148 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSetCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSetCommand.h"
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmSetCommand
-bool cmSetCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->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 (!strncmp(variable,"ENV{",4) && strlen(variable) > 5)
- {
+ if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) {
// what is the variable name
- char *varName = new char [strlen(variable)];
- strncpy(varName,variable+4,strlen(variable)-5);
- varName[strlen(variable)-5] = '\0';
+ char* varName = new char[strlen(variable)];
+ strncpy(varName, variable + 4, strlen(variable) - 5);
+ varName[strlen(variable) - 5] = '\0';
std::string putEnvArg = varName;
putEnvArg += "=";
// what is the current value if any
- const char *currValue = getenv(varName);
- delete [] varName;
+ 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].size())
- {
+ if (args.size() > 1 && !args[1].empty()) {
// but only if it is different from current value
- if (!currValue || strcmp(currValue,args[1].c_str()))
- {
+ if (!currValueSet || currValue != args[1]) {
putEnvArg += args[1];
- cmSystemTools::PutEnv(putEnvArg.c_str());
- }
- return true;
+ cmSystemTools::PutEnv(putEnvArg);
}
+ return true;
+ }
- // if it will be cleared, then clear it if it isn;t already clear
- if (currValue)
- {
- cmSystemTools::PutEnv(putEnvArg.c_str());
- }
- return true;
+ // if it will be cleared, then clear it if it isn't already clear
+ if (currValueSet) {
+ cmSystemTools::PutEnv(putEnvArg);
}
+ return true;
+ }
// SET (VAR) // Removes the definition of VAR.
- if (args.size() == 1)
- {
- this->Makefile->RemoveDefinition(args[0].c_str());
+ if (args.size() == 1) {
+ this->Makefile->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);
+ return true;
+ }
// here are the remaining options
// SET (VAR value )
+ // SET (VAR value PARENT_SCOPE)
// SET (VAR CACHE TYPE "doc String" [FORCE])
// SET (VAR value CACHE TYPE "doc string" [FORCE])
std::string value; // optional
bool cache = false; // optional
bool force = false; // optional
bool parentScope = false;
- cmCacheManager::CacheEntryType type
- = cmCacheManager::STRING; // required if cache
- const char* docstring = 0; // required if cache
+ cmStateEnums::CacheEntryType type =
+ cmStateEnums::STRING; // required if cache
+ const char* docstring = CM_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[args.size() - 1] == "PARENT_SCOPE") {
parentScope = true;
ignoreLastArgs++;
- }
- else
- {
+ } else {
// look for FORCE argument
- if (args.size() > 4 && args[args.size()-1] == "FORCE")
- {
+ if (args.size() > 4 && args[args.size() - 1] == "FORCE") {
force = true;
ignoreLastArgs++;
- }
+ }
// check for cache signature
- if (args.size() > 3 && args[args.size() - 3 - (force ? 1 : 0)] == "CACHE")
- {
+ if (args.size() > 3 &&
+ args[args.size() - 3 - (force ? 1 : 0)] == "CACHE") {
cache = true;
- ignoreLastArgs+=3;
- }
+ ignoreLastArgs += 3;
}
+ }
// collect any values into a single semi-colon separated value list
- if(static_cast<unsigned short>(args.size()) >
- static_cast<unsigned short>(1 + ignoreLastArgs))
- {
- value = args[1];
- size_t endPos = args.size() - ignoreLastArgs;
- for(size_t i = 2; i < endPos; ++i)
- {
- value += ";";
- value += args[i];
- }
- }
-
- if (parentScope)
- {
- if (value.empty())
- {
- this->Makefile->RaiseScope(variable, 0);
- }
- else
- {
- this->Makefile->RaiseScope(variable, value.c_str());
- }
- return true;
- }
+ value = cmJoin(cmMakeRange(args).advance(1).retreat(ignoreLastArgs), ";");
+ if (parentScope) {
+ this->Makefile->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") ||
(args.size() > 1 && args[args.size() - 2] == "CACHE") ||
- (force && !cache))
- {
+ (force && !cache)) {
this->SetError("given invalid arguments for CACHE mode.");
return false;
- }
+ }
- if(cache)
- {
+ if (cache) {
std::string::size_type cacheStart = args.size() - 3 - (force ? 1 : 0);
- type = cmCacheManager::StringToType(args[cacheStart+1].c_str());
- docstring = args[cacheStart+2].c_str();
- }
+ type = cmState::StringToCacheEntryType(args[cacheStart + 1].c_str());
+ docstring = args[cacheStart + 2].c_str();
+ }
// see if this is already in the cache
- cmCacheManager::CacheIterator it =
- this->Makefile->GetCacheManager()->GetCacheIterator(variable);
- if(!it.IsAtEnd() && (it.GetType() != cmCacheManager::UNINITIALIZED))
- {
+ cmState* state = this->Makefile->GetState();
+ const char* existingValue = state->GetCacheEntryValue(variable);
+ if (existingValue &&
+ (state->GetCacheEntryType(variable) != cmStateEnums::UNINITIALIZED)) {
// if the set is trying to CACHE the value but the value
// is already in the cache and the type is not internal
// then leave now without setting any definitions in the cache
// or the makefile
- if(cache && type != cmCacheManager::INTERNAL && !force)
- {
+ if (cache && type != cmStateEnums::INTERNAL && !force) {
return true;
- }
}
+ }
// 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);
- }
- else
- {
+ if (cache) {
+ this->Makefile->AddCacheDefinition(variable, value.c_str(), docstring,
+ type, force);
+ } else {
// add the definition
this->Makefile->AddDefinition(variable, value.c_str());
- }
+ }
return true;
}
-
diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h
index fe1d58df6..c0858b15b 100644
--- a/Source/cmSetCommand.h
+++ b/Source/cmSetCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSetCommand_h
#define cmSetCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmSetCommand
* \brief Set a CMAKE variable
*
@@ -25,139 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmSetCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSetCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "set";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set a CMake, cache or environment variable to a given value.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " set(<variable> <value>\n"
- " [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])\n"
- "Within CMake sets <variable> to the value <value>. "
- "<value> is expanded before <variable> is set to it. "
- "Normally, set will set a regular CMake variable. "
- "If CACHE is present, then the <variable> is put in the cache "
- "instead, unless it is already in the cache. "
- "See section 'Variable types in CMake' below for details of "
- "regular and cache variables and their interactions. "
- "If CACHE is used, <type> and <docstring> are required. <type> is used "
- "by the CMake GUI to choose a widget with which the user sets a value. "
- "The value for <type> may be one of\n"
- " FILEPATH = File chooser dialog.\n"
- " PATH = Directory chooser dialog.\n"
- " STRING = Arbitrary string.\n"
- " BOOL = Boolean ON/OFF checkbox.\n"
- " INTERNAL = No GUI entry (used for persistent variables).\n"
- "If <type> is INTERNAL, the cache variable is marked as internal, "
- "and will not be shown to the user in tools like cmake-gui. "
- "This is intended for values that should be persisted in the cache, "
- "but which users should not normally change. INTERNAL implies FORCE."
- "\n"
- "Normally, set(...CACHE...) creates cache variables, but does not "
- "modify them. "
- "If FORCE is specified, the value of the cache variable is set, even "
- "if the variable is already in the cache. This should normally be "
- "avoided, as it will remove any changes to the cache variable's value "
- "by the user.\n"
- "If PARENT_SCOPE is present, the variable will be set in the scope "
- "above the current scope. Each new directory or function creates a new "
- "scope. This command will set the value of a variable into the parent "
- "directory or calling function (whichever is applicable to the case at "
- "hand). PARENT_SCOPE cannot be combined with CACHE.\n"
- "If <value> is not specified then the variable is removed "
- "instead of set. See also: the unset() command.\n"
- " set(<variable> <value1> ... <valueN>)\n"
- "In this case <variable> is set to a semicolon separated list of "
- "values.\n"
- "<variable> can be an environment variable such as:\n"
- " set( ENV{PATH} /home/martink )\n"
- "in which case the environment variable will be set.\n"
- "*** Variable types in CMake ***\n"
- "In CMake there are two types of variables: normal variables and cache "
- "variables. Normal variables are meant for the internal use of the "
- "script (just like variables in most programming languages); they are "
- "not persisted across CMake runs. "
- "Cache variables (unless set with INTERNAL) are mostly intended for "
- "configuration settings where the first CMake run determines a "
- "suitable default value, which the user can then override, by editing "
- "the cache with tools such as ccmake or cmake-gui. "
- "Cache variables are stored in the CMake cache file, and "
- "are persisted across CMake runs. \n"
- "Both types can exist at the same time with the same name "
- "but different values. "
- "When ${FOO} is evaluated, CMake first looks for "
- "a normal variable 'FOO' in scope and uses it if set. "
- "If and only if no normal variable exists then it falls back to the "
- "cache variable 'FOO'.\n"
- "Some examples:\n"
- "The code 'set(FOO \"x\")' sets the normal variable 'FOO'. It does not "
- "touch the cache, but it will hide any existing cache value 'FOO'.\n"
- "The code 'set(FOO \"x\" CACHE ...)' checks for 'FOO' in the cache, "
- "ignoring any normal variable of the same name. If 'FOO' is in the "
- "cache then nothing happens to either the normal variable or the cache "
- "variable. If 'FOO' is not in the cache, then it is added to the "
- "cache.\n"
- "Finally, whenever a cache variable is added or modified by a command, "
- "CMake also *removes* the normal variable of the same name from the "
- "current scope so that an immediately following evaluation of "
- "it will expose the newly cached value.\n"
- "Normally projects should avoid using normal and cache variables of "
- "the same name, as this interaction can be hard to follow. "
- "However, in some situations it can be useful. "
- "One example (used by some projects):"
- "\n"
- "A project has a subproject in its source tree. The child project has "
- "its own CMakeLists.txt, which is included from the parent "
- "CMakeLists.txt using add_subdirectory(). "
- "Now, if the parent and the child project provide the same option "
- "(for example a compiler option), the parent gets the first chance "
- "to add a user-editable option to the cache. "
- "Normally, the child would then use the same value "
- "that the parent uses. "
- "However, it may be necessary to hard-code the value for the child "
- "project's option while still allowing the user to edit the value used "
- "by the parent project. The parent project can achieve this simply by "
- "setting a normal variable with the same name as the option in a scope "
- "sufficient to hide the option's cache variable from the child "
- "completely. The parent has already set the cache variable, so the "
- "child's set(...CACHE...) will do nothing, and evaluating the option "
- "variable will use the value from the normal variable, which hides the "
- "cache variable.";
- }
-
- cmTypeMacro(cmSetCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx
index 62c9b87c7..8d3961a79 100644
--- a/Source/cmSetDirectoryPropertiesCommand.cxx
+++ b/Source/cmSetDirectoryPropertiesCommand.cxx
@@ -1,70 +1,50 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetDirectoryPropertiesCommand.h"
-#include "cmake.h"
+#include "cmMakefile.h"
+
+class cmExecutionStatus;
// cmSetDirectoryPropertiesCommand
-bool cmSetDirectoryPropertiesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSetDirectoryPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::string errors;
- bool ret =
- cmSetDirectoryPropertiesCommand::RunCommand(this->Makefile,
- args.begin() + 1,
- args.end(), errors);
- if (!ret)
- {
- this->SetError(errors.c_str());
- }
+ bool ret = cmSetDirectoryPropertiesCommand::RunCommand(
+ this->Makefile, args.begin() + 1, args.end(), errors);
+ if (!ret) {
+ this->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)
+bool cmSetDirectoryPropertiesCommand::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)
- {
+ for (; ait != aitend; ait += 2) {
+ if (ait + 1 == aitend) {
errors = "Wrong number of arguments";
return false;
- }
+ }
const std::string& prop = *ait;
- const std::string& value = *(ait+1);
- if ( prop == "VARIABLES" )
- {
- errors =
- "Variables and cache variables should be set using SET command";
+ const std::string& value = *(ait + 1);
+ if (prop == "VARIABLES") {
+ errors = "Variables and cache variables should be set using SET command";
return false;
- }
- else if ( prop == "MACROS" )
- {
- errors =
- "Commands and macros cannot be set using SET_CMAKE_PROPERTIES";
+ }
+ if (prop == "MACROS") {
+ errors = "Commands and macros cannot be set using SET_CMAKE_PROPERTIES";
return false;
- }
- mf->SetProperty(prop.c_str(), value.c_str());
}
+ mf->SetProperty(prop, value.c_str());
+ }
return true;
}
-
diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h
index 8a50c60ff..8832b3389 100644
--- a/Source/cmSetDirectoryPropertiesCommand.h
+++ b/Source/cmSetDirectoryPropertiesCommand.h
@@ -1,78 +1,40 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSetDirectoryPropertiesCommand_h
#define cmSetDirectoryPropertiesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+class cmMakefile;
+
class cmSetDirectoryPropertiesCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmSetDirectoryPropertiesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE
+ {
+ return new cmSetDirectoryPropertiesCommand;
+ }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "set_directory_properties";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set a property of the directory.";
- }
+ 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,
+ static bool RunCommand(cmMakefile* mf,
std::vector<std::string>::const_iterator ait,
std::vector<std::string>::const_iterator aitend,
- std::string &errors);
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " set_directory_properties(PROPERTIES prop1 value1 prop2 value2)\n"
- "Set a property for the current directory and subdirectories. If the "
- "property is not found, CMake will report an error. The properties "
- "include: INCLUDE_DIRECTORIES, LINK_DIRECTORIES, "
- "INCLUDE_REGULAR_EXPRESSION, and ADDITIONAL_MAKE_CLEAN_FILES. "
- "ADDITIONAL_MAKE_CLEAN_FILES is a list of files that will be cleaned "
- "as a part of \"make clean\" stage.";
- }
-
- cmTypeMacro(cmSetDirectoryPropertiesCommand, cmCommand);
+ std::string& errors);
};
-
-
#endif
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 42078605a..b57f62a50 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -1,22 +1,22 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSetPropertyCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSetPropertyCommand.h"
-#include "cmSetTargetPropertiesCommand.h"
-#include "cmSetTestsPropertiesCommand.h"
-#include "cmSetSourceFilesPropertiesCommand.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstalledFile.h"
+#include "cmMakefile.h"
+#include "cmProperty.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTest.h"
+#include "cmake.h"
-#include "cmCacheManager.h"
+class cmExecutionStatus;
-//----------------------------------------------------------------------------
cmSetPropertyCommand::cmSetPropertyCommand()
{
this->AppendMode = false;
@@ -24,269 +24,221 @@ cmSetPropertyCommand::cmSetPropertyCommand()
this->Remove = true;
}
-//----------------------------------------------------------------------------
-bool cmSetPropertyCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->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();
cmProperty::ScopeType scope;
- if(*arg == "GLOBAL")
- {
+ if (*arg == "GLOBAL") {
scope = cmProperty::GLOBAL;
- }
- else if(*arg == "DIRECTORY")
- {
+ } else if (*arg == "DIRECTORY") {
scope = cmProperty::DIRECTORY;
- }
- else if(*arg == "TARGET")
- {
+ } else if (*arg == "TARGET") {
scope = cmProperty::TARGET;
- }
- else if(*arg == "SOURCE")
- {
+ } else if (*arg == "SOURCE") {
scope = cmProperty::SOURCE_FILE;
- }
- else if(*arg == "TEST")
- {
+ } else if (*arg == "TEST") {
scope = cmProperty::TEST;
- }
- else if(*arg == "CACHE")
- {
+ } else if (*arg == "CACHE") {
scope = cmProperty::CACHE;
- }
- else
- {
- cmOStringStream e;
+ } else if (*arg == "INSTALL") {
+ scope = cmProperty::INSTALL;
+ } else {
+ std::ostringstream e;
e << "given invalid scope " << *arg << ". "
- << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, CACHE.";
- this->SetError(e.str().c_str());
+ << "Valid scopes are GLOBAL, DIRECTORY, "
+ "TARGET, SOURCE, TEST, CACHE, INSTALL.";
+ this->SetError(e.str());
return false;
- }
+ }
// Parse the rest of the arguments up to the values.
- enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
+ enum Doing
+ {
+ DoingNone,
+ DoingNames,
+ DoingProperty,
+ DoingValues
+ };
Doing doing = DoingNames;
const char* sep = "";
- for(++arg; arg != args.end(); ++arg)
- {
- if(*arg == "PROPERTY")
- {
+ for (++arg; arg != args.end(); ++arg) {
+ 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")
- {
+ } else if (*arg == "APPEND_STRING") {
doing = DoingNone;
this->AppendMode = true;
this->Remove = false;
this->AppendAsString = true;
- }
- else if(doing == DoingNames)
- {
+ } else if (doing == DoingNames) {
this->Names.insert(*arg);
- }
- else if(doing == DoingProperty)
- {
+ } else if (doing == DoingProperty) {
this->PropertyName = *arg;
doing = DoingValues;
- }
- else if(doing == DoingValues)
- {
+ } else if (doing == DoingValues) {
this->PropertyValue += sep;
sep = ";";
this->PropertyValue += *arg;
this->Remove = false;
- }
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "given invalid argument \"" << *arg << "\".";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
// Make sure a property name was found.
- if(this->PropertyName.empty())
- {
+ if (this->PropertyName.empty()) {
this->SetError("not given a PROPERTY <name> argument.");
return false;
- }
+ }
// Dispatch property setting.
- switch(scope)
- {
- case cmProperty::GLOBAL: return this->HandleGlobalMode();
- case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
- case cmProperty::TARGET: return this->HandleTargetMode();
- case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
- case cmProperty::TEST: return this->HandleTestMode();
- case cmProperty::CACHE: return this->HandleCacheMode();
+ switch (scope) {
+ case cmProperty::GLOBAL:
+ return this->HandleGlobalMode();
+ case cmProperty::DIRECTORY:
+ return this->HandleDirectoryMode();
+ case cmProperty::TARGET:
+ return this->HandleTargetMode();
+ case cmProperty::SOURCE_FILE:
+ return this->HandleSourceMode();
+ case cmProperty::TEST:
+ return this->HandleTestMode();
+ case cmProperty::CACHE:
+ return this->HandleCacheMode();
+ case cmProperty::INSTALL:
+ return this->HandleInstallMode();
case cmProperty::VARIABLE:
case cmProperty::CACHED_VARIABLE:
break; // should never happen
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleGlobalMode()
{
- if(!this->Names.empty())
- {
+ if (!this->Names.empty()) {
this->SetError("given names for GLOBAL scope.");
return false;
- }
+ }
// Set or append the property.
cmake* cm = this->Makefile->GetCMakeInstance();
- const char* name = this->PropertyName.c_str();
- const char *value = this->PropertyValue.c_str();
- if (this->Remove)
- {
- value = 0;
- }
- if(this->AppendMode)
- {
+ std::string const& name = this->PropertyName;
+ const char* value = this->PropertyValue.c_str();
+ if (this->Remove) {
+ value = CM_NULLPTR;
+ }
+ if (this->AppendMode) {
cm->AppendProperty(name, value ? value : "", this->AppendAsString);
- }
- else
- {
+ } else {
cm->SetProperty(name, value);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleDirectoryMode()
{
- if(this->Names.size() > 1)
- {
+ if (this->Names.size() > 1) {
this->SetError("allows at most one name for DIRECTORY scope.");
return false;
- }
+ }
// Default to the current directory.
cmMakefile* mf = this->Makefile;
// Lookup the directory if given.
- if(!this->Names.empty())
- {
+ if (!this->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->GetCurrentDirectory();
+ if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
+ dir = this->Makefile->GetCurrentSourceDirectory();
dir += "/";
dir += *this->Names.begin();
- }
+ }
// The local generators are associated with collapsed paths.
- dir = cmSystemTools::CollapseFullPath(dir.c_str());
-
- // Lookup the generator.
- if(cmLocalGenerator* lg =
- (this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
- {
- // Use the makefile for the directory found.
- mf = lg->GetMakefile();
- }
- else
- {
+ dir = cmSystemTools::CollapseFullPath(dir);
+
+ mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
+ if (!mf) {
// Could not find the directory.
- this->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.");
+ this->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.");
return false;
- }
}
+ }
// Set or append the property.
- const char* name = this->PropertyName.c_str();
- const char *value = this->PropertyValue.c_str();
- if (this->Remove)
- {
- value = 0;
- }
- if(this->AppendMode)
- {
+ std::string const& name = this->PropertyName;
+ const char* value = this->PropertyValue.c_str();
+ if (this->Remove) {
+ value = CM_NULLPTR;
+ }
+ if (this->AppendMode) {
mf->AppendProperty(name, value ? value : "", this->AppendAsString);
- }
- else
- {
+ } else {
mf->SetProperty(name, value);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTargetMode()
{
- for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni)
- {
- if (this->Makefile->IsAlias(ni->c_str()))
- {
+ 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.");
return false;
- }
- if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
- {
+ }
+ if (cmTarget* target = this->Makefile->FindTargetToUse(*ni)) {
// Handle the current target.
- if(!this->HandleTarget(target))
- {
+ if (!this->HandleTarget(target)) {
return false;
- }
}
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "could not find TARGET " << *ni
<< ". Perhaps it has not yet been created.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
{
// Set or append the property.
- const char* name = this->PropertyName.c_str();
- const char *value = this->PropertyValue.c_str();
- if (this->Remove)
- {
- value = 0;
- }
- if(this->AppendMode)
- {
+ std::string const& name = this->PropertyName;
+ const char* value = this->PropertyValue.c_str();
+ if (this->Remove) {
+ value = CM_NULLPTR;
+ }
+ if (this->AppendMode) {
target->AppendProperty(name, value, this->AppendAsString);
- }
- else
- {
+ } else {
target->SetProperty(name, value);
- }
+ }
// Check the resulting value.
target->CheckProperty(name, this->Makefile);
@@ -294,197 +246,194 @@ bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleSourceMode()
{
- for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni)
- {
+ for (std::set<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni) {
// Get the source file.
- if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
- {
- if(!this->HandleSource(sf))
- {
+ if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(*ni)) {
+ if (!this->HandleSource(sf)) {
return false;
- }
}
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "given SOURCE name that could not be found or created: " << *ni;
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
{
// Set or append the property.
- const char* name = this->PropertyName.c_str();
- const char *value = this->PropertyValue.c_str();
- if (this->Remove)
- {
- value = 0;
- }
+ std::string const& name = this->PropertyName;
+ const char* value = this->PropertyValue.c_str();
+ if (this->Remove) {
+ value = CM_NULLPTR;
+ }
- if(this->AppendMode)
- {
+ if (this->AppendMode) {
sf->AppendProperty(name, value, this->AppendAsString);
- }
- else
- {
+ } else {
sf->SetProperty(name, value);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTestMode()
{
// Look for tests with all names given.
- std::set<cmStdString>::iterator next;
- for(std::set<cmStdString>::iterator ni = this->Names.begin();
- ni != this->Names.end(); ni = next)
- {
+ std::set<std::string>::iterator next;
+ for (std::set<std::string>::iterator ni = this->Names.begin();
+ ni != this->Names.end(); ni = next) {
next = ni;
++next;
- if(cmTest* test = this->Makefile->GetTest(ni->c_str()))
- {
- if(this->HandleTest(test))
- {
+ if (cmTest* test = this->Makefile->GetTest(*ni)) {
+ if (this->HandleTest(test)) {
this->Names.erase(ni);
- }
- else
- {
+ } else {
return false;
- }
}
}
+ }
// Names that are still left were not found.
- if(!this->Names.empty())
- {
- cmOStringStream e;
+ if (!this->Names.empty()) {
+ std::ostringstream e;
e << "given TEST names that do not exist:\n";
- for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni)
- {
+ for (std::set<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni) {
e << " " << *ni << "\n";
- }
- this->SetError(e.str().c_str());
- return false;
}
+ this->SetError(e.str());
+ return false;
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTest(cmTest* test)
{
// Set or append the property.
- const char* name = this->PropertyName.c_str();
- const char *value = this->PropertyValue.c_str();
- if (this->Remove)
- {
- value = 0;
- }
- if(this->AppendMode)
- {
+ std::string const& name = this->PropertyName;
+ const char* value = this->PropertyValue.c_str();
+ if (this->Remove) {
+ value = CM_NULLPTR;
+ }
+ if (this->AppendMode) {
test->AppendProperty(name, value, this->AppendAsString);
- }
- else
- {
+ } else {
test->SetProperty(name, value);
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleCacheMode()
{
- if(this->PropertyName == "ADVANCED")
- {
- if(!this->Remove &&
- !cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
- !cmSystemTools::IsOff(this->PropertyValue.c_str()))
- {
- cmOStringStream e;
+ 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().c_str());
+ this->SetError(e.str());
return false;
- }
}
- else if(this->PropertyName == "TYPE")
- {
- if(!cmCacheManager::IsType(this->PropertyValue.c_str()))
- {
- cmOStringStream e;
+ } 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().c_str());
+ this->SetError(e.str());
return false;
- }
}
- else if(this->PropertyName != "HELPSTRING" &&
- this->PropertyName != "STRINGS" &&
- this->PropertyName != "VALUE")
- {
- cmOStringStream e;
+ } 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().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni)
- {
+ for (std::set<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end(); ++ni) {
// Get the source file.
cmMakefile* mf = this->GetMakefile();
cmake* cm = mf->GetCMakeInstance();
- cmCacheManager::CacheIterator it =
- cm->GetCacheManager()->GetCacheIterator(ni->c_str());
- if(!it.IsAtEnd())
- {
- if(!this->HandleCacheEntry(it))
- {
+ const char* existingValue = cm->GetState()->GetCacheEntryValue(*ni);
+ if (existingValue) {
+ if (!this->HandleCacheEntry(*ni)) {
return false;
- }
}
- else
- {
- cmOStringStream e;
+ } else {
+ std::ostringstream e;
e << "could not find CACHE variable " << *ni
<< ". Perhaps it has not yet been created.";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmSetPropertyCommand::HandleCacheEntry(cmCacheManager::CacheIterator& it)
+bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey)
{
// Set or append the property.
- const char* name = this->PropertyName.c_str();
+ std::string const& name = this->PropertyName;
const char* value = this->PropertyValue.c_str();
- if (this->Remove)
- {
- value = 0;
- }
- if(this->AppendMode)
- {
- it.AppendProperty(name, value, this->AppendAsString);
- }
- else
- {
- it.SetProperty(name, value);
+ cmState* state = this->Makefile->GetState();
+ if (this->Remove) {
+ state->RemoveCacheEntryProperty(cacheKey, name);
+ }
+ if (this->AppendMode) {
+ state->AppendCacheEntryProperty(cacheKey, name, value,
+ this->AppendAsString);
+ } else {
+ state->SetCacheEntryProperty(cacheKey, name, value);
+ }
+
+ return true;
+}
+
+bool cmSetPropertyCommand::HandleInstallMode()
+{
+ cmake* cm = this->Makefile->GetCMakeInstance();
+
+ for (std::set<std::string>::const_iterator i = this->Names.begin();
+ i != this->Names.end(); ++i) {
+ if (cmInstalledFile* file =
+ cm->GetOrCreateInstalledFile(this->Makefile, *i)) {
+ if (!this->HandleInstall(file)) {
+ return false;
+ }
+ } else {
+ std::ostringstream e;
+ e << "given INSTALL name that could not be found or created: " << *i;
+ this->SetError(e.str());
+ return false;
}
+ }
+ return true;
+}
+bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file)
+{
+ // 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);
+ } else {
+ file->SetProperty(mf, name, value);
+ }
return true;
}
diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h
index 830299d46..08158244a 100644
--- a/Source/cmSetPropertyCommand.h
+++ b/Source/cmSetPropertyCommand.h
@@ -1,97 +1,38 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSetsPropertiesCommand_h
#define cmSetsPropertiesCommand_h
+#include "cmConfigure.h"
+
+#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();
- virtual cmCommand* Clone()
- {
- return new cmSetPropertyCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSetPropertyCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "set_property";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set a named property in a given scope.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " set_property(<GLOBAL |\n"
- " DIRECTORY [dir] |\n"
- " TARGET [target1 [target2 ...]] |\n"
- " SOURCE [src1 [src2 ...]] |\n"
- " TEST [test1 [test2 ...]] |\n"
- " CACHE [entry1 [entry2 ...]]>\n"
- " [APPEND] [APPEND_STRING]\n"
- " PROPERTY <name> [value1 [value2 ...]])\n"
- "Set one property on zero or more objects of a scope. "
- "The first argument determines the scope in which the property "
- "is set. It must be one of the following:\n"
- "GLOBAL scope is unique and does not accept a name.\n"
- "DIRECTORY scope defaults to the current directory but another "
- "directory (already processed by CMake) may be named by full or "
- "relative path.\n"
- "TARGET scope may name zero or more existing targets.\n"
- "SOURCE scope may name zero or more source files. "
- "Note that source file properties are visible only to targets "
- "added in the same directory (CMakeLists.txt).\n"
- "TEST scope may name zero or more existing tests.\n"
- "CACHE scope must name zero or more cache existing entries.\n"
- "The required PROPERTY option is immediately followed by the name "
- "of the property to set. Remaining arguments are used to "
- "compose the property value in the form of a semicolon-separated "
- "list. "
- "If the APPEND option is given the list is appended to any "
- "existing property value."
- "If the APPEND_STRING option is given the string is append to any "
- "existing property value as string, i.e. it results in a longer "
- "string and not a list of strings."
- ;
- }
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- cmTypeMacro(cmSetPropertyCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
- std::set<cmStdString> Names;
+ std::set<std::string> Names;
std::string PropertyName;
std::string PropertyValue;
bool Remove;
@@ -108,9 +49,9 @@ private:
bool HandleTestMode();
bool HandleTest(cmTest* test);
bool HandleCacheMode();
- bool HandleCacheEntry(cmCacheManager::CacheIterator&);
+ bool HandleCacheEntry(std::string const&);
+ bool HandleInstallMode();
+ bool HandleInstall(cmInstalledFile* file);
};
-
-
#endif
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index 619dfc5a5..33e1b2e06 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.cxx
+++ b/Source/cmSetSourceFilesPropertiesCommand.cxx
@@ -1,170 +1,125 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetSourceFilesPropertiesCommand.h"
+#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmSetSourceFilesPropertiesCommand
-bool cmSetSourceFilesPropertiesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSetSourceFilesPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// break the arguments into source file names and properties
int numFiles = 0;
std::vector<std::string>::const_iterator j;
j = args.begin();
// old style allows for specifier before PROPERTIES keyword
- while (j != args.end() &&
- *j != "ABSTRACT" &&
- *j != "WRAP_EXCLUDE" &&
- *j != "GENERATED" &&
- *j != "COMPILE_FLAGS" &&
- *j != "OBJECT_DEPENDS" &&
- *j != "PROPERTIES")
- {
+ while (j != args.end() && *j != "ABSTRACT" && *j != "WRAP_EXCLUDE" &&
+ *j != "GENERATED" && *j != "COMPILE_FLAGS" &&
+ *j != "OBJECT_DEPENDS" && *j != "PROPERTIES") {
numFiles++;
++j;
- }
+ }
// 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);
- if (!ret)
- {
- this->SetError(errors.c_str());
- }
+ bool ret = cmSetSourceFilesPropertiesCommand::RunCommand(
+ this->Makefile, args.begin(), args.begin() + numFiles,
+ args.begin() + numFiles, args.end(), errors);
+ if (!ret) {
+ this->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)
+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)
{
std::vector<std::string> propertyPairs;
bool generated = false;
std::vector<std::string>::const_iterator j;
// build the property pairs
- for(j= propbeg; j != propend;++j)
- {
+ for (j = propbeg; j != propend; ++j) {
// old style allows for specifier before PROPERTIES keyword
- if(*j == "ABSTRACT")
- {
+ if (*j == "ABSTRACT") {
propertyPairs.push_back("ABSTRACT");
propertyPairs.push_back("1");
- }
- else if(*j == "WRAP_EXCLUDE")
- {
+ } else if (*j == "WRAP_EXCLUDE") {
propertyPairs.push_back("WRAP_EXCLUDE");
propertyPairs.push_back("1");
- }
- else if(*j == "GENERATED")
- {
+ } else if (*j == "GENERATED") {
generated = true;
propertyPairs.push_back("GENERATED");
propertyPairs.push_back("1");
- }
- else if(*j == "COMPILE_FLAGS")
- {
+ } else if (*j == "COMPILE_FLAGS") {
propertyPairs.push_back("COMPILE_FLAGS");
++j;
- if(j == propend)
- {
+ if (j == propend) {
errors = "called with incorrect number of arguments "
- "COMPILE_FLAGS with no flags";
+ "COMPILE_FLAGS with no flags";
return false;
- }
- propertyPairs.push_back(*j);
}
- else if(*j == "OBJECT_DEPENDS")
- {
+ propertyPairs.push_back(*j);
+ } else if (*j == "OBJECT_DEPENDS") {
propertyPairs.push_back("OBJECT_DEPENDS");
++j;
- if(j == propend)
- {
+ if (j == propend) {
errors = "called with incorrect number of arguments "
- "OBJECT_DEPENDS with no dependencies";
+ "OBJECT_DEPENDS with no dependencies";
return false;
- }
- propertyPairs.push_back(*j);
}
- else if(*j == "PROPERTIES")
- {
+ propertyPairs.push_back(*j);
+ } else if (*j == "PROPERTIES") {
// now loop through the rest of the arguments, new style
++j;
- while (j != propend)
- {
+ while (j != propend) {
propertyPairs.push_back(*j);
- if(*j == "GENERATED")
- {
+ if (*j == "GENERATED") {
++j;
- if(j != propend && cmSystemTools::IsOn(j->c_str()))
- {
+ if (j != propend && cmSystemTools::IsOn(j->c_str())) {
generated = true;
- }
}
- else
- {
+ } else {
++j;
- }
- if(j == propend)
- {
+ }
+ if (j == propend) {
errors = "called with incorrect number of arguments.";
return false;
- }
+ }
propertyPairs.push_back(*j);
++j;
- }
+ }
// break out of the loop because j is already == end
break;
- }
- else
- {
+ } else {
errors = "called with illegal arguments, maybe missing a "
- "PROPERTIES specifier?";
+ "PROPERTIES specifier?";
return false;
- }
}
+ }
// now loop over all the files
- for(j= filebeg; j != fileend;++j)
- {
+ for (j = filebeg; j != fileend; ++j) {
// get the source file
- cmSourceFile* sf =
- mf->GetOrCreateSource(j->c_str(), generated);
- if(sf)
- {
+ cmSourceFile* sf = mf->GetOrCreateSource(*j, generated);
+ if (sf) {
// now loop through all the props and set them
unsigned int k;
- for (k = 0; k < propertyPairs.size(); k = k + 2)
- {
- sf->SetProperty(propertyPairs[k].c_str(),propertyPairs[k+1].c_str());
- }
+ for (k = 0; k < propertyPairs.size(); k = k + 2) {
+ sf->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str());
}
}
+ }
return true;
}
-
diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h
index f7009e781..2e22dc9ef 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.h
+++ b/Source/cmSetSourceFilesPropertiesCommand.h
@@ -1,74 +1,39 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSetSourceFilesPropertiesCommand_h
#define cmSetSourceFilesPropertiesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+class cmMakefile;
+
class cmSetSourceFilesPropertiesCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmSetSourceFilesPropertiesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE
+ {
+ return new cmSetSourceFilesPropertiesCommand;
+ }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "set_source_files_properties";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Source files can have properties that affect how they are built.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " set_source_files_properties([file1 [file2 [...]]]\n"
- " PROPERTIES prop1 value1\n"
- " [prop2 value2 [...]])\n"
- "Set properties associated with source files using a key/value "
- "paired list. "
- "See properties documentation for those known to CMake. "
- "Unrecognized properties are ignored. "
- "Source file properties are visible only to targets "
- "added in the same directory (CMakeLists.txt).";
- }
-
- cmTypeMacro(cmSetSourceFilesPropertiesCommand, cmCommand);
-
- static bool RunCommand(cmMakefile *mf,
+ 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::string& errors);
};
-
-
#endif
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index 78ef393cc..642591337 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -1,115 +1,80 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSetTargetPropertiesCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <iterator>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSetTargetPropertiesCommand.h"
-#include "cmLocalGenerator.h"
-#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+
+class cmExecutionStatus;
// cmSetTargetPropertiesCommand
-bool cmSetTargetPropertiesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSetTargetPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// first collect up the list of files
std::vector<std::string> propertyPairs;
- bool doingFiles = true;
int numFiles = 0;
std::vector<std::string>::const_iterator j;
- for(j= args.begin(); j != args.end();++j)
- {
- if(*j == "PROPERTIES")
- {
- doingFiles = false;
+ for (j = args.begin(); j != args.end(); ++j) {
+ if (*j == "PROPERTIES") {
// now loop through the rest of the arguments, new style
++j;
- while (j != args.end())
- {
- propertyPairs.push_back(*j);
- ++j;
- if(j == args.end())
- {
- this->SetError("called with incorrect number of arguments.");
- return false;
- }
- propertyPairs.push_back(*j);
- ++j;
- }
- // break out of the loop because j is already == end
- break;
- }
- else if (doingFiles)
- {
- numFiles++;
- }
- else
- {
- this->SetError("called with illegal arguments, maybe missing "
- "a PROPERTIES specifier?");
- return false;
+ if (std::distance(j, args.end()) % 2 != 0) {
+ this->SetError("called with incorrect number of arguments.");
+ return false;
}
+ propertyPairs.insert(propertyPairs.end(), j, args.end());
+ break;
}
- if(propertyPairs.size() == 0)
- {
- this->SetError("called with illegal arguments, maybe missing "
- "a PROPERTIES specifier?");
- return false;
- }
+ numFiles++;
+ }
+ if (propertyPairs.empty()) {
+ this->SetError("called with illegal arguments, maybe missing "
+ "a PROPERTIES specifier?");
+ return false;
+ }
// now loop over all the targets
int i;
- for(i = 0; i < numFiles; ++i)
- {
- if (this->Makefile->IsAlias(args[i].c_str()))
- {
+ for (i = 0; i < numFiles; ++i) {
+ if (this->Makefile->IsAlias(args[i])) {
this->SetError("can not be used on an ALIAS target.");
return false;
- }
- bool ret = cmSetTargetPropertiesCommand::SetOneTarget
- (args[i].c_str(),propertyPairs,this->Makefile);
- if (!ret)
- {
+ }
+ bool ret = cmSetTargetPropertiesCommand::SetOneTarget(
+ args[i], propertyPairs, this->Makefile);
+ if (!ret) {
std::string message = "Can not find target to add properties to: ";
message += args[i];
- this->SetError(message.c_str());
+ this->SetError(message);
return false;
- }
}
+ }
return true;
}
-bool cmSetTargetPropertiesCommand
-::SetOneTarget(const char *tname,
- std::vector<std::string> &propertyPairs,
- cmMakefile *mf)
+bool cmSetTargetPropertiesCommand::SetOneTarget(
+ const std::string& tname, std::vector<std::string>& propertyPairs,
+ cmMakefile* mf)
{
- if(cmTarget* target = mf->FindTargetToUse(tname))
- {
+ if (cmTarget* target = mf->FindTargetToUse(tname)) {
// now loop through all the props and set them
unsigned int k;
- for (k = 0; k < propertyPairs.size(); k = k + 2)
- {
- target->SetProperty(propertyPairs[k].c_str(),
- propertyPairs[k+1].c_str());
- target->CheckProperty(propertyPairs[k].c_str(), mf);
- }
+ for (k = 0; k < propertyPairs.size(); k = k + 2) {
+ target->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str());
+ target->CheckProperty(propertyPairs[k], mf);
}
+ }
// if file is not already in the makefile, then add it
- else
- {
+ else {
return false;
- }
+ }
return true;
}
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index cf9c19350..425618157 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -1,170 +1,36 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSetTargetsPropertiesCommand_h
#define cmSetTargetsPropertiesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+class cmMakefile;
+
class cmSetTargetPropertiesCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmSetTargetPropertiesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSetTargetPropertiesCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "set_target_properties";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Targets can have properties that affect how they are built.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
/**
* Used by this command and cmSetPropertiesCommand
*/
- static bool SetOneTarget(const char *tname,
- std::vector<std::string> &propertyPairs,
- cmMakefile *mf);
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " set_target_properties(target1 target2 ...\n"
- " PROPERTIES prop1 value1\n"
- " prop2 value2 ...)\n"
- "Set properties on a target. The syntax for the command is to "
- "list all the files you want "
- "to change, and then provide the values you want to set next. "
- "You can use any prop value pair you want and "
- "extract it later with the GET_TARGET_PROPERTY command.\n"
- "Properties that affect the name of a target's output file are "
- "as follows. "
- "The PREFIX and SUFFIX properties override the default target name "
- "prefix (such as \"lib\") and suffix (such as \".so\"). "
- "IMPORT_PREFIX and IMPORT_SUFFIX are the equivalent properties for "
- "the import library corresponding to a DLL "
- "(for SHARED library targets). "
- "OUTPUT_NAME sets the real name of a target when it is built and "
- "can be used to help create two targets of the same name even though "
- "CMake requires unique logical target names. There is also a "
- "<CONFIG>_OUTPUT_NAME that can set the output name on a "
- "per-configuration basis. "
- "<CONFIG>_POSTFIX sets a postfix for the real name of the target "
- "when it is built under the configuration named by <CONFIG> "
- "(in upper-case, such as \"DEBUG_POSTFIX\"). The value of "
- "this property is initialized when the target is created to the "
- "value of the variable CMAKE_<CONFIG>_POSTFIX (except for executable "
- "targets because earlier CMake versions which did not use this "
- "variable for executables)."
- "\n"
- "The LINK_FLAGS property can be used to add extra flags to the "
- "link step of a target. LINK_FLAGS_<CONFIG> will add to the "
- "configuration <CONFIG>, "
- "for example, DEBUG, RELEASE, MINSIZEREL, RELWITHDEBINFO. "
- "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when "
- "compiling sources in a shared library. "
- "If not set here then it is set to target_EXPORTS by default "
- "(with some substitutions if the target is not a valid C "
- "identifier). This is useful for headers to know whether they are "
- "being included from inside their library or outside to properly "
- "setup dllexport/dllimport decorations. "
- "The COMPILE_FLAGS property sets additional compiler flags used "
- "to build sources within the target. It may also be used to pass "
- "additional preprocessor definitions."
- "\n"
- "The LINKER_LANGUAGE property is used to change the tool "
- "used to link an executable or shared library. The default is "
- "set the language to match the files in the library. CXX and C "
- "are common values for this property."
- "\n"
- "For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and API version respectively. When building or "
- "installing appropriate symlinks are created if the platform "
- "supports symlinks and the linker supports so-names. "
- "If only one of both is specified the missing is assumed to have "
- "the same version number. "
- "For executables VERSION can be used to specify the build version. "
- "When building or installing appropriate symlinks are created if "
- "the platform supports symlinks. "
- "For shared libraries and executables on Windows the VERSION "
- "attribute is parsed to extract a \"major.minor\" version number. "
- "These numbers are used as the image version of the binary. "
- "\n"
- "There are a few properties used to specify RPATH rules. "
- "INSTALL_RPATH is a semicolon-separated list specifying the rpath "
- "to use in installed targets (for platforms that support it). "
- "INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true will "
- "append directories in the linker search path and outside the "
- "project to the INSTALL_RPATH. "
- "SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic "
- "generation of an rpath allowing the target to run from the "
- "build tree. "
- "BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link "
- "the target in the build tree with the INSTALL_RPATH. This takes "
- "precedence over SKIP_BUILD_RPATH and avoids the need for relinking "
- "before installation. INSTALL_NAME_DIR is a string specifying the "
- "directory portion of the \"install_name\" field of shared libraries "
- "on Mac OSX to use in the installed targets. "
- "When the target is created the values of "
- "the variables CMAKE_INSTALL_RPATH, "
- "CMAKE_INSTALL_RPATH_USE_LINK_PATH, CMAKE_SKIP_BUILD_RPATH, "
- "CMAKE_BUILD_WITH_INSTALL_RPATH, and CMAKE_INSTALL_NAME_DIR "
- "are used to initialize these properties.\n"
- "PROJECT_LABEL can be used to change the name of "
- "the target in an IDE like visual studio. VS_KEYWORD can be set "
- "to change the visual studio keyword, for example Qt integration "
- "works better if this is set to Qt4VSv1.0.\n"
- "VS_SCC_PROJECTNAME, VS_SCC_LOCALPATH, VS_SCC_PROVIDER and "
- "VS_SCC_AUXPATH can be set "
- "to add support for source control bindings in a Visual Studio "
- "project file.\n"
- "VS_GLOBAL_<variable> can be set to add a Visual Studio "
- "project-specific global variable. "
- "Qt integration works better if VS_GLOBAL_QtVersion is set to "
- "the Qt version FindQt4.cmake found. For example, \"4.7.3\"\n"
- "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
- "old way to specify CMake scripts to run before and after "
- "installing a target. They are used only when the old "
- "INSTALL_TARGETS command is used to install the target. Use the "
- "INSTALL command instead."
- "\n"
- "The EXCLUDE_FROM_DEFAULT_BUILD property is used by the visual "
- "studio generators. If it is set to 1 the target will not be "
- "part of the default build when you select \"Build Solution\". "
- "This can also be set on a per-configuration basis using "
- "EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG>."
- ;
- }
-
- cmTypeMacro(cmSetTargetPropertiesCommand, cmCommand);
+ static bool SetOneTarget(const std::string& tname,
+ std::vector<std::string>& propertyPairs,
+ cmMakefile* mf);
};
-
-
#endif
diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx
index 3d52cf242..e27c675c6 100644
--- a/Source/cmSetTestsPropertiesCommand.cxx
+++ b/Source/cmSetTestsPropertiesCommand.cxx
@@ -1,117 +1,78 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetTestsPropertiesCommand.h"
-#include "cmake.h"
+#include <iterator>
+
+#include "cmMakefile.h"
#include "cmTest.h"
+class cmExecutionStatus;
+
// cmSetTestsPropertiesCommand
-bool cmSetTestsPropertiesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSetTestsPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// first collect up the list of files
std::vector<std::string> propertyPairs;
- bool doingFiles = true;
int numFiles = 0;
std::vector<std::string>::const_iterator j;
- for(j= args.begin(); j != args.end();++j)
- {
- if(*j == "PROPERTIES")
- {
- doingFiles = false;
+ for (j = args.begin(); j != args.end(); ++j) {
+ if (*j == "PROPERTIES") {
// now loop through the rest of the arguments, new style
++j;
- while (j != args.end())
- {
- propertyPairs.push_back(*j);
- ++j;
- if(j == args.end())
- {
- this->SetError("called with incorrect number of arguments.");
- return false;
- }
- propertyPairs.push_back(*j);
- ++j;
- }
- // break out of the loop because j is already == end
- break;
- }
- else if (doingFiles)
- {
- numFiles++;
- }
- else
- {
- this->SetError("called with illegal arguments, maybe "
- "missing a PROPERTIES specifier?");
- return false;
+ if (std::distance(j, args.end()) % 2 != 0) {
+ this->SetError("called with incorrect number of arguments.");
+ return false;
}
+ propertyPairs.insert(propertyPairs.end(), j, args.end());
+ break;
}
- if(propertyPairs.size() == 0)
- {
+ numFiles++;
+ }
+ if (propertyPairs.empty()) {
this->SetError("called with illegal arguments, maybe "
"missing a PROPERTIES specifier?");
return false;
- }
-
+ }
// now loop over all the targets
int i;
- for(i = 0; i < numFiles; ++i)
- {
+ for (i = 0; i < numFiles; ++i) {
std::string errors;
- bool ret =
- cmSetTestsPropertiesCommand::SetOneTest(args[i].c_str(),
- propertyPairs,
- this->Makefile, errors);
- if (!ret)
- {
- this->SetError(errors.c_str());
+ bool ret = cmSetTestsPropertiesCommand::SetOneTest(args[i], propertyPairs,
+ this->Makefile, errors);
+ if (!ret) {
+ this->SetError(errors);
return ret;
- }
}
+ }
return true;
}
-
-bool cmSetTestsPropertiesCommand
-::SetOneTest(const char *tname,
- std::vector<std::string> &propertyPairs,
- cmMakefile *mf, std::string &errors)
+bool cmSetTestsPropertiesCommand::SetOneTest(
+ const std::string& tname, std::vector<std::string>& propertyPairs,
+ cmMakefile* mf, std::string& errors)
{
- if(cmTest* test = mf->GetTest(tname))
- {
+ if (cmTest* test = mf->GetTest(tname)) {
// now loop through all the props and set them
unsigned int k;
- for (k = 0; k < propertyPairs.size(); k = k + 2)
- {
- test->SetProperty(propertyPairs[k].c_str(),
- propertyPairs[k+1].c_str());
+ for (k = 0; k < propertyPairs.size(); k = k + 2) {
+ if (!propertyPairs[k].empty()) {
+ test->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str());
}
}
- else
- {
+ } else {
errors = "Can not find test to add properties to: ";
errors += tname;
return false;
- }
+ }
return true;
}
-
diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h
index 3a592189b..90f004c34 100644
--- a/Source/cmSetTestsPropertiesCommand.h
+++ b/Source/cmSetTestsPropertiesCommand.h
@@ -1,81 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSetTestsPropertiesCommand_h
#define cmSetTestsPropertiesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+class cmMakefile;
+
class cmSetTestsPropertiesCommand : public cmCommand
{
public:
- virtual cmCommand* Clone()
- {
- return new cmSetTestsPropertiesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSetTestsPropertiesCommand; }
/**
* This is called when the command is first encountered in
* the input file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "set_tests_properties";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set a property of the tests.";
- }
-
- /**
- * Longer documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " set_tests_properties(test1 [test2...] PROPERTIES prop1 value1 prop2"
- " value2)\n"
- "Set a property for the tests. If the property is not found, CMake "
- "will report an error. The properties include:\n"
- "WILL_FAIL: If set to true, this will invert the pass/fail flag of the"
- " test.\n"
- "PASS_REGULAR_EXPRESSION: If set, the test output will be checked "
- "against the specified regular expressions and at least one of the"
- " regular "
- "expressions has to match, otherwise the test will fail.\n"
- " Example: PASS_REGULAR_EXPRESSION \"TestPassed;All ok\"\n"
- "FAIL_REGULAR_EXPRESSION: If set, if the output will match to one of "
- "specified regular expressions, the test will fail.\n"
- " Example: PASS_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\"\n"
- "Both PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION expect a "
- "list of regular expressions.\n"
- "TIMEOUT: Setting this will limit the test runtime to the number of "
- "seconds specified.\n";
- }
-
- cmTypeMacro(cmSetTestsPropertiesCommand, cmCommand);
-
- static bool SetOneTest(const char *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);
};
-
-
#endif
diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx
index 2bdd1ad28..7eace268f 100644
--- a/Source/cmSiteNameCommand.cxx
+++ b/Source/cmSiteNameCommand.cxx
@@ -1,27 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSiteNameCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSiteNameCommand.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
-#include <cmsys/RegularExpression.hxx>
+class cmExecutionStatus;
// cmSiteNameCommand
-bool cmSiteNameCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() != 1 )
- {
+ if (args.size() != 1) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::vector<std::string> paths;
paths.push_back("/usr/bsd");
paths.push_back("/usr/sbin");
@@ -30,66 +26,56 @@ bool cmSiteNameCommand
paths.push_back("/sbin");
paths.push_back("/usr/local/bin");
- const char* cacheValue
- = this->Makefile->GetDefinition(args[0].c_str());
- if(cacheValue)
- {
+ const char* cacheValue = this->Makefile->GetDefinition(args[0]);
+ if (cacheValue) {
return true;
- }
+ }
- const char *temp = this->Makefile->GetDefinition("HOSTNAME");
+ const char* temp = this->Makefile->GetDefinition("HOSTNAME");
std::string hostname_cmd;
- if(temp)
- {
+ if (temp) {
hostname_cmd = temp;
- }
- else
- {
+ } else {
hostname_cmd = cmSystemTools::FindProgram("hostname", paths);
- }
+ }
std::string siteName = "unknown";
#if defined(_WIN32) && !defined(__CYGWIN__)
std::string host;
- if(cmSystemTools::ReadRegistryValue
- ("HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\"
- "Control\\ComputerName\\ComputerName;ComputerName", host))
- {
+ if (cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\"
+ "Control\\ComputerName\\ComputerName;ComputerName",
+ host)) {
siteName = host;
- }
+ }
#else
// try to find the hostname for this computer
- if (!cmSystemTools::IsOff(hostname_cmd.c_str()))
- {
+ if (!cmSystemTools::IsOff(hostname_cmd.c_str())) {
std::string host;
- cmSystemTools::RunSingleCommand(hostname_cmd.c_str(),
- &host, 0, 0, cmSystemTools::OUTPUT_NONE);
+ cmSystemTools::RunSingleCommand(hostname_cmd.c_str(), &host, CM_NULLPTR,
+ CM_NULLPTR, CM_NULLPTR,
+ cmSystemTools::OUTPUT_NONE);
// got the hostname
- if (host.length())
- {
+ if (!host.empty()) {
// remove any white space from the host name
std::string hostRegExp = "[ \t\n\r]*([^\t\n\r ]*)[ \t\n\r]*";
- cmsys::RegularExpression hostReg (hostRegExp.c_str());
- if (hostReg.find(host.c_str()))
- {
+ cmsys::RegularExpression hostReg(hostRegExp.c_str());
+ if (hostReg.find(host.c_str())) {
// strip whitespace
host = hostReg.match(1);
- }
+ }
- if(host.length())
- {
+ if (!host.empty()) {
siteName = host;
- }
}
}
+ }
#endif
- this->Makefile->
- AddCacheDefinition(args[0].c_str(),
- siteName.c_str(),
- "Name of the computer/site where compile is being run",
- cmCacheManager::STRING);
+ this->Makefile->AddCacheDefinition(
+ args[0], siteName.c_str(),
+ "Name of the computer/site where compile is being run",
+ cmStateEnums::STRING);
return true;
}
-
diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h
index 52a63bc9c..6c65480ed 100644
--- a/Source/cmSiteNameCommand.h
+++ b/Source/cmSiteNameCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSiteNameCommand_h
#define cmSiteNameCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmSiteNameCommand
* \brief site_name command
*
@@ -25,48 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmSiteNameCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSiteNameCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "site_name";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Set the given variable to the name of the computer.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " site_name(variable)\n";
- }
-
- cmTypeMacro(cmSiteNameCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 8bb7d96f5..5c4f18b40 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -1,138 +1,125 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceFile.h"
+#include <sstream>
+
+#include "cmCustomCommand.h"
#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
+#include "cmState.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include "cmDocumentCompileDefinitions.h"
-//----------------------------------------------------------------------------
-cmSourceFile::cmSourceFile(cmMakefile* mf, const char* name):
- Location(mf, name)
+cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name)
+ : Location(mf, name)
{
- this->CustomCommand = 0;
- this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
+ this->CustomCommand = CM_NULLPTR;
this->FindFullPathFailed = false;
+ this->IsUiFile = (".ui" == cmSystemTools::GetFilenameLastExtension(
+ this->Location.GetName()));
}
-//----------------------------------------------------------------------------
cmSourceFile::~cmSourceFile()
{
- this->SetCustomCommand(0);
+ this->SetCustomCommand(CM_NULLPTR);
}
-//----------------------------------------------------------------------------
std::string const& cmSourceFile::GetExtension() const
{
return this->Extension;
}
-//----------------------------------------------------------------------------
-const char* cmSourceFile::GetLanguage()
+const std::string cmSourceFile::propLANGUAGE = "LANGUAGE";
+
+void cmSourceFile::SetObjectLibrary(std::string const& objlib)
+{
+ this->ObjectLibrary = objlib;
+}
+
+std::string cmSourceFile::GetObjectLibrary() const
+{
+ return this->ObjectLibrary;
+}
+
+std::string cmSourceFile::GetLanguage()
{
// If the language was set explicitly by the user then use it.
- if(const char* lang = this->GetProperty("LANGUAGE"))
- {
+ if (const char* lang = this->GetProperty(propLANGUAGE)) {
return lang;
- }
+ }
// Perform computation needed to get the language if necessary.
- if(this->FullPath.empty() && this->Language.empty())
- {
+ if (this->FullPath.empty() && this->Language.empty()) {
// If a known extension is given or a known full path is given
// then trust that the current extension is sufficient to
// determine the language. This will fail only if the user
// specifies a full path to the source but leaves off the
// extension, which is kind of weird.
- if(this->Location.ExtensionIsAmbiguous() &&
- this->Location.DirectoryIsAmbiguous())
- {
+ if (this->Location.ExtensionIsAmbiguous() &&
+ this->Location.DirectoryIsAmbiguous()) {
// Finalize the file location to get the extension and set the
// language.
this->GetFullPath();
- }
- else
- {
+ } else {
// Use the known extension to get the language if possible.
std::string ext =
cmSystemTools::GetFilenameLastExtension(this->Location.GetName());
this->CheckLanguage(ext);
- }
}
+ }
// Now try to determine the language.
return static_cast<cmSourceFile const*>(this)->GetLanguage();
}
-//----------------------------------------------------------------------------
-const char* cmSourceFile::GetLanguage() const
+std::string cmSourceFile::GetLanguage() const
{
// If the language was set explicitly by the user then use it.
- if(const char* lang = this->GetProperty("LANGUAGE"))
- {
+ if (const char* lang = this->GetProperty(propLANGUAGE)) {
return lang;
- }
+ }
// If the language was determined from the source file extension use it.
- if(!this->Language.empty())
- {
- return this->Language.c_str();
- }
+ if (!this->Language.empty()) {
+ return this->Language;
+ }
// The language is not known.
- return 0;
+ return "";
}
-//----------------------------------------------------------------------------
cmSourceFileLocation const& cmSourceFile::GetLocation() const
{
- return this->Location;
+ return this->Location;
}
-//----------------------------------------------------------------------------
std::string const& cmSourceFile::GetFullPath(std::string* error)
{
- if(this->FullPath.empty())
- {
- if(this->FindFullPath(error))
- {
+ if (this->FullPath.empty()) {
+ if (this->FindFullPath(error)) {
this->CheckExtension();
- }
}
+ }
return this->FullPath;
}
-//----------------------------------------------------------------------------
std::string const& cmSourceFile::GetFullPath() const
{
return this->FullPath;
}
-//----------------------------------------------------------------------------
bool cmSourceFile::FindFullPath(std::string* error)
{
// If thie method has already failed once do not try again.
- if(this->FindFullPathFailed)
- {
+ if (this->FindFullPathFailed) {
return false;
- }
+ }
// If the file is generated compute the location without checking on
// disk.
- if(this->GetPropertyAsBool("GENERATED"))
- {
+ if (this->GetPropertyAsBool("GENERATED")) {
// The file is either already a full path or is relative to the
// build directory for the target.
this->Location.DirectoryUseBinary();
@@ -140,170 +127,140 @@ bool cmSourceFile::FindFullPath(std::string* error)
this->FullPath += "/";
this->FullPath += this->Location.GetName();
return true;
- }
+ }
// The file is not generated. It must exist on disk.
- cmMakefile* mf = this->Location.GetMakefile();
- const char* tryDirs[3] = {0, 0, 0};
- if(this->Location.DirectoryIsAmbiguous())
- {
- tryDirs[0] = mf->GetCurrentDirectory();
- tryDirs[1] = mf->GetCurrentOutputDirectory();
- }
- else
- {
+ 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] = "";
- }
- const std::vector<std::string>& srcExts = mf->GetSourceExtensions();
- const std::vector<std::string>& hdrExts = mf->GetHeaderExtensions();
- for(const char* const* di = tryDirs; *di; ++di)
- {
+ }
+ 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())
- {
+ if (!tryPath.empty()) {
tryPath += "/";
- }
+ }
tryPath += this->Location.GetName();
- tryPath = cmSystemTools::CollapseFullPath(tryPath.c_str(), *di);
- if(this->TryFullPath(tryPath.c_str(), 0))
- {
+ tryPath = cmSystemTools::CollapseFullPath(tryPath, *di);
+ if (this->TryFullPath(tryPath, "")) {
return true;
- }
- for(std::vector<std::string>::const_iterator ei = srcExts.begin();
- ei != srcExts.end(); ++ei)
- {
- if(this->TryFullPath(tryPath.c_str(), ei->c_str()))
- {
+ }
+ for (std::vector<std::string>::const_iterator ei = srcExts.begin();
+ ei != srcExts.end(); ++ei) {
+ if (this->TryFullPath(tryPath, *ei)) {
return true;
- }
}
- for(std::vector<std::string>::const_iterator ei = hdrExts.begin();
- ei != hdrExts.end(); ++ei)
- {
- if(this->TryFullPath(tryPath.c_str(), ei->c_str()))
- {
+ }
+ for (std::vector<std::string>::const_iterator ei = hdrExts.begin();
+ ei != hdrExts.end(); ++ei) {
+ if (this->TryFullPath(tryPath, *ei)) {
return true;
- }
}
}
+ }
- cmOStringStream e;
+ std::ostringstream e;
std::string missing = this->Location.GetDirectory();
- if(!missing.empty())
- {
+ 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)
- {
+ 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)
- {
+ }
+ for (std::vector<std::string>::const_iterator ext = hdrExts.begin();
+ ext != hdrExts.end(); ++ext) {
e << " ." << *ext;
- }
- if(error)
- {
+ }
+ if (error) {
*error = e.str();
- }
- else
- {
+ } else {
this->Location.GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
- }
+ }
this->FindFullPathFailed = true;
return false;
}
-//----------------------------------------------------------------------------
-bool cmSourceFile::TryFullPath(const char* tp, const char* ext)
+bool cmSourceFile::TryFullPath(const std::string& path, const std::string& ext)
{
- std::string tryPath = tp;
- if(ext && *ext)
- {
+ std::string tryPath = path;
+ if (!ext.empty()) {
tryPath += ".";
tryPath += ext;
- }
- if(cmSystemTools::FileExists(tryPath.c_str()))
- {
+ }
+ if (cmSystemTools::FileExists(tryPath.c_str())) {
this->FullPath = tryPath;
return true;
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
void cmSourceFile::CheckExtension()
{
// Compute the extension.
std::string realExt =
cmSystemTools::GetFilenameLastExtension(this->FullPath);
- if(!realExt.empty())
- {
+ if (!realExt.empty()) {
// Store the extension without the leading '.'.
this->Extension = realExt.substr(1);
- }
+ }
// Look for object files.
- if(this->Extension == "obj" ||
- this->Extension == "o" ||
- this->Extension == "lo")
- {
+ if (this->Extension == "obj" || this->Extension == "o" ||
+ this->Extension == "lo") {
this->SetProperty("EXTERNAL_OBJECT", "1");
- }
+ }
// Try to identify the source file language from the extension.
- if(this->Language.empty())
- {
+ if (this->Language.empty()) {
this->CheckLanguage(this->Extension);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmSourceFile::CheckLanguage(std::string const& ext)
{
// Try to identify the source file language from the extension.
- cmMakefile* mf = this->Location.GetMakefile();
- cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator();
- if(const char* l = gg->GetLanguageFromExtension(ext.c_str()))
- {
+ cmMakefile const* mf = this->Location.GetMakefile();
+ cmGlobalGenerator* gg = mf->GetGlobalGenerator();
+ std::string l = gg->GetLanguageFromExtension(ext.c_str());
+ if (!l.empty()) {
this->Language = l;
- }
+ }
}
-//----------------------------------------------------------------------------
bool cmSourceFile::Matches(cmSourceFileLocation const& loc)
{
return this->Location.Matches(loc);
}
-//----------------------------------------------------------------------------
-void cmSourceFile::SetProperty(const char* prop, const char* value)
+void cmSourceFile::SetProperty(const std::string& prop, const char* value)
{
- if (!prop)
- {
- return;
- }
+ this->Properties.SetProperty(prop, value);
- this->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE);
+ if (this->IsUiFile) {
+ cmMakefile const* mf = this->Location.GetMakefile();
+ if (prop == "AUTOUIC_OPTIONS") {
+ const_cast<cmMakefile*>(mf)->AddQtUiFileWithOptions(this);
+ }
+ }
}
-//----------------------------------------------------------------------------
-void cmSourceFile::AppendProperty(const char* prop, const char* value,
+void cmSourceFile::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
- if (!prop)
- {
- return;
- }
- this->Properties.AppendProperty(prop, value, cmProperty::SOURCE_FILE,
- asString);
+ this->Properties.AppendProperty(prop, value, asString);
}
-//----------------------------------------------------------------------------
-const char* cmSourceFile::GetPropertyForUser(const char *prop)
+const char* cmSourceFile::GetPropertyForUser(const std::string& prop)
{
// This method is a consequence of design history and backwards
// compatibility. GetProperty is (and should be) a const method.
@@ -319,239 +276,56 @@ const char* cmSourceFile::GetPropertyForUser(const char *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(strcmp(prop, "LOCATION") == 0)
- {
+ if (prop == "LOCATION") {
// Commit to a location.
this->GetFullPath();
- }
+ }
// Perform the normal property lookup.
return this->GetProperty(prop);
}
-//----------------------------------------------------------------------------
-const char* cmSourceFile::GetProperty(const char* prop) const
+const char* cmSourceFile::GetProperty(const std::string& prop) const
{
// Check for computed properties.
- if(strcmp(prop, "LOCATION") == 0)
- {
- if(this->FullPath.empty())
- {
- return 0;
- }
- else
- {
- return this->FullPath.c_str();
- }
+ if (prop == "LOCATION") {
+ if (this->FullPath.empty()) {
+ return CM_NULLPTR;
}
-
- bool chain = false;
- const char *retVal =
- this->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE, chain);
- if (chain)
- {
- cmMakefile* mf = this->Location.GetMakefile();
- return mf->GetProperty(prop,cmProperty::SOURCE_FILE);
+ return this->FullPath.c_str();
+ }
+
+ const char* retVal = this->Properties.GetPropertyValue(prop);
+ if (!retVal) {
+ cmMakefile const* mf = this->Location.GetMakefile();
+ const bool chain =
+ mf->GetState()->IsPropertyChained(prop, cmProperty::SOURCE_FILE);
+ if (chain) {
+ return mf->GetProperty(prop, chain);
}
+ }
return retVal;
}
-//----------------------------------------------------------------------------
-bool cmSourceFile::GetPropertyAsBool(const char* prop) const
+bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
{
return cmSystemTools::IsOn(this->GetProperty(prop));
}
-//----------------------------------------------------------------------------
cmCustomCommand* cmSourceFile::GetCustomCommand()
{
return this->CustomCommand;
}
-//----------------------------------------------------------------------------
cmCustomCommand const* cmSourceFile::GetCustomCommand() const
{
return this->CustomCommand;
}
-//----------------------------------------------------------------------------
void cmSourceFile::SetCustomCommand(cmCustomCommand* cc)
{
cmCustomCommand* old = this->CustomCommand;
this->CustomCommand = cc;
delete old;
}
-
-//----------------------------------------------------------------------------
-void cmSourceFile::DefineProperties(cmake *cm)
-{
- // define properties
- cm->DefineProperty
- ("ABSTRACT", cmProperty::SOURCE_FILE,
- "Is this source file an abstract class.",
- "A property on a source file that indicates if the source file "
- "represents a class that is abstract. This only makes sense for "
- "languages that have a notion of an abstract class and it is "
- "only used by some tools that wrap classes into other languages.");
-
- cm->DefineProperty
- ("COMPILE_FLAGS", cmProperty::SOURCE_FILE,
- "Additional flags to be added when compiling this source file.",
- "These flags will be added to the list of compile flags when "
- "this source file builds. Use COMPILE_DEFINITIONS to pass additional "
- "preprocessor definitions.");
-
- cm->DefineProperty
- ("COMPILE_DEFINITIONS", cmProperty::SOURCE_FILE,
- "Preprocessor definitions for compiling a source file.",
- "The COMPILE_DEFINITIONS property may be set to a "
- "semicolon-separated list of preprocessor "
- "definitions using the syntax VAR or VAR=value. Function-style "
- "definitions are not supported. CMake will automatically escape "
- "the value correctly for the native build system (note that CMake "
- "language syntax may require escapes to specify some values). "
- "This property may be set on a per-configuration basis using the name "
- "COMPILE_DEFINITIONS_<CONFIG> where <CONFIG> is an upper-case name "
- "(ex. \"COMPILE_DEFINITIONS_DEBUG\").\n"
- "CMake will automatically drop some definitions that "
- "are not supported by the native build tool. "
- "The VS6 IDE does not support definition values with spaces "
- "(but NMake does). Xcode does not support per-configuration "
- "definitions on source files.\n"
- CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
-
- cm->DefineProperty
- ("COMPILE_DEFINITIONS_<CONFIG>", cmProperty::SOURCE_FILE,
- "Per-configuration preprocessor definitions on a source file.",
- "This is the configuration-specific version of "
- "COMPILE_DEFINITIONS. Note that Xcode does not support "
- "per-configuration source file flags so this property will "
- "be ignored by the Xcode generator.");
-
- cm->DefineProperty
- ("EXTERNAL_OBJECT", cmProperty::SOURCE_FILE,
- "If set to true then this is an object file.",
- "If this property is set to true then the source file "
- "is really an object file and should not be compiled. "
- "It will still be linked into the target though.");
-
- cm->DefineProperty
- ("Fortran_FORMAT", cmProperty::SOURCE_FILE,
- "Set to FIXED or FREE to indicate the Fortran source layout.",
- "This property tells CMake whether a given Fortran source file "
- "uses fixed-format or free-format. "
- "CMake will pass the corresponding format flag to the compiler. "
- "Consider using the target-wide Fortran_FORMAT property if all "
- "source files in a target share the same format.");
-
- cm->DefineProperty
- ("GENERATED", cmProperty::SOURCE_FILE,
- "Is this source file generated as part of the build process.",
- "If a source file is generated by the build process CMake will "
- "handle it differently in terms of dependency checking etc. "
- "Otherwise having a non-existent source file could create problems.");
-
- cm->DefineProperty
- ("HEADER_FILE_ONLY", cmProperty::SOURCE_FILE,
- "Is this source file only a header file.",
- "A property on a source file that indicates if the source file "
- "is a header file with no associated implementation. This is "
- "set automatically based on the file extension and is used by "
- "CMake to determine if certain dependency information should be "
- "computed.");
-
- cm->DefineProperty
- ("KEEP_EXTENSION", cmProperty::SOURCE_FILE,
- "Make the output file have the same extension as the source file.",
- "If this property is set then the file extension of the output "
- "file will be the same as that of the source file. Normally "
- "the output file extension is computed based on the language "
- "of the source file, for example .cxx will go to a .o extension.");
-
- cm->DefineProperty
- ("LABELS", cmProperty::SOURCE_FILE,
- "Specify a list of text labels associated with a source file.",
- "This property has meaning only when the source file is listed in "
- "a target whose LABELS property is also set. "
- "No other semantics are currently specified.");
-
- cm->DefineProperty
- ("LANGUAGE", cmProperty::SOURCE_FILE,
- "What programming language is the file.",
- "A property that can be set to indicate what programming language "
- "the source file is. If it is not set the language is determined "
- "based on the file extension. Typical values are CXX C etc. Setting "
- "this property for a file means this file will be compiled. "
- "Do not set this for headers or files that should not be compiled.");
-
- cm->DefineProperty
- ("LOCATION", cmProperty::SOURCE_FILE,
- "The full path to a source file.",
- "A read only property on a SOURCE FILE that contains the full path "
- "to the source file.");
-
- cm->DefineProperty
- ("MACOSX_PACKAGE_LOCATION", cmProperty::SOURCE_FILE,
- "Place a source file inside a Mac OS X bundle, CFBundle, or framework.",
- "Executable targets with the MACOSX_BUNDLE property set are built "
- "as Mac OS X application bundles on Apple platforms. "
- "Shared library targets with the FRAMEWORK property set are built "
- "as Mac OS X frameworks on Apple platforms. "
- "Module library targets with the BUNDLE property set are built "
- "as Mac OS X CFBundle bundles on Apple platforms. "
- "Source files listed in the target with this property set will "
- "be copied to a directory inside the bundle or framework content "
- "folder specified by the property value. "
- "For bundles the content folder is \"<name>.app/Contents\". "
- "For frameworks the content folder is "
- "\"<name>.framework/Versions/<version>\". "
- "For cfbundles the content folder is "
- "\"<name>.bundle/Contents\" (unless the extension is changed). "
- "See the PUBLIC_HEADER, PRIVATE_HEADER, and RESOURCE target "
- "properties for specifying files meant for Headers, PrivateHeaders, "
- "or Resources directories.");
-
- cm->DefineProperty
- ("OBJECT_DEPENDS", cmProperty::SOURCE_FILE,
- "Additional files on which a compiled object file depends.",
- "Specifies a semicolon-separated list of full-paths to files on which "
- "any object files compiled from this source file depend. "
- "An object file will be recompiled if any of the named files is newer "
- "than it.\n"
- "This property need not be used to specify the dependency of a "
- "source file on a generated header file that it includes. "
- "Although the property was originally introduced for this purpose, it "
- "is no longer necessary. "
- "If the generated header file is created by a custom command in the "
- "same target as the source file, the automatic dependency scanning "
- "process will recognize the dependency. "
- "If the generated header file is created by another target, an "
- "inter-target dependency should be created with the add_dependencies "
- "command (if one does not already exist due to linking relationships).");
-
- cm->DefineProperty
- ("OBJECT_OUTPUTS", cmProperty::SOURCE_FILE,
- "Additional outputs for a Makefile rule.",
- "Additional outputs created by compilation of this source file. "
- "If any of these outputs is missing the object will be recompiled. "
- "This is supported only on Makefile generators and will be ignored "
- "on other generators.");
-
- cm->DefineProperty
- ("SYMBOLIC", cmProperty::SOURCE_FILE,
- "Is this just a name for a rule.",
- "If SYMBOLIC (boolean) is set to true the build system will be "
- "informed that the source file is not actually created on disk but "
- "instead used as a symbolic name for a build rule.");
-
- cm->DefineProperty
- ("WRAP_EXCLUDE", cmProperty::SOURCE_FILE,
- "Exclude this source file from any code wrapping techniques.",
- "Some packages can wrap source files into alternate languages "
- "to provide additional functionality. For example, C++ code "
- "can be wrapped into Java or Python etc using SWIG etc. "
- "If WRAP_EXCLUDE is set to true (1 etc) that indicates that "
- "this source file should not be wrapped.");
-}
-
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 6c68b8745..0be659c5f 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -1,22 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSourceFile_h
#define cmSourceFile_h
-#include "cmSourceFileLocation.h"
-#include "cmCustomCommand.h"
+#include "cmConfigure.h"
+
#include "cmPropertyMap.h"
+#include "cmSourceFileLocation.h"
-class cmake;
+#include <string>
+#include <vector>
+
+class cmCustomCommand;
+class cmMakefile;
/** \class cmSourceFile
* \brief Represent a class loaded from a makefile.
@@ -31,7 +27,7 @@ public:
* Construct with the makefile storing the source and the initial
* name referencing it.
*/
- cmSourceFile(cmMakefile* mf, const char* name);
+ cmSourceFile(cmMakefile* mf, const std::string& name);
~cmSourceFile();
@@ -40,17 +36,18 @@ public:
*/
cmCustomCommand* GetCustomCommand();
cmCustomCommand const* GetCustomCommand() const;
- void SetCustomCommand(cmCustomCommand *cc);
+ void SetCustomCommand(cmCustomCommand* cc);
///! Set/Get a property of this source file
- void SetProperty(const char *prop, const char *value);
- void AppendProperty(const char* prop, const char* value,bool asString=false);
- const char *GetProperty(const char *prop) const;
- bool GetPropertyAsBool(const char *prop) const;
+ 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) 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 char *prop);
+ const char* GetPropertyForUser(const std::string& prop);
/**
* The full path to the file. The non-const version of this method
@@ -60,7 +57,7 @@ public:
* horrible interface, but is necessary for backwards
* compatibility).
*/
- std::string const& GetFullPath(std::string* error = 0);
+ std::string const& GetFullPath(std::string* error = CM_NULLPTR);
std::string const& GetFullPath() const;
/**
@@ -78,20 +75,18 @@ public:
/**
* Get the language of the compiler to use for this source file.
*/
- const char* GetLanguage();
- const char* GetLanguage() const;
+ std::string GetLanguage();
+ std::string GetLanguage() const;
/**
* Return the vector that holds the list of dependencies
*/
- const std::vector<std::string> &GetDepends() const {return this->Depends;}
- void AddDepend(const char* d) { this->Depends.push_back(d); }
+ const std::vector<std::string>& GetDepends() const { return this->Depends; }
+ void AddDepend(const std::string& d) { this->Depends.push_back(d); }
// Get the properties
- cmPropertyMap &GetProperties() { return this->Properties; };
-
- // Define the properties
- static void DefineProperties(cmake *cm);
+ cmPropertyMap& GetProperties() { return this->Properties; }
+ const cmPropertyMap& GetProperties() const { return this->Properties; }
/**
* Check whether the given source file location could refer to this
@@ -99,6 +94,9 @@ public:
*/
bool Matches(cmSourceFileLocation const&);
+ void SetObjectLibrary(std::string const& objlib);
+ std::string GetObjectLibrary() const;
+
private:
cmSourceFileLocation Location;
cmPropertyMap Properties;
@@ -106,14 +104,17 @@ private:
std::string Extension;
std::string Language;
std::string FullPath;
+ std::string ObjectLibrary;
+ std::vector<std::string> Depends;
bool FindFullPathFailed;
+ bool IsUiFile;
bool FindFullPath(std::string* error);
- bool TryFullPath(const char* tryPath, const char* ext);
+ bool TryFullPath(const std::string& path, const std::string& ext);
void CheckExtension();
void CheckLanguage(std::string const& ext);
- std::vector<std::string> Depends;
+ static const std::string propLANGUAGE;
};
// TODO: Factor out into platform information modules.
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 5525b618a..86711d784 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -1,287 +1,250 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceFileLocation.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
+#include "cmConfigure.h"
+
+#include "cmAlgorithms.h"
#include "cmGlobalGenerator.h"
+#include "cmMakefile.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(cmMakefile* mf, const char* name): Makefile(mf)
+cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc)
+ : Makefile(loc.Makefile)
{
- this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name);
+ this->AmbiguousDirectory = loc.AmbiguousDirectory;
+ this->AmbiguousExtension = loc.AmbiguousExtension;
+ this->Directory = loc.Directory;
+ 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)
+ : Makefile(mf)
+{
+ this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str());
this->AmbiguousExtension = true;
this->Directory = cmSystemTools::GetFilenamePath(name);
+ if (cmSystemTools::FileIsFullPath(this->Directory.c_str())) {
+ this->Directory = cmSystemTools::CollapseFullPath(this->Directory);
+ }
this->Name = cmSystemTools::GetFilenameName(name);
this->UpdateExtension(name);
}
-//----------------------------------------------------------------------------
-void cmSourceFileLocation::Update(const char* name)
-{
- if(this->AmbiguousDirectory)
- {
- this->UpdateDirectory(name);
- }
- if(this->AmbiguousExtension)
- {
- this->UpdateExtension(name);
- }
-}
-
-//----------------------------------------------------------------------------
void cmSourceFileLocation::Update(cmSourceFileLocation const& loc)
{
- if(this->AmbiguousDirectory && !loc.AmbiguousDirectory)
- {
+ if (this->AmbiguousDirectory && !loc.AmbiguousDirectory) {
this->Directory = loc.Directory;
this->AmbiguousDirectory = false;
- }
- if(this->AmbiguousExtension && !loc.AmbiguousExtension)
- {
+ }
+ if (this->AmbiguousExtension && !loc.AmbiguousExtension) {
this->Name = loc.Name;
this->AmbiguousExtension = false;
- }
+ }
}
-//----------------------------------------------------------------------------
void cmSourceFileLocation::DirectoryUseSource()
{
- if(this->AmbiguousDirectory)
- {
- this->Directory =
- cmSystemTools::CollapseFullPath(
- this->Directory.c_str(), this->Makefile->GetCurrentDirectory());
+ assert(this->Makefile);
+ if (this->AmbiguousDirectory) {
+ this->Directory = cmSystemTools::CollapseFullPath(
+ this->Directory, this->Makefile->GetCurrentSourceDirectory());
this->AmbiguousDirectory = false;
- }
+ }
}
-//----------------------------------------------------------------------------
void cmSourceFileLocation::DirectoryUseBinary()
{
- if(this->AmbiguousDirectory)
- {
- this->Directory =
- cmSystemTools::CollapseFullPath(
- this->Directory.c_str(), this->Makefile->GetCurrentOutputDirectory());
+ assert(this->Makefile);
+ if (this->AmbiguousDirectory) {
+ this->Directory = cmSystemTools::CollapseFullPath(
+ this->Directory, this->Makefile->GetCurrentBinaryDirectory());
this->AmbiguousDirectory = false;
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmSourceFileLocation::UpdateExtension(const char* name)
+void cmSourceFileLocation::UpdateExtension(const std::string& name)
{
+ assert(this->Makefile);
// Check the extension.
std::string ext = cmSystemTools::GetFilenameLastExtension(name);
- if(!ext.empty()) { ext = ext.substr(1); }
+ if (!ext.empty()) {
+ ext = ext.substr(1);
+ }
// The global generator checks extensions of enabled languages.
- cmGlobalGenerator* gg =
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
- cmMakefile* mf = this->Makefile;
- const std::vector<std::string>& srcExts = mf->GetSourceExtensions();
- const std::vector<std::string>& hdrExts = mf->GetHeaderExtensions();
- if(gg->GetLanguageFromExtension(ext.c_str()) ||
- std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end() ||
- std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end())
- {
+ 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();
+ 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()) {
// This is a known extension. Use the given filename with extension.
this->Name = cmSystemTools::GetFilenameName(name);
this->AmbiguousExtension = false;
- }
- else
- {
+ } else {
// This is not a known extension. See if the file exists on disk as
// named.
std::string tryPath;
- if(this->AmbiguousDirectory)
- {
+ if (this->AmbiguousDirectory) {
// 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->GetCurrentDirectory();
+ tryPath = this->Makefile->GetCurrentSourceDirectory();
tryPath += "/";
- }
- if(!this->Directory.empty())
- {
+ }
+ if (!this->Directory.empty()) {
tryPath += this->Directory;
tryPath += "/";
- }
+ }
tryPath += this->Name;
- if(cmSystemTools::FileExists(tryPath.c_str(), true))
- {
+ if (cmSystemTools::FileExists(tryPath.c_str(), true)) {
// We found a source file named by the user on disk. Trust it's
// extension.
this->Name = cmSystemTools::GetFilenameName(name);
this->AmbiguousExtension = false;
// If the directory was ambiguous, it isn't anymore.
- if(this->AmbiguousDirectory)
- {
+ if (this->AmbiguousDirectory) {
this->DirectoryUseSource();
- }
}
}
+ }
}
-//----------------------------------------------------------------------------
-void cmSourceFileLocation::UpdateDirectory(const char* name)
-{
- // If a full path was given we know the directory.
- if(cmSystemTools::FileIsFullPath(name))
- {
- this->Directory = cmSystemTools::GetFilenamePath(name);
- this->AmbiguousDirectory = false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool
-cmSourceFileLocation
-::MatchesAmbiguousExtension(cmSourceFileLocation const& loc) const
+bool cmSourceFileLocation::MatchesAmbiguousExtension(
+ cmSourceFileLocation const& loc) const
{
+ assert(this->Makefile);
// This location's extension is not ambiguous but loc's extension
// is. See if the names match as-is.
- if(this->Name == loc.Name)
- {
+ if (this->Name == loc.Name) {
return true;
- }
+ }
// Check if loc's name could possibly be extended to our name by
// adding an extension.
- if(!(this->Name.size() > loc.Name.size() &&
- this->Name.substr(0, loc.Name.size()) == loc.Name &&
- this->Name[loc.Name.size()] == '.'))
- {
+ if (!(this->Name.size() > loc.Name.size() &&
+ this->Name[loc.Name.size()] == '.' &&
+ cmHasLiteralPrefixImpl(this->Name.c_str(), loc.Name.c_str(),
+ loc.Name.size()))) {
return false;
- }
+ }
// Only a fixed set of extensions will be tried to match a file on
// disk. One of these must match if loc refers to this source file.
- std::string ext = this->Name.substr(loc.Name.size()+1);
- cmMakefile* mf = this->Makefile;
- const std::vector<std::string>& srcExts = mf->GetSourceExtensions();
- if(std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end())
- {
- return true;
- }
- const std::vector<std::string>& hdrExts = mf->GetHeaderExtensions();
- if(std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end())
- {
+ 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;
- }
- return false;
+ }
+ std::vector<std::string> hdrExts =
+ mf->GetCMakeInstance()->GetHeaderExtensions();
+ return std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end();
}
-//----------------------------------------------------------------------------
bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
{
- if(this->AmbiguousExtension && loc.AmbiguousExtension)
- {
- // Both extensions are ambiguous. Since only the old fixed set of
- // extensions will be tried, the names must match at this point to
- // be the same file.
- if(this->Name != loc.Name)
- {
+ assert(this->Makefile);
+ if (this->AmbiguousExtension == loc.AmbiguousExtension) {
+ // Both extensions are similarly ambiguous. Since only the old fixed set
+ // of extensions will be tried, the names must match at this point to be
+ // the same file.
+ if (this->Name.size() != loc.Name.size() ||
+ !cmSystemTools::ComparePath(this->Name, loc.Name)) {
return false;
- }
}
- else if(this->AmbiguousExtension)
- {
- // Only "this" extension is ambiguous.
- if(!loc.MatchesAmbiguousExtension(*this))
- {
+ } else {
+ const cmSourceFileLocation* loc1;
+ const cmSourceFileLocation* loc2;
+ if (this->AmbiguousExtension) {
+ // Only "this" extension is ambiguous.
+ loc1 = &loc;
+ loc2 = this;
+ } else {
+ // Only "loc" extension is ambiguous.
+ loc1 = this;
+ loc2 = &loc;
+ }
+ if (!loc1->MatchesAmbiguousExtension(*loc2)) {
return false;
- }
- }
- else if(loc.AmbiguousExtension)
- {
- // Only "loc" extension is ambiguous.
- if(!this->MatchesAmbiguousExtension(loc))
- {
- return false;
- }
- }
- else
- {
- // Neither extension is ambiguous.
- if(this->Name != loc.Name)
- {
- return false;
- }
}
+ }
- if(!this->AmbiguousDirectory && !loc.AmbiguousDirectory)
- {
+ if (!this->AmbiguousDirectory && !loc.AmbiguousDirectory) {
// Both sides have absolute directories.
- if(this->Directory != loc.Directory)
- {
+ if (this->Directory != loc.Directory) {
return false;
- }
}
- else if(this->AmbiguousDirectory && loc.AmbiguousDirectory &&
- this->Makefile == loc.Makefile)
- {
- // Both sides have directories relative to the same location.
- if(this->Directory != loc.Directory)
- {
- return false;
+ } else if (this->AmbiguousDirectory && loc.AmbiguousDirectory) {
+ if (this->Makefile == loc.Makefile) {
+ // Both sides have directories relative to the same location.
+ if (this->Directory != loc.Directory) {
+ return false;
}
+ } else {
+ // 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.
+ this->Makefile->IssueMessage(
+ cmake::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.");
+ return false;
}
- else if(this->AmbiguousDirectory && loc.AmbiguousDirectory)
- {
- // 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.
- this->Makefile->IssueMessage(
- cmake::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."
- );
- return false;
- }
- else if(this->AmbiguousDirectory)
- {
+ } else if (this->AmbiguousDirectory) {
// Compare possible directory combinations.
- std::string srcDir =
- cmSystemTools::CollapseFullPath(
- this->Directory.c_str(), this->Makefile->GetCurrentDirectory());
- std::string binDir =
- cmSystemTools::CollapseFullPath(
- this->Directory.c_str(), this->Makefile->GetCurrentOutputDirectory());
- if(srcDir != loc.Directory &&
- binDir != loc.Directory)
- {
+ std::string const& srcDir = cmSystemTools::CollapseFullPath(
+ this->Directory, this->Makefile->GetCurrentSourceDirectory());
+ std::string const& binDir = cmSystemTools::CollapseFullPath(
+ this->Directory, this->Makefile->GetCurrentBinaryDirectory());
+ if (srcDir != loc.Directory && binDir != loc.Directory) {
return false;
- }
}
- else if(loc.AmbiguousDirectory)
- {
+ } else if (loc.AmbiguousDirectory) {
// Compare possible directory combinations.
- std::string srcDir =
- cmSystemTools::CollapseFullPath(
- loc.Directory.c_str(), loc.Makefile->GetCurrentDirectory());
- std::string binDir =
- cmSystemTools::CollapseFullPath(
- loc.Directory.c_str(), loc.Makefile->GetCurrentOutputDirectory());
- if(srcDir != this->Directory &&
- binDir != this->Directory)
- {
+ std::string const& srcDir = cmSystemTools::CollapseFullPath(
+ loc.Directory, loc.Makefile->GetCurrentSourceDirectory());
+ std::string const& binDir = cmSystemTools::CollapseFullPath(
+ loc.Directory, loc.Makefile->GetCurrentBinaryDirectory());
+ if (srcDir != this->Directory && binDir != this->Directory) {
return false;
- }
}
+ }
// File locations match.
this->Update(loc);
diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h
index 216dd07b8..6dbc2daed 100644
--- a/Source/cmSourceFileLocation.h
+++ b/Source/cmSourceFileLocation.h
@@ -1,18 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSourceFileLocation_h
#define cmSourceFileLocation_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
class cmMakefile;
@@ -33,10 +26,13 @@ public:
* Construct for a source file created in a given cmMakefile
* instance with an initial name.
*/
- cmSourceFileLocation(cmMakefile* mf, const char* name);
+ cmSourceFileLocation(cmMakefile const* mf, const std::string& name);
+ cmSourceFileLocation();
+ cmSourceFileLocation(const cmSourceFileLocation& loc);
+ cmSourceFileLocation& operator=(const cmSourceFileLocation& loc);
/**
- * Return whether the givne source file location could refers to the
+ * Return whether the given source file location could refers to the
* same source file as this location given the level of ambiguity in
* each location.
*/
@@ -68,7 +64,7 @@ public:
* Otherwise it will be a relative path (possibly empty) that is
* either with respect to the source or build tree.
*/
- const char* GetDirectory() const { return this->Directory.c_str(); }
+ const std::string& GetDirectory() const { return this->Directory; }
/**
* Get the file name as best is currently known. If
@@ -76,14 +72,14 @@ public:
* final name (but could be). Otherwise the returned name is the
* final name.
*/
- const char* GetName() const { return this->Name.c_str(); }
+ const std::string& GetName() const { return this->Name; }
/**
* Get the cmMakefile instance for which the source file was created.
*/
- cmMakefile* GetMakefile() const { return this->Makefile; }
+ cmMakefile const* GetMakefile() const { return this->Makefile; }
private:
- cmMakefile* Makefile;
+ cmMakefile const* Makefile;
bool AmbiguousDirectory;
bool AmbiguousExtension;
std::string Directory;
@@ -93,9 +89,7 @@ private:
// Update the location with additional knowledge.
void Update(cmSourceFileLocation const& loc);
- void Update(const char* name);
- void UpdateExtension(const char* name);
- void UpdateDirectory(const char* name);
+ void UpdateExtension(const std::string& name);
};
#endif
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index f09976f44..104e959a9 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceGroup.h"
class cmSourceGroupInternals
@@ -17,27 +8,24 @@ public:
std::vector<cmSourceGroup> GroupChildren;
};
-//----------------------------------------------------------------------------
cmSourceGroup::cmSourceGroup(const char* name, const char* regex,
- const char* parentName): Name(name)
+ const char* parentName)
+ : Name(name)
{
this->Internal = new cmSourceGroupInternals;
this->SetGroupRegex(regex);
- if(parentName)
- {
+ if (parentName) {
this->FullName = parentName;
this->FullName += "\\";
- }
+ }
this->FullName += this->Name;
}
-//----------------------------------------------------------------------------
cmSourceGroup::~cmSourceGroup()
{
delete this->Internal;
}
-//----------------------------------------------------------------------------
cmSourceGroup::cmSourceGroup(cmSourceGroup const& r)
{
this->Name = r.Name;
@@ -48,7 +36,6 @@ cmSourceGroup::cmSourceGroup(cmSourceGroup const& r)
this->Internal = new cmSourceGroupInternals(*r.Internal);
}
-//----------------------------------------------------------------------------
cmSourceGroup& cmSourceGroup::operator=(cmSourceGroup const& r)
{
this->Name = r.Name;
@@ -59,98 +46,78 @@ cmSourceGroup& cmSourceGroup::operator=(cmSourceGroup const& r)
return *this;
}
-//----------------------------------------------------------------------------
void cmSourceGroup::SetGroupRegex(const char* regex)
{
- if(regex)
- {
+ if (regex) {
this->GroupRegex.compile(regex);
- }
- else
- {
+ } else {
this->GroupRegex.compile("^$");
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmSourceGroup::AddGroupFile(const char* name)
+void cmSourceGroup::AddGroupFile(const std::string& name)
{
this->GroupFiles.insert(name);
}
-//----------------------------------------------------------------------------
const char* cmSourceGroup::GetName() const
{
return this->Name.c_str();
}
-//----------------------------------------------------------------------------
const char* cmSourceGroup::GetFullName() const
{
return this->FullName.c_str();
}
-//----------------------------------------------------------------------------
bool cmSourceGroup::MatchesRegex(const char* name)
{
return this->GroupRegex.find(name);
}
-//----------------------------------------------------------------------------
bool cmSourceGroup::MatchesFiles(const char* name)
{
- std::set<cmStdString>::const_iterator i = this->GroupFiles.find(name);
- if(i != this->GroupFiles.end())
- {
- return true;
- }
- return false;
+ return this->GroupFiles.find(name) != this->GroupFiles.end();
}
-//----------------------------------------------------------------------------
void cmSourceGroup::AssignSource(const cmSourceFile* sf)
{
this->SourceFiles.push_back(sf);
}
-//----------------------------------------------------------------------------
const std::vector<const cmSourceFile*>& cmSourceGroup::GetSourceFiles() const
{
return this->SourceFiles;
}
-//----------------------------------------------------------------------------
-void cmSourceGroup::AddChild(cmSourceGroup child)
+void cmSourceGroup::AddChild(cmSourceGroup const& child)
{
this->Internal->GroupChildren.push_back(child);
}
-//----------------------------------------------------------------------------
-cmSourceGroup *cmSourceGroup::lookupChild(const char* name)
+cmSourceGroup* cmSourceGroup::LookupChild(const char* name) const
{
// initializing iterators
- std::vector<cmSourceGroup>::iterator iter =
+ std::vector<cmSourceGroup>::const_iterator iter =
this->Internal->GroupChildren.begin();
- std::vector<cmSourceGroup>::iterator end =
+ const std::vector<cmSourceGroup>::const_iterator end =
this->Internal->GroupChildren.end();
// st
- for(;iter!=end; ++iter)
- {
+ for (; iter != end; ++iter) {
std::string sgName = iter->GetName();
// look if descenened is the one were looking for
- if(sgName == name)
- {
- return &(*iter); // if it so return it
- }
+ if (sgName == name) {
+ return const_cast<cmSourceGroup*>(&(*iter)); // if it so return it
}
+ }
// if no child with this name was found return NULL
- return NULL;
+ return CM_NULLPTR;
}
-cmSourceGroup *cmSourceGroup::MatchChildrenFiles(const char *name)
+cmSourceGroup* cmSourceGroup::MatchChildrenFiles(const char* name)
{
// initializing iterators
std::vector<cmSourceGroup>::iterator iter =
@@ -158,23 +125,19 @@ cmSourceGroup *cmSourceGroup::MatchChildrenFiles(const char *name)
std::vector<cmSourceGroup>::iterator end =
this->Internal->GroupChildren.end();
- if(this->MatchesFiles(name))
- {
+ if (this->MatchesFiles(name)) {
return this;
- }
- for(;iter!=end;++iter)
- {
- cmSourceGroup *result = iter->MatchChildrenFiles(name);
- if(result)
- {
+ }
+ for (; iter != end; ++iter) {
+ cmSourceGroup* result = iter->MatchChildrenFiles(name);
+ if (result) {
return result;
- }
}
- return 0;
+ }
+ return CM_NULLPTR;
}
-
-cmSourceGroup *cmSourceGroup::MatchChildrenRegex(const char *name)
+cmSourceGroup* cmSourceGroup::MatchChildrenRegex(const char* name)
{
// initializing iterators
std::vector<cmSourceGroup>::iterator iter =
@@ -182,24 +145,20 @@ cmSourceGroup *cmSourceGroup::MatchChildrenRegex(const char *name)
std::vector<cmSourceGroup>::iterator end =
this->Internal->GroupChildren.end();
- for(;iter!=end; ++iter)
- {
- cmSourceGroup *result = iter->MatchChildrenRegex(name);
- if(result)
- {
+ for (; iter != end; ++iter) {
+ cmSourceGroup* result = iter->MatchChildrenRegex(name);
+ if (result) {
return result;
- }
}
- if(this->MatchesRegex(name))
- {
+ }
+ if (this->MatchesRegex(name)) {
return this;
- }
+ }
- return 0;
+ return CM_NULLPTR;
}
-std::vector<cmSourceGroup> const&
-cmSourceGroup::GetGroupChildren() const
+std::vector<cmSourceGroup> const& cmSourceGroup::GetGroupChildren() const
{
return this->Internal->GroupChildren;
}
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index 11a0c74ae..97affed6e 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -1,22 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSourceGroup_h
#define cmSourceGroup_h
-#include "cmStandardIncludes.h"
-#include <cmsys/RegularExpression.hxx>
+#include "cmConfigure.h"
-class cmSourceFile;
+#include "cmsys/RegularExpression.hxx"
+#include <set>
+#include <string>
+#include <vector>
+class cmSourceFile;
class cmSourceGroupInternals;
/** \class cmSourceGroup
@@ -33,7 +27,7 @@ class cmSourceGroup
{
public:
cmSourceGroup(const char* name, const char* regex,
- const char* parentName=0);
+ const char* parentName = CM_NULLPTR);
cmSourceGroup(cmSourceGroup const& r);
~cmSourceGroup();
cmSourceGroup& operator=(cmSourceGroup const&);
@@ -46,17 +40,17 @@ public:
/**
* Add a file name to the explicit list of files for this group.
*/
- void AddGroupFile(const char* name);
+ void AddGroupFile(const std::string& name);
/**
* Add child to this sourcegroup
*/
- void AddChild(cmSourceGroup child);
+ void AddChild(cmSourceGroup const& child);
/**
* Looks up child and returns it
*/
- cmSourceGroup *lookupChild(const char *name);
+ cmSourceGroup* LookupChild(const char* name) const;
/**
* Get the name of this group.
@@ -82,12 +76,12 @@ public:
* Check if the given name matches this group's explicit file list
* in children.
*/
- cmSourceGroup *MatchChildrenFiles(const char *name);
+ cmSourceGroup* MatchChildrenFiles(const char* name);
/**
* Check if the given name matches this group's regex in children.
*/
- cmSourceGroup *MatchChildrenRegex(const char *name);
+ cmSourceGroup* MatchChildrenRegex(const char* name);
/**
* Assign the given source file to this group. Used only by
@@ -102,6 +96,7 @@ public:
const std::vector<const cmSourceFile*>& GetSourceFiles() const;
std::vector<cmSourceGroup> const& GetGroupChildren() const;
+
private:
/**
* The name of the source group.
@@ -118,7 +113,7 @@ private:
/**
* Set of file names explicitly added to this group.
*/
- std::set<cmStdString> GroupFiles;
+ std::set<std::string> GroupFiles;
/**
* Vector of all source files that have been assigned to
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 9cb80f617..a966300c0 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -1,102 +1,286 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSourceGroupCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <set>
+#include <sstream>
+#include <stddef.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSourceGroupCommand.h"
+#include "cmMakefile.h"
+#include "cmSourceGroup.h"
+#include "cmSystemTools.h"
+
+namespace {
+const size_t RootIndex = 1;
+const size_t FilesWithoutPrefixKeywordIndex = 2;
+const size_t FilesWithPrefixKeywordIndex = 4;
+const size_t PrefixKeywordIndex = 2;
+
+std::vector<std::string> tokenizePath(const std::string& path)
+{
+ return cmSystemTools::tokenize(path, "\\/");
+}
+
+std::string getFullFilePath(const std::string& currentPath,
+ const std::string& path)
+{
+ std::string fullPath = path;
+
+ if (!cmSystemTools::FileIsFullPath(path.c_str())) {
+ fullPath = currentPath;
+ fullPath += "/";
+ fullPath += path;
+ }
+
+ return cmSystemTools::CollapseFullPath(fullPath);
+}
+
+std::set<std::string> getSourceGroupFilesPaths(
+ const std::string& root, const std::vector<std::string>& files)
+{
+ 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 '/'
+ }
+
+ return ret;
+}
+
+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];
+ return false;
+ }
+ }
+
+ 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::string& currentSourceDir)
+{
+ std::vector<std::string> prepared;
+
+ for (; begin != end; ++begin) {
+ prepared.push_back(prepareFilePathForTree(*begin, currentSourceDir));
+ }
+
+ return prepared;
+}
+
+bool addFilesToItsSourceGroups(const std::string& root,
+ const std::set<std::string>& sgFilesPaths,
+ const std::string& prefix, cmMakefile& makefile,
+ std::string& errorMsg)
+{
+ cmSourceGroup* sg;
+
+ for (std::set<std::string>::const_iterator it = sgFilesPaths.begin();
+ it != sgFilesPaths.end(); ++it) {
+
+ std::vector<std::string> tokenizedPath;
+ if (!prefix.empty()) {
+ tokenizedPath = tokenizePath(prefix + '/' + *it);
+ } else {
+ tokenizedPath = tokenizePath(*it);
+ }
+
+ if (tokenizedPath.size() > 1) {
+ tokenizedPath.pop_back();
+
+ sg = addSourceGroup(tokenizedPath, makefile);
+
+ if (!sg) {
+ errorMsg = "Could not create source group for file: " + *it;
+ return false;
+ }
+ const std::string fullPath = getFullFilePath(root, *it);
+ sg->AddGroupFile(fullPath);
+ }
+ }
+
+ return true;
+}
+}
+
+class cmExecutionStatus;
// cmSourceGroupCommand
-bool cmSourceGroupCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
+ }
+
+ if (args[0] == "TREE") {
+ std::string error;
+
+ if (!processTree(args, error)) {
+ this->SetError(error);
+ return false;
}
+ return true;
+ }
+
std::string delimiter = "\\";
- if(this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER"))
- {
+ if (this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER")) {
delimiter = this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
- }
+ }
std::vector<std::string> folders =
cmSystemTools::tokenize(args[0], delimiter);
- cmSourceGroup* sg = 0;
+ cmSourceGroup* sg = CM_NULLPTR;
sg = this->Makefile->GetSourceGroup(folders);
- if(!sg)
- {
+ if (!sg) {
this->Makefile->AddSourceGroup(folders);
sg = this->Makefile->GetSourceGroup(folders);
- }
+ }
- if(!sg)
- {
+ if (!sg) {
this->SetError("Could not create or find source group");
return false;
- }
+ }
// If only two arguments are given, the pre-1.8 version of the
// command is being invoked.
- if(args.size() == 2 && args[1] != "FILES")
- {
+ if (args.size() == 2 && args[1] != "FILES") {
sg->SetGroupRegex(args[1].c_str());
return true;
- }
+ }
// Process arguments.
bool doingFiles = false;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- if(args[i] == "REGULAR_EXPRESSION")
- {
+ 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())
- {
+ if (i + 1 < args.size()) {
++i;
sg->SetGroupRegex(args[i].c_str());
- }
- else
- {
+ } else {
this->SetError("REGULAR_EXPRESSION argument given without a regex.");
return false;
- }
- doingFiles = false;
}
- else if(args[i] == "FILES")
- {
+ doingFiles = false;
+ } else if (args[i] == "FILES") {
// Next arguments will specify files.
doingFiles = true;
- }
- else if(doingFiles)
- {
+ } else if (doingFiles) {
// Convert name to full path and add to the group's list.
- std::string src = args[i].c_str();
- if(!cmSystemTools::FileIsFullPath(src.c_str()))
- {
- src = this->Makefile->GetCurrentDirectory();
+ std::string src = args[i];
+ if (!cmSystemTools::FileIsFullPath(src.c_str())) {
+ src = this->Makefile->GetCurrentSourceDirectory();
src += "/";
src += args[i];
- }
- src = cmSystemTools::CollapseFullPath(src.c_str());
- sg->AddGroupFile(src.c_str());
}
- else
- {
- cmOStringStream err;
- err << "Unknown argument \"" << args[i].c_str() << "\". "
+ 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().c_str());
+ this->SetError(err.str());
return false;
- }
}
+ }
+
+ return true;
+}
+
+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;
+ }
+
+ if (args.size() < 3) {
+ errorMsg = "Missing FILES arguments.";
+ return false;
+ }
+
+ if (args[FilesWithoutPrefixKeywordIndex] != "FILES" &&
+ args[PrefixKeywordIndex] != "PREFIX") {
+ errorMsg = "Unknown argument \"" + args[2] +
+ "\". Perhaps the FILES keyword is missing.\n";
+ return false;
+ }
+
+ if (args[PrefixKeywordIndex] == "PREFIX" &&
+ (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) {
+ errorMsg = "Missing FILES arguments.";
+ return false;
+ }
+
+ return true;
+}
+
+bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
+ std::string& errorMsg)
+{
+ if (!checkTreeArgumentsPreconditions(args, errorMsg)) {
+ return false;
+ }
+
+ const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]);
+ std::string prefix;
+ size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1;
+ if (args[PrefixKeywordIndex] == "PREFIX") {
+ prefix = args[PrefixKeywordIndex + 1];
+ filesBegin = FilesWithPrefixKeywordIndex + 1;
+ }
+
+ const std::vector<std::string> filesVector =
+ prepareFilesPathsForTree(args.begin() + filesBegin, args.end(),
+ this->Makefile->GetCurrentSourceDirectory());
+
+ if (!rootIsPrefix(root, filesVector, errorMsg)) {
+ return false;
+ }
+
+ std::set<std::string> sourceGroupPaths =
+ getSourceGroupFilesPaths(root, filesVector);
+
+ if (!addFilesToItsSourceGroups(root, sourceGroupPaths, prefix,
+ *(this->Makefile), errorMsg)) {
+ return false;
+ }
return true;
}
diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h
index 9f6b7e4f9..7d56b0d65 100644
--- a/Source/cmSourceGroupCommand.h
+++ b/Source/cmSourceGroupCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSourceGroupCommand_h
#define cmSourceGroupCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmSourceGroupCommand
* \brief Adds a cmSourceGroup to the cmMakefile.
*
@@ -26,56 +24,20 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmSourceGroupCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSourceGroupCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "source_group";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Define a grouping for sources in the makefile.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " source_group(name [REGULAR_EXPRESSION regex] "
- "[FILES src1 src2 ...])\n"
- "Defines a group into which sources will be placed in project files. "
- "This is mainly used to setup file tabs in Visual Studio. "
- "Any file whose name is listed or matches the regular expression will "
- "be placed in this group. If a file matches multiple groups, the LAST "
- "group that explicitly lists the file will be favored, if any. If no "
- "group explicitly lists the file, the LAST group whose regular "
- "expression matches the file will be favored.\n"
- "The name of the group may contain backslashes to specify subgroups:\n"
- " source_group(outer\\\\inner ...)\n"
- "For backwards compatibility, this command also supports the "
- "format:\n"
- " source_group(name regex)";
- }
-
- cmTypeMacro(cmSourceGroupCommand, cmCommand);
+ 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;
};
-
-
#endif
diff --git a/Source/cmStandardIncludes.cxx b/Source/cmStandardIncludes.cxx
deleted file mode 100644
index a4bdb2e32..000000000
--- a/Source/cmStandardIncludes.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmStandardIncludes.h"
-#if !defined(CMAKE_NO_ANSI_STRING_STREAM)
-cmOStringStream::cmOStringStream() {}
-cmOStringStream::~cmOStringStream() {}
-#endif
diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h
deleted file mode 100644
index a4aec2e12..000000000
--- a/Source/cmStandardIncludes.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-/**
- * Include header files as a function of the build process, compiler,
- * and operating system.
- */
-#ifndef cmStandardIncludes_h
-#define cmStandardIncludes_h
-
-// include configure generated header to define CMAKE_NO_ANSI_STREAM_HEADERS,
-// CMAKE_NO_STD_NAMESPACE, and other macros.
-#include <cmConfigure.h>
-#include <cmsys/Configure.hxx>
-
-#ifdef _MSC_VER
-#pragma warning ( disable : 4786 )
-#pragma warning ( disable : 4503 )
-#pragma warning ( disable : 4512 ) /* operator=() could not be generated */
-#define CMAKE_NO_ANSI_FOR_SCOPE
-#endif
-
-#ifdef __BORLANDC__
-# pragma warn -8030 /* Temporary used for parameter */
-# pragma warn -8027 /* 'for' not inlined. */
-# pragma warn -8026 /* 'exception' not inlined. */
-# pragma warn -8004 /* value never used */
-#endif
-
-#ifdef __ICL
-#pragma warning ( disable : 985 )
-#pragma warning ( disable : 1572 ) /* floating-point equality test */
-#endif
-
-#include <stdarg.h> // Work-around for SGI MIPSpro 7.4.2m header bug
-
-// This is a hack to prevent warnings about these functions being
-// declared but not referenced.
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma set woff 3970 /* conversion from pointer to same-sized */
-# include <sys/termios.h>
-class cmStandardIncludesHack
-{
-public:
- enum
- {
- Ref1 = sizeof(cfgetospeed(0)),
- Ref2 = sizeof(cfgetispeed(0)),
- Ref3 = sizeof(tcgetattr(0, 0)),
- Ref4 = sizeof(tcsetattr(0, 0, 0)),
- Ref5 = sizeof(cfsetospeed(0,0)),
- Ref6 = sizeof(cfsetispeed(0,0))
- };
-};
-#endif
-
-// Include stream compatibility layer from KWSys.
-// This is needed to work with large file support
-// on some platforms whose stream operators do not
-// support the large integer types.
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <cmsys/IOStream.hxx>
-# undef GetCurrentDirectory // Borland <iosfwd> includes windows.h
-#endif
-
-// Avoid warnings in system headers.
-#if defined(_MSC_VER)
-# pragma warning (push,1)
-#endif
-#if defined(__BORLANDC__)
-# pragma warn -8008 /* condition is always false (RESET BELOW!) */
-# pragma warn -8066 /* unreachable code (RESET BELOW!) */
-#endif
-
-#ifndef CMAKE_NO_ANSI_STREAM_HEADERS
-# include <fstream>
-# include <iostream>
-# include <iomanip>
-#else
-# include <fstream.h>
-# include <iostream.h>
-# include <iomanip.h>
-#endif
-
-#if !defined(CMAKE_NO_ANSI_STRING_STREAM)
-# include <sstream>
-#elif !defined(CMAKE_NO_ANSI_STREAM_HEADERS)
-# include <strstream>
-#else
-# include <strstream.h>
-#endif
-
-// we must have stl with the standard include style
-#include <vector>
-#include <string>
-#include <iterator>
-#include <algorithm>
-#include <functional>
-#include <map>
-#include <list>
-#include <set>
-#include <deque>
-
-#if defined(__BORLANDC__)
-# pragma warn .8008 /* condition is always false (disabled above) */
-# pragma warn .8066 /* unreachable code (disabled above) */
-#endif
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
-// include the "c" string header
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-// Borland C++ defines several of the stdlib.h and string.h symbols in
-// sub-headers search.h and mem.h. These sub-headers have using
-// declarations to pull functions from the std namespace to the global
-// namespace, but they are defined only if the header was not included
-// through the C++-style cstdlib or cstring header. These outer
-// headers are included by the streams library in C++-style and
-// include blockers are put in place that prevent including the
-// C-style versions from ever including the sub-headers. Therefore we
-// have to include the sub-headers here to get the using declarations.
-#if defined(__BORLANDC__)
-# include <mem.h> /* mem... functions from string.h */
-# include <search.h> /* search functions from stdlib.h */
-#endif
-
-
-#if !defined(_WIN32) && defined(__COMO__)
-// Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
-extern "C"
-{
-extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
-extern int pclose (FILE *__stream) __THROW;
-extern char *realpath (__const char *__restrict __name,
- char *__restrict __resolved) __THROW;
-extern char *strdup (__const char *__s) __THROW;
-extern int putenv (char *__string) __THROW;
-}
-#endif
-
-// if std:: is not supported, then just #define it away
-#ifdef CMAKE_NO_STD_NAMESPACE
-#define std
-#endif
-
-// if the compiler does not support ansi for scoping of vars use a
-// #define hack
-#ifdef CMAKE_NO_ANSI_FOR_SCOPE
-#define for if(false) {} else for
-#endif
-
-// Provide std::ios_base on ancient GCC 2.9x
-#if defined(__GNUC__) && __GNUC__ < 3
-namespace std { typedef ios ios_base; }
-#endif
-
-// check for the 720 compiler on the SGI
-// which has some strange properties that I don't think are worth
-// checking for in a general way in configure
-#if defined(__sgi) && !defined(__GNUC__)
-# if (_COMPILER_VERSION >= 730)
-# define CM_SGI_CC_730
-# elif (_COMPILER_VERSION >= 720)
-# define CM_HAS_STD_BUT_NOT_FOR_IOSTREAM
-# endif
-#endif
-
-#ifdef __DECCXX_VER
-# if __DECCXX_VER <= 60390008
-# define CM_HAS_STD_BUT_NOT_FOR_IOSTREAM
-# endif
-#endif
-
-#if defined( _MSC_VER )
-typedef unsigned short mode_t;
-#endif
-
-
-#ifdef CM_HAS_STD_BUT_NOT_FOR_IOSTREAM
-// some compilers have std:: but not for the stream library,
-// so we have to bring it into the std namespace by hand.
-namespace std {
-using ::ostream;
-using ::istream;
-using ::ios;
-using ::cout;
-using ::cerr;
-using ::cin;
-using ::ifstream;
-using ::ofstream;
-
-#if !defined(CMAKE_NO_ANSI_STRING_STREAM)
- using ::ostringstream;
- using ::istringstream;
-#else
- using ::ostrstream;
- using ::istrstream;
-#endif
-
-using ::endl;
-using ::ends;
-using ::flush;
-using ::dec;
-using ::hex;
-using ::setw;
-using ::setiosflags;
-using ::setfill;
-using ::setprecision;
-}
-// The string class is missing these operators so add them
-#if !defined(cmsys_STL_STRING_NEQ_CHAR_DEFINED)
-# define cmsys_STL_STRING_NO_NEQ_CHAR
-inline bool operator!=(std::string const& a, const char* b)
-{ return !(a==std::string(b)); }
-#endif
-
-inline bool operator==(std::string const& a, const char* b)
-{ return (a==std::string(b)); }
-# endif // end CM_SGI_CC_720
-
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma set woff 1375 /* base class destructor not virtual */
-#endif
-
-// use this class to shrink the size of symbols in .o files
-// std::string is really basic_string<....lots of stuff....>
-// when combined with a map or set, the symbols can be > 2000 chars!
-#include <cmsys/String.hxx>
-typedef cmsys::String cmStdString;
-
-// Define cmOStringStream and cmIStringStream wrappers to hide
-// differences between std::stringstream and the old strstream.
-#if !defined(CMAKE_NO_ANSI_STRING_STREAM)
-class cmOStringStream: public std::ostringstream
-{
-public:
- cmOStringStream();
- ~cmOStringStream();
-private:
- cmOStringStream(const cmOStringStream&);
- void operator=(const cmOStringStream&);
-};
-class cmIStringStream: public std::istringstream
-{
-public:
- typedef std::istringstream Superclass;
- cmIStringStream() {}
- cmIStringStream(const std::string& s): Superclass(s) {}
-private:
- cmIStringStream(const cmIStringStream&);
- void operator=(const cmIStringStream&);
-};
-#else
-class cmOStrStreamCleanup
-{
-public:
- cmOStrStreamCleanup(std::ostrstream& ostr): OStrStream(ostr) {}
- ~cmOStrStreamCleanup() { this->OStrStream.rdbuf()->freeze(0); }
- static void IgnoreUnusedVariable(const cmOStrStreamCleanup&) {}
-protected:
- std::ostrstream& OStrStream;
-};
-
-class cmOStringStream: public std::ostrstream
-{
-public:
- typedef std::ostrstream Superclass;
- cmOStringStream() {}
- std::string str()
- {
- cmOStrStreamCleanup cleanup(*this);
- cmOStrStreamCleanup::IgnoreUnusedVariable(cleanup);
- int pcount = this->pcount();
- const char* ptr = this->Superclass::str();
- return std::string(ptr?ptr:"", pcount);
- }
-private:
- cmOStringStream(const cmOStringStream&);
- void operator=(const cmOStringStream&);
-};
-
-class cmIStringStream: private std::string, public std::istrstream
-{
-public:
- typedef std::string StdString;
- typedef std::istrstream IStrStream;
- cmIStringStream(): StdString(), IStrStream(StdString::c_str()) {}
- cmIStringStream(const std::string& s):
- StdString(s), IStrStream(StdString::c_str()) {}
- std::string str() const { return *this; }
- void str(const std::string& s)
- {
- // Very dangerous. If this throws, the object is hosed. When the
- // destructor is later called, the program is hosed too.
- this->~cmIStringStream();
- new (this) cmIStringStream(s);
- }
-private:
- cmIStringStream(const cmIStringStream&);
- void operator=(const cmIStringStream&);
-};
-#endif
-
-/* Poison this operator to avoid common mistakes. */
-extern void operator << (std::ostream&, const cmOStringStream&);
-
-/** Standard documentation entry for cmDocumentation's formatting. */
-struct cmDocumentationEntry
-{
- std::string Name;
- std::string Brief;
- std::string Full;
- cmDocumentationEntry(){};
- cmDocumentationEntry(const char *doc[3])
- { if (doc[0]) this->Name = doc[0];
- if (doc[1]) this->Brief = doc[1];
- if (doc[2]) this->Full = doc[2]; };
- cmDocumentationEntry(const char *n, const char *b, const char *f)
- { if (n) this->Name = n; if (b) this->Brief = b; if (f) this->Full = f; };
-};
-
-/** 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;
-};
-
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma reset woff 1375 /* base class destructor not virtual */
-#endif
-
-// All subclasses of cmCommand or cmCTestGenericHandler should
-// invoke this macro.
-#define cmTypeMacro(thisClass,superclass) \
-virtual const char* GetNameOfClass() { return #thisClass; } \
-typedef superclass Superclass; \
-static bool IsTypeOf(const char *type) \
-{ \
- if ( !strcmp(#thisClass,type) ) \
- { \
- return true; \
- } \
- return Superclass::IsTypeOf(type); \
-} \
-virtual bool IsA(const char *type) \
-{ \
- return thisClass::IsTypeOf(type); \
-} \
-static thisClass* SafeDownCast(cmObject *c) \
-{ \
- if ( c && c->IsA(#thisClass) ) \
- { \
- return static_cast<thisClass *>(c); \
- } \
- return 0;\
-}
-
-
-
-#endif
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index acd636c43..c9f42e4ce 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -1,67 +1,47 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmStandardLexer_h
#define cmStandardLexer_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
/* Disable some warnings. */
#if defined(_MSC_VER)
-# 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(__BORLANDC__)
-# pragma warn -8008 /* condition always returns true */
-# pragma warn -8066 /* unreachable code */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
-
-/* Borland system header defines these macros without first undef-ing them. */
-#if defined(__BORLANDC__) && __BORLANDC__ >= 0x580
-# undef INT8_MIN
-# undef INT16_MIN
-# undef INT32_MIN
-# undef INT8_MAX
-# undef INT16_MAX
-# undef INT32_MAX
-# undef UINT8_MAX
-# undef UINT16_MAX
-# undef UINT32_MAX
-# include <stdint.h>
+#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403
+#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
-
-/* Make sure SGI termios does not define ECHO differently. */
-#if defined(__sgi) && !defined(__GNUC__)
-# include <sys/termios.h>
-# undef ECHO
#endif
-/* Define isatty on windows. */
+/* Make sure isatty is available. */
#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <io.h>
-# if defined( _MSC_VER )
-# define isatty _isatty
-# endif
-# define YY_NO_UNISTD_H 1
+#include <io.h>
+#if defined(_MSC_VER)
+#define isatty _isatty
+#endif
+#else
+#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. */
@@ -70,4 +50,12 @@
#define YY_NO_UNPUT 1
#define ECHO
+#include "cm_kwiml.h"
+typedef KWIML_INT_int8_t flex_int8_t;
+typedef KWIML_INT_uint8_t flex_uint8_t;
+typedef KWIML_INT_int16_t flex_int16_t;
+typedef KWIML_INT_uint16_t flex_uint16_t;
+typedef KWIML_INT_int32_t flex_int32_t;
+typedef KWIML_INT_uint32_t flex_uint32_t;
+
#endif
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
new file mode 100644
index 000000000..92e47f748
--- /dev/null
+++ b/Source/cmState.cxx
@@ -0,0 +1,855 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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 <utility>
+
+#include "cmAlgorithms.h"
+#include "cmCacheManager.h"
+#include "cmCommand.h"
+#include "cmDefinitions.h"
+#include "cmDisallowedCommand.h"
+#include "cmListFileCache.h"
+#include "cmStatePrivate.h"
+#include "cmStateSnapshot.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;
+}
+
+cmState::~cmState()
+{
+ delete this->CacheManager;
+ cmDeleteAll(this->BuiltinCommands);
+ cmDeleteAll(this->ScriptedCommands);
+}
+
+const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
+{
+ switch (targetType) {
+ case cmStateEnums::STATIC_LIBRARY:
+ return "STATIC_LIBRARY";
+ case cmStateEnums::MODULE_LIBRARY:
+ return "MODULE_LIBRARY";
+ case cmStateEnums::SHARED_LIBRARY:
+ return "SHARED_LIBRARY";
+ case cmStateEnums::OBJECT_LIBRARY:
+ return "OBJECT_LIBRARY";
+ case cmStateEnums::EXECUTABLE:
+ return "EXECUTABLE";
+ case cmStateEnums::UTILITY:
+ return "UTILITY";
+ case cmStateEnums::GLOBAL_TARGET:
+ return "GLOBAL_TARGET";
+ case cmStateEnums::INTERFACE_LIBRARY:
+ return "INTERFACE_LIBRARY";
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ return "UNKNOWN_LIBRARY";
+ }
+ assert(false && "Unexpected target type");
+ return CM_NULLPTR;
+}
+
+const char* cmCacheEntryTypes[] = { "BOOL", "PATH", "FILEPATH",
+ "STRING", "INTERNAL", "STATIC",
+ "UNINITIALIZED", CM_NULLPTR };
+
+const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type)
+{
+ if (type > 6) {
+ return cmCacheEntryTypes[6];
+ }
+ return cmCacheEntryTypes[type];
+}
+
+cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s)
+{
+ int i = 0;
+ while (cmCacheEntryTypes[i]) {
+ if (strcmp(s, cmCacheEntryTypes[i]) == 0) {
+ return static_cast<cmStateEnums::CacheEntryType>(i);
+ }
+ ++i;
+ }
+ return cmStateEnums::STRING;
+}
+
+bool cmState::IsCacheEntryType(std::string const& key)
+{
+ for (int i = 0; cmCacheEntryTypes[i]; ++i) {
+ if (strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool cmState::LoadCache(const std::string& path, bool internal,
+ std::set<std::string>& excludes,
+ std::set<std::string>& includes)
+{
+ return this->CacheManager->LoadCache(path, internal, excludes, includes);
+}
+
+bool cmState::SaveCache(const std::string& path)
+{
+ return this->CacheManager->SaveCache(path);
+}
+
+bool cmState::DeleteCache(const std::string& path)
+{
+ return this->CacheManager->DeleteCache(path);
+}
+
+std::vector<std::string> cmState::GetCacheEntryKeys() const
+{
+ std::vector<std::string> definitions;
+ definitions.reserve(this->CacheManager->GetSize());
+ cmCacheManager::CacheIterator cit = this->CacheManager->GetCacheIterator();
+ for (cit.Begin(); !cit.IsAtEnd(); cit.Next()) {
+ definitions.push_back(cit.GetName());
+ }
+ return definitions;
+}
+
+const char* cmState::GetCacheEntryValue(std::string const& key) const
+{
+ cmCacheManager::CacheEntry* e = this->CacheManager->GetCacheEntry(key);
+ if (!e) {
+ return CM_NULLPTR;
+ }
+ return e->Value.c_str();
+}
+
+const char* cmState::GetInitializedCacheValue(std::string const& key) const
+{
+ return this->CacheManager->GetInitializedCacheValue(key);
+}
+
+cmStateEnums::CacheEntryType cmState::GetCacheEntryType(
+ std::string const& key) const
+{
+ cmCacheManager::CacheIterator it =
+ this->CacheManager->GetCacheIterator(key.c_str());
+ return it.GetType();
+}
+
+void cmState::SetCacheEntryValue(std::string const& key,
+ std::string const& value)
+{
+ this->CacheManager->SetCacheEntryValue(key, value);
+}
+
+void cmState::SetCacheEntryProperty(std::string const& key,
+ std::string const& propertyName,
+ std::string const& value)
+{
+ cmCacheManager::CacheIterator it =
+ this->CacheManager->GetCacheIterator(key.c_str());
+ it.SetProperty(propertyName, value.c_str());
+}
+
+void cmState::SetCacheEntryBoolProperty(std::string const& key,
+ std::string const& propertyName,
+ bool value)
+{
+ cmCacheManager::CacheIterator it =
+ this->CacheManager->GetCacheIterator(key.c_str());
+ it.SetProperty(propertyName, value);
+}
+
+std::vector<std::string> cmState::GetCacheEntryPropertyList(
+ const std::string& key)
+{
+ cmCacheManager::CacheIterator it =
+ this->CacheManager->GetCacheIterator(key.c_str());
+ return it.GetPropertyList();
+}
+
+const char* cmState::GetCacheEntryProperty(std::string const& key,
+ std::string const& propertyName)
+{
+ cmCacheManager::CacheIterator it =
+ this->CacheManager->GetCacheIterator(key.c_str());
+ if (!it.PropertyExists(propertyName)) {
+ return CM_NULLPTR;
+ }
+ return it.GetProperty(propertyName);
+}
+
+bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
+ std::string const& propertyName)
+{
+ return this->CacheManager->GetCacheIterator(key.c_str())
+ .GetPropertyAsBool(propertyName);
+}
+
+void cmState::AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString,
+ cmStateEnums::CacheEntryType type)
+{
+ this->CacheManager->AddCacheEntry(key, value, helpString, type);
+}
+
+void cmState::RemoveCacheEntry(std::string const& key)
+{
+ this->CacheManager->RemoveCacheEntry(key);
+}
+
+void cmState::AppendCacheEntryProperty(const std::string& key,
+ const std::string& property,
+ const std::string& value, bool asString)
+{
+ this->CacheManager->GetCacheIterator(key.c_str())
+ .AppendProperty(property, value.c_str(), asString);
+}
+
+void cmState::RemoveCacheEntryProperty(std::string const& key,
+ std::string const& propertyName)
+{
+ this->CacheManager->GetCacheIterator(key.c_str())
+ .SetProperty(propertyName, (void*)CM_NULLPTR);
+}
+
+cmStateSnapshot cmState::Reset()
+{
+ this->GlobalProperties.clear();
+ this->PropertyDefinitions.clear();
+
+ cmStateDetail::PositionType pos = this->SnapshotData.Truncate();
+ this->ExecutionListFiles.Truncate();
+
+ {
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator it =
+ this->BuildsystemDirectory.Truncate();
+ it->IncludeDirectories.clear();
+ it->IncludeDirectoryBacktraces.clear();
+ it->CompileDefinitions.clear();
+ it->CompileDefinitionsBacktraces.clear();
+ it->CompileOptions.clear();
+ it->CompileOptionsBacktraces.clear();
+ it->DirectoryEnd = pos;
+ it->NormalTargetNames.clear();
+ it->Properties.clear();
+ it->Children.clear();
+ }
+
+ this->PolicyStack.Clear();
+ pos->Policies = this->PolicyStack.Root();
+ pos->PolicyRoot = this->PolicyStack.Root();
+ pos->PolicyScope = this->PolicyStack.Root();
+ assert(pos->Policies.IsValid());
+ assert(pos->PolicyRoot.IsValid());
+
+ {
+ std::string srcDir =
+ cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
+ std::string binDir =
+ 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());
+ }
+
+ this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "",
+ true);
+ this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::DIRECTORY, "", "",
+ true);
+ this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY, "", "",
+ true);
+
+ this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::TARGET, "", "",
+ true);
+ this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true);
+ this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true);
+
+ return cmStateSnapshot(this, pos);
+}
+
+void cmState::DefineProperty(const std::string& name,
+ cmProperty::ScopeType scope,
+ const char* ShortDescription,
+ const char* FullDescription, bool chained)
+{
+ this->PropertyDefinitions[scope].DefineProperty(
+ name, scope, ShortDescription, FullDescription, chained);
+}
+
+cmPropertyDefinition const* cmState::GetPropertyDefinition(
+ const std::string& name, cmProperty::ScopeType scope) const
+{
+ if (this->IsPropertyDefined(name, scope)) {
+ cmPropertyDefinitionMap const& defs =
+ this->PropertyDefinitions.find(scope)->second;
+ return &defs.find(name)->second;
+ }
+ return CM_NULLPTR;
+}
+
+bool cmState::IsPropertyDefined(const std::string& name,
+ cmProperty::ScopeType scope) const
+{
+ std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
+ this->PropertyDefinitions.find(scope);
+ if (it == this->PropertyDefinitions.end()) {
+ return false;
+ }
+ return it->second.IsPropertyDefined(name);
+}
+
+bool cmState::IsPropertyChained(const std::string& name,
+ cmProperty::ScopeType scope) const
+{
+ std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
+ this->PropertyDefinitions.find(scope);
+ if (it == this->PropertyDefinitions.end()) {
+ return false;
+ }
+ return it->second.IsPropertyChained(name);
+}
+
+void cmState::SetLanguageEnabled(std::string const& l)
+{
+ std::vector<std::string>::iterator it = std::lower_bound(
+ this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l);
+ if (it == this->EnabledLanguages.end() || *it != l) {
+ this->EnabledLanguages.insert(it, l);
+ }
+}
+
+bool cmState::GetLanguageEnabled(std::string const& l) const
+{
+ return std::binary_search(this->EnabledLanguages.begin(),
+ this->EnabledLanguages.end(), l);
+}
+
+std::vector<std::string> cmState::GetEnabledLanguages() const
+{
+ return this->EnabledLanguages;
+}
+
+void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
+{
+ this->EnabledLanguages = langs;
+}
+
+void cmState::ClearEnabledLanguages()
+{
+ this->EnabledLanguages.clear();
+}
+
+bool cmState::GetIsInTryCompile() const
+{
+ return this->IsInTryCompile;
+}
+
+void cmState::SetIsInTryCompile(bool b)
+{
+ this->IsInTryCompile = b;
+}
+
+bool cmState::GetIsGeneratorMultiConfig() const
+{
+ return this->IsGeneratorMultiConfig;
+}
+
+void cmState::SetIsGeneratorMultiConfig(bool b)
+{
+ this->IsGeneratorMultiConfig = b;
+}
+
+void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command)
+{
+ assert(name == cmSystemTools::LowerCase(name));
+ assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
+ this->BuiltinCommands.insert(std::make_pair(name, command));
+}
+
+void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command,
+ cmPolicies::PolicyID policy,
+ const char* message)
+{
+ this->AddBuiltinCommand(name,
+ new cmDisallowedCommand(command, policy, message));
+}
+
+void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
+{
+ this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error));
+}
+
+void cmState::AddScriptedCommand(std::string const& name, cmCommand* 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 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));
+}
+
+cmCommand* 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);
+ if (pos != this->ScriptedCommands.end()) {
+ return pos->second;
+ }
+ pos = this->BuiltinCommands.find(sName);
+ if (pos != this->BuiltinCommands.end()) {
+ return pos->second;
+ }
+ return CM_NULLPTR;
+}
+
+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 (std::map<std::string, cmCommand*>::const_iterator cmds =
+ this->ScriptedCommands.begin();
+ cmds != this->ScriptedCommands.end(); ++cmds) {
+ commandNames.push_back(cmds->first);
+ }
+ std::sort(commandNames.begin(), commandNames.end());
+ commandNames.erase(std::unique(commandNames.begin(), commandNames.end()),
+ commandNames.end());
+ return commandNames;
+}
+
+void cmState::RemoveUserDefinedCommands()
+{
+ cmDeleteAll(this->ScriptedCommands);
+ this->ScriptedCommands.clear();
+}
+
+void cmState::SetGlobalProperty(const std::string& prop, const char* value)
+{
+ this->GlobalProperties.SetProperty(prop, value);
+}
+
+void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
+ bool asString)
+{
+ this->GlobalProperties.AppendProperty(prop, value, asString);
+}
+
+const char* cmState::GetGlobalProperty(const std::string& prop)
+{
+ if (prop == "CACHE_VARIABLES") {
+ std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
+ this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
+ } else if (prop == "COMMANDS") {
+ std::vector<std::string> commands = this->GetCommandNames();
+ this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
+ } else if (prop == "IN_TRY_COMPILE") {
+ this->SetGlobalProperty("IN_TRY_COMPILE",
+ this->IsInTryCompile ? "1" : "0");
+ } else if (prop == "GENERATOR_IS_MULTI_CONFIG") {
+ this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG",
+ this->IsGeneratorMultiConfig ? "1" : "0");
+ } else if (prop == "ENABLED_LANGUAGES") {
+ std::string langs;
+ langs = cmJoin(this->EnabledLanguages, ";");
+ this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
+ }
+#define STRING_LIST_ELEMENT(F) ";" #F
+ if (prop == "CMAKE_C_KNOWN_FEATURES") {
+ return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
+ }
+ if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
+ return FOR_EACH_CXX_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));
+}
+
+void cmState::SetSourceDirectory(std::string const& sourceDirectory)
+{
+ this->SourceDirectory = sourceDirectory;
+ cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
+}
+
+const char* cmState::GetSourceDirectory() const
+{
+ return this->SourceDirectory.c_str();
+}
+
+void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
+{
+ this->BinaryDirectory = binaryDirectory;
+ cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
+}
+
+void cmState::SetWindowsShell(bool windowsShell)
+{
+ this->WindowsShell = windowsShell;
+}
+
+bool cmState::UseWindowsShell() const
+{
+ return this->WindowsShell;
+}
+
+void cmState::SetWindowsVSIDE(bool windowsVSIDE)
+{
+ this->WindowsVSIDE = windowsVSIDE;
+}
+
+bool cmState::UseWindowsVSIDE() const
+{
+ return this->WindowsVSIDE;
+}
+
+void cmState::SetWatcomWMake(bool watcomWMake)
+{
+ this->WatcomWMake = watcomWMake;
+}
+
+bool cmState::UseWatcomWMake() const
+{
+ return this->WatcomWMake;
+}
+
+void cmState::SetMinGWMake(bool minGWMake)
+{
+ this->MinGWMake = minGWMake;
+}
+
+bool cmState::UseMinGWMake() const
+{
+ return this->MinGWMake;
+}
+
+void cmState::SetNMake(bool nMake)
+{
+ this->NMake = nMake;
+}
+
+bool cmState::UseNMake() const
+{
+ return this->NMake;
+}
+
+void cmState::SetMSYSShell(bool mSYSShell)
+{
+ this->MSYSShell = mSYSShell;
+}
+
+bool cmState::UseMSYSShell() const
+{
+ return this->MSYSShell;
+}
+
+unsigned int cmState::GetCacheMajorVersion() const
+{
+ return this->CacheManager->GetCacheMajorVersion();
+}
+
+unsigned int cmState::GetCacheMinorVersion() const
+{
+ return this->CacheManager->GetCacheMinorVersion();
+}
+
+const char* cmState::GetBinaryDirectory() const
+{
+ return this->BinaryDirectory.c_str();
+}
+
+cmStateSnapshot cmState::CreateBaseSnapshot()
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(this->SnapshotData.Root());
+ pos->DirectoryParent = this->SnapshotData.Root();
+ pos->ScopeParent = this->SnapshotData.Root();
+ pos->SnapshotType = cmStateEnums::BaseType;
+ pos->Keep = true;
+ pos->BuildSystemDirectory =
+ this->BuildsystemDirectory.Push(this->BuildsystemDirectory.Root());
+ pos->ExecutionListFile =
+ this->ExecutionListFiles.Push(this->ExecutionListFiles.Root());
+ pos->IncludeDirectoryPosition = 0;
+ pos->CompileDefinitionsPosition = 0;
+ pos->CompileOptionsPosition = 0;
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->Policies = this->PolicyStack.Root();
+ pos->PolicyRoot = this->PolicyStack.Root();
+ pos->PolicyScope = this->PolicyStack.Root();
+ assert(pos->Policies.IsValid());
+ assert(pos->PolicyRoot.IsValid());
+ pos->Vars = this->VarTree.Push(this->VarTree.Root());
+ assert(pos->Vars.IsValid());
+ pos->Parent = this->VarTree.Root();
+ pos->Root = this->VarTree.Root();
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
+ cmStateSnapshot const& originSnapshot)
+{
+ assert(originSnapshot.IsValid());
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position);
+ pos->DirectoryParent = originSnapshot.Position;
+ pos->ScopeParent = originSnapshot.Position;
+ pos->SnapshotType = cmStateEnums::BuildsystemDirectoryType;
+ pos->Keep = true;
+ pos->BuildSystemDirectory = this->BuildsystemDirectory.Push(
+ originSnapshot.Position->BuildSystemDirectory);
+ pos->ExecutionListFile =
+ this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->Policies = originSnapshot.Position->Policies;
+ pos->PolicyRoot = originSnapshot.Position->Policies;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ assert(pos->Policies.IsValid());
+ assert(pos->PolicyRoot.IsValid());
+
+ cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
+ pos->Parent = origin;
+ pos->Root = origin;
+ pos->Vars = this->VarTree.Push(origin);
+
+ cmStateSnapshot snapshot = cmStateSnapshot(this, pos);
+ originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot);
+ snapshot.SetDefaultDefinitions();
+ snapshot.InitializeFromParent();
+ snapshot.SetDirectoryDefinitions();
+ return snapshot;
+}
+
+cmStateSnapshot cmState::CreateFunctionCallSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName)
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
+ pos->ScopeParent = originSnapshot.Position;
+ pos->SnapshotType = cmStateEnums::FunctionCallType;
+ pos->Keep = false;
+ pos->ExecutionListFile = this->ExecutionListFiles.Push(
+ originSnapshot.Position->ExecutionListFile, fileName);
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ assert(originSnapshot.Position->Vars.IsValid());
+ cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
+ pos->Parent = origin;
+ pos->Vars = this->VarTree.Push(origin);
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::CreateMacroCallSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName)
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
+ pos->SnapshotType = cmStateEnums::MacroCallType;
+ pos->Keep = false;
+ pos->ExecutionListFile = this->ExecutionListFiles.Push(
+ originSnapshot.Position->ExecutionListFile, fileName);
+ assert(originSnapshot.Position->Vars.IsValid());
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::CreateIncludeFileSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName)
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
+ pos->SnapshotType = cmStateEnums::IncludeFileType;
+ pos->Keep = true;
+ pos->ExecutionListFile = this->ExecutionListFiles.Push(
+ originSnapshot.Position->ExecutionListFile, fileName);
+ assert(originSnapshot.Position->Vars.IsValid());
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::CreateVariableScopeSnapshot(
+ cmStateSnapshot const& originSnapshot)
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
+ pos->ScopeParent = originSnapshot.Position;
+ pos->SnapshotType = cmStateEnums::VariableScopeType;
+ pos->Keep = false;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ assert(originSnapshot.Position->Vars.IsValid());
+
+ cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
+ pos->Parent = origin;
+ pos->Vars = this->VarTree.Push(origin);
+ assert(pos->Vars.IsValid());
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::CreateInlineListFileSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName)
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
+ pos->SnapshotType = cmStateEnums::InlineListFileType;
+ pos->Keep = true;
+ pos->ExecutionListFile = this->ExecutionListFiles.Push(
+ originSnapshot.Position->ExecutionListFile, fileName);
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
+ cmStateSnapshot const& originSnapshot)
+{
+ cmStateDetail::PositionType pos =
+ this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
+ pos->SnapshotType = cmStateEnums::PolicyScopeType;
+ pos->Keep = false;
+ pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->PolicyScope = originSnapshot.Position->Policies;
+ return cmStateSnapshot(this, pos);
+}
+
+cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
+{
+ cmStateDetail::PositionType pos = originSnapshot.Position;
+ cmStateDetail::PositionType prevPos = pos;
+ ++prevPos;
+ prevPos->IncludeDirectoryPosition =
+ prevPos->BuildSystemDirectory->IncludeDirectories.size();
+ prevPos->CompileDefinitionsPosition =
+ prevPos->BuildSystemDirectory->CompileDefinitions.size();
+ prevPos->CompileOptionsPosition =
+ prevPos->BuildSystemDirectory->CompileOptions.size();
+ prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
+
+ if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
+ if (pos->Vars != prevPos->Vars) {
+ assert(this->VarTree.IsLast(pos->Vars));
+ this->VarTree.Pop(pos->Vars);
+ }
+ if (pos->ExecutionListFile != prevPos->ExecutionListFile) {
+ assert(this->ExecutionListFiles.IsLast(pos->ExecutionListFile));
+ this->ExecutionListFiles.Pop(pos->ExecutionListFile);
+ }
+ this->SnapshotData.Pop(pos);
+ }
+
+ return cmStateSnapshot(this, prevPos);
+}
+
+static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
+ std::string& value)
+{
+ // input line is: key=value
+ static cmsys::RegularExpression reg(
+ "^([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
+ // input line is: "key"=value
+ static cmsys::RegularExpression regQuoted(
+ "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
+ bool flag = false;
+ if (regQuoted.find(entry)) {
+ var = regQuoted.match(1);
+ value = regQuoted.match(2);
+ flag = true;
+ } else if (reg.find(entry)) {
+ var = reg.match(1);
+ value = reg.match(2);
+ flag = true;
+ }
+
+ // 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] == '\'') {
+ value = value.substr(1, value.size() - 2);
+ }
+
+ return flag;
+}
+
+bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
+ std::string& value,
+ cmStateEnums::CacheEntryType& type)
+{
+ // input line is: key:type=value
+ static cmsys::RegularExpression reg(
+ "^([^=:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
+ // input line is: "key":type=value
+ static cmsys::RegularExpression regQuoted(
+ "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
+ bool flag = false;
+ if (regQuoted.find(entry)) {
+ var = regQuoted.match(1);
+ type = cmState::StringToCacheEntryType(regQuoted.match(2).c_str());
+ value = regQuoted.match(3);
+ flag = true;
+ } else if (reg.find(entry)) {
+ var = reg.match(1);
+ type = cmState::StringToCacheEntryType(reg.match(2).c_str());
+ value = reg.match(3);
+ flag = true;
+ }
+
+ // 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] == '\'') {
+ value = value.substr(1, value.size() - 2);
+ }
+
+ if (!flag) {
+ return ParseEntryWithoutType(entry, var, value);
+ }
+
+ return flag;
+}
diff --git a/Source/cmState.h b/Source/cmState.h
new file mode 100644
index 000000000..e03ad8981
--- /dev/null
+++ b/Source/cmState.h
@@ -0,0 +1,195 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmState_h
+#define cmState_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cmDefinitions.h"
+#include "cmLinkedTree.h"
+#include "cmPolicies.h"
+#include "cmProperty.h"
+#include "cmPropertyDefinitionMap.h"
+#include "cmPropertyMap.h"
+#include "cmStatePrivate.h"
+#include "cmStateTypes.h"
+
+class cmCacheManager;
+class cmCommand;
+class cmPropertyDefinition;
+class cmStateSnapshot;
+
+class cmState
+{
+ friend class cmStateSnapshot;
+
+public:
+ cmState();
+ ~cmState();
+
+ static const char* GetTargetTypeName(cmStateEnums::TargetType targetType);
+
+ cmStateSnapshot CreateBaseSnapshot();
+ cmStateSnapshot CreateBuildsystemDirectorySnapshot(
+ cmStateSnapshot const& originSnapshot);
+ cmStateSnapshot CreateFunctionCallSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName);
+ cmStateSnapshot CreateMacroCallSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName);
+ cmStateSnapshot CreateIncludeFileSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName);
+ cmStateSnapshot CreateVariableScopeSnapshot(
+ cmStateSnapshot const& originSnapshot);
+ cmStateSnapshot CreateInlineListFileSnapshot(
+ cmStateSnapshot const& originSnapshot, std::string const& fileName);
+ cmStateSnapshot CreatePolicyScopeSnapshot(
+ cmStateSnapshot const& originSnapshot);
+ cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot);
+
+ static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*);
+ static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType);
+ static bool IsCacheEntryType(std::string const& key);
+
+ bool LoadCache(const std::string& path, bool internal,
+ std::set<std::string>& excludes,
+ std::set<std::string>& includes);
+
+ bool SaveCache(const std::string& path);
+
+ 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;
+ 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);
+
+ void RemoveCacheEntry(std::string const& key);
+
+ void SetCacheEntryProperty(std::string const& key,
+ std::string const& propertyName,
+ std::string const& value);
+ void SetCacheEntryBoolProperty(std::string const& key,
+ std::string const& propertyName, bool value);
+ std::vector<std::string> GetCacheEntryPropertyList(std::string const& key);
+ const char* GetCacheEntryProperty(std::string const& key,
+ std::string const& propertyName);
+ bool GetCacheEntryPropertyAsBool(std::string const& key,
+ std::string const& propertyName);
+ void AppendCacheEntryProperty(std::string const& key,
+ const std::string& property,
+ const std::string& value,
+ bool asString = false);
+ void RemoveCacheEntryProperty(std::string const& key,
+ std::string const& propertyName);
+
+ ///! 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);
+
+ cmStateSnapshot Reset();
+ // Define a property
+ void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
+ const char* ShortDescription,
+ const char* FullDescription, bool chain = false);
+
+ // get property definition
+ cmPropertyDefinition const* GetPropertyDefinition(
+ const std::string& name, cmProperty::ScopeType scope) const;
+
+ // Is a property defined?
+ bool IsPropertyDefined(const std::string& name,
+ cmProperty::ScopeType scope) const;
+ bool IsPropertyChained(const std::string& name,
+ cmProperty::ScopeType scope) const;
+
+ void SetLanguageEnabled(std::string const& l);
+ bool GetLanguageEnabled(std::string const& l) const;
+ std::vector<std::string> GetEnabledLanguages() const;
+ void SetEnabledLanguages(std::vector<std::string> const& langs);
+ void ClearEnabledLanguages();
+
+ bool GetIsInTryCompile() const;
+ void SetIsInTryCompile(bool b);
+
+ 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,
+ cmPolicies::PolicyID policy, const char* message);
+ void AddUnexpectedCommand(std::string const& name, const char* error);
+ void AddScriptedCommand(std::string const& name, cmCommand* command);
+ void RemoveUserDefinedCommands();
+ std::vector<std::string> GetCommandNames() const;
+
+ void SetGlobalProperty(const std::string& prop, const char* value);
+ void AppendGlobalProperty(const std::string& prop, const char* value,
+ bool asString = false);
+ const char* GetGlobalProperty(const std::string& prop);
+ bool GetGlobalPropertyAsBool(const std::string& prop);
+
+ const char* GetSourceDirectory() const;
+ void SetSourceDirectory(std::string const& sourceDirectory);
+ const char* GetBinaryDirectory() const;
+ void SetBinaryDirectory(std::string const& binaryDirectory);
+
+ void SetWindowsShell(bool windowsShell);
+ bool UseWindowsShell() const;
+ void SetWindowsVSIDE(bool windowsVSIDE);
+ bool UseWindowsVSIDE() const;
+ void SetWatcomWMake(bool watcomWMake);
+ bool UseWatcomWMake() const;
+ void SetMinGWMake(bool minGWMake);
+ bool UseMinGWMake() const;
+ void SetNMake(bool nMake);
+ bool UseNMake() const;
+ void SetMSYSShell(bool mSYSShell);
+ bool UseMSYSShell() const;
+
+ unsigned int GetCacheMajorVersion() const;
+ unsigned int GetCacheMinorVersion() const;
+
+private:
+ friend class cmake;
+ void AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString,
+ cmStateEnums::CacheEntryType type);
+
+ std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
+ std::vector<std::string> EnabledLanguages;
+ std::map<std::string, cmCommand*> BuiltinCommands;
+ std::map<std::string, cmCommand*> ScriptedCommands;
+ cmPropertyMap GlobalProperties;
+ cmCacheManager* CacheManager;
+
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>
+ BuildsystemDirectory;
+
+ cmLinkedTree<std::string> ExecutionListFiles;
+
+ cmLinkedTree<cmStateDetail::PolicyStackEntry> PolicyStack;
+ cmLinkedTree<cmStateDetail::SnapshotDataType> SnapshotData;
+ cmLinkedTree<cmDefinitions> VarTree;
+
+ std::string SourceDirectory;
+ std::string BinaryDirectory;
+ bool IsInTryCompile;
+ bool IsGeneratorMultiConfig;
+ bool WindowsShell;
+ bool WindowsVSIDE;
+ bool WatcomWMake;
+ bool MinGWMake;
+ bool NMake;
+ bool MSYSShell;
+};
+
+#endif
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
new file mode 100644
index 000000000..46a185848
--- /dev/null
+++ b/Source/cmStateDirectory.cxx
@@ -0,0 +1,528 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmStateDirectory.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+#include <map>
+#include <utility>
+
+#include "cmProperty.h"
+#include "cmPropertyMap.h"
+#include "cmState.h"
+#include "cmStatePrivate.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+
+static std::string const kBINARY_DIR = "BINARY_DIR";
+static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS";
+static std::string const kSOURCE_DIR = "SOURCE_DIR";
+static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES";
+
+void cmStateDirectory::ComputeRelativePathTopSource()
+{
+ // Relative path conversion inside the source tree is not used to
+ // construct relative paths passed to build tools so it is safe to use
+ // even when the source is a network path.
+
+ cmStateSnapshot snapshot = this->Snapshot_;
+ std::vector<cmStateSnapshot> snapshots;
+ snapshots.push_back(snapshot);
+ while (true) {
+ snapshot = snapshot.GetBuildsystemDirectoryParent();
+ if (snapshot.IsValid()) {
+ snapshots.push_back(snapshot);
+ } else {
+ break;
+ }
+ }
+
+ 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();
+ if (cmSystemTools::IsSubDirectory(result, currentSource)) {
+ result = currentSource;
+ }
+ }
+ this->DirectoryState->RelativePathTopSource = result;
+}
+
+void cmStateDirectory::ComputeRelativePathTopBinary()
+{
+ cmStateSnapshot snapshot = this->Snapshot_;
+ std::vector<cmStateSnapshot> snapshots;
+ snapshots.push_back(snapshot);
+ while (true) {
+ snapshot = snapshot.GetBuildsystemDirectoryParent();
+ if (snapshot.IsValid()) {
+ snapshots.push_back(snapshot);
+ } else {
+ break;
+ }
+ }
+
+ 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();
+ if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
+ result = currentBinary;
+ }
+ }
+
+ // The current working directory on Windows cannot be a network
+ // path. Therefore relative paths cannot work when the binary tree
+ // is a network path.
+ if (result.size() < 2 || result.substr(0, 2) != "//") {
+ this->DirectoryState->RelativePathTopBinary = result;
+ } else {
+ this->DirectoryState->RelativePathTopBinary = "";
+ }
+}
+
+const char* cmStateDirectory::GetCurrentSource() const
+{
+ return this->DirectoryState->Location.c_str();
+}
+
+void cmStateDirectory::SetCurrentSource(std::string const& dir)
+{
+ std::string& loc = this->DirectoryState->Location;
+ loc = dir;
+ cmSystemTools::ConvertToUnixSlashes(loc);
+ loc = cmSystemTools::CollapseFullPath(loc);
+
+ this->ComputeRelativePathTopSource();
+
+ this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc);
+}
+
+const char* cmStateDirectory::GetCurrentBinary() const
+{
+ return this->DirectoryState->OutputLocation.c_str();
+}
+
+void cmStateDirectory::SetCurrentBinary(std::string const& dir)
+{
+ std::string& loc = this->DirectoryState->OutputLocation;
+ loc = dir;
+ cmSystemTools::ConvertToUnixSlashes(loc);
+ loc = cmSystemTools::CollapseFullPath(loc);
+
+ this->ComputeRelativePathTopBinary();
+
+ this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc);
+}
+
+const char* cmStateDirectory::GetRelativePathTopSource() const
+{
+ return this->DirectoryState->RelativePathTopSource.c_str();
+}
+
+const char* cmStateDirectory::GetRelativePathTopBinary() const
+{
+ return this->DirectoryState->RelativePathTopBinary.c_str();
+}
+
+void cmStateDirectory::SetRelativePathTopSource(const char* dir)
+{
+ this->DirectoryState->RelativePathTopSource = dir;
+}
+
+void cmStateDirectory::SetRelativePathTopBinary(const char* dir)
+{
+ this->DirectoryState->RelativePathTopBinary = dir;
+}
+
+cmStateDirectory::cmStateDirectory(
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
+ const cmStateSnapshot& snapshot)
+ : DirectoryState(iter)
+ , Snapshot_(snapshot)
+{
+}
+
+template <typename T, typename U>
+cmStringRange GetPropertyContent(T const& content, U contentEndPosition)
+{
+ std::vector<std::string>::const_iterator end =
+ content.begin() + contentEndPosition;
+
+ std::vector<std::string>::const_reverse_iterator rbegin =
+ cmMakeReverseIterator(end);
+ rbegin = std::find(rbegin, content.rend(), cmPropertySentinal);
+
+ return cmMakeRange(rbegin.base(), end);
+}
+
+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;
+
+ std::vector<std::string>::const_reverse_iterator rbegin =
+ cmMakeReverseIterator(entryEnd);
+ rbegin = std::find(rbegin, content.rend(), cmPropertySentinal);
+
+ std::vector<cmListFileBacktrace>::const_iterator it =
+ backtraces.begin() + std::distance(content.begin(), rbegin.base());
+
+ std::vector<cmListFileBacktrace>::const_iterator end = backtraces.end();
+ return cmMakeRange(it, end);
+}
+
+template <typename T, typename U, typename V>
+void AppendEntry(T& content, U& backtraces, V& endContentPosition,
+ const std::string& value, const cmListFileBacktrace& lfbt)
+{
+ if (value.empty()) {
+ return;
+ }
+
+ assert(endContentPosition == content.size());
+
+ content.push_back(value);
+ backtraces.push_back(lfbt);
+
+ endContentPosition = content.size();
+}
+
+template <typename T, typename U, typename V>
+void SetContent(T& content, U& backtraces, V& endContentPosition,
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ assert(endContentPosition == content.size());
+
+ content.resize(content.size() + 2);
+ backtraces.resize(backtraces.size() + 2);
+
+ content.back() = vec;
+ backtraces.back() = lfbt;
+
+ endContentPosition = content.size();
+}
+
+template <typename T, typename U, typename V>
+void ClearContent(T& content, U& backtraces, V& endContentPosition)
+{
+ assert(endContentPosition == content.size());
+
+ content.resize(content.size() + 1);
+ backtraces.resize(backtraces.size() + 1);
+
+ endContentPosition = content.size();
+}
+
+cmStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const
+{
+ return GetPropertyContent(
+ this->DirectoryState->IncludeDirectories,
+ this->Snapshot_.Position->IncludeDirectoryPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetIncludeDirectoriesEntryBacktraces() const
+{
+ return GetPropertyBacktraces(
+ this->DirectoryState->IncludeDirectories,
+ this->DirectoryState->IncludeDirectoryBacktraces,
+ this->Snapshot_.Position->IncludeDirectoryPosition);
+}
+
+void cmStateDirectory::AppendIncludeDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->IncludeDirectories,
+ this->DirectoryState->IncludeDirectoryBacktraces,
+ this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt);
+}
+
+void cmStateDirectory::PrependIncludeDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ std::vector<std::string>::iterator 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);
+ rbegin = std::find(rbegin, rend, cmPropertySentinal);
+
+ std::vector<std::string>::iterator entryIt = rbegin.base();
+ std::vector<std::string>::iterator entryBegin =
+ this->DirectoryState->IncludeDirectories.begin();
+
+ std::vector<cmListFileBacktrace>::iterator btIt =
+ this->DirectoryState->IncludeDirectoryBacktraces.begin() +
+ std::distance(entryBegin, entryIt);
+
+ this->DirectoryState->IncludeDirectories.insert(entryIt, vec);
+ this->DirectoryState->IncludeDirectoryBacktraces.insert(btIt, lfbt);
+
+ this->Snapshot_.Position->IncludeDirectoryPosition =
+ this->DirectoryState->IncludeDirectories.size();
+}
+
+void cmStateDirectory::SetIncludeDirectories(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->IncludeDirectories,
+ this->DirectoryState->IncludeDirectoryBacktraces,
+ this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearIncludeDirectories()
+{
+ ClearContent(this->DirectoryState->IncludeDirectories,
+ this->DirectoryState->IncludeDirectoryBacktraces,
+ this->Snapshot_.Position->IncludeDirectoryPosition);
+}
+
+cmStringRange cmStateDirectory::GetCompileDefinitionsEntries() const
+{
+ return GetPropertyContent(
+ this->DirectoryState->CompileDefinitions,
+ this->Snapshot_.Position->CompileDefinitionsPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetCompileDefinitionsEntryBacktraces() const
+{
+ return GetPropertyBacktraces(
+ this->DirectoryState->CompileDefinitions,
+ this->DirectoryState->CompileDefinitionsBacktraces,
+ this->Snapshot_.Position->CompileDefinitionsPosition);
+}
+
+void cmStateDirectory::AppendCompileDefinitionsEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->CompileDefinitions,
+ this->DirectoryState->CompileDefinitionsBacktraces,
+ this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::SetCompileDefinitions(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->CompileDefinitions,
+ this->DirectoryState->CompileDefinitionsBacktraces,
+ this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearCompileDefinitions()
+{
+ ClearContent(this->DirectoryState->CompileDefinitions,
+ this->DirectoryState->CompileDefinitionsBacktraces,
+ this->Snapshot_.Position->CompileDefinitionsPosition);
+}
+
+cmStringRange cmStateDirectory::GetCompileOptionsEntries() const
+{
+ return GetPropertyContent(this->DirectoryState->CompileOptions,
+ this->Snapshot_.Position->CompileOptionsPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetCompileOptionsEntryBacktraces() const
+{
+ return GetPropertyBacktraces(
+ this->DirectoryState->CompileOptions,
+ this->DirectoryState->CompileOptionsBacktraces,
+ this->Snapshot_.Position->CompileOptionsPosition);
+}
+
+void cmStateDirectory::AppendCompileOptionsEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->CompileOptions,
+ this->DirectoryState->CompileOptionsBacktraces,
+ this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::SetCompileOptions(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->CompileOptions,
+ this->DirectoryState->CompileOptionsBacktraces,
+ this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearCompileOptions()
+{
+ ClearContent(this->DirectoryState->CompileOptions,
+ this->DirectoryState->CompileOptionsBacktraces,
+ this->Snapshot_.Position->CompileOptionsPosition);
+}
+
+void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
+ cmListFileBacktrace const& lfbt)
+{
+ if (prop == "INCLUDE_DIRECTORIES") {
+ if (!value) {
+ this->ClearIncludeDirectories();
+ return;
+ }
+ this->SetIncludeDirectories(value, lfbt);
+ return;
+ }
+ if (prop == "COMPILE_OPTIONS") {
+ if (!value) {
+ this->ClearCompileOptions();
+ return;
+ }
+ this->SetCompileOptions(value, lfbt);
+ return;
+ }
+ if (prop == "COMPILE_DEFINITIONS") {
+ if (!value) {
+ this->ClearCompileDefinitions();
+ return;
+ }
+ this->SetCompileDefinitions(value, lfbt);
+ return;
+ }
+
+ this->DirectoryState->Properties.SetProperty(prop, value);
+}
+
+void cmStateDirectory::AppendProperty(const std::string& prop,
+ const char* value, bool asString,
+ cmListFileBacktrace const& lfbt)
+{
+ if (prop == "INCLUDE_DIRECTORIES") {
+ this->AppendIncludeDirectoriesEntry(value, lfbt);
+ return;
+ }
+ if (prop == "COMPILE_OPTIONS") {
+ this->AppendCompileOptionsEntry(value, lfbt);
+ return;
+ }
+ if (prop == "COMPILE_DEFINITIONS") {
+ this->AppendCompileDefinitionsEntry(value, lfbt);
+ return;
+ }
+
+ this->DirectoryState->Properties.AppendProperty(prop, value, asString);
+}
+
+const char* cmStateDirectory::GetProperty(const std::string& prop) const
+{
+ const bool chain =
+ this->Snapshot_.State->IsPropertyChained(prop, cmProperty::DIRECTORY);
+ return this->GetProperty(prop, chain);
+}
+
+const char* cmStateDirectory::GetProperty(const std::string& prop,
+ bool chain) const
+{
+ static std::string output;
+ output = "";
+ if (prop == "PARENT_DIRECTORY") {
+ cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
+ if (parent.IsValid()) {
+ return parent.GetDirectory().GetCurrentSource();
+ }
+ return "";
+ }
+ if (prop == kBINARY_DIR) {
+ output = this->GetCurrentBinary();
+ return output.c_str();
+ }
+ if (prop == kSOURCE_DIR) {
+ output = this->GetCurrentSource();
+ return output.c_str();
+ }
+ if (prop == kSUBDIRECTORIES) {
+ 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());
+ }
+ output = cmJoin(child_dirs, ";");
+ return output.c_str();
+ }
+ if (prop == kBUILDSYSTEM_TARGETS) {
+ output = cmJoin(this->DirectoryState->NormalTargetNames, ";");
+ return output.c_str();
+ }
+
+ if (prop == "LISTFILE_STACK") {
+ std::vector<std::string> listFiles;
+ cmStateSnapshot snp = this->Snapshot_;
+ while (snp.IsValid()) {
+ listFiles.push_back(snp.GetExecutionListFile());
+ snp = snp.GetCallStackParent();
+ }
+ std::reverse(listFiles.begin(), listFiles.end());
+ output = cmJoin(listFiles, ";");
+ return output.c_str();
+ }
+ if (prop == "CACHE_VARIABLES") {
+ output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";");
+ return output.c_str();
+ }
+ 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());
+ std::sort(res.begin(), res.end());
+ output = cmJoin(res, ";");
+ return output.c_str();
+ }
+ if (prop == "INCLUDE_DIRECTORIES") {
+ output = cmJoin(this->GetIncludeDirectoriesEntries(), ";");
+ return output.c_str();
+ }
+ if (prop == "COMPILE_OPTIONS") {
+ output = cmJoin(this->GetCompileOptionsEntries(), ";");
+ return output.c_str();
+ }
+ if (prop == "COMPILE_DEFINITIONS") {
+ output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
+ return output.c_str();
+ }
+
+ const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
+ if (!retVal && chain) {
+ cmStateSnapshot parentSnapshot =
+ this->Snapshot_.GetBuildsystemDirectoryParent();
+ if (parentSnapshot.IsValid()) {
+ return parentSnapshot.GetDirectory().GetProperty(prop, chain);
+ }
+ return this->Snapshot_.State->GetGlobalProperty(prop);
+ }
+
+ return retVal;
+}
+
+bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const
+{
+ return cmSystemTools::IsOn(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;
+}
+
+void cmStateDirectory::AddNormalTargetName(std::string const& name)
+{
+ this->DirectoryState->NormalTargetNames.push_back(name);
+}
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
new file mode 100644
index 000000000..79bb36943
--- /dev/null
+++ b/Source/cmStateDirectory.h
@@ -0,0 +1,83 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmStateDirectory_h
+#define cmStateDirectory_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmAlgorithms.h"
+#include "cmLinkedTree.h"
+#include "cmListFileCache.h"
+#include "cmStatePrivate.h"
+#include "cmStateSnapshot.h"
+
+class cmStateDirectory
+{
+ cmStateDirectory(
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
+ cmStateSnapshot const& snapshot);
+
+public:
+ const char* GetCurrentSource() const;
+ void SetCurrentSource(std::string const& dir);
+ const char* GetCurrentBinary() const;
+ void SetCurrentBinary(std::string const& dir);
+
+ const char* GetRelativePathTopSource() const;
+ const char* GetRelativePathTopBinary() const;
+ void SetRelativePathTopSource(const char* dir);
+ void SetRelativePathTopBinary(const char* dir);
+
+ cmStringRange GetIncludeDirectoriesEntries() const;
+ cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const;
+ void AppendIncludeDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void PrependIncludeDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetIncludeDirectories(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void ClearIncludeDirectories();
+
+ cmStringRange GetCompileDefinitionsEntries() const;
+ cmBacktraceRange GetCompileDefinitionsEntryBacktraces() const;
+ void AppendCompileDefinitionsEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetCompileDefinitions(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void ClearCompileDefinitions();
+
+ cmStringRange GetCompileOptionsEntries() const;
+ cmBacktraceRange GetCompileOptionsEntryBacktraces() const;
+ void AppendCompileOptionsEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetCompileOptions(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void ClearCompileOptions();
+
+ void SetProperty(const std::string& prop, const char* value,
+ cmListFileBacktrace const& lfbt);
+ void AppendProperty(const std::string& prop, const char* value,
+ bool asString, cmListFileBacktrace const& lfbt);
+ const char* GetProperty(const std::string& prop) const;
+ const char* GetProperty(const std::string& prop, bool chain) const;
+ bool GetPropertyAsBool(const std::string& prop) const;
+ std::vector<std::string> GetPropertyKeys() const;
+
+ void AddNormalTargetName(std::string const& name);
+
+private:
+ void ComputeRelativePathTopSource();
+ void ComputeRelativePathTopBinary();
+
+private:
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator
+ DirectoryState;
+ cmStateSnapshot Snapshot_;
+ friend class cmStateSnapshot;
+};
+
+#endif
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
new file mode 100644
index 000000000..f36ee37ea
--- /dev/null
+++ b/Source/cmStatePrivate.h
@@ -0,0 +1,96 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmStatePrivate_h
+#define cmStatePrivate_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmDefinitions.h"
+#include "cmLinkedTree.h"
+#include "cmListFileCache.h"
+#include "cmPolicies.h"
+#include "cmPropertyMap.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+
+namespace cmStateDetail {
+struct BuildsystemDirectoryStateType;
+struct PolicyStackEntry;
+} // namespace cmStateDetail
+
+static const std::string cmPropertySentinal = std::string();
+
+struct cmStateDetail::SnapshotDataType
+{
+ cmStateDetail::PositionType ScopeParent;
+ cmStateDetail::PositionType DirectoryParent;
+ cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator Policies;
+ cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator PolicyRoot;
+ cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator PolicyScope;
+ cmStateEnums::SnapshotType SnapshotType;
+ bool Keep;
+ cmLinkedTree<std::string>::iterator ExecutionListFile;
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator
+ BuildSystemDirectory;
+ cmLinkedTree<cmDefinitions>::iterator Vars;
+ cmLinkedTree<cmDefinitions>::iterator Root;
+ cmLinkedTree<cmDefinitions>::iterator Parent;
+ std::vector<std::string>::size_type IncludeDirectoryPosition;
+ std::vector<std::string>::size_type CompileDefinitionsPosition;
+ std::vector<std::string>::size_type CompileOptionsPosition;
+};
+
+struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
+{
+ typedef cmPolicies::PolicyMap derived;
+ PolicyStackEntry(bool w = false)
+ : derived()
+ , Weak(w)
+ {
+ }
+ PolicyStackEntry(derived const& d, bool w)
+ : derived(d)
+ , Weak(w)
+ {
+ }
+ bool Weak;
+};
+
+struct cmStateDetail::BuildsystemDirectoryStateType
+{
+ cmStateDetail::PositionType DirectoryEnd;
+
+ std::string Location;
+ std::string OutputLocation;
+
+ // The top-most directories for relative path conversion. Both the
+ // source and destination location of a relative path conversion
+ // must be underneath one of these directories (both under source or
+ // both under binary) in order for the relative path to be evaluated
+ // safely by the build tools.
+ std::string RelativePathTopSource;
+ std::string RelativePathTopBinary;
+
+ std::vector<std::string> IncludeDirectories;
+ std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces;
+
+ std::vector<std::string> CompileDefinitions;
+ std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
+
+ std::vector<std::string> CompileOptions;
+ std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
+
+ std::vector<std::string> NormalTargetNames;
+
+ std::string ProjectName;
+
+ cmPropertyMap Properties;
+
+ std::vector<cmStateSnapshot> Children;
+};
+
+#endif
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
new file mode 100644
index 000000000..77413c7b5
--- /dev/null
+++ b/Source/cmStateSnapshot.cxx
@@ -0,0 +1,437 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmStateSnapshot.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+#include <stdio.h>
+
+#include "cmAlgorithms.h"
+#include "cmDefinitions.h"
+#include "cmListFileCache.h"
+#include "cmPropertyMap.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStatePrivate.h"
+#include "cmVersion.h"
+#include "cmake.h"
+
+#if !defined(_WIN32)
+#include <sys/utsname.h>
+#endif
+
+#if defined(__CYGWIN__)
+#include "cmSystemTools.h"
+#endif
+
+cmStateSnapshot::cmStateSnapshot(cmState* state)
+ : State(state)
+ , Position()
+{
+}
+
+std::vector<cmStateSnapshot> cmStateSnapshot::GetChildren()
+{
+ return this->Position->BuildSystemDirectory->Children;
+}
+
+cmStateSnapshot::cmStateSnapshot(cmState* state,
+ cmStateDetail::PositionType position)
+ : State(state)
+ , Position(position)
+{
+}
+
+cmStateEnums::SnapshotType cmStateSnapshot::GetType() const
+{
+ return this->Position->SnapshotType;
+}
+
+void cmStateSnapshot::SetListFile(const std::string& listfile)
+{
+ *this->Position->ExecutionListFile = listfile;
+}
+
+std::string cmStateSnapshot::GetExecutionListFile() const
+{
+ return *this->Position->ExecutionListFile;
+}
+
+bool cmStateSnapshot::IsValid() const
+{
+ return this->State && this->Position.IsValid()
+ ? this->Position != this->State->SnapshotData.Root()
+ : false;
+}
+
+cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
+{
+ cmStateSnapshot snapshot;
+ if (!this->State || this->Position == this->State->SnapshotData.Root()) {
+ return snapshot;
+ }
+ cmStateDetail::PositionType parentPos = this->Position->DirectoryParent;
+ if (parentPos != this->State->SnapshotData.Root()) {
+ snapshot = cmStateSnapshot(this->State,
+ parentPos->BuildSystemDirectory->DirectoryEnd);
+ }
+
+ return snapshot;
+}
+
+cmStateSnapshot cmStateSnapshot::GetCallStackParent() const
+{
+ assert(this->State);
+ assert(this->Position != this->State->SnapshotData.Root());
+
+ cmStateSnapshot snapshot;
+ cmStateDetail::PositionType parentPos = this->Position;
+ while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
+ parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
+ ++parentPos;
+ }
+ if (parentPos->SnapshotType == cmStateEnums::BuildsystemDirectoryType ||
+ parentPos->SnapshotType == cmStateEnums::BaseType) {
+ return snapshot;
+ }
+
+ ++parentPos;
+ while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
+ parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
+ ++parentPos;
+ }
+
+ if (parentPos == this->State->SnapshotData.Root()) {
+ return snapshot;
+ }
+
+ snapshot = cmStateSnapshot(this->State, parentPos);
+ return snapshot;
+}
+
+cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const
+{
+ assert(this->State);
+ assert(this->Position != this->State->SnapshotData.Root());
+
+ cmStateDetail::PositionType pos = this->Position;
+ while (pos->SnapshotType != cmStateEnums::BaseType &&
+ pos->SnapshotType != cmStateEnums::BuildsystemDirectoryType &&
+ pos != this->State->SnapshotData.Root()) {
+ ++pos;
+ }
+ return cmStateSnapshot(this->State, pos);
+}
+
+void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak)
+{
+ cmStateDetail::PositionType pos = this->Position;
+ pos->Policies = this->State->PolicyStack.Push(
+ pos->Policies, cmStateDetail::PolicyStackEntry(entry, weak));
+}
+
+bool cmStateSnapshot::PopPolicy()
+{
+ cmStateDetail::PositionType pos = this->Position;
+ if (pos->Policies == pos->PolicyScope) {
+ return false;
+ }
+ pos->Policies = this->State->PolicyStack.Pop(pos->Policies);
+ return true;
+}
+
+bool cmStateSnapshot::CanPopPolicyScope()
+{
+ return this->Position->Policies == this->Position->PolicyScope;
+}
+
+void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id,
+ cmPolicies::PolicyStatus status)
+{
+ // Update the policy stack from the top to the top-most strong entry.
+ bool previous_was_weak = true;
+ for (cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator psi =
+ this->Position->Policies;
+ previous_was_weak && psi != this->Position->PolicyRoot; ++psi) {
+ psi->Set(id, status);
+ previous_was_weak = psi->Weak;
+ }
+}
+
+cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(
+ cmPolicies::PolicyID id) const
+{
+ cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id);
+
+ if (status == cmPolicies::REQUIRED_ALWAYS ||
+ status == cmPolicies::REQUIRED_IF_USED) {
+ return status;
+ }
+
+ cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir =
+ this->Position->BuildSystemDirectory;
+
+ while (true) {
+ assert(dir.IsValid());
+ cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf =
+ dir->DirectoryEnd->Policies;
+ cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
+ dir->DirectoryEnd->PolicyRoot;
+ for (; leaf != root; ++leaf) {
+ if (leaf->IsDefined(id)) {
+ status = leaf->Get(id);
+ return status;
+ }
+ }
+ cmStateDetail::PositionType e = dir->DirectoryEnd;
+ cmStateDetail::PositionType p = e->DirectoryParent;
+ if (p == this->State->SnapshotData.Root()) {
+ break;
+ }
+ dir = p->BuildSystemDirectory;
+ }
+ return status;
+}
+
+bool cmStateSnapshot::HasDefinedPolicyCMP0011()
+{
+ return !this->Position->Policies->IsEmpty();
+}
+
+const char* cmStateSnapshot::GetDefinition(std::string const& name) const
+{
+ assert(this->Position->Vars.IsValid());
+ return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
+}
+
+bool cmStateSnapshot::IsInitialized(std::string const& name) const
+{
+ return cmDefinitions::HasKey(name, this->Position->Vars,
+ this->Position->Root);
+}
+
+void cmStateSnapshot::SetDefinition(std::string const& name,
+ std::string const& value)
+{
+ this->Position->Vars->Set(name, value.c_str());
+}
+
+void cmStateSnapshot::RemoveDefinition(std::string const& name)
+{
+ this->Position->Vars->Set(name, CM_NULLPTR);
+}
+
+std::vector<std::string> cmStateSnapshot::UnusedKeys() const
+{
+ return this->Position->Vars->UnusedKeys();
+}
+
+std::vector<std::string> cmStateSnapshot::ClosureKeys() const
+{
+ return cmDefinitions::ClosureKeys(this->Position->Vars,
+ this->Position->Root);
+}
+
+bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef)
+{
+ if (this->Position->ScopeParent == this->Position->DirectoryParent) {
+ cmStateSnapshot parentDir = this->GetBuildsystemDirectoryParent();
+ if (!parentDir.IsValid()) {
+ return false;
+ }
+ // Update the definition in the parent directory top scope. This
+ // directory's scope was initialized by the closure of the parent
+ // scope, so we do not need to localize the definition first.
+ if (varDef) {
+ parentDir.SetDefinition(var, varDef);
+ } else {
+ parentDir.RemoveDefinition(var);
+ }
+ return true;
+ }
+ // First localize the definition in the current scope.
+ cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root);
+
+ // Now update the definition in the parent scope.
+ this->Position->Parent->Set(var, varDef);
+ return true;
+}
+
+template <typename T, typename U, typename V>
+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();
+
+ std::vector<std::string>::const_reverse_iterator parentRbegin =
+ cmMakeReverseIterator(parentEnd);
+ std::vector<std::string>::const_reverse_iterator parentRend =
+ parentContent.rend();
+ parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal);
+ std::vector<std::string>::const_iterator 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();
+
+ thisBacktraces = std::vector<cmListFileBacktrace>(btIt, btEnd);
+
+ contentEndPosition = thisContent.size();
+}
+
+void cmStateSnapshot::SetDefaultDefinitions()
+{
+/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
+ With CMake must separate between target and host platform. In most cases
+ the tests for WIN32, UNIX and APPLE will be for the target system, so an
+ additional set of variables for the host system is required ->
+ CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
+ WIN32, UNIX and APPLE are now set in the platform files in
+ Modules/Platforms/.
+ To keep cmake scripts (-P) and custom language and compiler modules
+ working, these variables are still also set here in this place, but they
+ will be reset in CMakeSystemSpecificInformation.cmake before the platform
+ files are executed. */
+#if defined(_WIN32)
+ this->SetDefinition("WIN32", "1");
+ this->SetDefinition("CMAKE_HOST_WIN32", "1");
+ this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows");
+#else
+ this->SetDefinition("UNIX", "1");
+ this->SetDefinition("CMAKE_HOST_UNIX", "1");
+
+ struct utsname uts_name;
+ if (uname(&uts_name) >= 0) {
+ this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname);
+ }
+#endif
+#if defined(__CYGWIN__)
+ std::string legacy;
+ if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
+ cmSystemTools::IsOn(legacy.c_str())) {
+ this->SetDefinition("WIN32", "1");
+ this->SetDefinition("CMAKE_HOST_WIN32", "1");
+ }
+#endif
+#if defined(__APPLE__)
+ this->SetDefinition("APPLE", "1");
+ this->SetDefinition("CMAKE_HOST_APPLE", "1");
+#endif
+#if defined(__sun__)
+ 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_VERSION", cmVersion::GetCMakeVersion());
+
+ this->SetDefinition("CMAKE_FILES_DIRECTORY",
+ cmake::GetCMakeFilesDirectory());
+
+ // Setup the default include file regular expression (match everything).
+ this->Position->BuildSystemDirectory->Properties.SetProperty(
+ "INCLUDE_REGULAR_EXPRESSION", "^.*$");
+}
+
+void cmStateSnapshot::SetDirectoryDefinitions()
+{
+ this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
+ this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR",
+ this->State->GetSourceDirectory());
+ this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
+ this->SetDefinition("CMAKE_CURRENT_BINARY_DIR",
+ this->State->GetBinaryDirectory());
+}
+
+void cmStateSnapshot::InitializeFromParent()
+{
+ cmStateDetail::PositionType parent = this->Position->DirectoryParent;
+ assert(this->Position->Vars.IsValid());
+ assert(parent->Vars.IsValid());
+
+ *this->Position->Vars =
+ cmDefinitions::MakeClosure(parent->Vars, parent->Root);
+
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->IncludeDirectories,
+ this->Position->BuildSystemDirectory->IncludeDirectories,
+ parent->BuildSystemDirectory->IncludeDirectoryBacktraces,
+ this->Position->BuildSystemDirectory->IncludeDirectoryBacktraces,
+ this->Position->IncludeDirectoryPosition);
+
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->CompileDefinitions,
+ this->Position->BuildSystemDirectory->CompileDefinitions,
+ parent->BuildSystemDirectory->CompileDefinitionsBacktraces,
+ this->Position->BuildSystemDirectory->CompileDefinitionsBacktraces,
+ this->Position->CompileDefinitionsPosition);
+
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->CompileOptions,
+ this->Position->BuildSystemDirectory->CompileOptions,
+ parent->BuildSystemDirectory->CompileOptionsBacktraces,
+ this->Position->BuildSystemDirectory->CompileOptionsBacktraces,
+ this->Position->CompileOptionsPosition);
+}
+
+cmState* cmStateSnapshot::GetState() const
+{
+ return this->State;
+}
+
+cmStateDirectory cmStateSnapshot::GetDirectory() const
+{
+ return cmStateDirectory(this->Position->BuildSystemDirectory, *this);
+}
+
+void cmStateSnapshot::SetProjectName(const std::string& name)
+{
+ this->Position->BuildSystemDirectory->ProjectName = name;
+}
+
+std::string cmStateSnapshot::GetProjectName() const
+{
+ return this->Position->BuildSystemDirectory->ProjectName;
+}
+
+void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
+{
+ 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());
+
+ this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir);
+ this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir);
+}
+
+bool cmStateSnapshot::StrictWeakOrder::operator()(
+ const cmStateSnapshot& lhs, const cmStateSnapshot& rhs) const
+{
+ return lhs.Position.StrictWeakOrdered(rhs.Position);
+}
+
+bool operator==(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs)
+{
+ return lhs.Position == rhs.Position;
+}
+
+bool operator!=(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs)
+{
+ return lhs.Position != rhs.Position;
+}
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
new file mode 100644
index 000000000..6293803b9
--- /dev/null
+++ b/Source/cmStateSnapshot.h
@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmStateSnapshot_h
+#define cmStateSnapshot_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmLinkedTree.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+
+class cmState;
+class cmStateDirectory;
+
+class cmStateSnapshot
+{
+public:
+ cmStateSnapshot(cmState* state = CM_NULLPTR);
+ cmStateSnapshot(cmState* state, cmStateDetail::PositionType position);
+
+ const char* GetDefinition(std::string const& name) const;
+ bool IsInitialized(std::string const& name) const;
+ void SetDefinition(std::string const& name, std::string const& value);
+ void RemoveDefinition(std::string const& name);
+ std::vector<std::string> UnusedKeys() const;
+ std::vector<std::string> ClosureKeys() const;
+ bool RaiseScope(std::string const& var, const char* varDef);
+
+ void SetListFile(std::string const& listfile);
+
+ std::string GetExecutionListFile() const;
+
+ std::vector<cmStateSnapshot> GetChildren();
+
+ bool IsValid() 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;
+ bool HasDefinedPolicyCMP0011();
+ void PushPolicy(cmPolicies::PolicyMap const& entry, bool weak);
+ bool PopPolicy();
+ bool CanPopPolicyScope();
+
+ cmState* GetState() const;
+
+ cmStateDirectory GetDirectory() const;
+
+ void SetProjectName(std::string const& name);
+ std::string GetProjectName() const;
+
+ void InitializeFromParent_ForSubdirsCommand();
+
+ struct StrictWeakOrder
+ {
+ bool operator()(const cmStateSnapshot& lhs,
+ const cmStateSnapshot& rhs) const;
+ };
+
+ void SetDirectoryDefinitions();
+ void SetDefaultDefinitions();
+
+private:
+ friend bool operator==(const cmStateSnapshot& lhs,
+ const cmStateSnapshot& rhs);
+ friend bool operator!=(const cmStateSnapshot& lhs,
+ const cmStateSnapshot& rhs);
+ friend class cmState;
+ friend class cmStateDirectory;
+ friend struct StrictWeakOrder;
+
+ void InitializeFromParent();
+
+ cmState* State;
+ cmStateDetail::PositionType Position;
+};
+
+bool operator==(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs);
+bool operator!=(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs);
+
+#endif
diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h
new file mode 100644
index 000000000..7d6158e33
--- /dev/null
+++ b/Source/cmStateTypes.h
@@ -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. */
+
+#ifndef cmStateTypes_h
+#define cmStateTypes_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmLinkedTree.h"
+
+namespace cmStateDetail {
+struct SnapshotDataType;
+typedef cmLinkedTree<cmStateDetail::SnapshotDataType>::iterator PositionType;
+}
+
+namespace cmStateEnums {
+
+enum SnapshotType
+{
+ BaseType,
+ BuildsystemDirectoryType,
+ FunctionCallType,
+ MacroCallType,
+ IncludeFileType,
+ InlineListFileType,
+ PolicyScopeType,
+ VariableScopeType
+};
+
+// There are multiple overlapping ranges represented here. Be aware that adding
+// a value to this enumeration may cause failures in numerous places which
+// assume details about the ordering.
+enum TargetType
+{
+ EXECUTABLE,
+ STATIC_LIBRARY,
+ SHARED_LIBRARY,
+ MODULE_LIBRARY,
+ OBJECT_LIBRARY,
+ UTILITY,
+ GLOBAL_TARGET,
+ INTERFACE_LIBRARY,
+ UNKNOWN_LIBRARY
+};
+
+enum CacheEntryType
+{
+ BOOL = 0,
+ PATH,
+ FILEPATH,
+ STRING,
+ INTERNAL,
+ STATIC,
+ UNINITIALIZED
+};
+
+enum ArtifactType
+{
+ RuntimeBinaryArtifact,
+ ImportLibraryArtifact
+};
+}
+
+#endif
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 68ba13f62..7a097ba21 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -1,473 +1,397 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmStringCommand.h"
-#include "cmCryptoHash.h"
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/SystemTools.hxx>
-
-#include <stdlib.h> // required for atoi
+#include "cmsys/RegularExpression.hxx"
#include <ctype.h>
-#include <time.h>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
-#include <cmTimestamp.h>
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmGeneratorExpression.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmUuid.h"
+#include "cm_auto_ptr.hxx"
-//----------------------------------------------------------------------------
-bool cmStringCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+class cmExecutionStatus;
+
+bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("must be called with at least one argument.");
return false;
- }
+ }
- const std::string &subCommand = args[0];
- if(subCommand == "REGEX")
- {
+ const std::string& subCommand = args[0];
+ if (subCommand == "REGEX") {
return this->HandleRegexCommand(args);
- }
- else if(subCommand == "REPLACE")
- {
+ }
+ if (subCommand == "REPLACE") {
return this->HandleReplaceCommand(args);
- }
- else if ( subCommand == "MD5" ||
- subCommand == "SHA1" ||
- subCommand == "SHA224" ||
- subCommand == "SHA256" ||
- subCommand == "SHA384" ||
- subCommand == "SHA512" )
- {
+ }
+ 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);
- }
- else if(subCommand == "TOLOWER")
- {
+ }
+ if (subCommand == "TOLOWER") {
return this->HandleToUpperLowerCommand(args, false);
- }
- else if(subCommand == "TOUPPER")
- {
+ }
+ if (subCommand == "TOUPPER") {
return this->HandleToUpperLowerCommand(args, true);
- }
- else if(subCommand == "COMPARE")
- {
+ }
+ if (subCommand == "COMPARE") {
return this->HandleCompareCommand(args);
- }
- else if(subCommand == "ASCII")
- {
+ }
+ if (subCommand == "ASCII") {
return this->HandleAsciiCommand(args);
- }
- else if(subCommand == "CONFIGURE")
- {
+ }
+ if (subCommand == "CONFIGURE") {
return this->HandleConfigureCommand(args);
- }
- else if(subCommand == "LENGTH")
- {
+ }
+ if (subCommand == "LENGTH") {
return this->HandleLengthCommand(args);
- }
- else if(subCommand == "SUBSTRING")
- {
+ }
+ if (subCommand == "APPEND") {
+ return this->HandleAppendCommand(args);
+ }
+ if (subCommand == "CONCAT") {
+ return this->HandleConcatCommand(args);
+ }
+ if (subCommand == "SUBSTRING") {
return this->HandleSubstringCommand(args);
- }
- else if(subCommand == "STRIP")
- {
+ }
+ if (subCommand == "STRIP") {
return this->HandleStripCommand(args);
- }
- else if(subCommand == "RANDOM")
- {
+ }
+ if (subCommand == "RANDOM") {
return this->HandleRandomCommand(args);
- }
- else if(subCommand == "FIND")
- {
+ }
+ if (subCommand == "FIND") {
return this->HandleFindCommand(args);
- }
- else if(subCommand == "TIMESTAMP")
- {
+ }
+ if (subCommand == "TIMESTAMP") {
return this->HandleTimestampCommand(args);
- }
- else if(subCommand == "MAKE_C_IDENTIFIER")
- {
+ }
+ if (subCommand == "MAKE_C_IDENTIFIER") {
return this->HandleMakeCIdentifierCommand(args);
- }
-
- std::string e = "does not recognize sub-command "+subCommand;
- this->SetError(e.c_str());
+ }
+ if (subCommand == "GENEX_STRIP") {
+ return this->HandleGenexStripCommand(args);
+ }
+ if (subCommand == "UUID") {
+ return this->HandleUuidCommand(args);
+ }
+
+ std::string e = "does not recognize sub-command " + subCommand;
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::HandleHashCommand(std::vector<std::string> const& args)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
- if(args.size() != 3)
- {
- cmOStringStream e;
+ if (args.size() != 3) {
+ std::ostringstream e;
e << args[0] << " requires an output variable and an input string";
- this->SetError(e.str().c_str());
+ this->SetError(e.str());
return false;
- }
+ }
- cmsys::auto_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
- if(hash.get())
- {
- std::string out = hash->HashString(args[2].c_str());
- this->Makefile->AddDefinition(args[1].c_str(), out.c_str());
+ CM_AUTO_PTR<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
+ if (hash.get()) {
+ std::string out = hash->HashString(args[2]);
+ this->Makefile->AddDefinition(args[1], out.c_str());
return true;
- }
+ }
return false;
#else
- cmOStringStream e;
+ std::ostringstream e;
e << args[0] << " not available during bootstrap";
this->SetError(e.str().c_str());
return false;
#endif
}
-//----------------------------------------------------------------------------
bool cmStringCommand::HandleToUpperLowerCommand(
std::vector<std::string> const& args, bool toUpper)
{
- if ( args.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("no output variable specified");
return false;
- }
+ }
- std::string outvar = args[2];
+ std::string const& outvar = args[2];
std::string output;
- if (toUpper)
- {
+ if (toUpper) {
output = cmSystemTools::UpperCase(args[1]);
- }
- else
- {
+ } else {
output = cmSystemTools::LowerCase(args[1]);
- }
+ }
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
+ this->Makefile->AddDefinition(outvar, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
{
- if ( args.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("No output variable specified");
return false;
- }
+ }
std::string::size_type cc;
- std::string outvar = args[args.size()-1];
- std::string output = "";
- for ( cc = 1; cc < args.size()-1; cc ++ )
- {
+ std::string const& outvar = args[args.size() - 1];
+ std::string output;
+ for (cc = 1; cc < args.size() - 1; cc++) {
int ch = atoi(args[cc].c_str());
- if ( ch > 0 && ch < 256 )
- {
+ if (ch > 0 && ch < 256) {
output += static_cast<char>(ch);
- }
- else
- {
+ } else {
std::string error = "Character with code ";
error += args[cc];
error += " does not exist.";
- this->SetError(error.c_str());
+ this->SetError(error);
return false;
- }
}
+ }
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
+ this->Makefile->AddDefinition(outvar, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::HandleConfigureCommand(
std::vector<std::string> const& args)
{
- if ( args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("No input string specified.");
return false;
- }
- else if ( args.size() < 3 )
- {
+ }
+ if (args.size() < 3) {
this->SetError("No output variable specified.");
return false;
- }
+ }
// Parse options.
bool escapeQuotes = false;
bool atOnly = false;
- for(unsigned int i = 3; i < args.size(); ++i)
- {
- if(args[i] == "@ONLY")
- {
+ for (unsigned int i = 3; i < args.size(); ++i) {
+ if (args[i] == "@ONLY") {
atOnly = true;
- }
- else if(args[i] == "ESCAPE_QUOTES")
- {
+ } else if (args[i] == "ESCAPE_QUOTES") {
escapeQuotes = true;
- }
- else
- {
- cmOStringStream err;
+ } else {
+ std::ostringstream err;
err << "Unrecognized argument \"" << args[i] << "\"";
- this->SetError(err.str().c_str());
+ this->SetError(err.str());
return false;
- }
}
+ }
// Configure the string.
std::string output;
this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes);
// Store the output in the provided variable.
- this->Makefile->AddDefinition(args[2].c_str(), output.c_str());
+ this->Makefile->AddDefinition(args[2], output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
+ if (args.size() < 2) {
this->SetError("sub-command REGEX requires a mode to be specified.");
return false;
- }
- std::string mode = args[1];
- if(mode == "MATCH")
- {
- if(args.size() < 5)
- {
+ }
+ 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.");
return false;
- }
- return this->RegexMatch(args);
}
- else if(mode == "MATCHALL")
- {
- if(args.size() < 5)
- {
+ return this->RegexMatch(args);
+ }
+ if (mode == "MATCHALL") {
+ if (args.size() < 5) {
this->SetError("sub-command REGEX, mode MATCHALL needs "
"at least 5 arguments total to command.");
return false;
- }
- return this->RegexMatchAll(args);
}
- else if(mode == "REPLACE")
- {
- if(args.size() < 6)
- {
+ return this->RegexMatchAll(args);
+ }
+ if (mode == "REPLACE") {
+ if (args.size() < 6) {
this->SetError("sub-command REGEX, mode REPLACE needs "
"at least 6 arguments total to command.");
return false;
- }
- return this->RegexReplace(args);
}
+ return this->RegexReplace(args);
+ }
- std::string e = "sub-command REGEX does not recognize mode "+mode;
- this->SetError(e.c_str());
+ std::string e = "sub-command REGEX does not recognize mode " + mode;
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
{
//"STRING(REGEX MATCH <regular_expression> <output variable>
// <input> [<input>...])\n";
- std::string regex = args[2];
- std::string outvar = args[3];
-
- // Concatenate all the last arguments together.
- std::string input = args[4];
- for(unsigned int i=5; i < args.size(); ++i)
- {
- input += args[i];
- }
+ std::string const& regex = args[2];
+ std::string const& outvar = args[3];
- this->ClearMatches(this->Makefile);
+ this->Makefile->ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if(!re.compile(regex.c_str()))
- {
+ if (!re.compile(regex.c_str())) {
std::string e =
- "sub-command REGEX, mode MATCH failed to compile regex \""+regex+"\".";
- this->SetError(e.c_str());
+ "sub-command REGEX, mode MATCH failed to compile regex \"" + regex +
+ "\".";
+ this->SetError(e);
return false;
- }
+ }
+
+ // Concatenate all the last arguments together.
+ std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
// Scan through the input for all matches.
std::string output;
- if(re.find(input.c_str()))
- {
- this->StoreMatches(this->Makefile, re);
+ if (re.find(input.c_str())) {
+ this->Makefile->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+
+ if (r - l == 0) {
+ std::string e = "sub-command REGEX, mode MATCH regex \"" + regex +
"\" matched an empty string.";
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
- }
- output = input.substr(l, r-l);
}
+ output = input.substr(l, r - l);
+ }
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
+ this->Makefile->AddDefinition(outvar, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
{
//"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
// [<input>...])\n";
- std::string regex = args[2];
- std::string outvar = args[3];
-
- // Concatenate all the last arguments together.
- std::string input = args[4];
- for(unsigned int i=5; i < args.size(); ++i)
- {
- input += args[i];
- }
+ std::string const& regex = args[2];
+ std::string const& outvar = args[3];
- this->ClearMatches(this->Makefile);
+ this->Makefile->ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if(!re.compile(regex.c_str()))
- {
+ if (!re.compile(regex.c_str())) {
std::string e =
- "sub-command REGEX, mode MATCHALL failed to compile regex \""+
- regex+"\".";
- this->SetError(e.c_str());
+ "sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex +
+ "\".";
+ this->SetError(e);
return false;
- }
+ }
+
+ // Concatenate all the last arguments together.
+ std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
// Scan through the input for all matches.
std::string output;
const char* p = input.c_str();
- while(re.find(p))
- {
- this->StoreMatches(this->Makefile, re);
+ while (re.find(p)) {
+ this->Makefile->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.c_str());
+ if (r - l == 0) {
+ std::string e = "sub-command REGEX, mode MATCHALL regex \"" + regex +
+ "\" matched an empty string.";
+ this->SetError(e);
return false;
- }
- if(output.length() > 0)
- {
+ }
+ if (!output.empty()) {
output += ";";
- }
- output += std::string(p+l, r-l);
- p += r;
}
+ output += std::string(p + l, r - l);
+ p += r;
+ }
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
+ this->Makefile->AddDefinition(outvar, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
{
//"STRING(REGEX REPLACE <regular_expression> <replace_expression>
// <output variable> <input> [<input>...])\n"
- std::string regex = args[2];
- std::string replace = args[3];
- std::string outvar = args[4];
+ std::string const& regex = args[2];
+ std::string const& replace = args[3];
+ std::string const& outvar = args[4];
// 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)
- {
+ 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));
+ replacement.push_back(replace.substr(l, r - l));
+ } else {
+ if (r - l > 0) {
+ 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))
- {
+ 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')
- {
+ }
+ 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] == '\\')
- {
+ } else if (replace[r + 1] == '\\') {
replacement.push_back("\\");
- }
- else
- {
+ } else {
std::string e = "sub-command REGEX, mode REPLACE: Unknown escape \"";
e += replace.substr(r, 2);
e += "\" in replace-expression.";
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
- }
- r += 2;
}
- l = r;
- }
-
- // Concatenate all the last arguments together.
- std::string input = args[5];
- for(unsigned int i=6; i < args.size(); ++i)
- {
- input += args[i];
+ r += 2;
}
+ l = r;
+ }
- this->ClearMatches(this->Makefile);
+ this->Makefile->ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if(!re.compile(regex.c_str()))
- {
+ if (!re.compile(regex.c_str())) {
std::string e =
- "sub-command REGEX, mode REPLACE failed to compile regex \""+
- regex+"\".";
- this->SetError(e.c_str());
+ "sub-command REGEX, mode REPLACE failed to compile regex \"" + regex +
+ "\".";
+ this->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.
std::string output;
std::string::size_type base = 0;
- while(re.find(input.c_str()+base))
- {
- this->StoreMatches(this->Makefile, re);
+ 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();
@@ -475,114 +399,69 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
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.c_str());
+ 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)
- {
+ 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
- {
+ } 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::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.c_str());
+ "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;
- }
+ }
// Concatenate the text after the last match.
- output += input.substr(base, input.length()-base);
+ output += input.substr(base, input.length() - base);
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
+ this->Makefile->AddDefinition(outvar, output.c_str());
return true;
}
-//----------------------------------------------------------------------------
-void cmStringCommand::ClearMatches(cmMakefile* mf)
-{
- for (unsigned int i=0; i<10; i++)
- {
- char name[128];
- sprintf(name, "CMAKE_MATCH_%d", i);
- const char* s = mf->GetDefinition(name);
- if(s && *s != 0)
- {
- mf->AddDefinition(name, "");
- mf->MarkVariableAsUsed(name);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re)
-{
- for (unsigned int i=0; i<10; i++)
- {
- std::string m = re.match(i);
- if(m.size() > 0)
- {
- char name[128];
- sprintf(name, "CMAKE_MATCH_%d", i);
- mf->AddDefinition(name, re.match(i).c_str());
- mf->MarkVariableAsUsed(name);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmStringCommand::HandleFindCommand(std::vector<std::string> const&
- args)
+bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
{
// check if all required parameters were passed
- if(args.size() < 4 || args.size() > 5)
- {
+ if (args.size() < 4 || args.size() > 5) {
this->SetError("sub-command FIND requires 3 or 4 parameters.");
return false;
- }
+ }
// check if the reverse flag was set or not
bool reverseMode = false;
- if(args.size() == 5 && args[4] == "REVERSE")
- {
+ if (args.size() == 5 && args[4] == "REVERSE") {
reverseMode = true;
- }
+ }
// if we have 5 arguments the last one must be REVERSE
- if(args.size() == 5 && args[4] != "REVERSE")
- {
+ if (args.size() == 5 && args[4] != "REVERSE") {
this->SetError("sub-command FIND: unknown last parameter");
return false;
- }
+ }
// local parameter names.
const std::string& sstring = args[1];
@@ -590,130 +469,109 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const&
const std::string& outvar = args[3];
// ensure that the user cannot accidentally specify REVERSE as a variable
- if(outvar == "REVERSE")
- {
- this->SetError("sub-command FIND does not allow to select REVERSE as "
+ 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?");
return false;
- }
+ }
// try to find the character and return its position
size_t pos;
- if(!reverseMode)
- {
+ if (!reverseMode) {
pos = sstring.find(schar);
- }
- else
- {
+ } else {
pos = sstring.rfind(schar);
- }
- if(std::string::npos != pos)
- {
- cmOStringStream s;
+ }
+ if (std::string::npos != pos) {
+ std::ostringstream s;
s << pos;
- this->Makefile->AddDefinition(outvar.c_str(), s.str().c_str());
+ this->Makefile->AddDefinition(outvar, s.str().c_str());
return true;
- }
+ }
// the character was not found, but this is not really an error
- this->Makefile->AddDefinition(outvar.c_str(), "-1");
+ this->Makefile->AddDefinition(outvar, "-1");
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand::HandleCompareCommand(std::vector<std::string> const&
- args)
+bool cmStringCommand::HandleCompareCommand(
+ std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
+ if (args.size() < 2) {
this->SetError("sub-command COMPARE requires a mode to be specified.");
return false;
- }
- std::string mode = args[1];
- if((mode == "EQUAL") || (mode == "NOTEQUAL") ||
- (mode == "LESS") || (mode == "GREATER"))
- {
- if(args.size() < 5)
- {
+ }
+ std::string const& mode = args[1];
+ if ((mode == "EQUAL") || (mode == "NOTEQUAL") || (mode == "LESS") ||
+ (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.c_str());
+ this->SetError(e);
return false;
- }
+ }
const std::string& left = args[2];
const std::string& right = args[3];
const std::string& outvar = args[4];
bool result;
- if(mode == "LESS")
- {
+ if (mode == "LESS") {
result = (left < right);
- }
- else if(mode == "GREATER")
- {
+ } else if (mode == "LESS_EQUAL") {
+ result = (left <= right);
+ } else if (mode == "GREATER") {
result = (left > right);
- }
- else if(mode == "EQUAL")
- {
+ } else if (mode == "GREATER_EQUAL") {
+ result = (left >= right);
+ } else if (mode == "EQUAL") {
result = (left == right);
- }
- else // if(mode == "NOTEQUAL")
- {
+ } else // if(mode == "NOTEQUAL")
+ {
result = !(left == right);
- }
- if(result)
- {
- this->Makefile->AddDefinition(outvar.c_str(), "1");
- }
- else
- {
- this->Makefile->AddDefinition(outvar.c_str(), "0");
- }
- return true;
}
- std::string e = "sub-command COMPARE does not recognize mode "+mode;
- this->SetError(e.c_str());
+ if (result) {
+ this->Makefile->AddDefinition(outvar, "1");
+ } else {
+ this->Makefile->AddDefinition(outvar, "0");
+ }
+ return true;
+ }
+ std::string e = "sub-command COMPARE does not recognize mode " + mode;
+ this->SetError(e);
return false;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand::HandleReplaceCommand(std::vector<std::string> const&
- args)
+bool cmStringCommand::HandleReplaceCommand(
+ std::vector<std::string> const& args)
{
- if(args.size() < 5)
- {
+ if (args.size() < 5) {
this->SetError("sub-command REPLACE requires at least four arguments.");
return false;
- }
+ }
const std::string& matchExpression = args[1];
const std::string& replaceExpression = args[2];
const std::string& variableName = args[3];
- std::string input = args[4];
- for(unsigned int i=5; i < args.size(); ++i)
- {
- input += args[i];
- }
+ std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
replaceExpression.c_str());
- this->Makefile->AddDefinition(variableName.c_str(), input.c_str());
+ this->Makefile->AddDefinition(variableName, input.c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand::HandleSubstringCommand(std::vector<std::string> const&
- args)
+bool cmStringCommand::HandleSubstringCommand(
+ std::vector<std::string> const& args)
{
- if(args.size() != 5)
- {
+ if (args.size() != 5) {
this->SetError("sub-command SUBSTRING requires four arguments.");
return false;
- }
+ }
const std::string& stringValue = args[1];
int begin = atoi(args[2].c_str());
@@ -722,38 +580,31 @@ bool cmStringCommand::HandleSubstringCommand(std::vector<std::string> const&
size_t stringLength = stringValue.size();
int intStringLength = static_cast<int>(stringLength);
- if ( begin < 0 || begin > intStringLength )
- {
- cmOStringStream ostr;
+ if (begin < 0 || begin > intStringLength) {
+ std::ostringstream ostr;
ostr << "begin index: " << begin << " is out of range 0 - "
<< stringLength;
- this->SetError(ostr.str().c_str());
+ this->SetError(ostr.str());
return false;
- }
- int leftOverLength = intStringLength - begin;
- if ( end < -1 || end > leftOverLength )
- {
- cmOStringStream ostr;
- ostr << "end index: " << end << " is out of range -1 - "
- << leftOverLength;
- this->SetError(ostr.str().c_str());
+ }
+ if (end < -1) {
+ std::ostringstream ostr;
+ ostr << "end index: " << end << " should be -1 or greater";
+ this->SetError(ostr.str());
return false;
- }
+ }
- this->Makefile->AddDefinition(variableName.c_str(),
+ this->Makefile->AddDefinition(variableName,
stringValue.substr(begin, end).c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand
-::HandleLengthCommand(std::vector<std::string> const& args)
+bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
this->SetError("sub-command LENGTH requires two arguments.");
return false;
- }
+ }
const std::string& stringValue = args[1];
const std::string& variableName = args[2];
@@ -762,37 +613,89 @@ bool cmStringCommand
char buffer[1024];
sprintf(buffer, "%d", static_cast<int>(length));
- this->Makefile->AddDefinition(variableName.c_str(), buffer);
+ this->Makefile->AddDefinition(variableName, buffer);
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand
-::HandleMakeCIdentifierCommand(std::vector<std::string> const& args)
+bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() < 2) {
+ this->SetError("sub-command APPEND requires at least one argument.");
+ return false;
+ }
+
+ // Skip if nothing to append.
+ if (args.size() < 3) {
+ return true;
+ }
+
+ const std::string& variable = args[1];
+
+ std::string value;
+ const char* oldValue = this->Makefile->GetDefinition(variable);
+ if (oldValue) {
+ value = oldValue;
+ }
+ value += cmJoin(cmMakeRange(args).advance(2), std::string());
+ this->Makefile->AddDefinition(variable, value.c_str());
+ return true;
+}
+
+bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 2) {
+ this->SetError("sub-command CONCAT requires at least one argument.");
+ return false;
+ }
+
+ std::string const& variableName = args[1];
+ std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
+
+ this->Makefile->AddDefinition(variableName, value.c_str());
+ return true;
+}
+
+bool cmStringCommand::HandleMakeCIdentifierCommand(
+ std::vector<std::string> const& args)
+{
+ if (args.size() != 3) {
this->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.c_str(),
- cmSystemTools::MakeCidentifier(input.c_str()).c_str());
+ this->Makefile->AddDefinition(variableName,
+ cmSystemTools::MakeCidentifier(input).c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand::HandleStripCommand(
+bool cmStringCommand::HandleGenexStripCommand(
std::vector<std::string> const& args)
{
- if(args.size() != 3)
- {
+ if (args.size() != 3) {
+ this->SetError("sub-command GENEX_STRIP requires two arguments.");
+ return false;
+ }
+
+ const std::string& input = args[1];
+
+ std::string result = cmGeneratorExpression::Preprocess(
+ input, cmGeneratorExpression::StripAllGeneratorExpressions);
+
+ const std::string& variableName = args[2];
+
+ this->Makefile->AddDefinition(variableName, result.c_str());
+ return true;
+}
+
+bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
+{
+ if (args.size() != 3) {
this->SetError("sub-command STRIP requires two arguments.");
return false;
- }
+ }
const std::string& stringValue = args[1];
const std::string& variableName = args[2];
@@ -801,165 +704,224 @@ bool cmStringCommand::HandleStripCommand(
size_t endPos = 0;
const char* ptr = stringValue.c_str();
size_t cc;
- for ( cc = 0; cc < inStringLength; ++ cc )
- {
- if ( !isspace(*ptr) )
- {
- if ( startPos > inStringLength )
- {
+ for (cc = 0; cc < inStringLength; ++cc) {
+ if (!isspace(*ptr)) {
+ if (startPos > inStringLength) {
startPos = cc;
- }
- endPos = cc;
}
- ++ ptr;
+ endPos = cc;
}
+ ++ptr;
+ }
size_t outLength = 0;
// if the input string didn't contain any non-space characters, return
// an empty string
- if (startPos > inStringLength)
- {
+ if (startPos > inStringLength) {
outLength = 0;
startPos = 0;
- }
- else
- {
- outLength=endPos - startPos + 1;
- }
+ } else {
+ outLength = endPos - startPos + 1;
+ }
- this->Makefile->AddDefinition(variableName.c_str(),
- stringValue.substr(startPos, outLength).c_str());
+ this->Makefile->AddDefinition(
+ variableName, stringValue.substr(startPos, outLength).c_str());
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand
-::HandleRandomCommand(std::vector<std::string> const& args)
+bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
{
- if(args.size() < 2 || args.size() == 3 || args.size() == 5)
- {
+ if (args.size() < 2 || args.size() == 3 || args.size() == 5) {
this->SetError("sub-command RANDOM requires at least one argument.");
return false;
- }
+ }
static bool seeded = false;
bool force_seed = false;
unsigned int seed = 0;
int length = 5;
const char cmStringCommandDefaultAlphabet[] = "qwertyuiopasdfghjklzxcvbnm"
- "QWERTYUIOPASDFGHJKLZXCVBNM"
- "0123456789";
+ "QWERTYUIOPASDFGHJKLZXCVBNM"
+ "0123456789";
std::string alphabet;
- if ( args.size() > 3 )
- {
+ if (args.size() > 3) {
size_t i = 1;
size_t stopAt = args.size() - 2;
- for ( ; i < stopAt; ++i )
- {
- if ( args[i] == "LENGTH" )
- {
+ for (; i < stopAt; ++i) {
+ if (args[i] == "LENGTH") {
++i;
length = atoi(args[i].c_str());
- }
- else if ( args[i] == "ALPHABET" )
- {
+ } else if (args[i] == "ALPHABET") {
++i;
alphabet = args[i];
- }
- else if ( args[i] == "RANDOM_SEED" )
- {
+ } else if (args[i] == "RANDOM_SEED") {
++i;
seed = static_cast<unsigned int>(atoi(args[i].c_str()));
force_seed = true;
- }
}
}
- if ( !alphabet.size() )
- {
+ }
+ if (alphabet.empty()) {
alphabet = cmStringCommandDefaultAlphabet;
- }
+ }
double sizeofAlphabet = static_cast<double>(alphabet.size());
- if ( sizeofAlphabet < 1 )
- {
+ if (sizeofAlphabet < 1) {
this->SetError("sub-command RANDOM invoked with bad alphabet.");
return false;
- }
- if ( length < 1 )
- {
+ }
+ if (length < 1) {
this->SetError("sub-command RANDOM invoked with bad length.");
return false;
- }
- const std::string& variableName = args[args.size()-1];
+ }
+ const std::string& variableName = args[args.size() - 1];
std::vector<char> result;
- if (!seeded || force_seed)
- {
+ if (!seeded || force_seed) {
seeded = true;
- srand(force_seed? seed : cmSystemTools::RandomSeed());
- }
+ srand(force_seed ? seed : cmSystemTools::RandomSeed());
+ }
const char* alphaPtr = alphabet.c_str();
int cc;
- for ( cc = 0; cc < length; cc ++ )
- {
- int idx=(int) (sizeofAlphabet* rand()/(RAND_MAX+1.0));
+ for (cc = 0; cc < length; cc++) {
+ int idx = (int)(sizeofAlphabet * rand() / (RAND_MAX + 1.0));
result.push_back(*(alphaPtr + idx));
- }
+ }
result.push_back(0);
- this->Makefile->AddDefinition(variableName.c_str(), &*result.begin());
+ this->Makefile->AddDefinition(variableName, &*result.begin());
return true;
}
-//----------------------------------------------------------------------------
-bool cmStringCommand
-::HandleTimestampCommand(std::vector<std::string> const& args)
+bool cmStringCommand::HandleTimestampCommand(
+ std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
+ if (args.size() < 2) {
this->SetError("sub-command TIMESTAMP requires at least one argument.");
return false;
- }
- else if(args.size() > 4)
- {
+ }
+ if (args.size() > 4) {
this->SetError("sub-command TIMESTAMP takes at most three arguments.");
return false;
- }
+ }
unsigned int argsIndex = 1;
- const std::string &outputVariable = args[argsIndex++];
+ const std::string& outputVariable = args[argsIndex++];
std::string formatString;
- if(args.size() > argsIndex && args[argsIndex] != "UTC")
- {
+ if (args.size() > argsIndex && args[argsIndex] != "UTC") {
formatString = args[argsIndex++];
- }
+ }
bool utcFlag = false;
- if(args.size() > argsIndex)
- {
- if(args[argsIndex] == "UTC")
- {
+ if (args.size() > argsIndex) {
+ if (args[argsIndex] == "UTC") {
utcFlag = true;
- }
- else
- {
+ } else {
std::string e = " TIMESTAMP sub-command does not recognize option " +
- args[argsIndex] + ".";
- this->SetError(e.c_str());
+ args[argsIndex] + ".";
+ this->SetError(e);
return false;
- }
}
+ }
cmTimestamp timestamp;
std::string result = timestamp.CurrentTime(formatString, utcFlag);
- this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str());
+ this->Makefile->AddDefinition(outputVariable, result.c_str());
return true;
}
+
+bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
+{
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ unsigned int argsIndex = 1;
+
+ if (args.size() < 2) {
+ this->SetError("UUID sub-command requires an output variable.");
+ return false;
+ }
+
+ const std::string& outputVariable = args[argsIndex++];
+
+ std::string uuidNamespaceString;
+ std::string uuidName;
+ std::string uuidType;
+ bool uuidUpperCase = false;
+
+ while (args.size() > argsIndex) {
+ if (args[argsIndex] == "NAMESPACE") {
+ ++argsIndex;
+ if (argsIndex >= args.size()) {
+ this->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.");
+ return false;
+ }
+ uuidName = args[argsIndex++];
+ } else if (args[argsIndex] == "TYPE") {
+ ++argsIndex;
+ if (argsIndex >= args.size()) {
+ this->SetError("UUID sub-command, TYPE requires a value.");
+ return false;
+ }
+ uuidType = args[argsIndex++];
+ } else if (args[argsIndex] == "UPPER") {
+ ++argsIndex;
+ uuidUpperCase = true;
+ } else {
+ std::string e =
+ "UUID sub-command does not recognize option " + args[argsIndex] + ".";
+ this->SetError(e);
+ return false;
+ }
+ }
+
+ std::string uuid;
+ cmUuid uuidGenerator;
+
+ std::vector<unsigned char> uuidNamespace;
+ if (!uuidGenerator.StringToBinary(uuidNamespaceString, uuidNamespace)) {
+ this->SetError("UUID sub-command, malformed NAMESPACE UUID.");
+ return false;
+ }
+
+ if (uuidType == "MD5") {
+ uuid = uuidGenerator.FromMd5(uuidNamespace, uuidName);
+ } else if (uuidType == "SHA1") {
+ uuid = uuidGenerator.FromSha1(uuidNamespace, uuidName);
+ } else {
+ std::string e = "UUID sub-command, unknown TYPE '" + uuidType + "'.";
+ this->SetError(e);
+ return false;
+ }
+
+ if (uuid.empty()) {
+ this->SetError("UUID sub-command, generation failed.");
+ return false;
+ }
+
+ if (uuidUpperCase) {
+ uuid = cmSystemTools::UpperCase(uuid);
+ }
+
+ this->Makefile->AddDefinition(outputVariable, uuid.c_str());
+ return true;
+#else
+ std::ostringstream e;
+ e << args[0] << " not available during bootstrap";
+ this->SetError(e.str().c_str());
+ return false;
+#endif
+}
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index f584cfdbf..88015ad5e 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -1,24 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmStringCommand_h
#define cmStringCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-class cmMakefile;
-namespace cmsys
-{
- class RegularExpression;
-}
+class cmExecutionStatus;
/** \class cmStringCommand
* \brief Common string operations
@@ -30,161 +22,15 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmStringCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmStringCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "string";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "String operations.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " string(REGEX MATCH <regular_expression>\n"
- " <output variable> <input> [<input>...])\n"
- " string(REGEX MATCHALL <regular_expression>\n"
- " <output variable> <input> [<input>...])\n"
- " string(REGEX REPLACE <regular_expression>\n"
- " <replace_expression> <output variable>\n"
- " <input> [<input>...])\n"
- " string(REPLACE <match_string>\n"
- " <replace_string> <output variable>\n"
- " <input> [<input>...])\n"
- " string(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512>\n"
- " <output variable> <input>)\n"
- " string(COMPARE EQUAL <string1> <string2> <output variable>)\n"
- " string(COMPARE NOTEQUAL <string1> <string2> <output variable>)\n"
- " string(COMPARE LESS <string1> <string2> <output variable>)\n"
- " string(COMPARE GREATER <string1> <string2> <output variable>)\n"
- " string(ASCII <number> [<number> ...] <output variable>)\n"
- " string(CONFIGURE <string1> <output variable>\n"
- " [@ONLY] [ESCAPE_QUOTES])\n"
- " string(TOUPPER <string1> <output variable>)\n"
- " string(TOLOWER <string1> <output variable>)\n"
- " string(LENGTH <string> <output variable>)\n"
- " string(SUBSTRING <string> <begin> <length> <output variable>)\n"
- " string(STRIP <string> <output variable>)\n"
- " string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]\n"
- " [RANDOM_SEED <seed>] <output variable>)\n"
- " string(FIND <string> <substring> <output variable> [REVERSE])\n"
- " string(TIMESTAMP <output variable> [<format string>] [UTC])\n"
- " string(MAKE_C_IDENTIFIER <input string> <output variable>)\n"
- "REGEX MATCH will match the regular expression once and store the "
- "match in the output variable.\n"
- "REGEX MATCHALL will match the regular expression as many times as "
- "possible and store the matches in the output variable as a list.\n"
- "REGEX REPLACE will match the regular expression as many times as "
- "possible and substitute the replacement expression for the match "
- "in the output. The replace expression may refer to paren-delimited "
- "subexpressions of the match using \\1, \\2, ..., \\9. Note that "
- "two backslashes (\\\\1) are required in CMake code to get a "
- "backslash through argument parsing.\n"
- "REPLACE will replace all occurrences of match_string in the input with "
- "replace_string and store the result in the output.\n"
- "MD5, SHA1, SHA224, SHA256, SHA384, and SHA512 "
- "will compute a cryptographic hash of the input string.\n"
- "COMPARE EQUAL/NOTEQUAL/LESS/GREATER will compare the strings and "
- "store true or false in the output variable.\n"
- "ASCII will convert all numbers into corresponding ASCII characters.\n"
- "CONFIGURE will transform a string like CONFIGURE_FILE transforms "
- "a file.\n"
- "TOUPPER/TOLOWER will convert string to upper/lower characters.\n"
- "LENGTH will return a given string's length.\n"
- "SUBSTRING will return a substring of a given string. If length is "
- "-1 the remainder of the string starting at begin will be returned.\n"
- "STRIP will return a substring of a given string with leading "
- "and trailing spaces removed.\n"
- "RANDOM will return a random string of given length consisting of "
- "characters from the given alphabet. Default length is 5 "
- "characters and default alphabet is all numbers and upper and "
- "lower case letters. If an integer RANDOM_SEED is given, its "
- "value will be used to seed the random number generator.\n"
- "FIND will return the position where the given substring was found "
- "in the supplied string. If the REVERSE flag was used, the command "
- "will search for the position of the last occurrence of the "
- "specified substring.\n"
- "The following characters have special meaning in regular expressions:\n"
- " ^ Matches at beginning of input\n"
- " $ Matches at end of input\n"
- " . Matches any single character\n"
- " [ ] Matches any character(s) inside the brackets\n"
- " [^ ] Matches any character(s) not inside the brackets\n"
- " - Inside brackets, specifies an inclusive range between\n"
- " characters on either side e.g. [a-f] is [abcdef]\n"
- " To match a literal - using brackets, make it the first\n"
- " or the last character e.g. [+*/-] matches basic\n"
- " mathematical operators.\n"
- " * Matches preceding pattern zero or more times\n"
- " + Matches preceding pattern one or more times\n"
- " ? Matches preceding pattern zero or once only\n"
- " | Matches a pattern on either side of the |\n"
- " () Saves a matched subexpression, which can be referenced \n"
- " in the REGEX REPLACE operation. Additionally it is saved\n"
- " by all regular expression-related commands, including \n"
- " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n"
- "*, + and ? have higher precedence than concatenation. | has lower "
- "precedence than concatenation. This means that the regular expression "
- "\"^ab+d$\" matches \"abbd\" but not \"ababd\", and the regular "
- "expression \"^(ab|cd)$\" matches \"ab\" but not \"abd\".\n"
- "TIMESTAMP will write a string representation of "
- "the current date and/or time to the output variable.\n"
- "Should the command be unable to obtain a timestamp "
- "the output variable will be set to the empty string \"\".\n"
- "The optional UTC flag requests the current date/time "
- "representation to be in Coordinated Universal Time (UTC) "
- "rather than local time.\n"
- "The optional <format string> may contain the following "
- "format specifiers: \n"
- " %d The day of the current month (01-31).\n"
- " %H The hour on a 24-hour clock (00-23).\n"
- " %I The hour on a 12-hour clock (01-12).\n"
- " %j The day of the current year (001-366).\n"
- " %m The month of the current year (01-12).\n"
- " %M The minute of the current hour (00-59).\n"
- " %S The second of the current minute.\n"
- " 60 represents a leap second. (00-60)\n"
- " %U The week number of the current year (00-53).\n"
- " %w The day of the current week. 0 is Sunday. (0-6)\n"
- " %y The last two digits of the current year (00-99)\n"
- " %Y The current year. \n"
- "Unknown format specifiers will be ignored "
- "and copied to the output as-is.\n"
- "If no explicit <format string> is given it will default to:\n"
- " %Y-%m-%dT%H:%M:%S for local time.\n"
- " %Y-%m-%dT%H:%M:%SZ for UTC.\n"
- "MAKE_C_IDENTIFIER will write a string which can be used as an "
- "identifier in C.";
- }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- cmTypeMacro(cmStringCommand, cmCommand);
- static void ClearMatches(cmMakefile* mf);
- static void StoreMatches(cmMakefile* mf, cmsys::RegularExpression& re);
protected:
bool HandleConfigureCommand(std::vector<std::string> const& args);
bool HandleAsciiCommand(std::vector<std::string> const& args);
@@ -199,23 +45,38 @@ protected:
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() {};
+ 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;
};
};
-
#endif
diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx
index e497b4642..3727dfa25 100644
--- a/Source/cmSubdirCommand.cxx
+++ b/Source/cmSubdirCommand.cxx
@@ -1,74 +1,56 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSubdirCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSubdirCommand.h"
+class cmExecutionStatus;
// cmSubdirCommand
-bool cmSubdirCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
bool res = true;
bool excludeFromAll = false;
- bool preorder = false;
- for(std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
- if(*i == "EXCLUDE_FROM_ALL")
- {
+ for (std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i) {
+ if (*i == "EXCLUDE_FROM_ALL") {
excludeFromAll = true;
continue;
- }
- if(*i == "PREORDER")
- {
- preorder = true;
+ }
+ if (*i == "PREORDER") {
+ // Ignored
continue;
- }
+ }
// if they specified a relative path then compute the full
std::string srcPath =
- std::string(this->Makefile->GetCurrentDirectory()) +
- "/" + i->c_str();
- if (cmSystemTools::FileIsDirectory(srcPath.c_str()))
- {
+ std::string(this->Makefile->GetCurrentSourceDirectory()) + "/" + *i;
+ if (cmSystemTools::FileIsDirectory(srcPath)) {
std::string binPath =
- std::string(this->Makefile->GetCurrentOutputDirectory()) +
- "/" + i->c_str();
- this->Makefile->AddSubDirectory(srcPath.c_str(), binPath.c_str(),
- excludeFromAll, preorder, false);
- }
+ std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" + *i;
+ this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, false);
+ }
// otherwise it is a full path
- else if ( cmSystemTools::FileIsDirectory(i->c_str()) )
- {
+ 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->GetCurrentOutputDirectory()) +
- "/" + cmSystemTools::GetFilenameName(i->c_str());
- this->Makefile->AddSubDirectory(i->c_str(), binPath.c_str(),
- excludeFromAll, preorder, false);
- }
- else
- {
+ std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" +
+ cmSystemTools::GetFilenameName(*i);
+ this->Makefile->AddSubDirectory(*i, binPath, excludeFromAll, false);
+ } else {
std::string error = "Incorrect SUBDIRS command. Directory: ";
error += *i + " does not exist.";
- this->SetError(error.c_str());
+ this->SetError(error);
res = false;
- }
}
+ }
return res;
}
-
diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h
index 618d5ff2b..a2af0fd58 100644
--- a/Source/cmSubdirCommand.h
+++ b/Source/cmSubdirCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSubdirCommand_h
#define cmSubdirCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmSubdirCommand
* \brief Specify a list of subdirectories to build.
*
@@ -27,66 +25,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmSubdirCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmSubdirCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "subdirs";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the add_subdirectory() command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "Add a list of subdirectories to the build.\n"
- " subdirs(dir1 dir2 ..."
- "[EXCLUDE_FROM_ALL exclude_dir1 exclude_dir2 ...]\n"
- " [PREORDER] )\n"
- "Add a list of subdirectories to the build. The add_subdirectory "
- "command should be used instead of subdirs although subdirs will "
- "still work. "
- "This will cause any CMakeLists.txt files in the sub directories "
- "to be processed by CMake. Any directories after the PREORDER flag "
- "are traversed first by makefile builds, the PREORDER flag has no "
- "effect on IDE projects. "
- " Any directories after the EXCLUDE_FROM_ALL marker "
- "will not be included in the top level makefile or project file. "
- "This is useful for having CMake create makefiles or projects for "
- "a set of examples in a project. You would want CMake to "
- "generate makefiles or project files for all the examples at "
- "the same time, but you would not want them to show up in the "
- "top level project or be built each time make is run from the top.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmSubdirCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx
index 2af7bf1c9..0bb2c0ac4 100644
--- a/Source/cmSubdirDependsCommand.cxx
+++ b/Source/cmSubdirDependsCommand.cxx
@@ -1,20 +1,11 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSubdirDependsCommand.h"
-// cmSubdirDependsCommand
-bool cmSubdirDependsCommand::InitialPass(std::vector<std::string> const& ,
- cmExecutionStatus &)
+class cmExecutionStatus;
+
+bool cmSubdirDependsCommand::InitialPass(std::vector<std::string> const&,
+ cmExecutionStatus&)
{
return true;
}
-
diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h
index b274d0196..d8ea9284f 100644
--- a/Source/cmSubdirDependsCommand.h
+++ b/Source/cmSubdirDependsCommand.h
@@ -1,77 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSubdirDependsCommand_h
#define cmSubdirDependsCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-/** \class cmSubdirDependsCommand
- * \brief Legacy command. Do not use.
- *
- * cmSubdirDependsCommand has been left in CMake for compatability with
- * projects already using it. Its functionality in supporting parallel
- * builds is now automatic. The command does not do anything.
- */
+class cmExecutionStatus;
+
class cmSubdirDependsCommand : public cmCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmSubdirDependsCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "subdir_depends";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Does nothing.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " subdir_depends(subdir dep1 dep2 ...)\n"
- "Does not do anything. This command used to help projects order "
- "parallel builds correctly. This functionality is now automatic.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmSubdirDependsCommand, cmCommand);
+ cmCommand* Clone() CM_OVERRIDE { return new cmSubdirDependsCommand; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 9ec49382a..f7192e0b6 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1,65 +1,79 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-# define _WIN32_WINNT 0x0400 /* for wincrypt.h */
-#endif
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSystemTools.h"
-#include <ctype.h>
-#include <errno.h>
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#ifdef __QNX__
-# include <malloc.h> /* for malloc/free on QNX */
+
+#include "cmAlgorithms.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 <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/Directory.hxx>
-#include <cmsys/System.h>
+#endif
+
#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include "cmArchiveWrite.h"
-# include <cm_libarchive.h>
-# include <cmsys/Terminal.h>
+#include "cmCryptoHash.h"
#endif
-#include <cmsys/stl/algorithm>
+
+#if defined(CMAKE_USE_ELF_PARSER)
+#include "cmELF.h"
+#endif
+
+#if defined(CMAKE_USE_MACH_PARSER)
+#include "cmMachO.h"
+#endif
+
+#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 <wincrypt.h>
+#include <windows.h>
+// include wincrypt.h after windows.h
+#include <wincrypt.h>
#else
-# include <sys/time.h>
-# include <sys/types.h>
-# include <unistd.h>
-# include <utime.h>
-# include <sys/wait.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <utime.h>
#endif
-#include <sys/stat.h>
-
-#if defined(_WIN32) && \
- (defined(_MSC_VER) || defined(__WATCOMC__) || \
- defined(__BORLANDC__) || defined(__MINGW32__))
-# include <io.h>
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
+#include <io.h>
#endif
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <fcntl.h>
-# include "cmCryptoHash.h"
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
#endif
-#if defined(CMAKE_USE_ELF_PARSER)
-# include "cmELF.h"
+#ifdef __QNX__
+#include <malloc.h> /* for malloc/free on QNX */
#endif
+static bool cm_isspace(char c)
+{
+ return ((c & 0x80) == 0) && isspace(c);
+}
+
class cmSystemToolsFileTime
{
public:
@@ -72,39 +86,61 @@ public:
#endif
};
-#if defined(__sgi) && !defined(__GNUC__)
-# pragma set woff 1375 /* base class destructor not virtual */
-#endif
-
#if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
// For GetEnvironmentVariables
-# if defined(_WIN32)
-extern __declspec( dllimport ) char** environ;
-# else
+#if defined(_WIN32)
+extern __declspec(dllimport) char** environ;
+#else
extern char** environ;
-# endif
+#endif
+#endif
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+static std::string cm_archive_entry_pathname(struct archive_entry* entry)
+{
+#if cmsys_STL_HAS_WSTRING
+ return cmsys::Encoding::ToNarrow(archive_entry_pathname_w(entry));
+#else
+ return archive_entry_pathname(entry);
+#endif
+}
+
+static int cm_archive_read_open_file(struct archive* a, const char* file,
+ int block_size)
+{
+#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
+ return archive_read_open_filename(a, file, block_size);
+#endif
+}
#endif
#ifdef _WIN32
class cmSystemToolsWindowsHandle
{
public:
- cmSystemToolsWindowsHandle(HANDLE h): handle_(h) {}
+ cmSystemToolsWindowsHandle(HANDLE h)
+ : handle_(h)
+ {
+ }
~cmSystemToolsWindowsHandle()
- {
- if(this->handle_ != INVALID_HANDLE_VALUE)
- {
+ {
+ 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; }
+ 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>
+
#define environ (*_NSGetEnviron())
#endif
@@ -115,26 +151,14 @@ bool cmSystemTools::s_FatalErrorOccured = false;
bool cmSystemTools::s_DisableMessages = false;
bool cmSystemTools::s_ForceUnixPaths = false;
-std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
-void cmSystemTools::SetWindows9xComspecSubstitute(const char* str)
-{
- if ( str )
- {
- cmSystemTools::s_Windows9xComspecSubstitute = str;
- }
-}
-const char* cmSystemTools::GetWindows9xComspecSubstitute()
-{
- return cmSystemTools::s_Windows9xComspecSubstitute.c_str();
-}
-
-void (*cmSystemTools::s_ErrorCallback)(const char*, const char*,
- bool&, void*);
-void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
-void* cmSystemTools::s_ErrorCallbackClientData = 0;
-void* cmSystemTools::s_StdoutCallbackClientData = 0;
-bool (*cmSystemTools::s_InterruptCallback)(void*);
-void* cmSystemTools::s_InterruptCallbackClientData = 0;
+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.
@@ -150,92 +174,90 @@ void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
// check for black line or comment
- while (regEntry.find(source))
- {
+ while (regEntry.find(source)) {
// the arguments are the second match
std::string key = regEntry.match(1);
std::string val;
- if (ReadRegistryValue(key.c_str(), val, view))
- {
+ if (ReadRegistryValue(key.c_str(), val, view)) {
std::string reg = "[";
reg += key + "]";
cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
- }
- else
- {
+ } else {
std::string reg = "[";
reg += key + "]";
cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
- }
}
+ }
}
#else
-void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64)
+void cmSystemTools::ExpandRegistryValues(std::string& source,
+ KeyWOW64 /*unused*/)
{
cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
- while (regEntry.find(source))
- {
+ while (regEntry.find(source)) {
// the arguments are the second match
std::string key = regEntry.match(1);
- std::string val;
std::string reg = "[";
reg += key + "]";
cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
- }
-
+ }
}
#endif
-std::string cmSystemTools::EscapeQuotes(const char* str)
+std::string cmSystemTools::EscapeQuotes(const std::string& str)
{
- std::string result = "";
- for(const char* ch = str; *ch != '\0'; ++ch)
- {
- if(*ch == '"')
- {
+ std::string result;
+ result.reserve(str.size());
+ for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
+ if (*ch == '"') {
result += '\\';
- }
- result += *ch;
}
+ result += *ch;
+ }
return result;
}
+std::string cmSystemTools::HelpFileName(std::string name)
+{
+ 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() && *start <= ' ')
+ while (start != s.end() && cm_isspace(*start)) {
++start;
- if (start == s.end())
+ }
+ if (start == s.end()) {
return "";
-
- std::string::const_iterator stop = s.end()-1;
- while(*stop <= ' ')
+ }
+ std::string::const_iterator stop = s.end() - 1;
+ while (cm_isspace(*stop)) {
--stop;
- return std::string(start, stop+1);
+ }
+ 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 char* m1, const char* m2, const char* m3,
+ const char* m4)
{
std::string message = "CMake Error: ";
- if(m1)
- {
+ if (m1) {
message += m1;
- }
- if(m2)
- {
+ }
+ if (m2) {
message += m2;
- }
- if(m3)
- {
+ }
+ if (m3) {
message += m3;
- }
- if(m4)
- {
+ }
+ if (m4) {
message += m4;
- }
+ }
cmSystemTools::s_ErrorOccured = true;
- cmSystemTools::Message(message.c_str(),"Error");
+ cmSystemTools::Message(message.c_str(), "Error");
}
void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
@@ -246,78 +268,73 @@ void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
bool cmSystemTools::GetInterruptFlag()
{
- if(s_InterruptCallback)
- {
+ if (s_InterruptCallback) {
return (*s_InterruptCallback)(s_InterruptCallbackClientData);
- }
+ }
return false;
}
-void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData)
+void cmSystemTools::SetMessageCallback(MessageCallback f, void* clientData)
{
- s_ErrorCallback = f;
- s_ErrorCallbackClientData = clientData;
+ s_MessageCallback = f;
+ s_MessageCallbackClientData = clientData;
}
-void cmSystemTools::SetStdoutCallback(StdoutCallback f, void* clientData)
+void cmSystemTools::SetStdoutCallback(OutputCallback f, void* clientData)
{
s_StdoutCallback = f;
s_StdoutCallbackClientData = clientData;
}
+void cmSystemTools::SetStderrCallback(OutputCallback f, void* clientData)
+{
+ s_StderrCallback = f;
+ s_StderrCallbackClientData = clientData;
+}
+
void cmSystemTools::Stdout(const char* s)
{
- if(s_StdoutCallback)
- {
- (*s_StdoutCallback)(s, static_cast<int>(strlen(s)),
- s_StdoutCallbackClientData);
- }
- else
- {
- std::cout << s;
- std::cout.flush();
- }
+ cmSystemTools::Stdout(s, strlen(s));
}
-void cmSystemTools::Stderr(const char* s, int length)
+void cmSystemTools::Stderr(const char* s)
{
+ cmSystemTools::Stderr(s, strlen(s));
+}
+
+void cmSystemTools::Stderr(const char* s, size_t length)
+{
+ if (s_StderrCallback) {
+ (*s_StderrCallback)(s, length, s_StderrCallbackClientData);
+ } else {
std::cerr.write(s, length);
std::cerr.flush();
+ }
}
-void cmSystemTools::Stdout(const char* s, int length)
+void cmSystemTools::Stdout(const char* s, size_t length)
{
- if(s_StdoutCallback)
- {
+ if (s_StdoutCallback) {
(*s_StdoutCallback)(s, length, s_StdoutCallbackClientData);
- }
- else
- {
+ } else {
std::cout.write(s, length);
std::cout.flush();
- }
+ }
}
-void cmSystemTools::Message(const char* m1, const char *title)
+void cmSystemTools::Message(const char* m1, const char* title)
{
- if(s_DisableMessages)
- {
+ if (s_DisableMessages) {
return;
- }
- if(s_ErrorCallback)
- {
- (*s_ErrorCallback)(m1, title, s_DisableMessages,
- s_ErrorCallbackClientData);
+ }
+ if (s_MessageCallback) {
+ (*s_MessageCallback)(m1, title, s_DisableMessages,
+ s_MessageCallbackClientData);
return;
- }
- else
- {
- std::cerr << m1 << std::endl << std::flush;
- }
-
+ }
+ std::cerr << m1 << std::endl << std::flush;
}
-
void cmSystemTools::ReportLastSystemError(const char* msg)
{
std::string m = msg;
@@ -328,71 +345,81 @@ void cmSystemTools::ReportLastSystemError(const char* msg)
bool cmSystemTools::IsInternallyOn(const char* val)
{
- if (!val)
- {
+ if (!val) {
return false;
- }
- std::basic_string<char> v = val;
+ }
+ std::string v = val;
+ if (v.size() > 4) {
+ return false;
+ }
- for(std::basic_string<char>::iterator c = v.begin();
- c != v.end(); c++)
- {
+ for (std::string::iterator c = v.begin(); c != v.end(); c++) {
*c = static_cast<char>(toupper(*c));
- }
- return (v == "I_ON" || v == "i_on");
+ }
+ return v == "I_ON";
}
bool cmSystemTools::IsOn(const char* val)
{
- if (!val)
- {
+ if (!val) {
return false;
- }
- std::basic_string<char> v = val;
-
- for(std::basic_string<char>::iterator c = v.begin();
- c != v.end(); c++)
- {
+ }
+ 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 (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
+ }
+ return (onValues.count(v) > 0);
}
bool cmSystemTools::IsNOTFOUND(const char* val)
{
- size_t len = strlen(val);
- const char* notfound = "-NOTFOUND";
- const size_t lenNotFound = 9;
- if(len < lenNotFound-1)
- {
- return false;
- }
- if(len == lenNotFound-1)
- {
- return ( strcmp(val, "NOTFOUND") == 0);
- }
- return ((strncmp((val + (len - lenNotFound)), notfound, lenNotFound) == 0));
+ if (strcmp(val, "NOTFOUND") == 0) {
+ return true;
+ }
+ return cmHasLiteralSuffix(val, "-NOTFOUND");
}
-
bool cmSystemTools::IsOff(const char* val)
{
- if (!val || strlen(val) == 0)
- {
+ if (!val || !*val) {
return true;
- }
- std::basic_string<char> v = val;
+ }
+ size_t len = strlen(val);
+ // Try and avoid toupper() for large strings.
+ if (len > 6) {
+ return cmSystemTools::IsNOTFOUND(val);
+ }
- for(std::basic_string<char>::iterator c = v.begin();
- c != v.end(); c++)
- {
+ 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 (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
- v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE");
+ }
+ return (offValues.count(v) > 0);
}
-//----------------------------------------------------------------------------
void cmSystemTools::ParseWindowsCommandLine(const char* command,
std::vector<std::string>& args)
{
@@ -404,95 +431,72 @@ void cmSystemTools::ParseWindowsCommandLine(const char* command,
bool in_quotes = false;
int backslashes = 0;
std::string arg;
- for(const char* c = command;*c; ++c)
- {
- if(*c == '\\')
- {
+ for (const char* c = command; *c; ++c) {
+ if (*c == '\\') {
++backslashes;
in_argument = true;
- }
- else if(*c == '"')
- {
- int backslash_pairs = backslashes >> 1;
+ } else if (*c == '"') {
+ int backslash_pairs = backslashes >> 1;
int backslash_escaped = backslashes & 1;
arg.append(backslash_pairs, '\\');
backslashes = 0;
- if(backslash_escaped)
- {
+ if (backslash_escaped) {
/* An odd number of backslashes precede this quote.
It is escaped. */
arg.append(1, '"');
- }
- else
- {
+ } else {
/* An even number of backslashes precede this quote.
It is not escaped. */
in_quotes = !in_quotes;
- }
- in_argument = true;
}
- else
- {
+ in_argument = true;
+ } else {
arg.append(backslashes, '\\');
backslashes = 0;
- if(isspace(*c))
- {
- if(in_quotes)
- {
+ if (cm_isspace(*c)) {
+ if (in_quotes) {
arg.append(1, *c);
- }
- else if(in_argument)
- {
+ } else if (in_argument) {
args.push_back(arg);
arg = "";
in_argument = false;
- }
}
- else
- {
+ } else {
in_argument = true;
arg.append(1, *c);
- }
}
}
+ }
arg.append(backslashes, '\\');
- if(in_argument)
- {
+ if (in_argument) {
args.push_back(arg);
- }
+ }
}
-//----------------------------------------------------------------------------
class cmSystemToolsArgV
{
char** ArgV;
+
public:
- cmSystemToolsArgV(char** argv): ArgV(argv) {}
+ cmSystemToolsArgV(char** argv)
+ : ArgV(argv)
+ {
+ }
~cmSystemToolsArgV()
- {
- for(char** arg = this->ArgV; arg && *arg; ++arg)
- {
+ {
+ for (char** arg = this->ArgV; arg && *arg; ++arg) {
free(*arg);
- }
- free(this->ArgV);
}
+ free(this->ArgV);
+ }
void Store(std::vector<std::string>& args) const
- {
- for(char** arg = this->ArgV; arg && *arg; ++arg)
- {
- args.push_back(*arg);
- }
- }
- void Store(std::vector<cmStdString>& args) const
- {
- for(char** arg = this->ArgV; arg && *arg; ++arg)
- {
+ {
+ for (char** arg = this->ArgV; arg && *arg; ++arg) {
args.push_back(*arg);
- }
}
+ }
};
-//----------------------------------------------------------------------------
void cmSystemTools::ParseUnixCommandLine(const char* command,
std::vector<std::string>& args)
{
@@ -501,673 +505,347 @@ void cmSystemTools::ParseUnixCommandLine(const char* command,
argv.Store(args);
}
-//----------------------------------------------------------------------------
-void cmSystemTools::ParseUnixCommandLine(const char* command,
- std::vector<cmStdString>& args)
-{
- // Invoke the underlying parser.
- cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
- argv.Store(args);
-}
-
-std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg,
- int shell_flags)
-{
- char local_buffer[1024];
- char* buffer = local_buffer;
- int size = cmsysSystem_Shell_GetArgumentSizeForWindows(arg, shell_flags);
- if(size > 1024)
- {
- buffer = new char[size];
- }
- cmsysSystem_Shell_GetArgumentForWindows(arg, buffer, shell_flags);
- std::string result(buffer);
- if(buffer != local_buffer)
- {
- delete [] buffer;
+std::vector<std::string> cmSystemTools::HandleResponseFile(
+ std::vector<std::string>::const_iterator argBeg,
+ 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;
+ 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());
+ } else {
+ std::string line;
+ cmSystemTools::GetLineFromStream(responseFile, line);
+ std::vector<std::string> args2;
+#ifdef _WIN32
+ cmSystemTools::ParseWindowsCommandLine(line.c_str(), args2);
+#else
+ cmSystemTools::ParseUnixCommandLine(line.c_str(), args2);
+#endif
+ arg_full.insert(arg_full.end(), args2.begin(), args2.end());
+ }
+ } else {
+ arg_full.push_back(arg);
}
- return result;
+ }
+ return arg_full;
}
-std::vector<cmStdString> cmSystemTools::ParseArguments(const char* command)
+std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
{
- std::vector<cmStdString> args;
+ 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] == '\\'))
- {
+ (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.
- for(const char* c = command; *c;)
- {
+ for (const char* c = command; *c;) {
// Skip over whitespace.
- while(*c == ' ' || *c == '\t')
- {
+ while (*c == ' ' || *c == '\t') {
++c;
- }
+ }
arg = "";
- if(*c == '"')
- {
+ if (*c == '"') {
// Parse a quoted argument.
++c;
- while(*c && *c != '"')
- {
+ while (*c && *c != '"') {
arg.append(1, *c);
++c;
- }
- if(*c)
- {
+ }
+ if (*c) {
++c;
- }
- args.push_back(arg);
}
- else if(*c == '\'')
- {
+ args.push_back(arg);
+ } else if (*c == '\'') {
// Parse a quoted argument.
++c;
- while(*c && *c != '\'')
- {
+ while (*c && *c != '\'') {
arg.append(1, *c);
++c;
- }
- if(*c)
- {
+ }
+ if (*c) {
++c;
- }
- args.push_back(arg);
}
- else if(*c)
- {
+ args.push_back(arg);
+ } else if (*c) {
// Parse an unquoted argument.
- while(*c && *c != ' ' && *c != '\t')
- {
- if(*c == '\\' && !win_path)
- {
+ while (*c && *c != ' ' && *c != '\t') {
+ if (*c == '\\' && !win_path) {
++c;
- if(*c)
- {
+ if (*c) {
arg.append(1, *c);
++c;
- }
}
- else
- {
+ } else {
arg.append(1, *c);
++c;
- }
}
- args.push_back(arg);
}
+ args.push_back(arg);
}
+ }
return args;
}
+size_t cmSystemTools::CalculateCommandLineLengthLimit()
+{
+ size_t sz =
+#ifdef _WIN32
+ // There's a maximum of 65536 bytes and thus 32768 WCHARs on Windows
+ // However, cmd.exe itself can only handle 8191 WCHARs and Ninja for
+ // example uses it to spawn processes.
+ size_t(8191);
+#elif defined(__linux)
+ // MAX_ARG_STRLEN is the maximum length of a string permissible for
+ // the execve() syscall on Linux. It's defined as (PAGE_SIZE * 32)
+ // in Linux's binfmts.h
+ static_cast<size_t>(sysconf(_SC_PAGESIZE) * 32);
+#else
+ size_t(0);
+#endif
+
+#if defined(_SC_ARG_MAX)
+ // ARG_MAX is the maximum size of the command and environment
+ // that can be passed to the exec functions on UNIX.
+ // The value in limits.h does not need to be present and may
+ // depend upon runtime memory constraints, hence sysconf()
+ // should be used to query it.
+ long szArgMax = sysconf(_SC_ARG_MAX);
+ // A return value of -1 signifies an undetermined limit, but
+ // it does not imply an infinite limit, and thus is ignored.
+ if (szArgMax != -1) {
+ // 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)
+ sz = std::min(sz, static_cast<size_t>(szArgMax));
+#else
+ sz = static_cast<size_t>(szArgMax);
+#endif
+ }
+#endif
+ return sz;
+}
-bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
- std::string* output ,
- int* retVal , const char* dir ,
- OutputOption outputflag ,
- double timeout )
+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)
{
std::vector<const char*> argv;
- for(std::vector<cmStdString>::const_iterator a = command.begin();
- a != command.end(); ++a)
- {
+ for (std::vector<std::string>::const_iterator a = command.begin();
+ a != command.end(); ++a) {
argv.push_back(a->c_str());
- }
- argv.push_back(0);
- if ( output )
- {
- *output = "";
- }
+ }
+ argv.push_back(CM_NULLPTR);
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, &*argv.begin());
cmsysProcess_SetWorkingDirectory(cp, dir);
- if(cmSystemTools::GetRunCommandHideConsole())
- {
+ if (cmSystemTools::GetRunCommandHideConsole()) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- }
+ }
- if (outputflag == OUTPUT_PASSTHROUGH)
- {
+ if (outputflag == OUTPUT_PASSTHROUGH) {
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
- }
+ captureStdOut = CM_NULLPTR;
+ captureStdErr = CM_NULLPTR;
+ } else if (outputflag == OUTPUT_MERGE ||
+ (captureStdErr && captureStdErr == captureStdOut)) {
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
+ captureStdErr = CM_NULLPTR;
+ }
+ assert(!captureStdErr || captureStdErr != captureStdOut);
cmsysProcess_SetTimeout(cp, timeout);
cmsysProcess_Execute(cp);
- std::vector<char> tempOutput;
+ std::vector<char> tempStdOut;
+ std::vector<char> tempStdErr;
char* data;
int length;
int pipe;
- if(outputflag != OUTPUT_PASSTHROUGH && (output || outputflag != OUTPUT_NONE))
- {
- while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0)
- {
- if(output || outputflag != OUTPUT_NONE)
- {
- // Translate NULL characters in the output into valid text.
- // Visual Studio 7 puts these characters in the output of its
- // build process.
- for(int i=0; i < length; ++i)
- {
- if(data[i] == '\0')
- {
- data[i] = ' ';
- }
- }
+ cmProcessOutput processOutput(encoding);
+ std::string strdata;
+ if (outputflag != OUTPUT_PASSTHROUGH &&
+ (captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) {
+ while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) >
+ 0) {
+ // Translate NULL characters in the output into valid text.
+ for (int i = 0; i < length; ++i) {
+ if (data[i] == '\0') {
+ data[i] = ' ';
}
- if ( output )
- {
- tempOutput.insert(tempOutput.end(), data, data+length);
+ }
+
+ if (pipe == cmsysProcess_Pipe_STDOUT) {
+ if (outputflag != OUTPUT_NONE) {
+ processOutput.DecodeText(data, length, strdata, 1);
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
}
- if(outputflag != OUTPUT_NONE)
- {
- if(outputflag == OUTPUT_MERGE)
- {
- cmSystemTools::Stdout(data, length);
- }
- else
- {
- if(pipe == cmsysProcess_Pipe_STDERR)
- {
- cmSystemTools::Stderr(data, length);
- }
- else if(pipe == cmsysProcess_Pipe_STDOUT)
- {
- cmSystemTools::Stdout(data, length);
- }
- }
+ if (captureStdOut) {
+ tempStdOut.insert(tempStdOut.end(), 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());
+ }
+ if (captureStdErr) {
+ tempStdErr.insert(tempStdErr.end(), data, data + length);
}
}
}
- cmsysProcess_WaitForExit(cp, 0);
- if ( output && tempOutput.begin() != tempOutput.end())
- {
- output->append(&*tempOutput.begin(), tempOutput.size());
+ if (outputflag != OUTPUT_NONE) {
+ processOutput.DecodeText(std::string(), strdata, 1);
+ if (!strdata.empty()) {
+ cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ }
+ processOutput.DecodeText(std::string(), strdata, 2);
+ if (!strdata.empty()) {
+ cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ }
}
+ }
+
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+
+ if (captureStdOut) {
+ captureStdOut->assign(tempStdOut.begin(), tempStdOut.end());
+ processOutput.DecodeText(*captureStdOut, *captureStdOut);
+ }
+ if (captureStdErr) {
+ captureStdErr->assign(tempStdErr.begin(), tempStdErr.end());
+ processOutput.DecodeText(*captureStdErr, *captureStdErr);
+ }
bool result = true;
- if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
- {
- if ( retVal )
- {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
+ if (retVal) {
*retVal = cmsysProcess_GetExitValue(cp);
- }
- else
- {
- if ( cmsysProcess_GetExitValue(cp) != 0 )
- {
+ } else {
+ if (cmsysProcess_GetExitValue(cp) != 0) {
result = false;
- }
}
}
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
- {
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) {
const char* exception_str = cmsysProcess_GetExceptionString(cp);
- if ( outputflag != OUTPUT_NONE )
- {
+ if (outputflag != OUTPUT_NONE) {
std::cerr << exception_str << std::endl;
- }
- if ( output )
- {
- output->append(exception_str, strlen(exception_str));
- }
- result = false;
}
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
- {
+ if (captureStdErr) {
+ captureStdErr->append(exception_str, strlen(exception_str));
+ }
+ result = false;
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
const char* error_str = cmsysProcess_GetErrorString(cp);
- if ( outputflag != OUTPUT_NONE )
- {
+ if (outputflag != OUTPUT_NONE) {
std::cerr << error_str << std::endl;
- }
- if ( output )
- {
- output->append(error_str, strlen(error_str));
- }
- result = false;
}
- else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
- {
+ if (captureStdErr) {
+ captureStdErr->append(error_str, strlen(error_str));
+ }
+ result = false;
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
const char* error_str = "Process terminated due to timeout\n";
- if ( outputflag != OUTPUT_NONE )
- {
+ if (outputflag != OUTPUT_NONE) {
std::cerr << error_str << std::endl;
- }
- if ( output )
- {
- output->append(error_str, strlen(error_str));
- }
- result = false;
}
+ if (captureStdErr) {
+ captureStdErr->append(error_str, strlen(error_str));
+ }
+ result = false;
+ }
cmsysProcess_Delete(cp);
return result;
}
-bool cmSystemTools::RunSingleCommand(
- const char* command,
- std::string* output,
- int *retVal,
- const char* dir,
- OutputOption outputflag,
- double timeout)
+bool cmSystemTools::RunSingleCommand(const char* command,
+ std::string* captureStdOut,
+ std::string* captureStdErr, int* retVal,
+ const char* dir, OutputOption outputflag,
+ double timeout)
{
- if(s_DisableRunCommandOutput)
- {
+ if (s_DisableRunCommandOutput) {
outputflag = OUTPUT_NONE;
- }
+ }
- std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
+ std::vector<std::string> args = cmSystemTools::ParseArguments(command);
- if(args.size() < 1)
- {
- return false;
- }
- return cmSystemTools::RunSingleCommand(args, output,retVal,
- dir, outputflag, timeout);
-}
-bool cmSystemTools::RunCommand(const char* command,
- std::string& output,
- const char* dir,
- bool verbose,
- int timeout)
-{
- int dummy;
- return cmSystemTools::RunCommand(command, output, dummy,
- dir, verbose, timeout);
-}
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-#include "cmWin32ProcessExecution.h"
-// use this for shell commands like echo and dir
-bool RunCommandViaWin32(const char* command,
- const char* dir,
- std::string& output,
- int& retVal,
- bool verbose,
- int timeout)
-{
-#if defined(__BORLANDC__)
- return
- cmWin32ProcessExecution::
- BorlandRunCommand(command, dir, output,
- retVal,
- verbose, timeout,
- cmSystemTools::GetRunCommandHideConsole());
-#else // Visual studio
- ::SetLastError(ERROR_SUCCESS);
- if ( ! command )
- {
- cmSystemTools::Error("No command specified");
+ if (args.empty()) {
return false;
- }
- cmWin32ProcessExecution resProc;
- if(cmSystemTools::GetRunCommandHideConsole())
- {
- resProc.SetHideWindows(true);
- }
-
- if ( cmSystemTools::GetWindows9xComspecSubstitute() )
- {
- resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
- }
- if ( !resProc.StartProcess(command, dir, verbose) )
- {
- output = resProc.GetOutput();
- if(verbose)
- {
- cmSystemTools::Stdout(output.c_str());
- }
- return false;
- }
- resProc.Wait(timeout);
- output = resProc.GetOutput();
- retVal = resProc.GetExitValue();
- return true;
-#endif
-}
-
-// use this for shell commands like echo and dir
-bool RunCommandViaSystem(const char* command,
- const char* dir,
- std::string& output,
- int& retVal,
- bool verbose)
-{
- std::cout << "@@ " << command << std::endl;
-
- std::string commandInDir;
- if(dir)
- {
- commandInDir = "cd ";
- commandInDir += cmSystemTools::ConvertToOutputPath(dir);
- commandInDir += " && ";
- commandInDir += command;
- }
- else
- {
- commandInDir = command;
- }
- command = commandInDir.c_str();
- std::string commandToFile = command;
- commandToFile += " > ";
- std::string tempFile;
- tempFile += _tempnam(0, "cmake");
-
- commandToFile += tempFile;
- retVal = system(commandToFile.c_str());
- std::ifstream fin(tempFile.c_str());
- if(!fin)
- {
- if(verbose)
- {
- std::string errormsg = "RunCommand produced no output: command: \"";
- errormsg += command;
- errormsg += "\"";
- errormsg += "\nOutput file: ";
- errormsg += tempFile;
- cmSystemTools::Error(errormsg.c_str());
- }
- fin.close();
- cmSystemTools::RemoveFile(tempFile.c_str());
- return false;
- }
- bool multiLine = false;
- std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- output += line;
- if(multiLine)
- {
- output += "\n";
- }
- multiLine = true;
- }
- fin.close();
- cmSystemTools::RemoveFile(tempFile.c_str());
- return true;
+ }
+ return cmSystemTools::RunSingleCommand(args, captureStdOut, captureStdErr,
+ retVal, dir, outputflag, timeout);
}
-#else // We have popen
-
-// BeOS seems to return from a successful pclose() before the process has
-// legitimately exited, or at least before SIGCHLD is thrown...the signal may
-// come quite some time after pclose returns! This causes havoc with later
-// parts of CMake that expect to catch the signal from other child processes,
-// so we explicitly wait to catch it here. This should be safe to do with
-// popen() so long as we don't actually collect the zombie process ourselves.
-#ifdef __BEOS__
-#include <signal.h>
-#undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below.
-static volatile bool beos_seen_signal = false;
-static void beos_popen_workaround(int sig)
+std::string cmSystemTools::PrintSingleCommand(
+ std::vector<std::string> const& command)
{
- beos_seen_signal = true;
-}
-#endif
-
-bool RunCommandViaPopen(const char* command,
- const char* dir,
- std::string& output,
- int& retVal,
- bool verbose,
- int /*timeout*/)
-{
- // if only popen worked on windows.....
- std::string commandInDir;
- if(dir)
- {
- commandInDir = "cd \"";
- commandInDir += dir;
- commandInDir += "\" && ";
- commandInDir += command;
- }
- else
- {
- commandInDir = command;
- }
-#ifndef __VMS
- commandInDir += " 2>&1";
-#endif
- command = commandInDir.c_str();
- const int BUFFER_SIZE = 4096;
- char buffer[BUFFER_SIZE];
- if(verbose)
- {
- cmSystemTools::Stdout("running ");
- cmSystemTools::Stdout(command);
- cmSystemTools::Stdout("\n");
- }
- fflush(stdout);
- fflush(stderr);
-
-#ifdef __BEOS__
- beos_seen_signal = false;
- signal(SIGCHLD, beos_popen_workaround);
-#endif
-
- FILE* cpipe = popen(command, "r");
- if(!cpipe)
- {
-#ifdef __BEOS__
- signal(SIGCHLD, SIG_DFL);
-#endif
- return false;
- }
- if (!fgets(buffer, BUFFER_SIZE, cpipe))
- {
- buffer[0] = 0;
- }
- while(!feof(cpipe))
- {
- if(verbose)
- {
- cmSystemTools::Stdout(buffer);
- }
- output += buffer;
- if(!fgets(buffer, BUFFER_SIZE, cpipe))
- {
- buffer[0] = 0;
- }
- }
-
- retVal = pclose(cpipe);
-
-#ifdef __BEOS__
- for (int i = 0; (!beos_seen_signal) && (i < 3); i++)
- {
- ::sleep(1); // signals should interrupt this...
- }
-
- if (!beos_seen_signal)
- {
- signal(SIGCHLD, SIG_DFL); // oh well, didn't happen. Go on anyhow.
- }
-#endif
-
- if (WIFEXITED(retVal))
- {
- retVal = WEXITSTATUS(retVal);
- return true;
- }
- if (WIFSIGNALED(retVal))
- {
- retVal = WTERMSIG(retVal);
- cmOStringStream error;
- error << "\nProcess terminated due to ";
- switch (retVal)
- {
-#ifdef SIGKILL
- case SIGKILL:
- error << "SIGKILL";
- break;
-#endif
-#ifdef SIGFPE
- case SIGFPE:
- error << "SIGFPE";
- break;
-#endif
-#ifndef __HAIKU__
-#ifdef SIGBUS
- case SIGBUS:
- error << "SIGBUS";
- break;
-#endif
-#endif
-#ifdef SIGSEGV
- case SIGSEGV:
- error << "SIGSEGV";
- break;
-#endif
- default:
- error << "signal " << retVal;
- break;
- }
- output += error.str();
- }
- return false;
-}
+ if (command.empty()) {
+ return std::string();
+ }
-#endif // endif WIN32 not CYGWIN
-
-
-// run a command unix uses popen (easy)
-// windows uses system and ShortPath
-bool cmSystemTools::RunCommand(const char* command,
- std::string& output,
- int &retVal,
- const char* dir,
- bool verbose,
- int timeout)
-{
- if(s_DisableRunCommandOutput)
- {
- verbose = false;
- }
-
-#if defined(WIN32) && !defined(__CYGWIN__)
- // if the command does not start with a quote, then
- // 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;
- if(command[0] == '\"')
- {
- // count the number of quotes
- for(const char* s = command; *s != 0; ++s)
- {
- if(*s == '\"')
- {
- count++;
- if(count > 2)
- {
- break;
- }
- }
- }
- // if there are more than two double quotes use
- // GetShortPathName, the cmd.exe program in windows which
- // is used by system fails to execute if there are more than
- // one set of quotes in the arguments
- 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()) )
- {
- shortCmd = cmd;
- }
- else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd))
- {
- cmSystemTools::Error("GetShortPath failed for " , cmd.c_str());
- return false;
- }
- shortCmd += " ";
- shortCmd += args;
-
- //return RunCommandViaSystem(shortCmd.c_str(), dir,
- // output, retVal, verbose);
- //return WindowsRunCommand(shortCmd.c_str(), dir,
- //output, retVal, verbose);
- return RunCommandViaWin32(shortCmd.c_str(), dir,
- output, retVal, verbose, timeout);
- }
- else
- {
- cmSystemTools::Error("Could not parse command line with quotes ",
- command);
- }
- }
- }
- // if there is only one set of quotes or no quotes then just run the command
- //return RunCommandViaSystem(command, dir, output, retVal, verbose);
- //return WindowsRunCommand(command, dir, output, retVal, verbose);
- return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout);
-#else
- return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout);
-#endif
+ return cmWrap('"', command, '"', " ");
}
bool cmSystemTools::DoesFileExistWithExtensions(
- const char* name,
- const std::vector<std::string>& headerExts)
+ const char* name, const std::vector<std::string>& headerExts)
{
std::string hname;
- for( std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext )
- {
+ 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()))
- {
+ if (cmSystemTools::FileExists(hname.c_str())) {
return true;
- }
}
+ }
return false;
}
std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
- const char* directory, const char* toplevel)
+ const char* directory,
+ const char* toplevel)
{
std::string file = fname;
cmSystemTools::ConvertToUnixSlashes(file);
std::string dir = directory;
cmSystemTools::ConvertToUnixSlashes(dir);
std::string prevDir;
- while(dir != prevDir)
- {
+ while (dir != prevDir) {
std::string path = dir + "/" + file;
- if ( cmSystemTools::FileExists(path.c_str()) )
- {
+ if (cmSystemTools::FileExists(path.c_str())) {
return path;
- }
- if ( dir.size() < strlen(toplevel) )
- {
+ }
+ if (dir.size() < strlen(toplevel)) {
break;
- }
- prevDir = dir;
- dir = cmSystemTools::GetParentDirectory(dir.c_str());
}
+ prevDir = dir;
+ dir = cmSystemTools::GetParentDirectory(dir);
+ }
return "";
}
@@ -1177,143 +855,242 @@ bool cmSystemTools::cmCopyFile(const char* source, const char* destination)
}
bool cmSystemTools::CopyFileIfDifferent(const char* source,
- const char* destination)
+ const char* destination)
{
return Superclass::CopyFileIfDifferent(source, destination);
}
-//----------------------------------------------------------------------------
+#ifdef _WIN32
+cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry()
+{
+ static WindowsFileRetry retry = { 0, 0 };
+ if (!retry.Count) {
+ unsigned int data[2] = { 0, 0 };
+ HKEY const keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
+ wchar_t const* const values[2] = { L"FilesystemRetryCount",
+ L"FilesystemRetryDelay" };
+ for (int k = 0; k < 2; ++k) {
+ HKEY hKey;
+ if (RegOpenKeyExW(keys[k], L"Software\\Kitware\\CMake\\Config", 0,
+ KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
+ for (int v = 0; v < 2; ++v) {
+ DWORD dwData, dwType, dwSize = 4;
+ if (!data[v] &&
+ RegQueryValueExW(hKey, values[v], 0, &dwType, (BYTE*)&dwData,
+ &dwSize) == ERROR_SUCCESS &&
+ dwType == REG_DWORD && dwSize == 4) {
+ data[v] = static_cast<unsigned int>(dwData);
+ }
+ }
+ RegCloseKey(hKey);
+ }
+ }
+ retry.Count = data[0] ? data[0] : 5;
+ retry.Delay = data[1] ? data[1] : 500;
+ }
+ return retry;
+}
+#endif
+
bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
{
#ifdef _WIN32
-# ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-# endif
+#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
creating/opening the destination file just before our MoveFileEx. */
- int tries = 5;
- while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
- {
- // Try again only if failure was due to access permissions.
- if(GetLastError() != ERROR_ACCESS_DENIED)
- {
+ WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry();
+ while (
+ !MoveFileExW(SystemTools::ConvertToWindowsExtendedPath(oldname).c_str(),
+ SystemTools::ConvertToWindowsExtendedPath(newname).c_str(),
+ MOVEFILE_REPLACE_EXISTING) &&
+ --retry.Count) {
+ DWORD last_error = GetLastError();
+ // Try again only if failure was due to access/sharing permissions.
+ if (last_error != ERROR_ACCESS_DENIED &&
+ last_error != ERROR_SHARING_VIOLATION) {
return false;
- }
- DWORD attrs = GetFileAttributes(newname);
- if((attrs != INVALID_FILE_ATTRIBUTES) &&
- (attrs & FILE_ATTRIBUTE_READONLY))
- {
+ }
+ DWORD attrs = GetFileAttributesW(
+ SystemTools::ConvertToWindowsExtendedPath(newname).c_str());
+ if ((attrs != INVALID_FILE_ATTRIBUTES) &&
+ (attrs & FILE_ATTRIBUTE_READONLY)) {
// Remove the read-only attribute from the destination file.
- SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
- }
- else
- {
+ SetFileAttributesW(
+ SystemTools::ConvertToWindowsExtendedPath(newname).c_str(),
+ attrs & ~FILE_ATTRIBUTE_READONLY);
+ } else {
// The file may be temporarily in use so wait a bit.
- cmSystemTools::Delay(100);
- }
+ cmSystemTools::Delay(retry.Delay);
}
- return tries > 0;
+ }
+ return retry.Count > 0;
#else
/* On UNIX we have an OS-provided call to do this atomically. */
return rename(oldname, newname) == 0;
#endif
}
-bool cmSystemTools::ComputeFileMD5(const char* source, char* md5out)
+bool cmSystemTools::ComputeFileMD5(const std::string& source, char* md5out)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
- cmCryptoHashMD5 md5;
- std::string str = md5.HashFile(source);
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
+ std::string const str = md5.HashFile(source);
strncpy(md5out, str.c_str(), 32);
return !str.empty();
#else
(void)source;
(void)md5out;
- cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
+ cmSystemTools::Message("md5sum not supported in bootstrapping mode",
+ "Error");
return false;
#endif
}
-std::string cmSystemTools::ComputeStringMD5(const char* input)
+std::string cmSystemTools::ComputeStringMD5(const std::string& input)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
- cmCryptoHashMD5 md5;
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
return md5.HashString(input);
#else
(void)input;
- cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
+ cmSystemTools::Message("md5sum not supported in bootstrapping mode",
+ "Error");
return "";
#endif
}
-void cmSystemTools::Glob(const char *directory, const char *regexp,
+std::string cmSystemTools::ComputeCertificateThumbprint(
+ const std::string& source)
+{
+ std::string thumbprint;
+
+#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32)
+ BYTE* certData = NULL;
+ CRYPT_INTEGER_BLOB cryptBlob;
+ HCERTSTORE certStore = NULL;
+ PCCERT_CONTEXT certContext = NULL;
+
+ HANDLE certFile = CreateFileW(
+ cmsys::Encoding::ToWide(source.c_str()).c_str(), GENERIC_READ,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (certFile != INVALID_HANDLE_VALUE && certFile != NULL) {
+ DWORD fileSize = GetFileSize(certFile, NULL);
+ if (fileSize != INVALID_FILE_SIZE) {
+ certData = new BYTE[fileSize];
+ if (certData != NULL) {
+ DWORD dwRead = 0;
+ if (ReadFile(certFile, certData, fileSize, &dwRead, NULL)) {
+ cryptBlob.cbData = fileSize;
+ cryptBlob.pbData = certData;
+
+ // Verify that this is a valid cert
+ if (PFXIsPFXBlob(&cryptBlob)) {
+ // Open the certificate as a store
+ certStore = PFXImportCertStore(&cryptBlob, NULL, CRYPT_EXPORTABLE);
+ if (certStore != NULL) {
+ // There should only be 1 cert.
+ certContext =
+ CertEnumCertificatesInStore(certStore, certContext);
+ if (certContext != NULL) {
+ // The hash is 20 bytes
+ BYTE hashData[20];
+ DWORD hashLength = 20;
+
+ // Buffer to print the hash. Each byte takes 2 chars +
+ // terminating character
+ char hashPrint[41];
+ char* pHashPrint = hashPrint;
+ // Get the hash property from the certificate
+ if (CertGetCertificateContextProperty(
+ certContext, CERT_HASH_PROP_ID, hashData, &hashLength)) {
+ for (DWORD i = 0; i < hashLength; i++) {
+ // Convert each byte to hexadecimal
+ sprintf(pHashPrint, "%02X", hashData[i]);
+ pHashPrint += 2;
+ }
+ *pHashPrint = '\0';
+ thumbprint = hashPrint;
+ }
+ CertFreeCertificateContext(certContext);
+ }
+ CertCloseStore(certStore, 0);
+ }
+ }
+ }
+ delete[] certData;
+ }
+ }
+ CloseHandle(certFile);
+ }
+#else
+ (void)source;
+ cmSystemTools::Message("ComputeCertificateThumbprint is not implemented",
+ "Error");
+#endif
+
+ return thumbprint;
+}
+
+void cmSystemTools::Glob(const std::string& directory,
+ const std::string& regexp,
std::vector<std::string>& files)
{
cmsys::Directory d;
- cmsys::RegularExpression reg(regexp);
+ cmsys::RegularExpression reg(regexp.c_str());
- if (d.Load(directory))
- {
+ if (d.Load(directory)) {
size_t numf;
- unsigned int i;
+ unsigned int i;
numf = d.GetNumberOfFiles();
- for (i = 0; i < numf; i++)
- {
+ for (i = 0; i < numf; i++) {
std::string fname = d.GetFile(i);
- if (reg.find(fname))
- {
+ if (reg.find(fname)) {
files.push_back(fname);
- }
}
}
+ }
}
-
-void cmSystemTools::GlobDirs(const char *fullPath,
+void cmSystemTools::GlobDirs(const std::string& path,
std::vector<std::string>& files)
{
- std::string path = fullPath;
std::string::size_type pos = path.find("/*");
- if(pos == std::string::npos)
- {
- files.push_back(fullPath);
+ if (pos == std::string::npos) {
+ files.push_back(path);
return;
- }
+ }
std::string startPath = path.substr(0, pos);
- std::string finishPath = path.substr(pos+2);
+ std::string finishPath = path.substr(pos + 2);
cmsys::Directory d;
- if (d.Load(startPath.c_str()))
- {
- for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
- {
- if((std::string(d.GetFile(i)) != ".")
- && (std::string(d.GetFile(i)) != ".."))
- {
+ if (d.Load(startPath)) {
+ 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 += "/";
fname += d.GetFile(i);
- if(cmSystemTools::FileIsDirectory(fname.c_str()))
- {
+ if (cmSystemTools::FileIsDirectory(fname)) {
fname += finishPath;
- cmSystemTools::GlobDirs(fname.c_str(), files);
- }
+ cmSystemTools::GlobDirs(fname, files);
}
}
}
+ }
}
-
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)
- {
+ for (i = arguments.begin(); i != arguments.end(); ++i) {
cmSystemTools::ExpandListArgument(*i, newargs);
- }
+ }
}
void cmSystemTools::ExpandListArgument(const std::string& arg,
@@ -1321,228 +1098,178 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
bool emptyArgs)
{
// If argument is empty, it is an empty list.
- if(arg.length() == 0 && !emptyArgs)
- {
+ if (!emptyArgs && arg.empty()) {
return;
- }
+ }
// if there are no ; in the name then just copy the current string
- if(arg.find(';') == std::string::npos)
- {
+ if (arg.find(';') == std::string::npos) {
newargs.push_back(arg);
return;
- }
- std::vector<char> newArgVec;
+ }
+ 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 = arg.c_str(); *c; ++c)
- {
- switch(*c)
- {
- case '\\':
- {
+ 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.
- ++c;
- if(*c == ';')
- {
- newArgVec.push_back(*c);
- }
- else
- {
- newArgVec.push_back('\\');
- if(*c)
- {
- newArgVec.push_back(*c);
- }
- else
- {
- // Terminate the loop properly.
- --c;
- }
- }
- } break;
- case '[':
- {
+ const char* next = c + 1;
+ if (*next == ';') {
+ newArg.append(last, c - last);
+ // Skip over the escape character
+ last = c = next;
+ }
+ } break;
+ case '[': {
++squareNesting;
- newArgVec.push_back(*c);
- } break;
- case ']':
- {
+ } break;
+ case ']': {
--squareNesting;
- newArgVec.push_back(*c);
- } break;
- case ';':
- {
+ } break;
+ case ';': {
// Break the string here if we are not nested inside square
// brackets.
- if(squareNesting == 0)
- {
- if ( newArgVec.size() || emptyArgs )
- {
+ 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.
- newArgVec.push_back(0);
- newargs.push_back(&*newArgVec.begin());
- newArgVec.clear();
- }
+ newargs.push_back(newArg);
+ newArg = "";
}
- else
- {
- newArgVec.push_back(*c);
- }
- } break;
- default:
- {
+ }
+ } break;
+ default: {
// Just append this character.
- newArgVec.push_back(*c);
- } break;
- }
+ } break;
}
- if ( newArgVec.size() || emptyArgs )
- {
+ }
+ newArg.append(last);
+ if (!newArg.empty() || emptyArgs) {
// Add the last argument if the string is not empty.
- newArgVec.push_back(0);
- newargs.push_back(&*newArgVec.begin());
- }
+ newargs.push_back(newArg);
+ }
}
-bool cmSystemTools::SimpleGlob(const cmStdString& glob,
- std::vector<cmStdString>& files,
+bool cmSystemTools::SimpleGlob(const std::string& glob,
+ std::vector<std::string>& files,
int type /* = 0 */)
{
files.clear();
- if ( glob[glob.size()-1] != '*' )
- {
+ if (glob[glob.size() - 1] != '*') {
return false;
- }
+ }
std::string path = cmSystemTools::GetFilenamePath(glob);
std::string ppath = cmSystemTools::GetFilenameName(glob);
- ppath = ppath.substr(0, ppath.size()-1);
- if ( path.size() == 0 )
- {
+ ppath = ppath.substr(0, ppath.size() - 1);
+ if (path.empty()) {
path = "/";
- }
+ }
bool res = false;
cmsys::Directory d;
- if (d.Load(path.c_str()))
- {
- for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
- {
- if((std::string(d.GetFile(i)) != ".")
- && (std::string(d.GetFile(i)) != ".."))
- {
+ if (d.Load(path)) {
+ for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
+ if ((std::string(d.GetFile(i)) != ".") &&
+ (std::string(d.GetFile(i)) != "..")) {
std::string fname = path;
- if ( path[path.size()-1] != '/' )
- {
- fname +="/";
- }
+ if (path[path.size() - 1] != '/') {
+ fname += "/";
+ }
fname += d.GetFile(i);
std::string sfname = d.GetFile(i);
- if ( type > 0 && cmSystemTools::FileIsDirectory(fname.c_str()) )
- {
+ if (type > 0 && cmSystemTools::FileIsDirectory(fname)) {
continue;
- }
- if ( type < 0 && !cmSystemTools::FileIsDirectory(fname.c_str()) )
- {
+ }
+ if (type < 0 && !cmSystemTools::FileIsDirectory(fname)) {
continue;
- }
- if ( sfname.size() >= ppath.size() &&
- sfname.substr(0, ppath.size()) ==
- ppath )
- {
+ }
+ if (sfname.size() >= ppath.size() &&
+ sfname.substr(0, ppath.size()) == ppath) {
files.push_back(fname);
res = true;
- }
}
}
}
+ }
return res;
}
cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
{
- if ( ! cext || *cext == 0 )
- {
+ if (!cext || *cext == 0) {
return cmSystemTools::NO_FILE_FORMAT;
- }
- //std::string ext = cmSystemTools::LowerCase(cext);
+ }
+ // 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; }
+ 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; }
+ 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<cmStdString>& l)
+bool cmSystemTools::Split(const char* s, std::vector<std::string>& l)
{
std::vector<std::string> temp;
bool res = Superclass::Split(s, temp);
- for(std::vector<std::string>::const_iterator i = temp.begin();
- i != temp.end(); ++i)
- {
- l.push_back(*i);
- }
+ l.insert(l.end(), temp.begin(), temp.end());
return res;
}
std::string cmSystemTools::ConvertToOutputPath(const char* path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- if(s_ForceUnixPaths)
- {
+ if (s_ForceUnixPaths) {
return cmSystemTools::ConvertToUnixOutputPath(path);
- }
+ }
return cmSystemTools::ConvertToWindowsOutputPath(path);
#else
return cmSystemTools::ConvertToUnixOutputPath(path);
@@ -1552,15 +1279,13 @@ std::string cmSystemTools::ConvertToOutputPath(const char* path)
void cmSystemTools::ConvertToOutputSlashes(std::string& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- if(!s_ForceUnixPaths)
- {
+ if (!s_ForceUnixPaths) {
// Convert to windows slashes.
std::string::size_type pos = 0;
- while((pos = path.find('/', pos)) != std::string::npos)
- {
+ while ((pos = path.find('/', pos)) != std::string::npos) {
path[pos++] = '\\';
- }
}
+ }
#else
static_cast<void>(path);
#endif
@@ -1575,67 +1300,51 @@ std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
#endif
}
-bool cmSystemTools::StringEndsWith(const char* str1, const char* str2)
-{
- if ( !str1 || !str2 || strlen(str1) < strlen(str2) )
- {
- return 0;
- }
- return !strncmp(str1 + (strlen(str1)-strlen(str2)), str2, strlen(str2));
-}
-
// compute the relative path from here to there
std::string cmSystemTools::RelativePath(const char* local, const char* remote)
{
- if(!cmSystemTools::FileIsFullPath(local))
- {
+ if (!cmSystemTools::FileIsFullPath(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);
- }
+ }
+ if (!cmSystemTools::FileIsFullPath(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)
{
- if(dir.empty() || dir == ".")
- {
+ if (dir.empty() || dir == ".") {
return file;
- }
+ }
std::vector<std::string> dirComponents;
std::vector<std::string> fileComponents;
- cmSystemTools::SplitPath(dir.c_str(), dirComponents);
- cmSystemTools::SplitPath(file.c_str(), fileComponents);
+ cmSystemTools::SplitPath(dir, dirComponents);
+ cmSystemTools::SplitPath(file, fileComponents);
- if(fileComponents.empty())
- {
+ if (fileComponents.empty()) {
return dir;
- }
- if(fileComponents[0] != "")
- {
+ }
+ if (fileComponents[0] != "") {
// File is not a relative path.
return file;
- }
+ }
- std::vector<std::string>::iterator i = fileComponents.begin()+1;
- while(i != fileComponents.end() && *i == ".." && dirComponents.size() > 1)
- {
- ++i; // Remove ".." file component.
+ 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.
- }
+ }
dirComponents.insert(dirComponents.end(), i, fileComponents.end());
return cmSystemTools::JoinPath(dirComponents);
}
#ifdef CMAKE_BUILD_WITH_CMAKE
-//----------------------------------------------------------------------
bool cmSystemTools::UnsetEnv(const char* value)
{
#if !defined(HAVE_UNSETENV)
@@ -1648,52 +1357,44 @@ bool cmSystemTools::UnsetEnv(const char* value)
#endif
}
-//----------------------------------------------------------------------
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
{
std::vector<std::string> env;
int cc;
- for ( cc = 0; environ[cc]; ++ cc )
- {
+ for (cc = 0; environ[cc]; ++cc) {
env.push_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->c_str());
- }
+ for (std::vector<std::string>::const_iterator eit = env.begin();
+ eit != env.end(); ++eit) {
+ cmSystemTools::PutEnv(*eit);
+ }
}
-//----------------------------------------------------------------------
cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
{
this->Env = cmSystemTools::GetEnvironmentVariables();
}
-//----------------------------------------------------------------------
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)
- {
+ for (std::vector<std::string>::const_iterator eit = currentEnv.begin();
+ eit != currentEnv.end(); ++eit) {
std::string var(*eit);
- std::string::size_type pos = var.find("=");
- if (pos != std::string::npos)
- {
+ std::string::size_type pos = var.find('=');
+ if (pos != std::string::npos) {
var = var.substr(0, pos);
- }
+ }
cmSystemTools::UnsetEnv(var.c_str());
- }
+ }
// Then put back each entry from the original environment:
cmSystemTools::AppendEnv(this->Env);
@@ -1712,92 +1413,95 @@ void cmSystemTools::EnableVSConsoleOutput()
// output and allow it to be captured on the fly.
cmSystemTools::PutEnv("vsconsoleoutput=1");
-# ifdef CMAKE_BUILD_WITH_CMAKE
+#ifdef CMAKE_BUILD_WITH_CMAKE
// 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)
{
- if(cmSystemTools::FileIsFullPath(path))
- {
- std::string libname = path;
- if(libname.find(".framework") == libname.size()+1-sizeof(".framework"))
- {
- return true;
- }
- }
- return false;
+ return (cmSystemTools::FileIsFullPath(path) &&
+ cmHasLiteralSuffix(path, ".framework"));
}
bool cmSystemTools::CreateTar(const char* outFileName,
- const std::vector<cmStdString>& files,
- bool gzip, bool bzip2, bool verbose)
+ const std::vector<std::string>& files,
+ cmTarCompression compressType, bool verbose,
+ std::string const& mtime,
+ std::string const& format)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- std::ofstream fout(outFileName, std::ios::out | cmsys_ios_binary);
- if(!fout)
- {
+ cmsys::ofstream fout(outFileName, 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());
return false;
- }
- cmArchiveWrite a(fout, (gzip? cmArchiveWrite::CompressGZip :
- (bzip2? cmArchiveWrite::CompressBZip2 :
- cmArchiveWrite::CompressNone)),
- cmArchiveWrite::TypeTAR);
+ }
+ cmArchiveWrite::Compress compress = cmArchiveWrite::CompressNone;
+ switch (compressType) {
+ case TarCompressGZip:
+ compress = cmArchiveWrite::CompressGZip;
+ break;
+ case TarCompressBZip2:
+ compress = cmArchiveWrite::CompressBZip2;
+ break;
+ case TarCompressXZ:
+ compress = cmArchiveWrite::CompressXZ;
+ break;
+ case TarCompressNone:
+ compress = cmArchiveWrite::CompressNone;
+ break;
+ }
+
+ cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format);
+
+ a.SetMTime(mtime);
a.SetVerbose(verbose);
- for(std::vector<cmStdString>::const_iterator i = files.begin();
- i != files.end(); ++i)
- {
+ for (std::vector<std::string>::const_iterator i = files.begin();
+ i != files.end(); ++i) {
std::string path = *i;
- if(cmSystemTools::FileIsFullPath(path.c_str()))
- {
+ if (cmSystemTools::FileIsFullPath(path.c_str())) {
// Get the relative path to the file.
path = cmSystemTools::RelativePath(cwd.c_str(), path.c_str());
- }
- if(!a.Add(path))
- {
+ }
+ if (!a.Add(path)) {
break;
- }
}
- if(!a)
- {
+ }
+ if (!a) {
cmSystemTools::Error(a.GetError().c_str());
return false;
- }
+ }
return true;
#else
(void)outFileName;
(void)files;
- (void)gzip;
(void)verbose;
return false;
#endif
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
-namespace{
-#define BSDTAR_FILESIZE_PRINTF "%lu"
-#define BSDTAR_FILESIZE_TYPE unsigned long
- void
- list_item_verbose(FILE *out, struct archive_entry *entry)
-{
- char tmp[100];
- size_t w;
- const char *p;
- const char *fmt;
- time_t tim;
- static time_t now;
+namespace {
+#define BSDTAR_FILESIZE_PRINTF "%lu"
+#define BSDTAR_FILESIZE_TYPE unsigned long
+void list_item_verbose(FILE* out, struct archive_entry* entry)
+{
+ char tmp[100];
+ size_t w;
+ const char* p;
+ const char* fmt;
+ time_t tim;
+ static time_t now;
size_t u_width = 6;
size_t gs_width = 13;
@@ -1808,57 +1512,44 @@ namespace{
* and just widen them as necessary. These numbers are completely
* arbitrary.
*/
- if (!now)
- {
+ if (!now) {
time(&now);
- }
- fprintf(out, "%s %d ",
- archive_entry_strmode(entry),
+ }
+ fprintf(out, "%s %d ", archive_entry_strmode(entry),
archive_entry_nlink(entry));
/* Use uname if it's present, else uid. */
p = archive_entry_uname(entry);
- if ((p == NULL) || (*p == '\0'))
- {
- sprintf(tmp, "%lu ",
- (unsigned long)archive_entry_uid(entry));
+ if ((p == CM_NULLPTR) || (*p == '\0')) {
+ sprintf(tmp, "%lu ", (unsigned long)archive_entry_uid(entry));
p = tmp;
- }
+ }
w = strlen(p);
- if (w > u_width)
- {
+ if (w > u_width) {
u_width = w;
- }
+ }
fprintf(out, "%-*s ", (int)u_width, p);
/* Use gname if it's present, else gid. */
p = archive_entry_gname(entry);
- if (p != NULL && p[0] != '\0')
- {
+ if (p != CM_NULLPTR && p[0] != '\0') {
fprintf(out, "%s", p);
w = strlen(p);
- }
- else
- {
- sprintf(tmp, "%lu",
- (unsigned long)archive_entry_gid(entry));
+ } else {
+ sprintf(tmp, "%lu", (unsigned long)archive_entry_gid(entry));
w = strlen(tmp);
fprintf(out, "%s", tmp);
- }
+ }
/*
* Print device number or file size, right-aligned so as to make
* total width of group and devnum/filesize fields be gs_width.
* If gs_width is too small, grow it.
*/
- if (archive_entry_filetype(entry) == AE_IFCHR
- || archive_entry_filetype(entry) == AE_IFBLK)
- {
- sprintf(tmp, "%lu,%lu",
- (unsigned long)archive_entry_rdevmajor(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));
- }
- else
- {
+ } else {
/*
* Note the use of platform-dependent macros to format
* the filesize here. We need the format string and the
@@ -1866,53 +1557,45 @@ namespace{
*/
sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
(BSDTAR_FILESIZE_TYPE)archive_entry_size(entry));
- }
- if (w + strlen(tmp) >= gs_width)
- {
- gs_width = w+strlen(tmp)+1;
- }
+ }
+ if (w + strlen(tmp) >= gs_width) {
+ gs_width = w + strlen(tmp) + 1;
+ }
fprintf(out, "%*s", (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
+#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"
+/* Windows' strftime function does not support %e format. */
+#define DAY_FMT "%d"
#else
-#define DAY_FMT "%e" /* Day number without leading zeros */
+#define DAY_FMT "%e" /* Day number without leading zeros */
#endif
- if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
- {
+ if (tim < now - HALF_YEAR || tim > now + HALF_YEAR) {
fmt = DAY_FMT " %b %Y";
- }
- else
- {
+ } else {
fmt = DAY_FMT " %b %H:%M";
- }
+ }
strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
fprintf(out, " %s ", tmp);
- fprintf(out, "%s", archive_entry_pathname(entry));
+ fprintf(out, "%s", cm_archive_entry_pathname(entry).c_str());
/* Extra information for links. */
if (archive_entry_hardlink(entry)) /* Hard link */
- {
- fprintf(out, " link to %s",
- archive_entry_hardlink(entry));
- }
- else if (archive_entry_symlink(entry)) /* Symbolic link */
- {
+ {
+ fprintf(out, " link to %s", archive_entry_hardlink(entry));
+ } else if (archive_entry_symlink(entry)) /* Symbolic link */
+ {
fprintf(out, " -> %s", archive_entry_symlink(entry));
- }
+ }
+ fflush(out);
}
-#ifdef __BORLANDC__
-# pragma warn -8066 /* unreachable code */
-#endif
-long copy_data(struct archive *ar, struct archive *aw)
+long copy_data(struct archive* ar, struct archive* aw)
{
long r;
- const void *buff;
+ const void* buff;
size_t size;
#if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
__LA_INT64_T offset;
@@ -1920,115 +1603,108 @@ long copy_data(struct archive *ar, struct archive *aw)
off_t offset;
#endif
- for (;;)
- {
+ for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
- if (r == ARCHIVE_EOF)
- {
+ if (r == ARCHIVE_EOF) {
return (ARCHIVE_OK);
- }
- if (r != ARCHIVE_OK)
- {
+ }
+ if (r != ARCHIVE_OK) {
return (r);
- }
+ }
r = archive_write_data_block(aw, buff, size, offset);
- if (r != ARCHIVE_OK)
- {
+ if (r != ARCHIVE_OK) {
cmSystemTools::Message("archive_write_data_block()",
archive_error_string(aw));
return (r);
- }
}
- return r;
+ }
+#if !defined(__clang__) && !defined(__HP_aCC)
+ return r; /* this should not happen but it quiets some compilers */
+#endif
}
-bool extract_tar(const char* outFileName, bool verbose,
- bool extract)
+bool extract_tar(const char* outFileName, bool verbose, bool extract)
{
+ cmLocaleRAII localeRAII;
+ static_cast<void>(localeRAII);
struct archive* a = archive_read_new();
- struct archive *ext = archive_write_disk_new();
- archive_read_support_compression_all(a);
+ struct archive* ext = archive_write_disk_new();
+ archive_read_support_filter_all(a);
archive_read_support_format_all(a);
- struct archive_entry *entry;
- int r = archive_read_open_file(a, outFileName, 10240);
- if(r)
- {
+ struct archive_entry* entry;
+ int r = cm_archive_read_open_file(a, outFileName, 10240);
+ if (r) {
cmSystemTools::Error("Problem with archive_read_open_file(): ",
archive_error_string(a));
+ archive_write_free(ext);
+ archive_read_close(a);
return false;
- }
- for (;;)
- {
+ }
+ for (;;) {
r = archive_read_next_header(a, &entry);
- if (r == ARCHIVE_EOF)
- {
+ if (r == ARCHIVE_EOF) {
break;
- }
- if (r != ARCHIVE_OK)
- {
+ }
+ if (r != ARCHIVE_OK) {
cmSystemTools::Error("Problem with archive_read_next_header(): ",
archive_error_string(a));
break;
+ }
+ if (verbose) {
+ if (extract) {
+ cmSystemTools::Stdout("x ");
+ cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str());
+ } else {
+ list_item_verbose(stdout, entry);
}
- if (verbose && extract)
- {
- cmSystemTools::Stdout("x ");
- cmSystemTools::Stdout(archive_entry_pathname(entry));
- }
- if(verbose && !extract)
- {
- list_item_verbose(stdout, entry);
- }
- else if(!extract)
- {
- cmSystemTools::Stdout(archive_entry_pathname(entry));
- }
- if(extract)
- {
+ cmSystemTools::Stdout("\n");
+ } else if (!extract) {
+ cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str());
+ 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));
+ if (r != ARCHIVE_OK) {
+ cmSystemTools::Error("Problem with archive_write_disk_set_options(): ",
+ archive_error_string(ext));
break;
- }
+ }
r = archive_write_header(ext, entry);
- if (r != ARCHIVE_OK)
- {
- cmSystemTools::Error("Problem with archive_write_header(): ",
- archive_error_string(ext));
- cmSystemTools::Error("Current file: ",
- archive_entry_pathname(entry));
- break;
- }
- else
- {
+ if (r == ARCHIVE_OK) {
copy_data(a, ext);
r = archive_write_finish_entry(ext);
- if (r != ARCHIVE_OK)
- {
+ if (r != ARCHIVE_OK) {
cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
archive_error_string(ext));
break;
- }
}
}
- if (verbose || !extract)
- {
- cmSystemTools::Stdout("\n");
+#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
+ else {
+ cmSystemTools::Error("Problem with archive_write_header(): ",
+ archive_error_string(ext));
+ cmSystemTools::Error("Current file: ",
+ cm_archive_entry_pathname(entry).c_str());
+ break;
}
}
+ }
+ archive_write_free(ext);
archive_read_close(a);
- archive_read_finish(a);
+ archive_read_free(a);
return r == ARCHIVE_EOF || r == ARCHIVE_OK;
}
}
#endif
-bool cmSystemTools::ExtractTar(const char* outFileName,
- bool , bool verbose)
+bool cmSystemTools::ExtractTar(const char* outFileName, bool verbose)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
return extract_tar(outFileName, verbose, true);
@@ -2039,9 +1715,7 @@ bool cmSystemTools::ExtractTar(const char* outFileName,
#endif
}
-bool cmSystemTools::ListTar(const char* outFileName,
- bool ,
- bool verbose)
+bool cmSystemTools::ListTar(const char* outFileName, bool verbose)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
return extract_tar(outFileName, verbose, false);
@@ -2053,105 +1727,98 @@ bool cmSystemTools::ListTar(const char* outFileName,
}
int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
- double timeout,
- std::vector<char>& out,
+ double timeout, std::vector<char>& out,
std::vector<char>& err)
{
line = "";
std::vector<char>::iterator outiter = out.begin();
std::vector<char>::iterator erriter = err.begin();
- while(1)
- {
+ cmProcessOutput processOutput;
+ std::string strdata;
+ while (true) {
// Check for a newline in stdout.
- for(;outiter != out.end(); ++outiter)
- {
- if((*outiter == '\r') && ((outiter+1) == out.end()))
- {
+ for (; outiter != out.end(); ++outiter) {
+ if ((*outiter == '\r') && ((outiter + 1) == out.end())) {
break;
- }
- else if(*outiter == '\n' || *outiter == '\0')
- {
- std::vector<char>::size_type length = outiter-out.begin();
- if(length > 1 && *(outiter-1) == '\r')
- {
+ }
+ if (*outiter == '\n' || *outiter == '\0') {
+ std::vector<char>::size_type length = outiter - out.begin();
+ if (length > 1 && *(outiter - 1) == '\r') {
--length;
- }
- if(length > 0)
- {
+ }
+ if (length > 0) {
line.append(&out[0], length);
- }
- out.erase(out.begin(), outiter+1);
- return cmsysProcess_Pipe_STDOUT;
}
+ out.erase(out.begin(), outiter + 1);
+ return cmsysProcess_Pipe_STDOUT;
}
+ }
// Check for a newline in stderr.
- for(;erriter != err.end(); ++erriter)
- {
- if((*erriter == '\r') && ((erriter+1) == err.end()))
- {
+ for (; erriter != err.end(); ++erriter) {
+ if ((*erriter == '\r') && ((erriter + 1) == err.end())) {
break;
- }
- else if(*erriter == '\n' || *erriter == '\0')
- {
- std::vector<char>::size_type length = erriter-err.begin();
- if(length > 1 && *(erriter-1) == '\r')
- {
+ }
+ if (*erriter == '\n' || *erriter == '\0') {
+ std::vector<char>::size_type length = erriter - err.begin();
+ if (length > 1 && *(erriter - 1) == '\r') {
--length;
- }
- if(length > 0)
- {
+ }
+ if (length > 0) {
line.append(&err[0], length);
- }
- err.erase(err.begin(), erriter+1);
- return cmsysProcess_Pipe_STDERR;
}
+ err.erase(err.begin(), erriter + 1);
+ return cmsysProcess_Pipe_STDERR;
}
+ }
// No newlines found. Wait for more data from the process.
int length;
char* data;
int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
- if(pipe == cmsysProcess_Pipe_Timeout)
- {
+ if (pipe == cmsysProcess_Pipe_Timeout) {
// Timeout has been exceeded.
return pipe;
- }
- else if(pipe == cmsysProcess_Pipe_STDOUT)
- {
+ }
+ if (pipe == cmsysProcess_Pipe_STDOUT) {
+ processOutput.DecodeText(data, length, strdata, 1);
// Append to the stdout buffer.
std::vector<char>::size_type size = out.size();
- out.insert(out.end(), data, data+length);
- outiter = out.begin()+size;
- }
- else if(pipe == cmsysProcess_Pipe_STDERR)
- {
+ out.insert(out.end(), strdata.begin(), strdata.end());
+ 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(), data, data+length);
- erriter = err.begin()+size;
- }
- else if(pipe == cmsysProcess_Pipe_None)
- {
+ err.insert(err.end(), strdata.begin(), strdata.end());
+ erriter = err.begin() + size;
+ } else if (pipe == cmsysProcess_Pipe_None) {
// Both stdout and stderr pipes have broken. Return leftover data.
- if(!out.empty())
- {
- line.append(&out[0], outiter-out.begin());
+ 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());
+ 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());
+ erriter = err.begin() + size;
+ }
+ if (!out.empty()) {
+ line.append(&out[0], outiter - out.begin());
out.erase(out.begin(), out.end());
return cmsysProcess_Pipe_STDOUT;
- }
- else if(!err.empty())
- {
- line.append(&err[0], erriter-err.begin());
+ }
+ if (!err.empty()) {
+ line.append(&err[0], erriter - err.begin());
err.erase(err.begin(), err.end());
return cmsysProcess_Pipe_STDERR;
- }
- else
- {
- return cmsysProcess_Pipe_None;
- }
}
+ return cmsysProcess_Pipe_None;
}
+ }
}
void cmSystemTools::DoNotInheritStdPipes()
@@ -2163,160 +1830,132 @@ void cmSystemTools::DoNotInheritStdPipes()
// shell windows
CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
- if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
- {
+ if (GetConsoleScreenBufferInfo(hOut, &hOutInfo)) {
return;
- }
+ }
{
- HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
- DuplicateHandle(GetCurrentProcess(), out,
- GetCurrentProcess(), &out, 0, FALSE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
- SetStdHandle(STD_OUTPUT_HANDLE, out);
+ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+ DuplicateHandle(GetCurrentProcess(), out, GetCurrentProcess(), &out, 0,
+ FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+ SetStdHandle(STD_OUTPUT_HANDLE, out);
}
{
- HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
- DuplicateHandle(GetCurrentProcess(), out,
- GetCurrentProcess(), &out, 0, FALSE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
- SetStdHandle(STD_ERROR_HANDLE, out);
+ HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
+ DuplicateHandle(GetCurrentProcess(), out, GetCurrentProcess(), &out, 0,
+ FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+ SetStdHandle(STD_ERROR_HANDLE, out);
}
#endif
}
-//----------------------------------------------------------------------------
bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- cmSystemToolsWindowsHandle hFrom =
- CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0,
- OPEN_EXISTING, 0, 0);
- cmSystemToolsWindowsHandle hTo =
- CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
- if(!hFrom || !hTo)
- {
+ 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))
- {
+ if (!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite)) {
return false;
- }
- if(!SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite))
- {
- return false;
- }
+ }
+ return SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite) != 0;
#else
struct stat fromStat;
- if(stat(fromFile, &fromStat) < 0)
- {
+ if (stat(fromFile, &fromStat) < 0) {
return false;
- }
+ }
struct utimbuf buf;
buf.actime = fromStat.st_atime;
buf.modtime = fromStat.st_mtime;
- if(utime(toFile, &buf) < 0)
- {
- return false;
- }
+ return utime(toFile, &buf) >= 0;
#endif
- return true;
}
-//----------------------------------------------------------------------------
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 =
- CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- if(!h)
- {
+ 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))
- {
+ }
+ if (!GetFileTime(h, &t->timeCreation, &t->timeLastAccess,
+ &t->timeLastWrite)) {
return false;
- }
+ }
#else
struct stat st;
- if(stat(fname, &st) < 0)
- {
+ 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 =
- CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
- if(!h)
- {
- return false;
- }
- if(!SetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
- {
+ 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
- if(utime(fname, &t->timeBuf) < 0)
- {
- return false;
- }
+ return utime(fname, &t->timeBuf) >= 0;
#endif
- return true;
}
-//----------------------------------------------------------------------------
#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;
HCRYPTPROV hProvider = 0;
- if(CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- {
- result = CryptGenRandom(hProvider, (DWORD)size, (BYTE*)data)? 1:0;
+ if (CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ result = CryptGenRandom(hProvider, (DWORD)size, (BYTE*)data) ? 1 : 0;
CryptReleaseContext(hProvider, 0);
- }
+ }
return result;
}
#endif
-//----------------------------------------------------------------------------
unsigned int cmSystemTools::RandomSeed()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
unsigned int seed = 0;
// Try using a real random source.
- if(WinCryptRandom(&seed, sizeof(seed)))
- {
+ if (WinCryptRandom(&seed, sizeof(seed))) {
return seed;
- }
+ }
// Fall back to the time and pid.
FILETIME ft;
@@ -2333,16 +1972,17 @@ unsigned int cmSystemTools::RandomSeed()
} seed;
// Try using a real random source.
- std::ifstream fin("/dev/urandom");
- if(fin && fin.read(seed.bytes, sizeof(seed)) &&
- fin.gcount() == sizeof(seed))
- {
+ cmsys::ifstream fin;
+ fin.rdbuf()->pubsetbuf(CM_NULLPTR, 0); // Unbuffered read.
+ fin.open("/dev/urandom");
+ if (fin.good() && fin.read(seed.bytes, sizeof(seed)) &&
+ fin.gcount() == sizeof(seed)) {
return seed.integer;
- }
+ }
// Fall back to the time and pid.
struct timeval t;
- gettimeofday(&t, 0);
+ gettimeofday(&t, CM_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);
@@ -2352,42 +1992,171 @@ unsigned int cmSystemTools::RandomSeed()
#endif
}
-//----------------------------------------------------------------------------
-static std::string cmSystemToolsExecutableDirectory;
-void cmSystemTools::FindExecutableDirectory(const char* argv0)
+static std::string cmSystemToolsCMakeCommand;
+static std::string cmSystemToolsCTestCommand;
+static std::string cmSystemToolsCPackCommand;
+static std::string cmSystemToolsCMakeCursesCommand;
+static std::string cmSystemToolsCMakeGUICommand;
+static std::string cmSystemToolsCMClDepsCommand;
+static std::string cmSystemToolsCMakeRoot;
+void cmSystemTools::FindCMakeResources(const char* argv0)
{
+ std::string exe_dir;
#if defined(_WIN32) && !defined(__CYGWIN__)
(void)argv0; // ignore this on windows
- char modulepath[_MAX_PATH];
- ::GetModuleFileName(NULL, modulepath, sizeof(modulepath));
- cmSystemToolsExecutableDirectory =
- cmSystemTools::GetFilenamePath(modulepath);
- return;
+ wchar_t modulepath[_MAX_PATH];
+ ::GetModuleFileNameW(NULL, modulepath, sizeof(modulepath));
+ exe_dir =
+ cmSystemTools::GetFilenamePath(cmsys::Encoding::ToNarrow(modulepath));
+#elif defined(__APPLE__)
+ (void)argv0; // ignore this on OS X
+#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)
+ unsigned long exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
+#else
+ uint32_t exe_path_size = 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);
+ _NSGetExecutablePath(exe_path, &exe_path_size);
+ }
+ exe_dir =
+ cmSystemTools::GetFilenamePath(cmSystemTools::GetRealPath(exe_path));
+ if (exe_path != exe_path_local) {
+ free(exe_path);
+ }
+ if (cmSystemTools::GetFilenameName(exe_dir) == "MacOS") {
+ // The executable is inside an application bundle.
+ // Look for ..<CMAKE_BIN_DIR> (install tree) and then fall back to
+ // ../../../bin (build tree).
+ exe_dir = cmSystemTools::GetFilenamePath(exe_dir);
+ if (cmSystemTools::FileExists(exe_dir + CMAKE_BIN_DIR "/cmake")) {
+ exe_dir += CMAKE_BIN_DIR;
+ } else {
+ exe_dir = cmSystemTools::GetFilenamePath(exe_dir);
+ exe_dir = cmSystemTools::GetFilenamePath(exe_dir);
+ }
+ }
#else
std::string errorMsg;
std::string exe;
- if(cmSystemTools::FindProgramPath(argv0, exe, errorMsg))
- {
+ if (cmSystemTools::FindProgramPath(argv0, exe, errorMsg)) {
// remove symlinks
- exe = cmSystemTools::GetRealPath(exe.c_str());
- cmSystemToolsExecutableDirectory =
- cmSystemTools::GetFilenamePath(exe.c_str());
- }
- else
- {
+ exe = cmSystemTools::GetRealPath(exe);
+ exe_dir = cmSystemTools::GetFilenamePath(exe);
+ } else {
// ???
+ }
+#endif
+ exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir);
+ cmSystemToolsCMakeCommand = exe_dir;
+ cmSystemToolsCMakeCommand += "/cmake";
+ cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension();
+#ifndef CMAKE_BUILD_WITH_CMAKE
+ // 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
+ // Install tree has
+ // - "<prefix><CMAKE_BIN_DIR>/cmake"
+ // - "<prefix><CMAKE_DATA_DIR>"
+ if (cmHasSuffix(exe_dir, CMAKE_BIN_DIR)) {
+ std::string const prefix =
+ exe_dir.substr(0, exe_dir.size() - strlen(CMAKE_BIN_DIR));
+ cmSystemToolsCMakeRoot = prefix + CMAKE_DATA_DIR;
+ }
+ if (cmSystemToolsCMakeRoot.empty() ||
+ !cmSystemTools::FileExists(
+ (cmSystemToolsCMakeRoot + "/Modules/CMake.cmake").c_str())) {
+ // Build tree has "<build>/bin[/<config>]/cmake" and
+ // "<build>/CMakeFiles/CMakeSourceDir.txt".
+ std::string dir = cmSystemTools::GetFilenamePath(exe_dir);
+ std::string src_dir_txt = dir + "/CMakeFiles/CMakeSourceDir.txt";
+ cmsys::ifstream fin(src_dir_txt.c_str());
+ std::string src_dir;
+ if (fin && cmSystemTools::GetLineFromStream(fin, src_dir) &&
+ cmSystemTools::FileIsDirectory(src_dir)) {
+ cmSystemToolsCMakeRoot = src_dir;
+ } else {
+ dir = cmSystemTools::GetFilenamePath(dir);
+ src_dir_txt = dir + "/CMakeFiles/CMakeSourceDir.txt";
+ cmsys::ifstream fin2(src_dir_txt.c_str());
+ if (fin2 && cmSystemTools::GetLineFromStream(fin2, src_dir) &&
+ cmSystemTools::FileIsDirectory(src_dir)) {
+ cmSystemToolsCMakeRoot = src_dir;
+ }
}
+ }
+#else
+ // Bootstrap build knows its source.
+ cmSystemToolsCMakeRoot = CMAKE_BOOTSTRAP_SOURCE_DIR;
#endif
}
-//----------------------------------------------------------------------------
-const char* cmSystemTools::GetExecutableDirectory()
+std::string const& cmSystemTools::GetCMakeCommand()
{
- return cmSystemToolsExecutableDirectory.c_str();
+ return cmSystemToolsCMakeCommand;
+}
+
+std::string const& cmSystemTools::GetCTestCommand()
+{
+ return cmSystemToolsCTestCommand;
+}
+
+std::string const& cmSystemTools::GetCPackCommand()
+{
+ return cmSystemToolsCPackCommand;
+}
+
+std::string const& cmSystemTools::GetCMakeCursesCommand()
+{
+ return cmSystemToolsCMakeCursesCommand;
+}
+
+std::string const& cmSystemTools::GetCMakeGUICommand()
+{
+ return cmSystemToolsCMakeGUICommand;
+}
+
+std::string const& cmSystemTools::GetCMClDepsCommand()
+{
+ return cmSystemToolsCMClDepsCommand;
+}
+
+std::string const& cmSystemTools::GetCMakeRoot()
+{
+ return cmSystemToolsCMakeRoot;
}
-//----------------------------------------------------------------------------
-#if defined(CMAKE_BUILD_WITH_CMAKE)
void cmSystemTools::MakefileColorEcho(int color, const char* message,
bool newline, bool enabled)
{
@@ -2398,143 +2167,106 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message,
// However, we can test for some situations when the answer is most
// likely no.
int assumeTTY = cmsysTerminal_Color_AssumeTTY;
- if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
- cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
- cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
- {
+ if (cmSystemTools::HasEnv("DART_TEST_FROM_DART") ||
+ cmSystemTools::HasEnv("DASHBOARD_TEST_FROM_CTEST") ||
+ cmSystemTools::HasEnv("CTEST_INTERACTIVE_DEBUG_MODE")) {
// Avoid printing color escapes during dashboard builds.
assumeTTY = 0;
- }
+ }
- if(enabled)
- {
- cmsysTerminal_cfprintf(color | assumeTTY, stdout, "%s%s",
- message, newline? "\n" : "");
- }
- else
- {
+ if (enabled && color != cmsysTerminal_Color_Normal) {
+ // Print with color. Delay the newline until later so that
+ // all color restore sequences appear before it.
+ cmsysTerminal_cfprintf(color | assumeTTY, stdout, "%s", message);
+ } else {
// Color is disabled. Print without color.
- fprintf(stdout, "%s%s", message, newline? "\n" : "");
- }
+ fprintf(stdout, "%s", message);
+ }
+
+ if (newline) {
+ fprintf(stdout, "\n");
+ }
}
-#endif
-//----------------------------------------------------------------------------
bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
std::string& soname)
{
- // For ELF shared libraries use a real parser to get the correct
- // soname.
+// For ELF shared libraries use a real parser to get the correct
+// soname.
#if defined(CMAKE_USE_ELF_PARSER)
cmELF elf(fullPath.c_str());
- if(elf)
- {
+ if (elf) {
return elf.GetSOName(soname);
- }
+ }
#endif
// If the file is not a symlink we have no guess for its soname.
- if(!cmSystemTools::FileIsSymlink(fullPath.c_str()))
- {
+ if (!cmSystemTools::FileIsSymlink(fullPath)) {
return false;
- }
- if(!cmSystemTools::ReadSymlink(fullPath.c_str(), soname))
- {
+ }
+ if (!cmSystemTools::ReadSymlink(fullPath, soname)) {
return false;
- }
+ }
// If the symlink has a path component we have no guess for the soname.
- if(!cmSystemTools::GetFilenamePath(soname).empty())
- {
+ if (!cmSystemTools::GetFilenamePath(soname).empty()) {
return false;
- }
+ }
// If the symlink points at an extended version of the same name
// assume it is the soname.
std::string name = cmSystemTools::GetFilenameName(fullPath);
- if(soname.length() > name.length() &&
- soname.substr(0, name.length()) == name)
- {
- return true;
- }
- return false;
+ return soname.length() > name.length() &&
+ soname.compare(0, name.length(), name) == 0;
}
-//----------------------------------------------------------------------------
bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
- std::string& soname)
+ std::string& soname)
{
- std::vector<cmStdString> cmds;
- cmds.push_back("otool");
- cmds.push_back("-D");
- cmds.push_back(fullPath.c_str());
-
- std::string output;
- if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
- {
- cmds.insert(cmds.begin(), "-r");
- cmds.insert(cmds.begin(), "xcrun");
- if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
- {
- return false;
- }
- }
+#if defined(CMAKE_USE_MACH_PARSER)
+ cmMachO macho(fullPath.c_str());
+ if (macho) {
+ return macho.GetInstallName(soname);
+ }
+#else
+ (void)fullPath;
+ (void)soname;
+#endif
- std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n");
- // otool returns extra lines reporting multiple install names
- // in case the binary is multi-arch and none of the architectures
- // is native (e.g. i386;ppc on x86_64)
- if(strs.size() >= 2)
- {
- soname = strs[1];
- return true;
- }
return false;
}
-//----------------------------------------------------------------------------
#if defined(CMAKE_USE_ELF_PARSER)
std::string::size_type cmSystemToolsFindRPath(std::string const& have,
std::string const& want)
{
- // Search for the desired rpath.
- std::string::size_type pos = have.find(want);
-
- // If the path is not present we are done.
- if(pos == std::string::npos)
- {
- return pos;
- }
-
- // Build a regex to match a properly separated path instance.
- std::string regex_str = "(^|:)(";
- for(std::string::const_iterator i = want.begin(); i != want.end(); ++i)
- {
- int ch = *i;
- if(!(('a' <= ch && ch <= 'z') ||
- ('A' <= ch && ch <= 'Z') ||
- ('0' <= ch && ch <= '9')))
- {
- // Escape the non-alphanumeric character.
- regex_str += "\\";
- }
- // Store the character.
- regex_str.append(1, static_cast<char>(ch));
+ std::string::size_type pos = 0;
+ while (pos < have.size()) {
+ // Look for an occurrence of the string.
+ std::string::size_type const beg = have.find(want, pos);
+ if (beg == std::string::npos) {
+ return std::string::npos;
}
- regex_str += ")(:|$)";
- // Look for the separated path.
- cmsys::RegularExpression regex(regex_str.c_str());
- if(regex.find(have))
- {
- // Return the position of the path portion.
- return regex.start(2);
+ // Make sure it is separated from preceding entries.
+ if (beg > 0 && have[beg - 1] != ':') {
+ pos = beg + 1;
+ continue;
}
- else
- {
- // The desired rpath was not found.
- return std::string::npos;
+
+ // Make sure it is separated from following entries.
+ std::string::size_type const end = beg + want.size();
+ if (end < have.size() && have[end] != ':') {
+ pos = beg + 1;
+ continue;
}
+
+ // Return the position of the path portion.
+ return beg;
+ }
+
+ // The desired rpath was not found.
+ return std::string::npos;
}
#endif
@@ -2548,182 +2280,176 @@ struct cmSystemToolsRPathInfo
};
#endif
-//----------------------------------------------------------------------------
bool cmSystemTools::ChangeRPath(std::string const& file,
std::string const& oldRPath,
- std::string const& newRPath,
- std::string* emsg,
+ std::string const& newRPath, std::string* emsg,
bool* changed)
{
#if defined(CMAKE_USE_ELF_PARSER)
- if(changed)
- {
+ if (changed) {
*changed = false;
- }
+ }
int rp_count = 0;
+ bool remove_rpath = true;
cmSystemToolsRPathInfo rp[2];
{
- // Parse the ELF binary.
- cmELF elf(file.c_str());
-
- // Get the RPATH and RUNPATH entries from it.
- int se_count = 0;
- cmELF::StringEntry const* se[2] = {0, 0};
- const char* se_name[2] = {0, 0};
- if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
- {
- se[se_count] = se_rpath;
- se_name[se_count] = "RPATH";
- ++se_count;
- }
- if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
- {
- se[se_count] = se_runpath;
- se_name[se_count] = "RUNPATH";
- ++se_count;
- }
- if(se_count == 0)
- {
- if(newRPath.empty())
- {
- // The new rpath is empty and there is no rpath anyway so it is
- // okay.
- return true;
- }
- else
- {
- if(emsg)
- {
+ // Parse the ELF binary.
+ cmELF elf(file.c_str());
+
+ // 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 };
+ if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
+ se[se_count] = se_rpath;
+ se_name[se_count] = "RPATH";
+ ++se_count;
+ }
+ if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
+ se[se_count] = se_runpath;
+ se_name[se_count] = "RUNPATH";
+ ++se_count;
+ }
+ if (se_count == 0) {
+ if (newRPath.empty()) {
+ // The new rpath is empty and there is no rpath anyway so it is
+ // okay.
+ return true;
+ }
+ if (emsg) {
*emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
*emsg += elf.GetErrorMessage();
- }
- return false;
}
+ return false;
}
- for(int i=0; i < se_count; ++i)
- {
- // If both RPATH and RUNPATH refer to the same string literal it
- // needs to be changed only once.
- if(rp_count && rp[0].Position == se[i]->Position)
- {
- continue;
+ for (int i = 0; i < se_count; ++i) {
+ // If both RPATH and RUNPATH refer to the same string literal it
+ // needs to be changed only once.
+ if (rp_count && rp[0].Position == se[i]->Position) {
+ continue;
}
- // Make sure the current rpath contains the old rpath.
- std::string::size_type pos =
- cmSystemToolsFindRPath(se[i]->Value, oldRPath);
- if(pos == std::string::npos)
- {
- // If it contains the new rpath instead then it is okay.
- if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
- {
- continue;
+ // Make sure the current rpath contains the old rpath.
+ std::string::size_type pos =
+ cmSystemToolsFindRPath(se[i]->Value, oldRPath);
+ if (pos == std::string::npos) {
+ // If it contains the new rpath instead then it is okay.
+ if (cmSystemToolsFindRPath(se[i]->Value, newRPath) !=
+ std::string::npos) {
+ remove_rpath = false;
+ continue;
}
- if(emsg)
- {
- cmOStringStream e;
+ if (emsg) {
+ std::ostringstream e;
+ /* clang-format off */
e << "The current " << se_name[i] << " is:\n"
<< " " << se[i]->Value << "\n"
<< "which does not contain:\n"
<< " " << oldRPath << "\n"
<< "as was expected.";
- *emsg = e.str();
+ /* clang-format on */
+ *emsg = e.str();
}
- return false;
+ return false;
+ }
+
+ // Store information about the entry in the file.
+ rp[rp_count].Position = se[i]->Position;
+ rp[rp_count].Size = se[i]->Size;
+ rp[rp_count].Name = se_name[i];
+
+ std::string::size_type prefix_len = pos;
+
+ // If oldRPath was at the end of the file's RPath, and newRPath is empty,
+ // we should remove the unnecessary ':' at the end.
+ if (newRPath.empty() && pos > 0 && se[i]->Value[pos - 1] == ':' &&
+ pos + oldRPath.length() == se[i]->Value.length()) {
+ prefix_len--;
}
- // Store information about the entry in the file.
- rp[rp_count].Position = se[i]->Position;
- rp[rp_count].Size = se[i]->Size;
- rp[rp_count].Name = se_name[i];
-
- // Construct the new value which preserves the part of the path
- // not being changed.
- rp[rp_count].Value = se[i]->Value.substr(0, pos);
- rp[rp_count].Value += newRPath;
- rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
- oldRPath.npos);
-
- // Make sure there is enough room to store the new rpath and at
- // 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.";
+ // 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);
+ rp[rp_count].Value += newRPath;
+ rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length());
+
+ if (!rp[rp_count].Value.empty()) {
+ remove_rpath = false;
+ }
+
+ // Make sure there is enough room to store the new rpath and at
+ // 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.";
}
- return false;
+ return false;
}
- // This entry is ready for update.
- ++rp_count;
+ // This entry is ready for update.
+ ++rp_count;
}
}
// If no runtime path needs to be changed, we are done.
- if(rp_count == 0)
- {
+ if (rp_count == 0) {
return true;
- }
+ }
+
+ // If the resulting rpath is empty, just remove the entire entry instead.
+ if (remove_rpath) {
+ return cmSystemTools::RemoveRPath(file, emsg, changed);
+ }
{
- // Open the file for update.
- std::ofstream f(file.c_str(),
- std::ios::in | std::ios::out | std::ios::binary);
- if(!f)
- {
- if(emsg)
- {
- *emsg = "Error opening file for update.";
+ // Open the file for update.
+ cmsys::ofstream f(file.c_str(),
+ std::ios::in | std::ios::out | std::ios::binary);
+ if (!f) {
+ if (emsg) {
+ *emsg = "Error opening file for update.";
}
- return false;
+ return false;
}
- // Store the new RPATH and RUNPATH strings.
- for(int i=0; i < rp_count; ++i)
- {
- // Seek to the RPATH position.
- if(!f.seekp(rp[i].Position))
- {
- if(emsg)
- {
- *emsg = "Error seeking to ";
- *emsg += rp[i].Name;
- *emsg += " position.";
+ // Store the new RPATH and RUNPATH strings.
+ for (int i = 0; i < rp_count; ++i) {
+ // Seek to the RPATH position.
+ if (!f.seekp(rp[i].Position)) {
+ if (emsg) {
+ *emsg = "Error seeking to ";
+ *emsg += rp[i].Name;
+ *emsg += " position.";
}
- return false;
+ return false;
}
- // Write the new rpath. Follow it with enough null terminators to
- // fill the string table entry.
- f << rp[i].Value;
- for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
- {
- f << '\0';
+ // Write the new rpath. Follow it with enough null terminators to
+ // fill the string table entry.
+ f << rp[i].Value;
+ for (unsigned long j = rp[i].Value.length(); j < rp[i].Size; ++j) {
+ f << '\0';
}
- // Make sure it wrote correctly.
- if(!f)
- {
- if(emsg)
- {
- *emsg = "Error writing the new ";
- *emsg += rp[i].Name;
- *emsg += " string to the file.";
+ // Make sure it wrote correctly.
+ if (!f) {
+ if (emsg) {
+ *emsg = "Error writing the new ";
+ *emsg += rp[i].Name;
+ *emsg += " string to the file.";
}
- return false;
+ return false;
}
}
}
// Everything was updated successfully.
- if(changed)
- {
+ if (changed) {
*changed = true;
- }
+ }
return true;
#else
(void)file;
@@ -2735,199 +2461,278 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
#endif
}
-//----------------------------------------------------------------------------
bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
const char* lhss, const char* rhss)
{
- // Parse out up to 8 components.
- unsigned int lhs[8] = {0,0,0,0,0,0,0,0};
- unsigned int rhs[8] = {0,0,0,0,0,0,0,0};
- sscanf(lhss, "%u.%u.%u.%u.%u.%u.%u.%u",
- &lhs[0], &lhs[1], &lhs[2], &lhs[3],
- &lhs[4], &lhs[5], &lhs[6], &lhs[7]);
- sscanf(rhss, "%u.%u.%u.%u.%u.%u.%u.%u",
- &rhs[0], &rhs[1], &rhs[2], &rhs[3],
- &rhs[4], &rhs[5], &rhs[6], &rhs[7]);
-
- // Do component-wise comparison.
- for(unsigned int i=0; i < 8; ++i)
- {
- if(lhs[i] < rhs[i])
- {
+ const char* endl = lhss;
+ const char* endr = rhss;
+ unsigned long lhs, rhs;
+
+ while (((*endl >= '0') && (*endl <= '9')) ||
+ ((*endr >= '0') && (*endr <= '9'))) {
+ // Do component-wise comparison.
+ lhs = strtoul(endl, const_cast<char**>(&endl), 10);
+ rhs = strtoul(endr, const_cast<char**>(&endr), 10);
+
+ if (lhs < rhs) {
// lhs < rhs, so true if operation is LESS
- return op == cmSystemTools::OP_LESS;
- }
- else if(lhs[i] > rhs[i])
- {
+ return (op & cmSystemTools::OP_LESS) != 0;
+ }
+ if (lhs > rhs) {
// lhs > rhs, so true if operation is GREATER
- return op == cmSystemTools::OP_GREATER;
- }
+ return (op & cmSystemTools::OP_GREATER) != 0;
+ }
+
+ if (*endr == '.') {
+ endr++;
}
+
+ if (*endl == '.') {
+ endl++;
+ }
+ }
// lhs == rhs, so true if operation is EQUAL
- return op == cmSystemTools::OP_EQUAL;
+ return (op & cmSystemTools::OP_EQUAL) != 0;
+}
+
+bool cmSystemTools::VersionCompareEqual(std::string const& lhs,
+ std::string const& rhs)
+{
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, lhs.c_str(),
+ rhs.c_str());
+}
+
+bool cmSystemTools::VersionCompareGreater(std::string const& lhs,
+ std::string const& rhs)
+{
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, lhs.c_str(),
+ rhs.c_str());
+}
+
+bool cmSystemTools::VersionCompareGreaterEq(std::string const& lhs,
+ std::string const& rhs)
+{
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
+ lhs.c_str(), rhs.c_str());
+}
+
+static size_t cm_strverscmp_find_first_difference_or_end(const char* lhs,
+ const char* rhs)
+{
+ size_t i = 0;
+ /* Step forward until we find a difference or both strings end together.
+ The difference may lie on the null-terminator of one string. */
+ while (lhs[i] == rhs[i] && lhs[i] != 0) {
+ ++i;
+ }
+ return i;
+}
+
+static size_t cm_strverscmp_find_digits_begin(const char* s, size_t i)
+{
+ /* Step back until we are not preceded by a digit. */
+ while (i > 0 && isdigit(s[i - 1])) {
+ --i;
+ }
+ return i;
+}
+
+static size_t cm_strverscmp_find_digits_end(const char* s, size_t i)
+{
+ /* Step forward over digits. */
+ while (isdigit(s[i])) {
+ ++i;
+ }
+ return i;
+}
+
+static size_t cm_strverscmp_count_leading_zeros(const char* s, size_t b)
+{
+ size_t i = b;
+ /* Step forward over zeros that are followed by another digit. */
+ while (s[i] == '0' && isdigit(s[i + 1])) {
+ ++i;
+ }
+ return i - b;
+}
+
+static int cm_strverscmp(const char* lhs, const char* rhs)
+{
+ size_t const i = cm_strverscmp_find_first_difference_or_end(lhs, rhs);
+ if (lhs[i] != rhs[i]) {
+ /* The strings differ starting at 'i'. Check for a digit sequence. */
+ size_t const b = cm_strverscmp_find_digits_begin(lhs, i);
+ if (b != i || (isdigit(lhs[i]) && isdigit(rhs[i]))) {
+ /* A digit sequence starts at 'b', preceding or at 'i'. */
+
+ /* Look for leading zeros, implying a leading decimal point. */
+ size_t const lhs_zeros = cm_strverscmp_count_leading_zeros(lhs, b);
+ size_t const rhs_zeros = cm_strverscmp_count_leading_zeros(rhs, b);
+ if (lhs_zeros != rhs_zeros) {
+ /* The side with more leading zeros orders first. */
+ return rhs_zeros > lhs_zeros ? 1 : -1;
+ }
+ if (lhs_zeros == 0) {
+ /* No leading zeros; compare digit sequence lengths. */
+ size_t const lhs_end = cm_strverscmp_find_digits_end(lhs, i);
+ size_t const rhs_end = cm_strverscmp_find_digits_end(rhs, i);
+ if (lhs_end != rhs_end) {
+ /* The side with fewer digits orders first. */
+ return lhs_end > rhs_end ? 1 : -1;
+ }
+ }
+ }
+ }
+
+ /* Ordering was not decided by digit sequence lengths; compare bytes. */
+ return lhs[i] - rhs[i];
+}
+
+int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs)
+{
+ return cm_strverscmp(lhs.c_str(), rhs.c_str());
}
-//----------------------------------------------------------------------------
bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
bool* removed)
{
#if defined(CMAKE_USE_ELF_PARSER)
- if(removed)
- {
+ if (removed) {
*removed = false;
- }
+ }
int zeroCount = 0;
- unsigned long zeroPosition[2] = {0,0};
- unsigned long zeroSize[2] = {0,0};
+ unsigned long zeroPosition[2] = { 0, 0 };
+ unsigned long zeroSize[2] = { 0, 0 };
unsigned long bytesBegin = 0;
std::vector<char> bytes;
{
- // Parse the ELF binary.
- cmELF elf(file.c_str());
+ // Parse the ELF binary.
+ cmELF elf(file.c_str());
- // 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] = {0, 0};
- if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
- {
- se[se_count++] = se_rpath;
- }
- if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
- {
- se[se_count++] = se_runpath;
- }
- if(se_count == 0)
- {
- // There is no RPATH or RUNPATH anyway.
- return true;
+ // 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 };
+ if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
+ se[se_count++] = se_rpath;
+ }
+ if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
+ se[se_count++] = se_runpath;
+ }
+ if (se_count == 0) {
+ // There is no RPATH or RUNPATH anyway.
+ return true;
}
- if(se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection)
- {
- cmsys_stl::swap(se[0], se[1]);
+ if (se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection) {
+ std::swap(se[0], se[1]);
}
- // Get the size of the dynamic section header.
- unsigned int count = elf.GetDynamicEntryCount();
- if(count == 0)
- {
- // This should happen only for invalid ELF files where a DT_NULL
- // appears before the end of the table.
- if(emsg)
- {
- *emsg = "DYNAMIC section contains a DT_NULL before the end.";
+ // Obtain a copy of the dynamic entries
+ cmELF::DynamicEntryList dentries = elf.GetDynamicEntries();
+ if (dentries.empty()) {
+ // This should happen only for invalid ELF files where a DT_NULL
+ // appears before the end of the table.
+ if (emsg) {
+ *emsg = "DYNAMIC section contains a DT_NULL before the end.";
}
- return false;
+ return false;
}
- // Save information about the string entries to be zeroed.
- zeroCount = se_count;
- for(int i=0; i < se_count; ++i)
- {
- zeroPosition[i] = se[i]->Position;
- zeroSize[i] = se[i]->Size;
- }
-
- // Get the range of file positions corresponding to each entry and
- // the rest of the table after them.
- unsigned long entryBegin[3] = {0,0,0};
- unsigned long entryEnd[2] = {0,0};
- for(int i=0; i < se_count; ++i)
- {
- entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection);
- entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection+1);
- }
- entryBegin[se_count] = elf.GetDynamicEntryPosition(count);
-
- // The data are to be written over the old table entries starting at
- // the first one being removed.
- bytesBegin = entryBegin[0];
- unsigned long bytesEnd = entryBegin[se_count];
-
- // Allocate a buffer to hold the part of the file to be written.
- // Initialize it with zeros.
- bytes.resize(bytesEnd - bytesBegin, 0);
-
- // Read the part of the DYNAMIC section header that will move.
- // The remainder of the buffer will be left with zeros which
- // represent a DT_NULL entry.
- char* data = &bytes[0];
- for(int i=0; i < se_count; ++i)
- {
- // Read data between the entries being removed.
- unsigned long sz = entryBegin[i+1] - entryEnd[i];
- if(sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data))
- {
- if(emsg)
- {
- *emsg = "Failed to read DYNAMIC section header.";
- }
- return false;
- }
- data += sz;
+ // Save information about the string entries to be zeroed.
+ zeroCount = se_count;
+ for (int i = 0; i < se_count; ++i) {
+ zeroPosition[i] = se[i]->Position;
+ zeroSize[i] = se[i]->Size;
}
+
+ // Get size of one DYNAMIC entry
+ unsigned long const sizeof_dentry =
+ elf.GetDynamicEntryPosition(1) - elf.GetDynamicEntryPosition(0);
+
+ // 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();) {
+ if (it->first == cmELF::TagRPath || it->first == cmELF::TagRunPath) {
+ it = dentries.erase(it);
+ entriesErased++;
+ continue;
+ }
+ if (cmELF::TagMipsRldMapRel != 0 &&
+ it->first == cmELF::TagMipsRldMapRel) {
+ // Background: debuggers need to know the "linker map" which contains
+ // the addresses each dynamic object is loaded at. Most arches use
+ // the DT_DEBUG tag which the dynamic linker writes to (directly) and
+ // 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
+ // 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
+ // into memory it should not be changing.
+ //
+ // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
+ // we move it up by n bytes, we add n bytes to the value of this tag.
+ it->second += entriesErased * sizeof_dentry;
+ }
+
+ it++;
+ }
+
+ // Encode new entries list
+ bytes = elf.EncodeDynamicEntries(dentries);
+ bytesBegin = elf.GetDynamicEntryPosition(0);
}
// Open the file for update.
- std::ofstream f(file.c_str(),
- std::ios::in | std::ios::out | std::ios::binary);
- if(!f)
- {
- if(emsg)
- {
+ cmsys::ofstream f(file.c_str(),
+ std::ios::in | std::ios::out | std::ios::binary);
+ if (!f) {
+ if (emsg) {
*emsg = "Error opening file for update.";
- }
- return false;
}
+ return false;
+ }
// Write the new DYNAMIC table header.
- if(!f.seekp(bytesBegin))
- {
- if(emsg)
- {
+ if (!f.seekp(bytesBegin)) {
+ if (emsg) {
*emsg = "Error seeking to DYNAMIC table header for RPATH.";
- }
- return false;
}
- if(!f.write(&bytes[0], bytes.size()))
- {
- if(emsg)
- {
- *emsg = "Error replacing DYNAMIC table header.";
- }
return false;
+ }
+ if (!f.write(&bytes[0], bytes.size())) {
+ if (emsg) {
+ *emsg = "Error replacing DYNAMIC table header.";
}
+ return false;
+ }
// Fill the RPATH and RUNPATH strings with zero bytes.
- for(int i=0; i < zeroCount; ++i)
- {
- if(!f.seekp(zeroPosition[i]))
- {
- if(emsg)
- {
+ for (int i = 0; i < zeroCount; ++i) {
+ if (!f.seekp(zeroPosition[i])) {
+ if (emsg) {
*emsg = "Error seeking to RPATH position.";
- }
- return false;
}
- for(unsigned long j=0; j < zeroSize[i]; ++j)
- {
+ return false;
+ }
+ for (unsigned long j = 0; j < zeroSize[i]; ++j) {
f << '\0';
- }
- if(!f)
- {
- if(emsg)
- {
+ }
+ if (!f) {
+ if (emsg) {
*emsg = "Error writing the empty rpath string to the file.";
- }
- return false;
}
+ return false;
}
+ }
// Everything was updated successfully.
- if(removed)
- {
+ if (removed) {
*removed = true;
- }
+ }
return true;
#else
(void)file;
@@ -2937,7 +2742,6 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
#endif
}
-//----------------------------------------------------------------------------
bool cmSystemTools::CheckRPath(std::string const& file,
std::string const& newRPath)
{
@@ -2947,27 +2751,21 @@ bool cmSystemTools::CheckRPath(std::string const& file,
// Get the RPATH or RUNPATH entry from it.
cmELF::StringEntry const* se = elf.GetRPath();
- if(!se)
- {
+ if (!se) {
se = elf.GetRunPath();
- }
+ }
// Make sure the current rpath contains the new rpath.
- if(newRPath.empty())
- {
- if(!se)
- {
+ if (newRPath.empty()) {
+ if (!se) {
return true;
- }
}
- else
- {
- if(se &&
- cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
- {
+ } else {
+ if (se &&
+ cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) {
return true;
- }
}
+ }
return false;
#else
(void)file;
@@ -2976,49 +2774,55 @@ bool cmSystemTools::CheckRPath(std::string const& file,
#endif
}
-//----------------------------------------------------------------------------
bool cmSystemTools::RepeatedRemoveDirectory(const char* dir)
{
// Windows sometimes locks files temporarily so try a few times.
- for(int i = 0; i < 10; ++i)
- {
- if(cmSystemTools::RemoveADirectory(dir))
- {
+ for (int i = 0; i < 10; ++i) {
+ if (cmSystemTools::RemoveADirectory(dir)) {
return true;
- }
- cmSystemTools::Delay(100);
}
+ cmSystemTools::Delay(100);
+ }
return false;
}
-//----------------------------------------------------------------------------
std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
- const std::string& sep)
+ 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)
- {
+ 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));
- }
- } while (tokend!=std::string::npos);
+ } else {
+ tokens.push_back(str.substr(tokstart, tokend - tokstart));
+ }
+ } while (tokend != std::string::npos);
- if (tokens.empty())
- {
+ if (tokens.empty()) {
tokens.push_back("");
- }
+ }
return tokens;
}
+
+bool cmSystemTools::StringToLong(const char* str, long* value)
+{
+ errno = 0;
+ char* endp;
+ *value = strtol(str, &endp, 10);
+ return (*endp == '\0') && (endp != str) && (errno == 0);
+}
+
+bool cmSystemTools::StringToULong(const char* str, unsigned long* value)
+{
+ errno = 0;
+ char* endp;
+ *value = strtoul(str, &endp, 10);
+ return (*endp == '\0') && (endp != str) && (errno == 0);
+}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 9d7dae9ef..9de796728 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -1,21 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmSystemTools_h
#define cmSystemTools_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Process.h>
+#include "cmProcessOutput.h"
+#include "cmsys/Process.h"
+#include "cmsys/SystemTools.hxx" // IWYU pragma: export
+#include <stddef.h>
+#include <string>
+#include <vector>
class cmSystemToolsFileTime;
@@ -25,10 +20,11 @@ class cmSystemToolsFileTime;
* cmSystemTools is a class that provides helper functions
* for the CMake build system.
*/
-class cmSystemTools: public cmsys::SystemTools
+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
@@ -38,7 +34,7 @@ public:
std::vector<std::string>& argsOut);
static void ExpandListArgument(const std::string& arg,
std::vector<std::string>& argsOut,
- bool emptyArgs=false);
+ bool emptyArgs = false);
/**
* Look for and replace registry values in a string
@@ -47,75 +43,78 @@ public:
KeyWOW64 view = KeyWOW64_Default);
///! Escape quotes in a string.
- static std::string EscapeQuotes(const char* str);
+ static std::string EscapeQuotes(const std::string& str);
+
+ /** Map help document name to file name. */
+ static std::string HelpFileName(std::string);
/**
* Returns a string that has whitespace removed from the start and the end.
*/
static std::string TrimWhitespace(const std::string& s);
- typedef void (*ErrorCallback)(const char*, const char*, bool&, void*);
+ typedef void (*MessageCallback)(const char*, const char*, bool&, void*);
/**
* 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).
*/
- static void SetErrorCallback(ErrorCallback f, void* clientData=0);
+ static void SetMessageCallback(MessageCallback f,
+ void* clientData = CM_NULLPTR);
/**
* Display an error message.
*/
- static void Error(const char* m, const char* m2=0,
- const char* m3=0, const char* m4=0);
+ static void Error(const char* m, const char* m2 = CM_NULLPTR,
+ const char* m3 = CM_NULLPTR, const char* m4 = CM_NULLPTR);
/**
* Display a message.
*/
- static void Message(const char* m, const char* title=0);
+ static void Message(const char* m, const char* title = CM_NULLPTR);
+
+ typedef void (*OutputCallback)(const char*, size_t length, void*);
///! Send a string to stdout
static void Stdout(const char* s);
- static void Stdout(const char* s, int length);
- typedef void (*StdoutCallback)(const char*, int length, void*);
- static void SetStdoutCallback(StdoutCallback, void* clientData=0);
-
- ///! Send a string to stderr. Stdout callbacks will not be invoced.
- static void Stderr(const char* s, int length);
+ static void Stdout(const char* s, size_t length);
+ static void SetStdoutCallback(OutputCallback, void* clientData = CM_NULLPTR);
+ ///! 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);
typedef bool (*InterruptCallback)(void*);
- static void SetInterruptCallback(InterruptCallback f, void* clientData=0);
+ static void SetInterruptCallback(InterruptCallback f,
+ void* clientData = CM_NULLPTR);
static bool GetInterruptFlag();
///! Return true if there was an error at any point.
static bool GetErrorOccuredFlag()
- {
- return cmSystemTools::s_ErrorOccured ||
- cmSystemTools::s_FatalErrorOccured ||
- GetInterruptFlag();
- }
+ {
+ return cmSystemTools::s_ErrorOccured ||
+ cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
+ }
///! 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.
+ {
+ cmSystemTools::s_FatalErrorOccured = true;
+ }
+ static void SetErrorOccured() { cmSystemTools::s_ErrorOccured = true; }
+ ///! Return true if there was an error at any point.
static bool GetFatalErrorOccured()
- {
- return cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
- }
+ {
+ return cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
+ }
- ///! Set the error occured 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;
- }
+ {
+ cmSystemTools::s_FatalErrorOccured = false;
+ cmSystemTools::s_ErrorOccured = false;
+ }
/**
* Does a string indicates that CMake/CPack/CTest internally
@@ -144,8 +143,7 @@ public:
static bool IsPathToFramework(const char* value);
static bool DoesFileExistWithExtensions(
- const char *name,
- const std::vector<std::string>& sourceExts);
+ const char* name, const std::vector<std::string>& sourceExts);
/**
* Check if the given file exists in one of the parent directory of the
@@ -153,11 +151,13 @@ public:
* Toplevel specifies the top-most directory to where it will look.
*/
static std::string FileExistsInParentDirectories(const char* fname,
- const char* directory, const char* toplevel);
+ const char* directory,
+ const char* toplevel);
- static void Glob(const char *directory, const char *regexp,
+ static void Glob(const std::string& directory, const std::string& regexp,
std::vector<std::string>& files);
- static void GlobDirs(const char *fullPath, std::vector<std::string>& files);
+ static void GlobDirs(const std::string& fullPath,
+ std::vector<std::string>& files);
/**
* Try to find a list of files that match the "simple" globbing
@@ -168,49 +168,33 @@ public:
* want to find. 0 means all files, -1 means directories, 1 means
* files only. This method returns true if search was succesfull.
*/
- static bool SimpleGlob(const cmStdString& glob,
- std::vector<cmStdString>& files,
- int type = 0);
+ 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);
+ 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);
///! Compute the md5sum of a file
- static bool ComputeFileMD5(const char* source, char* md5out);
+ static bool ComputeFileMD5(const std::string& source, char* md5out);
/** Compute the md5sum of a string. */
- static std::string ComputeStringMD5(const char* input);
+ static std::string ComputeStringMD5(const std::string& input);
+
+ ///! Get the SHA thumbprint for a certificate file
+ static std::string ComputeCertificateThumbprint(const std::string& source);
- /**
- * Run an executable command and put the stdout in output.
- * A temporary file is created in the binaryDir for storing the
- * output because windows does not have popen.
- *
- * If verbose is false, no user-viewable output from the program
- * being run will be generated.
- *
- * If timeout is specified, the command will be terminated after
- * timeout expires.
- */
- static bool RunCommand(const char* command, std::string& output,
- const char* directory = 0,
- bool verbose = true, int timeout = 0);
- static bool RunCommand(const char* command, std::string& output,
- int &retVal, const char* directory = 0,
- bool verbose = true, int timeout = 0);
/**
* Run a single executable command
*
* Output is controlled with outputflag. If outputflag is OUTPUT_NONE, no
* user-viewable output from the program being run will be generated.
* OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged
- * into stdout. OUTPUT_NORMAL passes through the output to stdout/stderr as
+ * into stdout. OUTPUT_FORWARD copies the output to stdout/stderr as
* it was received. OUTPUT_PASSTHROUGH passes through the original handles.
*
* If timeout is specified, the command will be terminated after
@@ -226,15 +210,18 @@ public:
* it into this function or it will not work. The command must be correctly
* escaped for this to with spaces.
*/
- enum OutputOption
- {
- OUTPUT_NONE = 0,
- OUTPUT_MERGE,
- OUTPUT_NORMAL,
- OUTPUT_PASSTHROUGH
- };
- static bool RunSingleCommand(const char* command, std::string* output = 0,
- int* retVal = 0, const char* dir = 0,
+ enum OutputOption
+ {
+ OUTPUT_NONE = 0,
+ OUTPUT_MERGE,
+ 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,
OutputOption outputflag = OUTPUT_MERGE,
double timeout = 0.0);
/**
@@ -242,16 +229,21 @@ public:
* the command to run, and each argument to the command should
* be in comand[1]...command[command.size()]
*/
- static bool RunSingleCommand(std::vector<cmStdString> const& command,
- std::string* output = 0,
- int* retVal = 0, const char* dir = 0,
+ 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,
OutputOption outputflag = OUTPUT_MERGE,
- double timeout = 0.0);
+ double timeout = 0.0,
+ Encoding encoding = cmProcessOutput::Auto);
+
+ static std::string PrintSingleCommand(std::vector<std::string> const&);
/**
* Parse arguments out of a single string command
*/
- static std::vector<cmStdString> ParseArguments(const char* command);
+ static std::vector<std::string> ParseArguments(const char* command);
/** Parse arguments out of a windows command line string. */
static void ParseWindowsCommandLine(const char* command,
@@ -260,24 +252,27 @@ public:
/** Parse arguments out of a unix command line string. */
static void ParseUnixCommandLine(const char* command,
std::vector<std::string>& args);
- static void ParseUnixCommandLine(const char* command,
- std::vector<cmStdString>& args);
- /** Compute an escaped version of the given argument for use in a
- windows shell. See kwsys/System.h.in for details. */
- static std::string EscapeWindowsShellArgument(const char* arg,
- int shell_flags);
+ /**
+ * Handle response file in an argument list and return a new argument list
+ * **/
+ static std::vector<std::string> HandleResponseFile(
+ std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd);
+
+ 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 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 {
+ enum FileFormat
+ {
NO_FILE_FORMAT = 0,
C_FILE_FORMAT,
CXX_FILE_FORMAT,
@@ -293,35 +288,46 @@ public:
UNKNOWN_FILE_FORMAT
};
- enum CompareOp {
- OP_LESS,
- OP_GREATER,
- OP_EQUAL
+ enum CompareOp
+ {
+ OP_EQUAL = 1,
+ OP_LESS = 2,
+ OP_GREATER = 4,
+ OP_LESS_EQUAL = OP_LESS | OP_EQUAL,
+ OP_GREATER_EQUAL = OP_GREATER | OP_EQUAL
};
/**
* Compare versions
*/
static bool VersionCompare(CompareOp op, const char* lhs, const char* rhs);
+ static bool VersionCompareEqual(std::string const& lhs,
+ std::string const& rhs);
+ static bool VersionCompareGreater(std::string const& lhs,
+ std::string const& rhs);
+ static bool VersionCompareGreaterEq(std::string const& lhs,
+ std::string const& rhs);
/**
- * Determine the file type based on the extension
+ * Compare two ASCII strings using natural versioning order.
+ * Non-numerical characters are compared directly.
+ * Numerical characters are first globbed such that, e.g.
+ * `test000 < test01 < test0 < test1 < test10`.
+ * Return a value less than, equal to, or greater than zero if lhs
+ * precedes, equals, or succeeds rhs in the defined ordering.
*/
- static FileFormat GetFileFormat(const char* ext);
+ static int strverscmp(std::string const& lhs, std::string const& rhs);
/**
- * On Windows 9x we need a comspec (command.com) substitute to run
- * programs correctly. This string has to be constant available
- * through the running of program. This method does not create a copy.
+ * Determine the file type based on the extension
*/
- static void SetWindows9xComspecSubstitute(const char*);
- static const char* GetWindows9xComspecSubstitute();
+ static FileFormat GetFileFormat(const char* ext);
/** Windows if this is true, the CreateProcess in RunCommand will
* not show new consol windows when running programs.
*/
- static void SetRunCommandHideConsole(bool v){s_RunCommandHideConsole = v;}
- static bool GetRunCommandHideConsole(){ return s_RunCommandHideConsole;}
+ static void SetRunCommandHideConsole(bool v) { s_RunCommandHideConsole = v; }
+ static bool GetRunCommandHideConsole() { return s_RunCommandHideConsole; }
/** Call cmSystemTools::Error with the message m, plus the
* result of strerror(errno)
*/
@@ -329,21 +335,14 @@ public:
/** a general output handler for cmsysProcess */
static int WaitForLine(cmsysProcess* process, std::string& line,
- double timeout,
- std::vector<char>& out,
+ double 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<cmStdString>& l);
- static void SetForceUnixPaths(bool v)
- {
- s_ForceUnixPaths = v;
- }
- static bool GetForceUnixPaths()
- {
- return s_ForceUnixPaths;
- }
+ 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);
@@ -353,8 +352,6 @@ public:
// 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);
- //! Check if the first string ends with the second one.
- static bool StringEndsWith(const char* str1, const char* str2);
/** compute the relative path from local to remote. local must
be a directory. remote can be a file or a directory.
@@ -389,9 +386,11 @@ public:
original environment. */
class SaveRestoreEnvironment
{
+ CM_DISABLE_COPY(SaveRestoreEnvironment)
public:
SaveRestoreEnvironment();
- virtual ~SaveRestoreEnvironment();
+ ~SaveRestoreEnvironment();
+
private:
std::vector<std::string> Env;
};
@@ -401,13 +400,20 @@ public:
static void EnableVSConsoleOutput();
/** Create tar */
- static bool ListTar(const char* outFileName,
- bool gzip, bool verbose);
+ enum cmTarCompression
+ {
+ TarCompressGZip,
+ TarCompressBZip2,
+ TarCompressXZ,
+ TarCompressNone
+ };
+ static bool ListTar(const char* outFileName, bool verbose);
static bool CreateTar(const char* outFileName,
- const std::vector<cmStdString>& files, bool gzip,
- bool bzip2, bool verbose);
- static bool ExtractTar(const char* inFileName, bool gzip,
- bool verbose);
+ 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);
// 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
@@ -428,19 +434,21 @@ public:
/** Random seed generation. */
static unsigned int RandomSeed();
- /** Find the directory containing the running executable. Save it
- in a global location to be queried by GetExecutableDirectory
- later. */
- static void FindExecutableDirectory(const char* argv0);
+ /** Find the directory containing CMake executables. */
+ static void FindCMakeResources(const char* argv0);
- /** Get the directory containing the currently running executable. */
- static const char* GetExecutableDirectory();
+ /** Get the CMake resource paths, after FindCMakeResources. */
+ static std::string const& GetCTestCommand();
+ static std::string const& GetCPackCommand();
+ static std::string const& GetCMakeCommand();
+ static std::string const& GetCMakeGUICommand();
+ static std::string const& GetCMakeCursesCommand();
+ static std::string const& GetCMClDepsCommand();
+ static std::string const& GetCMakeRoot();
-#if defined(CMAKE_BUILD_WITH_CMAKE)
/** Echo a message in color using KWSys's Terminal cprintf. */
- static void MakefileColorEcho(int color, const char* message,
- bool newLine, bool enabled);
-#endif
+ static void MakefileColorEcho(int color, const char* message, bool newLine,
+ bool enabled);
/** Try to guess the soname of a shared library. */
static bool GuessLibrarySOName(std::string const& fullPath,
@@ -448,23 +456,22 @@ public:
/** Try to guess the install name of a shared library. */
static bool GuessLibraryInstallName(std::string const& fullPath,
- std::string& soname);
+ std::string& soname);
/** Try to set the RPATH in an ELF binary. */
- static bool ChangeRPath(std::string const& file,
- std::string const& oldRPath,
+ static bool ChangeRPath(std::string const& file, std::string const& oldRPath,
std::string const& newRPath,
- std::string* emsg = 0,
- bool* changed = 0);
+ std::string* emsg = CM_NULLPTR,
+ bool* changed = CM_NULLPTR);
/** Try to remove the RPATH from an ELF binary. */
- static bool RemoveRPath(std::string const& file, std::string* emsg = 0,
- bool* removed = 0);
+ static bool RemoveRPath(std::string const& file,
+ std::string* emsg = CM_NULLPTR,
+ bool* removed = CM_NULLPTR);
/** Check whether the RPATH in an ELF binary contains the path
given. */
- static bool CheckRPath(std::string const& file,
- std::string const& newRPath);
+ 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);
@@ -472,6 +479,19 @@ public:
/** Tokenize a string */
static std::vector<std::string> tokenize(const std::string& str,
const std::string& sep);
+
+ /** 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);
+
+#ifdef _WIN32
+ struct WindowsFileRetry
+ {
+ unsigned int Count;
+ unsigned int Delay;
+ };
+ static WindowsFileRetry GetWindowsFileRetry();
+#endif
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
@@ -479,14 +499,14 @@ private:
static bool s_FatalErrorOccured;
static bool s_DisableMessages;
static bool s_DisableRunCommandOutput;
- static ErrorCallback s_ErrorCallback;
- static StdoutCallback s_StdoutCallback;
+ static MessageCallback s_MessageCallback;
+ static OutputCallback s_StdoutCallback;
+ static OutputCallback s_StderrCallback;
static InterruptCallback s_InterruptCallback;
- static void* s_ErrorCallbackClientData;
+ static void* s_MessageCallbackClientData;
static void* s_StdoutCallbackClientData;
+ static void* s_StderrCallbackClientData;
static void* s_InterruptCallbackClientData;
-
- static std::string s_Windows9xComspecSubstitute;
};
#endif
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 4ba6c1981..c95a3ca2c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1,2588 +1,754 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTarget.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <assert.h>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmTarget.h"
-#include "cmake.h"
-#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmLocalGenerator.h"
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
-#include "cmComputeLinkInformation.h"
-#include "cmDocumentCompileDefinitions.h"
-#include "cmDocumentGeneratorExpressions.h"
-#include "cmDocumentLocationUndefined.h"
#include "cmListFileCache.h"
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorExpressionDAGChecker.h"
-#include <cmsys/RegularExpression.hxx>
-#include <map>
-#include <set>
-#include <queue>
-#include <stdlib.h> // required for atof
-#include <assert.h>
+#include "cmMakefile.h"
+#include "cmMessenger.h"
+#include "cmOutputConverter.h"
+#include "cmProperty.h"
+#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmTargetPropertyComputer.h"
+#include "cm_unordered_set.hxx"
+#include "cmake.h"
-const char* cmTarget::GetTargetTypeName(TargetType targetType)
+template <>
+const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>(
+ cmTarget const* tgt)
{
- switch( targetType )
- {
- case cmTarget::STATIC_LIBRARY:
- return "STATIC_LIBRARY";
- case cmTarget::MODULE_LIBRARY:
- return "MODULE_LIBRARY";
- case cmTarget::SHARED_LIBRARY:
- return "SHARED_LIBRARY";
- case cmTarget::OBJECT_LIBRARY:
- return "OBJECT_LIBRARY";
- case cmTarget::EXECUTABLE:
- return "EXECUTABLE";
- case cmTarget::UTILITY:
- return "UTILITY";
- case cmTarget::GLOBAL_TARGET:
- return "GLOBAL_TARGET";
- case cmTarget::UNKNOWN_LIBRARY:
- return "UNKNOWN_LIBRARY";
- }
- assert(0 && "Unexpected target type");
- return 0;
-}
+ static std::string loc;
+ if (tgt->IsImported()) {
+ loc = tgt->ImportedGetFullPath("", cmStateEnums::RuntimeBinaryArtifact);
+ return loc.c_str();
+ }
-//----------------------------------------------------------------------------
-struct cmTarget::OutputInfo
-{
- std::string OutDir;
- std::string ImpDir;
- std::string PdbDir;
-};
+ cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
+ if (!gg->GetConfigureDoneCMP0026()) {
+ gg->CreateGenerationObjects();
+ }
+ cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
+ loc = gt->GetLocationForBuild();
+ return loc.c_str();
+}
-//----------------------------------------------------------------------------
-struct cmTarget::ImportInfo
+template <>
+const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>(
+ cmTarget const* tgt, const std::string& config)
{
- bool NoSOName;
- std::string Location;
- std::string SOName;
- std::string ImportLibrary;
- cmTarget::LinkInterface LinkInterface;
-};
+ static std::string loc;
+ if (tgt->IsImported()) {
+ loc =
+ tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+ return loc.c_str();
+ }
-struct TargetConfigPair : public std::pair<cmTarget*, std::string> {
- TargetConfigPair(cmTarget* tgt, const std::string &config)
- : std::pair<cmTarget*, std::string>(tgt, config) {}
-};
+ cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
+ if (!gg->GetConfigureDoneCMP0026()) {
+ gg->CreateGenerationObjects();
+ }
+ cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
+ loc = gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+ return loc.c_str();
+}
-//----------------------------------------------------------------------------
-class cmTargetInternals
+template <>
+const char* cmTargetPropertyComputer::GetSources<cmTarget>(
+ cmTarget const* tgt, cmMessenger* messenger,
+ cmListFileBacktrace const& context)
{
-public:
- cmTargetInternals()
- {
- this->PolicyWarnedCMP0022 = false;
- this->SourceFileFlagsConstructed = false;
- }
- cmTargetInternals(cmTargetInternals const& r)
- {
- this->PolicyWarnedCMP0022 = false;
- this->SourceFileFlagsConstructed = false;
- // Only some of these entries are part of the object state.
- // Others not copied here are result caches.
- this->SourceEntries = r.SourceEntries;
- }
- ~cmTargetInternals();
- typedef cmTarget::SourceFileFlags SourceFileFlags;
- std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
- bool SourceFileFlagsConstructed;
-
- // The backtrace when the target was created.
- cmListFileBacktrace Backtrace;
+ cmStringRange entries = tgt->GetSourceEntries();
+ if (entries.empty()) {
+ return CM_NULLPTR;
+ }
- // Cache link interface computation from each configuration.
- struct OptionalLinkInterface: public cmTarget::LinkInterface
- {
- OptionalLinkInterface(): Exists(false) {}
- bool Exists;
- };
- typedef std::map<TargetConfigPair, OptionalLinkInterface>
- LinkInterfaceMapType;
- LinkInterfaceMapType LinkInterfaceMap;
- bool PolicyWarnedCMP0022;
-
- typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
- OutputInfoMapType OutputInfoMap;
-
- typedef std::map<TargetConfigPair, cmTarget::ImportInfo>
- ImportInfoMapType;
- ImportInfoMapType ImportInfoMap;
-
- // Cache link implementation computation from each configuration.
- typedef std::map<TargetConfigPair,
- cmTarget::LinkImplementation> LinkImplMapType;
- LinkImplMapType LinkImplMap;
-
- typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
- LinkClosureMapType;
- LinkClosureMapType LinkClosureMap;
-
- struct SourceEntry { std::vector<cmSourceFile*> Depends; };
- typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
- SourceEntriesType SourceEntries;
-
- struct TargetPropertyEntry {
- TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
- const std::string &targetName = std::string())
- : ge(cge), TargetName(targetName)
- {}
- const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
- std::vector<std::string> CachedEntries;
- const std::string TargetName;
- };
- std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
- std::vector<TargetPropertyEntry*> CompileOptionsEntries;
- std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
- std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
-
- std::map<std::string, std::vector<TargetPropertyEntry*> >
- CachedLinkInterfaceIncludeDirectoriesEntries;
- std::map<std::string, std::vector<TargetPropertyEntry*> >
- CachedLinkInterfaceCompileOptionsEntries;
- std::map<std::string, std::vector<TargetPropertyEntry*> >
- CachedLinkInterfaceCompileDefinitionsEntries;
-
- std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
- std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
- std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
-};
+ 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);
+
+ if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ continue;
+ }
-//----------------------------------------------------------------------------
-void deleteAndClear(
- std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
-{
- for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
- it = entries.begin(),
- end = entries.end();
- it != end; ++it)
- {
- delete *it;
- }
- entries.clear();
-}
+ bool addContent = false;
+ bool noMessage = true;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
+ noMessage = false;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ addContent = true;
+ }
+ 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.";
+ messenger->IssueMessage(messageType, e.str(), context);
+ }
+ if (addContent) {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ }
+ } else if (cmGeneratorExpression::Find(*li) == std::string::npos) {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ } else {
+ cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(*li);
+ // Construct what is known about this source file location.
+ cmSourceFileLocation const& location = sf->GetLocation();
+ std::string sname = location.GetDirectory();
+ if (!sname.empty()) {
+ sname += "/";
+ }
+ sname += location.GetName();
-//----------------------------------------------------------------------------
-void deleteAndClear(
- std::map<std::string,
- std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries)
-{
- for (std::map<std::string,
- std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator
- it = entries.begin(), end = entries.end(); it != end; ++it)
- {
- deleteAndClear(it->second);
+ ss << sep;
+ sep = ";";
+ // Append this list entry.
+ ss << sname;
+ }
}
+ }
+ static std::string srcs;
+ srcs = ss.str();
+ return srcs.c_str();
}
-//----------------------------------------------------------------------------
-cmTargetInternals::~cmTargetInternals()
+class cmTargetInternals
{
- deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
- deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
- deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
-}
+public:
+ std::vector<std::string> IncludeDirectoriesEntries;
+ std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
+ std::vector<std::string> CompileOptionsEntries;
+ std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
+ std::vector<std::string> CompileFeaturesEntries;
+ std::vector<cmListFileBacktrace> CompileFeaturesBacktraces;
+ std::vector<std::string> CompileDefinitionsEntries;
+ std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
+ std::vector<std::string> SourceEntries;
+ std::vector<cmListFileBacktrace> SourceBacktraces;
+ std::vector<std::string> LinkImplementationPropertyEntries;
+ std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
+};
-//----------------------------------------------------------------------------
-cmTarget::cmTarget()
+cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
+ Visibility vis, cmMakefile* mf)
{
-#define INITIALIZE_TARGET_POLICY_MEMBER(POLICY) \
- this->PolicyStatus ## POLICY = cmPolicies::WARN;
-
- CM_FOR_EACH_TARGET_POLICY(INITIALIZE_TARGET_POLICY_MEMBER)
-
-#undef INITIALIZE_TARGET_POLICY_MEMBER
-
- this->Makefile = 0;
- this->LinkLibrariesAnalyzed = false;
+ assert(mf);
+ this->Name = name;
+ this->TargetTypeValue = type;
+ this->Makefile = mf;
this->HaveInstallRule = false;
this->DLLPlatform = false;
- this->IsApple = false;
- this->IsImportedTarget = false;
+ this->IsAndroid = false;
+ this->IsImportedTarget =
+ (vis == VisibilityImported || vis == VisibilityImportedGlobally);
+ this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
this->BuildInterfaceIncludesAppended = false;
- this->DebugIncludesDone = false;
- this->DebugCompileOptionsDone = false;
- this->DebugCompileDefinitionsDone = false;
-}
-//----------------------------------------------------------------------------
-void cmTarget::DefineProperties(cmake *cm)
-{
- cm->DefineProperty
- ("AUTOMOC", cmProperty::TARGET,
- "Should the target be processed with automoc (for Qt projects).",
- "AUTOMOC is a boolean specifying whether CMake will handle "
- "the Qt moc preprocessor automatically, i.e. without having to use "
- "the QT4_WRAP_CPP() or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are "
- "supported. "
- "When this property is set to TRUE, CMake will scan the source files "
- "at build time and invoke moc accordingly. "
- "If an #include statement like #include \"moc_foo.cpp\" is found, "
- "the Q_OBJECT class declaration is expected in the header, and moc is "
- "run on the header file. "
- "If an #include statement like #include \"foo.moc\" is found, "
- "then a Q_OBJECT is expected in the current source file and moc "
- "is run on the file itself. "
- "Additionally, all header files are parsed for Q_OBJECT macros, "
- "and if found, moc is also executed on those files. The resulting "
- "moc files, which are not included as shown above in any of the source "
- "files are included in a generated <targetname>_automoc.cpp file, "
- "which is compiled as part of the target."
- "This property is initialized by the value of the variable "
- "CMAKE_AUTOMOC if it is set when a target is created.\n"
- "Additional command line options for moc can be set via the "
- "AUTOMOC_MOC_OPTIONS property.\n"
- "By setting the CMAKE_AUTOMOC_RELAXED_MODE variable to TRUE the rules "
- "for searching the files which will be processed by moc can be relaxed. "
- "See the documentation for this variable for more details.\n"
- "The global property AUTOMOC_TARGETS_FOLDER can be used to group the "
- "automoc targets together in an IDE, e.g. in MSVS.");
-
- cm->DefineProperty
- ("AUTOMOC_MOC_OPTIONS", cmProperty::TARGET,
- "Additional options for moc when using automoc (see the AUTOMOC property)",
- "This property is only used if the AUTOMOC property is set to TRUE for "
- "this target. In this case, it holds additional command line options "
- "which will be used when moc is executed during the build, i.e. it is "
- "equivalent to the optional OPTIONS argument of the qt4_wrap_cpp() "
- "macro.\n"
- "By default it is empty.");
-
- cm->DefineProperty
- ("BUILD_WITH_INSTALL_RPATH", cmProperty::TARGET,
- "Should build tree targets have install tree rpaths.",
- "BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link "
- "the target in the build tree with the INSTALL_RPATH. This takes "
- "precedence over SKIP_BUILD_RPATH and avoids the need for relinking "
- "before installation. "
- "This property is initialized by the value of the variable "
- "CMAKE_BUILD_WITH_INSTALL_RPATH if it is set when a target is created.");
-
- cm->DefineProperty
- ("COMPILE_FLAGS", cmProperty::TARGET,
- "Additional flags to use when compiling this target's sources.",
- "The COMPILE_FLAGS property sets additional compiler flags used "
- "to build sources within the target. Use COMPILE_DEFINITIONS "
- "to pass additional preprocessor definitions.");
-
- cm->DefineProperty
- ("COMPILE_DEFINITIONS", cmProperty::TARGET,
- "Preprocessor definitions for compiling a target's sources.",
- "The COMPILE_DEFINITIONS property may be set to a "
- "semicolon-separated list of preprocessor "
- "definitions using the syntax VAR or VAR=value. Function-style "
- "definitions are not supported. CMake will automatically escape "
- "the value correctly for the native build system (note that CMake "
- "language syntax may require escapes to specify some values). "
- "This property may be set on a per-configuration basis using the name "
- "COMPILE_DEFINITIONS_<CONFIG> where <CONFIG> is an upper-case name "
- "(ex. \"COMPILE_DEFINITIONS_DEBUG\").\n"
- "CMake will automatically drop some definitions that "
- "are not supported by the native build tool. "
- "The VS6 IDE does not support definition values with spaces "
- "(but NMake does).\n"
- "Contents of COMPILE_DEFINITIONS may use \"generator expressions\" with "
- "the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
-
- cm->DefineProperty
- ("COMPILE_DEFINITIONS_<CONFIG>", cmProperty::TARGET,
- "Per-configuration preprocessor definitions on a target.",
- "This is the configuration-specific version of COMPILE_DEFINITIONS.");
-
- cm->DefineProperty
- ("COMPILE_OPTIONS", cmProperty::TARGET,
- "List of options to pass to the compiler.",
- "This property specifies the list of options specified "
- "so far for this property. "
- "This property exists on directories and targets."
- "\n"
- "The target property values are used by the generators to set "
- "the options for the compiler.\n"
- "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
- "the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("INTERFACE_COMPILE_OPTIONS", cmProperty::TARGET,
- "List of interface options to pass to the compiler.",
- "Targets may populate this property to publish the compile options "
- "required to compile against the headers for the target. Consuming "
- "targets can add entries to their own COMPILE_OPTIONS property such "
- "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_OPTIONS> to use the "
- "compile options specified in the interface of 'foo'."
- "\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("DEFINE_SYMBOL", cmProperty::TARGET,
- "Define a symbol when compiling this target's sources.",
- "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when "
- "compiling sources in a shared library. "
- "If not set here then it is set to target_EXPORTS by default "
- "(with some substitutions if the target is not a valid C "
- "identifier). This is useful for headers to know whether they are "
- "being included from inside their library or outside to properly "
- "setup dllexport/dllimport decorations. ");
-
- cm->DefineProperty
- ("DEBUG_POSTFIX", cmProperty::TARGET,
- "See target property <CONFIG>_POSTFIX.",
- "This property is a special case of the more-general <CONFIG>_POSTFIX "
- "property for the DEBUG configuration.");
-
- cm->DefineProperty
- ("<CONFIG>_POSTFIX", cmProperty::TARGET,
- "Postfix to append to the target file name for configuration <CONFIG>.",
- "When building with configuration <CONFIG> the value of this property "
- "is appended to the target file name built on disk. "
- "For non-executable targets, this property is initialized by the value "
- "of the variable CMAKE_<CONFIG>_POSTFIX if it is set when a target is "
- "created. "
- "This property is ignored on the Mac for Frameworks and App Bundles.");
-
- cm->DefineProperty
- ("EchoString", cmProperty::TARGET,
- "A message to be displayed when the target is built.",
- "A message to display on some generators (such as makefiles) when "
- "the target is built.");
-
- cm->DefineProperty
- ("BUNDLE", cmProperty::TARGET,
- "This target is a CFBundle on the Mac.",
- "If a module library target has this property set to true it will "
- "be built as a CFBundle when built on the mac. It will have the "
- "directory structure required for a CFBundle and will be suitable "
- "to be used for creating Browser Plugins or other application "
- "resources.");
-
- cm->DefineProperty
- ("BUNDLE_EXTENSION", cmProperty::TARGET,
- "The file extension used to name a BUNDLE target on the Mac.",
- "The default value is \"bundle\" - you can also use \"plugin\" or "
- "whatever file extension is required by the host app for your "
- "bundle.");
-
- cm->DefineProperty
- ("EXCLUDE_FROM_DEFAULT_BUILD", cmProperty::TARGET,
- "Exclude target from \"Build Solution\".",
- "This property is only used by Visual Studio generators 7 and above. "
- "When set to TRUE, the target will not be built when you press "
- "\"Build Solution\".");
-
- cm->DefineProperty
- ("EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG>", cmProperty::TARGET,
- "Per-configuration version of target exclusion from \"Build Solution\". ",
- "This is the configuration-specific version of "
- "EXCLUDE_FROM_DEFAULT_BUILD. If the generic EXCLUDE_FROM_DEFAULT_BUILD "
- "is also set on a target, EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG> takes "
- "precedence in configurations for which it has a value.");
-
- cm->DefineProperty
- ("FRAMEWORK", cmProperty::TARGET,
- "This target is a framework on the Mac.",
- "If a shared library target has this property set to true it will "
- "be built as a framework when built on the mac. It will have the "
- "directory structure required for a framework and will be suitable "
- "to be used with the -framework option");
-
- cm->DefineProperty
- ("HAS_CXX", cmProperty::TARGET,
- "Link the target using the C++ linker tool (obsolete).",
- "This is equivalent to setting the LINKER_LANGUAGE property to CXX. "
- "See that property's documentation for details.");
-
- cm->DefineProperty
- ("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM", cmProperty::TARGET,
- "Specify #include line transforms for dependencies in a target.",
- "This property specifies rules to transform macro-like #include lines "
- "during implicit dependency scanning of C and C++ source files. "
- "The list of rules must be semicolon-separated with each entry of "
- "the form \"A_MACRO(%)=value-with-%\" (the % must be literal). "
- "During dependency scanning occurrences of A_MACRO(...) on #include "
- "lines will be replaced by the value given with the macro argument "
- "substituted for '%'. For example, the entry\n"
- " MYDIR(%)=<mydir/%>\n"
- "will convert lines of the form\n"
- " #include MYDIR(myheader.h)\n"
- "to\n"
- " #include <mydir/myheader.h>\n"
- "allowing the dependency to be followed.\n"
- "This property applies to sources in the target on which it is set.");
-
- cm->DefineProperty
- ("IMPORT_PREFIX", cmProperty::TARGET,
- "What comes before the import library name.",
- "Similar to the target property PREFIX, but used for import libraries "
- "(typically corresponding to a DLL) instead of regular libraries. "
- "A target property that can be set to override the prefix "
- "(such as \"lib\") on an import library name.");
-
- cm->DefineProperty
- ("IMPORT_SUFFIX", cmProperty::TARGET,
- "What comes after the import library name.",
- "Similar to the target property SUFFIX, but used for import libraries "
- "(typically corresponding to a DLL) instead of regular libraries. "
- "A target property that can be set to override the suffix "
- "(such as \".lib\") on an import library name.");
-
- cm->DefineProperty
- ("IMPORTED", cmProperty::TARGET,
- "Read-only indication of whether a target is IMPORTED.",
- "The boolean value of this property is true for targets created with "
- "the IMPORTED option to add_executable or add_library. "
- "It is false for targets built within the project.");
-
- cm->DefineProperty
- ("IMPORTED_CONFIGURATIONS", cmProperty::TARGET,
- "Configurations provided for an IMPORTED target.",
- "Set this to the list of configuration names available for an "
- "IMPORTED target. "
- "The names correspond to configurations defined in the project from "
- "which the target is imported. "
- "If the importing project uses a different set of configurations "
- "the names may be mapped using the MAP_IMPORTED_CONFIG_<CONFIG> "
- "property. "
- "Ignored for non-imported targets.");
-
- cm->DefineProperty
- ("IMPORTED_IMPLIB", cmProperty::TARGET,
- "Full path to the import library for an IMPORTED target.",
- "Set this to the location of the \".lib\" part of a windows DLL. "
- "Ignored for non-imported targets.");
-
- cm->DefineProperty
- ("IMPORTED_IMPLIB_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_IMPLIB property.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_DEPENDENT_LIBRARIES", cmProperty::TARGET,
- "Dependent shared libraries of an imported shared library.",
- "Shared libraries may be linked to other shared libraries as part "
- "of their implementation. On some platforms the linker searches "
- "for the dependent libraries of shared libraries they are including "
- "in the link. "
- "Set this property to the list of dependent shared libraries of an "
- "imported library. "
- "The list "
- "should be disjoint from the list of interface libraries in the "
- "INTERFACE_LINK_LIBRARIES property. On platforms requiring "
- "dependent shared libraries to be found at link time CMake uses this "
- "list to add appropriate files or paths to the link command line. "
- "Ignored for non-imported targets.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_DEPENDENT_LIBRARIES_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_LINK_DEPENDENT_LIBRARIES.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported. "
- "If set, this property completely overrides the generic property "
- "for the named configuration.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_INTERFACE_LIBRARIES", cmProperty::TARGET,
- "Transitive link interface of an IMPORTED target.",
- "Set this to the list of libraries whose interface is included when "
- "an IMPORTED library target is linked to another target. "
- "The libraries will be included on the link line for the target. "
- "Unlike the LINK_INTERFACE_LIBRARIES property, this property applies "
- "to all imported target types, including STATIC libraries. "
- "This property is ignored for non-imported targets.\n"
- "This property is ignored if the target also has a non-empty "
- "INTERFACE_LINK_LIBRARIES property.\n"
- "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_LINK_INTERFACE_LIBRARIES.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported. "
- "If set, this property completely overrides the generic property "
- "for the named configuration.\n"
- "This property is ignored if the target also has a non-empty "
- "INTERFACE_LINK_LIBRARIES property.\n"
- "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_INTERFACE_LANGUAGES", cmProperty::TARGET,
- "Languages compiled into an IMPORTED static library.",
- "Set this to the list of languages of source files compiled to "
- "produce a STATIC IMPORTED library (such as \"C\" or \"CXX\"). "
- "CMake accounts for these languages when computing how to link a "
- "target to the imported library. "
- "For example, when a C executable links to an imported C++ static "
- "library CMake chooses the C++ linker to satisfy language runtime "
- "dependencies of the static library. "
- "\n"
- "This property is ignored for targets that are not STATIC libraries. "
- "This property is ignored for non-imported targets.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_INTERFACE_LANGUAGES_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_LINK_INTERFACE_LANGUAGES.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported. "
- "If set, this property completely overrides the generic property "
- "for the named configuration.");
-
- cm->DefineProperty
- ("IMPORTED_LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
- "Repetition count for cycles of IMPORTED static libraries.",
- "This is LINK_INTERFACE_MULTIPLICITY for IMPORTED targets.");
- cm->DefineProperty
- ("IMPORTED_LINK_INTERFACE_MULTIPLICITY_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_LINK_INTERFACE_MULTIPLICITY.",
- "If set, this property completely overrides the generic property "
- "for the named configuration.");
-
- cm->DefineProperty
- ("IMPORTED_LOCATION", cmProperty::TARGET,
- "Full path to the main file on disk for an IMPORTED target.",
- "Set this to the location of an IMPORTED target file on disk. "
- "For executables this is the location of the executable file. "
- "For bundles on OS X this is the location of the executable file "
- "inside Contents/MacOS under the application bundle folder. "
- "For static libraries and modules this is the location of the "
- "library or module. "
- "For shared libraries on non-DLL platforms this is the location of "
- "the shared library. "
- "For frameworks on OS X this is the location of the library file "
- "symlink just inside the framework folder. "
- "For DLLs this is the location of the \".dll\" part of the library. "
- "For UNKNOWN libraries this is the location of the file to be linked. "
- "Ignored for non-imported targets."
- "\n"
- "Projects may skip IMPORTED_LOCATION if the configuration-specific "
- "property IMPORTED_LOCATION_<CONFIG> is set. "
- "To get the location of an imported target read one of the "
- "LOCATION or LOCATION_<CONFIG> properties.");
-
- cm->DefineProperty
- ("IMPORTED_LOCATION_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_LOCATION property.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported.");
-
- cm->DefineProperty
- ("IMPORTED_SONAME", cmProperty::TARGET,
- "The \"soname\" of an IMPORTED target of shared library type.",
- "Set this to the \"soname\" embedded in an imported shared library. "
- "This is meaningful only on platforms supporting the feature. "
- "Ignored for non-imported targets.");
-
- cm->DefineProperty
- ("IMPORTED_SONAME_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_SONAME property.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported.");
-
- cm->DefineProperty
- ("IMPORTED_NO_SONAME", cmProperty::TARGET,
- "Specifies that an IMPORTED shared library target has no \"soname\". ",
- "Set this property to true for an imported shared library file that "
- "has no \"soname\" field. "
- "CMake may adjust generated link commands for some platforms to prevent "
- "the linker from using the path to the library in place of its missing "
- "soname. "
- "Ignored for non-imported targets.");
-
- cm->DefineProperty
- ("IMPORTED_NO_SONAME_<CONFIG>", cmProperty::TARGET,
- "<CONFIG>-specific version of IMPORTED_NO_SONAME property.",
- "Configuration names correspond to those provided by the project "
- "from which the target is imported.");
-
- cm->DefineProperty
- ("EXCLUDE_FROM_ALL", cmProperty::TARGET,
- "Exclude the target from the all target.",
- "A property on a target that indicates if the target is excluded "
- "from the default build target. If it is not, then with a Makefile "
- "for example typing make will cause this target to be built. "
- "The same concept applies to the default build of other generators. "
- "Installing a target with EXCLUDE_FROM_ALL set to true has "
- "undefined behavior.");
-
- cm->DefineProperty
- ("LINK_LIBRARIES", cmProperty::TARGET,
- "List of direct link dependencies.",
- "This property specifies the list of libraries or targets which will be "
- "used for linking. "
- "In addition to accepting values from the target_link_libraries "
- "command, values may be set directly on any target using the "
- "set_property command. "
- "\n"
- "The target property values are used by the generators to set "
- "the link libraries for the compiler. "
- "See also the target_link_libraries command.\n"
- "Contents of LINK_LIBRARIES may use \"generator expressions\" with "
- "the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("INCLUDE_DIRECTORIES", cmProperty::TARGET,
- "List of preprocessor include file search directories.",
- "This property specifies the list of directories given "
- "so far to the include_directories command. "
- "This property exists on directories and targets. "
- "In addition to accepting values from the include_directories "
- "command, values may be set directly on any directory or any "
- "target using the set_property command. "
- "A target gets its initial value for this property from the value "
- "of the directory property. "
- "A directory gets its initial value from its parent directory if "
- "it has one. "
- "Both directory and target property values are adjusted by calls "
- "to the include_directories command."
- "\n"
- "The target property values are used by the generators to set "
- "the include paths for the compiler. "
- "See also the include_directories command.\n"
- "Contents of INCLUDE_DIRECTORIES may use \"generator expressions\" with "
- "the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("INSTALL_NAME_DIR", cmProperty::TARGET,
- "Mac OSX directory name for installed targets.",
- "INSTALL_NAME_DIR is a string specifying the "
- "directory portion of the \"install_name\" field of shared libraries "
- "on Mac OSX to use in the installed targets. ");
-
- cm->DefineProperty
- ("INSTALL_RPATH", cmProperty::TARGET,
- "The rpath to use for installed targets.",
- "A semicolon-separated list specifying the rpath "
- "to use in installed targets (for platforms that support it). "
- "This property is initialized by the value of the variable "
- "CMAKE_INSTALL_RPATH if it is set when a target is created.");
-
- cm->DefineProperty
- ("INSTALL_RPATH_USE_LINK_PATH", cmProperty::TARGET,
- "Add paths to linker search and installed rpath.",
- "INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true will "
- "append directories in the linker search path and outside the "
- "project to the INSTALL_RPATH. "
- "This property is initialized by the value of the variable "
- "CMAKE_INSTALL_RPATH_USE_LINK_PATH if it is set when a target is "
- "created.");
-
- cm->DefineProperty
- ("INTERPROCEDURAL_OPTIMIZATION", cmProperty::TARGET,
- "Enable interprocedural optimization for a target.",
- "If set to true, enables interprocedural optimizations "
- "if they are known to be supported by the compiler.");
-
- cm->DefineProperty
- ("INTERPROCEDURAL_OPTIMIZATION_<CONFIG>", cmProperty::TARGET,
- "Per-configuration interprocedural optimization for a target.",
- "This is a per-configuration version of INTERPROCEDURAL_OPTIMIZATION. "
- "If set, this property overrides the generic property "
- "for the named configuration.");
-
- cm->DefineProperty
- ("LABELS", cmProperty::TARGET,
- "Specify a list of text labels associated with a target.",
- "Target label semantics are currently unspecified.");
-
- cm->DefineProperty
- ("LINK_FLAGS", cmProperty::TARGET,
- "Additional flags to use when linking this target.",
- "The LINK_FLAGS property can be used to add extra flags to the "
- "link step of a target. LINK_FLAGS_<CONFIG> will add to the "
- "configuration <CONFIG>, "
- "for example, DEBUG, RELEASE, MINSIZEREL, RELWITHDEBINFO. ");
-
- cm->DefineProperty
- ("LINK_FLAGS_<CONFIG>", cmProperty::TARGET,
- "Per-configuration linker flags for a target.",
- "This is the configuration-specific version of LINK_FLAGS.");
-
-#define CM_LINK_SEARCH_SUMMARY \
- "Some linkers support switches such as -Bstatic and -Bdynamic " \
- "to determine whether to use static or shared libraries for -lXXX " \
- "options. CMake uses these options to set the link type for " \
- "libraries whose full paths are not known or (in some cases) are in " \
- "implicit link directories for the platform. "
-
- cm->DefineProperty
- ("LINK_SEARCH_START_STATIC", cmProperty::TARGET,
- "Assume the linker looks for static libraries by default.",
- CM_LINK_SEARCH_SUMMARY
- "By default the linker search type is assumed to be -Bdynamic at "
- "the beginning of the library list. This property switches the "
- "assumption to -Bstatic. It is intended for use when linking an "
- "executable statically (e.g. with the GNU -static option). "
- "See also LINK_SEARCH_END_STATIC.");
-
- cm->DefineProperty
- ("LINK_SEARCH_END_STATIC", cmProperty::TARGET,
- "End a link line such that static system libraries are used.",
- CM_LINK_SEARCH_SUMMARY
- "By default CMake adds an option at the end of the library list (if "
- "necessary) to set the linker search type back to its starting type. "
- "This property switches the final linker search type to -Bstatic "
- "regardless of how it started. "
- "See also LINK_SEARCH_START_STATIC.");
-
- cm->DefineProperty
- ("LINKER_LANGUAGE", cmProperty::TARGET,
- "Specifies language whose compiler will invoke the linker.",
- "For executables, shared libraries, and modules, this sets the "
- "language whose compiler is used to link the target "
- "(such as \"C\" or \"CXX\"). "
- "A typical value for an executable is the language of the source "
- "file providing the program entry point (main). "
- "If not set, the language with the highest linker preference "
- "value is the default. "
- "See documentation of CMAKE_<LANG>_LINKER_PREFERENCE variables."
- "\n"
- "If this property is not set by the user, it will be calculated at "
- "generate-time by CMake."
- );
-
- cm->DefineProperty
- ("LOCATION", cmProperty::TARGET,
- "Read-only location of a target on disk.",
- "For an imported target, this read-only property returns the value of "
- "the LOCATION_<CONFIG> property for an unspecified configuration "
- "<CONFIG> provided by the target.\n"
- "For a non-imported target, this property is provided for compatibility "
- "with CMake 2.4 and below. "
- "It was meant to get the location of an executable target's output file "
- "for use in add_custom_command. "
- "The path may contain a build-system-specific portion that "
- "is replaced at build time with the configuration getting built "
- "(such as \"$(ConfigurationName)\" in VS). "
- "In CMake 2.6 and above add_custom_command automatically recognizes a "
- "target name in its COMMAND and DEPENDS options and computes the "
- "target location. "
- "In CMake 2.8.4 and above add_custom_command recognizes generator "
- "expressions to refer to target locations anywhere in the command. "
- "Therefore this property is not needed for creating custom commands."
- CM_LOCATION_UNDEFINED_BEHAVIOR("reading this property"));
-
- cm->DefineProperty
- ("LOCATION_<CONFIG>", cmProperty::TARGET,
- "Read-only property providing a target location on disk.",
- "A read-only property that indicates where a target's main file is "
- "located on disk for the configuration <CONFIG>. "
- "The property is defined only for library and executable targets. "
- "An imported target may provide a set of configurations different "
- "from that of the importing project. "
- "By default CMake looks for an exact-match but otherwise uses an "
- "arbitrary available configuration. "
- "Use the MAP_IMPORTED_CONFIG_<CONFIG> property to map imported "
- "configurations explicitly."
- CM_LOCATION_UNDEFINED_BEHAVIOR("reading this property"));
-
- cm->DefineProperty
- ("LINK_DEPENDS", cmProperty::TARGET,
- "Additional files on which a target binary depends for linking.",
- "Specifies a semicolon-separated list of full-paths to files on which "
- "the link rule for this target depends. "
- "The target binary will be linked if any of the named files is newer "
- "than it."
- "\n"
- "This property is ignored by non-Makefile generators. "
- "It is intended to specify dependencies on \"linker scripts\" for "
- "custom Makefile link rules.");
-
- cm->DefineProperty
- ("LINK_DEPENDS_NO_SHARED", cmProperty::TARGET,
- "Do not depend on linked shared library files.",
- "Set this property to true to tell CMake generators not to add "
- "file-level dependencies on the shared library files linked by "
- "this target. "
- "Modification to the shared libraries will not be sufficient to "
- "re-link this target. "
- "Logical target-level dependencies will not be affected so the "
- "linked shared libraries will still be brought up to date before "
- "this target is built."
- "\n"
- "This property is initialized by the value of the variable "
- "CMAKE_LINK_DEPENDS_NO_SHARED if it is set when a target is "
- "created.");
-
- cm->DefineProperty
- ("LINK_INTERFACE_LIBRARIES", cmProperty::TARGET,
- "List public interface libraries for a shared library or executable.",
- "By default linking to a shared library target transitively "
- "links to targets with which the library itself was linked. "
- "For an executable with exports (see the ENABLE_EXPORTS property) "
- "no default transitive link dependencies are used. "
- "This property replaces the default transitive link dependencies with "
- "an explicit list. "
- "When the target is linked into another target the libraries "
- "listed (and recursively their link interface libraries) will be "
- "provided to the other target also. "
- "If the list is empty then no transitive link dependencies will be "
- "incorporated when this target is linked into another target even if "
- "the default set is non-empty. "
- "This property is initialized by the value of the variable "
- "CMAKE_LINK_INTERFACE_LIBRARIES if it is set when a target is "
- "created. "
- "This property is ignored for STATIC libraries.\n"
- "This property is overridden by the INTERFACE_LINK_LIBRARIES property if "
- "policy CMP0022 is NEW.\n"
- "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
-
- cm->DefineProperty
- ("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
- "Per-configuration list of public interface libraries for a target.",
- "This is the configuration-specific version of "
- "LINK_INTERFACE_LIBRARIES. "
- "If set, this property completely overrides the generic property "
- "for the named configuration.\n"
- "This property is overridden by the INTERFACE_LINK_LIBRARIES property if "
- "policy CMP0022 is NEW.\n"
- "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
-
- cm->DefineProperty
- ("INTERFACE_LINK_LIBRARIES", cmProperty::TARGET,
- "List public interface libraries for a library.",
- "This property contains the list of transitive link dependencies. "
- "When the target is linked into another target the libraries "
- "listed (and recursively their link interface libraries) will be "
- "provided to the other target also. "
- "This property is overridden by the LINK_INTERFACE_LIBRARIES or "
- "LINK_INTERFACE_LIBRARIES_<CONFIG> property if "
- "policy CMP0022 is OLD or unset.\n"
- "\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET,
- "List of public include directories for a library.",
- "Targets may populate this property to publish the include directories "
- "required to compile against the headers for the target. Consuming "
- "targets can add entries to their own INCLUDE_DIRECTORIES property such "
- "as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the "
- "include directories specified in the interface of 'foo'."
- "\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", cmProperty::TARGET,
- "List of public system include directories for a library.",
- "Targets may populate this property to publish the include directories "
- "which contain system headers, and therefore should not result in "
- "compiler warnings. Consuming targets will then mark the same include "
- "directories as system headers."
- "\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET,
- "List of public compile definitions for a library.",
- "Targets may populate this property to publish the compile definitions "
- "required to compile against the headers for the target. Consuming "
- "targets can add entries to their own COMPILE_DEFINITIONS property such "
- "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_DEFINITIONS> to use the "
- "compile definitions specified in the interface of 'foo'."
- "\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
-
- cm->DefineProperty
- ("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
- "Repetition count for STATIC libraries with cyclic dependencies.",
- "When linking to a STATIC library target with cyclic dependencies the "
- "linker may need to scan more than once through the archives in the "
- "strongly connected component of the dependency graph. "
- "CMake by default constructs the link line so that the linker will "
- "scan through the component at least twice. "
- "This property specifies the minimum number of scans if it is larger "
- "than the default. "
- "CMake uses the largest value specified by any target in a component.");
- cm->DefineProperty
- ("LINK_INTERFACE_MULTIPLICITY_<CONFIG>", cmProperty::TARGET,
- "Per-configuration repetition count for cycles of STATIC libraries.",
- "This is the configuration-specific version of "
- "LINK_INTERFACE_MULTIPLICITY. "
- "If set, this property completely overrides the generic property "
- "for the named configuration.");
-
- cm->DefineProperty
- ("MAP_IMPORTED_CONFIG_<CONFIG>", cmProperty::TARGET,
- "Map from project configuration to IMPORTED target's configuration.",
- "Set this to the list of configurations of an imported target that "
- "may be used for the current project's <CONFIG> configuration. "
- "Targets imported from another project may not provide the same set "
- "of configuration names available in the current project. "
- "Setting this property tells CMake what imported configurations are "
- "suitable for use when building the <CONFIG> configuration. "
- "The first configuration in the list found to be provided by the "
- "imported target is selected. If this property is set and no matching "
- "configurations are available, then the imported target is considered "
- "to be not found. This property is ignored for non-imported targets.",
- false /* TODO: make this chained */ );
-
- cm->DefineProperty
- ("OSX_ARCHITECTURES", cmProperty::TARGET,
- "Target specific architectures for OS X.",
- "The OSX_ARCHITECTURES property sets the target binary architecture "
- "for targets on OS X. "
- "This property is initialized by the value of the variable "
- "CMAKE_OSX_ARCHITECTURES if it is set when a target is created. "
- "Use OSX_ARCHITECTURES_<CONFIG> to set the binary architectures on a "
- "per-configuration basis. "
- "<CONFIG> is an upper-case name (ex: \"OSX_ARCHITECTURES_DEBUG\").");
-
- cm->DefineProperty
- ("OSX_ARCHITECTURES_<CONFIG>", cmProperty::TARGET,
- "Per-configuration OS X binary architectures for a target.",
- "This property is the configuration-specific version of "
- "OSX_ARCHITECTURES.");
-
- cm->DefineProperty
- ("NAME", cmProperty::TARGET,
- "Logical name for the target.",
- "Read-only logical name for the target as used by CMake.");
-
- cm->DefineProperty
- ("EXPORT_NAME", cmProperty::TARGET,
- "Exported name for target files.",
- "This sets the name for the IMPORTED target generated when it this "
- "target is is exported. "
- "If not set, the logical target name is used by default.");
-
- cm->DefineProperty
- ("OUTPUT_NAME", cmProperty::TARGET,
- "Output name for target files.",
- "This sets the base name for output files created for an executable or "
- "library target. "
- "If not set, the logical target name is used by default.");
-
- cm->DefineProperty
- ("OUTPUT_NAME_<CONFIG>", cmProperty::TARGET,
- "Per-configuration target file base name.",
- "This is the configuration-specific version of OUTPUT_NAME.");
-
- cm->DefineProperty
- ("ALIASED_TARGET", cmProperty::TARGET,
- "Name of target aliased by this target.",
- "If this is an ALIAS target, this property contains the name of the "
- "target aliased.");
-
- cm->DefineProperty
- ("<CONFIG>_OUTPUT_NAME", cmProperty::TARGET,
- "Old per-configuration target file base name.",
- "This is a configuration-specific version of OUTPUT_NAME. "
- "Use OUTPUT_NAME_<CONFIG> instead.");
-
- cm->DefineProperty
- ("PDB_NAME", cmProperty::TARGET,
- "Output name for MS debug symbols .pdb file from linker.",
- "Set the base name for debug symbols file created for an "
- "executable or shared library target. "
- "If not set, the logical target name is used by default. "
- "\n"
- "This property is not implemented by the Visual Studio 6 generator.");
-
- cm->DefineProperty
- ("PDB_NAME_<CONFIG>", cmProperty::TARGET,
- "Per-configuration name for MS debug symbols .pdb file. ",
- "This is the configuration-specific version of PDB_NAME. "
- "\n"
- "This property is not implemented by the Visual Studio 6 generator.");
-
- cm->DefineProperty
- ("PRE_INSTALL_SCRIPT", cmProperty::TARGET,
- "Deprecated install support.",
- "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
- "old way to specify CMake scripts to run before and after "
- "installing a target. They are used only when the old "
- "INSTALL_TARGETS command is used to install the target. Use the "
- "INSTALL command instead.");
-
- cm->DefineProperty
- ("PREFIX", cmProperty::TARGET,
- "What comes before the library name.",
- "A target property that can be set to override the prefix "
- "(such as \"lib\") on a library name.");
-
- cm->DefineProperty
- ("<LANG>_VISIBILITY_PRESET", cmProperty::TARGET,
- "Value for symbol visibility compile flags",
- "The <LANG>_VISIBILITY_PRESET property determines the value passed in "
- "a visibility related compile option, such as -fvisibility= for <LANG>. "
- "This property only has an affect for libraries and executables with "
- "exports. This property is initialized by the value of the variable "
- "CMAKE_<LANG>_VISIBILITY_PRESET if it is set when a target is created.");
-
- cm->DefineProperty
- ("VISIBILITY_INLINES_HIDDEN", cmProperty::TARGET,
- "Whether to add a compile flag to hide symbols of inline functions",
- "The VISIBILITY_INLINES_HIDDEN property determines whether a flag for "
- "hiding symbols for inline functions. the value passed used in "
- "a visibility related compile option, such as -fvisibility=. This "
- "property only has an affect for libraries and executables with "
- "exports. This property is initialized by the value of the variable "
- "CMAKE_VISIBILITY_INLINES_HIDDEN if it is set when a target is "
- "created.");
-
- cm->DefineProperty
- ("POSITION_INDEPENDENT_CODE", cmProperty::TARGET,
- "Whether to create a position-independent target",
- "The POSITION_INDEPENDENT_CODE property determines whether position "
- "independent executables or shared libraries will be created. "
- "This property is true by default for SHARED and MODULE library "
- "targets and false otherwise. "
- "This property is initialized by the value of the variable "
- "CMAKE_POSITION_INDEPENDENT_CODE if it is set when a target is "
- "created.");
-
- cm->DefineProperty
- ("INTERFACE_POSITION_INDEPENDENT_CODE", cmProperty::TARGET,
- "Whether consumers need to create a position-independent target",
- "The INTERFACE_POSITION_INDEPENDENT_CODE property informs consumers of "
- "this target whether they must set their POSITION_INDEPENDENT_CODE "
- "property to ON. If this property is set to ON, then the "
- "POSITION_INDEPENDENT_CODE property on all consumers will be set to "
- "ON. Similarly, if this property is set to OFF, then the "
- "POSITION_INDEPENDENT_CODE property on all consumers will be set to "
- "OFF. If this property is undefined, then consumers will determine "
- "their POSITION_INDEPENDENT_CODE property by other means. Consumers "
- "must ensure that the targets that they link to have a consistent "
- "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property.");
-
- cm->DefineProperty
- ("COMPATIBLE_INTERFACE_BOOL", cmProperty::TARGET,
- "Properties which must be compatible with their link interface",
- "The COMPATIBLE_INTERFACE_BOOL property may contain a list of properties"
- "for this target which must be consistent when evaluated as a boolean "
- "in the INTERFACE of all linked dependees. For example, if a "
- "property \"FOO\" appears in the list, then for each dependee, the "
- "\"INTERFACE_FOO\" property content in all of its dependencies must be "
- "consistent with each other, and with the \"FOO\" property in the "
- "dependee. Consistency in this sense has the meaning that if the "
- "property is set, then it must have the same boolean value as all "
- "others, and if the property is not set, then it is ignored. Note that "
- "for each dependee, the set of properties from this property must not "
- "intersect with the set of properties from the "
- "COMPATIBLE_INTERFACE_STRING property.");
-
- cm->DefineProperty
- ("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET,
- "Properties which must be string-compatible with their link interface",
- "The COMPATIBLE_INTERFACE_STRING property may contain a list of "
- "properties for this target which must be the same when evaluated as "
- "a string in the INTERFACE of all linked dependees. For example, "
- "if a property \"FOO\" appears in the list, then for each dependee, the "
- "\"INTERFACE_FOO\" property content in all of its dependencies must be "
- "equal with each other, and with the \"FOO\" property in the dependee. "
- "If the property is not set, then it is ignored. Note that for each "
- "dependee, the set of properties from this property must not intersect "
- "with the set of properties from the COMPATIBLE_INTERFACE_BOOL "
- "property.");
-
- cm->DefineProperty
- ("POST_INSTALL_SCRIPT", cmProperty::TARGET,
- "Deprecated install support.",
- "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
- "old way to specify CMake scripts to run before and after "
- "installing a target. They are used only when the old "
- "INSTALL_TARGETS command is used to install the target. Use the "
- "INSTALL command instead.");
-
- cm->DefineProperty
- ("PRIVATE_HEADER", cmProperty::TARGET,
- "Specify private header files in a FRAMEWORK shared library target.",
- "Shared library targets marked with the FRAMEWORK property generate "
- "frameworks on OS X and normal shared libraries on other platforms. "
- "This property may be set to a list of header files to be placed "
- "in the PrivateHeaders directory inside the framework folder. "
- "On non-Apple platforms these headers may be installed using the "
- "PRIVATE_HEADER option to the install(TARGETS) command.");
-
- cm->DefineProperty
- ("PUBLIC_HEADER", cmProperty::TARGET,
- "Specify public header files in a FRAMEWORK shared library target.",
- "Shared library targets marked with the FRAMEWORK property generate "
- "frameworks on OS X and normal shared libraries on other platforms. "
- "This property may be set to a list of header files to be placed "
- "in the Headers directory inside the framework folder. "
- "On non-Apple platforms these headers may be installed using the "
- "PUBLIC_HEADER option to the install(TARGETS) command.");
-
- cm->DefineProperty
- ("RESOURCE", cmProperty::TARGET,
- "Specify resource files in a FRAMEWORK shared library target.",
- "Shared library targets marked with the FRAMEWORK property generate "
- "frameworks on OS X and normal shared libraries on other platforms. "
- "This property may be set to a list of files to be placed "
- "in the Resources directory inside the framework folder. "
- "On non-Apple platforms these files may be installed using the "
- "RESOURCE option to the install(TARGETS) command.");
-
- cm->DefineProperty
- ("RULE_LAUNCH_COMPILE", cmProperty::TARGET,
- "Specify a launcher for compile rules.",
- "See the global property of the same name for details. "
- "This overrides the global and directory property for a target.",
- true);
- cm->DefineProperty
- ("RULE_LAUNCH_LINK", cmProperty::TARGET,
- "Specify a launcher for link rules.",
- "See the global property of the same name for details. "
- "This overrides the global and directory property for a target.",
- true);
- cm->DefineProperty
- ("RULE_LAUNCH_CUSTOM", cmProperty::TARGET,
- "Specify a launcher for custom rules.",
- "See the global property of the same name for details. "
- "This overrides the global and directory property for a target.",
- true);
-
- cm->DefineProperty
- ("SKIP_BUILD_RPATH", cmProperty::TARGET,
- "Should rpaths be used for the build tree.",
- "SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic "
- "generation of an rpath allowing the target to run from the "
- "build tree. "
- "This property is initialized by the value of the variable "
- "CMAKE_SKIP_BUILD_RPATH if it is set when a target is created.");
-
- cm->DefineProperty
- ("NO_SONAME", cmProperty::TARGET,
- "Whether to set \"soname\" when linking a shared library or module.",
- "Enable this boolean property if a generated shared library or module "
- "should not have \"soname\" set. Default is to set \"soname\" on all "
- "shared libraries and modules as long as the platform supports it. "
- "Generally, use this property only for leaf private libraries or "
- "plugins. If you use it on normal shared libraries which other targets "
- "link against, on some platforms a linker will insert a full path to "
- "the library (as specified at link time) into the dynamic section of "
- "the dependent binary. Therefore, once installed, dynamic loader may "
- "eventually fail to locate the library for the binary.");
-
- cm->DefineProperty
- ("SOVERSION", cmProperty::TARGET,
- "What version number is this target.",
- "For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and API version respectively. When building or "
- "installing appropriate symlinks are created if the platform "
- "supports symlinks and the linker supports so-names. "
- "If only one of both is specified the missing is assumed to have "
- "the same version number. "
- "SOVERSION is ignored if NO_SONAME property is set. "
- "For shared libraries and executables on Windows the VERSION "
- "attribute is parsed to extract a \"major.minor\" version number. "
- "These numbers are used as the image version of the binary. ");
-
- cm->DefineProperty
- ("STATIC_LIBRARY_FLAGS", cmProperty::TARGET,
- "Extra flags to use when linking static libraries.",
- "Extra flags to use when linking a static library.");
-
- cm->DefineProperty
- ("STATIC_LIBRARY_FLAGS_<CONFIG>", cmProperty::TARGET,
- "Per-configuration flags for creating a static library.",
- "This is the configuration-specific version of STATIC_LIBRARY_FLAGS.");
-
- cm->DefineProperty
- ("SUFFIX", cmProperty::TARGET,
- "What comes after the target name.",
- "A target property that can be set to override the suffix "
- "(such as \".so\" or \".exe\") on the name of a library, module or "
- "executable.");
-
- cm->DefineProperty
- ("TYPE", cmProperty::TARGET,
- "The type of the target.",
- "This read-only property can be used to test the type of the given "
- "target. It will be one of STATIC_LIBRARY, MODULE_LIBRARY, "
- "SHARED_LIBRARY, EXECUTABLE or one of the internal target types.");
-
- cm->DefineProperty
- ("VERSION", cmProperty::TARGET,
- "What version number is this target.",
- "For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and API version respectively. When building or "
- "installing appropriate symlinks are created if the platform "
- "supports symlinks and the linker supports so-names. "
- "If only one of both is specified the missing is assumed to have "
- "the same version number. "
- "For executables VERSION can be used to specify the build version. "
- "When building or installing appropriate symlinks are created if "
- "the platform supports symlinks. "
- "For shared libraries and executables on Windows the VERSION "
- "attribute is parsed to extract a \"major.minor\" version number. "
- "These numbers are used as the image version of the binary. ");
-
-
- cm->DefineProperty
- ("WIN32_EXECUTABLE", cmProperty::TARGET,
- "Build an executable with a WinMain entry point on windows.",
- "When this property is set to true the executable when linked "
- "on Windows will be created with a WinMain() entry point instead "
- "of just main(). "
- "This makes it a GUI executable instead of a console application. "
- "See the CMAKE_MFC_FLAG variable documentation to configure use "
- "of MFC for WinMain executables. "
- "This property is initialized by the value of the variable "
- "CMAKE_WIN32_EXECUTABLE if it is set when a target is created.");
-
- cm->DefineProperty
- ("MACOSX_BUNDLE", cmProperty::TARGET,
- "Build an executable as an application bundle on Mac OS X.",
- "When this property is set to true the executable when built "
- "on Mac OS X will be created as an application bundle. "
- "This makes it a GUI executable that can be launched from "
- "the Finder. "
- "See the MACOSX_BUNDLE_INFO_PLIST target property for information "
- "about creation of the Info.plist file for the application bundle. "
- "This property is initialized by the value of the variable "
- "CMAKE_MACOSX_BUNDLE if it is set when a target is created.");
-
- cm->DefineProperty
- ("MACOSX_BUNDLE_INFO_PLIST", cmProperty::TARGET,
- "Specify a custom Info.plist template for a Mac OS X App Bundle.",
- "An executable target with MACOSX_BUNDLE enabled will be built as an "
- "application bundle on Mac OS X. "
- "By default its Info.plist file is created by configuring a template "
- "called MacOSXBundleInfo.plist.in located in the CMAKE_MODULE_PATH. "
- "This property specifies an alternative template file name which "
- "may be a full path.\n"
- "The following target properties may be set to specify content to "
- "be configured into the file:\n"
- " MACOSX_BUNDLE_INFO_STRING\n"
- " MACOSX_BUNDLE_ICON_FILE\n"
- " MACOSX_BUNDLE_GUI_IDENTIFIER\n"
- " MACOSX_BUNDLE_LONG_VERSION_STRING\n"
- " MACOSX_BUNDLE_BUNDLE_NAME\n"
- " MACOSX_BUNDLE_SHORT_VERSION_STRING\n"
- " MACOSX_BUNDLE_BUNDLE_VERSION\n"
- " MACOSX_BUNDLE_COPYRIGHT\n"
- "CMake variables of the same name may be set to affect all targets "
- "in a directory that do not have each specific property set. "
- "If a custom Info.plist is specified by this property it may of course "
- "hard-code all the settings instead of using the target properties.");
-
- cm->DefineProperty
- ("MACOSX_FRAMEWORK_INFO_PLIST", cmProperty::TARGET,
- "Specify a custom Info.plist template for a Mac OS X Framework.",
- "A library target with FRAMEWORK enabled will be built as a "
- "framework on Mac OS X. "
- "By default its Info.plist file is created by configuring a template "
- "called MacOSXFrameworkInfo.plist.in located in the CMAKE_MODULE_PATH. "
- "This property specifies an alternative template file name which "
- "may be a full path.\n"
- "The following target properties may be set to specify content to "
- "be configured into the file:\n"
- " MACOSX_FRAMEWORK_ICON_FILE\n"
- " MACOSX_FRAMEWORK_IDENTIFIER\n"
- " MACOSX_FRAMEWORK_SHORT_VERSION_STRING\n"
- " MACOSX_FRAMEWORK_BUNDLE_VERSION\n"
- "CMake variables of the same name may be set to affect all targets "
- "in a directory that do not have each specific property set. "
- "If a custom Info.plist is specified by this property it may of course "
- "hard-code all the settings instead of using the target properties.");
-
- cm->DefineProperty
- ("MACOSX_RPATH", cmProperty::TARGET,
- "Whether to use rpaths on Mac OS X.",
- "When this property is set to true, the directory portion of the"
- "\"install_name\" field of shared libraries will default to \"@rpath\"."
- "Runtime paths will also be embedded in binaries using this target."
- "This property is initialized by the value of the variable "
- "CMAKE_MACOSX_RPATH if it is set when a target is created.");
-
- cm->DefineProperty
- ("ENABLE_EXPORTS", cmProperty::TARGET,
- "Specify whether an executable exports symbols for loadable modules.",
- "Normally an executable does not export any symbols because it is "
- "the final program. It is possible for an executable to export "
- "symbols to be used by loadable modules. When this property is "
- "set to true CMake will allow other targets to \"link\" to the "
- "executable with the TARGET_LINK_LIBRARIES command. "
- "On all platforms a target-level dependency on the executable is "
- "created for targets that link to it. "
- "For DLL platforms an import library will be created for the "
- "exported symbols and then used for linking. "
- "All Windows-based systems including Cygwin are DLL platforms. "
- "For non-DLL platforms that require all symbols to be resolved at "
- "link time, such as Mac OS X, the module will \"link\" to the "
- "executable using a flag like \"-bundle_loader\". "
- "For other non-DLL platforms the link rule is simply ignored since "
- "the dynamic loader will automatically bind symbols when the "
- "module is loaded. "
- );
-
- cm->DefineProperty
- ("Fortran_FORMAT", cmProperty::TARGET,
- "Set to FIXED or FREE to indicate the Fortran source layout.",
- "This property tells CMake whether the Fortran source files "
- "in a target use fixed-format or free-format. "
- "CMake will pass the corresponding format flag to the compiler. "
- "Use the source-specific Fortran_FORMAT property to change the "
- "format of a specific source file. "
- "If the variable CMAKE_Fortran_FORMAT is set when a target "
- "is created its value is used to initialize this property.");
-
- cm->DefineProperty
- ("Fortran_MODULE_DIRECTORY", cmProperty::TARGET,
- "Specify output directory for Fortran modules provided by the target.",
- "If the target contains Fortran source files that provide modules "
- "and the compiler supports a module output directory this specifies "
- "the directory in which the modules will be placed. "
- "When this property is not set the modules will be placed in the "
- "build directory corresponding to the target's source directory. "
- "If the variable CMAKE_Fortran_MODULE_DIRECTORY is set when a target "
- "is created its value is used to initialize this property."
- "\n"
- "Note that some compilers will automatically search the module output "
- "directory for modules USEd during compilation but others will not. "
- "If your sources USE modules their location must be specified by "
- "INCLUDE_DIRECTORIES regardless of this property.");
-
- cm->DefineProperty
- ("GNUtoMS", cmProperty::TARGET,
- "Convert GNU import library (.dll.a) to MS format (.lib).",
- "When linking a shared library or executable that exports symbols "
- "using GNU tools on Windows (MinGW/MSYS) with Visual Studio installed "
- "convert the import library (.dll.a) from GNU to MS format (.lib). "
- "Both import libraries will be installed by install(TARGETS) and "
- "exported by install(EXPORT) and export() to be linked by applications "
- "with either GNU- or MS-compatible tools."
- "\n"
- "If the variable CMAKE_GNUtoMS is set when a target "
- "is created its value is used to initialize this property. "
- "The variable must be set prior to the first command that enables "
- "a language such as project() or enable_language(). "
- "CMake provides the variable as an option to the user automatically "
- "when configuring on Windows with GNU tools.");
-
- cm->DefineProperty
- ("XCODE_ATTRIBUTE_<an-attribute>", cmProperty::TARGET,
- "Set Xcode target attributes directly.",
- "Tell the Xcode generator to set '<an-attribute>' to a given value "
- "in the generated Xcode project. Ignored on other generators.");
-
- cm->DefineProperty
- ("GENERATOR_FILE_NAME", cmProperty::TARGET,
- "Generator's file for this target.",
- "An internal property used by some generators to record the name of the "
- "project or dsp file associated with this target. Note that at configure "
- "time, this property is only set for targets created by "
- "include_external_msproject().");
-
- cm->DefineProperty
- ("SOURCES", cmProperty::TARGET,
- "Source names specified for a target.",
- "Read-only list of sources specified for a target. "
- "The names returned are suitable for passing to the "
- "set_source_files_properties command.");
-
- cm->DefineProperty
- ("FOLDER", cmProperty::TARGET,
- "Set the folder name. Use to organize targets in an IDE.",
- "Targets with no FOLDER property will appear as top level "
- "entities in IDEs like Visual Studio. Targets with the same "
- "FOLDER property value will appear next to each other in a "
- "folder of that name. To nest folders, use FOLDER values such "
- "as 'GUI/Dialogs' with '/' characters separating folder levels.");
-
- cm->DefineProperty
- ("PROJECT_LABEL", cmProperty::TARGET,
- "Change the name of a target in an IDE.",
- "Can be used to change the name of the target in an IDE "
- "like Visual Studio. ");
- cm->DefineProperty
- ("VS_KEYWORD", cmProperty::TARGET,
- "Visual Studio project keyword.",
- "Can be set to change the visual studio keyword, for example "
- "Qt integration works better if this is set to Qt4VSv1.0. ");
- cm->DefineProperty
- ("VS_SCC_PROVIDER", cmProperty::TARGET,
- "Visual Studio Source Code Control Provider.",
- "Can be set to change the visual studio source code control "
- "provider property.");
- cm->DefineProperty
- ("VS_SCC_LOCALPATH", cmProperty::TARGET,
- "Visual Studio Source Code Control Local Path.",
- "Can be set to change the visual studio source code control "
- "local path property.");
- cm->DefineProperty
- ("VS_SCC_PROJECTNAME", cmProperty::TARGET,
- "Visual Studio Source Code Control Project.",
- "Can be set to change the visual studio source code control "
- "project name property.");
- cm->DefineProperty
- ("VS_SCC_AUXPATH", cmProperty::TARGET,
- "Visual Studio Source Code Control Aux Path.",
- "Can be set to change the visual studio source code control "
- "auxpath property.");
- cm->DefineProperty
- ("VS_GLOBAL_PROJECT_TYPES", cmProperty::TARGET,
- "Visual Studio project type(s).",
- "Can be set to one or more UUIDs recognized by Visual Studio "
- "to indicate the type of project. This value is copied "
- "verbatim into the generated project file. Example for a "
- "managed C++ unit testing project:\n"
- " {3AC096D0-A1C2-E12C-1390-A8335801FDAB};"
- "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\n"
- "UUIDs are semicolon-delimited.");
- cm->DefineProperty
- ("VS_GLOBAL_KEYWORD", cmProperty::TARGET,
- "Visual Studio project keyword.",
- "Sets the \"keyword\" attribute for a generated Visual Studio "
- "project. Defaults to \"Win32Proj\". You may wish to override "
- "this value with \"ManagedCProj\", for example, in a Visual "
- "Studio managed C++ unit test project.");
- cm->DefineProperty
- ("VS_GLOBAL_ROOTNAMESPACE", cmProperty::TARGET,
- "Visual Studio project root namespace.",
- "Sets the \"RootNamespace\" attribute for a generated Visual Studio "
- "project. The attribute will be generated only if this is set.");
- cm->DefineProperty
- ("VS_DOTNET_TARGET_FRAMEWORK_VERSION", cmProperty::TARGET,
- "Specify the .NET target framework version.",
- "Used to specify the .NET target framework version for C++/CLI. "
- "For example, \"v4.5\".");
- cm->DefineProperty
- ("VS_DOTNET_REFERENCES", cmProperty::TARGET,
- "Visual Studio managed project .NET references",
- "Adds one or more semicolon-delimited .NET references to a "
- "generated Visual Studio project. For example, \"System;"
- "System.Windows.Forms\".");
- cm->DefineProperty
- ("VS_WINRT_EXTENSIONS", cmProperty::TARGET,
- "Visual Studio project C++/CX language extensions for Windows Runtime",
- "Can be set to enable C++/CX language extensions.");
- cm->DefineProperty
- ("VS_WINRT_REFERENCES", cmProperty::TARGET,
- "Visual Studio project Windows Runtime Metadata references",
- "Adds one or more semicolon-delimited WinRT references to a "
- "generated Visual Studio project. For example, \"Windows;"
- "Windows.UI.Core\".");
- cm->DefineProperty
- ("VS_GLOBAL_<variable>", cmProperty::TARGET,
- "Visual Studio project-specific global variable.",
- "Tell the Visual Studio generator to set the global variable "
- "'<variable>' to a given value in the generated Visual Studio "
- "project. Ignored on other generators. Qt integration works "
- "better if VS_GLOBAL_QtVersion is set to the version "
- "FindQt4.cmake found. For example, \"4.7.3\"");
-
-#define CM_TARGET_FILE_TYPES_DOC \
- "There are three kinds of target files that may be built: " \
- "archive, library, and runtime. " \
- "Executables are always treated as runtime targets. " \
- "Static libraries are always treated as archive targets. " \
- "Module libraries are always treated as library targets. " \
- "For non-DLL platforms shared libraries are treated as library " \
- "targets. " \
- "For DLL platforms the DLL part of a shared library is treated as " \
- "a runtime target and the corresponding import library is treated as " \
- "an archive target. " \
- "All Windows-based systems including Cygwin are DLL platforms."
-
-#define CM_TARGET_OUTDIR_DOC(TYPE, type) \
- "This property specifies the directory into which " #type " target " \
- "files should be built. " \
- "Multi-configuration generators (VS, Xcode) append " \
- "a per-configuration subdirectory to the specified directory. " \
- CM_TARGET_FILE_TYPES_DOC " " \
- "This property is initialized by the value of the variable " \
- "CMAKE_" #TYPE "_OUTPUT_DIRECTORY if it is set when a target is created."
-
-#define CM_TARGET_OUTDIR_CONFIG_DOC(TYPE) \
- "This is a per-configuration version of " #TYPE "_OUTPUT_DIRECTORY, " \
- "but multi-configuration generators (VS, Xcode) do NOT append " \
- "a per-configuration subdirectory to the specified directory. " \
- "This property is initialized by the value of the variable " \
- "CMAKE_" #TYPE "_OUTPUT_DIRECTORY_<CONFIG> " \
- "if it is set when a target is created."
-
- cm->DefineProperty
- ("ARCHIVE_OUTPUT_DIRECTORY", cmProperty::TARGET,
- "Output directory in which to build ARCHIVE target files.",
- CM_TARGET_OUTDIR_DOC(ARCHIVE, archive));
- cm->DefineProperty
- ("ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output directory for ARCHIVE target files.",
- CM_TARGET_OUTDIR_CONFIG_DOC(ARCHIVE));
- cm->DefineProperty
- ("LIBRARY_OUTPUT_DIRECTORY", cmProperty::TARGET,
- "Output directory in which to build LIBRARY target files.",
- CM_TARGET_OUTDIR_DOC(LIBRARY, library));
- cm->DefineProperty
- ("LIBRARY_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output directory for LIBRARY target files.",
- CM_TARGET_OUTDIR_CONFIG_DOC(LIBRARY));
- cm->DefineProperty
- ("RUNTIME_OUTPUT_DIRECTORY", cmProperty::TARGET,
- "Output directory in which to build RUNTIME target files.",
- CM_TARGET_OUTDIR_DOC(RUNTIME, runtime));
- cm->DefineProperty
- ("RUNTIME_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output directory for RUNTIME target files.",
- CM_TARGET_OUTDIR_CONFIG_DOC(RUNTIME));
-
- cm->DefineProperty
- ("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET,
- "Output directory for MS debug symbols .pdb file from linker.",
- "This property specifies the directory into which the MS debug symbols "
- "will be placed by the linker. "
- "This property is initialized by the value of the variable "
- "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created."
- "\n"
- "This property is not implemented by the Visual Studio 6 generator.");
- cm->DefineProperty
- ("PDB_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output directory for MS debug symbols .pdb files.",
- "This is a per-configuration version of PDB_OUTPUT_DIRECTORY, "
- "but multi-configuration generators (VS, Xcode) do NOT append "
- "a per-configuration subdirectory to the specified directory. "
- "This property is initialized by the value of the variable "
- "CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG> "
- "if it is set when a target is created."
- "\n"
- "This property is not implemented by the Visual Studio 6 generator.");
-
- cm->DefineProperty
- ("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET,
- "Output name for ARCHIVE target files.",
- "This property specifies the base name for archive target files. "
- "It overrides OUTPUT_NAME and OUTPUT_NAME_<CONFIG> properties. "
- CM_TARGET_FILE_TYPES_DOC);
- cm->DefineProperty
- ("ARCHIVE_OUTPUT_NAME_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output name for ARCHIVE target files.",
- "This is the configuration-specific version of ARCHIVE_OUTPUT_NAME.");
- cm->DefineProperty
- ("LIBRARY_OUTPUT_NAME", cmProperty::TARGET,
- "Output name for LIBRARY target files.",
- "This property specifies the base name for library target files. "
- "It overrides OUTPUT_NAME and OUTPUT_NAME_<CONFIG> properties. "
- CM_TARGET_FILE_TYPES_DOC);
- cm->DefineProperty
- ("LIBRARY_OUTPUT_NAME_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output name for LIBRARY target files.",
- "This is the configuration-specific version of LIBRARY_OUTPUT_NAME.");
- cm->DefineProperty
- ("RUNTIME_OUTPUT_NAME", cmProperty::TARGET,
- "Output name for RUNTIME target files.",
- "This property specifies the base name for runtime target files. "
- "It overrides OUTPUT_NAME and OUTPUT_NAME_<CONFIG> properties. "
- CM_TARGET_FILE_TYPES_DOC);
- cm->DefineProperty
- ("RUNTIME_OUTPUT_NAME_<CONFIG>", cmProperty::TARGET,
- "Per-configuration output name for RUNTIME target files.",
- "This is the configuration-specific version of RUNTIME_OUTPUT_NAME.");
-}
-
-void cmTarget::SetType(TargetType type, const char* name)
-{
- this->Name = name;
// only add dependency information for library targets
- this->TargetTypeValue = type;
- if(this->TargetTypeValue >= STATIC_LIBRARY
- && this->TargetTypeValue <= MODULE_LIBRARY)
- {
+ if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
+ this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY) {
this->RecordDependencies = true;
- }
- else
- {
+ } else {
this->RecordDependencies = false;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::SetMakefile(cmMakefile* mf)
-{
- // Set our makefile.
- this->Makefile = mf;
-
- // set the cmake instance of the properties
- this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
+ }
// Check whether this is a DLL platform.
- this->DLLPlatform = (this->Makefile->IsOn("WIN32") ||
- this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ this->DLLPlatform =
+ (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
+ this->Makefile->IsOn("MINGW"));
- // Check whether we are targeting an Apple platform.
- this->IsApple = this->Makefile->IsOn("APPLE");
+ // Check whether we are targeting an Android platform.
+ this->IsAndroid =
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"),
+ "Android") == 0;
// Setup default property values.
- this->SetPropertyDefault("INSTALL_NAME_DIR", 0);
- this->SetPropertyDefault("INSTALL_RPATH", "");
- this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
- this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
- this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
- this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
- this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
- this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
- this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
- this->SetPropertyDefault("Fortran_FORMAT", 0);
- this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
- this->SetPropertyDefault("GNUtoMS", 0);
- this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
- this->SetPropertyDefault("AUTOMOC", 0);
- this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
- this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0);
- this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
- this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
- this->SetPropertyDefault("MACOSX_BUNDLE", 0);
- this->SetPropertyDefault("MACOSX_RPATH", 0);
+ 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);
+ }
+ if (this->GetType() != cmStateEnums::UTILITY) {
+ this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", CM_NULLPTR);
+ }
// Collect the set of configuration types.
std::vector<std::string> configNames;
mf->GetConfigurations(configNames);
// Setup per-configuration property default values.
- const char* configProps[] = {
- "ARCHIVE_OUTPUT_DIRECTORY_",
- "LIBRARY_OUTPUT_DIRECTORY_",
- "RUNTIME_OUTPUT_DIRECTORY_",
- "PDB_OUTPUT_DIRECTORY_",
- 0};
- 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)
- {
- std::string property = *p;
- property += configUpper;
- this->SetPropertyDefault(property.c_str(), 0);
+ if (this->GetType() != cmStateEnums::UTILITY) {
+ const char* 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
+ };
+ 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) {
+ // Interface libraries have no output locations, so honor only
+ // the configuration map.
+ if (this->TargetTypeValue == cmStateEnums::INTERFACE_LIBRARY &&
+ strcmp(*p, "MAP_IMPORTED_CONFIG_") != 0) {
+ continue;
+ }
+ std::string property = *p;
+ property += configUpper;
+ this->SetPropertyDefault(property, CM_NULLPTR);
}
- // Initialize per-configuration name postfix property from the
- // variable only for non-executable targets. This preserves
- // compatibility with previous CMake versions in which executables
- // did not support this variable. Projects may still specify the
- // property directly. TODO: Make this depend on backwards
- // compatibility setting.
- if(this->TargetTypeValue != cmTarget::EXECUTABLE)
- {
- std::string property = cmSystemTools::UpperCase(*ci);
- property += "_POSTFIX";
- this->SetPropertyDefault(property.c_str(), 0);
+ // Initialize per-configuration name postfix property from the
+ // variable only for non-executable targets. This preserves
+ // 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);
}
}
+ }
// Save the backtrace of target construction.
- this->Makefile->GetBacktrace(this->Internal->Backtrace);
-
- // Initialize the INCLUDE_DIRECTORIES property based on the current value
- // of the same directory property:
- const std::vector<cmValueWithOrigin> parentIncludes =
- this->Makefile->GetIncludeDirectoriesEntries();
-
- for (std::vector<cmValueWithOrigin>::const_iterator it
- = parentIncludes.begin(); it != parentIncludes.end(); ++it)
- {
- this->InsertInclude(*it);
- }
-
- const std::set<cmStdString> parentSystemIncludes =
- this->Makefile->GetSystemIncludeDirectories();
-
- for (std::set<cmStdString>::const_iterator it
- = parentSystemIncludes.begin();
- it != parentSystemIncludes.end(); ++it)
- {
- this->SystemIncludeDirectories.insert(*it);
- }
-
- const std::vector<cmValueWithOrigin> parentOptions =
- this->Makefile->GetCompileOptionsEntries();
-
- for (std::vector<cmValueWithOrigin>::const_iterator it
- = parentOptions.begin(); it != parentOptions.end(); ++it)
- {
- this->InsertCompileOption(*it);
- }
+ this->Backtrace = this->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();
+
+ this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(),
+ parentSystemIncludes.end());
+
+ const cmStringRange parentOptions =
+ this->Makefile->GetCompileOptionsEntries();
+ const cmBacktraceRange parentOptionsBts =
+ this->Makefile->GetCompileOptionsBacktraces();
+
+ this->Internal->CompileOptionsEntries.insert(
+ this->Internal->CompileOptionsEntries.end(), parentOptions.begin(),
+ parentOptions.end());
+ this->Internal->CompileOptionsBacktraces.insert(
+ this->Internal->CompileOptionsBacktraces.end(), parentOptionsBts.begin(),
+ parentOptionsBts.end());
+ }
- this->SetPropertyDefault("C_VISIBILITY_PRESET", 0);
- this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0);
- this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0);
+ 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);
+ }
- if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
- || this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
- {
+ if (this->TargetTypeValue == cmStateEnums::EXECUTABLE) {
+ this->SetPropertyDefault("ANDROID_GUI", CM_NULLPTR);
+ this->SetPropertyDefault("CROSSCOMPILING_EMULATOR", CM_NULLPTR);
+ this->SetPropertyDefault("ENABLE_EXPORTS", CM_NULLPTR);
+ }
+ if (this->TargetTypeValue == cmStateEnums::SHARED_LIBRARY ||
+ this->TargetTypeValue == cmStateEnums::MODULE_LIBRARY) {
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
- }
- this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
+ }
+ if (this->TargetTypeValue == cmStateEnums::SHARED_LIBRARY ||
+ this->TargetTypeValue == cmStateEnums::EXECUTABLE) {
+ this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", CM_NULLPTR);
+ }
- // Record current policies for later use.
-#define CAPTURE_TARGET_POLICY(POLICY) \
- this->PolicyStatus ## POLICY = \
- this->Makefile->GetPolicyStatus(cmPolicies::POLICY);
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ this->GetType() != cmStateEnums::UTILITY) {
+ this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", CM_NULLPTR);
+ }
- CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY)
+ // Record current policies for later use.
+ this->Makefile->RecordPolicies(this->PolicyMap);
+
+ if (this->TargetTypeValue == 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);
+ }
-#undef CAPTURE_TARGET_POLICY
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ this->GetType() != cmStateEnums::UTILITY) {
+ this->SetPropertyDefault("JOB_POOL_COMPILE", CM_NULLPTR);
+ this->SetPropertyDefault("JOB_POOL_LINK", CM_NULLPTR);
+ }
}
-//----------------------------------------------------------------------------
-void cmTarget::FinishConfigure()
+cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
- // Erase any cached link information that might have been comptued
- // on-demand during the configuration. This ensures that build
- // system generation uses up-to-date information even if other cache
- // invalidation code in this source file is buggy.
- this->ClearLinkMaps();
-
- // Do old-style link dependency analysis.
- this->AnalyzeLibDependencies(*this->Makefile);
+ return this->GetMakefile()->GetGlobalGenerator();
}
-//----------------------------------------------------------------------------
-void cmTarget::ClearLinkMaps()
+void cmTarget::AddUtility(const std::string& u, cmMakefile* makefile)
{
- this->Internal->LinkImplMap.clear();
- this->Internal->LinkInterfaceMap.clear();
- this->Internal->LinkClosureMap.clear();
- for (cmTargetLinkInformationMap::const_iterator it
- = this->LinkInformation.begin();
- it != this->LinkInformation.end(); ++it)
- {
- delete it->second;
- }
- this->LinkInformation.clear();
+ if (this->Utilities.insert(u).second && makefile) {
+ this->UtilityBacktraces.insert(
+ std::make_pair(u, makefile->GetBacktrace()));
+ }
}
-//----------------------------------------------------------------------------
-cmListFileBacktrace const& cmTarget::GetBacktrace() const
+cmListFileBacktrace const* cmTarget::GetUtilityBacktrace(
+ const std::string& u) const
{
- return this->Internal->Backtrace;
-}
+ std::map<std::string, cmListFileBacktrace>::const_iterator i =
+ this->UtilityBacktraces.find(u);
+ if (i == this->UtilityBacktraces.end()) {
+ return CM_NULLPTR;
+ }
-//----------------------------------------------------------------------------
-std::string cmTarget::GetSupportDirectory() const
-{
- std::string dir = this->Makefile->GetCurrentOutputDirectory();
- dir += cmake::GetCMakeFilesDirectory();
- dir += "/";
- dir += this->Name;
-#if defined(__VMS)
- dir += "_dir";
-#else
- dir += ".dir";
-#endif
- return dir;
+ return &i->second;
}
-//----------------------------------------------------------------------------
-bool cmTarget::IsExecutableWithExports()
+cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
- return (this->GetType() == cmTarget::EXECUTABLE &&
- this->GetPropertyAsBool("ENABLE_EXPORTS"));
+ return this->Backtrace;
}
-//----------------------------------------------------------------------------
-bool cmTarget::IsLinkable()
+bool cmTarget::IsExecutableWithExports() const
{
- return (this->GetType() == cmTarget::STATIC_LIBRARY ||
- this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY ||
- this->GetType() == cmTarget::UNKNOWN_LIBRARY ||
- this->IsExecutableWithExports());
+ return (this->GetType() == cmStateEnums::EXECUTABLE &&
+ this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
-//----------------------------------------------------------------------------
-bool cmTarget::HasImportLibrary()
+bool cmTarget::HasImportLibrary() const
{
return (this->DLLPlatform &&
- (this->GetType() == cmTarget::SHARED_LIBRARY ||
+ (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()));
}
-//----------------------------------------------------------------------------
-bool cmTarget::IsFrameworkOnApple()
+bool cmTarget::IsFrameworkOnApple() const
{
- return (this->GetType() == cmTarget::SHARED_LIBRARY &&
+ return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
this->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("FRAMEWORK"));
}
-//----------------------------------------------------------------------------
-bool cmTarget::IsAppBundleOnApple()
+bool cmTarget::IsAppBundleOnApple() const
{
- return (this->GetType() == cmTarget::EXECUTABLE &&
+ return (this->GetType() == cmStateEnums::EXECUTABLE &&
this->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("MACOSX_BUNDLE"));
}
-//----------------------------------------------------------------------------
-bool cmTarget::IsCFBundleOnApple()
-{
- return (this->GetType() == cmTarget::MODULE_LIBRARY &&
- this->Makefile->IsOn("APPLE") &&
- this->GetPropertyAsBool("BUNDLE"));
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::IsBundleOnApple()
-{
- return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
- this->IsCFBundleOnApple();
-}
-
-//----------------------------------------------------------------------------
-class cmTargetTraceDependencies
+void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
-public:
- cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal);
- void Trace();
-private:
- cmTarget* Target;
- cmTargetInternals* Internal;
- cmMakefile* Makefile;
- cmGlobalGenerator* GlobalGenerator;
- typedef cmTargetInternals::SourceEntry SourceEntry;
- SourceEntry* CurrentEntry;
- std::queue<cmSourceFile*> SourceQueue;
- std::set<cmSourceFile*> SourcesQueued;
- typedef std::map<cmStdString, cmSourceFile*> NameMapType;
- NameMapType NameMap;
-
- void QueueSource(cmSourceFile* sf);
- void FollowName(std::string const& name);
- void FollowNames(std::vector<std::string> const& names);
- bool IsUtility(std::string const& dep);
- void CheckCustomCommand(cmCustomCommand const& cc);
- void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
-};
-
-//----------------------------------------------------------------------------
-cmTargetTraceDependencies
-::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal):
- Target(target), Internal(internal)
-{
- // Convenience.
- this->Makefile = this->Target->GetMakefile();
- this->GlobalGenerator =
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
- this->CurrentEntry = 0;
-
- // Queue all the source files already specified for the target.
- std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); ++si)
- {
- this->QueueSource(*si);
- }
-
- // Queue pre-build, pre-link, and post-build rule dependencies.
- this->CheckCustomCommands(this->Target->GetPreBuildCommands());
- this->CheckCustomCommands(this->Target->GetPreLinkCommands());
- this->CheckCustomCommands(this->Target->GetPostBuildCommands());
-}
-
-//----------------------------------------------------------------------------
-void cmTargetTraceDependencies::Trace()
-{
- // Process one dependency at a time until the queue is empty.
- while(!this->SourceQueue.empty())
- {
- // Get the next source from the queue.
- cmSourceFile* sf = this->SourceQueue.front();
- this->SourceQueue.pop();
- this->CurrentEntry = &this->Internal->SourceEntries[sf];
-
- // Queue dependencies added explicitly by the user.
- if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
- {
- std::vector<std::string> objDeps;
- cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
- this->FollowNames(objDeps);
- }
-
- // Queue the source needed to generate this file, if any.
- this->FollowName(sf->GetFullPath());
-
- // Queue dependencies added programatically by commands.
- this->FollowNames(sf->GetDepends());
-
- // Queue custom command dependencies.
- if(cmCustomCommand const* cc = sf->GetCustomCommand())
- {
- this->CheckCustomCommand(*cc);
- }
- }
- this->CurrentEntry = 0;
-}
-
-//----------------------------------------------------------------------------
-void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
-{
- if(this->SourcesQueued.insert(sf).second)
- {
- this->SourceQueue.push(sf);
-
- // Make sure this file is in the target.
- this->Target->AddSourceFile(sf);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmTargetTraceDependencies::FollowName(std::string const& name)
-{
- NameMapType::iterator i = this->NameMap.find(name);
- if(i == this->NameMap.end())
- {
- // Check if we know how to generate this file.
- cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str());
- 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);
- }
-
- 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);
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
-{
- // Dependencies on targets (utilities) are supposed to be named by
- // just the target name. However for compatibility we support
- // naming the output file generated by the target (assuming there is
- // no output-name property which old code would not have set). In
- // that case the target name will be the file basename of the
- // dependency.
- std::string util = cmSystemTools::GetFilenameName(dep);
- if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
- {
- util = cmSystemTools::GetFilenameWithoutLastExtension(util);
- }
-
- // Check for a target with this name.
- if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str()))
- {
- // 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(t->GetType() >= cmTarget::EXECUTABLE &&
- t->GetType() <= cmTarget::MODULE_LIBRARY)
- {
- // This is really only for compatibility so we do not need to
- // worry about configuration names and output names.
- std::string tLocation = t->GetLocation(0);
- tLocation = cmSystemTools::GetFilenamePath(tLocation);
- std::string depLocation = cmSystemTools::GetFilenamePath(dep);
- depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
- tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
- if(depLocation == tLocation)
- {
- this->Target->AddUtility(util.c_str());
- return true;
- }
- }
- }
- else
- {
- // The original name of the dependency was not a full path. It
- // must name a target, so add the target-level dependency.
- this->Target->AddUtility(util.c_str());
- return true;
- }
- }
-
- // The dependency does not name a target built in this project.
- return false;
+ if (!srcs.empty()) {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->SourceEntries.push_back(cmJoin(srcs, ";"));
+ this->Internal->SourceBacktraces.push_back(lfbt);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmTargetTraceDependencies
-::CheckCustomCommand(cmCustomCommand const& cc)
+void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
- // Transform command names that reference targets built in this
- // project to corresponding target-level dependencies.
- cmGeneratorExpression ge(cc.GetBacktrace());
-
- // Add target-level dependencies referenced by generator expressions.
- std::set<cmTarget*> targets;
-
- for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
- cit != cc.GetCommandLines().end(); ++cit)
- {
- std::string const& command = *cit->begin();
- // Check for a target with this name.
- if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str()))
- {
- if(t->GetType() == cmTarget::EXECUTABLE)
- {
- // The command refers to an executable target built in
- // this project. Add the target-level dependency to make
- // sure the executable is up to date before this custom
- // command possibly runs.
- this->Target->AddUtility(command.c_str());
- }
- }
-
- // Check for target references in generator expressions.
- for(cmCustomCommandLine::const_iterator cli = cit->begin();
- cli != cit->end(); ++cli)
- {
- const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
- = ge.Parse(*cli);
- cge->Evaluate(this->Makefile, 0, true);
- std::set<cmTarget*> geTargets = cge->GetTargets();
- for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
- it != geTargets.end(); ++it)
- {
- targets.insert(*it);
+ 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] == '<')) {
+ if (!filename.empty()) {
+ filename = this->ProcessSourceItemCMP0049(filename);
+ if (filename.empty()) {
+ return;
}
}
+ this->Makefile->GetOrCreateSource(filename);
}
-
- for(std::set<cmTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ++ti)
- {
- this->Target->AddUtility((*ti)->GetName());
- }
-
- // Queue the custom command dependencies.
- std::vector<std::string> const& depends = cc.GetDepends();
- for(std::vector<std::string>::const_iterator di = depends.begin();
- di != depends.end(); ++di)
- {
- std::string const& dep = *di;
- if(!this->IsUtility(dep))
- {
- // The dependency does not name a target and may be a file we
- // know how to generate. Queue it.
- this->FollowName(dep);
- }
- }
+ 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);
+ }
}
-//----------------------------------------------------------------------------
-void
-cmTargetTraceDependencies
-::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
+std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
{
- for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
- cli != commands.end(); ++cli)
- {
- this->CheckCustomCommand(*cli);
- }
-}
+ std::string src = s;
-//----------------------------------------------------------------------------
-void cmTarget::TraceDependencies()
-{
- // CMake-generated targets have no dependencies to trace. Normally tracing
- // would find nothing anyway, but when building CMake itself the "install"
- // target command ends up referencing the "cmake" target but we do not
- // really want the dependency because "install" depend on "all" anyway.
- if(this->GetType() == cmTarget::GLOBAL_TARGET)
- {
- return;
+ // For backwards compatibility replace varibles 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;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n";
+ break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ messageType = cmake::FATAL_ERROR;
}
-
- // Use a helper object to trace the dependencies.
- cmTargetTraceDependencies tracer(this, this->Internal.Get());
- tracer.Trace();
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::FindSourceFiles()
-{
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->SourceFiles.begin();
- si != this->SourceFiles.end(); ++si)
- {
- std::string e;
- if((*si)->GetFullPath(&e).empty())
- {
- if(!e.empty())
- {
- cmake* cm = this->Makefile->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e,
- this->GetBacktrace());
- }
- return false;
+ if (!noMessage) {
+ e << "Legacy variable expansion in source file \"" << s
+ << "\" expanded to \"" << src << "\" in target \"" << this->GetName()
+ << "\". This behavior will be removed in a "
+ "future version of CMake.";
+ this->Makefile->IssueMessage(messageType, e.str());
+ if (messageType == cmake::FATAL_ERROR) {
+ return "";
}
}
- return true;
+ }
+ return src;
}
-//----------------------------------------------------------------------------
-std::vector<cmSourceFile*> const& cmTarget::GetSourceFiles()
+cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
{
- return this->SourceFiles;
+ std::string src = this->ProcessSourceItemCMP0049(s);
+ if (!s.empty() && src.empty()) {
+ return CM_NULLPTR;
+ }
+ return this->AddSource(src);
}
-//----------------------------------------------------------------------------
-void cmTarget::AddSourceFile(cmSourceFile* sf)
+struct CreateLocation
{
- typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
- SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
- if(i == this->Internal->SourceEntries.end())
- {
- typedef cmTargetInternals::SourceEntry SourceEntry;
- SourceEntriesType::value_type entry(sf, SourceEntry());
- i = this->Internal->SourceEntries.insert(entry).first;
- this->SourceFiles.push_back(sf);
- }
-}
+ cmMakefile const* Makefile;
-//----------------------------------------------------------------------------
-std::vector<cmSourceFile*> const*
-cmTarget::GetSourceDepends(cmSourceFile* sf)
-{
- typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
- SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
- if(i != this->Internal->SourceEntries.end())
- {
- return &i->second.Depends;
- }
- return 0;
-}
+ CreateLocation(cmMakefile const* mf)
+ : Makefile(mf)
+ {
+ }
-//----------------------------------------------------------------------------
-void cmTarget::AddSources(std::vector<std::string> const& srcs)
-{
- for(std::vector<std::string>::const_iterator i = srcs.begin();
- i != srcs.end(); ++i)
- {
- const char* src = i->c_str();
- if(src[0] == '$' && src[1] == '<')
- {
- this->ProcessSourceExpression(*i);
- }
- else
- {
- this->AddSource(src);
- }
- }
-}
+ cmSourceFileLocation operator()(const std::string& filename)
+ {
+ return cmSourceFileLocation(this->Makefile, filename);
+ }
+};
-//----------------------------------------------------------------------------
-cmSourceFile* cmTarget::AddSource(const char* s)
+struct LocationMatcher
{
- std::string src = s;
-
- // For backwards compatibility replace varibles in source names.
- // This should eventually be removed.
- this->Makefile->ExpandVariablesInString(src);
+ const cmSourceFileLocation& Needle;
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(src.c_str());
- this->AddSourceFile(sf);
- return sf;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::ProcessSourceExpression(std::string const& expr)
-{
- if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 &&
- expr[expr.size()-1] == '>')
- {
- std::string objLibName = expr.substr(17, expr.size()-18);
- this->ObjectLibraries.push_back(objLibName);
- }
- else
- {
- cmOStringStream e;
- e << "Unrecognized generator expression:\n"
- << " " << expr;
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- }
-}
+ LocationMatcher(const cmSourceFileLocation& needle)
+ : Needle(needle)
+ {
+ }
-//----------------------------------------------------------------------------
-struct cmTarget::SourceFileFlags
-cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf)
-{
- struct SourceFileFlags flags;
- this->ConstructSourceFileFlags();
- std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
- this->Internal->SourceFlagsMap.find(sf);
- if(si != this->Internal->SourceFlagsMap.end())
- {
- flags = si->second;
- }
- return flags;
-}
+ bool operator()(cmSourceFileLocation& loc)
+ {
+ return loc.Matches(this->Needle);
+ }
+};
-//----------------------------------------------------------------------------
-void cmTarget::ConstructSourceFileFlags()
+struct TargetPropertyEntryFinder
{
- if(this->Internal->SourceFileFlagsConstructed)
- {
- return;
- }
- this->Internal->SourceFileFlagsConstructed = true;
-
- // 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->c_str()))
- {
- SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
- flags.MacFolder = "Headers";
- flags.Type = cmTarget::SourceFileTypePublicHeader;
- }
- }
- }
-
- // 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->c_str()))
- {
- SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
- flags.MacFolder = "PrivateHeaders";
- flags.Type = cmTarget::SourceFileTypePrivateHeader;
- }
- }
- }
+private:
+ const cmSourceFileLocation& Needle;
- // 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->c_str()))
- {
- SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
- flags.MacFolder = "Resources";
- flags.Type = cmTarget::SourceFileTypeResource;
- }
- }
- }
+public:
+ TargetPropertyEntryFinder(const cmSourceFileLocation& needle)
+ : Needle(needle)
+ {
+ }
- // Handle the MACOSX_PACKAGE_LOCATION property on source files that
- // were not listed in one of the other lists.
- std::vector<cmSourceFile*> const& sources = this->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); ++si)
- {
- cmSourceFile* sf = *si;
- if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"))
- {
- SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
- if(flags.Type == cmTarget::SourceFileTypeNormal)
- {
- flags.MacFolder = location;
- if(strcmp(location, "Resources") == 0)
- {
- flags.Type = cmTarget::SourceFileTypeResource;
- }
- else
- {
- flags.Type = cmTarget::SourceFileTypeMacContent;
- }
- }
- }
- }
-}
+ 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(),
+ CreateLocation(this->Needle.GetMakefile()));
+
+ return std::find_if(locations.begin(), locations.end(),
+ LocationMatcher(this->Needle)) != locations.end();
+ }
+};
-//----------------------------------------------------------------------------
-void cmTarget::MergeLinkLibraries( cmMakefile& mf,
- const char *selfname,
- const LinkLibraryVectorType& libs )
+cmSourceFile* cmTarget::AddSource(const std::string& src)
{
- // Only add on libraries we haven't added on before.
- // Assumption: the global link libraries could only grow, never shrink
- LinkLibraryVectorType::const_iterator i = libs.begin();
- i += this->PrevLinkedLibraries.size();
- for( ; i != libs.end(); ++i )
- {
- // This is equivalent to the target_link_libraries plain signature.
- this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
- this->AppendProperty("INTERFACE_LINK_LIBRARIES",
- this->GetDebugGeneratorExpressions(i->first.c_str(), i->second).c_str());
- }
- this->PrevLinkedLibraries = libs;
+ cmSourceFileLocation sfl(this->Makefile, src);
+ if (std::find_if(this->Internal->SourceEntries.begin(),
+ this->Internal->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);
+ }
+ if (cmGeneratorExpression::Find(src) != std::string::npos) {
+ return CM_NULLPTR;
+ }
+ return this->Makefile->GetOrCreateSource(src);
}
-//----------------------------------------------------------------------------
-void cmTarget::AddLinkDirectory(const char* d)
+void cmTarget::AddLinkDirectory(const std::string& d)
{
// Make sure we don't add unnecessary search directories.
- if(this->LinkDirectoriesEmmitted.insert(d).second)
- {
+ if (this->LinkDirectoriesEmmitted.insert(d).second) {
this->LinkDirectories.push_back(d);
- }
+ }
}
-//----------------------------------------------------------------------------
-const std::vector<std::string>& cmTarget::GetLinkDirectories()
+const std::vector<std::string>& cmTarget::GetLinkDirectories() const
{
return this->LinkDirectories;
}
-//----------------------------------------------------------------------------
-cmTarget::LinkLibraryType cmTarget::ComputeLinkType(const char* config)
-{
- // No configuration is always optimized.
- if(!(config && *config))
- {
- return cmTarget::OPTIMIZED;
- }
-
- // Get the list of configurations considered to be DEBUG.
- std::vector<std::string> const& debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
-
- // Check if any entry in the list matches this configuration.
- std::string configUpper = cmSystemTools::UpperCase(config);
- for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
- i != debugConfigs.end(); ++i)
- {
- if(*i == configUpper)
- {
- return cmTarget::DEBUG;
- }
- }
-
- // The current configuration is not a debug configuration.
- return cmTarget::OPTIMIZED;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::ClearDependencyInformation( cmMakefile& mf,
- const char* target )
+void cmTarget::ClearDependencyInformation(cmMakefile& mf,
+ const std::string& target)
{
// 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.c_str(), "",
- "Dependencies for target", cmCacheManager::STATIC);
- }
- else
- {
- if (mf.GetDefinition( depname.c_str() ))
- {
+ 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() );
- }
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::NameResolvesToFramework(const std::string& libname)
-{
- return this->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
- NameResolvesToFramework(libname);
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetDirectLinkLibraries(const char *config,
- std::vector<std::string> &libs, cmTarget *head)
-{
- const char *prop = this->GetProperty("LINK_LIBRARIES");
- if (prop)
- {
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
- const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "LINK_LIBRARIES", 0, 0);
- cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
- config,
- false,
- head,
- &dagChecker),
- libs);
-
- std::set<cmStdString> seenProps = cge->GetSeenTargetProperties();
- for (std::set<cmStdString>::const_iterator it = seenProps.begin();
- it != seenProps.end(); ++it)
- {
- if (!this->GetProperty(it->c_str()))
- {
- this->LinkImplicitNullProperties.insert(*it);
- }
- }
+ cmSystemTools::Error(message.c_str());
}
+ }
}
-//----------------------------------------------------------------------------
-std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
- cmTarget::LinkLibraryType llt)
+std::string cmTarget::GetDebugGeneratorExpressions(
+ const std::string& value, cmTargetLinkLibraryType llt) const
{
- if (llt == GENERAL)
- {
+ if (llt == GENERAL_LibraryType) {
return value;
- }
+ }
// Get the list of configurations considered to be DEBUG.
- std::vector<std::string> const& debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+ std::vector<std::string> debugConfigs =
+ this->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)
- {
+ if (debugConfigs.size() > 1) {
+ for (std::vector<std::string>::const_iterator li =
+ debugConfigs.begin() + 1;
+ li != debugConfigs.end(); ++li) {
configString += ",$<CONFIG:" + *li + ">";
- }
- configString = "$<OR:" + configString + ">";
}
+ configString = "$<OR:" + configString + ">";
+ }
- if (llt == OPTIMIZED)
- {
+ if (llt == OPTIMIZED_LibraryType) {
configString = "$<NOT:" + configString + ">";
- }
+ }
return "$<" + configString + ":" + value + ">";
}
-//----------------------------------------------------------------------------
-static std::string targetNameGenex(const char *lib)
+static std::string targetNameGenex(const std::string& lib)
{
- return std::string("$<TARGET_NAME:") + lib + ">";
+ return "$<TARGET_NAME:" + lib + ">";
}
-//----------------------------------------------------------------------------
-bool cmTarget::PushTLLCommandTrace(TLLSignature signature)
+bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
+ cmListFileContext const& lfc)
{
bool ret = true;
- if (!this->TLLCommands.empty())
- {
- if (this->TLLCommands.back().first != signature)
- {
+ if (!this->TLLCommands.empty()) {
+ if (this->TLLCommands.back().first != signature) {
ret = false;
- }
}
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- this->TLLCommands.push_back(std::make_pair(signature, lfbt));
+ }
+ if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) {
+ this->TLLCommands.push_back(std::make_pair(signature, lfc));
+ }
return ret;
}
-//----------------------------------------------------------------------------
-void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
- TLLSignature sig) const
+void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
{
- std::vector<cmListFileBacktrace> sigs;
- typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container;
- for(Container::const_iterator it = this->TLLCommands.begin();
- it != this->TLLCommands.end(); ++it)
- {
- if (it->first == sig)
- {
- sigs.push_back(it->second);
- }
- }
- if (!sigs.empty())
- {
- const char *sigString
- = (sig == cmTarget::KeywordTLLSignature ? "keyword"
- : "plain");
- s << "The uses of the " << sigString << " signature are here:\n";
- std::set<cmStdString> emitted;
- for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin();
- it != sigs.end(); ++it)
- {
- cmListFileBacktrace::const_iterator i = it->begin();
- if(i != it->end())
- {
- cmListFileContext const& lfc = *i;
- cmOStringStream line;
- line << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
- if (emitted.insert(line.str()).second)
- {
- s << line.str();
- }
- ++i;
- }
- }
+ 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);
+ s << " * " << lfc << std::endl;
}
+ }
}
-//----------------------------------------------------------------------------
-void cmTarget::AddLinkLibrary(cmMakefile& mf,
- const char *target, const char* lib,
- LinkLibraryType llt)
+void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
+ cmTargetLinkLibraryType llt)
{
- // Never add a self dependency, even if the user asks for it.
- if(strcmp( target, lib ) == 0)
- {
- return;
- }
-
+ cmTarget* tgt = this->Makefile->FindTargetToUse(lib);
{
- cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
- const bool isNonImportedTarget = tgt && !tgt->IsImported();
-
- const std::string libName = (isNonImportedTarget && llt != GENERAL)
- ? targetNameGenex(lib)
- : std::string(lib);
- this->AppendProperty("LINK_LIBRARIES",
- this->GetDebugGeneratorExpressions(libName,
- llt).c_str());
+ const bool isNonImportedTarget = tgt && !tgt->IsImported();
+
+ const std::string libName =
+ (isNonImportedTarget && llt != GENERAL_LibraryType)
+ ? targetNameGenex(lib)
+ : lib;
+ this->AppendProperty(
+ "LINK_LIBRARIES",
+ this->GetDebugGeneratorExpressions(libName, llt).c_str());
}
- if (cmGeneratorExpression::Find(lib) != std::string::npos)
- {
+ if (cmGeneratorExpression::Find(lib) != std::string::npos ||
+ (tgt && tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
+ (this->Name == lib)) {
return;
- }
+ }
cmTarget::LibraryID tmp;
tmp.first = lib;
tmp.second = llt;
- this->LinkLibraries.push_back( tmp );
this->OriginalLinkLibraries.push_back(tmp);
- this->ClearLinkMaps();
// Add the explicit dependency information for this target. This is
// simply a set of libraries separated by ";". There should always
@@ -2592,1211 +758,358 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
// 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 = target;
+ if (this->RecordDependencies) {
+ std::string targetEntry = this->Name;
targetEntry += "_LIB_DEPENDS";
std::string dependencies;
- const char* old_val = mf.GetDefinition( targetEntry.c_str() );
- if( old_val )
- {
+ const char* old_val = mf.GetDefinition(targetEntry);
+ if (old_val) {
dependencies += old_val;
- }
- switch (llt)
- {
- case cmTarget::GENERAL:
+ }
+ switch (llt) {
+ case GENERAL_LibraryType:
dependencies += "general";
break;
- case cmTarget::DEBUG:
+ case DEBUG_LibraryType:
dependencies += "debug";
break;
- case cmTarget::OPTIMIZED:
+ case OPTIMIZED_LibraryType:
dependencies += "optimized";
break;
- }
+ }
dependencies += ";";
dependencies += lib;
dependencies += ";";
- mf.AddCacheDefinition( targetEntry.c_str(), dependencies.c_str(),
- "Dependencies for the target",
- cmCacheManager::STATIC );
- }
+ mf.AddCacheDefinition(targetEntry, dependencies.c_str(),
+ "Dependencies for the target", cmStateEnums::STATIC);
+ }
+}
+void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
+{
+ this->SystemIncludeDirectories.insert(incs.begin(), incs.end());
}
-//----------------------------------------------------------------------------
-void
-cmTarget::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
+cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
- for(std::set<cmStdString>::const_iterator li = incs.begin();
- li != incs.end(); ++li)
- {
- this->SystemIncludeDirectories.insert(*li);
- }
+ return cmMakeRange(this->Internal->IncludeDirectoriesEntries);
}
-//----------------------------------------------------------------------------
-void
-cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs)
+cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
{
- for(std::vector<std::string>::const_iterator li = incs.begin();
- li != incs.end(); ++li)
- {
- this->SystemIncludeDirectories.insert(*li);
- }
+ return cmMakeRange(this->Internal->IncludeDirectoriesBacktraces);
}
-//----------------------------------------------------------------------------
-void cmTarget::FinalizeSystemIncludeDirectories()
+cmStringRange cmTarget::GetCompileOptionsEntries() const
{
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkInterfacePropertyEntries.begin(),
- end = this->Internal->LinkInterfacePropertyEntries.end();
- it != end; ++it)
- {
- {
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(it->Value);
- std::string targetName = cge->Evaluate(this->Makefile, 0,
- false, this, 0, 0);
- if (!this->Makefile->FindTargetToUse(targetName.c_str()))
- {
- continue;
- }
- }
- std::string includeGenex = "$<TARGET_PROPERTY:" +
- it->Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>";
- if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
- {
- // Because it->Value is a generator expression, ensure that it
- // evaluates to the non-empty string before being used in the
- // TARGET_PROPERTY expression.
- includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
- }
- this->SystemIncludeDirectories.insert(includeGenex);
- }
+ return cmMakeRange(this->Internal->CompileOptionsEntries);
}
-//----------------------------------------------------------------------------
-void
-cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
+cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
{
- // There are two key parts of the dependency analysis: (1)
- // determining the libraries in the link line, and (2) constructing
- // the dependency graph for those libraries.
- //
- // The latter is done using the cache entries that record the
- // dependencies of each library.
- //
- // The former is a more thorny issue, since it is not clear how to
- // determine if two libraries listed on the link line refer to the a
- // single library or not. For example, consider the link "libraries"
- // /usr/lib/libtiff.so -ltiff
- // Is this one library or two? The solution implemented here is the
- // simplest (and probably the only practical) one: two libraries are
- // the same if their "link strings" are identical. Thus, the two
- // libraries above are considered distinct. This also means that for
- // dependency analysis to be effective, the CMake user must specify
- // libraries build by his project without using any linker flags or
- // file extensions. That is,
- // LINK_LIBRARIES( One Two )
- // instead of
- // LINK_LIBRARIES( -lOne ${binarypath}/libTwo.a )
- // The former is probably what most users would do, but it never
- // hurts to document the assumptions. :-) Therefore, in the analysis
- // code, the "canonical name" of a library is simply its name as
- // given to a LINK_LIBRARIES command.
- //
- // Also, we will leave the original link line intact; we will just add any
- // dependencies that were missing.
- //
- // There is a problem with recursive external libraries
- // (i.e. libraries with no dependency information that are
- // recursively dependent). We must make sure that the we emit one of
- // the libraries twice to satisfy the recursion, but we shouldn't
- // emit it more times than necessary. In particular, we must make
- // sure that handling this improbable case doesn't cost us when
- // dealing with the common case of non-recursive libraries. The
- // solution is to assume that the recursion is satisfied at one node
- // of the dependency tree. To illustrate, assume libA and libB are
- // extrenal and mutually dependent. Suppose libX depends on
- // libA, and libY on libA and libX. Then
- // TARGET_LINK_LIBRARIES( Y X A B A )
- // TARGET_LINK_LIBRARIES( X A B A )
- // TARGET_LINK_LIBRARIES( Exec Y )
- // would result in "-lY -lX -lA -lB -lA". This is the correct way to
- // specify the dependencies, since the mutual dependency of A and B
- // is resolved *every time libA is specified*.
- //
- // Something like
- // TARGET_LINK_LIBRARIES( Y X A B A )
- // TARGET_LINK_LIBRARIES( X A B )
- // TARGET_LINK_LIBRARIES( Exec Y )
- // would result in "-lY -lX -lA -lB", and the mutual dependency
- // information is lost. This is because in some case (Y), the mutual
- // dependency of A and B is listed, while in another other case (X),
- // it is not. Depending on which line actually emits A, the mutual
- // dependency may or may not be on the final link line. We can't
- // handle this pathalogical case cleanly without emitting extra
- // libraries for the normal cases. Besides, the dependency
- // information for X is wrong anyway: if we build an executable
- // depending on X alone, we would not have the mutual dependency on
- // A and B resolved.
- //
- // IMPROVEMENTS:
- // -- The current algorithm will not always pick the "optimal" link line
- // when recursive dependencies are present. It will instead break the
- // cycles at an aribtrary point. The majority of projects won't have
- // cyclic dependencies, so this is probably not a big deal. Note that
- // the link line is always correct, just not necessary optimal.
-
- {
- // Expand variables in link library names. This is for backwards
- // compatibility with very early CMake versions and should
- // eventually be removed. This code was moved here from the end of
- // old source list processing code which was called just before this
- // method.
- for(LinkLibraryVectorType::iterator p = this->LinkLibraries.begin();
- p != this->LinkLibraries.end(); ++p)
- {
- this->Makefile->ExpandVariablesInString(p->first, true, true);
- }
- }
-
- // The dependency map.
- DependencyMap dep_map;
-
- // 1. Build the dependency graph
- //
- for(LinkLibraryVectorType::reverse_iterator lib
- = this->LinkLibraries.rbegin();
- lib != this->LinkLibraries.rend(); ++lib)
- {
- this->GatherDependencies( mf, *lib, dep_map);
- }
-
- // 2. Remove any dependencies that are already satisfied in the original
- // link line.
- //
- for(LinkLibraryVectorType::iterator lib = this->LinkLibraries.begin();
- lib != this->LinkLibraries.end(); ++lib)
- {
- for( LinkLibraryVectorType::iterator lib2 = lib;
- lib2 != this->LinkLibraries.end(); ++lib2)
- {
- this->DeleteDependency( dep_map, *lib, *lib2);
- }
- }
-
-
- // 3. Create the new link line by simply emitting any dependencies that are
- // missing. Start from the back and keep adding.
- //
- std::set<DependencyMap::key_type> done, visited;
- std::vector<DependencyMap::key_type> newLinkLibraries;
- for(LinkLibraryVectorType::reverse_iterator lib =
- this->LinkLibraries.rbegin();
- lib != this->LinkLibraries.rend(); ++lib)
- {
- // skip zero size library entries, this may happen
- // if a variable expands to nothing.
- if (lib->first.size() != 0)
- {
- this->Emit( *lib, dep_map, done, visited, newLinkLibraries );
- }
- }
-
- // 4. Add the new libraries to the link line.
- //
- for( std::vector<DependencyMap::key_type>::reverse_iterator k =
- newLinkLibraries.rbegin();
- k != newLinkLibraries.rend(); ++k )
- {
- // get the llt from the dep_map
- this->LinkLibraries.push_back( std::make_pair(k->first,k->second) );
- }
- this->LinkLibrariesAnalyzed = true;
+ return cmMakeRange(this->Internal->CompileOptionsBacktraces);
}
-//----------------------------------------------------------------------------
-void cmTarget::InsertDependency( DependencyMap& depMap,
- const LibraryID& lib,
- const LibraryID& dep)
+cmStringRange cmTarget::GetCompileFeaturesEntries() const
{
- depMap[lib].push_back(dep);
+ return cmMakeRange(this->Internal->CompileFeaturesEntries);
}
-//----------------------------------------------------------------------------
-void cmTarget::DeleteDependency( DependencyMap& depMap,
- const LibraryID& lib,
- const LibraryID& dep)
+cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
{
- // Make sure there is an entry in the map for lib. If so, delete all
- // dependencies to dep. There may be repeated entries because of
- // external libraries that are specified multiple times.
- DependencyMap::iterator map_itr = depMap.find( lib );
- if( map_itr != depMap.end() )
- {
- DependencyList& depList = map_itr->second;
- DependencyList::iterator itr;
- while( (itr = std::find(depList.begin(), depList.end(), dep)) !=
- depList.end() )
- {
- depList.erase( itr );
- }
- }
+ return cmMakeRange(this->Internal->CompileFeaturesBacktraces);
}
-//----------------------------------------------------------------------------
-void cmTarget::Emit(const LibraryID lib,
- const DependencyMap& dep_map,
- std::set<LibraryID>& emitted,
- std::set<LibraryID>& visited,
- DependencyList& link_line )
+cmStringRange cmTarget::GetCompileDefinitionsEntries() const
{
- // It's already been emitted
- if( emitted.find(lib) != emitted.end() )
- {
- return;
- }
+ return cmMakeRange(this->Internal->CompileDefinitionsEntries);
+}
- // Emit the dependencies only if this library node hasn't been
- // visited before. If it has, then we have a cycle. The recursion
- // that got us here should take care of everything.
-
- if( visited.insert(lib).second )
- {
- if( dep_map.find(lib) != dep_map.end() ) // does it have dependencies?
- {
- const DependencyList& dep_on = dep_map.find( lib )->second;
- DependencyList::const_reverse_iterator i;
-
- // To cater for recursive external libraries, we must emit
- // duplicates on this link line *unless* they were emitted by
- // some other node, in which case we assume that the recursion
- // was resolved then. We making the simplifying assumption that
- // any duplicates on a single link line are on purpose, and must
- // be preserved.
-
- // This variable will keep track of the libraries that were
- // emitted directly from the current node, and not from a
- // recursive call. This way, if we come across a library that
- // has already been emitted, we repeat it iff it has been
- // emitted here.
- std::set<DependencyMap::key_type> emitted_here;
- for( i = dep_on.rbegin(); i != dep_on.rend(); ++i )
- {
- if( emitted_here.find(*i) != emitted_here.end() )
- {
- // a repeat. Must emit.
- emitted.insert(*i);
- link_line.push_back( *i );
- }
- else
- {
- // Emit only if no-one else has
- if( emitted.find(*i) == emitted.end() )
- {
- // emit dependencies
- Emit( *i, dep_map, emitted, visited, link_line );
- // emit self
- emitted.insert(*i);
- emitted_here.insert(*i);
- link_line.push_back( *i );
- }
- }
- }
- }
- }
+cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
+{
+ return cmMakeRange(this->Internal->CompileDefinitionsBacktraces);
}
-//----------------------------------------------------------------------------
-void cmTarget::GatherDependencies( const cmMakefile& mf,
- const LibraryID& lib,
- DependencyMap& dep_map)
+cmStringRange cmTarget::GetSourceEntries() const
{
- // If the library is already in the dependency map, then it has
- // already been fully processed.
- if( dep_map.find(lib) != dep_map.end() )
- {
- return;
- }
+ return cmMakeRange(this->Internal->SourceEntries);
+}
- const char* deps = mf.GetDefinition( (lib.first+"_LIB_DEPENDS").c_str() );
- if( deps && strcmp(deps,"") != 0 )
- {
- // Make sure this library is in the map, even if it has an empty
- // set of dependencies. This distinguishes the case of explicitly
- // no dependencies with that of unspecified dependencies.
- dep_map[lib];
-
- // Parse the dependency information, which is a set of
- // type, library pairs separated by ";". There is always a trailing ";".
- cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
- std::string depline = deps;
- std::string::size_type start = 0;
- std::string::size_type end;
- end = depline.find( ";", start );
- while( end != std::string::npos )
- {
- std::string l = depline.substr( start, end-start );
- if( l.size() != 0 )
- {
- if (l == "debug")
- {
- llt = cmTarget::DEBUG;
- }
- else if (l == "optimized")
- {
- llt = cmTarget::OPTIMIZED;
- }
- else if (l == "general")
- {
- llt = cmTarget::GENERAL;
- }
- else
- {
- LibraryID lib2(l,llt);
- this->InsertDependency( dep_map, lib, lib2);
- this->GatherDependencies( mf, lib2, dep_map);
- llt = cmTarget::GENERAL;
- }
- }
- start = end+1; // skip the ;
- end = depline.find( ";", start );
- }
- // cannot depend on itself
- this->DeleteDependency( dep_map, lib, lib);
- }
+cmBacktraceRange cmTarget::GetSourceBacktraces() const
+{
+ return cmMakeRange(this->Internal->SourceBacktraces);
+}
+
+cmStringRange cmTarget::GetLinkImplementationEntries() const
+{
+ return cmMakeRange(this->Internal->LinkImplementationPropertyEntries);
+}
+
+cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
+{
+ return cmMakeRange(this->Internal->LinkImplementationPropertyBacktraces);
}
-//----------------------------------------------------------------------------
-void cmTarget::SetProperty(const char* prop, const char* value)
+void cmTarget::SetProperty(const std::string& prop, const char* value)
{
- if (!prop)
- {
+ if (!cmTargetPropertyComputer::PassesWhitelist(
+ this->GetType(), prop, this->Makefile->GetMessenger(),
+ this->Makefile->GetBacktrace())) {
return;
- }
- if (strcmp(prop, "NAME") == 0)
- {
- cmOStringStream e;
+ }
+ 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());
+ return;
+ }
+ if (prop == "NAME") {
+ std::ostringstream e;
e << "NAME property is read-only\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
- if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmGeneratorExpression ge(lfbt);
- deleteAndClear(this->Internal->IncludeDirectoriesEntries);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
- this->Internal->IncludeDirectoriesEntries.push_back(
- new cmTargetInternals::TargetPropertyEntry(cge));
+ }
+ if (prop == "TYPE") {
+ std::ostringstream e;
+ e << "TYPE property is read-only\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
- if(strcmp(prop,"COMPILE_OPTIONS") == 0)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmGeneratorExpression ge(lfbt);
- deleteAndClear(this->Internal->CompileOptionsEntries);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
- this->Internal->CompileOptionsEntries.push_back(
- new cmTargetInternals::TargetPropertyEntry(cge));
+ }
+ 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());
return;
- }
- if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmGeneratorExpression ge(lfbt);
- deleteAndClear(this->Internal->CompileDefinitionsEntries);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
- this->Internal->CompileDefinitionsEntries.push_back(
- new cmTargetInternals::TargetPropertyEntry(cge));
+ }
+ if (prop == "SOURCES" && this->IsImported()) {
+ std::ostringstream e;
+ e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
- if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
- {
- cmOStringStream e;
- e << "EXPORT_NAME property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ }
+
+ if (prop == "INCLUDE_DIRECTORIES") {
+ this->Internal->IncludeDirectoriesEntries.clear();
+ this->Internal->IncludeDirectoriesBacktraces.clear();
+ if (value) {
+ this->Internal->IncludeDirectoriesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "COMPILE_OPTIONS") {
+ this->Internal->CompileOptionsEntries.clear();
+ this->Internal->CompileOptionsBacktraces.clear();
+ if (value) {
+ this->Internal->CompileOptionsEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->CompileOptionsBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "COMPILE_FEATURES") {
+ this->Internal->CompileFeaturesEntries.clear();
+ this->Internal->CompileFeaturesBacktraces.clear();
+ if (value) {
+ this->Internal->CompileFeaturesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->CompileFeaturesBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "COMPILE_DEFINITIONS") {
+ this->Internal->CompileDefinitionsEntries.clear();
+ this->Internal->CompileDefinitionsBacktraces.clear();
+ if (value) {
+ this->Internal->CompileDefinitionsEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "LINK_LIBRARIES") {
+ this->Internal->LinkImplementationPropertyEntries.clear();
+ this->Internal->LinkImplementationPropertyBacktraces.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkImplementationPropertyEntries.push_back(value);
+ this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "SOURCES") {
+ this->Internal->SourceEntries.clear();
+ this->Internal->SourceBacktraces.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->SourceEntries.push_back(value);
+ this->Internal->SourceBacktraces.push_back(lfbt);
+ }
+ } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
+ !this->CheckImportedLibName(prop, value ? value : "")) {
+ /* error was reported by check method */
+ } else if (prop == "CUDA_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());
return;
- }
- if (strcmp(prop, "LINK_LIBRARIES") == 0)
- {
- this->Internal->LinkInterfacePropertyEntries.clear();
- if (cmGeneratorExpression::IsValidTargetName(value)
- || cmGeneratorExpression::Find(value) != std::string::npos)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmValueWithOrigin entry(value, lfbt);
- this->Internal->LinkInterfacePropertyEntries.push_back(entry);
- }
- // Fall through
- }
- this->Properties.SetProperty(prop, value, cmProperty::TARGET);
- this->MaybeInvalidatePropertyCache(prop);
+ } else {
+ this->Properties.SetProperty(prop, value);
+ }
}
-//----------------------------------------------------------------------------
-void cmTarget::AppendProperty(const char* prop, const char* value,
+void cmTarget::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
- if (!prop)
- {
+ if (!cmTargetPropertyComputer::PassesWhitelist(
+ this->GetType(), prop, this->Makefile->GetMessenger(),
+ this->Makefile->GetBacktrace())) {
return;
- }
- if (strcmp(prop, "NAME") == 0)
- {
- cmOStringStream e;
+ }
+ if (prop == "NAME") {
+ std::ostringstream e;
e << "NAME property is read-only\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- return;
- }
- if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmGeneratorExpression ge(lfbt);
- this->Internal->IncludeDirectoriesEntries.push_back(
- new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
- return;
- }
- if(strcmp(prop,"COMPILE_OPTIONS") == 0)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmGeneratorExpression ge(lfbt);
- this->Internal->CompileOptionsEntries.push_back(
- new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
- return;
- }
- if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmGeneratorExpression ge(lfbt);
- this->Internal->CompileDefinitionsEntries.push_back(
- new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
- if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
- {
- cmOStringStream e;
+ }
+ 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().c_str());
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
- }
- if (strcmp(prop, "LINK_LIBRARIES") == 0)
- {
- if (cmGeneratorExpression::IsValidTargetName(value)
- || cmGeneratorExpression::Find(value) != std::string::npos)
- {
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmValueWithOrigin entry(value, lfbt);
- this->Internal->LinkInterfacePropertyEntries.push_back(entry);
- }
- // Fall through
- }
- this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString);
- this->MaybeInvalidatePropertyCache(prop);
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetExportName()
-{
- const char *exportName = this->GetProperty("EXPORT_NAME");
-
- if (exportName && *exportName)
- {
- if (!cmGeneratorExpression::IsValidTargetName(exportName))
- {
- cmOStringStream e;
- e << "EXPORT_NAME property \"" << exportName << "\" for \""
- << this->GetName() << "\": is not valid.";
- cmSystemTools::Error(e.str().c_str());
- return "";
- }
- return exportName;
- }
- return this->GetName();
+ }
+ if (prop == "SOURCES" && this->IsImported()) {
+ std::ostringstream e;
+ e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+ if (prop == "INCLUDE_DIRECTORIES") {
+ if (value && *value) {
+ this->Internal->IncludeDirectoriesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->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);
+ }
+ } 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);
+ }
+ } 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);
+ }
+ } 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);
+ }
+ } else if (prop == "SOURCES") {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->SourceEntries.push_back(value);
+ this->Internal->SourceBacktraces.push_back(lfbt);
+ } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ prop + " property may not be APPENDed.");
+ } else {
+ this->Properties.AppendProperty(prop, value, asString);
+ }
}
-//----------------------------------------------------------------------------
void cmTarget::AppendBuildInterfaceIncludes()
{
- if(this->GetType() != cmTarget::SHARED_LIBRARY &&
- this->GetType() != cmTarget::STATIC_LIBRARY &&
- this->GetType() != cmTarget::MODULE_LIBRARY &&
- !this->IsExecutableWithExports())
- {
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ !this->IsExecutableWithExports()) {
return;
- }
- if (this->BuildInterfaceIncludesAppended)
- {
+ }
+ if (this->BuildInterfaceIncludesAppended) {
return;
- }
+ }
this->BuildInterfaceIncludesAppended = true;
- if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE"))
- {
- const char *binDir = this->Makefile->GetStartOutputDirectory();
- const char *srcDir = this->Makefile->GetStartDirectory();
- const std::string dirs = std::string(binDir ? binDir : "")
- + std::string(binDir ? ";" : "")
- + std::string(srcDir ? srcDir : "");
- if (!dirs.empty())
- {
+ 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 (!dirs.empty()) {
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
- ("$<BUILD_INTERFACE:" + dirs + ">").c_str());
- }
+ ("$<BUILD_INTERFACE:" + dirs + ">").c_str());
}
+ }
}
-//----------------------------------------------------------------------------
-void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
- bool before)
+void cmTarget::InsertInclude(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
{
- cmGeneratorExpression ge(entry.Backtrace);
+ std::vector<std::string>::iterator position = before
+ ? this->Internal->IncludeDirectoriesEntries.begin()
+ : this->Internal->IncludeDirectoriesEntries.end();
- std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
- = before ? this->Internal->IncludeDirectoriesEntries.begin()
- : this->Internal->IncludeDirectoriesEntries.end();
+ std::vector<cmListFileBacktrace>::iterator btPosition = before
+ ? this->Internal->IncludeDirectoriesBacktraces.begin()
+ : this->Internal->IncludeDirectoriesBacktraces.end();
- this->Internal->IncludeDirectoriesEntries.insert(position,
- new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+ this->Internal->IncludeDirectoriesEntries.insert(position, entry);
+ this->Internal->IncludeDirectoriesBacktraces.insert(btPosition, bt);
}
-//----------------------------------------------------------------------------
-void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry,
- bool before)
+void cmTarget::InsertCompileOption(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
{
- cmGeneratorExpression ge(entry.Backtrace);
+ std::vector<std::string>::iterator position = before
+ ? this->Internal->CompileOptionsEntries.begin()
+ : this->Internal->CompileOptionsEntries.end();
- std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
- = before ? this->Internal->CompileOptionsEntries.begin()
- : this->Internal->CompileOptionsEntries.end();
+ std::vector<cmListFileBacktrace>::iterator btPosition = before
+ ? this->Internal->CompileOptionsBacktraces.begin()
+ : this->Internal->CompileOptionsBacktraces.end();
- this->Internal->CompileOptionsEntries.insert(position,
- new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+ this->Internal->CompileOptionsEntries.insert(position, entry);
+ this->Internal->CompileOptionsBacktraces.insert(btPosition, bt);
}
-//----------------------------------------------------------------------------
-void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry,
- bool before)
+void cmTarget::InsertCompileDefinition(std::string const& entry,
+ cmListFileBacktrace const& bt)
{
- cmGeneratorExpression ge(entry.Backtrace);
-
- std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
- = before ? this->Internal->CompileDefinitionsEntries.begin()
- : this->Internal->CompileDefinitionsEntries.end();
-
- this->Internal->CompileDefinitionsEntries.insert(position,
- new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+ this->Internal->CompileDefinitionsEntries.push_back(entry);
+ this->Internal->CompileDefinitionsBacktraces.push_back(bt);
}
-//----------------------------------------------------------------------------
-static void processIncludeDirectories(cmTarget *tgt,
- const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
- std::vector<std::string> &includes,
- std::set<std::string> &uniqueIncludes,
- cmGeneratorExpressionDAGChecker *dagChecker,
- const char *config, bool debugIncludes)
-{
- cmMakefile *mf = tgt->GetMakefile();
-
- for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
- it = entries.begin(), end = entries.end(); it != end; ++it)
- {
- bool testIsOff = true;
- bool cacheIncludes = false;
- std::vector<std::string> entryIncludes = (*it)->CachedEntries;
- if(!entryIncludes.empty())
- {
- testIsOff = false;
- }
- else
- {
- cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
- config,
- false,
- tgt,
- dagChecker),
- entryIncludes);
- if (mf->IsGeneratingBuildSystem()
- && !(*it)->ge->GetHadContextSensitiveCondition())
- {
- cacheIncludes = true;
- }
- }
- std::string usedIncludes;
- for(std::vector<std::string>::iterator
- li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
- {
- cmTarget *dependentTarget =
- mf->FindTargetToUse((*it)->TargetName.c_str());
-
- const bool fromImported = dependentTarget
- && dependentTarget->IsImported();
-
- if (fromImported && !cmSystemTools::FileExists(li->c_str()))
- {
- cmOStringStream e;
- e << "Imported target \"" << (*it)->TargetName << "\" includes "
- "non-existent path\n \"" << *li << "\"\nin its "
- "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
- "* The path was deleted, renamed, or moved to another "
- "location.\n"
- "* An install or uninstall procedure did not complete "
- "successfully.\n"
- "* The installation package was faulty and references files it "
- "does not provide.\n";
- tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
- return;
- }
-
- if (!cmSystemTools::FileIsFullPath(li->c_str()))
- {
- cmOStringStream e;
- bool noMessage = false;
- cmake::MessageType messageType = cmake::FATAL_ERROR;
- if (!(*it)->TargetName.empty())
- {
- e << "Target \"" << (*it)->TargetName << "\" contains relative "
- "path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
- " \"" << *li << "\"";
- }
- else
- {
- switch(tgt->GetPolicyStatusCMP0021())
- {
- case cmPolicies::WARN:
- {
- cmOStringStream w;
- e << (mf->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0021)) << "\n";
- messageType = cmake::AUTHOR_WARNING;
- }
- break;
- case cmPolicies::OLD:
- noMessage = true;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Issue the fatal message.
- break;
- }
- e << "Found relative path while evaluating include directories of "
- "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n";
- }
- if (!noMessage)
- {
- tgt->GetMakefile()->IssueMessage(messageType, e.str().c_str());
- if (messageType == cmake::FATAL_ERROR)
- {
- return;
- }
- }
- }
-
- if (testIsOff && !cmSystemTools::IsOff(li->c_str()))
- {
- cmSystemTools::ConvertToUnixSlashes(*li);
- }
- std::string inc = *li;
-
- if(uniqueIncludes.insert(inc).second)
- {
- includes.push_back(inc);
- if (debugIncludes)
- {
- usedIncludes += " * " + inc + "\n";
- }
- }
- }
- if (cacheIncludes)
- {
- (*it)->CachedEntries = entryIncludes;
- }
- if (!usedIncludes.empty())
- {
- mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
- std::string("Used includes for target ")
- + tgt->GetName() + ":\n"
- + usedIncludes, (*it)->ge->GetBacktrace());
- }
- }
-}
-
-//----------------------------------------------------------------------------
-std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
-{
- std::vector<std::string> includes;
- std::set<std::string> uniqueIncludes;
- cmListFileBacktrace lfbt;
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INCLUDE_DIRECTORIES", 0, 0);
-
- this->AppendBuildInterfaceIncludes();
-
- std::vector<std::string> debugProperties;
- const char *debugProp =
- this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
- if (debugProp)
- {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
- }
-
- bool debugIncludes = !this->DebugIncludesDone
- && std::find(debugProperties.begin(),
- debugProperties.end(),
- "INCLUDE_DIRECTORIES")
- != debugProperties.end();
-
- if (this->Makefile->IsGeneratingBuildSystem())
- {
- this->DebugIncludesDone = true;
- }
-
- processIncludeDirectories(this,
- this->Internal->IncludeDirectoriesEntries,
- includes,
- uniqueIncludes,
- &dagChecker,
- config,
- debugIncludes);
-
- std::string configString = config ? config : "";
- if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString])
- {
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkInterfacePropertyEntries.begin(),
- end = this->Internal->LinkInterfacePropertyEntries.end();
- it != end; ++it)
- {
- {
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(it->Value);
- std::string result = cge->Evaluate(this->Makefile, config,
- false, this, 0, 0);
- if (!this->Makefile->FindTargetToUse(result.c_str()))
- {
- continue;
- }
- }
- std::string includeGenex = "$<TARGET_PROPERTY:" +
- it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>";
- if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
- {
- // Because it->Value is a generator expression, ensure that it
- // evaluates to the non-empty string before being used in the
- // TARGET_PROPERTY expression.
- includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
- }
- cmGeneratorExpression ge(it->Backtrace);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
- includeGenex);
-
- this->Internal
- ->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back(
- new cmTargetInternals::TargetPropertyEntry(cge,
- it->Value));
- }
-
- if(this->Makefile->IsOn("APPLE"))
- {
- LinkImplementation const* impl = this->GetLinkImplementation(config,
- this);
- for(std::vector<std::string>::const_iterator
- it = impl->Libraries.begin();
- it != impl->Libraries.end(); ++it)
- {
- std::string libDir = cmSystemTools::CollapseFullPath(it->c_str());
-
- static cmsys::RegularExpression
- frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
- if(!frameworkCheck.find(libDir))
- {
- continue;
- }
-
- libDir = frameworkCheck.match(1);
-
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(libDir.c_str());
- this->Internal
- ->CachedLinkInterfaceIncludeDirectoriesEntries[configString]
- .push_back(new cmTargetInternals::TargetPropertyEntry(cge));
- }
- }
- }
-
- processIncludeDirectories(this,
- this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries[configString],
- includes,
- uniqueIncludes,
- &dagChecker,
- config,
- debugIncludes);
-
- if (!this->Makefile->IsGeneratingBuildSystem())
- {
- deleteAndClear(
- this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries);
- }
- else
- {
- this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString]
- = true;
- }
-
- return includes;
-}
-
-//----------------------------------------------------------------------------
-static void processCompileOptionsInternal(cmTarget *tgt,
- const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
- std::vector<std::string> &options,
- std::set<std::string> &uniqueOptions,
- cmGeneratorExpressionDAGChecker *dagChecker,
- const char *config, bool debugOptions, const char *logName)
-{
- cmMakefile *mf = tgt->GetMakefile();
-
- for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
- it = entries.begin(), end = entries.end(); it != end; ++it)
- {
- bool cacheOptions = false;
- std::vector<std::string> entryOptions = (*it)->CachedEntries;
- if(entryOptions.empty())
- {
- cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
- config,
- false,
- tgt,
- dagChecker),
- entryOptions);
- if (mf->IsGeneratingBuildSystem()
- && !(*it)->ge->GetHadContextSensitiveCondition())
- {
- cacheOptions = true;
- }
- }
- std::string usedOptions;
- for(std::vector<std::string>::iterator
- li = entryOptions.begin(); li != entryOptions.end(); ++li)
- {
- std::string opt = *li;
-
- if(uniqueOptions.insert(opt).second)
- {
- options.push_back(opt);
- if (debugOptions)
- {
- usedOptions += " * " + opt + "\n";
- }
- }
- }
- if (cacheOptions)
- {
- (*it)->CachedEntries = entryOptions;
- }
- if (!usedOptions.empty())
- {
- mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
- std::string("Used compile ") + logName
- + std::string(" for target ")
- + tgt->GetName() + ":\n"
- + usedOptions, (*it)->ge->GetBacktrace());
- }
- }
-}
-
-//----------------------------------------------------------------------------
-static void processCompileOptions(cmTarget *tgt,
- const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
- std::vector<std::string> &options,
- std::set<std::string> &uniqueOptions,
- cmGeneratorExpressionDAGChecker *dagChecker,
- const char *config, bool debugOptions)
-{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "options");
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetCompileOptions(std::vector<std::string> &result,
- const char *config)
-{
- std::set<std::string> uniqueOptions;
- cmListFileBacktrace lfbt;
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "COMPILE_OPTIONS", 0, 0);
-
- std::vector<std::string> debugProperties;
- const char *debugProp =
- this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
- if (debugProp)
- {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
- }
-
- bool debugOptions = !this->DebugCompileOptionsDone
- && std::find(debugProperties.begin(),
- debugProperties.end(),
- "COMPILE_OPTIONS")
- != debugProperties.end();
-
- if (this->Makefile->IsGeneratingBuildSystem())
- {
- this->DebugCompileOptionsDone = true;
- }
-
- processCompileOptions(this,
- this->Internal->CompileOptionsEntries,
- result,
- uniqueOptions,
- &dagChecker,
- config,
- debugOptions);
-
- std::string configString = config ? config : "";
- if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[configString])
- {
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkInterfacePropertyEntries.begin(),
- end = this->Internal->LinkInterfacePropertyEntries.end();
- it != end; ++it)
- {
- {
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(it->Value);
- std::string targetResult = cge->Evaluate(this->Makefile, config,
- false, this, 0, 0);
- if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
- {
- continue;
- }
- }
- std::string optionGenex = "$<TARGET_PROPERTY:" +
- it->Value + ",INTERFACE_COMPILE_OPTIONS>";
- if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
- {
- // Because it->Value is a generator expression, ensure that it
- // evaluates to the non-empty string before being used in the
- // TARGET_PROPERTY expression.
- optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">";
- }
- cmGeneratorExpression ge(it->Backtrace);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
- optionGenex);
-
- this->Internal
- ->CachedLinkInterfaceCompileOptionsEntries[configString].push_back(
- new cmTargetInternals::TargetPropertyEntry(cge,
- it->Value));
- }
- }
-
- processCompileOptions(this,
- this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString],
- result,
- uniqueOptions,
- &dagChecker,
- config,
- debugOptions);
-
- if (!this->Makefile->IsGeneratingBuildSystem())
- {
- deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries);
- }
- else
- {
- this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true;
- }
-}
-
-//----------------------------------------------------------------------------
-static void processCompileDefinitions(cmTarget *tgt,
- const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
- std::vector<std::string> &options,
- std::set<std::string> &uniqueOptions,
- cmGeneratorExpressionDAGChecker *dagChecker,
- const char *config, bool debugOptions)
-{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions,
- "definitions");
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
- const char *config)
-{
- std::set<std::string> uniqueOptions;
- cmListFileBacktrace lfbt;
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "COMPILE_DEFINITIONS", 0, 0);
-
- std::vector<std::string> debugProperties;
- const char *debugProp =
- this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
- if (debugProp)
- {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
- }
-
- bool debugDefines = !this->DebugCompileDefinitionsDone
- && std::find(debugProperties.begin(),
- debugProperties.end(),
- "COMPILE_DEFINITIONS")
- != debugProperties.end();
-
- if (this->Makefile->IsGeneratingBuildSystem())
- {
- this->DebugCompileDefinitionsDone = true;
- }
-
- processCompileDefinitions(this,
- this->Internal->CompileDefinitionsEntries,
- list,
- uniqueOptions,
- &dagChecker,
- config,
- debugDefines);
-
- std::string configString = config ? config : "";
- if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString])
- {
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkInterfacePropertyEntries.begin(),
- end = this->Internal->LinkInterfacePropertyEntries.end();
- it != end; ++it)
- {
- {
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(it->Value);
- std::string targetResult = cge->Evaluate(this->Makefile, config,
- false, this, 0, 0);
- if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
- {
- continue;
- }
- }
- std::string defsGenex = "$<TARGET_PROPERTY:" +
- it->Value + ",INTERFACE_COMPILE_DEFINITIONS>";
- if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
- {
- // Because it->Value is a generator expression, ensure that it
- // evaluates to the non-empty string before being used in the
- // TARGET_PROPERTY expression.
- defsGenex = "$<$<BOOL:" + it->Value + ">:" + defsGenex + ">";
- }
- cmGeneratorExpression ge(it->Backtrace);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
- defsGenex);
-
- this->Internal
- ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
- new cmTargetInternals::TargetPropertyEntry(cge,
- it->Value));
- }
- if (config)
- {
- std::string configPropName = "COMPILE_DEFINITIONS_"
- + cmSystemTools::UpperCase(config);
- const char *configProp = this->GetProperty(configPropName.c_str());
- std::string defsString = (configProp ? configProp : "");
-
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(defsString);
- this->Internal
- ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
- new cmTargetInternals::TargetPropertyEntry(cge));
- }
-
- }
-
- processCompileDefinitions(this,
- this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[configString],
- list,
- uniqueOptions,
- &dagChecker,
- config,
- debugDefines);
-
- if (!this->Makefile->IsGeneratingBuildSystem())
- {
- deleteAndClear(this->Internal
- ->CachedLinkInterfaceCompileDefinitionsEntries);
- }
- else
- {
- this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]
- = true;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
-{
- // Wipe out maps caching information affected by this property.
- if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
- {
- this->Internal->ImportInfoMap.clear();
- }
- if(!this->IsImported() && strncmp(prop, "LINK_INTERFACE_", 15) == 0)
- {
- this->ClearLinkMaps();
- }
-}
-
-//----------------------------------------------------------------------------
-static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
- const char* prop, const char* value, cmMakefile* context, bool imported
- )
+static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
+ const char* value,
+ cmMakefile* context,
+ bool imported)
{
// Look for link-type keywords in the value.
- static cmsys::RegularExpression
- keys("(^|;)(debug|optimized|general)(;|$)");
- if(!keys.find(value))
- {
+ static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)");
+ if (!keys.find(value)) {
return;
- }
+ }
// Support imported and non-imported versions of the property.
- const char* base = (imported?
- "IMPORTED_LINK_INTERFACE_LIBRARIES" :
- "LINK_INTERFACE_LIBRARIES");
+ const char* base = (imported ? "IMPORTED_LINK_INTERFACE_LIBRARIES"
+ : "LINK_INTERFACE_LIBRARIES");
// Report an error.
- cmOStringStream e;
+ std::ostringstream e;
e << "Property " << prop << " may not contain link-type keyword \""
<< keys.match(2) << "\". "
<< "The " << base << " property has a per-configuration "
<< "version called " << base << "_<CONFIG> which may be "
<< "used to specify per-configuration rules.";
- if(!imported)
- {
+ if (!imported) {
e << " "
<< "Alternatively, an IMPORTED library may be created, configured "
<< "with a per-configuration location, and then named in the "
@@ -3809,2220 +1122,398 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
<< "The command automatically recognizes link-type keywords and sets "
<< "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG "
<< "properties accordingly.";
- }
+ }
context->IssueMessage(cmake::FATAL_ERROR, e.str());
}
-//----------------------------------------------------------------------------
static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
cmMakefile* context)
{
// Look for link-type keywords in the value.
- static cmsys::RegularExpression
- keys("(^|;)(debug|optimized|general)(;|$)");
- if(!keys.find(value))
- {
+ static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)");
+ if (!keys.find(value)) {
return;
- }
+ }
// Report an error.
- cmOStringStream e;
+ std::ostringstream e;
e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
- "keyword \"" << keys.match(2) << "\". The INTERFACE_LINK_LIBRARIES "
- "property may contain configuration-sensitive generator-expressions "
- "which may be used to specify per-configuration rules.";
+ "keyword \""
+ << keys.match(2)
+ << "\". The INTERFACE_LINK_LIBRARIES "
+ "property may contain configuration-sensitive generator-expressions "
+ "which may be used to specify per-configuration rules.";
context->IssueMessage(cmake::FATAL_ERROR, e.str());
}
-//----------------------------------------------------------------------------
-void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
+void cmTarget::CheckProperty(const std::string& prop,
+ cmMakefile* context) const
{
// Certain properties need checking.
- if(strncmp(prop, "LINK_INTERFACE_LIBRARIES", 24) == 0)
- {
- if(const char* value = this->GetProperty(prop))
- {
+ if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) {
+ if (const char* value = this->GetProperty(prop)) {
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, false);
- }
}
- if(strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES", 33) == 0)
- {
- if(const char* value = this->GetProperty(prop))
- {
+ }
+ if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) {
+ if (const char* value = this->GetProperty(prop)) {
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
- }
}
- if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0)
- {
- if(const char* value = this->GetProperty(prop))
- {
+ }
+ if (cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) {
+ if (const char* value = this->GetProperty(prop)) {
cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
- }
}
+ }
}
-//----------------------------------------------------------------------------
-void cmTarget::MarkAsImported()
-{
- this->IsImportedTarget = true;
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::HaveWellDefinedOutputFiles()
-{
- return
- this->GetType() == cmTarget::STATIC_LIBRARY ||
- this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY ||
- this->GetType() == cmTarget::EXECUTABLE;
-}
-
-//----------------------------------------------------------------------------
-cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config)
-{
- // There is no output information for imported targets.
- if(this->IsImported())
- {
- return 0;
- }
-
- // Only libraries and executables have well-defined output files.
- if(!this->HaveWellDefinedOutputFiles())
- {
- std::string msg = "cmTarget::GetOutputInfo called for ";
- msg += this->GetName();
- msg += " which has type ";
- msg += cmTarget::GetTargetTypeName(this->GetType());
- this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg);
- abort();
- return 0;
- }
-
- // Lookup/compute/cache the output information for this configuration.
- std::string config_upper;
- if(config && *config)
- {
- config_upper = cmSystemTools::UpperCase(config);
- }
- typedef cmTargetInternals::OutputInfoMapType OutputInfoMapType;
- OutputInfoMapType::const_iterator i =
- this->Internal->OutputInfoMap.find(config_upper);
- if(i == this->Internal->OutputInfoMap.end())
- {
- OutputInfo info;
- this->ComputeOutputDir(config, false, info.OutDir);
- this->ComputeOutputDir(config, true, info.ImpDir);
- if(!this->ComputePDBOutputDir(config, info.PdbDir))
- {
- info.PdbDir = info.OutDir;
+const char* cmTarget::GetComputedProperty(
+ const std::string& prop, cmMessenger* messenger,
+ cmListFileBacktrace const& context) const
+{
+ return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context);
+}
+
+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);
+ MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
+ MAKE_STATIC_PROP(COMPILE_FEATURES);
+ MAKE_STATIC_PROP(COMPILE_OPTIONS);
+ MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
+ MAKE_STATIC_PROP(IMPORTED);
+ 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);
+ }
+ if (specialProps.count(prop)) {
+ if (prop == propLINK_LIBRARIES) {
+ if (this->Internal->LinkImplementationPropertyEntries.empty()) {
+ return CM_NULLPTR;
}
- OutputInfoMapType::value_type entry(config_upper, info);
- i = this->Internal->OutputInfoMap.insert(entry).first;
- }
- return &i->second;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetDirectory(const char* config, bool implib)
-{
- if (this->IsImported())
- {
- // Return the directory from which the target is imported.
- return
- cmSystemTools::GetFilenamePath(
- this->ImportedGetFullPath(config, implib));
- }
- else if(OutputInfo const* info = this->GetOutputInfo(config))
- {
- // Return the directory in which the target will be built.
- return implib? info->ImpDir : info->OutDir;
- }
- return "";
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetPDBDirectory(const char* config)
-{
- if(OutputInfo const* info = this->GetOutputInfo(config))
- {
- // Return the directory in which the target will be built.
- return info->PdbDir;
- }
- return "";
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetLocation(const char* config)
-{
- if (this->IsImported())
- {
- return this->ImportedGetLocation(config);
- }
- else
- {
- return this->NormalGetLocation(config);
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::ImportedGetLocation(const char* config)
-{
- this->Location = this->ImportedGetFullPath(config, false);
- return this->Location.c_str();
-}
-//----------------------------------------------------------------------------
-const char* cmTarget::NormalGetLocation(const char* config)
-{
- // Handle the configuration-specific case first.
- if(config)
- {
- this->Location = this->GetFullPath(config, false);
- return this->Location.c_str();
+ static std::string output;
+ output = cmJoin(this->Internal->LinkImplementationPropertyEntries, ";");
+ return output.c_str();
}
-
- // Now handle the deprecated build-time configuration location.
- this->Location = this->GetDirectory();
- const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
- if(cfgid && strcmp(cfgid, ".") != 0)
- {
- this->Location += "/";
- this->Location += cfgid;
+ // the type property returns what type the target is
+ if (prop == propTYPE) {
+ return cmState::GetTargetTypeName(this->GetType());
}
-
- if(this->IsAppBundleOnApple())
- {
- std::string macdir = this->BuildMacContentDirectory("", config, false);
- if(!macdir.empty())
- {
- this->Location += "/";
- this->Location += macdir;
+ if (prop == propINCLUDE_DIRECTORIES) {
+ if (this->Internal->IncludeDirectoriesEntries.empty()) {
+ return CM_NULLPTR;
}
- }
- this->Location += "/";
- this->Location += this->GetFullName(config, false);
- return this->Location.c_str();
-}
-//----------------------------------------------------------------------------
-void cmTarget::GetTargetVersion(int& major, int& minor)
-{
- int patch;
- this->GetTargetVersion(false, major, minor, patch);
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetTargetVersion(bool soversion,
- int& major, int& minor, int& patch)
-{
- // Set the default values.
- major = 0;
- minor = 0;
- patch = 0;
-
- // Look for a VERSION or SOVERSION property.
- const char* prop = soversion? "SOVERSION" : "VERSION";
- if(const char* version = this->GetProperty(prop))
- {
- // Try to parse the version number and store the results that were
- // successfully parsed.
- int parsed_major;
- int parsed_minor;
- int parsed_patch;
- switch(sscanf(version, "%d.%d.%d",
- &parsed_major, &parsed_minor, &parsed_patch))
- {
- case 3: patch = parsed_patch; // no break!
- case 2: minor = parsed_minor; // no break!
- case 1: major = parsed_major; // no break!
- default: break;
- }
+ static std::string output;
+ output = cmJoin(this->Internal->IncludeDirectoriesEntries, ";");
+ return output.c_str();
}
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetFeature(const char* feature, const char* config)
-{
- if(config && *config)
- {
- std::string featureConfig = feature;
- featureConfig += "_";
- featureConfig += cmSystemTools::UpperCase(config);
- if(const char* value = this->GetProperty(featureConfig.c_str()))
- {
- return value;
+ if (prop == propCOMPILE_FEATURES) {
+ if (this->Internal->CompileFeaturesEntries.empty()) {
+ return CM_NULLPTR;
}
- }
- if(const char* value = this->GetProperty(feature))
- {
- return value;
- }
- return this->Makefile->GetFeature(feature, config);
-}
-
-//----------------------------------------------------------------------------
-const char *cmTarget::GetProperty(const char* prop)
-{
- return this->GetProperty(prop, cmProperty::TARGET);
-}
-//----------------------------------------------------------------------------
-const char *cmTarget::GetProperty(const char* prop,
- cmProperty::ScopeType scope)
-{
- if(!prop)
- {
- return 0;
+ static std::string output;
+ output = cmJoin(this->Internal->CompileFeaturesEntries, ";");
+ return output.c_str();
}
+ if (prop == propCOMPILE_OPTIONS) {
+ if (this->Internal->CompileOptionsEntries.empty()) {
+ return CM_NULLPTR;
+ }
- if (strcmp(prop, "NAME") == 0)
- {
- return this->GetName();
+ static std::string output;
+ output = cmJoin(this->Internal->CompileOptionsEntries, ";");
+ return output.c_str();
}
-
- // Watch for special "computed" properties that are dependent on
- // other properties or variables. Always recompute them.
- if(this->GetType() == cmTarget::EXECUTABLE ||
- this->GetType() == cmTarget::STATIC_LIBRARY ||
- this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY ||
- this->GetType() == cmTarget::UNKNOWN_LIBRARY)
- {
- if(strcmp(prop,"LOCATION") == 0)
- {
- // Set the LOCATION property of the target.
- //
- // For an imported target this is the location of an arbitrary
- // available configuration.
- //
- // For a non-imported target this is deprecated because it
- // cannot take into account the per-configuration name of the
- // target because the configuration type may not be known at
- // CMake time.
- this->SetProperty("LOCATION", this->GetLocation(0));
+ if (prop == propCOMPILE_DEFINITIONS) {
+ if (this->Internal->CompileDefinitionsEntries.empty()) {
+ return CM_NULLPTR;
}
- // Support "LOCATION_<CONFIG>".
- if(strncmp(prop, "LOCATION_", 9) == 0)
- {
- std::string configName = prop+9;
- this->SetProperty(prop, this->GetLocation(configName.c_str()));
- }
- else
- {
- // Support "<CONFIG>_LOCATION" for compatiblity.
- int len = static_cast<int>(strlen(prop));
- if(len > 9 && strcmp(prop+len-9, "_LOCATION") == 0)
- {
- std::string configName(prop, len-9);
- if(configName != "IMPORTED")
- {
- this->SetProperty(prop, this->GetLocation(configName.c_str()));
- }
- }
- }
+ static std::string output;
+ output = cmJoin(this->Internal->CompileDefinitionsEntries, ";");
+ return output.c_str();
}
- if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
- {
- static std::string output;
- output = "";
- std::string sep;
- typedef cmTargetInternals::TargetPropertyEntry
- TargetPropertyEntry;
- for (std::vector<TargetPropertyEntry*>::const_iterator
- it = this->Internal->IncludeDirectoriesEntries.begin(),
- end = this->Internal->IncludeDirectoriesEntries.end();
- it != end; ++it)
- {
- output += sep;
- output += (*it)->ge->GetInput();
- sep = ";";
+ if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
+ if (this->Utilities.empty()) {
+ return CM_NULLPTR;
}
- return output.c_str();
+
+ static std::string output;
+ output = cmJoin(this->Utilities, ";");
+ return output.c_str();
}
- if(strcmp(prop,"COMPILE_OPTIONS") == 0)
- {
- static std::string output;
- output = "";
- std::string sep;
- typedef cmTargetInternals::TargetPropertyEntry
- TargetPropertyEntry;
- for (std::vector<TargetPropertyEntry*>::const_iterator
- it = this->Internal->CompileOptionsEntries.begin(),
- end = this->Internal->CompileOptionsEntries.end();
- it != end; ++it)
- {
- output += sep;
- output += (*it)->ge->GetInput();
- sep = ";";
- }
- return output.c_str();
+ if (prop == propIMPORTED) {
+ return this->IsImported() ? "TRUE" : "FALSE";
}
- if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
- {
- static std::string output;
- output = "";
- std::string sep;
- typedef cmTargetInternals::TargetPropertyEntry
- TargetPropertyEntry;
- for (std::vector<TargetPropertyEntry*>::const_iterator
- it = this->Internal->CompileDefinitionsEntries.begin(),
- end = this->Internal->CompileDefinitionsEntries.end();
- it != end; ++it)
- {
- output += sep;
- output += (*it)->ge->GetInput();
- sep = ";";
- }
- return output.c_str();
+ if (prop == propNAME) {
+ return this->GetName().c_str();
}
-
- if (strcmp(prop,"IMPORTED") == 0)
- {
- return this->IsImported()?"TRUE":"FALSE";
+ if (prop == propBINARY_DIR) {
+ return this->GetMakefile()
+ ->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentBinary();
}
-
- if(!strcmp(prop,"SOURCES"))
- {
- cmOStringStream ss;
- const char* sep = "";
- for(std::vector<cmSourceFile*>::const_iterator
- i = this->SourceFiles.begin();
- i != this->SourceFiles.end(); ++i)
- {
- // Separate from the previous list entries.
- ss << sep;
- sep = ";";
-
- // Construct what is known about this source file location.
- cmSourceFileLocation const& location = (*i)->GetLocation();
- std::string sname = location.GetDirectory();
- if(!sname.empty())
- {
- sname += "/";
- }
- sname += location.GetName();
-
- // Append this list entry.
- ss << sname;
- }
- this->SetProperty("SOURCES", ss.str().c_str());
+ if (prop == propSOURCE_DIR) {
+ return this->GetMakefile()
+ ->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentSource();
}
+ }
- // the type property returns what type the target is
- if (!strcmp(prop,"TYPE"))
- {
- return cmTarget::GetTargetTypeName(this->GetType());
- }
- bool chain = false;
- const char *retVal =
- this->Properties.GetPropertyValue(prop, scope, chain);
- if (chain)
- {
- return this->Makefile->GetProperty(prop,scope);
+ const char* retVal = this->Properties.GetPropertyValue(prop);
+ if (!retVal) {
+ const bool chain = this->GetMakefile()->GetState()->IsPropertyChained(
+ prop, cmProperty::TARGET);
+ if (chain) {
+ return this->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
+ prop, chain);
}
+ }
return retVal;
}
-//----------------------------------------------------------------------------
-bool cmTarget::GetPropertyAsBool(const char* prop)
+bool cmTarget::GetPropertyAsBool(const std::string& prop) const
{
return cmSystemTools::IsOn(this->GetProperty(prop));
}
-//----------------------------------------------------------------------------
-class cmTargetCollectLinkLanguages
-{
-public:
- cmTargetCollectLinkLanguages(cmTarget* target, const char* config,
- std::set<cmStdString>& languages,
- cmTarget* head):
- Config(config), Languages(languages), HeadTarget(head)
- { this->Visited.insert(target); }
-
- void Visit(cmTarget* target)
- {
- if(!target || !this->Visited.insert(target).second)
- {
- return;
- }
-
- cmTarget::LinkInterface const* iface =
- target->GetLinkInterface(this->Config, this->HeadTarget);
- if(!iface) { return; }
-
- for(std::vector<std::string>::const_iterator
- li = iface->Languages.begin(); li != iface->Languages.end(); ++li)
- {
- this->Languages.insert(*li);
- }
-
- cmMakefile* mf = target->GetMakefile();
- for(std::vector<std::string>::const_iterator
- li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
- {
- this->Visit(mf->FindTargetToUse(li->c_str()));
- }
- }
-private:
- const char* Config;
- std::set<cmStdString>& Languages;
- cmTarget* HeadTarget;
- std::set<cmTarget*> Visited;
-};
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head)
-{
- cmTarget *headTarget = head ? head : this;
- const char* lang = this->GetLinkClosure(config, headTarget)
- ->LinkerLanguage.c_str();
- return *lang? lang : 0;
-}
-
-//----------------------------------------------------------------------------
-cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config,
- cmTarget *head)
-{
- TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : ""));
- cmTargetInternals::LinkClosureMapType::iterator
- i = this->Internal->LinkClosureMap.find(key);
- if(i == this->Internal->LinkClosureMap.end())
- {
- LinkClosure lc;
- this->ComputeLinkClosure(config, lc, head);
- cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
- i = this->Internal->LinkClosureMap.insert(entry).first;
- }
- return &i->second;
-}
-
-//----------------------------------------------------------------------------
-class cmTargetSelectLinker
+const char* cmTarget::GetSuffixVariableInternal(
+ cmStateEnums::ArtifactType artifact) const
{
- int Preference;
- cmTarget* Target;
- cmMakefile* Makefile;
- cmGlobalGenerator* GG;
- std::set<cmStdString> Preferred;
-public:
- cmTargetSelectLinker(cmTarget* target): Preference(0), Target(target)
- {
- this->Makefile = this->Target->GetMakefile();
- this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
- }
- void Consider(const char* lang)
- {
- int preference = this->GG->GetLinkerPreference(lang);
- if(preference > this->Preference)
- {
- this->Preference = preference;
- this->Preferred.clear();
- }
- if(preference == this->Preference)
- {
- this->Preferred.insert(lang);
- }
- }
- std::string Choose()
- {
- if(this->Preferred.empty())
- {
- return "";
- }
- else if(this->Preferred.size() > 1)
- {
- cmOStringStream e;
- e << "Target " << this->Target->GetName()
- << " contains multiple languages with the highest linker preference"
- << " (" << this->Preference << "):\n";
- for(std::set<cmStdString>::const_iterator
- li = this->Preferred.begin(); li != this->Preferred.end(); ++li)
- {
- e << " " << *li << "\n";
- }
- e << "Set the LINKER_LANGUAGE property for this target.";
- cmake* cm = this->Makefile->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
- this->Target->GetBacktrace());
+ switch (this->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
+ return "CMAKE_STATIC_LIBRARY_SUFFIX";
+ case cmStateEnums::SHARED_LIBRARY:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ return "CMAKE_SHARED_LIBRARY_SUFFIX";
+ case cmStateEnums::ImportLibraryArtifact:
+ return "CMAKE_IMPORT_LIBRARY_SUFFIX";
}
- return *this->Preferred.begin();
- }
-};
-
-//----------------------------------------------------------------------------
-void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc,
- cmTarget *head)
-{
- // Get languages built in this target.
- std::set<cmStdString> languages;
- LinkImplementation const* impl = this->GetLinkImplementation(config, head);
- for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
- li != impl->Languages.end(); ++li)
- {
- languages.insert(*li);
- }
-
- // Add interface languages from linked targets.
- cmTargetCollectLinkLanguages cll(this, config, languages, head);
- for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
- li != impl->Libraries.end(); ++li)
- {
- cll.Visit(this->Makefile->FindTargetToUse(li->c_str()));
- }
-
- // Store the transitive closure of languages.
- for(std::set<cmStdString>::const_iterator li = languages.begin();
- li != languages.end(); ++li)
- {
- lc.Languages.push_back(*li);
- }
-
- // Choose the language whose linker should be used.
- if(this->GetProperty("HAS_CXX"))
- {
- lc.LinkerLanguage = "CXX";
- }
- else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE"))
- {
- lc.LinkerLanguage = linkerLang;
- }
- else
- {
- // Find the language with the highest preference value.
- 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());
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ return "CMAKE_SHARED_MODULE_SUFFIX";
+ case cmStateEnums::ImportLibraryArtifact:
+ return "CMAKE_IMPORT_LIBRARY_SUFFIX";
}
-
- // Now consider languages that propagate from linked targets.
- for(std::set<cmStdString>::const_iterator sit = languages.begin();
- sit != languages.end(); ++sit)
- {
- std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES";
- if(this->Makefile->IsOn(propagates.c_str()))
- {
- tsl.Consider(sit->c_str());
- }
+ break;
+ case cmStateEnums::EXECUTABLE:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // Android GUI application packages store the native
+ // binary as a shared library.
+ return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ ? "CMAKE_SHARED_LIBRARY_SUFFIX"
+ : "CMAKE_EXECUTABLE_SUFFIX");
+ case cmStateEnums::ImportLibraryArtifact:
+ return "CMAKE_IMPORT_LIBRARY_SUFFIX";
}
-
- lc.LinkerLanguage = tsl.Choose();
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetSuffixVariableInternal(bool implib)
-{
- switch(this->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- return "CMAKE_STATIC_LIBRARY_SUFFIX";
- case cmTarget::SHARED_LIBRARY:
- return (implib
- ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
- : "CMAKE_SHARED_LIBRARY_SUFFIX");
- case cmTarget::MODULE_LIBRARY:
- return (implib
- ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
- : "CMAKE_SHARED_MODULE_SUFFIX");
- case cmTarget::EXECUTABLE:
- return (implib
- ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
- : "CMAKE_EXECUTABLE_SUFFIX");
+ break;
default:
break;
- }
+ }
return "";
}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetPrefixVariableInternal(bool implib)
+const char* cmTarget::GetPrefixVariableInternal(
+ cmStateEnums::ArtifactType artifact) const
{
- switch(this->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
+ switch (this->GetType()) {
+ case cmStateEnums::STATIC_LIBRARY:
return "CMAKE_STATIC_LIBRARY_PREFIX";
- case cmTarget::SHARED_LIBRARY:
- return (implib
- ? "CMAKE_IMPORT_LIBRARY_PREFIX"
- : "CMAKE_SHARED_LIBRARY_PREFIX");
- case cmTarget::MODULE_LIBRARY:
- return (implib
- ? "CMAKE_IMPORT_LIBRARY_PREFIX"
- : "CMAKE_SHARED_MODULE_PREFIX");
- case cmTarget::EXECUTABLE:
- return (implib? "CMAKE_IMPORT_LIBRARY_PREFIX" : "");
+ case cmStateEnums::SHARED_LIBRARY:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ return "CMAKE_SHARED_LIBRARY_PREFIX";
+ case cmStateEnums::ImportLibraryArtifact:
+ return "CMAKE_IMPORT_LIBRARY_PREFIX";
+ }
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ return "CMAKE_SHARED_MODULE_PREFIX";
+ case cmStateEnums::ImportLibraryArtifact:
+ return "CMAKE_IMPORT_LIBRARY_PREFIX";
+ }
+ break;
+ case cmStateEnums::EXECUTABLE:
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // Android GUI application packages store the native
+ // binary as a shared library.
+ return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ ? "CMAKE_SHARED_LIBRARY_PREFIX"
+ : "");
+ case cmStateEnums::ImportLibraryArtifact:
+ return "CMAKE_IMPORT_LIBRARY_PREFIX";
+ }
+ break;
default:
break;
- }
+ }
return "";
}
-//----------------------------------------------------------------------------
-std::string cmTarget::GetPDBName(const char* config)
+std::string cmTarget::ImportedGetFullPath(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
- std::string prefix;
- std::string base;
- std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
-
- std::vector<std::string> props;
- std::string configUpper =
- cmSystemTools::UpperCase(config? config : "");
- if(!configUpper.empty())
- {
- // PDB_NAME_<CONFIG>
- props.push_back("PDB_NAME_" + configUpper);
- }
+ assert(this->IsImported());
- // PDB_NAME
- props.push_back("PDB_NAME");
+ // Lookup/compute/cache the import information for this
+ // configuration.
+ std::string desired_config = config;
+ if (config.empty()) {
+ desired_config = "NOCONFIG";
+ }
- for(std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i)
- {
- if(const char* outName = this->GetProperty(i->c_str()))
- {
- base = outName;
- break;
- }
- }
- return prefix+base+".pdb";
-}
+ std::string result;
-//----------------------------------------------------------------------------
-bool cmTarget::HasSOName(const char* config)
-{
- // soname is supported only for shared libraries and modules,
- // and then only when the platform supports an soname flag.
- return ((this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY) &&
- !this->GetPropertyAsBool("NO_SONAME") &&
- this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config,
- this)));
-}
+ const char* loc = CM_NULLPTR;
+ const char* imp = CM_NULLPTR;
+ std::string suffix;
-//----------------------------------------------------------------------------
-std::string cmTarget::GetSOName(const char* config)
-{
- if(this->IsImported())
- {
- // Lookup the imported soname.
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
- {
- if(info->NoSOName)
- {
- // The imported library has no builtin soname so the name
- // searched at runtime will be just the filename.
- return cmSystemTools::GetFilenameName(info->Location);
- }
- else
- {
- // Use the soname given if any.
- if(info->SOName.find("@rpath/") == 0)
- {
- return info->SOName.substr(6);
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ this->GetMappedConfig(desired_config, &loc, &imp, suffix)) {
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ if (loc) {
+ result = loc;
+ } else {
+ std::string impProp = "IMPORTED_LOCATION";
+ impProp += suffix;
+ if (const char* config_location = this->GetProperty(impProp)) {
+ result = config_location;
+ } else if (const char* location =
+ this->GetProperty("IMPORTED_LOCATION")) {
+ result = location;
}
- return info->SOName;
}
- }
- else
- {
- return "";
- }
- }
- else
- {
- // 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;
- }
-}
+ break;
-//----------------------------------------------------------------------------
-bool cmTarget::HasMacOSXRpath(const char* config)
-{
- bool install_name_is_rpath = false;
- bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH");
-
- if(!this->IsImportedTarget)
- {
- const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
- bool use_install_name =
- this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
- if(install_name && use_install_name &&
- std::string(install_name) == "@rpath")
- {
- install_name_is_rpath = true;
- }
- else if(install_name && use_install_name)
- {
- return false;
- }
- }
- else
- {
- // Lookup the imported soname.
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
- {
- if(!info->NoSOName && !info->SOName.empty())
- {
- if(info->SOName.find("@rpath/") == 0)
- {
- install_name_is_rpath = true;
- }
- }
- else
- {
- std::string install_name;
- cmSystemTools::GuessLibraryInstallName(info->Location, install_name);
- if(install_name.find("@rpath") != std::string::npos)
- {
- install_name_is_rpath = true;
+ case cmStateEnums::ImportLibraryArtifact:
+ if (imp) {
+ result = imp;
+ } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports()) {
+ std::string impProp = "IMPORTED_IMPLIB";
+ impProp += suffix;
+ if (const char* config_implib = this->GetProperty(impProp)) {
+ result = config_implib;
+ } else if (const char* implib =
+ this->GetProperty("IMPORTED_IMPLIB")) {
+ result = implib;
}
}
- }
- }
-
- if(!install_name_is_rpath && !macosx_rpath)
- {
- return false;
- }
-
- if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG"))
- {
- cmOStringStream w;
- w << "Attempting to use";
- if(macosx_rpath)
- {
- w << " MACOSX_RPATH";
- }
- else
- {
- w << " @rpath";
- }
- w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
- w << " This could be because you are using a Mac OS X version";
- w << " less than 10.5 or because CMake's platform configuration is";
- w << " corrupt.";
- cmake* cm = this->Makefile->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
-{
- if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
- {
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
- {
- return info->NoSOName;
- }
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::NormalGetRealName(const char* config)
-{
- // 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 = "NormalGetRealName called on imported target: ";
- msg += this->GetName();
- this->GetMakefile()->
- IssueMessage(cmake::INTERNAL_ERROR,
- msg.c_str());
- }
-
- if(this->GetType() == cmTarget::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;
- }
- else
- {
- // 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;
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetFullName(const char* config, bool implib)
-{
- if(this->IsImported())
- {
- return this->GetFullNameImported(config, implib);
- }
- else
- {
- return this->GetFullNameInternal(config, implib);
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetFullNameImported(const char* config, bool implib)
-{
- return cmSystemTools::GetFilenameName(
- this->ImportedGetFullPath(config, implib));
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetFullNameComponents(std::string& prefix, std::string& base,
- std::string& suffix, const char* config,
- bool implib)
-{
- this->GetFullNameInternal(config, implib, prefix, base, suffix);
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetFullPath(const char* config, bool implib,
- bool realname)
-{
- if(this->IsImported())
- {
- return this->ImportedGetFullPath(config, implib);
- }
- else
- {
- return this->NormalGetFullPath(config, implib, realname);
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
- bool realname)
-{
- std::string fpath = this->GetDirectory(config, implib);
- fpath += "/";
- if(this->IsAppBundleOnApple())
- {
- fpath = this->BuildMacContentDirectory(fpath, config, false);
- fpath += "/";
- }
-
- // Add the full name of the target.
- if(implib)
- {
- fpath += this->GetFullName(config, true);
- }
- else if(realname)
- {
- fpath += this->NormalGetRealName(config);
- }
- else
- {
- fpath += this->GetFullName(config, false);
+ break;
}
- return fpath;
-}
+ }
-//----------------------------------------------------------------------------
-std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
-{
- std::string result;
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
- {
- result = implib? info->ImportLibrary : info->Location;
- }
- if(result.empty())
- {
+ if (result.empty()) {
result = this->GetName();
result += "-NOTFOUND";
- }
+ }
return result;
}
-//----------------------------------------------------------------------------
-std::string cmTarget::GetFullNameInternal(const char* config, bool implib)
-{
- std::string prefix;
- std::string base;
- std::string suffix;
- this->GetFullNameInternal(config, implib, prefix, base, suffix);
- return prefix+base+suffix;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetFullNameInternal(const char* config,
- bool implib,
- std::string& outPrefix,
- std::string& outBase,
- std::string& outSuffix)
-{
- // Use just the target name for non-main target types.
- if(this->GetType() != cmTarget::STATIC_LIBRARY &&
- this->GetType() != cmTarget::SHARED_LIBRARY &&
- this->GetType() != cmTarget::MODULE_LIBRARY &&
- this->GetType() != cmTarget::EXECUTABLE)
- {
- outPrefix = "";
- outBase = this->GetName();
- outSuffix = "";
- return;
- }
-
- // Return an empty name for the import library if this platform
- // does not support import libraries.
- if(implib &&
- !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
- {
- outPrefix = "";
- outBase = "";
- outSuffix = "";
- return;
- }
-
- // The implib option is only allowed for shared libraries, module
- // libraries, and executables.
- if(this->GetType() != cmTarget::SHARED_LIBRARY &&
- this->GetType() != cmTarget::MODULE_LIBRARY &&
- this->GetType() != cmTarget::EXECUTABLE)
- {
- implib = false;
- }
-
- // Compute the full name for main target types.
- const char* targetPrefix = (implib
- ? this->GetProperty("IMPORT_PREFIX")
- : this->GetProperty("PREFIX"));
- const char* targetSuffix = (implib
- ? this->GetProperty("IMPORT_SUFFIX")
- : this->GetProperty("SUFFIX"));
- const char* configPostfix = 0;
- if(config && *config)
- {
- std::string configProp = cmSystemTools::UpperCase(config);
- configProp += "_POSTFIX";
- configPostfix = this->GetProperty(configProp.c_str());
- // Mac application bundles and frameworks have no postfix.
- if(configPostfix &&
- (this->IsAppBundleOnApple() || this->IsFrameworkOnApple()))
- {
- configPostfix = 0;
- }
- }
- const char* prefixVar = this->GetPrefixVariableInternal(implib);
- const char* suffixVar = this->GetSuffixVariableInternal(implib);
-
- // Check for language-specific default prefix and suffix.
- if(const char* ll = this->GetLinkerLanguage(config, this))
- {
- if(!targetSuffix && suffixVar && *suffixVar)
- {
- std::string langSuff = suffixVar + std::string("_") + ll;
- targetSuffix = this->Makefile->GetDefinition(langSuff.c_str());
- }
- if(!targetPrefix && prefixVar && *prefixVar)
- {
- std::string langPrefix = prefixVar + std::string("_") + ll;
- targetPrefix = this->Makefile->GetDefinition(langPrefix.c_str());
- }
- }
-
- // 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);
- }
-
- // frameworks have directory prefix but no suffix
- std::string fw_prefix;
- if(this->IsFrameworkOnApple())
- {
- fw_prefix = this->GetOutputName(config, false);
- fw_prefix += ".framework/";
- targetPrefix = fw_prefix.c_str();
- targetSuffix = 0;
- }
-
- if(this->IsCFBundleOnApple())
- {
- fw_prefix = this->GetOutputName(config, false);
- fw_prefix += ".";
- const char *ext = this->GetProperty("BUNDLE_EXTENSION");
- if (!ext)
- {
- ext = "bundle";
- }
- fw_prefix += ext;
- fw_prefix += "/Contents/MacOS/";
- targetPrefix = fw_prefix.c_str();
- targetSuffix = 0;
- }
-
- // Begin the final name with the prefix.
- outPrefix = targetPrefix?targetPrefix:"";
-
- // Append the target name or property-specified name.
- outBase += this->GetOutputName(config, implib);
-
- // Append the per-configuration postfix.
- outBase += configPostfix?configPostfix:"";
-
- // Name shared libraries with their version number on some platforms.
- if(const char* soversion = this->GetProperty("SOVERSION"))
- {
- if(this->GetType() == cmTarget::SHARED_LIBRARY && !implib &&
- this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION"))
- {
- outBase += "-";
- outBase += soversion;
- }
- }
-
- // Append the suffix.
- outSuffix = targetSuffix?targetSuffix:"";
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetLibraryNames(std::string& name,
- std::string& soName,
- std::string& realName,
- std::string& impName,
- std::string& pdbName,
- const char* config)
-{
- // 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->Makefile->IssueMessage(cmake::INTERNAL_ERROR,
- msg.c_str());
- return;
- }
-
- // Check for library version properties.
- const char* version = this->GetProperty("VERSION");
- const char* soversion = this->GetProperty("SOVERSION");
- if(!this->HasSOName(config) ||
- this->IsFrameworkOnApple())
- {
- // Versioning is supported only for shared libraries and modules,
- // and then only when the platform supports an soname flag.
- version = 0;
- soversion = 0;
- }
- if(version && !soversion)
- {
- // The soversion must be set if the library version is set. Use
- // the library version as the soversion.
- soversion = version;
- }
- if(!version && soversion)
- {
- // Use the soversion as the library version.
- version = soversion;
- }
-
- // Get the components of the library name.
- std::string prefix;
- std::string base;
- std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
-
- // The library name.
- name = prefix+base+suffix;
-
- if(this->IsFrameworkOnApple())
- {
- realName = prefix;
- realName += "Versions/";
- realName += this->GetFrameworkVersion();
- realName += "/";
- realName += base;
- soName = realName;
- }
- else
- {
- // The library's soname.
- this->ComputeVersionedName(soName, prefix, base, suffix,
- name, soversion);
- // The library's real name on disk.
- this->ComputeVersionedName(realName, prefix, base, suffix,
- name, version);
- }
-
- // The import library name.
- if(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY)
- {
- impName = this->GetFullNameInternal(config, true);
- }
- else
- {
- impName = "";
- }
-
- // The program database file name.
- pdbName = this->GetPDBName(config);
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::ComputeVersionedName(std::string& vName,
- std::string const& prefix,
- std::string const& base,
- std::string const& suffix,
- std::string const& name,
- const char* version)
-{
- vName = this->IsApple? (prefix+base) : name;
- if(version)
- {
- vName += ".";
- vName += version;
- }
- vName += this->IsApple? suffix : std::string();
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetExecutableNames(std::string& name,
- std::string& realName,
- std::string& impName,
- std::string& pdbName,
- const char* config)
-{
- // 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->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg.c_str());
- }
-
- // This versioning is supported only for executables and then only
- // when the platform supports symbolic links.
-#if defined(_WIN32) && !defined(__CYGWIN__)
- const char* version = 0;
-#else
- // Check for executable version properties.
- const char* version = this->GetProperty("VERSION");
- if(this->GetType() != cmTarget::EXECUTABLE || this->Makefile->IsOn("XCODE"))
- {
- version = 0;
- }
-#endif
-
- // Get the components of the executable name.
- std::string prefix;
- std::string base;
- std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
-
- // The executable name.
- name = prefix+base+suffix;
-
- // The executable's real name on disk.
-#if defined(__CYGWIN__)
- realName = prefix+base;
-#else
- realName = name;
-#endif
- if(version)
- {
- realName += "-";
- realName += version;
- }
-#if defined(__CYGWIN__)
- realName += suffix;
-#endif
-
- // The import library name.
- impName = this->GetFullNameInternal(config, true);
-
- // The program database file name.
- pdbName = this->GetPDBName(config);
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::HasImplibGNUtoMS()
-{
- return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS");
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::GetImplibGNUtoMS(std::string const& gnuName,
- std::string& out, const char* newExt)
-{
- if(this->HasImplibGNUtoMS() &&
- gnuName.size() > 6 && gnuName.substr(gnuName.size()-6) == ".dll.a")
- {
- out = gnuName.substr(0, gnuName.size()-6);
- out += newExt? newExt : ".lib";
- return true;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GenerateTargetManifest(const char* config)
-{
- cmMakefile* mf = this->Makefile;
- cmLocalGenerator* lg = mf->GetLocalGenerator();
- cmGlobalGenerator* gg = lg->GetGlobalGenerator();
-
- // Get the names.
- std::string name;
- std::string soName;
- std::string realName;
- std::string impName;
- std::string pdbName;
- if(this->GetType() == cmTarget::EXECUTABLE)
- {
- this->GetExecutableNames(name, realName, impName, pdbName, config);
- }
- else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
- this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY)
- {
- this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
- }
- else
- {
- return;
- }
-
- // Get the directory.
- std::string dir = this->GetDirectory(config, false);
-
- // Add each name.
- std::string f;
- if(!name.empty())
- {
- f = dir;
- f += "/";
- f += name;
- gg->AddToManifest(config? config:"", f);
- }
- if(!soName.empty())
- {
- f = dir;
- f += "/";
- f += soName;
- gg->AddToManifest(config? config:"", f);
- }
- if(!realName.empty())
- {
- f = dir;
- f += "/";
- f += realName;
- gg->AddToManifest(config? config:"", f);
- }
- if(!pdbName.empty())
- {
- f = this->GetPDBDirectory(config);
- f += "/";
- f += pdbName;
- gg->AddToManifest(config? config:"", f);
- }
- if(!impName.empty())
- {
- f = this->GetDirectory(config, true);
- f += "/";
- f += impName;
- gg->AddToManifest(config? config:"", f);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::SetPropertyDefault(const char* property,
+void cmTarget::SetPropertyDefault(const std::string& property,
const char* default_value)
{
// Compute the name of the variable holding the default value.
std::string var = "CMAKE_";
var += property;
- if(const char* value = this->Makefile->GetDefinition(var.c_str()))
- {
+ if (const char* value = this->Makefile->GetDefinition(var)) {
this->SetProperty(property, value);
- }
- else if(default_value)
- {
+ } else if (default_value) {
this->SetProperty(property, default_value);
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::HaveBuildTreeRPATH(const char *config)
-{
- if (this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
- {
- return false;
- }
- std::vector<std::string> libs;
- this->GetDirectLinkLibraries(config, libs, this);
- return !libs.empty();
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::HaveInstallTreeRPATH()
-{
- const char* install_rpath = this->GetProperty("INSTALL_RPATH");
- return (install_rpath && *install_rpath) &&
- !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
+ }
}
-//----------------------------------------------------------------------------
-bool cmTarget::NeedRelinkBeforeInstall(const char* config)
+bool cmTarget::CheckImportedLibName(std::string const& prop,
+ std::string const& value) const
{
- // Only executables and shared libraries can have an rpath and may
- // need relinking.
- if(this->TargetTypeValue != cmTarget::EXECUTABLE &&
- this->TargetTypeValue != cmTarget::SHARED_LIBRARY &&
- this->TargetTypeValue != cmTarget::MODULE_LIBRARY)
- {
- return false;
- }
-
- // If there is no install location this target will not be installed
- // and therefore does not need relinking.
- if(!this->GetHaveInstallRule())
- {
- return false;
- }
-
- // If skipping all rpaths completely then no relinking is needed.
- if(this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
- {
- return false;
- }
-
- // If building with the install-tree rpath no relinking is needed.
- if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
- {
- return false;
- }
-
- // If chrpath is going to be used no relinking is needed.
- if(this->IsChrpathUsed(config))
- {
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY ||
+ !this->IsImported()) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, prop +
+ " property may be set only on imported INTERFACE library targets.");
return false;
- }
-
- // Check for rpath support on this platform.
- if(const char* ll = this->GetLinkerLanguage(config, this))
- {
- std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
- flagVar += ll;
- flagVar += "_FLAG";
- if(!this->Makefile->IsSet(flagVar.c_str()))
- {
- // There is no rpath support on this platform so nothing needs
- // relinking.
+ }
+ if (!value.empty()) {
+ if (value[0] == '-') {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, prop +
+ " property value\n " + value +
+ "\nmay not start with '-'.");
return false;
- }
- }
- else
- {
- // No linker language is known. This error will be reported by
- // other code.
- return false;
- }
-
- // If either a build or install tree rpath is set then the rpath
- // will likely change between the build tree and install tree and
- // this target must be relinked.
- return this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
-{
- // If building directly for installation then the build tree install_name
- // is the same as the install tree.
- if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
- {
- return GetInstallNameDirForInstallTree();
- }
-
- // Use the build tree directory for the target.
- if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
- !this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
- !this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
- {
- std::string dir;
- if(this->GetPropertyAsBool("MACOSX_RPATH"))
- {
- dir = "@rpath";
- }
- else
- {
- dir = this->GetDirectory(config);
- }
- dir += "/";
- return dir;
- }
- else
- {
- return "";
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForInstallTree()
-{
- if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
- std::string dir;
- const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
-
- if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
- !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"))
- {
- if(install_name_dir && *install_name_dir)
- {
- dir = install_name_dir;
- dir += "/";
- }
- }
- if(!install_name_dir && this->GetPropertyAsBool("MACOSX_RPATH"))
- {
- dir = "@rpath/";
- }
- return dir;
- }
- else
- {
- return "";
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetOutputTargetType(bool implib)
-{
- switch(this->GetType())
- {
- case cmTarget::SHARED_LIBRARY:
- if(this->DLLPlatform)
- {
- if(implib)
- {
- // A DLL import library is treated as an archive target.
- return "ARCHIVE";
- }
- else
- {
- // A DLL shared library is treated as a runtime target.
- return "RUNTIME";
- }
- }
- else
- {
- // For non-DLL platforms shared libraries are treated as
- // library targets.
- return "LIBRARY";
- }
- case cmTarget::STATIC_LIBRARY:
- // Static libraries are always treated as archive targets.
- return "ARCHIVE";
- case cmTarget::MODULE_LIBRARY:
- if(implib)
- {
- // Module libraries are always treated as library targets.
- return "ARCHIVE";
- }
- else
- {
- // Module import libraries are treated as archive targets.
- return "LIBRARY";
- }
- case cmTarget::EXECUTABLE:
- if(implib)
- {
- // Executable import libraries are treated as archive targets.
- return "ARCHIVE";
- }
- else
- {
- // Executables are always treated as runtime targets.
- return "RUNTIME";
- }
- default:
- break;
}
- return "";
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::ComputeOutputDir(const char* config,
- bool implib, std::string& out)
-{
- bool usesDefaultOutputDir = false;
-
- // Look for a target property defining the target output directory
- // based on the target type.
- std::string targetTypeName = this->GetOutputTargetType(implib);
- const char* propertyName = 0;
- std::string propertyNameStr = targetTypeName;
- if(!propertyNameStr.empty())
- {
- propertyNameStr += "_OUTPUT_DIRECTORY";
- propertyName = propertyNameStr.c_str();
- }
-
- // Check for a per-configuration output directory target property.
- std::string configUpper = cmSystemTools::UpperCase(config? config : "");
- const char* configProp = 0;
- std::string configPropStr = targetTypeName;
- if(!configPropStr.empty())
- {
- configPropStr += "_OUTPUT_DIRECTORY_";
- configPropStr += configUpper;
- configProp = configPropStr.c_str();
- }
-
- // Select an output directory.
- if(const char* config_outdir = this->GetProperty(configProp))
- {
- // Use the user-specified per-configuration output directory.
- out = config_outdir;
-
- // Skip per-configuration subdirectory.
- config = 0;
- }
- else if(const char* outdir = this->GetProperty(propertyName))
- {
- // Use the user-specified output directory.
- out = outdir;
- }
- else if(this->GetType() == cmTarget::EXECUTABLE)
- {
- // Lookup the output path for executables.
- out = this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
- }
- else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
- this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY)
- {
- // Lookup the output path for libraries.
- out = this->Makefile->GetSafeDefinition("LIBRARY_OUTPUT_PATH");
- }
- if(out.empty())
- {
- // Default to the current output directory.
- usesDefaultOutputDir = true;
- out = ".";
- }
-
- // Convert the output path to a full path in case it is
- // specified as a relative path. Treat a relative path as
- // relative to the current output directory for this makefile.
- out = (cmSystemTools::CollapseFullPath
- (out.c_str(), this->Makefile->GetStartOutputDirectory()));
-
- // The generator may add the configuration's subdirectory.
- if(config && *config)
- {
- const char *platforms = this->Makefile->GetDefinition(
- "CMAKE_XCODE_EFFECTIVE_PLATFORMS");
- std::string suffix =
- usesDefaultOutputDir && platforms ? "$(EFFECTIVE_PLATFORM_NAME)" : "";
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
- AppendDirectoryForConfig("/", config, suffix.c_str(), out);
- }
-
- return usesDefaultOutputDir;
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out)
-{
- // Look for a target property defining the target output directory
- // based on the target type.
- std::string targetTypeName = "PDB";
- const char* propertyName = 0;
- std::string propertyNameStr = targetTypeName;
- if(!propertyNameStr.empty())
- {
- propertyNameStr += "_OUTPUT_DIRECTORY";
- propertyName = propertyNameStr.c_str();
- }
-
- // Check for a per-configuration output directory target property.
- std::string configUpper = cmSystemTools::UpperCase(config? config : "");
- const char* configProp = 0;
- std::string configPropStr = targetTypeName;
- if(!configPropStr.empty())
- {
- configPropStr += "_OUTPUT_DIRECTORY_";
- configPropStr += configUpper;
- configProp = configPropStr.c_str();
- }
-
- // Select an output directory.
- if(const char* config_outdir = this->GetProperty(configProp))
- {
- // Use the user-specified per-configuration output directory.
- out = config_outdir;
-
- // Skip per-configuration subdirectory.
- config = 0;
- }
- else if(const char* outdir = this->GetProperty(propertyName))
- {
- // Use the user-specified output directory.
- out = outdir;
- }
- if(out.empty())
- {
- return false;
- }
-
- // Convert the output path to a full path in case it is
- // specified as a relative path. Treat a relative path as
- // relative to the current output directory for this makefile.
- out = (cmSystemTools::CollapseFullPath
- (out.c_str(), this->Makefile->GetStartOutputDirectory()));
-
- // The generator may add the configuration's subdirectory.
- if(config && *config)
- {
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
- AppendDirectoryForConfig("/", config, "", out);
+ 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) + "'.");
+ return false;
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib)
-{
- std::string dir;
- return this->ComputeOutputDir(config, implib, dir);
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetOutputName(const char* config, bool implib)
-{
- std::vector<std::string> props;
- std::string type = this->GetOutputTargetType(implib);
- std::string configUpper = cmSystemTools::UpperCase(config? config : "");
- if(!type.empty() && !configUpper.empty())
- {
- // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
- props.push_back(type + "_OUTPUT_NAME_" + configUpper);
- }
- if(!type.empty())
- {
- // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
- props.push_back(type + "_OUTPUT_NAME");
- }
- if(!configUpper.empty())
- {
- // OUTPUT_NAME_<CONFIG>
- props.push_back("OUTPUT_NAME_" + configUpper);
- // <CONFIG>_OUTPUT_NAME
- props.push_back(configUpper + "_OUTPUT_NAME");
- }
- // OUTPUT_NAME
- props.push_back("OUTPUT_NAME");
-
- for(std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i)
- {
- if(const char* outName = this->GetProperty(i->c_str()))
- {
- return outName;
- }
- }
- return this->GetName();
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetFrameworkVersion()
-{
- if(const char* fversion = this->GetProperty("FRAMEWORK_VERSION"))
- {
- return fversion;
- }
- else if(const char* tversion = this->GetProperty("VERSION"))
- {
- return tversion;
- }
- else
- {
- return "A";
- }
-}
-
-//----------------------------------------------------------------------------
-const char* cmTarget::GetExportMacro()
-{
- // Define the symbol for targets that export symbols.
- if(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY ||
- this->IsExecutableWithExports())
- {
- if(const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL"))
- {
- this->ExportMacro = custom_export_name;
- }
- else
- {
- std::string in = this->GetName();
- in += "_EXPORTS";
- this->ExportMacro = cmSystemTools::MakeCindentifier(in.c_str());
- }
- return this->ExportMacro.c_str();
- }
- else
- {
- return 0;
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p)
-{
- return this->LinkImplicitNullProperties.find(p)
- != this->LinkImplicitNullProperties.end();
-}
-
-//----------------------------------------------------------------------------
-template<typename PropertyType>
-PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
- PropertyType *);
-
-//----------------------------------------------------------------------------
-template<>
-bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
-{
- return tgt->GetPropertyAsBool(prop);
-}
-
-//----------------------------------------------------------------------------
-template<>
-const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop,
- const char **)
-{
- return tgt->GetProperty(prop);
-}
-
-//----------------------------------------------------------------------------
-template<typename PropertyType>
-bool consistentProperty(PropertyType lhs, PropertyType rhs);
-
-//----------------------------------------------------------------------------
-template<>
-bool consistentProperty(bool lhs, bool rhs)
-{
- return lhs == rhs;
-}
-
-//----------------------------------------------------------------------------
-template<>
-bool consistentProperty(const char *lhs, const char *rhs)
-{
- if (!lhs && !rhs)
- return true;
- if (!lhs || !rhs)
- return false;
- return strcmp(lhs, rhs) == 0;
-}
-
-//----------------------------------------------------------------------------
-template<typename PropertyType>
-PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
- const std::string &p,
- const char *config,
- const char *defaultValue,
- PropertyType *)
-{
- PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
- 0);
- const bool explicitlySet = tgt->GetProperties()
- .find(p.c_str())
- != tgt->GetProperties().end();
- const bool impliedByUse =
- tgt->IsNullImpliedByLinkLibraries(p);
- assert((impliedByUse ^ explicitlySet)
- || (!impliedByUse && !explicitlySet));
-
- cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
- if(!info)
- {
- return propContent;
- }
- const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
- bool propInitialized = explicitlySet;
-
- for(cmComputeLinkInformation::ItemVector::const_iterator li =
- deps.begin();
- li != deps.end(); ++li)
- {
- // 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.
-
- if (!li->Target)
- {
- continue;
- }
-
- const bool ifaceIsSet = li->Target->GetProperties()
- .find("INTERFACE_" + p)
- != li->Target->GetProperties().end();
- PropertyType ifacePropContent =
- getTypedProperty<PropertyType>(li->Target,
- ("INTERFACE_" + p).c_str(), 0);
- if (explicitlySet)
- {
- if (ifaceIsSet)
- {
- if (!consistentProperty(propContent, ifacePropContent))
- {
- cmOStringStream e;
- e << "Property " << p << " on target \""
- << tgt->GetName() << "\" does\nnot match the "
- "INTERFACE_" << p << " property requirement\nof "
- "dependency \"" << li->Target->GetName() << "\".\n";
- cmSystemTools::Error(e.str().c_str());
- break;
- }
- else
- {
- // Agree
- continue;
- }
- }
- else
- {
- // Explicitly set on target and not set in iface. Can't disagree.
- continue;
- }
- }
- else if (impliedByUse)
- {
- if (ifaceIsSet)
- {
- if (!consistentProperty(propContent, ifacePropContent))
- {
- cmOStringStream e;
- e << "Property " << p << " on target \""
- << tgt->GetName() << "\" is\nimplied to be " << defaultValue
- << " because it was used to determine the link libraries\n"
- "already. The INTERFACE_" << p << " property on\ndependency \""
- << li->Target->GetName() << "\" is in conflict.\n";
- cmSystemTools::Error(e.str().c_str());
- break;
- }
- else
- {
- // Agree
- continue;
- }
- }
- else
- {
- // Implicitly set on target and not set in iface. Can't disagree.
- continue;
- }
- }
- else
- {
- if (ifaceIsSet)
- {
- if (propInitialized)
- {
- if (!consistentProperty(propContent, ifacePropContent))
- {
- cmOStringStream e;
- e << "The INTERFACE_" << p << " property of \""
- << li->Target->GetName() << "\" does\nnot agree with the value "
- "of " << p << " already determined\nfor \""
- << tgt->GetName() << "\".\n";
- cmSystemTools::Error(e.str().c_str());
- break;
- }
- else
- {
- // Agree.
- continue;
- }
- }
- else
- {
- propContent = ifacePropContent;
- propInitialized = true;
- }
- }
- else
- {
- // Not set. Nothing to agree on.
- continue;
- }
- }
- }
- return propContent;
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
- const char *config)
-{
- return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
- 0);
-}
-
-//----------------------------------------------------------------------------
-const char * cmTarget::GetLinkInterfaceDependentStringProperty(
- const std::string &p,
- const char *config)
-{
- return checkInterfacePropertyCompatibility<const char *>(this,
- p,
- config,
- "empty", 0);
-}
-
-//----------------------------------------------------------------------------
-bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
- const char *interfaceProperty,
- const char *config)
-{
- cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
- if(!info)
- {
- return false;
- }
-
- const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
-
- for(cmComputeLinkInformation::ItemVector::const_iterator li =
- deps.begin();
- li != deps.end(); ++li)
- {
- if (!li->Target)
- {
- continue;
- }
- const char *prop = li->Target->GetProperty(interfaceProperty);
- if (!prop)
- {
- continue;
- }
-
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(prop, props);
-
- for(std::vector<std::string>::iterator pi = props.begin();
- pi != props.end(); ++pi)
- {
- if (*pi == p)
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p,
- const char *config)
-{
- if (this->TargetTypeValue == OBJECT_LIBRARY)
- {
- return false;
- }
- return (p == "POSITION_INDEPENDENT_CODE") ||
- isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL",
- config);
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p,
- const char *config)
-{
- if (this->TargetTypeValue == OBJECT_LIBRARY)
- {
- return false;
- }
- return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
- config);
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
-{
- for(std::vector<cmSourceFile*>::const_iterator
- i = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
- {
- if(const char* lang = (*i)->GetLanguage())
- {
- languages.insert(lang);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::IsChrpathUsed(const char* config)
-{
- // Only certain target types have an rpath.
- if(!(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->GetType() == cmTarget::MODULE_LIBRARY ||
- this->GetType() == cmTarget::EXECUTABLE))
- {
- return false;
- }
-
- // If the target will not be installed we do not need to change its
- // rpath.
- if(!this->GetHaveInstallRule())
- {
- return false;
- }
-
- // Skip chrpath if skipping rpath altogether.
- if(this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
- {
- return false;
- }
-
- // Skip chrpath if it does not need to be changed at install time.
- if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
- {
- return false;
- }
-
- // Allow the user to disable builtin chrpath explicitly.
- if(this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH"))
- {
- return false;
- }
-
- if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
- {
- return true;
- }
-
-#if defined(CMAKE_USE_ELF_PARSER)
- // Enable if the rpath flag uses a separator and the target uses ELF
- // binaries.
- if(const char* ll = this->GetLinkerLanguage(config, this))
- {
- std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
- sepVar += ll;
- sepVar += "_FLAG_SEP";
- const char* sep = this->Makefile->GetDefinition(sepVar.c_str());
- if(sep && *sep)
- {
- // TODO: Add ELF check to ABI detection and get rid of
- // CMAKE_EXECUTABLE_FORMAT.
- if(const char* fmt =
- this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT"))
- {
- return strcmp(fmt, "ELF") == 0;
- }
- }
- }
-#endif
- static_cast<void>(config);
- return false;
-}
-
-//----------------------------------------------------------------------------
-cmTarget::ImportInfo const*
-cmTarget::GetImportInfo(const char* config, cmTarget *headTarget)
+bool cmTarget::GetMappedConfig(std::string const& desired_config,
+ const char** loc, const char** imp,
+ std::string& suffix) const
{
- // There is no imported information for non-imported targets.
- if(!this->IsImported())
- {
- return 0;
- }
-
- // Lookup/compute/cache the import information for this
- // configuration.
std::string config_upper;
- if(config && *config)
- {
- config_upper = cmSystemTools::UpperCase(config);
- }
- else
- {
- config_upper = "NOCONFIG";
- }
- TargetConfigPair key(headTarget, config_upper);
- typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType;
-
- ImportInfoMapType::const_iterator i =
- this->Internal->ImportInfoMap.find(key);
- if(i == this->Internal->ImportInfoMap.end())
- {
- ImportInfo info;
- this->ComputeImportInfo(config_upper, info, headTarget);
- ImportInfoMapType::value_type entry(key, info);
- i = this->Internal->ImportInfoMap.insert(entry).first;
- }
-
- // If the location is empty then the target is not available for
- // this configuration.
- if(i->second.Location.empty() && i->second.ImportLibrary.empty())
- {
- return 0;
- }
+ if (!desired_config.empty()) {
+ config_upper = cmSystemTools::UpperCase(desired_config);
+ }
- // Return the import information.
- return &i->second;
-}
+ std::string locPropBase;
+ if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ locPropBase = "IMPORTED_LIBNAME";
+ } else if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ locPropBase = "IMPORTED_OBJECTS";
+ } else {
+ locPropBase = "IMPORTED_LOCATION";
+ }
-bool cmTarget::GetMappedConfig(std::string const& desired_config,
- const char** loc,
- const char** imp,
- std::string& suffix)
-{
// Track the configuration-specific property suffix.
suffix = "_";
- suffix += desired_config;
+ suffix += config_upper;
std::vector<std::string> mappedConfigs;
{
- std::string mapProp = "MAP_IMPORTED_CONFIG_";
- mapProp += desired_config;
- if(const char* mapValue = this->GetProperty(mapProp.c_str()))
- {
- cmSystemTools::ExpandListArgument(mapValue, mappedConfigs);
+ std::string mapProp = "MAP_IMPORTED_CONFIG_";
+ mapProp += config_upper;
+ if (const char* mapValue = this->GetProperty(mapProp)) {
+ cmSystemTools::ExpandListArgument(mapValue, mappedConfigs, true);
}
}
@@ -6032,1028 +1523,114 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
bool allowImp = this->HasImportLibrary();
// If a mapping was found, check its configurations.
- for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
- !*loc && !*imp && mci != mappedConfigs.end(); ++mci)
- {
+ for (std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
+ !*loc && !*imp && mci != mappedConfigs.end(); ++mci) {
// Look for this configuration.
- std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
- std::string locProp = "IMPORTED_LOCATION_";
- locProp += mcUpper;
- *loc = this->GetProperty(locProp.c_str());
- if(allowImp)
- {
- std::string impProp = "IMPORTED_IMPLIB_";
- impProp += mcUpper;
- *imp = this->GetProperty(impProp.c_str());
- }
-
- // If it was found, use it for all properties below.
- if(*loc || *imp)
- {
- suffix = "_";
- suffix += mcUpper;
+ if (mci->empty()) {
+ // An empty string in the mapping has a special meaning:
+ // look up the config-less properties.
+ *loc = this->GetProperty(locPropBase);
+ if (allowImp) {
+ *imp = this->GetProperty("IMPORTED_IMPLIB");
+ }
+ // If it was found, set the suffix.
+ if (*loc || *imp) {
+ suffix = "";
+ }
+ } else {
+ std::string mcUpper = cmSystemTools::UpperCase(*mci);
+ std::string locProp = locPropBase + "_";
+ locProp += mcUpper;
+ *loc = this->GetProperty(locProp);
+ if (allowImp) {
+ std::string impProp = "IMPORTED_IMPLIB_";
+ impProp += mcUpper;
+ *imp = this->GetProperty(impProp);
+ }
+
+ // If it was found, use it for all properties below.
+ if (*loc || *imp) {
+ suffix = "_";
+ suffix += mcUpper;
}
}
+ }
// If we needed to find one of the mapped configurations but did not
- // then the target is not found. The project does not want any
- // other configuration.
- if(!mappedConfigs.empty() && !*loc && !*imp)
- {
- return false;
- }
+ // then the target location is not found. The project does not want
+ // any other configuration.
+ if (!mappedConfigs.empty() && !*loc && !*imp) {
+ // Interface libraries are always available because their
+ // library name is optional so it is okay to leave *loc empty.
+ return this->GetType() == cmStateEnums::INTERFACE_LIBRARY;
+ }
// If we have not yet found it then there are no mapped
// configurations. Look for an exact-match.
- if(!*loc && !*imp)
- {
- std::string locProp = "IMPORTED_LOCATION";
+ if (!*loc && !*imp) {
+ std::string locProp = locPropBase;
locProp += suffix;
- *loc = this->GetProperty(locProp.c_str());
- if(allowImp)
- {
+ *loc = this->GetProperty(locProp);
+ if (allowImp) {
std::string impProp = "IMPORTED_IMPLIB";
impProp += suffix;
- *imp = this->GetProperty(impProp.c_str());
- }
+ *imp = this->GetProperty(impProp);
}
+ }
// If we have not yet found it then there are no mapped
// configurations and no exact match.
- if(!*loc && !*imp)
- {
+ if (!*loc && !*imp) {
// The suffix computed above is not useful.
suffix = "";
// Look for a configuration-less location. This may be set by
// manually-written code.
- *loc = this->GetProperty("IMPORTED_LOCATION");
- if(allowImp)
- {
+ *loc = this->GetProperty(locPropBase);
+ if (allowImp) {
*imp = this->GetProperty("IMPORTED_IMPLIB");
- }
}
+ }
// If we have not yet found it then the project is willing to try
// any available configuration.
- if(!*loc && !*imp)
- {
+ if (!*loc && !*imp) {
std::vector<std::string> availableConfigs;
- if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
- {
+ if (const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
cmSystemTools::ExpandListArgument(iconfigs, availableConfigs);
- }
- for(std::vector<std::string>::const_iterator
- aci = availableConfigs.begin();
- !*loc && !*imp && aci != availableConfigs.end(); ++aci)
- {
+ }
+ for (std::vector<std::string>::const_iterator aci =
+ availableConfigs.begin();
+ !*loc && !*imp && aci != availableConfigs.end(); ++aci) {
suffix = "_";
suffix += cmSystemTools::UpperCase(*aci);
- std::string locProp = "IMPORTED_LOCATION";
+ std::string locProp = locPropBase;
locProp += suffix;
- *loc = this->GetProperty(locProp.c_str());
- if(allowImp)
- {
+ *loc = this->GetProperty(locProp);
+ if (allowImp) {
std::string impProp = "IMPORTED_IMPLIB";
impProp += suffix;
- *imp = this->GetProperty(impProp.c_str());
- }
+ *imp = this->GetProperty(impProp);
}
}
- // If we have not yet found it then the target is not available.
- if(!*loc && !*imp)
- {
- return false;
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::ComputeImportInfo(std::string const& desired_config,
- ImportInfo& info,
- cmTarget *headTarget)
-{
- // This method finds information about an imported target from its
- // properties. The "IMPORTED_" namespace is reserved for properties
- // defined by the project exporting the target.
-
- // Initialize members.
- info.NoSOName = false;
-
- const char* loc = 0;
- const char* imp = 0;
- std::string suffix;
- if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
- {
- return;
- }
-
- // A provided configuration has been chosen. Load the
- // configuration's properties.
-
- // Get the location.
- if(loc)
- {
- info.Location = loc;
- }
- else
- {
- std::string impProp = "IMPORTED_LOCATION";
- impProp += suffix;
- if(const char* config_location = this->GetProperty(impProp.c_str()))
- {
- info.Location = config_location;
- }
- else if(const char* location = this->GetProperty("IMPORTED_LOCATION"))
- {
- info.Location = location;
- }
- }
-
- // Get the soname.
- if(this->GetType() == cmTarget::SHARED_LIBRARY)
- {
- std::string soProp = "IMPORTED_SONAME";
- soProp += suffix;
- if(const char* config_soname = this->GetProperty(soProp.c_str()))
- {
- info.SOName = config_soname;
- }
- else if(const char* soname = this->GetProperty("IMPORTED_SONAME"))
- {
- info.SOName = soname;
- }
- }
-
- // Get the "no-soname" mark.
- if(this->GetType() == cmTarget::SHARED_LIBRARY)
- {
- std::string soProp = "IMPORTED_NO_SONAME";
- soProp += suffix;
- if(const char* config_no_soname = this->GetProperty(soProp.c_str()))
- {
- info.NoSOName = cmSystemTools::IsOn(config_no_soname);
- }
- else if(const char* no_soname = this->GetProperty("IMPORTED_NO_SONAME"))
- {
- info.NoSOName = cmSystemTools::IsOn(no_soname);
- }
- }
-
- // Get the import library.
- if(imp)
- {
- info.ImportLibrary = imp;
- }
- else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->IsExecutableWithExports())
- {
- std::string impProp = "IMPORTED_IMPLIB";
- impProp += suffix;
- if(const char* config_implib = this->GetProperty(impProp.c_str()))
- {
- info.ImportLibrary = config_implib;
- }
- else if(const char* implib = this->GetProperty("IMPORTED_IMPLIB"))
- {
- info.ImportLibrary = implib;
- }
- }
-
- // Get the link interface.
- {
- std::string linkProp = "INTERFACE_LINK_LIBRARIES";
- const char *propertyLibs = this->GetProperty(linkProp.c_str());
-
- if (!propertyLibs)
- {
- linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- linkProp += suffix;
- propertyLibs = this->GetProperty(linkProp.c_str());
- }
-
- if(!propertyLibs)
- {
- linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- propertyLibs = this->GetProperty(linkProp.c_str());
- }
- if(propertyLibs)
- {
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- linkProp, 0, 0);
- cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs)
- ->Evaluate(this->Makefile,
- desired_config.c_str(),
- false,
- headTarget,
- this,
- &dagChecker),
- info.LinkInterface.Libraries);
- }
}
-
- // Get the link dependencies.
- {
- std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
- linkProp += suffix;
- if(const char* config_libs = this->GetProperty(linkProp.c_str()))
- {
- cmSystemTools::ExpandListArgument(config_libs,
- info.LinkInterface.SharedDeps);
- }
- else if(const char* libs =
- this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES"))
- {
- cmSystemTools::ExpandListArgument(libs, info.LinkInterface.SharedDeps);
- }
+ // If we have not yet found it then the target location is not available.
+ if (!*loc && !*imp) {
+ // Interface libraries are always available because their
+ // library name is optional so it is okay to leave *loc empty.
+ return this->GetType() == cmStateEnums::INTERFACE_LIBRARY;
}
- // Get the link languages.
- if(this->LinkLanguagePropagatesToDependents())
- {
- std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
- linkProp += suffix;
- if(const char* config_libs = this->GetProperty(linkProp.c_str()))
- {
- cmSystemTools::ExpandListArgument(config_libs,
- info.LinkInterface.Languages);
- }
- else if(const char* libs =
- this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES"))
- {
- cmSystemTools::ExpandListArgument(libs,
- info.LinkInterface.Languages);
- }
- }
-
- // Get the cyclic repetition count.
- if(this->GetType() == cmTarget::STATIC_LIBRARY)
- {
- std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
- linkProp += suffix;
- if(const char* config_reps = this->GetProperty(linkProp.c_str()))
- {
- sscanf(config_reps, "%u", &info.LinkInterface.Multiplicity);
- }
- else if(const char* reps =
- this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY"))
- {
- sscanf(reps, "%u", &info.LinkInterface.Multiplicity);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
- cmTarget *head)
-{
- // Imported targets have their own link interface.
- if(this->IsImported())
- {
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head))
- {
- return &info->LinkInterface;
- }
- return 0;
- }
-
- // Link interfaces are not supported for executables that do not
- // export symbols.
- if(this->GetType() == cmTarget::EXECUTABLE &&
- !this->IsExecutableWithExports())
- {
- return 0;
- }
-
- // Lookup any existing link interface for this configuration.
- TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
-
- cmTargetInternals::LinkInterfaceMapType::iterator
- i = this->Internal->LinkInterfaceMap.find(key);
- if(i == this->Internal->LinkInterfaceMap.end())
- {
- // Compute the link interface for this configuration.
- cmTargetInternals::OptionalLinkInterface iface;
- iface.Exists = this->ComputeLinkInterface(config, iface, head);
-
- // Store the information for this configuration.
- cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface);
- i = this->Internal->LinkInterfaceMap.insert(entry).first;
- }
-
- return i->second.Exists? &i->second : 0;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::GetTransitivePropertyLinkLibraries(
- const char* config,
- cmTarget *headTarget,
- std::vector<std::string> &libs)
-{
- cmTarget::LinkInterface const* iface = this->GetLinkInterface(config,
- headTarget);
- if (!iface)
- {
- return;
- }
- if(this->GetType() != STATIC_LIBRARY
- || this->GetPolicyStatusCMP0022() == cmPolicies::WARN
- || this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
- {
- libs = iface->Libraries;
- return;
- }
-
- const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
- const char* interfaceLibs = this->GetProperty(linkIfaceProp);
-
- if (!interfaceLibs)
- {
- return;
- }
-
- // The interface libraries have been explicitly set.
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
- cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
- linkIfaceProp, 0, 0);
- dagChecker.SetTransitivePropertiesOnly();
- cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate(
- this->Makefile,
- config,
- false,
- headTarget,
- this, &dagChecker), libs);
-}
-
-//----------------------------------------------------------------------------
-bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
- cmTarget *headTarget)
-{
- // Construct the property name suffix for this configuration.
- std::string suffix = "_";
- if(config && *config)
- {
- suffix += cmSystemTools::UpperCase(config);
- }
- else
- {
- suffix += "NOCONFIG";
- }
-
- // An explicit list of interface libraries may be set for shared
- // libraries and executables that export symbols.
- const char* explicitLibraries = 0;
- std::string linkIfaceProp;
- if(this->PolicyStatusCMP0022 != cmPolicies::OLD &&
- this->PolicyStatusCMP0022 != cmPolicies::WARN)
- {
- // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
- linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
- explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
- }
- else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->IsExecutableWithExports())
- {
- // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
- // shared lib or executable.
-
- // Lookup the per-configuration property.
- linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
- linkIfaceProp += suffix;
- explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
-
- // If not set, try the generic property.
- if(!explicitLibraries)
- {
- linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
- explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
- }
- }
-
- if(explicitLibraries && this->PolicyStatusCMP0022 == cmPolicies::WARN &&
- !this->Internal->PolicyWarnedCMP0022)
- {
- // Compare the explicitly set old link interface properties to the
- // preferred new link interface property one and warn if different.
- const char* newExplicitLibraries =
- this->GetProperty("INTERFACE_LINK_LIBRARIES");
- if (newExplicitLibraries
- && strcmp(newExplicitLibraries, explicitLibraries) != 0)
- {
- cmOStringStream w;
- w <<
- (this->Makefile->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
- "Target \"" << this->GetName() << "\" has an "
- "INTERFACE_LINK_LIBRARIES property which differs from its " <<
- linkIfaceProp << " properties."
- "\n"
- "INTERFACE_LINK_LIBRARIES:\n"
- " " << newExplicitLibraries << "\n" <<
- linkIfaceProp << ":\n"
- " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
- this->Internal->PolicyWarnedCMP0022 = true;
- }
- }
-
- // There is no implicit link interface for executables or modules
- // so if none was explicitly set then there is no link interface.
- // Note that CMake versions 2.2 and below allowed linking to modules.
- bool canLinkModules = this->Makefile->NeedBackwardsCompatibility(2,2);
- if(!explicitLibraries &&
- (this->GetType() == cmTarget::EXECUTABLE ||
- (this->GetType() == cmTarget::MODULE_LIBRARY && !canLinkModules)))
- {
- return false;
- }
-
- if(explicitLibraries)
- {
- // The interface libraries have been explicitly set.
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
- cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
- linkIfaceProp, 0, 0);
- cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate(
- this->Makefile,
- config,
- false,
- headTarget,
- this, &dagChecker), iface.Libraries);
-
- if(this->GetType() == cmTarget::SHARED_LIBRARY
- || this->GetType() == cmTarget::STATIC_LIBRARY)
- {
- // Shared libraries may have runtime implementation dependencies
- // on other shared libraries that are not in the interface.
- std::set<cmStdString> emitted;
- for(std::vector<std::string>::const_iterator
- li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li)
- {
- emitted.insert(*li);
- }
- LinkImplementation const* impl = this->GetLinkImplementation(config,
- headTarget);
- for(std::vector<std::string>::const_iterator
- li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
- {
- if(emitted.insert(*li).second)
- {
- if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->c_str()))
- {
- // This is a runtime dependency on another shared library.
- if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
- {
- iface.SharedDeps.push_back(*li);
- }
- }
- else
- {
- // TODO: Recognize shared library file names. Perhaps this
- // should be moved to cmComputeLinkInformation, but that creates
- // a chicken-and-egg problem since this list is needed for its
- // construction.
- }
- }
- }
- if(this->LinkLanguagePropagatesToDependents())
- {
- // Targets using this archive need its language runtime libraries.
- iface.Languages = impl->Languages;
- }
- }
- }
- else if (this->PolicyStatusCMP0022 == cmPolicies::WARN
- || this->PolicyStatusCMP0022 == cmPolicies::OLD)
- // 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
- // to the link implementation.
- {
- // The link implementation is the default link interface.
- LinkImplementation const* impl = this->GetLinkImplementation(config,
- headTarget);
- iface.ImplementationIsInterface = true;
- iface.Libraries = impl->Libraries;
- iface.WrongConfigLibraries = impl->WrongConfigLibraries;
- if(this->LinkLanguagePropagatesToDependents())
- {
- // Targets using this archive need its language runtime libraries.
- iface.Languages = impl->Languages;
- }
-
- if(this->PolicyStatusCMP0022 == cmPolicies::WARN &&
- !this->Internal->PolicyWarnedCMP0022)
- {
- // Compare the link implementation fallback link interface to the
- // preferred new link interface property and warn if different.
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
- cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
- "INTERFACE_LINK_LIBRARIES", 0, 0);
- std::vector<std::string> ifaceLibs;
- const char* newExplicitLibraries =
- this->GetProperty("INTERFACE_LINK_LIBRARIES");
- cmSystemTools::ExpandListArgument(
- ge.Parse(newExplicitLibraries)->Evaluate(this->Makefile,
- config,
- false,
- headTarget,
- this, &dagChecker),
- ifaceLibs);
- if (ifaceLibs != impl->Libraries)
- {
- std::string oldLibraries;
- std::string newLibraries;
- const char *sep = "";
- for(std::vector<std::string>::const_iterator it
- = impl->Libraries.begin(); it != impl->Libraries.end(); ++it)
- {
- oldLibraries += sep;
- oldLibraries += *it;
- sep = ";";
- }
- sep = "";
- for(std::vector<std::string>::const_iterator it
- = ifaceLibs.begin(); it != ifaceLibs.end(); ++it)
- {
- newLibraries += sep;
- newLibraries += *it;
- sep = ";";
- }
- if(oldLibraries.empty())
- { oldLibraries = "(empty)"; }
- if(newLibraries.empty())
- { newLibraries = "(empty)"; }
-
- cmOStringStream w;
- w <<
- (this->Makefile->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
- "Target \"" << this->GetName() << "\" has an "
- "INTERFACE_LINK_LIBRARIES property. "
- "This should be preferred as the source of the link interface "
- "for this library but because CMP0022 is not set CMake is "
- "ignoring the property and using the link implementation "
- "as the link interface instead."
- "\n"
- "INTERFACE_LINK_LIBRARIES:\n"
- " " << newLibraries << "\n"
- "Link implementation:\n"
- " " << oldLibraries << "\n";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
- this->Internal->PolicyWarnedCMP0022 = true;
- }
- }
- }
-
- if(this->GetType() == cmTarget::STATIC_LIBRARY)
- {
- // How many repetitions are needed if this library has cyclic
- // dependencies?
- std::string propName = "LINK_INTERFACE_MULTIPLICITY";
- propName += suffix;
- if(const char* config_reps = this->GetProperty(propName.c_str()))
- {
- sscanf(config_reps, "%u", &iface.Multiplicity);
- }
- else if(const char* reps =
- this->GetProperty("LINK_INTERFACE_MULTIPLICITY"))
- {
- sscanf(reps, "%u", &iface.Multiplicity);
- }
- }
-
return true;
}
-//----------------------------------------------------------------------------
-cmTarget::LinkImplementation const*
-cmTarget::GetLinkImplementation(const char* config, cmTarget *head)
-{
- // There is no link implementation for imported targets.
- if(this->IsImported())
- {
- return 0;
- }
-
- // Lookup any existing link implementation for this configuration.
- TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
-
- cmTargetInternals::LinkImplMapType::iterator
- i = this->Internal->LinkImplMap.find(key);
- if(i == this->Internal->LinkImplMap.end())
- {
- // Compute the link implementation for this configuration.
- LinkImplementation impl;
- this->ComputeLinkImplementation(config, impl, head);
-
- // Store the information for this configuration.
- cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
- i = this->Internal->LinkImplMap.insert(entry).first;
- }
-
- return &i->second;
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::ComputeLinkImplementation(const char* config,
- LinkImplementation& impl,
- cmTarget *head)
-{
- // Compute which library configuration to link.
- cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
-
- // Collect libraries directly linked in this configuration.
- std::vector<std::string> llibs;
- this->GetDirectLinkLibraries(config, llibs, head);
- for(std::vector<std::string>::const_iterator li = llibs.begin();
- li != llibs.end(); ++li)
- {
- // Skip entries that resolve to the target itself or are empty.
- std::string item = this->CheckCMP0004(*li);
- if(item == this->GetName() || item.empty())
- {
- continue;
- }
- // The entry is meant for this configuration.
- impl.Libraries.push_back(item);
- }
-
- LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries();
- for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin();
- li != oldllibs.end(); ++li)
- {
- if(li->second != cmTarget::GENERAL && li->second != linkType)
- {
- std::string item = this->CheckCMP0004(li->first);
- if(item == this->GetName() || item.empty())
- {
- continue;
- }
- // Support OLD behavior for CMP0003.
- impl.WrongConfigLibraries.push_back(item);
- }
- }
-
- // This target needs runtime libraries for its source languages.
- std::set<cmStdString> languages;
- // Get languages used in our source files.
- this->GetLanguages(languages);
- // Get languages used in object library sources.
- for(std::vector<std::string>::iterator i = this->ObjectLibraries.begin();
- i != this->ObjectLibraries.end(); ++i)
- {
- if(cmTarget* objLib = this->Makefile->FindTargetToUse(i->c_str()))
- {
- if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- objLib->GetLanguages(languages);
- }
- }
- }
- // Copy the set of langauges to the link implementation.
- for(std::set<cmStdString>::iterator li = languages.begin();
- li != languages.end(); ++li)
- {
- impl.Languages.push_back(*li);
- }
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::CheckCMP0004(std::string const& item)
-{
- // Strip whitespace off the library names because we used to do this
- // in case variables were expanded at generate time. We no longer
- // do the expansion but users link to libraries like " ${VAR} ".
- std::string lib = item;
- std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
- if(pos != lib.npos)
- {
- lib = lib.substr(pos, lib.npos);
- }
- pos = lib.find_last_not_of(" \t\r\n");
- if(pos != lib.npos)
- {
- lib = lib.substr(0, pos+1);
- }
- if(lib != item)
- {
- cmake* cm = this->Makefile->GetCMakeInstance();
- switch(this->PolicyStatusCMP0004)
- {
- case cmPolicies::WARN:
- {
- cmOStringStream w;
- w << (this->Makefile->GetPolicies()
- ->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());
- }
- case cmPolicies::OLD:
- break;
- case cmPolicies::NEW:
- {
- cmOStringStream e;
- 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());
- }
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- {
- cmOStringStream e;
- e << (this->Makefile->GetPolicies()
- ->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());
- }
- break;
- }
- }
- return lib;
-}
-
-template<typename PropertyType>
-PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
- const std::string prop,
- const char *config,
- PropertyType *);
-
-template<>
-bool getLinkInterfaceDependentProperty(cmTarget *tgt,
- const std::string prop,
- const char *config, bool *)
-{
- return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
-}
-
-template<>
-const char * getLinkInterfaceDependentProperty(cmTarget *tgt,
- const std::string prop,
- const char *config,
- const char **)
-{
- return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
-}
-
-//----------------------------------------------------------------------------
-template<typename PropertyType>
-void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
- const char *propName,
- std::set<cmStdString> &emitted,
- const char *config,
- PropertyType *)
-{
- const char *prop = dependee->GetProperty(propName);
- if (!prop)
- {
- return;
- }
-
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(prop, props);
-
- for(std::vector<std::string>::iterator pi = props.begin();
- pi != props.end(); ++pi)
- {
- if (depender->GetMakefile()->GetCMakeInstance()
- ->GetIsPropertyDefined(pi->c_str(),
- cmProperty::TARGET))
- {
- cmOStringStream e;
- e << "Target \"" << dependee->GetName() << "\" has property \""
- << *pi << "\" listed in its " << propName << " property. "
- "This is not allowed. Only user-defined properties may appear "
- "listed in the " << propName << " property.";
- depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
- return;
- }
- if(emitted.insert(*pi).second)
- {
- getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
- 0);
- if (cmSystemTools::GetErrorOccuredFlag())
- {
- return;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
- const char* config)
-{
- const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
-
- std::set<cmStdString> emittedBools;
- std::set<cmStdString> emittedStrings;
-
- for(cmComputeLinkInformation::ItemVector::const_iterator li =
- deps.begin();
- li != deps.end(); ++li)
- {
- if (!li->Target)
- {
- continue;
- }
-
- checkPropertyConsistency<bool>(this, li->Target,
- "COMPATIBLE_INTERFACE_BOOL",
- emittedBools, config, 0);
- if (cmSystemTools::GetErrorOccuredFlag())
- {
- return;
- }
- checkPropertyConsistency<const char *>(this, li->Target,
- "COMPATIBLE_INTERFACE_STRING",
- emittedStrings, config, 0);
- if (cmSystemTools::GetErrorOccuredFlag())
- {
- return;
- }
- }
-
- for(std::set<cmStdString>::const_iterator li = emittedBools.begin();
- li != emittedBools.end(); ++li)
- {
- const std::set<cmStdString>::const_iterator si = emittedStrings.find(*li);
- if (si != emittedStrings.end())
- {
- cmOStringStream e;
- e << "Property \"" << *li << "\" appears in both the "
- "COMPATIBLE_INTERFACE_BOOL and the COMPATIBLE_INTERFACE_STRING "
- "property in the dependencies of target \"" << this->GetName() <<
- "\". This is not allowed. A property may only require compatibility "
- "in a boolean interpretation or a string interpretation, but not both.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- break;
- }
- }
-}
-
-//----------------------------------------------------------------------------
-cmComputeLinkInformation*
-cmTarget::GetLinkInformation(const char* config, cmTarget *head)
-{
- cmTarget *headTarget = head ? head : this;
- // Lookup any existing information for this configuration.
- TargetConfigPair key(headTarget,
- cmSystemTools::UpperCase(config?config:""));
- cmTargetLinkInformationMap::iterator
- i = this->LinkInformation.find(key);
- if(i == this->LinkInformation.end())
- {
- // Compute information for this configuration.
- cmComputeLinkInformation* info =
- new cmComputeLinkInformation(this, config, headTarget);
- if(!info || !info->Compute())
- {
- delete info;
- info = 0;
- }
-
- // Store the information for this configuration.
- cmTargetLinkInformationMap::value_type entry(key, info);
- i = this->LinkInformation.insert(entry).first;
-
- if (info)
- {
- this->CheckPropertyCompatibility(info, config);
- }
- }
- return i->second;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetFrameworkDirectory(const char* config,
- bool rootDir)
-{
- std::string fpath;
- fpath += this->GetOutputName(config, false);
- fpath += ".framework";
- if(!rootDir)
- {
- fpath += "/Versions/";
- fpath += this->GetFrameworkVersion();
- }
- return fpath;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetCFBundleDirectory(const char* config,
- bool contentOnly)
-{
- std::string fpath;
- fpath += this->GetOutputName(config, false);
- fpath += ".";
- const char *ext = this->GetProperty("BUNDLE_EXTENSION");
- if (!ext)
- {
- ext = "bundle";
- }
- fpath += ext;
- fpath += "/Contents";
- if(!contentOnly)
- fpath += "/MacOS";
- return fpath;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetAppBundleDirectory(const char* config,
- bool contentOnly)
-{
- std::string fpath = this->GetFullName(config, false);
- fpath += ".app/Contents";
- if(!contentOnly)
- fpath += "/MacOS";
- return fpath;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::BuildMacContentDirectory(const std::string& base,
- const char* config,
- bool contentOnly)
-{
- std::string fpath = base;
- if(this->IsAppBundleOnApple())
- {
- fpath += this->GetAppBundleDirectory(config, contentOnly);
- }
- if(this->IsFrameworkOnApple())
- {
- fpath += this->GetFrameworkDirectory(config, contentOnly);
- }
- if(this->IsCFBundleOnApple())
- {
- fpath += this->GetCFBundleDirectory(config, contentOnly);
- }
- return fpath;
-}
-
-//----------------------------------------------------------------------------
-std::string cmTarget::GetMacContentDirectory(const char* config,
- bool implib)
-{
- // Start with the output directory for the target.
- std::string fpath = this->GetDirectory(config, implib);
- fpath += "/";
- bool contentOnly = true;
- if(this->IsFrameworkOnApple())
- {
- // additional files with a framework go into the version specific
- // directory
- contentOnly = false;
- }
- fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
- return fpath;
-}
-
-//----------------------------------------------------------------------------
-cmTargetLinkInformationMap
-::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived()
-{
- // Ideally cmTarget instances should never be copied. However until
- // we can make a sweep to remove that, this copy constructor avoids
- // allowing the resources (LinkInformation) from getting copied. In
- // the worst case this will lead to extra cmComputeLinkInformation
- // instances. We also enforce in debug mode that the map be emptied
- // when copied.
- static_cast<void>(r);
- assert(r.empty());
-}
-
-//----------------------------------------------------------------------------
-cmTargetLinkInformationMap::~cmTargetLinkInformationMap()
-{
- for(derived::iterator i = this->begin(); i != this->end(); ++i)
- {
- delete i->second;
- }
-}
-
-//----------------------------------------------------------------------------
cmTargetInternalPointer::cmTargetInternalPointer()
{
this->Pointer = new cmTargetInternals;
}
-//----------------------------------------------------------------------------
-cmTargetInternalPointer
-::cmTargetInternalPointer(cmTargetInternalPointer const& r)
+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
@@ -7061,20 +1638,17 @@ cmTargetInternalPointer
this->Pointer = new cmTargetInternals(*r.Pointer);
}
-//----------------------------------------------------------------------------
cmTargetInternalPointer::~cmTargetInternalPointer()
{
- deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
- deleteAndClear(this->Pointer->CompileOptionsEntries);
- deleteAndClear(this->Pointer->CompileDefinitionsEntries);
delete this->Pointer;
}
-//----------------------------------------------------------------------------
-cmTargetInternalPointer&
-cmTargetInternalPointer::operator=(cmTargetInternalPointer const& r)
+cmTargetInternalPointer& cmTargetInternalPointer::operator=(
+ cmTargetInternalPointer const& r)
{
- if(this == &r) { return *this; } // avoid warning on HP about self check
+ 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.
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 27b74ca4b..1f00c0155 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -1,51 +1,32 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTarget_h
#define cmTarget_h
-#include "cmCustomCommand.h"
-#include "cmPropertyMap.h"
-#include "cmPolicies.h"
-#include "cmListFileCache.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <cmsys/auto_ptr.hxx>
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
-#define CM_FOR_EACH_TARGET_POLICY(F) \
- F(CMP0003) \
- F(CMP0004) \
- F(CMP0008) \
- F(CMP0020) \
- F(CMP0021) \
- F(CMP0022)
+#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
+#include "cmListFileCache.h"
+#include "cmPolicies.h"
+#include "cmPropertyMap.h"
+#include "cmStateTypes.h"
+#include "cmTargetLinkLibraryType.h"
+#include "cm_unordered_map.hxx"
-class cmake;
+class cmGlobalGenerator;
class cmMakefile;
+class cmMessenger;
class cmSourceFile;
-class cmGlobalGenerator;
-class cmComputeLinkInformation;
-class cmListFileBacktrace;
-class cmTarget;
-
-struct cmTargetLinkInformationMap:
- public std::map<std::pair<cmTarget*, std::string>, cmComputeLinkInformation*>
-{
- typedef std::map<std::pair<cmTarget*, std::string>,
- cmComputeLinkInformation*> derived;
- cmTargetLinkInformationMap() {}
- cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r);
- ~cmTargetLinkInformationMap();
-};
-
class cmTargetInternals;
+
class cmTargetInternalPointer
{
public:
@@ -68,40 +49,41 @@ private:
class cmTarget
{
public:
- cmTarget();
- enum TargetType { EXECUTABLE, STATIC_LIBRARY,
- SHARED_LIBRARY, MODULE_LIBRARY,
- OBJECT_LIBRARY, UTILITY, GLOBAL_TARGET,
- UNKNOWN_LIBRARY};
- static const char* GetTargetTypeName(TargetType targetType);
- enum CustomCommandType { PRE_BUILD, PRE_LINK, POST_BUILD };
+ enum Visibility
+ {
+ VisibilityNormal,
+ VisibilityImported,
+ VisibilityImportedGlobally
+ };
- /**
- * Return the type of target.
- */
- TargetType GetType() const
- {
- return this->TargetTypeValue;
- }
+ cmTarget(std::string const& name, cmStateEnums::TargetType type,
+ Visibility vis, cmMakefile* mf);
+
+ enum CustomCommandType
+ {
+ PRE_BUILD,
+ PRE_LINK,
+ POST_BUILD
+ };
/**
- * Set the target type
+ * Return the type of target.
*/
- void SetType(TargetType f, const char* name);
+ cmStateEnums::TargetType GetType() const { return this->TargetTypeValue; }
- void MarkAsImported();
+ cmGlobalGenerator* GetGlobalGenerator() const;
///! Set/Get the name of the target
- const char* GetName() const {return this->Name.c_str();}
- const char* GetExportName();
+ const std::string& GetName() const { return this->Name; }
- ///! Set the cmMakefile that owns this target
- void SetMakefile(cmMakefile *mf);
- cmMakefile *GetMakefile() const { return this->Makefile;};
+ /** Get the cmMakefile that owns this target. */
+ cmMakefile* GetMakefile() const { return this->Makefile; }
-#define DECLARE_TARGET_POLICY(POLICY) \
- cmPolicies::PolicyStatus GetPolicyStatus ## POLICY () const \
- { return this->PolicyStatus ## POLICY; }
+#define DECLARE_TARGET_POLICY(POLICY) \
+ cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \
+ { \
+ return this->PolicyMap.Get(cmPolicies::POLICY); \
+ }
CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY)
@@ -110,632 +92,244 @@ public:
/**
* Get the list of the custom commands for this target
*/
- std::vector<cmCustomCommand> &GetPreBuildCommands()
- {return this->PreBuildCommands;}
- std::vector<cmCustomCommand> &GetPreLinkCommands()
- {return this->PreLinkCommands;}
- std::vector<cmCustomCommand> &GetPostBuildCommands()
- {return this->PostBuildCommands;}
-
- /**
- * Get the list of the source files used by this target
- */
- std::vector<cmSourceFile*> const& GetSourceFiles();
- void AddSourceFile(cmSourceFile* sf);
- std::vector<std::string> const& GetObjectLibraries() const
- {
- return this->ObjectLibraries;
- }
-
- /** Get sources that must be built before the given source. */
- std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf);
-
- /**
- * Flags for a given source file as used in this target. Typically assigned
- * via SET_TARGET_PROPERTIES when the property is a list of source files.
- */
- enum SourceFileType
+ std::vector<cmCustomCommand> const& GetPreBuildCommands() const
{
- SourceFileTypeNormal,
- SourceFileTypePrivateHeader, // is in "PRIVATE_HEADER" target property
- SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property
- SourceFileTypeResource, // is in "RESOURCE" target property *or*
- // has MACOSX_PACKAGE_LOCATION=="Resources"
- SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources"
- };
- struct SourceFileFlags
+ return this->PreBuildCommands;
+ }
+ std::vector<cmCustomCommand> const& GetPreLinkCommands() const
{
- SourceFileFlags(): Type(SourceFileTypeNormal), MacFolder(0) {}
- SourceFileFlags(SourceFileFlags const& r):
- Type(r.Type), MacFolder(r.MacFolder) {}
- SourceFileType Type;
- const char* MacFolder; // location inside Mac content folders
- };
-
- /**
- * Get the flags for a given source file as used in this target
- */
- struct SourceFileFlags GetTargetSourceFileFlags(const cmSourceFile* sf);
+ 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);
+ }
/**
* Add sources to the target.
*/
void AddSources(std::vector<std::string> const& srcs);
- cmSourceFile* AddSource(const char* src);
-
- enum LinkLibraryType {GENERAL, DEBUG, OPTIMIZED};
+ void AddTracedSources(std::vector<std::string> const& srcs);
+ cmSourceFile* AddSourceCMP0049(const std::string& src);
+ cmSourceFile* AddSource(const std::string& src);
//* how we identify a library, by name and type
- typedef std::pair<cmStdString, LinkLibraryType> LibraryID;
-
- typedef std::vector<LibraryID > LinkLibraryVectorType;
- const LinkLibraryVectorType &GetLinkLibraries() const {
- return this->LinkLibraries;}
- const LinkLibraryVectorType &GetOriginalLinkLibraries() const
- {return this->OriginalLinkLibraries;}
- void GetDirectLinkLibraries(const char *config,
- std::vector<std::string> &,
- cmTarget *head);
+ typedef std::pair<std::string, cmTargetLinkLibraryType> LibraryID;
- /** Compute the link type to use for the given configuration. */
- LinkLibraryType ComputeLinkType(const char* config);
+ 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 char* target);
-
- // Check to see if a library is a framework and treat it different on Mac
- bool NameResolvesToFramework(const std::string& libname);
- void AddLinkLibrary(cmMakefile& mf,
- const char *target, const char* lib,
- LinkLibraryType llt);
- enum TLLSignature {
+ void ClearDependencyInformation(cmMakefile& mf, const std::string& target);
+
+ void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
+ cmTargetLinkLibraryType llt);
+ enum TLLSignature
+ {
KeywordTLLSignature,
PlainTLLSignature
};
- bool PushTLLCommandTrace(TLLSignature signature);
- void GetTllSignatureTraces(cmOStringStream &s, TLLSignature sig) const;
+ bool PushTLLCommandTrace(TLLSignature signature,
+ cmListFileContext const& lfc);
+ void GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const;
- void MergeLinkLibraries( cmMakefile& mf, const char* selfname,
- const LinkLibraryVectorType& libs );
+ const std::vector<std::string>& GetLinkDirectories() const;
- const std::vector<std::string>& GetLinkDirectories();
-
- void AddLinkDirectory(const char* d);
+ void AddLinkDirectory(const std::string& d);
/**
* Set the path where this target should be installed. This is relative to
* INSTALL_PREFIX
*/
- std::string GetInstallPath() {return this->InstallPath;}
- void SetInstallPath(const char *name) {this->InstallPath = name;}
+ std::string GetInstallPath() const { return this->InstallPath; }
+ void SetInstallPath(const char* name) { this->InstallPath = 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() {return this->RuntimeInstallPath;}
- void SetRuntimeInstallPath(const char *name) {
- this->RuntimeInstallPath = name; }
+ std::string GetRuntimeInstallPath() const
+ {
+ return this->RuntimeInstallPath;
+ }
+ void SetRuntimeInstallPath(const char* name)
+ {
+ this->RuntimeInstallPath = name;
+ }
/**
* Get/Set whether there is an install rule for this target.
*/
- bool GetHaveInstallRule() { return this->HaveInstallRule; }
+ bool GetHaveInstallRule() const { return this->HaveInstallRule; }
void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; }
/** 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 char* u) { this->Utilities.insert(u);}
+ void AddUtility(const std::string& u, cmMakefile* makefile = CM_NULLPTR);
///! Get the utilities used by this target
- std::set<cmStdString>const& GetUtilities() const { return this->Utilities; }
-
- /** Finalize the target at the end of the Configure step. */
- void FinishConfigure();
+ std::set<std::string> const& GetUtilities() const { return this->Utilities; }
+ cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
///! Set/Get a property of this target file
- void SetProperty(const char *prop, const char *value);
- void AppendProperty(const char* prop, const char* value,bool asString=false);
- const char *GetProperty(const char *prop);
- const char *GetProperty(const char *prop, cmProperty::ScopeType scope);
- bool GetPropertyAsBool(const char *prop);
- void CheckProperty(const char* prop, cmMakefile* context);
-
- const char* GetFeature(const char* feature, const char* config);
-
- bool IsImported() const {return this->IsImportedTarget;}
-
- /** The link interface specifies transitive library dependencies and
- other information needed by targets that link to this target. */
- struct LinkInterface
- {
- // Languages whose runtime libraries must be linked.
- std::vector<std::string> Languages;
-
- // Libraries listed in the interface.
- std::vector<std::string> Libraries;
-
- // Shared library dependencies needed for linking on some platforms.
- std::vector<std::string> SharedDeps;
-
- // Number of repetitions of a strongly connected component of two
- // or more static libraries.
- int Multiplicity;
-
- // Libraries listed for other configurations.
- // Needed only for OLD behavior of CMP0003.
- std::vector<std::string> WrongConfigLibraries;
-
- bool ImplementationIsInterface;
-
- LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
- };
-
- /** Get the link interface for the given configuration. Returns 0
- if the target cannot be linked. */
- LinkInterface const* GetLinkInterface(const char* config,
- cmTarget *headTarget);
- void GetTransitivePropertyLinkLibraries(const char* config,
- cmTarget *headTarget,
- std::vector<std::string> &libs);
-
- /** The link implementation specifies the direct library
- dependencies needed by the object files of the target. */
- struct LinkImplementation
- {
- // Languages whose runtime libraries must be linked.
- std::vector<std::string> Languages;
-
- // Libraries linked directly in this configuration.
- std::vector<std::string> Libraries;
-
- // Libraries linked directly in other configurations.
- // Needed only for OLD behavior of CMP0003.
- std::vector<std::string> WrongConfigLibraries;
- };
- LinkImplementation const* GetLinkImplementation(const char* config,
- cmTarget *head);
-
- /** Link information from the transitive closure of the link
- implementation and the interfaces of its dependencies. */
- struct LinkClosure
+ 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) 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;
+
+ bool IsImported() const { return this->IsImportedTarget; }
+ bool IsImportedGloballyVisible() const
{
- // The preferred linker language.
- std::string LinkerLanguage;
-
- // Languages whose runtime libraries must be linked.
- std::vector<std::string> Languages;
- };
- LinkClosure const* GetLinkClosure(const char* config, cmTarget *head);
-
- /** Strip off leading and trailing whitespace from an item named in
- the link dependencies of this target. */
- std::string CheckCMP0004(std::string const& item);
-
- /** Get the directory in which this target will be built. If the
- configuration name is given then the generator will add its
- subdirectory for that configuration. Otherwise just the canonical
- output directory is given. */
- std::string GetDirectory(const char* config = 0, bool implib = false);
-
- /** Get the directory in which this targets .pdb files will be placed.
- If the configuration name is given then the generator will add its
- subdirectory for that configuration. Otherwise just the canonical
- pdb output directory is given. */
- std::string GetPDBDirectory(const char* config = 0);
-
- /** Get the location of the target in the build tree for the given
- configuration. This location is suitable for use as the LOCATION
- target property. */
- const char* GetLocation(const char* config);
-
- /** Get the target major and minor version numbers interpreted from
- the VERSION property. Version 0 is returned if the property is
- not set or cannot be parsed. */
- void GetTargetVersion(int& major, int& minor);
-
- /** Get the target major, minor, and patch version numbers
- interpreted from the VERSION or SOVERSION property. Version 0
- is returned if the property is not set or cannot be parsed. */
- void GetTargetVersion(bool soversion, int& major, int& minor, int& patch);
-
- /**
- * Trace through the source files in this target and add al source files
- * that they depend on, used by all generators
- */
- void TraceDependencies();
-
- /**
- * Make sure the full path to all source files is known.
- */
- bool FindSourceFiles();
-
- ///! Return the preferred linker language for this target
- const char* GetLinkerLanguage(const char* config = 0, cmTarget *head = 0);
-
- /** Get the full name of the target according to the settings in its
- makefile. */
- std::string GetFullName(const char* config=0, bool implib = false);
- void GetFullNameComponents(std::string& prefix,
- std::string& base, std::string& suffix,
- const char* config=0, bool implib = false);
-
- /** Get the name of the pdb file for the target. */
- std::string GetPDBName(const char* config=0);
-
- /** Whether this library has soname enabled and platform supports it. */
- bool HasSOName(const char* config);
-
- /** Get the soname of the target. Allowed only for a shared library. */
- std::string GetSOName(const char* config);
-
- /** Whether this library has @rpath and platform supports it. */
- bool HasMacOSXRpath(const char* config);
-
- /** Test for special case of a third-party shared library that has
- no soname at all. */
- bool IsImportedSharedLibWithoutSOName(const char* config);
-
- /** Get the full path to the target according to the settings in its
- makefile and the configuration type. */
- std::string GetFullPath(const char* config=0, bool implib = false,
- bool realname = false);
-
- /** 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 char* config);
-
- /** 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 char* config);
-
- /** Does this target have a GNU implib to convert to MS format? */
- bool HasImplibGNUtoMS();
-
- /** 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 = 0);
-
- /** Add the target output files to the global generator manifest. */
- void GenerateTargetManifest(const char* config);
-
- /**
- * Compute whether this target must be relinked before installing.
- */
- bool NeedRelinkBeforeInstall(const char* config);
-
- bool HaveBuildTreeRPATH(const char *config);
- bool HaveInstallTreeRPATH();
-
- /** Return true if builtin chrpath will work for this target */
- bool IsChrpathUsed(const char* config);
-
- /** Return the install name directory for the target in the
- * build tree. For example: "@rpath/", "@loader_path/",
- * or "/full/path/to/library". */
- std::string GetInstallNameDirForBuildTree(const char* config);
-
- /** Return the install name directory for the target in the
- * install tree. For example: "@rpath/" or "@loader_path/". */
- std::string GetInstallNameDirForInstallTree();
-
- cmComputeLinkInformation* GetLinkInformation(const char* config,
- cmTarget *head = 0);
+ return this->ImportedGloballyVisible;
+ }
// Get the properties
- cmPropertyMap &GetProperties() { return this->Properties; };
-
- bool GetMappedConfig(std::string const& desired_config,
- const char** loc,
- const char** imp,
- std::string& suffix);
-
- // Define the properties
- static void DefineProperties(cmake *cm);
+ cmPropertyMap const& GetProperties() const { return this->Properties; }
- /** Get the macro to define when building sources in this target.
- If no macro should be defined null is returned. */
- const char* GetExportMacro();
-
- void GetCompileDefinitions(std::vector<std::string> &result,
- const char *config);
-
- // Compute the set of languages compiled by the target. This is
- // computed every time it is called because the languages can change
- // when source file properties are changed and we do not have enough
- // information to forward these property changes to the targets
- // until we have per-target object file properties.
- void GetLanguages(std::set<cmStdString>& languages) 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. */
- bool IsExecutableWithExports();
-
- /** Return whether this target may be used to link another target. */
- bool IsLinkable();
-
- /** Return whether or not the target is for a DLL platform. */
- bool IsDLLPlatform() { return this->DLLPlatform; }
-
- /** Return whether or not the target has a DLL import library. */
- bool HasImportLibrary();
+ bool IsExecutableWithExports() const;
/** Return whether this target is a shared library Framework on
Apple. */
- bool IsFrameworkOnApple();
-
- /** Return whether this target is a CFBundle (plugin) on Apple. */
- bool IsCFBundleOnApple();
+ bool IsFrameworkOnApple() const;
/** Return whether this target is an executable Bundle on Apple. */
- bool IsAppBundleOnApple();
-
- /** Return whether this target is an executable Bundle, a framework
- or CFBundle on Apple. */
- bool IsBundleOnApple();
-
- /** Return the framework version string. Undefined if
- IsFrameworkOnApple returns false. */
- std::string GetFrameworkVersion();
+ bool IsAppBundleOnApple() const;
/** Get a backtrace from the creation of the target. */
cmListFileBacktrace const& GetBacktrace() const;
- /** Get a build-tree directory in which to place target support files. */
- std::string GetSupportDirectory() const;
-
- /** Return whether this target uses the default value for its output
- directory. */
- bool UsesDefaultOutputDir(const char* config, bool implib);
-
- /** @return the mac content directory for this target. */
- std::string GetMacContentDirectory(const char* config,
- bool implib);
-
- /** @return whether this target have a well defined output file name. */
- bool HaveWellDefinedOutputFiles();
-
- /** @return the Mac framework directory without the base. */
- std::string GetFrameworkDirectory(const char* config, bool rootDir);
-
- /** @return the Mac CFBundle directory without the base */
- std::string GetCFBundleDirectory(const char* config, bool contentOnly);
-
- /** @return the Mac App directory without the base */
- std::string GetAppBundleDirectory(const char* config, bool contentOnly);
-
- std::vector<std::string> GetIncludeDirectories(const char *config);
- void InsertInclude(const cmValueWithOrigin &entry,
- bool before = false);
- void InsertCompileOption(const cmValueWithOrigin &entry,
- bool before = false);
- void InsertCompileDefinition(const cmValueWithOrigin &entry,
+ void InsertInclude(std::string const& entry, cmListFileBacktrace const& bt,
bool before = false);
+ void InsertCompileOption(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before = false);
+ void InsertCompileDefinition(std::string const& entry,
+ cmListFileBacktrace const& bt);
void AppendBuildInterfaceIncludes();
- void GetCompileOptions(std::vector<std::string> &result,
- const char *config);
-
- bool IsNullImpliedByLinkLibraries(const std::string &p);
- bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
- const char *config);
- bool IsLinkInterfaceDependentStringProperty(const std::string &p,
- const char *config);
-
- bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
- const char *config);
-
- const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
- const char *config);
-
- std::string GetDebugGeneratorExpressions(const std::string &value,
- cmTarget::LinkLibraryType llt);
+ std::string GetDebugGeneratorExpressions(const std::string& value,
+ cmTargetLinkLibraryType llt) const;
- void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
- void AddSystemIncludeDirectories(const std::vector<std::string> &incs);
- std::set<cmStdString> const & GetSystemIncludeDirectories() const
- { return this->SystemIncludeDirectories; }
-
- void FinalizeSystemIncludeDirectories();
-
- bool LinkLanguagePropagatesToDependents() const
- { return this->TargetTypeValue == STATIC_LIBRARY; }
+ void AddSystemIncludeDirectories(const std::set<std::string>& incs);
+ std::set<std::string> const& GetSystemIncludeDirectories() const
+ {
+ return this->SystemIncludeDirectories;
+ }
-private:
- // The set of include directories that are marked as system include
- // directories.
- std::set<cmStdString> SystemIncludeDirectories;
+ cmStringRange GetIncludeDirectoriesEntries() const;
+ cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
- std::vector<std::pair<TLLSignature, cmListFileBacktrace> > TLLCommands;
+ cmStringRange GetCompileOptionsEntries() const;
+ cmBacktraceRange GetCompileOptionsBacktraces() const;
- /**
- * A list of direct dependencies. Use in conjunction with DependencyMap.
- */
- typedef std::vector< LibraryID > DependencyList;
-
- /**
- * This map holds the dependency graph. map[x] returns a set of
- * direct dependencies of x. Note that the direct depenencies are
- * ordered. This is necessary to handle direct dependencies that
- * themselves have no dependency information.
- */
- typedef std::map< LibraryID, DependencyList > DependencyMap;
-
- /**
- * Inserts \a dep at the end of the dependency list of \a lib.
- */
- void InsertDependency( DependencyMap& depMap,
- const LibraryID& lib,
- const LibraryID& dep);
+ cmStringRange GetCompileFeaturesEntries() const;
+ cmBacktraceRange GetCompileFeaturesBacktraces() const;
- /*
- * Deletes \a dep from the dependency list of \a lib.
- */
- void DeleteDependency( DependencyMap& depMap,
- const LibraryID& lib,
- const LibraryID& dep);
+ cmStringRange GetCompileDefinitionsEntries() const;
+ cmBacktraceRange GetCompileDefinitionsBacktraces() const;
- /**
- * Emits the library \a lib and all its dependencies into link_line.
- * \a emitted keeps track of the libraries that have been emitted to
- * avoid duplicates--it is more efficient than searching
- * link_line. \a visited is used detect cycles. Note that \a
- * link_line is in reverse order, in that the dependencies of a
- * library are listed before the library itself.
- */
- void Emit( const LibraryID lib,
- const DependencyMap& dep_map,
- std::set<LibraryID>& emitted,
- std::set<LibraryID>& visited,
- DependencyList& link_line);
+ cmStringRange GetSourceEntries() const;
+ cmBacktraceRange GetSourceBacktraces() const;
+ cmStringRange GetLinkImplementationEntries() const;
+ cmBacktraceRange GetLinkImplementationBacktraces() const;
- /**
- * Finds the dependencies for \a lib and inserts them into \a
- * dep_map.
- */
- void GatherDependencies( const cmMakefile& mf,
- const LibraryID& lib,
- DependencyMap& dep_map);
+ struct StrictTargetComparison
+ {
+ bool operator()(cmTarget const* t1, cmTarget const* t2) const;
+ };
- void AnalyzeLibDependencies( const cmMakefile& mf );
+ std::string ImportedGetFullPath(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
- const char* GetSuffixVariableInternal(bool implib);
- const char* GetPrefixVariableInternal(bool implib);
- std::string GetFullNameInternal(const char* config, bool implib);
- void GetFullNameInternal(const char* config, bool implib,
- std::string& outPrefix, std::string& outBase,
- std::string& outSuffix);
+private:
+ 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 char* property, const char* default_value);
-
- // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
- const char* GetOutputTargetType(bool implib);
-
- // Get the target base name.
- std::string GetOutputName(const char* config, bool implib);
+ void SetPropertyDefault(const std::string& property,
+ const char* default_value);
- const char* ImportedGetLocation(const char* config);
- const char* NormalGetLocation(const char* config);
-
- std::string GetFullNameImported(const char* config, bool implib);
-
- std::string ImportedGetFullPath(const char* config, bool implib);
- std::string NormalGetFullPath(const char* config, bool implib,
- bool realname);
-
- /** Get the real name of the target. Allowed only for non-imported
- targets. When a library or executable file is versioned this is
- the full versioned name. If the target is not versioned this is
- the same as GetFullName. */
- std::string NormalGetRealName(const char* config);
-
- /** Append to @a base the mac content directory and return it. */
- std::string BuildMacContentDirectory(const std::string& base,
- const char* config,
- bool contentOnly);
+ 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;
- TargetType TargetTypeValue;
- std::vector<cmSourceFile*> SourceFiles;
- std::vector<std::string> ObjectLibraries;
- LinkLibraryVectorType LinkLibraries;
- LinkLibraryVectorType PrevLinkedLibraries;
- bool LinkLibrariesAnalyzed;
- std::vector<std::string> LinkDirectories;
- std::set<cmStdString> LinkDirectoriesEmmitted;
+ std::vector<std::pair<TLLSignature, cmListFileContext> > TLLCommands;
+ LinkLibraryVectorType OriginalLinkLibraries;
+ cmMakefile* Makefile;
+ cmTargetInternalPointer Internal;
+ cmStateEnums::TargetType TargetTypeValue;
bool HaveInstallRule;
- std::string InstallPath;
- std::string RuntimeInstallPath;
- std::string Location;
- std::string ExportMacro;
- std::set<cmStdString> Utilities;
bool RecordDependencies;
- cmPropertyMap Properties;
- LinkLibraryVectorType OriginalLinkLibraries;
bool DLLPlatform;
- bool IsApple;
+ bool IsAndroid;
bool IsImportedTarget;
- bool DebugIncludesDone;
- bool DebugCompileOptionsDone;
- bool DebugCompileDefinitionsDone;
- mutable std::set<std::string> LinkImplicitNullProperties;
+ bool ImportedGloballyVisible;
bool BuildInterfaceIncludesAppended;
- // Cache target output paths for each configuration.
- struct OutputInfo;
- OutputInfo const* GetOutputInfo(const char* config);
- bool ComputeOutputDir(const char* config, bool implib, std::string& out);
- bool ComputePDBOutputDir(const char* config, std::string& out);
-
- // Cache import information from properties for each configuration.
- struct ImportInfo;
- ImportInfo const* GetImportInfo(const char* config,
- cmTarget *workingTarget);
- void ComputeImportInfo(std::string const& desired_config, ImportInfo& info,
- cmTarget *head);
-
- cmTargetLinkInformationMap LinkInformation;
- void CheckPropertyCompatibility(cmComputeLinkInformation *info,
- const char* config);
-
- bool ComputeLinkInterface(const char* config, LinkInterface& iface,
- cmTarget *head);
-
- void ComputeLinkImplementation(const char* config,
- LinkImplementation& impl, cmTarget *head);
- void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget *head);
-
- void ClearLinkMaps();
-
- void MaybeInvalidatePropertyCache(const char* prop);
+ std::string ProcessSourceItemCMP0049(const std::string& s);
- void ProcessSourceExpression(std::string const& expr);
-
- // The cmMakefile instance that owns this target. This should
- // always be set.
- cmMakefile* Makefile;
-
- // Policy status recorded when target was created.
-#define TARGET_POLICY_MEMBER(POLICY) \
- cmPolicies::PolicyStatus PolicyStatus ## POLICY;
-
- CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_MEMBER)
-
-#undef TARGET_POLICY_MEMBER
+ /** Return whether or not the target has a DLL import library. */
+ bool HasImportLibrary() const;
// Internal representation details.
friend class cmTargetInternals;
- cmTargetInternalPointer Internal;
+ friend class cmGeneratorTarget;
+ friend class cmTargetTraceDependencies;
- void ConstructSourceFileFlags();
- void ComputeVersionedName(std::string& vName,
- std::string const& prefix,
- std::string const& base,
- std::string const& suffix,
- std::string const& name,
- const char* version);
+ cmListFileBacktrace Backtrace;
};
-typedef std::map<cmStdString,cmTarget> cmTargets;
+typedef CM_UNORDERED_MAP<std::string, cmTarget> cmTargets;
-class cmTargetSet: public std::set<cmStdString> {};
-class cmTargetManifest: public std::map<cmStdString, cmTargetSet> {};
+class cmTargetSet : public std::set<std::string>
+{
+};
+class cmTargetManifest : public std::map<std::string, cmTargetSet>
+{
+};
#endif
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index 46c9666ef..008d1a210 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -1,66 +1,61 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetCompileDefinitionsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmTargetCompileDefinitionsCommand.h"
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
-bool cmTargetCompileDefinitionsCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmTargetCompileDefinitionsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
return this->HandleArguments(args, "COMPILE_DEFINITIONS");
}
-void cmTargetCompileDefinitionsCommand
-::HandleImportedTarget(const std::string &tgt)
+void cmTargetCompileDefinitionsCommand::HandleImportedTarget(
+ const std::string& tgt)
{
- cmOStringStream e;
- e << "Cannot specify compile definitions for imported target \""
- << tgt << "\".";
+ std::ostringstream e;
+ e << "Cannot specify compile definitions for imported target \"" << tgt
+ << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
-void cmTargetCompileDefinitionsCommand
-::HandleMissingTarget(const std::string &name)
+void cmTargetCompileDefinitionsCommand::HandleMissingTarget(
+ const std::string& name)
{
- cmOStringStream e;
- e << "Cannot specify compile definitions for target \"" << 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());
}
-//----------------------------------------------------------------------------
-std::string cmTargetCompileDefinitionsCommand
-::Join(const std::vector<std::string> &content)
+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 (strncmp(it->c_str(), "-D", 2) == 0)
- {
+ 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
- {
+ } else {
defs += sep + *it;
- }
- sep = ";";
}
+ sep = ";";
+ }
return defs;
}
-//----------------------------------------------------------------------------
-void cmTargetCompileDefinitionsCommand
-::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
- bool, bool)
+bool cmTargetCompileDefinitionsCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
{
tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
+ return true;
}
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index 585485d2a..11abf571c 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -1,88 +1,45 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetCompileDefinitionsCommand_h
#define cmTargetCompileDefinitionsCommand_h
+#include "cmConfigure.h"
+
+#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.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
return new cmTargetCompileDefinitionsCommand;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "target_compile_definitions";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Add compile definitions to a target.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " target_compile_definitions(<target> "
- "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
- " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
- "Specify compile definitions to use when compiling a given target. "
- "The named <target> must have been created by a command such as "
- "add_executable or add_library and must not be an IMPORTED target. "
- "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
- "the scope of the following arguments. PRIVATE and PUBLIC items will "
- "populate the COMPILE_DEFINITIONS property of <target>. PUBLIC and "
- "INTERFACE items will populate the INTERFACE_COMPILE_DEFINITIONS "
- "property of <target>. "
- "The following arguments specify compile definitions. "
- "Repeated calls for the same <target> append items in the order called."
- "\n"
- "Arguments to target_compile_definitions may use \"generator "
- "expressions\" with the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- ;
- }
-
- cmTypeMacro(cmTargetCompileDefinitionsCommand, cmTargetPropCommandBase);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
- virtual void HandleImportedTarget(const std::string &tgt);
- virtual void HandleMissingTarget(const std::string &name);
+ void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
+ void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
- virtual void HandleDirectContent(cmTarget *tgt,
- const std::vector<std::string> &content,
- bool prepend, bool system);
- virtual std::string Join(const std::vector<std::string> &content);
+ 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;
};
#endif
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
new file mode 100644
index 000000000..1b6c00887
--- /dev/null
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -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. */
+#include "cmTargetCompileFeaturesCommand.h"
+
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+class cmTarget;
+
+bool cmTargetCompileFeaturesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
+}
+
+void cmTargetCompileFeaturesCommand::HandleImportedTarget(
+ const std::string& tgt)
+{
+ std::ostringstream e;
+ e << "Cannot specify compile features for imported target \"" << tgt
+ << "\".";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetCompileFeaturesCommand::HandleMissingTarget(
+ const std::string& name)
+{
+ 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());
+}
+
+std::string cmTargetCompileFeaturesCommand::Join(
+ const std::vector<std::string>& content)
+{
+ return cmJoin(content, ";");
+}
+
+bool cmTargetCompileFeaturesCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
+{
+ 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;
+}
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
new file mode 100644
index 000000000..990868004
--- /dev/null
+++ b/Source/cmTargetCompileFeaturesCommand.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 cmTargetCompileFeaturesCommand_h
+#define cmTargetCompileFeaturesCommand_h
+
+#include "cmConfigure.h"
+
+#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;
+};
+
+#endif
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 254acc73d..1b4056d76 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -1,62 +1,51 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetCompileOptionsCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmTargetCompileOptionsCommand.h"
+#include "cmAlgorithms.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
-bool cmTargetCompileOptionsCommand
-::InitialPass(std::vector<std::string> const& args, 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)
+void cmTargetCompileOptionsCommand::HandleImportedTarget(
+ const std::string& tgt)
{
- cmOStringStream e;
- e << "Cannot specify compile options for imported target \""
- << tgt << "\".";
+ std::ostringstream e;
+ e << "Cannot specify compile options for imported target \"" << tgt << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
-void cmTargetCompileOptionsCommand
-::HandleMissingTarget(const std::string &name)
+void cmTargetCompileOptionsCommand::HandleMissingTarget(
+ const std::string& name)
{
- cmOStringStream e;
- e << "Cannot specify compile options for target \"" << 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());
}
-//----------------------------------------------------------------------------
-std::string cmTargetCompileOptionsCommand
-::Join(const std::vector<std::string> &content)
+std::string cmTargetCompileOptionsCommand::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)
- {
- defs += sep + *it;
- sep = ";";
- }
- return defs;
+ return cmJoin(content, ";");
}
-//----------------------------------------------------------------------------
-void cmTargetCompileOptionsCommand
-::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
- bool, bool)
+bool cmTargetCompileOptionsCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
{
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmValueWithOrigin entry(this->Join(content), lfbt);
- tgt->InsertCompileOption(entry);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ tgt->InsertCompileOption(this->Join(content), lfbt);
+ return true;
}
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index b9afd7169..b5408f7cb 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -1,90 +1,42 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetCompileOptionsCommand_h
#define cmTargetCompileOptionsCommand_h
+#include "cmConfigure.h"
+
+#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.
*/
- virtual cmCommand* Clone()
- {
- return new cmTargetCompileOptionsCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmTargetCompileOptionsCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "target_compile_options";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Add compile options to a target.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " target_compile_options(<target> [BEFORE] "
- "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
- " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
- "Specify compile options to use when compiling a given target. "
- "The named <target> must have been created by a command such as "
- "add_executable or add_library and must not be an IMPORTED target. "
- "If BEFORE is specified, the content will be prepended to the property "
- "instead of being appended.\n"
- "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
- "the scope of the following arguments. PRIVATE and PUBLIC items will "
- "populate the COMPILE_OPTIONS property of <target>. PUBLIC and "
- "INTERFACE items will populate the INTERFACE_COMPILE_OPTIONS "
- "property of <target>. "
- "The following arguments specify compile opitions. "
- "Repeated calls for the same <target> append items in the order called."
- "\n"
- "Arguments to target_compile_options may use \"generator "
- "expressions\" with the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- ;
- }
-
- cmTypeMacro(cmTargetCompileOptionsCommand, cmTargetPropCommandBase);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
- virtual void HandleImportedTarget(const std::string &tgt);
- virtual void HandleMissingTarget(const std::string &name);
+ void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
+ void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
- virtual void HandleDirectContent(cmTarget *tgt,
- const std::vector<std::string> &content,
- bool prepend, bool system);
- virtual std::string Join(const std::vector<std::string> &content);
+ 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;
};
#endif
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index 258bacd6d..daa902ecf 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -1,48 +1,54 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetDepend_h
#define cmTargetDepend_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <set>
-class cmTarget;
+class cmGeneratorTarget;
/** One edge in the global target dependency graph.
It may be marked as a 'link' or 'util' edge or both. */
class cmTargetDepend
{
- cmTarget* Target;
+ cmGeneratorTarget const* Target;
// The set order depends only on the Target, so we use
// mutable members to acheive a map with set syntax.
mutable bool Link;
mutable bool Util;
+
public:
- cmTargetDepend(cmTarget* t): Target(t), Link(false), Util(false) {}
- operator cmTarget*() const { return this->Target; }
- cmTarget* operator->() const { return this->Target; }
- cmTarget& operator*() const { return *this->Target; }
- friend bool operator < (cmTargetDepend const& l, cmTargetDepend const& r)
- { return l.Target < r.Target; }
+ cmTargetDepend(cmGeneratorTarget const* t)
+ : Target(t)
+ , Link(false)
+ , Util(false)
+ {
+ }
+ 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)
+ {
+ return l.Target < r.Target;
+ }
void SetType(bool strong) const
- {
- if(strong) { this->Util = true; }
- else { this->Link = true; }
+ {
+ if (strong) {
+ this->Util = true;
+ } else {
+ this->Link = true;
}
+ }
bool IsLink() const { return this->Link; }
bool IsUtil() const { return this->Util; }
};
/** Unordered set of (direct) dependencies of a target. */
-class cmTargetDependSet: public std::set<cmTargetDepend> {};
+class cmTargetDependSet : public std::set<cmTargetDepend>
+{
+};
#endif
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 76658887d..9304eabbb 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -1,22 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetExport_h
#define cmTargetExport_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-class cmTarget;
-class cmInstallTargetGenerator;
+#include <string>
+
+class cmGeneratorTarget;
class cmInstallFilesGenerator;
+class cmInstallTargetGenerator;
/** \brief A member of an ExportSet
*
@@ -25,13 +18,15 @@ class cmInstallFilesGenerator;
class cmTargetExport
{
public:
- cmTarget* Target; ///< The target
+ std::string TargetName;
+ cmGeneratorTarget* Target;
///@name Generators
///@{
cmInstallTargetGenerator* ArchiveGenerator;
cmInstallTargetGenerator* RuntimeGenerator;
cmInstallTargetGenerator* LibraryGenerator;
+ cmInstallTargetGenerator* ObjectsGenerator;
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index e7b906c9e..65a31490f 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -1,104 +1,99 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetIncludeDirectoriesCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <set>
+#include <sstream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmTargetIncludeDirectoriesCommand.h"
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
-//----------------------------------------------------------------------------
-bool cmTargetIncludeDirectoriesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmTargetIncludeDirectoriesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
return this->HandleArguments(args, "INCLUDE_DIRECTORIES",
ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
}
-//----------------------------------------------------------------------------
-void cmTargetIncludeDirectoriesCommand
-::HandleImportedTarget(const std::string &tgt)
+void cmTargetIncludeDirectoriesCommand::HandleImportedTarget(
+ const std::string& tgt)
{
- cmOStringStream e;
- e << "Cannot specify include directories for imported target \""
- << tgt << "\".";
+ std::ostringstream e;
+ e << "Cannot specify include directories for imported target \"" << tgt
+ << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
-//----------------------------------------------------------------------------
-void cmTargetIncludeDirectoriesCommand
-::HandleMissingTarget(const std::string &name)
+void cmTargetIncludeDirectoriesCommand::HandleMissingTarget(
+ const std::string& name)
{
- cmOStringStream e;
- e << "Cannot specify include directories for target \"" << 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());
}
-//----------------------------------------------------------------------------
-std::string cmTargetIncludeDirectoriesCommand
-::Join(const std::vector<std::string> &content)
+std::string cmTargetIncludeDirectoriesCommand::Join(
+ const std::vector<std::string>& content)
{
std::string dirs;
std::string sep;
- std::string prefix = this->Makefile->GetStartDirectory() + 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) != std::string::npos)
- {
+ 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;
- }
- else
- {
+ } else {
dirs += sep + prefix + *it;
- }
- sep = ";";
}
+ sep = ";";
+ }
return dirs;
}
-//----------------------------------------------------------------------------
-void cmTargetIncludeDirectoriesCommand
-::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
- bool prepend, bool system)
+bool cmTargetIncludeDirectoriesCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
+ bool system)
{
- cmListFileBacktrace lfbt;
- this->Makefile->GetBacktrace(lfbt);
- cmValueWithOrigin entry(this->Join(content), lfbt);
- tgt->InsertInclude(entry, prepend);
- if (system)
- {
- tgt->AddSystemIncludeDirectories(content);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ tgt->InsertInclude(this->Join(content), lfbt, prepend);
+ if (system) {
+ std::string prefix =
+ this->Makefile->GetCurrentSourceDirectory() + std::string("/");
+ 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);
+ } else {
+ sdirs.insert(prefix + *it);
+ }
}
+ tgt->AddSystemIncludeDirectories(sdirs);
+ }
+ return true;
}
-//----------------------------------------------------------------------------
-void cmTargetIncludeDirectoriesCommand
-::HandleInterfaceContent(cmTarget *tgt,
- const std::vector<std::string> &content,
- bool prepend, bool system)
+void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
+ bool system)
{
- cmTargetPropCommandBase::HandleInterfaceContent(tgt, content,
- prepend, system);
+ cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, prepend,
+ system);
- if (system)
- {
- std::string joined;
- std::string sep;
- for(std::vector<std::string>::const_iterator it = content.begin();
- it != content.end(); ++it)
- {
- joined += sep;
- sep = ";";
- joined += *it;
- }
+ if (system) {
+ std::string joined = this->Join(content);
tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
joined.c_str());
- }
+ }
}
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index fcc37f06a..374a867dc 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -1,105 +1,49 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetIncludeDirectoriesCommand_h
#define cmTargetIncludeDirectoriesCommand_h
+#include "cmConfigure.h"
+
+#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.
*/
- virtual cmCommand* Clone()
- {
+ cmCommand* Clone() CM_OVERRIDE
+ {
return new cmTargetIncludeDirectoriesCommand;
- }
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "target_include_directories";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Add include directories to a target.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " target_include_directories(<target> [SYSTEM] [BEFORE] "
- "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
- " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
- "Specify include directories or targets to use when compiling a given "
- "target. "
- "The named <target> must have been created by a command such as "
- "add_executable or add_library and must not be an IMPORTED target.\n"
- "If BEFORE is specified, the content will be prepended to the property "
- "instead of being appended.\n"
- "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
- "the scope of the following arguments. PRIVATE and PUBLIC items will "
- "populate the INCLUDE_DIRECTORIES property of <target>. PUBLIC and "
- "INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES "
- "property of <target>. "
- "The following arguments specify include directories. Specified "
- "include directories may be absolute paths or relative paths. "
- "Repeated calls for the same <target> append items in the order called."
- "If SYSTEM is specified, the compiler will be told the "
- "directories are meant as system include directories on some "
- "platforms (signalling this setting might achieve effects such as "
- "the compiler skipping warnings, or these fixed-install system files "
- "not being considered in dependency calculations - see compiler "
- "docs). If SYSTEM is used together with PUBLIC or INTERFACE, the "
- "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES target property will be "
- "populated with the specified directories."
- "\n"
- "Arguments to target_include_directories may use \"generator "
- "expressions\" with the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- ;
- }
-
- cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmTargetPropCommandBase);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
private:
- virtual void HandleImportedTarget(const std::string &tgt);
- virtual void HandleMissingTarget(const std::string &name);
+ void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
+ void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
- virtual void HandleDirectContent(cmTarget *tgt,
- const std::vector<std::string> &content,
- bool prepend, bool system);
- virtual void HandleInterfaceContent(cmTarget *tgt,
- const std::vector<std::string> &content,
- bool prepend, bool system);
+ 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;
- virtual std::string Join(const std::vector<std::string> &content);
+ std::string Join(const std::vector<std::string>& content) CM_OVERRIDE;
};
#endif
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index c2f46a1b1..e17303645 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -1,83 +1,76 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetLinkLibrariesCommand.h"
+#include <sstream>
+#include <string.h>
+
#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmake.h"
-const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
-{
- "general",
- "debug",
- "optimized"
+class cmExecutionStatus;
+
+const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] = {
+ "general", "debug", "optimized"
};
// cmTargetLinkLibrariesCommand
-bool cmTargetLinkLibrariesCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmTargetLinkLibrariesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
// must have one argument
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- if (this->Makefile->IsAlias(args[0].c_str()))
- {
+ if (this->Makefile->IsAlias(args[0])) {
this->SetError("can not be used on an ALIAS target.");
return false;
- }
+ }
// Lookup the target for which libraries are specified.
this->Target =
- this->Makefile->GetCMakeInstance()
- ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
- if(!this->Target)
- {
- cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
- cmOStringStream e;
+ this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
+ args[0]);
+ if (!this->Target) {
+ cmake::MessageType t = cmake::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))
- {
+ if (args.size() < 2) {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016)) {
case cmPolicies::WARN:
t = cmake::AUTHOR_WARNING;
// Print the warning.
e << "\n"
<< "CMake does not support this but it used to work accidentally "
<< "and is being allowed for compatibility."
- << "\n" << this->Makefile->GetPolicies()->
- GetPolicyWarning(cmPolicies::CMP0016);
- break;
- case cmPolicies::OLD: // OLD behavior does not warn.
+ << "\n"
+ << cmPolicies::GetPolicyWarning(cmPolicies::CMP0016);
+ break;
+ case cmPolicies::OLD: // OLD behavior does not warn.
t = cmake::MESSAGE;
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
- e << "\n" << this->Makefile->GetPolicies()->
- GetRequiredPolicyError(cmPolicies::CMP0016);
+ e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0016);
break;
- case cmPolicies::NEW: // NEW behavior prints the error.
- default:
+ case cmPolicies::NEW: // NEW behavior prints the error.
break;
- }
}
+ }
// now actually print the message
- switch(t)
- {
+ switch (t) {
case cmake::AUTHOR_WARNING:
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
break;
@@ -87,28 +80,52 @@ bool cmTargetLinkLibrariesCommand
break;
default:
break;
- }
- return true;
}
+ return true;
+ }
- if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- cmOStringStream e;
+ if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ 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)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n";
+ modal = "should";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ modal = "must";
+ messageType = cmake::FATAL_ERROR;
+ }
+ if (modal) {
+ e << "Utility target \"" << this->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) {
+ return false;
+ }
}
+ }
// but we might not have any libs after variable expansion
- if(args.size() < 2)
- {
+ if (args.size() < 2) {
return true;
- }
+ }
// Keep track of link configuration specifiers.
- cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
+ cmTargetLinkLibraryType llt = GENERAL_LibraryType;
bool haveLLT = false;
// Start with primary linking and switch to link interface
@@ -117,225 +134,188 @@ bool cmTargetLinkLibrariesCommand
// 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")
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ if (args[i] == "LINK_INTERFACE_LIBRARIES") {
this->CurrentProcessingState = ProcessingPlainLinkInterface;
- if(i != 1)
- {
+ if (i != 1) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
"The LINK_INTERFACE_LIBRARIES option must appear as the second "
- "argument, just after the target name."
- );
+ "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)
- {
+ } 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."
- );
+ cmake::FATAL_ERROR, "The INTERFACE option must appear as the second "
+ "argument, just after the target name.");
return true;
- }
- this->CurrentProcessingState = ProcessingKeywordLinkInterface;
}
- else if(args[i] == "LINK_PUBLIC")
- {
- if(i != 1
- && this->CurrentProcessingState != ProcessingPlainPrivateInterface)
- {
+ this->CurrentProcessingState = ProcessingKeywordLinkInterface;
+ } else if (args[i] == "LINK_PUBLIC") {
+ if (i != 1 &&
+ this->CurrentProcessingState != ProcessingPlainPrivateInterface &&
+ this->CurrentProcessingState != ProcessingPlainPublicInterface) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
"The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
- "argument, just after the target name."
- );
+ "argument, just after the target name.");
return true;
- }
- this->CurrentProcessingState = ProcessingPlainPublicInterface;
}
- else if(args[i] == "PUBLIC")
- {
- if(i != 1
- && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
- && this->CurrentProcessingState != ProcessingKeywordPublicInterface
- && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
- {
+ this->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 "
- "argument, just after the target name."
- );
+ "argument, just after the target name.");
return true;
- }
- this->CurrentProcessingState = ProcessingKeywordPublicInterface;
}
- else if(args[i] == "LINK_PRIVATE")
- {
- if(i != 1
- && this->CurrentProcessingState != ProcessingPlainPublicInterface)
- {
+ this->CurrentProcessingState = ProcessingKeywordPublicInterface;
+ } else if (args[i] == "LINK_PRIVATE") {
+ if (i != 1 &&
+ this->CurrentProcessingState != ProcessingPlainPublicInterface &&
+ this->CurrentProcessingState != ProcessingPlainPrivateInterface) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
"The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
- "argument, just after the target name."
- );
+ "argument, just after the target name.");
return true;
- }
- this->CurrentProcessingState = ProcessingPlainPrivateInterface;
}
- else if(args[i] == "PRIVATE")
- {
- if(i != 1
- && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
- && this->CurrentProcessingState != ProcessingKeywordPublicInterface
- && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
- {
+ this->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 "
- "argument, just after the target name."
- );
+ "argument, just after the target name.");
return true;
- }
+ }
this->CurrentProcessingState = ProcessingKeywordPrivateInterface;
+ } else if (args[i] == "debug") {
+ if (haveLLT) {
+ this->LinkLibraryTypeSpecifierWarning(llt, DEBUG_LibraryType);
}
- else if(args[i] == "debug")
- {
- if(haveLLT)
- {
- this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
- }
- llt = cmTarget::DEBUG;
+ llt = DEBUG_LibraryType;
haveLLT = true;
+ } else if (args[i] == "optimized") {
+ if (haveLLT) {
+ this->LinkLibraryTypeSpecifierWarning(llt, OPTIMIZED_LibraryType);
}
- else if(args[i] == "optimized")
- {
- if(haveLLT)
- {
- this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
- }
- llt = cmTarget::OPTIMIZED;
+ llt = OPTIMIZED_LibraryType;
haveLLT = true;
+ } else if (args[i] == "general") {
+ if (haveLLT) {
+ this->LinkLibraryTypeSpecifierWarning(llt, GENERAL_LibraryType);
}
- else if(args[i] == "general")
- {
- if(haveLLT)
- {
- this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
- }
- llt = cmTarget::GENERAL;
+ llt = GENERAL_LibraryType;
haveLLT = true;
- }
- else if(haveLLT)
- {
+ } else if (haveLLT) {
// The link type was specified by the previous argument.
haveLLT = false;
- if (!this->HandleLibrary(args[i].c_str(), llt))
- {
+ if (!this->HandleLibrary(args[i], llt)) {
return false;
- }
}
- else
- {
+ } 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
// only there for backwards compatibility when mixing projects built
// with old versions of CMake and new)
- llt = cmTarget::GENERAL;
+ llt = GENERAL_LibraryType;
std::string linkType = args[0];
linkType += "_LINK_TYPE";
- const char* linkTypeString =
- this->Makefile->GetDefinition( linkType.c_str() );
- if(linkTypeString)
- {
- if(strcmp(linkTypeString, "debug") == 0)
- {
- llt = cmTarget::DEBUG;
- }
- if(strcmp(linkTypeString, "optimized") == 0)
- {
- llt = cmTarget::OPTIMIZED;
- }
+ const char* linkTypeString = this->Makefile->GetDefinition(linkType);
+ if (linkTypeString) {
+ if (strcmp(linkTypeString, "debug") == 0) {
+ llt = DEBUG_LibraryType;
}
- if (!this->HandleLibrary(args[i].c_str(), llt))
- {
- return false;
+ if (strcmp(linkTypeString, "optimized") == 0) {
+ llt = OPTIMIZED_LibraryType;
}
}
+ if (!this->HandleLibrary(args[i], llt)) {
+ return false;
+ }
}
+ }
// Make sure the last argument was not a library type specifier.
- if(haveLLT)
- {
- cmOStringStream e;
+ 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());
cmSystemTools::SetFatalErrorOccured();
- }
+ }
- const cmPolicies::PolicyStatus policy22Status
- = this->Target->GetPolicyStatusCMP0022();
+ const cmPolicies::PolicyStatus policy22Status =
+ this->Target->GetPolicyStatusCMP0022();
// If any of the LINK_ options were given, make sure the
// LINK_INTERFACE_LIBRARIES target property exists.
// Use of any of the new keywords implies awareness of
// this property. And if no libraries are named, it should
// result in an empty link interface.
- if((policy22Status == cmPolicies::OLD ||
- policy22Status == cmPolicies::WARN) &&
+ if ((policy22Status == cmPolicies::OLD ||
+ policy22Status == cmPolicies::WARN) &&
this->CurrentProcessingState != ProcessingLinkLibraries &&
- !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
- {
+ !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
-void
-cmTargetLinkLibrariesCommand
-::LinkLibraryTypeSpecifierWarning(int left, int right)
+void cmTargetLinkLibrariesCommand::LinkLibraryTypeSpecifierWarning(int left,
+ int right)
{
- cmOStringStream w;
- w << "Link library type specifier \""
- << this->LinkLibraryTypeNames[left] << "\" is followed by specifier \""
- << this->LinkLibraryTypeNames[right] << "\" instead of a library name. "
+ 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());
}
-//----------------------------------------------------------------------------
-bool
-cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
- cmTarget::LinkLibraryType llt)
+bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
+ cmTargetLinkLibraryType llt)
{
+ if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
+ this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "INTERFACE 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)
- ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature;
- if (!this->Target->PushTLLCommandTrace(sig))
- {
- const char *modal = 0;
+ (this->CurrentProcessingState == ProcessingPlainPrivateInterface ||
+ this->CurrentProcessingState == ProcessingPlainPublicInterface ||
+ this->CurrentProcessingState == ProcessingKeywordPrivateInterface ||
+ this->CurrentProcessingState == ProcessingKeywordPublicInterface ||
+ this->CurrentProcessingState == ProcessingKeywordLinkInterface)
+ ? cmTarget::KeywordTLLSignature
+ : cmTarget::PlainTLLSignature;
+ if (!this->Target->PushTLLCommandTrace(
+ sig, this->Makefile->GetExecutionContext())) {
+ std::ostringstream e;
+ const char* modal = CM_NULLPTR;
cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0023))
- {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) {
case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n";
modal = "should";
case cmPolicies::OLD:
break;
@@ -344,114 +324,131 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
case cmPolicies::NEW:
modal = "must";
messageType = cmake::FATAL_ERROR;
- }
+ }
- if(modal)
- {
- cmOStringStream e;
- // If the sig is a keyword form and there is a conflict, the existing
- // form must be the plain form.
- const char *existingSig
- = (sig == cmTarget::KeywordTLLSignature ? "plain"
- : "keyword");
- e << this->Makefile->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0023) << "\n"
- "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,
+ if (modal) {
+ // If the sig is a keyword form and there is a conflict, the existing
+ // 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().c_str());
- if(messageType == cmake::FATAL_ERROR)
- {
- return false;
- }
- }
+ this->Makefile->IssueMessage(messageType, e.str());
+ if (messageType == cmake::FATAL_ERROR) {
+ return false;
+ }
}
+ }
// Handle normal case first.
- if(this->CurrentProcessingState != ProcessingKeywordLinkInterface
- && this->CurrentProcessingState != ProcessingPlainLinkInterface)
- {
- this->Makefile
- ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
- if(this->CurrentProcessingState == ProcessingLinkLibraries)
- {
- this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ 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 {
+
+ 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());
+ }
+
+ this->Target->AddLinkLibrary(*this->Makefile, lib, llt);
+ }
+
+ if (this->CurrentProcessingState == ProcessingLinkLibraries) {
+ this->Target->AppendProperty(
+ "INTERFACE_LINK_LIBRARIES",
this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
return true;
- }
- else if(this->CurrentProcessingState != ProcessingKeywordPublicInterface
- && this->CurrentProcessingState != ProcessingPlainPublicInterface)
- {
- if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
- {
- std::string configLib = this->Target
- ->GetDebugGeneratorExpressions(lib, llt);
- if (cmGeneratorExpression::IsValidTargetName(lib)
- || cmGeneratorExpression::Find(lib) != std::string::npos)
- {
+ }
+ 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());
- }
+ }
// Not a 'public' or 'interface' library. Do not add to interface
// property.
return true;
- }
}
+ }
- this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
- this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+ this->Target->AppendProperty(
+ "INTERFACE_LINK_LIBRARIES",
+ this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
- const cmPolicies::PolicyStatus policy22Status
- = this->Target->GetPolicyStatusCMP0022();
+ const cmPolicies::PolicyStatus policy22Status =
+ this->Target->GetPolicyStatusCMP0022();
- if (policy22Status != cmPolicies::OLD
- && policy22Status != cmPolicies::WARN)
- {
+ if (policy22Status != cmPolicies::OLD &&
+ policy22Status != cmPolicies::WARN) {
return true;
- }
+ }
+
+ if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return true;
+ }
// Get the list of configurations considered to be DEBUG.
- std::vector<std::string> const& debugConfigs =
+ std::vector<std::string> debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
std::string prop;
// Include this library in the link interface for the target.
- if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
- {
+ 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)
- {
+ for (std::vector<std::string>::const_iterator i = debugConfigs.begin();
+ i != debugConfigs.end(); ++i) {
prop = "LINK_INTERFACE_LIBRARIES_";
prop += *i;
- this->Target->AppendProperty(prop.c_str(), lib);
- }
+ this->Target->AppendProperty(prop, lib.c_str());
}
- if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
- {
+ }
+ if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) {
// Put in the non-DEBUG configuration interfaces.
- this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
+ 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)
- {
+ 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.c_str()))
- {
- this->Target->SetProperty(prop.c_str(), "");
- }
+ if (!this->Target->GetProperty(prop)) {
+ this->Target->SetProperty(prop, "");
}
}
+ }
return true;
}
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index 2cf6b03ef..3fd20accd 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetLinkLibrariesCommand_h
#define cmTargetLinkLibrariesCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmDocumentGeneratorExpressions.h"
+#include "cmTargetLinkLibraryType.h"
+
+class cmExecutionStatus;
+class cmTarget;
/** \class cmTargetLinkLibrariesCommand
* \brief Specify a list of libraries to link into executables.
@@ -28,180 +27,22 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmTargetLinkLibrariesCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmTargetLinkLibrariesCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "target_link_libraries";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return
- "Link a target to given libraries.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " target_link_libraries(<target> [item1 [item2 [...]]]\n"
- " [[debug|optimized|general] <item>] ...)\n"
- "Specify libraries or flags to use when linking a given target. "
- "The named <target> must have been created in the current directory "
- "by a command such as add_executable or add_library. "
- "The remaining arguments specify library names or flags. "
- "Repeated calls for the same <target> append items in the order called."
- "\n"
- "If a library name matches that of another target in the project "
- "a dependency will automatically be added in the build system to make "
- "sure the library being linked is up-to-date before the target links. "
- "Item names starting with '-', but not '-l' or '-framework', are "
- "treated as linker flags."
- "\n"
- "A \"debug\", \"optimized\", or \"general\" keyword indicates that "
- "the library immediately following it is to be used only for the "
- "corresponding build configuration. "
- "The \"debug\" keyword corresponds to the Debug configuration "
- "(or to configurations named in the DEBUG_CONFIGURATIONS global "
- "property if it is set). "
- "The \"optimized\" keyword corresponds to all other configurations. "
- "The \"general\" keyword corresponds to all configurations, and is "
- "purely optional (assumed if omitted). "
- "Higher granularity may be achieved for per-configuration rules "
- "by creating and linking to IMPORTED library targets. "
- "See the IMPORTED mode of the add_library command for more "
- "information. "
- "\n"
- "Library dependencies are transitive by default with this signature. "
- "When this target is linked into another target then the libraries "
- "linked to this target will appear on the link line for the other "
- "target too. "
- "This transitive \"link interface\" is stored in the "
- "INTERFACE_LINK_LIBRARIES target property when policy CMP0022 is set "
- "to NEW and may be overridden by setting the property directly. "
- "("
- "When CMP0022 is not set to NEW, transitive linking is builtin "
- "but may be overridden by the LINK_INTERFACE_LIBRARIES property. "
- "Calls to other signatures of this command may set the property "
- "making any libraries linked exclusively by this signature private."
- ")"
- "\n"
- "CMake will also propagate \"usage requirements\" from linked library "
- "targets. "
- "Usage requirements affect compilation of sources in the <target>. "
- "They are specified by properties defined on linked targets. "
- "During generation of the build system, CMake integrates "
- "usage requirement property values with the corresponding "
- "build properties for <target>:\n"
- " INTERFACE_COMPILE_DEFINITONS: Appends to COMPILE_DEFINITONS\n"
- " INTERFACE_INCLUDE_DIRECTORIES: Appends to INCLUDE_DIRECTORIES\n"
- " INTERFACE_POSITION_INDEPENDENT_CODE: Sets POSITION_INDEPENDENT_CODE\n"
- " or checked for consistency with existing value\n"
- "\n"
- "If an <item> is a library in a Mac OX framework, the Headers "
- "directory of the framework will also be processed as a \"usage "
- "requirement\". This has the same effect as passing the framework "
- "directory as an include directory."
- " target_link_libraries(<target>\n"
- " <PRIVATE|PUBLIC|INTERFACE> <lib> ...\n"
- " [<PRIVATE|PUBLIC|INTERFACE> <lib> ... ] ...])\n"
- "The PUBLIC, PRIVATE and INTERFACE keywords can be used to specify "
- "both the link dependencies and the link interface in one command. "
- "Libraries and targets following PUBLIC are linked to, and are "
- "made part of the link interface. Libraries and targets "
- "following PRIVATE are linked to, but are not made part of the "
- "link interface. Libraries following INTERFACE are appended "
- "to the link interface and are not used for linking <target>."
- "\n"
- " target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
- " [[debug|optimized|general] <lib>] ...)\n"
- "The LINK_INTERFACE_LIBRARIES mode appends the libraries "
- "to the INTERFACE_LINK_LIBRARIES target property instead of using them "
- "for linking. If policy CMP0022 is not NEW, then this mode also "
- "appends libraries to the LINK_INTERFACE_LIBRARIES and its "
- "per-configuration equivalent. This signature "
- "is for compatibility only. Prefer the INTERFACE mode instead. "
- "Libraries specified as \"debug\" are wrapped in a generator "
- "expression to correspond to debug builds. If policy CMP0022 is not "
- "NEW, the libraries are also appended to the "
- "LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties "
- "corresponding to configurations listed in the DEBUG_CONFIGURATIONS "
- "global property if it is set). "
- "Libraries specified as \"optimized\" are appended to the "
- "INTERFACE_LINK_LIBRARIES property. If policy CMP0022 is not NEW, "
- "they are also appended to the LINK_INTERFACE_LIBRARIES property. "
- "Libraries specified as \"general\" (or without any keyword) are "
- "treated as if specified for both \"debug\" and \"optimized\"."
- "\n"
- " target_link_libraries(<target>\n"
- " <LINK_PRIVATE|LINK_PUBLIC>\n"
- " [[debug|optimized|general] <lib>] ...\n"
- " [<LINK_PRIVATE|LINK_PUBLIC>\n"
- " [[debug|optimized|general] <lib>] ...])\n"
- "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both "
- "the link dependencies and the link interface in one command. This "
- "signature is for compatibility only. Prefer the PUBLIC or PRIVATE "
- "keywords instead. "
- "Libraries and targets following LINK_PUBLIC are linked to, and are "
- "made part of the INTERFACE_LINK_LIBRARIES. If policy CMP0022 is not "
- "NEW, they are also made part of the LINK_INTERFACE_LIBRARIES. "
- "Libraries and targets following LINK_PRIVATE are linked to, but are "
- "not made part of the INTERFACE_LINK_LIBRARIES (or "
- "LINK_INTERFACE_LIBRARIES)."
- "\n"
- "The library dependency graph is normally acyclic (a DAG), but in the "
- "case of mutually-dependent STATIC libraries CMake allows the graph "
- "to contain cycles (strongly connected components). "
- "When another target links to one of the libraries CMake repeats "
- "the entire connected component. "
- "For example, the code\n"
- " add_library(A STATIC a.c)\n"
- " add_library(B STATIC b.c)\n"
- " target_link_libraries(A B)\n"
- " target_link_libraries(B A)\n"
- " add_executable(main main.c)\n"
- " target_link_libraries(main A)\n"
- "links 'main' to 'A B A B'. "
- "("
- "While one repetition is usually sufficient, pathological object "
- "file and symbol arrangements can require more. "
- "One may handle such cases by manually repeating the component in "
- "the last target_link_libraries call. "
- "However, if two archives are really so interdependent they should "
- "probably be combined into a single archive."
- ")"
- "\n"
- "Arguments to target_link_libraries may use \"generator expressions\" "
- "with the syntax \"$<...>\". Note however, that generator expressions "
- "will not be used in OLD handling of CMP0003 or CMP0004."
- "\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
- ;
- }
-
- cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand);
private:
void LinkLibraryTypeSpecifierWarning(int left, int right);
static const char* LinkLibraryTypeNames[3];
cmTarget* Target;
- enum ProcessingState {
+ enum ProcessingState
+ {
ProcessingLinkLibraries,
ProcessingPlainLinkInterface,
ProcessingKeywordLinkInterface,
@@ -213,9 +54,7 @@ private:
ProcessingState CurrentProcessingState;
- bool HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
+ bool HandleLibrary(const std::string& lib, cmTargetLinkLibraryType llt);
};
-
-
#endif
diff --git a/Source/cmTargetLinkLibraryType.h b/Source/cmTargetLinkLibraryType.h
new file mode 100644
index 000000000..192c6da29
--- /dev/null
+++ b/Source/cmTargetLinkLibraryType.h
@@ -0,0 +1,13 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetLinkLibraryType_h
+#define cmTargetLinkLibraryType_h
+
+enum cmTargetLinkLibraryType
+{
+ GENERAL_LibraryType,
+ DEBUG_LibraryType,
+ OPTIMIZED_LibraryType
+};
+
+#endif
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 1862cb696..45fe430c1 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -1,169 +1,142 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetPropCommandBase.h"
#include "cmGlobalGenerator.h"
-
-//----------------------------------------------------------------------------
-bool cmTargetPropCommandBase
-::HandleArguments(std::vector<std::string> const& args, const char *prop,
- ArgumentFlags flags)
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+bool cmTargetPropCommandBase::HandleArguments(
+ std::vector<std::string> const& args, const std::string& prop,
+ ArgumentFlags flags)
{
- if(args.size() < 2)
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// Lookup the target for which libraries are specified.
- if (this->Makefile->IsAlias(args[0].c_str()))
- {
+ if (this->Makefile->IsAlias(args[0])) {
this->SetError("can not be used on an ALIAS target.");
return false;
- }
+ }
this->Target =
- this->Makefile->GetCMakeInstance()
- ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
- if(!this->Target)
- {
- this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
- }
- if(!this->Target)
- {
+ this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
+ args[0]);
+ if (!this->Target) {
+ this->Target = this->Makefile->FindTargetToUse(args[0]);
+ }
+ if (!this->Target) {
this->HandleMissingTarget(args[0]);
return false;
- }
- if ((this->Target->GetType() != cmTarget::SHARED_LIBRARY)
- && (this->Target->GetType() != cmTarget::STATIC_LIBRARY)
- && (this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
- && (this->Target->GetType() != cmTarget::MODULE_LIBRARY)
- && (this->Target->GetType() != cmTarget::EXECUTABLE))
- {
+ }
+ if ((this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::EXECUTABLE)) {
this->SetError("called with non-compilable target type");
return false;
- }
+ }
bool system = false;
unsigned int argIndex = 1;
- if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM")
- {
- if (args.size() < 3)
- {
+ if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
system = true;
++argIndex;
- }
+ }
bool prepend = false;
- if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE")
- {
- if (args.size() < 3)
- {
+ if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
prepend = true;
++argIndex;
- }
+ }
this->Property = prop;
- while (argIndex < args.size())
- {
- if (!this->ProcessContentArgs(args, argIndex, prepend, system))
- {
+ while (argIndex < args.size()) {
+ if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool cmTargetPropCommandBase
-::ProcessContentArgs(std::vector<std::string> const& args,
- unsigned int &argIndex, bool prepend, bool system)
+bool cmTargetPropCommandBase::ProcessContentArgs(
+ std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
+ bool system)
{
- const std::string scope = args[argIndex];
+ std::string const& scope = args[argIndex];
- if(scope != "PUBLIC"
- && scope != "PRIVATE"
- && scope != "INTERFACE" )
- {
+ if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
this->SetError("called with invalid arguments");
return false;
- }
+ }
- if(this->Target->IsImported())
- {
+ 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;
- for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex)
- {
- if(args[i] == "PUBLIC"
- || args[i] == "PRIVATE"
- || args[i] == "INTERFACE" )
- {
- this->PopulateTargetProperies(scope, content, prepend, system);
- return true;
- }
- content.push_back(args[i]);
+ 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);
}
- this->PopulateTargetProperies(scope, content, prepend, system);
- return true;
+ content.push_back(args[i]);
+ }
+ return this->PopulateTargetProperies(scope, content, prepend, system);
}
-//----------------------------------------------------------------------------
-void cmTargetPropCommandBase
-::PopulateTargetProperies(const std::string &scope,
- const std::vector<std::string> &content,
- bool prepend, bool system)
+bool cmTargetPropCommandBase::PopulateTargetProperies(
+ const std::string& scope, const std::vector<std::string>& content,
+ bool prepend, bool system)
{
- if (scope == "PRIVATE" || scope == "PUBLIC")
- {
- this->HandleDirectContent(this->Target, content, prepend, system);
+ if (scope == "PRIVATE" || scope == "PUBLIC") {
+ if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
+ return false;
}
- if (scope == "INTERFACE" || scope == "PUBLIC")
- {
+ }
+ if (scope == "INTERFACE" || scope == "PUBLIC") {
this->HandleInterfaceContent(this->Target, content, prepend, system);
- }
+ }
+ return true;
}
-//----------------------------------------------------------------------------
-void cmTargetPropCommandBase::HandleInterfaceContent(cmTarget *tgt,
- const std::vector<std::string> &content,
- bool prepend, bool)
+void cmTargetPropCommandBase::HandleInterfaceContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
{
- if (prepend)
- {
+ if (prepend) {
const std::string propName = std::string("INTERFACE_") + this->Property;
- const char *propValue = tgt->GetProperty(propName.c_str());
- const std::string totalContent = this->Join(content) + (propValue
- ? std::string(";") + propValue
- : std::string());
- tgt->SetProperty(propName.c_str(), totalContent.c_str());
- }
- else
- {
- tgt->AppendProperty(("INTERFACE_" + this->Property).c_str(),
- this->Join(content).c_str());
- }
+ const char* propValue = tgt->GetProperty(propName);
+ const std::string totalContent = this->Join(content) +
+ (propValue ? std::string(";") + propValue : std::string());
+ tgt->SetProperty(propName, totalContent.c_str());
+ } else {
+ tgt->AppendProperty("INTERFACE_" + this->Property,
+ this->Join(content).c_str());
+ }
}
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 690582fdd..46a2f6b07 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -1,59 +1,53 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2013 Stephen Kelly <steveire@gmail.com>
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTargetPropCommandBase_h
#define cmTargetPropCommandBase_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmDocumentGeneratorExpressions.h"
class cmTarget;
-//----------------------------------------------------------------------------
class cmTargetPropCommandBase : public cmCommand
{
public:
-
- enum ArgumentFlags {
+ enum ArgumentFlags
+ {
NO_FLAGS = 0,
PROCESS_BEFORE = 1,
PROCESS_SYSTEM = 2
};
bool HandleArguments(std::vector<std::string> const& args,
- const char *prop, ArgumentFlags flags = NO_FLAGS);
+ const std::string& prop,
+ ArgumentFlags flags = NO_FLAGS);
- cmTypeMacro(cmTargetPropCommandBase, cmCommand);
protected:
std::string Property;
- cmTarget *Target;
+ cmTarget* Target;
+
+ virtual void HandleInterfaceContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system);
- 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 void HandleImportedTarget(const std::string& tgt) = 0;
+ virtual void HandleMissingTarget(const std::string& name) = 0;
- virtual void HandleDirectContent(cmTarget *tgt,
- const std::vector<std::string> &content,
+ virtual bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
bool prepend, bool system) = 0;
- virtual std::string Join(const std::vector<std::string> &content) = 0;
+ virtual std::string Join(const std::vector<std::string>& content) = 0;
bool ProcessContentArgs(std::vector<std::string> const& args,
- unsigned int &argIndex, bool prepend, bool system);
- void PopulateTargetProperies(const std::string &scope,
- const std::vector<std::string> &content,
+ unsigned int& argIndex, bool prepend, bool system);
+ bool PopulateTargetProperies(const std::string& scope,
+ const std::vector<std::string>& content,
bool prepend, bool system);
};
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
new file mode 100644
index 000000000..a57bc5aea
--- /dev/null
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -0,0 +1,92 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmTargetPropertyComputer.h"
+
+#include <sstream>
+
+#include "cmMessenger.h"
+#include "cmPolicies.h"
+#include "cmStateSnapshot.h"
+#include "cm_unordered_set.hxx"
+#include "cmake.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;
+ switch (context.GetBottom().GetPolicy(cmPolicies::CMP0026)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n";
+ modal = "should";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ modal = "may";
+ messageType = cmake::FATAL_ERROR;
+ }
+
+ if (modal) {
+ e << "The LOCATION property " << modal << " not be read from target \""
+ << tgtName
+ << "\". Use the target name directly with "
+ "add_custom_command, or use the generator expression $<TARGET_FILE>, "
+ "as appropriate.\n";
+ messenger->IssueMessage(messageType, e.str(), context);
+ }
+
+ return messageType != cmake::FATAL_ERROR;
+}
+
+bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
+ const std::string& prop)
+{
+ 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 (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;
+ }
+
+ return false;
+}
+
+bool cmTargetPropertyComputer::PassesWhitelist(
+ cmStateEnums::TargetType tgtType, std::string const& prop,
+ cmMessenger* messenger, cmListFileBacktrace const& context)
+{
+ if (tgtType == cmStateEnums::INTERFACE_LIBRARY &&
+ !WhiteListedInterfaceProperty(prop)) {
+ std::ostringstream e;
+ e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
+ "The property \""
+ << prop << "\" is not allowed.";
+ messenger->IssueMessage(cmake::FATAL_ERROR, e.str(), context);
+ return false;
+ }
+ return true;
+}
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
new file mode 100644
index 000000000..94688e313
--- /dev/null
+++ b/Source/cmTargetPropertyComputer.h
@@ -0,0 +1,110 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetPropertyComputer_h
+#define cmTargetPropertyComputer_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+#include "cmAlgorithms.h"
+#include "cmListFileCache.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+
+class cmMessenger;
+
+class cmTargetPropertyComputer
+{
+public:
+ template <typename Target>
+ static const char* GetProperty(Target const* tgt, const std::string& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+ {
+ if (const char* loc = GetLocation(tgt, prop, messenger, context)) {
+ return loc;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return CM_NULLPTR;
+ }
+ if (prop == "SOURCES") {
+ return GetSources(tgt, messenger, context);
+ }
+ return CM_NULLPTR;
+ }
+
+ static bool WhiteListedInterfaceProperty(const std::string& prop);
+
+ static bool PassesWhitelist(cmStateEnums::TargetType tgtType,
+ std::string const& prop, cmMessenger* messenger,
+ cmListFileBacktrace const& context);
+
+private:
+ static bool HandleLocationPropertyPolicy(std::string const& tgtName,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context);
+
+ template <typename Target>
+ static const char* ComputeLocationForBuild(Target const* tgt);
+ template <typename Target>
+ static const char* ComputeLocation(Target const* tgt,
+ std::string const& config);
+
+ template <typename Target>
+ static const char* GetLocation(Target const* tgt, std::string const& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+
+ {
+ // Watch for special "computed" properties that are dependent on
+ // other properties or variables. Always recompute them.
+ if (tgt->GetType() == cmStateEnums::EXECUTABLE ||
+ tgt->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ tgt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ tgt->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ tgt->GetType() == cmStateEnums::UNKNOWN_LIBRARY) {
+ static const std::string propLOCATION = "LOCATION";
+ if (prop == propLOCATION) {
+ if (!tgt->IsImported() &&
+ !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
+ context)) {
+ return CM_NULLPTR;
+ }
+ return ComputeLocationForBuild(tgt);
+ }
+
+ // Support "LOCATION_<CONFIG>".
+ if (cmHasLiteralPrefix(prop, "LOCATION_")) {
+ if (!tgt->IsImported() &&
+ !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
+ context)) {
+ return CM_NULLPTR;
+ }
+ const char* configName = prop.c_str() + 9;
+ return ComputeLocation(tgt, configName);
+ }
+
+ // Support "<CONFIG>_LOCATION".
+ if (cmHasLiteralSuffix(prop, "_LOCATION") &&
+ !cmHasLiteralPrefix(prop, "XCODE_ATTRIBUTE_")) {
+ std::string configName(prop.c_str(), prop.size() - 9);
+ if (configName != "IMPORTED") {
+ if (!tgt->IsImported() &&
+ !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
+ context)) {
+ return CM_NULLPTR;
+ }
+ return ComputeLocation(tgt, configName);
+ }
+ }
+ }
+ return CM_NULLPTR;
+ }
+
+ template <typename Target>
+ static const char* GetSources(Target const* tgt, cmMessenger* messenger,
+ cmListFileBacktrace const& context);
+};
+
+#endif
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
new file mode 100644
index 000000000..058659a52
--- /dev/null
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -0,0 +1,47 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetSourcesCommand.h"
+
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
+{
+ return this->HandleArguments(args, "SOURCES");
+}
+
+void cmTargetSourcesCommand::HandleImportedTarget(const std::string& tgt)
+{
+ std::ostringstream e;
+ e << "Cannot specify sources for imported target \"" << tgt << "\".";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
+{
+ std::ostringstream e;
+ e << "Cannot specify sources for target \"" << name
+ << "\" "
+ "which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+std::string cmTargetSourcesCommand::Join(
+ const std::vector<std::string>& content)
+{
+ return cmJoin(content, ";");
+}
+
+bool cmTargetSourcesCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
+{
+ tgt->AppendProperty("SOURCES", this->Join(content).c_str());
+ return true;
+}
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
new file mode 100644
index 000000000..09ba72915
--- /dev/null
+++ b/Source/cmTargetSourcesCommand.h
@@ -0,0 +1,43 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetSourcesCommand_h
+#define cmTargetSourcesCommand_h
+
+#include "cmConfigure.h"
+
+#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;
+};
+
+#endif
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index 0904431d1..4d0cbaafc 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -1,205 +1,63 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTest.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
cmTest::cmTest(cmMakefile* mf)
+ : Backtrace(mf->GetBacktrace())
{
this->Makefile = mf;
this->OldStyle = true;
- this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
- this->Backtrace = new cmListFileBacktrace;
- this->Makefile->GetBacktrace(*this->Backtrace);
}
-//----------------------------------------------------------------------------
cmTest::~cmTest()
{
- delete this->Backtrace;
}
-//----------------------------------------------------------------------------
cmListFileBacktrace const& cmTest::GetBacktrace() const
{
- return *this->Backtrace;
+ return this->Backtrace;
}
-//----------------------------------------------------------------------------
-void cmTest::SetName(const char* name)
+void cmTest::SetName(const std::string& name)
{
- if ( !name )
- {
- name = "";
- }
this->Name = name;
}
-//----------------------------------------------------------------------------
void cmTest::SetCommand(std::vector<std::string> const& command)
{
this->Command = command;
}
-//----------------------------------------------------------------------------
-const char *cmTest::GetProperty(const char* prop) const
+const char* cmTest::GetProperty(const std::string& prop) const
{
- bool chain = false;
- const char *retVal =
- this->Properties.GetPropertyValue(prop, cmProperty::TEST, chain);
- if (chain)
- {
- return this->Makefile->GetProperty(prop,cmProperty::TEST);
+ const char* retVal = this->Properties.GetPropertyValue(prop);
+ if (!retVal) {
+ const bool chain =
+ this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST);
+ if (chain) {
+ return this->Makefile->GetProperty(prop, chain);
}
+ }
return retVal;
}
-//----------------------------------------------------------------------------
-bool cmTest::GetPropertyAsBool(const char* prop) const
+bool cmTest::GetPropertyAsBool(const std::string& prop) const
{
return cmSystemTools::IsOn(this->GetProperty(prop));
}
-//----------------------------------------------------------------------------
-void cmTest::SetProperty(const char* prop, const char* value)
+void cmTest::SetProperty(const std::string& prop, const char* value)
{
- if (!prop)
- {
- return;
- }
-
- this->Properties.SetProperty(prop, value, cmProperty::TEST);
+ this->Properties.SetProperty(prop, value);
}
-//----------------------------------------------------------------------------
-void cmTest::AppendProperty(const char* prop, const char* value, bool asString)
+void cmTest::AppendProperty(const std::string& prop, const char* value,
+ bool asString)
{
- if (!prop)
- {
- return;
- }
- this->Properties.AppendProperty(prop, value, cmProperty::TEST, asString);
-}
-
-//----------------------------------------------------------------------------
-void cmTest::DefineProperties(cmake *cm)
-{
- cm->DefineProperty
- ("ATTACHED_FILES", cmProperty::TEST,
- "Attach a list of files to a dashboard submission.",
- "Set this property to a list of files that will be encoded and "
- "submitted to the dashboard as an addition to the test result.");
-
- cm->DefineProperty
- ("ATTACHED_FILES_ON_FAIL", cmProperty::TEST,
- "Attach a list of files to a dashboard submission if the test fails.",
- "Same as ATTACHED_FILES, but these files will only be included if the "
- "test does not pass.");
-
- cm->DefineProperty
- ("COST", cmProperty::TEST,
- "Set this to a floating point value. Tests in a test set will be "
- "run in descending order of cost.", "This property describes the cost "
- "of a test. You can explicitly set this value; tests with higher COST "
- "values will run first.");
-
- cm->DefineProperty
- ("DEPENDS", cmProperty::TEST,
- "Specifies that this test should only be run after the specified "
- "list of tests.",
- "Set this to a list of tests that must finish before this test is run.");
-
- cm->DefineProperty
- ("ENVIRONMENT", cmProperty::TEST,
- "Specify environment variables that should be defined for running "
- "a test.",
- "If set to a list of environment variables and values of the form "
- "MYVAR=value those environment variables will be defined while "
- "running the test. The environment is restored to its previous state "
- "after the test is done.");
-
- cm->DefineProperty
- ("FAIL_REGULAR_EXPRESSION", cmProperty::TEST,
- "If the output matches this regular expression the test will fail.",
- "If set, if the output matches one of "
- "specified regular expressions, the test will fail."
- "For example: FAIL_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\"");
-
- cm->DefineProperty
- ("LABELS", cmProperty::TEST,
- "Specify a list of text labels associated with a test.",
- "The list is reported in dashboard submissions.");
-
- cm->DefineProperty
- ("RESOURCE_LOCK", cmProperty::TEST,
- "Specify a list of resources that are locked by this test.",
- "If multiple tests specify the same resource lock, they are guaranteed "
- "not to run concurrently.");
-
- cm->DefineProperty
- ("MEASUREMENT", cmProperty::TEST,
- "Specify a CDASH measurement and value to be reported for a test.",
- "If set to a name then that name will be reported to CDASH as a "
- "named measurement with a value of 1. You may also specify a value "
- "by setting MEASUREMENT to \"measurement=value\".");
-
- cm->DefineProperty
- ("PASS_REGULAR_EXPRESSION", cmProperty::TEST,
- "The output must match this regular expression for the test to pass.",
- "If set, the test output will be checked "
- "against the specified regular expressions and at least one of the"
- " regular expressions has to match, otherwise the test will fail.");
-
- cm->DefineProperty
- ("PROCESSORS", cmProperty::TEST,
- "How many process slots this test requires",
- "Denotes the number of processors that this test will require. This is "
- "typically used for MPI tests, and should be used in conjunction with "
- "the ctest_test PARALLEL_LEVEL option.");
-
- cm->DefineProperty
- ("REQUIRED_FILES", cmProperty::TEST,
- "List of files required to run the test.",
- "If set to a list of files, the test will not be run unless all of the "
- "files exist.");
-
- cm->DefineProperty
- ("RUN_SERIAL", cmProperty::TEST,
- "Do not run this test in parallel with any other test.",
- "Use this option in conjunction with the ctest_test PARALLEL_LEVEL "
- "option to specify that this test should not be run in parallel with "
- "any other tests.");
-
- cm->DefineProperty
- ("TIMEOUT", cmProperty::TEST,
- "How many seconds to allow for this test.",
- "This property if set will limit a test to not take more than "
- "the specified number of seconds to run. If it exceeds that the "
- "test process will be killed and ctest will move to the next test. "
- "This setting takes precedence over "
- "CTEST_TESTING_TIMEOUT.");
-
- cm->DefineProperty
- ("WILL_FAIL", cmProperty::TEST,
- "If set to true, this will invert the pass/fail flag of the test.",
- "This property can be used for tests that are expected to fail and "
- "return a non zero return code.");
-
- cm->DefineProperty
- ("WORKING_DIRECTORY", cmProperty::TEST,
- "The directory from which the test executable will be called.",
- "If this is not set it is called from the directory the test executable "
- "is located in.");
+ this->Properties.AppendProperty(prop, value, asString);
}
diff --git a/Source/cmTest.h b/Source/cmTest.h
index 73ac133f1..d4839d171 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -1,21 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTest_h
#define cmTest_h
-#include "cmCustomCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmListFileCache.h"
#include "cmPropertyMap.h"
+
+#include <string>
+#include <vector>
+
class cmMakefile;
-class cmListFileBacktrace;
/** \class cmTest
* \brief Represent a test
@@ -31,32 +27,22 @@ public:
~cmTest();
///! Set the test name
- void SetName(const char* name);
- const char* GetName() const { return this->Name.c_str(); }
+ 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;
- }
-
- /**
- * Print the structure to std::cout.
- */
- void Print() const;
+ std::vector<std::string> const& GetCommand() const { return this->Command; }
///! Set/Get a property of this source file
- void SetProperty(const char *prop, const char *value);
- void AppendProperty(const char* prop, const char* value,bool asString=false);
- const char *GetProperty(const char *prop) const;
- bool GetPropertyAsBool(const char *prop) const;
- cmPropertyMap &GetProperties() { return this->Properties; };
-
- // Define the properties
- static void DefineProperties(cmake *cm);
+ 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) const;
+ bool GetPropertyAsBool(const std::string& prop) const;
+ cmPropertyMap& GetProperties() { return this->Properties; }
/** Get the cmMakefile instance that owns this test. */
- cmMakefile *GetMakefile() { return this->Makefile;};
+ cmMakefile* GetMakefile() { return this->Makefile; }
/** Get the backtrace of the command that created this test. */
cmListFileBacktrace const& GetBacktrace() const;
@@ -67,14 +53,13 @@ public:
private:
cmPropertyMap Properties;
- cmStdString Name;
+ std::string Name;
std::vector<std::string> Command;
bool OldStyle;
cmMakefile* Makefile;
- cmListFileBacktrace* Backtrace;
+ cmListFileBacktrace Backtrace;
};
#endif
-
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 42f511ea3..be4b37847 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -1,92 +1,63 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTestGenerator.h"
+#include <map>
+#include <ostream>
+#include <utility>
+
#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmProperty.h"
+#include "cmPropertyMap.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
#include "cmTest.h"
-//----------------------------------------------------------------------------
-cmTestGenerator
-::cmTestGenerator(cmTest* test,
- std::vector<std::string> const& configurations):
- cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations),
- Test(test)
+cmTestGenerator::cmTestGenerator(
+ cmTest* test, std::vector<std::string> const& configurations)
+ : cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations)
+ , Test(test)
{
this->ActionsPerConfig = !test->GetOldStyle();
this->TestGenerated = false;
+ this->LG = CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-cmTestGenerator
-::~cmTestGenerator()
+cmTestGenerator::~cmTestGenerator()
{
}
-//----------------------------------------------------------------------------
-void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
- Indent const& indent)
+void cmTestGenerator::Compute(cmLocalGenerator* lg)
{
- // First create the tests.
- this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
+ this->LG = lg;
+}
- // Now generate the test properties.
- if(this->TestGenerated)
- {
- cmTest* test = this->Test;
- cmMakefile* mf = test->GetMakefile();
- cmLocalGenerator* lg = mf->GetLocalGenerator();
- std::ostream& fout = os;
- cmPropertyMap::const_iterator pit;
- cmPropertyMap* mpit = &test->GetProperties();
- if ( mpit->size() )
- {
- fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
- for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
- {
- fout << " " << pit->first
- << " " << lg->EscapeForCMake(pit->second.GetValue());
- }
- fout << ")" << std::endl;
- }
- }
+void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
+{
+ // Create the tests.
+ this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
}
-//----------------------------------------------------------------------------
-void cmTestGenerator::GenerateScriptActions(std::ostream& os,
- Indent const& indent)
+void cmTestGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
{
- if(this->ActionsPerConfig)
- {
+ if (this->ActionsPerConfig) {
// This is the per-config generation in a single-configuration
// build generator case. The superclass will call our per-config
// method.
this->cmScriptGenerator::GenerateScriptActions(os, indent);
- }
- else
- {
+ } else {
// This is an old-style test, so there is only one config.
- //assert(this->Test->GetOldStyle());
+ // assert(this->Test->GetOldStyle());
this->GenerateOldStyle(os, indent);
- }
+ }
}
-//----------------------------------------------------------------------------
void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
- const char* config,
- Indent const& indent)
+ const std::string& config,
+ Indent indent)
{
this->TestGenerated = true;
@@ -94,7 +65,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
cmGeneratorExpression ge(this->Test->GetBacktrace());
// Start the test command.
- os << indent << "ADD_TEST(" << this->Test->GetName() << " ";
+ os << indent << "add_test(" << this->Test->GetName() << " ";
// Get the test command line to be executed.
std::vector<std::string> const& command = this->Test->GetCommand();
@@ -102,52 +73,70 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Check whether the command executable is a target whose name is to
// be translated.
std::string exe = command[0];
- cmMakefile* mf = this->Test->GetMakefile();
- cmTarget* target = mf->FindTargetToUse(exe.c_str());
- if(target && target->GetType() == cmTarget::EXECUTABLE)
- {
+ cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(exe);
+ if (target && target->GetType() == cmStateEnums::EXECUTABLE) {
// Use the target file on disk.
exe = target->GetFullPath(config);
+
+ // 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);
+ 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) << " ";
+ }
}
- else
- {
+ } else {
// Use the command name given.
- exe = ge.Parse(exe.c_str())->Evaluate(mf, config);
+ exe = ge.Parse(exe.c_str())->Evaluate(this->LG, config);
cmSystemTools::ConvertToUnixSlashes(exe);
- }
+ }
// Generate the command line with full escapes.
- cmLocalGenerator* lg = mf->GetLocalGenerator();
- os << lg->EscapeForCMake(exe.c_str());
- for(std::vector<std::string>::const_iterator ci = command.begin()+1;
- ci != command.end(); ++ci)
- {
- os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config));
- }
+ 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));
+ }
// 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;
+ }
}
-//----------------------------------------------------------------------------
-void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os,
- Indent const& indent)
+void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent)
{
- os << indent << "ADD_TEST(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
+ os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
}
-//----------------------------------------------------------------------------
bool cmTestGenerator::NeedsScriptNoConfig() const
{
- return (this->TestGenerated && // test generated for at least one config
+ return (this->TestGenerated && // test generated for at least one config
this->ActionsPerConfig && // test is config-aware
- this->Configurations.empty() && // test runs in all configs
+ this->Configurations.empty() && // test runs in all configs
!this->ConfigurationTypes->empty()); // config-dependent command
}
-//----------------------------------------------------------------------------
-void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
- Indent const& indent)
+void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent)
{
this->TestGenerated = true;
@@ -157,28 +146,37 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
std::string exe = command[0];
cmSystemTools::ConvertToUnixSlashes(exe);
fout << indent;
- fout << "ADD_TEST(";
+ 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::vector<std::string>::const_iterator argit = command.begin() + 1;
+ argit != command.end(); ++argit) {
// 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 (std::string::const_iterator c = argit->begin(); c != argit->end();
+ ++c) {
// 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 << "\"";
+ 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 << ")" << std::endl;
+ }
}
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h
index 2c69fc3c5..b2273050f 100644
--- a/Source/cmTestGenerator.h
+++ b/Source/cmTestGenerator.h
@@ -1,43 +1,45 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTestGenerator_h
#define cmTestGenerator_h
+#include "cmConfigure.h"
+
#include "cmScriptGenerator.h"
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
class cmTest;
/** \class cmTestGenerator
* \brief Support class for generating install scripts.
*
*/
-class cmTestGenerator: public cmScriptGenerator
+class cmTestGenerator : public cmScriptGenerator
{
+ CM_DISABLE_COPY(cmTestGenerator)
+
public:
cmTestGenerator(cmTest* test,
- std::vector<std::string> const&
- configurations = std::vector<std::string>());
- virtual ~cmTestGenerator();
+ std::vector<std::string> const& configurations =
+ std::vector<std::string>());
+ ~cmTestGenerator() CM_OVERRIDE;
-protected:
- virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
- virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
- virtual void GenerateScriptForConfig(std::ostream& os,
- const char* config,
- Indent const& indent);
- virtual void GenerateScriptNoConfig(std::ostream& os, Indent const& indent);
- virtual bool NeedsScriptNoConfig() const;
- void GenerateOldStyle(std::ostream& os, Indent const& indent);
+ void Compute(cmLocalGenerator* lg);
+protected:
+ void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScriptActions(std::ostream& os, Indent indent) CM_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;
+ void GenerateOldStyle(std::ostream& os, Indent indent);
+
+ cmLocalGenerator* LG;
cmTest* Test;
bool TestGenerated;
};
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index ac26503c6..4b9718847 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -1,112 +1,130 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTimestamp.h"
+#include "cmConfigure.h"
#include <cstring>
+#include <sstream>
+#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
-std::string cmTimestamp::CurrentTime(
- const std::string& formatString, bool utcFlag)
+std::string cmTimestamp::CurrentTime(const std::string& formatString,
+ bool utcFlag)
{
- time_t currentTimeT = time(0);
- if(currentTimeT == time_t(-1))
- {
- return std::string();
+ time_t currentTimeT = time(CM_NULLPTR);
+ std::string source_date_epoch;
+ cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
+ if (!source_date_epoch.empty()) {
+ std::istringstream iss(source_date_epoch);
+ iss >> currentTimeT;
+ if (iss.fail() || !iss.eof()) {
+ cmSystemTools::Error("Cannot parse SOURCE_DATE_EPOCH as integer");
+ exit(27);
}
+ }
+ if (currentTimeT == time_t(-1)) {
+ return std::string();
+ }
return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
}
-//----------------------------------------------------------------------------
std::string cmTimestamp::FileModificationTime(const char* path,
- const std::string& formatString, bool utcFlag)
+ const std::string& formatString,
+ bool utcFlag)
{
- struct stat info;
- memset(&info, 0, sizeof(info));
-
- if(stat(path, &info) != 0)
- {
+ if (!cmsys::SystemTools::FileExists(path)) {
return std::string();
- }
+ }
- return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag);
+ time_t mtime = cmsys::SystemTools::ModifiedTime(path);
+ return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
}
-//----------------------------------------------------------------------------
std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
- std::string formatString, bool utcFlag)
+ std::string formatString,
+ bool utcFlag) const
{
- if(formatString.empty())
- {
+ if (formatString.empty()) {
formatString = "%Y-%m-%dT%H:%M:%S";
- if(utcFlag)
- {
+ if (utcFlag) {
formatString += "Z";
- }
}
+ }
struct tm timeStruct;
memset(&timeStruct, 0, sizeof(timeStruct));
- struct tm* ptr = (struct tm*) 0;
- if(utcFlag)
- {
+ struct tm* ptr = (struct tm*)CM_NULLPTR;
+ if (utcFlag) {
ptr = gmtime(&timeT);
- }
- else
- {
+ } else {
ptr = localtime(&timeT);
- }
+ }
- if(ptr == 0)
- {
+ if (ptr == CM_NULLPTR) {
return std::string();
- }
+ }
timeStruct = *ptr;
std::string result;
- for(std::string::size_type i = 0; i < formatString.size(); ++i)
- {
+ for (std::string::size_type i = 0; i < formatString.size(); ++i) {
char c1 = formatString[i];
- char c2 = (i+1 < formatString.size()) ?
- formatString[i+1] : static_cast<char>(0);
+ char c2 = (i + 1 < formatString.size()) ? formatString[i + 1]
+ : static_cast<char>(0);
- if(c1 == '%' && c2 != 0)
- {
- result += AddTimestampComponent(c2, timeStruct);
+ if (c1 == '%' && c2 != 0) {
+ result += AddTimestampComponent(c2, timeStruct, timeT);
++i;
- }
- else
- {
+ } else {
result += c1;
- }
}
+ }
return result;
}
-//----------------------------------------------------------------------------
-std::string cmTimestamp::AddTimestampComponent(
- char flag, struct tm& timeStruct)
+time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return _mkgmtime(&tm);
+#else
+ // From Linux timegm() manpage.
+
+ std::string tz_old;
+ cmSystemTools::GetEnv("TZ", tz_old);
+ tz_old = "TZ=" + tz_old;
+
+ // The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
+ // It seems that "TZ=" does NOT work, at least under Windows
+ // with neither MSVC nor MinGW, so let's use explicit "TZ=UTC"
+
+ cmSystemTools::PutEnv("TZ=UTC");
+
+ tzset();
+
+ time_t result = mktime(&tm);
+
+ cmSystemTools::PutEnv(tz_old);
+
+ tzset();
+
+ return result;
+#endif
+}
+
+std::string cmTimestamp::AddTimestampComponent(char flag,
+ struct tm& timeStruct,
+ const time_t timeT) const
{
std::string formatString = "%";
formatString += flag;
- switch(flag)
- {
+ switch (flag) {
+ case 'a':
+ case 'b':
case 'd':
case 'H':
case 'I':
@@ -118,17 +136,37 @@ std::string cmTimestamp::AddTimestampComponent(
case 'w':
case 'y':
case 'Y':
+ case '%':
break;
- default:
- {
- return formatString;
+ case 's': // Seconds since UNIX epoch (midnight 1-jan-1970)
+ {
+ // Build a time_t for UNIX epoch and substract from the input "timeT":
+ struct tm tmUnixEpoch;
+ memset(&tmUnixEpoch, 0, sizeof(tmUnixEpoch));
+ tmUnixEpoch.tm_mday = 1;
+ tmUnixEpoch.tm_year = 1970 - 1900;
+
+ const time_t unixEpoch = this->CreateUtcTimeTFromTm(tmUnixEpoch);
+ if (unixEpoch == -1) {
+ cmSystemTools::Error(
+ "Error generating UNIX epoch in "
+ "STRING(TIMESTAMP ...). Please, file a bug report aginst CMake");
+ return std::string();
}
+
+ std::ostringstream ss;
+ ss << static_cast<long int>(difftime(timeT, unixEpoch));
+ return ss.str();
+ }
+ default: {
+ return formatString;
}
+ }
char buffer[16];
- size_t size = strftime(buffer, sizeof(buffer),
- formatString.c_str(), &timeStruct);
+ size_t size =
+ strftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct);
return std::string(buffer, size);
}
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
index 24c186983..8dd499a3e 100644
--- a/Source/cmTimestamp.h
+++ b/Source/cmTimestamp.h
@@ -1,22 +1,15 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTimestamp_h
#define cmTimestamp_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include <string>
#include <time.h>
/** \class cmTimestamp
- * \brief Utility class to generate sting representation of a timestamp
+ * \brief Utility class to generate string representation of a timestamp
*
*/
class cmTimestamp
@@ -27,14 +20,17 @@ public:
std::string CurrentTime(const std::string& formatString, bool utcFlag);
std::string FileModificationTime(const char* path,
- const std::string& formatString, bool utcFlag);
+ const std::string& formatString,
+ bool utcFlag);
private:
- std::string CreateTimestampFromTimeT(time_t timeT,
- std::string formatString, bool utcFlag);
+ time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
- std::string AddTimestampComponent(char flag, struct tm& timeStruct);
-};
+ std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString,
+ bool utcFlag) const;
+ std::string AddTimestampComponent(char flag, struct tm& timeStruct,
+ time_t timeT) const;
+};
#endif
diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx
index 12ce015d2..b6bfbfa69 100644
--- a/Source/cmTryCompileCommand.cxx
+++ b/Source/cmTryCompileCommand.cxx
@@ -1,42 +1,35 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTryCompileCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmake.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmTryCompileCommand.h"
+class cmExecutionStatus;
// cmTryCompileCommand
-bool cmTryCompileCommand
-::InitialPass(std::vector<std::string> const& argv, cmExecutionStatus &)
+bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv,
+ cmExecutionStatus&)
{
- if(argv.size() < 3)
- {
+ if (argv.size() < 3) {
return false;
- }
+ }
- if(this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
- cmake::FIND_PACKAGE_MODE)
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "The TRY_COMPILE() command is not supported in --find-package mode.");
+ if (this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
+ cmake::FIND_PACKAGE_MODE) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The TRY_COMPILE() command is not supported in --find-package mode.");
return false;
- }
+ }
- this->TryCompileCode(argv);
+ this->TryCompileCode(argv, false);
// if They specified clean then we clean up what we can
- if (this->SrcFileSignature)
- {
- if(!this->Makefile->GetCMakeInstance()->GetDebugTryCompile())
- {
+ if (this->SrcFileSignature) {
+ if (!this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) {
this->CleanupFiles(this->BinaryDirectory.c_str());
- }
}
+ }
return true;
}
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index a20594cbe..483654822 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTryCompileCommand_h
#define cmTryCompileCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCoreTryCompile.h"
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmTryCompileCommand
* \brief Specifies where to install some files
*
@@ -25,101 +24,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmTryCompileCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmTryCompileCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "try_compile";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Try building some code.";
- }
-
- /**
- * More documentation. */
- virtual const char* GetFullDocumentation() const
- {
- return
- " try_compile(RESULT_VAR <bindir> <srcdir>\n"
- " <projectName> [targetName] [CMAKE_FLAGS flags...]\n"
- " [OUTPUT_VARIABLE <var>])\n"
- "Try building a project. In this form, srcdir should contain a "
- "complete CMake project with a CMakeLists.txt file and all sources. "
- "The bindir and srcdir will not be deleted after this command is run. "
- "Specify targetName to build a specific target instead of the 'all' or "
- "'ALL_BUILD' target."
- "\n"
- " try_compile(RESULT_VAR <bindir> <srcfile|SOURCES srcfile...>\n"
- " [CMAKE_FLAGS flags...]\n"
- " [COMPILE_DEFINITIONS flags...]\n"
- " [LINK_LIBRARIES libs...]\n"
- " [OUTPUT_VARIABLE <var>]\n"
- " [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]])\n"
- "Try building an executable from one or more source files. "
- "In this form the user need only supply one or more source files "
- "that include a definition for 'main'. "
- "CMake will create a CMakeLists.txt file to build the source(s) "
- "as an executable. "
- "Specify COPY_FILE to get a copy of the linked executable at the "
- "given fileName and optionally COPY_FILE_ERROR to capture any error."
- "\n"
- "In this version all files in bindir/CMakeFiles/CMakeTmp "
- "will be cleaned automatically. For debugging, --debug-trycompile can "
- "be passed to cmake to avoid this clean. However, multiple sequential "
- "try_compile operations reuse this single output directory. If you "
- "use --debug-trycompile, you can only debug one try_compile call at a "
- "time. The recommended procedure is to configure with cmake all the "
- "way through once, then delete the cache entry associated with "
- "the try_compile call of interest, and then re-run cmake again with "
- "--debug-trycompile."
- "\n"
- "Some extra flags that can be included are, "
- "INCLUDE_DIRECTORIES, LINK_DIRECTORIES, and LINK_LIBRARIES. "
- "COMPILE_DEFINITIONS are -Ddefinition that will be passed to the "
- "compile line.\n"
- "The srcfile signature also accepts a LINK_LIBRARIES argument which "
- "may contain a list of libraries or IMPORTED targets which will be "
- "linked to in the generated project. If LINK_LIBRARIES is specified "
- "as a parameter to try_compile, then any LINK_LIBRARIES passed as "
- "CMAKE_FLAGS will be ignored.\n"
- "try_compile creates a CMakeList.txt "
- "file on the fly that looks like this:\n"
- " add_definitions( <expanded COMPILE_DEFINITIONS from calling "
- "cmake>)\n"
- " include_directories(${INCLUDE_DIRECTORIES})\n"
- " link_directories(${LINK_DIRECTORIES})\n"
- " add_executable(cmTryCompileExec sources)\n"
- " target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES})\n"
- "In both versions of the command, "
- "if OUTPUT_VARIABLE is specified, then the "
- "output from the build process is stored in the given variable. "
- "The success or failure of the try_compile, i.e. TRUE or FALSE "
- "respectively, is returned in "
- "RESULT_VAR. CMAKE_FLAGS can be used to pass -DVAR:TYPE=VALUE flags "
- "to the cmake that is run during the build. "
- "Set variable CMAKE_TRY_COMPILE_CONFIGURATION to choose a build "
- "configuration."
- ;
- }
-
- cmTypeMacro(cmTryCompileCommand, cmCoreTryCompile);
-
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 4fc0b13c0..07e20e62f 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -1,34 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTryRunCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
+#include <stdio.h>
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmTryRunCommand.h"
-#include "cmCacheManager.h"
-#include "cmTryCompileCommand.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
// cmTryRunCommand
-bool cmTryRunCommand
-::InitialPass(std::vector<std::string> const& argv, cmExecutionStatus &)
+bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
+ cmExecutionStatus&)
{
- if(argv.size() < 4)
- {
+ if (argv.size() < 4) {
return false;
- }
+ }
- if(this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
- cmake::FIND_PACKAGE_MODE)
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "The TRY_RUN() command is not supported in --find-package mode.");
+ if (this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
+ cmake::FIND_PACKAGE_MODE) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The TRY_RUN() command is not supported in --find-package mode.");
return false;
- }
+ }
// build an arg list for TryCompile and extract the runArgs,
std::vector<std::string> tryCompile;
@@ -41,151 +41,121 @@ bool cmTryRunCommand
std::string runArgs;
unsigned int i;
- for (i = 1; i < argv.size(); ++i)
- {
- if (argv[i] == "ARGS")
- {
+ for (i = 1; i < argv.size(); ++i) {
+ if (argv[i] == "ARGS") {
++i;
while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
- argv[i] != "CMAKE_FLAGS")
- {
+ argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_LIBRARIES") {
runArgs += " ";
runArgs += argv[i];
++i;
- }
- if (i < argv.size())
- {
+ }
+ if (i < argv.size()) {
tryCompile.push_back(argv[i]);
- }
}
- else
- {
- if (argv[i] == "OUTPUT_VARIABLE")
- {
- if ( argv.size() <= (i+1) )
- {
+ } else {
+ if (argv[i] == "OUTPUT_VARIABLE") {
+ if (argv.size() <= (i + 1)) {
cmSystemTools::Error(
"OUTPUT_VARIABLE specified but there is no variable");
return false;
- }
+ }
i++;
this->OutputVariable = argv[i];
- }
- else if (argv[i] == "RUN_OUTPUT_VARIABLE")
- {
- if (argv.size() <= (i + 1))
- {
+ } else if (argv[i] == "RUN_OUTPUT_VARIABLE") {
+ if (argv.size() <= (i + 1)) {
cmSystemTools::Error(
"RUN_OUTPUT_VARIABLE specified but there is no variable");
return false;
- }
+ }
i++;
this->RunOutputVariable = argv[i];
- }
- else if (argv[i] == "COMPILE_OUTPUT_VARIABLE")
- {
- if (argv.size() <= (i + 1))
- {
+ } else if (argv[i] == "COMPILE_OUTPUT_VARIABLE") {
+ if (argv.size() <= (i + 1)) {
cmSystemTools::Error(
"COMPILE_OUTPUT_VARIABLE specified but there is no variable");
return false;
- }
+ }
i++;
this->CompileOutputVariable = argv[i];
- }
- else
- {
+ } else {
tryCompile.push_back(argv[i]);
- }
}
}
+ }
// although they could be used together, don't allow it, because
// using OUTPUT_VARIABLE makes crosscompiling harder
- if (this->OutputVariable.size()
- && ((this->RunOutputVariable.size())
- || (this->CompileOutputVariable.size())))
- {
+ if (!this->OutputVariable.empty() &&
+ (!this->RunOutputVariable.empty() ||
+ !this->CompileOutputVariable.empty())) {
cmSystemTools::Error(
"You cannot use OUTPUT_VARIABLE together with COMPILE_OUTPUT_VARIABLE "
"or RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE and/or "
"RUN_OUTPUT_VARIABLE.");
return false;
- }
+ }
bool captureRunOutput = false;
- if (this->OutputVariable.size())
- {
+ if (!this->OutputVariable.empty()) {
captureRunOutput = true;
tryCompile.push_back("OUTPUT_VARIABLE");
tryCompile.push_back(this->OutputVariable);
- }
- if (this->CompileOutputVariable.size())
- {
+ }
+ if (!this->CompileOutputVariable.empty()) {
tryCompile.push_back("OUTPUT_VARIABLE");
tryCompile.push_back(this->CompileOutputVariable);
- }
- if (this->RunOutputVariable.size())
- {
+ }
+ if (!this->RunOutputVariable.empty()) {
captureRunOutput = true;
- }
+ }
this->RunResultVariable = argv[0];
this->CompileResultVariable = argv[1];
// do the try compile
- int res = this->TryCompileCode(tryCompile);
+ int res = this->TryCompileCode(tryCompile, true);
// now try running the command if it compiled
- if (!res)
- {
- if (this->OutputFile.size() == 0)
- {
+ if (!res) {
+ if (this->OutputFile.empty()) {
cmSystemTools::Error(this->FindErrorMessage.c_str());
- }
- else
- {
+ } else {
// "run" it and capture the output
std::string runOutputContents;
- if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING"))
- {
- this->DoNotRunExecutable(runArgs,
- argv[3],
- captureRunOutput ? &runOutputContents : 0);
- }
- else
- {
+ if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") &&
+ !this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) {
+ this->DoNotRunExecutable(runArgs, argv[3], captureRunOutput
+ ? &runOutputContents
+ : CM_NULLPTR);
+ } else {
this->RunExecutable(runArgs, &runOutputContents);
- }
+ }
// now put the output into the variables
- if(this->RunOutputVariable.size())
- {
- this->Makefile->AddDefinition(this->RunOutputVariable.c_str(),
+ if (!this->RunOutputVariable.empty()) {
+ this->Makefile->AddDefinition(this->RunOutputVariable,
runOutputContents.c_str());
- }
+ }
- if(this->OutputVariable.size())
- {
+ if (!this->OutputVariable.empty()) {
// if the TryCompileCore saved output in this outputVariable then
// prepend that output to this output
- const char* compileOutput
- = this->Makefile->GetDefinition(this->OutputVariable.c_str());
- if (compileOutput)
- {
+ const char* compileOutput =
+ this->Makefile->GetDefinition(this->OutputVariable);
+ if (compileOutput) {
runOutputContents = std::string(compileOutput) + runOutputContents;
- }
- this->Makefile->AddDefinition(this->OutputVariable.c_str(),
- runOutputContents.c_str());
}
+ this->Makefile->AddDefinition(this->OutputVariable,
+ runOutputContents.c_str());
}
}
+ }
// if we created a directory etc, then cleanup after ourselves
- if(!this->Makefile->GetCMakeInstance()->GetDebugTryCompile())
- {
+ if (!this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) {
this->CleanupFiles(this->BinaryDirectory.c_str());
- }
+ }
return true;
}
@@ -193,29 +163,44 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
std::string* out)
{
int retVal = -1;
- std::string finalCommand = cmSystemTools::ConvertToRunCommandPath(
- this->OutputFile.c_str());
- if (runArgs.size())
- {
- finalCommand += runArgs;
+
+ std::string finalCommand;
+ const std::string emulator =
+ this->Makefile->GetSafeDefinition("CMAKE_CROSSCOMPILING_EMULATOR");
+ if (!emulator.empty()) {
+ std::vector<std::string> emulatorWithArgs;
+ cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
+ finalCommand +=
+ cmSystemTools::ConvertToRunCommandPath(emulatorWithArgs[0].c_str());
+ finalCommand += " ";
+ for (std::vector<std::string>::const_iterator ei =
+ emulatorWithArgs.begin() + 1;
+ ei != emulatorWithArgs.end(); ++ei) {
+ finalCommand += "\"";
+ finalCommand += *ei;
+ finalCommand += "\"";
+ finalCommand += " ";
}
+ }
+ finalCommand +=
+ cmSystemTools::ConvertToRunCommandPath(this->OutputFile.c_str());
+ if (!runArgs.empty()) {
+ finalCommand += runArgs;
+ }
int timeout = 0;
- bool worked = cmSystemTools::RunSingleCommand(finalCommand.c_str(),
- out, &retVal,
- 0, cmSystemTools::OUTPUT_NONE, timeout);
+ bool worked = cmSystemTools::RunSingleCommand(
+ finalCommand.c_str(), out, out, &retVal, CM_NULLPTR,
+ cmSystemTools::OUTPUT_NONE, timeout);
// set the run var
char retChar[1000];
- if (worked)
- {
+ if (worked) {
sprintf(retChar, "%i", retVal);
- }
- else
- {
+ } else {
strcpy(retChar, "FAILED_TO_RUN");
- }
- this->Makefile->AddCacheDefinition(this->RunResultVariable.c_str(), retChar,
+ }
+ this->Makefile->AddCacheDefinition(this->RunResultVariable, retChar,
"Result of TRY_RUN",
- cmCacheManager::INTERNAL);
+ cmStateEnums::INTERNAL);
}
/* This is only used when cross compiling. Instead of running the
@@ -223,91 +208,83 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
the executable would have produced.
*/
void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
- const std::string& srcFile,
- std::string* out
- )
+ const std::string& srcFile,
+ std::string* out)
{
// 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();
+ std::string copyDest = this->Makefile->GetHomeOutputDirectory();
copyDest += cmake::GetCMakeFilesDirectory();
copyDest += "/";
- copyDest += cmSystemTools::GetFilenameWithoutExtension(
- this->OutputFile.c_str());
+ copyDest += cmSystemTools::GetFilenameWithoutExtension(this->OutputFile);
copyDest += "-";
copyDest += this->RunResultVariable;
- copyDest += cmSystemTools::GetFilenameExtension(this->OutputFile.c_str());
- cmSystemTools::CopyFileAlways(this->OutputFile.c_str(), copyDest.c_str());
+ copyDest += cmSystemTools::GetFilenameExtension(this->OutputFile);
+ cmSystemTools::CopyFileAlways(this->OutputFile, copyDest);
- std::string resultFileName = this->Makefile->GetHomeOutputDirectory();
+ std::string resultFileName = this->Makefile->GetHomeOutputDirectory();
resultFileName += "/TryRunResults.cmake";
std::string detailsString = "For details see ";
detailsString += resultFileName;
- std::string internalRunOutputName=this->RunResultVariable+"__TRYRUN_OUTPUT";
+ std::string internalRunOutputName =
+ this->RunResultVariable + "__TRYRUN_OUTPUT";
bool error = false;
- if (this->Makefile->GetDefinition(this->RunResultVariable.c_str()) == 0)
- {
+ if (this->Makefile->GetDefinition(this->RunResultVariable) == CM_NULLPTR) {
// 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;
- this->Makefile->AddCacheDefinition(this->RunResultVariable.c_str(),
+ this->Makefile->AddCacheDefinition(this->RunResultVariable,
"PLEASE_FILL_OUT-FAILED_TO_RUN",
- comment.c_str(),
- cmCacheManager::STRING);
-
- cmCacheManager::CacheIterator it = this->Makefile->GetCacheManager()->
- GetCacheIterator(this->RunResultVariable.c_str());
- if ( !it.IsAtEnd() )
- {
- it.SetProperty("ADVANCED", "1");
- }
+ comment.c_str(), cmStateEnums::STRING);
- error = true;
+ cmState* state = this->Makefile->GetState();
+ const char* existingValue =
+ state->GetCacheEntryValue(this->RunResultVariable);
+ if (existingValue) {
+ state->SetCacheEntryProperty(this->RunResultVariable, "ADVANCED", "1");
}
+ error = true;
+ }
+
// is the output from the executable used ?
- if (out!=0)
- {
- if (this->Makefile->GetDefinition(internalRunOutputName.c_str()) == 0)
- {
+ if (out != CM_NULLPTR) {
+ if (this->Makefile->GetDefinition(internalRunOutputName) == CM_NULLPTR) {
// if the variables doesn't exist, create it with a helpful error text
// and mark it as advanced
std::string comment;
- comment+="Output of TRY_RUN(), contains the text, which the executable "
- "would have printed on stdout and stderr on its target platform.\n";
+ comment +=
+ "Output of TRY_RUN(), contains the text, which the executable "
+ "would have printed on stdout and stderr on its target platform.\n";
comment += detailsString;
- this->Makefile->AddCacheDefinition(internalRunOutputName.c_str(),
- "PLEASE_FILL_OUT-NOTFOUND",
- comment.c_str(),
- cmCacheManager::STRING);
- cmCacheManager::CacheIterator it = this->Makefile->GetCacheManager()->
- GetCacheIterator(internalRunOutputName.c_str());
- if ( !it.IsAtEnd() )
- {
- it.SetProperty("ADVANCED", "1");
- }
+ this->Makefile->AddCacheDefinition(
+ internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(),
+ cmStateEnums::STRING);
+ cmState* state = this->Makefile->GetState();
+ const char* existing = state->GetCacheEntryValue(internalRunOutputName);
+ if (existing) {
+ state->SetCacheEntryProperty(internalRunOutputName, "ADVANCED", "1");
+ }
error = true;
- }
}
+ }
- if (error)
- {
+ if (error) {
static bool firstTryRun = true;
- std::ofstream file(resultFileName.c_str(),
- firstTryRun ? std::ios::out : std::ios::app);
- if ( file )
- {
- if (firstTryRun)
- {
+ cmsys::ofstream file(resultFileName.c_str(),
+ firstTryRun ? std::ios::out : std::ios::app);
+ if (file) {
+ if (firstTryRun) {
+ /* clang-format off */
file << "# This file was generated by CMake because it detected "
"TRY_RUN() commands\n"
"# in crosscompiling mode. It will be overwritten by the next "
@@ -315,9 +292,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
"# Copy it to a safe location, set the variables to "
"appropriate values\n"
"# and use it then to preset the CMake cache (using -C).\n\n";
- }
+ /* clang-format on */
+ }
- std::string comment ="\n";
+ std::string comment = "\n";
comment += this->RunResultVariable;
comment += "\n indicates whether the executable would have been able "
"to run on its\n"
@@ -326,19 +304,19 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
comment += " to\n"
" the exit code (in many cases 0 for success), otherwise "
"enter \"FAILED_TO_RUN\".\n";
- if (out!=0)
- {
+ if (out != CM_NULLPTR) {
comment += internalRunOutputName;
- comment += "\n contains the text the executable "
- "would have printed on stdout and stderr.\n"
- " If the executable would not have been able to run, set ";
+ comment +=
+ "\n contains the text the executable "
+ "would have printed on stdout and stderr.\n"
+ " If the executable would not have been able to run, set ";
comment += internalRunOutputName;
comment += " empty.\n"
" Otherwise check if the output is evaluated by the "
"calling CMake code. If so,\n"
" check what the source file would have printed when "
"called with the given arguments.\n";
- }
+ }
comment += "The ";
comment += this->CompileResultVariable;
comment += " variable holds the build result for this TRY_RUN().\n\n"
@@ -349,39 +327,36 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
comment += "Run arguments : ";
comment += runArgs;
comment += "\n";
- comment += " Called from: " + this->Makefile->GetListFileStack();
+ comment += " Called from: " + this->Makefile->FormatListFileStack();
cmsys::SystemTools::ReplaceString(comment, "\n", "\n# ");
file << comment << "\n\n";
- file << "SET( " << this->RunResultVariable << " \n \""
- << this->Makefile->GetDefinition(this->RunResultVariable.c_str())
+ file << "set( " << this->RunResultVariable << " \n \""
+ << this->Makefile->GetDefinition(this->RunResultVariable)
<< "\"\n CACHE STRING \"Result from TRY_RUN\" FORCE)\n\n";
- if (out!=0)
- {
- file << "SET( " << internalRunOutputName << " \n \""
- << this->Makefile->GetDefinition(internalRunOutputName.c_str())
+ if (out != CM_NULLPTR) {
+ file << "set( " << internalRunOutputName << " \n \""
+ << this->Makefile->GetDefinition(internalRunOutputName)
<< "\"\n CACHE STRING \"Output from TRY_RUN\" FORCE)\n\n";
- }
- file.close();
}
+ file.close();
+ }
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!=0)
- {
+ if (out != CM_NULLPTR) {
errorMessage += " " + internalRunOutputName + " (advanced)\n";
- }
+ }
errorMessage += detailsString;
cmSystemTools::Error(errorMessage.c_str());
return;
- }
+ }
- if (out!=0)
- {
- (*out) = this->Makefile->GetDefinition(internalRunOutputName.c_str());
- }
+ if (out != CM_NULLPTR) {
+ (*out) = this->Makefile->GetDefinition(internalRunOutputName);
+ }
}
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index 13b997307..c27b026ad 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmTryRunCommand_h
#define cmTryRunCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCoreTryCompile.h"
+class cmCommand;
+class cmExecutionStatus;
+
/** \class cmTryRunCommand
* \brief Specifies where to install some files
*
@@ -25,81 +24,15 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmTryRunCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmTryRunCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "try_run";}
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Try compiling and then running some code.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR\n"
- " bindir srcfile [CMAKE_FLAGS <Flags>]\n"
- " [COMPILE_DEFINITIONS <flags>]\n"
- " [COMPILE_OUTPUT_VARIABLE comp]\n"
- " [RUN_OUTPUT_VARIABLE run]\n"
- " [OUTPUT_VARIABLE var]\n"
- " [ARGS <arg1> <arg2>...])\n"
- "Try compiling a srcfile. Return TRUE or FALSE for success or failure "
- "in COMPILE_RESULT_VAR. Then if the compile succeeded, run the "
- "executable and return its exit code in RUN_RESULT_VAR. "
- "If the executable was built, but failed to run, then RUN_RESULT_VAR "
- "will be set to FAILED_TO_RUN. "
- "COMPILE_OUTPUT_VARIABLE specifies the variable where the output from "
- "the compile step goes. RUN_OUTPUT_VARIABLE specifies the variable "
- "where the output from the running executable goes.\n"
- "For compatibility reasons OUTPUT_VARIABLE is still supported, which "
- "gives you the output from the compile and run step combined.\n"
- "Cross compiling issues\n"
- "When cross compiling, the executable compiled in the first step "
- "usually cannot be run on the build host. try_run() checks the "
- "CMAKE_CROSSCOMPILING variable to detect whether CMake is in "
- "crosscompiling mode. If that's the case, it will still try to compile "
- "the executable, but it will not try to run the executable. Instead it "
- "will create cache variables which must be filled by the user or by "
- "presetting them in some CMake script file to the values the "
- "executable would have produced if it had been run on its actual "
- "target platform. These variables are RUN_RESULT_VAR (explanation see "
- "above) and if RUN_OUTPUT_VARIABLE (or OUTPUT_VARIABLE) was used, an "
- "additional cache variable "
- "RUN_RESULT_VAR__COMPILE_RESULT_VAR__TRYRUN_OUTPUT."
- "This is intended to hold stdout and stderr from the executable.\n"
- "In order to make cross compiling your project easier, use try_run "
- "only if really required. If you use try_run, use RUN_OUTPUT_VARIABLE "
- "(or OUTPUT_VARIABLE) only if really required. Using them will require "
- "that when crosscompiling, the cache variables will have to be set "
- "manually to the output of the executable. You can also \"guard\" the "
- "calls to try_run with if(CMAKE_CROSSCOMPILING) and provide an "
- "easy-to-preset alternative for this case.\n"
- "Set variable CMAKE_TRY_COMPILE_CONFIGURATION to choose a build "
- "configuration."
- ;
- }
-
- cmTypeMacro(cmTryRunCommand, cmCoreTryCompile);
private:
void RunExecutable(const std::string& runArgs,
std::string* runOutputContents);
@@ -114,5 +47,4 @@ private:
std::string CompileOutputVariable;
};
-
#endif
diff --git a/Source/cmUnexpectedCommand.cxx b/Source/cmUnexpectedCommand.cxx
new file mode 100644
index 000000000..a8de9e689
--- /dev/null
+++ b/Source/cmUnexpectedCommand.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 "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
new file mode 100644
index 000000000..995d8a5d6
--- /dev/null
+++ b/Source/cmUnexpectedCommand.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 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 5c0cfaa03..31525ba4a 100644
--- a/Source/cmUnsetCommand.cxx
+++ b/Source/cmUnsetCommand.cxx
@@ -1,59 +1,55 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmUnsetCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmUnsetCommand.h"
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmUnsetCommand
bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &)
+ cmExecutionStatus&)
{
- if(args.size() < 1 || args.size() > 2)
- {
+ if (args.empty() || args.size() > 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
const char* variable = args[0].c_str();
// unset(ENV{VAR})
- if (!strncmp(variable,"ENV{",4) && strlen(variable) > 5)
- {
+ if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) {
// what is the variable name
- char *envVarName = new char [strlen(variable)];
- strncpy(envVarName,variable+4,strlen(variable)-5);
- envVarName[strlen(variable)-5] = '\0';
+ char* envVarName = new char[strlen(variable)];
+ strncpy(envVarName, variable + 4, strlen(variable) - 5);
+ envVarName[strlen(variable) - 5] = '\0';
#ifdef CMAKE_BUILD_WITH_CMAKE
cmSystemTools::UnsetEnv(envVarName);
#endif
delete[] envVarName;
return true;
- }
+ }
// unset(VAR)
- else if (args.size() == 1)
- {
+ if (args.size() == 1) {
this->Makefile->RemoveDefinition(variable);
return true;
- }
+ }
// unset(VAR CACHE)
- else if ((args.size() == 2) && (args[1] == "CACHE"))
- {
+ if ((args.size() == 2) && (args[1] == "CACHE")) {
this->Makefile->RemoveCacheDefinition(variable);
return true;
- }
- // ERROR: second argument isn't CACHE
- else
- {
- this->SetError("called with an invalid second argument");
- return false;
- }
+ }
+ // unset(VAR PARENT_SCOPE)
+ if ((args.size() == 2) && (args[1] == "PARENT_SCOPE")) {
+ this->Makefile->RaiseScope(variable, CM_NULLPTR);
+ return true;
+ }
+ // ERROR: second argument isn't CACHE or PARENT_SCOPE
+ this->SetError("called with an invalid second argument");
+ return false;
}
-
diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h
index 9cf95d98d..2a1f3f0a6 100644
--- a/Source/cmUnsetCommand.h
+++ b/Source/cmUnsetCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmUnsetCommand_h
#define cmUnsetCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmUnsetCommand
* \brief Unset a CMAKE variable
*
@@ -25,55 +23,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmUnsetCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmUnsetCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const {return "unset";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Unset a variable, cache variable, or environment variable.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " unset(<variable> [CACHE])\n"
- "Removes the specified variable causing it to become undefined. "
- "If CACHE is present then the variable is removed from the cache "
- "instead of the current scope.\n"
- "<variable> can be an environment variable such as:\n"
- " unset(ENV{LD_LIBRARY_PATH})\n"
- "in which case the variable will be removed from the current "
- "environment.";
- }
-
- cmTypeMacro(cmUnsetCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index 4c189e665..07095b137 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -1,68 +1,56 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmUseMangledMesaCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmUseMangledMesaCommand.h"
#include "cmSystemTools.h"
-#include <cmsys/RegularExpression.hxx>
+class cmExecutionStatus;
-// cmUseMangledMesaCommand
-bool cmUseMangledMesaCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
// expected two arguments:
// arguement one: the full path to gl_mangle.h
// arguement two : directory for output of edited headers
- if(args.size() != 2)
- {
+ if (args.size() != 2) {
this->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()))
- {
+ if (!cmSystemTools::FileExists(glh.c_str())) {
std::string e = "Bad path to Mesa, could not find: ";
e += glh;
e += " ";
- this->SetError(e.c_str());
+ this->SetError(e);
return false;
- }
+ }
const char* destDir = args[1].c_str();
std::vector<std::string> files;
cmSystemTools::Glob(inputDir, "\\.h$", files);
- if(files.size() == 0)
- {
+ if (files.empty()) {
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)
- {
+ 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);
- }
+ }
return true;
}
-void
-cmUseMangledMesaCommand::
-CopyAndFullPathMesaHeader(const char* source,
- const char* outdir)
+void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source,
+ const char* outdir)
{
std::string dir, file;
cmSystemTools::SplitProgramPath(source, dir, file);
@@ -71,21 +59,19 @@ CopyAndFullPathMesaHeader(const char* source,
outFile += file;
std::string tempOutputFile = outFile;
tempOutputFile += ".tmp";
- std::ofstream fout(tempOutputFile.c_str());
- if(!fout)
- {
+ cmsys::ofstream fout(tempOutputFile.c_str());
+ if (!fout) {
cmSystemTools::Error("Could not open file for write in copy operation: ",
tempOutputFile.c_str(), outdir);
cmSystemTools::ReportLastSystemError("");
return;
- }
- std::ifstream fin(source);
- if(!fin)
- {
+ }
+ cmsys::ifstream fin(source);
+ if (!fin) {
cmSystemTools::Error("Could not open file for read in copy operation",
source);
return;
- }
+ }
// now copy input to output and expand variables in the
// input file at the same time
std::string inLine;
@@ -96,36 +82,25 @@ CopyAndFullPathMesaHeader(const char* source,
cmsys::RegularExpression glDirLine("(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()))
- {
+ while (cmSystemTools::GetLineFromStream(fin, inLine)) {
+ if (includeLine.find(inLine.c_str())) {
std::string includeFile = includeLine.match(1);
- if(glDirLine.find(includeFile.c_str()))
- {
+ if (glDirLine.find(includeFile.c_str())) {
std::string gfile = glDirLine.match(3);
- fout << "#include \"" << outdir << "/" << gfile.c_str() << "\"\n";
- }
- else if(glLine.find(includeFile.c_str()))
- {
- fout << "#include \"" << outdir << "/" <<
- includeLine.match(1).c_str() << "\"\n";
- }
- else
- {
+ fout << "#include \"" << outdir << "/" << gfile << "\"\n";
+ } else if (glLine.find(includeFile.c_str())) {
+ fout << "#include \"" << outdir << "/" << includeLine.match(1)
+ << "\"\n";
+ } else {
fout << inLine << "\n";
- }
}
- else
- {
+ } else {
fout << inLine << "\n";
- }
}
+ }
// close the files before attempting to copy
fin.close();
fout.close();
- cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(),
- outFile.c_str());
- cmSystemTools::RemoveFile(tempOutputFile.c_str());
+ cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(), outFile.c_str());
+ cmSystemTools::RemoveFile(tempOutputFile);
}
-
diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h
index 2f52960c4..511882989 100644
--- a/Source/cmUseMangledMesaCommand.h
+++ b/Source/cmUseMangledMesaCommand.h
@@ -1,88 +1,26 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmUseMangledMesaCommand_h
#define cmUseMangledMesaCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-#include "cmSourceFile.h"
+class cmExecutionStatus;
-/** \class cmUseMangledMesaCommand
- * \brief Create Tcl Wrappers for VTK classes.
- *
- * cmUseMangledMesaCommand is used to define a CMake variable include
- * path location by specifying a file and list of directories.
- */
class cmUseMangledMesaCommand : public cmCommand
{
public:
- cmTypeMacro(cmUseMangledMesaCommand, cmCommand);
-
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmUseMangledMesaCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "use_mangled_mesa";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Copy mesa headers for use in combination with system GL.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " use_mangled_mesa(PATH_TO_MESA OUTPUT_DIRECTORY)\n"
- "The path to mesa includes, should contain gl_mangle.h. "
- "The mesa headers are copied to the specified output directory. "
- "This allows mangled mesa headers to override other GL headers by "
- "being added to the include directory path earlier.";
- }
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
+ 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);
+ void CopyAndFullPathMesaHeader(const char* source, const char* outdir);
};
-
#endif
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index 6ea3dfac8..eabd7ef31 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -1,32 +1,30 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmUtilitySourceCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <string.h>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmUtilitySourceCommand.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
// cmUtilitySourceCommand
-bool cmUtilitySourceCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 3)
- {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::vector<std::string>::const_iterator arg = args.begin();
// The first argument is the cache entry name.
- std::string cacheEntry = *arg++;
- const char* cacheValue =
- this->Makefile->GetDefinition(cacheEntry.c_str());
+ std::string const& cacheEntry = *arg++;
+ const char* cacheValue = this->Makefile->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.
@@ -34,94 +32,83 @@ bool cmUtilitySourceCommand
this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
bool haveCacheValue = false;
- if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING"))
- {
- haveCacheValue = (cacheValue != 0);
- if (!haveCacheValue)
- {
+ if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
+ haveCacheValue = (cacheValue != CM_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");
- }
- }
- else
- {
- haveCacheValue = (cacheValue &&
- (strstr(cacheValue, "(IntDir)") == 0 ||
- (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
- (this->Makefile->GetCacheMajorVersion() != 0 &&
- this->Makefile->GetCacheMinorVersion() != 0 ));
+ "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");
}
-
- if(haveCacheValue)
- {
+ } else {
+ cmState* state = this->Makefile->GetState();
+ haveCacheValue =
+ (cacheValue && (strstr(cacheValue, "(IntDir)") == CM_NULLPTR ||
+ (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
+ (state->GetCacheMajorVersion() != 0 &&
+ state->GetCacheMinorVersion() != 0));
+ }
+
+ if (haveCacheValue) {
return true;
- }
+ }
// The second argument is the utility's executable name, which will be
// needed later.
- std::string utilityName = *arg++;
+ std::string const& utilityName = *arg++;
// The third argument specifies the relative directory of the source
// of the utility.
- std::string relativeSource = *arg++;
- std::string utilitySource = this->Makefile->GetCurrentDirectory();
- utilitySource = utilitySource+"/"+relativeSource;
+ std::string const& relativeSource = *arg++;
+ std::string utilitySource = this->Makefile->GetCurrentSourceDirectory();
+ utilitySource = utilitySource + "/" + relativeSource;
// If the directory doesn't exist, the source has not been included.
- if(!cmSystemTools::FileExists(utilitySource.c_str()))
- { return true; }
+ if (!cmSystemTools::FileExists(utilitySource.c_str())) {
+ 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()))
- { return true; }
+ while (arg != args.end()) {
+ std::string file = utilitySource + "/" + *arg++;
+ if (!cmSystemTools::FileExists(file.c_str())) {
+ return true;
}
+ }
// The source exists.
std::string cmakeCFGout =
this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
- std::string utilityDirectory = this->Makefile->GetCurrentOutputDirectory();
+ std::string utilityDirectory = this->Makefile->GetCurrentBinaryDirectory();
std::string exePath;
- if (this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
- {
+ if (this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")) {
exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
- }
- if(exePath.size())
- {
+ }
+ if (!exePath.empty()) {
utilityDirectory = exePath;
- }
- else
- {
- utilityDirectory += "/"+relativeSource;
- }
+ } else {
+ utilityDirectory += "/" + relativeSource;
+ }
// Construct the cache entry for the executable's location.
- std::string utilityExecutable =
- utilityDirectory+"/"+cmakeCFGout+"/"
- +utilityName+this->Makefile->GetDefinition("CMAKE_EXECUTABLE_SUFFIX");
+ std::string utilityExecutable = utilityDirectory + "/" + cmakeCFGout + "/" +
+ utilityName + this->Makefile->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.c_str(),
- utilityExecutable.c_str(),
- "Path to an internal program.",
- cmCacheManager::FILEPATH);
+ this->Makefile->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.c_str(),
- utilityName.c_str(),
- "Executable to project name.",
- cmCacheManager::INTERNAL);
+ this->Makefile->AddCacheDefinition(utilityExecutable, utilityName.c_str(),
+ "Executable to project name.",
+ cmStateEnums::INTERNAL);
return true;
}
-
diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h
index 195f605f2..a95b48d6a 100644
--- a/Source/cmUtilitySourceCommand.h
+++ b/Source/cmUtilitySourceCommand.h
@@ -1,90 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmUtilitySourceCommand_h
#define cmUtilitySourceCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-/** \class cmUtilitySourceCommand
- * \brief A command to setup a cache entry with the location of a third-party
- * utility's source.
- *
- * cmUtilitySourceCommand is used when a third-party utility's source is
- * included in the project's source tree. It specifies the location of
- * the executable's source, and any files that may be needed to confirm the
- * identity of the source.
- */
+class cmExecutionStatus;
+
class cmUtilitySourceCommand : public cmCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmUtilitySourceCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "utility_source";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Specify the source tree of a third-party utility.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " utility_source(cache_entry executable_name\n"
- " path_to_source [file1 file2 ...])\n"
- "When a third-party utility's source is included in the distribution, "
- "this command specifies its location and name. The cache entry will "
- "not be set unless the path_to_source and all listed files exist. It "
- "is assumed that the source tree of the utility will have been built "
- "before it is needed.\n"
- "When cross compiling CMake will print a warning if a utility_source() "
- "command is executed, because in many cases it is used to build an "
- "executable which is executed later on. This doesn't work when "
- "cross compiling, since the executable can run only on their target "
- "platform. So in this case the cache entry has to be adjusted manually "
- "so it points to an executable which is runnable on the build host.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
-
- cmTypeMacro(cmUtilitySourceCommand, cmCommand);
+ cmCommand* Clone() CM_OVERRIDE { return new cmUtilitySourceCommand; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
-
#endif
diff --git a/Source/cmUtils.hxx b/Source/cmUtils.hxx
new file mode 100644
index 000000000..c5c767c02
--- /dev/null
+++ b/Source/cmUtils.hxx
@@ -0,0 +1,17 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmUtils_hxx
+#define cmUtils_hxx
+
+#include "cmsys/SystemTools.hxx"
+
+// 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).
+inline bool isCMakeVerbose()
+{
+ return (cmSystemTools::HasEnv("VERBOSE") &&
+ !cmSystemTools::HasEnv("CMAKE_NO_VERBOSE"));
+}
+
+#endif
diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx
new file mode 100644
index 000000000..201e1ccef
--- /dev/null
+++ b/Source/cmUuid.cxx
@@ -0,0 +1,175 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmUuid.h"
+
+#include "cmCryptoHash.h"
+
+#include <string.h>
+
+cmUuid::cmUuid()
+{
+ Groups.push_back(4);
+ Groups.push_back(2);
+ Groups.push_back(2);
+ Groups.push_back(2);
+ Groups.push_back(6);
+}
+
+std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name) const
+{
+ std::vector<unsigned char> hashInput;
+ this->CreateHashInput(uuidNamespace, name, hashInput);
+
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
+ md5.Initialize();
+ md5.Append(&hashInput[0], hashInput.size());
+ std::vector<unsigned char> digest = md5.Finalize();
+
+ return this->FromDigest(&digest[0], 3);
+}
+
+std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name) const
+{
+ std::vector<unsigned char> hashInput;
+ this->CreateHashInput(uuidNamespace, name, hashInput);
+
+ cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
+ sha1.Initialize();
+ sha1.Append(&hashInput[0], hashInput.size());
+ std::vector<unsigned char> digest = sha1.Finalize();
+
+ return this->FromDigest(&digest[0], 5);
+}
+
+void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name,
+ std::vector<unsigned char>& output) const
+{
+ output = uuidNamespace;
+
+ if (!name.empty()) {
+ output.resize(output.size() + name.size());
+
+ memcpy(&output[0] + uuidNamespace.size(), name.c_str(), name.size());
+ }
+}
+
+std::string cmUuid::FromDigest(const unsigned char* digest,
+ unsigned char version) const
+{
+ typedef unsigned char byte_t;
+
+ byte_t uuid[16] = { 0 };
+ memcpy(uuid, digest, 16);
+
+ uuid[6] &= 0xF;
+ uuid[6] |= byte_t(version << 4);
+
+ uuid[8] &= 0x3F;
+ uuid[8] |= 0x80;
+
+ return this->BinaryToString(uuid);
+}
+
+bool cmUuid::StringToBinary(std::string const& input,
+ std::vector<unsigned char>& output) const
+{
+ output.clear();
+ output.reserve(16);
+
+ if (input.length() != 36) {
+ return false;
+ }
+ size_t index = 0;
+ for (size_t i = 0; i < this->Groups.size(); ++i) {
+ if (i != 0 && input[index++] != '-') {
+ return false;
+ }
+ size_t digits = this->Groups[i] * 2;
+ if (!StringToBinaryImpl(input.substr(index, digits), output)) {
+ return false;
+ }
+
+ index += digits;
+ }
+
+ return true;
+}
+
+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) {
+ if (i != 0) {
+ output += '-';
+ }
+
+ size_t bytes = this->Groups[i];
+ for (size_t j = 0; j < bytes; ++j) {
+ unsigned char byte = input[inputIndex++];
+ output += this->ByteToHex(byte);
+ }
+ }
+
+ return output;
+}
+
+std::string cmUuid::ByteToHex(unsigned char byte) const
+{
+ 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;
+ }
+
+ return result;
+}
+
+bool cmUuid::StringToBinaryImpl(std::string const& input,
+ std::vector<unsigned char>& output) const
+{
+ if (input.size() % 2) {
+ return false;
+ }
+
+ for (size_t i = 0; i < input.size(); i += 2) {
+ char c1 = 0;
+ if (!IntFromHexDigit(input[i], c1)) {
+ return false;
+ }
+
+ char c2 = 0;
+ if (!IntFromHexDigit(input[i + 1], c2)) {
+ return false;
+ }
+
+ output.push_back(char(c1 << 4 | c2));
+ }
+
+ return true;
+}
+
+bool cmUuid::IntFromHexDigit(char input, char& output) const
+{
+ if (input >= '0' && input <= '9') {
+ output = char(input - '0');
+ return true;
+ }
+ if (input >= 'a' && input <= 'f') {
+ output = char(input - 'a' + 0xA);
+ return true;
+ }
+ if (input >= 'A' && input <= 'F') {
+ output = char(input - 'A' + 0xA);
+ return true;
+ }
+ return false;
+}
diff --git a/Source/cmUuid.h b/Source/cmUuid.h
new file mode 100644
index 000000000..158ce6ee4
--- /dev/null
+++ b/Source/cmUuid.h
@@ -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. */
+#ifndef cmUuid_h
+#define cmUuid_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+/** \class cmUuid
+ * \brief Utility class to generate UUIDs as defined by RFC4122
+ *
+ */
+class cmUuid
+{
+public:
+ cmUuid();
+
+ std::string FromMd5(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name) const;
+
+ std::string FromSha1(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name) const;
+
+ bool StringToBinary(std::string const& input,
+ std::vector<unsigned char>& output) const;
+
+private:
+ std::string ByteToHex(unsigned char byte) const;
+
+ void CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name,
+ std::vector<unsigned char>& output) const;
+
+ std::string FromDigest(const unsigned char* digest,
+ unsigned char version) const;
+
+ bool StringToBinaryImpl(std::string const& input,
+ std::vector<unsigned char>& output) const;
+
+ 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
index a7b1b3651..dbd760ed1 100644
--- a/Source/cmVS10CLFlagTable.h
+++ b/Source/cmVS10CLFlagTable.h
@@ -1,270 +1,204 @@
-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
+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},
+ { "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}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS10CSharpFlagTable.h b/Source/cmVS10CSharpFlagTable.h
new file mode 100644
index 000000000..493ec2b12
--- /dev/null
+++ b/Source/cmVS10CSharpFlagTable.h
@@ -0,0 +1,120 @@
+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
new file mode 100644
index 000000000..da19d649b
--- /dev/null
+++ b/Source/cmVS10CudaFlagTable.h
@@ -0,0 +1,51 @@
+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
new file mode 100644
index 000000000..5b61066ca
--- /dev/null
+++ b/Source/cmVS10CudaHostFlagTable.h
@@ -0,0 +1,35 @@
+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
index 79aeeff71..65f28ef40 100644
--- a/Source/cmVS10LibFlagTable.h
+++ b/Source/cmVS10LibFlagTable.h
@@ -1,102 +1,76 @@
-static cmVS7FlagTable cmVS10LibFlagTable[] =
-{
+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},
+ // 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},
+ { "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},
+ { "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
- {"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
- //Bool Properties With Argument
-
- //String List Properties
+ // 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},
+ { "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},
+ // 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},
+ { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
// Skip [TrackerLogDirectory] - no command line Switch.
// Skip [AdditionalOptions] - no command line Switch.
- {0,0,0,0,0}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h
index 5d1562002..c30ea9a66 100644
--- a/Source/cmVS10LinkFlagTable.h
+++ b/Source/cmVS10LinkFlagTable.h
@@ -1,305 +1,244 @@
-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", 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},
- {"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",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"EnableUAC", "MANIFESTUAC:NO", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired},
- {"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},
+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},
+ { "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},
+ { "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},
+ { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
+ cmVS7FlagTable::UserValue },
// Skip [HeapCommitSize] - no command line Switch.
- {"StackReserveSize", "STACK:",
- "Stack Reserve Size",
- "", cmVS7FlagTable::UserValue},
+ { "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},
+ { "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}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS10MASMFlagTable.h b/Source/cmVS10MASMFlagTable.h
new file mode 100644
index 000000000..0a452453f
--- /dev/null
+++ b/Source/cmVS10MASMFlagTable.h
@@ -0,0 +1,76 @@
+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
new file mode 100644
index 000000000..b91af9270
--- /dev/null
+++ b/Source/cmVS10NASMFlagTable.h
@@ -0,0 +1,50 @@
+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
new file mode 100644
index 000000000..6e2b8344c
--- /dev/null
+++ b/Source/cmVS10RCFlagTable.h
@@ -0,0 +1,7 @@
+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
index 5ab8ebbb3..75317093f 100644
--- a/Source/cmVS11CLFlagTable.h
+++ b/Source/cmVS11CLFlagTable.h
@@ -1,291 +1,219 @@
-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},
- {"PREfastAdditionalOptions", "analyze:",
- "Additional Code Analysis Native options",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
- {"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
+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},
+ { "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.
- {"PREfastLog", "analyze:log ",
- "Code Analysis Log",
- "", cmVS7FlagTable::UserValue},
// Skip [AdditionalOptions] - no command line Switch.
- {0,0,0,0,0}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS11CSharpFlagTable.h b/Source/cmVS11CSharpFlagTable.h
new file mode 100644
index 000000000..71870b698
--- /dev/null
+++ b/Source/cmVS11CSharpFlagTable.h
@@ -0,0 +1,120 @@
+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
index 942944241..8aacaacd3 100644
--- a/Source/cmVS11LibFlagTable.h
+++ b/Source/cmVS11LibFlagTable.h
@@ -1,102 +1,76 @@
-static cmVS7FlagTable cmVS11LibFlagTable[] =
-{
+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},
+ // 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},
+ { "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},
+ { "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
- {"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
- //Bool Properties With Argument
-
- //String List Properties
+ // 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},
+ { "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},
+ // 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},
+ { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
// Skip [AdditionalOptions] - no command line Switch.
// Skip [TrackerLogDirectory] - no command line Switch.
- {0,0,0,0,0}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS11LinkFlagTable.h b/Source/cmVS11LinkFlagTable.h
index b4587a836..1b3a046f6 100644
--- a/Source/cmVS11LinkFlagTable.h
+++ b/Source/cmVS11LinkFlagTable.h
@@ -1,343 +1,269 @@
-static cmVS7FlagTable cmVS11LinkFlagTable[] =
-{
+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},
+ // 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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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
- {"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", 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 },
- //Bool Properties With Argument
- {"EnableUAC", "MANIFESTUAC:NO", "", "false",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"EnableUAC", "MANIFESTUAC:NO", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired},
- {"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},
+ // 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},
+ { "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},
+ // 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},
+ { "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},
+ { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
+ cmVS7FlagTable::UserValue },
// Skip [HeapCommitSize] - no command line Switch.
- {"StackReserveSize", "STACK:",
- "Stack Reserve Size",
- "", cmVS7FlagTable::UserValue},
+ { "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},
+ { "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}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS11MASMFlagTable.h b/Source/cmVS11MASMFlagTable.h
new file mode 100644
index 000000000..fdf8239da
--- /dev/null
+++ b/Source/cmVS11MASMFlagTable.h
@@ -0,0 +1,76 @@
+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
new file mode 100644
index 000000000..4997fe115
--- /dev/null
+++ b/Source/cmVS11RCFlagTable.h
@@ -0,0 +1,7 @@
+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
index 8f5131989..9515c91b8 100644
--- a/Source/cmVS12CLFlagTable.h
+++ b/Source/cmVS12CLFlagTable.h
@@ -1,297 +1,221 @@
-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},
- {"PREfastAdditionalOptions", "analyze:",
- "Additional Code Analysis Native options",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
- {"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
+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},
+ { "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.
- {"PREfastLog", "analyze:log ",
- "Code Analysis Log",
- "", cmVS7FlagTable::UserValue},
// Skip [AdditionalOptions] - no command line Switch.
- {0,0,0,0,0}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS12CSharpFlagTable.h b/Source/cmVS12CSharpFlagTable.h
new file mode 100644
index 000000000..f98b1840d
--- /dev/null
+++ b/Source/cmVS12CSharpFlagTable.h
@@ -0,0 +1,120 @@
+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
index 10bb8057f..0f7a25955 100644
--- a/Source/cmVS12LibFlagTable.h
+++ b/Source/cmVS12LibFlagTable.h
@@ -1,102 +1,76 @@
-static cmVS7FlagTable cmVS12LibFlagTable[] =
-{
+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},
+ // 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},
+ { "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},
+ { "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
- {"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
- //Bool Properties With Argument
-
- //String List Properties
+ // 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},
+ { "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},
+ // 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},
+ { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
// Skip [AdditionalOptions] - no command line Switch.
// Skip [TrackerLogDirectory] - no command line Switch.
- {0,0,0,0,0}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h
index 73d450a9d..168c34c22 100644
--- a/Source/cmVS12LinkFlagTable.h
+++ b/Source/cmVS12LinkFlagTable.h
@@ -1,343 +1,269 @@
-static cmVS7FlagTable cmVS12LinkFlagTable[] =
-{
+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},
+ // 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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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},
+ { "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
- {"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", 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 },
- //Bool Properties With Argument
- {"EnableUAC", "MANIFESTUAC:NO", "", "false",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"EnableUAC", "MANIFESTUAC:NO", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired},
- {"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},
+ // 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},
+ { "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},
+ // 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},
+ { "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},
+ { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
+ cmVS7FlagTable::UserValue },
// Skip [HeapCommitSize] - no command line Switch.
- {"StackReserveSize", "STACK:",
- "Stack Reserve Size",
- "", cmVS7FlagTable::UserValue},
+ { "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},
+ { "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}
+ { 0, 0, 0, 0, 0 }
};
diff --git a/Source/cmVS12MASMFlagTable.h b/Source/cmVS12MASMFlagTable.h
new file mode 100644
index 000000000..acc0d48e1
--- /dev/null
+++ b/Source/cmVS12MASMFlagTable.h
@@ -0,0 +1,76 @@
+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
new file mode 100644
index 000000000..a650f8522
--- /dev/null
+++ b/Source/cmVS12RCFlagTable.h
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 000000000..60b437974
--- /dev/null
+++ b/Source/cmVS140CLFlagTable.h
@@ -0,0 +1,239 @@
+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
new file mode 100644
index 000000000..256c35f70
--- /dev/null
+++ b/Source/cmVS140CSharpFlagTable.h
@@ -0,0 +1,120 @@
+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
new file mode 100644
index 000000000..b9a4dc30a
--- /dev/null
+++ b/Source/cmVS140LinkFlagTable.h
@@ -0,0 +1,282 @@
+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
new file mode 100644
index 000000000..f751fc875
--- /dev/null
+++ b/Source/cmVS141CLFlagTable.h
@@ -0,0 +1,250 @@
+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
new file mode 100644
index 000000000..85085817c
--- /dev/null
+++ b/Source/cmVS141CSharpFlagTable.h
@@ -0,0 +1,120 @@
+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
new file mode 100644
index 000000000..8f0f1f42d
--- /dev/null
+++ b/Source/cmVS141LinkFlagTable.h
@@ -0,0 +1,283 @@
+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
new file mode 100644
index 000000000..7fa713893
--- /dev/null
+++ b/Source/cmVS14LibFlagTable.h
@@ -0,0 +1,76 @@
+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
new file mode 100644
index 000000000..82ec9f1d0
--- /dev/null
+++ b/Source/cmVS14MASMFlagTable.h
@@ -0,0 +1,76 @@
+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
new file mode 100644
index 000000000..5dc8d5ada
--- /dev/null
+++ b/Source/cmVS14RCFlagTable.h
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 000000000..7168f266c
--- /dev/null
+++ b/Source/cmVSSetupHelper.cxx
@@ -0,0 +1,394 @@
+/* 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 "cmSystemTools.h"
+
+#ifndef VSSetupConstants
+#define VSSetupConstants
+/* clang-format off */
+const IID IID_ISetupConfiguration = {
+ 0x42843719, 0xDB4C, 0x46C2,
+ { 0x8E, 0x7C, 0x64, 0xF1, 0x81, 0x6E, 0xFD, 0x5B }
+};
+const IID IID_ISetupConfiguration2 = {
+ 0x26AAB78C, 0x4A60, 0x49D6,
+ { 0xAF, 0x3B, 0x3C, 0x35, 0xBC, 0x93, 0x36, 0x5D }
+};
+const IID IID_ISetupPackageReference = {
+ 0xda8d8a16, 0xb2b6, 0x4487,
+ { 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5 }
+};
+const IID IID_ISetupHelper = {
+ 0x42b21b78, 0x6192, 0x463e,
+ { 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c }
+};
+const IID IID_IEnumSetupInstances = {
+ 0x6380BCFF, 0x41D3, 0x4B2E,
+ { 0x8B, 0x2E, 0xBF, 0x8A, 0x68, 0x10, 0xC8, 0x48 }
+};
+const IID IID_ISetupInstance2 = {
+ 0x89143C9A, 0x05AF, 0x49B0,
+ { 0xB7, 0x17, 0x72, 0xE2, 0x18, 0xA2, 0x18, 0x5C }
+};
+const IID IID_ISetupInstance = {
+ 0xB41463C3, 0x8866, 0x43B5,
+ { 0xBC, 0x33, 0x2B, 0x06, 0x76, 0xF7, 0xF4, 0x2E }
+};
+const CLSID CLSID_SetupConfiguration = {
+ 0x177F0C4A, 0x1CD3, 0x4DE7,
+ { 0xA3, 0x2C, 0x71, 0xDB, 0xBB, 0x9F, 0xA3, 0x6D }
+};
+/* 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)
+ , setupConfig2(NULL)
+ , setupHelper(NULL)
+ , initializationFailure(false)
+{
+ comInitialized = CoInitializeEx(NULL, 0);
+ if (SUCCEEDED(comInitialized)) {
+ Initialize();
+ } else {
+ initializationFailure = true;
+ }
+}
+
+cmVSSetupAPIHelper::~cmVSSetupAPIHelper()
+{
+ setupHelper = NULL;
+ setupConfig2 = NULL;
+ setupConfig = NULL;
+ if (SUCCEEDED(comInitialized))
+ CoUninitialize();
+}
+
+bool cmVSSetupAPIHelper::IsVS2017Installed()
+{
+ return this->EnumerateAndChooseVSInstance();
+}
+
+bool cmVSSetupAPIHelper::IsWin10SDKInstalled()
+{
+ return (this->EnumerateAndChooseVSInstance() &&
+ chosenInstanceInfo.IsWin10SDKInstalled);
+}
+
+bool cmVSSetupAPIHelper::IsWin81SDKInstalled()
+{
+ return (this->EnumerateAndChooseVSInstance() &&
+ chosenInstanceInfo.IsWin81SDKInstalled);
+}
+
+bool cmVSSetupAPIHelper::CheckInstalledComponent(
+ SmartCOMPtr<ISetupPackageReference> package, bool& bVCToolset,
+ bool& bWin10SDK, bool& bWin81SDK)
+{
+ bool ret = false;
+ bVCToolset = bWin10SDK = bWin81SDK = false;
+ SmartBSTR bstrId;
+ if (FAILED(package->GetId(&bstrId))) {
+ return ret;
+ }
+
+ SmartBSTR bstrType;
+ if (FAILED(package->GetType(&bstrType))) {
+ return ret;
+ }
+
+ 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
+ // component name ex: Microsoft.VisualStudio.Component.Windows10SDK.10240
+ if (id.find(Win10SDKComponent) != std::wstring::npos &&
+ type.compare(ComponentType) == 0) {
+ bWin10SDK = true;
+ ret = true;
+ }
+
+ if (id.compare(Win81SDKComponent) == 0 && type.compare(ComponentType) == 0) {
+ bWin81SDK = true;
+ ret = true;
+ }
+
+ return ret;
+}
+
+// Gather additional info such as if VCToolset, WinSDKs are installed, location
+// of VS and version information.
+bool cmVSSetupAPIHelper::GetVSInstanceInfo(
+ SmartCOMPtr<ISetupInstance2> pInstance, VSInstanceInfo& vsInstanceInfo)
+{
+ bool isVCToolSetInstalled = false;
+ if (pInstance == NULL)
+ return false;
+
+ SmartBSTR bstrId;
+ if (SUCCEEDED(pInstance->GetInstanceId(&bstrId))) {
+ vsInstanceInfo.InstanceId = std::wstring(bstrId);
+ } else {
+ return false;
+ }
+
+ InstanceState state;
+ if (FAILED(pInstance->GetState(&state))) {
+ return false;
+ }
+
+ ULONGLONG ullVersion = 0;
+ SmartBSTR bstrVersion;
+ if (FAILED(pInstance->GetInstallationVersion(&bstrVersion))) {
+ return false;
+ } else {
+ vsInstanceInfo.Version = std::wstring(bstrVersion);
+ if (FAILED(setupHelper->ParseVersion(bstrVersion, &ullVersion))) {
+ vsInstanceInfo.ullVersion = 0;
+ } else {
+ vsInstanceInfo.ullVersion = ullVersion;
+ }
+ }
+
+ // Reboot may have been required before the installation path was created.
+ SmartBSTR bstrInstallationPath;
+ if ((eLocal & state) == eLocal) {
+ if (FAILED(pInstance->GetInstallationPath(&bstrInstallationPath))) {
+ return false;
+ } else {
+ vsInstanceInfo.VSInstallLocation = std::wstring(bstrInstallationPath);
+ }
+ }
+
+ // Reboot may have been required before the product package was registered
+ // (last).
+ if ((eRegistered & state) == eRegistered) {
+ SmartCOMPtr<ISetupPackageReference> product;
+ if (FAILED(pInstance->GetProduct(&product)) || !product) {
+ return false;
+ }
+
+ LPSAFEARRAY lpsaPackages;
+ if (FAILED(pInstance->GetPackages(&lpsaPackages)) ||
+ lpsaPackages == NULL) {
+ return false;
+ }
+
+ int lower = lpsaPackages->rgsabound[0].lLbound;
+ int upper = lpsaPackages->rgsabound[0].cElements + lower;
+
+ IUnknown** ppData = (IUnknown**)lpsaPackages->pvData;
+ for (int i = lower; i < upper; i++) {
+ SmartCOMPtr<ISetupPackageReference> package = NULL;
+ if (FAILED(ppData[i]->QueryInterface(IID_ISetupPackageReference,
+ (void**)&package)) ||
+ package == NULL)
+ continue;
+
+ bool vcToolsetInstalled = false, win10SDKInstalled = false,
+ win81SDkInstalled = false;
+ bool ret = CheckInstalledComponent(package, vcToolsetInstalled,
+ win10SDKInstalled, win81SDkInstalled);
+ if (ret) {
+ isVCToolSetInstalled |= vcToolsetInstalled;
+ vsInstanceInfo.IsWin10SDKInstalled |= win10SDKInstalled;
+ vsInstanceInfo.IsWin81SDKInstalled |= win81SDkInstalled;
+ }
+ }
+
+ SafeArrayDestroy(lpsaPackages);
+ }
+
+ return isVCToolSetInstalled;
+}
+
+bool cmVSSetupAPIHelper::GetVSInstanceInfo(std::string& vsInstallLocation)
+{
+ vsInstallLocation = "";
+ bool isInstalled = this->EnumerateAndChooseVSInstance();
+
+ if (isInstalled) {
+ std::string str(chosenInstanceInfo.VSInstallLocation.begin(),
+ chosenInstanceInfo.VSInstallLocation.end());
+ vsInstallLocation = str;
+ }
+
+ return isInstalled;
+}
+
+bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
+{
+ bool isVSInstanceExists = false;
+ if (chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) {
+ return true;
+ }
+
+ if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL ||
+ setupHelper == NULL)
+ return false;
+
+ std::string envVSCommonToolsDir;
+
+ // 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)) {
+ 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;
+ if (FAILED(
+ setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) ||
+ !enumInstances) {
+ return false;
+ }
+
+ SmartCOMPtr<ISetupInstance> instance;
+ while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) {
+ SmartCOMPtr<ISetupInstance2> instance2 = NULL;
+ if (FAILED(
+ instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) ||
+ !instance2) {
+ instance = NULL;
+ continue;
+ }
+
+ VSInstanceInfo instanceInfo;
+ bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo);
+ instance = instance2 = NULL;
+
+ if (isInstalled) {
+ if (!envVSCommonToolsDir.empty()) {
+ std::string currentVSLocation(instanceInfo.VSInstallLocation.begin(),
+ instanceInfo.VSInstallLocation.end());
+ cmSystemTools::ConvertToUnixSlashes(currentVSLocation);
+ currentVSLocation += "/Common7/Tools";
+ if (cmSystemTools::ComparePath(currentVSLocation,
+ envVSCommonToolsDir)) {
+ chosenInstanceInfo = instanceInfo;
+ return true;
+ }
+ }
+ vecVSInstances.push_back(instanceInfo);
+ }
+ }
+
+ if (vecVSInstances.size() > 0) {
+ isVSInstanceExists = true;
+ int index = ChooseVSInstance(vecVSInstances);
+ chosenInstanceInfo = vecVSInstances[index];
+ }
+
+ return isVSInstanceExists;
+}
+
+int cmVSSetupAPIHelper::ChooseVSInstance(
+ const std::vector<VSInstanceInfo>& vecVSInstances)
+{
+ if (vecVSInstances.size() == 0)
+ return -1;
+
+ if (vecVSInstances.size() == 1)
+ return 0;
+
+ unsigned int chosenIndex = 0;
+ for (unsigned int i = 1; i < vecVSInstances.size(); i++) {
+ // If the current has Win10 SDK but not the chosen one, then choose the
+ // current VS instance
+ if (!vecVSInstances[chosenIndex].IsWin10SDKInstalled &&
+ vecVSInstances[i].IsWin10SDKInstalled) {
+ chosenIndex = i;
+ continue;
+ }
+
+ // If the chosen one has Win10 SDK but the current one is not, then look at
+ // the next VS instance even the current
+ // instance version may be higher
+ if (vecVSInstances[chosenIndex].IsWin10SDKInstalled &&
+ !vecVSInstances[i].IsWin10SDKInstalled) {
+ continue;
+ }
+
+ // If both chosen one and current one doesn't have Win10 SDK but the
+ // current one has Win8.1 SDK installed,
+ // then choose the current one
+ if (!vecVSInstances[chosenIndex].IsWin10SDKInstalled &&
+ !vecVSInstances[i].IsWin10SDKInstalled &&
+ !vecVSInstances[chosenIndex].IsWin81SDKInstalled &&
+ vecVSInstances[i].IsWin81SDKInstalled) {
+ chosenIndex = i;
+ continue;
+ }
+
+ // If there is no difference in WinSDKs then look for the highest version
+ // of installed VS
+ if ((vecVSInstances[chosenIndex].IsWin10SDKInstalled ==
+ vecVSInstances[i].IsWin10SDKInstalled) &&
+ (vecVSInstances[chosenIndex].IsWin81SDKInstalled ==
+ vecVSInstances[i].IsWin81SDKInstalled) &&
+ vecVSInstances[chosenIndex].Version < vecVSInstances[i].Version) {
+ chosenIndex = i;
+ continue;
+ }
+ }
+
+ return chosenIndex;
+}
+
+bool cmVSSetupAPIHelper::Initialize()
+{
+ if (initializationFailure)
+ return false;
+
+ if (FAILED(comInitialized)) {
+ initializationFailure = true;
+ return false;
+ }
+
+ if (FAILED(setupConfig.CoCreateInstance(CLSID_SetupConfiguration, NULL,
+ IID_ISetupConfiguration,
+ CLSCTX_INPROC_SERVER)) ||
+ setupConfig == NULL) {
+ initializationFailure = true;
+ return false;
+ }
+
+ if (FAILED(setupConfig.QueryInterface(IID_ISetupConfiguration2,
+ (void**)&setupConfig2)) ||
+ setupConfig2 == NULL) {
+ initializationFailure = true;
+ return false;
+ }
+
+ if (FAILED(
+ setupConfig.QueryInterface(IID_ISetupHelper, (void**)&setupHelper)) ||
+ setupHelper == NULL) {
+ initializationFailure = true;
+ return false;
+ }
+
+ initializationFailure = false;
+ return true;
+}
diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h
new file mode 100644
index 000000000..d2f514c63
--- /dev/null
+++ b/Source/cmVSSetupHelper.h
@@ -0,0 +1,154 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmVSSetupHelper_h
+#define cmVSSetupHelper_h
+
+#ifndef NOMINMAX
+#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>
+
+template <class T>
+class SmartCOMPtr
+{
+public:
+ SmartCOMPtr() { ptr = NULL; }
+ SmartCOMPtr(T* p)
+ {
+ ptr = p;
+ if (ptr != NULL)
+ ptr->AddRef();
+ }
+ SmartCOMPtr(const SmartCOMPtr<T>& sptr)
+ {
+ ptr = sptr.ptr;
+ if (ptr != NULL)
+ ptr->AddRef();
+ }
+ T** operator&() { return &ptr; }
+ T* operator->() { return ptr; }
+ T* operator=(T* p)
+ {
+ if (*this != p) {
+ ptr = p;
+ if (ptr != NULL)
+ ptr->AddRef();
+ }
+ return *this;
+ }
+ operator T*() const { return ptr; }
+ template <class I>
+ HRESULT QueryInterface(REFCLSID rclsid, I** pp)
+ {
+ if (pp != NULL) {
+ return ptr->QueryInterface(rclsid, (void**)pp);
+ } else {
+ return E_FAIL;
+ }
+ }
+ HRESULT CoCreateInstance(REFCLSID clsid, IUnknown* pUnknown,
+ REFIID interfaceId, DWORD dwClsContext = CLSCTX_ALL)
+ {
+ HRESULT hr = ::CoCreateInstance(clsid, pUnknown, dwClsContext, interfaceId,
+ (void**)&ptr);
+ return hr;
+ }
+ ~SmartCOMPtr()
+ {
+ if (ptr != NULL)
+ ptr->Release();
+ }
+
+private:
+ T* ptr;
+};
+
+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;
+ }
+ operator BSTR() const { return str; }
+ BSTR* operator&() throw() { return &str; }
+ ~SmartBSTR() throw() { ::SysFreeString(str); }
+private:
+ BSTR str;
+};
+
+struct VSInstanceInfo
+{
+ std::wstring InstanceId;
+ std::wstring VSInstallLocation;
+ std::wstring Version;
+ ULONGLONG ullVersion;
+ bool IsWin10SDKInstalled;
+ bool IsWin81SDKInstalled;
+
+ VSInstanceInfo()
+ {
+ InstanceId = VSInstallLocation = Version = L"";
+ ullVersion = 0;
+ IsWin10SDKInstalled = IsWin81SDKInstalled = false;
+ }
+};
+
+class cmVSSetupAPIHelper
+{
+public:
+ cmVSSetupAPIHelper();
+ ~cmVSSetupAPIHelper();
+
+ bool IsVS2017Installed();
+ bool GetVSInstanceInfo(std::string& vsInstallLocation);
+ bool IsWin10SDKInstalled();
+ bool IsWin81SDKInstalled();
+
+private:
+ bool Initialize();
+ bool GetVSInstanceInfo(SmartCOMPtr<ISetupInstance2> instance2,
+ VSInstanceInfo& vsInstanceInfo);
+ bool CheckInstalledComponent(SmartCOMPtr<ISetupPackageReference> package,
+ bool& bVCToolset, bool& bWin10SDK,
+ bool& bWin81SDK);
+ int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances);
+ bool EnumerateAndChooseVSInstance();
+
+ // COM ptrs to query about VS instances
+ SmartCOMPtr<ISetupConfiguration> setupConfig;
+ SmartCOMPtr<ISetupConfiguration2> setupConfig2;
+ SmartCOMPtr<ISetupHelper> setupHelper;
+ // used to indicate failure in Initialize(), so we don't have to call again
+ bool initializationFailure;
+ // indicated if COM initialization is successful
+ HRESULT comInitialized;
+ // current best instance of VS selected
+ VSInstanceInfo chosenInstanceInfo;
+};
+
+#endif
diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index 747e9be5e..06ca53c0a 100644
--- a/Source/cmVariableRequiresCommand.cxx
+++ b/Source/cmVariableRequiresCommand.cxx
@@ -1,76 +1,64 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmVariableRequiresCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmVariableRequiresCommand.h"
-#include "cmCacheManager.h"
+class cmExecutionStatus;
// cmLibraryCommand
-bool cmVariableRequiresCommand
-::InitialPass(std::vector<std::string>const& args, cmExecutionStatus &)
+bool cmVariableRequiresCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
{
- if(args.size() < 3 )
- {
+ if (args.size() < 3) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
- std::string testVariable = args[0];
- if(!this->Makefile->IsOn(testVariable.c_str()))
- {
+ std::string const& testVariable = args[0];
+ if (!this->Makefile->IsOn(testVariable)) {
return true;
- }
- std::string resultVariable = args[1];
+ }
+ std::string const& resultVariable = args[1];
bool requirementsMet = true;
std::string notSet;
bool hasAdvanced = false;
- for(unsigned int i = 2; i < args.size(); ++i)
- {
- if(!this->Makefile->IsOn(args[i].c_str()))
- {
+ cmState* state = this->Makefile->GetState();
+ for (unsigned int i = 2; i < args.size(); ++i) {
+ if (!this->Makefile->IsOn(args[i])) {
requirementsMet = false;
notSet += args[i];
notSet += "\n";
- cmCacheManager::CacheIterator it =
- this->Makefile->GetCacheManager()->GetCacheIterator(args[i].c_str());
- if(!it.IsAtEnd() && it.GetPropertyAsBool("ADVANCED"))
- {
+ if (state->GetCacheEntryValue(args[i]) &&
+ state->GetCacheEntryPropertyAsBool(args[i], "ADVANCED")) {
hasAdvanced = true;
- }
}
}
- const char* reqVar = this->Makefile->GetDefinition(resultVariable.c_str());
+ }
+ const char* reqVar = this->Makefile->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.c_str(), requirementsMet);
- }
+ if (!reqVar || (!requirementsMet && this->Makefile->IsOn(reqVar))) {
+ this->Makefile->AddDefinition(resultVariable, requirementsMet);
+ }
- if(!requirementsMet)
- {
+ if (!requirementsMet) {
std::string message = "Variable assertion failed:\n";
- message += testVariable +
- " Requires that the following unset variables are set:\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";
- if(hasAdvanced)
- {
+ 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.c_str());
+ }
return true;
}
diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h
index c86f43dc6..9808d5f0c 100644
--- a/Source/cmVariableRequiresCommand.h
+++ b/Source/cmVariableRequiresCommand.h
@@ -1,82 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVariableRequiresCommand_h
#define cmVariableRequiresCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
-/** \class cmVariableRequiresCommand
- * \brief Displays a message to the user
- *
- */
+class cmExecutionStatus;
+
class cmVariableRequiresCommand : public cmCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- virtual cmCommand* Clone()
- {
- return new cmVariableRequiresCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "variable_requires";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the if() command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- "Assert satisfaction of an option's required variables.\n"
- " variable_requires(TEST_VARIABLE RESULT_VARIABLE\n"
- " REQUIRED_VARIABLE1\n"
- " REQUIRED_VARIABLE2 ...)\n"
- "The first argument (TEST_VARIABLE) is the name of the variable to be "
- "tested, if that variable is false nothing else is done. If "
- "TEST_VARIABLE is true, then "
- "the next argument (RESULT_VARIABLE) is a variable that is set to true "
- "if all the required variables are set. "
- "The rest of the arguments are variables that must be true or not "
- "set to NOTFOUND to avoid an error. If any are not true, an error "
- "is reported.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmVariableRequiresCommand, cmCommand);
+ cmCommand* Clone() CM_OVERRIDE { return new cmVariableRequiresCommand; }
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 8ad6fce8f..419e1a411 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -1,33 +1,23 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmVariableWatch.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmAlgorithms.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmVariableWatch.h"
+#include "cm_auto_ptr.hxx"
+#include <algorithm>
+#include <utility>
-static const char* const cmVariableWatchAccessStrings[] =
-{
- "READ_ACCESS",
- "UNKNOWN_READ_ACCESS",
- "UNKNOWN_DEFINED_ACCESS",
- "ALLOWED_UNKNOWN_READ_ACCESS",
- "MODIFIED_ACCESS",
- "REMOVED_ACCESS",
- "NO_ACCESS"
+static const char* const cmVariableWatchAccessStrings[] = {
+ "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS",
+ "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS"
};
const char* cmVariableWatch::GetAccessAsString(int access_type)
{
- if ( access_type < 0 || access_type >= cmVariableWatch::NO_ACCESS )
- {
+ if (access_type < 0 || access_type >= cmVariableWatch::NO_ACCESS) {
return "NO_ACCESS";
- }
+ }
return cmVariableWatchAccessStrings[access_type];
}
@@ -35,86 +25,73 @@ cmVariableWatch::cmVariableWatch()
{
}
-cmVariableWatch::~cmVariableWatch()
+template <typename C>
+void deleteAllSecond(typename C::value_type it)
{
- cmVariableWatch::StringToVectorOfPairs::iterator svp_it;
-
- for ( svp_it = this->WatchMap.begin();
- svp_it != this->WatchMap.end(); ++svp_it )
- {
- cmVariableWatch::VectorOfPairs::iterator p_it;
+ cmDeleteAll(it.second);
+}
- for ( p_it = svp_it->second.begin();
- p_it != svp_it->second.end(); ++p_it )
- {
- delete *p_it;
- }
- }
+cmVariableWatch::~cmVariableWatch()
+{
+ std::for_each(this->WatchMap.begin(), this->WatchMap.end(),
+ deleteAllSecond<cmVariableWatch::StringToVectorOfPairs>);
}
-bool cmVariableWatch::AddWatch(const std::string& variable,
- WatchMethod method, void* client_data /*=0*/,
+bool cmVariableWatch::AddWatch(const std::string& variable, WatchMethod method,
+ void* client_data /*=0*/,
DeleteData delete_data /*=0*/)
{
- cmVariableWatch::Pair* p = new cmVariableWatch::Pair;
+ CM_AUTO_PTR<cmVariableWatch::Pair> p(new 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 ++ )
- {
+ for (cc = 0; cc < vp->size(); cc++) {
cmVariableWatch::Pair* pair = (*vp)[cc];
- if ( pair->Method == method &&
- client_data && client_data == pair->ClientData)
- {
+ if (pair->Method == method && client_data &&
+ client_data == pair->ClientData) {
// Callback already exists
return false;
- }
}
- vp->push_back(p);
+ }
+ vp->push_back(p.release());
return true;
}
void cmVariableWatch::RemoveWatch(const std::string& variable,
- WatchMethod method,
- void* client_data /*=0*/)
+ WatchMethod method, void* client_data /*=0*/)
{
- if ( !this->WatchMap.count(variable) )
- {
+ if (!this->WatchMap.count(variable)) {
return;
- }
+ }
cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
cmVariableWatch::VectorOfPairs::iterator it;
- for ( it = vp->begin(); it != vp->end(); ++it )
- {
- if ( (*it)->Method == method &&
- // 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)))
- {
+ for (it = vp->begin(); it != vp->end(); ++it) {
+ if ((*it)->Method == method &&
+ // 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;
- }
}
+ }
}
-void cmVariableWatch::VariableAccessed(const std::string& variable,
- int access_type,
- const char* newValue,
- const cmMakefile* mf) const
+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);
- if ( mit != this->WatchMap.end() )
- {
+ 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);
- }
+ for (it = vp->begin(); it != vp->end(); it++) {
+ (*it)->Method(variable, access_type, (*it)->ClientData, newValue, mf);
}
+ return true;
+ }
+ return false;
}
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 790c75acc..a575afe9d 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -1,18 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVariableWatch_h
#define cmVariableWatch_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
class cmMakefile;
@@ -25,7 +20,8 @@ class cmVariableWatch
{
public:
typedef void (*WatchMethod)(const std::string& variable, int access_type,
- void* client_data, const char* newValue, const cmMakefile* mf);
+ void* client_data, const char* newValue,
+ const cmMakefile* mf);
typedef void (*DeleteData)(void* client_data);
cmVariableWatch();
@@ -35,29 +31,29 @@ public:
* Add watch to the variable
*/
bool AddWatch(const std::string& variable, WatchMethod method,
- void* client_data=0, DeleteData delete_data=0);
+ void* client_data = CM_NULLPTR,
+ DeleteData delete_data = CM_NULLPTR);
void RemoveWatch(const std::string& variable, WatchMethod method,
- void* client_data=0);
+ void* client_data = CM_NULLPTR);
/**
* This method is called when variable is accessed
*/
- void VariableAccessed(const std::string& variable, int access_type,
- const char* newValue, const cmMakefile* mf) const;
+ bool VariableAccessed(const std::string& variable, int access_type,
+ const char* newValue, const cmMakefile* mf) const;
/**
* Different access types.
*/
enum
- {
+ {
VARIABLE_READ_ACCESS = 0,
UNKNOWN_VARIABLE_READ_ACCESS,
UNKNOWN_VARIABLE_DEFINED_ACCESS,
- ALLOWED_UNKNOWN_VARIABLE_READ_ACCESS,
VARIABLE_MODIFIED_ACCESS,
VARIABLE_REMOVED_ACCESS,
NO_ACCESS
- };
+ };
/**
* Return the access as string
@@ -68,23 +64,26 @@ protected:
struct Pair
{
WatchMethod Method;
- void* ClientData;
- DeleteData DeleteDataCall;
- Pair() : Method(0), ClientData(0), DeleteDataCall(0) {}
+ void* ClientData;
+ DeleteData DeleteDataCall;
+ Pair()
+ : Method(CM_NULLPTR)
+ , ClientData(CM_NULLPTR)
+ , DeleteDataCall(CM_NULLPTR)
+ {
+ }
~Pair()
- {
- if (this->DeleteDataCall && this->ClientData)
- {
+ {
+ if (this->DeleteDataCall && this->ClientData) {
this->DeleteDataCall(this->ClientData);
- }
}
+ }
};
- typedef std::vector< Pair* > VectorOfPairs;
- typedef std::map<cmStdString, VectorOfPairs > StringToVectorOfPairs;
+ typedef std::vector<Pair*> VectorOfPairs;
+ typedef std::map<std::string, VectorOfPairs> StringToVectorOfPairs;
StringToVectorOfPairs WatchMap;
};
-
#endif
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 33e159bce..281850ecc 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -1,37 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableWatchCommand.h"
+#include <sstream>
+
+#include "cmExecutionStatus.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
#include "cmVariableWatch.h"
+#include "cmake.h"
-//----------------------------------------------------------------------------
struct cmVariableWatchCallbackData
{
bool InCallback;
std::string Command;
};
-//----------------------------------------------------------------------------
-static void cmVariableWatchCommandVariableAccessed(
- const std::string& variable, int access_type, void* client_data,
- const char* newValue, const cmMakefile* mf)
+static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
+ int access_type,
+ void* client_data,
+ const char* newValue,
+ const cmMakefile* mf)
{
- cmVariableWatchCallbackData* data
- = static_cast<cmVariableWatchCallbackData*>(client_data);
+ cmVariableWatchCallbackData* data =
+ static_cast<cmVariableWatchCallbackData*>(client_data);
- if ( data->InCallback )
- {
+ if (data->InCallback) {
return;
- }
+ }
data->InCallback = true;
cmListFileFunction newLFF;
@@ -44,102 +41,82 @@ static void cmVariableWatchCommandVariableAccessed(
cmMakefile* makefile = const_cast<cmMakefile*>(mf);
std::string stack = makefile->GetProperty("LISTFILE_STACK");
- if ( !data->Command.empty() )
- {
+ if (!data->Command.empty()) {
newLFF.Arguments.clear();
newLFF.Arguments.push_back(
- cmListFileArgument(variable, cmListFileArgument::Quoted,
- "unknown", 9999));
+ cmListFileArgument(variable, cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(accessString, cmListFileArgument::Quoted,
- "unknown", 9999));
+ cmListFileArgument(accessString, cmListFileArgument::Quoted, 9999));
+ newLFF.Arguments.push_back(cmListFileArgument(
+ newValue ? newValue : "", cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted,
- "unknown", 9999));
+ cmListFileArgument(currentListFile, cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(currentListFile, cmListFileArgument::Quoted,
- "unknown", 9999));
- newLFF.Arguments.push_back(
- cmListFileArgument(stack, cmListFileArgument::Quoted,
- "unknown", 9999));
+ cmListFileArgument(stack, cmListFileArgument::Quoted, 9999));
newLFF.Name = data->Command;
- newLFF.FilePath = "Some weird path";
newLFF.Line = 9999;
cmExecutionStatus status;
- if(!makefile->ExecuteCommand(newLFF,status))
- {
- arg.FilePath = "Unknown";
- arg.Line = 0;
- cmOStringStream error;
- error << "Error in cmake code at\n"
- << arg.FilePath << ":" << arg.Line << ":\n"
- << "A command failed during the invocation of callback \""
- << data->Command << "\".";
+ 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());
data->InCallback = false;
return;
- }
- processed = true;
}
- if ( !processed )
- {
- cmOStringStream msg;
- msg << "Variable \"" << variable.c_str() << "\" was accessed using "
- << accessString << " with value \"" << (newValue?newValue:"") << "\".";
+ processed = true;
+ }
+ if (!processed) {
+ std::ostringstream msg;
+ msg << "Variable \"" << variable << "\" was accessed using "
+ << accessString << " with value \"" << (newValue ? newValue : "")
+ << "\".";
makefile->IssueMessage(cmake::LOG, msg.str());
- }
+ }
data->InCallback = false;
}
-//----------------------------------------------------------------------------
static void deleteVariableWatchCallbackData(void* client_data)
{
- cmVariableWatchCallbackData* data
- = static_cast<cmVariableWatchCallbackData*>(client_data);
+ cmVariableWatchCallbackData* data =
+ static_cast<cmVariableWatchCallbackData*>(client_data);
delete data;
}
-//----------------------------------------------------------------------------
cmVariableWatchCommand::cmVariableWatchCommand()
{
}
-//----------------------------------------------------------------------------
cmVariableWatchCommand::~cmVariableWatchCommand()
{
std::set<std::string>::const_iterator it;
- for ( it = this->WatchedVariables.begin();
- it != this->WatchedVariables.end();
- ++it )
- {
+ for (it = this->WatchedVariables.begin(); it != this->WatchedVariables.end();
+ ++it) {
this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
*it, cmVariableWatchCommandVariableAccessed);
- }
+ }
}
-//----------------------------------------------------------------------------
-bool cmVariableWatchCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if ( args.size() < 1 )
- {
+ if (args.empty()) {
this->SetError("must be called with at least one argument.");
return false;
- }
- std::string variable = args[0];
+ }
+ std::string const& variable = args[0];
std::string command;
- if ( args.size() > 1 )
- {
+ if (args.size() > 1) {
command = args[1];
- }
- if ( variable == "CMAKE_CURRENT_LIST_FILE" )
- {
- cmOStringStream ostr;
- ostr << "cannot be set on the variable: " << variable.c_str();
- this->SetError(ostr.str().c_str());
+ }
+ if (variable == "CMAKE_CURRENT_LIST_FILE") {
+ std::ostringstream ostr;
+ ostr << "cannot be set on the variable: " << variable;
+ this->SetError(ostr.str());
return false;
- }
+ }
cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
@@ -147,13 +124,12 @@ bool cmVariableWatchCommand
data->Command = command;
this->WatchedVariables.insert(variable);
- if ( !this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
- variable, cmVariableWatchCommandVariableAccessed,
- data, deleteVariableWatchCallbackData) )
- {
+ if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
+ variable, cmVariableWatchCommandVariableAccessed, data,
+ deleteVariableWatchCallbackData)) {
deleteVariableWatchCallbackData(data);
return false;
- }
+ }
return true;
}
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 545535c40..9f0439175 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -1,19 +1,18 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVariableWatchCommand_h
#define cmVariableWatchCommand_h
+#include "cmConfigure.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmVariableWatchCommand
* \brief Watch when the variable changes and invoke command
*
@@ -24,66 +23,27 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmVariableWatchCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmVariableWatchCommand; }
//! Default constructor
cmVariableWatchCommand();
//! Destructor.
- ~cmVariableWatchCommand();
+ ~cmVariableWatchCommand() CM_OVERRIDE;
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
+ 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. */
- virtual bool HasFinalPass() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "variable_watch";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Watch the CMake variable for change.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " variable_watch(<variable name> [<command to execute>])\n"
- "If the specified variable changes, the message will be printed about "
- "the variable being changed. If the command is specified, the command "
- "will be executed. The command will receive the following arguments:"
- " COMMAND(<variable> <access> <value> <current list file> <stack>)";
- }
-
- cmTypeMacro(cmVariableWatchCommand, cmCommand);
+ bool HasFinalPass() const CM_OVERRIDE { return true; }
protected:
std::set<std::string> WatchedVariables;
};
-
#endif
-
-
diff --git a/Source/cmVersion.cxx b/Source/cmVersion.cxx
index 047d24d74..a091b91a7 100644
--- a/Source/cmVersion.cxx
+++ b/Source/cmVersion.cxx
@@ -1,22 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVersion.h"
-#include "cmVersionMacros.h"
+#include "cmVersionConfig.h"
-unsigned int cmVersion::GetMajorVersion() { return CMake_VERSION_MAJOR; }
-unsigned int cmVersion::GetMinorVersion() { return CMake_VERSION_MINOR; }
-unsigned int cmVersion::GetPatchVersion() { return CMake_VERSION_PATCH; }
-unsigned int cmVersion::GetTweakVersion() { return CMake_VERSION_TWEAK; }
+unsigned int cmVersion::GetMajorVersion()
+{
+ return CMake_VERSION_MAJOR;
+}
+unsigned int cmVersion::GetMinorVersion()
+{
+ return CMake_VERSION_MINOR;
+}
+unsigned int cmVersion::GetPatchVersion()
+{
+ return CMake_VERSION_PATCH;
+}
+unsigned int cmVersion::GetTweakVersion()
+{
+ return 0;
+}
const char* cmVersion::GetCMakeVersion()
{
diff --git a/Source/cmVersion.h b/Source/cmVersion.h
index e31352476..bfd994d09 100644
--- a/Source/cmVersion.h
+++ b/Source/cmVersion.h
@@ -1,18 +1,9 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVersion_h
#define cmVersion_h
-#include "cmStandardIncludes.h"
+#include "cm_kwiml.h"
/** \class cmVersion
* \brief Helper class for providing CMake and CTest version information.
@@ -32,8 +23,12 @@ public:
static const char* GetCMakeVersion();
};
-#define CMake_VERSION_ENCODE(major, minor, patch) \
- ((major)*0x10000u + (minor)*0x100u + (patch))
+/* Encode with room for up to 1000 minor releases between major releases
+ and to encode dates until the year 10000 in the patch level. */
+#define CMake_VERSION_ENCODE__BASE KWIML_INT_UINT64_C(100000000)
+#define CMake_VERSION_ENCODE(major, minor, patch) \
+ ((((major)*1000u) * CMake_VERSION_ENCODE__BASE) + \
+ (((minor) % 1000u) * CMake_VERSION_ENCODE__BASE) + \
+ (((patch) % CMake_VERSION_ENCODE__BASE)))
#endif
-
diff --git a/Source/cmVersionConfig.h.in b/Source/cmVersionConfig.h.in
index 76bc8fe94..06251f36a 100644
--- a/Source/cmVersionConfig.h.in
+++ b/Source/cmVersionConfig.h.in
@@ -1,16 +1,8 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#define CMake_VERSION_MAJOR @CMake_VERSION_MAJOR@
#define CMake_VERSION_MINOR @CMake_VERSION_MINOR@
#define CMake_VERSION_PATCH @CMake_VERSION_PATCH@
-#define CMake_VERSION_TWEAK @CMake_VERSION_TWEAK@
+#define CMake_VERSION_SUFFIX "@CMake_VERSION_SUFFIX@"
+#define CMake_VERSION_IS_DIRTY @CMake_VERSION_IS_DIRTY@
#define CMake_VERSION "@CMake_VERSION@"
diff --git a/Source/cmVersionMacros.h b/Source/cmVersionMacros.h
index 67f58ca41..1b617bd2b 100644
--- a/Source/cmVersionMacros.h
+++ b/Source/cmVersionMacros.h
@@ -1,22 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVersionMacros_h
#define cmVersionMacros_h
#include "cmVersionConfig.h"
-#define CMake_VERSION_TWEAK_IS_RELEASE(tweak) ((tweak) < 20000000)
-#if CMake_VERSION_TWEAK_IS_RELEASE(CMake_VERSION_TWEAK)
-# define CMake_VERSION_IS_RELEASE 1
+#define CMake_VERSION_PATCH_IS_RELEASE(patch) ((patch) < 20000000)
+#if CMake_VERSION_PATCH_IS_RELEASE(CMake_VERSION_PATCH)
+#define CMake_VERSION_IS_RELEASE 1
#endif
#endif
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 6376376a0..dee153f6b 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1,68 +1,21 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudio10TargetGenerator.h"
-#include "cmGlobalVisualStudio10Generator.h"
-#include "cmGeneratorTarget.h"
-#include "cmTarget.h"
+
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalVisualStudio10Generator.h"
+#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSystemTools.h"
#include "cmVisualStudioGeneratorOptions.h"
-#include "cmLocalVisualStudio7Generator.h"
-#include "cmVS10CLFlagTable.h"
-#include "cmVS10LinkFlagTable.h"
-#include "cmVS10LibFlagTable.h"
-#include "cmVS11CLFlagTable.h"
-#include "cmVS11LinkFlagTable.h"
-#include "cmVS11LibFlagTable.h"
-#include "cmVS12CLFlagTable.h"
-#include "cmVS12LinkFlagTable.h"
-#include "cmVS12LibFlagTable.h"
+#include "windows.h"
-#include <cmsys/auto_ptr.hxx>
-
-static cmVS7FlagTable const*
-cmVSGetCLFlagTable(cmLocalVisualStudioGenerator* lg)
-{
- if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12)
- { return cmVS12CLFlagTable; }
- else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11)
- { return cmVS11CLFlagTable; }
- else
- { return cmVS10CLFlagTable; }
-}
-
-static cmVS7FlagTable const*
-cmVSGetLibFlagTable(cmLocalVisualStudioGenerator* lg)
-{
- if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12)
- { return cmVS12LibFlagTable; }
- else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11)
- { return cmVS11LibFlagTable; }
- else
- { return cmVS10LibFlagTable; }
-}
-
-static cmVS7FlagTable const*
-cmVSGetLinkFlagTable(cmLocalVisualStudioGenerator* lg)
-{
- if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12)
- { return cmVS12LinkFlagTable; }
- else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11)
- { return cmVS11LinkFlagTable; }
- else
- { return cmVS10LinkFlagTable; }
-}
+#include "cm_auto_ptr.hxx"
static std::string cmVS10EscapeXML(std::string arg)
{
@@ -78,269 +31,552 @@ static std::string cmVS10EscapeComment(std::string comment)
// does "echo $CDATA" with no escapes. We must encode the string.
// http://technet.microsoft.com/en-us/library/cc772462%28WS.10%29.aspx
std::string echoable;
- for(std::string::iterator c = comment.begin(); c != comment.end(); ++c)
- {
- switch (*c)
- {
- case '\r': break;
- case '\n': echoable += '\t'; break;
+ for (std::string::iterator c = comment.begin(); c != comment.end(); ++c) {
+ switch (*c) {
+ case '\r':
+ break;
+ case '\n':
+ echoable += '\t';
+ break;
case '"': /* no break */
case '|': /* no break */
case '&': /* no break */
case '<': /* no break */
case '>': /* no break */
- case '^': echoable += '^'; /* no break */
- default: echoable += *c; break;
- }
+ case '^':
+ echoable += '^'; /* no break */
+ default:
+ echoable += *c;
+ break;
}
+ }
return echoable;
}
-cmVisualStudio10TargetGenerator::
-cmVisualStudio10TargetGenerator(cmTarget* target,
- cmGlobalVisualStudio10Generator* gg)
+static bool cmVS10IsTargetsFile(std::string const& path)
+{
+ std::string const ext = cmSystemTools::GetFilenameLastExtension(path);
+ return cmSystemTools::Strucmp(ext.c_str(), ".targets") == 0;
+}
+
+static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
+{
+ std::string res;
+ res = ".vcxproj";
+ if (cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(t)) {
+ res = ".csproj";
+ }
+ return res;
+}
+
+cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
+ cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
{
this->GlobalGenerator = gg;
- this->Target = target;
- this->GeneratorTarget = gg->GetGeneratorTarget(target);
- this->Makefile = target->GetMakefile();
+ this->GeneratorTarget = target;
+ this->Makefile = target->Target->GetMakefile();
+ this->Makefile->GetConfigurations(this->Configurations);
this->LocalGenerator =
- (cmLocalVisualStudio7Generator*)
- this->Makefile->GetLocalGenerator();
- this->Name = this->Target->GetName();
- this->GlobalGenerator->CreateGUID(this->Name.c_str());
+ (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;
+ }
+ sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u",
+ &this->NsightTegraVersion[0], &this->NsightTegraVersion[1],
+ &this->NsightTegraVersion[2], &this->NsightTegraVersion[3]);
+ 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->GetTargetDirectory(this->GeneratorTarget);
+ this->InSourceBuild =
+ (strcmp(this->Makefile->GetCurrentSourceDirectory(),
+ this->Makefile->GetCurrentBinaryDirectory()) == 0);
}
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
- for(OptionsMap::iterator i = this->ClOptions.begin();
- i != this->ClOptions.end(); ++i)
- {
+ 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)
- {
+ }
+ for (OptionsMap::iterator i = this->LinkOptions.begin();
+ i != this->LinkOptions.end(); ++i) {
delete i->second;
- }
- if(!this->BuildFileStream)
- {
+ }
+ 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->PathToVcxproj);
- }
+ }
+ if (this->BuildFileStream->Close()) {
+ this->GlobalGenerator->FileReplacedDuringGenerate(this->PathToProjectFile);
+ }
delete this->BuildFileStream;
}
void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
- const char* tag,
- const char* config,
- int indentLevel,
- const char* attribute,
- const char* end,
- std::ostream* stream)
+ const char* tag, const std::string& config, int indentLevel,
+ const char* attribute, const char* end, std::ostream* stream)
{
- if(!stream)
- {
+ if (!stream) {
stream = this->BuildFileStream;
- }
+ }
stream->fill(' ');
- stream->width(indentLevel*2 );
- (*stream ) << "";
- (*stream ) << "<" << tag
- << " Condition=\"'$(Configuration)|$(Platform)'=='";
- (*stream ) << config << "|" << this->Platform << "'\"";
- if(attribute)
- {
- (*stream ) << attribute;
- }
+ stream->width(indentLevel * 2);
+ (*stream) << ""; // applies indentation
+ (*stream) << "<" << tag << " Condition=\"";
+ (*stream) << "'$(Configuration)|$(Platform)'=='";
+ (*stream) << config << "|" << this->Platform;
+ (*stream) << "'";
+ // 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;
- }
+ (*stream) << ">";
+ if (end) {
+ (*stream) << end;
+ }
}
void cmVisualStudio10TargetGenerator::WriteString(const char* line,
int indentLevel)
{
this->BuildFileStream->fill(' ');
- this->BuildFileStream->width(indentLevel*2 );
+ this->BuildFileStream->width(indentLevel * 2);
// write an empty string to get the fill level indent to print
- (*this->BuildFileStream ) << "";
- (*this->BuildFileStream ) << line;
+ (*this->BuildFileStream) << "";
+ (*this->BuildFileStream) << line;
}
-#define VS10_USER_PROPS "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"
+#define VS10_CXX_DEFAULT_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
+#define VS10_CXX_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.props"
+#define VS10_CXX_USER_PROPS \
+ "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"
+#define VS10_CXX_TARGETS "$(VCTargetsPath)\\Microsoft.Cpp.targets"
+
+#define VS10_CSharp_DEFAULT_PROPS \
+ "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props"
+// This does not seem to exist by default, it's just provided for consistency
+// in case users want to have default custom props for C# targets
+#define VS10_CSharp_USER_PROPS \
+ "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props"
+#define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"
void cmVisualStudio10TargetGenerator::Generate()
{
// do not generate external ms projects
- if(this->Target->GetProperty("EXTERNAL_MSPROJECT"))
- {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
return;
- }
+ }
+ this->ProjectFileExtension =
+ computeProjectFileExtension(this->GeneratorTarget);
+ if (this->ProjectFileExtension == ".vcxproj") {
+ this->ProjectType = vcxproj;
+ this->Managed = false;
+ } else if (this->ProjectFileExtension == ".csproj") {
+ this->ProjectType = csproj;
+ this->Managed = true;
+ }
// Tell the global generator the name of the project file
- this->Target->SetProperty("GENERATOR_FILE_NAME",this->Name.c_str());
- this->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
- ".vcxproj");
- if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
- {
- if(!this->ComputeClOptions())
- {
+ this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
+ this->Name.c_str());
+ this->GeneratorTarget->Target->SetProperty(
+ "GENERATOR_FILE_NAME_EXT", this->ProjectFileExtension.c_str());
+ if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
+ if (!this->ComputeClOptions()) {
return;
- }
- if(!this->ComputeLinkOptions())
- {
+ }
+ if (!this->ComputeRcOptions()) {
return;
- }
}
- cmMakefile* mf = this->Target->GetMakefile();
- std::string path = mf->GetStartOutputDirectory();
+ if (!this->ComputeCudaOptions()) {
+ return;
+ }
+ if (!this->ComputeCudaLinkOptions()) {
+ return;
+ }
+ if (!this->ComputeMasmOptions()) {
+ return;
+ }
+ if (!this->ComputeNasmOptions()) {
+ return;
+ }
+ if (!this->ComputeLinkOptions()) {
+ return;
+ }
+ if (!this->ComputeLibOptions()) {
+ return;
+ }
+ }
+ std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
path += "/";
path += this->Name;
- path += ".vcxproj";
- this->BuildFileStream =
- new cmGeneratedFileStream(path.c_str());
- this->PathToVcxproj = path;
+ path += this->ProjectFileExtension;
+ this->BuildFileStream = new cmGeneratedFileStream(path.c_str());
+ this->PathToProjectFile = path;
this->BuildFileStream->SetCopyIfDifferent(true);
// Write the encoding header into the file
- char magic[] = {0xEF,0xBB, 0xBF};
+ char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
this->BuildFileStream->write(magic, 3);
- //get the tools version to use
+ // get the tools version to use
const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- std::string project_defaults="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+ 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(toolsVer + "\" ");
project_defaults.append(
- "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
- this->WriteString(project_defaults.c_str(),0);
+ "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";
+ } else {
+ // Nsight Tegra 2.0 uses project revision 9.
+ (*this->BuildFileStream) << "9";
+ }
+ (*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);
+ }
- this->WriteProjectConfigurations();
+ if (csproj != this->ProjectType) {
+ this->WriteProjectConfigurations();
+ }
this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
- this->WriteString("<ProjectGUID>", 2);
- (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGUID>\n";
+ this->WriteString("<ProjectGuid>", 2);
+ (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGuid>\n";
+
+ if (this->MSTools &&
+ this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
+ this->WriteApplicationTypeSettings();
+ this->VerifyNecessaryFiles();
+ }
const char* vsProjectTypes =
- this->Target->GetProperty("VS_GLOBAL_PROJECT_TYPES");
- if(vsProjectTypes)
- {
- this->WriteString("<ProjectTypes>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectTypes) <<
- "</ProjectTypes>\n";
+ 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* vsProjectName = this->Target->GetProperty("VS_SCC_PROJECTNAME");
- const char* vsLocalPath = this->Target->GetProperty("VS_SCC_LOCALPATH");
- const char* vsProvider = this->Target->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 )
- {
+ if (vsProjectName && vsLocalPath && vsProvider) {
this->WriteString("<SccProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName) <<
- "</SccProjectName>\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName)
+ << "</SccProjectName>\n";
this->WriteString("<SccLocalPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath) <<
- "</SccLocalPath>\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath)
+ << "</SccLocalPath>\n";
this->WriteString("<SccProvider>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider) <<
- "</SccProvider>\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider)
+ << "</SccProvider>\n";
- const char* vsAuxPath = this->Target->GetProperty("VS_SCC_AUXPATH");
- if( vsAuxPath )
- {
+ const char* vsAuxPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
+ if (vsAuxPath) {
this->WriteString("<SccAuxPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath) <<
- "</SccAuxPath>\n";
- }
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath)
+ << "</SccAuxPath>\n";
}
+ }
+
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
+ this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2);
+ }
const char* vsGlobalKeyword =
- this->Target->GetProperty("VS_GLOBAL_KEYWORD");
- if(!vsGlobalKeyword)
- {
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
+ if (!vsGlobalKeyword) {
this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
- }
- else
- {
+ } else {
this->WriteString("<Keyword>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword) <<
- "</Keyword>\n";
- }
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword)
+ << "</Keyword>\n";
+ }
const char* vsGlobalRootNamespace =
- this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
- if(vsGlobalRootNamespace)
- {
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
+ if (vsGlobalRootNamespace) {
this->WriteString("<RootNamespace>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace) <<
- "</RootNamespace>\n";
- }
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace)
+ << "</RootNamespace>\n";
+ }
this->WriteString("<Platform>", 2);
- (*this->BuildFileStream) << this->Platform << "</Platform>\n";
- const char* projLabel = this->Target->GetProperty("PROJECT_LABEL");
- if(!projLabel)
- {
+ (*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) << projLabel << "</ProjectName>\n";
- if(const char* targetFrameworkVersion = this->Target->GetProperty(
- "VS_DOTNET_TARGET_FRAMEWORK_VERSION"))
- {
+ (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
+ if (const char* targetFrameworkVersion = this->GeneratorTarget->GetProperty(
+ "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
this->WriteString("<TargetFrameworkVersion>", 2);
- (*this->BuildFileStream) << targetFrameworkVersion
+ (*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;
}
+ 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";
+ }
+ break;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ outputType += "Utility";
+ break;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
+ }
+ outputType += "</OutputType>\n";
+ this->WriteString(outputType.c_str(), 2);
+ this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n",
+ 2);
+ }
+
this->WriteString("</PropertyGroup>\n", 1);
- this->WriteString("<Import Project="
- "\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n",
- 1);
+
+ 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;
+ }
+
this->WriteProjectConfigurationValues();
- this->WriteString(
- "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n", 1);
+
+ if (vcxproj == this->ProjectType) {
+ this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
+ }
this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
- if (this->GlobalGenerator->IsMasmEnabled())
- {
+ if (this->GlobalGenerator->IsCudaEnabled()) {
this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\masm.props\" />\n", 2);
- }
+ "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);
- this->WriteString("<Import Project=\"" VS10_USER_PROPS "\""
- " Condition=\"exists('" VS10_USER_PROPS "')\""
- " Label=\"LocalAppDataPlatform\" />", 2);
+ {
+ 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()) {
+ 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->WriteString(
- "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\""
- " />\n", 1);
+ 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();
this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
- if (this->GlobalGenerator->IsMasmEnabled())
- {
+ this->WriteTargetsFileReferences();
+ if (this->GlobalGenerator->IsCudaEnabled()) {
this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\masm.targets\" />\n", 2);
- }
+ "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();
@@ -349,91 +585,308 @@ void cmVisualStudio10TargetGenerator::Generate()
void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
{
std::vector<std::string> references;
- if(const char* vsDotNetReferences =
- this->Target->GetProperty("VS_DOTNET_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);
+ }
+ 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();
+ if (!cmsys::SystemTools::FileIsFullPath(path)) {
+ path = std::string(this->GeneratorTarget->Target->GetMakefile()
+ ->GetCurrentSourceDirectory()) +
+ "/" + path;
+ }
+ this->ConvertToWindowsSlash(path);
+ hintReferences.push_back(HintReference(name, path));
+ }
}
- if(!references.empty())
- {
+ }
+ if (!references.empty() || !hintReferences.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("<CopyLocalSatelliteAssemblies>true"
- "</CopyLocalSatelliteAssemblies>\n", 3);
- this->WriteString("<ReferenceOutputAssembly>true"
- "</ReferenceOutputAssembly>\n", 3);
- this->WriteString("</Reference>\n", 2);
+ for (std::vector<std::string>::iterator ri = references.begin();
+ ri != references.end(); ++ri) {
+ // if the entry from VS_DOTNET_REFERENCES is an existing file, generate
+ // a new hint-reference and name it from the filename
+ if (cmsys::SystemTools::FileExists(*ri, true)) {
+ std::string name =
+ cmsys::SystemTools::GetFilenameWithoutExtension(*ri);
+ std::string path = *ri;
+ this->ConvertToWindowsSlash(path);
+ hintReferences.push_back(HintReference(name, path));
+ } else {
+ this->WriteDotNetReference(*ri, "");
}
+ }
+ for (std::vector<std::pair<std::string, std::string> >::const_iterator i =
+ hintReferences.begin();
+ i != hintReferences.end(); ++i) {
+ this->WriteDotNetReference(i->first, i->second);
+ }
this->WriteString("</ItemGroup>\n", 1);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteDotNetReference(
+ std::string const& ref, std::string const& hint)
+{
+ this->WriteString("<Reference Include=\"", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(ref) << "\">\n";
+ this->WriteString("<CopyLocalSatelliteAssemblies>true"
+ "</CopyLocalSatelliteAssemblies>\n",
+ 3);
+ this->WriteString("<ReferenceOutputAssembly>true"
+ "</ReferenceOutputAssembly>\n",
+ 3);
+ if (!hint.empty()) {
+ const char* privateReference = "True";
+ if (const char* value = this->GeneratorTarget->GetProperty(
+ "VS_DOTNET_REFERENCES_COPY_LOCAL")) {
+ if (cmSystemTools::IsOff(value)) {
+ privateReference = "False";
+ }
}
+ this->WriteString("<Private>", 3);
+ (*this->BuildFileStream) << privateReference << "</Private>\n";
+ this->WriteString("<HintPath>", 3);
+ (*this->BuildFileStream) << hint << "</HintPath>\n";
+ }
+ this->WriteString("</Reference>\n", 2);
}
void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
{
- std::vector<cmSourceFile*> const& resxObjs =
- this->GeneratorTarget->ResxSources;
- if(!resxObjs.empty())
- {
+ std::vector<cmSourceFile const*> resxObjs;
+ this->GeneratorTarget->GetResxSources(resxObjs, "");
+ if (!resxObjs.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for(std::vector<cmSourceFile*>::const_iterator oi = resxObjs.begin();
- oi != resxObjs.end(); ++oi)
- {
+ 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);
- (*this->BuildFileStream ) << obj << "\">\n";
-
- this->WriteString("<DependentUpon>", 3);
- std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
- (*this->BuildFileStream ) << hFileName;
- this->WriteString("</DependentUpon>\n", 3);
-
- std::vector<std::string> const * configs =
- this->GlobalGenerator->GetConfigurations();
- for(std::vector<std::string>::const_iterator i = configs->begin();
- i != configs->end(); ++i)
- {
- this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
- if(this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE"))
- {
- (*this->BuildFileStream ) << "$(RootNamespace).";
+ bool useRelativePath = false;
+ if (csproj == this->ProjectType && 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);
+ useRelativePath = true;
+ }
+ }
+ (*this->BuildFileStream) << obj << "\">\n";
+
+ if (csproj != this->ProjectType) {
+ this->WriteString("<DependentUpon>", 3);
+ std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
+ (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
+
+ for (std::vector<std::string>::const_iterator i =
+ this->Configurations.begin();
+ i != this->Configurations.end(); ++i) {
+ this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
+ if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
+ // Handle variant of VS_GLOBAL_<variable> for RootNamespace.
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
+ (*this->BuildFileStream) << "$(RootNamespace).";
+ }
+ (*this->BuildFileStream) << "%(Filename)";
+ (*this->BuildFileStream) << ".resources";
+ (*this->BuildFileStream) << "</LogicalName>\n";
+ }
+ } else {
+ std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+ this->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) {
+ std::string link;
+ if (obj.find(srcDir) == 0) {
+ link = obj.substr(srcDir.length() + 1);
+ } else if (obj.find(binDir) == 0) {
+ link = obj.substr(binDir.length() + 1);
+ } else {
+ link = cmsys::SystemTools::GetFilenameName(obj);
+ }
+ if (!link.empty()) {
+ this->WriteString("<Link>", 3);
+ (*this->BuildFileStream) << link << "</Link>\n";
+ }
+ }
+ // Determine if this is a generated resource from a .Designer.cs file
+ std::string designerResource =
+ 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")) {
+ generator = g;
+ }
+ if (!generator.empty()) {
+ this->WriteString("<Generator>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(generator)
+ << "</Generator>\n";
+ if (designerResource.find(srcDir) == 0) {
+ designerResource = designerResource.substr(srcDir.length() + 1);
+ } else if (designerResource.find(binDir) == 0) {
+ designerResource = designerResource.substr(binDir.length() + 1);
+ } else {
+ designerResource =
+ cmsys::SystemTools::GetFilenameName(designerResource);
+ }
+ this->ConvertToWindowsSlash(designerResource);
+ this->WriteString("<LastGenOutput>", 3);
+ (*this->BuildFileStream) << designerResource
+ << "</LastGenOutput>\n";
+ }
+ }
+ const cmPropertyMap& props = (*oi)->GetProperties();
+ for (cmPropertyMap::const_iterator p = props.begin(); p != props.end();
+ ++p) {
+ 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()) {
+ std::string value = props.GetPropertyValue(p->first);
+ if (!value.empty()) {
+ this->WriteString("<", 3);
+ (*this->BuildFileStream) << tagName << ">";
+ (*this->BuildFileStream) << cmVS10EscapeXML(value);
+ (*this->BuildFileStream) << "</" << tagName << ">\n";
+ }
+ }
}
- (*this->BuildFileStream ) << "%(Filename)";
- (*this->BuildFileStream ) << ".resources";
- (*this->BuildFileStream ) << "</LogicalName>\n";
}
+ }
this->WriteString("</EmbeddedResource>\n", 2);
+ }
+ this->WriteString("</ItemGroup>\n", 1);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
+{
+ 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");
+ if (xamlTypeProperty) {
+ xamlType = xamlTypeProperty;
+ } else {
+ xamlType = "Page";
+ }
+
+ this->WriteSource(xamlType, *oi, ">\n");
+ if (csproj == this->ProjectType && !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();
+ std::string link;
+ if (obj.find(srcDir) == 0) {
+ link = obj.substr(srcDir.length() + 1);
+ } else if (obj.find(binDir) == 0) {
+ link = obj.substr(binDir.length() + 1);
+ } else {
+ link = cmsys::SystemTools::GetFilenameName(obj);
+ }
+ if (!link.empty()) {
+ this->ConvertToWindowsSlash(link);
+ this->WriteString("<Link>", 3);
+ (*this->BuildFileStream) << link << "</Link>\n";
+ }
}
+ this->WriteString("<SubType>Designer</SubType>\n", 3);
+ this->WriteString("</", 2);
+ (*this->BuildFileStream) << xamlType << ">\n";
+ }
this->WriteString("</ItemGroup>\n", 1);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
+{
+ 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);
}
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences()
+{
+ 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 << "')";
+ if (!tac.Configs.empty()) {
+ (*this->BuildFileStream) << " And (";
+ for (size_t j = 0; j < tac.Configs.size(); ++j) {
+ if (j > 0) {
+ (*this->BuildFileStream) << " Or ";
+ }
+ (*this->BuildFileStream) << "'$(Configuration)'=='" << tac.Configs[j]
+ << "'";
+ }
+ (*this->BuildFileStream) << ")";
+ }
+ (*this->BuildFileStream) << "\" />\n";
+ }
}
void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
{
std::vector<std::string> references;
- if(const char* vsWinRTReferences =
- this->Target->GetProperty("VS_WINRT_REFERENCES"))
- {
+ if (const char* vsWinRTReferences =
+ this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) {
cmSystemTools::ExpandListArgument(vsWinRTReferences, references);
- }
- if(!references.empty())
- {
+ }
+
+ if (this->GlobalGenerator->TargetsWindowsPhone() &&
+ this->GlobalGenerator->GetSystemVersion() == "8.0" &&
+ references.empty()) {
+ 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)
- {
+ 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);
- }
- this->WriteString("</ItemGroup>\n", 1);
}
+ this->WriteString("</ItemGroup>\n", 1);
+ }
}
// ConfigurationType Application, Utility StaticLibrary DynamicLibrary
@@ -441,382 +894,479 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
{
this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
- for(std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
+ 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->BuildFileStream) << *i << "|" << this->Platform << "\">\n";
this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream ) << *i << "</Configuration>\n";
+ (*this->BuildFileStream) << *i << "</Configuration>\n";
this->WriteString("<Platform>", 3);
- (*this->BuildFileStream) << this->Platform << "</Platform>\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
+ << "</Platform>\n";
this->WriteString("</ProjectConfiguration>\n", 2);
- }
+ }
this->WriteString("</ItemGroup>\n", 1);
}
void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
- for(std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
- this->WritePlatformConfigTag("PropertyGroup",
- i->c_str(),
- 1, " Label=\"Configuration\"", "\n");
- std::string configType = "<ConfigurationType>";
- switch(this->Target->GetType())
- {
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::MODULE_LIBRARY:
- configType += "DynamicLibrary";
- break;
- case cmTarget::OBJECT_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
- configType += "StaticLibrary";
- break;
- case cmTarget::EXECUTABLE:
- configType += "Application";
- break;
- case cmTarget::UTILITY:
- configType += "Utility";
- break;
- case cmTarget::GLOBAL_TARGET:
- case cmTarget::UNKNOWN_LIBRARY:
- break;
+ 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>";
+ if (const char* vsConfigurationType =
+ this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
+ configType += cmVS10EscapeXML(vsConfigurationType);
+ } else {
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ configType += "DynamicLibrary";
+ break;
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ configType += "StaticLibrary";
+ break;
+ case cmStateEnums::EXECUTABLE:
+ if (this->NsightTegra &&
+ !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
+ // Android executables are .so too.
+ configType += "DynamicLibrary";
+ } else {
+ configType += "Application";
+ }
+ break;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ if (this->NsightTegra) {
+ // Tegra-Android platform does not understand "Utility".
+ configType += "StaticLibrary";
+ } else {
+ configType += "Utility";
+ }
+ break;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
+ }
}
- configType += "</ConfigurationType>\n";
- this->WriteString(configType.c_str(), 2);
+ configType += "</ConfigurationType>\n";
+ this->WriteString(configType.c_str(), 2);
+ }
- const char* mfcFlag =
- this->Target->GetMakefile()->GetDefinition("CMAKE_MFC_FLAG");
- std::string mfcFlagValue = mfcFlag ? mfcFlag : "0";
+ if (this->MSTools) {
+ if (!this->Managed) {
+ this->WriteMSToolConfigurationValues(*i);
+ } else {
+ this->WriteMSToolConfigurationValuesManaged(*i);
+ }
+ } else if (this->NsightTegra) {
+ this->WriteNsightTegraConfigurationValues(*i);
+ }
+
+ this->WriteString("</PropertyGroup>\n", 1);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
+ std::string const& config)
+{
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ const char* mfcFlag =
+ this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
+ "CMAKE_MFC_FLAG");
+ if (mfcFlag) {
+ std::string const mfcFlagValue = mfcFlag;
std::string useOfMfcValue = "false";
- if(mfcFlagValue == "1")
- {
- useOfMfcValue = "Static";
- }
- else if(mfcFlagValue == "2")
- {
- useOfMfcValue = "Dynamic";
+ if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
+ if (mfcFlagValue == "1") {
+ useOfMfcValue = "Static";
+ } else if (mfcFlagValue == "2") {
+ useOfMfcValue = "Dynamic";
}
+ }
std::string mfcLine = "<UseOfMfc>";
mfcLine += useOfMfcValue + "</UseOfMfc>\n";
this->WriteString(mfcLine.c_str(), 2);
+ }
- if((this->Target->GetType() <= cmTarget::OBJECT_LIBRARY &&
- this->ClOptions[*i]->UsingUnicode()) ||
- this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
- {
- this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
- }
- else if (this->Target->GetType() <= cmTarget::MODULE_LIBRARY &&
- this->ClOptions[*i]->UsingSBCS())
- {
- this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
- }
- else
- {
- this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
- }
- if(const char* toolset = gg->GetPlatformToolset())
- {
- std::string pts = "<PlatformToolset>";
- pts += toolset;
- pts += "</PlatformToolset>\n";
- this->WriteString(pts.c_str(), 2);
- }
- if(this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
- {
- this->WriteString("<WindowsAppContainer>true"
- "</WindowsAppContainer>\n", 2);
- }
+ if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
+ this->ClOptions[config]->UsingUnicode()) ||
+ this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
+ this->GlobalGenerator->TargetsWindowsPhone() ||
+ this->GlobalGenerator->TargetsWindowsStore() ||
+ this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
+ this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
+ } else if (this->GeneratorTarget->GetType() <=
+ cmStateEnums::MODULE_LIBRARY &&
+ this->ClOptions[config]->UsingSBCS()) {
+ this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
+ } else {
+ this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
+ }
+ if (const char* toolset = gg->GetPlatformToolset()) {
+ std::string pts = "<PlatformToolset>";
+ pts += toolset;
+ pts += "</PlatformToolset>\n";
+ this->WriteString(pts.c_str(), 2);
+ }
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
+ this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
+ this->WriteString("<WindowsAppContainer>true"
+ "</WindowsAppContainer>\n",
+ 2);
+ }
+}
- this->WriteString("</PropertyGroup>\n", 1);
- }
+void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
+ std::string const& config)
+{
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+
+ Options& o = *(this->ClOptions[config]);
+
+ if (o.IsDebug()) {
+ this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2);
+ this->WriteString("<DefineDebug>true</DefineDebug>\n", 2);
+ }
+
+ std::string outDir =
+ this->GeneratorTarget->GetDirectory(config.c_str()) + "/";
+ this->ConvertToWindowsSlash(outDir);
+ this->WriteString("<OutputPath>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
+
+ if (o.HasFlag("Platform")) {
+ this->WriteString("<PlatformTarget>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform"))
+ << "</PlatformTarget>\n";
+ o.RemoveFlag("Platform");
+ }
+
+ if (const char* toolset = gg->GetPlatformToolset()) {
+ this->WriteString("<PlatformToolset>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(toolset)
+ << "</PlatformToolset>\n";
+ }
+
+ std::string postfixName = cmSystemTools::UpperCase(config);
+ postfixName += "_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";
+
+ 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";
+ }
+
+ o.OutputFlagMap(*this->BuildFileStream, " ");
+}
+
+//----------------------------------------------------------------------------
+void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
+ std::string const&)
+{
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ const char* toolset = gg->GetPlatformToolset();
+ std::string ntv = "<NdkToolchainVersion>";
+ ntv += toolset ? toolset : "Default";
+ ntv += "</NdkToolchainVersion>\n";
+ this->WriteString(ntv.c_str(), 2);
+ if (const char* minApi =
+ this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
+ this->WriteString("<AndroidMinAPI>", 2);
+ (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(minApi)
+ << "</AndroidMinAPI>\n";
+ }
+ if (const char* api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
+ this->WriteString("<AndroidTargetAPI>", 2);
+ (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(api)
+ << "</AndroidTargetAPI>\n";
+ }
+
+ if (const char* cpuArch =
+ this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
+ this->WriteString("<AndroidArch>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) << "</AndroidArch>\n";
+ }
+
+ if (const char* stlType =
+ this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
+ this->WriteString("<AndroidStlType>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(stlType)
+ << "</AndroidStlType>\n";
+ }
}
void cmVisualStudio10TargetGenerator::WriteCustomCommands()
{
this->SourcesVisited.clear();
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->CustomCommands.begin();
- si != this->GeneratorTarget->CustomCommands.end(); ++si)
- {
+ 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);
- }
+ }
}
-//----------------------------------------------------------------------------
-void cmVisualStudio10TargetGenerator::WriteCustomCommand(cmSourceFile* sf)
+void cmVisualStudio10TargetGenerator::WriteCustomCommand(
+ cmSourceFile const* sf)
{
- if(this->SourcesVisited.insert(sf).second)
- {
- if(std::vector<cmSourceFile*> const* depends =
- this->Target->GetSourceDepends(sf))
- {
- for(std::vector<cmSourceFile*>::const_iterator di = depends->begin();
- di != depends->end(); ++di)
- {
+ if (this->SourcesVisited.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);
- }
}
- if(cmCustomCommand const* command = sf->GetCustomCommand())
- {
+ }
+ if (cmCustomCommand const* command = sf->GetCustomCommand()) {
this->WriteString("<ItemGroup>\n", 1);
this->WriteCustomRule(sf, *command);
this->WriteString("</ItemGroup>\n", 1);
- }
}
+ }
}
-void
-cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
- cmCustomCommand const &
- command)
+void cmVisualStudio10TargetGenerator::WriteCustomRule(
+ 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 (source->GetPropertyAsBool("__CMAKE_RULE")) {
+ if (!cmSystemTools::FileExists(sourcePath.c_str())) {
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(sourcePath);
cmSystemTools::MakeDirectory(path.c_str());
- std::ofstream fout(sourcePath.c_str());
- if(fout)
- {
+ cmsys::ofstream fout(sourcePath.c_str());
+ if (fout) {
fout << "# generated from CMake\n";
fout.flush();
fout.close();
- }
- else
- {
+ // Force given file to have a very old timestamp, thus
+ // preventing dependent rebuilds.
+ this->ForceOld(sourcePath);
+ } else {
std::string error = "Could not create file: [";
- error += sourcePath;
+ error += sourcePath;
error += "] ";
- cmSystemTools::Error
- (error.c_str(), cmSystemTools::GetLastSystemError().c_str());
- }
+ cmSystemTools::Error(error.c_str(),
+ cmSystemTools::GetLastSystemError().c_str());
}
}
+ }
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- std::string comment = lg->ConstructComment(command);
- comment = cmVS10EscapeComment(comment);
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
this->WriteSource("CustomBuild", source, ">\n");
- for(std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
- std::string script =
- cmVS10EscapeXML(lg->ConstructScript(command, i->c_str()));
- this->WritePlatformConfigTag("Message",i->c_str(), 3);
- (*this->BuildFileStream ) << cmVS10EscapeXML(comment) << "</Message>\n";
+ for (std::vector<std::string>::const_iterator i =
+ this->Configurations.begin();
+ i != this->Configurations.end(); ++i) {
+ cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
+ 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->BuildFileStream) << script << "</Command>\n";
this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3);
- (*this->BuildFileStream ) << source->GetFullPath();
- for(std::vector<std::string>::const_iterator d =
- command.GetDepends().begin();
- d != command.GetDepends().end();
- ++d)
- {
+ (*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))
- {
+ if (this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(),
+ dep)) {
this->ConvertToWindowsSlash(dep);
- (*this->BuildFileStream ) << ";" << dep;
- }
+ (*this->BuildFileStream) << ";" << cmVS10EscapeXML(dep);
}
- (*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n";
+ }
+ (*this->BuildFileStream) << ";%(AdditionalInputs)</AdditionalInputs>\n";
this->WritePlatformConfigTag("Outputs", i->c_str(), 3);
const char* sep = "";
- for(std::vector<std::string>::const_iterator o =
- command.GetOutputs().begin();
- o != command.GetOutputs().end();
- ++o)
- {
+ 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 << out;
+ (*this->BuildFileStream) << sep << cmVS10EscapeXML(out);
sep = ";";
- }
- (*this->BuildFileStream ) << "</Outputs>\n";
- if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
- {
+ }
+ (*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->BuildFileStream) << "false</LinkObjects>\n";
}
+ }
this->WriteString("</CustomBuild>\n", 2);
}
-std::string
-cmVisualStudio10TargetGenerator::ConvertPath(std::string const& path,
- bool forceRelative)
+std::string cmVisualStudio10TargetGenerator::ConvertPath(
+ std::string const& path, bool forceRelative)
{
return forceRelative
? cmSystemTools::RelativePath(
- this->Makefile->GetCurrentOutputDirectory(), path.c_str())
- : this->LocalGenerator->Convert(path.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED);
+ this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str())
+ : path.c_str();
}
void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
{
// first convert all of the slashes
std::string::size_type pos = 0;
- while((pos = s.find('/', pos)) != std::string::npos)
- {
+ while ((pos = s.find('/', pos)) != std::string::npos) {
s[pos] = '\\';
pos++;
- }
+ }
}
void cmVisualStudio10TargetGenerator::WriteGroups()
{
+ if (csproj == this->ProjectType) {
+ return;
+ }
+
// collect up group information
- std::vector<cmSourceGroup> sourceGroups =
- this->Makefile->GetSourceGroups();
- std::vector<cmSourceFile*> classes = this->Target->GetSourceFiles();
+ std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
+
+ std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+ this->GeneratorTarget->GetAllConfigSources();
std::set<cmSourceGroup*> groupsUsed;
- for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
- s != classes.end(); s++)
- {
- cmSourceFile* sf = *s;
- std::string const& source = sf->GetFullPath();
- cmSourceGroup& sourceGroup =
+ for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
+ sources.begin();
+ si != sources.end(); ++si) {
+ std::string const& source = si->Source->GetFullPath();
+ cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
- groupsUsed.insert(&sourceGroup);
- }
+ groupsUsed.insert(sourceGroup);
+ }
this->AddMissingSourceGroups(groupsUsed, sourceGroups);
// Write out group file
- std::string path = this->Makefile->GetStartOutputDirectory();
+ std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
path += "/";
path += this->Name;
- path += ".vcxproj.filters";
+ path += computeProjectFileExtension(this->GeneratorTarget);
+ path += ".filters";
cmGeneratedFileStream fout(path.c_str());
fout.SetCopyIfDifferent(true);
- char magic[] = {0xEF,0xBB, 0xBF};
+ char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
fout.write(magic, 3);
cmGeneratedFileStream* save = this->BuildFileStream;
- this->BuildFileStream = & fout;
+ this->BuildFileStream = &fout;
- //get the tools version to use
+ // get the tools version to use
const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- std::string project_defaults="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+ 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(toolsVer + "\" ");
project_defaults.append(
- "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
- this->WriteString(project_defaults.c_str(),0);
+ "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)
- {
+ 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);
+ }
}
+ this->WriteString("</ItemGroup>\n", 1);
+ }
- std::vector<cmSourceFile*> const& resxObjs =
- this->GeneratorTarget->ResxSources;
- if(!resxObjs.empty())
- {
+ std::vector<cmSourceFile const*> resxObjs;
+ this->GeneratorTarget->GetResxSources(resxObjs, "");
+ if (!resxObjs.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for(std::vector<cmSourceFile*>::const_iterator oi = resxObjs.begin();
- oi != resxObjs.end(); ++oi)
- {
+ 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 ) << obj << "\">\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</EmbeddedResource>\n", 2);
- }
- this->WriteString("</ItemGroup>\n", 1);
}
-
- // Add object library contents as external objects.
- std::vector<std::string> objs;
- this->GeneratorTarget->UseObjectLibraries(objs);
- if(!objs.empty())
- {
- this->WriteString("<ItemGroup>\n", 1);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- std::string obj = *oi;
- this->WriteString("<Object Include=\"", 2);
- this->ConvertToWindowsSlash(obj);
- (*this->BuildFileStream ) << obj << "\">\n";
- this->WriteString("<Filter>Object Libraries</Filter>\n", 3);
- this->WriteString("</Object>\n", 2);
- }
this->WriteString("</ItemGroup>\n", 1);
- }
+ }
this->WriteString("<ItemGroup>\n", 1);
- for(std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
- g != groupsUsed.end(); ++g)
- {
+ for (std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
+ g != groupsUsed.end(); ++g) {
cmSourceGroup* sg = *g;
const char* name = sg->GetFullName();
- if(strlen(name) != 0)
- {
+ if (strlen(name) != 0) {
this->WriteString("<Filter Include=\"", 2);
(*this->BuildFileStream) << name << "\">\n";
std::string guidName = "SG_Filter_";
guidName += name;
- this->GlobalGenerator->CreateGUID(guidName.c_str());
this->WriteString("<UniqueIdentifier>", 3);
- std::string guid
- = this->GlobalGenerator->GetGUID(guidName.c_str());
- (*this->BuildFileStream)
- << "{"
- << guid << "}"
- << "</UniqueIdentifier>\n";
+ std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str());
+ (*this->BuildFileStream) << "{" << guid << "}"
+ << "</UniqueIdentifier>\n";
this->WriteString("</Filter>\n", 2);
- }
- }
- if(!objs.empty())
- {
- this->WriteString("<Filter Include=\"Object Libraries\">\n", 2);
- std::string guidName = "SG_Filter_Object Libraries";
- this->GlobalGenerator->CreateGUID(guidName.c_str());
- this->WriteString("<UniqueIdentifier>", 3);
- std::string guid =
- this->GlobalGenerator->GetGUID(guidName.c_str());
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
- this->WriteString("</Filter>\n", 2);
}
+ }
- if(!this->GeneratorTarget->ResxSources.empty())
- {
+ if (!resxObjs.empty() || !this->AddedFiles.empty()) {
this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
std::string guidName = "SG_Filter_Resource Files";
- this->GlobalGenerator->CreateGUID(guidName.c_str());
this->WriteString("<UniqueIdentifier>", 3);
- std::string guid =
- this->GlobalGenerator->GetGUID(guidName.c_str());
+ 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);
@@ -830,108 +1380,331 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
// restore stream pointer
this->BuildFileStream = save;
- if (fout.Close())
- {
+ if (fout.Close()) {
this->GlobalGenerator->FileReplacedDuringGenerate(path);
- }
+ }
}
// Add to groupsUsed empty source groups that have non-empty children.
-void
-cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
+void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
std::set<cmSourceGroup*>& groupsUsed,
- const std::vector<cmSourceGroup>& allGroups
- )
+ const std::vector<cmSourceGroup>& allGroups)
{
- for(std::vector<cmSourceGroup>::const_iterator current = allGroups.begin();
- current != allGroups.end(); ++current)
- {
+ for (std::vector<cmSourceGroup>::const_iterator current = allGroups.begin();
+ current != allGroups.end(); ++current) {
std::vector<cmSourceGroup> const& children = current->GetGroupChildren();
- if(children.empty())
- {
+ 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.find(current_ptr) != groupsUsed.end()) {
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();
- while(child_it != children.end())
- {
+ while (child_it != children.end()) {
cmSourceGroup* child_ptr = const_cast<cmSourceGroup*>(&(*child_it));
- if(groupsUsed.find(child_ptr) != groupsUsed.end())
- {
+ if (groupsUsed.find(child_ptr) != groupsUsed.end()) {
break; // found a child that was already added => add current group too
- }
- child_it++;
}
+ child_it++;
+ }
- if(child_it == children.end())
- {
+ if (child_it == children.end()) {
continue; // no descendants have source files => ignore this group
- }
+ }
groupsUsed.insert(current_ptr);
- }
+ }
}
-void
-cmVisualStudio10TargetGenerator::
-WriteGroupSources(const char* name,
- ToolSources const& sources,
- std::vector<cmSourceGroup>& sourceGroups)
+void cmVisualStudio10TargetGenerator::WriteGroupSources(
+ const char* 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* sf = s->SourceFile;
+ for (ToolSources::const_iterator s = sources.begin(); s != sources.end();
+ ++s) {
+ cmSourceFile const* sf = s->SourceFile;
std::string const& source = sf->GetFullPath();
- cmSourceGroup& sourceGroup =
+ cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
- const char* filter = sourceGroup.GetFullName();
+ const char* filter = sourceGroup->GetFullName();
this->WriteString("<", 2);
std::string path = this->ConvertPath(source, s->RelativePath);
this->ConvertToWindowsSlash(path);
- (*this->BuildFileStream) << name << " Include=\""
- << path;
- if(strlen(filter))
- {
+ (*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
- {
+ } else {
(*this->BuildFileStream) << "\" />\n";
- }
}
+ }
this->WriteString("</ItemGroup>\n", 1);
}
-void cmVisualStudio10TargetGenerator::WriteSource(
- const char* tool, cmSourceFile* sf, const char* end)
+void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
+{
+ std::string const& fileName = sf->GetFullPath();
+ if (this->IsResxHeader(fileName)) {
+ this->WriteSource("ClInclude", sf, ">\n");
+ this->WriteString("<FileType>CppForm</FileType>\n", 3);
+ this->WriteString("</ClInclude>\n", 2);
+ } 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);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
+{
+ bool toolHasSettings = false;
+ std::string tool = "None";
+ std::string shaderType;
+ std::string shaderEntryPoint;
+ std::string shaderModel;
+ std::string shaderAdditionalFlags;
+ std::string settingsGenerator;
+ std::string settingsLastGenOutput;
+ std::string sourceLink;
+ std::string subType;
+ std::string copyToOutDir;
+ std::string includeInVsix;
+ std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
+ if (csproj == this->ProjectType) {
+ // 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
+ // in none of these paths, it is added with the plain filename without
+ // any path. This means the file will show up at root-level of the csproj
+ // (where CMakeLists.txt etc. are).
+ if (!this->InSourceBuild) {
+ toolHasSettings = true;
+ std::string fullFileName = sf->GetFullPath();
+ std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
+ std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+ if (fullFileName.find(binDir) != std::string::npos) {
+ sourceLink = "";
+ } else if (fullFileName.find(srcDir) != std::string::npos) {
+ sourceLink = fullFileName.substr(srcDir.length() + 1);
+ } else {
+ // fallback: add plain filename without any path
+ sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName);
+ }
+ if (!sourceLink.empty()) {
+ this->ConvertToWindowsSlash(sourceLink);
+ }
+ }
+ }
+ if (ext == "hlsl") {
+ tool = "FXCompile";
+ // Figure out the type of shader compiler to use.
+ if (const char* st = sf->GetProperty("VS_SHADER_TYPE")) {
+ shaderType = st;
+ toolHasSettings = true;
+ }
+ // Figure out which entry point to use if any
+ if (const char* se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) {
+ shaderEntryPoint = se;
+ toolHasSettings = true;
+ }
+ // Figure out which shader model to use if any
+ if (const char* sm = sf->GetProperty("VS_SHADER_MODEL")) {
+ shaderModel = sm;
+ 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;
+ }
+ } else if (ext == "jpg" || ext == "png") {
+ tool = "Image";
+ } else if (ext == "resw") {
+ tool = "PRIResource";
+ } else if (ext == "xml") {
+ tool = "XML";
+ } 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();
+ }
+ std::size_t pos = settingsLastGenOutput.find(".settings");
+ settingsLastGenOutput.replace(pos, 9, ".Designer.cs");
+ settingsGenerator = "SettingsSingleFileGenerator";
+ toolHasSettings = true;
+ } else if (ext == "vsixmanifest") {
+ subType = "Designer";
+ }
+ if (const char* c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
+ copyToOutDir = c;
+ toolHasSettings = true;
+ }
+ if (sf->GetPropertyAsBool("VS_INCLUDE_IN_VSIX")) {
+ includeInVsix = "True";
+ tool = "Content";
+ toolHasSettings = true;
+ }
+
+ if (this->NsightTegra) {
+ // Nsight Tegra needs specific file types to check up-to-dateness.
+ std::string name = cmSystemTools::LowerCase(sf->GetLocation().GetName());
+ if (name == "androidmanifest.xml" || name == "build.xml" ||
+ name == "proguard.cfg" || name == "proguard-project.txt" ||
+ ext == "properties") {
+ tool = "AndroidBuild";
+ } else if (ext == "java") {
+ tool = "JCompile";
+ } else if (ext == "asm" || ext == "s") {
+ tool = "ClCompile";
+ }
+ }
+
+ const char* toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE");
+ if (toolOverride && *toolOverride) {
+ tool = toolOverride;
+ }
+
+ std::string deployContent;
+ std::string deployLocation;
+ if (this->GlobalGenerator->TargetsWindowsPhone() ||
+ this->GlobalGenerator->TargetsWindowsStore()) {
+ const char* content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
+ if (content && *content) {
+ toolHasSettings = true;
+ deployContent = content;
+
+ const char* location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
+ if (location && *location) {
+ deployLocation = location;
+ }
+ }
+ }
+
+ if (toolHasSettings) {
+ this->WriteSource(tool, sf, ">\n");
+
+ if (!deployContent.empty()) {
+ cmGeneratorExpression ge;
+ CM_AUTO_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);
+ }
+ 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);
+ } else {
+ this->WriteString("<ExcludedFromBuild Condition=\""
+ "'$(Configuration)|$(Platform)'=='",
+ 3);
+ (*this->BuildFileStream) << this->Configurations[i] << "|"
+ << this->Platform << "'\">true";
+ this->WriteString("</ExcludedFromBuild>\n", 0);
+ }
+ }
+ }
+ if (!shaderType.empty()) {
+ this->WriteString("<ShaderType>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(shaderType)
+ << "</ShaderType>\n";
+ }
+ if (!shaderEntryPoint.empty()) {
+ this->WriteString("<EntryPointName>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(shaderEntryPoint)
+ << "</EntryPointName>\n";
+ }
+ if (!shaderModel.empty()) {
+ this->WriteString("<ShaderModel>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(shaderModel)
+ << "</ShaderModel>\n";
+ }
+ if (!shaderAdditionalFlags.empty()) {
+ this->WriteString("<AdditionalOptions>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
+ << "</AdditionalOptions>\n";
+ }
+ if (!settingsGenerator.empty()) {
+ this->WriteString("<Generator>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(settingsGenerator)
+ << "</Generator>\n";
+ }
+ if (!settingsLastGenOutput.empty()) {
+ this->WriteString("<LastGenOutput>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(settingsLastGenOutput)
+ << "</LastGenOutput>\n";
+ }
+ if (!sourceLink.empty()) {
+ this->WriteString("<Link>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
+ }
+ if (!subType.empty()) {
+ this->WriteString("<SubType>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(subType) << "</SubType>\n";
+ }
+ if (!copyToOutDir.empty()) {
+ this->WriteString("<CopyToOutputDirectory>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(copyToOutDir)
+ << "</CopyToOutputDirectory>\n";
+ }
+ if (!includeInVsix.empty()) {
+ this->WriteString("<IncludeInVSIX>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(includeInVsix)
+ << "</IncludeInVSIX>\n";
+ }
+
+ this->WriteString("</", 2);
+ (*this->BuildFileStream) << tool << ">\n";
+ } else {
+ this->WriteSource(tool, sf);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
+ cmSourceFile const* sf,
+ const char* end)
{
// Visual Studio tools append relative paths to the current dir, as in:
//
// c:\path\to\current\dir\..\..\..\relative\path\to\source.c
//
// and fail if this exceeds the maximum allowed path length. Our path
- // conversion uses full paths outside the build tree to allow deeper trees.
- bool forceRelative = false;
- std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false);
- if(this->LocalGenerator->GetVersion() == cmLocalVisualStudioGenerator::VS10
- && cmSystemTools::FileIsFullPath(sourceFile.c_str()))
- {
+ // conversion uses full paths when possible to allow deeper trees.
+ // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA
+ // we must use relative paths.
+ bool forceRelative = sf->GetLanguage() == "CUDA";
+ std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
+ if (this->LocalGenerator->GetVersion() ==
+ cmGlobalVisualStudioGenerator::VS10 &&
+ cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
// 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
@@ -942,372 +1715,485 @@ void cmVisualStudio10TargetGenerator::WriteSource(
// when the combined path will not be too long so property pages appear.
std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true);
size_t const maxLen = 250;
- if(sf->GetCustomCommand() ||
- ((strlen(this->Makefile->GetCurrentOutputDirectory()) + 1 +
- sourceRel.length()) <= maxLen))
- {
+ if (sf->GetCustomCommand() ||
+ ((strlen(this->LocalGenerator->GetCurrentBinaryDirectory()) + 1 +
+ sourceRel.length()) <= maxLen)) {
forceRelative = true;
sourceFile = sourceRel;
- }
- else
- {
- this->GlobalGenerator->PathTooLong(this->Target, sf, sourceRel);
- }
+ } else {
+ this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel);
}
+ }
this->ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
- (*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\"";
-
- if(sf->GetExtension() == "h" &&
- this->IsResxHeader(sf->GetFullPath()))
- {
- (*this->BuildFileStream ) << ">\n";
- this->WriteString("<FileType>CppForm</FileType>\n", 3);
- this->WriteString("</ClInclude>\n", 2);
- }
- else
- {
- (*this->BuildFileStream ) << (end? end : " />\n");
- }
+ (*this->BuildFileStream) << tool << " Include=\""
+ << cmVS10EscapeXML(sourceFile) << "\""
+ << (end ? end : " />\n");
- ToolSource toolSource = {sf, forceRelative};
+ ToolSource toolSource = { sf, forceRelative };
this->Tools[tool].push_back(toolSource);
}
-void cmVisualStudio10TargetGenerator::WriteSources(
- const char* tool, std::vector<cmSourceFile*> const& sources)
-{
- for(std::vector<cmSourceFile*>::const_iterator
- si = sources.begin(); si != sources.end(); ++si)
- {
- this->WriteSource(tool, *si);
- }
-}
-
void cmVisualStudio10TargetGenerator::WriteAllSources()
{
- if(this->Target->GetType() > cmTarget::UTILITY)
- {
+ if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
return;
- }
+ }
this->WriteString("<ItemGroup>\n", 1);
- this->WriteSources("ClInclude", this->GeneratorTarget->HeaderSources);
- this->WriteSources("Midl", this->GeneratorTarget->IDLSources);
+ std::vector<size_t> all_configs;
+ for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
+ all_configs.push_back(ci);
+ }
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ObjectSources.begin();
- si != this->GeneratorTarget->ObjectSources.end(); ++si)
- {
- const char* lang = (*si)->GetLanguage();
- const char* tool = NULL;
- if (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0)
- {
- tool = "ClCompile";
- }
- else if (strcmp(lang, "ASM_MASM") == 0 &&
- this->GlobalGenerator->IsMasmEnabled())
- {
- tool = "MASM";
- }
- else if (strcmp(lang, "RC") == 0)
- {
- tool = "ResourceCompile";
- }
+ std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+ this->GeneratorTarget->GetAllConfigSources();
- if (tool)
- {
- this->WriteSource(tool, *si, " ");
- if (this->OutputSourceSpecificFlags(*si))
- {
- this->WriteString("</", 2);
- (*this->BuildFileStream ) << tool << ">\n";
+ for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
+ sources.begin();
+ si != sources.end(); ++si) {
+ std::string tool;
+ switch (si->Kind) {
+ case cmGeneratorTarget::SourceKindAppManifest:
+ tool = "AppxManifest";
+ break;
+ case cmGeneratorTarget::SourceKindCertificate:
+ tool = "None";
+ break;
+ case cmGeneratorTarget::SourceKindCustomCommand:
+ // Handled elsewhere.
+ break;
+ case cmGeneratorTarget::SourceKindExternalObject:
+ tool = "Object";
+ if (this->LocalGenerator->GetVersion() <
+ cmGlobalVisualStudioGenerator::VS11) {
+ // For VS == 10 we cannot use LinkObjects to avoid linking custom
+ // command outputs. If an object file is generated in this target,
+ // 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);
+ if (d && !d->empty()) {
+ tool = "None";
+ }
}
- else
- {
- (*this->BuildFileStream ) << " />\n";
+ break;
+ case cmGeneratorTarget::SourceKindExtra:
+ this->WriteExtraSource(si->Source);
+ break;
+ case cmGeneratorTarget::SourceKindHeader:
+ this->WriteHeaderSource(si->Source);
+ break;
+ case cmGeneratorTarget::SourceKindIDL:
+ tool = "Midl";
+ break;
+ case cmGeneratorTarget::SourceKindManifest:
+ // Handled elsewhere.
+ break;
+ case cmGeneratorTarget::SourceKindModuleDefinition:
+ tool = "None";
+ break;
+ case cmGeneratorTarget::SourceKindObjectSource: {
+ const std::string& lang = si->Source->GetLanguage();
+ if (lang == "C" || lang == "CXX") {
+ tool = "ClCompile";
+ } else if (lang == "ASM_MASM" &&
+ this->GlobalGenerator->IsMasmEnabled()) {
+ tool = "MASM";
+ } else if (lang == "ASM_NASM" &&
+ this->GlobalGenerator->IsNasmEnabled()) {
+ tool = "NASM";
+ } else if (lang == "RC") {
+ tool = "ResourceCompile";
+ } else if (lang == "CSharp") {
+ tool = "Compile";
+ } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) {
+ tool = "CudaCompile";
+ } else {
+ tool = "None";
}
- }
- else
- {
- this->WriteSource("None", *si);
- }
+ } break;
+ case cmGeneratorTarget::SourceKindResx:
+ // Handled elsewhere.
+ break;
+ case cmGeneratorTarget::SourceKindXaml:
+ // Handled elsewhere.
+ break;
}
- if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
- {
- // For VS >= 11 we use LinkObjects to avoid linking custom command
- // outputs. Use Object for all external objects, generated or not.
- this->WriteSources("Object", this->GeneratorTarget->ExternalObjects);
- }
- else
- {
- // If an object file is generated in this target, then vs10 will use
- // it in the build, and we have to list it as None instead of Object.
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ExternalObjects.begin();
- si != this->GeneratorTarget->ExternalObjects.end(); ++si)
- {
- std::vector<cmSourceFile*> const* d=this->Target->GetSourceDepends(*si);
- this->WriteSource((d && !d->empty())? "None":"Object", *si);
+ if (!tool.empty()) {
+ // Compute set of configurations to exclude, if any.
+ 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;
+ }
+ if (have_nested) {
+ this->WriteString("</", 2);
+ (*this->BuildFileStream) << tool << ">\n";
+ } else {
+ (*this->BuildFileStream) << " />\n";
+ }
+ } 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);
}
}
+ }
- this->WriteSources("None", this->GeneratorTarget->ExtraSources);
-
- // Add object library contents as external objects.
- std::vector<std::string> objs;
- this->GeneratorTarget->UseObjectLibraries(objs);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
- {
- std::string obj = *oi;
- this->WriteString("<Object Include=\"", 2);
- this->ConvertToWindowsSlash(obj);
- (*this->BuildFileStream ) << obj << "\" />\n";
- }
+ if (this->IsMissingFiles) {
+ this->WriteMissingFiles();
+ }
this->WriteString("</ItemGroup>\n", 1);
}
bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
- cmSourceFile* source)
+ cmSourceFile const* source)
{
- cmSourceFile& sf = *source;
+ cmSourceFile const& sf = *source;
std::string objectName;
- if(this->GeneratorTarget->ExplicitObjectName.find(&sf)
- != this->GeneratorTarget->ExplicitObjectName.end())
- {
- objectName = this->GeneratorTarget->Objects[&sf];
- }
+ if (this->GeneratorTarget->HasExplicitObjectName(&sf)) {
+ objectName = this->GeneratorTarget->GetObjectName(&sf);
+ }
std::string flags;
+ bool configDependentFlags = false;
std::string defines;
- if(const char* cflags = sf.GetProperty("COMPILE_FLAGS"))
- {
- flags += cflags;
+ if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
+
+ if (cmGeneratorExpression::Find(cflags) != std::string::npos) {
+ configDependentFlags = true;
}
- if(const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS"))
- {
+ flags += cflags;
+ }
+ if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
defines += cdefs;
- }
- const char* lang =
- this->GlobalGenerator->GetLanguageFromExtension
- (sf.GetExtension().c_str());
- const char* sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
- const char* linkLanguage = this->Target->GetLinkerLanguage();
+ }
+ std::string lang =
+ this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
+ std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
+ const std::string& linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage("");
bool needForceLang = false;
// source file does not match its extension language
- if(lang && sourceLang && strcmp(lang, sourceLang) != 0)
- {
+ if (lang != sourceLang) {
needForceLang = true;
lang = sourceLang;
- }
+ }
// if the source file does not match the linker language
// then force c or c++
- if(needForceLang || (linkLanguage && lang
- && strcmp(lang, linkLanguage) != 0))
- {
- if(strcmp(lang, "CXX") == 0)
- {
+ const char* compileAs = 0;
+ if (needForceLang || (linkLanguage != lang)) {
+ if (lang == "CXX") {
// force a C++ file type
- flags += " /TP ";
- }
- else if(strcmp(lang, "C") == 0)
- {
+ compileAs = "CompileAsCpp";
+ } else if (lang == "C") {
// force to c
- flags += " /TC ";
- }
+ compileAs = "CompileAsC";
}
+ }
+ 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.size())
- {
- (*this->BuildFileStream ) << firstString;
+ if (!objectName.empty()) {
+ (*this->BuildFileStream) << firstString;
firstString = "";
hasFlags = true;
this->WriteString("<ObjectFileName>", 3);
- (*this->BuildFileStream )
- << "$(IntDir)/" << objectName << "</ObjectFileName>\n";
- }
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
- for( std::vector<std::string>::iterator config = configs->begin();
- config != configs->end(); ++config)
- {
+ (*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);
std::string configDefines = defines;
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
- if(const char* ccdefs = sf.GetProperty(defPropName.c_str()))
- {
- if(configDefines.size())
- {
+ if (const char* ccdefs = sf.GetProperty(defPropName.c_str())) {
+ if (!configDefines.empty()) {
configDefines += ";";
- }
- configDefines += ccdefs;
}
+ configDefines += ccdefs;
+ }
// if we have flags or defines for this config then
// use them
- if(flags.size() || configDefines.size())
- {
- (*this->BuildFileStream ) << firstString;
+ if (!flags.empty() || configDependentFlags || !configDefines.empty() ||
+ compileAs || noWinRT) {
+ (*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
- cmVisualStudioGeneratorOptions
- clOptions(this->LocalGenerator,
- cmVisualStudioGeneratorOptions::Compiler,
- cmVSGetCLFlagTable(this->LocalGenerator), 0, this);
- clOptions.Parse(flags.c_str());
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmIDEFlagTable const* flagtable = CM_NULLPTR;
+ const std::string& srclang = source->GetLanguage();
+ if (srclang == "C" || srclang == "CXX") {
+ flagtable = gg->GetClFlagTable();
+ } else if (srclang == "ASM_MASM" &&
+ this->GlobalGenerator->IsMasmEnabled()) {
+ flagtable = gg->GetMasmFlagTable();
+ } else if (lang == "ASM_NASM" &&
+ this->GlobalGenerator->IsNasmEnabled()) {
+ flagtable = gg->GetNasmFlagTable();
+ } else if (srclang == "RC") {
+ flagtable = gg->GetRcFlagTable();
+ } else if (srclang == "CSharp") {
+ flagtable = gg->GetCSharpFlagTable();
+ }
+ cmVisualStudioGeneratorOptions clOptions(
+ this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
+ flagtable, 0, this);
+ if (compileAs) {
+ clOptions.AddFlag("CompileAs", compileAs);
+ }
+ if (noWinRT) {
+ 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());
+ } else {
+ clOptions.Parse(flags.c_str());
+ }
+ if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
+ clOptions.AppendFlag("AdditionalIncludeDirectories",
+ "%(AdditionalIncludeDirectories)");
+ }
+ if (clOptions.HasFlag("DisableSpecificWarnings")) {
+ clOptions.AppendFlag("DisableSpecificWarnings",
+ "%(DisableSpecificWarnings)");
+ }
clOptions.AddDefines(configDefines.c_str());
clOptions.SetConfiguration((*config).c_str());
- clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
+ clOptions.PrependInheritedString("AdditionalOptions");
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream,
- " ", "\n", lang);
+ clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
+ "\n", 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";
+ }
+ if (csproj == this->ProjectType) {
+ std::string f = source->GetFullPath();
+ typedef std::map<std::string, std::string> CsPropMap;
+ 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);
+ }
+ }
+ }
+ }
+ // 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";
}
}
+ }
+
return hasFlags;
}
+void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
+ std::vector<size_t> const& exclude_configs)
+{
+ for (std::vector<size_t>::const_iterator ci = exclude_configs.begin();
+ ci != exclude_configs.end(); ++ci) {
+ this->WriteString("", 3);
+ (*this->BuildFileStream)
+ << "<ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='"
+ << cmVS10EscapeXML(this->Configurations[*ci]) << "|"
+ << cmVS10EscapeXML(this->Platform) << "'\">true</ExcludedFromBuild>\n";
+ }
+}
void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
{
- cmTarget::TargetType ttype = this->Target->GetType();
- if(ttype > cmTarget::GLOBAL_TARGET)
- {
+ cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
+ if (ttype > cmStateEnums::GLOBAL_TARGET) {
return;
- }
+ }
+ if (csproj == this->ProjectType) {
+ return;
+ }
- this->WriteString("<PropertyGroup>\n", 2);
+ this->WriteString("<PropertyGroup>\n", 1);
this->WriteString("<_ProjectFileVersion>10.0.20506.1"
- "</_ProjectFileVersion>\n", 3);
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
- for(std::vector<std::string>::iterator config = configs->begin();
- config != configs->end(); ++config)
- {
- if(ttype >= cmTarget::UTILITY)
- {
- this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
+ "</_ProjectFileVersion>\n",
+ 2);
+ for (std::vector<std::string>::const_iterator config =
+ this->Configurations.begin();
+ config != this->Configurations.end(); ++config) {
+ if (ttype >= cmStateEnums::UTILITY) {
+ this->WritePlatformConfigTag("IntDir", config->c_str(), 2);
*this->BuildFileStream
<< "$(Platform)\\$(Configuration)\\$(ProjectName)\\"
<< "</IntDir>\n";
- }
- else
- {
- std::string intermediateDir = this->LocalGenerator->
- GetTargetDirectory(*this->Target);
+ } else {
+ std::string intermediateDir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
intermediateDir += "/";
intermediateDir += *config;
intermediateDir += "/";
std::string outDir;
std::string targetNameFull;
- if(ttype == cmTarget::OBJECT_LIBRARY)
- {
+ if (ttype == cmStateEnums::OBJECT_LIBRARY) {
outDir = intermediateDir;
- targetNameFull = this->Target->GetName();
+ targetNameFull = this->GeneratorTarget->GetName();
targetNameFull += ".lib";
- }
- else
- {
- outDir = this->Target->GetDirectory(config->c_str()) + "/";
- targetNameFull = this->Target->GetFullName(config->c_str());
- }
+ } else {
+ outDir = this->GeneratorTarget->GetDirectory(config->c_str()) + "/";
+ targetNameFull = this->GeneratorTarget->GetFullName(config->c_str());
+ }
this->ConvertToWindowsSlash(intermediateDir);
this->ConvertToWindowsSlash(outDir);
- this->WritePlatformConfigTag("OutDir", config->c_str(), 3);
- *this->BuildFileStream << outDir
- << "</OutDir>\n";
+ this->WritePlatformConfigTag("OutDir", config->c_str(), 2);
+ *this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n";
- this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
- *this->BuildFileStream << intermediateDir
+ this->WritePlatformConfigTag("IntDir", config->c_str(), 2);
+ *this->BuildFileStream << cmVS10EscapeXML(intermediateDir)
<< "</IntDir>\n";
- this->WritePlatformConfigTag("TargetName", config->c_str(), 3);
- *this->BuildFileStream
- << cmSystemTools::GetFilenameWithoutLastExtension(
- targetNameFull.c_str())
- << "</TargetName>\n";
+ if (const char* workingDir = this->GeneratorTarget->GetProperty(
+ "VS_DEBUGGER_WORKING_DIRECTORY")) {
+ this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory",
+ config->c_str(), 2);
+ *this->BuildFileStream << cmVS10EscapeXML(workingDir)
+ << "</LocalDebuggerWorkingDirectory>\n";
+ }
- this->WritePlatformConfigTag("TargetExt", config->c_str(), 3);
- *this->BuildFileStream
- << cmSystemTools::GetFilenameLastExtension(targetNameFull.c_str())
- << "</TargetExt>\n";
+ std::string name =
+ cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
+ this->WritePlatformConfigTag("TargetName", config->c_str(), 2);
+ *this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n";
+
+ std::string ext =
+ cmSystemTools::GetFilenameLastExtension(targetNameFull);
+ if (ext.empty()) {
+ // An empty TargetExt causes a default extension to be used.
+ // A single "." appears to be treated as an empty extension.
+ ext = ".";
+ }
+ this->WritePlatformConfigTag("TargetExt", config->c_str(), 2);
+ *this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n";
this->OutputLinkIncremental(*config);
- }
}
- this->WriteString("</PropertyGroup>\n", 2);
+ }
+ this->WriteString("</PropertyGroup>\n", 1);
}
-
-
-void
-cmVisualStudio10TargetGenerator::
-OutputLinkIncremental(std::string const& configName)
+void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
+ std::string const& configName)
{
+ if (!this->MSTools) {
+ return;
+ }
+ if (csproj == this->ProjectType) {
+ return;
+ }
// static libraries and things greater than modules do not need
// to set this option
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
- || this->Target->GetType() > cmTarget::MODULE_LIBRARY)
- {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
return;
- }
+ }
Options& linkOptions = *(this->LinkOptions[configName]);
const char* incremental = linkOptions.GetFlag("LinkIncremental");
- this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3);
- *this->BuildFileStream << (incremental?incremental:"true")
+ this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 2);
+ *this->BuildFileStream << (incremental ? incremental : "true")
<< "</LinkIncremental>\n";
linkOptions.RemoveFlag("LinkIncremental");
const char* manifest = linkOptions.GetFlag("GenerateManifest");
- this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 3);
- *this->BuildFileStream << (manifest?manifest:"true")
+ this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 2);
+ *this->BuildFileStream << (manifest ? manifest : "true")
<< "</GenerateManifest>\n";
linkOptions.RemoveFlag("GenerateManifest");
// Some link options belong here. Use them now and remove them so that
// WriteLinkOptions does not use them.
- const char* flags[] = {
- "LinkDelaySign",
- "LinkKeyFile",
- 0};
- for(const char** f = flags; *f; ++f)
- {
+ const char* flags[] = { "LinkDelaySign", "LinkKeyFile", 0 };
+ for (const char** f = flags; *f; ++f) {
const char* flag = *f;
- if(const char* value = linkOptions.GetFlag(flag))
- {
- this->WritePlatformConfigTag(flag, configName.c_str(), 3);
+ if (const char* value = linkOptions.GetFlag(flag)) {
+ this->WritePlatformConfigTag(flag, configName.c_str(), 2);
*this->BuildFileStream << value << "</" << flag << ">\n";
linkOptions.RemoveFlag(flag);
- }
}
+ }
}
-//----------------------------------------------------------------------------
bool cmVisualStudio10TargetGenerator::ComputeClOptions()
{
- std::vector<std::string> const* configs =
- this->GlobalGenerator->GetConfigurations();
- for(std::vector<std::string>::const_iterator i = configs->begin();
- i != configs->end(); ++i)
- {
- if(!this->ComputeClOptions(*i))
- {
+ for (std::vector<std::string>::const_iterator i =
+ this->Configurations.begin();
+ i != this->Configurations.end(); ++i) {
+ if (!this->ComputeClOptions(*i)) {
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudio10TargetGenerator::ComputeClOptions(
std::string const& configName)
{
@@ -1315,407 +2201,1120 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// copied from cmLocalVisualStudio7Generator.cxx 805
// TODO: Integrate code below with cmLocalVisualStudio7Generator.
- cmsys::auto_ptr<Options> pOptions(
- new Options(this->LocalGenerator, Options::Compiler,
- cmVSGetCLFlagTable(this->LocalGenerator)));
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ CM_AUTO_PTR<Options> pOptions;
+ switch (this->ProjectType) {
+ case vcxproj:
+ pOptions = CM_AUTO_PTR<Options>(new Options(
+ this->LocalGenerator, Options::Compiler, gg->GetClFlagTable()));
+ break;
+ case csproj:
+ pOptions = CM_AUTO_PTR<Options>(new Options(this->LocalGenerator,
+ Options::CSharpCompiler,
+ gg->GetCSharpFlagTable()));
+ break;
+ }
Options& clOptions = *pOptions;
std::string flags;
- // collect up flags for
- if(this->Target->GetType() < cmTarget::UTILITY)
- {
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(configName.c_str());
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- this->Name.c_str());
- return false;
- }
- if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
- || strcmp(linkLanguage, "Fortran") == 0)
- {
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += linkLanguage;
- baseFlagVar += "_FLAGS";
- flags = this->
- Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str());
- std::string flagVar = baseFlagVar + std::string("_") +
- cmSystemTools::UpperCase(configName);
- flags += " ";
- flags += this->
- Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str());
- }
- // set the correct language
- if(strcmp(linkLanguage, "C") == 0)
- {
- flags += " /TC ";
- }
- if(strcmp(linkLanguage, "CXX") == 0)
- {
- flags += " /TP ";
+ const std::string& linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(configName.c_str());
+ if (linkLanguage.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: ",
+ this->Name.c_str());
+ return false;
+ }
+
+ // Choose a language whose flags to use for ClCompile.
+ static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+ std::string langForClCompile;
+ if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
+ cmArrayEnd(clLangs)) {
+ 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;
+ break;
}
- this->LocalGenerator->AddCompileOptions(flags, this->Target,
- linkLanguage, configName.c_str());
}
+ }
+ 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->AddCompileOptions(flags, this->GeneratorTarget,
+ langForClCompile, configName);
+ }
+ // set the correct language
+ if (linkLanguage == "C") {
+ clOptions.AddFlag("CompileAs", "CompileAsC");
+ }
+ if (linkLanguage == "CXX") {
+ clOptions.AddFlag("CompileAs", "CompileAsCpp");
+ }
+
+ // Check IPO related warning/error.
+ this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags();
- clOptions.FixExceptionHandlingDefault();
- clOptions.AddFlag("PrecompiledHeader", "NotUsing");
- std::string asmLocation = configName + "/";
- clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+ std::string defineFlags =
+ this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ if (this->MSTools) {
+ if (vcxproj == this->ProjectType) {
+ clOptions.FixExceptionHandlingDefault();
+ clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+ std::string asmLocation = configName + "/";
+ clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+ }
+ }
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
std::vector<std::string> targetDefines;
- this->Target->GetCompileDefinitions(targetDefines, configName.c_str());
+ switch (this->ProjectType) {
+ case vcxproj:
+ this->GeneratorTarget->GetCompileDefinitions(targetDefines,
+ configName.c_str(), "CXX");
+ break;
+ case csproj:
+ this->GeneratorTarget->GetCompileDefinitions(
+ targetDefines, configName.c_str(), "CSharp");
+ break;
+ }
clOptions.AddDefines(targetDefines);
- clOptions.SetVerboseMakefile(
- this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
+ 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 += "\"";
clOptions.AddDefine(configDefine);
- if(const char* exportMacro = this->Target->GetExportMacro())
- {
+ if (const char* 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")) {
+ clOptions.AddFlag("CompileAsWinRT", "true");
+ // For WinRT components, add the _WINRT_DLL define to produce a lib
+ if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ clOptions.AddDefine("_WINRT_DLL");
+ }
+ } else if (this->GlobalGenerator->TargetsWindowsStore() ||
+ this->GlobalGenerator->TargetsWindowsPhone()) {
+ if (!clOptions.IsWinRt()) {
+ clOptions.AddFlag("CompileAsWinRT", "false");
+ }
+ }
+ if (const char* winRT = clOptions.GetFlag("CompileAsWinRT")) {
+ if (cmSystemTools::IsOn(winRT)) {
+ this->TargetCompileAsWinRT = true;
+ }
}
+ }
+
+ if (csproj != this->ProjectType && clOptions.IsManaged()) {
+ this->Managed = true;
+ std::string managedType = clOptions.GetFlag("CompileAsManaged");
+ if (managedType == "Safe") {
+ // force empty calling convention if safe clr is used
+ clOptions.AddFlag("CallingConvention", "");
+ }
+ }
this->ClOptions[configName] = pOptions.release();
return true;
}
-//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator::WriteClOptions(
- std::string const& configName,
- std::vector<std::string> const& includes)
+ std::string const& configName, std::vector<std::string> const& includes)
{
Options& clOptions = *(this->ClOptions[configName]);
+ if (this->ProjectType == csproj) {
+ return;
+ }
this->WriteString("<ClCompile>\n", 2);
- clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
- this->OutputIncludes(includes);
+ clOptions.PrependInheritedString("AdditionalOptions");
+ clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
+ clOptions.AppendFlag("AdditionalIncludeDirectories",
+ "%(AdditionalIncludeDirectories)");
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
+ "\n", "CXX");
- // If not in debug mode, write the DebugInformationFormat field
- // without value so PDBs don't get generated uselessly.
- if(!clOptions.IsDebug())
- {
- this->WriteString("<DebugInformationFormat>"
- "</DebugInformationFormat>\n", 3);
+ if (this->NsightTegra) {
+ if (const char* processMax =
+ this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
+ this->WriteString("<ProcessMax>", 3);
+ *this->BuildFileStream << cmVS10EscapeXML(processMax)
+ << "</ProcessMax>\n";
}
+ }
+
+ if (this->MSTools) {
+ cmsys::RegularExpression clangToolset(
+ "(v[0-9]+_clang_.*|LLVM-vs[0-9]+.*)");
+ const char* toolset = this->GlobalGenerator->GetPlatformToolset();
+ if (toolset && clangToolset.find(toolset)) {
+ this->WriteString("<ObjectFileName>"
+ "$(IntDir)%(filename).obj"
+ "</ObjectFileName>\n",
+ 3);
+ } else {
+ this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
+ }
+
+ // If not in debug mode, write the DebugInformationFormat field
+ // without value so PDBs don't get generated uselessly.
+ if (!clOptions.IsDebug()) {
+ this->WriteString("<DebugInformationFormat>"
+ "</DebugInformationFormat>\n",
+ 3);
+ }
+
+ // Specify the compiler program database file if configured.
+ std::string pdb =
+ this->GeneratorTarget->GetCompilePDBPath(configName.c_str());
+ if (!pdb.empty()) {
+ this->ConvertToWindowsSlash(pdb);
+ this->WriteString("<ProgramDataBaseFileName>", 3);
+ *this->BuildFileStream << cmVS10EscapeXML(pdb)
+ << "</ProgramDataBaseFileName>\n";
+ }
+ }
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "CXX");
- this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
this->WriteString("</ClCompile>\n", 2);
}
-void cmVisualStudio10TargetGenerator::
-OutputIncludes(std::vector<std::string> const & includes)
+bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
{
- this->WriteString("<AdditionalIncludeDirectories>", 3);
- for(std::vector<std::string>::const_iterator i = includes.begin();
- i != includes.end(); ++i)
- {
- std::string incDir = *i;
- this->ConvertToWindowsSlash(incDir);
- *this->BuildFileStream << cmVS10EscapeXML(incDir) << ";";
+ for (std::vector<std::string>::const_iterator i =
+ this->Configurations.begin();
+ i != this->Configurations.end(); ++i) {
+ if (!this->ComputeRcOptions(*i)) {
+ return false;
}
- this->WriteString("%(AdditionalIncludeDirectories)"
- "</AdditionalIncludeDirectories>\n", 0);
+ }
+ return true;
}
+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()));
+ 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));
+
+ rcOptions.Parse(flags.c_str());
+ // For historical reasons, add the C preprocessor defines to RC.
+ Options& clOptions = *(this->ClOptions[configName]);
+ rcOptions.AddDefines(clOptions.GetDefines());
-void cmVisualStudio10TargetGenerator::
-WriteRCOptions(std::string const& configName,
- std::vector<std::string> const & includes)
+ this->RcOptions[configName] = pOptions.release();
+ return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteRCOptions(
+ std::string const& configName, std::vector<std::string> const& includes)
{
+ if (!this->MSTools) {
+ return;
+ }
this->WriteString("<ResourceCompile>\n", 2);
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
+
+ Options& rcOptions = *(this->RcOptions[configName]);
+ rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", "RC");
- this->OutputIncludes(includes);
+ rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
+ rcOptions.AppendFlag("AdditionalIncludeDirectories",
+ "%(AdditionalIncludeDirectories)");
+ rcOptions.PrependInheritedString("AdditionalOptions");
+ rcOptions.OutputFlagMap(*this->BuildFileStream, " ");
+
this->WriteString("</ResourceCompile>\n", 2);
}
+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)) {
+ return false;
+ }
+ }
+ return true;
+}
-void
-cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config)
+bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
+ std::string const& configName)
{
- if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
- {
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ CM_AUTO_PTR<Options> pOptions(new 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));
+ this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
+ configName);
+
+ // Get preprocessor definitions for this directory.
+ std::string defineFlags =
+ this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+
+ cudaOptions.Parse(flags.c_str());
+ cudaOptions.Parse(defineFlags.c_str());
+ cudaOptions.ParseFinish();
+
+ if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+ cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
+ } else if (this->GeneratorTarget->GetPropertyAsBool(
+ "CUDA_PTX_COMPILATION")) {
+ cudaOptions.AddFlag("NvccCompilation", "ptx");
+ // 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");
+ }
+
+ // Convert the host compiler options to the toolset's abstractions
+ // using a secondary flag table.
+ cudaOptions.ClearTables();
+ cudaOptions.AddTable(gg->GetCudaHostFlagTable());
+ cudaOptions.Reparse("AdditionalCompilerOptions");
+
+ // `CUDA 8.0.targets` places AdditionalCompilerOptions before nvcc!
+ // Pass them through -Xcompiler in AdditionalOptions instead.
+ if (const char* acoPtr = cudaOptions.GetFlag("AdditionalCompilerOptions")) {
+ std::string aco = acoPtr;
+ cudaOptions.RemoveFlag("AdditionalCompilerOptions");
+ if (!aco.empty()) {
+ aco = this->LocalGenerator->EscapeForShell(aco, false);
+ cudaOptions.AppendFlagString("AdditionalOptions", "-Xcompiler=" + aco);
+ }
+ }
+
+ cudaOptions.FixCudaCodeGeneration();
+
+ std::vector<std::string> targetDefines;
+ this->GeneratorTarget->GetCompileDefinitions(targetDefines,
+ configName.c_str(), "CUDA");
+ cudaOptions.AddDefines(targetDefines);
+
+ // Add a definition for the configuration name.
+ std::string configDefine = "CMAKE_INTDIR=\"";
+ configDefine += configName;
+ configDefine += "\"";
+ cudaOptions.AddDefine(configDefine);
+ if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
+ cudaOptions.AddDefine(exportMacro);
+ }
+
+ this->CudaOptions[configName] = pOptions.release();
+ return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteCudaOptions(
+ std::string const& configName, std::vector<std::string> const& includes)
+{
+ if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
+ return;
+ }
+ this->WriteString("<CudaCompile>\n", 2);
+
+ Options& cudaOptions = *(this->CudaOptions[configName]);
+ cudaOptions.AppendFlag("Include", includes);
+ cudaOptions.AppendFlag("Include", "%(Include)");
+ cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
+ "\n", "CUDA");
+ cudaOptions.PrependInheritedString("AdditionalOptions");
+ cudaOptions.OutputFlagMap(*this->BuildFileStream, " ");
+
+ this->WriteString("</CudaCompile>\n", 2);
+}
+
+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)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+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()));
+ 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;
+ }
+
+ cudaLinkOptions.AddFlag("PerformDeviceLink",
+ doDeviceLinking ? "true" : "false");
+
+ // Suppress deprecation warnings for default GPU targets during device link.
+ if (cmSystemTools::VersionCompareGreaterEq(
+ this->GlobalGenerator->GetPlatformToolsetCudaString(), "8.0")) {
+ cudaLinkOptions.AppendFlagString("AdditionalOptions",
+ "-Wno-deprecated-gpu-targets");
+ }
+
+ this->CudaLinkOptions[configName] = pOptions.release();
+ return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
+ std::string const& configName)
+{
+ if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
return;
+ }
+
+ if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
+ return;
+ }
+
+ this->WriteString("<CudaLink>\n", 2);
+ Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]);
+ cudaLinkOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ this->WriteString("</CudaLink>\n", 2);
+}
+
+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)) {
+ return false;
}
+ }
+ return true;
+}
+
+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()));
+ 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();
+ return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteMasmOptions(
+ std::string const& configName, std::vector<std::string> const& includes)
+{
+ if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
+ return;
+ }
+ this->WriteString("<MASM>\n", 2);
+
+ // Preprocessor definitions and includes are shared with clOptions.
+ Options& clOptions = *(this->ClOptions[configName]);
+ clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
+ "\n", "ASM_MASM");
+
+ Options& masmOptions = *(this->MasmOptions[configName]);
+ masmOptions.AppendFlag("IncludePaths", includes);
+ masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+ masmOptions.PrependInheritedString("AdditionalOptions");
+ masmOptions.OutputFlagMap(*this->BuildFileStream, " ");
+
+ this->WriteString("</MASM>\n", 2);
+}
+
+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)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+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()));
+ 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();
+ return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteNasmOptions(
+ std::string const& configName, std::vector<std::string> includes)
+{
+ 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] += "\\";
+ }
+
+ nasmOptions.AppendFlag("IncludePaths", includes);
+ nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+ nasmOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ nasmOptions.PrependInheritedString("AdditionalOptions");
+ nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
+ "\n", "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);
+}
+
+void cmVisualStudio10TargetGenerator::WriteLibOptions(
+ std::string const& config)
+{
+ if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ return;
+ }
std::string libflags;
- this->LocalGenerator->GetStaticLibraryFlags(libflags,
- cmSystemTools::UpperCase(config), this->Target);
- if(!libflags.empty())
- {
+ this->LocalGenerator->GetStaticLibraryFlags(
+ libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
+ if (!libflags.empty()) {
this->WriteString("<Lib>\n", 2);
- cmVisualStudioGeneratorOptions
- libOptions(this->LocalGenerator,
- cmVisualStudioGeneratorOptions::Linker,
- cmVSGetLibFlagTable(this->LocalGenerator), 0, this);
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmVisualStudioGeneratorOptions libOptions(
+ this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
+ gg->GetLibFlagTable(), 0, this);
libOptions.Parse(libflags.c_str());
- libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
+ libOptions.PrependInheritedString("AdditionalOptions");
libOptions.OutputFlagMap(*this->BuildFileStream, " ");
this->WriteString("</Lib>\n", 2);
+ }
+
+ // We cannot generate metadata for static libraries. WindowsPhone
+ // and WindowsStore tools look at GenerateWindowsMetadata in the
+ // 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);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteManifestOptions(
+ std::string const& config)
+{
+ if (this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE &&
+ this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ return;
+ }
+
+ 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);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
+ std::string const& configName)
+{
+ // Look through the sources for AndroidManifest.xml and use
+ // its location as the root source directory.
+ std::string rootDir = this->LocalGenerator->GetCurrentSourceDirectory();
+ {
+ std::vector<cmSourceFile const*> extraSources;
+ this->GeneratorTarget->GetExtraSources(extraSources, "");
+ for (std::vector<cmSourceFile const*>::const_iterator si =
+ extraSources.begin();
+ si != extraSources.end(); ++si) {
+ if ("androidmanifest.xml" ==
+ cmSystemTools::LowerCase((*si)->GetLocation().GetName())) {
+ rootDir = (*si)->GetLocation().GetDirectory();
+ break;
+ }
+ }
+ }
+
+ // Tell MSBuild to launch Ant.
+ {
+ std::string antBuildPath = rootDir;
+ this->WriteString("<AntBuild>\n", 2);
+ this->WriteString("<AntBuildPath>", 3);
+ this->ConvertToWindowsSlash(antBuildPath);
+ (*this->BuildFileStream) << cmVS10EscapeXML(antBuildPath)
+ << "</AntBuildPath>\n";
+ }
+
+ if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
+ this->WriteString("<SkipAntStep>true</SkipAntStep>\n", 3);
+ }
+
+ if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
+ this->WriteString("<EnableProGuard>true</EnableProGuard>\n", 3);
+ }
+
+ if (const char* proGuardConfigLocation =
+ this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
+ this->WriteString("<ProGuardConfigLocation>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(proGuardConfigLocation)
+ << "</ProGuardConfigLocation>\n";
+ }
+
+ if (const char* securePropertiesLocation =
+ this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
+ this->WriteString("<SecurePropertiesLocation>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(securePropertiesLocation)
+ << "</SecurePropertiesLocation>\n";
+ }
+
+ 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";
+ }
+
+ 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";
+ }
+
+ if (const char* javaSourceDir =
+ this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
+ this->WriteString("<JavaSourceDir>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(javaSourceDir)
+ << "</JavaSourceDir>\n";
+ }
+
+ 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";
+ }
+
+ if (const char* jarDeps =
+ this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
+ this->WriteString("<JarDependencies>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(jarDeps)
+ << "</JarDependencies>\n";
+ }
+
+ if (const char* assetsDirectories =
+ this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
+ this->WriteString("<AssetsDirectories>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(assetsDirectories)
+ << "</AssetsDirectories>\n";
+ }
+
+ {
+ std::string manifest_xml = rootDir + "/AndroidManifest.xml";
+ this->ConvertToWindowsSlash(manifest_xml);
+ this->WriteString("<AndroidManifestLocation>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(manifest_xml)
+ << "</AndroidManifestLocation>\n";
+ }
+
+ if (const char* antAdditionalOptions =
+ this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
+ this->WriteString("<AdditionalOptions>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(antAdditionalOptions)
+ << " %(AdditionalOptions)</AdditionalOptions>\n";
+ }
+
+ this->WriteString("</AntBuild>\n", 2);
}
-//----------------------------------------------------------------------------
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
{
- if(this->Target->GetType() == cmTarget::EXECUTABLE ||
- this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
- this->Target->GetType() == cmTarget::MODULE_LIBRARY)
- {
- std::vector<std::string> const* configs =
- this->GlobalGenerator->GetConfigurations();
- for(std::vector<std::string>::const_iterator i = configs->begin();
- i != configs->end(); ++i)
- {
- if(!this->ComputeLinkOptions(*i))
- {
+ 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)) {
return false;
- }
}
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool
-cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
+bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
+ std::string const& config)
{
- cmsys::auto_ptr<Options> pOptions(
- new Options(this->LocalGenerator, Options::Linker,
- cmVSGetLinkFlagTable(this->LocalGenerator), 0, this));
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ CM_AUTO_PTR<Options> pOptions(new Options(
+ this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this));
Options& linkOptions = *pOptions;
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(config.c_str());
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target: ",
- this->Name.c_str());
+ cmGeneratorTarget::LinkClosure const* linkClosure =
+ this->GeneratorTarget->GetLinkClosure(config);
+
+ const std::string& linkLanguage = linkClosure->LinkerLanguage;
+ if (linkLanguage.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: ",
+ this->Name.c_str());
return false;
- }
+ }
std::string CONFIG = cmSystemTools::UpperCase(config);
const char* linkType = "SHARED";
- if(this->Target->GetType() == cmTarget::MODULE_LIBRARY)
- {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
linkType = "MODULE";
- }
- if(this->Target->GetType() == cmTarget::EXECUTABLE)
- {
+ }
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
linkType = "EXE";
- }
- std::string stackVar = "CMAKE_";
- stackVar += linkLanguage;
- stackVar += "_STACK_SIZE";
- const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
+ }
std::string flags;
- if(stackVal)
- {
- flags += " /STACK:";
- flags += stackVal;
- }
std::string linkFlagVarBase = "CMAKE_";
linkFlagVarBase += linkType;
linkFlagVarBase += "_LINKER_FLAGS";
flags += " ";
- flags += this->
- Target->GetMakefile()->GetRequiredDefinition(linkFlagVarBase.c_str());
+ flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
+ linkFlagVarBase.c_str());
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
flags += " ";
- flags += this->
- Target->GetMakefile()->GetRequiredDefinition(linkFlagVar.c_str());
- const char* targetLinkFlags = this->Target->GetProperty("LINK_FLAGS");
- if(targetLinkFlags)
- {
+ flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
+ linkFlagVar.c_str());
+ const char* targetLinkFlags =
+ this->GeneratorTarget->GetProperty("LINK_FLAGS");
+ if (targetLinkFlags) {
flags += " ";
flags += targetLinkFlags;
- }
+ }
std::string flagsProp = "LINK_FLAGS_";
flagsProp += CONFIG;
- if(const char* flagsConfig = this->Target->GetProperty(flagsProp.c_str()))
- {
+ if (const char* flagsConfig =
+ this->GeneratorTarget->GetProperty(flagsProp.c_str())) {
flags += " ";
flags += flagsConfig;
+ }
+
+ cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(config.c_str());
+ if (!pcli) {
+ cmSystemTools::Error(
+ "CMake can not compute cmComputeLinkInformation for target: ",
+ this->Name.c_str());
+ 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()) {
+ switch (this->CudaOptions[config]->GetCudaRuntime()) {
+ case cmVisualStudioGeneratorOptions::CudaRuntimeStatic:
+ libVec.push_back("cudart_static.lib");
+ break;
+ case cmVisualStudioGeneratorOptions::CudaRuntimeShared:
+ libVec.push_back("cudart.lib");
+ break;
+ case cmVisualStudioGeneratorOptions::CudaRuntimeNone:
+ break;
}
- if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") )
- {
- linkOptions.AddFlag("SubSystem", "Windows");
- }
- else
- {
- linkOptions.AddFlag("SubSystem", "Console");
- }
+ }
std::string standardLibsVar = "CMAKE_";
standardLibsVar += linkLanguage;
standardLibsVar += "_STANDARD_LIBRARIES";
- std::string
- libs = this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
- // Remove trailing spaces from libs
- std::string::size_type pos = libs.size()-1;
- if(libs.size() != 0)
- {
- while(libs[pos] == ' ')
- {
- pos--;
- }
- }
- if(pos != libs.size()-1)
- {
- libs = libs.substr(0, pos+1);
- }
- // Replace spaces in libs with ;
- cmSystemTools::ReplaceString(libs, " ", ";");
- cmComputeLinkInformation* pcli =
- this->Target->GetLinkInformation(config.c_str());
- if(!pcli)
- {
- cmSystemTools::Error
- ("CMake can not compute cmComputeLinkInformation for target: ",
- this->Name.c_str());
- return false;
- }
- // add the libraries for the target to libs string
- cmComputeLinkInformation& cli = *pcli;
- this->AddLibraries(cli, libs);
- linkOptions.AddFlag("AdditionalDependencies", libs.c_str());
+ std::string const libs =
+ this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+ 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);
+ }
std::vector<std::string> const& ldirs = cli.GetDirectories();
- const char* sep = "";
- std::string linkDirs;
- for(std::vector<std::string>::const_iterator d = ldirs.begin();
- d != ldirs.end(); ++d)
- {
+ std::vector<std::string> linkDirs;
+ for (std::vector<std::string>::const_iterator d = ldirs.begin();
+ d != ldirs.end(); ++d) {
// first just full path
- linkDirs += sep;
- linkDirs += *d;
- sep = ";";
- linkDirs += sep;
+ linkDirs.push_back(*d);
// next path with configuration type Debug, Release, etc
- linkDirs += *d;
- linkDirs += "/$(Configuration)";
- linkDirs += sep;
- }
- linkDirs += "%(AdditionalLibraryDirectories)";
- linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs.c_str());
- linkOptions.AddFlag("AdditionalDependencies", libs.c_str());
- linkOptions.AddFlag("Version", "");
- if(linkOptions.IsDebug() || flags.find("/debug") != flags.npos)
- {
- linkOptions.AddFlag("GenerateDebugInformation", "true");
- }
- else
- {
- linkOptions.AddFlag("GenerateDebugInformation", "false");
- }
+ 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;
- if(this->Target->GetType() == cmTarget::EXECUTABLE)
- {
- this->Target->GetExecutableNames(targetName, targetNameFull,
- targetNameImport, targetNamePDB,
- config.c_str());
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
+ this->GeneratorTarget->GetExecutableNames(targetName, targetNameFull,
+ targetNameImport, targetNamePDB,
+ config.c_str());
+ } else {
+ this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
+ targetNameFull, targetNameImport,
+ targetNamePDB, config.c_str());
+ }
+
+ if (this->MSTools) {
+ linkOptions.AddFlag("Version", "");
+
+ if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+ if (this->GlobalGenerator->TargetsWindowsCE()) {
+ linkOptions.AddFlag("SubSystem", "WindowsCE");
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
+ if (this->ClOptions[config]->UsingUnicode()) {
+ linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup");
+ } else {
+ linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup");
+ }
+ }
+ } else {
+ linkOptions.AddFlag("SubSystem", "Windows");
+ }
+ } else {
+ if (this->GlobalGenerator->TargetsWindowsCE()) {
+ linkOptions.AddFlag("SubSystem", "WindowsCE");
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
+ if (this->ClOptions[config]->UsingUnicode()) {
+ linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup");
+ } else {
+ linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup");
+ }
+ }
+ } else {
+ linkOptions.AddFlag("SubSystem", "Console");
+ };
}
- else
- {
- this->Target->GetLibraryNames(targetName, targetNameSO, targetNameFull,
- targetNameImport, targetNamePDB,
- config.c_str());
+
+ if (const char* stackVal = this->Makefile->GetDefinition(
+ "CMAKE_" + linkLanguage + "_STACK_SIZE")) {
+ linkOptions.AddFlag("StackReserveSize", stackVal);
+ }
+
+ 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;
+
+ linkOptions.AddFlag("ImportLibrary", imLib.c_str());
+ linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str());
+
+ // A Windows Runtime component uses internal .NET metadata,
+ // so does not have an import library.
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") &&
+ this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) {
+ linkOptions.AddFlag("GenerateWindowsMetadata", "true");
+ } else if (this->GlobalGenerator->TargetsWindowsPhone() ||
+ this->GlobalGenerator->TargetsWindowsStore()) {
+ // WindowsPhone and WindowsStore components are in an app container
+ // and produce WindowsMetadata. If we are not producing a WINRT
+ // component, then do not generate the metadata here.
+ linkOptions.AddFlag("GenerateWindowsMetadata", "false");
}
- std::string pdb = this->Target->GetPDBDirectory(config.c_str());
- pdb += "/";
- pdb += targetNamePDB;
- std::string imLib = this->Target->GetDirectory(config.c_str(), true);
- imLib += "/";
- imLib += targetNameImport;
+ if (this->GlobalGenerator->TargetsWindowsPhone() &&
+ this->GlobalGenerator->GetSystemVersion() == "8.0") {
+ // WindowsPhone 8.0 does not have ole32.
+ linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
+ }
+ } else if (this->NsightTegra) {
+ linkOptions.AddFlag("SoName", targetNameSO.c_str());
+ }
- linkOptions.AddFlag("ImportLibrary", imLib.c_str());
- linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str());
linkOptions.Parse(flags.c_str());
- if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
- {
- linkOptions.AddFlag("ModuleDefinitionFile",
- this->GeneratorTarget->ModuleDefinitionFile.c_str());
+
+ if (this->MSTools) {
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ this->GeneratorTarget->GetModuleDefinitionInfo(config);
+ if (mdi && !mdi->DefFile.empty()) {
+ linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
+ }
+ linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
+ "%(IgnoreSpecificDefaultLibraries)");
+ }
+
+ // VS 2015 without all updates has a v140 toolset whose
+ // GenerateDebugInformation expects No/Debug instead of false/true.
+ if (gg->GetPlatformToolsetNeedsDebugEnum()) {
+ if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
+ if (strcmp(debug, "false") == 0) {
+ linkOptions.AddFlag("GenerateDebugInformation", "No");
+ } else if (strcmp(debug, "true") == 0) {
+ linkOptions.AddFlag("GenerateDebugInformation", "Debug");
+ }
}
+ }
this->LinkOptions[config] = pOptions.release();
return true;
}
-//----------------------------------------------------------------------------
-void
-cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config)
+bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
{
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
- || this->Target->GetType() > cmTarget::MODULE_LIBRARY)
- {
- return;
+ 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)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
+ std::string const& config)
+{
+ cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(config.c_str());
+ if (!pcli) {
+ cmSystemTools::Error(
+ "CMake can not compute cmComputeLinkInformation for target: ",
+ this->Name.c_str());
+ return false;
+ }
+
+ cmComputeLinkInformation& cli = *pcli;
+ typedef cmComputeLinkInformation::ItemVector 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);
+ this->AddTargetsFileAndConfigPair(path, config);
}
+ }
+
+ return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteLinkOptions(
+ std::string const& config)
+{
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
+ return;
+ }
+ if (csproj == this->ProjectType) {
+ return;
+ }
Options& linkOptions = *(this->LinkOptions[config]);
this->WriteString("<Link>\n", 2);
- linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
+ linkOptions.PrependInheritedString("AdditionalOptions");
linkOptions.OutputFlagMap(*this->BuildFileStream, " ");
this->WriteString("</Link>\n", 2);
- if(!this->GlobalGenerator->NeedLinkLibraryDependencies(*this->Target))
- {
+ if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
+ this->GeneratorTarget)) {
this->WriteString("<ProjectReference>\n", 2);
this->WriteString(
- " <LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 2);
+ "<LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 3);
this->WriteString("</ProjectReference>\n", 2);
- }
+ }
}
void cmVisualStudio10TargetGenerator::AddLibraries(
- cmComputeLinkInformation& cli,
- std::string& libstring)
+ cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
+ std::vector<std::string>& vsTargetVec)
{
typedef cmComputeLinkInformation::ItemVector ItemVector;
- ItemVector libs = cli.GetItems();
- const char* sep = ";";
- for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
- {
- if(l->IsPath)
- {
- std::string path = this->LocalGenerator->
- Convert(l->Value.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED);
+ 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);
- libstring += sep;
- libstring += path;
- }
- else
- {
- libstring += sep;
- libstring += l->Value;
+ 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);
}
+ }
}
+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);
+ }
+ return;
+ }
+ }
+ TargetsFileAndConfigs entry;
+ entry.File = targetsFile;
+ entry.Configs.push_back(config);
+ this->TargetsFileAndConfigsVec.push_back(entry);
+}
-void cmVisualStudio10TargetGenerator::
-WriteMidlOptions(std::string const& /*config*/,
- std::vector<std::string> const & includes)
+void cmVisualStudio10TargetGenerator::WriteMidlOptions(
+ std::string const& /*config*/, std::vector<std::string> const& includes)
{
+ if (!this->MSTools) {
+ return;
+ }
+ if (csproj == this->ProjectType) {
+ return;
+ }
+
// This processes *any* of the .idl files specified in the project's file
// list (and passed as the item metadata %(Filename) expressing the rule
// input filename) into output files at the per-config *build* dir
@@ -1732,150 +3331,978 @@ WriteMidlOptions(std::string const& /*config*/,
// only). Perhaps there's something to be done to make this more automatic
// on the CMake side?
this->WriteString("<Midl>\n", 2);
- this->OutputIncludes(includes);
- this->WriteString("<OutputDirectory>$(IntDir)</OutputDirectory>\n", 3);
+ 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("<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);
}
-
void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
{
- std::vector<std::string> *configs =
- static_cast<cmGlobalVisualStudio7Generator *>
- (this->GlobalGenerator)->GetConfigurations();
- for(std::vector<std::string>::iterator i = configs->begin();
- i != configs->end(); ++i)
- {
+ 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());
+ 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";
// output cl compile flags <ClCompile></ClCompile>
- if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
- {
+ if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
this->WriteClOptions(*i, includes);
// output rc compile flags <ResourceCompile></ResourceCompile>
this->WriteRCOptions(*i, includes);
- }
+ this->WriteCudaOptions(*i, includes);
+ this->WriteMasmOptions(*i, includes);
+ this->WriteNasmOptions(*i, includes);
+ }
// output midl flags <Midl></Midl>
this->WriteMidlOptions(*i, includes);
// write events
- this->WriteEvents(*i);
+ if (csproj != this->ProjectType) {
+ this->WriteEvents(*i);
+ }
// output link flags <Link></Link>
this->WriteLinkOptions(*i);
+ this->WriteCudaLinkOptions(*i);
// output lib flags <Lib></Lib>
this->WriteLibOptions(*i);
- this->WriteString("</ItemDefinitionGroup>\n", 1);
+ // output manifest flags <Manifest></Manifest>
+ this->WriteManifestOptions(*i);
+ if (this->NsightTegra &&
+ this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
+ this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
+ this->WriteAntBuildOptions(*i);
}
+ this->WriteString("</ItemDefinitionGroup>\n", 1);
+ }
}
-void
-cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName)
+void cmVisualStudio10TargetGenerator::WriteEvents(
+ std::string const& configName)
{
- this->WriteEvent("PreLinkEvent",
- this->Target->GetPreLinkCommands(), configName);
+ bool addedPrelink = false;
+ cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+ this->GeneratorTarget->GetModuleDefinitionInfo(configName);
+ if (mdi && mdi->DefFileGenerated) {
+ addedPrelink = true;
+ std::vector<cmCustomCommand> commands =
+ this->GeneratorTarget->GetPreLinkCommands();
+ this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
+ commands, configName);
+ this->WriteEvent("PreLinkEvent", commands, configName);
+ }
+ if (!addedPrelink) {
+ this->WriteEvent("PreLinkEvent",
+ this->GeneratorTarget->GetPreLinkCommands(), configName);
+ }
this->WriteEvent("PreBuildEvent",
- this->Target->GetPreBuildCommands(), configName);
+ this->GeneratorTarget->GetPreBuildCommands(), configName);
this->WriteEvent("PostBuildEvent",
- this->Target->GetPostBuildCommands(), configName);
+ this->GeneratorTarget->GetPostBuildCommands(), configName);
}
void cmVisualStudio10TargetGenerator::WriteEvent(
- const char* name,
- std::vector<cmCustomCommand> & commands,
+ const char* name, std::vector<cmCustomCommand> const& commands,
std::string const& configName)
{
- if(commands.size() == 0)
- {
+ if (commands.empty()) {
return;
- }
+ }
this->WriteString("<", 2);
- (*this->BuildFileStream ) << name << ">\n";
+ (*this->BuildFileStream) << name << ">\n";
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
std::string script;
const char* pre = "";
std::string comment;
- for(std::vector<cmCustomCommand>::iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- cmCustomCommand& command = *i;
+ for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+ i != commands.end(); ++i) {
+ cmCustomCommandGenerator ccg(*i, configName, this->LocalGenerator);
comment += pre;
- comment += lg->ConstructComment(command);
+ comment += lg->ConstructComment(ccg);
script += pre;
pre = "\n";
- script +=
- cmVS10EscapeXML(lg->ConstructScript(command, configName.c_str()));
- }
+ script += cmVS10EscapeXML(lg->ConstructScript(ccg));
+ }
comment = cmVS10EscapeComment(comment);
- this->WriteString("<Message>",3);
- (*this->BuildFileStream ) << cmVS10EscapeXML(comment) << "</Message>\n";
- this->WriteString("<Command>", 3);
- (*this->BuildFileStream ) << script;
- (*this->BuildFileStream ) << "</Command>" << "\n";
+ if (csproj != this->ProjectType) {
+ this->WriteString("<Message>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
+ this->WriteString("<Command>", 3);
+ } else {
+ if (!comment.empty()) {
+ (*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment) << "\n";
+ }
+ }
+ (*this->BuildFileStream) << script;
+ if (csproj != this->ProjectType) {
+ (*this->BuildFileStream) << "</Command>";
+ }
+ (*this->BuildFileStream) << "\n";
this->WriteString("</", 2);
- (*this->BuildFileStream ) << name << ">\n";
+ (*this->BuildFileStream) << name << ">\n";
}
-
void cmVisualStudio10TargetGenerator::WriteProjectReferences()
{
- cmGlobalGenerator::TargetDependSet const& unordered
- = this->GlobalGenerator->GetTargetDirectDepends(*this->Target);
+ cmGlobalGenerator::TargetDependSet const& unordered =
+ this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
typedef cmGlobalVisualStudioGenerator::OrderedTargetDependSet
OrderedTargetDependSet;
- OrderedTargetDependSet depends(unordered);
+ OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
this->WriteString("<ItemGroup>\n", 1);
- for( OrderedTargetDependSet::const_iterator i = depends.begin();
- i != depends.end(); ++i)
- {
- cmTarget* dt = *i;
+ for (OrderedTargetDependSet::const_iterator i = depends.begin();
+ i != depends.end(); ++i) {
+ cmGeneratorTarget const* dt = *i;
+ 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 (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
+ ->TargetIsFortranOnly(dt)) {
continue;
- }
+ }
this->WriteString("<ProjectReference Include=\"", 2);
- cmMakefile* mf = dt->GetMakefile();
+ cmLocalGenerator* lg = dt->GetLocalGenerator();
std::string name = dt->GetName();
std::string path;
const char* p = dt->GetProperty("EXTERNAL_MSPROJECT");
- if(p)
- {
+ if (p) {
path = p;
- }
- else
- {
- path = mf->GetStartOutputDirectory();
+ } else {
+ path = lg->GetCurrentBinaryDirectory();
path += "/";
path += dt->GetName();
- path += ".vcxproj";
- }
- (*this->BuildFileStream) << path << "\">\n";
+ path += computeProjectFileExtension(dt);
+ }
+ this->ConvertToWindowsSlash(path);
+ (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
this->WriteString("<Project>", 3);
(*this->BuildFileStream)
- << this->GlobalGenerator->GetGUID(name.c_str())
- << "</Project>\n";
- this->WriteString("</ProjectReference>\n", 2);
+ << "{" << 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);
+ }
}
+ this->WriteString("</ProjectReference>\n", 2);
+ }
this->WriteString("</ItemGroup>\n", 1);
}
-bool cmVisualStudio10TargetGenerator::
- IsResxHeader(const std::string& headerFile)
+void cmVisualStudio10TargetGenerator::WritePlatformExtensions()
+{
+ // This only applies to Windows 10 apps
+ if (this->GlobalGenerator->TargetsWindowsStore() &&
+ cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
+ const char* desktopExtensionsVersion =
+ this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
+ if (desktopExtensionsVersion) {
+ this->WriteSinglePlatformExtension("WindowsDesktop",
+ desktopExtensionsVersion);
+ }
+ const char* mobileExtensionsVersion =
+ this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
+ if (mobileExtensionsVersion) {
+ this->WriteSinglePlatformExtension("WindowsMobile",
+ mobileExtensionsVersion);
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
+ 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";
+}
+
+void cmVisualStudio10TargetGenerator::WriteSDKReferences()
+{
+ std::vector<std::string> sdkReferences;
+ bool hasWrittenItemGroup = false;
+ 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";
+ }
+ }
+
+ // This only applies to Windows 10 apps
+ if (this->GlobalGenerator->TargetsWindowsStore() &&
+ cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
+ const char* desktopExtensionsVersion =
+ this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
+ const char* mobileExtensionsVersion =
+ this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
+ const char* iotExtensionsVersion =
+ this->GeneratorTarget->GetProperty("VS_IOT_EXTENSIONS_VERSION");
+
+ if (desktopExtensionsVersion || mobileExtensionsVersion ||
+ iotExtensionsVersion) {
+ if (!hasWrittenItemGroup) {
+ this->WriteString("<ItemGroup>\n", 1);
+ hasWrittenItemGroup = true;
+ }
+ if (desktopExtensionsVersion) {
+ this->WriteSingleSDKReference("WindowsDesktop",
+ desktopExtensionsVersion);
+ }
+ if (mobileExtensionsVersion) {
+ this->WriteSingleSDKReference("WindowsMobile",
+ mobileExtensionsVersion);
+ }
+ if (iotExtensionsVersion) {
+ this->WriteSingleSDKReference("WindowsIoT", iotExtensionsVersion);
+ }
+ }
+
+ if (hasWrittenItemGroup) {
+ this->WriteString("</ItemGroup>\n", 1);
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
+ std::string const& extension, std::string const& version)
+{
+ this->WriteString("<SDKReference Include=\"", 2);
+ (*this->BuildFileStream) << extension << ", Version=" << version
+ << "\" />\n";
+}
+
+void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
+{
+ if ((this->GlobalGenerator->TargetsWindowsStore() ||
+ this->GlobalGenerator->TargetsWindowsPhone()) &&
+ (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType())) {
+ 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);
+ break;
+ }
+
+ if (this->IsMissingFiles &&
+ !(this->GlobalGenerator->TargetsWindowsPhone() &&
+ this->GlobalGenerator->GetSystemVersion() == "8.0")) {
+ // 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);
+ std::string resourcePriFile =
+ this->DefaultArtifactDir + "/resources.pri";
+ this->ConvertToWindowsSlash(resourcePriFile);
+ (*this->BuildFileStream) << resourcePriFile << "</ProjectPriFullPath>\n";
+
+ // If we are missing files and we don't have a certificate and
+ // aren't targeting WP8.0, add a default certificate
+ if (pfxFile.empty()) {
+ std::string templateFolder =
+ cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
+ pfxFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
+ cmSystemTools::CopyAFile(templateFolder + "/Windows_TemporaryKey.pfx",
+ pfxFile, false);
+ this->ConvertToWindowsSlash(pfxFile);
+ this->AddedFiles.push_back(pfxFile);
+ }
+
+ this->WriteString("<", 2);
+ (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
+ << "</PackageCertificateKeyFile>\n";
+ std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
+ if (!thumb.empty()) {
+ this->WriteString("<PackageCertificateThumbprint>", 2);
+ (*this->BuildFileStream) << thumb
+ << "</PackageCertificateThumbprint>\n";
+ }
+ this->WriteString("</PropertyGroup>\n", 1);
+ } else if (!pfxFile.empty()) {
+ this->WriteString("<PropertyGroup>\n", 1);
+ this->WriteString("<", 2);
+ (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
+ << "</PackageCertificateKeyFile>\n";
+ std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
+ if (!thumb.empty()) {
+ this->WriteString("<PackageCertificateThumbprint>", 2);
+ (*this->BuildFileStream) << thumb
+ << "</PackageCertificateThumbprint>\n";
+ }
+ this->WriteString("</PropertyGroup>\n", 1);
+ }
+ }
+}
+
+bool cmVisualStudio10TargetGenerator::IsResxHeader(
+ const std::string& headerFile)
+{
+ std::set<std::string> expectedResxHeaders;
+ this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders, "");
+
+ std::set<std::string>::const_iterator it =
+ expectedResxHeaders.find(headerFile);
+ return it != expectedResxHeaders.end();
+}
+
+bool cmVisualStudio10TargetGenerator::IsXamlHeader(
+ const std::string& headerFile)
+{
+ std::set<std::string> expectedXamlHeaders;
+ this->GeneratorTarget->GetExpectedXamlHeaders(expectedXamlHeaders, "");
+
+ std::set<std::string>::const_iterator it =
+ expectedXamlHeaders.find(headerFile);
+ return it != expectedXamlHeaders.end();
+}
+
+bool cmVisualStudio10TargetGenerator::IsXamlSource(
+ const std::string& sourceFile)
+{
+ std::set<std::string> expectedXamlSources;
+ this->GeneratorTarget->GetExpectedXamlSources(expectedXamlSources, "");
+
+ std::set<std::string>::const_iterator it =
+ expectedXamlSources.find(sourceFile);
+ return it != expectedXamlSources.end();
+}
+
+void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
+{
+ cmGlobalVisualStudio10Generator* gg =
+ static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ bool isAppContainer = false;
+ bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
+ bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
+ std::string const& v = this->GlobalGenerator->GetSystemVersion();
+ 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";
+ // Visual Studio 14.0 is necessary for building 10.0 apps
+ this->WriteString("<MinimumVisualStudioVersion>14.0"
+ "</MinimumVisualStudioVersion>\n",
+ 2);
+
+ if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
+ isAppContainer = true;
+ }
+ } else if (v == "8.1") {
+ this->WriteString("<ApplicationTypeRevision>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(v)
+ << "</ApplicationTypeRevision>\n";
+ // Visual Studio 12.0 is necessary for building 8.1 apps
+ this->WriteString("<MinimumVisualStudioVersion>12.0"
+ "</MinimumVisualStudioVersion>\n",
+ 2);
+
+ if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
+ isAppContainer = true;
+ }
+ } else if (v == "8.0") {
+ this->WriteString("<ApplicationTypeRevision>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(v)
+ << "</ApplicationTypeRevision>\n";
+ // Visual Studio 11.0 is necessary for building 8.0 apps
+ this->WriteString("<MinimumVisualStudioVersion>11.0"
+ "</MinimumVisualStudioVersion>\n",
+ 2);
+
+ if (isWindowsStore &&
+ this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
+ isAppContainer = true;
+ } 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";
+ }
+ }
+ }
+ if (isAppContainer) {
+ this->WriteString("<AppContainerApplication>true"
+ "</AppContainerApplication>\n",
+ 2);
+ } else if (this->Platform == "ARM") {
+ this->WriteString("<WindowsSDKDesktopARMSupport>true"
+ "</WindowsSDKDesktopARMSupport>\n",
+ 2);
+ }
+ std::string const& targetPlatformVersion =
+ gg->GetWindowsTargetPlatformVersion();
+ if (!targetPlatformVersion.empty()) {
+ this->WriteString("<WindowsTargetPlatformVersion>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
+ << "</WindowsTargetPlatformVersion>\n";
+ }
+ 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")) {
+ // If the min version is not set, then use the TargetPlatformVersion
+ if (!targetPlatformVersion.empty()) {
+ this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
+ << "</WindowsTargetPlatformMinVersion>\n";
+ }
+ }
+
+ // Added IoT Startup Task support
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
+ this->WriteString("<ContainsStartupTask>true</ContainsStartupTask>\n", 2);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
+{
+ // For Windows and Windows Phone executables, we will assume that if a
+ // manifest is not present that we need to add all the necessary files
+ if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
+ std::vector<cmSourceFile const*> manifestSources;
+ this->GeneratorTarget->GetAppManifest(manifestSources, "");
+ {
+ std::string const& v = this->GlobalGenerator->GetSystemVersion();
+ if (this->GlobalGenerator->TargetsWindowsPhone()) {
+ if (v == "8.0") {
+ // Look through the sources for WMAppManifest.xml
+ 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) {
+ // Need to do a lowercase comparison on the filename
+ if ("wmappmanifest.xml" ==
+ cmSystemTools::LowerCase((*si)->GetLocation().GetName())) {
+ foundManifest = true;
+ break;
+ }
+ }
+ if (!foundManifest) {
+ this->IsMissingFiles = true;
+ }
+ } else if (v == "8.1") {
+ if (manifestSources.empty()) {
+ this->IsMissingFiles = true;
+ }
+ }
+ } else if (this->GlobalGenerator->TargetsWindowsStore()) {
+ if (manifestSources.empty()) {
+ if (v == "8.0") {
+ this->IsMissingFiles = true;
+ } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) {
+ this->IsMissingFiles = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteMissingFiles()
+{
+ std::string const& v = this->GlobalGenerator->GetSystemVersion();
+ if (this->GlobalGenerator->TargetsWindowsPhone()) {
+ if (v == "8.0") {
+ this->WriteMissingFilesWP80();
+ } else if (v == "8.1") {
+ this->WriteMissingFilesWP81();
+ }
+ } else if (this->GlobalGenerator->TargetsWindowsStore()) {
+ if (v == "8.0") {
+ this->WriteMissingFilesWS80();
+ } else if (v == "8.1") {
+ this->WriteMissingFilesWS81();
+ } else if (cmHasLiteralPrefix(v, "10.0")) {
+ this->WriteMissingFilesWS10_0();
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
+{
+ std::string templateFolder =
+ cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
+
+ // For WP80, the manifest needs to be in the same folder as the project
+ // this can cause an overwrite problem if projects aren't organized in
+ // folders
+ std::string manifestFile =
+ this->LocalGenerator->GetCurrentBinaryDirectory() +
+ std::string("/WMAppManifest.xml");
+ std::string artifactDir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ this->ConvertToWindowsSlash(artifactDir);
+ std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
+ std::string targetNameXML =
+ cmVS10EscapeXML(this->GeneratorTarget->GetName());
+
+ cmGeneratedFileStream fout(manifestFile.c_str());
+ fout.SetCopyIfDifferent(true);
+
+ /* clang-format off */
+ fout <<
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<Deployment"
+ " xmlns=\"http://schemas.microsoft.com/windowsphone/2012/deployment\""
+ " AppPlatformVersion=\"8.0\">\n"
+ "\t<DefaultLanguage xmlns=\"\" code=\"en-US\"/>\n"
+ "\t<App xmlns=\"\" ProductID=\"{" << this->GUID << "}\""
+ " Title=\"CMake Test Program\" RuntimeType=\"Modern Native\""
+ " Version=\"1.0.0.0\" Genre=\"apps.normal\" Author=\"CMake\""
+ " Description=\"Default CMake App\" Publisher=\"CMake\""
+ " PublisherID=\"{" << this->GUID << "}\">\n"
+ "\t\t<IconPath IsRelative=\"true\" IsResource=\"false\">"
+ << artifactDirXML << "\\ApplicationIcon.png</IconPath>\n"
+ "\t\t<Capabilities/>\n"
+ "\t\t<Tasks>\n"
+ "\t\t\t<DefaultTask Name=\"_default\""
+ " ImagePath=\"" << targetNameXML << ".exe\" ImageParams=\"\" />\n"
+ "\t\t</Tasks>\n"
+ "\t\t<Tokens>\n"
+ "\t\t\t<PrimaryToken TokenID=\"" << targetNameXML << "Token\""
+ " TaskName=\"_default\">\n"
+ "\t\t\t\t<TemplateFlip>\n"
+ "\t\t\t\t\t<SmallImageURI IsRelative=\"true\" IsResource=\"false\">"
+ << artifactDirXML << "\\SmallLogo.png</SmallImageURI>\n"
+ "\t\t\t\t\t<Count>0</Count>\n"
+ "\t\t\t\t\t<BackgroundImageURI IsRelative=\"true\" IsResource=\"false\">"
+ << artifactDirXML << "\\Logo.png</BackgroundImageURI>\n"
+ "\t\t\t\t</TemplateFlip>\n"
+ "\t\t\t</PrimaryToken>\n"
+ "\t\t</Tokens>\n"
+ "\t\t<ScreenResolutions>\n"
+ "\t\t\t<ScreenResolution Name=\"ID_RESOLUTION_WVGA\" />\n"
+ "\t\t</ScreenResolutions>\n"
+ "\t</App>\n"
+ "</Deployment>\n";
+ /* 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);
+ 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";
+ 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";
+ 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";
+ this->AddedFiles.push_back(applicationIcon);
+}
+
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81()
+{
+ std::string manifestFile =
+ this->DefaultArtifactDir + "/package.appxManifest";
+ std::string artifactDir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ this->ConvertToWindowsSlash(artifactDir);
+ std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
+ std::string targetNameXML =
+ cmVS10EscapeXML(this->GeneratorTarget->GetName());
+
+ cmGeneratedFileStream fout(manifestFile.c_str());
+ fout.SetCopyIfDifferent(true);
+
+ /* clang-format off */
+ fout <<
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
+ " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\""
+ " xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\">\n"
+ "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
+ " Version=\"1.0.0.0\" />\n"
+ "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID << "\""
+ " PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
+ "\t<Properties>\n"
+ "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
+ "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
+ "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
+ "\t</Properties>\n"
+ "\t<Prerequisites>\n"
+ "\t\t<OSMinVersion>6.3.1</OSMinVersion>\n"
+ "\t\t<OSMaxVersionTested>6.3.1</OSMaxVersionTested>\n"
+ "\t</Prerequisites>\n"
+ "\t<Resources>\n"
+ "\t\t<Resource Language=\"x-generate\" />\n"
+ "\t</Resources>\n"
+ "\t<Applications>\n"
+ "\t\t<Application Id=\"App\""
+ " Executable=\"" << targetNameXML << ".exe\""
+ " EntryPoint=\"" << targetNameXML << ".App\">\n"
+ "\t\t\t<m2:VisualElements\n"
+ "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
+ "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
+ "\t\t\t\tBackgroundColor=\"#336699\"\n"
+ "\t\t\t\tForegroundText=\"light\"\n"
+ "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
+ "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
+ "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
+ "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
+ "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
+ "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
+ "\t\t\t\t</m2:DefaultTile>\n"
+ "\t\t\t\t<m2:SplashScreen"
+ " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
+ "\t\t\t</m2:VisualElements>\n"
+ "\t\t</Application>\n"
+ "\t</Applications>\n"
+ "</Package>\n";
+ /* clang-format on */
+
+ this->WriteCommonMissingFiles(manifestFile);
+}
+
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80()
+{
+ std::string manifestFile =
+ this->DefaultArtifactDir + "/package.appxManifest";
+ std::string artifactDir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ this->ConvertToWindowsSlash(artifactDir);
+ std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
+ std::string targetNameXML =
+ cmVS10EscapeXML(this->GeneratorTarget->GetName());
+
+ cmGeneratedFileStream fout(manifestFile.c_str());
+ fout.SetCopyIfDifferent(true);
+
+ /* clang-format off */
+ fout <<
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\">\n"
+ "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
+ " Version=\"1.0.0.0\" />\n"
+ "\t<Properties>\n"
+ "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
+ "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
+ "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
+ "\t</Properties>\n"
+ "\t<Prerequisites>\n"
+ "\t\t<OSMinVersion>6.2.1</OSMinVersion>\n"
+ "\t\t<OSMaxVersionTested>6.2.1</OSMaxVersionTested>\n"
+ "\t</Prerequisites>\n"
+ "\t<Resources>\n"
+ "\t\t<Resource Language=\"x-generate\" />\n"
+ "\t</Resources>\n"
+ "\t<Applications>\n"
+ "\t\t<Application Id=\"App\""
+ " Executable=\"" << targetNameXML << ".exe\""
+ " EntryPoint=\"" << targetNameXML << ".App\">\n"
+ "\t\t\t<VisualElements"
+ " DisplayName=\"" << targetNameXML << "\""
+ " Description=\"" << targetNameXML << "\""
+ " BackgroundColor=\"#336699\" ForegroundText=\"light\""
+ " Logo=\"" << artifactDirXML << "\\Logo.png\""
+ " SmallLogo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
+ "\t\t\t\t<DefaultTile ShowName=\"allLogos\""
+ " ShortName=\"" << targetNameXML << "\" />\n"
+ "\t\t\t\t<SplashScreen"
+ " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
+ "\t\t\t</VisualElements>\n"
+ "\t\t</Application>\n"
+ "\t</Applications>\n"
+ "</Package>\n";
+ /* clang-format on */
+
+ this->WriteCommonMissingFiles(manifestFile);
+}
+
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81()
+{
+ std::string manifestFile =
+ this->DefaultArtifactDir + "/package.appxManifest";
+ std::string artifactDir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ this->ConvertToWindowsSlash(artifactDir);
+ std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
+ std::string targetNameXML =
+ cmVS10EscapeXML(this->GeneratorTarget->GetName());
+
+ cmGeneratedFileStream fout(manifestFile.c_str());
+ fout.SetCopyIfDifferent(true);
+
+ /* clang-format off */
+ fout <<
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
+ " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\">\n"
+ "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
+ " Version=\"1.0.0.0\" />\n"
+ "\t<Properties>\n"
+ "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
+ "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
+ "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
+ "\t</Properties>\n"
+ "\t<Prerequisites>\n"
+ "\t\t<OSMinVersion>6.3</OSMinVersion>\n"
+ "\t\t<OSMaxVersionTested>6.3</OSMaxVersionTested>\n"
+ "\t</Prerequisites>\n"
+ "\t<Resources>\n"
+ "\t\t<Resource Language=\"x-generate\" />\n"
+ "\t</Resources>\n"
+ "\t<Applications>\n"
+ "\t\t<Application Id=\"App\""
+ " Executable=\"" << targetNameXML << ".exe\""
+ " EntryPoint=\"" << targetNameXML << ".App\">\n"
+ "\t\t\t<m2:VisualElements\n"
+ "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
+ "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
+ "\t\t\t\tBackgroundColor=\"#336699\"\n"
+ "\t\t\t\tForegroundText=\"light\"\n"
+ "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
+ "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
+ "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
+ "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
+ "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
+ "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
+ "\t\t\t\t</m2:DefaultTile>\n"
+ "\t\t\t\t<m2:SplashScreen"
+ " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
+ "\t\t\t</m2:VisualElements>\n"
+ "\t\t</Application>\n"
+ "\t</Applications>\n"
+ "</Package>\n";
+ /* clang-format on */
+
+ this->WriteCommonMissingFiles(manifestFile);
+}
+
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0()
+{
+ std::string manifestFile =
+ this->DefaultArtifactDir + "/package.appxManifest";
+ std::string artifactDir =
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ this->ConvertToWindowsSlash(artifactDir);
+ std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
+ std::string targetNameXML =
+ cmVS10EscapeXML(this->GeneratorTarget->GetName());
+
+ cmGeneratedFileStream fout(manifestFile.c_str());
+ fout.SetCopyIfDifferent(true);
+
+ /* clang-format off */
+ fout <<
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<Package\n\t"
+ "xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\""
+ "\txmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\n"
+ "\txmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\""
+ "\n\tIgnorableNamespaces=\"uap mp\">\n\n"
+ "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
+ " Version=\"1.0.0.0\" />\n"
+ "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID <<
+ "\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
+ "\t<Properties>\n"
+ "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
+ "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
+ "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
+ "\t</Properties>\n"
+ "\t<Dependencies>\n"
+ "\t\t<TargetDeviceFamily Name=\"Windows.Universal\" "
+ "MinVersion=\"10.0.0.0\" MaxVersionTested=\"10.0.0.0\" />\n"
+ "\t</Dependencies>\n"
+
+ "\t<Resources>\n"
+ "\t\t<Resource Language=\"x-generate\" />\n"
+ "\t</Resources>\n"
+ "\t<Applications>\n"
+ "\t\t<Application Id=\"App\""
+ " Executable=\"" << targetNameXML << ".exe\""
+ " EntryPoint=\"" << targetNameXML << ".App\">\n"
+ "\t\t\t<uap:VisualElements\n"
+ "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
+ "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
+ "\t\t\t\tBackgroundColor=\"#336699\"\n"
+ "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
+ "\t\t\t\tSquare44x44Logo=\"" << artifactDirXML <<
+ "\\SmallLogo44x44.png\">\n"
+ "\t\t\t\t<uap:SplashScreen"
+ " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
+ "\t\t\t</uap:VisualElements>\n"
+ "\t\t</Application>\n"
+ "\t</Applications>\n"
+ "</Package>\n";
+ /* clang-format on */
+
+ this->WriteCommonMissingFiles(manifestFile);
+}
+
+void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
+ 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);
+ 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";
+ 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";
+ 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";
+ 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";
+ 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";
+ 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";
+}
+
+bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
+{
+ HANDLE h =
+ CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(source).c_str(),
+ FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, 0);
+ if (!h) {
+ return false;
+ }
+
+ FILETIME const ftime_20010101 = { 3365781504u, 29389701u };
+ if (!SetFileTime(h, &ftime_20010101, &ftime_20010101, &ftime_20010101)) {
+ CloseHandle(h);
+ return false;
+ }
+
+ CloseHandle(h);
+ return true;
+}
+
+std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
+ const char* relativeFilePath) const
{
- std::set<std::string>::iterator it =
- this->GeneratorTarget->ExpectedResxHeaders.find(headerFile);
+ // Always search in the standard modules location.
+ std::string path = cmSystemTools::GetCMakeRoot() + "/";
+ path += relativeFilePath;
+ this->ConvertToWindowsSlash(path);
- return it != this->GeneratorTarget->ExpectedResxHeaders.end();
+ return path;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 9a480a87f..61066158c 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -1,119 +1,199 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVisualStudioTargetGenerator_h
#define cmVisualStudioTargetGenerator_h
-#include "cmStandardIncludes.h"
-class cmTarget;
-class cmMakefile;
-class cmGeneratorTarget;
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmComputeLinkInformation;
+class cmCustomCommand;
class cmGeneratedFileStream;
+class cmGeneratorTarget;
class cmGlobalVisualStudio10Generator;
-class cmSourceFile;
-class cmCustomCommand;
class cmLocalVisualStudio7Generator;
-class cmComputeLinkInformation;
+class cmMakefile;
+class cmSourceFile;
+class cmSourceGroup;
class cmVisualStudioGeneratorOptions;
-#include "cmSourceGroup.h"
class cmVisualStudio10TargetGenerator
{
public:
- cmVisualStudio10TargetGenerator(cmTarget* target,
+ cmVisualStudio10TargetGenerator(cmGeneratorTarget* target,
cmGlobalVisualStudio10Generator* gg);
~cmVisualStudio10TargetGenerator();
void Generate();
// used by cmVisualStudioGeneratorOptions
- void WritePlatformConfigTag(
- const char* tag,
- const char* config,
- int indentLevel,
- const char* attribute = 0,
- const char* end = 0,
- std::ostream* strm = 0
- );
+ 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
{
- cmSourceFile* SourceFile;
+ cmSourceFile const* SourceFile;
bool RelativePath;
};
- struct ToolSources: public std::vector<ToolSource> {};
+ struct ToolSources : public std::vector<ToolSource>
+ {
+ };
+
+ struct TargetsFileAndConfigs
+ {
+ std::string File;
+ std::vector<std::string> Configs;
+ };
std::string ConvertPath(std::string const& path, bool forceRelative);
- void ConvertToWindowsSlash(std::string& s);
+ static void ConvertToWindowsSlash(std::string& s);
void WriteString(const char* line, int indentLevel);
void WriteProjectConfigurations();
void WriteProjectConfigurationValues();
- void WriteSource(const char* tool, cmSourceFile* sf, const char* end = 0);
- void WriteSources(const char* tool, std::vector<cmSourceFile*> const&);
+ 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();
+ void VerifyNecessaryFiles();
+ void WriteMissingFiles();
+ void WriteMissingFilesWP80();
+ void WriteMissingFilesWP81();
+ void WriteMissingFilesWS80();
+ void WriteMissingFilesWS81();
+ void WriteMissingFilesWS10_0();
+ void WritePlatformExtensions();
+ void WriteSinglePlatformExtension(std::string const& extension,
+ std::string const& version);
+ void WriteSDKReferences();
+ void WriteSingleSDKReference(std::string const& extension,
+ std::string const& version);
+ void WriteCommonMissingFiles(const std::string& manifestFile);
+ void WriteTargetSpecificReferences();
+ void WriteTargetsFileReferences();
bool ComputeClOptions();
bool ComputeClOptions(std::string const& configName);
void WriteClOptions(std::string const& config,
- std::vector<std::string> const & includes);
+ std::vector<std::string> const& includes);
+ bool ComputeRcOptions();
+ bool ComputeRcOptions(std::string const& config);
void WriteRCOptions(std::string const& config,
- std::vector<std::string> const & includes);
+ std::vector<std::string> const& includes);
+ bool ComputeCudaOptions();
+ bool ComputeCudaOptions(std::string const& config);
+ void WriteCudaOptions(std::string const& config,
+ std::vector<std::string> const& includes);
+
+ bool ComputeCudaLinkOptions();
+ bool ComputeCudaLinkOptions(std::string const& config);
+ void WriteCudaLinkOptions(std::string const& config);
+
+ bool ComputeMasmOptions();
+ bool ComputeMasmOptions(std::string const& config);
+ void WriteMasmOptions(std::string const& config,
+ std::vector<std::string> const& includes);
+ bool ComputeNasmOptions();
+ bool ComputeNasmOptions(std::string const& config);
+ void WriteNasmOptions(std::string const& config,
+ std::vector<std::string> includes);
+
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 OutputIncludes(std::vector<std::string> const & includes);
+ std::vector<std::string> const& includes);
+ void WriteAntBuildOptions(std::string const& config);
void OutputLinkIncremental(std::string const& configName);
- void WriteCustomRule(cmSourceFile* source,
- cmCustomCommand const & command);
+ void WriteCustomRule(cmSourceFile const* source,
+ cmCustomCommand const& command);
void WriteCustomCommands();
- void WriteCustomCommand(cmSourceFile* sf);
+ void WriteCustomCommand(cmSourceFile const* sf);
void WriteGroups();
void WriteProjectReferences();
- bool OutputSourceSpecificFlags(cmSourceFile* source);
- void AddLibraries(cmComputeLinkInformation& cli, std::string& libstring);
+ void WriteApplicationTypeSettings();
+ bool OutputSourceSpecificFlags(cmSourceFile const* source);
+ void AddLibraries(cmComputeLinkInformation& cli,
+ std::vector<std::string>& libVec,
+ std::vector<std::string>& vsTargetVec);
+ 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, std::vector<cmCustomCommand> & commands,
+ void WriteEvent(const char* name,
+ std::vector<cmCustomCommand> const& commands,
std::string const& configName);
void WriteGroupSources(const char* name, ToolSources const& sources,
- std::vector<cmSourceGroup>& );
+ std::vector<cmSourceGroup>&);
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
bool IsResxHeader(const std::string& headerFile);
+ bool IsXamlHeader(const std::string& headerFile);
+ bool IsXamlSource(const std::string& headerFile);
+
+ bool ForceOld(const std::string& source) const;
private:
typedef cmVisualStudioGeneratorOptions Options;
- typedef std::map<cmStdString, Options*> OptionsMap;
+ typedef std::map<std::string, Options*> OptionsMap;
OptionsMap ClOptions;
+ OptionsMap RcOptions;
+ OptionsMap CudaOptions;
+ OptionsMap CudaLinkOptions;
+ OptionsMap MasmOptions;
+ OptionsMap NasmOptions;
OptionsMap LinkOptions;
- std::string PathToVcxproj;
- cmTarget* Target;
+ std::string PathToProjectFile;
+ std::string ProjectFileExtension;
+ enum VsProjectType
+ {
+ vcxproj,
+ csproj
+ } ProjectType;
+ bool InSourceBuild;
+ std::vector<std::string> Configurations;
+ std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
cmGeneratorTarget* GeneratorTarget;
cmMakefile* Makefile;
std::string Platform;
std::string GUID;
std::string Name;
+ bool MSTools;
+ bool Managed;
+ bool NsightTegra;
+ int NsightTegraVersion[4];
+ bool TargetCompileAsWinRT;
cmGlobalVisualStudio10Generator* GlobalGenerator;
cmGeneratedFileStream* BuildFileStream;
cmLocalVisualStudio7Generator* LocalGenerator;
- std::set<cmSourceFile*> SourcesVisited;
+ std::set<cmSourceFile const*> SourcesVisited;
+ bool IsMissingFiles;
+ std::vector<std::string> AddedFiles;
+ std::string DefaultArtifactDir;
- typedef std::map<cmStdString, ToolSources> ToolSourceMap;
+ typedef std::map<std::string, ToolSources> ToolSourceMap;
ToolSourceMap Tools;
+ std::string GetCMakeFilePath(const char* name) const;
};
#endif
diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx
new file mode 100644
index 000000000..9a1d95078
--- /dev/null
+++ b/Source/cmVisualStudio10ToolsetOptions.cxx
@@ -0,0 +1,162 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmVisualStudio10ToolsetOptions.h"
+
+#include "cmAlgorithms.h"
+#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 const& name, std::string const& toolset) const
+{
+ std::string const useToolset = this->GetToolsetName(name, toolset);
+
+ if (toolset == "v141") {
+ return cmVS141CLFlagTable;
+ } else if (useToolset == "v140") {
+ return cmVS140CLFlagTable;
+ } else if (useToolset == "v120") {
+ return cmVS12CLFlagTable;
+ } else if (useToolset == "v110") {
+ return cmVS11CLFlagTable;
+ } else if (useToolset == "v100") {
+ return cmVS10CLFlagTable;
+ } else {
+ return 0;
+ }
+}
+
+cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetCSharpFlagTable(
+ std::string const& name, std::string const& toolset) const
+{
+ std::string const useToolset = this->GetToolsetName(name, toolset);
+
+ if ((useToolset == "v141")) {
+ return cmVS141CSharpFlagTable;
+ } else if (useToolset == "v140") {
+ return cmVS140CSharpFlagTable;
+ } else if (useToolset == "v120") {
+ return cmVS12CSharpFlagTable;
+ } else if (useToolset == "v110") {
+ return cmVS11CSharpFlagTable;
+ } else if (useToolset == "v100") {
+ return cmVS10CSharpFlagTable;
+ } else {
+ return 0;
+ }
+}
+
+cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetRcFlagTable(
+ std::string const& name, std::string const& toolset) const
+{
+ std::string const useToolset = this->GetToolsetName(name, toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141")) {
+ return cmVS14RCFlagTable;
+ } else if (useToolset == "v120") {
+ return cmVS12RCFlagTable;
+ } else if (useToolset == "v110") {
+ return cmVS11RCFlagTable;
+ } else if (useToolset == "v100") {
+ return cmVS10RCFlagTable;
+ } else {
+ return 0;
+ }
+}
+
+cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLibFlagTable(
+ std::string const& name, std::string const& toolset) const
+{
+ std::string const useToolset = this->GetToolsetName(name, toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141")) {
+ return cmVS14LibFlagTable;
+ } else if (useToolset == "v120") {
+ return cmVS12LibFlagTable;
+ } else if (useToolset == "v110") {
+ return cmVS11LibFlagTable;
+ } else if (useToolset == "v100") {
+ return cmVS10LibFlagTable;
+ } else {
+ return 0;
+ }
+}
+
+cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLinkFlagTable(
+ std::string const& name, std::string const& toolset) const
+{
+ std::string const useToolset = this->GetToolsetName(name, toolset);
+
+ if (useToolset == "v141") {
+ return cmVS141LinkFlagTable;
+ } else if (useToolset == "v140") {
+ return cmVS140LinkFlagTable;
+ } else if (useToolset == "v120") {
+ return cmVS12LinkFlagTable;
+ } else if (useToolset == "v110") {
+ return cmVS11LinkFlagTable;
+ } else if (useToolset == "v100") {
+ return cmVS10LinkFlagTable;
+ } else {
+ return 0;
+ }
+}
+
+cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetMasmFlagTable(
+ std::string const& name, std::string const& toolset) const
+{
+ std::string const useToolset = this->GetToolsetName(name, toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141")) {
+ return cmVS14MASMFlagTable;
+ } else if (useToolset == "v120") {
+ return cmVS12MASMFlagTable;
+ } else if (useToolset == "v110") {
+ return cmVS11MASMFlagTable;
+ } else if (useToolset == "v100") {
+ return cmVS10MASMFlagTable;
+ } else {
+ return 0;
+ }
+}
+
+std::string cmVisualStudio10ToolsetOptions::GetToolsetName(
+ std::string const& name, std::string const& toolset) const
+{
+ static_cast<void>(name);
+ std::size_t length = toolset.length();
+
+ if (cmHasLiteralSuffix(toolset, "_xp")) {
+ length -= 3;
+ }
+
+ return toolset.substr(0, length);
+}
diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h
new file mode 100644
index 000000000..4233337ba
--- /dev/null
+++ b/Source/cmVisualStudio10ToolsetOptions.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 cmVisualStudio10ToolsetOptions_h
+#define cmVisualStudio10ToolsetOptions_h
+
+#include "cmConfigure.h"
+
+#include <string>
+
+struct cmIDEFlagTable;
+
+/** \class cmVisualStudio10ToolsetOptions
+ * \brief Retrieves toolset options for MSBuild.
+ *
+ * cmVisualStudio10ToolsetOptions manages toolsets within MSBuild
+ */
+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 GetToolsetName(std::string const& name,
+ std::string const& toolset) const;
+};
+#endif
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 6aca787f5..1f808c8b2 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -1,11 +1,14 @@
#include "cmVisualStudioGeneratorOptions.h"
+
+#include "cmAlgorithms.h"
+#include "cmLocalVisualStudioGenerator.h"
+#include "cmOutputConverter.h"
#include "cmSystemTools.h"
-#include <cmsys/System.h>
#include "cmVisualStudio10TargetGenerator.h"
-inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s)
+static std::string cmVisualStudio10GeneratorOptionsEscapeForXML(
+ std::string ret)
{
- std::string ret = s;
cmSystemTools::ReplaceString(ret, ";", "%3B");
cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "<", "&lt;");
@@ -13,9 +16,8 @@ inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s)
return ret;
}
-inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s)
+static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
{
- std::string ret = s;
cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "\"", "&quot;");
cmSystemTools::ReplaceString(ret, "<", "&lt;");
@@ -24,21 +26,40 @@ inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s)
return ret;
}
-//----------------------------------------------------------------------------
-cmVisualStudioGeneratorOptions
-::cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg,
- Tool tool,
- cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable,
- cmVisualStudio10TargetGenerator* g):
- cmIDEOptions(),
- LocalGenerator(lg), Version(lg->GetVersion()), CurrentTool(tool),
- TargetGenerator(g)
+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)
+ : cmIDEOptions()
+ , LocalGenerator(lg)
+ , Version(lg->GetVersion())
+ , CurrentTool(tool)
+ , TargetGenerator(g)
{
// Store the given flag tables.
- cmIDEFlagTable const** ft = this->FlagTable;
- if(table) { *ft++ = table; }
- if(extraTable) { *ft++ = extraTable; }
+ this->AddTable(table);
+ this->AddTable(extraTable);
// Preprocessor definitions are not allowed for linker tools.
this->AllowDefine = (tool != Linker);
@@ -49,9 +70,29 @@ cmVisualStudioGeneratorOptions
this->FortranRuntimeDebug = false;
this->FortranRuntimeDLL = false;
this->FortranRuntimeMT = false;
+
+ this->UnknownFlagField = "AdditionalOptions";
+}
+
+void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
+{
+ if (table) {
+ for (int i = 0; i < FlagTableCount; ++i) {
+ if (!this->FlagTable[i]) {
+ this->FlagTable[i] = table;
+ break;
+ }
+ }
+ }
+}
+
+void cmVisualStudioGeneratorOptions::ClearTables()
+{
+ for (int i = 0; i < FlagTableCount; ++i) {
+ this->FlagTable[i] = CM_NULLPTR;
+ }
}
-//----------------------------------------------------------------------------
void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
{
// Exception handling is on by default because the platform file has
@@ -59,15 +100,12 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
// initialization to off, but the user has the option of removing
// the flag to disable exception handling. When the user does
// remove the flag we need to override the IDE default of on.
- switch (this->Version)
- {
- case cmLocalVisualStudioGenerator::VS7:
- case cmLocalVisualStudioGenerator::VS71:
- this->FlagMap["ExceptionHandling"] = "FALSE";
- break;
- case cmLocalVisualStudioGenerator::VS10:
- case cmLocalVisualStudioGenerator::VS11:
- case cmLocalVisualStudioGenerator::VS12:
+ switch (this->Version) {
+ case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VS15:
// 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
@@ -76,11 +114,10 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
break;
default:
this->FlagMap["ExceptionHandling"] = "0";
- break;
- }
+ break;
+ }
}
-//----------------------------------------------------------------------------
void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
{
// If verbose makefiles have been requested and the /nologo option
@@ -92,49 +129,133 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
// an empty string, instead of "FALSE", in order to avoid a warning:
// "cl ... warning D9035: option 'nologo-' has been deprecated"
//
- if(verbose &&
- this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end())
- {
+ if (verbose &&
+ this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end()) {
this->FlagMap["SuppressStartupBanner"] =
- this->Version < cmLocalVisualStudioGenerator::VS10 ? "FALSE" : "";
- }
+ this->Version < cmGlobalVisualStudioGenerator::VS10 ? "FALSE" : "";
+ }
}
bool cmVisualStudioGeneratorOptions::IsDebug() const
{
- return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end();
+ if (this->CurrentTool != CSharpCompiler) {
+ return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end();
+ }
+ std::map<std::string, FlagValue>::const_iterator i =
+ this->FlagMap.find("DebugType");
+ if (i != this->FlagMap.end()) {
+ if (i->second.size() == 1) {
+ return i->second[0] != "none";
+ }
+ }
+ return false;
+}
+
+bool cmVisualStudioGeneratorOptions::IsWinRt() const
+{
+ return this->FlagMap.find("CompileAsWinRT") != this->FlagMap.end();
+}
+
+bool cmVisualStudioGeneratorOptions::IsManaged() const
+{
+ return this->FlagMap.find("CompileAsManaged") != this->FlagMap.end();
}
-//----------------------------------------------------------------------------
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")
- {
+ for (std::vector<std::string>::const_iterator di = this->Defines.begin();
+ di != this->Defines.end(); ++di) {
+ if (*di == "_UNICODE") {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
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")
- {
+ for (std::vector<std::string>::const_iterator di = this->Defines.begin();
+ di != this->Defines.end(); ++di) {
+ if (*di == "_SBCS") {
return true;
- }
}
+ }
return false;
}
-//----------------------------------------------------------------------------
+cmVisualStudioGeneratorOptions::CudaRuntime
+cmVisualStudioGeneratorOptions::GetCudaRuntime() const
+{
+ std::map<std::string, FlagValue>::const_iterator i =
+ this->FlagMap.find("CudaRuntime");
+ if (i != this->FlagMap.end() && i->second.size() == 1) {
+ std::string const& cudaRuntime = i->second[0];
+ if (cudaRuntime == "Static") {
+ return CudaRuntimeStatic;
+ }
+ if (cudaRuntime == "Shared") {
+ return CudaRuntimeShared;
+ }
+ if (cudaRuntime == "None") {
+ return CudaRuntimeNone;
+ }
+ }
+ // nvcc default is static
+ return CudaRuntimeStatic;
+}
+
+void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
+{
+ // Extract temporary values stored by our flag table.
+ FlagValue arch = this->TakeFlag("cmake-temp-arch");
+ FlagValue code = this->TakeFlag("cmake-temp-code");
+ FlagValue gencode = this->TakeFlag("cmake-temp-gencode");
+
+ // No -code allowed without -arch.
+ if (arch.empty()) {
+ code.clear();
+ }
+
+ if (arch.empty() && gencode.empty()) {
+ return;
+ }
+
+ // Create a CodeGeneration field with [arch],[code] syntax in each entry.
+ // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
+ FlagValue& result = this->FlagMap["CodeGeneration"];
+
+ // First entries for the -arch=<arch> [-code=<code>,...] pair.
+ if (!arch.empty()) {
+ std::string arch_name = arch[0];
+ std::vector<std::string> codes;
+ if (!code.empty()) {
+ codes = cmSystemTools::tokenize(code[0], ",");
+ }
+ if (codes.empty()) {
+ codes.push_back(arch_name);
+ // nvcc -arch=<arch> has a special case that allows a real
+ // architecture to be specified instead of a virtual arch.
+ // 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;
+ 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;
+ cmSystemTools::ReplaceString(entry, "arch=", "");
+ cmSystemTools::ReplaceString(entry, "code=", "");
+ result.push_back(entry);
+ }
+}
+
void cmVisualStudioGeneratorOptions::Parse(const char* flags)
{
// Parse the input string as a windows command line since the string
@@ -144,18 +265,15 @@ void cmVisualStudioGeneratorOptions::Parse(const char* flags)
// 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)
- {
+ for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end();
+ ++ai) {
this->HandleFlag(ai->c_str());
- }
+ }
}
-//----------------------------------------------------------------------------
void cmVisualStudioGeneratorOptions::ParseFinish()
{
- if(this->CurrentTool == FortranCompiler)
- {
+ if (this->CurrentTool == FortranCompiler) {
// "RuntimeLibrary" attribute values:
// "rtMultiThreaded", "0", /threads /libs:static
// "rtMultiThreadedDLL", "2", /threads /libs:dll
@@ -167,206 +285,185 @@ void cmVisualStudioGeneratorOptions::ParseFinish()
// "rtSingleThreadedDebug", "5", /dbglibs /libs:static
// "rtSingleThreadedDebugDLL", "11", /dbglibs /libs:dll
std::string rl = "rtMultiThreaded";
- rl += this->FortranRuntimeDebug? "Debug" : "";
- rl += this->FortranRuntimeDLL? "DLL" : "";
+ rl += this->FortranRuntimeDebug ? "Debug" : "";
+ rl += this->FortranRuntimeDLL ? "DLL" : "";
this->FlagMap["RuntimeLibrary"] = rl;
+ }
+
+ if (this->CurrentTool == CudaCompiler) {
+ std::map<std::string, FlagValue>::iterator i =
+ this->FlagMap.find("CudaRuntime");
+ if (i != this->FlagMap.end() && i->second.size() == 1) {
+ std::string& cudaRuntime = i->second[0];
+ if (cudaRuntime == "static") {
+ cudaRuntime = "Static";
+ } else if (cudaRuntime == "shared") {
+ cudaRuntime = "Shared";
+ } else if (cudaRuntime == "none") {
+ cudaRuntime = "None";
+ }
}
+ }
+}
+
+void cmVisualStudioGeneratorOptions::PrependInheritedString(
+ std::string const& key)
+{
+ std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+ if (i == this->FlagMap.end() || i->second.size() != 1) {
+ return;
+ }
+ std::string& value = i->second[0];
+ value = "%(" + key + ") " + value;
+}
+
+void cmVisualStudioGeneratorOptions::Reparse(std::string const& key)
+{
+ std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+ if (i == this->FlagMap.end() || i->second.size() != 1) {
+ return;
+ }
+ std::string const original = i->second[0];
+ i->second[0] = "";
+ this->UnknownFlagField = key;
+ this->Parse(original.c_str());
}
-//----------------------------------------------------------------------------
void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* 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 (this->CurrentTool == FortranCompiler) {
+ if (strcmp(flag, "/dbglibs") == 0) {
this->FortranRuntimeDebug = true;
return;
- }
- if(strcmp(flag, "/threads") == 0)
- {
+ }
+ if (strcmp(flag, "/threads") == 0) {
this->FortranRuntimeMT = true;
return;
- }
- if(strcmp(flag, "/libs:dll") == 0)
- {
+ }
+ if (strcmp(flag, "/libs:dll") == 0) {
this->FortranRuntimeDLL = true;
return;
- }
- if(strcmp(flag, "/libs:static") == 0)
- {
+ }
+ if (strcmp(flag, "/libs:static") == 0) {
this->FortranRuntimeDLL = false;
return;
- }
}
+ }
// This option is not known. Store it in the output flags.
- this->FlagString += " ";
- this->FlagString +=
- cmSystemTools::EscapeWindowsShellArgument(
- flag,
- cmsysSystem_Shell_Flag_AllowMakeVariables |
- cmsysSystem_Shell_Flag_VSIDE);
+ std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
+ flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
+ cmOutputConverter::Shell_Flag_VSIDE);
+ this->AppendFlagString(this->UnknownFlagField, opts);
+}
+
+cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
+ std::string const& key)
+{
+ FlagValue value;
+ std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+ if (i != this->FlagMap.end()) {
+ value = i->second;
+ this->FlagMap.erase(i);
+ }
+ return value;
}
-//----------------------------------------------------------------------------
void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
{
this->Configuration = config;
}
-//----------------------------------------------------------------------------
-void
-cmVisualStudioGeneratorOptions
-::OutputPreprocessorDefinitions(std::ostream& fout,
- const char* prefix,
- const char* suffix,
- const char* lang)
+void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
+ std::ostream& fout, const char* prefix, const char* suffix,
+ const std::string& lang)
{
- if(this->Defines.empty())
- {
+ if (this->Defines.empty()) {
return;
- }
- if(this->Version >= cmLocalVisualStudioGenerator::VS10)
- {
+ }
+ const char* tag = "PreprocessorDefinitions";
+ 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.size())
- {
+ if (!this->Configuration.empty()) {
fout << prefix;
this->TargetGenerator->WritePlatformConfigTag(
- "PreprocessorDefinitions",
- this->Configuration.c_str(),
- 0,
- 0, 0, &fout);
- }
- else
- {
- fout << prefix << "<PreprocessorDefinitions>";
- }
- }
- else
- {
- fout << prefix << "PreprocessorDefinitions=\"";
+ tag, this->Configuration.c_str(), 0, 0, 0, &fout);
+ } else {
+ fout << prefix << "<" << tag << ">";
}
+ } else {
+ fout << prefix << tag << "=\"";
+ }
const char* sep = "";
- for(std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di)
- {
+ std::vector<std::string>::const_iterator de =
+ cmRemoveDuplicates(this->Defines);
+ for (std::vector<std::string>::const_iterator di = this->Defines.begin();
+ di != de; ++di) {
// Escape the definition for the compiler.
std::string define;
- if(this->Version < cmLocalVisualStudioGenerator::VS10)
- {
- define =
- this->LocalGenerator->EscapeForShell(di->c_str(), true);
- }
- else
- {
+ if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
+ define = this->LocalGenerator->EscapeForShell(di->c_str(), true);
+ } else {
define = *di;
- }
+ }
// Escape this flag for the IDE.
- if(this->Version >= cmLocalVisualStudioGenerator::VS10)
- {
- define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str());
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ define = cmVisualStudio10GeneratorOptionsEscapeForXML(define);
- if(0 == strcmp(lang, "RC"))
- {
+ if (lang == "RC") {
cmSystemTools::ReplaceString(define, "\"", "\\\"");
- }
- }
- else
- {
- define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str());
}
+ } else {
+ define = cmVisualStudioGeneratorOptionsEscapeForXML(define);
+ }
// Store the flag in the project file.
fout << sep << define;
sep = ";";
- }
- if(this->Version >= cmLocalVisualStudioGenerator::VS10)
- {
- fout << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix;
- }
- else
- {
+ }
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ fout << ";%(" << tag << ")</" << tag << ">" << suffix;
+ } else {
fout << "\"" << suffix;
- }
+ }
}
-//----------------------------------------------------------------------------
-void
-cmVisualStudioGeneratorOptions
-::OutputFlagMap(std::ostream& fout, const char* indent)
+void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
+ const char* indent)
{
- if(this->Version >= cmLocalVisualStudioGenerator::VS10)
- {
- for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m)
- {
+ 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.size())
- {
+ if (!this->Configuration.empty()) {
this->TargetGenerator->WritePlatformConfigTag(
- m->first.c_str(),
- this->Configuration.c_str(),
- 0,
- 0, 0, &fout);
- }
- else
- {
+ m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
+ } else {
fout << "<" << m->first << ">";
- }
- fout << m->second;
- if (m->first == "AdditionalIncludeDirectories")
- {
- fout << ";%(AdditionalIncludeDirectories)";
- }
- fout << "</" << m->first << ">\n";
}
- }
- else
- {
- for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m)
- {
- fout << indent << m->first << "=\"" << m->second << "\"\n";
+ 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";
}
-}
-
-//----------------------------------------------------------------------------
-void
-cmVisualStudioGeneratorOptions
-::OutputAdditionalOptions(std::ostream& fout,
- const char* prefix,
- const char* suffix)
-{
- if(!this->FlagString.empty())
- {
- if(this->Version >= cmLocalVisualStudioGenerator::VS10)
- {
- fout << prefix;
- if(this->Configuration.size())
- {
- this->TargetGenerator->WritePlatformConfigTag(
- "AdditionalOptions",
- this->Configuration.c_str(),
- 0,
- 0, 0, &fout);
- }
- else
- {
- fout << "<AdditionalOptions>";
- }
- fout << this->FlagString.c_str()
- << " %(AdditionalOptions)</AdditionalOptions>\n";
- }
- else
- {
- fout << prefix << "AdditionalOptions=\"";
- fout <<
- cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str());
- fout << "\"" << suffix;
+ } 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 = ";";
}
+ fout << "\"\n";
}
+ }
}
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 90f76672d..44d271908 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -1,45 +1,62 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVisualStudioGeneratorOptions_h
#define cmVisualStudioGeneratorOptions_h
-#include "cmLocalVisualStudioGenerator.h"
+#include "cmConfigure.h"
+
+#include <iosfwd>
+#include <string>
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmIDEFlagTable.h"
#include "cmIDEOptions.h"
+
+class cmLocalVisualStudioGenerator;
+
typedef cmIDEFlagTable cmVS7FlagTable;
class cmVisualStudio10TargetGenerator;
-//----------------------------------------------------------------------------
-class cmVisualStudioGeneratorOptions: public cmIDEOptions
+class cmVisualStudioGeneratorOptions : public cmIDEOptions
{
public:
// Construct an options table for a given tool.
enum Tool
{
Compiler,
+ ResourceCompiler,
+ CudaCompiler,
+ MasmCompiler,
+ NasmCompiler,
Linker,
- FortranCompiler
+ FortranCompiler,
+ CSharpCompiler
};
- cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg,
- Tool tool,
+ cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
cmVS7FlagTable const* table,
cmVS7FlagTable const* extraTable = 0,
cmVisualStudio10TargetGenerator* g = 0);
+ cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVisualStudio10TargetGenerator* g = 0);
+
+ // Add a table of flags.
+ void AddTable(cmVS7FlagTable const* table);
+
+ // Clear the flag tables.
+ void ClearTables();
+
// Store options from command line flags.
void Parse(const char* flags);
void ParseFinish();
+ void PrependInheritedString(std::string const& key);
+
+ // Parse the content of the given flag table entry again to extract
+ // known flags and leave the rest in the original entry.
+ void Reparse(std::string const& key);
+
// Fix the ExceptionHandling option to default to off.
void FixExceptionHandlingDefault();
@@ -50,20 +67,29 @@ public:
bool UsingUnicode() const;
bool UsingSBCS() const;
+ enum CudaRuntime
+ {
+ CudaRuntimeStatic,
+ CudaRuntimeShared,
+ CudaRuntimeNone
+ };
+ CudaRuntime GetCudaRuntime() const;
+
+ void FixCudaCodeGeneration();
+
bool IsDebug() const;
+ bool IsWinRt() const;
+ bool IsManaged() const;
// Write options to output.
- void OutputPreprocessorDefinitions(std::ostream& fout,
- const char* prefix,
+ void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
const char* suffix,
- const char* lang);
+ const std::string& lang);
void OutputFlagMap(std::ostream& fout, const char* indent);
- void OutputAdditionalOptions(std::ostream& fout,
- const char* prefix,
- const char* suffix);
void SetConfiguration(const char* config);
+
private:
cmLocalVisualStudioGenerator* LocalGenerator;
- cmLocalVisualStudioGenerator::VSVersion Version;
+ cmGlobalVisualStudioGenerator::VSVersion Version;
std::string Configuration;
Tool CurrentTool;
@@ -73,7 +99,11 @@ private:
bool FortranRuntimeDLL;
bool FortranRuntimeMT;
+ std::string UnknownFlagField;
+
virtual void StoreUnknownFlag(const char* flag);
+
+ FlagValue TakeFlag(std::string const& key);
};
#endif
diff --git a/Source/cmVisualStudioSlnData.cxx b/Source/cmVisualStudioSlnData.cxx
index 82b4ee84f..48112ddea 100644
--- a/Source/cmVisualStudioSlnData.cxx
+++ b/Source/cmVisualStudioSlnData.cxx
@@ -1,19 +1,9 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudioSlnData.h"
-//----------------------------------------------------------------------------
-const cmSlnProjectEntry*
-cmSlnData::GetProjectByGUID(const std::string& projectGUID) const
+const cmSlnProjectEntry* cmSlnData::GetProjectByGUID(
+ const std::string& projectGUID) const
{
ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID));
if (it != ProjectsByGUID.end())
@@ -22,9 +12,8 @@ cmSlnData::GetProjectByGUID(const std::string& projectGUID) const
return NULL;
}
-//----------------------------------------------------------------------------
-const cmSlnProjectEntry*
-cmSlnData::GetProjectByName(const std::string& projectName) const
+const cmSlnProjectEntry* cmSlnData::GetProjectByName(
+ const std::string& projectName) const
{
ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName));
if (it != ProjectNameIndex.end())
@@ -33,30 +22,28 @@ cmSlnData::GetProjectByName(const std::string& projectName) const
return NULL;
}
-//----------------------------------------------------------------------------
std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const
{
ProjectStringIndex::const_iterator it(this->ProjectNameIndex.begin()),
- itEnd(this->ProjectNameIndex.end());
+ itEnd(this->ProjectNameIndex.end());
std::vector<cmSlnProjectEntry> result;
for (; it != itEnd; ++it)
result.push_back(it->second->second);
return result;
}
-//----------------------------------------------------------------------------
cmSlnProjectEntry* cmSlnData::AddProject(
- const std::string& projectGUID,
- const std::string& projectName,
+ const std::string& projectGUID, const std::string& projectName,
const std::string& projectRelativePath)
{
ProjectStorage::iterator it(ProjectsByGUID.find(projectGUID));
if (it != ProjectsByGUID.end())
return NULL;
- it = ProjectsByGUID.insert(
- ProjectStorage::value_type(
- projectGUID,
- cmSlnProjectEntry(projectGUID, projectName, projectRelativePath))).first;
+ it = ProjectsByGUID
+ .insert(ProjectStorage::value_type(
+ projectGUID,
+ cmSlnProjectEntry(projectGUID, projectName, projectRelativePath)))
+ .first;
ProjectNameIndex[projectName] = it;
return &it->second;
}
diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h
index ec128cf11..e12047fb5 100644
--- a/Source/cmVisualStudioSlnData.h
+++ b/Source/cmVisualStudioSlnData.h
@@ -1,28 +1,25 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVisualStudioSlnData_h
#define cmVisualStudioSlnData_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
+
+#include <map>
+#include <string>
+#include <vector>
class cmSlnProjectEntry
{
public:
cmSlnProjectEntry() {}
- cmSlnProjectEntry(const std::string& guid,
- const std::string& name,
+ cmSlnProjectEntry(const std::string& guid, const std::string& name,
const std::string& relativePath)
- : Guid(guid), Name(name), RelativePath(relativePath)
- {}
+ : Guid(guid)
+ , Name(name)
+ , RelativePath(relativePath)
+ {
+ }
std::string GetGUID() const { return Guid; }
std::string GetName() const { return Name; }
@@ -32,15 +29,14 @@ private:
std::string Guid, Name, RelativePath;
};
-
class cmSlnData
{
public:
- const cmSlnProjectEntry*
- GetProjectByGUID(const std::string& projectGUID) const;
+ const cmSlnProjectEntry* GetProjectByGUID(
+ const std::string& projectGUID) const;
- const cmSlnProjectEntry*
- GetProjectByName(const std::string& projectName) const;
+ const cmSlnProjectEntry* GetProjectByName(
+ const std::string& projectName) const;
std::vector<cmSlnProjectEntry> GetProjects() const;
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index bae59740a..1a32abacf 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -1,35 +1,24 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ 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>
-//----------------------------------------------------------------------------
-namespace
+namespace {
+enum LineFormat
{
- enum LineFormat
- {
- LineMultiValueTag,
- LineSingleValueTag,
- LineKeyValuePair,
- LineVerbatim
- };
+ LineMultiValueTag,
+ LineSingleValueTag,
+ LineKeyValuePair,
+ LineVerbatim
+};
}
-//----------------------------------------------------------------------------
class cmVisualStudioSlnParser::ParsedLine
{
public:
@@ -46,11 +35,17 @@ public:
void SetTag(const std::string& tag) { this->Tag = tag; }
void SetArg(const std::string& arg) { this->Arg = StringData(arg, false); }
void SetQuotedArg(const std::string& arg)
- { this->Arg = StringData(arg, true); }
+ {
+ this->Arg = StringData(arg, true);
+ }
void AddValue(const std::string& value)
- { this->Values.push_back(StringData(value, false)); }
+ {
+ this->Values.push_back(StringData(value, false));
+ }
void AddQuotedValue(const std::string& value)
- { this->Values.push_back(StringData(value, true)); }
+ {
+ this->Values.push_back(StringData(value, true));
+ }
void CopyVerbatim(const std::string& line) { this->Tag = line; }
@@ -63,25 +58,21 @@ private:
static const std::string Quote;
};
-//----------------------------------------------------------------------------
const std::string cmVisualStudioSlnParser::ParsedLine::BadString;
const std::string cmVisualStudioSlnParser::ParsedLine::Quote("\"");
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParsedLine::IsComment() const
{
assert(!this->Tag.empty());
- return (this->Tag[0]== '#');
+ return (this->Tag[0] == '#');
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParsedLine::IsKeyValuePair() const
{
assert(!this->Tag.empty());
return this->Arg.first.empty() && this->Values.size() == 1;
}
-//----------------------------------------------------------------------------
std::string cmVisualStudioSlnParser::ParsedLine::GetArgVerbatim() const
{
if (this->Arg.second)
@@ -90,9 +81,8 @@ std::string cmVisualStudioSlnParser::ParsedLine::GetArgVerbatim() const
return this->Arg.first;
}
-//----------------------------------------------------------------------------
-const std::string&
-cmVisualStudioSlnParser::ParsedLine::GetValue(size_t idxValue) const
+const std::string& cmVisualStudioSlnParser::ParsedLine::GetValue(
+ size_t idxValue) const
{
if (idxValue < this->Values.size())
return this->Values[idxValue].first;
@@ -100,23 +90,19 @@ cmVisualStudioSlnParser::ParsedLine::GetValue(size_t idxValue) const
return BadString;
}
-//----------------------------------------------------------------------------
-std::string
-cmVisualStudioSlnParser::ParsedLine::GetValueVerbatim(size_t idxValue) const
+std::string cmVisualStudioSlnParser::ParsedLine::GetValueVerbatim(
+ size_t idxValue) const
{
- if (idxValue < this->Values.size())
- {
+ if (idxValue < this->Values.size()) {
const StringData& data = this->Values[idxValue];
if (data.second)
return Quote + data.first + Quote;
else
return data.first;
- }
- else
+ } else
return BadString;
}
-//----------------------------------------------------------------------------
class cmVisualStudioSlnParser::State
{
public:
@@ -128,8 +114,7 @@ public:
LineFormat NextLineFormat() const;
bool Process(const cmVisualStudioSlnParser::ParsedLine& line,
- cmSlnData& output,
- cmVisualStudioSlnParser::ResultData& result);
+ cmSlnData& output, cmVisualStudioSlnParser::ResultData& result);
bool Finished(cmVisualStudioSlnParser::ResultData& result);
@@ -155,17 +140,15 @@ private:
void IgnoreUntilTag(const std::string& endTag);
};
-//----------------------------------------------------------------------------
-cmVisualStudioSlnParser::State::State(DataGroupSet requestedData) :
- RequestedData(requestedData),
- CurrentLine(0)
+cmVisualStudioSlnParser::State::State(DataGroupSet requestedData)
+ : RequestedData(requestedData)
+ , CurrentLine(0)
{
if (this->RequestedData.test(DataGroupProjectDependenciesBit))
this->RequestedData.set(DataGroupProjectsBit);
this->Stack.push(FileStateStart);
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::State::ReadLine(std::istream& input,
std::string& line)
{
@@ -173,96 +156,88 @@ bool cmVisualStudioSlnParser::State::ReadLine(std::istream& input,
return !std::getline(input, line).fail();
}
-//----------------------------------------------------------------------------
LineFormat cmVisualStudioSlnParser::State::NextLineFormat() const
{
- switch (this->Stack.top())
- {
- case FileStateStart: return LineVerbatim;
- case FileStateTopLevel: return LineMultiValueTag;
- case FileStateProject: return LineSingleValueTag;
- case FileStateProjectDependencies: return LineKeyValuePair;
- case FileStateGlobal: return LineSingleValueTag;
- case FileStateSolutionConfigurations: return LineKeyValuePair;
- case FileStateProjectConfigurations: return LineKeyValuePair;
- case FileStateSolutionFilters: return LineKeyValuePair;
- case FileStateGlobalSection: return LineKeyValuePair;
- case FileStateIgnore: return LineVerbatim;
+ switch (this->Stack.top()) {
+ case FileStateStart:
+ return LineVerbatim;
+ case FileStateTopLevel:
+ return LineMultiValueTag;
+ case FileStateProject:
+ return LineSingleValueTag;
+ case FileStateProjectDependencies:
+ return LineKeyValuePair;
+ case FileStateGlobal:
+ return LineSingleValueTag;
+ case FileStateSolutionConfigurations:
+ return LineKeyValuePair;
+ case FileStateProjectConfigurations:
+ return LineKeyValuePair;
+ case FileStateSolutionFilters:
+ return LineKeyValuePair;
+ case FileStateGlobalSection:
+ return LineKeyValuePair;
+ case FileStateIgnore:
+ return LineVerbatim;
default:
assert(false);
return LineVerbatim;
- }
+ }
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::State::Process(
- const cmVisualStudioSlnParser::ParsedLine& line,
- cmSlnData& output, cmVisualStudioSlnParser::ResultData& result)
+ const cmVisualStudioSlnParser::ParsedLine& line, cmSlnData& output,
+ cmVisualStudioSlnParser::ResultData& result)
{
assert(!line.IsComment());
- switch (this->Stack.top())
- {
+ switch (this->Stack.top()) {
case FileStateStart:
if (!cmSystemTools::StringStartsWith(
- line.GetTag().c_str(), "Microsoft Visual Studio Solution File"))
- {
+ line.GetTag().c_str(), "Microsoft Visual Studio Solution File")) {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
this->Stack.pop();
this->Stack.push(FileStateTopLevel);
break;
case FileStateTopLevel:
- if (line.GetTag().compare("Project") == 0)
- {
- if (line.GetValueCount() != 3)
- {
+ if (line.GetTag().compare("Project") == 0) {
+ if (line.GetValueCount() != 3) {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
- if (this->RequestedData.test(DataGroupProjectsBit))
- {
- if (!output.AddProject(line.GetValue(2),
- line.GetValue(0),
- line.GetValue(1)))
- {
+ }
+ if (this->RequestedData.test(DataGroupProjectsBit)) {
+ if (!output.AddProject(line.GetValue(2), line.GetValue(0),
+ line.GetValue(1))) {
result.SetError(ResultErrorInputData, this->GetCurrentLine());
return false;
- }
- this->Stack.push(FileStateProject);
}
- else
+ this->Stack.push(FileStateProject);
+ } else
this->IgnoreUntilTag("EndProject");
- }
- else if (line.GetTag().compare("Global") == 0)
+ } else if (line.GetTag().compare("Global") == 0)
this->Stack.push(FileStateGlobal);
- else
- {
+ else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateProject:
if (line.GetTag().compare("EndProject") == 0)
this->Stack.pop();
- else if (line.GetTag().compare("ProjectSection") == 0)
- {
+ else if (line.GetTag().compare("ProjectSection") == 0) {
if (line.GetArg().compare("ProjectDependencies") == 0 &&
- line.GetValue(0).compare("postProject") == 0)
- {
+ line.GetValue(0).compare("postProject") == 0) {
if (this->RequestedData.test(DataGroupProjectDependenciesBit))
this->Stack.push(FileStateProjectDependencies);
else
this->IgnoreUntilTag("EndProjectSection");
- }
- else
+ } else
this->IgnoreUntilTag("EndProjectSection");
- }
- else
- {
+ } else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateProjectDependencies:
if (line.GetTag().compare("EndProjectSection") == 0)
@@ -270,51 +245,42 @@ bool cmVisualStudioSlnParser::State::Process(
else if (line.IsKeyValuePair())
// implement dependency storing here, once needed
;
- else
- {
+ else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateGlobal:
if (line.GetTag().compare("EndGlobal") == 0)
this->Stack.pop();
- else if (line.GetTag().compare("GlobalSection") == 0)
- {
+ else if (line.GetTag().compare("GlobalSection") == 0) {
if (line.GetArg().compare("SolutionConfigurationPlatforms") == 0 &&
- line.GetValue(0).compare("preSolution") == 0)
- {
+ line.GetValue(0).compare("preSolution") == 0) {
if (this->RequestedData.test(DataGroupSolutionConfigurationsBit))
this->Stack.push(FileStateSolutionConfigurations);
else
this->IgnoreUntilTag("EndGlobalSection");
- }
- else if (line.GetArg().compare("ProjectConfigurationPlatforms") == 0 &&
- line.GetValue(0).compare("postSolution") == 0)
- {
+ } else if (line.GetArg().compare("ProjectConfigurationPlatforms") ==
+ 0 &&
+ line.GetValue(0).compare("postSolution") == 0) {
if (this->RequestedData.test(DataGroupProjectConfigurationsBit))
this->Stack.push(FileStateProjectConfigurations);
else
this->IgnoreUntilTag("EndGlobalSection");
- }
- else if (line.GetArg().compare("NestedProjects") == 0 &&
- line.GetValue(0).compare("preSolution") == 0)
- {
+ } else if (line.GetArg().compare("NestedProjects") == 0 &&
+ line.GetValue(0).compare("preSolution") == 0) {
if (this->RequestedData.test(DataGroupSolutionFiltersBit))
this->Stack.push(FileStateSolutionFilters);
else
this->IgnoreUntilTag("EndGlobalSection");
- }
- else if (this->RequestedData.test(DataGroupGenericGlobalSectionsBit))
+ } else if (this->RequestedData.test(DataGroupGenericGlobalSectionsBit))
this->Stack.push(FileStateGlobalSection);
else
this->IgnoreUntilTag("EndGlobalSection");
- }
- else
- {
+ } else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateSolutionConfigurations:
if (line.GetTag().compare("EndGlobalSection") == 0)
@@ -322,11 +288,10 @@ bool cmVisualStudioSlnParser::State::Process(
else if (line.IsKeyValuePair())
// implement configuration storing here, once needed
;
- else
- {
+ else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateProjectConfigurations:
if (line.GetTag().compare("EndGlobalSection") == 0)
@@ -334,11 +299,10 @@ bool cmVisualStudioSlnParser::State::Process(
else if (line.IsKeyValuePair())
// implement configuration storing here, once needed
;
- else
- {
+ else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateSolutionFilters:
if (line.GetTag().compare("EndGlobalSection") == 0)
@@ -346,11 +310,10 @@ bool cmVisualStudioSlnParser::State::Process(
else if (line.IsKeyValuePair())
// implement filter storing here, once needed
;
- else
- {
+ else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateGlobalSection:
if (line.GetTag().compare("EndGlobalSection") == 0)
@@ -358,59 +321,52 @@ bool cmVisualStudioSlnParser::State::Process(
else if (line.IsKeyValuePair())
// implement section storing here, once needed
;
- else
- {
+ else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
break;
case FileStateIgnore:
- if (line.GetTag() == this->EndIgnoreTag)
- {
+ if (line.GetTag() == this->EndIgnoreTag) {
this->Stack.pop();
this->EndIgnoreTag = "";
- }
+ }
break;
default:
result.SetError(ResultErrorBadInternalState, this->GetCurrentLine());
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::State::Finished(
cmVisualStudioSlnParser::ResultData& result)
{
- if (this->Stack.top() != FileStateTopLevel)
- {
+ if (this->Stack.top() != FileStateTopLevel) {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
- }
+ }
result.Result = ResultOK;
return true;
}
-//----------------------------------------------------------------------------
void cmVisualStudioSlnParser::State::IgnoreUntilTag(const std::string& endTag)
{
this->Stack.push(FileStateIgnore);
this->EndIgnoreTag = endTag;
}
-//----------------------------------------------------------------------------
cmVisualStudioSlnParser::ResultData::ResultData()
: Result(ResultOK)
, ResultLine(0)
-{}
+{
+}
-//----------------------------------------------------------------------------
void cmVisualStudioSlnParser::ResultData::Clear()
{
*this = ResultData();
}
-//----------------------------------------------------------------------------
void cmVisualStudioSlnParser::ResultData::SetError(ParseResult error,
size_t line)
{
@@ -418,114 +374,99 @@ void cmVisualStudioSlnParser::ResultData::SetError(ParseResult error,
this->ResultLine = line;
}
-//----------------------------------------------------------------------------
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupProjects(
- 1 << cmVisualStudioSlnParser::DataGroupProjectsBit);
+ cmVisualStudioSlnParser::DataGroupProjects(
+ 1 << cmVisualStudioSlnParser::DataGroupProjectsBit);
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupProjectDependencies(
- 1 << cmVisualStudioSlnParser::DataGroupProjectDependenciesBit);
+ cmVisualStudioSlnParser::DataGroupProjectDependencies(
+ 1 << cmVisualStudioSlnParser::DataGroupProjectDependenciesBit);
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupSolutionConfigurations(
- 1 << cmVisualStudioSlnParser::DataGroupSolutionConfigurationsBit);
+ cmVisualStudioSlnParser::DataGroupSolutionConfigurations(
+ 1 << cmVisualStudioSlnParser::DataGroupSolutionConfigurationsBit);
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupProjectConfigurations(
- 1 << cmVisualStudioSlnParser::DataGroupProjectConfigurationsBit);
+ cmVisualStudioSlnParser::DataGroupProjectConfigurations(
+ 1 << cmVisualStudioSlnParser::DataGroupProjectConfigurationsBit);
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupSolutionFilters(
- 1 << cmVisualStudioSlnParser::DataGroupSolutionFiltersBit);
+ cmVisualStudioSlnParser::DataGroupSolutionFilters(
+ 1 << cmVisualStudioSlnParser::DataGroupSolutionFiltersBit);
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupGenericGlobalSections(
- 1 << cmVisualStudioSlnParser::DataGroupGenericGlobalSectionsBit);
+ cmVisualStudioSlnParser::DataGroupGenericGlobalSections(
+ 1 << cmVisualStudioSlnParser::DataGroupGenericGlobalSectionsBit);
const cmVisualStudioSlnParser::DataGroupSet
-cmVisualStudioSlnParser::DataGroupAll(~0);
+ cmVisualStudioSlnParser::DataGroupAll(~0);
-//----------------------------------------------------------------------------
-bool cmVisualStudioSlnParser::Parse(std::istream& input,
- cmSlnData& output,
+bool cmVisualStudioSlnParser::Parse(std::istream& input, cmSlnData& output,
DataGroupSet dataGroups)
{
this->LastResult.Clear();
- if (!this->IsDataGroupSetSupported(dataGroups))
- {
+ if (!this->IsDataGroupSetSupported(dataGroups)) {
this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0);
return false;
- }
+ }
State state(dataGroups);
return this->ParseImpl(input, output, state);
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseFile(const std::string& file,
cmSlnData& output,
DataGroupSet dataGroups)
{
this->LastResult.Clear();
- if (!this->IsDataGroupSetSupported(dataGroups))
- {
+ if (!this->IsDataGroupSetSupported(dataGroups)) {
this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0);
return false;
- }
- std::ifstream f(file.c_str());
- if (!f)
- {
+ }
+ cmsys::ifstream f(file.c_str());
+ if (!f) {
this->LastResult.SetError(ResultErrorOpeningInput, 0);
return false;
- }
+ }
State state(dataGroups);
return this->ParseImpl(f, output, state);
}
-//----------------------------------------------------------------------------
-cmVisualStudioSlnParser::ParseResult
-cmVisualStudioSlnParser::GetParseResult() const
+cmVisualStudioSlnParser::ParseResult cmVisualStudioSlnParser::GetParseResult()
+ const
{
return this->LastResult.Result;
}
-//----------------------------------------------------------------------------
size_t cmVisualStudioSlnParser::GetParseResultLine() const
{
return this->LastResult.ResultLine;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::GetParseHadBOM() const
{
return this->LastResult.HadBOM;
}
-//----------------------------------------------------------------------------
-bool
-cmVisualStudioSlnParser::IsDataGroupSetSupported(DataGroupSet dataGroups) const
+bool cmVisualStudioSlnParser::IsDataGroupSetSupported(
+ DataGroupSet dataGroups) const
{
return (dataGroups & DataGroupProjects) == dataGroups;
- //only supporting DataGroupProjects for now
+ // only supporting DataGroupProjects for now
}
-//----------------------------------------------------------------------------
-bool cmVisualStudioSlnParser::ParseImpl(std::istream& input,
- cmSlnData& output,
+bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output,
State& state)
{
std::string line;
// Does the .sln start with a Byte Order Mark?
if (!this->ParseBOM(input, line, state))
return false;
- do
- {
+ do {
line = cmSystemTools::TrimWhitespace(line);
if (line.empty())
continue;
ParsedLine parsedLine;
- switch (state.NextLineFormat())
- {
+ switch (state.NextLineFormat()) {
case LineMultiValueTag:
if (!this->ParseMultiValueTag(line, parsedLine, state))
return false;
@@ -541,40 +482,34 @@ bool cmVisualStudioSlnParser::ParseImpl(std::istream& input,
case LineVerbatim:
parsedLine.CopyVerbatim(line);
break;
- }
+ }
if (parsedLine.IsComment())
continue;
if (!state.Process(parsedLine, output, this->LastResult))
return false;
- }
- while (state.ReadLine(input, line));
+ } while (state.ReadLine(input, line));
return state.Finished(this->LastResult);
}
-//----------------------------------------------------------------------------
-bool cmVisualStudioSlnParser::ParseBOM(std::istream& input,
- std::string& line,
+bool cmVisualStudioSlnParser::ParseBOM(std::istream& input, std::string& line,
State& state)
{
char bom[4];
- if (!input.get(bom, 4))
- {
+ if (!input.get(bom, 4)) {
this->LastResult.SetError(ResultErrorReadingInput, 1);
return false;
- }
+ }
this->LastResult.HadBOM =
(bom[0] == char(0xEF) && bom[1] == char(0xBB) && bom[2] == char(0xBF));
- if (!state.ReadLine(input, line))
- {
+ if (!state.ReadLine(input, line)) {
this->LastResult.SetError(ResultErrorReadingInput, 1);
return false;
- }
+ }
if (!this->LastResult.HadBOM)
- line = bom + line; // it wasn't a BOM, prepend it to first line
+ line = bom + line; // it wasn't a BOM, prepend it to first line
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseMultiValueTag(const std::string& line,
ParsedLine& parsedLine,
State& state)
@@ -583,49 +518,41 @@ bool cmVisualStudioSlnParser::ParseMultiValueTag(const std::string& line,
const std::string& fullTag = line.substr(0, idxEqualSign);
if (!this->ParseTag(fullTag, parsedLine, state))
return false;
- if (idxEqualSign != line.npos)
- {
+ if (idxEqualSign != line.npos) {
size_t idxFieldStart = idxEqualSign + 1;
- if (idxFieldStart < line.size())
- {
+ if (idxFieldStart < line.size()) {
size_t idxParsing = idxFieldStart;
bool inQuotes = false;
- for (;;)
- {
+ for (;;) {
idxParsing = line.find_first_of(",\"", idxParsing);
bool fieldOver = false;
- if (idxParsing == line.npos)
- {
+ if (idxParsing == line.npos) {
fieldOver = true;
- if (inQuotes)
- {
+ if (inQuotes) {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
- }
}
- else if (line[idxParsing] == ',' && !inQuotes)
+ } else if (line[idxParsing] == ',' && !inQuotes)
fieldOver = true;
else if (line[idxParsing] == '"')
inQuotes = !inQuotes;
- if (fieldOver)
- {
- if (!this->ParseValue(line.substr(idxFieldStart,
- idxParsing - idxFieldStart),
- parsedLine))
+ if (fieldOver) {
+ if (!this->ParseValue(
+ line.substr(idxFieldStart, idxParsing - idxFieldStart),
+ parsedLine))
return false;
if (idxParsing == line.npos)
- break; //end of last field
+ break; // end of last field
idxFieldStart = idxParsing + 1;
- }
- ++idxParsing;
}
+ ++idxParsing;
}
}
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseSingleValueTag(const std::string& line,
ParsedLine& parsedLine,
State& state)
@@ -634,25 +561,22 @@ bool cmVisualStudioSlnParser::ParseSingleValueTag(const std::string& line,
const std::string& fullTag = line.substr(0, idxEqualSign);
if (!this->ParseTag(fullTag, parsedLine, state))
return false;
- if (idxEqualSign != line.npos)
- {
+ if (idxEqualSign != line.npos) {
if (!this->ParseValue(line.substr(idxEqualSign + 1), parsedLine))
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line,
ParsedLine& parsedLine,
State& /*state*/)
{
size_t idxEqualSign = line.find('=');
- if (idxEqualSign == line.npos)
- {
+ if (idxEqualSign == line.npos) {
parsedLine.CopyVerbatim(line);
return true;
- }
+ }
const std::string& key = line.substr(0, idxEqualSign);
parsedLine.SetTag(cmSystemTools::TrimWhitespace(key));
const std::string& value = line.substr(idxEqualSign + 1);
@@ -660,44 +584,36 @@ bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line,
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
- ParsedLine& parsedLine,
- State& state)
+ ParsedLine& parsedLine, State& state)
{
size_t idxLeftParen = fullTag.find('(');
- if (idxLeftParen == fullTag.npos)
- {
+ if (idxLeftParen == fullTag.npos) {
parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag));
return true;
- }
+ }
parsedLine.SetTag(
cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen)));
size_t idxRightParen = fullTag.rfind(')');
- if (idxRightParen == fullTag.npos)
- {
+ if (idxRightParen == fullTag.npos) {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
- }
+ }
const std::string& arg = cmSystemTools::TrimWhitespace(
fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
- if (arg[0] == '"')
- {
- if (arg[arg.size() - 1] != '"')
- {
+ if (arg[0] == '"') {
+ if (arg[arg.size() - 1] != '"') {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
- }
- parsedLine.SetQuotedArg(arg.substr(1, arg.size() - 2));
}
- else
+ parsedLine.SetQuotedArg(arg.substr(1, arg.size() - 2));
+ } else
parsedLine.SetArg(arg);
return true;
}
-//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
ParsedLine& parsedLine)
{
diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h
index bee70cc13..d51732407 100644
--- a/Source/cmVisualStudioSlnParser.h
+++ b/Source/cmVisualStudioSlnParser.h
@@ -1,25 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVisualStudioSlnParser_h
#define cmVisualStudioSlnParser_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h"
#include <bitset>
-
+#include <iosfwd>
+#include <stddef.h>
+#include <string>
class cmSlnData;
-
class cmVisualStudioSlnParser
{
public:
@@ -60,12 +52,10 @@ public:
static const DataGroupSet DataGroupGenericGlobalSections;
static const DataGroupSet DataGroupAll;
- bool Parse(std::istream& input,
- cmSlnData& output,
+ bool Parse(std::istream& input, cmSlnData& output,
DataGroupSet dataGroups = DataGroupAll);
- bool ParseFile(const std::string& file,
- cmSlnData& output,
+ bool ParseFile(const std::string& file, cmSlnData& output,
DataGroupSet dataGroups = DataGroupAll);
ParseResult GetParseResult() const;
@@ -76,6 +66,7 @@ public:
protected:
class State;
+
friend class State;
class ParsedLine;
@@ -96,20 +87,16 @@ protected:
bool ParseBOM(std::istream& input, std::string& line, State& state);
- bool ParseMultiValueTag(const std::string& line,
- ParsedLine& parsedLine,
+ bool ParseMultiValueTag(const std::string& line, ParsedLine& parsedLine,
State& state);
- bool ParseSingleValueTag(const std::string& line,
- ParsedLine& parsedLine,
+ bool ParseSingleValueTag(const std::string& line, ParsedLine& parsedLine,
State& state);
- bool ParseKeyValuePair(const std::string& line,
- ParsedLine& parsedLine,
+ bool ParseKeyValuePair(const std::string& line, ParsedLine& parsedLine,
State& state);
- bool ParseTag(const std::string& fullTag,
- ParsedLine& parsedLine,
+ bool ParseTag(const std::string& fullTag, ParsedLine& parsedLine,
State& state);
bool ParseValue(const std::string& value, ParsedLine& parsedLine);
diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx
index 219a5eb49..fc64d0fb0 100644
--- a/Source/cmVisualStudioWCEPlatformParser.cxx
+++ b/Source/cmVisualStudioWCEPlatformParser.cxx
@@ -1,15 +1,7 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudioWCEPlatformParser.h"
+
#include "cmGlobalVisualStudioGenerator.h"
#include "cmXMLParser.h"
@@ -20,15 +12,12 @@ int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version)
const std::string vckey = registryBase + "\\Setup\\VC;ProductDir";
const std::string vskey = registryBase + "\\Setup\\VS;ProductDir";
- if(!cmSystemTools::ReadRegistryValue(vckey.c_str(),
- this->VcInstallDir,
- cmSystemTools::KeyWOW64_32) ||
- !cmSystemTools::ReadRegistryValue(vskey.c_str(),
- this->VsInstallDir,
- cmSystemTools::KeyWOW64_32))
- {
+ if (!cmSystemTools::ReadRegistryValue(vckey.c_str(), this->VcInstallDir,
+ cmSystemTools::KeyWOW64_32) ||
+ !cmSystemTools::ReadRegistryValue(vskey.c_str(), this->VsInstallDir,
+ cmSystemTools::KeyWOW64_32)) {
return 0;
- }
+ }
cmSystemTools::ConvertToUnixSlashes(this->VcInstallDir);
cmSystemTools::ConvertToUnixSlashes(this->VsInstallDir);
this->VcInstallDir.append("/");
@@ -42,10 +31,9 @@ int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version)
std::string cmVisualStudioWCEPlatformParser::GetOSVersion() const
{
- if (this->OSMinorVersion.empty())
- {
+ if (this->OSMinorVersion.empty()) {
return OSMajorVersion;
- }
+ }
return OSMajorVersion + "." + OSMinorVersion;
}
@@ -54,109 +42,81 @@ const char* cmVisualStudioWCEPlatformParser::GetArchitectureFamily() const
{
std::map<std::string, std::string>::const_iterator it =
this->Macros.find("ARCHFAM");
- if (it != this->Macros.end())
- {
+ if (it != this->Macros.end()) {
return it->second.c_str();
- }
+ }
return 0;
}
-void cmVisualStudioWCEPlatformParser::StartElement(const char* name,
+void cmVisualStudioWCEPlatformParser::StartElement(const std::string& name,
const char** attributes)
{
- if(this->FoundRequiredName)
- {
+ if (this->FoundRequiredName) {
return;
- }
+ }
this->CharacterData = "";
- if(strcmp(name, "PlatformData") == 0)
- {
+ if (name == "PlatformData") {
this->PlatformName = "";
this->OSMajorVersion = "";
this->OSMinorVersion = "";
this->Macros.clear();
- }
+ }
- if(strcmp(name, "Macro") == 0)
- {
+ if (name == "Macro") {
std::string macroName;
std::string macroValue;
- for(const char** attr = attributes; *attr; attr += 2)
- {
- if(strcmp(attr[0], "Name") == 0)
- {
+ for (const char** attr = attributes; *attr; attr += 2) {
+ if (strcmp(attr[0], "Name") == 0) {
macroName = attr[1];
- }
- else if(strcmp(attr[0], "Value") == 0)
- {
+ } else if (strcmp(attr[0], "Value") == 0) {
macroValue = attr[1];
- }
}
+ }
- if(!macroName.empty())
- {
+ if (!macroName.empty()) {
this->Macros[macroName] = macroValue;
- }
}
- else if(strcmp(name, "Directories") == 0)
- {
- for(const char** attr = attributes; *attr; attr += 2)
- {
- if(strcmp(attr[0], "Include") == 0)
- {
+ } else if (name == "Directories") {
+ for (const char** attr = attributes; *attr; attr += 2) {
+ if (strcmp(attr[0], "Include") == 0) {
this->Include = attr[1];
- }
- else if(strcmp(attr[0], "Library") == 0)
- {
+ } else if (strcmp(attr[0], "Library") == 0) {
this->Library = attr[1];
- }
- else if(strcmp(attr[0], "Path") == 0)
- {
+ } else if (strcmp(attr[0], "Path") == 0) {
this->Path = attr[1];
- }
}
}
+ }
}
-void cmVisualStudioWCEPlatformParser::EndElement(const char* name)
+void cmVisualStudioWCEPlatformParser::EndElement(const std::string& name)
{
- if(!this->RequiredName)
- {
- if(strcmp(name, "PlatformName") == 0)
- {
+ if (!this->RequiredName) {
+ if (name == "PlatformName") {
this->AvailablePlatforms.push_back(this->CharacterData);
- }
- return;
}
+ return;
+ }
- if(this->FoundRequiredName)
- {
+ if (this->FoundRequiredName) {
return;
- }
+ }
- if(strcmp(name, "PlatformName") == 0)
- {
+ if (name == "PlatformName") {
this->PlatformName = this->CharacterData;
- }
- else if(strcmp(name, "OSMajorVersion") == 0)
- {
+ } else if (name == "OSMajorVersion") {
this->OSMajorVersion = this->CharacterData;
- }
- else if(strcmp(name, "OSMinorVersion") == 0)
- {
- this->OSMinorVersion = this->CharacterData;
- }
- else if(strcmp(name, "Platform") == 0)
- {
- if(this->PlatformName == this->RequiredName)
- {
+ } else if (name == "OSMinorVersion") {
+ this->OSMinorVersion = this->CharacterData;
+ } else if (name == "Platform") {
+ if (this->PlatformName == this->RequiredName) {
this->FoundRequiredName = true;
- }
}
+ }
}
void cmVisualStudioWCEPlatformParser::CharacterDataHandler(const char* data,
@@ -166,14 +126,14 @@ void cmVisualStudioWCEPlatformParser::CharacterDataHandler(const char* data,
}
std::string cmVisualStudioWCEPlatformParser::FixPaths(
- const std::string& paths) const
+ const std::string& paths) const
{
std::string ret = paths;
cmSystemTools::ReplaceString(ret, "$(PATH)", "%PATH%");
cmSystemTools::ReplaceString(ret, "$(VCInstallDir)", VcInstallDir.c_str());
cmSystemTools::ReplaceString(ret, "$(VSInstallDir)", VsInstallDir.c_str());
- cmSystemTools::ReplaceString(ret, "\\", "/");
+ std::replace(ret.begin(), ret.end(), '\\', '/');
cmSystemTools::ReplaceString(ret, "//", "/");
- cmSystemTools::ReplaceString(ret, "/", "\\");
+ std::replace(ret.begin(), ret.end(), '/', '\\');
return ret;
}
diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h
index 466e1dd43..75c3d1a39 100644
--- a/Source/cmVisualStudioWCEPlatformParser.h
+++ b/Source/cmVisualStudioWCEPlatformParser.h
@@ -1,17 +1,14 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmVisualStudioWCEPlatformParser_h
#define cmVisualStudioWCEPlatformParser_h
-#include "cmStandardIncludes.h"
+
+#include "cmConfigure.h"
+
+#include <map>
+#include <stddef.h>
+#include <string>
+#include <vector>
#include "cmXMLParser.h"
@@ -21,28 +18,33 @@ class cmVisualStudioWCEPlatformParser : public cmXMLParser
{
public:
cmVisualStudioWCEPlatformParser(const char* name = NULL)
- : RequiredName(name)
- , FoundRequiredName(false)
- {
- }
+ : RequiredName(name)
+ , FoundRequiredName(false)
+ {
+ }
int ParseVersion(const char* version);
- bool Found() const {return this->FoundRequiredName;}
+ bool Found() const { return this->FoundRequiredName; }
const char* GetArchitectureFamily() const;
std::string GetOSVersion() const;
- std::string GetIncludeDirectories() const {
- return this->FixPaths(this->Include); }
- std::string GetLibraryDirectories() const {
- return this->FixPaths(this->Library); }
- std::string GetPathDirectories() const {
- return this->FixPaths(this->Path); }
- const std::vector<std::string>& GetAvailablePlatforms() const {
- return this->AvailablePlatforms; }
+ std::string GetIncludeDirectories() const
+ {
+ return this->FixPaths(this->Include);
+ }
+ std::string GetLibraryDirectories() const
+ {
+ return this->FixPaths(this->Library);
+ }
+ std::string GetPathDirectories() const { return this->FixPaths(this->Path); }
+ const std::vector<std::string>& GetAvailablePlatforms() const
+ {
+ return this->AvailablePlatforms;
+ }
protected:
- virtual void StartElement(const char* name, const char** attributes);
- void EndElement(const char* name);
+ virtual void StartElement(const std::string& name, const char** attributes);
+ void EndElement(const std::string& name);
void CharacterDataHandler(const char* data, int length);
private:
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 7d2eeadd6..24d7bf1bf 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -1,103 +1,110 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWhileCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConditionEvaluator.h"
+#include "cmExecutionStatus.h"
+#include "cmExpandedCommandArgument.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cm_auto_ptr.hxx"
+#include "cmake.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmWhileCommand.h"
-#include "cmIfCommand.h"
+cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
+ : Makefile(mf)
+ , Depth(0)
+{
+ this->Makefile->PushLoopBlock();
+}
+
+cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
+{
+ this->Makefile->PopLoopBlock();
+}
-bool cmWhileFunctionBlocker::
-IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
- cmExecutionStatus &inStatus)
+bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
+ cmMakefile& mf,
+ cmExecutionStatus& inStatus)
{
// at end of for each execute recorded commands
- if (!cmSystemTools::Strucmp(lff.Name.c_str(),"while"))
- {
+ 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"))
- {
+ } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
// if this is the endwhile for this while loop then execute
- if (!this->Depth)
- {
+ if (!this->Depth) {
// Remove the function blocker for this scope or bail.
- cmsys::auto_ptr<cmFunctionBlocker>
- fb(mf.RemoveFunctionBlocker(this, lff));
- if(!fb.get()) { return false; }
+ CM_AUTO_PTR<cmFunctionBlocker> fb(mf.RemoveFunctionBlocker(this, lff));
+ if (!fb.get()) {
+ return false;
+ }
std::string errorString;
- std::vector<std::string> expandedArguments;
+ 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 =
- cmIfCommand::IsTrue(expandedArguments,errorString,
- &mf, messageType);
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
- while (isTrue)
- {
- if (errorString.size())
- {
+ 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?"\"":"");
+ for (i = 0; i < this->Args.size(); ++i) {
+ err += (this->Args[i].Delim ? "\"" : "");
err += this->Args[i].Value;
- err += (this->Args[i].Delim?"\"":"");
+ err += (this->Args[i].Delim ? "\"" : "");
err += " ";
- }
+ }
err += "(";
err += errorString;
err += ").";
mf.IssueMessage(messageType, err);
- if (messageType == cmake::FATAL_ERROR)
- {
+ 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)
- {
+ for (unsigned int c = 0; c < this->Functions.size(); ++c) {
cmExecutionStatus status;
- mf.ExecuteCommand(this->Functions[c],status);
- if (status.GetReturnInvoked())
- {
- inStatus.SetReturnInvoked(true);
+ mf.ExecuteCommand(this->Functions[c], status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
return true;
- }
- if (status.GetBreakInvoked())
- {
+ }
+ if (status.GetBreakInvoked()) {
return true;
- }
- if(cmSystemTools::GetFatalErrorOccured() )
- {
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
return true;
- }
}
+ }
expandedArguments.clear();
mf.ExpandArguments(this->Args, expandedArguments);
- isTrue =
- cmIfCommand::IsTrue(expandedArguments,errorString,
- &mf, messageType);
- }
- return true;
- }
- else
- {
- // decrement for each nested while that ends
- this->Depth--;
+ isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString,
+ messageType);
}
+ return true;
}
+ // decrement for each nested while that ends
+ this->Depth--;
+ }
// record the command
this->Functions.push_back(lff);
@@ -106,37 +113,31 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
return true;
}
-bool cmWhileFunctionBlocker::
-ShouldRemove(const cmListFileFunction& lff, cmMakefile& )
+bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
+ cmMakefile&)
{
- if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endwhile"))
- {
+ 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.size() == 0 ||
- lff.Arguments == this->Args)
- {
+ if (lff.Arguments.empty() || lff.Arguments == this->Args) {
return true;
- }
}
+ }
return false;
}
-bool cmWhileCommand
-::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &)
+bool cmWhileCommand::InvokeInitialPass(
+ const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
{
- if(args.size() < 1)
- {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
// create a function blocker
- cmWhileFunctionBlocker *f = new cmWhileFunctionBlocker();
+ cmWhileFunctionBlocker* f = new cmWhileFunctionBlocker(this->Makefile);
f->Args = args;
this->Makefile->AddFunctionBlocker(f);
return true;
}
-
diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h
index 1bdf27af3..a95e4c30c 100644
--- a/Source/cmWhileCommand.h
+++ b/Source/cmWhileCommand.h
@@ -1,34 +1,34 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmWhileCommand_h
#define cmWhileCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
+class cmExecutionStatus;
+class cmMakefile;
+
class cmWhileFunctionBlocker : public cmFunctionBlocker
{
public:
- cmWhileFunctionBlocker() {this->Depth=0;}
- virtual ~cmWhileFunctionBlocker() {}
- virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile &mf,
- cmExecutionStatus &);
- virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
+ 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;
};
@@ -39,63 +39,24 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmWhileCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmWhileCommand; }
/**
* This overrides the default InvokeInitialPass implementation.
* It records the arguments before expansion.
*/
- virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus &);
+ bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus&) CM_OVERRIDE;
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus &) { return false; }
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "while";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Evaluate a group of commands while a condition is true";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " while(condition)\n"
- " COMMAND1(ARGS ...)\n"
- " COMMAND2(ARGS ...)\n"
- " ...\n"
- " endwhile(condition)\n"
- "All commands between while and the matching endwhile are recorded "
- "without being invoked. Once the endwhile is evaluated, the "
- "recorded list of commands is invoked as long as the condition "
- "is true. The condition is evaluated using the same logic as the "
- "if command.";
- }
-
- cmTypeMacro(cmWhileCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const&,
+ cmExecutionStatus&) CM_OVERRIDE
+ {
+ return false;
+ }
};
-
#endif
diff --git a/Source/cmWin32ProcessExecution.cxx b/Source/cmWin32ProcessExecution.cxx
deleted file mode 100644
index 1bdeffbed..000000000
--- a/Source/cmWin32ProcessExecution.cxx
+++ /dev/null
@@ -1,884 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmWin32ProcessExecution.h"
-
-#include "cmSystemTools.h"
-
-#include <malloc.h>
-#include <io.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <windows.h>
-
-#if defined(__BORLANDC__)
-# define STRICMP stricmp
-# define TO_INTPTR(x) ((long)(x))
-#endif // Borland
-#if defined(_MSC_VER) // Visual studio
-# if ( _MSC_VER >= 1300 )
-# include <stddef.h>
-# define TO_INTPTR(x) ((intptr_t)(x))
-# else // Visual Studio 6
-# define TO_INTPTR(x) ((long)(x))
-# endif // Visual studio .NET
-# define STRICMP _stricmp
-#endif // Visual Studio
-#if defined(__MINGW32__)
-# include <stdint.h>
-# define TO_INTPTR(x) ((intptr_t)(x))
-# define STRICMP _stricmp
-#endif // MinGW
-
-#define POPEN_1 1
-#define POPEN_2 2
-#define POPEN_3 3
-#define POPEN_4 4
-
-#define cmMAX(x,y) (((x)<(y))?(y):(x))
-
-void DisplayErrorMessage()
-{
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL
- );
- // Process any inserts in lpMsgBuf.
- // ...
- // Display the string.
- MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
- // Free the buffer.
- LocalFree( lpMsgBuf );
-}
-
-// Code from a Borland web site with the following explaination :
-/* In this article, I will explain how to spawn a console application
- * and redirect its standard input/output using anonymous pipes. An
- * anonymous pipe is a pipe that goes only in one direction (read
- * pipe, write pipe, etc.). Maybe you are asking, "why would I ever
- * need to do this sort of thing?" One example would be a Windows
- * telnet server, where you spawn a shell and listen on a port and
- * send and receive data between the shell and the socket
- * client. (Windows does not really have a built-in remote
- * shell). First, we should talk about pipes. A pipe in Windows is
- * simply a method of communication, often between process. The SDK
- * defines a pipe as "a communication conduit with two ends;
- a process
- * with a handle to one end can communicate with a process having a
- * handle to the other end." In our case, we are using "anonymous"
- * pipes, one-way pipes that "transfer data between a parent process
- * and a child process or between two child processes of the same
- * parent process." It's easiest to imagine a pipe as its namesake. An
- * actual pipe running between processes that can carry data. We are
- * using anonymous pipes because the console app we are spawning is a
- * child process. We use the CreatePipe function which will create an
- * anonymous pipe and return a read handle and a write handle. We will
- * create two pipes, on for stdin and one for stdout. We will then
- * monitor the read end of the stdout pipe to check for display on our
- * child process. Every time there is something availabe for reading,
- * we will display it in our app. Consequently, we check for input in
- * our app and send it off to the write end of the stdin pipe. */
-
-inline bool IsWinNT()
-//check if we're running NT
-{
- OSVERSIONINFO osv;
- osv.dwOSVersionInfoSize = sizeof(osv);
- GetVersionEx(&osv);
- return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
-}
-
-//---------------------------------------------------------------------------
-bool cmWin32ProcessExecution::BorlandRunCommand(
- const char* command, const char* dir,
- std::string& output, int& retVal, bool verbose, int /* timeout */,
- bool hideWindows)
-{
- //verbose = true;
- //std::cerr << std::endl
- // << "WindowsRunCommand(" << command << ")" << std::endl
- // << std::flush;
- const int BUFFER_SIZE = 4096;
- char buf[BUFFER_SIZE];
-
-//i/o buffer
- STARTUPINFO si;
- SECURITY_ATTRIBUTES sa;
- SECURITY_DESCRIPTOR sd;
-
-//security information for pipes
- PROCESS_INFORMATION pi;
- HANDLE newstdin,newstdout,read_stdout,write_stdin;
-
-//pipe handles
- if (IsWinNT())
-//initialize security descriptor (Windows NT)
- {
- InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
- SetSecurityDescriptorDacl(&sd, true, NULL, false);
- sa.lpSecurityDescriptor = &sd;
-
- }
- else sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.bInheritHandle = true;
-
-//allow inheritable handles
- if (!CreatePipe(&newstdin,&write_stdin,&sa,0))
-//create stdin pipe
- {
- return false;
- }
- if (!CreatePipe(&read_stdout,&newstdout,&sa,0))
-//create stdout pipe
- {
- CloseHandle(newstdin);
- CloseHandle(write_stdin);
- return false;
-
- }
- GetStartupInfo(&si);
-
-//set startupinfo for the spawned process
- /* The dwFlags member tells CreateProcess how to make the
- * process. STARTF_USESTDHANDLES validates the hStd*
- * members. STARTF_USESHOWWINDOW validates the wShowWindow
- * member. */
-
- si.cb = sizeof(STARTUPINFO);
- si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
- si.hStdOutput = newstdout;
- si.hStdError = newstdout;
- si.wShowWindow = SW_SHOWDEFAULT;
- if(hideWindows)
- {
- si.wShowWindow = SW_HIDE;
- }
-
-//set the new handles for the child process si.hStdInput = newstdin;
- char* commandAndArgs = strcpy(new char[strlen(command)+1], command);
- if (!CreateProcess(NULL,commandAndArgs,NULL,NULL,TRUE,
- 0, // CREATE_NEW_CONSOLE,
- NULL,dir,&si,&pi))
- {
- std::cerr << "CreateProcess failed " << commandAndArgs << std::endl;
- CloseHandle(newstdin);
- CloseHandle(newstdout);
- CloseHandle(read_stdout);
- CloseHandle(write_stdin);
- delete [] commandAndArgs;
- return false;
-
- }
- delete [] commandAndArgs;
- unsigned long exit=0;
-
-//process exit code unsigned
- unsigned long bread;
-
-//bytes read unsigned
- unsigned long avail;
-
-//bytes available
- memset(buf, 0, sizeof(buf));
- for(;;)
-//main program loop
- {
- Sleep(10);
-//check to see if there is any data to read from stdout
- //std::cout << "Peek for data..." << std::endl;
- PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
- if (bread != 0)
- {
- memset(buf, 0, sizeof(buf));
- if (avail > 1023)
- {
- while (bread >= 1023)
- {
- //std::cout << "Read data..." << std::endl;
- ReadFile(read_stdout,buf,1023,&bread,NULL);
-
- //read the stdout pipe
- memset(buf, 0, sizeof(buf));
- output += buf;
- if (verbose)
- {
- cmSystemTools::Stdout(buf);
- }
- }
- }
- else
- {
- ReadFile(read_stdout,buf,1023,&bread,NULL);
- output += buf;
- if(verbose)
- {
- cmSystemTools::Stdout(buf);
- }
-
- }
-
- }
-
- //std::cout << "Check for process..." << std::endl;
- GetExitCodeProcess(pi.hProcess,&exit);
-
-//while the process is running
- if (exit != STILL_ACTIVE) break;
-
- }
- WaitForSingleObject(pi.hProcess, INFINITE);
- GetExitCodeProcess(pi.hProcess,&exit);
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
- CloseHandle(newstdin);
-
-//clean stuff up
- CloseHandle(newstdout);
- CloseHandle(read_stdout);
- CloseHandle(write_stdin);
- retVal = exit;
- return true;
-
-}
-
-bool cmWin32ProcessExecution::StartProcess(
- const char* cmd, const char* path, bool verbose)
-{
- this->Initialize();
- this->Verbose = verbose;
- return this->PrivateOpen(cmd, path, _O_RDONLY | _O_TEXT, POPEN_3);
-}
-
-bool cmWin32ProcessExecution::Wait(int timeout)
-{
- return this->PrivateClose(timeout);
-}
-
-static BOOL RealPopenCreateProcess(const char *cmdstring,
- const char *path,
- const char *szConsoleSpawn,
- HANDLE hStdin,
- HANDLE hStdout,
- HANDLE hStderr,
- HANDLE *hProcess,
- bool hideWindows,
- std::string& output)
-{
- PROCESS_INFORMATION piProcInfo;
- STARTUPINFO siStartInfo;
- char *s1=0,*s2=0;
- const char *s3 = " /c ";
- int i = GetEnvironmentVariable("COMSPEC",NULL,0);
- if (i)
- {
- char *comshell;
-
- s1 = (char *)malloc(i);
- int x = GetEnvironmentVariable("COMSPEC", s1, i);
- if (!x)
- {
- free(s1);
- return x;
- }
-
- /* Explicitly check if we are using COMMAND.COM. If we are
- * then use the w9xpopen hack.
- */
- comshell = s1 + x;
- while (comshell >= s1 && *comshell != '\\')
- --comshell;
- ++comshell;
-
- if (GetVersion() < 0x80000000 &&
- STRICMP(comshell, "command.com") != 0)
- {
- /* NT/2000 and not using command.com. */
- x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1;
- s2 = (char *)malloc(x);
- ZeroMemory(s2, x);
- //sprintf(s2, "%s%s%s", s1, s3, cmdstring);
- sprintf(s2, "%s", cmdstring);
- }
- else
- {
- /*
- * Oh gag, we're on Win9x or using COMMAND.COM. Use
- * the workaround listed in KB: Q150956
- */
- char modulepath[_MAX_PATH];
- struct stat statinfo;
- GetModuleFileName(NULL, modulepath, sizeof(modulepath));
- for (i = x = 0; modulepath[i]; i++)
- if (modulepath[i] == '\\')
- x = i+1;
- modulepath[x] = '\0';
- /* Create the full-name to w9xpopen, so we can test it exists */
- strncat(modulepath,
- szConsoleSpawn,
- (sizeof(modulepath)/sizeof(modulepath[0]))
- -strlen(modulepath));
- if (stat(modulepath, &statinfo) != 0)
- {
- /* Eeek - file-not-found - possibly an embedding
- situation - see if we can locate it in sys.prefix
- */
- strncpy(modulepath,
- ".",
- sizeof(modulepath)/sizeof(modulepath[0]));
- if (modulepath[strlen(modulepath)-1] != '\\')
- strcat(modulepath, "\\");
- strncat(modulepath,
- szConsoleSpawn,
- (sizeof(modulepath)/sizeof(modulepath[0]))
- -strlen(modulepath));
- /* No where else to look - raise an easily identifiable
- error, rather than leaving Windows to report
- "file not found" - as the user is probably blissfully
- unaware this shim EXE is used, and it will confuse them.
- (well, it confused me for a while ;-)
- */
- if (stat(modulepath, &statinfo) != 0)
- {
- std::cout
- << "Can not locate '" << modulepath
- << "' which is needed "
- "for popen to work with your shell "
- "or platform." << std::endl;
- free(s1);
- free(s2);
- return FALSE;
- }
- }
- x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1 +
- (int)strlen(modulepath) +
- (int)strlen(szConsoleSpawn) + 1;
- if(s2)
- {
- free(s2);
- }
- s2 = (char *)malloc(x);
- ZeroMemory(s2, x);
- sprintf(
- s2,
- "%s %s%s%s",
- modulepath,
- s1,
- s3,
- cmdstring);
- sprintf(
- s2,
- "%s %s",
- modulepath,
- cmdstring);
- }
- }
-
- /* Could be an else here to try cmd.exe / command.com in the path
- Now we'll just error out.. */
- else
- {
- std::cout << "Cannot locate a COMSPEC environment variable to "
- << "use as the shell" << std::endl;
- free(s2);
- free(s1);
- return FALSE;
- }
-
- ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- siStartInfo.hStdInput = hStdin;
- siStartInfo.hStdOutput = hStdout;
- siStartInfo.hStdError = hStderr;
- siStartInfo.wShowWindow = SW_SHOWDEFAULT;
- if(hideWindows)
- {
- siStartInfo.wShowWindow = SW_HIDE;
- }
-
- //std::cout << "Create process: " << s2 << std::endl;
- if (CreateProcess(NULL,
- s2,
- NULL,
- NULL,
- TRUE,
- 0, //CREATE_NEW_CONSOLE,
- NULL,
- path,
- &siStartInfo,
- &piProcInfo) )
- {
- /* Close the handles now so anyone waiting is woken. */
- CloseHandle(piProcInfo.hThread);
- /* Return process handle */
- *hProcess = piProcInfo.hProcess;
- //std::cout << "Process created..." << std::endl;
- free(s2);
- free(s1);
- return TRUE;
- }
-
- output += "CreateProcessError: ";
- {
- /* Format the error message. */
- char message[1024];
- DWORD original = GetLastError();
- DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- message, 1023, 0);
- if(length < 1)
- {
- /* FormatMessage failed. Use a default message. */
- _snprintf(message, 1023,
- "Process execution failed with error 0x%X. "
- "FormatMessage failed with error 0x%X",
- original, GetLastError());
- }
- output += message;
- }
- output += "\n";
- output += "for command: ";
- output += s2;
- if(path)
- {
- output += "\nin dir: ";
- output += path;
- }
- output += "\n";
- free(s2);
- free(s1);
- return FALSE;
-}
-
-/* The following code is based off of KB: Q190351 */
-
-bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
- const char* path,
- int mode,
- int n)
-{
- HANDLE hProcess;
-
- SECURITY_ATTRIBUTES saAttr;
- BOOL fSuccess;
- int fd1, fd2, fd3;
- this->hChildStdinRd = 0;
- this->hChildStdinWr = 0;
- this->hChildStdoutRd = 0;
- this->hChildStdoutWr = 0;
- this->hChildStderrRd = 0;
- this->hChildStderrWr = 0;
- this->hChildStdinWrDup = 0;
- this->hChildStdoutRdDup = 0;
- this->hChildStderrRdDup = 0;
-
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- fd1 = 0;
- fd2 = 0;
- fd3 = 0;
-
- if (!CreatePipe(&this->hChildStdinRd, &this->hChildStdinWr, &saAttr, 0))
- {
- this->Output += "CreatePipeError\n";
- return false;
- }
-
- /* Create new output read handle and the input write handle. Set
- * the inheritance properties to FALSE. Otherwise, the child inherits
- * these handles; resulting in non-closeable handles to the pipes
- * being created. */
- fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdinWr,
- GetCurrentProcess(), &this->hChildStdinWrDup, 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
- if (!fSuccess)
- {
- this->Output += "DuplicateHandleError\n";
- return false;
- }
-
-
- /* Close the inheritable version of ChildStdin
- that we're using. */
- CloseHandle(hChildStdinWr);
-
- if (!CreatePipe(&this->hChildStdoutRd, &this->hChildStdoutWr, &saAttr, 0))
- {
- this->Output += "CreatePipeError\n";
- return false;
- }
-
- fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdoutRd,
- GetCurrentProcess(), &this->hChildStdoutRdDup, 0,
- FALSE, DUPLICATE_SAME_ACCESS);
- if (!fSuccess)
- {
- this->Output += "DuplicateHandleError\n";
- return false;
- }
-
- /* Close the inheritable version of ChildStdout
- that we're using. */
- CloseHandle(hChildStdoutRd);
-
- if (n != POPEN_4)
- {
- if (!CreatePipe(&this->hChildStderrRd, &this->hChildStderrWr, &saAttr, 0))
- {
- this->Output += "CreatePipeError\n";
- return false;
- }
- fSuccess = DuplicateHandle(GetCurrentProcess(),
- this->hChildStderrRd,
- GetCurrentProcess(),
- &this->hChildStderrRdDup, 0,
- FALSE, DUPLICATE_SAME_ACCESS);
- if (!fSuccess)
- {
- this->Output += "DuplicateHandleError\n";
- return false;
- }
- /* Close the inheritable version of ChildStdErr that we're using. */
- CloseHandle(hChildStderrRd);
-
- }
-
- switch (n)
- {
- case POPEN_1:
- switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY))
- {
- case _O_WRONLY | _O_TEXT:
- /* Case for writing to child Stdin in text mode. */
- fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
- /* We don't care about these pipes anymore,
- so close them. */
- break;
-
- case _O_RDONLY | _O_TEXT:
- /* Case for reading from child Stdout in text mode. */
- fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
- /* We don't care about these pipes anymore,
- so close them. */
- break;
-
- case _O_RDONLY | _O_BINARY:
- /* Case for readinig from child Stdout in
- binary mode. */
- fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
- /* We don't care about these pipes anymore,
- so close them. */
- break;
-
- case _O_WRONLY | _O_BINARY:
- /* Case for writing to child Stdin in binary mode. */
- fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
- /* We don't care about these pipes anymore,
- so close them. */
- break;
- }
- break;
-
- case POPEN_2:
- case POPEN_4:
- //if ( 1 )
- {
- fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
- fd2 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
- break;
- }
-
- case POPEN_3:
- //if ( 1)
- {
- fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
- fd2 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
- fd3 = _open_osfhandle(TO_INTPTR(this->hChildStderrRdDup), mode);
- break;
- }
- }
-
- if (n == POPEN_4)
- {
- if (!RealPopenCreateProcess(cmdstring,
- path,
- this->ConsoleSpawn.c_str(),
- this->hChildStdinRd,
- this->hChildStdoutWr,
- this->hChildStdoutWr,
- &hProcess, this->HideWindows,
- this->Output))
- {
- if(fd1 >= 0)
- {
- close(fd1);
- }
- if(fd2 >= 0)
- {
- close(fd2);
- }
- if(fd3 >= 0)
- {
- close(fd3);
- }
- return 0;
- }
- }
- else
- {
- if (!RealPopenCreateProcess(cmdstring,
- path,
- this->ConsoleSpawn.c_str(),
- this->hChildStdinRd,
- this->hChildStdoutWr,
- this->hChildStderrWr,
- &hProcess, this->HideWindows,
- this->Output))
- {
- if(fd1 >= 0)
- {
- close(fd1);
- }
- if(fd2 >= 0)
- {
- close(fd2);
- }
- if(fd3 >= 0)
- {
- close(fd3);
- }
- return 0;
- }
- }
-
- /* Child is launched. Close the parents copy of those pipe
- * handles that only the child should have open. You need to
- * make sure that no handles to the write end of the output pipe
- * are maintained in this process or else the pipe will not close
- * when the child process exits and the ReadFile will hang. */
- this->ProcessHandle = hProcess;
- if ( fd1 >= 0 )
- {
- this->pStdIn = fd1;
- }
- if ( fd2 >= 0 )
- {
- this->pStdOut = fd2;
- }
- if ( fd3 >= 0 )
- {
- this->pStdErr = fd3;
- }
-
- return true;
-}
-
-bool cmWin32ProcessExecution::CloseHandles()
-{
- if(this->pStdErr != -1 )
- {
- // this will close this as well: this->hChildStderrRdDup
- _close(this->pStdErr);
- this->pStdErr = -1;
- this->hChildStderrRdDup = 0;
- }
- if(this->pStdIn != -1 )
- {
- // this will close this as well: this->hChildStdinWrDup
- _close(this->pStdIn);
- this->pStdIn = -1;
- this->hChildStdinWrDup = 0;
- }
- if(this->pStdOut != -1 )
- {
- // this will close this as well: this->hChildStdoutRdDup
- _close(this->pStdOut);
- this->pStdOut = -1;
- this->hChildStdoutRdDup = 0;
- }
-
- bool ret = true;
- if (this->hChildStdinRd && !CloseHandle(this->hChildStdinRd))
- {
- ret = false;
- }
- this->hChildStdinRd = 0;
- // now close these two
- if (this->hChildStdoutWr && !CloseHandle(this->hChildStdoutWr))
- {
- ret = false;
- }
- this->hChildStdoutWr = 0;
- if (this->hChildStderrWr && !CloseHandle(this->hChildStderrWr))
- {
- ret = false;
- }
- this->hChildStderrWr = 0;
- return ret;
-}
-cmWin32ProcessExecution::~cmWin32ProcessExecution()
-{
- this->CloseHandles();
-}
-
-bool cmWin32ProcessExecution::PrivateClose(int /* timeout */)
-{
- HANDLE hProcess = this->ProcessHandle;
-
- int result = -1;
- DWORD exit_code;
-
- std::string output = "";
- bool done = false;
- while(!done)
- {
- Sleep(10);
- bool have_some = false;
- struct _stat fsout;
- struct _stat fserr;
- int rout = _fstat(this->pStdOut, &fsout);
- int rerr = _fstat(this->pStdErr, &fserr);
- if ( rout && rerr )
- {
- break;
- }
- if (fserr.st_size > 0)
- {
- char buffer[1024];
- int len = read(this->pStdErr, buffer, 1023);
- buffer[len] = 0;
- if ( this->Verbose )
- {
- cmSystemTools::Stdout(buffer);
- }
- output += buffer;
- have_some = true;
- }
- if (fsout.st_size > 0)
- {
- char buffer[1024];
- int len = read(this->pStdOut, buffer, 1023);
- buffer[len] = 0;
- if ( this->Verbose )
- {
- cmSystemTools::Stdout(buffer);
- }
- output += buffer;
- have_some = true;
- }
- unsigned long exitCode;
- if ( ! have_some )
- {
- GetExitCodeProcess(hProcess,&exitCode);
- if (exitCode != STILL_ACTIVE)
- {
- break;
- }
- }
- }
-
-
- if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
- GetExitCodeProcess(hProcess, &exit_code))
- {
- result = exit_code;
- }
- else
- {
- /* Indicate failure - this will cause the file object
- * to raise an I/O error and translate the last Win32
- * error code from errno. We do have a problem with
- * last errors that overlap the normal errno table,
- * but that's a consistent problem with the file object.
- */
- if (result != EOF)
- {
- /* If the error wasn't from the fclose(), then
- * set errno for the file object error handling.
- */
- errno = GetLastError();
- }
- result = -1;
- }
-
- /* Free up the native handle at this point */
- CloseHandle(hProcess);
- this->ExitValue = result;
- this->Output += output;
- bool ret = this->CloseHandles();
- if ( result < 0 || !ret)
- {
- return false;
- }
- return true;
-}
-
-int cmWin32ProcessExecution::Windows9xHack(const char* command)
-{
- BOOL bRet;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- DWORD exit_code=0;
-
- if (!command)
- {
- cmSystemTools::Error("Windows9xHack: Command not specified");
- return 1;
- }
-
- /* Make child process use this app's standard files. */
- ZeroMemory(&si, sizeof si);
- si.cb = sizeof si;
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-
-
- char * app = 0;
- char* cmd = new char[ strlen(command) + 1 ];
- strcpy(cmd, command);
-
- bRet = CreateProcess(
- app, cmd,
- 0, 0,
- TRUE, 0,
- 0, 0,
- &si, &pi
- );
- delete [] cmd;
-
- if (bRet)
- {
- if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED)
- {
- GetExitCodeProcess(pi.hProcess, &exit_code);
- }
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return exit_code;
- }
-
- return 1;
-}
diff --git a/Source/cmWin32ProcessExecution.h b/Source/cmWin32ProcessExecution.h
deleted file mode 100644
index 2127ebd2e..000000000
--- a/Source/cmWin32ProcessExecution.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cmWin32ProcessExecution_h
-#define cmWin32ProcessExecution_h
-
-#include "cmStandardIncludes.h"
-#include "windows.h"
-
-class cmMakefile;
-
-/** \class cmWin32ProcessExecution
- * \brief A process executor for windows
- *
- * cmWin32ProcessExecution is a class that provides a "clean" way of
- * executing processes on Windows. It is modified code from Python 2.1
- * distribution.
- *
- * Portable 'popen' replacement for Win32.
- *
- * Written by Bill Tutt <billtut@microsoft.com>. Minor tweaks and 2.0
- * integration by Fredrik Lundh <fredrik@pythonware.com> Return code
- * handling by David Bolen <db3l@fitlinxx.com>.
- *
- * Modified for CMake.
- *
- * For more information, please check Microsoft Knowledge Base
- * Articles Q190351 and Q150956.
- */
-class cmWin32ProcessExecution
-{
-public:
- cmWin32ProcessExecution()
- {
- this->HideWindows = false;
- this->SetConsoleSpawn("w9xpopen.exe");
- this->Initialize();
- }
- ~cmWin32ProcessExecution();
- ///! If true windows will be created hidden.
- void SetHideWindows(bool v) { this->HideWindows = v; }
-
- /**
- * Initialize the process execution datastructure. Do not call while
- * running the process.
- */
- void Initialize()
- {
- this->ProcessHandle = 0;
- this->ExitValue = -1;
- // Comment this out. Maybe we will need it in the future.
- // file IO access to the process might be cool.
- //this->StdIn = 0;
- //this->StdOut = 0;
- //this->StdErr = 0;
- this->pStdIn = -1;
- this->pStdOut = -1;
- this->pStdErr = -1;
- }
-
- /**
- * Start the process in the directory path. Make sure that the
- * executable is either in the path or specify the full path. The
- * argument verbose specifies whether or not to display output while
- * it is being generated.
- */
- bool StartProcess(const char*, const char* path, bool verbose);
-
- /**
- * Wait for the process to finish. If timeout is specified, it will
- * break the process after timeout expires. (Timeout code is not yet
- * implemented.
- */
- bool Wait(int timeout);
-
- /**
- * Get the output of the process (mixed stdout and stderr) as
- * std::string.
- */
- const std::string GetOutput() const { return this->Output; }
-
- /**
- * Get the return value of the process. If the process is still
- * running, the return value is -1.
- */
- int GetExitValue() const { return this->ExitValue; }
-
- /**
- * On Windows 9x there is a bug in the process execution code which
- * may result in blocking. That is why this workaround is
- * used. Specify the console spawn, which should run the
- * Windows9xHack code.
- */
- void SetConsoleSpawn(const char* prog) { this->ConsoleSpawn = prog; }
- static int Windows9xHack(const char* command);
-
- /** Code from a Borland web site with the following explaination :
- * In this article, I will explain how to spawn a console
- * application and redirect its standard input/output using
- * anonymous pipes. An anonymous pipe is a pipe that goes only in
- * one direction (read pipe, write pipe, etc.). Maybe you are
- * asking, "why would I ever need to do this sort of thing?" One
- * example would be a Windows telnet server, where you spawn a shell
- * and listen on a port and send and receive data between the shell
- * and the socket client. (Windows does not really have a built-in
- * remote shell). First, we should talk about pipes. A pipe in
- * Windows is simply a method of communication, often between
- * process. The SDK defines a pipe as "a communication conduit with
- * two ends; a process with a handle to one end can communicate with
- * a process having a handle to the other end." In our case, we are
- * using "anonymous" pipes, one-way pipes that "transfer data
- * between a parent process and a child process or between two child
- * processes of the same parent process." It's easiest to imagine a
- * pipe as its namesake. An actual pipe running between processes
- * that can carry data. We are using anonymous pipes because the
- * console app we are spawning is a child process. We use the
- * CreatePipe function which will create an anonymous pipe and
- * return a read handle and a write handle. We will create two
- * pipes, on for stdin and one for stdout. We will then monitor the
- * read end of the stdout pipe to check for display on our child
- * process. Every time there is something availabe for reading, we
- * will display it in our app. Consequently, we check for input in
- * our app and send it off to the write end of the stdin pipe.
- */
- static bool BorlandRunCommand(const char* command,
- const char* dir,
- std::string& output, int& retVal,
- bool verbose,
- int timeout, bool hideWindows);
-
-private:
- bool CloseHandles();
- bool PrivateOpen(const char*, const char*, int, int);
- bool PrivateClose(int timeout);
-
- HANDLE ProcessHandle;
- HANDLE hChildStdinRd;
- HANDLE hChildStdinWr;
- HANDLE hChildStdoutRd;
- HANDLE hChildStdoutWr;
- HANDLE hChildStderrRd;
- HANDLE hChildStderrWr;
- HANDLE hChildStdinWrDup;
- HANDLE hChildStdoutRdDup;
- HANDLE hChildStderrRdDup;
-
-
- int pStdIn;
- int pStdOut;
- int pStdErr;
-
- int ExitValue;
-
- std::string Output;
- std::string ConsoleSpawn;
- bool Verbose;
- bool HideWindows;
-};
-
-
-#endif
diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx
new file mode 100644
index 000000000..99c9ba86a
--- /dev/null
+++ b/Source/cmWorkingDirectory.cxx
@@ -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. */
+#include "cmWorkingDirectory.h"
+
+#include "cmSystemTools.h"
+
+cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
+{
+ this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
+ cmSystemTools::ChangeDirectory(newdir);
+}
+
+cmWorkingDirectory::~cmWorkingDirectory()
+{
+ this->Pop();
+}
+
+void cmWorkingDirectory::Pop()
+{
+ if (!this->OldDir.empty()) {
+ cmSystemTools::ChangeDirectory(this->OldDir);
+ this->OldDir.clear();
+ }
+}
diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h
new file mode 100644
index 000000000..aff926755
--- /dev/null
+++ b/Source/cmWorkingDirectory.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 cmWorkingDirectory_h
+#define cmWorkingDirectory_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** \class cmWorkingDirectory
+ * \brief An RAII class to manipulate the working directory.
+ */
+class cmWorkingDirectory
+{
+public:
+ cmWorkingDirectory(std::string const& newdir);
+ ~cmWorkingDirectory();
+
+ void Pop();
+
+private:
+ std::string OldDir;
+};
+
+#endif
diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx
index 3642c6fba..fc5fd2111 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -1,55 +1,45 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWriteFileCommand.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmsys/FStream.hxx"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmWriteFileCommand.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cm_sys_stat.h"
-#include <sys/types.h>
-#include <sys/stat.h>
+class cmExecutionStatus;
// cmLibraryCommand
-bool cmWriteFileCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
{
- if(args.size() < 2 )
- {
+ if (args.size() < 2) {
this->SetError("called with incorrect number of arguments");
return false;
- }
+ }
std::string message;
std::vector<std::string>::const_iterator i = args.begin();
- std::string fileName = *i;
+ std::string const& fileName = *i;
bool overwrite = true;
i++;
- for(;i != args.end(); ++i)
- {
- if ( *i == "APPEND" )
- {
+ for (; i != args.end(); ++i) {
+ if (*i == "APPEND") {
overwrite = false;
- }
- else
- {
+ } else {
message += *i;
- }
}
+ }
- if ( !this->Makefile->CanIWriteThisFile(fileName.c_str()) )
- {
- std::string e = "attempted to write a file: " + fileName
- + " into a source directory.";
- this->SetError(e.c_str());
+ if (!this->Makefile->CanIWriteThisFile(fileName.c_str())) {
+ std::string e =
+ "attempted to write a file: " + fileName + " into a source directory.";
+ this->SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
- }
+ }
std::string dir = cmSystemTools::GetFilenamePath(fileName);
cmSystemTools::MakeDirectory(dir.c_str());
@@ -57,37 +47,31 @@ bool cmWriteFileCommand
mode_t mode = 0;
// Set permissions to writable
- if ( cmSystemTools::GetPermissions(fileName.c_str(), mode) )
- {
+ if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
cmSystemTools::SetPermissions(fileName.c_str(),
-#if defined( _MSC_VER ) || defined( __MINGW32__ )
- mode | S_IWRITE
-#elif defined( __BORLANDC__ )
- mode | S_IWUSR
+#if defined(_MSC_VER) || defined(__MINGW32__)
+ mode | S_IWRITE
#else
- mode | S_IWUSR | S_IWGRP
+ mode | S_IWUSR | S_IWGRP
#endif
- );
- }
+ );
+ }
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
- std::ofstream file(fileName.c_str(),
- overwrite?std::ios::out : std::ios::app);
- if ( !file )
- {
+ 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.c_str();
+ error += fileName;
error += " for writing.";
- this->SetError(error.c_str());
+ this->SetError(error);
return false;
- }
+ }
file << message << std::endl;
file.close();
- if(mode)
- {
+ if (mode) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
- }
+ }
return true;
}
-
diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h
index 771ef5a1b..19922cdf3 100644
--- a/Source/cmWriteFileCommand.h
+++ b/Source/cmWriteFileCommand.h
@@ -1,19 +1,17 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmWriteFileCommand_h
#define cmWriteFileCommand_h
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
#include "cmCommand.h"
+class cmExecutionStatus;
+
/** \class cmWriteFileCommand
* \brief Writes a message to a file
*
@@ -24,62 +22,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone()
- {
- return new cmWriteFileCommand;
- }
+ cmCommand* Clone() CM_OVERRIDE { return new cmWriteFileCommand; }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- virtual bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus &status);
-
- /**
- * This determines if the command is invoked when in script mode.
- */
- virtual bool IsScriptable() const { return true; }
-
- /**
- * The name of the command as specified in CMakeList.txt.
- */
- virtual const char* GetName() const { return "write_file";}
-
- /**
- * Succinct documentation.
- */
- virtual const char* GetTerseDocumentation() const
- {
- return "Deprecated. Use the file(WRITE ) command instead.";
- }
-
- /**
- * More documentation.
- */
- virtual const char* GetFullDocumentation() const
- {
- return
- " write_file(filename \"message to write\"... [APPEND])\n"
- "The first argument is the file name, the rest of the arguments are "
- "messages to write. If the argument APPEND is specified, then "
- "the message will be appended.\n"
- "NOTE 1: file(WRITE ... and file(APPEND ... do exactly the same as "
- "this one but add some more functionality.\n"
- "NOTE 2: When using write_file the produced file cannot be used as an "
- "input to CMake (CONFIGURE_FILE, source file ...) because it will "
- "lead to an infinite loop. Use configure_file if you want to generate "
- "input files to CMake.";
- }
-
- /** This command is kept for compatibility with older CMake versions. */
- virtual bool IsDiscouraged() const
- {
- return true;
- }
-
- cmTypeMacro(cmWriteFileCommand, cmCommand);
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) CM_OVERRIDE;
};
-
#endif
diff --git a/Source/cmXCode21Object.cxx b/Source/cmXCode21Object.cxx
index 855e1ad2f..719e62765 100644
--- a/Source/cmXCode21Object.cxx
+++ b/Source/cmXCode21Object.cxx
@@ -1,74 +1,61 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmXCode21Object.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <ostream>
+#include <string>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmXCode21Object.h"
#include "cmSystemTools.h"
-//----------------------------------------------------------------------------
cmXCode21Object::cmXCode21Object(PBXType ptype, Type type)
- :cmXCodeObject(ptype, type)
+ : cmXCodeObject(ptype, type)
{
this->Version = 21;
}
-//----------------------------------------------------------------------------
void cmXCode21Object::PrintComment(std::ostream& out)
{
- if(this->Comment.size() == 0)
- {
+ if (this->Comment.empty()) {
cmXCodeObject* n = this->GetObject("name");
- if(n)
- {
+ if (n) {
this->Comment = n->GetString();
cmSystemTools::ReplaceString(this->Comment, "\"", "");
- }
}
- out << "/* ";
+ }
+ if (this->Comment.empty()) {
+ return;
+ }
+ out << " /* ";
out << this->Comment;
out << " */";
}
-//----------------------------------------------------------------------------
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)
- {
+ for (std::vector<cmXCodeObject*>::const_iterator i = v.begin(); i != v.end();
+ ++i) {
cmXCodeObject* obj = *i;
- if(obj->GetType() == OBJECT && obj->GetIsA() == t)
- {
+ if (obj->GetType() == OBJECT && obj->GetIsA() == t) {
hasOne = true;
break;
- }
}
- if(!hasOne)
- {
+ }
+ if (!hasOne) {
return;
- }
- out << "\n/* Begin " << PBXTypeNames[t] << " section */\n";
- for(std::vector<cmXCodeObject*>::const_iterator i = v.begin();
- i != v.end(); ++i)
- {
+ }
+ out << "\n/* Begin " << PBXTypeNames[t] << " section */\n";
+ for (std::vector<cmXCodeObject*>::const_iterator i = v.begin(); i != v.end();
+ ++i) {
cmXCodeObject* obj = *i;
- if(obj->GetType() == OBJECT && obj->GetIsA() == t)
- {
- obj->Print(out);
- }
+ if (obj->GetType() == OBJECT && obj->GetIsA() == t) {
+ obj->Print(out);
}
- out << "/* End " << PBXTypeNames[t] << " section */\n";
+ }
+ out << "/* End " << PBXTypeNames[t] << " section */\n";
}
-//----------------------------------------------------------------------------
void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v,
std::ostream& out)
{
@@ -79,8 +66,7 @@ void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v,
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXBuildStyle);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXContainerItemProxy);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXFileReference);
- cmXCode21Object::PrintList(v, out,
- cmXCode21Object::PBXFrameworksBuildPhase);
+ cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXFrameworksBuildPhase);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXGroup);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXHeadersBuildPhase);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXNativeTarget);
@@ -90,8 +76,7 @@ void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v,
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXResourcesBuildPhase);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXSourcesBuildPhase);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXCopyFilesBuildPhase);
- cmXCode21Object::PrintList(v, out,
- cmXCode21Object::PBXApplicationReference);
+ cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXApplicationReference);
cmXCode21Object::PrintList(v, out,
cmXCode21Object::PBXExecutableFileReference);
cmXCode21Object::PrintList(v, out, cmXCode21Object::PBXLibraryReference);
diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h
index cc3ab047b..bcd8d93e1 100644
--- a/Source/cmXCode21Object.h
+++ b/Source/cmXCode21Object.h
@@ -1,17 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmXCode21Object_h
#define cmXCode21Object_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <vector>
+
#include "cmXCodeObject.h"
class cmXCode21Object : public cmXCodeObject
@@ -19,10 +15,8 @@ class cmXCode21Object : public cmXCodeObject
public:
cmXCode21Object(PBXType ptype, Type type);
virtual void PrintComment(std::ostream&);
- static void PrintList(std::vector<cmXCodeObject*> const&,
- std::ostream& out,
+ static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out,
PBXType t);
- static void PrintList(std::vector<cmXCodeObject*> const&,
- std::ostream& out);
+ static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out);
};
#endif
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index 6abf6bf00..0def8c321 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -1,232 +1,217 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmXCodeObject.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include <CoreFoundation/CoreFoundation.h>
+#include <ostream>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmXCodeObject.h"
#include "cmSystemTools.h"
-#include <CoreFoundation/CoreFoundation.h> // CFUUIDCreate
-
-//----------------------------------------------------------------------------
const char* cmXCodeObject::PBXTypeNames[] = {
- "PBXGroup", "PBXBuildStyle", "PBXProject", "PBXHeadersBuildPhase",
- "PBXSourcesBuildPhase", "PBXFrameworksBuildPhase", "PBXNativeTarget",
- "PBXFileReference", "PBXBuildFile", "PBXContainerItemProxy",
- "PBXTargetDependency", "PBXShellScriptBuildPhase",
- "PBXResourcesBuildPhase", "PBXApplicationReference",
- "PBXExecutableFileReference", "PBXLibraryReference", "PBXToolTarget",
- "PBXLibraryTarget", "PBXAggregateTarget", "XCBuildConfiguration",
- "XCConfigurationList",
- "PBXCopyFilesBuildPhase",
- "None"
- };
+ /* clang-format needs this comment to break after the opening brace */
+ "PBXGroup",
+ "PBXBuildStyle",
+ "PBXProject",
+ "PBXHeadersBuildPhase",
+ "PBXSourcesBuildPhase",
+ "PBXFrameworksBuildPhase",
+ "PBXNativeTarget",
+ "PBXFileReference",
+ "PBXBuildFile",
+ "PBXContainerItemProxy",
+ "PBXTargetDependency",
+ "PBXShellScriptBuildPhase",
+ "PBXResourcesBuildPhase",
+ "PBXApplicationReference",
+ "PBXExecutableFileReference",
+ "PBXLibraryReference",
+ "PBXToolTarget",
+ "PBXLibraryTarget",
+ "PBXAggregateTarget",
+ "XCBuildConfiguration",
+ "XCConfigurationList",
+ "PBXCopyFilesBuildPhase",
+ "None"
+};
-//----------------------------------------------------------------------------
cmXCodeObject::~cmXCodeObject()
{
this->Version = 15;
}
-//----------------------------------------------------------------------------
cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
{
this->Version = 15;
this->Target = 0;
- this->Object =0;
+ this->Object = 0;
this->IsA = ptype;
- if(type == OBJECT)
- {
+ if (type == OBJECT) {
// Set the Id of an Xcode object to a unique string for each instance.
// However the Xcode user file references certain Ids: for those cases,
// override the generated Id using SetId().
//
- char cUuid[40] = {0};
+ char cUuid[40] = { 0 };
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, uuid);
CFStringGetCString(s, cUuid, sizeof(cUuid), kCFStringEncodingUTF8);
this->Id = cUuid;
CFRelease(s);
CFRelease(uuid);
- }
- else
- {
+ } else {
this->Id =
"Temporary cmake object, should not be referred to in Xcode file";
- }
+ }
cmSystemTools::ReplaceString(this->Id, "-", "");
- if(this->Id.size() > 24)
- {
+ if (this->Id.size() > 24) {
this->Id = this->Id.substr(0, 24);
- }
+ }
this->TypeValue = type;
- if(this->TypeValue == OBJECT)
- {
+ if (this->TypeValue == OBJECT) {
this->AddAttribute("isa", 0);
- }
+ }
+}
+
+bool cmXCodeObject::IsEmpty() const
+{
+ switch (this->TypeValue) {
+ case OBJECT_LIST:
+ return this->List.empty();
+ case STRING:
+ return this->String.empty();
+ case ATTRIBUTE_GROUP:
+ return this->ObjectAttributes.empty();
+ case OBJECT_REF:
+ case OBJECT:
+ return this->Object == 0;
+ }
+ return true; // unreachable, but quiets warnings
}
-//----------------------------------------------------------------------------
void cmXCodeObject::Indent(int level, std::ostream& out)
{
- while(level)
- {
- out << " ";
+ while (level) {
+ out << "\t";
level--;
- }
+ }
}
-//----------------------------------------------------------------------------
void cmXCodeObject::Print(std::ostream& out)
{
std::string separator = "\n";
int indentFactor = 1;
- if(this->Version > 15
- && (this->IsA == PBXFileReference || this->IsA == PBXBuildFile))
- {
+ cmXCodeObject::Indent(2 * indentFactor, out);
+ if (this->Version > 15 &&
+ (this->IsA == PBXFileReference || this->IsA == PBXBuildFile)) {
separator = " ";
indentFactor = 0;
- }
- cmXCodeObject::Indent(2*indentFactor, out);
- out << this->Id << " ";
- if(!(this->IsA == PBXGroup && this->Comment.size() == 0))
- {
- this->PrintComment(out);
- }
+ }
+ out << this->Id;
+ this->PrintComment(out);
out << " = {";
- if(separator == "\n")
- {
+ if (separator == "\n") {
out << separator;
- }
- std::map<cmStdString, cmXCodeObject*>::iterator i;
- cmXCodeObject::Indent(3*indentFactor, out);
- out << "isa = " << PBXTypeNames[this->IsA] << ";" << separator;
- for(i = this->ObjectAttributes.begin();
- i != this->ObjectAttributes.end(); ++i)
- {
- cmXCodeObject* object = i->second;
- if(i->first != "isa")
- {
- cmXCodeObject::Indent(3*indentFactor, out);
- }
- else
- {
+ }
+ 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")
continue;
+
+ PrintAttribute(out, 3, separator, indentFactor, i->first, i->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,
+ const cmXCodeObject* object,
+ const cmXCodeObject* parent)
+{
+ cmXCodeObject::Indent(level * factor, out);
+ switch (object->TypeValue) {
+ case OBJECT_LIST: {
+ out << name << " = (";
+ if (parent->TypeValue != ATTRIBUTE_GROUP) {
+ out << separator;
}
- if(object->TypeValue == OBJECT_LIST)
- {
- out << i->first << " = (" << separator;
- for(unsigned int k = 0; k < i->second->List.size(); k++)
- {
- cmXCodeObject::Indent(4*indentFactor, out);
- out << i->second->List[k]->Id << " ";
- i->second->List[k]->PrintComment(out);
- out << "," << separator;
+ for (unsigned int i = 0; i < object->List.size(); ++i) {
+ if (object->List[i]->TypeValue == STRING) {
+ object->List[i]->PrintString(out);
+ if (i + 1 < object->List.size()) {
+ out << ",";
+ }
+ } else {
+ cmXCodeObject::Indent((level + 1) * factor, out);
+ out << object->List[i]->Id;
+ object->List[i]->PrintComment(out);
+ out << "," << separator;
}
- cmXCodeObject::Indent(3*indentFactor, out);
- out << ");" << separator;
}
- else if(object->TypeValue == ATTRIBUTE_GROUP)
- {
- std::map<cmStdString, cmXCodeObject*>::iterator j;
- out << i->first << " = {" << separator;
- for(j = object->ObjectAttributes.begin(); j !=
- object->ObjectAttributes.end(); ++j)
- {
- cmXCodeObject::Indent(4 *indentFactor, out);
-
- if(j->second->TypeValue == STRING)
- {
- cmXCodeObject::PrintString(out,j->first);
- out << " = ";
- j->second->PrintString(out);
- out << ";";
- }
- else if(j->second->TypeValue == OBJECT_LIST)
- {
- cmXCodeObject::PrintString(out,j->first);
- out << " = (";
- for(unsigned int k = 0; k < j->second->List.size(); k++)
- {
- if(j->second->List[k]->TypeValue == STRING)
- {
- j->second->List[k]->PrintString(out);
- out << ", ";
- }
- else
- {
- out << "List_" << k << "_TypeValue_IS_NOT_STRING, ";
- }
- }
- out << ");";
- }
- else
- {
- cmXCodeObject::PrintString(out,j->first);
- out << " = error_unexpected_TypeValue_" <<
- j->second->TypeValue << ";";
- }
+ if (parent->TypeValue != ATTRIBUTE_GROUP) {
+ cmXCodeObject::Indent(level * factor, out);
+ }
+ out << ");" << separator;
+ } break;
+ case ATTRIBUTE_GROUP: {
+ out << name << " = {";
+ if (separator == "\n") {
out << separator;
- }
- cmXCodeObject::Indent(3 *indentFactor, out);
- out << "};" << separator;
}
- else if(object->TypeValue == OBJECT_REF)
- {
- cmXCodeObject::PrintString(out,i->first);
+ 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);
+ }
+ cmXCodeObject::Indent(level * factor, out);
+ out << "};" << separator;
+ } break;
+
+ case OBJECT_REF: {
+ cmXCodeObject::PrintString(out, name);
out << " = " << object->Object->Id;
- if(object->Object->HasComment() && i->first != "remoteGlobalIDString")
- {
- out << " ";
+ if (object->Object->HasComment() && name != "remoteGlobalIDString") {
object->Object->PrintComment(out);
- }
- out << ";" << separator;
}
- else if(object->TypeValue == STRING)
- {
- cmXCodeObject::PrintString(out,i->first);
+ out << ";" << separator;
+ } break;
+
+ case STRING: {
+ cmXCodeObject::PrintString(out, name);
out << " = ";
object->PrintString(out);
out << ";" << separator;
- }
- else
- {
- out << "what is this?? " << i->first << "\n";
- }
+ } break;
+
+ default: {
+ break;
}
- cmXCodeObject::Indent(2*indentFactor, out);
- out << "};\n";
+ }
}
-//----------------------------------------------------------------------------
void cmXCodeObject::PrintList(std::vector<cmXCodeObject*> const& objs,
std::ostream& out)
{
cmXCodeObject::Indent(1, out);
out << "objects = {\n";
- for(unsigned int i = 0; i < objs.size(); ++i)
- {
- if(objs[i]->TypeValue == OBJECT)
- {
+ for (unsigned int i = 0; i < objs.size(); ++i) {
+ if (objs[i]->TypeValue == OBJECT) {
objs[i]->Print(out);
- }
}
+ }
cmXCodeObject::Indent(1, out);
out << "};\n";
}
-//----------------------------------------------------------------------------
void cmXCodeObject::CopyAttributes(cmXCodeObject* copy)
{
this->ObjectAttributes = copy->ObjectAttributes;
@@ -235,38 +220,36 @@ void cmXCodeObject::CopyAttributes(cmXCodeObject* copy)
this->Object = copy->Object;
}
-//----------------------------------------------------------------------------
-void cmXCodeObject::PrintString(std::ostream& os,cmStdString String)
+void cmXCodeObject::PrintString(std::ostream& os, std::string String)
{
// The string needs to be quoted if it contains any characters
// considered special by the Xcode project file parser.
- bool needQuote =
- (String.empty() ||
- String.find_first_of(" <>.+-=@$[],") != String.npos);
- const char* quote = needQuote? "\"" : "";
+ bool needQuote = (String.empty() || String.find("//") != std::string::npos ||
+ String.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "$_./") != std::string::npos);
+ const char* quote = needQuote ? "\"" : "";
// Print the string, quoted and escaped as necessary.
os << quote;
- for(std::string::const_iterator i = String.begin();
- i != String.end(); ++i)
- {
- if(*i == '"')
- {
- // Escape double-quotes.
+ for (std::string::const_iterator i = String.begin(); i != String.end();
+ ++i) {
+ if (*i == '"' || *i == '\\') {
+ // Escape double-quotes and backslashes.
os << '\\';
- }
- os << *i;
}
+ os << *i;
+ }
os << quote;
}
void cmXCodeObject::PrintString(std::ostream& os) const
{
- cmXCodeObject::PrintString(os,this->String);
+ cmXCodeObject::PrintString(os, this->String);
}
-//----------------------------------------------------------------------------
-void cmXCodeObject::SetString(const char* s)
+void cmXCodeObject::SetString(const std::string& s)
{
this->String = s;
}
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index b89f78cf3..b92e6e33e 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -1,170 +1,173 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmXCodeObject_h
#define cmXCodeObject_h
-#include "cmStandardIncludes.h"
-class cmTarget;
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+class cmGeneratorTarget;
class cmXCodeObject
{
public:
- enum Type { OBJECT_LIST, STRING, ATTRIBUTE_GROUP, OBJECT_REF, OBJECT };
- enum PBXType { PBXGroup, PBXBuildStyle, PBXProject, PBXHeadersBuildPhase,
- PBXSourcesBuildPhase, PBXFrameworksBuildPhase,
- PBXNativeTarget, PBXFileReference, PBXBuildFile,
- PBXContainerItemProxy, PBXTargetDependency,
- PBXShellScriptBuildPhase, PBXResourcesBuildPhase,
- PBXApplicationReference, PBXExecutableFileReference,
- PBXLibraryReference, PBXToolTarget, PBXLibraryTarget,
- PBXAggregateTarget,XCBuildConfiguration,XCConfigurationList,
- PBXCopyFilesBuildPhase,
- None
+ enum Type
+ {
+ OBJECT_LIST,
+ STRING,
+ ATTRIBUTE_GROUP,
+ OBJECT_REF,
+ OBJECT
+ };
+ enum PBXType
+ {
+ PBXGroup,
+ PBXBuildStyle,
+ PBXProject,
+ PBXHeadersBuildPhase,
+ PBXSourcesBuildPhase,
+ PBXFrameworksBuildPhase,
+ PBXNativeTarget,
+ PBXFileReference,
+ PBXBuildFile,
+ PBXContainerItemProxy,
+ PBXTargetDependency,
+ PBXShellScriptBuildPhase,
+ PBXResourcesBuildPhase,
+ PBXApplicationReference,
+ PBXExecutableFileReference,
+ PBXLibraryReference,
+ PBXToolTarget,
+ PBXLibraryTarget,
+ PBXAggregateTarget,
+ XCBuildConfiguration,
+ XCConfigurationList,
+ PBXCopyFilesBuildPhase,
+ None
+ };
+ class StringVec : public std::vector<std::string>
+ {
};
- class StringVec: public std::vector<cmStdString> {};
static const char* PBXTypeNames[];
virtual ~cmXCodeObject();
cmXCodeObject(PBXType ptype, Type type);
- Type GetType() { return this->TypeValue;}
- PBXType GetIsA() { return this->IsA;}
+ Type GetType() const { return this->TypeValue; }
+ PBXType GetIsA() const { return this->IsA; }
- void SetString(const char* s);
- const char* GetString()
- {
- return this->String.c_str();
- }
+ bool IsEmpty() const;
- void AddAttribute(const char* name, cmXCodeObject* value)
- {
- this->ObjectAttributes[name] = value;
- }
+ void SetString(const std::string& s);
+ const std::string& GetString() const { return this->String; }
- void SetObject(cmXCodeObject* value)
- {
- this->Object = value;
- }
- cmXCodeObject* GetObject()
- {
- return this->Object;
- }
- void AddObject(cmXCodeObject* value)
- {
- this->List.push_back(value);
+ void AddAttribute(const std::string& name, cmXCodeObject* value)
+ {
+ this->ObjectAttributes[name] = value;
+ }
+
+ void AddAttributeIfNotEmpty(const std::string& name, cmXCodeObject* value)
+ {
+ if (value && !value->IsEmpty()) {
+ AddAttribute(name, value);
}
- bool HasObject(cmXCodeObject* o)
+ }
+
+ 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());
+ return !(std::find(this->List.begin(), this->List.end(), o) ==
+ this->List.end());
}
void AddUniqueObject(cmXCodeObject* value)
{
- if(std::find(this->List.begin(), this->List.end(), value)
- == this->List.end())
- {
+ if (std::find(this->List.begin(), this->List.end(), value) ==
+ this->List.end()) {
this->List.push_back(value);
- }
+ }
}
static void Indent(int level, std::ostream& out);
void Print(std::ostream& out);
- virtual void PrintComment(std::ostream&) {};
+ void PrintAttribute(std::ostream& out, const int level,
+ const std::string separator, const int factor,
+ const std::string& name, const cmXCodeObject* object,
+ const cmXCodeObject* parent);
+ virtual void PrintComment(std::ostream&) {}
- static void PrintList(std::vector<cmXCodeObject*> const&,
- std::ostream& out);
- const char* GetId()
- {
- return this->Id.c_str();
- }
- void SetId(const char* id)
- {
- this->Id = id;
- }
- cmTarget* GetTarget()
- {
- return this->Target;
- }
- void SetTarget(cmTarget* t)
- {
- this->Target = t;
- }
- const char* GetComment() {return this->Comment.c_str();}
- bool HasComment() { return (this->Comment.size() != 0);}
- cmXCodeObject* GetObject(const char* name)
- {
- if(this->ObjectAttributes.count(name))
- {
- return this->ObjectAttributes[name];
- }
- return 0;
+ static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out);
+ const std::string& GetId() const { return this->Id; }
+ void SetId(const std::string& id) { this->Id = id; }
+ cmGeneratorTarget* GetTarget() const { return this->Target; }
+ void SetTarget(cmGeneratorTarget* t) { this->Target = t; }
+ const std::string& GetComment() const { return this->Comment; }
+ 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);
+ if (i != this->ObjectAttributes.end()) {
+ return i->second;
}
- // serach the attribute list for an object of the specified type
- cmXCodeObject* GetObject(cmXCodeObject::PBXType t)
- {
- for(std::vector<cmXCodeObject*>::iterator i = this->List.begin();
- i != this->List.end(); ++i)
- {
- cmXCodeObject* o = *i;
- if(o->IsA == t)
- {
- return o;
- }
- }
- return 0;
+ return 0;
+ }
+ // 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;
+ if (o->IsA == t) {
+ return o;
+ }
}
+ return 0;
+ }
- void CopyAttributes(cmXCodeObject* );
+ void CopyAttributes(cmXCodeObject*);
- void AddDependLibrary(const char* configName,
- const char* l)
- {
- if(!configName)
- {
- configName = "";
- }
- this->DependLibraries[configName].push_back(l);
- }
- std::map<cmStdString, StringVec> const& GetDependLibraries()
- {
- return this->DependLibraries;
- }
- void AddDependTarget(const char* configName,
- const char* tName)
- {
- if(!configName)
- {
- configName = "";
- }
- this->DependTargets[configName].push_back(tName);
- }
- std::map<cmStdString, StringVec> const& GetDependTargets()
- {
+ void AddDependLibrary(const std::string& configName, const std::string& l)
+ {
+ this->DependLibraries[configName].push_back(l);
+ }
+ std::map<std::string, StringVec> const& GetDependLibraries() const
+ {
+ return this->DependLibraries;
+ }
+ void AddDependTarget(const std::string& configName, const std::string& tName)
+ {
+ this->DependTargets[configName].push_back(tName);
+ }
+ std::map<std::string, StringVec> const& GetDependTargets() const
+ {
return this->DependTargets;
- }
- std::vector<cmXCodeObject*> const& GetObjectList() { return this->List;}
- void SetComment(const char* c) { this->Comment = c;}
- static void PrintString(std::ostream& os,cmStdString String);
+ }
+ std::vector<cmXCodeObject*> const& GetObjectList() const
+ {
+ return this->List;
+ }
+ void SetComment(const std::string& c) { this->Comment = c; }
+ static void PrintString(std::ostream& os, std::string String);
+
protected:
void PrintString(std::ostream& os) const;
- cmTarget* Target;
+ cmGeneratorTarget* Target;
Type TypeValue;
- cmStdString Id;
+ std::string Id;
PBXType IsA;
int Version;
- cmStdString Comment;
- cmStdString String;
+ std::string Comment;
+ std::string String;
cmXCodeObject* Object;
std::vector<cmXCodeObject*> List;
- std::map<cmStdString, StringVec> DependLibraries;
- std::map<cmStdString, StringVec> DependTargets;
- std::map<cmStdString, cmXCodeObject*> ObjectAttributes;
+ std::map<std::string, StringVec> DependLibraries;
+ std::map<std::string, StringVec> DependTargets;
+ std::map<std::string, cmXCodeObject*> ObjectAttributes;
};
#endif
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
new file mode 100644
index 000000000..5c22531d4
--- /dev/null
+++ b/Source/cmXCodeScheme.cxx
@@ -0,0 +1,227 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmXCodeScheme.h"
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmXMLSafe.h"
+
+cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj,
+ const std::vector<std::string>& configList,
+ unsigned int xcVersion)
+ : Target(xcObj)
+ , TargetName(xcObj->GetTarget()->GetName())
+ , BuildableName(xcObj->GetTarget()->GetFullName())
+ , TargetId(xcObj->GetId())
+ , ConfigList(configList)
+ , XcodeVersion(xcVersion)
+{
+}
+
+void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
+ const std::string& container)
+{
+ // Create shared scheme sub-directory tree
+ //
+ std::string xcodeSchemeDir = xcProjDir;
+ xcodeSchemeDir += "/xcshareddata/xcschemes";
+ cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str());
+
+ std::string xcodeSchemeFile = xcodeSchemeDir;
+ xcodeSchemeFile += "/";
+ xcodeSchemeFile += this->TargetName;
+ xcodeSchemeFile += ".xcscheme";
+
+ cmGeneratedFileStream fout(xcodeSchemeFile.c_str());
+ fout.SetCopyIfDifferent(true);
+ if (!fout) {
+ return;
+ }
+
+ WriteXCodeXCScheme(fout, container);
+}
+
+void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
+ const std::string& container)
+{
+ cmXMLWriter xout(fout);
+ xout.SetIndentationElement(std::string(3, ' '));
+ xout.StartDocument();
+
+ xout.StartElement("Scheme");
+ xout.BreakAttributes();
+ xout.Attribute("LastUpgradeVersion", WriteVersionString());
+ xout.Attribute("version", "1.3");
+
+ WriteBuildAction(xout, container);
+ WriteTestAction(xout, FindConfiguration("Debug"));
+ WriteLaunchAction(xout, FindConfiguration("Debug"), container);
+ WriteProfileAction(xout, FindConfiguration("Release"));
+ WriteAnalyzeAction(xout, FindConfiguration("Debug"));
+ WriteArchiveAction(xout, FindConfiguration("Release"));
+
+ xout.EndElement();
+}
+
+void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
+ const std::string& container)
+{
+ xout.StartElement("BuildAction");
+ xout.BreakAttributes();
+ xout.Attribute("parallelizeBuildables", "YES");
+ xout.Attribute("buildImplicitDependencies", "YES");
+
+ xout.StartElement("BuildActionEntries");
+ xout.StartElement("BuildActionEntry");
+ xout.BreakAttributes();
+ xout.Attribute("buildForTesting", "YES");
+ xout.Attribute("buildForRunning", "YES");
+ xout.Attribute("buildForProfiling", "YES");
+ 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();
+
+ xout.EndElement(); // BuildActionEntry
+ xout.EndElement(); // BuildActionEntries
+ xout.EndElement(); // BuildAction
+}
+
+void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
+ std::string configuration)
+{
+ xout.StartElement("TestAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.Attribute("selectedDebuggerIdentifier",
+ "Xcode.DebuggerFoundation.Debugger.LLDB");
+ xout.Attribute("selectedLauncherIdentifier",
+ "Xcode.DebuggerFoundation.Launcher.LLDB");
+ xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
+
+ xout.StartElement("Testables");
+ xout.EndElement();
+
+ xout.StartElement("AdditionalOptions");
+ xout.EndElement();
+
+ xout.EndElement(); // TestAction
+}
+
+void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
+ std::string configuration,
+ const std::string& container)
+{
+ xout.StartElement("LaunchAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.Attribute("selectedDebuggerIdentifier",
+ "Xcode.DebuggerFoundation.Debugger.LLDB");
+ xout.Attribute("selectedLauncherIdentifier",
+ "Xcode.DebuggerFoundation.Launcher.LLDB");
+ xout.Attribute("launchStyle", "0");
+ xout.Attribute("useCustomWorkingDirectory", "NO");
+ xout.Attribute("ignoresPersistentStateOnLaunch", "NO");
+ xout.Attribute("debugDocumentVersioning", "YES");
+ xout.Attribute("debugServiceExtension", "internal");
+ xout.Attribute("allowLocationSimulation", "YES");
+
+ if (IsExecutable(this->Target)) {
+ xout.StartElement("BuildableProductRunnable");
+ xout.BreakAttributes();
+ xout.Attribute("runnableDebuggingMode", "0");
+
+ } else {
+ 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();
+
+ xout.EndElement(); // MacroExpansion
+
+ xout.StartElement("AdditionalOptions");
+ xout.EndElement();
+
+ xout.EndElement(); // LaunchAction
+}
+
+void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
+ std::string configuration)
+{
+ xout.StartElement("ProfileAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
+ xout.Attribute("savedToolIdentifier", "");
+ xout.Attribute("useCustomWorkingDirectory", "NO");
+ xout.Attribute("debugDocumentVersioning", "YES");
+ xout.EndElement();
+}
+
+void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout,
+ std::string configuration)
+{
+ xout.StartElement("AnalyzeAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.EndElement();
+}
+
+void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout,
+ std::string configuration)
+{
+ xout.StartElement("ArchiveAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.Attribute("revealArchiveInOrganizer", "YES");
+ xout.EndElement();
+}
+
+std::string cmXCodeScheme::WriteVersionString()
+{
+ std::ostringstream v;
+ v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10;
+ return v.str();
+}
+
+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)
+ return this->ConfigList[0];
+
+ return name;
+}
+
+bool cmXCodeScheme::IsExecutable(const cmXCodeObject* target)
+{
+ cmGeneratorTarget* gt = target->GetTarget();
+ if (!gt) {
+ cmSystemTools::Error("Error no target on xobject\n");
+ return false;
+ }
+
+ return gt->GetType() == cmStateEnums::EXECUTABLE;
+}
diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h
new file mode 100644
index 000000000..379afed42
--- /dev/null
+++ b/Source/cmXCodeScheme.h
@@ -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. */
+#ifndef cmXCodeScheme_h
+#define cmXCodeScheme_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmGlobalXCodeGenerator.h"
+#include "cmSystemTools.h"
+#include "cmXCodeObject.h"
+#include "cmXMLWriter.h"
+
+/** \class cmXCodeScheme
+ * \brief Write shared schemes for native targets in Xcode project.
+ */
+class cmXCodeScheme
+{
+public:
+ cmXCodeScheme(cmXCodeObject* xcObj,
+ const std::vector<std::string>& configList,
+ unsigned int xcVersion);
+
+ void WriteXCodeSharedScheme(const std::string& xcProjDir,
+ const std::string& container);
+
+private:
+ const cmXCodeObject* const Target;
+ 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,
+ 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);
+
+ std::string WriteVersionString();
+ std::string FindConfiguration(const std::string& name);
+
+ static bool IsExecutable(const cmXCodeObject* target);
+};
+
+#endif
diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx
index 882fc172e..18afbf370 100644
--- a/Source/cmXMLParser.cxx
+++ b/Source/cmXMLParser.cxx
@@ -1,76 +1,63 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXMLParser.h"
-#include <cm_expat.h>
+#include "cm_expat.h"
+#include "cmsys/FStream.hxx"
#include <ctype.h>
+#include <iostream>
+#include <sstream>
+#include <string.h>
-//----------------------------------------------------------------------------
cmXMLParser::cmXMLParser()
{
- this->Parser = 0;
+ this->Parser = CM_NULLPTR;
this->ParseError = 0;
+ this->ReportCallback = CM_NULLPTR;
+ this->ReportCallbackData = CM_NULLPTR;
}
-//----------------------------------------------------------------------------
cmXMLParser::~cmXMLParser()
{
- if ( this->Parser )
- {
+ if (this->Parser) {
this->CleanupParser();
- }
+ }
}
-//----------------------------------------------------------------------------
int cmXMLParser::Parse(const char* string)
{
return (int)this->InitializeParser() &&
- this->ParseChunk(string, strlen(string)) &&
- this->CleanupParser();
+ this->ParseChunk(string, strlen(string)) && this->CleanupParser();
}
int cmXMLParser::ParseFile(const char* file)
{
- if ( !file )
- {
+ if (!file) {
return 0;
- }
+ }
- std::ifstream ifs(file);
- if ( !ifs )
- {
+ cmsys::ifstream ifs(file);
+ if (!ifs) {
return 0;
- }
+ }
- cmOStringStream str;
+ std::ostringstream str;
str << ifs.rdbuf();
return this->Parse(str.str().c_str());
}
-//----------------------------------------------------------------------------
int cmXMLParser::InitializeParser()
{
- if ( this->Parser )
- {
+ if (this->Parser) {
std::cerr << "Parser already initialized" << std::endl;
this->ParseError = 1;
return 0;
- }
+ }
// Create the expat XML parser.
- this->Parser = XML_ParserCreate(0);
+ this->Parser = XML_ParserCreate(CM_NULLPTR);
XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
- &cmXMLParserStartElement,
- &cmXMLParserEndElement);
+ &cmXMLParserStartElement, &cmXMLParserEndElement);
XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
&cmXMLParserCharacterDataHandler);
XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);
@@ -78,123 +65,101 @@ int cmXMLParser::InitializeParser()
return 1;
}
-//----------------------------------------------------------------------------
int cmXMLParser::ParseChunk(const char* inputString,
std::string::size_type length)
{
- if ( !this->Parser )
- {
+ if (!this->Parser) {
std::cerr << "Parser not initialized" << std::endl;
this->ParseError = 1;
return 0;
- }
+ }
int res;
res = this->ParseBuffer(inputString, length);
- if ( res == 0 )
- {
+ if (res == 0) {
this->ParseError = 1;
- }
+ }
return res;
}
-//----------------------------------------------------------------------------
int cmXMLParser::CleanupParser()
{
- if ( !this->Parser )
- {
+ if (!this->Parser) {
std::cerr << "Parser not initialized" << std::endl;
this->ParseError = 1;
return 0;
- }
+ }
int result = !this->ParseError;
- if(result)
- {
+ if (result) {
// Tell the expat XML parser about the end-of-input.
- if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
- {
+ if (!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1)) {
this->ReportXmlParseError();
result = 0;
- }
}
+ }
// Clean up the parser.
XML_ParserFree(static_cast<XML_Parser>(this->Parser));
- this->Parser = 0;
+ this->Parser = CM_NULLPTR;
return result;
}
-//----------------------------------------------------------------------------
int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count)
{
// Pass the buffer to the expat XML parser.
- if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer,
- static_cast<int>(count), 0))
- {
+ if (!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer,
+ static_cast<int>(count), 0)) {
this->ReportXmlParseError();
return 0;
- }
+ }
return 1;
}
-//----------------------------------------------------------------------------
int cmXMLParser::ParseBuffer(const char* buffer)
{
return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
}
-//----------------------------------------------------------------------------
int cmXMLParser::ParsingComplete()
{
// Default behavior is to parse to end of stream.
return 0;
}
-//----------------------------------------------------------------------------
-void cmXMLParser::StartElement(const char * name,
- const char ** /*atts*/)
+void cmXMLParser::StartElement(const std::string& name, const char** /*atts*/)
{
std::cout << "Start element: " << name << std::endl;
}
-//----------------------------------------------------------------------------
-void cmXMLParser::EndElement(const char * name)
+void cmXMLParser::EndElement(const std::string& name)
{
std::cout << "End element: " << name << std::endl;
}
-//----------------------------------------------------------------------------
void cmXMLParser::CharacterDataHandler(const char* /*inData*/,
- int /*inLength*/)
+ int /*inLength*/)
{
}
-//----------------------------------------------------------------------------
int cmXMLParser::IsSpace(char c)
{
return isspace(c);
}
-//----------------------------------------------------------------------------
const char* cmXMLParser::FindAttribute(const char** atts,
const char* attribute)
{
- if(atts && attribute)
- {
- for(const char** a = atts; *a && *(a+1); a += 2)
- {
- if(strcmp(*a, attribute) == 0)
- {
- return *(a+1);
- }
+ if (atts && attribute) {
+ for (const char** a = atts; *a && *(a + 1); a += 2) {
+ if (strcmp(*a, attribute) == 0) {
+ return *(a + 1);
}
}
- return 0;
+ }
+ return CM_NULLPTR;
}
-//----------------------------------------------------------------------------
-void cmXMLParserStartElement(void* parser, const char *name,
- const char **atts)
+void cmXMLParserStartElement(void* parser, const char* name, const char** atts)
{
// Begin element handler that is registered with the XML_Parser.
// This just casts the user data to a cmXMLParser and calls
@@ -202,17 +167,15 @@ void cmXMLParserStartElement(void* parser, const char *name,
static_cast<cmXMLParser*>(parser)->StartElement(name, atts);
}
-//----------------------------------------------------------------------------
-void cmXMLParserEndElement(void* parser, const char *name)
+void cmXMLParserEndElement(void* parser, const char* name)
{
// End element handler that is registered with the XML_Parser. This
// just casts the user data to a cmXMLParser and calls EndElement.
static_cast<cmXMLParser*>(parser)->EndElement(name);
}
-//----------------------------------------------------------------------------
void cmXMLParserCharacterDataHandler(void* parser, const char* data,
- int length)
+ int length)
{
// Character data handler that is registered with the XML_Parser.
// This just casts the user data to a cmXMLParser and calls
@@ -220,7 +183,6 @@ void cmXMLParserCharacterDataHandler(void* parser, const char* data,
static_cast<cmXMLParser*>(parser)->CharacterDataHandler(data, length);
}
-//----------------------------------------------------------------------------
void cmXMLParser::ReportXmlParseError()
{
XML_Parser parser = static_cast<XML_Parser>(this->Parser);
@@ -229,9 +191,12 @@ void cmXMLParser::ReportXmlParseError()
XML_ErrorString(XML_GetErrorCode(parser)));
}
-//----------------------------------------------------------------------------
-void cmXMLParser::ReportError(int line, int, const char* msg)
+void cmXMLParser::ReportError(int line, int /*unused*/, const char* msg)
{
- std::cerr << "Error parsing XML in stream at line "
- << line << ": " << msg << std::endl;
+ if (this->ReportCallback) {
+ this->ReportCallback(line, msg, this->ReportCallbackData);
+ } else {
+ std::cerr << "Error parsing XML in stream at line " << line << ": " << msg
+ << std::endl;
+ }
}
diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h
index d916075e5..98ba04956 100644
--- a/Source/cmXMLParser.h
+++ b/Source/cmXMLParser.h
@@ -1,24 +1,16 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmXMLParser_h
#define cmXMLParser_h
-#include "cmStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-extern "C"
-{
- void cmXMLParserStartElement(void*, const char*, const char**);
- void cmXMLParserEndElement(void*, const char*);
- void cmXMLParserCharacterDataHandler(void*, const char*, int);
+#include <string>
+
+extern "C" {
+void cmXMLParserStartElement(void*, const char*, const char**);
+void cmXMLParserEndElement(void*, const char*);
+void cmXMLParserCharacterDataHandler(void*, const char*, int);
}
/** \class cmXMLParser
@@ -50,13 +42,21 @@ public:
virtual int ParseChunk(const char* inputString,
std::string::size_type length);
virtual int CleanupParser();
+ typedef void (*ReportFunction)(int, const char*, void*);
+ void SetErrorCallback(ReportFunction f, void* d)
+ {
+ this->ReportCallback = f;
+ this->ReportCallbackData = d;
+ }
protected:
//! This variable is true if there was a parse error while parsing in
- //chunks.
+ // chunks.
int ParseError;
+ ReportFunction ReportCallback;
+ void* ReportCallbackData;
- //1 Expat parser structure. Exists only during call to Parse().
+ // 1 Expat parser structure. Exists only during call to Parse().
void* Parser;
/**
@@ -74,11 +74,11 @@ protected:
* element. atts = Null-terminated array of attribute name/value pairs.
* Even indices are attribute names, and odd indices are values.
*/
- virtual void StartElement(const char* name, const char** atts);
+ virtual void StartElement(const std::string& name, const char** atts);
//! Called at the end of an element in the XML source opened when
- //StartElement was called.
- virtual void EndElement(const char* name);
+ // StartElement was called.
+ virtual void EndElement(const std::string& name);
//! Called when there is character data to handle.
virtual void CharacterDataHandler(const char* data, int length);
@@ -94,8 +94,7 @@ protected:
static int IsSpace(char c);
//! Send the given buffer to the XML parser.
- virtual int ParseBuffer(const char* buffer,
- std::string::size_type length);
+ virtual int ParseBuffer(const char* buffer, std::string::size_type length);
//! Send the given c-style string to the XML parser.
int ParseBuffer(const char* buffer);
diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx
index 72fdc3466..d9bdc023b 100644
--- a/Source/cmXMLSafe.cxx
+++ b/Source/cmXMLSafe.cxx
@@ -1,102 +1,90 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXMLSafe.h"
#include "cm_utf8.h"
-#include <cmsys/ios/iostream>
-#include <cmsys/ios/sstream>
-
-#include <string.h>
+#include <sstream>
#include <stdio.h>
+#include <string.h>
-//----------------------------------------------------------------------------
-cmXMLSafe::cmXMLSafe(const char* s):
- Data(s),
- Size(static_cast<unsigned long>(strlen(s))),
- DoQuotes(true)
+cmXMLSafe::cmXMLSafe(const char* s)
+ : Data(s)
+ , Size(static_cast<unsigned long>(strlen(s)))
+ , DoQuotes(true)
{
}
-//----------------------------------------------------------------------------
-cmXMLSafe::cmXMLSafe(cmsys_stl::string const& s):
- Data(s.c_str()),
- Size(static_cast<unsigned long>(s.length())),
- DoQuotes(true)
+cmXMLSafe::cmXMLSafe(std::string const& s)
+ : Data(s.c_str())
+ , Size(static_cast<unsigned long>(s.length()))
+ , DoQuotes(true)
{
}
-//----------------------------------------------------------------------------
cmXMLSafe& cmXMLSafe::Quotes(bool b)
{
this->DoQuotes = b;
return *this;
}
-//----------------------------------------------------------------------------
-cmsys_stl::string cmXMLSafe::str()
+std::string cmXMLSafe::str()
{
- cmsys_ios::ostringstream ss;
+ std::ostringstream ss;
ss << *this;
return ss.str();
}
-//----------------------------------------------------------------------------
-cmsys_ios::ostream& operator<<(cmsys_ios::ostream& os, cmXMLSafe const& self)
+std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self)
{
char const* first = self.Data;
char const* last = self.Data + self.Size;
- while(first != last)
- {
+ while (first != last) {
unsigned int ch;
- if(const char* next = cm_utf8_decode_character(first, last, &ch))
- {
+ if (const char* next = cm_utf8_decode_character(first, last, &ch)) {
// http://www.w3.org/TR/REC-xml/#NT-Char
- if((ch >= 0x20 && ch <= 0xD7FF) ||
- (ch >= 0xE000 && ch <= 0xFFFD) ||
- (ch >= 0x10000 && ch <= 0x10FFFF) ||
- ch == 0x9 || ch == 0xA || ch == 0xD)
- {
- switch(ch)
- {
+ if ((ch >= 0x20 && ch <= 0xD7FF) || (ch >= 0xE000 && ch <= 0xFFFD) ||
+ (ch >= 0x10000 && ch <= 0x10FFFF) || ch == 0x9 || ch == 0xA ||
+ ch == 0xD) {
+ switch (ch) {
// Escape XML control characters.
- case '&': os << "&amp;"; break;
- case '<': os << "&lt;"; break;
- case '>': os << "&gt;"; break;
- case '"': os << (self.DoQuotes? "&quot;" : "\""); break;
- case '\'': os << (self.DoQuotes? "&apos;" : "'"); break;
- case '\r': break; // Ignore CR
+ case '&':
+ os << "&amp;";
+ break;
+ case '<':
+ os << "&lt;";
+ break;
+ case '>':
+ os << "&gt;";
+ break;
+ case '"':
+ os << (self.DoQuotes ? "&quot;" : "\"");
+ break;
+ case '\'':
+ os << (self.DoQuotes ? "&apos;" : "'");
+ break;
+ case '\r':
+ break; // Ignore CR
// Print the UTF-8 character.
- default: os.write(first, next-first); break;
- }
+ default:
+ os.write(first, next - first);
+ break;
}
- else
- {
+ } else {
// Use a human-readable hex value for this invalid character.
char buf[16];
sprintf(buf, "%X", ch);
os << "[NON-XML-CHAR-0x" << buf << "]";
- }
+ }
first = next;
- }
- else
- {
+ } else {
ch = static_cast<unsigned char>(*first++);
// Use a human-readable hex value for this invalid byte.
char buf[16];
sprintf(buf, "%X", ch);
os << "[NON-UTF-8-BYTE-0x" << buf << "]";
- }
}
+ }
return os;
}
diff --git a/Source/cmXMLSafe.h b/Source/cmXMLSafe.h
index cba9f390d..9aaf2d157 100644
--- a/Source/cmXMLSafe.h
+++ b/Source/cmXMLSafe.h
@@ -1,19 +1,12 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmXMLSafe_h
#define cmXMLSafe_h
-#include <cmsys/stl/string>
-#include <cmsys/ios/iosfwd>
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <string>
/** \class cmXMLSafe
* \brief Write strings to XML with proper escapes
@@ -24,7 +17,7 @@ public:
/** Construct with the data to be written. This assumes the data
will exist for the duration of this object's life. */
cmXMLSafe(const char* s);
- cmXMLSafe(cmsys_stl::string const& s);
+ cmXMLSafe(std::string const& s);
/** Specify whether to escape quotes too. This is needed when
writing the content of an attribute value. By default quotes
@@ -32,13 +25,13 @@ public:
cmXMLSafe& Quotes(bool b = true);
/** Get the escaped data as a string. */
- cmsys_stl::string str();
+ std::string str();
+
private:
char const* Data;
unsigned long Size;
bool DoQuotes;
- friend cmsys_ios::ostream& operator<<(cmsys_ios::ostream&,
- cmXMLSafe const&);
+ friend std::ostream& operator<<(std::ostream&, cmXMLSafe const&);
};
#endif
diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx
new file mode 100644
index 000000000..3cbc70dbd
--- /dev/null
+++ b/Source/cmXMLWriter.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 "cmXMLWriter.h"
+
+#include "cmsys/FStream.hxx"
+#include <cassert>
+
+cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
+ : Output(output)
+ , IndentationElement(1, '\t')
+ , Level(level)
+ , ElementOpen(false)
+ , BreakAttrib(false)
+ , IsContent(false)
+{
+}
+
+cmXMLWriter::~cmXMLWriter()
+{
+ assert(this->Elements.empty());
+}
+
+void cmXMLWriter::StartDocument(const char* encoding)
+{
+ this->Output << "<?xml version=\"1.0\" encoding=\"" << encoding << "\"?>";
+}
+
+void cmXMLWriter::EndDocument()
+{
+ assert(this->Elements.empty());
+ this->Output << '\n';
+}
+
+void cmXMLWriter::StartElement(std::string const& name)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << '<' << name;
+ this->Elements.push(name);
+ this->ElementOpen = true;
+ this->BreakAttrib = false;
+}
+
+void cmXMLWriter::EndElement()
+{
+ assert(!this->Elements.empty());
+ if (this->ElementOpen) {
+ this->Output << "/>";
+ } else {
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1);
+ this->IsContent = false;
+ this->Output << "</" << this->Elements.top() << '>';
+ }
+ this->Elements.pop();
+ this->ElementOpen = false;
+}
+
+void cmXMLWriter::Element(const char* name)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << '<' << name << "/>";
+}
+
+void cmXMLWriter::BreakAttributes()
+{
+ this->BreakAttrib = true;
+}
+
+void cmXMLWriter::Comment(const char* comment)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << "<!-- " << comment << " -->";
+}
+
+void cmXMLWriter::CData(std::string const& data)
+{
+ this->PreContent();
+ this->Output << "<![CDATA[" << data << "]]>";
+}
+
+void cmXMLWriter::Doctype(const char* doctype)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << "<!DOCTYPE " << doctype << ">";
+}
+
+void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << "<?" << target << ' ' << data << "?>";
+}
+
+void cmXMLWriter::FragmentFile(const char* fname)
+{
+ this->CloseStartElement();
+ cmsys::ifstream fin(fname, std::ios::in | std::ios::binary);
+ this->Output << fin.rdbuf();
+}
+
+void cmXMLWriter::SetIndentationElement(std::string const& element)
+{
+ this->IndentationElement = element;
+}
+
+void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
+{
+ if (condition) {
+ this->Output << '\n';
+ for (std::size_t i = 0; i < indent + this->Level; ++i) {
+ this->Output << this->IndentationElement;
+ }
+ }
+}
+
+void cmXMLWriter::PreAttribute()
+{
+ assert(this->ElementOpen);
+ this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ if (!this->BreakAttrib) {
+ this->Output << ' ';
+ }
+}
+
+void cmXMLWriter::PreContent()
+{
+ this->CloseStartElement();
+ this->IsContent = true;
+}
+
+void cmXMLWriter::CloseStartElement()
+{
+ if (this->ElementOpen) {
+ this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ this->Output << '>';
+ this->ElementOpen = false;
+ }
+}
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
new file mode 100644
index 000000000..ed76a88c7
--- /dev/null
+++ b/Source/cmXMLWriter.h
@@ -0,0 +1,118 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmXMLWiter_h
+#define cmXMLWiter_h
+
+#include "cmConfigure.h"
+
+#include "cmXMLSafe.h"
+
+#include <ostream>
+#include <stack>
+#include <string>
+#include <vector>
+
+class cmXMLWriter
+{
+ CM_DISABLE_COPY(cmXMLWriter)
+
+public:
+ cmXMLWriter(std::ostream& output, std::size_t level = 0);
+ ~cmXMLWriter();
+
+ void StartDocument(const char* encoding = "UTF-8");
+ void EndDocument();
+
+ void StartElement(std::string const& name);
+ void EndElement();
+
+ void BreakAttributes();
+
+ template <typename T>
+ void Attribute(const char* name, T const& value)
+ {
+ this->PreAttribute();
+ this->Output << name << "=\"" << SafeAttribute(value) << '"';
+ }
+
+ void Element(const char* name);
+
+ template <typename T>
+ void Element(std::string const& name, T const& value)
+ {
+ this->StartElement(name);
+ this->Content(value);
+ this->EndElement();
+ }
+
+ template <typename T>
+ void Content(T const& content)
+ {
+ this->PreContent();
+ this->Output << SafeContent(content);
+ }
+
+ void Comment(const char* comment);
+
+ void CData(std::string const& data);
+
+ void Doctype(const char* doctype);
+
+ void ProcessingInstruction(const char* target, const char* data);
+
+ void FragmentFile(const char* fname);
+
+ void SetIndentationElement(std::string const& element);
+
+private:
+ void ConditionalLineBreak(bool condition, std::size_t indent);
+
+ void PreAttribute();
+ void PreContent();
+
+ void CloseStartElement();
+
+private:
+ static cmXMLSafe SafeAttribute(const char* value)
+ {
+ return cmXMLSafe(value);
+ }
+
+ static cmXMLSafe SafeAttribute(std::string const& value)
+ {
+ return cmXMLSafe(value);
+ }
+
+ template <typename T>
+ static T SafeAttribute(T value)
+ {
+ return value;
+ }
+
+ static cmXMLSafe SafeContent(const char* value)
+ {
+ return cmXMLSafe(value).Quotes(false);
+ }
+
+ static cmXMLSafe SafeContent(std::string const& value)
+ {
+ return cmXMLSafe(value).Quotes(false);
+ }
+
+ template <typename T>
+ static T SafeContent(T value)
+ {
+ return value;
+ }
+
+private:
+ std::ostream& Output;
+ std::stack<std::string, std::vector<std::string> > Elements;
+ std::string IndentationElement;
+ std::size_t Level;
+ bool ElementOpen;
+ bool BreakAttrib;
+ bool IsContent;
+};
+
+#endif
diff --git a/Source/kwsys/auto_ptr.hxx.in b/Source/cm_auto_ptr.hxx
index ad9654cb4..773602af9 100644
--- a/Source/kwsys/auto_ptr.hxx.in
+++ b/Source/cm_auto_ptr.hxx
@@ -1,34 +1,34 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* 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
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_auto_ptr_hxx
-#define @KWSYS_NAMESPACE@_auto_ptr_hxx
+#ifdef CMake_HAVE_CXX_AUTO_PTR
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
+#include <memory>
+#define CM_AUTO_PTR std::auto_ptr
-// The HP compiler and VS6 cannot handle the conversions necessary to use
+#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) || (defined(_MSC_VER) && _MSC_VER <= 1200)
-# define @KWSYS_NAMESPACE@_AUTO_PTR_REF 0
-# define @KWSYS_NAMESPACE@_AUTO_PTR_CONST const
-# define @KWSYS_NAMESPACE@_AUTO_PTR_CAST(a) cast(a)
+#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 @KWSYS_NAMESPACE@_AUTO_PTR_REF 1
-# define @KWSYS_NAMESPACE@_AUTO_PTR_CONST
-# define @KWSYS_NAMESPACE@_AUTO_PTR_CAST(a) a
+#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
@@ -36,24 +36,24 @@
// 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
+#if __has_warning("-Wdeprecated")
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated"
+#endif
#endif
-namespace @KWSYS_NAMESPACE@
-{
+namespace cm {
-template <class X> class auto_ptr;
+template <class X>
+class auto_ptr;
-#if @KWSYS_NAMESPACE@_AUTO_PTR_REF
-namespace detail
-{
+#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
+template <class Y>
+struct auto_ptr_ref
{
Y* p_;
@@ -62,7 +62,10 @@ template <class Y> struct auto_ptr_ref
// 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) {}
+ auto_ptr_ref(Y* p, int)
+ : p_(p)
+ {
+ }
};
}
#endif
@@ -71,10 +74,12 @@ template <class Y> struct auto_ptr_ref
template <class X>
class auto_ptr
{
-#if !@KWSYS_NAMESPACE@_AUTO_PTR_REF
+#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); }
+ {
+ return const_cast<auto_ptr<Y>&>(a);
+ }
#endif
/** The pointer to the object held. */
@@ -87,19 +92,19 @@ public:
/** 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> @KWSYS_NAMESPACE@_AUTO_PTR_CONST& a) throw():
- x_(@KWSYS_NAMESPACE@_AUTO_PTR_CAST(a).release())
- {
- }
+ 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> @KWSYS_NAMESPACE@_AUTO_PTR_CONST& a) throw()
- {
- this->reset(@KWSYS_NAMESPACE@_AUTO_PTR_CAST(a).release());
- return *this;
- }
+ 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
@@ -107,113 +112,109 @@ public:
*
* auto_ptr<X> ptr(new X());
*/
- explicit auto_ptr(X* p=0) throw(): x_(p)
- {
- }
+ 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 @KWSYS_NAMESPACE@_AUTO_PTR_CONST& a) throw():
- x_(@KWSYS_NAMESPACE@_AUTO_PTR_CAST(a).release())
- {
- }
+ 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 @KWSYS_NAMESPACE@_AUTO_PTR_CONST& a) throw()
- {
- this->reset(@KWSYS_NAMESPACE@_AUTO_PTR_CAST(a).release());
- return *this;
- }
+ 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_;
- }
+ X& operator*() const throw() { return *this->x_; }
/** Return a pointer to the object held. */
- X* operator->() const throw()
- {
- return this->x_;
- }
+ X* operator->() const throw() { return this->x_; }
/** Return a pointer to the object held. */
- X* get() const throw()
- {
- return this->x_;
- }
+ 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_ = 0;
+ 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)
- {
+ 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()
- {
+ template <class Y>
+ operator auto_ptr<Y>() throw()
+ {
return auto_ptr<Y>(this->release());
- }
+ }
-#if @KWSYS_NAMESPACE@_AUTO_PTR_REF
+#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_)
- {
- }
+ 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;
- }
+ 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()
- {
+ template <class Y>
+ operator detail::auto_ptr_ref<Y>() throw()
+ {
return detail::auto_ptr_ref<Y>(this->release(), 1);
- }
+ }
#endif
};
-} // namespace @KWSYS_NAMESPACE@
+} // namespace cm
// Undo warning suppression.
#if defined(__clang__) && defined(__has_warning)
-# if __has_warning("-Wdeprecated")
-# pragma clang diagnostic pop
-# endif
+#if __has_warning("-Wdeprecated")
+#pragma clang diagnostic pop
+#endif
+#endif
+
#endif
#endif
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
new file mode 100644
index 000000000..cf55741a7
--- /dev/null
+++ b/Source/cm_codecvt.cxx
@@ -0,0 +1,243 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cm_codecvt.hxx"
+
+#if defined(_WIN32)
+#include <assert.h>
+#include <string.h>
+#include <windows.h>
+#undef max
+#include "cmsys/Encoding.hxx"
+#endif
+
+#if defined(_WIN32)
+/* Number of leading ones before a zero in the byte (see cm_utf8.c). */
+extern "C" unsigned char const cm_utf8_ones[256];
+#endif
+
+codecvt::codecvt(Encoding e)
+#if defined(_WIN32)
+ : m_codepage(0)
+#endif
+{
+ switch (e) {
+ case codecvt::ANSI:
+#if defined(_WIN32)
+ m_noconv = false;
+ m_codepage = CP_ACP;
+ break;
+#endif
+ // We don't know which ANSI encoding to use for other platforms than
+ // Windows so we don't do any conversion there
+ case codecvt::UTF8:
+ // Assume internal encoding is UTF-8
+ case codecvt::None:
+ // No encoding
+ default:
+ m_noconv = true;
+ }
+}
+
+codecvt::~codecvt(){};
+
+bool codecvt::do_always_noconv() const throw()
+{
+ return m_noconv;
+};
+
+std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
+ const char* from_end,
+ const char*& from_next, char* to,
+ char* to_end, char*& to_next) const
+{
+ from_next = from;
+ to_next = to;
+ if (m_noconv) {
+ return std::codecvt_base::noconv;
+ }
+#if defined(_WIN32)
+ // Use a const view of the state because we should not modify it until we
+ // have fully processed and consume a byte (with sufficient space in the
+ // output buffer). We call helpers to re-cast and modify the state
+ State const& lstate = reinterpret_cast<State&>(state);
+
+ while (from_next != from_end) {
+ // Count leading ones in the bits of the next byte.
+ unsigned char const ones =
+ cm_utf8_ones[static_cast<unsigned char>(*from_next)];
+
+ if (ones != 1 && lstate.buffered != 0) {
+ // We have a buffered partial codepoint that we never completed.
+ return std::codecvt_base::error;
+ } else if (ones == 1 && lstate.buffered == 0) {
+ // This is a continuation of a codepoint that never started.
+ return std::codecvt_base::error;
+ }
+
+ // Compute the number of bytes in the current codepoint.
+ int need = 0;
+ switch (ones) {
+ case 0: // 0xxx xxxx: new codepoint of size 1
+ need = 1;
+ break;
+ case 1: // 10xx xxxx: continues a codepoint
+ assert(lstate.size != 0);
+ need = lstate.size;
+ break;
+ case 2: // 110x xxxx: new codepoint of size 2
+ need = 2;
+ break;
+ case 3: // 1110 xxxx: new codepoint of size 3
+ need = 3;
+ break;
+ case 4: // 1111 0xxx: new codepoint of size 4
+ need = 4;
+ break;
+ default: // invalid byte
+ return std::codecvt_base::error;
+ }
+ assert(need > 0);
+
+ if (lstate.buffered + 1 == need) {
+ // This byte completes a codepoint.
+ std::codecvt_base::result decode_result =
+ this->Decode(state, need, from_next, to_next, to_end);
+ if (decode_result != std::codecvt_base::ok) {
+ return decode_result;
+ }
+ } else {
+ // This byte does not complete a codepoint.
+ this->BufferPartial(state, need, from_next);
+ }
+ }
+
+ return std::codecvt_base::ok;
+#else
+ static_cast<void>(state);
+ static_cast<void>(from);
+ static_cast<void>(from_end);
+ static_cast<void>(from_next);
+ static_cast<void>(to);
+ static_cast<void>(to_end);
+ 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,
+ char*& to_next) const
+{
+ to_next = to;
+ if (m_noconv) {
+ return std::codecvt_base::noconv;
+ }
+#if defined(_WIN32)
+ State& lstate = reinterpret_cast<State&>(state);
+ if (lstate.buffered != 0) {
+ return this->DecodePartial(state, to_next, to_end);
+ }
+ return std::codecvt_base::ok;
+#else
+ static_cast<void>(state);
+ 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,
+ const char*& from_next,
+ char*& to_next, char* to_end) const
+{
+ State& lstate = reinterpret_cast<State&>(state);
+
+ // Collect all the bytes for this codepoint.
+ char buf[4];
+ memcpy(buf, lstate.partial, lstate.buffered);
+ buf[lstate.buffered] = *from_next;
+
+ // Convert the encoding.
+ wchar_t wbuf[2];
+ int wlen =
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buf, size, wbuf, 2);
+ if (wlen <= 0) {
+ return std::codecvt_base::error;
+ }
+
+ int tlen = WideCharToMultiByte(m_codepage, 0, wbuf, wlen, to_next,
+ to_end - to_next, NULL, NULL);
+ if (tlen <= 0) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ return std::codecvt_base::partial;
+ }
+ return std::codecvt_base::error;
+ }
+
+ // Move past the now-consumed byte in the input buffer.
+ ++from_next;
+
+ // Move past the converted codepoint in the output buffer.
+ to_next += tlen;
+
+ // Re-initialize the state for the next codepoint to start.
+ lstate = State();
+
+ return std::codecvt_base::ok;
+}
+
+std::codecvt_base::result codecvt::DecodePartial(mbstate_t& state,
+ char*& to_next,
+ char* to_end) const
+{
+ State& lstate = reinterpret_cast<State&>(state);
+
+ // Try converting the partial codepoint.
+ wchar_t wbuf[2];
+ int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, lstate.partial,
+ lstate.buffered, wbuf, 2);
+ if (wlen <= 0) {
+ return std::codecvt_base::error;
+ }
+
+ int tlen = WideCharToMultiByte(m_codepage, 0, wbuf, wlen, to_next,
+ to_end - to_next, NULL, NULL);
+ if (tlen <= 0) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ return std::codecvt_base::partial;
+ }
+ return std::codecvt_base::error;
+ }
+
+ // Move past the converted codepoint in the output buffer.
+ to_next += tlen;
+
+ // Re-initialize the state for the next codepoint to start.
+ lstate = State();
+
+ return std::codecvt_base::ok;
+}
+
+void codecvt::BufferPartial(mbstate_t& state, int size,
+ const char*& from_next) const
+{
+ State& lstate = reinterpret_cast<State&>(state);
+
+ // Save the byte in our buffer for later.
+ lstate.partial[lstate.buffered++] = *from_next;
+ lstate.size = size;
+
+ // Move past the now-consumed byte in the input buffer.
+ ++from_next;
+}
+#endif
+
+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
new file mode 100644
index 000000000..30c6d5407
--- /dev/null
+++ b/Source/cm_codecvt.hxx
@@ -0,0 +1,66 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_codecvt_hxx
+#define cm_codecvt_hxx
+
+#include "cmConfigure.h"
+
+#include <locale>
+#include <wchar.h>
+
+class codecvt : public std::codecvt<char, char, mbstate_t>
+{
+public:
+ enum Encoding
+ {
+ None,
+ UTF8,
+ ANSI
+ };
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+
+ codecvt(Encoding e);
+
+protected:
+ ~codecvt() CM_OVERRIDE;
+ bool do_always_noconv() const throw() CM_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;
+ 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;
+
+private:
+ // The mbstate_t argument to do_out and do_unshift is responsible
+ // for storing state between calls. We cannot control the type
+ // since we want to imbue on standard streams. However, we do
+ // know that it is a trivial type. Define our own type to overlay
+ // on it safely with no alignment requirements.
+ struct State
+ {
+ // Buffer bytes we have consumed from a partial codepoint.
+ char partial[3];
+
+ // Number of bytes we have buffered from a partial codepoint.
+ unsigned char buffered : 4;
+
+ // Size of the current codepoint in bytes.
+ unsigned char size : 4;
+ };
+
+ bool m_noconv;
+#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.c b/Source/cm_get_date.c
new file mode 100644
index 000000000..4bef80315
--- /dev/null
+++ b/Source/cm_get_date.c
@@ -0,0 +1,7 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cm_get_date.h"
+
+#define __archive_get_date cm_get_date
+
+#include "../Utilities/cmlibarchive/libarchive/archive_getdate.c"
diff --git a/Source/cm_get_date.h b/Source/cm_get_date.h
new file mode 100644
index 000000000..6acf8dea3
--- /dev/null
+++ b/Source/cm_get_date.h
@@ -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. */
+#ifndef cm_get_date_h
+#define cm_get_date_h
+
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Parse a date/time string. Treat relative times with respect to 'now'. */
+time_t cm_get_date(time_t now, const char* str);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/Source/cm_sha2.c b/Source/cm_sha2.c
deleted file mode 100644
index 24de2b294..000000000
--- a/Source/cm_sha2.c
+++ /dev/null
@@ -1,1617 +0,0 @@
-/*
- * FILE: sha2.c
- * AUTHOR: Aaron D. Gifford
- * http://www.aarongifford.com/computers/sha.html
- *
- * Copyright (c) 2000-2003, Aaron D. Gifford
- * All rights reserved.
- *
- * 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 copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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.
- *
- * $Id: sha2.c,v 1.4 2004/01/07 22:58:18 adg Exp $
- */
-
-#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */
-#include <assert.h> /* assert() */
-#include "cm_sha2.h" /* "sha2.h" -> "cm_sha2.h" renamed for CMake */
-
-/*
- * ASSERT NOTE:
- * Some sanity checking code is included using assert(). On my FreeBSD
- * system, this additional code can be removed by compiling with NDEBUG
- * defined. Check your own systems manpage on assert() to see how to
- * compile WITHOUT the sanity checking code on your system.
- *
- * UNROLLED TRANSFORM LOOP NOTE:
- * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
- * loop version for the hash transform rounds (defined using macros
- * later in this file). Either define on the command line, for example:
- *
- * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
- *
- * or define below:
- *
- * #define SHA2_UNROLL_TRANSFORM
- *
- */
-
-
-/*** SHA-224/256/384/512 Machine Architecture Definitions *************/
-/*
- * BYTE_ORDER NOTE:
- *
- * Please make sure that your system defines BYTE_ORDER. If your
- * architecture is little-endian, make sure it also defines
- * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
- * equivilent.
- *
- * If your system does not define the above, then you can do so by
- * hand like this:
- *
- * #define LITTLE_ENDIAN 1234
- * #define BIG_ENDIAN 4321
- *
- * And for little-endian machines, add:
- *
- * #define BYTE_ORDER LITTLE_ENDIAN
- *
- * Or for big-endian machines:
- *
- * #define BYTE_ORDER BIG_ENDIAN
- *
- * The FreeBSD machine this was written on defines BYTE_ORDER
- * appropriately by including <sys/types.h> (which in turn includes
- * <machine/endian.h> where the appropriate definitions are actually
- * made).
- */
-#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
-/* CMake modification: use byte order from cmIML. */
-# include "cmIML/ABI.h"
-# undef BYTE_ORDER
-# undef BIG_ENDIAN
-# undef LITTLE_ENDIAN
-# define BYTE_ORDER cmIML_ABI_ENDIAN_ID
-# define BIG_ENDIAN cmIML_ABI_ENDIAN_ID_BIG
-# define LITTLE_ENDIAN cmIML_ABI_ENDIAN_ID_LITTLE
-#endif
-
-/* CMake modification: use types computed in header. */
-typedef cm_sha2_uint8_t sha_byte; /* Exactly 1 byte */
-typedef cm_sha2_uint32_t sha_word32; /* Exactly 4 bytes */
-typedef cm_sha2_uint64_t sha_word64; /* Exactly 8 bytes */
-#define SHA_UINT32_C(x) cmIML_INT_UINT32_C(x)
-#define SHA_UINT64_C(x) cmIML_INT_UINT64_C(x)
-#if defined(__BORLANDC__)
-# pragma warn -8004 /* variable assigned value that is never used */
-#endif
-#if defined(__clang__)
-# pragma clang diagnostic ignored "-Wcast-align"
-#endif
-
-/*** ENDIAN REVERSAL MACROS *******************************************/
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define REVERSE32(w,x) { \
- sha_word32 tmp = (w); \
- tmp = (tmp >> 16) | (tmp << 16); \
- (x) = ((tmp & SHA_UINT32_C(0xff00ff00)) >> 8) | \
- ((tmp & SHA_UINT32_C(0x00ff00ff)) << 8); \
-}
-#define REVERSE64(w,x) { \
- sha_word64 tmp = (w); \
- tmp = (tmp >> 32) | (tmp << 32); \
- tmp = ((tmp & SHA_UINT64_C(0xff00ff00ff00ff00)) >> 8) | \
- ((tmp & SHA_UINT64_C(0x00ff00ff00ff00ff)) << 8); \
- (x) = ((tmp & SHA_UINT64_C(0xffff0000ffff0000)) >> 16) | \
- ((tmp & SHA_UINT64_C(0x0000ffff0000ffff)) << 16); \
-}
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-/*
- * Macro for incrementally adding the unsigned 64-bit integer n to the
- * unsigned 128-bit integer (represented using a two-element array of
- * 64-bit words):
- */
-#define ADDINC128(w,n) { \
- (w)[0] += (sha_word64)(n); \
- if ((w)[0] < (n)) { \
- (w)[1]++; \
- } \
-}
-
-/*
- * Macros for copying blocks of memory and for zeroing out ranges
- * of memory. Using these macros makes it easy to switch from
- * using memset()/memcpy() and using bzero()/bcopy().
- *
- * Please define either SHA2_USE_MEMSET_MEMCPY or define
- * SHA2_USE_BZERO_BCOPY depending on which function set you
- * choose to use:
- */
-#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
-/* Default to memset()/memcpy() if no option is specified */
-#define SHA2_USE_MEMSET_MEMCPY 1
-#endif
-#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
-/* Abort with an error if BOTH options are defined */
-#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
-#endif
-
-#ifdef SHA2_USE_MEMSET_MEMCPY
-#define MEMSET_BZERO(p,l) memset((p), 0, (l))
-#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
-#endif
-#ifdef SHA2_USE_BZERO_BCOPY
-#define MEMSET_BZERO(p,l) bzero((p), (l))
-#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l))
-#endif
-
-
-/*** THE SIX LOGICAL FUNCTIONS ****************************************/
-/*
- * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
- *
- * NOTE: In the original SHA-256/384/512 document, the shift-right
- * function was named R and the rotate-right function was called S.
- * (See: http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf on the
- * web.)
- *
- * The newer NIST FIPS 180-2 document uses a much clearer naming
- * scheme, SHR for shift-right, ROTR for rotate-right, and ROTL for
- * rotate-left. (See:
- * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
- * on the web.)
- *
- * WARNING: These macros must be used cautiously, since they reference
- * supplied parameters sometimes more than once, and thus could have
- * unexpected side-effects if used without taking this into account.
- */
-/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
-#define SHR(b,x) ((x) >> (b))
-/* 32-bit Rotate-right (used in SHA-256): */
-#define ROTR32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
-/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
-#define ROTR64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
-/* 32-bit Rotate-left (used in SHA-1): */
-#define ROTL32(b,x) (((x) << (b)) | ((x) >> (32 - (b))))
-
-/* Two logical functions used in SHA-1, SHA-254, SHA-256, SHA-384, and SHA-512: */
-#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
-#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
-
-/* Function used in SHA-1: */
-#define Parity(x,y,z) ((x) ^ (y) ^ (z))
-
-/* Four logical functions used in SHA-256: */
-#define Sigma0_256(x) (ROTR32(2, (x)) ^ ROTR32(13, (x)) ^ ROTR32(22, (x)))
-#define Sigma1_256(x) (ROTR32(6, (x)) ^ ROTR32(11, (x)) ^ ROTR32(25, (x)))
-#define sigma0_256(x) (ROTR32(7, (x)) ^ ROTR32(18, (x)) ^ SHR( 3 , (x)))
-#define sigma1_256(x) (ROTR32(17, (x)) ^ ROTR32(19, (x)) ^ SHR( 10, (x)))
-
-/* Four of six logical functions used in SHA-384 and SHA-512: */
-#define Sigma0_512(x) (ROTR64(28, (x)) ^ ROTR64(34, (x)) ^ ROTR64(39, (x)))
-#define Sigma1_512(x) (ROTR64(14, (x)) ^ ROTR64(18, (x)) ^ ROTR64(41, (x)))
-#define sigma0_512(x) (ROTR64( 1, (x)) ^ ROTR64( 8, (x)) ^ SHR( 7, (x)))
-#define sigma1_512(x) (ROTR64(19, (x)) ^ ROTR64(61, (x)) ^ SHR( 6, (x)))
-
-/*** INTERNAL FUNCTION PROTOTYPES *************************************/
-
-/* SHA-224 and SHA-256: */
-void SHA256_Internal_Init(SHA_CTX*, const sha_word32*);
-void SHA256_Internal_Last(SHA_CTX*);
-void SHA256_Internal_Transform(SHA_CTX*, const sha_word32*);
-
-/* SHA-384 and SHA-512: */
-void SHA512_Internal_Init(SHA_CTX*, const sha_word64*);
-void SHA512_Internal_Last(SHA_CTX*);
-void SHA512_Internal_Transform(SHA_CTX*, const sha_word64*);
-
-
-/*** SHA2 INITIAL HASH VALUES AND CONSTANTS ***************************/
-
-/* Hash constant words K for SHA-1: */
-#define K1_0_TO_19 SHA_UINT32_C(0x5a827999)
-#define K1_20_TO_39 SHA_UINT32_C(0x6ed9eba1)
-#define K1_40_TO_59 SHA_UINT32_C(0x8f1bbcdc)
-#define K1_60_TO_79 SHA_UINT32_C(0xca62c1d6)
-
-/* Initial hash value H for SHA-1: */
-static const sha_word32 sha1_initial_hash_value[5] = {
- SHA_UINT32_C(0x67452301),
- SHA_UINT32_C(0xefcdab89),
- SHA_UINT32_C(0x98badcfe),
- SHA_UINT32_C(0x10325476),
- SHA_UINT32_C(0xc3d2e1f0)
-};
-
-/* Hash constant words K for SHA-224 and SHA-256: */
-static const sha_word32 K256[64] = {
- SHA_UINT32_C(0x428a2f98), SHA_UINT32_C(0x71374491),
- SHA_UINT32_C(0xb5c0fbcf), SHA_UINT32_C(0xe9b5dba5),
- SHA_UINT32_C(0x3956c25b), SHA_UINT32_C(0x59f111f1),
- SHA_UINT32_C(0x923f82a4), SHA_UINT32_C(0xab1c5ed5),
- SHA_UINT32_C(0xd807aa98), SHA_UINT32_C(0x12835b01),
- SHA_UINT32_C(0x243185be), SHA_UINT32_C(0x550c7dc3),
- SHA_UINT32_C(0x72be5d74), SHA_UINT32_C(0x80deb1fe),
- SHA_UINT32_C(0x9bdc06a7), SHA_UINT32_C(0xc19bf174),
- SHA_UINT32_C(0xe49b69c1), SHA_UINT32_C(0xefbe4786),
- SHA_UINT32_C(0x0fc19dc6), SHA_UINT32_C(0x240ca1cc),
- SHA_UINT32_C(0x2de92c6f), SHA_UINT32_C(0x4a7484aa),
- SHA_UINT32_C(0x5cb0a9dc), SHA_UINT32_C(0x76f988da),
- SHA_UINT32_C(0x983e5152), SHA_UINT32_C(0xa831c66d),
- SHA_UINT32_C(0xb00327c8), SHA_UINT32_C(0xbf597fc7),
- SHA_UINT32_C(0xc6e00bf3), SHA_UINT32_C(0xd5a79147),
- SHA_UINT32_C(0x06ca6351), SHA_UINT32_C(0x14292967),
- SHA_UINT32_C(0x27b70a85), SHA_UINT32_C(0x2e1b2138),
- SHA_UINT32_C(0x4d2c6dfc), SHA_UINT32_C(0x53380d13),
- SHA_UINT32_C(0x650a7354), SHA_UINT32_C(0x766a0abb),
- SHA_UINT32_C(0x81c2c92e), SHA_UINT32_C(0x92722c85),
- SHA_UINT32_C(0xa2bfe8a1), SHA_UINT32_C(0xa81a664b),
- SHA_UINT32_C(0xc24b8b70), SHA_UINT32_C(0xc76c51a3),
- SHA_UINT32_C(0xd192e819), SHA_UINT32_C(0xd6990624),
- SHA_UINT32_C(0xf40e3585), SHA_UINT32_C(0x106aa070),
- SHA_UINT32_C(0x19a4c116), SHA_UINT32_C(0x1e376c08),
- SHA_UINT32_C(0x2748774c), SHA_UINT32_C(0x34b0bcb5),
- SHA_UINT32_C(0x391c0cb3), SHA_UINT32_C(0x4ed8aa4a),
- SHA_UINT32_C(0x5b9cca4f), SHA_UINT32_C(0x682e6ff3),
- SHA_UINT32_C(0x748f82ee), SHA_UINT32_C(0x78a5636f),
- SHA_UINT32_C(0x84c87814), SHA_UINT32_C(0x8cc70208),
- SHA_UINT32_C(0x90befffa), SHA_UINT32_C(0xa4506ceb),
- SHA_UINT32_C(0xbef9a3f7), SHA_UINT32_C(0xc67178f2)
-};
-
-/* Initial hash value H for SHA-224: */
-static const sha_word32 sha224_initial_hash_value[8] = {
- SHA_UINT32_C(0xc1059ed8),
- SHA_UINT32_C(0x367cd507),
- SHA_UINT32_C(0x3070dd17),
- SHA_UINT32_C(0xf70e5939),
- SHA_UINT32_C(0xffc00b31),
- SHA_UINT32_C(0x68581511),
- SHA_UINT32_C(0x64f98fa7),
- SHA_UINT32_C(0xbefa4fa4)
-};
-
-/* Initial hash value H for SHA-256: */
-static const sha_word32 sha256_initial_hash_value[8] = {
- SHA_UINT32_C(0x6a09e667),
- SHA_UINT32_C(0xbb67ae85),
- SHA_UINT32_C(0x3c6ef372),
- SHA_UINT32_C(0xa54ff53a),
- SHA_UINT32_C(0x510e527f),
- SHA_UINT32_C(0x9b05688c),
- SHA_UINT32_C(0x1f83d9ab),
- SHA_UINT32_C(0x5be0cd19)
-};
-
-/* Hash constant words K for SHA-384 and SHA-512: */
-static const sha_word64 K512[80] = {
- SHA_UINT64_C(0x428a2f98d728ae22), SHA_UINT64_C(0x7137449123ef65cd),
- SHA_UINT64_C(0xb5c0fbcfec4d3b2f), SHA_UINT64_C(0xe9b5dba58189dbbc),
- SHA_UINT64_C(0x3956c25bf348b538), SHA_UINT64_C(0x59f111f1b605d019),
- SHA_UINT64_C(0x923f82a4af194f9b), SHA_UINT64_C(0xab1c5ed5da6d8118),
- SHA_UINT64_C(0xd807aa98a3030242), SHA_UINT64_C(0x12835b0145706fbe),
- SHA_UINT64_C(0x243185be4ee4b28c), SHA_UINT64_C(0x550c7dc3d5ffb4e2),
- SHA_UINT64_C(0x72be5d74f27b896f), SHA_UINT64_C(0x80deb1fe3b1696b1),
- SHA_UINT64_C(0x9bdc06a725c71235), SHA_UINT64_C(0xc19bf174cf692694),
- SHA_UINT64_C(0xe49b69c19ef14ad2), SHA_UINT64_C(0xefbe4786384f25e3),
- SHA_UINT64_C(0x0fc19dc68b8cd5b5), SHA_UINT64_C(0x240ca1cc77ac9c65),
- SHA_UINT64_C(0x2de92c6f592b0275), SHA_UINT64_C(0x4a7484aa6ea6e483),
- SHA_UINT64_C(0x5cb0a9dcbd41fbd4), SHA_UINT64_C(0x76f988da831153b5),
- SHA_UINT64_C(0x983e5152ee66dfab), SHA_UINT64_C(0xa831c66d2db43210),
- SHA_UINT64_C(0xb00327c898fb213f), SHA_UINT64_C(0xbf597fc7beef0ee4),
- SHA_UINT64_C(0xc6e00bf33da88fc2), SHA_UINT64_C(0xd5a79147930aa725),
- SHA_UINT64_C(0x06ca6351e003826f), SHA_UINT64_C(0x142929670a0e6e70),
- SHA_UINT64_C(0x27b70a8546d22ffc), SHA_UINT64_C(0x2e1b21385c26c926),
- SHA_UINT64_C(0x4d2c6dfc5ac42aed), SHA_UINT64_C(0x53380d139d95b3df),
- SHA_UINT64_C(0x650a73548baf63de), SHA_UINT64_C(0x766a0abb3c77b2a8),
- SHA_UINT64_C(0x81c2c92e47edaee6), SHA_UINT64_C(0x92722c851482353b),
- SHA_UINT64_C(0xa2bfe8a14cf10364), SHA_UINT64_C(0xa81a664bbc423001),
- SHA_UINT64_C(0xc24b8b70d0f89791), SHA_UINT64_C(0xc76c51a30654be30),
- SHA_UINT64_C(0xd192e819d6ef5218), SHA_UINT64_C(0xd69906245565a910),
- SHA_UINT64_C(0xf40e35855771202a), SHA_UINT64_C(0x106aa07032bbd1b8),
- SHA_UINT64_C(0x19a4c116b8d2d0c8), SHA_UINT64_C(0x1e376c085141ab53),
- SHA_UINT64_C(0x2748774cdf8eeb99), SHA_UINT64_C(0x34b0bcb5e19b48a8),
- SHA_UINT64_C(0x391c0cb3c5c95a63), SHA_UINT64_C(0x4ed8aa4ae3418acb),
- SHA_UINT64_C(0x5b9cca4f7763e373), SHA_UINT64_C(0x682e6ff3d6b2b8a3),
- SHA_UINT64_C(0x748f82ee5defb2fc), SHA_UINT64_C(0x78a5636f43172f60),
- SHA_UINT64_C(0x84c87814a1f0ab72), SHA_UINT64_C(0x8cc702081a6439ec),
- SHA_UINT64_C(0x90befffa23631e28), SHA_UINT64_C(0xa4506cebde82bde9),
- SHA_UINT64_C(0xbef9a3f7b2c67915), SHA_UINT64_C(0xc67178f2e372532b),
- SHA_UINT64_C(0xca273eceea26619c), SHA_UINT64_C(0xd186b8c721c0c207),
- SHA_UINT64_C(0xeada7dd6cde0eb1e), SHA_UINT64_C(0xf57d4f7fee6ed178),
- SHA_UINT64_C(0x06f067aa72176fba), SHA_UINT64_C(0x0a637dc5a2c898a6),
- SHA_UINT64_C(0x113f9804bef90dae), SHA_UINT64_C(0x1b710b35131c471b),
- SHA_UINT64_C(0x28db77f523047d84), SHA_UINT64_C(0x32caab7b40c72493),
- SHA_UINT64_C(0x3c9ebe0a15c9bebc), SHA_UINT64_C(0x431d67c49c100d4c),
- SHA_UINT64_C(0x4cc5d4becb3e42b6), SHA_UINT64_C(0x597f299cfc657e2a),
- SHA_UINT64_C(0x5fcb6fab3ad6faec), SHA_UINT64_C(0x6c44198c4a475817)
-};
-
-/* Initial hash value H for SHA-384 */
-static const sha_word64 sha384_initial_hash_value[8] = {
- SHA_UINT64_C(0xcbbb9d5dc1059ed8),
- SHA_UINT64_C(0x629a292a367cd507),
- SHA_UINT64_C(0x9159015a3070dd17),
- SHA_UINT64_C(0x152fecd8f70e5939),
- SHA_UINT64_C(0x67332667ffc00b31),
- SHA_UINT64_C(0x8eb44a8768581511),
- SHA_UINT64_C(0xdb0c2e0d64f98fa7),
- SHA_UINT64_C(0x47b5481dbefa4fa4)
-};
-
-/* Initial hash value H for SHA-512 */
-static const sha_word64 sha512_initial_hash_value[8] = {
- SHA_UINT64_C(0x6a09e667f3bcc908),
- SHA_UINT64_C(0xbb67ae8584caa73b),
- SHA_UINT64_C(0x3c6ef372fe94f82b),
- SHA_UINT64_C(0xa54ff53a5f1d36f1),
- SHA_UINT64_C(0x510e527fade682d1),
- SHA_UINT64_C(0x9b05688c2b3e6c1f),
- SHA_UINT64_C(0x1f83d9abfb41bd6b),
- SHA_UINT64_C(0x5be0cd19137e2179)
-};
-
-/*
- * Constant used by SHA224/256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char *sha_hex_digits = "0123456789abcdef";
-
-
-/*** SHA-1: ***********************************************************/
-void SHA1_Init(SHA_CTX* context) {
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- MEMCPY_BCOPY(context->s1.state, sha1_initial_hash_value, sizeof(sha_word32) * 5);
- MEMSET_BZERO(context->s1.buffer, 64);
- context->s1.bitcount = 0;
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-1 round macros: */
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND1_0_TO_15(a,b,c,d,e) \
- REVERSE32(*data++, W1[j]); \
- (e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \
- K1_0_TO_19 + W1[j]; \
- (b) = ROTL32(30, (b)); \
- j++;
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND1_0_TO_15(a,b,c,d,e) \
- (e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \
- K1_0_TO_19 + ( W1[j] = *data++ ); \
- (b) = ROTL32(30, (b)); \
- j++;
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND1_16_TO_19(a,b,c,d,e) \
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
- (e) = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
- (b) = ROTL32(30, b); \
- j++;
-
-#define ROUND1_20_TO_39(a,b,c,d,e) \
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
- (e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
- (b) = ROTL32(30, b); \
- j++;
-
-#define ROUND1_40_TO_59(a,b,c,d,e) \
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
- (e) = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
- (b) = ROTL32(30, b); \
- j++;
-
-#define ROUND1_60_TO_79(a,b,c,d,e) \
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
- (e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
- (b) = ROTL32(30, b); \
- j++;
-
-void SHA1_Internal_Transform(SHA_CTX* context, const sha_word32* data) {
- sha_word32 a, b, c, d, e;
- sha_word32 T1, *W1;
- int j;
-
- W1 = (sha_word32*)context->s1.buffer;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->s1.state[0];
- b = context->s1.state[1];
- c = context->s1.state[2];
- d = context->s1.state[3];
- e = context->s1.state[4];
-
- j = 0;
-
- /* Rounds 0 to 15 unrolled: */
- ROUND1_0_TO_15(a,b,c,d,e);
- ROUND1_0_TO_15(e,a,b,c,d);
- ROUND1_0_TO_15(d,e,a,b,c);
- ROUND1_0_TO_15(c,d,e,a,b);
- ROUND1_0_TO_15(b,c,d,e,a);
- ROUND1_0_TO_15(a,b,c,d,e);
- ROUND1_0_TO_15(e,a,b,c,d);
- ROUND1_0_TO_15(d,e,a,b,c);
- ROUND1_0_TO_15(c,d,e,a,b);
- ROUND1_0_TO_15(b,c,d,e,a);
- ROUND1_0_TO_15(a,b,c,d,e);
- ROUND1_0_TO_15(e,a,b,c,d);
- ROUND1_0_TO_15(d,e,a,b,c);
- ROUND1_0_TO_15(c,d,e,a,b);
- ROUND1_0_TO_15(b,c,d,e,a);
- ROUND1_0_TO_15(a,b,c,d,e);
-
- /* Rounds 16 to 19 unrolled: */
- ROUND1_16_TO_19(e,a,b,c,d);
- ROUND1_16_TO_19(d,e,a,b,c);
- ROUND1_16_TO_19(c,d,e,a,b);
- ROUND1_16_TO_19(b,c,d,e,a);
-
- /* Rounds 20 to 39 unrolled: */
- ROUND1_20_TO_39(a,b,c,d,e);
- ROUND1_20_TO_39(e,a,b,c,d);
- ROUND1_20_TO_39(d,e,a,b,c);
- ROUND1_20_TO_39(c,d,e,a,b);
- ROUND1_20_TO_39(b,c,d,e,a);
- ROUND1_20_TO_39(a,b,c,d,e);
- ROUND1_20_TO_39(e,a,b,c,d);
- ROUND1_20_TO_39(d,e,a,b,c);
- ROUND1_20_TO_39(c,d,e,a,b);
- ROUND1_20_TO_39(b,c,d,e,a);
- ROUND1_20_TO_39(a,b,c,d,e);
- ROUND1_20_TO_39(e,a,b,c,d);
- ROUND1_20_TO_39(d,e,a,b,c);
- ROUND1_20_TO_39(c,d,e,a,b);
- ROUND1_20_TO_39(b,c,d,e,a);
- ROUND1_20_TO_39(a,b,c,d,e);
- ROUND1_20_TO_39(e,a,b,c,d);
- ROUND1_20_TO_39(d,e,a,b,c);
- ROUND1_20_TO_39(c,d,e,a,b);
- ROUND1_20_TO_39(b,c,d,e,a);
-
- /* Rounds 40 to 59 unrolled: */
- ROUND1_40_TO_59(a,b,c,d,e);
- ROUND1_40_TO_59(e,a,b,c,d);
- ROUND1_40_TO_59(d,e,a,b,c);
- ROUND1_40_TO_59(c,d,e,a,b);
- ROUND1_40_TO_59(b,c,d,e,a);
- ROUND1_40_TO_59(a,b,c,d,e);
- ROUND1_40_TO_59(e,a,b,c,d);
- ROUND1_40_TO_59(d,e,a,b,c);
- ROUND1_40_TO_59(c,d,e,a,b);
- ROUND1_40_TO_59(b,c,d,e,a);
- ROUND1_40_TO_59(a,b,c,d,e);
- ROUND1_40_TO_59(e,a,b,c,d);
- ROUND1_40_TO_59(d,e,a,b,c);
- ROUND1_40_TO_59(c,d,e,a,b);
- ROUND1_40_TO_59(b,c,d,e,a);
- ROUND1_40_TO_59(a,b,c,d,e);
- ROUND1_40_TO_59(e,a,b,c,d);
- ROUND1_40_TO_59(d,e,a,b,c);
- ROUND1_40_TO_59(c,d,e,a,b);
- ROUND1_40_TO_59(b,c,d,e,a);
-
- /* Rounds 60 to 79 unrolled: */
- ROUND1_60_TO_79(a,b,c,d,e);
- ROUND1_60_TO_79(e,a,b,c,d);
- ROUND1_60_TO_79(d,e,a,b,c);
- ROUND1_60_TO_79(c,d,e,a,b);
- ROUND1_60_TO_79(b,c,d,e,a);
- ROUND1_60_TO_79(a,b,c,d,e);
- ROUND1_60_TO_79(e,a,b,c,d);
- ROUND1_60_TO_79(d,e,a,b,c);
- ROUND1_60_TO_79(c,d,e,a,b);
- ROUND1_60_TO_79(b,c,d,e,a);
- ROUND1_60_TO_79(a,b,c,d,e);
- ROUND1_60_TO_79(e,a,b,c,d);
- ROUND1_60_TO_79(d,e,a,b,c);
- ROUND1_60_TO_79(c,d,e,a,b);
- ROUND1_60_TO_79(b,c,d,e,a);
- ROUND1_60_TO_79(a,b,c,d,e);
- ROUND1_60_TO_79(e,a,b,c,d);
- ROUND1_60_TO_79(d,e,a,b,c);
- ROUND1_60_TO_79(c,d,e,a,b);
- ROUND1_60_TO_79(b,c,d,e,a);
-
- /* Compute the current intermediate hash value */
- context->s1.state[0] += a;
- context->s1.state[1] += b;
- context->s1.state[2] += c;
- context->s1.state[3] += d;
- context->s1.state[4] += e;
-
- /* Clean up */
- a = b = c = d = e = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-void SHA1_Internal_Transform(SHA_CTX* context, const sha_word32* data) {
- sha_word32 a, b, c, d, e;
- sha_word32 T1, *W1;
- int j;
-
- W1 = (sha_word32*)context->s1.buffer;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->s1.state[0];
- b = context->s1.state[1];
- c = context->s1.state[2];
- d = context->s1.state[3];
- e = context->s1.state[4];
- j = 0;
- do {
-#if BYTE_ORDER == LITTLE_ENDIAN
- T1 = data[j];
- /* Copy data while converting to host byte order */
- REVERSE32(*data++, W1[j]);
- T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + W1[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
- T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + (W1[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
- e = d;
- d = c;
- c = ROTL32(30, b);
- b = a;
- a = T1;
- j++;
- } while (j < 16);
-
- do {
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
- T1 = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + (W1[j&0x0f] = ROTL32(1, T1));
- e = d;
- d = c;
- c = ROTL32(30, b);
- b = a;
- a = T1;
- j++;
- } while (j < 20);
-
- do {
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
- T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + (W1[j&0x0f] = ROTL32(1, T1));
- e = d;
- d = c;
- c = ROTL32(30, b);
- b = a;
- a = T1;
- j++;
- } while (j < 40);
-
- do {
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
- T1 = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + (W1[j&0x0f] = ROTL32(1, T1));
- e = d;
- d = c;
- c = ROTL32(30, b);
- b = a;
- a = T1;
- j++;
- } while (j < 60);
-
- do {
- T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
- T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + (W1[j&0x0f] = ROTL32(1, T1));
- e = d;
- d = c;
- c = ROTL32(30, b);
- b = a;
- a = T1;
- j++;
- } while (j < 80);
-
-
- /* Compute the current intermediate hash value */
- context->s1.state[0] += a;
- context->s1.state[1] += b;
- context->s1.state[2] += c;
- context->s1.state[3] += d;
- context->s1.state[4] += e;
-
- /* Clean up */
- a = b = c = d = e = T1 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA1_Update(SHA_CTX* context, const sha_byte *data, size_t len) {
- unsigned int freespace, usedspace;
- if (len == 0) {
- /* Calling with no data is valid - we do nothing */
- return;
- }
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0 && data != (sha_byte*)0);
-
- usedspace = (unsigned int)((context->s1.bitcount >> 3) % 64);
- if (usedspace > 0) {
- /* Calculate how much free space is available in the buffer */
- freespace = 64 - usedspace;
-
- if (len >= freespace) {
- /* Fill the buffer completely and process it */
- MEMCPY_BCOPY(&context->s1.buffer[usedspace], data, freespace);
- context->s1.bitcount += freespace << 3;
- len -= freespace;
- data += freespace;
- SHA1_Internal_Transform(context, (sha_word32*)context->s1.buffer);
- } else {
- /* The buffer is not yet full */
- MEMCPY_BCOPY(&context->s1.buffer[usedspace], data, len);
- context->s1.bitcount += len << 3;
- /* Clean up: */
- usedspace = freespace = 0;
- return;
- }
- }
- while (len >= 64) {
- /* Process as many complete blocks as we can */
- SHA1_Internal_Transform(context, (sha_word32*)data);
- context->s1.bitcount += 512;
- len -= 64;
- data += 64;
- }
- if (len > 0) {
- /* There's left-overs, so save 'em */
- MEMCPY_BCOPY(context->s1.buffer, data, len);
- context->s1.bitcount += len << 3;
- }
- /* Clean up: */
- usedspace = freespace = 0;
-}
-
-void SHA1_Final(sha_byte digest[], SHA_CTX* context) {
- sha_word32 *d = (sha_word32*)digest;
- unsigned int usedspace;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- if (digest == (sha_byte*)0) {
- /*
- * No digest buffer, so we can do nothing
- * except clean up and go home
- */
- MEMSET_BZERO(context, sizeof(*context));
- return;
- }
-
- usedspace = (unsigned int)((context->s1.bitcount >> 3) % 64);
- if (usedspace == 0) {
- /* Set-up for the last transform: */
- MEMSET_BZERO(context->s1.buffer, 56);
-
- /* Begin padding with a 1 bit: */
- *context->s1.buffer = 0x80;
- } else {
- /* Begin padding with a 1 bit: */
- context->s1.buffer[usedspace++] = 0x80;
-
- if (usedspace <= 56) {
- /* Set-up for the last transform: */
- MEMSET_BZERO(&context->s1.buffer[usedspace], 56 - usedspace);
- } else {
- if (usedspace < 64) {
- MEMSET_BZERO(&context->s1.buffer[usedspace], 64 - usedspace);
- }
- /* Do second-to-last transform: */
- SHA1_Internal_Transform(context, (sha_word32*)context->s1.buffer);
-
- /* And set-up for the last transform: */
- MEMSET_BZERO(context->s1.buffer, 56);
- }
- /* Clean up: */
- usedspace = 0;
- }
- /* Set the bit count: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert FROM host byte order */
- REVERSE64(context->s1.bitcount,context->s1.bitcount);
-#endif
- MEMCPY_BCOPY(&context->s1.buffer[56], &context->s1.bitcount,
- sizeof(sha_word64));
-
- /* Final transform: */
- SHA1_Internal_Transform(context, (sha_word32*)context->s1.buffer);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < (SHA1_DIGEST_LENGTH >> 2); j++) {
- REVERSE32(context->s1.state[j],context->s1.state[j]);
- *d++ = context->s1.state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->s1.state, SHA1_DIGEST_LENGTH);
-#endif
-
- /* Clean up: */
- MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA1_End(SHA_CTX* context, char buffer[]) {
- sha_byte digest[SHA1_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA1_Final(digest, context);
-
- for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
- *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(*context));
- }
- MEMSET_BZERO(digest, SHA1_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA1_Data(const sha_byte* data, size_t len, char digest[SHA1_DIGEST_STRING_LENGTH]) {
- SHA_CTX context;
-
- SHA1_Init(&context);
- SHA1_Update(&context, data, len);
- return SHA1_End(&context, digest);
-}
-
-
-/*** SHA-256: *********************************************************/
-void SHA256_Internal_Init(SHA_CTX* context, const sha_word32* ihv) {
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- MEMCPY_BCOPY(context->s256.state, ihv, sizeof(sha_word32) * 8);
- MEMSET_BZERO(context->s256.buffer, 64);
- context->s256.bitcount = 0;
-}
-
-void SHA256_Init(SHA_CTX* context) {
- SHA256_Internal_Init(context, sha256_initial_hash_value);
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-256 round macros: */
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
- REVERSE32(*data++, W256[j]); \
- T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
- K256[j] + W256[j]; \
- (d) += T1; \
- (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
- j++
-
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
- T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
- K256[j] + (W256[j] = *data++); \
- (d) += T1; \
- (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
- j++
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND256(a,b,c,d,e,f,g,h) \
- s0 = W256[(j+1)&0x0f]; \
- s0 = sigma0_256(s0); \
- s1 = W256[(j+14)&0x0f]; \
- s1 = sigma1_256(s1); \
- T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
- (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
- (d) += T1; \
- (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
- j++
-
-void SHA256_Internal_Transform(SHA_CTX* context, const sha_word32* data) {
- sha_word32 a, b, c, d, e, f, g, h, s0, s1;
- sha_word32 T1, *W256;
- int j;
-
- W256 = (sha_word32*)context->s256.buffer;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->s256.state[0];
- b = context->s256.state[1];
- c = context->s256.state[2];
- d = context->s256.state[3];
- e = context->s256.state[4];
- f = context->s256.state[5];
- g = context->s256.state[6];
- h = context->s256.state[7];
-
- j = 0;
- do {
- /* Rounds 0 to 15 (unrolled): */
- ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
- ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
- ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
- ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
- ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
- ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
- ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
- ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
- } while (j < 16);
-
- /* Now for the remaining rounds to 64: */
- do {
- ROUND256(a,b,c,d,e,f,g,h);
- ROUND256(h,a,b,c,d,e,f,g);
- ROUND256(g,h,a,b,c,d,e,f);
- ROUND256(f,g,h,a,b,c,d,e);
- ROUND256(e,f,g,h,a,b,c,d);
- ROUND256(d,e,f,g,h,a,b,c);
- ROUND256(c,d,e,f,g,h,a,b);
- ROUND256(b,c,d,e,f,g,h,a);
- } while (j < 64);
-
- /* Compute the current intermediate hash value */
- context->s256.state[0] += a;
- context->s256.state[1] += b;
- context->s256.state[2] += c;
- context->s256.state[3] += d;
- context->s256.state[4] += e;
- context->s256.state[5] += f;
- context->s256.state[6] += g;
- context->s256.state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-void SHA256_Internal_Transform(SHA_CTX* context, const sha_word32* data) {
- sha_word32 a, b, c, d, e, f, g, h, s0, s1;
- sha_word32 T1, T2, *W256;
- int j;
-
- W256 = (sha_word32*)context->s256.buffer;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->s256.state[0];
- b = context->s256.state[1];
- c = context->s256.state[2];
- d = context->s256.state[3];
- e = context->s256.state[4];
- f = context->s256.state[5];
- g = context->s256.state[6];
- h = context->s256.state[7];
-
- j = 0;
- do {
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Copy data while converting to host byte order */
- REVERSE32(*data++,W256[j]);
- /* Apply the SHA-256 compression function to update a..h */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
- /* Apply the SHA-256 compression function to update a..h with copy */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
- T2 = Sigma0_256(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 16);
-
- do {
- /* Part of the message block expansion: */
- s0 = W256[(j+1)&0x0f];
- s0 = sigma0_256(s0);
- s1 = W256[(j+14)&0x0f];
- s1 = sigma1_256(s1);
-
- /* Apply the SHA-256 compression function to update a..h */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
- (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
- T2 = Sigma0_256(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 64);
-
- /* Compute the current intermediate hash value */
- context->s256.state[0] += a;
- context->s256.state[1] += b;
- context->s256.state[2] += c;
- context->s256.state[3] += d;
- context->s256.state[4] += e;
- context->s256.state[5] += f;
- context->s256.state[6] += g;
- context->s256.state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = T2 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA256_Update(SHA_CTX* context, const sha_byte *data, size_t len) {
- unsigned int freespace, usedspace;
-
- if (len == 0) {
- /* Calling with no data is valid - we do nothing */
- return;
- }
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0 && data != (sha_byte*)0);
-
- usedspace = (unsigned int)((context->s256.bitcount >> 3) % 64);
- if (usedspace > 0) {
- /* Calculate how much free space is available in the buffer */
- freespace = 64 - usedspace;
-
- if (len >= freespace) {
- /* Fill the buffer completely and process it */
- MEMCPY_BCOPY(&context->s256.buffer[usedspace], data, freespace);
- context->s256.bitcount += freespace << 3;
- len -= freespace;
- data += freespace;
- SHA256_Internal_Transform(context, (sha_word32*)context->s256.buffer);
- } else {
- /* The buffer is not yet full */
- MEMCPY_BCOPY(&context->s256.buffer[usedspace], data, len);
- context->s256.bitcount += len << 3;
- /* Clean up: */
- usedspace = freespace = 0;
- return;
- }
- }
- while (len >= 64) {
- /* Process as many complete blocks as we can */
- SHA256_Internal_Transform(context, (sha_word32*)data);
- context->s256.bitcount += 512;
- len -= 64;
- data += 64;
- }
- if (len > 0) {
- /* There's left-overs, so save 'em */
- MEMCPY_BCOPY(context->s256.buffer, data, len);
- context->s256.bitcount += len << 3;
- }
- /* Clean up: */
- usedspace = freespace = 0;
-}
-
-void SHA256_Internal_Last(SHA_CTX* context) {
- unsigned int usedspace;
-
- usedspace = (unsigned int)((context->s256.bitcount >> 3) % 64);
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert FROM host byte order */
- REVERSE64(context->s256.bitcount,context->s256.bitcount);
-#endif
- if (usedspace > 0) {
- /* Begin padding with a 1 bit: */
- context->s256.buffer[usedspace++] = 0x80;
-
- if (usedspace <= 56) {
- /* Set-up for the last transform: */
- MEMSET_BZERO(&context->s256.buffer[usedspace], 56 - usedspace);
- } else {
- if (usedspace < 64) {
- MEMSET_BZERO(&context->s256.buffer[usedspace], 64 - usedspace);
- }
- /* Do second-to-last transform: */
- SHA256_Internal_Transform(context, (sha_word32*)context->s256.buffer);
-
- /* And set-up for the last transform: */
- MEMSET_BZERO(context->s256.buffer, 56);
- }
- /* Clean up: */
- usedspace = 0;
- } else {
- /* Set-up for the last transform: */
- MEMSET_BZERO(context->s256.buffer, 56);
-
- /* Begin padding with a 1 bit: */
- *context->s256.buffer = 0x80;
- }
- /* Set the bit count: */
- MEMCPY_BCOPY(&context->s256.buffer[56], &context->s256.bitcount,
- sizeof(sha_word64));
-
- /* Final transform: */
- SHA256_Internal_Transform(context, (sha_word32*)context->s256.buffer);
-}
-
-void SHA256_Final(sha_byte digest[], SHA_CTX* context) {
- sha_word32 *d = (sha_word32*)digest;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha_byte*)0) {
- SHA256_Internal_Last(context);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < (SHA256_DIGEST_LENGTH >> 2); j++) {
- REVERSE32(context->s256.state[j],context->s256.state[j]);
- *d++ = context->s256.state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->s256.state, SHA256_DIGEST_LENGTH);
-#endif
- }
-
- /* Clean up state data: */
- MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA256_End(SHA_CTX* context, char buffer[]) {
- sha_byte digest[SHA256_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA256_Final(digest, context);
-
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
- *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(*context));
- }
- MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA256_Data(const sha_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
- SHA_CTX context;
-
- SHA256_Init(&context);
- SHA256_Update(&context, data, len);
- return SHA256_End(&context, digest);
-}
-
-
-/*** SHA-224: *********************************************************/
-void SHA224_Init(SHA_CTX* context) {
- SHA256_Internal_Init(context, sha224_initial_hash_value);
-}
-
-void SHA224_Internal_Transform(SHA_CTX* context, const sha_word32* data) {
- SHA256_Internal_Transform(context, data);
-}
-
-void SHA224_Update(SHA_CTX* context, const sha_byte *data, size_t len) {
- SHA256_Update(context, data, len);
-}
-
-void SHA224_Final(sha_byte digest[], SHA_CTX* context) {
- sha_word32 *d = (sha_word32*)digest;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha_byte*)0) {
- SHA256_Internal_Last(context);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < (SHA224_DIGEST_LENGTH >> 2); j++) {
- REVERSE32(context->s256.state[j],context->s256.state[j]);
- *d++ = context->s256.state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->s256.state, SHA224_DIGEST_LENGTH);
-#endif
- }
-
- /* Clean up state data: */
- MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA224_End(SHA_CTX* context, char buffer[]) {
- sha_byte digest[SHA224_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA224_Final(digest, context);
-
- for (i = 0; i < SHA224_DIGEST_LENGTH; i++) {
- *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(*context));
- }
- MEMSET_BZERO(digest, SHA224_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA224_Data(const sha_byte* data, size_t len, char digest[SHA224_DIGEST_STRING_LENGTH]) {
- SHA_CTX context;
-
- SHA224_Init(&context);
- SHA224_Update(&context, data, len);
- return SHA224_End(&context, digest);
-}
-
-
-/*** SHA-512: *********************************************************/
-void SHA512_Internal_Init(SHA_CTX* context, const sha_word64* ihv) {
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- MEMCPY_BCOPY(context->s512.state, ihv, sizeof(sha_word64) * 8);
- MEMSET_BZERO(context->s512.buffer, 128);
- context->s512.bitcount[0] = context->s512.bitcount[1] = 0;
-}
-
-void SHA512_Init(SHA_CTX* context) {
- SHA512_Internal_Init(context, sha512_initial_hash_value);
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-512 round macros: */
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
- REVERSE64(*data++, W512[j]); \
- T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
- K512[j] + W512[j]; \
- (d) += T1, \
- (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
- j++
-
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
- T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
- K512[j] + (W512[j] = *data++); \
- (d) += T1; \
- (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
- j++
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND512(a,b,c,d,e,f,g,h) \
- s0 = W512[(j+1)&0x0f]; \
- s0 = sigma0_512(s0); \
- s1 = W512[(j+14)&0x0f]; \
- s1 = sigma1_512(s1); \
- T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
- (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
- (d) += T1; \
- (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
- j++
-
-void SHA512_Internal_Transform(SHA_CTX* context, const sha_word64* data) {
- sha_word64 a, b, c, d, e, f, g, h, s0, s1;
- sha_word64 T1, *W512 = (sha_word64*)context->s512.buffer;
- int j;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->s512.state[0];
- b = context->s512.state[1];
- c = context->s512.state[2];
- d = context->s512.state[3];
- e = context->s512.state[4];
- f = context->s512.state[5];
- g = context->s512.state[6];
- h = context->s512.state[7];
-
- j = 0;
- do {
- ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
- ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
- ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
- ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
- ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
- ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
- ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
- ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
- } while (j < 16);
-
- /* Now for the remaining rounds up to 79: */
- do {
- ROUND512(a,b,c,d,e,f,g,h);
- ROUND512(h,a,b,c,d,e,f,g);
- ROUND512(g,h,a,b,c,d,e,f);
- ROUND512(f,g,h,a,b,c,d,e);
- ROUND512(e,f,g,h,a,b,c,d);
- ROUND512(d,e,f,g,h,a,b,c);
- ROUND512(c,d,e,f,g,h,a,b);
- ROUND512(b,c,d,e,f,g,h,a);
- } while (j < 80);
-
- /* Compute the current intermediate hash value */
- context->s512.state[0] += a;
- context->s512.state[1] += b;
- context->s512.state[2] += c;
- context->s512.state[3] += d;
- context->s512.state[4] += e;
- context->s512.state[5] += f;
- context->s512.state[6] += g;
- context->s512.state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-void SHA512_Internal_Transform(SHA_CTX* context, const sha_word64* data) {
- sha_word64 a, b, c, d, e, f, g, h, s0, s1;
- sha_word64 T1, T2, *W512 = (sha_word64*)context->s512.buffer;
- int j;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->s512.state[0];
- b = context->s512.state[1];
- c = context->s512.state[2];
- d = context->s512.state[3];
- e = context->s512.state[4];
- f = context->s512.state[5];
- g = context->s512.state[6];
- h = context->s512.state[7];
-
- j = 0;
- do {
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert TO host byte order */
- REVERSE64(*data++, W512[j]);
- /* Apply the SHA-512 compression function to update a..h */
- T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
- /* Apply the SHA-512 compression function to update a..h with copy */
- T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
- T2 = Sigma0_512(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 16);
-
- do {
- /* Part of the message block expansion: */
- s0 = W512[(j+1)&0x0f];
- s0 = sigma0_512(s0);
- s1 = W512[(j+14)&0x0f];
- s1 = sigma1_512(s1);
-
- /* Apply the SHA-512 compression function to update a..h */
- T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
- (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
- T2 = Sigma0_512(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 80);
-
- /* Compute the current intermediate hash value */
- context->s512.state[0] += a;
- context->s512.state[1] += b;
- context->s512.state[2] += c;
- context->s512.state[3] += d;
- context->s512.state[4] += e;
- context->s512.state[5] += f;
- context->s512.state[6] += g;
- context->s512.state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = T2 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA512_Update(SHA_CTX* context, const sha_byte *data, size_t len) {
- unsigned int freespace, usedspace;
-
- if (len == 0) {
- /* Calling with no data is valid - we do nothing */
- return;
- }
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0 && data != (sha_byte*)0);
-
- usedspace = (unsigned int)((context->s512.bitcount[0] >> 3) % 128);
- if (usedspace > 0) {
- /* Calculate how much free space is available in the buffer */
- freespace = 128 - usedspace;
-
- if (len >= freespace) {
- /* Fill the buffer completely and process it */
- MEMCPY_BCOPY(&context->s512.buffer[usedspace], data, freespace);
- ADDINC128(context->s512.bitcount, freespace << 3);
- len -= freespace;
- data += freespace;
- SHA512_Internal_Transform(context, (sha_word64*)context->s512.buffer);
- } else {
- /* The buffer is not yet full */
- MEMCPY_BCOPY(&context->s512.buffer[usedspace], data, len);
- ADDINC128(context->s512.bitcount, len << 3);
- /* Clean up: */
- usedspace = freespace = 0;
- return;
- }
- }
- while (len >= 128) {
- /* Process as many complete blocks as we can */
- SHA512_Internal_Transform(context, (sha_word64*)data);
- ADDINC128(context->s512.bitcount, 1024);
- len -= 128;
- data += 128;
- }
- if (len > 0) {
- /* There's left-overs, so save 'em */
- MEMCPY_BCOPY(context->s512.buffer, data, len);
- ADDINC128(context->s512.bitcount, len << 3);
- }
- /* Clean up: */
- usedspace = freespace = 0;
-}
-
-void SHA512_Internal_Last(SHA_CTX* context) {
- unsigned int usedspace;
-
- usedspace = (unsigned int)((context->s512.bitcount[0] >> 3) % 128);
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert FROM host byte order */
- REVERSE64(context->s512.bitcount[0],context->s512.bitcount[0]);
- REVERSE64(context->s512.bitcount[1],context->s512.bitcount[1]);
-#endif
- if (usedspace > 0) {
- /* Begin padding with a 1 bit: */
- context->s512.buffer[usedspace++] = 0x80;
-
- if (usedspace <= 112) {
- /* Set-up for the last transform: */
- MEMSET_BZERO(&context->s512.buffer[usedspace], 112 - usedspace);
- } else {
- if (usedspace < 128) {
- MEMSET_BZERO(&context->s512.buffer[usedspace], 128 - usedspace);
- }
- /* Do second-to-last transform: */
- SHA512_Internal_Transform(context, (sha_word64*)context->s512.buffer);
-
- /* And set-up for the last transform: */
- MEMSET_BZERO(context->s512.buffer, 112);
- }
- /* Clean up: */
- usedspace = 0;
- } else {
- /* Prepare for final transform: */
- MEMSET_BZERO(context->s512.buffer, 112);
-
- /* Begin padding with a 1 bit: */
- *context->s512.buffer = 0x80;
- }
- /* Store the length of input data (in bits): */
- MEMCPY_BCOPY(&context->s512.buffer[112], &context->s512.bitcount[1],
- sizeof(sha_word64));
- MEMCPY_BCOPY(&context->s512.buffer[120], &context->s512.bitcount[0],
- sizeof(sha_word64));
-
- /* Final transform: */
- SHA512_Internal_Transform(context, (sha_word64*)context->s512.buffer);
-}
-
-void SHA512_Final(sha_byte digest[], SHA_CTX* context) {
- sha_word64 *d = (sha_word64*)digest;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha_byte*)0) {
- SHA512_Internal_Last(context);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < (SHA512_DIGEST_LENGTH >> 3); j++) {
- REVERSE64(context->s512.state[j],context->s512.state[j]);
- *d++ = context->s512.state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->s512.state, SHA512_DIGEST_LENGTH);
-#endif
- }
-
- /* Zero out state data */
- MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA512_End(SHA_CTX* context, char buffer[]) {
- sha_byte digest[SHA512_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA512_Final(digest, context);
-
- for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
- *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(*context));
- }
- MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA512_Data(const sha_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
- SHA_CTX context;
-
- SHA512_Init(&context);
- SHA512_Update(&context, data, len);
- return SHA512_End(&context, digest);
-}
-
-
-/*** SHA-384: *********************************************************/
-void SHA384_Init(SHA_CTX* context) {
- SHA512_Internal_Init(context, sha384_initial_hash_value);
-}
-
-void SHA384_Update(SHA_CTX* context, const sha_byte* data, size_t len) {
- SHA512_Update(context, data, len);
-}
-
-void SHA384_Final(sha_byte digest[], SHA_CTX* context) {
- sha_word64 *d = (sha_word64*)digest;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha_byte*)0) {
- SHA512_Internal_Last(context);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < (SHA384_DIGEST_LENGTH >> 3); j++) {
- REVERSE64(context->s512.state[j],context->s512.state[j]);
- *d++ = context->s512.state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->s512.state, SHA384_DIGEST_LENGTH);
-#endif
- }
-
- /* Zero out state data */
- MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA384_End(SHA_CTX* context, char buffer[]) {
- sha_byte digest[SHA384_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA384_Final(digest, context);
-
- for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
- *buffer++ = sha_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(*context));
- }
- MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA384_Data(const sha_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
- SHA_CTX context;
-
- SHA384_Init(&context);
- SHA384_Update(&context, data, len);
- return SHA384_End(&context, digest);
-}
diff --git a/Source/cm_sha2.h b/Source/cm_sha2.h
deleted file mode 100644
index 71395f06b..000000000
--- a/Source/cm_sha2.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * FILE: sha2.h
- * AUTHOR: Aaron D. Gifford
- * http://www.aarongifford.com/computers/sha.html
- *
- * Copyright (c) 2000-2003, Aaron D. Gifford
- * All rights reserved.
- *
- * 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 copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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.
- *
- * $Id: sha2.h,v 1.4 2004/01/07 19:06:18 adg Exp $
- */
-
-#ifndef __SHA2_H__
-#define __SHA2_H__
-
-#include "cm_sha2_mangle.h"
-
-/* CMake modification: use integer types from cmIML. */
-#include "cmIML/INT.h"
-typedef cmIML_INT_uint8_t cm_sha2_uint8_t;
-typedef cmIML_INT_uint32_t cm_sha2_uint32_t;
-typedef cmIML_INT_uint64_t cm_sha2_uint64_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Import u_intXX_t size_t type definitions from system headers. You
- * may need to change this, or define these things yourself in this
- * file.
- */
-#include <sys/types.h>
-
-/*** SHA-224/256/384/512 Various Length Definitions *******************/
-
-/* Digest lengths for SHA-1/224/256/384/512 */
-#define SHA1_DIGEST_LENGTH 20
-#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1)
-#define SHA224_DIGEST_LENGTH 28
-#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
-#define SHA256_DIGEST_LENGTH 32
-#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
-#define SHA384_DIGEST_LENGTH 48
-#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
-#define SHA512_DIGEST_LENGTH 64
-#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
-
-
-/*** SHA-224/256/384/512 Context Structures ***************************/
-
-typedef union _SHA_CTX {
- /* SHA-1 uses this part of the union: */
- struct {
- cm_sha2_uint32_t state[5];
- cm_sha2_uint64_t bitcount;
- cm_sha2_uint8_t buffer[64];
- } s1;
-
- /* SHA-224 and SHA-256 use this part of the union: */
- struct {
- cm_sha2_uint32_t state[8];
- cm_sha2_uint64_t bitcount;
- cm_sha2_uint8_t buffer[64];
- } s256;
-
- /* SHA-384 and SHA-512 use this part of the union: */
- struct {
- cm_sha2_uint64_t state[8];
- cm_sha2_uint64_t bitcount[2];
- cm_sha2_uint8_t buffer[128];
- } s512;
-} SHA_CTX;
-
-/*** SHA-256/384/512 Function Prototypes ******************************/
-
-void SHA1_Init(SHA_CTX*);
-void SHA1_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t);
-void SHA1_Final(cm_sha2_uint8_t[SHA1_DIGEST_LENGTH], SHA_CTX*);
-char* SHA1_End(SHA_CTX*, char[SHA1_DIGEST_STRING_LENGTH]);
-char* SHA1_Data(const cm_sha2_uint8_t*, size_t,
- char[SHA1_DIGEST_STRING_LENGTH]);
-
-void SHA224_Init(SHA_CTX*);
-void SHA224_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t);
-void SHA224_Final(cm_sha2_uint8_t[SHA224_DIGEST_LENGTH], SHA_CTX*);
-char* SHA224_End(SHA_CTX*, char[SHA224_DIGEST_STRING_LENGTH]);
-char* SHA224_Data(const cm_sha2_uint8_t*, size_t,
- char[SHA224_DIGEST_STRING_LENGTH]);
-
-void SHA256_Init(SHA_CTX*);
-void SHA256_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t);
-void SHA256_Final(cm_sha2_uint8_t[SHA256_DIGEST_LENGTH], SHA_CTX*);
-char* SHA256_End(SHA_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
-char* SHA256_Data(const cm_sha2_uint8_t*, size_t,
- char[SHA256_DIGEST_STRING_LENGTH]);
-
-void SHA384_Init(SHA_CTX*);
-void SHA384_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t);
-void SHA384_Final(cm_sha2_uint8_t[SHA384_DIGEST_LENGTH], SHA_CTX*);
-char* SHA384_End(SHA_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
-char* SHA384_Data(const cm_sha2_uint8_t*, size_t,
- char[SHA384_DIGEST_STRING_LENGTH]);
-
-void SHA512_Init(SHA_CTX*);
-void SHA512_Update(SHA_CTX*, const cm_sha2_uint8_t*, size_t);
-void SHA512_Final(cm_sha2_uint8_t[SHA512_DIGEST_LENGTH], SHA_CTX*);
-char* SHA512_End(SHA_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
-char* SHA512_Data(const cm_sha2_uint8_t*, size_t,
- char[SHA512_DIGEST_STRING_LENGTH]);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __SHA2_H__ */
diff --git a/Source/cm_sha2_mangle.h b/Source/cm_sha2_mangle.h
deleted file mode 100644
index e73d13141..000000000
--- a/Source/cm_sha2_mangle.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef cm_sha2_mangle_h
-#define cm_sha2_mangle_h
-
-/* Mangle sha2 symbol names to avoid possible conflict with
- implementations in other libraries to which CMake links. */
-#define SHA1_Data cmSHA1_Data
-#define SHA1_End cmSHA1_End
-#define SHA1_Final cmSHA1_Final
-#define SHA1_Init cmSHA1_Init
-#define SHA1_Internal_Transform cmSHA1_Internal_Transform
-#define SHA1_Update cmSHA1_Update
-#define SHA224_Data cmSHA224_Data
-#define SHA224_End cmSHA224_End
-#define SHA224_Final cmSHA224_Final
-#define SHA224_Init cmSHA224_Init
-#define SHA224_Internal_Transform cmSHA224_Internal_Transform
-#define SHA224_Update cmSHA224_Update
-#define SHA256_Data cmSHA256_Data
-#define SHA256_End cmSHA256_End
-#define SHA256_Final cmSHA256_Final
-#define SHA256_Init cmSHA256_Init
-#define SHA256_Internal_Init cmSHA256_Internal_Init
-#define SHA256_Internal_Last cmSHA256_Internal_Last
-#define SHA256_Internal_Transform cmSHA256_Internal_Transform
-#define SHA256_Update cmSHA256_Update
-#define SHA384_Data cmSHA384_Data
-#define SHA384_End cmSHA384_End
-#define SHA384_Final cmSHA384_Final
-#define SHA384_Init cmSHA384_Init
-#define SHA384_Update cmSHA384_Update
-#define SHA512_Data cmSHA512_Data
-#define SHA512_End cmSHA512_End
-#define SHA512_Final cmSHA512_Final
-#define SHA512_Init cmSHA512_Init
-#define SHA512_Internal_Init cmSHA512_Internal_Init
-#define SHA512_Internal_Last cmSHA512_Internal_Last
-#define SHA512_Internal_Transform cmSHA512_Internal_Transform
-#define SHA512_Update cmSHA512_Update
-
-#endif
diff --git a/Source/cm_sys_stat.h b/Source/cm_sys_stat.h
new file mode 100644
index 000000000..26e4baa03
--- /dev/null
+++ b/Source/cm_sys_stat.h
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_sys_stat_h
+#define cm_sys_stat_h
+
+#if defined(_MSC_VER)
+typedef unsigned short mode_t;
+#endif
+
+#include <sys/types.h>
+// include sys/stat.h after sys/types.h
+#include <sys/stat.h>
+
+#endif
diff --git a/Source/cm_unordered_map.hxx b/Source/cm_unordered_map.hxx
new file mode 100644
index 000000000..bf3890314
--- /dev/null
+++ b/Source/cm_unordered_map.hxx
@@ -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 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
new file mode 100644
index 000000000..dd1a9a115
--- /dev/null
+++ b/Source/cm_unordered_set.hxx
@@ -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 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 c9bf259ac..52af4a6f4 100644
--- a/Source/cm_utf8.c
+++ b/Source/cm_utf8.c
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cm_utf8.h"
/*
@@ -24,61 +15,63 @@
*/
/* Number of leading ones before a zero in the byte. */
-static unsigned char const cm_utf8_ones[256] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 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,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8
+unsigned char const cm_utf8_ones[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8
};
/* Mask away control bits from bytes with n leading ones. */
-static unsigned char const cm_utf8_mask[7] = {
- 0xEF, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01
-};
+static unsigned char const cm_utf8_mask[7] = { 0xEF, 0x3F, 0x1F, 0x0F,
+ 0x07, 0x03, 0x01 };
/* Minimum allowed value when first byte has n leading ones. */
static unsigned int const cm_utf8_min[7] = {
- 0, 0, 1u<<7, 1u<<11, 1u<<16, 1u<<21, 1u<<26 /*, 1u<<31 */
+ 0, 0, 1u << 7, 1u << 11, 1u << 16, 1u << 21, 1u << 26 /*, 1u<<31 */
};
-/*--------------------------------------------------------------------------*/
const char* cm_utf8_decode_character(const char* first, const char* last,
unsigned int* pc)
{
/* Count leading ones in the first byte. */
unsigned char c = (unsigned char)*first++;
unsigned char const ones = cm_utf8_ones[c];
- switch(ones)
- {
- case 0: *pc = c; return first; /* One-byte character. */
- case 1: case 7: case 8: return 0; /* Invalid leading byte. */
- default: break;
- }
+ switch (ones) {
+ case 0:
+ *pc = c;
+ return first; /* One-byte character. */
+ case 1:
+ case 7:
+ case 8:
+ return 0; /* Invalid leading byte. */
+ default:
+ break;
+ }
/* Extract bits from this multi-byte character. */
{
- unsigned int uc = c & cm_utf8_mask[ones];
- int left;
- for(left = ones-1; left && first != last; --left)
- {
- c = (unsigned char)*first++;
- if(cm_utf8_ones[c] != 1)
- {
- return 0;
+ unsigned int uc = c & cm_utf8_mask[ones];
+ int left;
+ for (left = ones - 1; left && first != last; --left) {
+ c = (unsigned char)*first++;
+ if (cm_utf8_ones[c] != 1) {
+ return 0;
}
- uc = (uc << 6) | (c & cm_utf8_mask[1]);
+ uc = (uc << 6) | (c & cm_utf8_mask[1]);
}
- if(left > 0 || uc < cm_utf8_min[ones])
- {
- return 0;
+ if (left > 0 || uc < cm_utf8_min[ones]) {
+ return 0;
}
- *pc = uc;
- return first;
+ *pc = uc;
+ return first;
}
}
diff --git a/Source/cm_utf8.h b/Source/cm_utf8.h
index 06e2868d5..fcb43e0e4 100644
--- a/Source/cm_utf8.h
+++ b/Source/cm_utf8.h
@@ -1,14 +1,5 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cm_utf8_h
#define cm_utf8_h
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 14ddc1b01..689439378 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1,590 +1,537 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmake.h"
-#include "cmDocumentVariables.h"
-#include "time.h"
-#include "cmCacheManager.h"
-#include "cmMakefile.h"
-#include "cmLocalGenerator.h"
-#include "cmExternalMakefileProjectGenerator.h"
+
+#include "cmAlgorithms.h"
#include "cmCommands.h"
-#include "cmCommand.h"
+#include "cmDocumentation.h"
+#include "cmDocumentationEntry.h"
+#include "cmDocumentationFormatter.h"
+#include "cmExternalMakefileProjectGenerator.h"
#include "cmFileTimeComparison.h"
-#include "cmGeneratedFileStream.h"
-#include "cmQtAutomoc.h"
-#include "cmSourceFile.h"
-#include "cmVersion.h"
-#include "cmTest.h"
-#include "cmDocumentationFormatterText.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmLinkLineComputer.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessenger.h"
+#include "cmState.h"
+#include "cmStateDirectory.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 "cmGraphVizWriter.h"
-# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
-# include "cmVariableWatch.h"
-# include <cmsys/Terminal.h>
-# include <cmsys/CommandLineArguments.hxx>
-#endif
+#include "cm_jsoncpp_writer.h"
-#include <cmsys/Directory.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
+#include "cmGraphVizWriter.h"
+#include "cmVariableWatch.h"
+#include "cm_unordered_map.hxx"
+#endif
// only build kdevelop generator on non-windows platforms
// when not bootstrapping cmake
#if !defined(_WIN32)
-# if defined(CMAKE_BUILD_WITH_CMAKE)
-# define CMAKE_USE_KDEVELOP
-# endif
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#define CMAKE_USE_KDEVELOP
+#endif
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE)
-# define CMAKE_USE_ECLIPSE
+#define CMAKE_USE_ECLIPSE
#endif
#if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
-# define CMAKE_BOOT_MINGW
+#define CMAKE_BOOT_MINGW
#endif
// include the generator
#if defined(_WIN32) && !defined(__CYGWIN__)
-# if !defined(CMAKE_BOOT_MINGW)
-# include "cmGlobalVisualStudio6Generator.h"
-# include "cmGlobalVisualStudio7Generator.h"
-# include "cmGlobalVisualStudio71Generator.h"
-# include "cmGlobalVisualStudio8Generator.h"
-# include "cmGlobalVisualStudio9Generator.h"
-# include "cmGlobalVisualStudio10Generator.h"
-# include "cmGlobalVisualStudio11Generator.h"
-# include "cmGlobalVisualStudio12Generator.h"
-# include "cmGlobalBorlandMakefileGenerator.h"
-# include "cmGlobalNMakeMakefileGenerator.h"
-# include "cmGlobalJOMMakefileGenerator.h"
-# include "cmGlobalWatcomWMakeGenerator.h"
-# define CMAKE_HAVE_VS_GENERATORS
-# endif
-# include "cmGlobalMSYSMakefileGenerator.h"
-# include "cmGlobalMinGWMakefileGenerator.h"
-# include "cmWin32ProcessExecution.h"
+#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"
#else
#endif
+#if defined(CMAKE_USE_WMAKE)
+#include "cmGlobalWatcomWMakeGenerator.h"
+#endif
#include "cmGlobalUnixMakefileGenerator3.h"
+#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmGlobalNinjaGenerator.h"
-
-
-#if defined(CMAKE_HAVE_VS_GENERATORS)
-#include "cmCallVisualStudioMacro.h"
-#include "cmVisualStudioWCEPlatformParser.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"
+#include "cmGlobalKdevelopGenerator.h"
#endif
#ifdef CMAKE_USE_ECLIPSE
-# include "cmExtraEclipseCDT4Generator.h"
+#include "cmExtraEclipseCDT4Generator.h"
#endif
-#include <stdlib.h> // required for atoi
+#if defined(__APPLE__)
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmGlobalXCodeGenerator.h"
-#if defined( __APPLE__ )
-# if defined(CMAKE_BUILD_WITH_CMAKE)
-# include "cmGlobalXCodeGenerator.h"
-# define CMAKE_USE_XCODE 1
-# endif
-# include <sys/types.h>
-# include <sys/time.h>
-# include <sys/resource.h>
+#define CMAKE_USE_XCODE 1
+#endif
+#include <sys/resource.h>
+#include <sys/time.h>
#endif
-#include <sys/stat.h> // struct stat
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
-static bool cmakeCheckStampFile(const char* stampName);
-static bool cmakeCheckStampList(const char* stampName);
+namespace {
-void cmNeedBackwardsCompatibility(const std::string& variable,
- int access_type, void*, const char*, const cmMakefile*)
-{
-#ifdef CMAKE_BUILD_WITH_CMAKE
- if (access_type == cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS)
- {
- std::string message = "An attempt was made to access a variable: ";
- message += variable;
- message +=
- " that has not been defined. Some variables were always defined "
- "by CMake in versions prior to 1.6. To fix this you might need to set "
- "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
- "you are writing a CMakeLists file, (or have already set "
- "CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less) then you probably need "
- "to include a CMake module to test for the feature this variable "
- "defines.";
- cmSystemTools::Error(message.c_str());
- }
-#else
- (void)variable;
- (void)access_type;
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+typedef CM_UNORDERED_MAP<std::string, Json::Value> JsonValueMapType;
#endif
-}
-void cmWarnUnusedCliWarning(const std::string& variable,
- int, void* ctx, const char*, const cmMakefile*)
+} // namespace
+
+static bool cmakeCheckStampFile(const char* stampName, bool verbose = true);
+static bool cmakeCheckStampList(const char* stampList, bool verbose = true);
+
+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()
+cmake::cmake(Role role)
{
this->Trace = false;
+ this->TraceExpand = false;
this->WarnUninitialized = false;
this->WarnUnused = false;
this->WarnUnusedCli = true;
this->CheckSystemVars = false;
- this->SuppressDevWarnings = false;
- this->DoSuppressDevWarnings = false;
this->DebugOutput = false;
this->DebugTryCompile = false;
this->ClearBuildSystem = false;
this->FileComparison = new cmFileTimeComparison;
- this->Policies = new cmPolicies();
- this->InitializeProperties();
+ this->State = new cmState;
+ this->CurrentSnapshot = this->State->CreateBaseSnapshot();
+ this->Messenger = new cmMessenger(this->State);
#ifdef __APPLE__
struct rlimit rlp;
- if(!getrlimit(RLIMIT_STACK, &rlp))
- {
- if(rlp.rlim_cur != rlp.rlim_max)
- {
- rlp.rlim_cur = rlp.rlim_max;
- setrlimit(RLIMIT_STACK, &rlp);
- }
+ if (!getrlimit(RLIMIT_STACK, &rlp)) {
+ if (rlp.rlim_cur != rlp.rlim_max) {
+ rlp.rlim_cur = rlp.rlim_max;
+ setrlimit(RLIMIT_STACK, &rlp);
}
+ }
#endif
- this->Verbose = false;
- this->InTryCompile = false;
- this->CacheManager = new cmCacheManager(this);
- this->GlobalGenerator = 0;
- this->ProgressCallback = 0;
- this->ProgressCallbackClientData = 0;
+ 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;
- this->VariableWatch->AddWatch("CMAKE_WORDS_BIGENDIAN",
- cmNeedBackwardsCompatibility);
- this->VariableWatch->AddWatch("CMAKE_SIZEOF_INT",
- cmNeedBackwardsCompatibility);
- this->VariableWatch->AddWatch("CMAKE_X_LIBS",
- cmNeedBackwardsCompatibility);
#endif
this->AddDefaultGenerators();
this->AddDefaultExtraGenerators();
- this->AddDefaultCommands();
+ if (role == RoleScript || role == RoleProject) {
+ this->AddScriptingCommands();
+ }
+ if (role == RoleProject) {
+ this->AddProjectCommands();
+ }
// 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");
}
cmake::~cmake()
{
- delete this->CacheManager;
- delete this->Policies;
- if (this->GlobalGenerator)
- {
+ delete this->State;
+ delete this->Messenger;
+ if (this->GlobalGenerator) {
delete this->GlobalGenerator;
- this->GlobalGenerator = 0;
- }
- for(RegisteredCommandsMap::iterator j = this->Commands.begin();
- j != this->Commands.end(); ++j)
- {
- delete (*j).second;
- }
- for(RegisteredGeneratorsVector::iterator j = this->Generators.begin();
- j != this->Generators.end(); ++j)
- {
- delete *j;
- }
+ this->GlobalGenerator = CM_NULLPTR;
+ }
+ cmDeleteAll(this->Generators);
#ifdef CMAKE_BUILD_WITH_CMAKE
delete this->VariableWatch;
#endif
delete this->FileComparison;
}
-void cmake::InitializeProperties()
-{
- this->Properties.clear();
- this->Properties.SetCMakeInstance(this);
- this->AccessedProperties.clear();
- this->PropertyDefinitions.clear();
-
- // initialize properties
- cmCacheManager::DefineProperties(this);
- cmSourceFile::DefineProperties(this);
- cmTarget::DefineProperties(this);
- cmMakefile::DefineProperties(this);
- cmTest::DefineProperties(this);
- cmake::DefineProperties(this);
-}
-
-void cmake::CleanupCommandsAndMacros()
-{
- this->InitializeProperties();
- std::vector<cmCommand*> commands;
- for(RegisteredCommandsMap::iterator j = this->Commands.begin();
- j != this->Commands.end(); ++j)
- {
- if ( !j->second->IsA("cmMacroHelperCommand") &&
- !j->second->IsA("cmFunctionHelperCommand"))
- {
- commands.push_back(j->second);
- }
- else
- {
- delete j->second;
- }
- }
- this->Commands.erase(this->Commands.begin(), this->Commands.end());
- std::vector<cmCommand*>::iterator it;
- for ( it = commands.begin(); it != commands.end();
- ++ it )
- {
- this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
- }
-}
-
-bool cmake::CommandExists(const char* name) const
-{
- std::string sName = cmSystemTools::LowerCase(name);
- return (this->Commands.find(sName) != this->Commands.end());
-}
-
-cmCommand *cmake::GetCommand(const char *name)
-{
- cmCommand* rm = 0;
- std::string sName = cmSystemTools::LowerCase(name);
- RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
- if (pos != this->Commands.end())
- {
- rm = (*pos).second;
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
+{
+ Json::Value obj = Json::objectValue;
+ // Version information:
+ Json::Value version = Json::objectValue;
+ version["string"] = CMake_VERSION;
+ version["major"] = CMake_VERSION_MAJOR;
+ version["minor"] = CMake_VERSION_MINOR;
+ version["suffix"] = CMake_VERSION_SUFFIX;
+ version["isDirty"] = (CMake_VERSION_IS_DIRTY == 1);
+ version["patch"] = CMake_VERSION_PATCH;
+
+ obj["version"] = version;
+
+ // 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
+ // only
+ continue;
}
- return rm;
-}
-void cmake::RenameCommand(const char*oldName, const char* newName)
-{
- // if the command already exists, free the old one
- std::string sOldName = cmSystemTools::LowerCase(oldName);
- std::string sNewName = cmSystemTools::LowerCase(newName);
- RegisteredCommandsMap::iterator pos = this->Commands.find(sOldName);
- if ( pos == this->Commands.end() )
- {
- return;
+ if (i->extraName.empty()) {
+ Json::Value gen = Json::objectValue;
+ gen["name"] = i->name;
+ gen["toolsetSupport"] = i->supportsToolset;
+ gen["platformSupport"] = i->supportsPlatform;
+ gen["extraGenerators"] = Json::arrayValue;
+ generatorMap[i->name] = gen;
+ } else {
+ Json::Value& gen = generatorMap[i->baseName];
+ gen["extraGenerators"].append(i->extraName);
}
- cmCommand* cmd = pos->second;
+ }
- pos = this->Commands.find(sNewName);
- if (pos != this->Commands.end())
- {
- delete pos->second;
- this->Commands.erase(pos);
- }
- this->Commands.insert(RegisteredCommandsMap::value_type(sNewName, cmd));
- pos = this->Commands.find(sOldName);
- this->Commands.erase(pos);
-}
+ Json::Value generators = Json::arrayValue;
+ for (JsonValueMapType::const_iterator i = generatorMap.begin();
+ i != generatorMap.end(); ++i) {
+ generators.append(i->second);
+ }
+ obj["generators"] = generators;
+ obj["serverMode"] = haveServerMode;
-void cmake::RemoveCommand(const char* name)
-{
- std::string sName = cmSystemTools::LowerCase(name);
- RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
- if ( pos != this->Commands.end() )
- {
- delete pos->second;
- this->Commands.erase(pos);
- }
+ return obj;
}
+#endif
-void cmake::AddCommand(cmCommand* wg)
+std::string cmake::ReportCapabilities(bool haveServerMode) const
{
- std::string name = cmSystemTools::LowerCase(wg->GetName());
- // if the command already exists, free the old one
- RegisteredCommandsMap::iterator pos = this->Commands.find(name);
- if (pos != this->Commands.end())
- {
- delete pos->second;
- this->Commands.erase(pos);
- }
- this->Commands.insert( RegisteredCommandsMap::value_type(name, wg));
+ std::string result;
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ Json::FastWriter writer;
+ result = writer.write(this->ReportCapabilitiesJson(haveServerMode));
+#else
+ result = "Not supported";
+#endif
+ return result;
}
-
-void cmake::RemoveUnscriptableCommands()
+void cmake::CleanupCommandsAndMacros()
{
- std::vector<std::string> unscriptableCommands;
- cmake::RegisteredCommandsMap* commands = this->GetCommands();
- for (cmake::RegisteredCommandsMap::const_iterator pos = commands->begin();
- pos != commands->end();
- ++pos)
- {
- if (!pos->second->IsScriptable())
- {
- unscriptableCommands.push_back(pos->first);
- }
- }
-
- for(std::vector<std::string>::const_iterator it=unscriptableCommands.begin();
- it != unscriptableCommands.end();
- ++it)
- {
- this->RemoveCommand(it->c_str());
- }
+ this->CurrentSnapshot = this->State->Reset();
+ this->State->RemoveUserDefinedCommands();
+ this->CurrentSnapshot.SetDefaultDefinitions();
}
// Parse the args
bool cmake::SetCacheArgs(const std::vector<std::string>& args)
{
bool findPackageMode = false;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- std::string arg = args[i];
- if(arg.find("-D",0) == 0)
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ std::string const& arg = args[i];
+ if (arg.find("-D", 0) == 0) {
std::string entry = arg.substr(2);
- if(entry.size() == 0)
- {
+ if (entry.empty()) {
++i;
- if(i < args.size())
- {
+ if (i < args.size()) {
entry = args[i];
- }
- else
- {
+ } else {
cmSystemTools::Error("-D must be followed with VAR=VALUE.");
return false;
- }
}
+ }
std::string var, value;
- cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
- if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
- {
+ cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
+ if (cmState::ParseCacheEntry(entry, var, value, type)) {
// The value is transformed if it is a filepath for example, so
// we can't compare whether the value is already in the cache until
// after we call AddCacheEntry.
- const char *cachedValue =
- this->CacheManager->GetCacheValue(var.c_str());
+ bool haveValue = false;
+ std::string cachedValue;
+ if (this->WarnUnusedCli) {
+ if (const char* v = this->State->GetInitializedCacheValue(var)) {
+ haveValue = true;
+ cachedValue = v;
+ }
+ }
- this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
- "No help, variable specified on the command line.", type);
- if(this->WarnUnusedCli)
- {
- if (!cachedValue
- || strcmp(this->CacheManager->GetCacheValue(var.c_str()),
- cachedValue) != 0)
- {
- this->WatchUnusedCli(var.c_str());
- }
+ this->AddCacheEntry(var, value.c_str(),
+ "No help, variable specified on the command line.",
+ type);
+
+ if (this->WarnUnusedCli) {
+ if (!haveValue ||
+ cachedValue != this->State->GetInitializedCacheValue(var)) {
+ this->WatchUnusedCli(var);
}
}
- else
- {
+ } else {
std::cerr << "Parse error in command line argument: " << arg << "\n"
<< "Should be: VAR:type=value\n";
cmSystemTools::Error("No cmake script provided.");
return false;
+ }
+ } else if (cmHasLiteralPrefix(arg, "-W")) {
+ std::string entry = arg.substr(2);
+ if (entry.empty()) {
+ ++i;
+ if (i < args.size()) {
+ entry = args[i];
+ } else {
+ cmSystemTools::Error("-W must be followed with [no-]<name>.");
+ return false;
}
}
- else if(arg.find("-Wno-dev",0) == 0)
- {
- this->SuppressDevWarnings = true;
- this->DoSuppressDevWarnings = true;
+
+ std::string name;
+ bool foundNo = false;
+ bool foundError = false;
+ unsigned int nameStartPosition = 0;
+
+ if (entry.find("no-", nameStartPosition) == 0) {
+ foundNo = true;
+ nameStartPosition += 3;
}
- else if(arg.find("-Wdev",0) == 0)
- {
- this->SuppressDevWarnings = false;
- this->DoSuppressDevWarnings = true;
+
+ if (entry.find("error=", nameStartPosition) == 0) {
+ foundError = true;
+ nameStartPosition += 6;
}
- else if(arg.find("-U",0) == 0)
- {
+
+ name = entry.substr(nameStartPosition);
+ if (name.empty()) {
+ cmSystemTools::Error("No warning name provided.");
+ return false;
+ }
+
+ if (!foundNo && !foundError) {
+ // -W<name>
+ this->DiagLevels[name] = std::max(this->DiagLevels[name], DIAG_WARN);
+ } else if (foundNo && !foundError) {
+ // -Wno<name>
+ this->DiagLevels[name] = DIAG_IGNORE;
+ } else if (!foundNo && foundError) {
+ // -Werror=<name>
+ this->DiagLevels[name] = DIAG_ERROR;
+ } else {
+ // -Wno-error=<name>
+ this->DiagLevels[name] = std::min(this->DiagLevels[name], DIAG_WARN);
+ }
+ } else if (arg.find("-U", 0) == 0) {
std::string entryPattern = arg.substr(2);
- if(entryPattern.size() == 0)
- {
+ if (entryPattern.empty()) {
++i;
- if(i < args.size())
- {
+ if (i < args.size()) {
entryPattern = args[i];
- }
- else
- {
+ } else {
cmSystemTools::Error("-U must be followed with VAR.");
return false;
- }
}
+ }
cmsys::RegularExpression regex(
- cmsys::Glob::PatternToRegex(entryPattern.c_str(), true, true).c_str());
- //go through all cache entries and collect the vars which will be removed
+ cmsys::Glob::PatternToRegex(entryPattern, true, true).c_str());
+ // go through all cache entries and collect the vars which will be
+ // removed
std::vector<std::string> entriesToDelete;
- cmCacheManager::CacheIterator it =
- this->CacheManager->GetCacheIterator();
- for ( it.Begin(); !it.IsAtEnd(); it.Next() )
- {
- cmCacheManager::CacheEntryType t = it.GetType();
- if(t != cmCacheManager::STATIC)
- {
- std::string entryName = it.GetName();
- if (regex.find(entryName.c_str()))
- {
- entriesToDelete.push_back(entryName);
- }
+ 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);
+ if (t != cmStateEnums::STATIC) {
+ if (regex.find(it->c_str())) {
+ entriesToDelete.push_back(*it);
}
}
+ }
// now remove them from the cache
- for(std::vector<std::string>::const_iterator currentEntry =
- entriesToDelete.begin();
- currentEntry != entriesToDelete.end();
- ++currentEntry)
- {
- this->CacheManager->RemoveCacheEntry(currentEntry->c_str());
- }
+ for (std::vector<std::string>::const_iterator currentEntry =
+ entriesToDelete.begin();
+ currentEntry != entriesToDelete.end(); ++currentEntry) {
+ this->State->RemoveCacheEntry(*currentEntry);
}
- else if(arg.find("-C",0) == 0)
- {
+ } else if (arg.find("-C", 0) == 0) {
std::string path = arg.substr(2);
- if ( path.size() == 0 )
- {
+ if (path.empty()) {
++i;
- if(i < args.size())
- {
+ if (i < args.size()) {
path = args[i];
- }
- else
- {
+ } else {
cmSystemTools::Error("-C must be followed by a file name.");
return false;
- }
}
- std::cerr << "loading initial cache file " << path.c_str() << "\n";
- this->ReadListFile(args, path.c_str());
}
- else if(arg.find("-P",0) == 0)
- {
+ std::cout << "loading initial cache file " << path << "\n";
+ this->ReadListFile(args, path.c_str());
+ } else if (arg.find("-P", 0) == 0) {
i++;
- if(i >= args.size())
- {
+ if (i >= args.size()) {
cmSystemTools::Error("-P must be followed by a file name.");
return false;
- }
+ }
std::string path = args[i];
- if ( path.size() == 0 )
- {
+ if (path.empty()) {
cmSystemTools::Error("No cmake script provided.");
return false;
- }
- this->ReadListFile(args, path.c_str());
}
- else if (arg.find("--find-package",0) == 0)
- {
+ // Register fake project commands that hint misuse in script mode.
+ GetProjectCommandsInScriptMode(this->State);
+ this->ReadListFile(args, path.c_str());
+ } else if (arg.find("--find-package", 0) == 0) {
findPackageMode = true;
- }
}
+ }
- if (findPackageMode)
- {
+ if (findPackageMode) {
return this->FindPackage(args);
- }
+ }
return true;
}
void cmake::ReadListFile(const std::vector<std::string>& args,
- const char *path)
+ const char* path)
{
// if a generator was not yet created, temporarily create one
- cmGlobalGenerator *gg = this->GetGlobalGenerator();
+ cmGlobalGenerator* gg = this->GetGlobalGenerator();
bool created = false;
// if a generator was not specified use a generic one
- if (!gg)
- {
- gg = new cmGlobalGenerator;
- gg->SetCMakeInstance(this);
+ if (!gg) {
+ gg = new cmGlobalGenerator(this);
created = true;
- }
+ }
// read in the list file to fill the cache
- if(path)
- {
- cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
- lg->GetMakefile()->SetHomeOutputDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- lg->GetMakefile()->SetStartOutputDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- lg->GetMakefile()->SetHomeDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- lg->GetMakefile()->SetStartDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- if (this->GetWorkingMode() != NORMAL_MODE)
- {
+ if (path) {
+ 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.SetDefaultDefinitions();
+ CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(gg, snapshot));
+ if (this->GetWorkingMode() != NORMAL_MODE) {
std::string file(cmSystemTools::CollapseFullPath(path));
cmSystemTools::ConvertToUnixSlashes(file);
- lg->GetMakefile()->SetScriptModeFile(file.c_str());
+ mf->SetScriptModeFile(file.c_str());
- lg->GetMakefile()->SetArgcArgv(args);
- }
- if (!lg->GetMakefile()->ReadListFile(0, path))
- {
+ mf->SetArgcArgv(args);
+ }
+ if (!mf->ReadListFile(path)) {
cmSystemTools::Error("Error processing file: ", path);
- }
}
+ this->SetHomeDirectory(homeDir);
+ this->SetHomeOutputDirectory(homeOutputDir);
+ }
// free generic one if generated
- if (created)
- {
+ if (created) {
delete gg;
- }
+ }
}
-
bool cmake::FindPackage(const std::vector<std::string>& args)
{
+ this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+
// if a generator was not yet created, temporarily create one
- cmGlobalGenerator *gg = new cmGlobalGenerator;
- gg->SetCMakeInstance(this);
+ cmGlobalGenerator* gg = new cmGlobalGenerator(this);
this->SetGlobalGenerator(gg);
+ cmStateSnapshot snapshot = this->GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentBinary(
+ cmSystemTools::GetCurrentWorkingDirectory());
+ snapshot.GetDirectory().SetCurrentSource(
+ cmSystemTools::GetCurrentWorkingDirectory());
// read in the list file to fill the cache
- cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
- cmMakefile* mf = lg->GetMakefile();
- mf->SetHomeOutputDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- mf->SetStartOutputDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- mf->SetHomeDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- mf->SetStartDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
+ snapshot.SetDefaultDefinitions();
+ cmMakefile* mf = new cmMakefile(gg, snapshot);
+ gg->AddMakefile(mf);
mf->SetArgcArgv(args);
std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake");
- mf->ReadListFile(0, systemFile.c_str());
+ mf->ReadListFile(systemFile.c_str());
std::string language = mf->GetSafeDefinition("LANGUAGE");
std::string mode = mf->GetSafeDefinition("MODE");
@@ -592,34 +539,27 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
bool packageFound = mf->IsOn("PACKAGE_FOUND");
bool quiet = mf->IsOn("PACKAGE_QUIET");
- if (!packageFound)
- {
- if (!quiet)
- {
+ if (!packageFound) {
+ if (!quiet) {
printf("%s not found.\n", packageName.c_str());
- }
}
- else if (mode == "EXIST")
- {
- if (!quiet)
- {
+ } else if (mode == "EXIST") {
+ if (!quiet) {
printf("%s found.\n", packageName.c_str());
- }
}
- else if (mode == "COMPILE")
- {
+ } else if (mode == "COMPILE") {
std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS");
std::vector<std::string> includeDirs;
cmSystemTools::ExpandListArgument(includes, includeDirs);
- std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0,
- language.c_str(), false);
+ gg->CreateGenerationObjects();
+ cmLocalGenerator* lg = gg->LocalGenerators[0];
+ std::string includeFlags =
+ lg->GetIncludeFlags(includeDirs, CM_NULLPTR, language);
std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
- }
- else if (mode == "LINK")
- {
+ } else if (mode == "LINK") {
const char* targetName = "dummy";
std::vector<std::string> srcs;
cmTarget* tgt = mf->AddExecutable(targetName, srcs, true);
@@ -628,249 +568,208 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
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)
- {
- mf->AddLinkLibraryForTarget(targetName, libIt->c_str(),
- cmTarget::GENERAL);
- }
+ for (std::vector<std::string>::const_iterator libIt = libList.begin();
+ libIt != libList.end(); ++libIt) {
+ tgt->AddLinkLibrary(*mf, *libIt, GENERAL_LibraryType);
+ }
+ std::string buildType = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ buildType = cmSystemTools::UpperCase(buildType);
std::string linkLibs;
std::string frameworkPath;
std::string linkPath;
std::string flags;
std::string linkFlags;
- cmGeneratorTarget gtgt(tgt);
- lg->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags,
- &gtgt);
+ gg->CreateGenerationObjects();
+ cmGeneratorTarget* gtgt = gg->FindGeneratorTarget(tgt->GetName());
+ cmLocalGenerator* lg = gtgt->GetLocalGenerator();
+ cmLinkLineComputer linkLineComputer(lg,
+ lg->GetStateSnapshot().GetDirectory());
+ lg->GetTargetFlags(&linkLineComputer, buildType, linkLibs, flags,
+ linkFlags, frameworkPath, linkPath, gtgt);
linkLibs = frameworkPath + linkPath + linkLibs;
- printf("%s\n", linkLibs.c_str() );
+ printf("%s\n", linkLibs.c_str());
-/* if ( use_win32 )
- {
- tgt->SetProperty("WIN32_EXECUTABLE", "ON");
- }
- if ( use_macbundle)
- {
- tgt->SetProperty("MACOSX_BUNDLE", "ON");
- }*/
- }
+ /* if ( use_win32 )
+ {
+ tgt->SetProperty("WIN32_EXECUTABLE", "ON");
+ }
+ if ( use_macbundle)
+ {
+ tgt->SetProperty("MACOSX_BUNDLE", "ON");
+ }*/
+ }
// free generic one if generated
-// this->SetGlobalGenerator(0); // setting 0-pointer is not possible
-// delete gg; // this crashes inside the cmake instance
+ // this->SetGlobalGenerator(0); // setting 0-pointer is not possible
+ // delete gg; // this crashes inside the cmake instance
return packageFound;
}
-
// Parse the args
void cmake::SetArgs(const std::vector<std::string>& args,
bool directoriesSetBefore)
{
bool directoriesSet = directoriesSetBefore;
bool haveToolset = false;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- std::string arg = args[i];
- if(arg.find("-H",0) == 0)
- {
+ 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;
std::string path = arg.substr(2);
- path = cmSystemTools::CollapseFullPath(path.c_str());
+ path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
- this->SetHomeDirectory(path.c_str());
- }
- else if(arg.find("-S",0) == 0)
- {
+ 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)
- {
+ } else if (arg.find("-O", 0) == 0) {
// There is no local generate anymore. Ignore -O option.
- }
- else if(arg.find("-B",0) == 0)
- {
+ } else if (arg.find("-B", 0) == 0) {
directoriesSet = true;
std::string path = arg.substr(2);
- path = cmSystemTools::CollapseFullPath(path.c_str());
+ path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
- this->SetHomeOutputDirectory(path.c_str());
- }
- else if((i < args.size()-1) && (arg.find("--check-build-system",0) == 0))
- {
+ this->SetHomeOutputDirectory(path);
+ } else if ((i < args.size() - 2) &&
+ (arg.find("--check-build-system", 0) == 0)) {
this->CheckBuildSystemArgument = args[++i];
this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0);
- }
- else if((i < args.size()-1) && (arg.find("--check-stamp-file",0) == 0))
- {
+ } else if ((i < args.size() - 1) &&
+ (arg.find("--check-stamp-file", 0) == 0)) {
this->CheckStampFile = args[++i];
- }
- else if((i < args.size()-1) && (arg.find("--check-stamp-list",0) == 0))
- {
+ } else if ((i < args.size() - 1) &&
+ (arg.find("--check-stamp-list", 0) == 0)) {
this->CheckStampList = args[++i];
- }
+ }
#if defined(CMAKE_HAVE_VS_GENERATORS)
- else if((i < args.size()-1) && (arg.find("--vs-solution-file",0) == 0))
- {
+ else if ((i < args.size() - 1) &&
+ (arg.find("--vs-solution-file", 0) == 0)) {
this->VSSolutionFile = args[++i];
- }
+ }
#endif
- else if(arg.find("-V",0) == 0)
- {
- this->Verbose = true;
- }
- else if(arg.find("-D",0) == 0)
- {
+ else if (arg.find("-D", 0) == 0) {
// skip for now
- }
- else if(arg.find("-U",0) == 0)
- {
+ } else if (arg.find("-U", 0) == 0) {
// skip for now
- }
- else if(arg.find("-C",0) == 0)
- {
+ } else if (arg.find("-C", 0) == 0) {
// skip for now
- }
- else if(arg.find("-P",0) == 0)
- {
+ } else if (arg.find("-P", 0) == 0) {
// skip for now
i++;
- }
- else if(arg.find("--find-package",0) == 0)
- {
+ } else if (arg.find("--find-package", 0) == 0) {
// skip for now
i++;
- }
- else if(arg.find("-Wno-dev",0) == 0)
- {
- // skip for now
- }
- else if(arg.find("-Wdev",0) == 0)
- {
+ } else if (arg.find("-W", 0) == 0) {
// skip for now
- }
- else if(arg.find("--graphviz=",0) == 0)
- {
+ } else if (arg.find("--graphviz=", 0) == 0) {
std::string path = arg.substr(strlen("--graphviz="));
- path = cmSystemTools::CollapseFullPath(path.c_str());
+ path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
this->GraphVizFile = path;
- if ( this->GraphVizFile.empty() )
- {
+ if (this->GraphVizFile.empty()) {
cmSystemTools::Error("No file specified for --graphviz");
- }
}
- else if(arg.find("--debug-trycompile",0) == 0)
- {
+ } else if (arg.find("--debug-trycompile", 0) == 0) {
std::cout << "debug trycompile on\n";
this->DebugTryCompileOn();
- }
- else if(arg.find("--debug-output",0) == 0)
- {
+ } else if (arg.find("--debug-output", 0) == 0) {
std::cout << "Running with debug output on.\n";
this->SetDebugOutputOn(true);
- }
- else if(arg.find("--trace",0) == 0)
- {
+ } else if (arg.find("--trace-expand", 0) == 0) {
+ std::cout << "Running with expanded trace output on.\n";
+ this->SetTrace(true);
+ this->SetTraceExpand(true);
+ } else if (arg.find("--trace-source=", 0) == 0) {
+ std::string file = arg.substr(strlen("--trace-source="));
+ cmSystemTools::ConvertToUnixSlashes(file);
+ this->AddTraceSource(file);
+ this->SetTrace(true);
+ } else if (arg.find("--trace", 0) == 0) {
std::cout << "Running with trace output on.\n";
this->SetTrace(true);
- }
- else if(arg.find("--warn-uninitialized",0) == 0)
- {
+ this->SetTraceExpand(false);
+ } else if (arg.find("--warn-uninitialized", 0) == 0) {
std::cout << "Warn about uninitialized values.\n";
this->SetWarnUninitialized(true);
- }
- else if(arg.find("--warn-unused-vars",0) == 0)
- {
+ } else if (arg.find("--warn-unused-vars", 0) == 0) {
std::cout << "Finding unused variables.\n";
this->SetWarnUnused(true);
- }
- else if(arg.find("--no-warn-unused-cli",0) == 0)
- {
- std::cout << "Not searching for unused variables given on the " <<
- "command line.\n";
+ } else if (arg.find("--no-warn-unused-cli", 0) == 0) {
+ std::cout << "Not searching for unused variables given on the "
+ << "command line.\n";
this->SetWarnUnusedCli(false);
- }
- else if(arg.find("--check-system-vars",0) == 0)
- {
- std::cout << "Also check system files when warning about unused and " <<
- "uninitialized variables.\n";
+ } else if (arg.find("--check-system-vars", 0) == 0) {
+ std::cout << "Also check system files when warning about unused and "
+ << "uninitialized variables.\n";
this->SetCheckSystemVars(true);
+ } else if (arg.find("-A", 0) == 0) {
+ std::string value = arg.substr(2);
+ if (value.empty()) {
+ ++i;
+ if (i >= args.size()) {
+ cmSystemTools::Error("No platform specified for -A");
+ return;
+ }
+ value = args[i];
}
- else if(arg.find("-T",0) == 0)
- {
+ if (havePlatform) {
+ cmSystemTools::Error("Multiple -A options not allowed");
+ return;
+ }
+ this->GeneratorPlatform = value;
+ havePlatform = true;
+ } else if (arg.find("-T", 0) == 0) {
std::string value = arg.substr(2);
- if(value.size() == 0)
- {
+ if (value.empty()) {
++i;
- if(i >= args.size())
- {
+ if (i >= args.size()) {
cmSystemTools::Error("No toolset specified for -T");
return;
- }
- value = args[i];
}
- if(haveToolset)
- {
+ value = args[i];
+ }
+ if (haveToolset) {
cmSystemTools::Error("Multiple -T options not allowed");
return;
- }
+ }
this->GeneratorToolset = value;
haveToolset = true;
- }
- else if(arg.find("-G",0) == 0)
- {
+ } else if (arg.find("-G", 0) == 0) {
std::string value = arg.substr(2);
- if(value.size() == 0)
- {
+ if (value.empty()) {
++i;
- if(i >= args.size())
- {
+ if (i >= args.size()) {
cmSystemTools::Error("No generator specified for -G");
+ this->PrintGeneratorList();
return;
- }
- value = args[i];
}
- cmGlobalGenerator* gen =
- this->CreateGlobalGenerator(value.c_str());
- if(!gen)
- {
+ value = args[i];
+ }
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(value);
+ if (!gen) {
cmSystemTools::Error("Could not create named generator ",
value.c_str());
- }
- else
- {
+ this->PrintGeneratorList();
+ } else {
this->SetGlobalGenerator(gen);
- }
}
+ }
// no option assume it is the path to the source
- else
- {
+ else {
directoriesSet = true;
this->SetDirectoriesFromFile(arg.c_str());
- }
}
- if(!directoriesSet)
- {
- this->SetHomeOutputDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- this->SetStartOutputDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- this->SetHomeDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- this->SetStartDirectory
- (cmSystemTools::GetCurrentWorkingDirectory().c_str());
- }
-
- this->SetStartDirectory(this->GetHomeDirectory());
- this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
+ }
+ if (!directoriesSet) {
+ this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ }
}
-//----------------------------------------------------------------------------
void cmake::SetDirectoriesFromFile(const char* arg)
{
// Check if the argument refers to a CMakeCache.txt or
@@ -878,1200 +777,358 @@ void cmake::SetDirectoriesFromFile(const char* arg)
std::string listPath;
std::string cachePath;
bool argIsFile = false;
- if(cmSystemTools::FileIsDirectory(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()))
- {
+ if (cmSystemTools::FileExists(cacheFile.c_str())) {
cachePath = path;
- }
- if(cmSystemTools::FileExists(listFile.c_str()))
- {
+ }
+ if (cmSystemTools::FileExists(listFile.c_str())) {
listPath = path;
- }
}
- else if(cmSystemTools::FileExists(arg))
- {
+ } else if (cmSystemTools::FileExists(arg)) {
argIsFile = true;
std::string fullPath = cmSystemTools::CollapseFullPath(arg);
- std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
+ std::string name = cmSystemTools::GetFilenameName(fullPath);
name = cmSystemTools::LowerCase(name);
- if(name == "cmakecache.txt")
- {
- cachePath = cmSystemTools::GetFilenamePath(fullPath.c_str());
- }
- else if(name == "cmakelists.txt")
- {
- listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
- }
+ if (name == "cmakecache.txt") {
+ cachePath = cmSystemTools::GetFilenamePath(fullPath);
+ } else if (name == "cmakelists.txt") {
+ listPath = cmSystemTools::GetFilenamePath(fullPath);
}
- else
- {
+ } else {
// Specified file or directory does not exist. Try to set things
// up to produce a meaningful error message.
std::string fullPath = cmSystemTools::CollapseFullPath(arg);
- std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
+ std::string name = cmSystemTools::GetFilenameName(fullPath);
name = cmSystemTools::LowerCase(name);
- if(name == "cmakecache.txt" || name == "cmakelists.txt")
- {
+ if (name == "cmakecache.txt" || name == "cmakelists.txt") {
argIsFile = true;
- listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
- }
- else
- {
+ listPath = cmSystemTools::GetFilenamePath(fullPath);
+ } else {
listPath = fullPath;
- }
}
+ }
// If there is a CMakeCache.txt file, use its settings.
- if(cachePath.length() > 0)
- {
- cmCacheManager* cachem = this->GetCacheManager();
- cmCacheManager::CacheIterator it = cachem->NewIterator();
- if(cachem->LoadCache(cachePath.c_str()) &&
- it.Find("CMAKE_HOME_DIRECTORY"))
- {
- this->SetHomeOutputDirectory(cachePath.c_str());
- this->SetStartOutputDirectory(cachePath.c_str());
- this->SetHomeDirectory(it.GetValue());
- this->SetStartDirectory(it.GetValue());
- return;
+ if (!cachePath.empty()) {
+ if (this->LoadCache(cachePath)) {
+ const char* existingValue =
+ this->State->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
+ if (existingValue) {
+ this->SetHomeOutputDirectory(cachePath);
+ this->SetHomeDirectory(existingValue);
+ return;
}
}
+ }
// If there is a CMakeLists.txt file, use it as the source tree.
- if(listPath.length() > 0)
- {
- this->SetHomeDirectory(listPath.c_str());
- this->SetStartDirectory(listPath.c_str());
+ if (!listPath.empty()) {
+ this->SetHomeDirectory(listPath);
- if(argIsFile)
- {
+ if (argIsFile) {
// Source CMakeLists.txt file given. It was probably dropped
// onto the executable in a GUI. Default to an in-source build.
- this->SetHomeOutputDirectory(listPath.c_str());
- this->SetStartOutputDirectory(listPath.c_str());
- }
- else
- {
+ 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.c_str());
- this->SetStartOutputDirectory(cwd.c_str());
- }
- return;
+ 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.c_str());
- this->SetStartDirectory(full.c_str());
- this->SetHomeOutputDirectory(cwd.c_str());
- this->SetStartOutputDirectory(cwd.c_str());
+ this->SetHomeDirectory(full);
+ this->SetHomeOutputDirectory(cwd);
}
// at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
// cache
int cmake::AddCMakePaths()
{
- // Find the cmake executable
- std::string cMakeSelf = cmSystemTools::GetExecutableDirectory();
- cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
- cMakeSelf += "/cmake";
- cMakeSelf += cmSystemTools::GetExecutableExtension();
-#ifdef __APPLE__
- // on the apple this might be the gui bundle
- if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
- {
- cMakeSelf = cmSystemTools::GetExecutableDirectory();
- cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
- cMakeSelf += "../../../..";
- cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
- cMakeSelf = cmSystemTools::CollapseFullPath(cMakeSelf.c_str());
- cMakeSelf += "/cmake";
- std::cerr << cMakeSelf.c_str() << "\n";
- }
-#endif
- if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
- {
- cmSystemTools::Error("CMake executable cannot be found at ",
- cMakeSelf.c_str());
- return 0;
- }
// Save the value in the cache
- this->CacheManager->AddCacheEntry
- ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
- cmCacheManager::INTERNAL);
- // if the edit command is not yet in the cache,
- // or if CMakeEditCommand has been set on this object,
- // then set the CMAKE_EDIT_COMMAND in the cache
- // This will mean that the last gui to edit the cache
- // will be the one that make edit_cache uses.
- if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
- || !this->CMakeEditCommand.empty())
- {
- // Find and save the command to edit the cache
- std::string editCacheCommand;
- if(!this->CMakeEditCommand.empty())
- {
- editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf)
- + std::string("/")
- + this->CMakeEditCommand
- + cmSystemTools::GetFilenameExtension(cMakeSelf);
- }
- if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
- {
- editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
- "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
- }
- if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
- {
- editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
- "/cmake-gui" + cmSystemTools::GetFilenameExtension(cMakeSelf);
- }
- if(cmSystemTools::FileExists(editCacheCommand.c_str()))
- {
- this->CacheManager->AddCacheEntry
- ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
- "Path to cache edit program executable.", cmCacheManager::INTERNAL);
- }
- }
- std::string ctestCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
- "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf);
- if(cmSystemTools::FileExists(ctestCommand.c_str()))
- {
- this->CacheManager->AddCacheEntry
- ("CMAKE_CTEST_COMMAND", ctestCommand.c_str(),
- "Path to ctest program executable.", cmCacheManager::INTERNAL);
- }
- std::string cpackCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
- "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf);
- if(cmSystemTools::FileExists(cpackCommand.c_str()))
- {
- this->CacheManager->AddCacheEntry
- ("CMAKE_CPACK_COMMAND", cpackCommand.c_str(),
- "Path to cpack program executable.", cmCacheManager::INTERNAL);
- }
-
- // do CMAKE_ROOT, look for the environment variable first
- std::string cMakeRoot;
- std::string modules;
- if (getenv("CMAKE_ROOT"))
- {
- cMakeRoot = getenv("CMAKE_ROOT");
- modules = cMakeRoot + "/Modules/CMake.cmake";
- }
- if(!cmSystemTools::FileExists(modules.c_str()))
- {
- // next try exe/..
- cMakeRoot = cmSystemTools::GetRealPath(cMakeSelf.c_str());
- cMakeRoot = cmSystemTools::GetProgramPath(cMakeRoot.c_str());
- std::string::size_type slashPos = cMakeRoot.rfind("/");
- if(slashPos != std::string::npos)
- {
- cMakeRoot = cMakeRoot.substr(0, slashPos);
- }
- // is there no Modules directory there?
- modules = cMakeRoot + "/Modules/CMake.cmake";
- }
-
- if (!cmSystemTools::FileExists(modules.c_str()))
- {
- // try exe/../share/cmake
- cMakeRoot += CMAKE_DATA_DIR;
- modules = cMakeRoot + "/Modules/CMake.cmake";
- }
-#ifdef CMAKE_ROOT_DIR
- if (!cmSystemTools::FileExists(modules.c_str()))
- {
- // try compiled in root directory
- cMakeRoot = CMAKE_ROOT_DIR;
- modules = cMakeRoot + "/Modules/CMake.cmake";
- }
+ this->AddCacheEntry("CMAKE_COMMAND",
+ cmSystemTools::GetCMakeCommand().c_str(),
+ "Path to CMake executable.", cmStateEnums::INTERNAL);
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ this->AddCacheEntry(
+ "CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(),
+ "Path to ctest program executable.", cmStateEnums::INTERNAL);
+ this->AddCacheEntry(
+ "CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand().c_str(),
+ "Path to cpack program executable.", cmStateEnums::INTERNAL);
#endif
- if (!cmSystemTools::FileExists(modules.c_str()))
- {
- // try
- cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
- cMakeRoot += CMAKE_DATA_DIR;
- modules = cMakeRoot + "/Modules/CMake.cmake";
- }
- if(!cmSystemTools::FileExists(modules.c_str()))
- {
- // next try exe
- cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
- // is there no Modules directory there?
- modules = cMakeRoot + "/Modules/CMake.cmake";
- }
- if (!cmSystemTools::FileExists(modules.c_str()))
- {
+ if (!cmSystemTools::FileExists(
+ (cmSystemTools::GetCMakeRoot() + "/Modules/CMake.cmake").c_str())) {
// couldn't find modules
- cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
+ cmSystemTools::Error(
+ "Could not find CMAKE_ROOT !!!\n"
"CMake has most likely not been installed correctly.\n"
"Modules directory not found in\n",
- cMakeRoot.c_str());
+ cmSystemTools::GetCMakeRoot().c_str());
return 0;
- }
- this->CacheManager->AddCacheEntry
- ("CMAKE_ROOT", cMakeRoot.c_str(),
- "Path to CMake installation.", cmCacheManager::INTERNAL);
-
-#ifdef _WIN32
- std::string comspec = "cmw9xcom.exe";
- cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
-#endif
- return 1;
-}
-
-
-
-void CMakeCommandUsage(const char* program)
-{
- cmOStringStream errorStream;
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
- errorStream
- << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
-#else
- errorStream
- << "cmake bootstrap\n";
-#endif
- // If you add new commands, change here,
- // and in cmakemain.cxx in the options table
- errorStream
- << "Usage: " << program << " -E [command] [arguments ...]\n"
- << "Available commands: \n"
- << " chdir dir cmd [args]... - run command in a given directory\n"
- << " compare_files file1 file2 - check if file1 is same as file2\n"
- << " copy file destination - copy file to destination (either file "
- "or directory)\n"
- << " copy_directory source destination - copy directory 'source' "
- "content to directory 'destination'\n"
- << " copy_if_different in-file out-file - copy file if input has "
- "changed\n"
- << " echo [string]... - displays arguments as text\n"
- << " echo_append [string]... - displays arguments as text but no new "
- "line\n"
- << " environment - display the current environment\n"
- << " make_directory dir - create a directory\n"
- << " md5sum file1 [...] - compute md5sum of files\n"
- << " remove [-f] file1 file2 ... - remove the file(s), use -f to force "
- "it\n"
- << " remove_directory dir - remove a directory and its contents\n"
- << " rename oldname newname - rename a file or directory "
- "(on one volume)\n"
- << " tar [cxt][vfz][cvfj] 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"
-#if defined(_WIN32) && !defined(__CYGWIN__)
- << "Available on Windows only:\n"
- << " comspec - on windows 9x use this for RunCommand\n"
- << " delete_regv key - delete registry value\n"
- << " env_vs8_wince sdkname - displays a batch file which sets the "
- "environment for the provided Windows CE SDK installed in VS2005\n"
- << " 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
- ;
-
- cmSystemTools::Error(errorStream.str().c_str());
-}
-
-int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
-{
- // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
- if (args.size() > 1)
- {
- // Copy file
- if (args[1] == "copy" && args.size() == 4)
- {
- if(!cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str()))
- {
- std::cerr << "Error copying file \"" << args[2].c_str()
- << "\" to \"" << args[3].c_str() << "\".\n";
- return 1;
- }
- return 0;
- }
-
- // Copy file if different.
- if (args[1] == "copy_if_different" && args.size() == 4)
- {
- if(!cmSystemTools::CopyFileIfDifferent(args[2].c_str(),
- args[3].c_str()))
- {
- std::cerr << "Error copying file (if different) from \""
- << args[2].c_str() << "\" to \"" << args[3].c_str()
- << "\".\n";
- return 1;
- }
- return 0;
- }
-
- // Copy directory content
- if (args[1] == "copy_directory" && args.size() == 4)
- {
- if(!cmSystemTools::CopyADirectory(args[2].c_str(), args[3].c_str()))
- {
- std::cerr << "Error copying directory from \""
- << args[2].c_str() << "\" to \"" << args[3].c_str()
- << "\".\n";
- return 1;
- }
- return 0;
- }
-
- // Rename a file or directory
- if (args[1] == "rename" && args.size() == 4)
- {
- if(!cmSystemTools::RenameFile(args[2].c_str(), args[3].c_str()))
- {
- std::string e = cmSystemTools::GetLastSystemError();
- std::cerr << "Error renaming from \""
- << args[2].c_str() << "\" to \"" << args[3].c_str()
- << "\": " << e << "\n";
- return 1;
- }
- return 0;
- }
-
- // Compare files
- if (args[1] == "compare_files" && args.size() == 4)
- {
- if(cmSystemTools::FilesDiffer(args[2].c_str(), args[3].c_str()))
- {
- std::cerr << "Files \""
- << args[2].c_str() << "\" to \"" << args[3].c_str()
- << "\" are different.\n";
- return 1;
- }
- return 0;
- }
-
- // Echo string
- else if (args[1] == "echo" )
- {
- unsigned int cc;
- const char* space = "";
- for ( cc = 2; cc < args.size(); cc ++ )
- {
- std::cout << space << args[cc];
- space = " ";
- }
- std::cout << std::endl;
- return 0;
- }
-
- // Echo string no new line
- else if (args[1] == "echo_append" )
- {
- unsigned int cc;
- const char* space = "";
- for ( cc = 2; cc < args.size(); cc ++ )
- {
- std::cout << space << args[cc];
- space = " ";
- }
- return 0;
- }
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- // Command to create a symbolic link. Fails on platforms not
- // supporting them.
- else 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->c_str() << std::endl;
- }
- return 0;
- }
-#endif
-
- else if (args[1] == "make_directory" && args.size() == 3)
- {
- if(!cmSystemTools::MakeDirectory(args[2].c_str()))
- {
- std::cerr << "Error making directory \"" << args[2].c_str()
- << "\".\n";
- return 1;
- }
- return 0;
- }
-
- else if (args[1] == "remove_directory" && args.size() == 3)
- {
- if(cmSystemTools::FileIsDirectory(args[2].c_str()) &&
- !cmSystemTools::RemoveADirectory(args[2].c_str()))
- {
- std::cerr << "Error removing directory \"" << args[2].c_str()
- << "\".\n";
- return 1;
- }
- return 0;
- }
-
- // Remove file
- else 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")
- {
- 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].c_str()) && !force &&
- cmSystemTools::FileExists(args[cc].c_str()))
- {
- return 1;
- }
- }
- }
- return 0;
- }
- // Touch file
- else if (args[1] == "touch" && 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].c_str(), true))
- {
- return 1;
- }
- }
- return 0;
- }
- // Touch file
- else 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].c_str(), false))
- {
- return 1;
- }
- }
- return 0;
- }
-
- // Clock command
- else if (args[1] == "time" && args.size() > 2)
- {
- std::string command = args[2];
- for (std::string::size_type cc = 3; cc < args.size(); cc ++)
- {
- command += " ";
- command += args[cc];
- }
-
- clock_t clock_start, clock_finish;
- time_t time_start, time_finish;
-
- time(&time_start);
- clock_start = clock();
- int ret =0;
- cmSystemTools::RunSingleCommand(command.c_str(), 0, &ret);
-
- clock_finish = clock();
- time(&time_finish);
-
- double clocks_per_sec = static_cast<double>(CLOCKS_PER_SEC);
- std::cout << "Elapsed time: "
- << static_cast<long>(time_finish - time_start) << " s. (time)"
- << ", "
- << static_cast<double>(clock_finish - clock_start) / clocks_per_sec
- << " s. (clock)"
- << "\n";
- return ret;
- }
- // Command to calculate the md5sum of a file
- else 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;
- }
-
- // Command to change directory and run a program.
- else if (args[1] == "chdir" && args.size() >= 4)
- {
- std::string directory = args[2];
- if(!cmSystemTools::FileExists(directory.c_str()))
- {
- cmSystemTools::Error("Directory does not exist for chdir command: ",
- args[2].c_str());
- return 1;
- }
-
- std::string command = "\"";
- command += args[3];
- command += "\"";
- for (std::string::size_type cc = 4; cc < args.size(); cc ++)
- {
- command += " \"";
- command += args[cc];
- command += "\"";
- }
- int retval = 0;
- int timeout = 0;
- if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, &retval,
- directory.c_str(), cmSystemTools::OUTPUT_NORMAL, timeout) )
- {
- return retval;
- }
-
- return 1;
- }
-
- // Command to start progress for a build
- else if (args[1] == "cmake_progress_start" && args.size() == 4)
- {
- // basically remove the directory
- std::string dirName = args[2];
- dirName += "/Progress";
- cmSystemTools::RemoveADirectory(dirName.c_str());
-
- // is the last argument a filename that exists?
- FILE *countFile = fopen(args[3].c_str(),"r");
- int count;
- if (countFile)
- {
- if (1!=fscanf(countFile,"%i",&count))
- {
- cmSystemTools::Message("Could not read from count file.");
- }
- fclose(countFile);
- }
- else
- {
- count = atoi(args[3].c_str());
- }
- if (count)
- {
- cmSystemTools::MakeDirectory(dirName.c_str());
- // write the count into the directory
- std::string fName = dirName;
- fName += "/count.txt";
- FILE *progFile = fopen(fName.c_str(),"w");
- if (progFile)
- {
- fprintf(progFile,"%i\n",count);
- fclose(progFile);
- }
- }
- return 0;
- }
-
- // Command to report progress for a build
- else if (args[1] == "cmake_progress_report" && args.size() >= 3)
- {
- std::string dirName = args[2];
- dirName += "/Progress";
- std::string fName;
- FILE *progFile;
-
- // read the count
- fName = dirName;
- fName += "/count.txt";
- progFile = fopen(fName.c_str(),"r");
- int count = 0;
- if (!progFile)
- {
- return 0;
- }
- else
- {
- if (1!=fscanf(progFile,"%i",&count))
- {
- cmSystemTools::Message("Could not read from progress file.");
- }
- fclose(progFile);
- }
- unsigned int i;
- for (i = 3; i < args.size(); ++i)
- {
- fName = dirName;
- fName += "/";
- fName += args[i];
- progFile = fopen(fName.c_str(),"w");
- if (progFile)
- {
- fprintf(progFile,"empty");
- fclose(progFile);
- }
- }
- int fileNum = static_cast<int>
- (cmsys::Directory::GetNumberOfFilesInDirectory(dirName.c_str()));
- if (count > 0)
- {
- // print the progress
- fprintf(stdout,"[%3i%%] ",((fileNum-3)*100)/count);
- }
- return 0;
- }
-
- // Command to create a symbolic link. Fails on platforms not
- // supporting them.
- else if (args[1] == "create_symlink" && args.size() == 4)
- {
- const char* destinationFileName = args[3].c_str();
- if ( cmSystemTools::FileExists(destinationFileName) )
- {
- if ( cmSystemTools::FileIsSymlink(destinationFileName) )
- {
- if ( !cmSystemTools::RemoveFile(destinationFileName) ||
- cmSystemTools::FileExists(destinationFileName) )
- {
- return 0;
- }
- }
- else
- {
- return 0;
- }
- }
- return cmSystemTools::CreateSymlink(args[2].c_str(),
- args[3].c_str())? 0:1;
- }
-
- // Internal CMake shared library support.
- else if (args[1] == "cmake_symlink_library" && args.size() == 5)
- {
- return cmake::SymlinkLibrary(args);
- }
- // Internal CMake versioned executable support.
- else if (args[1] == "cmake_symlink_executable" && args.size() == 4)
- {
- return cmake::SymlinkExecutable(args);
- }
-
-#if defined(CMAKE_HAVE_VS_GENERATORS)
- // Internal CMake support for calling Visual Studio macros.
- else if (args[1] == "cmake_call_visual_studio_macro" && args.size() >= 4)
- {
- // args[2] = full path to .sln file or "ALL"
- // args[3] = name of Visual Studio macro to call
- // args[4..args.size()-1] = [optional] args for Visual Studio macro
-
- std::string macroArgs;
-
- if (args.size() > 4)
- {
- macroArgs = args[4];
-
- for (size_t i = 5; i < args.size(); ++i)
- {
- macroArgs += " ";
- macroArgs += args[i];
- }
- }
-
- return cmCallVisualStudioMacro::CallMacro(args[2], args[3],
- macroArgs, true);
- }
-#endif
-
- // Internal CMake dependency scanning support.
- else if (args[1] == "cmake_depends" && args.size() >= 6)
- {
- // 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).
- bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != 0)
- && (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == 0));
-
- // Create a cmake object instance to process dependencies.
- cmake cm;
- std::string gen;
- std::string homeDir;
- std::string startDir;
- std::string homeOutDir;
- std::string startOutDir;
- std::string depInfo;
- bool color = false;
- if(args.size() >= 8)
- {
- // Full signature:
- //
- // -E cmake_depends <generator>
- // <home-src-dir> <start-src-dir>
- // <home-out-dir> <start-out-dir>
- // <dep-info> [--color=$(COLOR)]
- //
- // All paths are provided.
- gen = args[2];
- homeDir = args[3];
- startDir = args[4];
- homeOutDir = args[5];
- startOutDir = args[6];
- depInfo = args[7];
- 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()));
- }
- }
- else
- {
- // Support older signature for existing makefiles:
- //
- // -E cmake_depends <generator>
- // <home-out-dir> <start-out-dir>
- // <dep-info>
- //
- // Just pretend the source directories are the same as the
- // binary directories so at least scanning will work.
- gen = args[2];
- homeDir = args[3];
- startDir = args[4];
- homeOutDir = args[3];
- startOutDir = args[3];
- depInfo = args[5];
- }
-
- // Create a local generator configured for the directory in
- // which dependencies will be scanned.
- homeDir = cmSystemTools::CollapseFullPath(homeDir.c_str());
- startDir = cmSystemTools::CollapseFullPath(startDir.c_str());
- homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir.c_str());
- startOutDir = cmSystemTools::CollapseFullPath(startOutDir.c_str());
- cm.SetHomeDirectory(homeDir.c_str());
- cm.SetStartDirectory(startDir.c_str());
- cm.SetHomeOutputDirectory(homeOutDir.c_str());
- cm.SetStartOutputDirectory(startOutDir.c_str());
- if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
- {
- cm.SetGlobalGenerator(ggd);
- cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
- lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
- lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
- lgd->GetMakefile()->MakeStartDirectoriesCurrent();
-
- // Actually scan dependencies.
- return lgd->UpdateDependencies(depInfo.c_str(),
- verbose, color)? 0 : 2;
- }
- return 1;
- }
-
- // Internal CMake link script support.
- else if (args[1] == "cmake_link_script" && args.size() >= 3)
- {
- return cmake::ExecuteLinkScript(args);
- }
-
- // Internal CMake unimplemented feature notification.
- else if (args[1] == "cmake_unimplemented_variable")
- {
- std::cerr << "Feature not implemented for this platform.";
- if(args.size() == 3)
- {
- std::cerr << " Variable " << args[2] << " is not set.";
- }
- std::cerr << std::endl;
- return 1;
- }
- else if (args[1] == "vs_link_exe")
- {
- return cmake::VisualStudioLink(args, 1);
- }
- else if (args[1] == "vs_link_dll")
- {
- return cmake::VisualStudioLink(args, 2);
- }
-#ifdef CMAKE_BUILD_WITH_CMAKE
- // Internal CMake color makefile support.
- else if (args[1] == "cmake_echo_color")
- {
- return cmake::ExecuteEchoColor(args);
- }
- else if (args[1] == "cmake_automoc" && args.size() >= 4)
- {
- cmQtAutomoc automoc;
- const char *config = args[3].empty() ? 0 : args[3].c_str();
- bool automocSuccess = automoc.Run(args[2].c_str(), config);
- return automocSuccess ? 0 : 1;
- }
-#endif
-
- // Tar files
- else if (args[1] == "tar" && args.size() > 3)
- {
- std::string flags = args[2];
- std::string outFile = args[3];
- std::vector<cmStdString> files;
- for (std::string::size_type cc = 4; cc < args.size(); cc ++)
- {
- files.push_back(args[cc]);
- }
- bool gzip = false;
- bool bzip2 = false;
- bool verbose = false;
- if ( flags.find_first_of('j') != flags.npos )
- {
- bzip2 = true;
- }
- if ( flags.find_first_of('z') != flags.npos )
- {
- gzip = true;
- }
- if ( flags.find_first_of('v') != flags.npos )
- {
- verbose = true;
- }
-
- if ( flags.find_first_of('t') != flags.npos )
- {
- if ( !cmSystemTools::ListTar(outFile.c_str(), gzip, verbose) )
- {
- cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
- return 1;
- }
- }
- else if ( flags.find_first_of('c') != flags.npos )
- {
- if ( !cmSystemTools::CreateTar(
- outFile.c_str(), files, gzip, bzip2, verbose) )
- {
- cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
- return 1;
- }
- }
- else if ( flags.find_first_of('x') != flags.npos )
- {
- if ( !cmSystemTools::ExtractTar(
- outFile.c_str(), gzip, verbose) )
- {
- cmSystemTools::Error("Problem extracting tar: ", outFile.c_str());
- return 1;
- }
-#ifdef WIN32
- // OK, on windows 7 after we untar some files,
- // sometimes we can not rename the directory after
- // the untar is done. This breaks the external project
- // untar and rename code. So, by default we will wait
- // 1/10th of a second after the untar. If CMAKE_UNTAR_DELAY
- // is set in the env, its value will be used instead of 100.
- int delay = 100;
- const char* delayVar = cmSystemTools::GetEnv("CMAKE_UNTAR_DELAY");
- if(delayVar)
- {
- delay = atoi(delayVar);
- }
- if(delay)
- {
- cmSystemTools::Delay(delay);
- }
-#endif
- }
- return 0;
- }
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- // Internal CMake Fortran module support.
- else if (args[1] == "cmake_copy_f90_mod" && args.size() >= 4)
- {
- return cmDependsFortran::CopyModule(args)? 0 : 1;
- }
-#endif
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // Write registry value
- else if (args[1] == "write_regv" && args.size() > 3)
- {
- return cmSystemTools::WriteRegistryValue(args[2].c_str(),
- args[3].c_str()) ? 0 : 1;
- }
-
- // Delete registry value
- else if (args[1] == "delete_regv" && args.size() > 2)
- {
- return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
- }
- // Remove file
- else if (args[1] == "comspec" && args.size() > 2)
- {
- unsigned int cc;
- std::string command = args[2];
- for ( cc = 3; cc < args.size(); cc ++ )
- {
- command += " " + args[cc];
- }
- return cmWin32ProcessExecution::Windows9xHack(command.c_str());
- }
- else if (args[1] == "env_vs8_wince" && args.size() == 3)
- {
- return cmake::WindowsCEEnvironment("8.0", args[2]);
- }
- else if (args[1] == "env_vs9_wince" && args.size() == 3)
- {
- return cmake::WindowsCEEnvironment("9.0", args[2]);
- }
-#endif
- }
+ }
+ this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot().c_str(),
+ "Path to CMake installation.", cmStateEnums::INTERNAL);
- ::CMakeCommandUsage(args[0].c_str());
return 1;
}
-void cmake::AddExtraGenerator(const char* name,
- CreateExtraGeneratorFunctionType newFunction)
-{
- cmExternalMakefileProjectGenerator* extraGenerator = newFunction();
- const std::vector<std::string>& supportedGlobalGenerators =
- extraGenerator->GetSupportedGlobalGenerators();
-
- for(std::vector<std::string>::const_iterator
- it = supportedGlobalGenerators.begin();
- it != supportedGlobalGenerators.end();
- ++it )
- {
- std::string fullName = cmExternalMakefileProjectGenerator::
- CreateFullGeneratorName(it->c_str(), name);
- this->ExtraGenerators[fullName.c_str()] = newFunction;
- }
- delete extraGenerator;
-}
-
void cmake::AddDefaultExtraGenerators()
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // e.g. kdevelop4 ?
-#endif
-
- this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
- &cmExtraCodeBlocksGenerator::New);
- this->AddExtraGenerator(cmExtraSublimeTextGenerator::GetActualName(),
- &cmExtraSublimeTextGenerator::New);
+ 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
- this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
- &cmExtraEclipseCDT4Generator::New);
+ this->ExtraGenerators.push_back(cmExtraEclipseCDT4Generator::GetFactory());
#endif
#ifdef CMAKE_USE_KDEVELOP
- this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
- &cmGlobalKdevelopGenerator::New);
- // for kdevelop also add the generator with just the name of the
- // extra generator, since it was this way since cmake 2.2
- this->ExtraGenerators[cmGlobalKdevelopGenerator::GetActualName()]
- = &cmGlobalKdevelopGenerator::New;
+ this->ExtraGenerators.push_back(cmGlobalKdevelopGenerator::GetFactory());
#endif
-
#endif
}
-
-//----------------------------------------------------------------------------
-void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
+void cmake::GetRegisteredGenerators(
+ std::vector<GeneratorInfo>& generators) const
{
- for(RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
- i != this->Generators.end(); ++i)
- {
+ for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin(),
+ e = this->Generators.end();
+ i != e; ++i) {
+ std::vector<std::string> names;
(*i)->GetGenerators(names);
+
+ for (size_t j = 0; j < names.size(); ++j) {
+ GeneratorInfo info;
+ info.supportsToolset = (*i)->SupportsToolset();
+ info.supportsPlatform = (*i)->SupportsPlatform();
+ info.name = names[j];
+ info.baseName = names[j];
+ info.isAlias = false;
+ generators.push_back(info);
}
- for(RegisteredExtraGeneratorsMap::const_iterator
- i = this->ExtraGenerators.begin();
- i != this->ExtraGenerators.end(); ++i)
- {
- names.push_back(i->first);
+ }
+
+ for (RegisteredExtraGeneratorsVector::const_iterator
+ i = this->ExtraGenerators.begin(),
+ e = this->ExtraGenerators.end();
+ i != e; ++i) {
+ const std::vector<std::string> genList =
+ (*i)->GetSupportedGlobalGenerators();
+ for (std::vector<std::string>::const_iterator gen = genList.begin();
+ gen != genList.end(); ++gen) {
+ GeneratorInfo info;
+ info.name = cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ *gen, (*i)->GetName());
+ info.baseName = *gen;
+ info.extraName = (*i)->GetName();
+ info.supportsPlatform = false;
+ info.supportsToolset = false;
+ info.isAlias = false;
+ generators.push_back(info);
+ }
+ for (std::vector<std::string>::const_iterator a = (*i)->Aliases.begin();
+ a != (*i)->Aliases.end(); ++a) {
+ GeneratorInfo info;
+ info.name = *a;
+ if (!genList.empty()) {
+ info.baseName = genList.at(0);
+ }
+ info.extraName = (*i)->GetName();
+ info.supportsPlatform = false;
+ info.supportsToolset = false;
+ info.isAlias = true;
+ generators.push_back(info);
}
+ }
}
-cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name)
+static std::pair<cmExternalMakefileProjectGenerator*, std::string>
+createExtraGenerator(
+ const std::vector<cmExternalMakefileProjectGeneratorFactory*>& in,
+ const std::string& name)
{
- cmExternalMakefileProjectGenerator* extraGenerator = 0;
- RegisteredExtraGeneratorsMap::const_iterator extraGenIt =
- this->ExtraGenerators.find(name);
- if (extraGenIt != this->ExtraGenerators.end())
- {
- extraGenerator = (extraGenIt->second)();
- name = extraGenerator->GetGlobalGeneratorName(name);
+ for (std::vector<cmExternalMakefileProjectGeneratorFactory*>::const_iterator
+ i = in.begin();
+ i != in.end(); ++i) {
+ const std::vector<std::string> generators =
+ (*i)->GetSupportedGlobalGenerators();
+ if ((*i)->GetName() == name) { // Match aliases
+ return std::make_pair((*i)->CreateExternalMakefileProjectGenerator(),
+ generators.at(0));
}
+ for (std::vector<std::string>::const_iterator g = generators.begin();
+ g != generators.end(); ++g) {
+ const std::string fullName =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ *g, (*i)->GetName());
+ if (fullName == name) {
+ return std::make_pair((*i)->CreateExternalMakefileProjectGenerator(),
+ *g);
+ }
+ }
+ }
+ return std::make_pair(
+ static_cast<cmExternalMakefileProjectGenerator*>(CM_NULLPTR), name);
+}
+
+cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname)
+{
+ std::pair<cmExternalMakefileProjectGenerator*, std::string> extra =
+ createExtraGenerator(this->ExtraGenerators, gname);
+ cmExternalMakefileProjectGenerator* extraGenerator = extra.first;
+ const std::string name = extra.second;
- cmGlobalGenerator* generator = 0;
- for (RegisteredGeneratorsVector::const_iterator i =
- this->Generators.begin(); i != this->Generators.end(); ++i)
- {
- generator = (*i)->CreateGlobalGenerator(name);
- if (generator)
- {
+ cmGlobalGenerator* generator = CM_NULLPTR;
+ for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
+ i != this->Generators.end(); ++i) {
+ generator = (*i)->CreateGlobalGenerator(name, this);
+ if (generator) {
break;
- }
}
+ }
- if (generator)
- {
- generator->SetCMakeInstance(this);
+ if (generator) {
generator->SetExternalMakefileProjectGenerator(extraGenerator);
- }
- else
- {
+ } else {
delete extraGenerator;
- }
+ }
return generator;
}
-void cmake::SetHomeDirectory(const char* dir)
+void cmake::SetHomeDirectory(const std::string& dir)
+{
+ this->State->SetSourceDirectory(dir);
+ if (this->CurrentSnapshot.IsValid()) {
+ this->CurrentSnapshot.SetDefinition("CMAKE_SOURCE_DIR", dir);
+ }
+}
+
+const char* cmake::GetHomeDirectory() const
{
- this->cmHomeDirectory = dir;
- cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory);
+ return this->State->GetSourceDirectory();
+}
+
+void cmake::SetHomeOutputDirectory(const std::string& dir)
+{
+ this->State->SetBinaryDirectory(dir);
+ if (this->CurrentSnapshot.IsValid()) {
+ this->CurrentSnapshot.SetDefinition("CMAKE_BINARY_DIR", dir);
+ }
}
-void cmake::SetHomeOutputDirectory(const char* lib)
+const char* cmake::GetHomeOutputDirectory() const
{
- this->HomeOutputDirectory = lib;
- cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory);
+ return this->State->GetBinaryDirectory();
}
-void cmake::SetGlobalGenerator(cmGlobalGenerator *gg)
+std::string cmake::FindCacheFile(const std::string& binaryDir)
{
- if(!gg)
- {
+ std::string cachePath = binaryDir;
+ cmSystemTools::ConvertToUnixSlashes(cachePath);
+ std::string cacheFile = cachePath;
+ cacheFile += "/CMakeCache.txt";
+ if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ // search in parent directories for cache
+ std::string cmakeFiles = cachePath;
+ cmakeFiles += "/CMakeFiles";
+ if (cmSystemTools::FileExists(cmakeFiles.c_str())) {
+ std::string cachePathFound =
+ cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
+ cachePath.c_str(), "/");
+ if (!cachePathFound.empty()) {
+ cachePath = cmSystemTools::GetFilenamePath(cachePathFound);
+ }
+ }
+ }
+ return cachePath;
+}
+
+void cmake::SetGlobalGenerator(cmGlobalGenerator* gg)
+{
+ if (!gg) {
cmSystemTools::Error("Error SetGlobalGenerator called with null");
return;
- }
+ }
// delete the old generator
- if (this->GlobalGenerator)
- {
+ if (this->GlobalGenerator) {
delete this->GlobalGenerator;
// restore the original environment variables CXX and CC
// Restore CC
std::string env = "CC=";
- if(this->CCEnvironment.size())
- {
+ if (!this->CCEnvironment.empty()) {
env += this->CCEnvironment;
- }
- cmSystemTools::PutEnv(env.c_str());
+ }
+ cmSystemTools::PutEnv(env);
env = "CXX=";
- if(this->CXXEnvironment.size())
- {
+ if (!this->CXXEnvironment.empty()) {
env += this->CXXEnvironment;
- }
- cmSystemTools::PutEnv(env.c_str());
}
+ cmSystemTools::PutEnv(env);
+ }
// set the new
this->GlobalGenerator = gg;
// set the global flag for unix style paths on cmSystemTools as soon as
// the generator is set. This allows gmake to be used on windows.
- cmSystemTools::SetForceUnixPaths
- (this->GlobalGenerator->GetForceUnixPaths());
+ cmSystemTools::SetForceUnixPaths(this->GlobalGenerator->GetForceUnixPaths());
// Save the environment variables CXX and CC
- const char* cxx = getenv("CXX");
- const char* cc = getenv("CC");
- if(cxx)
- {
- this->CXXEnvironment = cxx;
- }
- else
- {
+ if (!cmSystemTools::GetEnv("CXX", this->CXXEnvironment)) {
this->CXXEnvironment = "";
- }
- if(cc)
- {
- this->CCEnvironment = cc;
- }
- else
- {
+ }
+ if (!cmSystemTools::GetEnv("CC", this->CCEnvironment)) {
this->CCEnvironment = "";
- }
- // set the cmake instance just to be sure
- gg->SetCMakeInstance(this);
+ }
}
int cmake::DoPreConfigureChecks()
{
- // Make sure the Start directory contains a CMakeLists.txt file.
+ // Make sure the Source directory contains a CMakeLists.txt file.
std::string srcList = this->GetHomeDirectory();
srcList += "/CMakeLists.txt";
- if(!cmSystemTools::FileExists(srcList.c_str()))
- {
- cmOStringStream err;
- if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
- {
+ if (!cmSystemTools::FileExists(srcList.c_str())) {
+ std::ostringstream err;
+ if (cmSystemTools::FileIsDirectory(this->GetHomeDirectory())) {
err << "The source directory \"" << this->GetHomeDirectory()
<< "\" does not appear to contain CMakeLists.txt.\n";
- }
- else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
- {
+ } else if (cmSystemTools::FileExists(this->GetHomeDirectory())) {
err << "The source directory \"" << this->GetHomeDirectory()
<< "\" is a file, not a directory.\n";
- }
- else
- {
+ } else {
err << "The source directory \"" << this->GetHomeDirectory()
<< "\" does not exist.\n";
- }
+ }
err << "Specify --help for usage, or press the help button on the CMake "
- "GUI.";
+ "GUI.";
cmSystemTools::Error(err.str().c_str());
return -2;
- }
+ }
// do a sanity check on some values
- if(this->CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY"))
- {
+ if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) {
std::string cacheStart =
- this->CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY");
+ this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
cacheStart += "/CMakeLists.txt";
std::string currentStart = this->GetHomeDirectory();
currentStart += "/CMakeLists.txt";
- if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
- {
+ if (!cmSystemTools::SameFile(cacheStart, currentStart)) {
std::string message = "The source \"";
message += currentStart;
message += "\" does not match the source \"";
@@ -2080,12 +1137,10 @@ int cmake::DoPreConfigureChecks()
message += "Re-run cmake with a different source directory.";
cmSystemTools::Error(message.c_str());
return -2;
- }
}
- else
- {
+ } else {
return 0;
- }
+ }
return 1;
}
struct SaveCacheEntry
@@ -2093,94 +1148,130 @@ struct SaveCacheEntry
std::string key;
std::string value;
std::string help;
- cmCacheManager::CacheEntryType type;
+ cmStateEnums::CacheEntryType type;
};
-int cmake::HandleDeleteCacheVariables(const char* var)
+int cmake::HandleDeleteCacheVariables(const std::string& var)
{
std::vector<std::string> argsSplit;
cmSystemTools::ExpandListArgument(std::string(var), argsSplit, true);
// erase the property to avoid infinite recursion
- this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
- if(this->GetIsInTryCompile())
- {
+ this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
+ if (this->State->GetIsInTryCompile()) {
return 0;
- }
- cmCacheManager::CacheIterator ci = this->CacheManager->NewIterator();
+ }
std::vector<SaveCacheEntry> saved;
- cmOStringStream warning;
+ std::ostringstream warning;
+ /* clang-format off */
warning
<< "You have changed variables that require your cache to be deleted.\n"
<< "Configure will be re-run and you may have to reset some variables.\n"
<< "The following variables have changed:\n";
- for(std::vector<std::string>::iterator i = argsSplit.begin();
- i != argsSplit.end(); ++i)
- {
+ /* clang-format on */
+ for (std::vector<std::string>::iterator i = argsSplit.begin();
+ i != argsSplit.end(); ++i) {
SaveCacheEntry save;
save.key = *i;
warning << *i << "= ";
i++;
save.value = *i;
warning << *i << "\n";
- if(ci.Find(save.key.c_str()))
- {
- save.type = ci.GetType();
- save.help = ci.GetProperty("HELPSTRING");
+ const char* existingValue = this->State->GetCacheEntryValue(save.key);
+ if (existingValue) {
+ save.type = this->State->GetCacheEntryType(save.key);
+ if (const char* help =
+ this->State->GetCacheEntryProperty(save.key, "HELPSTRING")) {
+ save.help = help;
}
- saved.push_back(save);
}
+ saved.push_back(save);
+ }
// remove the cache
- this->CacheManager->DeleteCache(this->GetStartOutputDirectory());
+ this->DeleteCache(this->GetHomeOutputDirectory());
// 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.c_str(), i->value.c_str(),
- i->help.c_str(), i->type);
- }
+ 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);
+ }
cmSystemTools::Message(warning.str().c_str());
// avoid reconfigure if there were errors
- if(!cmSystemTools::GetErrorOccuredFlag())
- {
+ if (!cmSystemTools::GetErrorOccuredFlag()) {
// re-run configure
return this->Configure();
- }
+ }
return 0;
}
int cmake::Configure()
{
- if(this->DoSuppressDevWarnings)
- {
- if(this->SuppressDevWarnings)
- {
- this->CacheManager->
- AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE",
- "Suppress Warnings that are meant for"
- " the author of the CMakeLists.txt files.",
- cmCacheManager::INTERNAL);
+ DiagLevel diagLevel;
+
+ if (this->DiagLevels.count("deprecated") == 1) {
+
+ diagLevel = this->DiagLevels["deprecated"];
+ if (diagLevel == DIAG_IGNORE) {
+ this->SetSuppressDeprecatedWarnings(true);
+ this->SetDeprecatedWarningsAsErrors(false);
+ } else if (diagLevel == DIAG_WARN) {
+ this->SetSuppressDeprecatedWarnings(false);
+ this->SetDeprecatedWarningsAsErrors(false);
+ } else if (diagLevel == DIAG_ERROR) {
+ this->SetSuppressDeprecatedWarnings(false);
+ this->SetDeprecatedWarningsAsErrors(true);
+ }
+ }
+
+ if (this->DiagLevels.count("dev") == 1) {
+ bool setDeprecatedVariables = false;
+
+ const char* cachedWarnDeprecated =
+ this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
+ const char* cachedErrorDeprecated =
+ this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
+
+ // don't overwrite deprecated warning setting from a previous invocation
+ if (!cachedWarnDeprecated && !cachedErrorDeprecated) {
+ setDeprecatedVariables = true;
+ }
+
+ diagLevel = this->DiagLevels["dev"];
+ if (diagLevel == DIAG_IGNORE) {
+ this->SetSuppressDevWarnings(true);
+ this->SetDevWarningsAsErrors(false);
+
+ if (setDeprecatedVariables) {
+ this->SetSuppressDeprecatedWarnings(true);
+ this->SetDeprecatedWarningsAsErrors(false);
}
- else
- {
- this->CacheManager->
- AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE",
- "Suppress Warnings that are meant for"
- " the author of the CMakeLists.txt files.",
- cmCacheManager::INTERNAL);
+ } else if (diagLevel == DIAG_WARN) {
+ this->SetSuppressDevWarnings(false);
+ this->SetDevWarningsAsErrors(false);
+
+ if (setDeprecatedVariables) {
+ this->SetSuppressDeprecatedWarnings(false);
+ this->SetDeprecatedWarningsAsErrors(false);
+ }
+ } else if (diagLevel == DIAG_ERROR) {
+ this->SetSuppressDevWarnings(false);
+ this->SetDevWarningsAsErrors(true);
+
+ if (setDeprecatedVariables) {
+ this->SetSuppressDeprecatedWarnings(false);
+ this->SetDeprecatedWarningsAsErrors(true);
}
}
+ }
+
int ret = this->ActualConfigure();
const char* delCacheVars =
- this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
- if(delCacheVars && delCacheVars[0] != 0)
- {
+ this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
+ if (delCacheVars && delCacheVars[0] != 0) {
return this->HandleDeleteCacheVariables(delCacheVars);
- }
+ }
return ret;
-
}
int cmake::ActualConfigure()
@@ -2190,183 +1281,120 @@ int cmake::ActualConfigure()
this->CleanupCommandsAndMacros();
int res = 0;
- if ( this->GetWorkingMode() == NORMAL_MODE )
- {
+ if (this->GetWorkingMode() == NORMAL_MODE) {
res = this->DoPreConfigureChecks();
- }
- if ( res < 0 )
- {
+ }
+ if (res < 0) {
return -2;
- }
- if ( !res )
- {
- this->CacheManager->AddCacheEntry
- ("CMAKE_HOME_DIRECTORY",
- this->GetHomeDirectory(),
- "Start directory with the top level CMakeLists.txt file for this "
- "project",
- cmCacheManager::INTERNAL);
- }
+ }
+ if (!res) {
+ this->AddCacheEntry(
+ "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory(),
+ "Source directory with the top level CMakeLists.txt file for this "
+ "project",
+ cmStateEnums::INTERNAL);
+ }
// no generator specified on the command line
- if(!this->GlobalGenerator)
- {
+ if (!this->GlobalGenerator) {
const char* genName =
- this->CacheManager->GetCacheValue("CMAKE_GENERATOR");
+ this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
const char* extraGenName =
- this->CacheManager->GetCacheValue("CMAKE_EXTRA_GENERATOR");
- if(genName)
- {
- std::string fullName = cmExternalMakefileProjectGenerator::
- CreateFullGeneratorName(genName, extraGenName);
- this->GlobalGenerator = this->CreateGlobalGenerator(fullName.c_str());
- }
- if(this->GlobalGenerator)
- {
+ this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
+ if (genName) {
+ std::string fullName =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ genName, extraGenName ? extraGenName : "");
+ this->GlobalGenerator = this->CreateGlobalGenerator(fullName);
+ }
+ if (this->GlobalGenerator) {
// set the global flag for unix style paths on cmSystemTools as
// soon as the generator is set. This allows gmake to be used
// on windows.
- cmSystemTools::SetForceUnixPaths
- (this->GlobalGenerator->GetForceUnixPaths());
- }
- else
- {
-#if defined(__BORLANDC__) && defined(_WIN32)
- this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator);
-#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
- std::string installedCompiler;
- // Try to find the newest VS installed on the computer and
- // use that as a default if -G is not specified
- const std::string vsregBase =
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\";
- std::vector<std::string> vsVerions;
- vsVerions.push_back("VisualStudio\\");
- vsVerions.push_back("VCExpress\\");
- vsVerions.push_back("WDExpress\\");
- struct VSRegistryEntryName
- {
- const char* MSVersion;
- const char* GeneratorName;
- };
- VSRegistryEntryName version[] = {
- {"6.0", "Visual Studio 6"},
- {"7.0", "Visual Studio 7"},
- {"7.1", "Visual Studio 7 .NET 2003"},
- {"8.0", "Visual Studio 8 2005"},
- {"9.0", "Visual Studio 9 2008"},
- {"10.0", "Visual Studio 10"},
- {"11.0", "Visual Studio 11"},
- {"12.0", "Visual Studio 12"},
- {0, 0}};
- for(int i=0; version[i].MSVersion != 0; i++)
- {
- for(size_t b=0; b < vsVerions.size(); b++)
- {
- std::string reg = vsregBase + vsVerions[b] + version[i].MSVersion;
- reg += ";InstallDir]";
- cmSystemTools::ExpandRegistryValues(reg,
- cmSystemTools::KeyWOW64_32);
- if (!(reg == "/registry"))
- {
- installedCompiler = version[i].GeneratorName;
- break;
- }
- }
- }
- cmGlobalGenerator* gen
- = this->CreateGlobalGenerator(installedCompiler.c_str());
- if(!gen)
- {
- gen = new cmGlobalNMakeMakefileGenerator;
- }
- this->SetGlobalGenerator(gen);
- std::cout << "-- Building for: " << gen->GetName() << "\n";
-#else
- this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3);
-#endif
- }
- if(!this->GlobalGenerator)
- {
+ cmSystemTools::SetForceUnixPaths(
+ this->GlobalGenerator->GetForceUnixPaths());
+ } else {
+ this->CreateDefaultGlobalGenerator();
+ }
+ if (!this->GlobalGenerator) {
cmSystemTools::Error("Could not create generator");
return -1;
- }
}
+ }
- const char* genName = this->CacheManager->GetCacheValue("CMAKE_GENERATOR");
- if(genName)
- {
- if(strcmp(this->GlobalGenerator->GetName(), genName) != 0)
- {
+ const char* 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 or choose a different"
- " binary directory.";
+ message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.";
cmSystemTools::Error(message.c_str());
return -2;
- }
}
- if(!this->CacheManager->GetCacheValue("CMAKE_GENERATOR"))
- {
- this->CacheManager->AddCacheEntry("CMAKE_GENERATOR",
- this->GlobalGenerator->GetName(),
- "Name of generator.",
- cmCacheManager::INTERNAL);
- this->CacheManager->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
- this->GlobalGenerator->GetExtraGeneratorName(),
- "Name of external makefile project generator.",
- cmCacheManager::INTERNAL);
+ }
+ if (!this->State->GetInitializedCacheValue("CMAKE_GENERATOR")) {
+ this->AddCacheEntry("CMAKE_GENERATOR",
+ this->GlobalGenerator->GetName().c_str(),
+ "Name of generator.", cmStateEnums::INTERNAL);
+ this->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
+ this->GlobalGenerator->GetExtraGeneratorName().c_str(),
+ "Name of external makefile project generator.",
+ cmStateEnums::INTERNAL);
+ }
+
+ if (const char* 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());
+ return -2;
}
+ } else {
+ this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM",
+ this->GeneratorPlatform.c_str(),
+ "Name of generator platform.", cmStateEnums::INTERNAL);
+ }
- if(const char* tsName =
- this->CacheManager->GetCacheValue("CMAKE_GENERATOR_TOOLSET"))
- {
- if(this->GeneratorToolset.empty())
- {
+ if (const char* tsName =
+ this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
+ if (this->GeneratorToolset.empty()) {
this->GeneratorToolset = tsName;
- }
- else if(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 or choose a different"
- " binary directory.";
+ message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.";
cmSystemTools::Error(message.c_str());
return -2;
- }
- }
- else
- {
- this->CacheManager->AddCacheEntry("CMAKE_GENERATOR_TOOLSET",
- this->GeneratorToolset.c_str(),
- "Name of generator toolset.",
- cmCacheManager::INTERNAL);
- }
- if(!this->GeneratorToolset.empty() &&
- !this->GlobalGenerator->SetGeneratorToolset(this->GeneratorToolset))
- {
- return -2;
}
+ } else {
+ this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET",
+ this->GeneratorToolset.c_str(),
+ "Name of generator toolset.", cmStateEnums::INTERNAL);
+ }
// reset any system configuration information, except for when we are
// InTryCompile. With TryCompile the system info is taken from the parent's
// info to save time
- if (!this->InTryCompile)
- {
+ if (!this->State->GetIsInTryCompile()) {
this->GlobalGenerator->ClearEnabledLanguages();
- }
- // Truncate log files
- if (!this->InTryCompile)
- {
this->TruncateOutputLog("CMakeOutput.log");
this->TruncateOutputLog("CMakeError.log");
- }
+ }
// actually do the configure
this->GlobalGenerator->Configure();
@@ -2380,96 +1408,119 @@ int cmake::ActualConfigure()
// project requires compatibility with CMake 2.4. We detect this
// here by looking for the old CMAKE_BACKWARDS_COMPATIBILITY
// variable created when CMP0001 is not set to NEW.
- if(this->GetCacheManager()->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
- {
- if(!this->CacheManager->GetCacheValue("LIBRARY_OUTPUT_PATH"))
- {
- this->CacheManager->AddCacheEntry
- ("LIBRARY_OUTPUT_PATH", "",
- "Single output directory for building all libraries.",
- cmCacheManager::PATH);
- }
- if(!this->CacheManager->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
- {
- this->CacheManager->AddCacheEntry
- ("EXECUTABLE_OUTPUT_PATH", "",
- "Single output directory for building all executables.",
- cmCacheManager::PATH);
- }
- }
- if(!this->CacheManager->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
- {
- this->CacheManager->AddCacheEntry
- ("CMAKE_USE_RELATIVE_PATHS", "OFF",
- "If true, cmake will use relative paths in makefiles and projects.",
- cmCacheManager::BOOL);
- cmCacheManager::CacheIterator it =
- this->CacheManager->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
- if ( !it.PropertyExists("ADVANCED") )
- {
- it.SetProperty("ADVANCED", "1");
- }
- }
-
- if(cmSystemTools::GetFatalErrorOccured() &&
- (!this->CacheManager->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
- cmSystemTools::IsOff(this->CacheManager->
- GetCacheValue("CMAKE_MAKE_PROGRAM"))))
- {
- // We must have a bad generator selection. Wipe the cache entry so the
- // user can select another.
- this->CacheManager->RemoveCacheEntry("CMAKE_GENERATOR");
- this->CacheManager->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
+ if (this->State->GetInitializedCacheValue("CMAKE_BACKWARDS_COMPATIBILITY")) {
+ if (!this->State->GetInitializedCacheValue("LIBRARY_OUTPUT_PATH")) {
+ this->AddCacheEntry(
+ "LIBRARY_OUTPUT_PATH", "",
+ "Single output directory for building all libraries.",
+ cmStateEnums::PATH);
+ }
+ if (!this->State->GetInitializedCacheValue("EXECUTABLE_OUTPUT_PATH")) {
+ this->AddCacheEntry(
+ "EXECUTABLE_OUTPUT_PATH", "",
+ "Single output directory for building all executables.",
+ cmStateEnums::PATH);
}
+ }
- cmMakefile* mf=this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
- if (mf->IsOn("CTEST_USE_LAUNCHERS")
- && !this->GetProperty("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL))
- {
- cmSystemTools::Error("CTEST_USE_LAUNCHERS is enabled, but the "
- "RULE_LAUNCH_COMPILE global property is not defined.\n"
- "Did you forget to include(CTest) in the toplevel "
- "CMakeLists.txt ?");
- }
+ cmMakefile* mf = this->GlobalGenerator->GetMakefiles()[0];
+ if (mf->IsOn("CTEST_USE_LAUNCHERS") &&
+ !this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE")) {
+ cmSystemTools::Error(
+ "CTEST_USE_LAUNCHERS is enabled, but the "
+ "RULE_LAUNCH_COMPILE global property is not defined.\n"
+ "Did you forget to include(CTest) in the toplevel "
+ "CMakeLists.txt ?");
+ }
// only save the cache if there were no fatal errors
- if ( this->GetWorkingMode() == NORMAL_MODE )
- {
- this->CacheManager->SaveCache(this->GetHomeOutputDirectory());
- }
- if ( !this->GraphVizFile.empty() )
- {
- std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
- this->GenerateGraphViz(this->GraphVizFile.c_str());
- }
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (this->GetWorkingMode() == NORMAL_MODE) {
+ this->SaveCache(this->GetHomeOutputDirectory());
+ }
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
- }
+ }
return 0;
}
+void cmake::CreateDefaultGlobalGenerator()
+{
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
+ std::string found;
+ // Try to find the newest VS installed on the computer and
+ // use that as a default if -G is not specified
+ const std::string vsregBase = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\";
+ static const char* const vsVariants[] = {
+ /* clang-format needs this comment to break after the opening brace */
+ "VisualStudio\\", "VCExpress\\", "WDExpress\\"
+ };
+ struct VSVersionedGenerator
+ {
+ const char* MSVersion;
+ 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" }
+ };
+ static const char* const vsEntries[] = {
+ "\\Setup\\VC;ProductDir", //
+ ";InstallDir" //
+ };
+ cmVSSetupAPIHelper vsSetupAPIHelper;
+ if (vsSetupAPIHelper.IsVS2017Installed()) {
+ found = "Visual Studio 15 2017";
+ } else {
+ for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators);
+ found.empty() && g != cmArrayEnd(vsGenerators); ++g) {
+ for (const char* const* v = cmArrayBegin(vsVariants);
+ found.empty() && v != cmArrayEnd(vsVariants); ++v) {
+ for (const char* const* e = cmArrayBegin(vsEntries);
+ found.empty() && e != cmArrayEnd(vsEntries); ++e) {
+ std::string const reg = vsregBase + *v + g->MSVersion + *e;
+ std::string dir;
+ if (cmSystemTools::ReadRegistryValue(reg, dir,
+ cmSystemTools::KeyWOW64_32) &&
+ cmSystemTools::PathExists(dir)) {
+ found = g->GeneratorName;
+ }
+ }
+ }
+ }
+ }
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(found);
+ if (!gen) {
+ gen = new cmGlobalNMakeMakefileGenerator(this);
+ }
+ this->SetGlobalGenerator(gen);
+ std::cout << "-- Building for: " << gen->GetName() << "\n";
+#else
+ this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3(this));
+#endif
+}
+
void cmake::PreLoadCMakeFiles()
{
std::vector<std::string> args;
std::string pre_load = this->GetHomeDirectory();
- if ( pre_load.size() > 0 )
- {
+ if (!pre_load.empty()) {
pre_load += "/PreLoad.cmake";
- if ( cmSystemTools::FileExists(pre_load.c_str()) )
- {
+ if (cmSystemTools::FileExists(pre_load.c_str())) {
this->ReadListFile(args, pre_load.c_str());
- }
}
+ }
pre_load = this->GetHomeOutputDirectory();
- if ( pre_load.size() > 0 )
- {
+ if (!pre_load.empty()) {
pre_load += "/PreLoad.cmake";
- if ( cmSystemTools::FileExists(pre_load.c_str()) )
- {
+ if (cmSystemTools::FileExists(pre_load.c_str())) {
this->ReadListFile(args, pre_load.c_str());
- }
}
+ }
}
// handle a command line invocation
@@ -2477,556 +1528,499 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
{
// Process the arguments
this->SetArgs(args);
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
- }
+ }
// 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()))
- {
+ if (!this->CheckStampList.empty() &&
+ cmakeCheckStampList(this->CheckStampList.c_str())) {
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()))
- {
+ if (!this->CheckStampFile.empty() &&
+ cmakeCheckStampFile(this->CheckStampFile.c_str())) {
return 0;
- }
-
- // set the cmake command
- this->CMakeCommand = args[0];
+ }
- if ( this->GetWorkingMode() == NORMAL_MODE )
- {
+ if (this->GetWorkingMode() == NORMAL_MODE) {
// load the cache
- if(this->LoadCache() < 0)
- {
+ if (this->LoadCache() < 0) {
cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
return -1;
- }
}
- else
- {
+ } else {
this->AddCMakePaths();
- }
+ }
+
// Add any cache args
- if ( !this->SetCacheArgs(args) )
- {
+ if (!this->SetCacheArgs(args)) {
cmSystemTools::Error("Problem processing arguments. Aborting.\n");
return -1;
- }
+ }
// In script mode we terminate after running the script.
- if(this->GetWorkingMode() != NORMAL_MODE)
- {
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ if (this->GetWorkingMode() != NORMAL_MODE) {
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
- }
- else
- {
- return 0;
- }
}
+ return 0;
+ }
// If MAKEFLAGS are given in the environment, remove the environment
// variable. This will prevent try-compile from succeeding when it
// should fail (if "-i" is an option). We cannot simply test
// whether "-i" is given and remove it because some make programs
// encode the MAKEFLAGS variable in a strange way.
- if(getenv("MAKEFLAGS"))
- {
+ if (cmSystemTools::HasEnv("MAKEFLAGS")) {
cmSystemTools::PutEnv("MAKEFLAGS=");
- }
+ }
this->PreLoadCMakeFiles();
- if ( noconfigure )
- {
+ if (noconfigure) {
return 0;
- }
+ }
// now run the global generate
// Check the state of the build system to see if we need to regenerate.
- if(!this->CheckBuildSystem())
- {
+ if (!this->CheckBuildSystem()) {
return 0;
- }
+ }
- // If we are doing global generate, we better set start and start
- // output directory to the root of the project.
- std::string oldstartdir = this->GetStartDirectory();
- std::string oldstartoutputdir = this->GetStartOutputDirectory();
- this->SetStartDirectory(this->GetHomeDirectory());
- this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
int ret = this->Configure();
- if (ret || this->GetWorkingMode() != NORMAL_MODE)
- {
+ if (ret || this->GetWorkingMode() != NORMAL_MODE) {
#if defined(CMAKE_HAVE_VS_GENERATORS)
- if(!this->VSSolutionFile.empty() && this->GlobalGenerator)
- {
+ if (!this->VSSolutionFile.empty() && this->GlobalGenerator) {
// CMake is running to regenerate a Visual Studio build tree
// during a build from the VS IDE. The build files cannot be
// regenerated, so we should stop the build.
- cmSystemTools::Message(
- "CMake Configure step failed. "
- "Build files cannot be regenerated correctly. "
- "Attempting to stop IDE build.");
+ cmSystemTools::Message("CMake Configure step failed. "
+ "Build files cannot be regenerated correctly. "
+ "Attempting to stop IDE build.");
cmGlobalVisualStudioGenerator* gg =
static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop,
this->VSSolutionFile.c_str());
- }
+ }
#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)
- {
- return ret;
- }
- this->SetStartDirectory(oldstartdir.c_str());
- this->SetStartOutputDirectory(oldstartoutputdir.c_str());
-
return ret;
}
int cmake::Generate()
{
- if(!this->GlobalGenerator)
- {
+ if (!this->GlobalGenerator) {
return -1;
- }
+ }
+ if (!this->GlobalGenerator->Compute()) {
+ return -1;
+ }
this->GlobalGenerator->Generate();
- if(this->WarnUnusedCli)
- {
+ if (!this->GraphVizFile.empty()) {
+ std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
+ this->GenerateGraphViz(this->GraphVizFile.c_str());
+ }
+ if (this->WarnUnusedCli) {
this->RunCheckForUnusedVariables();
- }
- if(cmSystemTools::GetErrorOccuredFlag())
- {
+ }
+ if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
- }
- if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
- {
- this->ReportUndefinedPropertyAccesses
- (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
- }
+ }
// 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->CacheManager->SaveCache(this->GetHomeOutputDirectory());
- }
+ if (this->GetWorkingMode() == NORMAL_MODE) {
+ this->SaveCache(this->GetHomeOutputDirectory());
+ }
return 0;
}
-void cmake::AddCacheEntry(const char* key, const char* value,
- const char* helpString,
- int type)
+void cmake::AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString, int type)
{
- this->CacheManager->AddCacheEntry(key, value,
- helpString,
- cmCacheManager::CacheEntryType(type));
+ this->State->AddCacheEntry(key, value, helpString,
+ cmStateEnums::CacheEntryType(type));
+ this->UnwatchUnusedCli(key);
}
-const char* cmake::GetCacheDefinition(const char* name) const
+const char* cmake::GetCacheDefinition(const std::string& name) const
{
- return this->CacheManager->GetCacheValue(name);
+ return this->State->GetInitializedCacheValue(name);
}
-void cmake::AddDefaultCommands()
+void cmake::AddScriptingCommands()
{
- std::list<cmCommand*> commands;
- GetBootstrapCommands1(commands);
- GetBootstrapCommands2(commands);
- GetPredefinedCommands(commands);
- for(std::list<cmCommand*>::iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- this->AddCommand(*i);
- }
+ GetScriptingCommands(this->State);
+}
+
+void cmake::AddProjectCommands()
+{
+ GetProjectCommands(this->State);
}
void cmake::AddDefaultGenerators()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
-# if !defined(CMAKE_BOOT_MINGW)
- this->Generators.push_back(
- cmGlobalVisualStudio6Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio7Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio10Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio11Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio12Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio71Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio8Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalVisualStudio9Generator::NewFactory());
- this->Generators.push_back(
- cmGlobalBorlandMakefileGenerator::NewFactory());
- this->Generators.push_back(
- cmGlobalNMakeMakefileGenerator::NewFactory());
- this->Generators.push_back(
- cmGlobalJOMMakefileGenerator::NewFactory());
- this->Generators.push_back(
- cmGlobalWatcomWMakeGenerator::NewFactory());
-# endif
- this->Generators.push_back(
- cmGlobalMSYSMakefileGenerator::NewFactory());
- this->Generators.push_back(
- cmGlobalMinGWMakefileGenerator::NewFactory());
+#if !defined(CMAKE_BOOT_MINGW)
+ this->Generators.push_back(cmGlobalVisualStudio15Generator::NewFactory());
+ 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
+ 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)
+ this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory());
+#endif
+#if defined(CMAKE_USE_WMAKE)
+ this->Generators.push_back(cmGlobalWatcomWMakeGenerator::NewFactory());
#endif
- this->Generators.push_back(
- cmGlobalUnixMakefileGenerator3::NewFactory());
- this->Generators.push_back(
- cmGlobalNinjaGenerator::NewFactory());
#ifdef CMAKE_USE_XCODE
- this->Generators.push_back(
- cmGlobalXCodeGenerator::NewFactory());
+ this->Generators.push_back(cmGlobalXCodeGenerator::NewFactory());
#endif
}
+bool cmake::ParseCacheEntry(const std::string& entry, std::string& var,
+ std::string& value,
+ cmStateEnums::CacheEntryType& type)
+{
+ return cmState::ParseCacheEntry(entry, var, value, type);
+}
+
int cmake::LoadCache()
{
// could we not read the cache
- if (!this->CacheManager->LoadCache(this->GetHomeOutputDirectory()))
- {
+ 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()))
- {
+ if (cmSystemTools::FileExists(cacheFile.c_str())) {
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 "
"permissions of the directory you are trying to run CMake on.");
return -1;
- }
- }
-
- if (this->CMakeCommand.size() < 2)
- {
- cmSystemTools::Error(
- "cmake command was not specified prior to loading the cache in "
- "cmake.cxx");
- return -1;
}
+ }
// setup CMAKE_ROOT and CMAKE_COMMAND
- if(!this->AddCMakePaths())
- {
+ if (!this->AddCMakePaths()) {
return -3;
- }
+ }
return 0;
}
-void cmake::SetProgressCallback(ProgressCallbackType f, void *cd)
+bool cmake::LoadCache(const std::string& path)
{
- this->ProgressCallback = f;
- this->ProgressCallbackClientData = cd;
+ std::set<std::string> emptySet;
+ return this->LoadCache(path, true, emptySet, emptySet);
}
-void cmake::UpdateProgress(const char *msg, float prog)
+bool cmake::LoadCache(const std::string& path, bool internal,
+ std::set<std::string>& excludes,
+ std::set<std::string>& includes)
{
- if(this->ProgressCallback && !this->InTryCompile)
- {
- (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData);
- return;
- }
+ 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);
+ }
+ return result;
}
-void cmake::GetCommandDocumentation(std::vector<cmDocumentationEntry>& v,
- bool withCurrentCommands,
- bool withCompatCommands) const
+bool cmake::SaveCache(const std::string& path)
{
- for(RegisteredCommandsMap::const_iterator j = this->Commands.begin();
- j != this->Commands.end(); ++j)
- {
- if ((( withCompatCommands == false) && ( (*j).second->IsDiscouraged()))
- || ((withCurrentCommands == false) && (!(*j).second->IsDiscouraged()))
- || (!((*j).second->ShouldAppearInDocumentation()))
- )
- {
- continue;
- }
+ 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);
+ }
+ return result;
+}
- cmDocumentationEntry e((*j).second->GetName(),
- (*j).second->GetTerseDocumentation(),
- (*j).second->GetFullDocumentation());
- v.push_back(e);
- }
+bool cmake::DeleteCache(const std::string& path)
+{
+ return this->State->DeleteCache(path);
+}
+
+void cmake::SetProgressCallback(ProgressCallbackType f, void* cd)
+{
+ this->ProgressCallback = f;
+ this->ProgressCallbackClientData = cd;
}
-void cmake::GetPolicyDocumentation(std::vector<cmDocumentationEntry>& v)
+void cmake::UpdateProgress(const char* msg, float prog)
{
- this->Policies->GetDocumentation(v);
+ if (this->ProgressCallback && !this->State->GetIsInTryCompile()) {
+ (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData);
+ return;
+ }
}
-void cmake::GetPropertiesDocumentation(std::map<std::string,
- cmDocumentationSection *>& v)
+bool cmake::GetIsInTryCompile() const
{
- // loop over the properties and put them into the doc structure
- std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
- i = this->PropertyDefinitions.begin();
- for (;i != this->PropertyDefinitions.end(); ++i)
- {
- i->second.GetPropertiesDocumentation(v);
- }
+ return this->State->GetIsInTryCompile();
+}
+
+void cmake::SetIsInTryCompile(bool b)
+{
+ this->State->SetIsInTryCompile(b);
}
void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
{
- for(RegisteredGeneratorsVector::const_iterator i =
- this->Generators.begin(); i != this->Generators.end(); ++i)
- {
+ for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
+ i != this->Generators.end(); ++i) {
cmDocumentationEntry e;
(*i)->GetDocumentation(e);
v.push_back(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();
+
+ // Aliases:
+ for (std::vector<std::string>::const_iterator a = (*i)->Aliases.begin();
+ a != (*i)->Aliases.end(); ++a) {
+ cmDocumentationEntry e;
+ e.Name = *a;
+ e.Brief = doc;
+ v.push_back(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) {
+ cmDocumentationEntry e;
+ e.Name =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*g, name);
+ e.Brief = doc;
+ v.push_back(e);
}
- for(RegisteredExtraGeneratorsMap::const_iterator i =
- this->ExtraGenerators.begin(); i != this->ExtraGenerators.end(); ++i)
- {
- cmDocumentationEntry e;
- cmExternalMakefileProjectGenerator* generator = (i->second)();
- generator->GetDocumentation(e, i->first.c_str());
- e.Name = i->first;
- delete generator;
- v.push_back(e);
- }
+ }
+}
+
+void cmake::PrintGeneratorList()
+{
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmDocumentation doc;
+ std::vector<cmDocumentationEntry> generators;
+ this->GetGeneratorDocumentation(generators);
+ doc.AppendSection("Generators", generators);
+ std::cerr << "\n";
+ doc.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr);
+#endif
}
void cmake::UpdateConversionPathTable()
{
// Update the path conversion table with any specified file:
const char* tablepath =
- this->CacheManager->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
+ this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE");
- if(tablepath)
- {
- std::ifstream table( tablepath );
- if(!table)
- {
+ if (tablepath) {
+ cmsys::ifstream table(tablepath);
+ if (!table) {
cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath,
- ". CMake can not open file.");
+ ". CMake can not open file.");
cmSystemTools::ReportLastSystemError("CMake can not open file.");
- }
- else
- {
+ } else {
std::string a, b;
- while(!table.eof())
- {
+ while (!table.eof()) {
// two entries per line
- table >> a; table >> b;
- cmSystemTools::AddTranslationPath( a.c_str(), b.c_str());
- }
+ table >> a;
+ table >> b;
+ cmSystemTools::AddTranslationPath(a, b);
}
}
+ }
}
-//----------------------------------------------------------------------------
int cmake::CheckBuildSystem()
{
- // We do not need to rerun CMake. Check dependency integrity. Use
- // the make system's VERBOSE environment variable to enable verbose
- // output. This can be skipped by setting CMAKE_NO_VERBOSE (which is set
- // by the Eclipse and KDevelop generators).
- bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != 0)
- && (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == 0));
+ // We do not need to rerun CMake. Check dependency integrity.
+ const bool verbose = isCMakeVerbose();
// This method will check the integrity of the build system if the
// option was given on the command line. It reads the given file to
// determine whether CMake should rerun.
// If no file is provided for the check, we have to rerun.
- if(this->CheckBuildSystemArgument.size() == 0)
- {
- if(verbose)
- {
- cmOStringStream msg;
+ if (this->CheckBuildSystemArgument.empty()) {
+ if (verbose) {
+ std::ostringstream msg;
msg << "Re-run cmake no build system arguments\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
- return 1;
}
+ return 1;
+ }
// If the file provided does not exist, we have to rerun.
- if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument.c_str()))
- {
- if(verbose)
- {
- cmOStringStream msg;
- msg << "Re-run cmake missing file: "
- << this->CheckBuildSystemArgument.c_str() << "\n";
+ if (!cmSystemTools::FileExists(this->CheckBuildSystemArgument.c_str())) {
+ if (verbose) {
+ std::ostringstream msg;
+ msg << "Re-run cmake missing file: " << this->CheckBuildSystemArgument
+ << "\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
- return 1;
}
+ return 1;
+ }
// Read the rerun check file and use it to decide whether to do the
// global generate.
- cmake cm;
- cmGlobalGenerator gg;
- gg.SetCMakeInstance(&cm);
- cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
- cmMakefile* mf = lg->GetMakefile();
- if(!mf->ReadListFile(0, this->CheckBuildSystemArgument.c_str()) ||
- cmSystemTools::GetErrorOccuredFlag())
- {
- if(verbose)
- {
- cmOStringStream msg;
- msg << "Re-run cmake error reading : "
- << this->CheckBuildSystemArgument.c_str() << "\n";
+ cmake cm(RoleScript); // Actually, all we need is the `set` command.
+ 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()) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
+ if (verbose) {
+ std::ostringstream msg;
+ msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument
+ << "\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
+ }
// There was an error reading the file. Just rerun.
return 1;
- }
+ }
- if(this->ClearBuildSystem)
- {
+ if (this->ClearBuildSystem) {
// Get the generator used for this build system.
const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
- if(!genName || genName[0] == '\0')
- {
+ if (!genName || genName[0] == '\0') {
genName = "Unix Makefiles";
- }
+ }
// Create the generator and use it to clear the dependencies.
- cmsys::auto_ptr<cmGlobalGenerator>
- ggd(this->CreateGlobalGenerator(genName));
- if(ggd.get())
- {
- cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
- lgd->ClearDependencies(mf, verbose);
- }
+ CM_AUTO_PTR<cmGlobalGenerator> ggd(this->CreateGlobalGenerator(genName));
+ if (ggd.get()) {
+ 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);
}
+ }
// 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"))
- {
+ if (const char* productStr = mf->GetDefinition("CMAKE_MAKEFILE_PRODUCTS")) {
cmSystemTools::ExpandListArgument(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->c_str())))
- {
- if(verbose)
- {
- cmOStringStream msg;
+ }
+ for (std::vector<std::string>::const_iterator pi = products.begin();
+ pi != products.end(); ++pi) {
+ if (!(cmSystemTools::FileExists(pi->c_str()) ||
+ cmSystemTools::FileIsSymlink(*pi))) {
+ if (verbose) {
+ std::ostringstream msg;
msg << "Re-run cmake, missing byproduct: " << *pi << "\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
- return 1;
}
+ return 1;
}
+ }
// 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");
- if(dependsStr && outputsStr)
- {
+ if (dependsStr && outputsStr) {
cmSystemTools::ExpandListArgument(dependsStr, depends);
cmSystemTools::ExpandListArgument(outputsStr, outputs);
- }
- if(depends.empty() || outputs.empty())
- {
+ }
+ if (depends.empty() || outputs.empty()) {
// Not enough information was provided to do the test. Just rerun.
- if(verbose)
- {
- cmOStringStream msg;
+ if (verbose) {
+ std::ostringstream msg;
msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
- "or CMAKE_MAKEFILE_OUTPUTS :\n";
+ "or CMAKE_MAKEFILE_OUTPUTS :\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
- return 1;
}
+ return 1;
+ }
// Find the newest dependency.
std::vector<std::string>::iterator dep = depends.begin();
std::string dep_newest = *dep++;
- for(;dep != depends.end(); ++dep)
- {
+ for (; dep != depends.end(); ++dep) {
int result = 0;
- if(this->FileComparison->FileTimeCompare(dep_newest.c_str(),
- dep->c_str(), &result))
- {
- if(result < 0)
- {
+ if (this->FileComparison->FileTimeCompare(dep_newest.c_str(), dep->c_str(),
+ &result)) {
+ if (result < 0) {
dep_newest = *dep;
- }
}
- else
- {
- if(verbose)
- {
- cmOStringStream msg;
+ } else {
+ if (verbose) {
+ std::ostringstream msg;
msg << "Re-run cmake: build system dependency is missing\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
- return 1;
}
+ return 1;
}
+ }
// Find the oldest output.
std::vector<std::string>::iterator out = outputs.begin();
std::string out_oldest = *out++;
- for(;out != outputs.end(); ++out)
- {
+ for (; out != outputs.end(); ++out) {
int result = 0;
- if(this->FileComparison->FileTimeCompare(out_oldest.c_str(),
- out->c_str(), &result))
- {
- if(result > 0)
- {
+ if (this->FileComparison->FileTimeCompare(out_oldest.c_str(), out->c_str(),
+ &result)) {
+ if (result > 0) {
out_oldest = *out;
- }
}
- else
- {
- if(verbose)
- {
- cmOStringStream msg;
+ } else {
+ if (verbose) {
+ std::ostringstream msg;
msg << "Re-run cmake: build system output is missing\n";
cmSystemTools::Stdout(msg.str().c_str());
- }
- return 1;
}
+ return 1;
}
+ }
// 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) ||
- result < 0)
- {
- if(verbose)
- {
- cmOStringStream msg;
- msg << "Re-run cmake file: " << out_oldest.c_str()
- << " older than: " << dep_newest.c_str() << "\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ int result = 0;
+ if (!this->FileComparison->FileTimeCompare(out_oldest.c_str(),
+ dep_newest.c_str(), &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());
}
- return 1;
+ return 1;
}
}
@@ -3034,116 +2028,35 @@ int cmake::CheckBuildSystem()
return 0;
}
-//----------------------------------------------------------------------------
void cmake::TruncateOutputLog(const char* fname)
{
std::string fullPath = this->GetHomeOutputDirectory();
fullPath += "/";
fullPath += fname;
struct stat st;
- if ( ::stat(fullPath.c_str(), &st) )
- {
+ if (::stat(fullPath.c_str(), &st)) {
return;
- }
- if ( !this->CacheManager->GetCacheValue("CMAKE_CACHEFILE_DIR") )
- {
- cmSystemTools::RemoveFile(fullPath.c_str());
+ }
+ if (!this->State->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) {
+ cmSystemTools::RemoveFile(fullPath);
return;
- }
+ }
off_t fsize = st.st_size;
const off_t maxFileSize = 50 * 1024;
- if ( fsize < maxFileSize )
- {
- //TODO: truncate file
+ if (fsize < maxFileSize) {
+ // TODO: truncate file
return;
- }
+ }
}
inline std::string removeQuotes(const std::string& s)
{
- if(s[0] == '\"' && s[s.size()-1] == '\"')
- {
- return s.substr(1, s.size()-2);
- }
+ if (s[0] == '\"' && s[s.size() - 1] == '\"') {
+ return s.substr(1, s.size() - 2);
+ }
return s;
}
-std::string cmake::FindCMakeProgram(const char* name) const
-{
- std::string path;
- if ((name) && (*name))
- {
- const cmMakefile* mf
- = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
-#ifdef CMAKE_BUILD_WITH_CMAKE
- path = mf->GetRequiredDefinition("CMAKE_COMMAND");
- path = removeQuotes(path);
- path = cmSystemTools::GetFilenamePath(path.c_str());
- path += "/";
- path += name;
- path += cmSystemTools::GetExecutableExtension();
- if(!cmSystemTools::FileExists(path.c_str()))
- {
- path = mf->GetRequiredDefinition("CMAKE_COMMAND");
- path = cmSystemTools::GetFilenamePath(path.c_str());
- path += "/Debug/";
- path += name;
- path += cmSystemTools::GetExecutableExtension();
- }
- if(!cmSystemTools::FileExists(path.c_str()))
- {
- path = mf->GetRequiredDefinition("CMAKE_COMMAND");
- path = cmSystemTools::GetFilenamePath(path.c_str());
- path += "/Release/";
- path += name;
- path += cmSystemTools::GetExecutableExtension();
- }
-#else
- // Only for bootstrap
- path += mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
- path += "/";
- path += name;
- path += cmSystemTools::GetExecutableExtension();
-#endif
- }
- return path;
-}
-
-const char* cmake::GetCTestCommand()
-{
- if ( this->CTestCommand.empty() )
- {
- this->CTestCommand = this->FindCMakeProgram("ctest");
- }
- if ( this->CTestCommand.empty() )
- {
- cmSystemTools::Error("Cannot find the CTest executable");
- this->CTestCommand = "CTEST-COMMAND-NOT-FOUND";
- }
- return this->CTestCommand.c_str();
-}
-
-const char* cmake::GetCPackCommand()
-{
- if ( this->CPackCommand.empty() )
- {
- this->CPackCommand = this->FindCMakeProgram("cpack");
- }
- if ( this->CPackCommand.empty() )
- {
- cmSystemTools::Error("Cannot find the CPack executable");
- this->CPackCommand = "CPACK-COMMAND-NOT-FOUND";
- }
- return this->CPackCommand.c_str();
-}
-
-
-const char* cmake::GetCMakeCommand()
-{
- return this->CMakeCommand.c_str();
-}
-
-
void cmake::MarkCliAsUsed(const std::string& variable)
{
this->UsedCliVariables[variable] = true;
@@ -3152,8 +2065,8 @@ void cmake::MarkCliAsUsed(const std::string& variable)
void cmake::GenerateGraphViz(const char* fileName) const
{
#ifdef CMAKE_BUILD_WITH_CMAKE
- cmsys::auto_ptr<cmGraphVizWriter> gvWriter(
- new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
+ CM_AUTO_PTR<cmGraphVizWriter> gvWriter(
+ new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
std::string settingsFile = this->GetHomeOutputDirectory();
settingsFile += "/CMakeGraphVizOptions.cmake";
@@ -3169,717 +2082,52 @@ void cmake::GenerateGraphViz(const char* fileName) const
#endif
}
-
-//----------------------------------------------------------------------------
-int cmake::SymlinkLibrary(std::vector<std::string>& args)
-{
- int result = 0;
- std::string realName = args[2];
- std::string soName = args[3];
- std::string name = args[4];
- if(soName != realName)
- {
- if(!cmake::SymlinkInternal(realName, soName))
- {
- cmSystemTools::ReportLastSystemError("cmake_symlink_library");
- result = 1;
- }
- }
- if(name != soName)
- {
- if(!cmake::SymlinkInternal(soName, name))
- {
- cmSystemTools::ReportLastSystemError("cmake_symlink_library");
- result = 1;
- }
- }
- return result;
-}
-
-//----------------------------------------------------------------------------
-int cmake::SymlinkExecutable(std::vector<std::string>& args)
-{
- int result = 0;
- std::string realName = args[2];
- std::string name = args[3];
- if(name != realName)
- {
- if(!cmake::SymlinkInternal(realName, name))
- {
- cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
- result = 1;
- }
- }
- return result;
-}
-
-//----------------------------------------------------------------------------
-bool cmake::SymlinkInternal(std::string const& file, std::string const& link)
-{
- if(cmSystemTools::FileExists(link.c_str()) ||
- cmSystemTools::FileIsSymlink(link.c_str()))
- {
- cmSystemTools::RemoveFile(link.c_str());
- }
-#if defined(_WIN32) && !defined(__CYGWIN__)
- return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str());
-#else
- std::string linktext = cmSystemTools::GetFilenameName(file);
- return cmSystemTools::CreateSymlink(linktext.c_str(), link.c_str());
-#endif
-}
-
-//----------------------------------------------------------------------------
-#ifdef CMAKE_BUILD_WITH_CMAKE
-int cmake::ExecuteEchoColor(std::vector<std::string>& args)
-{
- // The arguments are
- // argv[0] == <cmake-executable>
- // argv[1] == cmake_echo_color
-
- bool enabled = true;
- int color = cmsysTerminal_Color_Normal;
- bool newline = true;
- for(unsigned int i=2; i < args.size(); ++i)
- {
- if(args[i].find("--switch=") == 0)
- {
- // Enable or disable color based on the switch value.
- std::string value = args[i].substr(9);
- if(!value.empty())
- {
- if(cmSystemTools::IsOn(value.c_str()))
- {
- enabled = true;
- }
- else
- {
- enabled = false;
- }
- }
- }
- else if(args[i] == "--normal")
- {
- color = cmsysTerminal_Color_Normal;
- }
- else if(args[i] == "--black")
- {
- color = cmsysTerminal_Color_ForegroundBlack;
- }
- else if(args[i] == "--red")
- {
- color = cmsysTerminal_Color_ForegroundRed;
- }
- else if(args[i] == "--green")
- {
- color = cmsysTerminal_Color_ForegroundGreen;
- }
- else if(args[i] == "--yellow")
- {
- color = cmsysTerminal_Color_ForegroundYellow;
- }
- else if(args[i] == "--blue")
- {
- color = cmsysTerminal_Color_ForegroundBlue;
- }
- else if(args[i] == "--magenta")
- {
- color = cmsysTerminal_Color_ForegroundMagenta;
- }
- else if(args[i] == "--cyan")
- {
- color = cmsysTerminal_Color_ForegroundCyan;
- }
- else if(args[i] == "--white")
- {
- color = cmsysTerminal_Color_ForegroundWhite;
- }
- else if(args[i] == "--bold")
- {
- color |= cmsysTerminal_Color_ForegroundBold;
- }
- else if(args[i] == "--no-newline")
- {
- newline = false;
- }
- else if(args[i] == "--newline")
- {
- newline = true;
- }
- else
- {
- // Color is enabled. Print with the current color.
- cmSystemTools::MakefileColorEcho(color, args[i].c_str(),
- newline, enabled);
- }
- }
-
- return 0;
-}
-#else
-int cmake::ExecuteEchoColor(std::vector<std::string>&)
+void cmake::SetProperty(const std::string& prop, const char* value)
{
- return 1;
+ this->State->SetGlobalProperty(prop, value);
}
-#endif
-//----------------------------------------------------------------------------
-int cmake::ExecuteLinkScript(std::vector<std::string>& args)
+void cmake::AppendProperty(const std::string& prop, const char* value,
+ bool asString)
{
- // The arguments are
- // argv[0] == <cmake-executable>
- // argv[1] == cmake_link_script
- // argv[2] == <link-script-name>
- // argv[3] == --verbose=?
- bool verbose = false;
- if(args.size() >= 4)
- {
- if(args[3].find("--verbose=") == 0)
- {
- if(!cmSystemTools::IsOff(args[3].substr(10).c_str()))
- {
- verbose = true;
- }
- }
- }
-
- // Allocate a process instance.
- cmsysProcess* cp = cmsysProcess_New();
- if(!cp)
- {
- std::cerr << "Error allocating process instance in link script."
- << std::endl;
- return 1;
- }
-
- // Children should share stdout and stderr with this process.
- cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
- cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
-
- // Run the command lines verbatim.
- cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
-
- // Read command lines from the script.
- std::ifstream fin(args[2].c_str());
- if(!fin)
- {
- std::cerr << "Error opening link script \""
- << args[2] << "\"" << std::endl;
- return 1;
- }
-
- // Run one command at a time.
- std::string command;
- int result = 0;
- while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
- {
- // Skip empty command lines.
- if(command.find_first_not_of(" \t") == command.npos)
- {
- continue;
- }
-
- // Setup this command line.
- const char* cmd[2] = {command.c_str(), 0};
- cmsysProcess_SetCommand(cp, cmd);
-
- // Report the command if verbose output is enabled.
- if(verbose)
- {
- std::cout << command << std::endl;
- }
-
- // Run the command and wait for it to exit.
- cmsysProcess_Execute(cp);
- cmsysProcess_WaitForExit(cp, 0);
-
- // Report failure if any.
- switch(cmsysProcess_GetState(cp))
- {
- case cmsysProcess_State_Exited:
- {
- int value = cmsysProcess_GetExitValue(cp);
- if(value != 0)
- {
- result = value;
- }
- }
- break;
- case cmsysProcess_State_Exception:
- std::cerr << "Error running link command: "
- << cmsysProcess_GetExceptionString(cp) << std::endl;
- result = 1;
- break;
- case cmsysProcess_State_Error:
- std::cerr << "Error running link command: "
- << cmsysProcess_GetErrorString(cp) << std::endl;
- result = 2;
- break;
- default:
- break;
- };
- }
-
- // Free the process instance.
- cmsysProcess_Delete(cp);
-
- // Return the final resulting return value.
- return result;
+ this->State->AppendGlobalProperty(prop, value, asString);
}
-void cmake::DefineProperties(cmake *cm)
+const char* cmake::GetProperty(const std::string& prop)
{
- cm->DefineProperty
- ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL,
- "If set, report any undefined properties to this file.",
- "If this property is set to a filename then when CMake runs "
- "it will report any properties or variables that were accessed "
- "but not defined into the filename specified in this property."
- );
-
- cm->DefineProperty
- ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL,
- "Does the target platform support shared libraries.",
- "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
- "platform supports shared libraries. Basically all current general "
- "general purpose OS do so, the exception are usually embedded systems "
- "with no or special OSs.");
-
- cm->DefineProperty
- ("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS", cmProperty::GLOBAL,
- "Set if shared libraries may be named like archives.",
- "On AIX shared libraries may be named \"lib<name>.a\". "
- "This property is set to true on such platforms.");
-
- cm->DefineProperty
- ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL,
- "Whether FIND_LIBRARY should automatically search lib64 directories.",
- "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
- "FIND_LIBRARY command should automatically search the lib64 variant of "
- "directories called lib in the search path when building 64-bit "
- "binaries.");
- cm->DefineProperty
- ("FIND_LIBRARY_USE_OPENBSD_VERSIONING", cmProperty::GLOBAL,
- "Whether FIND_LIBRARY should find OpenBSD-style shared libraries.",
- "This property is a boolean specifying whether the FIND_LIBRARY "
- "command should find shared libraries with OpenBSD-style versioned "
- "extension: \".so.<major>.<minor>\". "
- "The property is set to true on OpenBSD and false on other platforms.");
- cm->DefineProperty
- ("ENABLED_FEATURES", cmProperty::GLOBAL,
- "List of features which are enabled during the CMake run.",
- "List of features which are enabled during the CMake run. By default "
- "it contains the names of all packages which were found. This is "
- "determined using the <NAME>_FOUND variables. Packages which are "
- "searched QUIET are not listed. A project can add its own features to "
- "this list. "
- "This property is used by the macros in FeatureSummary.cmake.");
- cm->DefineProperty
- ("DISABLED_FEATURES", cmProperty::GLOBAL,
- "List of features which are disabled during the CMake run.",
- "List of features which are disabled during the CMake run. By default "
- "it contains the names of all packages which were not found. This is "
- "determined using the <NAME>_FOUND variables. Packages which are "
- "searched QUIET are not listed. A project can add its own features to "
- "this list. "
- "This property is used by the macros in FeatureSummary.cmake.");
- cm->DefineProperty
- ("PACKAGES_FOUND", cmProperty::GLOBAL,
- "List of packages which were found during the CMake run.",
- "List of packages which were found during the CMake run. Whether a "
- "package has been found is determined using the <NAME>_FOUND variables.");
- cm->DefineProperty
- ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL,
- "List of packages which were not found during the CMake run.",
- "List of packages which were not found during the CMake run. Whether a "
- "package has been found is determined using the <NAME>_FOUND variables.");
-
- cm->DefineProperty(
- "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL,
- "Internal property",
- "Used to detect compiler changes, Do not set.");
-
- cm->DefineProperty(
- "DEBUG_CONFIGURATIONS", cmProperty::GLOBAL,
- "Specify which configurations are for debugging.",
- "The value must be a semi-colon separated list of configuration names. "
- "Currently this property is used only by the target_link_libraries "
- "command (see its documentation for details). "
- "Additional uses may be defined in the future. "
- "\n"
- "This property must be set at the top level of the project and before "
- "the first target_link_libraries command invocation. "
- "If any entry in the list does not match a valid configuration for "
- "the project the behavior is undefined.");
-
- cm->DefineProperty(
- "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL,
- "Enable global target dependency graph debug mode.",
- "CMake automatically analyzes the global inter-target dependency graph "
- "at the beginning of native build system generation. "
- "This property causes it to display details of its analysis to stderr.");
-
- cm->DefineProperty(
- "GLOBAL_DEPENDS_NO_CYCLES", cmProperty::GLOBAL,
- "Disallow global target dependency graph cycles.",
- "CMake automatically analyzes the global inter-target dependency graph "
- "at the beginning of native build system generation. "
- "It reports an error if the dependency graph contains a cycle that "
- "does not consist of all STATIC library targets. "
- "This property tells CMake to disallow all cycles completely, even "
- "among static libraries.");
-
- cm->DefineProperty(
- "ALLOW_DUPLICATE_CUSTOM_TARGETS", cmProperty::GLOBAL,
- "Allow duplicate custom targets to be created.",
- "Normally CMake requires that all targets built in a project have "
- "globally unique logical names (see policy CMP0002). "
- "This is necessary to generate meaningful project file names in "
- "Xcode and VS IDE generators. "
- "It also allows the target names to be referenced unambiguously.\n"
- "Makefile generators are capable of supporting duplicate custom target "
- "names. "
- "For projects that care only about Makefile generators and do "
- "not wish to support Xcode or VS IDE generators, one may set this "
- "property to true to allow duplicate custom targets. "
- "The property allows multiple add_custom_target command calls in "
- "different directories to specify the same target name. "
- "However, setting this property will cause non-Makefile generators "
- "to produce an error and refuse to generate the project."
- );
-
- cm->DefineProperty
- ("IN_TRY_COMPILE", cmProperty::GLOBAL,
- "Read-only property that is true during a try-compile configuration.",
- "True when building a project inside a TRY_COMPILE or TRY_RUN command.");
- cm->DefineProperty
- ("ENABLED_LANGUAGES", cmProperty::GLOBAL,
- "Read-only property that contains the list of currently "
- "enabled languages",
- "Set to list of currently enabled languages.");
-
- cm->DefineProperty
- ("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL,
- "Specify a launcher for compile rules.",
- "Makefile generators prefix compiler commands with the given "
- "launcher command line. "
- "This is intended to allow launchers to intercept build problems "
- "with high granularity. "
- "Non-Makefile generators currently ignore this property.");
- cm->DefineProperty
- ("RULE_LAUNCH_LINK", cmProperty::GLOBAL,
- "Specify a launcher for link rules.",
- "Makefile generators prefix link and archive commands with the given "
- "launcher command line. "
- "This is intended to allow launchers to intercept build problems "
- "with high granularity. "
- "Non-Makefile generators currently ignore this property.");
- cm->DefineProperty
- ("RULE_LAUNCH_CUSTOM", cmProperty::GLOBAL,
- "Specify a launcher for custom rules.",
- "Makefile generators prefix custom commands with the given "
- "launcher command line. "
- "This is intended to allow launchers to intercept build problems "
- "with high granularity. "
- "Non-Makefile generators currently ignore this property.");
-
- cm->DefineProperty
- ("RULE_MESSAGES", cmProperty::GLOBAL,
- "Specify whether to report a message for each make rule.",
- "This property specifies whether Makefile generators should add a "
- "progress message describing what each build rule does. "
- "If the property is not set the default is ON. "
- "Set the property to OFF to disable granular messages and report only "
- "as each target completes. "
- "This is intended to allow scripted builds to avoid the build time "
- "cost of detailed reports. "
- "If a CMAKE_RULE_MESSAGES cache entry exists its value initializes "
- "the value of this property. "
- "Non-Makefile generators currently ignore this property.");
-
- cm->DefineProperty
- ("USE_FOLDERS", cmProperty::GLOBAL,
- "Use the FOLDER target property to organize targets into folders.",
- "If not set, CMake treats this property as OFF by default. "
- "CMake generators that are capable of organizing into a "
- "hierarchy of folders use the values of the FOLDER target "
- "property to name those folders. See also the documentation "
- "for the FOLDER target property.");
-
- cm->DefineProperty
- ("AUTOMOC_TARGETS_FOLDER", cmProperty::GLOBAL,
- "Name of FOLDER for *_automoc targets that are added automatically by "
- "CMake for targets for which AUTOMOC is enabled.",
- "If not set, CMake uses the FOLDER property of the parent target as a "
- "default value for this property. See also the documentation for the "
- "FOLDER target property and the AUTOMOC target property.");
-
- cm->DefineProperty
- ("PREDEFINED_TARGETS_FOLDER", cmProperty::GLOBAL,
- "Name of FOLDER for targets that are added automatically by CMake.",
- "If not set, CMake uses \"CMakePredefinedTargets\" as a default "
- "value for this property. Targets such as INSTALL, PACKAGE and "
- "RUN_TESTS will be organized into this FOLDER. See also the "
- "documentation for the FOLDER target property.");
-
- // ================================================================
- // define variables as well
- // ================================================================
- cmDocumentVariables::DefineVariables(cm);
+ return this->State->GetGlobalProperty(prop);
}
-
-void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
- const char *ShortDescription,
- const char *FullDescription,
- bool chained, const char *docSection)
+bool cmake::GetPropertyAsBool(const std::string& prop)
{
- this->PropertyDefinitions[scope].DefineProperty(name,scope,ShortDescription,
- FullDescription,
- docSection,
- chained);
+ return this->State->GetGlobalPropertyAsBool(prop);
}
-bool cmake::GetIsPropertyDefined(const char *name,
- cmProperty::ScopeType scope)
+cmInstalledFile* cmake::GetOrCreateInstalledFile(cmMakefile* mf,
+ const std::string& name)
{
- return this->PropertyDefinitions[scope].find(name) !=
- this->PropertyDefinitions[scope].end();
-}
+ std::map<std::string, cmInstalledFile>::iterator i =
+ this->InstalledFiles.find(name);
-cmPropertyDefinition *cmake
-::GetPropertyDefinition(const char *name,
- cmProperty::ScopeType scope)
-{
- if (this->IsPropertyDefined(name,scope))
- {
- return &(this->PropertyDefinitions[scope][name]);
- }
- return 0;
-}
-
-void cmake::RecordPropertyAccess(const char *name,
- cmProperty::ScopeType scope)
-{
- this->AccessedProperties.insert
- (std::pair<cmStdString,cmProperty::ScopeType>(name,scope));
-}
-
-void cmake::ReportUndefinedPropertyAccesses(const char *filename)
-{
- if(!this->GlobalGenerator)
- { return; }
- FILE *progFile = fopen(filename,"w");
- if(!progFile)
- { return; }
-
- // what are the enabled languages?
- std::vector<std::string> enLangs;
- this->GlobalGenerator->GetEnabledLanguages(enLangs);
-
- // Common configuration names.
- // TODO: Compute current configuration(s).
- std::vector<std::string> enConfigs;
- enConfigs.push_back("");
- enConfigs.push_back("DEBUG");
- enConfigs.push_back("RELEASE");
- enConfigs.push_back("MINSIZEREL");
- enConfigs.push_back("RELWITHDEBINFO");
-
- // take all the defined properties and add definitions for all the enabled
- // languages
- std::set<std::pair<cmStdString,cmProperty::ScopeType> > aliasedProperties;
- std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
- i = this->PropertyDefinitions.begin();
- for (;i != this->PropertyDefinitions.end(); ++i)
- {
- cmPropertyDefinitionMap::iterator j;
- for (j = i->second.begin(); j != i->second.end(); ++j)
- {
- // TODO: What if both <LANG> and <CONFIG> appear?
- if (j->first.find("<CONFIG>") != std::string::npos)
- {
- std::vector<std::string>::const_iterator k;
- for (k = enConfigs.begin(); k != enConfigs.end(); ++k)
- {
- std::string tmp = j->first;
- cmSystemTools::ReplaceString(tmp, "<CONFIG>", k->c_str());
- // add alias
- aliasedProperties.insert
- (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
- }
- }
- if (j->first.find("<LANG>") != std::string::npos)
- {
- std::vector<std::string>::const_iterator k;
- for (k = enLangs.begin(); k != enLangs.end(); ++k)
- {
- std::string tmp = j->first;
- cmSystemTools::ReplaceString(tmp, "<LANG>", k->c_str());
- // add alias
- aliasedProperties.insert
- (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
- }
- }
- }
- }
-
- std::set<std::pair<cmStdString,cmProperty::ScopeType> >::const_iterator ap;
- ap = this->AccessedProperties.begin();
- for (;ap != this->AccessedProperties.end(); ++ap)
- {
- if (!this->IsPropertyDefined(ap->first.c_str(),ap->second) &&
- aliasedProperties.find(std::pair<cmStdString,cmProperty::ScopeType>
- (ap->first,ap->second)) ==
- aliasedProperties.end())
- {
- const char *scopeStr = "";
- switch (ap->second)
- {
- case cmProperty::TARGET:
- scopeStr = "TARGET";
- break;
- case cmProperty::SOURCE_FILE:
- scopeStr = "SOURCE_FILE";
- break;
- case cmProperty::DIRECTORY:
- scopeStr = "DIRECTORY";
- break;
- case cmProperty::TEST:
- scopeStr = "TEST";
- break;
- case cmProperty::VARIABLE:
- scopeStr = "VARIABLE";
- break;
- case cmProperty::CACHED_VARIABLE:
- scopeStr = "CACHED_VARIABLE";
- break;
- default:
- scopeStr = "unknown";
- break;
- }
- fprintf(progFile, "%s with scope %s\n", ap->first.c_str(), scopeStr);
- }
- }
- fclose(progFile);
-}
-
-bool cmake::IsPropertyDefined(const char *name, cmProperty::ScopeType scope)
-{
- return this->PropertyDefinitions[scope].IsPropertyDefined(name);
-}
-
-bool cmake::IsPropertyChained(const char *name, cmProperty::ScopeType scope)
-{
- return this->PropertyDefinitions[scope].IsPropertyChained(name);
-}
-
-void cmake::SetProperty(const char* prop, const char* value)
-{
- if (!prop)
- {
- return;
- }
-
- // Special hook to invalidate cached value.
- if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0)
- {
- this->DebugConfigs.clear();
- }
-
- this->Properties.SetProperty(prop, value, cmProperty::GLOBAL);
-}
-
-void cmake::AppendProperty(const char* prop, const char* value, bool asString)
-{
- if (!prop)
- {
- return;
- }
-
- // Special hook to invalidate cached value.
- if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0)
- {
- this->DebugConfigs.clear();
- }
-
- this->Properties.AppendProperty(prop, value, cmProperty::GLOBAL, asString);
-}
-
-const char *cmake::GetProperty(const char* prop)
-{
- return this->GetProperty(prop, cmProperty::GLOBAL);
+ if (i != this->InstalledFiles.end()) {
+ cmInstalledFile& file = i->second;
+ return &file;
+ }
+ cmInstalledFile& file = this->InstalledFiles[name];
+ file.SetName(mf, name);
+ return &file;
}
-const char *cmake::GetProperty(const char* prop, cmProperty::ScopeType scope)
+cmInstalledFile const* cmake::GetInstalledFile(const std::string& name) const
{
- if(!prop)
- {
- return 0;
- }
- bool chain = false;
-
- // watch for special properties
- std::string propname = prop;
- std::string output = "";
- if ( propname == "CACHE_VARIABLES" )
- {
- cmCacheManager::CacheIterator cit =
- this->GetCacheManager()->GetCacheIterator();
- for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
- {
- if ( output.size() )
- {
- output += ";";
- }
- output += cit.GetName();
- }
- this->SetProperty("CACHE_VARIABLES", output.c_str());
- }
- else if ( propname == "COMMANDS" )
- {
- cmake::RegisteredCommandsMap::iterator cmds
- = this->GetCommands()->begin();
- for (unsigned int cc=0 ; cmds != this->GetCommands()->end(); ++ cmds )
- {
- if ( cc > 0 )
- {
- output += ";";
- }
- output += cmds->first.c_str();
- cc++;
- }
- this->SetProperty("COMMANDS",output.c_str());
- }
- else if ( propname == "IN_TRY_COMPILE" )
- {
- this->SetProperty("IN_TRY_COMPILE",
- this->GetIsInTryCompile()? "1":"0");
- }
- else if ( propname == "ENABLED_LANGUAGES" )
- {
- std::string lang;
- if(this->GlobalGenerator)
- {
- std::vector<std::string> enLangs;
- this->GlobalGenerator->GetEnabledLanguages(enLangs);
- const char* sep = "";
- for(std::vector<std::string>::iterator i = enLangs.begin();
- i != enLangs.end(); ++i)
- {
- lang += sep;
- sep = ";";
- lang += *i;
- }
- }
- this->SetProperty("ENABLED_LANGUAGES", lang.c_str());
- }
- return this->Properties.GetPropertyValue(prop, scope, chain);
-}
+ std::map<std::string, cmInstalledFile>::const_iterator i =
+ this->InstalledFiles.find(name);
-bool cmake::GetPropertyAsBool(const char* prop)
-{
- return cmSystemTools::IsOn(this->GetProperty(prop));
+ if (i != this->InstalledFiles.end()) {
+ cmInstalledFile const& file = i->second;
+ return &file;
+ }
+ return CM_NULLPTR;
}
int cmake::GetSystemInformation(std::vector<std::string>& args)
@@ -3888,66 +2136,51 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
std::string resultFile;
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
std::string destPath = cwd + "/__cmake_systeminformation";
- cmSystemTools::RemoveADirectory(destPath.c_str());
- if (!cmSystemTools::MakeDirectory(destPath.c_str()))
- {
+ cmSystemTools::RemoveADirectory(destPath);
+ if (!cmSystemTools::MakeDirectory(destPath.c_str())) {
std::cerr << "Error: --system-information must be run from a "
- "writable directory!\n";
+ "writable directory!\n";
return 1;
- }
+ }
// process the arguments
bool writeToStdout = true;
- for(unsigned int i=1; i < args.size(); ++i)
- {
- std::string arg = args[i];
- if(arg.find("-V",0) == 0)
- {
- this->Verbose = true;
- }
- else if(arg.find("-G",0) == 0)
- {
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ std::string const& arg = args[i];
+ if (arg.find("-G", 0) == 0) {
std::string value = arg.substr(2);
- if(value.size() == 0)
- {
+ if (value.empty()) {
++i;
- if(i >= args.size())
- {
+ if (i >= args.size()) {
cmSystemTools::Error("No generator specified for -G");
+ this->PrintGeneratorList();
return -1;
- }
- value = args[i];
}
- cmGlobalGenerator* gen =
- this->CreateGlobalGenerator(value.c_str());
- if(!gen)
- {
+ value = args[i];
+ }
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(value);
+ if (!gen) {
cmSystemTools::Error("Could not create named generator ",
value.c_str());
- }
- else
- {
+ this->PrintGeneratorList();
+ } else {
this->SetGlobalGenerator(gen);
- }
}
+ }
// no option assume it is the output file
- else
- {
- if (!cmSystemTools::FileIsFullPath(arg.c_str()))
- {
+ else {
+ if (!cmSystemTools::FileIsFullPath(arg.c_str())) {
resultFile = cwd;
resultFile += "/";
- }
+ }
resultFile += arg;
writeToStdout = false;
- }
}
-
+ }
// we have to find the module directory, so we can copy the files
this->AddCMakePaths();
- std::string modulesPath =
- this->CacheManager->GetCacheValue("CMAKE_ROOT");
+ std::string modulesPath = cmSystemTools::GetCMakeRoot();
modulesPath += "/Modules";
std::string inFile = modulesPath;
inFile += "/SystemInformation.cmake";
@@ -3955,67 +2188,58 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
outFile += "/CMakeLists.txt";
// Copy file
- if(!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str()))
- {
- std::cerr << "Error copying file \"" << inFile.c_str()
- << "\" to \"" << outFile.c_str() << "\".\n";
+ if (!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str())) {
+ std::cerr << "Error copying file \"" << inFile << "\" to \"" << outFile
+ << "\".\n";
return 1;
- }
+ }
// do we write to a file or to stdout?
- if (resultFile.size() == 0)
- {
+ if (resultFile.empty()) {
resultFile = cwd;
resultFile += "/__cmake_systeminformation/results.txt";
- }
+ }
- // now run cmake on the CMakeLists file
- cmSystemTools::ChangeDirectory(destPath.c_str());
- 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);
- int res = this->Run(args2, false);
-
- if (res != 0)
- {
- std::cerr << "Error: --system-information failed on internal CMake!\n";
- return res;
+ {
+ // now run cmake on the CMakeLists file
+ cmWorkingDirectory workdir(destPath);
+ 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);
+ int res = this->Run(args2, false);
+
+ if (res != 0) {
+ std::cerr << "Error: --system-information failed on internal CMake!\n";
+ return res;
}
-
- // change back to the original directory
- cmSystemTools::ChangeDirectory(cwd.c_str());
+ }
// echo results to stdout if needed
- if (writeToStdout)
- {
- FILE* fin = fopen(resultFile.c_str(), "r");
- if(fin)
- {
+ if (writeToStdout) {
+ FILE* fin = cmsys::SystemTools::Fopen(resultFile, "r");
+ if (fin) {
const int bufferSize = 4096;
char buffer[bufferSize];
size_t n;
- while((n = fread(buffer, 1, bufferSize, fin)) > 0)
- {
- for(char* c = buffer; c < buffer+n; ++c)
- {
+ while ((n = fread(buffer, 1, bufferSize, fin)) > 0) {
+ for (char* c = buffer; c < buffer + n; ++c) {
putc(*c, stdout);
- }
- fflush(stdout);
}
- fclose(fin);
+ fflush(stdout);
}
+ fclose(fin);
}
+ }
// clean up the directory
- cmSystemTools::RemoveADirectory(destPath.c_str());
+ cmSystemTools::RemoveADirectory(destPath);
return 0;
}
-//----------------------------------------------------------------------------
-static bool cmakeCheckStampFile(const char* stampName)
+static bool cmakeCheckStampFile(const char* stampName, bool verbose)
{
// The stamp file does not exist. Use the stamp dependencies to
// determine whether it is really out of date. This works in
@@ -4025,29 +2249,26 @@ static bool cmakeCheckStampFile(const char* stampName)
std::string stampDepends = stampName;
stampDepends += ".depend";
#if defined(_WIN32) || defined(__CYGWIN__)
- std::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
#else
- std::ifstream fin(stampDepends.c_str(), std::ios::in);
+ cmsys::ifstream fin(stampDepends.c_str());
#endif
- if(!fin)
- {
+ if (!fin) {
// The stamp dependencies file cannot be read. Just assume the
// build system is really out of date.
std::cout << "CMake is re-running because " << stampName
<< " dependency file is missing.\n";
return false;
- }
+ }
// Compare the stamp dependencies against the dependency file itself.
cmFileTimeComparison ftc;
std::string dep;
- while(cmSystemTools::GetLineFromStream(fin, dep))
- {
+ while (cmSystemTools::GetLineFromStream(fin, dep)) {
int result;
- if(dep.length() >= 1 && dep[0] != '#' &&
- (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result)
- || result < 0))
- {
+ 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
@@ -4056,595 +2277,195 @@ static bool cmakeCheckStampFile(const char* stampName)
std::cout << " is newer than '" << stampDepends << "'\n";
std::cout << " result='" << result << "'\n";
return false;
- }
}
+ }
// The build system is up to date. The stamp file has been removed
// by the VS IDE due to a "rebuild" request. Restore it atomically.
- cmOStringStream stampTempStream;
+ std::ostringstream stampTempStream;
stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
std::string stampTempString = stampTempStream.str();
const char* stampTemp = stampTempString.c_str();
{
- // TODO: Teach cmGeneratedFileStream to use a random temp file (with
- // multiple tries in unlikely case of conflict) and use that here.
- std::ofstream stamp(stampTemp);
- stamp << "# CMake generation timestamp file for this directory.\n";
- }
- if(cmSystemTools::RenameFile(stampTemp, stampName))
- {
- // 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";
- return true;
- }
- else
- {
- cmSystemTools::RemoveFile(stampTemp);
- cmSystemTools::Error("Cannot restore timestamp ", stampName);
- return false;
+ // 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);
+ 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";
}
+ return true;
+ }
+ cmSystemTools::RemoveFile(stampTemp);
+ cmSystemTools::Error("Cannot restore timestamp ", stampName);
+ return false;
}
-//----------------------------------------------------------------------------
-static bool cmakeCheckStampList(const char* stampList)
+static bool cmakeCheckStampList(const char* stampList, bool verbose)
{
// If the stamp list does not exist CMake must rerun to generate it.
- if(!cmSystemTools::FileExists(stampList))
- {
+ if (!cmSystemTools::FileExists(stampList)) {
std::cout << "CMake is re-running because generate.stamp.list "
<< "is missing.\n";
return false;
- }
- std::ifstream fin(stampList);
- if(!fin)
- {
+ }
+ cmsys::ifstream fin(stampList);
+ if (!fin) {
std::cout << "CMake is re-running because generate.stamp.list "
<< "could not be read.\n";
return false;
- }
+ }
// Check each stamp.
std::string stampName;
- while(cmSystemTools::GetLineFromStream(fin, stampName))
- {
- if(!cmakeCheckStampFile(stampName.c_str()))
- {
+ while (cmSystemTools::GetLineFromStream(fin, stampName)) {
+ if (!cmakeCheckStampFile(stampName.c_str(), verbose)) {
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-int cmake::WindowsCEEnvironment(const char* version, const std::string& name)
-{
-#if defined(CMAKE_HAVE_VS_GENERATORS)
- cmVisualStudioWCEPlatformParser parser(name.c_str());
- parser.ParseVersion(version);
- if (parser.Found())
- {
- std::cout << "@echo off" << std::endl;
- std::cout << "echo Environment Selection: " << name << std::endl;
- std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl;
- std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() <<std::endl;
- std::cout << "set LIB=" << parser.GetLibraryDirectories() <<std::endl;
- return 0;
- }
-#else
- (void)version;
-#endif
-
- std::cerr << "Could not find " << name;
- return -1;
-}
-
-// 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 cmake::VisualStudioLink(std::vector<std::string>& args, int type)
-{
- if(args.size() < 2)
- {
- return -1;
- }
- bool verbose = false;
- if(cmSystemTools::GetEnv("VERBOSE"))
- {
- verbose = true;
- }
- std::vector<std::string> expandedArgs;
- for(std::vector<std::string>::iterator i = args.begin();
- i != args.end(); ++i)
- {
- // check for nmake temporary files
- if((*i)[0] == '@' && i->find("@CMakeFiles") != 0 )
- {
- std::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);
- }
- }
- bool hasIncremental = false;
- bool hasManifest = true;
- for(std::vector<std::string>::iterator i = expandedArgs.begin();
- i != expandedArgs.end(); ++i)
- {
- if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL:YES") == 0)
- {
- hasIncremental = true;
- }
- if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL") == 0)
- {
- hasIncremental = true;
- }
- if(cmSystemTools::Strucmp(i->c_str(), "/MANIFEST:NO") == 0)
- {
- hasManifest = false;
- }
- }
- if(hasIncremental && hasManifest)
- {
- if(verbose)
- {
- std::cout << "Visual Studio Incremental Link with embedded manifests\n";
- }
- return cmake::VisualStudioLinkIncremental(expandedArgs, type, verbose);
- }
- if(verbose)
- {
- if(!hasIncremental)
- {
- std::cout << "Visual Studio Non-Incremental Link\n";
- }
- else
- {
- std::cout << "Visual Studio Incremental Link without manifests\n";
- }
- }
- return cmake::VisualStudioLinkNonIncremental(expandedArgs,
- type, hasManifest, verbose);
-}
-
-int cmake::ParseVisualStudioLinkCommand(std::vector<std::string>& args,
- std::vector<cmStdString>& command,
- std::string& targetName)
-{
- std::vector<std::string>::iterator i = args.begin();
- i++; // skip -E
- i++; // skip vs_link_dll or vs_link_exe
- command.push_back(*i);
- i++; // move past link command
- for(; i != args.end(); ++i)
- {
- command.push_back(*i);
- if(i->find("/Fe") == 0)
- {
- targetName = i->substr(3);
- }
- if(i->find("/out:") == 0)
- {
- targetName = i->substr(5);
- }
- }
- if(targetName.size() == 0 || command.size() == 0)
- {
- return -1;
- }
- return 0;
-}
-
-bool cmake::RunCommand(const char* comment,
- std::vector<cmStdString>& command,
- bool verbose,
- int* retCodeOut)
-{
- if(verbose)
- {
- std::cout << comment << ":\n";
- for(std::vector<cmStdString>::iterator i = command.begin();
- i != command.end(); ++i)
- {
- std::cout << i->c_str() << " ";
- }
- std::cout << "\n";
- }
- std::string output;
- int retCode =0;
- // use rc command to create .res file
- cmSystemTools::RunSingleCommand(command,
- &output,
- &retCode, 0, 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") == output.npos
- || retCode !=0)
- {
- std::cout << output;
- }
- // if retCodeOut is requested then always return true
- // and set the retCodeOut to retCode
- if(retCodeOut)
- {
- *retCodeOut = retCode;
- return true;
- }
- if(retCode != 0)
- {
- std::cout << comment << " failed. with " << retCode << "\n";
- }
- return retCode == 0;
-}
-
-int cmake::VisualStudioLinkIncremental(std::vector<std::string>& args,
- int type, bool verbose)
+void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
+ cmListFileBacktrace const& backtrace) const
{
- // This follows the steps listed here:
- // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
-
- // 1. Compiler compiles the application and generates the *.obj files.
- // 2. An empty manifest file is generated if this is a clean build and if
- // not the previous one is reused.
- // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
- // *.res file.
- // 4. Linker generates the binary (EXE or DLL) with the /incremental
- // switch and embeds the dummy manifest file. The linker also generates
- // the real manifest file based on the binaries that your binary depends
- // on.
- // 5. The manifest tool (mt.exe) is then used to generate the final
- // manifest.
-
- // If the final manifest is changed, then 6 and 7 are run, if not
- // they are skipped, and it is done.
-
- // 6. The resource compiler is invoked one more time.
- // 7. Finally, the Linker does another incremental link, but since the
- // only thing that has changed is the *.res file that contains the
- // manifest it is a short link.
- std::vector<cmStdString> linkCommand;
- std::string targetName;
- if(cmake::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
- {
- return -1;
- }
- std::string manifestArg = "/MANIFESTFILE:";
- std::vector<cmStdString> rcCommand;
- rcCommand.push_back(cmSystemTools::FindProgram("rc.exe"));
- std::vector<cmStdString> mtCommand;
- mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
- std::string tempManifest;
- tempManifest = targetName;
- tempManifest += ".intermediate.manifest";
- std::string resourceInputFile = targetName;
- resourceInputFile += ".resource.txt";
- if(verbose)
- {
- std::cout << "Create " << resourceInputFile.c_str() << "\n";
- }
- // Create input file for rc command
- std::ofstream fout(resourceInputFile.c_str());
- if(!fout)
- {
- return -1;
- }
- std::string manifestFile = targetName;
- manifestFile += ".embed.manifest";
- std::string fullPath= cmSystemTools::CollapseFullPath(manifestFile.c_str());
- fout << type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
- "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath.c_str() << "\"";
- fout.close();
- manifestArg += tempManifest;
- // add the manifest arg to the linkCommand
- linkCommand.push_back("/MANIFEST");
- linkCommand.push_back(manifestArg);
- // if manifestFile is not yet created, create an
- // empty one
- if(!cmSystemTools::FileExists(manifestFile.c_str()))
- {
- if(verbose)
- {
- std::cout << "Create empty: " << manifestFile.c_str() << "\n";
- }
- std::ofstream foutTmp(manifestFile.c_str());
- }
- std::string resourceFile = manifestFile;
- resourceFile += ".res";
- // add the resource file to the end of the link command
- linkCommand.push_back(resourceFile);
- std::string outputOpt = "/fo";
- outputOpt += resourceFile;
- rcCommand.push_back(outputOpt);
- rcCommand.push_back(resourceInputFile);
- // Run rc command to create resource
- if(!cmake::RunCommand("RC Pass 1", rcCommand, verbose))
- {
- return -1;
- }
- // Now run the link command to link and create manifest
- if(!cmake::RunCommand("LINK Pass 1", linkCommand, verbose))
- {
- return -1;
- }
- // create mt command
- std::string outArg("/out:");
- outArg+= manifestFile;
- mtCommand.push_back("/nologo");
- mtCommand.push_back(outArg);
- mtCommand.push_back("/notify_update");
- mtCommand.push_back("/manifest");
- mtCommand.push_back(tempManifest);
- // now run mt.exe to create the final manifest file
- int mtRet =0;
- cmake::RunCommand("MT", mtCommand, verbose, &mtRet);
- // if mt returns 0, then the manifest was not changed and
- // we do not need to do another link step
- if(mtRet == 0)
- {
- return 0;
- }
- // check for magic mt return value if mt returns the magic number
- // 1090650113 then it means that it updated the manifest file and we need
- // to do the final link. If mt has any value other than 0 or 1090650113
- // then there was some problem with the command itself and there was an
- // error so return the error code back out of cmake so make can report it.
- if(mtRet != 1090650113)
- {
- return mtRet;
- }
- // update the resource file with the new manifest from the mt command.
- if(!cmake::RunCommand("RC Pass 2", rcCommand, verbose))
- {
- return -1;
- }
- // Run the final incremental link that will put the new manifest resource
- // into the file incrementally.
- if(!cmake::RunCommand("FINAL LINK", linkCommand, verbose))
- {
- return -1;
- }
- return 0;
+ this->Messenger->IssueMessage(t, text, backtrace);
}
-int cmake::VisualStudioLinkNonIncremental(std::vector<std::string>& args,
- int type,
- bool hasManifest,
- bool verbose)
+std::vector<std::string> cmake::GetDebugConfigs()
{
- std::vector<cmStdString> linkCommand;
- std::string targetName;
- if(cmake::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
- {
- return -1;
- }
- // Run the link command as given
- if (hasManifest)
- {
- linkCommand.push_back("/MANIFEST");
- }
- if(!cmake::RunCommand("LINK", linkCommand, verbose))
- {
- return -1;
- }
- if(!hasManifest)
- {
- return 0;
- }
- std::vector<cmStdString> mtCommand;
- mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
- mtCommand.push_back("/nologo");
- mtCommand.push_back("/manifest");
- std::string manifestFile = targetName;
- manifestFile += ".manifest";
- mtCommand.push_back(manifestFile);
- std::string outresource = "/outputresource:";
- outresource += targetName;
- outresource += ";#";
- if(type == 1)
- {
- outresource += "1";
- }
- else if(type == 2)
- {
- outresource += "2";
- }
- mtCommand.push_back(outresource);
- // Now use the mt tool to embed the manifest into the exe or dll
- if(!cmake::RunCommand("MT", mtCommand, verbose))
- {
- return -1;
- }
- return 0;
-}
-
-//----------------------------------------------------------------------------
-void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
- cmListFileBacktrace const& backtrace)
-{
- cmOStringStream msg;
- bool isError = false;
- // Construct the message header.
- if(t == cmake::FATAL_ERROR)
- {
- isError = true;
- msg << "CMake Error";
- }
- else if(t == cmake::INTERNAL_ERROR)
- {
- isError = true;
- msg << "CMake Internal Error (please report a bug)";
- }
- else if(t == cmake::LOG)
- {
- msg << "CMake Debug Log";
- }
- else
- {
- msg << "CMake Warning";
- if(t == cmake::AUTHOR_WARNING)
- {
- // Allow suppression of these warnings.
- cmCacheManager::CacheIterator it = this->CacheManager
- ->GetCacheIterator("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
- if(!it.IsAtEnd() && it.GetValueAsBool())
- {
- return;
- }
- msg << " (dev)";
- }
- }
-
- // Add the immediate context.
- cmListFileBacktrace::const_iterator i = backtrace.begin();
- if(i != backtrace.end())
- {
- cmListFileContext const& lfc = *i;
- msg << (lfc.Line? " at ": " in ") << lfc;
- ++i;
- }
-
- // Add the message text.
- {
- msg << ":\n";
- cmDocumentationFormatterText formatter;
- formatter.SetIndent(" ");
- formatter.PrintFormatted(msg, text.c_str());
- }
-
- // Add the rest of the context.
- if(i != backtrace.end())
- {
- msg << "Call Stack (most recent call first):\n";
- while(i != backtrace.end())
- {
- cmListFileContext const& lfc = *i;
- msg << " " << lfc << "\n";
- ++i;
- }
- }
-
- // Add a note about warning suppression.
- if(t == cmake::AUTHOR_WARNING)
- {
- msg <<
- "This warning is for project developers. Use -Wno-dev to suppress it.";
- }
-
- // Add a terminating blank line.
- msg << "\n";
-
- // Output the message.
- if(isError)
- {
- cmSystemTools::SetErrorOccured();
- cmSystemTools::Message(msg.str().c_str(), "Error");
- }
- else
- {
- cmSystemTools::Message(msg.str().c_str(), "Warning");
- }
+ std::vector<std::string> configs;
+ if (const char* config_list =
+ this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) {
+ // Expand the specified list and convert to upper-case.
+ cmSystemTools::ExpandListArgument(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");
+ }
+ return configs;
}
-//----------------------------------------------------------------------------
-std::vector<std::string> const& cmake::GetDebugConfigs()
+cmMessenger* cmake::GetMessenger() const
{
- // Compute on-demand.
- if(this->DebugConfigs.empty())
- {
- if(const char* config_list = this->GetProperty("DEBUG_CONFIGURATIONS"))
- {
- // Expand the specified list and convert to upper-case.
- cmSystemTools::ExpandListArgument(config_list, this->DebugConfigs);
- for(std::vector<std::string>::iterator i = this->DebugConfigs.begin();
- i != this->DebugConfigs.end(); ++i)
- {
- *i = cmSystemTools::UpperCase(*i);
- }
- }
- // If no configurations were specified, use a default list.
- if(this->DebugConfigs.empty())
- {
- this->DebugConfigs.push_back("DEBUG");
- }
- }
- return this->DebugConfigs;
+ return this->Messenger;
}
-
-int cmake::Build(const std::string& dir,
- const std::string& target,
+int cmake::Build(const std::string& dir, const std::string& target,
const std::string& config,
- const std::vector<std::string>& nativeOptions,
- bool clean,
- cmSystemTools::OutputOption outputflag)
+ const std::vector<std::string>& nativeOptions, bool clean)
{
- if(!cmSystemTools::FileIsDirectory(dir.c_str()))
- {
+
+ this->SetHomeDirectory("");
+ this->SetHomeOutputDirectory("");
+ if (!cmSystemTools::FileIsDirectory(dir)) {
std::cerr << "Error: " << dir << " is not a directory\n";
return 1;
- }
- std::string cachePath = dir;
- cmSystemTools::ConvertToUnixSlashes(cachePath);
- cmCacheManager* cachem = this->GetCacheManager();
- cmCacheManager::CacheIterator it = cachem->NewIterator();
- if(!cachem->LoadCache(cachePath.c_str()))
- {
+ }
+
+ std::string cachePath = FindCacheFile(dir);
+ if (!this->LoadCache(cachePath)) {
std::cerr << "Error: could not load cache\n";
return 1;
- }
- if(!it.Find("CMAKE_GENERATOR"))
- {
- std::cerr << "Error: could find generator in Cache\n";
+ }
+ const char* cachedGenerator =
+ this->State->GetCacheEntryValue("CMAKE_GENERATOR");
+ if (!cachedGenerator) {
+ std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
- }
- cmsys::auto_ptr<cmGlobalGenerator> gen(
- this->CreateGlobalGenerator(it.GetValue()));
+ }
+ CM_AUTO_PTR<cmGlobalGenerator> gen(
+ this->CreateGlobalGenerator(cachedGenerator));
+ if (!gen.get()) {
+ std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator
+ << "\"\n";
+ return 1;
+ }
std::string output;
std::string projName;
- std::string makeProgram;
- if(!it.Find("CMAKE_PROJECT_NAME"))
- {
+ const char* cachedProjectName =
+ this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
+ if (!cachedProjectName) {
std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
return 1;
+ }
+ projName = cachedProjectName;
+ bool verbose = false;
+ const char* cachedVerbose =
+ this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE");
+ if (cachedVerbose) {
+ verbose = cmSystemTools::IsOn(cachedVerbose);
+ }
+
+#ifdef CMAKE_HAVE_VS_GENERATORS
+ // For VS generators, explicitly check if regeneration is necessary before
+ // 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();
+
+ // 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());
+
+ this->AddScriptingCommands();
+ this->AddProjectCommands();
+
+ int ret = this->Configure();
+ if (ret) {
+ cmSystemTools::Message("CMake Configure step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
}
- projName = it.GetValue();
- if(!it.Find("CMAKE_MAKE_PROGRAM"))
- {
- std::cerr << "Error: could not find CMAKE_MAKE_PROGRAM in Cache\n";
- return 1;
+ ret = this->Generate();
+ if (ret) {
+ cmSystemTools::Message("CMake Generate step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
}
- makeProgram = it.GetValue();
- return gen->Build(0, dir.c_str(),
- projName.c_str(), target.c_str(),
- &output,
- makeProgram.c_str(),
- config.c_str(), clean, false, 0, outputflag,
- 0, nativeOptions);
+ 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);
+ }
+#endif
+
+ return gen->Build("", dir, projName, target, output, "", config, clean,
+ false, verbose, 0, cmSystemTools::OUTPUT_PASSTHROUGH,
+ nativeOptions);
}
-void cmake::WatchUnusedCli(const char* var)
+void cmake::WatchUnusedCli(const std::string& var)
{
#ifdef CMAKE_BUILD_WITH_CMAKE
this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this);
- if(this->UsedCliVariables.find(var) == this->UsedCliVariables.end())
- {
+ if (this->UsedCliVariables.find(var) == this->UsedCliVariables.end()) {
this->UsedCliVariables[var] = false;
- }
+ }
#endif
}
-void cmake::UnwatchUnusedCli(const char* var)
+void cmake::UnwatchUnusedCli(const std::string& var)
{
#ifdef CMAKE_BUILD_WITH_CMAKE
this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning);
@@ -4656,21 +2477,114 @@ void cmake::RunCheckForUnusedVariables()
{
#ifdef CMAKE_BUILD_WITH_CMAKE
bool haveUnused = false;
- cmOStringStream msg;
+ std::ostringstream msg;
msg << "Manually-specified variables were not used by the project:";
- for(std::map<cmStdString, bool>::const_iterator
- it = this->UsedCliVariables.begin();
- it != this->UsedCliVariables.end(); ++it)
- {
- if(!it->second)
- {
+ for (std::map<std::string, bool>::const_iterator it =
+ this->UsedCliVariables.begin();
+ it != this->UsedCliVariables.end(); ++it) {
+ if (!it->second) {
haveUnused = true;
msg << "\n " << it->first;
- }
- }
- if(haveUnused)
- {
- this->IssueMessage(cmake::WARNING, msg.str(), cmListFileBacktrace());
}
+ }
+ if (haveUnused) {
+ this->IssueMessage(cmake::WARNING, msg.str());
+ }
#endif
}
+
+bool cmake::GetSuppressDevWarnings() const
+{
+ return this->Messenger->GetSuppressDevWarnings();
+}
+
+void cmake::SetSuppressDevWarnings(bool b)
+{
+ std::string value;
+
+ // equivalent to -Wno-dev
+ if (b) {
+ value = "TRUE";
+ }
+ // equivalent to -Wdev
+ else {
+ value = "FALSE";
+ }
+
+ this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value.c_str(),
+ "Suppress Warnings that are meant for"
+ " the author of the CMakeLists.txt files.",
+ cmStateEnums::INTERNAL);
+}
+
+bool cmake::GetSuppressDeprecatedWarnings() const
+{
+ return this->Messenger->GetSuppressDeprecatedWarnings();
+}
+
+void cmake::SetSuppressDeprecatedWarnings(bool b)
+{
+ std::string value;
+
+ // equivalent to -Wno-deprecated
+ if (b) {
+ value = "FALSE";
+ }
+ // equivalent to -Wdeprecated
+ else {
+ value = "TRUE";
+ }
+
+ this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value.c_str(),
+ "Whether to issue warnings for deprecated "
+ "functionality.",
+ cmStateEnums::INTERNAL);
+}
+
+bool cmake::GetDevWarningsAsErrors() const
+{
+ return this->Messenger->GetDevWarningsAsErrors();
+}
+
+void cmake::SetDevWarningsAsErrors(bool b)
+{
+ std::string value;
+
+ // equivalent to -Werror=dev
+ if (b) {
+ value = "FALSE";
+ }
+ // equivalent to -Wno-error=dev
+ else {
+ value = "TRUE";
+ }
+
+ this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value.c_str(),
+ "Suppress errors that are meant for"
+ " the author of the CMakeLists.txt files.",
+ cmStateEnums::INTERNAL);
+}
+
+bool cmake::GetDeprecatedWarningsAsErrors() const
+{
+ return this->Messenger->GetDeprecatedWarningsAsErrors();
+}
+
+void cmake::SetDeprecatedWarningsAsErrors(bool b)
+{
+ std::string value;
+
+ // equivalent to -Werror=deprecated
+ if (b) {
+ value = "TRUE";
+ }
+ // equivalent to -Wno-error=deprecated
+ else {
+ value = "FALSE";
+ }
+
+ this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value.c_str(),
+ "Whether to issue deprecation errors for macros"
+ " and functions.",
+ cmStateEnums::INTERNAL);
+}
diff --git a/Source/cmake.h b/Source/cmake.h
index a50c1ed02..4ddacf701 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -1,36 +1,33 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmake_h
+#define cmake_h
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h"
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
-#ifndef cmake_h
-#define cmake_h
+#include "cmInstalledFile.h"
+#include "cmListFileCache.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
-#include "cmSystemTools.h"
-#include "cmPropertyDefinitionMap.h"
-#include "cmPropertyMap.h"
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cm_jsoncpp_value.h"
+#endif
-class cmGlobalGeneratorFactory;
+class cmExternalMakefileProjectGeneratorFactory;
+class cmFileTimeComparison;
class cmGlobalGenerator;
-class cmLocalGenerator;
-class cmCacheManager;
+class cmGlobalGeneratorFactory;
class cmMakefile;
-class cmCommand;
+class cmMessenger;
+class cmState;
class cmVariableWatch;
-class cmFileTimeComparison;
-class cmExternalMakefileProjectGenerator;
-class cmDocumentationSection;
-class cmPolicies;
-class cmListFileBacktrace;
-class cmTarget;
-class cmGeneratedFileStream;
+struct cmDocumentationEntry;
/** \brief Represents a cmake invocation.
*
@@ -41,7 +38,7 @@ class cmGeneratedFileStream;
* The basic process for a GUI is as follows:
*
* -# Create a cmake instance
- * -# Set the Home & Start directories, generator, and cmake command. this
+ * -# Set the Home directories, generator, and cmake command. this
* can be done using the Set methods or by using SetArgs and passing in
* command line arguments.
* -# Load the cache by calling LoadCache (duh)
@@ -52,33 +49,52 @@ class cmGeneratedFileStream;
* -# Let the user change values and go back to step 5
* -# call Generate
- * If your GUI allows the user to change the start & home directories then
+ * If your GUI allows the user to change the home directories then
* you must at a minimum redo steps 2 through 7.
*/
class cmake
{
- public:
+ CM_DISABLE_COPY(cmake)
+
+public:
+ enum Role
+ {
+ RoleInternal, // no commands
+ RoleScript, // script commands
+ RoleProject // all commands
+ };
+
enum MessageType
- { AUTHOR_WARNING,
+ {
+ AUTHOR_WARNING,
+ AUTHOR_ERROR,
FATAL_ERROR,
INTERNAL_ERROR,
MESSAGE,
WARNING,
- LOG
+ LOG,
+ DEPRECATION_ERROR,
+ DEPRECATION_WARNING
};
+ enum DiagLevel
+ {
+ DIAG_IGNORE,
+ DIAG_WARN,
+ DIAG_ERROR
+ };
/** \brief Describes the working modes of cmake */
enum WorkingMode
{
NORMAL_MODE, ///< Cmake runs to create project files
- /** \brief Script mode (started by using -P).
- *
- * In script mode there is no generator and no cache. Also,
- * languages are not enabled, so add_executable and things do
- * nothing.
- */
+ /** \brief Script mode (started by using -P).
+ *
+ * In script mode there is no generator and no cache. Also,
+ * languages are not enabled, so add_executable and things do
+ * nothing.
+ */
SCRIPT_MODE,
/** \brief A pkg-config like mode
*
@@ -89,71 +105,55 @@ class cmake
*/
FIND_PACKAGE_MODE
};
- typedef std::map<cmStdString, cmCommand*> RegisteredCommandsMap;
+
+ struct GeneratorInfo
+ {
+ std::string name;
+ std::string baseName;
+ std::string extraName;
+ bool supportsToolset;
+ bool supportsPlatform;
+ bool isAlias;
+ };
+
+ typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
/// Default constructor
- cmake();
+ cmake(Role role);
/// Destructor
~cmake();
- static const char *GetCMakeFilesDirectory() {return "/CMakeFiles";};
- static const char *GetCMakeFilesDirectoryPostSlash() {
- return "CMakeFiles/";};
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ Json::Value ReportCapabilitiesJson(bool haveServerMode) const;
+#endif
+ std::string ReportCapabilities(bool haveServerMode) const;
+
+ static const char* GetCMakeFilesDirectory() { return "/CMakeFiles"; }
+ static const char* GetCMakeFilesDirectoryPostSlash()
+ {
+ return "CMakeFiles/";
+ }
//@{
/**
* Set/Get the home directory (or output directory) in the project. The
* home directory is the top directory of the project. It is the
- * path-to-source cmake was run with. Remember that CMake processes
- * CMakeLists files by recursing up the tree starting at the StartDirectory
- * and going up until it reaches the HomeDirectory.
+ * path-to-source cmake was run with.
*/
- void SetHomeDirectory(const char* dir);
- const char* GetHomeDirectory() const
- {
- return this->cmHomeDirectory.c_str();
- }
- void SetHomeOutputDirectory(const char* lib);
- const char* GetHomeOutputDirectory() const
- {
- return this->HomeOutputDirectory.c_str();
- }
- //@}
-
- //@{
- /**
- * Set/Get the start directory (or output directory). The start directory
- * is the directory of the CMakeLists.txt file that started the current
- * round of processing. Remember that CMake processes CMakeLists files by
- * recursing up the tree starting at the StartDirectory and going up until
- * it reaches the HomeDirectory.
- */
- void SetStartDirectory(const char* dir)
- {
- this->cmStartDirectory = dir;
- cmSystemTools::ConvertToUnixSlashes(this->cmStartDirectory);
- }
- const char* GetStartDirectory() const
- {
- return this->cmStartDirectory.c_str();
- }
- void SetStartOutputDirectory(const char* lib)
- {
- this->StartOutputDirectory = lib;
- cmSystemTools::ConvertToUnixSlashes(this->StartOutputDirectory);
- }
- const char* GetStartOutputDirectory() const
- {
- return this->StartOutputDirectory.c_str();
- }
+ void SetHomeDirectory(const std::string& dir);
+ const char* GetHomeDirectory() const;
+ void SetHomeOutputDirectory(const std::string& dir);
+ const char* GetHomeOutputDirectory() const;
//@}
/**
* Handle a command line invocation of cmake.
*/
- int Run(const std::vector<std::string>&args)
- { return this->Run(args, false); }
- int Run(const std::vector<std::string>&args, bool noconfigure);
+ int Run(const std::vector<std::string>& args)
+ {
+ return this->Run(args, false);
+ }
+ int Run(const std::vector<std::string>& args, bool noconfigure);
/**
* Run the global generator Generate step.
@@ -169,91 +169,98 @@ class cmake
int Configure();
int ActualConfigure();
+ ///! 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);
+
int LoadCache();
+ bool LoadCache(const std::string& path);
+ bool LoadCache(const std::string& path, bool internal,
+ std::set<std::string>& excludes,
+ std::set<std::string>& includes);
+ bool SaveCache(const std::string& path);
+ bool DeleteCache(const std::string& path);
void PreLoadCMakeFiles();
///! Create a GlobalGenerator
- cmGlobalGenerator* CreateGlobalGenerator(const char* name);
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name);
///! Return the global generator assigned to this instance of cmake
- cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
+ cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
///! Return the global generator assigned to this instance of cmake, const
const cmGlobalGenerator* GetGlobalGenerator() const
- { return this->GlobalGenerator; }
+ {
+ return this->GlobalGenerator;
+ }
+
+ ///! 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
- void SetGlobalGenerator(cmGlobalGenerator *);
+ void SetGlobalGenerator(cmGlobalGenerator*);
///! Get the names of the current registered generators
- void GetRegisteredGenerators(std::vector<std::string>& names);
+ void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const;
+
+ ///! Set the name of the selected generator-specific platform.
+ void SetGeneratorPlatform(std::string const& ts)
+ {
+ this->GeneratorPlatform = ts;
+ }
+
+ ///! Get the name of the selected generator-specific platform.
+ std::string const& GetGeneratorPlatform() const
+ {
+ return this->GeneratorPlatform;
+ }
///! Set the name of the selected generator-specific toolset.
void SetGeneratorToolset(std::string const& ts)
- { this->GeneratorToolset = ts; }
+ {
+ this->GeneratorToolset = ts;
+ }
///! Get the name of the selected generator-specific toolset.
std::string const& GetGeneratorToolset() const
- { return this->GeneratorToolset; }
-
- ///! get the cmCachemManager used by this invocation of cmake
- cmCacheManager *GetCacheManager() { return this->CacheManager; }
+ {
+ return this->GeneratorToolset;
+ }
- ///! set the cmake command this instance of cmake should use
- void SetCMakeCommand(const char* cmd) { this->CMakeCommand = cmd; }
+ const std::vector<std::string>& GetSourceExtensions() const
+ {
+ return this->SourceFileExtensions;
+ }
+ const std::vector<std::string>& GetHeaderExtensions() const
+ {
+ return this->HeaderFileExtensions;
+ }
/**
* Given a variable name, return its value (as a string).
*/
- const char* GetCacheDefinition(const char*) const;
+ const char* GetCacheDefinition(const std::string&) const;
///! Add an entry into the cache
- void AddCacheEntry(const char* key, const char* value,
- const char* helpString,
- int type);
- /**
- * Execute commands during the build process. Supports options such
- * as echo, remove file etc.
- */
- static int ExecuteCMakeCommand(std::vector<std::string>&);
+ void AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString, int type);
/**
* Get the system information and write it to the file specified
*/
int GetSystemInformation(std::vector<std::string>&);
- /**
- * Add a command to this cmake instance
- */
- void AddCommand(cmCommand* );
- void RenameCommand(const char* oldName, const char* newName);
- void RemoveCommand(const char* name);
- void RemoveUnscriptableCommands();
-
- /**
- * Get a command by its name
- */
- cmCommand *GetCommand(const char *name);
-
- /** Get list of all commands */
- RegisteredCommandsMap* GetCommands() { return &this->Commands; }
-
- /** Check if a command exists. */
- bool CommandExists(const char* name) const;
-
///! Parse command line arguments
void SetArgs(const std::vector<std::string>&,
bool directoriesSetBefore = false);
///! Is this cmake running as a result of a TRY_COMPILE command
- bool GetIsInTryCompile() { return this->InTryCompile; }
-
- ///! Is this cmake running as a result of a TRY_COMPILE command
- void SetIsInTryCompile(bool i) { this->InTryCompile = i; }
+ bool GetIsInTryCompile() const;
+ void SetIsInTryCompile(bool b);
///! 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 *);
+ typedef void (*ProgressCallbackType)(const char* msg, float progress, void*);
/**
* Set the function used by GUIs to receive progress updates
* Function gets passed: message as a const char*, a progress
@@ -261,41 +268,34 @@ class cmake
* number provided may be negative in cases where a message is
* to be displayed without any progress percentage.
*/
- void SetProgressCallback(ProgressCallbackType f, void* clientData=0);
+ void SetProgressCallback(ProgressCallbackType f,
+ void* clientData = CM_NULLPTR);
///! this is called by generators to update the progress
- void UpdateProgress(const char *msg, float prog);
-
- ///! get the cmake policies instance
- cmPolicies *GetPolicies() {return this->Policies;} ;
+ void UpdateProgress(const char* msg, float prog);
///! Get the variable watch object
cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
- /** Get the documentation entries for the supported commands.
- * If withCurrentCommands is true, the documentation for the
- * recommended set of commands is included.
- * If withCompatCommands is true, the documentation for discouraged
- * (compatibility) commands is included.
- * You probably don't want to set both to false.
- */
- void GetCommandDocumentation(std::vector<cmDocumentationEntry>& entries,
- bool withCurrentCommands = true,
- bool withCompatCommands = true) const;
- void GetPropertiesDocumentation(std::map<std::string,
- cmDocumentationSection *>&);
void GetGeneratorDocumentation(std::vector<cmDocumentationEntry>&);
- void GetPolicyDocumentation(std::vector<cmDocumentationEntry>& entries);
///! Set/Get a property of this target file
- void SetProperty(const char *prop, const char *value);
- void AppendProperty(const char *prop, const char *value,bool asString=false);
- const char *GetProperty(const char *prop);
- const char *GetProperty(const char *prop, cmProperty::ScopeType scope);
- bool GetPropertyAsBool(const char *prop);
+ 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
+ cmInstalledFile* GetOrCreateInstalledFile(cmMakefile* mf,
+ const std::string& name);
+
+ cmInstalledFile const* GetInstalledFile(const std::string& name) const;
- // Get the properties
- cmPropertyMap &GetProperties() { return this->Properties; };
+ InstalledFilesMap const& GetInstalledFiles() const
+ {
+ return this->InstalledFiles;
+ }
///! Do all the checks before running configure
int DoPreConfigureChecks();
@@ -304,8 +304,8 @@ class cmake
WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
///! Debug the try compile stuff by not deleting the files
- bool GetDebugTryCompile(){return this->DebugTryCompile;}
- void DebugTryCompileOn(){this->DebugTryCompile = true;}
+ bool GetDebugTryCompile() { return this->DebugTryCompile; }
+ void DebugTryCompileOn() { this->DebugTryCompile = true; }
/**
* Generate CMAKE_ROOT and CMAKE_COMMAND cache entries
@@ -317,119 +317,135 @@ class cmake
*/
cmFileTimeComparison* GetFileComparison() { return this->FileComparison; }
- /**
- * Get the path to ctest
- */
- const char* GetCTestCommand();
- const char* GetCPackCommand();
- const char* GetCMakeCommand();
-
// Do we want debug output during the cmake run.
bool GetDebugOutput() { return this->DebugOutput; }
- void SetDebugOutputOn(bool b) { this->DebugOutput = b;}
+ void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
// Do we want trace output during the cmake run.
- bool GetTrace() { return this->Trace;}
- void SetTrace(bool b) { this->Trace = b;}
- bool GetWarnUninitialized() { return this->WarnUninitialized;}
- void SetWarnUninitialized(bool b) { this->WarnUninitialized = b;}
- bool GetWarnUnused() { return this->WarnUnused;}
- void SetWarnUnused(bool b) { this->WarnUnused = b;}
- bool GetWarnUnusedCli() { return this->WarnUnusedCli;}
- void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b;}
- bool GetCheckSystemVars() { return this->CheckSystemVars;}
- void SetCheckSystemVars(bool b) { this->CheckSystemVars = b;}
+ bool GetTrace() { return this->Trace; }
+ void SetTrace(bool b) { this->Trace = b; }
+ bool GetTraceExpand() { return this->TraceExpand; }
+ void SetTraceExpand(bool b) { this->TraceExpand = b; }
+ void AddTraceSource(std::string const& file)
+ {
+ this->TraceOnlyThisSources.push_back(file);
+ }
+ std::vector<std::string> const& GetTraceSources() const
+ {
+ return this->TraceOnlyThisSources;
+ }
+ bool GetWarnUninitialized() { return this->WarnUninitialized; }
+ void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
+ bool GetWarnUnused() { return this->WarnUnused; }
+ void SetWarnUnused(bool b) { this->WarnUnused = b; }
+ bool GetWarnUnusedCli() { return this->WarnUnusedCli; }
+ void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }
+ bool GetCheckSystemVars() { return this->CheckSystemVars; }
+ void SetCheckSystemVars(bool b) { this->CheckSystemVars = b; }
void MarkCliAsUsed(const std::string& variable);
- // Define a property
- void DefineProperty(const char *name, cmProperty::ScopeType scope,
- const char *ShortDescription,
- const char *FullDescription,
- bool chain = false,
- const char *variableGroup = 0);
-
- bool GetIsPropertyDefined(const char *name, cmProperty::ScopeType scope);
+ /** Get the list of configurations (in upper case) considered to be
+ debugging configurations.*/
+ std::vector<std::string> GetDebugConfigs();
- // get property definition
- cmPropertyDefinition *GetPropertyDefinition
- (const char *name, cmProperty::ScopeType scope);
+ void SetCMakeEditCommand(std::string const& s)
+ {
+ this->CMakeEditCommand = s;
+ }
+ std::string const& GetCMakeEditCommand() const
+ {
+ return this->CMakeEditCommand;
+ }
- // Is a property defined?
- bool IsPropertyDefined(const char *name, cmProperty::ScopeType scope);
- bool IsPropertyChained(const char *name, cmProperty::ScopeType scope);
+ cmMessenger* GetMessenger() const;
- /** Get the list of configurations (in upper case) considered to be
- debugging configurations.*/
- std::vector<std::string> const& GetDebugConfigs();
+ /*
+ * 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);
- // record accesses of properties and variables
- void RecordPropertyAccess(const char *name, cmProperty::ScopeType scope);
- void ReportUndefinedPropertyAccesses(const char *filename);
+ /*
+ * 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);
- // Define the properties
- static void DefineProperties(cmake *cm);
+ /*
+ * Get the state of treating developer (author) warnings as errors.
+ * Returns false, by default, if warnings should not be treated as errors,
+ * true otherwise.
+ */
+ bool GetDevWarningsAsErrors() const;
+ /**
+ * Set the state of treating developer (author) warnings as errors.
+ */
+ void SetDevWarningsAsErrors(bool v);
- void SetCMakeEditCommand(const char* s)
- {
- this->CMakeEditCommand = s;
- }
- void SetSuppressDevWarnings(bool v)
- {
- this->SuppressDevWarnings = v;
- this->DoSuppressDevWarnings = true;
- }
+ /*
+ * Get the state of treating deprecated warnings as errors.
+ * Returns false, by default, if warnings should not be treated as errors,
+ * true otherwise.
+ */
+ bool GetDeprecatedWarningsAsErrors() const;
+ /**
+ * Set the state of treating developer (author) warnings as errors.
+ */
+ void SetDeprecatedWarningsAsErrors(bool v);
/** Display a message to the user. */
- void IssueMessage(cmake::MessageType t, std::string const& text,
- cmListFileBacktrace const& backtrace);
+ void IssueMessage(
+ cmake::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,
+ int Build(const std::string& dir, const std::string& target,
const std::string& config,
- const std::vector<std::string>& nativeOptions,
- bool clean,
- cmSystemTools::OutputOption outputflag);
+ const std::vector<std::string>& nativeOptions, bool clean);
+
+ void UnwatchUnusedCli(const std::string& var);
+ void WatchUnusedCli(const std::string& var);
+
+ cmState* GetState() const { return this->State; }
+ void SetCurrentSnapshot(cmStateSnapshot const& snapshot)
+ {
+ this->CurrentSnapshot = snapshot;
+ }
+ cmStateSnapshot GetCurrentSnapshot() const { return this->CurrentSnapshot; }
- void UnwatchUnusedCli(const char* var);
- void WatchUnusedCli(const char* var);
protected:
void RunCheckForUnusedVariables();
void InitializeProperties();
- int HandleDeleteCacheVariables(const char* var);
- cmPropertyMap Properties;
- std::set<std::pair<cmStdString,cmProperty::ScopeType> > AccessedProperties;
+ int HandleDeleteCacheVariables(const std::string& var);
- std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>
- PropertyDefinitions;
-
- typedef
- cmExternalMakefileProjectGenerator* (*CreateExtraGeneratorFunctionType)();
- typedef std::map<cmStdString,
- CreateExtraGeneratorFunctionType> RegisteredExtraGeneratorsMap;
typedef std::vector<cmGlobalGeneratorFactory*> RegisteredGeneratorsVector;
- RegisteredCommandsMap Commands;
RegisteredGeneratorsVector Generators;
- RegisteredExtraGeneratorsMap ExtraGenerators;
- void AddDefaultCommands();
+ typedef std::vector<cmExternalMakefileProjectGeneratorFactory*>
+ RegisteredExtraGeneratorsVector;
+ RegisteredExtraGeneratorsVector ExtraGenerators;
+ void AddScriptingCommands();
+ void AddProjectCommands();
void AddDefaultGenerators();
void AddDefaultExtraGenerators();
- void AddExtraGenerator(const char* name,
- CreateExtraGeneratorFunctionType newFunction);
-
- cmPolicies *Policies;
- cmGlobalGenerator *GlobalGenerator;
- cmCacheManager *CacheManager;
- std::string cmHomeDirectory;
- std::string HomeOutputDirectory;
- std::string cmStartDirectory;
- std::string StartOutputDirectory;
- bool SuppressDevWarnings;
- bool DoSuppressDevWarnings;
+
+ cmGlobalGenerator* GlobalGenerator;
+ std::map<std::string, DiagLevel> DiagLevels;
+ std::string GeneratorPlatform;
std::string GeneratorToolset;
///! read in a cmake list file to initialize the cache
- void ReadListFile(const std::vector<std::string>& args, const char *path);
+ void ReadListFile(const std::vector<std::string>& args, const char* path);
bool FindPackage(const std::vector<std::string>& args);
///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file.
@@ -450,114 +466,154 @@ protected:
void GenerateGraphViz(const char* fileName) const;
- static int SymlinkLibrary(std::vector<std::string>& args);
- static int SymlinkExecutable(std::vector<std::string>& 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 WindowsCEEnvironment(const char* version,
- const std::string& name);
- static int VisualStudioLink(std::vector<std::string>& args, int type);
- static int VisualStudioLinkIncremental(std::vector<std::string>& args,
- int type,
- bool verbose);
- static int VisualStudioLinkNonIncremental(std::vector<std::string>& args,
- int type,
- bool hasManifest,
- bool verbose);
- static int ParseVisualStudioLinkCommand(std::vector<std::string>& args,
- std::vector<cmStdString>& command,
- std::string& targetName);
- static bool RunCommand(const char* comment,
- std::vector<cmStdString>& command,
- bool verbose,
- int* retCodeOut = 0);
cmVariableWatch* VariableWatch;
- ///! Find the full path to one of the cmake programs like ctest, cpack, etc.
- std::string FindCMakeProgram(const char* name) const;
private:
- cmake(const cmake&); // Not implemented.
- void operator=(const cmake&); // Not implemented.
ProgressCallbackType ProgressCallback;
void* ProgressCallbackClientData;
- bool Verbose;
bool InTryCompile;
WorkingMode CurrentWorkingMode;
bool DebugOutput;
bool Trace;
+ bool TraceExpand;
bool WarnUninitialized;
bool WarnUnused;
bool WarnUnusedCli;
bool CheckSystemVars;
- std::map<cmStdString, bool> UsedCliVariables;
+ std::map<std::string, bool> UsedCliVariables;
std::string CMakeEditCommand;
- std::string CMakeCommand;
std::string CXXEnvironment;
std::string CCEnvironment;
std::string CheckBuildSystemArgument;
std::string CheckStampFile;
std::string CheckStampList;
std::string VSSolutionFile;
- std::string CTestCommand;
- std::string CPackCommand;
+ std::vector<std::string> SourceFileExtensions;
+ std::vector<std::string> HeaderFileExtensions;
bool ClearBuildSystem;
bool DebugTryCompile;
cmFileTimeComparison* FileComparison;
std::string GraphVizFile;
- std::vector<std::string> DebugConfigs;
+ InstalledFilesMap InstalledFiles;
+
+ cmState* State;
+ cmStateSnapshot CurrentSnapshot;
+ cmMessenger* Messenger;
+
+ std::vector<std::string> TraceOnlyThisSources;
void UpdateConversionPathTable();
+
+ // Print a list of valid generators to stderr.
+ void PrintGeneratorList();
+
+ 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;
};
-#define CMAKE_STANDARD_OPTIONS_TABLE \
- {"-C <initial-cache>", "Pre-load a script to populate the cache.", \
- "When cmake is first run in an empty build tree, it creates a " \
- "CMakeCache.txt file and populates it with customizable settings " \
- "for the project. This option may be used to specify a file from " \
- "which to load cache entries before the first pass through " \
- "the project's cmake listfiles. The loaded entries take priority " \
- "over the project's default values. The given file should be a CMake " \
- "script containing SET commands that use the CACHE option, " \
- "not a cache-format file."}, \
- {"-D <var>:<type>=<value>", "Create a cmake cache entry.", \
- "When cmake is first run in an empty build tree, it creates a " \
- "CMakeCache.txt file and populates it with customizable settings " \
- "for the project. This option may be used to specify a setting " \
- "that takes priority over the project's default value. The option " \
- "may be repeated for as many cache entries as desired."}, \
- {"-U <globbing_expr>", "Remove matching entries from CMake cache.", \
- "This option may be used to remove one or more variables from the " \
- "CMakeCache.txt file, globbing expressions using * and ? are supported. "\
- "The option may be repeated for as many cache entries as desired.\n" \
- "Use with care, you can make your CMakeCache.txt non-working."}, \
- {"-G <generator-name>", "Specify a build system generator.", \
- "CMake may support multiple native build systems on certain platforms. " \
- "A generator is responsible for generating a particular build " \
- "system. Possible generator names are specified in the Generators " \
- "section."},\
- {"-T <toolset-name>", "Specify toolset name if supported by generator.", \
- "Some CMake generators support a toolset name to be given to the " \
- "native build system to choose a compiler. " \
- "This is supported only on specific generators:\n" \
- " Visual Studio >= 10\n" \
- " Xcode >= 3.0\n" \
- "See native build system documentation for allowed toolset names."}, \
- {"-Wno-dev", "Suppress developer warnings.",\
- "Suppress warnings that are meant for the author"\
- " of the CMakeLists.txt files."},\
- {"-Wdev", "Enable developer warnings.",\
- "Enable warnings that are meant for the author"\
- " of the CMakeLists.txt files."}
-
-
-#define CMAKE_STANDARD_INTRODUCTION \
- {0, \
- "CMake is a cross-platform build system generator. Projects " \
- "specify their build process with platform-independent CMake listfiles " \
- "included in each directory of a source tree with the name " \
- "CMakeLists.txt. " \
- "Users build a project by using CMake to generate a build system " \
- "for a native tool on their platform.", 0}
+#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." }, \
+ { "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
+ { "-G <generator-name>", "Specify a build system generator." }, \
+ { "-T <toolset-name>", \
+ "Specify toolset name if supported by generator." }, \
+ { "-A <platform-name>", \
+ "Specify platform name if supported by generator." }, \
+ { "-Wdev", "Enable developer warnings." }, \
+ { "-Wno-dev", "Suppress developer warnings." }, \
+ { "-Werror=dev", "Make developer warnings errors." }, \
+ { "-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." }, \
+ { \
+ "-Wno-error=deprecated", "Make deprecated macro and function warnings " \
+ "not errors." \
+ }
+
+#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)
+
+#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) \
+ 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) \
+ F(cxx_extern_templates) \
+ 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) \
+ F(cxx_nonstatic_member_init) \
+ F(cxx_nullptr) \
+ F(cxx_override) \
+ 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)
+
#endif
diff --git a/Source/cmake.version.manifest b/Source/cmake.version.manifest
new file mode 100644
index 000000000..e7010c972
--- /dev/null
+++ b/Source/cmake.version.manifest
@@ -0,0 +1,18 @@
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
+ manifestVersion="1.0"
+ xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 68d833964..da1fe6d64 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -1,579 +1,356 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-// include these first, otherwise there will be problems on Windows
-// with GetCurrentDirectory() being redefined
+/* 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 "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+#include "cmcmd.h"
+
#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmDynamicLoader.h"
#include "cmDocumentation.h"
+#include "cmDynamicLoader.h"
#endif
-#include "cmake.h"
-#include "cmCacheManager.h"
-#include "cmListFileCache.h"
-#include "cmakewizard.h"
-#include "cmSourceFile.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
+#include "cmsys/Encoding.hxx"
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmsys/ConsoleBuf.hxx"
+#endif
+#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[][3] =
-{
- {0,
- " cmake - Cross-Platform Makefile Generator.", 0},
- {0,0,0}
+static const char* cmDocumentationName[][2] = {
+ { CM_NULLPTR, " cmake - Cross-Platform Makefile Generator." },
+ { CM_NULLPTR, CM_NULLPTR }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationUsage[][3] =
-{
- {0,
- " cmake [options] <path-to-source>\n"
- " cmake [options] <path-to-existing-build>", 0},
- {0,0,0}
+static const char* cmDocumentationUsage[][2] = {
+ { CM_NULLPTR, " cmake [options] <path-to-source>\n"
+ " cmake [options] <path-to-existing-build>" },
+ { CM_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 }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationDescription[][3] =
-{
- {0,
- "The \"cmake\" executable is the CMake command-line interface. It may "
- "be used to configure projects in scripts. Project configuration "
- "settings "
- "may be specified on the command line with the -D option. The -i option "
- "will cause cmake to interactively prompt for such settings.", 0},
- CMAKE_STANDARD_INTRODUCTION,
- {0,0,0}
+static const char* cmDocumentationUsageNote[][2] = {
+ { CM_NULLPTR, "Run 'cmake --help' for more information." },
+ { CM_NULLPTR, CM_NULLPTR }
};
-#define CMAKE_BUILD_OPTIONS \
- " <dir> = Project binary directory to be built.\n" \
- " --target <tgt> = 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" \
- " --use-stderr = Don't merge stdout/stderr output and pass the\n" \
- " original stdout/stderr handles to the native\n" \
- " tool so it can use the capabilities of the\n" \
- " calling terminal (e.g. colored output).\n" \
+#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[][3] =
-{
+static const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
- {"-E", "CMake command mode.",
- "For true platform independence, CMake provides a list of commands "
- "that can be used on all systems. Run with -E help for the usage "
- "information. Commands available are: chdir, compare_files, copy, "
- "copy_directory, copy_if_different, echo, echo_append, environment, "
- "make_directory, md5sum, remove, remove_directory, rename, tar, time, "
- "touch, touch_nocreate. In addition, some platform specific commands "
- "are available. "
- "On Windows: comspec, delete_regv, write_regv. "
- "On UNIX: create_symlink."},
- {"-i", "Run in wizard mode.",
- "Wizard mode runs cmake interactively without a GUI. The user is "
- "prompted to answer questions about the project configuration. "
- "The answers are used to set cmake cache values."},
- {"-L[A][H]", "List non-advanced cached variables.",
- "List cache variables will run CMake and list all the variables from the "
- "CMake cache that are not marked as INTERNAL or ADVANCED. This will "
- "effectively display current CMake settings, which can then be changed "
- "with -D option. Changing some of the variables may result in more "
- "variables being created. If A is specified, then it will display also "
- "advanced variables. If H is specified, it will also display help for "
- "each variable."},
- {"--build <dir>", "Build a CMake-generated project binary tree.",
- "This abstracts a native build tool's command-line interface with the "
- "following options:\n"
- CMAKE_BUILD_OPTIONS
- "Run cmake --build with no options for quick help."},
- {"-N", "View mode only.",
- "Only load the cache. Do not actually run configure and generate steps."},
- {"-P <file>", "Process script mode.",
- "Process the given cmake file as a script written in the CMake language. "
- "No configure or generate step is performed and the cache is not"
- " modified. If variables are defined using -D, this must be done "
- "before the -P argument."},
- {"--find-package", "Run in pkg-config like mode.",
- "Search a package using find_package() and print the resulting flags "
- "to stdout. This can be used to use cmake instead of pkg-config to find "
- "installed libraries in plain Makefile-based projects or in "
- "autoconf-based projects (via share/aclocal/cmake.m4)."},
- {"--graphviz=[file]", "Generate graphviz of dependencies, see "
- "CMakeGraphVizOptions.cmake for more.",
- "Generate a graphviz input file that will contain all the library and "
- "executable dependencies in the project. See the documentation for "
- "CMakeGraphVizOptions.cmake for more details. "},
- {"--system-information [file]", "Dump information about this system.",
- "Dump a wide range of information about the current system. If run "
- "from the top of a binary tree for a CMake project it will dump "
- "additional information such as the cache, log files etc."},
- {"--debug-trycompile", "Do not delete the try_compile build tree. Only "
- "useful on one try_compile at a time.",
- "Do not delete the files and directories created for try_compile calls. "
- "This is useful in debugging failed try_compiles. It may however "
- "change the results of the try-compiles as old junk from a previous "
- "try-compile may cause a different test to either pass or fail "
- "incorrectly. This option is best used for one try-compile at a time, "
- "and only when debugging." },
- {"--debug-output", "Put cmake in a debug mode.",
- "Print extra stuff during the cmake run like stack traces with "
- "message(send_error ) calls."},
- {"--trace", "Put cmake in trace mode.",
- "Print a trace of all calls made and from where with "
- "message(send_error ) calls."},
- {"--warn-uninitialized", "Warn about uninitialized values.",
- "Print a warning when an uninitialized variable is used."},
- {"--warn-unused-vars", "Warn about unused variables.",
- "Find variables that are declared or set, but not used."},
- {"--no-warn-unused-cli", "Don't warn about command line options.",
- "Don't find variables that are declared on the command line, but not "
- "used."},
- {"--check-system-vars", "Find problems with variable usage in system "
- "files.", "Normally, unused and uninitialized variables are searched for "
- "only in CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR. This flag tells CMake to "
- "warn about other files as well."},
- {"--help-command cmd [file]", "Print help for a single command and exit.",
- "Full documentation specific to the given command is displayed. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-command-list [file]", "List available listfile commands and exit.",
- "The list contains all commands for which help may be obtained by using "
- "the --help-command argument followed by a command name. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-commands [file]", "Print help for all commands and exit.",
- "Full documentation specific for all current commands is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-compatcommands [file]", "Print help for compatibility commands. ",
- "Full documentation specific for all compatibility commands is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-module module [file]", "Print help for a single module and exit.",
- "Full documentation specific to the given module is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-module-list [file]", "List available modules and exit.",
- "The list contains all modules for which help may be obtained by using "
- "the --help-module argument followed by a module name. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-modules [file]", "Print help for all modules and exit.",
- "Full documentation for all modules is displayed. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-custom-modules [file]" , "Print help for all custom modules and "
- "exit.",
- "Full documentation for all custom modules is displayed. "
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-policy cmp [file]",
- "Print help for a single policy and exit.",
- "Full documentation specific to the given policy is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-policies [file]", "Print help for all policies and exit.",
- "Full documentation for all policies is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-property prop [file]",
- "Print help for a single property and exit.",
- "Full documentation specific to the given property is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-property-list [file]", "List available properties and exit.",
- "The list contains all properties for which help may be obtained by using "
- "the --help-property argument followed by a property name. If a file is "
- "specified, the help is written into it."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-properties [file]", "Print help for all properties and exit.",
- "Full documentation for all properties is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-variable var [file]",
- "Print help for a single variable and exit.",
- "Full documentation specific to the given variable is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-variable-list [file]", "List documented variables and exit.",
- "The list contains all variables for which help may be obtained by using "
- "the --help-variable argument followed by a variable name. If a file is "
- "specified, the help is written into it."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {"--help-variables [file]", "Print help for all variables and exit.",
- "Full documentation for all variables is displayed."
- "If a file is specified, the documentation is written into and the output "
- "format is determined depending on the filename suffix. Supported are man "
- "page, HTML, DocBook and plain text."},
- {0,0,0}
+ { "-E", "CMake command mode." },
+ { "-L[A][H]", "List non-advanced cached variables." },
+ { "--build <dir>", "Build a CMake-generated project binary tree." },
+ { "-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." },
+ { "--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." },
+ { "--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." },
+ { "--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 }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationSeeAlso[][3] =
-{
- {0, "ccmake", 0},
- {0, "cpack", 0},
- {0, "ctest", 0},
- {0, "cmakecommands", 0},
- {0, "cmakecompat", 0},
- {0, "cmakemodules", 0},
- {0, "cmakeprops", 0},
- {0, "cmakevars", 0},
- {0, 0, 0}
-};
+#endif
-//----------------------------------------------------------------------------
-static const char * cmDocumentationNOTE[][3] =
+static int do_command(int ac, char const* const* av)
{
- {0,
- "CMake no longer configures a project when run with no arguments. "
- "In order to configure the project in the current directory, run\n"
- " cmake .", 0},
- {0,0,0}
-};
-#endif
+ std::vector<std::string> args;
+ args.reserve(ac - 1);
+ args.push_back(av[0]);
+ args.insert(args.end(), av + 2, av + ac);
+ return cmcmd::ExecuteCMakeCommand(args);
+}
-int do_cmake(int ac, char** av);
-static int do_build(int ac, char** av);
+int do_cmake(int ac, char const* const* av);
+static int do_build(int ac, char const* const* av);
-static cmMakefile* cmakemainGetMakefile(void *clientdata)
+static cmMakefile* cmakemainGetMakefile(void* clientdata)
{
- cmake* cm = (cmake *)clientdata;
- if(cm && cm->GetDebugOutput())
- {
- cmGlobalGenerator* gg=cm->GetGlobalGenerator();
- if (gg)
- {
- cmLocalGenerator* lg=gg->GetCurrentLocalGenerator();
- if (lg)
- {
- cmMakefile* mf = lg->GetMakefile();
- return mf;
- }
- }
+ cmake* cm = (cmake*)clientdata;
+ if (cm && cm->GetDebugOutput()) {
+ cmGlobalGenerator* gg = cm->GetGlobalGenerator();
+ if (gg) {
+ return gg->GetCurrentMakefile();
}
- return 0;
+ }
+ return CM_NULLPTR;
}
-static std::string cmakemainGetStack(void *clientdata)
+static std::string cmakemainGetStack(void* clientdata)
{
std::string msg;
- cmMakefile* mf=cmakemainGetMakefile(clientdata);
- if (mf)
- {
- msg = mf->GetListFileStack();
- if (!msg.empty())
- {
+ cmMakefile* mf = cmakemainGetMakefile(clientdata);
+ if (mf) {
+ msg = mf->FormatListFileStack();
+ if (!msg.empty()) {
msg = "\n Called from: " + msg;
- }
}
+ }
return msg;
}
-static void cmakemainErrorCallback(const char* m, const char*, bool&,
- void *clientdata)
+static void cmakemainMessageCallback(const char* m, const char* /*unused*/,
+ bool& /*unused*/, void* clientdata)
{
std::cerr << m << cmakemainGetStack(clientdata) << std::endl << std::flush;
}
-static void cmakemainProgressCallback(const char *m, float prog,
+static void cmakemainProgressCallback(const char* m, float prog,
void* clientdata)
{
cmMakefile* mf = cmakemainGetMakefile(clientdata);
std::string dir;
- if ((mf) && (strstr(m, "Configuring")==m) && (prog<0))
- {
+ if ((mf) && (strstr(m, "Configuring") == m) && (prog < 0)) {
dir = " ";
- dir += mf->GetCurrentDirectory();
- }
- else if ((mf) && (strstr(m, "Generating")==m))
- {
+ dir += mf->GetCurrentSourceDirectory();
+ } else if ((mf) && (strstr(m, "Generating") == m)) {
dir = " ";
- dir += mf->GetCurrentOutputDirectory();
- }
+ dir += mf->GetCurrentBinaryDirectory();
+ }
- if ((prog < 0) || (!dir.empty()))
- {
- std::cout << "-- " << m << dir << cmakemainGetStack(clientdata)<<std::endl;
- }
+ if ((prog < 0) || (!dir.empty())) {
+ std::cout << "-- " << m << dir << cmakemainGetStack(clientdata)
+ << std::endl;
+ }
std::cout.flush();
}
-
-int main(int ac, char** av)
+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::FindExecutableDirectory(av[0]);
- if(ac > 1 && strcmp(av[1], "--build") == 0)
- {
- return do_build(ac, av);
+ 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** av)
+int do_cmake(int ac, char const* const* av)
{
- if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
- {
+ if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
std::cerr << "Current working directory cannot be established."
<< std::endl;
return 1;
- }
+ }
#ifdef CMAKE_BUILD_WITH_CMAKE
cmDocumentation doc;
doc.addCMakeStandardDocSections();
- if(doc.CheckOptions(ac, av, "-E"))
- {
+ if (doc.CheckOptions(ac, av)) {
// Construct and print requested documentation.
- cmake hcm;
+ cmake hcm(cmake::RoleInternal);
+ hcm.SetHomeDirectory("");
+ hcm.SetHomeOutputDirectory("");
hcm.AddCMakePaths();
- doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT"));
// the command line args are processed here so that you can do
// -DCMAKE_MODULE_PATH=/some/path and have this value accessible here
- std::vector<std::string> args;
- for(int i =0; i < ac; ++i)
- {
- args.push_back(av[i]);
- }
+ std::vector<std::string> args(av, av + ac);
hcm.SetCacheArgs(args);
- const char* modulePath = hcm.GetCacheDefinition("CMAKE_MODULE_PATH");
- if (modulePath)
- {
- doc.SetCMakeModulePath(modulePath);
- }
- std::vector<cmDocumentationEntry> commands;
- std::vector<cmDocumentationEntry> policies;
- std::vector<cmDocumentationEntry> compatCommands;
std::vector<cmDocumentationEntry> generators;
- std::map<std::string,cmDocumentationSection *> propDocs;
- hcm.GetPolicyDocumentation(policies);
- hcm.GetCommandDocumentation(commands, true, false);
- hcm.GetCommandDocumentation(compatCommands, false, true);
- hcm.GetPropertiesDocumentation(propDocs);
hcm.GetGeneratorDocumentation(generators);
doc.SetName("cmake");
- doc.SetSection("Name",cmDocumentationName);
- doc.SetSection("Usage",cmDocumentationUsage);
- doc.SetSection("Description",cmDocumentationDescription);
- doc.AppendSection("Generators",generators);
- doc.PrependSection("Options",cmDocumentationOptions);
- doc.SetSection("Commands",commands);
- doc.SetSection("Policies",policies);
- doc.AppendSection("Compatibility Commands",compatCommands);
- doc.SetSections(propDocs);
-
- cmDocumentationEntry e;
- e.Brief =
- "variables defined by cmake, that give information about the project, "
- "and cmake";
- doc.PrependSection("Variables that Provide Information",e);
-
- doc.SetSeeAlsoList(cmDocumentationSeeAlso);
- int result = doc.PrintRequestedDocumentation(std::cout)? 0:1;
-
- // If we were run with no arguments, but a CMakeLists.txt file
- // exists, the user may have been trying to use the old behavior
- // of cmake to build a project in-source. Print a message
- // explaining the change to standard error and return an error
- // condition in case the program is running from a script.
- if((ac == 1) && cmSystemTools::FileExists("CMakeLists.txt"))
- {
- doc.ClearSections();
- doc.SetSection("NOTE", cmDocumentationNOTE);
- doc.Print(cmDocumentation::UsageForm, 0, std::cerr);
- return 1;
- }
- return result;
+ doc.SetSection("Name", cmDocumentationName);
+ doc.SetSection("Usage", cmDocumentationUsage);
+ if (ac == 1) {
+ doc.AppendSection("Usage", cmDocumentationUsageNote);
}
+ doc.AppendSection("Generators", generators);
+ doc.PrependSection("Options", cmDocumentationOptions);
+
+ return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
+ }
#else
- if ( ac == 1 )
- {
- std::cout <<
- "Bootstrap CMake should not be used outside CMake build process."
- << std::endl;
+ if (ac == 1) {
+ std::cout
+ << "Bootstrap CMake should not be used outside CMake build process."
+ << std::endl;
return 0;
- }
+ }
#endif
- bool wiz = false;
bool sysinfo = false;
- bool command = false;
bool list_cached = false;
bool list_all_cached = false;
bool list_help = false;
bool view_only = false;
cmake::WorkingMode workingMode = cmake::NORMAL_MODE;
std::vector<std::string> args;
- for(int i =0; i < ac; ++i)
- {
- if(!command && strcmp(av[i], "-i") == 0)
- {
- wiz = true;
- }
- else if(!command && strcmp(av[i], "--system-information") == 0)
- {
+ for (int i = 0; i < ac; ++i) {
+ if (strcmp(av[i], "-i") == 0) {
+ /* clang-format off */
+ std::cerr <<
+ "The \"cmake -i\" wizard mode is no longer supported.\n"
+ "Use the -D option to set cache values on the command line.\n"
+ "Use cmake-gui or ccmake for an interactive dialog.\n";
+ /* clang-format on */
+ return 1;
+ }
+ if (strcmp(av[i], "--system-information") == 0) {
sysinfo = true;
- }
- // if command has already been set, then
- // do not eat the -E
- else if (!command && strcmp(av[i], "-E") == 0)
- {
- command = true;
- }
- else if (!command && strcmp(av[i], "-N") == 0)
- {
+ } else if (strcmp(av[i], "-N") == 0) {
view_only = true;
- }
- else if (!command && strcmp(av[i], "-L") == 0)
- {
+ } else if (strcmp(av[i], "-L") == 0) {
list_cached = true;
- }
- else if (!command && strcmp(av[i], "-LA") == 0)
- {
+ } else if (strcmp(av[i], "-LA") == 0) {
list_all_cached = true;
- }
- else if (!command && strcmp(av[i], "-LH") == 0)
- {
+ } else if (strcmp(av[i], "-LH") == 0) {
list_cached = true;
list_help = true;
- }
- else if (!command && strcmp(av[i], "-LAH") == 0)
- {
+ } else if (strcmp(av[i], "-LAH") == 0) {
list_all_cached = true;
list_help = true;
- }
- else if (!command && strncmp(av[i], "-P", strlen("-P")) == 0)
- {
- if ( i == ac -1 )
- {
+ } else if (cmHasLiteralPrefix(av[i], "-P")) {
+ if (i == ac - 1) {
cmSystemTools::Error("No script specified for argument -P");
- }
- else
- {
+ } else {
workingMode = cmake::SCRIPT_MODE;
args.push_back(av[i]);
i++;
args.push_back(av[i]);
- }
}
- else if (!command && strncmp(av[i], "--find-package",
- strlen("--find-package")) == 0)
- {
+ } else if (cmHasLiteralPrefix(av[i], "--find-package")) {
workingMode = cmake::FIND_PACKAGE_MODE;
args.push_back(av[i]);
- }
- else
- {
+ } else {
args.push_back(av[i]);
- }
- }
- if(command)
- {
- int ret = cmake::ExecuteCMakeCommand(args);
- return ret;
}
- if (wiz)
- {
- cmakewizard wizard;
- return wizard.RunWizard(args);
- }
- if (sysinfo)
- {
- cmake cm;
+ }
+ if (sysinfo) {
+ cmake cm(cmake::RoleProject);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
int ret = cm.GetSystemInformation(args);
return ret;
- }
- cmake cm;
- cmSystemTools::SetErrorCallback(cmakemainErrorCallback, (void *)&cm);
- cm.SetProgressCallback(cmakemainProgressCallback, (void *)&cm);
+ }
+ cmake::Role const role =
+ workingMode == cmake::SCRIPT_MODE ? cmake::RoleScript : cmake::RoleProject;
+ cmake cm(role);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
+ cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm);
cm.SetWorkingMode(workingMode);
int res = cm.Run(args, view_only);
- if ( list_cached || list_all_cached )
- {
- cmCacheManager::CacheIterator it =
- cm.GetCacheManager()->GetCacheIterator();
+ if (list_cached || list_all_cached) {
std::cout << "-- Cache values" << std::endl;
- for ( it.Begin(); !it.IsAtEnd(); it.Next() )
- {
- cmCacheManager::CacheEntryType t = it.GetType();
- if ( t != cmCacheManager::INTERNAL && t != cmCacheManager::STATIC &&
- t != cmCacheManager::UNINITIALIZED )
- {
- bool advanced = it.PropertyExists("ADVANCED");
- if ( list_all_cached || !advanced)
- {
- if ( list_help )
- {
- std::cout << "// " << it.GetProperty("HELPSTRING") << std::endl;
- }
- std::cout << it.GetName() << ":" <<
- cmCacheManager::TypeToString(it.GetType())
- << "=" << it.GetValue() << std::endl;
- if ( list_help )
- {
+ 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);
+ if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC &&
+ t != cmStateEnums::UNINITIALIZED) {
+ const char* advancedProp =
+ cm.GetState()->GetCacheEntryProperty(*it, "ADVANCED");
+ if (list_all_cached || !advancedProp) {
+ if (list_help) {
+ std::cout << "// "
+ << cm.GetState()->GetCacheEntryProperty(*it,
+ "HELPSTRING")
+ << std::endl;
+ }
+ std::cout << *it << ":" << cmState::CacheEntryTypeToString(t) << "="
+ << cm.GetState()->GetCacheEntryValue(*it) << std::endl;
+ if (list_help) {
std::cout << std::endl;
- }
}
}
}
}
+ }
// Always return a non-negative value. Windows tools do not always
// interpret negative return values as errors.
- if(res != 0)
- {
+ if (res != 0) {
return 1;
- }
- else
- {
- return 0;
- }
+ }
+ return 0;
}
-//----------------------------------------------------------------------------
-static int do_build(int ac, char** av)
+static int do_build(int ac, char const* const* av)
{
#ifndef CMAKE_BUILD_WITH_CMAKE
std::cerr << "This cmake does not support --build\n";
@@ -584,43 +361,42 @@ static int do_build(int ac, char** av)
std::string dir;
std::vector<std::string> nativeOptions;
bool clean = false;
- cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_MERGE;
-
- enum Doing { DoingNone, DoingDir, DoingTarget, DoingConfig, DoingNative};
+ bool hasTarget = false;
+
+ enum Doing
+ {
+ DoingNone,
+ DoingDir,
+ DoingTarget,
+ DoingConfig,
+ DoingNative
+ };
Doing doing = DoingDir;
- for(int i=2; i < ac; ++i)
- {
- if(doing == DoingNative)
- {
+ 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;
}
- else if(strcmp(av[i], "--target") == 0)
- {
- doing = DoingTarget;
- }
- else if(strcmp(av[i], "--config") == 0)
- {
+ } else if (strcmp(av[i], "--config") == 0) {
doing = DoingConfig;
- }
- else if(strcmp(av[i], "--clean-first") == 0)
- {
+ } else if (strcmp(av[i], "--clean-first") == 0) {
clean = true;
doing = DoingNone;
- }
- else if(strcmp(av[i], "--use-stderr") == 0)
- {
- outputflag = cmSystemTools::OUTPUT_PASSTHROUGH;
- }
- else if(strcmp(av[i], "--") == 0)
- {
+ } else if (strcmp(av[i], "--use-stderr") == 0) {
+ /* tolerate legacy option */
+ } else if (strcmp(av[i], "--") == 0) {
doing = DoingNative;
- }
- else
- {
- switch (doing)
- {
+ } else {
+ switch (doing) {
case DoingDir:
- dir = av[i];
+ dir = cmSystemTools::CollapseFullPath(av[i]);
doing = DoingNone;
break;
case DoingTarget:
@@ -635,27 +411,23 @@ static int do_build(int ac, char** av)
std::cerr << "Unknown argument " << av[i] << std::endl;
dir = "";
break;
- }
}
}
- if(dir.empty())
- {
+ }
+ if (dir.empty()) {
+ /* clang-format off */
std::cerr <<
"Usage: cmake --build <dir> [options] [-- [native-options]]\n"
"Options:\n"
CMAKE_BUILD_OPTIONS
;
+ /* clang-format on */
return 1;
- }
-
- // Hack for vs6 that passes ".\Debug" as "$(IntDir)" value:
- //
- if (cmSystemTools::StringStartsWith(config.c_str(), ".\\"))
- {
- config = config.substr(2);
- }
+ }
- cmake cm;
- return cm.Build(dir, target, config, nativeOptions, clean, outputflag);
+ cmake cm(cmake::RoleInternal);
+ cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
+ cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm);
+ return cm.Build(dir, target, config, nativeOptions, clean);
#endif
}
diff --git a/Source/cmaketest.h.in b/Source/cmaketest.h.in
deleted file mode 100644
index aada52dba..000000000
--- a/Source/cmaketest.h.in
+++ /dev/null
@@ -1,16 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#define CMAKE_BINARY_DIR "${CMake_BINARY_DIR}"
-#define EXECUTABLE_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}"
-#define MAKEPROGRAM "${MAKEPROGRAM}"
-#define CMAKE_GENERATOR "${CMAKE_GENERATOR}"
-#define DART_MAKECOMMAND "${MAKECOMMAND}"
diff --git a/Source/cmakewizard.cxx b/Source/cmakewizard.cxx
deleted file mode 100644
index bac403a89..000000000
--- a/Source/cmakewizard.cxx
+++ /dev/null
@@ -1,155 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmakewizard.h"
-#include "cmake.h"
-#include "cmCacheManager.h"
-
-cmakewizard::cmakewizard()
-{
- this->ShowAdvanced = false;
-}
-
-
-void cmakewizard::AskUser(const char* key,
- cmCacheManager::CacheIterator& iter)
-{
- printf("Variable Name: %s\n", key);
- const char* helpstring = iter.GetProperty("HELPSTRING");
- printf("Description: %s\n", (helpstring?helpstring:"(none)"));
- printf("Current Value: %s\n", iter.GetValue());
- printf("New Value (Enter to keep current value): ");
- char buffer[4096];
- if(!fgets(buffer, static_cast<int>(sizeof(buffer) - 1), stdin))
- {
- buffer[0] = 0;
- }
-
- if(strlen(buffer) > 0)
- {
- std::string sbuffer = buffer;
- std::string::size_type pos = sbuffer.find_last_not_of(" \n\r\t");
- std::string value = "";
- if ( pos != std::string::npos )
- {
- value = sbuffer.substr(0, pos+1);
- }
-
- if ( value.size() > 0 )
- {
- if(iter.GetType() == cmCacheManager::PATH ||
- iter.GetType() == cmCacheManager::FILEPATH)
- {
- cmSystemTools::ConvertToUnixSlashes(value);
- }
- if(iter.GetType() == cmCacheManager::BOOL)
- {
- if(!cmSystemTools::IsOn(value.c_str()))
- {
- value = "OFF";
- }
- }
- iter.SetValue(value.c_str());
- }
- }
- printf("\n");
-}
-
-bool cmakewizard::AskAdvanced()
-{
- printf("Would you like to see advanced options? [No]:");
- char buffer[4096];
- if(!fgets(buffer, static_cast<int>(sizeof(buffer) - 1), stdin))
- {
- buffer[0] = 0;
- }
- else if(buffer[0] == 'y' || buffer[0] == 'Y')
- {
- return true;
- }
- return false;
-}
-
-
-void cmakewizard::ShowMessage(const char* m)
-{
- printf("%s\n", m);
-}
-
-
-
-int cmakewizard::RunWizard(std::vector<std::string> const& args)
-{
- this->ShowAdvanced = this->AskAdvanced();
- cmSystemTools::DisableRunCommandOutput();
- cmake make;
- make.SetArgs(args);
- make.SetCMakeCommand(args[0].c_str());
- make.LoadCache();
- make.SetCacheArgs(args);
- std::map<cmStdString, cmStdString> askedCache;
- bool asked = false;
- // continue asking questions until no new questions are asked
- do
- {
- asked = false;
- // run cmake
- this->ShowMessage(
- "Please wait while cmake processes CMakeLists.txt files....\n");
-
- make.Configure();
- this->ShowMessage("\n");
- // load the cache from disk
- cmCacheManager *cachem = make.GetCacheManager();
- cachem->LoadCache(make.GetHomeOutputDirectory());
- cmCacheManager::CacheIterator i = cachem->NewIterator();
- // iterate over all entries in the cache
- for(;!i.IsAtEnd(); i.Next())
- {
- std::string key = i.GetName();
- if( i.GetType() == cmCacheManager::INTERNAL ||
- i.GetType() == cmCacheManager::STATIC ||
- i.GetType() == cmCacheManager::UNINITIALIZED )
- {
- continue;
- }
- if(askedCache.count(key))
- {
- std::string& e = askedCache.find(key)->second;
- if(e != i.GetValue())
- {
- if(this->ShowAdvanced || !i.GetPropertyAsBool("ADVANCED"))
- {
- this->AskUser(key.c_str(), i);
- asked = true;
- }
- }
- }
- else
- {
- if(this->ShowAdvanced || !i.GetPropertyAsBool("ADVANCED"))
- {
- this->AskUser(key.c_str(), i);
- asked = true;
- }
- }
- askedCache[key] = i.GetValue();
- }
- cachem->SaveCache(make.GetHomeOutputDirectory());
- }
- while(asked);
- if(make.Generate() == 0)
- {
- this->ShowMessage("CMake complete, run make to build project.\n");
- return 0;
- }
- return 1;
-}
diff --git a/Source/cmakewizard.h b/Source/cmakewizard.h
deleted file mode 100644
index 0c8dba93c..000000000
--- a/Source/cmakewizard.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-
-#include "cmMakefile.h"
-
-class cmakewizard
-{
-public:
- cmakewizard();
- virtual ~cmakewizard() {}
- /**
- * Prompt the user to see if they want to see advanced entries.
- */
- virtual bool AskAdvanced();
-
- /**
- * Prompt the User for a new value for key, the answer is put in entry.
- */
- virtual void AskUser(const char* key, cmCacheManager::CacheIterator& iter);
- ///! Show a message to wait for cmake to run.
- virtual void ShowMessage(const char*);
-
- /**
- * Run cmake in wizard mode. This will coninue to ask the user questions
- * until there are no more entries in the cache.
- */
- int RunWizard(std::vector<std::string>const& args);
-
-private:
- bool ShowAdvanced;
-};
-
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
index 9aaeeaa4d..72da456d4 100644
--- a/Source/cmakexbuild.cxx
+++ b/Source/cmakexbuild.cxx
@@ -1,16 +1,13 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmsys/Process.h"
+#include <iostream>
+#include <string>
+#include <vector>
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include <cmsys/Process.h>
-#include "cmStandardIncludes.h"
#include "cmSystemTools.h"
// This is a wrapper program for xcodebuild
@@ -31,62 +28,50 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
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")
- != line.npos)
- {
+ 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") == line.npos))
- {
- if(pipe == cmsysProcess_Pipe_STDERR)
- {
+ if (!hitbug && (line.find("setenv") == std::string::npos)) {
+ if (pipe == cmsysProcess_Pipe_STDERR) {
std::cerr << line << "\n";
- }
- else if(pipe == cmsysProcess_Pipe_STDOUT)
- {
+ } else if (pipe == cmsysProcess_Pipe_STDOUT) {
std::cout << line << "\n";
- }
}
- pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
}
+ pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
+ }
cmsysProcess_WaitForExit(cp, 0);
- if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
- {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
return cmsysProcess_GetExitValue(cp);
- }
- if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
- {
+ }
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
return -1;
- }
+ }
return -1;
}
-int main(int ac, char*av[])
+int main(int ac, char* av[])
{
std::vector<const char*> argv;
argv.push_back("xcodebuild");
- for(int i =1; i < ac; i++)
- {
+ for (int i = 1; i < ac; i++) {
argv.push_back(av[i]);
- }
+ }
argv.push_back(0);
bool hitbug = true;
int ret = 0;
- while(hitbug)
- {
+ while (hitbug) {
ret = RunXCode(argv, hitbug);
- }
- if(ret < 0)
- {
+ }
+ if (ret < 0) {
return 255;
- }
+ }
return ret;
}
-
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 85715574f..0c5bbe2df 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -12,23 +12,27 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
// Wrapper around cl that adds /showIncludes to command line, and uses that to
// generate .d files that match the style from gcc -MD.
//
// /showIncludes is equivalent to -MD, not -MMD, that is, system headers are
// included.
+#include "cmSystemTools.h"
+#include "cmsys/Encoding.hxx"
-#include <windows.h>
+#include <algorithm>
#include <sstream>
-#include <cmSystemTools.h>
+#include <windows.h>
// We don't want any wildcard expansion.
// See http://msdn.microsoft.com/en-us/library/zay8tzh6(v=vs.85).aspx
-void _setargv() {}
+void _setargv()
+{
+}
-static void Fatal(const char* msg, ...) {
+static void Fatal(const char* msg, ...)
+{
va_list ap;
fprintf(stderr, "ninja: FATAL: ");
va_start(ap, msg);
@@ -42,20 +46,23 @@ static void Fatal(const char* msg, ...) {
ExitProcess(1);
}
-static void usage(const char* msg) {
+static void usage(const char* msg)
+{
Fatal("%s\n\nusage:\n "
- "cmcldeps "
- "<language C, CXX or RC> "
- "<source file path> "
- "<output path for *.d file> "
- "<output path for *.obj file> "
- "<prefix of /showIncludes> "
- "<path to cl.exe> "
- "<path to tool (cl or rc)> "
- "<rest of command ...>\n", msg);
+ "cmcldeps "
+ "<language C, CXX or RC> "
+ "<source file path> "
+ "<output path for *.d file> "
+ "<output path for *.obj file> "
+ "<prefix of /showIncludes> "
+ "<path to cl.exe> "
+ "<path to tool (cl or rc)> "
+ "<rest of command ...>\n",
+ msg);
}
-static std::string trimLeadingSpace(const std::string& cmdline) {
+static std::string trimLeadingSpace(const std::string& cmdline)
+{
int i = 0;
for (; cmdline[i] == ' '; ++i)
;
@@ -63,7 +70,8 @@ static std::string trimLeadingSpace(const std::string& cmdline) {
}
static void replaceAll(std::string& str, const std::string& search,
- const std::string& repl) {
+ const std::string& repl)
+{
std::string::size_type pos = 0;
while ((pos = str.find(search, pos)) != std::string::npos) {
str.replace(pos, search.size(), repl);
@@ -71,13 +79,15 @@ static void replaceAll(std::string& str, const std::string& search,
}
}
-bool startsWith(const std::string& str, const std::string& what) {
+bool startsWith(const std::string& str, const std::string& what)
+{
return str.compare(0, what.size(), what) == 0;
}
// Strips one argument from the cmdline and returns it. "surrounding quotes"
// are removed from the argument if there were any.
-static std::string getArg(std::string& cmdline) {
+static std::string getArg(std::string& cmdline)
+{
std::string ret;
bool in_quoted = false;
unsigned int i = 0;
@@ -100,16 +110,13 @@ static std::string getArg(std::string& cmdline) {
return ret;
}
-static void parseCommandLine(LPTSTR wincmdline,
- std::string& lang,
- std::string& srcfile,
- std::string& dfile,
- std::string& objfile,
- std::string& prefix,
- std::string& clpath,
- std::string& binpath,
- std::string& rest) {
- std::string cmdline(wincmdline);
+static void parseCommandLine(LPWSTR wincmdline, std::string& lang,
+ std::string& srcfile, std::string& dfile,
+ std::string& objfile, std::string& prefix,
+ std::string& clpath, std::string& binpath,
+ std::string& rest)
+{
+ std::string cmdline = cmsys::Encoding::ToNarrow(wincmdline);
/* self */ getArg(cmdline);
lang = getArg(cmdline);
srcfile = getArg(cmdline);
@@ -123,13 +130,15 @@ static void parseCommandLine(LPTSTR wincmdline,
// Not all backslashes need to be escaped in a depfile, but it's easier that
// way. See the re2c grammar in ninja's source code for more info.
-static void escapePath(std::string &path) {
+static void escapePath(std::string& path)
+{
replaceAll(path, "\\", "\\\\");
replaceAll(path, " ", "\\ ");
}
static void outputDepFile(const std::string& dfile, const std::string& objfile,
- std::vector<std::string>& incs) {
+ std::vector<std::string>& incs)
+{
if (dfile.empty())
return;
@@ -138,7 +147,7 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
std::sort(incs.begin(), incs.end());
incs.erase(std::unique(incs.begin(), incs.end()), incs.end());
- FILE* out = fopen(dfile.c_str(), "wb");
+ FILE* out = cmsys::SystemTools::Fopen(dfile.c_str(), "wb");
// FIXME should this be fatal or not? delete obj? delete d?
if (!out)
@@ -168,13 +177,14 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
fclose(out);
}
-
-bool contains(const std::string& str, const std::string& what) {
+bool contains(const std::string& str, const std::string& what)
+{
return str.find(what) != std::string::npos;
}
std::string replace(const std::string& str, const std::string& what,
- const std::string& replacement) {
+ const std::string& replacement)
+{
size_t pos = str.find(what);
if (pos == std::string::npos)
return str;
@@ -182,34 +192,29 @@ std::string replace(const std::string& str, const std::string& what,
return replaced.replace(pos, what.size(), replacement);
}
-
-
-static int process( const std::string& srcfilename,
- const std::string& dfile,
- const std::string& objfile,
- const std::string& prefix,
- const std::string& cmd,
- const std::string& dir = "",
- bool quiet = false)
+static int process(const std::string& srcfilename, const std::string& dfile,
+ const std::string& objfile, const std::string& prefix,
+ const std::string& cmd, const std::string& dir = "",
+ bool quiet = false)
{
std::string output;
// break up command line into a vector
std::vector<std::string> args;
cmSystemTools::ParseWindowsCommandLine(cmd.c_str(), args);
// convert to correct vector type for RunSingleCommand
- std::vector<cmStdString> command;
- for(std::vector<std::string>::iterator i = args.begin();
- i != args.end(); ++i)
- {
- command.push_back(i->c_str());
- }
+ std::vector<std::string> command;
+ for (std::vector<std::string>::iterator i = args.begin(); i != args.end();
+ ++i) {
+ command.push_back(*i);
+ }
// run the command
int exit_code = 0;
- bool run = cmSystemTools::RunSingleCommand(command, &output, &exit_code,
+ bool run =
+ cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code,
dir.c_str(), cmSystemTools::OUTPUT_NONE);
// process the include directives and output everything else
- std::stringstream ss(output);
+ std::istringstream ss(output);
std::string line;
std::vector<std::string> includes;
bool isFirstLine = true; // cl prints always first the source filename
@@ -237,8 +242,8 @@ static int process( const std::string& srcfilename,
return exit_code;
}
-
-int main() {
+int main()
+{
// Use the Win32 API instead of argc/argv so we can avoid interpreting the
// rest of command line after the .d and .obj. Custom parsing seemed
@@ -247,18 +252,18 @@ int main() {
// the same command line verbatim.
std::string lang, srcfile, dfile, objfile, prefix, cl, binpath, rest;
- parseCommandLine(GetCommandLine(), lang, srcfile, dfile, objfile,
- prefix, cl, binpath, rest);
+ parseCommandLine(GetCommandLineW(), lang, srcfile, dfile, objfile, prefix,
+ cl, binpath, rest);
// needed to suppress filename output of msvc tools
std::string srcfilename;
{
- std::string::size_type pos = srcfile.rfind("\\");
- if (pos == std::string::npos) {
- srcfilename = srcfile;
- } else {
- srcfilename = srcfile.substr(pos + 1);
- }
+ std::string::size_type pos = srcfile.rfind('\\');
+ if (pos == std::string::npos) {
+ srcfilename = srcfile;
+ } else {
+ srcfilename = srcfile.substr(pos + 1);
+ }
}
std::string nol = " /nologo ";
@@ -274,31 +279,26 @@ int main() {
clrest = replace(clrest, "/fo", "/out:");
clrest = replace(clrest, objfile, objfile + ".dep.obj ");
- // rc: src\x\x.rc -> cl: /Tc src\x\x.rc
- if (srcfile.find(" ") != std::string::npos)
- srcfile = "\"" + srcfile + "\"";
- clrest = replace(clrest, srcfile, "/Tc " + srcfile);
-
- cl = "\"" + cl + "\" /P /DRC_INVOKED ";
+ cl = "\"" + cl + "\" /P /DRC_INVOKED /TC ";
// call cl in object dir so the .i is generated there
std::string objdir;
{
- std::string::size_type pos = objfile.rfind("\\");
- if (pos != std::string::npos) {
- objdir = objfile.substr(0, pos);
- }
+ std::string::size_type pos = objfile.rfind("\\");
+ if (pos != std::string::npos) {
+ objdir = objfile.substr(0, pos);
+ }
}
// extract dependencies with cl.exe
- int exit_code = process(srcfilename, dfile, objfile,
- prefix, cl + nol + show + clrest, objdir, true);
+ int exit_code = process(srcfilename, dfile, objfile, prefix,
+ cl + nol + show + clrest, objdir, true);
if (exit_code != 0)
return exit_code;
// compile rc file with rc.exe
- return process(srcfilename, "" , objfile, prefix, binpath + " " + rest);
+ return process(srcfilename, "", objfile, prefix, binpath + " " + rest);
}
usage("Invalid language specified.");
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
new file mode 100644
index 000000000..d5b086174
--- /dev/null
+++ b/Source/cmcmd.cxx
@@ -0,0 +1,1666 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmcmd.h"
+
+#include "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmQtAutoGenerators.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.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"
+#endif
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
+#endif
+
+#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32)
+#include "bindexplib.h"
+#endif
+
+#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__)
+#include "cmVisualStudioWCEPlatformParser.h"
+#endif
+
+#include "cmConfigure.h"
+#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>
+
+int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd);
+int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd);
+
+void CMakeCommandUsage(const char* program)
+{
+ std::ostringstream errorStream;
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ /* clang-format off */
+ errorStream
+ << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
+/* clang-format on */
+#else
+ /* clang-format off */
+ errorStream
+ << "cmake bootstrap\n";
+/* clang-format on */
+#endif
+ // If you add new commands, change here,
+ // and in cmakemain.cxx in the options table
+ /* clang-format off */
+ errorStream
+ << "Usage: " << program << " -E <command> [arguments...]\n"
+ << "Available commands: \n"
+ << " 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"
+ << " copy <file>... destination - copy files to destination "
+ "(either file or directory)\n"
+ << " copy_directory <dir>... destination - copy content of <dir>... "
+ "directories to 'destination' directory\n"
+ << " copy_if_different <file>... destination - copy files if it has "
+ "changed\n"
+ << " echo [<string>...] - displays arguments as text\n"
+ << " echo_append [<string>...] - displays arguments as text but no new "
+ "line\n"
+ << " env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...\n"
+ << " - run command in a modified environment\n"
+ << " environment - display the current environment\n"
+ << " make_directory <dir>... - create parent and <dir> directories\n"
+ << " md5sum <file>... - create MD5 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"
+ << " 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"
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ << "Available on Windows only:\n"
+ << " delete_regv key - delete registry value\n"
+ << " env_vs8_wince sdkname - displays a batch file which sets the "
+ "environment for the provided Windows CE SDK installed in VS2005\n"
+ << " 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());
+}
+
+static bool cmTarFilesFrom(std::string const& file,
+ std::vector<std::string>& files)
+{
+ if (cmSystemTools::FileIsDirectory(file)) {
+ std::ostringstream e;
+ e << "-E tar --files-from= file '" << file << "' is a directory";
+ cmSystemTools::Error(e.str().c_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());
+ return false;
+ }
+ std::string line;
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ if (line.empty()) {
+ continue;
+ }
+ if (cmHasLiteralPrefix(line, "--add-file=")) {
+ files.push_back(line.substr(11));
+ } else if (cmHasLiteralPrefix(line, "-")) {
+ std::ostringstream e;
+ e << "-E tar --files-from='" << file << "' file invalid line:\n"
+ << line << "\n";
+ cmSystemTools::Error(e.str().c_str());
+ return false;
+ } else {
+ files.push_back(line);
+ }
+ }
+ return true;
+}
+
+int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
+{
+ // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
+ if (args.size() > 1) {
+ // Copy file
+ if (args[1] == "copy" && args.size() > 3) {
+ // 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";
+ 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";
+ return_value = true;
+ }
+ }
+ return return_value;
+ }
+
+ // Copy file if different.
+ if (args[1] == "copy_if_different" && args.size() > 3) {
+ // 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_if_different command) \""
+ << args[args.size() - 1] << "\" 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";
+ return_value = true;
+ }
+ }
+ return return_value;
+ }
+
+ // Copy directory content
+ 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";
+ return_value = true;
+ }
+ }
+ return return_value;
+ }
+
+ // Rename a file or directory
+ if (args[1] == "rename" && args.size() == 4) {
+ if (!cmSystemTools::RenameFile(args[2].c_str(), args[3].c_str())) {
+ std::string e = cmSystemTools::GetLastSystemError();
+ std::cerr << "Error renaming from \"" << args[2] << "\" to \""
+ << args[3] << "\": " << e << "\n";
+ return 1;
+ }
+ return 0;
+ }
+
+ // 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";
+ return 1;
+ }
+ return 0;
+ }
+
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+ 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";
+ return 1;
+ }
+ cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary);
+ if (!fin) {
+ std::cerr << "could not open object list file: " << args[3].c_str()
+ << "\n";
+ return 1;
+ }
+ std::string file;
+ bindexplib deffile;
+ while (cmSystemTools::GetLineFromStream(fin, file)) {
+ std::string const& ext = cmSystemTools::GetFilenameLastExtension(file);
+ if (cmSystemTools::LowerCase(ext) == ".def") {
+ if (!deffile.AddDefinitionFile(file.c_str())) {
+ return 1;
+ }
+ } else {
+ if (!deffile.AddObjectFile(file.c_str())) {
+ return 1;
+ }
+ }
+ }
+ deffile.WriteFile(fout);
+ fclose(fout);
+ 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;
+ }
+
+ // Echo string
+ if (args[1] == "echo") {
+ std::cout << cmJoin(cmMakeRange(args).advance(2), " ") << std::endl;
+ return 0;
+ }
+
+ // Echo string no new line
+ if (args[1] == "echo_append") {
+ std::cout << cmJoin(cmMakeRange(args).advance(2), " ");
+ return 0;
+ }
+
+ if (args[1] == "env") {
+ std::vector<std::string>::const_iterator ai = args.begin() + 2;
+ std::vector<std::string>::const_iterator ae = args.end();
+ for (; ai != ae; ++ai) {
+ std::string const& a = *ai;
+ if (cmHasLiteralPrefix(a, "--unset=")) {
+ // Unset environment variable.
+ cmSystemTools::UnPutEnv(a.c_str() + 8);
+ } else if (!a.empty() && a[0] == '-') {
+ // Environment variable and command names cannot start in '-',
+ // so this must be an unknown option.
+ std::cerr << "cmake -E env: unknown option '" << a << "'"
+ << std::endl;
+ return 1;
+ } else if (a.find('=') != std::string::npos) {
+ // Set environment variable.
+ cmSystemTools::PutEnv(a);
+ } else {
+ // This is the beginning of the command.
+ break;
+ }
+ }
+
+ if (ai == ae) {
+ std::cerr << "cmake -E env: no command given" << std::endl;
+ return 1;
+ }
+
+ // 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,
+ cmSystemTools::OUTPUT_PASSTHROUGH)) {
+ return retval;
+ }
+ return 1;
+ }
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ 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;
+ }
+ return 0;
+ }
+#endif
+
+ if (args[1] == "make_directory" && args.size() > 2) {
+ // If error occurs we want to continue copying next files.
+ bool return_value = false;
+ for (std::string::size_type cc = 2; cc < args.size(); cc++) {
+ if (!cmSystemTools::MakeDirectory(args[cc].c_str())) {
+ std::cerr << "Error creating directory \"" << args[cc] << "\".\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;
+ }
+ return 0;
+ }
+
+ // 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") {
+ 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())) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+ }
+
+ // 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)) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ // 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)) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ // capabilities
+ if (args[1] == "capabilities") {
+ if (args.size() > 2) {
+ 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
+ return 0;
+ }
+
+ // Sleep command
+ if (args[1] == "sleep" && args.size() > 2) {
+ double total = 0;
+ for (size_t i = 2; i < args.size(); ++i) {
+ double num = 0.0;
+ char unit;
+ char extra;
+ int n = sscanf(args[i].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";
+ return 1;
+ }
+ }
+ if (total > 0) {
+ cmSystemTools::Delay(static_cast<unsigned int>(total * 1000));
+ }
+ return 0;
+ }
+
+ // Clock command
+ 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;
+
+ time(&time_start);
+ clock_start = clock();
+ int ret = 0;
+ cmSystemTools::RunSingleCommand(command, CM_NULLPTR, CM_NULLPTR, &ret);
+
+ clock_finish = clock();
+ time(&time_finish);
+
+ double clocks_per_sec = static_cast<double>(CLOCKS_PER_SEC);
+ std::cout << "Elapsed time: "
+ << static_cast<long>(time_finish - time_start) << " s. (time)"
+ << ", "
+ << static_cast<double>(clock_finish - clock_start) /
+ clocks_per_sec
+ << " s. (clock)"
+ << "\n";
+ return ret;
+ }
+
+ // 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;
+ }
+
+ // 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());
+ 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)) {
+ return retval;
+ }
+
+ return 1;
+ }
+
+ // 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";
+ cmSystemTools::RemoveADirectory(dirName);
+
+ // is the last argument a filename that exists?
+ FILE* countFile = cmsys::SystemTools::Fopen(args[3], "r");
+ int count;
+ if (countFile) {
+ if (1 != fscanf(countFile, "%i", &count)) {
+ cmSystemTools::Message("Could not read from count file.");
+ }
+ fclose(countFile);
+ } else {
+ count = atoi(args[3].c_str());
+ }
+ if (count) {
+ cmSystemTools::MakeDirectory(dirName.c_str());
+ // write the count into the directory
+ std::string fName = dirName;
+ fName += "/count.txt";
+ FILE* progFile = cmsys::SystemTools::Fopen(fName, "w");
+ if (progFile) {
+ fprintf(progFile, "%i\n", count);
+ fclose(progFile);
+ }
+ }
+ return 0;
+ }
+
+ // Command to report progress for a build
+ if (args[1] == "cmake_progress_report" && args.size() >= 3) {
+ // This has been superseded by cmake_echo_color --progress-*
+ // options. We leave it here to avoid errors if somehow this
+ // is invoked by an existing makefile without regenerating.
+ return 0;
+ }
+
+ // Command to create a symbolic link. Fails on platforms not
+ // supporting them.
+ if (args[1] == "create_symlink" && args.size() == 4) {
+ const char* destinationFileName = args[3].c_str();
+ if ((cmSystemTools::FileExists(destinationFileName) ||
+ cmSystemTools::FileIsSymlink(destinationFileName)) &&
+ !cmSystemTools::RemoveFile(destinationFileName)) {
+ std::string emsg = cmSystemTools::GetLastSystemError();
+ std::cerr << "failed to create symbolic link '" << destinationFileName
+ << "' because existing path cannot be removed: " << emsg
+ << "\n";
+ 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;
+ }
+
+ // Internal CMake shared library support.
+ if (args[1] == "cmake_symlink_library" && args.size() == 5) {
+ return cmcmd::SymlinkLibrary(args);
+ }
+
+ // Internal CMake versioned executable support.
+ if (args[1] == "cmake_symlink_executable" && args.size() == 4) {
+ return cmcmd::SymlinkExecutable(args);
+ }
+
+ // Internal CMake dependency scanning support.
+ if (args[1] == "cmake_depends" && args.size() >= 6) {
+ const bool verbose = isCMakeVerbose();
+
+ // Create a cmake object instance to process dependencies.
+ cmake cm(cmake::RoleScript); // All we need is the `set` command.
+ std::string gen;
+ std::string homeDir;
+ std::string startDir;
+ std::string homeOutDir;
+ std::string startOutDir;
+ std::string depInfo;
+ bool color = false;
+ if (args.size() >= 8) {
+ // Full signature:
+ //
+ // -E cmake_depends <generator>
+ // <home-src-dir> <start-src-dir>
+ // <home-out-dir> <start-out-dir>
+ // <dep-info> [--color=$(COLOR)]
+ //
+ // All paths are provided.
+ gen = args[2];
+ homeDir = args[3];
+ startDir = args[4];
+ homeOutDir = args[5];
+ startOutDir = args[6];
+ depInfo = args[7];
+ 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()));
+ }
+ } else {
+ // Support older signature for existing makefiles:
+ //
+ // -E cmake_depends <generator>
+ // <home-out-dir> <start-out-dir>
+ // <dep-info>
+ //
+ // Just pretend the source directories are the same as the
+ // binary directories so at least scanning will work.
+ gen = args[2];
+ homeDir = args[3];
+ startDir = args[4];
+ homeOutDir = args[3];
+ startOutDir = args[3];
+ depInfo = args[5];
+ }
+
+ // Create a local generator configured for the directory in
+ // which dependencies will be scanned.
+ homeDir = cmSystemTools::CollapseFullPath(homeDir);
+ startDir = cmSystemTools::CollapseFullPath(startDir);
+ homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir);
+ startOutDir = cmSystemTools::CollapseFullPath(startOutDir);
+ cm.SetHomeDirectory(homeDir);
+ cm.SetHomeOutputDirectory(homeOutDir);
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ if (cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen)) {
+ cm.SetGlobalGenerator(ggd);
+ 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()));
+
+ // Actually scan dependencies.
+ return lgd->UpdateDependencies(depInfo.c_str(), verbose, color) ? 0
+ : 2;
+ }
+ return 1;
+ }
+
+ // Internal CMake link script support.
+ if (args[1] == "cmake_link_script" && args.size() >= 3) {
+ return cmcmd::ExecuteLinkScript(args);
+ }
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // Internal CMake ninja dependency scanning support.
+ if (args[1] == "cmake_ninja_depends") {
+ return cmcmd_cmake_ninja_depends(args.begin() + 2, args.end());
+ }
+
+ // Internal CMake ninja dyndep support.
+ if (args[1] == "cmake_ninja_dyndep") {
+ return cmcmd_cmake_ninja_dyndep(args.begin() + 2, args.end());
+ }
+#endif
+
+ // Internal CMake unimplemented feature notification.
+ if (args[1] == "cmake_unimplemented_variable") {
+ std::cerr << "Feature not implemented for this platform.";
+ if (args.size() == 3) {
+ std::cerr << " Variable " << args[2] << " is not set.";
+ }
+ std::cerr << std::endl;
+ return 1;
+ }
+
+ if (args[1] == "vs_link_exe") {
+ return cmcmd::VisualStudioLink(args, 1);
+ }
+
+ if (args[1] == "vs_link_dll") {
+ return cmcmd::VisualStudioLink(args, 2);
+ }
+
+ // Internal CMake color makefile support.
+ if (args[1] == "cmake_echo_color") {
+ 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;
+ }
+#endif
+
+ // Tar files
+ if (args[1] == "tar" && args.size() > 3) {
+ const char* knownFormats[] = { "7zip", "gnutar", "pax", "paxr", "zip" };
+
+ std::string const& flags = args[2];
+ std::string const& outFile = args[3];
+ std::vector<std::string> files;
+ std::string mtime;
+ std::string format;
+ bool doing_options = true;
+ for (std::string::size_type cc = 4; cc < args.size(); cc++) {
+ std::string const& arg = args[cc];
+ if (doing_options && cmHasLiteralPrefix(arg, "--")) {
+ if (arg == "--") {
+ doing_options = false;
+ } else if (cmHasLiteralPrefix(arg, "--mtime=")) {
+ mtime = arg.substr(8);
+ } else if (cmHasLiteralPrefix(arg, "--files-from=")) {
+ std::string const& files_from = arg.substr(13);
+ if (!cmTarFilesFrom(files_from, files)) {
+ return 1;
+ }
+ } 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());
+ return 1;
+ }
+ } else {
+ cmSystemTools::Error("Unknown option to -E tar: ", arg.c_str());
+ return 1;
+ }
+ } else {
+ files.push_back(arg);
+ }
+ }
+ cmSystemTools::cmTarCompression compress =
+ cmSystemTools::TarCompressNone;
+ 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;
+ }
+ if ((format == "7zip" || format == "zip") && nCompress > 0) {
+ cmSystemTools::Error("Can not use compression flags with format: ",
+ format.c_str());
+ return 1;
+ }
+ if (nCompress > 1) {
+ cmSystemTools::Error("Can only compress a tar file one way; "
+ "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());
+ 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());
+ 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());
+ return 1;
+ }
+#ifdef WIN32
+ // OK, on windows 7 after we untar some files,
+ // sometimes we can not rename the directory after
+ // the untar is done. This breaks the external project
+ // untar and rename code. So, by default we will wait
+ // 1/10th of a second after the untar. If CMAKE_UNTAR_DELAY
+ // is set in the env, its value will be used instead of 100.
+ int delay = 100;
+ std::string delayVar;
+ if (cmSystemTools::GetEnv("CMAKE_UNTAR_DELAY", delayVar)) {
+ delay = atoi(delayVar.c_str());
+ }
+ if (delay) {
+ cmSystemTools::Delay(delay);
+ }
+#endif
+ }
+ return 0;
+ }
+
+ if (args[1] == "server") {
+ const std::string pipePrefix = "--pipe=";
+ bool supportExperimental = false;
+ bool isDebug = false;
+ std::string pipe;
+
+ for (size_t i = 2; i < args.size(); ++i) {
+ const std::string& a = args[i];
+
+ if (a == "--experimental") {
+ supportExperimental = true;
+ } else if (a == "--debug") {
+ pipe.clear();
+ isDebug = true;
+ } else if (a.substr(0, pipePrefix.size()) == pipePrefix) {
+ isDebug = false;
+ pipe = a.substr(pipePrefix.size());
+ if (pipe.empty()) {
+ cmSystemTools::Error("No pipe given after --pipe=");
+ return 2;
+ }
+ } else {
+ cmSystemTools::Error("Unknown argument for server mode");
+ return 1;
+ }
+ }
+#if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE
+ cmServerConnection* conn;
+ if (isDebug) {
+ conn = new cmServerStdIoConnection;
+ } else {
+ conn = new cmServerPipeConnection(pipe);
+ }
+ cmServer server(conn, supportExperimental);
+ std::string errorMessage;
+ if (server.Serve(&errorMessage)) {
+ return 0;
+ }
+ cmSystemTools::Error(errorMessage.c_str());
+#else
+ static_cast<void>(supportExperimental);
+ static_cast<void>(isDebug);
+ cmSystemTools::Error("CMake was not built with server mode enabled");
+#endif
+ return 1;
+ }
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ // Internal CMake Fortran module support.
+ if (args[1] == "cmake_copy_f90_mod" && args.size() >= 4) {
+ return cmDependsFortran::CopyModule(args) ? 0 : 1;
+ }
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Write registry value
+ if (args[1] == "write_regv" && args.size() > 3) {
+ return cmSystemTools::WriteRegistryValue(args[2].c_str(),
+ args[3].c_str())
+ ? 0
+ : 1;
+ }
+
+ // Delete registry value
+ if (args[1] == "delete_regv" && args.size() > 2) {
+ return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
+ }
+
+ // Remove file
+ if (args[1] == "comspec" && args.size() > 2) {
+ std::cerr << "Win9x helper \"cmake -E comspec\" no longer supported\n";
+ return 1;
+ }
+
+ if (args[1] == "env_vs8_wince" && args.size() == 3) {
+ return cmcmd::WindowsCEEnvironment("8.0", args[2]);
+ }
+
+ if (args[1] == "env_vs9_wince" && args.size() == 3) {
+ return cmcmd::WindowsCEEnvironment("9.0", args[2]);
+ }
+#endif
+ }
+
+ ::CMakeCommandUsage(args[0].c_str());
+ return 1;
+}
+
+int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
+{
+ int result = 0;
+ std::string const& realName = args[2];
+ std::string const& soName = args[3];
+ std::string const& name = args[4];
+ if (soName != realName) {
+ if (!cmcmd::SymlinkInternal(realName, soName)) {
+ cmSystemTools::ReportLastSystemError("cmake_symlink_library");
+ result = 1;
+ }
+ }
+ if (name != soName) {
+ if (!cmcmd::SymlinkInternal(soName, name)) {
+ cmSystemTools::ReportLastSystemError("cmake_symlink_library");
+ result = 1;
+ }
+ }
+ return result;
+}
+
+int cmcmd::SymlinkExecutable(std::vector<std::string>& args)
+{
+ int result = 0;
+ std::string const& realName = args[2];
+ std::string const& name = args[3];
+ if (name != realName) {
+ if (!cmcmd::SymlinkInternal(realName, name)) {
+ cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
+ result = 1;
+ }
+ }
+ return result;
+}
+
+bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link)
+{
+ if (cmSystemTools::FileExists(link.c_str()) ||
+ cmSystemTools::FileIsSymlink(link)) {
+ cmSystemTools::RemoveFile(link);
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str());
+#else
+ std::string linktext = cmSystemTools::GetFilenameName(file);
+ return cmSystemTools::CreateSymlink(linktext, link);
+#endif
+}
+
+static void cmcmdProgressReport(std::string const& dir, std::string const& num)
+{
+ std::string dirName = dir;
+ dirName += "/Progress";
+ std::string fName;
+ FILE* progFile;
+
+ // read the count
+ fName = dirName;
+ fName += "/count.txt";
+ progFile = cmsys::SystemTools::Fopen(fName, "r");
+ int count = 0;
+ if (!progFile) {
+ return;
+ }
+ if (1 != fscanf(progFile, "%i", &count)) {
+ cmSystemTools::Message("Could not read from progress file.");
+ }
+ fclose(progFile);
+
+ const char* last = num.c_str();
+ for (const char* c = last;; ++c) {
+ if (*c == ',' || *c == '\0') {
+ if (c != last) {
+ fName = dirName;
+ fName += "/";
+ fName.append(last, c - last);
+ progFile = cmsys::SystemTools::Fopen(fName, "w");
+ if (progFile) {
+ fprintf(progFile, "empty");
+ fclose(progFile);
+ }
+ }
+ if (*c == '\0') {
+ break;
+ }
+ last = c + 1;
+ }
+ }
+ int fileNum =
+ static_cast<int>(cmsys::Directory::GetNumberOfFilesInDirectory(dirName));
+ if (count > 0) {
+ // print the progress
+ fprintf(stdout, "[%3i%%] ", ((fileNum - 3) * 100) / count);
+ }
+}
+
+int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
+{
+ // The arguments are
+ // argv[0] == <cmake-executable>
+ // argv[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) {
+ // Enable or disable color based on the switch value.
+ std::string value = args[i].substr(9);
+ if (!value.empty()) {
+ enabled = cmSystemTools::IsOn(value.c_str());
+ }
+ } else if (cmHasLiteralPrefix(args[i], "--progress-dir=")) {
+ progressDir = args[i].substr(15);
+ } else if (cmHasLiteralPrefix(args[i], "--progress-num=")) {
+ if (!progressDir.empty()) {
+ std::string const& progressNum = args[i].substr(15);
+ cmcmdProgressReport(progressDir, progressNum);
+ }
+ } else if (args[i] == "--normal") {
+ color = cmsysTerminal_Color_Normal;
+ } else if (args[i] == "--black") {
+ color = cmsysTerminal_Color_ForegroundBlack;
+ } else if (args[i] == "--red") {
+ color = cmsysTerminal_Color_ForegroundRed;
+ } else if (args[i] == "--green") {
+ color = cmsysTerminal_Color_ForegroundGreen;
+ } else if (args[i] == "--yellow") {
+ color = cmsysTerminal_Color_ForegroundYellow;
+ } else if (args[i] == "--blue") {
+ color = cmsysTerminal_Color_ForegroundBlue;
+ } else if (args[i] == "--magenta") {
+ color = cmsysTerminal_Color_ForegroundMagenta;
+ } else if (args[i] == "--cyan") {
+ color = cmsysTerminal_Color_ForegroundCyan;
+ } else if (args[i] == "--white") {
+ color = cmsysTerminal_Color_ForegroundWhite;
+ } else if (args[i] == "--bold") {
+ color |= cmsysTerminal_Color_ForegroundBold;
+ } else if (args[i] == "--no-newline") {
+ newline = false;
+ } else if (args[i] == "--newline") {
+ newline = true;
+ } else {
+ // Color is enabled. Print with the current color.
+ cmSystemTools::MakefileColorEcho(color, args[i].c_str(), newline,
+ enabled);
+ }
+ }
+
+ return 0;
+}
+
+int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
+{
+ // The arguments are
+ // argv[0] == <cmake-executable>
+ // argv[1] == cmake_link_script
+ // argv[2] == <link-script-name>
+ // argv[3] == --verbose=?
+ bool verbose = false;
+ if (args.size() >= 4) {
+ if (args[3].find("--verbose=") == 0) {
+ if (!cmSystemTools::IsOff(args[3].substr(10).c_str())) {
+ verbose = true;
+ }
+ }
+ }
+
+ // Allocate a process instance.
+ cmsysProcess* cp = cmsysProcess_New();
+ if (!cp) {
+ std::cerr << "Error allocating process instance in link script."
+ << std::endl;
+ return 1;
+ }
+
+ // Children should share stdout and stderr with this process.
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
+
+ // Run the command lines verbatim.
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
+
+ // Read command lines from the script.
+ cmsys::ifstream fin(args[2].c_str());
+ if (!fin) {
+ std::cerr << "Error opening link script \"" << args[2] << "\""
+ << std::endl;
+ return 1;
+ }
+
+ // Run one command at a time.
+ std::string command;
+ int result = 0;
+ while (result == 0 && cmSystemTools::GetLineFromStream(fin, command)) {
+ // Skip empty command lines.
+ if (command.find_first_not_of(" \t") == std::string::npos) {
+ continue;
+ }
+
+ // Setup this command line.
+ const char* cmd[2] = { command.c_str(), CM_NULLPTR };
+ cmsysProcess_SetCommand(cp, cmd);
+
+ // Report the command if verbose output is enabled.
+ if (verbose) {
+ std::cout << command << std::endl;
+ }
+
+ // Run the command and wait for it to exit.
+ cmsysProcess_Execute(cp);
+ cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+
+ // Report failure if any.
+ switch (cmsysProcess_GetState(cp)) {
+ case cmsysProcess_State_Exited: {
+ int value = cmsysProcess_GetExitValue(cp);
+ if (value != 0) {
+ result = value;
+ }
+ } break;
+ case cmsysProcess_State_Exception:
+ std::cerr << "Error running link command: "
+ << cmsysProcess_GetExceptionString(cp) << std::endl;
+ result = 1;
+ break;
+ case cmsysProcess_State_Error:
+ std::cerr << "Error running link command: "
+ << cmsysProcess_GetErrorString(cp) << std::endl;
+ result = 2;
+ break;
+ default:
+ break;
+ };
+ }
+
+ // Free the process instance.
+ cmsysProcess_Delete(cp);
+
+ // Return the final resulting return value.
+ return result;
+}
+
+int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name)
+{
+#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__)
+ cmVisualStudioWCEPlatformParser parser(name.c_str());
+ parser.ParseVersion(version);
+ if (parser.Found()) {
+ std::cout << "@echo off" << std::endl;
+ std::cout << "echo Environment Selection: " << name << std::endl;
+ std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl;
+ std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() << std::endl;
+ std::cout << "set LIB=" << parser.GetLibraryDirectories() << std::endl;
+ return 0;
+ }
+#else
+ (void)version;
+#endif
+
+ std::cerr << "Could not find " << name;
+ return -1;
+}
+
+class cmVSLink
+{
+ int Type;
+ bool Verbose;
+ bool Incremental;
+ bool LinkGeneratesManifest;
+ std::vector<std::string> LinkCommand;
+ std::vector<std::string> UserManifests;
+ std::string LinkerManifestFile;
+ std::string ManifestFile;
+ std::string ManifestFileRC;
+ std::string ManifestFileRes;
+ std::string TargetFile;
+
+public:
+ cmVSLink(int type, bool verbose)
+ : Type(type)
+ , Verbose(verbose)
+ , Incremental(false)
+ , LinkGeneratesManifest(true)
+ {
+ }
+ bool Parse(std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd);
+ int Link();
+
+private:
+ int LinkIncremental();
+ int LinkNonIncremental();
+ int RunMT(std::string const& out, bool notify);
+};
+
+// 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)
+{
+ 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) {
+ // check for nmake temporary files
+ 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);
+ }
+ }
+
+ cmVSLink vsLink(type, verbose);
+ if (!vsLink.Parse(expandedArgs.begin() + 2, expandedArgs.end())) {
+ return -1;
+ }
+ return vsLink.Link();
+}
+
+static bool RunCommand(const char* comment, std::vector<std::string>& command,
+ bool verbose, int* retCodeOut = CM_NULLPTR)
+{
+ if (verbose) {
+ std::cout << comment << ":\n";
+ std::cout << cmJoin(command, " ") << "\n";
+ }
+ 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
+ if (retCodeOut) {
+ *retCodeOut = retCode;
+ return true;
+ }
+ if (retCode != 0) {
+ std::cout << comment << " failed. with " << retCode << "\n";
+ }
+ return retCode == 0;
+}
+
+bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
+ std::vector<std::string>::const_iterator argEnd)
+{
+ // Parse our own arguments.
+ std::string intDir;
+ std::vector<std::string>::const_iterator arg = argBeg;
+ while (arg != argEnd && cmHasLiteralPrefix(*arg, "-")) {
+ if (*arg == "--") {
+ ++arg;
+ break;
+ }
+ if (*arg == "--manifests") {
+ for (++arg; arg != argEnd && !cmHasLiteralPrefix(*arg, "-"); ++arg) {
+ this->UserManifests.push_back(*arg);
+ }
+ } else if (cmHasLiteralPrefix(*arg, "--intdir=")) {
+ intDir = arg->substr(9);
+ ++arg;
+ } else {
+ std::cerr << "unknown argument '" << *arg << "'\n";
+ return false;
+ }
+ }
+ if (intDir.empty()) {
+ return false;
+ }
+
+ // The rest of the arguments form the link command.
+ if (arg == argEnd) {
+ return false;
+ }
+ this->LinkCommand.insert(this->LinkCommand.begin(), arg, argEnd);
+
+ // Parse the link command to extract information we need.
+ for (; arg != argEnd; ++arg) {
+ if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL:YES") == 0) {
+ this->Incremental = true;
+ } else if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0) {
+ this->Incremental = true;
+ } else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0) {
+ this->LinkGeneratesManifest = false;
+ } else if (cmHasLiteralPrefix(*arg, "/Fe")) {
+ this->TargetFile = arg->substr(3);
+ } else if (cmHasLiteralPrefix(*arg, "/out:")) {
+ this->TargetFile = arg->substr(5);
+ }
+ }
+
+ if (this->TargetFile.empty()) {
+ return false;
+ }
+
+ this->ManifestFile = intDir + "/embed.manifest";
+ this->LinkerManifestFile = intDir + "/intermediate.manifest";
+
+ if (this->Incremental) {
+ // We will compile a resource containing the manifest and
+ // pass it to the link command.
+ this->ManifestFileRC = intDir + "/manifest.rc";
+ this->ManifestFileRes = intDir + "/manifest.res";
+ } else if (this->UserManifests.empty()) {
+ // Prior to support for user-specified manifests CMake placed the
+ // linker-generated manifest next to the binary (as if it were not to be
+ // embedded) when not linking incrementally. Preserve this behavior.
+ this->ManifestFile = this->TargetFile + ".manifest";
+ this->LinkerManifestFile = this->ManifestFile;
+ }
+
+ if (this->LinkGeneratesManifest) {
+ this->LinkCommand.push_back("/MANIFEST");
+ this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile);
+ }
+
+ return true;
+}
+
+int cmVSLink::Link()
+{
+ if (this->Incremental &&
+ (this->LinkGeneratesManifest || !this->UserManifests.empty())) {
+ if (this->Verbose) {
+ std::cout << "Visual Studio Incremental Link with embedded manifests\n";
+ }
+ return LinkIncremental();
+ }
+ if (this->Verbose) {
+ if (!this->Incremental) {
+ std::cout << "Visual Studio Non-Incremental Link\n";
+ } else {
+ std::cout << "Visual Studio Incremental Link without manifests\n";
+ }
+ }
+ return LinkNonIncremental();
+}
+
+int cmVSLink::LinkIncremental()
+{
+ // This follows the steps listed here:
+ // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
+
+ // 1. Compiler compiles the application and generates the *.obj files.
+ // 2. An empty manifest file is generated if this is a clean build and if
+ // not the previous one is reused.
+ // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
+ // *.res file.
+ // 4. Linker generates the binary (EXE or DLL) with the /incremental
+ // switch and embeds the dummy manifest file. The linker also generates
+ // the real manifest file based on the binaries that your binary depends
+ // on.
+ // 5. The manifest tool (mt.exe) is then used to generate the final
+ // manifest.
+
+ // If the final manifest is changed, then 6 and 7 are run, if not
+ // they are skipped, and it is done.
+
+ // 6. The resource compiler is invoked one more time.
+ // 7. Finally, the Linker does another incremental link, but since the
+ // only thing that has changed is the *.res file that contains the
+ // manifest it is a short link.
+
+ // Create a resource file referencing the manifest.
+ std::string absManifestFile =
+ cmSystemTools::CollapseFullPath(this->ManifestFile);
+ if (this->Verbose) {
+ std::cout << "Create " << this->ManifestFileRC << "\n";
+ }
+ {
+ cmsys::ofstream fout(this->ManifestFileRC.c_str());
+ if (!fout) {
+ return -1;
+ }
+ fout << this->Type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
+ "24 /* RT_MANIFEST */ \""
+ << absManifestFile << "\"";
+ }
+
+ // If we have not previously generated a manifest file,
+ // generate an empty one so the resource compiler succeeds.
+ if (!cmSystemTools::FileExists(this->ManifestFile)) {
+ if (this->Verbose) {
+ std::cout << "Create empty: " << this->ManifestFile << "\n";
+ }
+ cmsys::ofstream foutTmp(this->ManifestFile.c_str());
+ }
+
+ // 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->ManifestFileRC);
+ if (!RunCommand("RC Pass 1", rcCommand, this->Verbose)) {
+ return -1;
+ }
+
+ // Tell the linker to use our manifest compiled into a resource.
+ this->LinkCommand.push_back(this->ManifestFileRes);
+
+ // Run the link command (possibly generates intermediate manifest).
+ if (!RunCommand("LINK Pass 1", this->LinkCommand, this->Verbose)) {
+ 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) {
+ return mtRet;
+ }
+
+ // Compile the resource file again.
+ if (!RunCommand("RC Pass 2", rcCommand, this->Verbose)) {
+ return -1;
+ }
+
+ // Link incrementally again to use the updated resource.
+ if (!RunCommand("FINAL LINK", this->LinkCommand, this->Verbose)) {
+ return -1;
+ }
+ return 0;
+}
+
+int cmVSLink::LinkNonIncremental()
+{
+ // Run the link command (possibly generates intermediate manifest).
+ if (!RunCommand("LINK", this->LinkCommand, this->Verbose)) {
+ return -1;
+ }
+
+ // If we have no manifest files we are done.
+ if (!this->LinkGeneratesManifest && this->UserManifests.empty()) {
+ return 0;
+ }
+
+ // Run the manifest tool to embed the final manifest in the binary.
+ std::string mtOut =
+ "/outputresource:" + this->TargetFile + (this->Type == 1 ? ";#1" : ";#2");
+ return this->RunMT(mtOut, false);
+}
+
+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");
+ if (this->LinkGeneratesManifest) {
+ mtCommand.push_back(this->LinkerManifestFile);
+ }
+ mtCommand.insert(mtCommand.end(), this->UserManifests.begin(),
+ this->UserManifests.end());
+ 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");
+ }
+ int mtRet = 0;
+ if (!RunCommand("MT", mtCommand, this->Verbose, &mtRet)) {
+ return -1;
+ }
+ return mtRet;
+}
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
new file mode 100644
index 000000000..929f1ae47
--- /dev/null
+++ b/Source/cmcmd.h
@@ -0,0 +1,32 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmcmd_h
+#define cmcmd_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmcmd
+{
+public:
+ /**
+ * Execute commands during the build process. Supports options such
+ * as echo, remove file etc.
+ */
+ static int ExecuteCMakeCommand(std::vector<std::string>&);
+
+protected:
+ static int SymlinkLibrary(std::vector<std::string>& args);
+ static int SymlinkExecutable(std::vector<std::string>& 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 WindowsCEEnvironment(const char* version,
+ const std::string& name);
+ static int VisualStudioLink(std::vector<std::string>& args, int type);
+};
+
+#endif
diff --git a/Source/cmparseMSBuildXML.py b/Source/cmparseMSBuildXML.py
index d1b61ef6a..1b38d1547 100755
--- a/Source/cmparseMSBuildXML.py
+++ b/Source/cmparseMSBuildXML.py
@@ -12,6 +12,12 @@
# "${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:
diff --git a/Source/cmw9xcom.cxx b/Source/cmw9xcom.cxx
deleted file mode 100644
index ab238d539..000000000
--- a/Source/cmw9xcom.cxx
+++ /dev/null
@@ -1,45 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#include "cmSystemTools.h"
-#include "cmWin32ProcessExecution.h"
-
-// this is a test driver program for cmake.
-int main (int argc, char *argv[])
-{
- cmSystemTools::EnableMSVCDebugHook();
- if ( argc <= 1 )
- {
- std::cerr << "Usage: " << argv[0] << " executable" << std::endl;
- return 1;
- }
- std::string arg = argv[1];
- if ( (arg.find_first_of(" ") != arg.npos) &&
- (arg.find_first_of("\"") == arg.npos) )
- {
- arg = "\"" + arg + "\"";
- }
- std::string command = arg;
- int cc;
- for ( cc = 2; cc < argc; cc ++ )
- {
- std::string nextArg = argv[cc];
- if ( (nextArg.find_first_of(" ") != nextArg.npos) &&
- (nextArg.find_first_of("\"") == nextArg.npos) )
- {
- nextArg = "\"" + nextArg + "\"";
- }
- command += " ";
- command += nextArg;
- }
-
- return cmWin32ProcessExecution::Windows9xHack(command.c_str());
-}
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index e767a1612..84e815d1d 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -1,344 +1,197 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmConfigure.h"
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+#include "CTest/cmCTestLaunch.h"
+#include "CTest/cmCTestScriptHandler.h"
#include "cmCTest.h"
-#include "cmSystemTools.h"
-
-// Need these for documentation support.
-#include "cmake.h"
#include "cmDocumentation.h"
+#include "cmSystemTools.h"
-#include "CTest/cmCTestScriptHandler.h"
-#include "CTest/cmCTestLaunch.h"
-
-//----------------------------------------------------------------------------
-static const char * cmDocumentationName[][3] =
-{
- {0,
- " ctest - Testing driver provided by CMake.", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char * cmDocumentationUsage[][3] =
-{
- {0,
- " ctest [options]", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char * cmDocumentationDescription[][3] =
-{
- {0,
- "The \"ctest\" executable is the CMake test driver program. "
- "CMake-generated build trees created for projects that use "
- "the ENABLE_TESTING and ADD_TEST commands have testing support. "
- "This program will run the tests and report results.", 0},
- {0,0,0}
-};
-
-//----------------------------------------------------------------------------
-static const char * cmDocumentationOptions[][3] =
-{
- {"-C <cfg>, --build-config <cfg>", "Choose configuration to test.",
- "Some CMake-generated build trees can have multiple build configurations "
- "in the same tree. This option can be used to specify which one should "
- "be tested. Example configurations are \"Debug\" and \"Release\"."},
- {"-V,--verbose", "Enable verbose output from tests.",
- "Test output is normally suppressed and only summary information is "
- "displayed. This option will show all test output."},
- {"-VV,--extra-verbose", "Enable more verbose output from tests.",
- "Test output is normally suppressed and only summary information is "
- "displayed. This option will show even more test output."},
- {"--debug", "Displaying more verbose internals of CTest.",
- "This feature will result in a large number of output that is mostly "
- "useful for debugging dashboard problems."},
- {"--output-on-failure", "Output anything outputted by the test program "
- "if the test should fail. This option can also be enabled by setting "
- "the environment variable CTEST_OUTPUT_ON_FAILURE"},
- {"-F", "Enable failover.", "This option allows ctest to resume a test "
- "set execution that was previously interrupted. If no interruption "
- "occurred, the -F option will have no effect."},
- {"-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the"
- "given number of jobs.",
- "This option tells ctest to run the tests in parallel using given "
- "number of jobs. This option can also be set by setting "
- "the environment variable CTEST_PARALLEL_LEVEL."},
- {"-Q,--quiet", "Make ctest quiet.",
- "This option will suppress all the output. The output log file will "
- "still be generated if the --output-log is specified. Options such "
- "as --verbose, --extra-verbose, and --debug are ignored if --quiet is "
- "specified."},
- {"-O <file>, --output-log <file>", "Output to log file",
- "This option tells ctest to write all its output to a log file."},
- {"-N,--show-only", "Disable actual execution of tests.",
- "This option tells ctest to list the tests that would be run but not "
- "actually run them. Useful in conjunction with the -R and -E options."},
- {"-L <regex>, --label-regex <regex>", "Run tests with labels matching "
- "regular expression.",
- "This option tells ctest to run only the tests whose labels match the "
- "given regular expression."},
- {"-R <regex>, --tests-regex <regex>", "Run tests matching regular "
- "expression.",
- "This option tells ctest to run only the tests whose names match the "
- "given regular expression."},
- {"-E <regex>, --exclude-regex <regex>", "Exclude tests matching regular "
- "expression.",
- "This option tells ctest to NOT run the tests whose names match the "
- "given regular expression."},
- {"-LE <regex>, --label-exclude <regex>", "Exclude tests with labels "
- "matching regular expression.",
- "This option tells ctest to NOT run the tests whose labels match the "
- "given regular expression."},
- {"-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test",
- "This option tells ctest to act as a Dart client and perform "
- "a dashboard test. All tests are <Mode><Test>, where Mode can be "
- "Experimental, Nightly, and Continuous, and Test can be Start, Update, "
- "Configure, Build, Test, Coverage, and Submit."},
- {"-D <var>:<type>=<value>", "Define a variable for script mode",
- "Pass in variable values on the command line. Use in "
- "conjunction with -S to pass variable values to a dashboard script. "
- "Parsing -D arguments as variable values is only attempted if "
- "the value following -D does not match any of the known dashboard "
- "types."},
- {"-M <model>, --test-model <model>", "Sets the model for a dashboard",
- "This option tells ctest to act as a Dart client "
- "where the TestModel can be Experimental, "
- "Nightly, and Continuous. Combining -M and -T is similar to -D"},
- {"-T <action>, --test-action <action>", "Sets the dashboard action to "
- "perform",
- "This option tells ctest to act as a Dart client "
- "and perform some action such as start, build, test etc. "
- "Combining -M and -T is similar to -D"},
- {"--track <track>", "Specify the track to submit dashboard to",
- "Submit dashboard to specified track instead of default one. By "
- "default, the dashboard is submitted to Nightly, Experimental, or "
- "Continuous track, but by specifying this option, the track can be "
- "arbitrary."},
- {"-S <script>, --script <script>", "Execute a dashboard for a "
- "configuration",
- "This option tells ctest to load in a configuration script which sets "
- "a number of parameters such as the binary and source directories. Then "
- "ctest will do what is required to create and run a dashboard. This "
- "option basically sets up a dashboard and then runs ctest -D with the "
- "appropriate options."},
- {"-SP <script>, --script-new-process <script>", "Execute a dashboard for a "
- "configuration",
- "This option does the same operations as -S but it will do them in a "
- "separate process. This is primarily useful in cases where the script "
- "may modify the environment and you do not want the modified environment "
- "to impact other -S scripts."},
- {"-A <file>, --add-notes <file>", "Add a notes file with submission",
- "This option tells ctest to include a notes file when submitting "
- "dashboard. "},
- {"-I [Start,End,Stride,test#,test#|Test file], --tests-information",
- "Run a specific number of tests by number.",
- "This option causes ctest to run tests starting at number Start, ending "
- "at number End, and incrementing by Stride. Any additional numbers after "
- "Stride are considered individual test numbers. Start, End,or stride "
- "can be empty. Optionally a file can be given that contains the same "
- "syntax as the command line."},
- {"-U, --union", "Take the Union of -I and -R",
- "When both -R and -I are specified by default the intersection of "
- "tests are run. By specifying -U the union of tests is run instead."},
- {"--max-width <width>", "Set the max width for a test name to output",
- "Set the maximum width for each test name to show in the output. This "
- "allows the user to widen the output to avoid clipping the test name which "
- "can be very annoying."},
- {"--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1.",
- "This option causes ctest to run tests in either an interactive mode or "
- "a non-interactive mode. On Windows this means that in non-interactive "
- "mode, all system debug pop up windows are blocked. In dashboard mode "
- "(Experimental, Nightly, Continuous), the default is non-interactive. "
- "When just running tests not for a dashboard the default is to allow "
- "popups and interactive "
- "debugging."},
- {"--no-label-summary", "Disable timing summary information for labels.",
- "This option tells ctest not to print summary information for each label "
- "associated with the tests run. If there are no labels on the "
- "tests, nothing extra is printed."},
- {"--build-and-test", "Configure, build and run a test.",
- "This option tells ctest to configure (i.e. run cmake on), build, and or "
- "execute a test. The configure and test steps are optional. The arguments "
- "to this command line are the source and binary directories. By default "
- "this will run CMake on the Source/Bin directories specified unless "
- "--build-nocmake is specified. Both --build-makeprogram and "
- "--build-generator MUST be provided to use --build-and-test. If "
- "--test-command is specified then that will be run after the build is "
- "complete. Other options that affect this mode are --build-target "
- "--build-nocmake, --build-run-dir, "
- "--build-two-config, --build-exe-dir, --build-project,"
- "--build-noclean, --build-options"},
- {"--build-target", "Specify a specific target to build.",
- "This option goes with the --build-and-test option, if left out the all "
- "target is built." },
- {"--build-nocmake", "Run the build without running cmake first.",
- "Skip the cmake step." },
- {"--build-run-dir", "Specify directory to run programs from.",
- "Directory where programs will be after it has been compiled." },
- {"--build-two-config", "Run CMake twice", "" },
- {"--build-exe-dir", "Specify the directory for the executable.", "" },
- {"--build-generator", "Specify the generator to use.", "" },
- {"--build-generator-toolset", "Specify the generator-specific toolset.",""},
- {"--build-project", "Specify the name of the project to build.", "" },
- {"--build-makeprogram", "Specify the make program to use.", "" },
- {"--build-noclean", "Skip the make clean step.", "" },
- {"--build-config-sample",
- "A sample executable to use to determine the configuration",
- "A sample executable to use to determine the configuration that "
- "should be used. e.g. Debug/Release/etc" },
- {"--build-options", "Add extra options to the build step.",
- "This option must be the last option with the exception of --test-command"
- },
-
- {"--test-command", "The test to run with the --build-and-test option.", ""
- },
- {"--test-timeout", "The time limit in seconds, internal use only.", ""
- },
- {"--tomorrow-tag", "Nightly or experimental starts with next day tag.",
- "This is useful if the build will not finish in one day." },
- {"--ctest-config", "The configuration file used to initialize CTest state "
- "when submitting dashboards.",
- "This option tells CTest to use different initialization file instead of "
- "CTestConfiguration.tcl. This way multiple initialization files can be "
- "used for example to submit to multiple dashboards." },
- {"--overwrite", "Overwrite CTest configuration option.",
- "By default ctest uses configuration options from configuration file. "
- "This option will overwrite the configuration option." },
- {"--extra-submit <file>[;<file>]", "Submit extra files to the dashboard.",
- "This option will submit extra files to the dashboard." },
- {"--force-new-ctest-process", "Run child CTest instances as new processes",
- "By default CTest will run child CTest instances within the same process. "
- "If this behavior is not desired, this argument will enforce new "
- "processes for child CTest processes." },
- {"--schedule-random", "Use a random order for scheduling tests",
- "This option will run the tests in a random order. It is commonly used to "
- "detect implicit dependencies in a test suite." },
- {"--submit-index", "Submit individual dashboard tests with specific index",
- "This option allows performing the same CTest action (such as test) "
- "multiple times and submit all stages to the same dashboard (Dart2 "
- "required). Each execution requires different index." },
- {"--timeout <seconds>", "Set a global timeout on all tests.",
- "This option will set a global timeout on all tests that do not already "
- "have a timeout set on them."},
- {"--stop-time <time>", "Set a time at which all tests should stop running.",
- "Set a real time of day at which all tests should timeout. Example: "
- "7:00:00 -0400. Any time format understood by the curl date parser is "
- "accepted. Local time is assumed if no timezone is specified."},
- {"--http1.0", "Submit using HTTP 1.0.",
- "This option will force CTest to use HTTP 1.0 to submit files to the "
- "dashboard, instead of HTTP 1.1."},
- {"--no-compress-output", "Do not compress test output when submitting.",
- "This flag will turn off automatic compression of test output. Use this "
- "to maintain compatibility with an older version of CDash which doesn't "
- "support compressed test output."},
- {"--print-labels", "Print all available test labels.",
- "This option will not run any tests, it will simply print the list of "
- "all labels associated with the test set."},
- {"--help-command <cmd> [<file>]", "Show help for a single command and exit.",
- "Prints the help for the command to stdout or to the specified file." },
- {"--help-command-list [<file>]", "List available commands and exit.",
- "Prints the list of all available listfile commands to stdout or the "
- "specified file." },
- {"--help-commands [<file>]", "Print help for all commands and exit.",
- "Prints the help for all commands to stdout or to the specified file." },
- {0,0,0}
+#include "cmsys/Encoding.hxx"
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmsys/ConsoleBuf.hxx"
+#endif
+#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 }
};
-//----------------------------------------------------------------------------
-static const char * cmDocumentationSeeAlso[][3] =
-{
- {0, "cmake", 0},
- {0, "ccmake", 0},
- {0, 0, 0}
+static const char* cmDocumentationUsage[][2] = { { CM_NULLPTR,
+ " ctest [options]" },
+ { CM_NULLPTR, CM_NULLPTR } };
+
+static const char* cmDocumentationOptions[][2] = {
+ { "-C <cfg>, --build-config <cfg>", "Choose configuration to test." },
+ { "-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" },
+ { "-F", "Enable failover." },
+ { "-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." },
+ { "-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" },
+ { "-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" },
+ { "--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." },
+ { "--no-label-summary", "Disable timing summary information for labels." },
+ { "--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." },
+ { "--build-run-dir", "Specify directory to run programs from." },
+ { "--build-two-config", "Run CMake twice" },
+ { "--build-exe-dir", "Specify the directory for the executable." },
+ { "--build-generator", "Specify the generator to use." },
+ { "--build-generator-platform", "Specify the generator-specific platform." },
+ { "--build-generator-toolset", "Specify the generator-specific toolset." },
+ { "--build-project", "Specify the name of the project to build." },
+ { "--build-makeprogram", "Specify the make program to use." },
+ { "--build-noclean", "Skip the make clean step." },
+ { "--build-config-sample",
+ "A sample executable to use to determine the configuration" },
+ { "--build-options", "Add extra options to the build step." },
+
+ { "--test-command", "The test to run with the --build-and-test option." },
+ { "--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",
+ "Run child CTest instances as new processes" },
+ { "--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." },
+ { "--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 }
};
// this is a test driver program for cmCTest.
-int main (int argc, char *argv[])
+int main(int argc, char const* const* argv)
{
+#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 encoding_args =
+ cmsys::Encoding::CommandLineArguments::Main(argc, argv);
+ argc = encoding_args.argc();
+ argv = encoding_args.argv();
+
cmSystemTools::DoNotInheritStdPipes();
cmSystemTools::EnableMSVCDebugHook();
- cmSystemTools::FindExecutableDirectory(argv[0]);
+ cmSystemTools::FindCMakeResources(argv[0]);
// Dispatch 'ctest --launch' mode directly.
- if(argc >= 2 && strcmp(argv[1], "--launch") == 0)
- {
+ if (argc >= 2 && strcmp(argv[1], "--launch") == 0) {
return cmCTestLaunch::Main(argc, argv);
- }
+ }
cmCTest inst;
- if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
- {
+ if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
cmCTestLog(&inst, ERROR_MESSAGE,
- "Current working directory cannot be established." << std::endl);
+ "Current working directory cannot be established."
+ << std::endl);
return 1;
- }
+ }
// If there is a testing input file, check for documentation options
// only if there are actually arguments. We want running without
// arguments to run tests.
- if(argc > 1 || !(cmSystemTools::FileExists("CTestTestfile.cmake") ||
- cmSystemTools::FileExists("DartTestfile.txt")))
- {
- if(argc == 1)
- {
+ if (argc > 1 ||
+ !(cmSystemTools::FileExists("CTestTestfile.cmake") ||
+ cmSystemTools::FileExists("DartTestfile.txt"))) {
+ if (argc == 1) {
cmCTestLog(&inst, ERROR_MESSAGE, "*********************************"
- << std::endl
- << "No test configuration file found!" << std::endl
- << "*********************************" << std::endl);
- }
+ << std::endl
+ << "No test configuration file found!" << std::endl
+ << "*********************************" << std::endl);
+ }
cmDocumentation doc;
doc.addCTestStandardDocSections();
- if(doc.CheckOptions(argc, argv))
- {
+ if (doc.CheckOptions(argc, argv)) {
// Construct and print requested documentation.
- std::vector<cmDocumentationEntry> commands;
cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(inst.GetHandler("script"));
+ static_cast<cmCTestScriptHandler*>(inst.GetHandler("script"));
ch->CreateCMake();
- ch->GetCommandDocumentation(commands);
doc.SetShowGenerators(false);
doc.SetName("ctest");
- doc.SetSection("Name",cmDocumentationName);
- doc.SetSection("Usage",cmDocumentationUsage);
- doc.SetSection("Description",cmDocumentationDescription);
- doc.PrependSection("Options",cmDocumentationOptions);
- doc.SetSection("Commands",commands);
- doc.SetSeeAlsoList(cmDocumentationSeeAlso);
-#ifdef cout
-# undef cout
-#endif
- return doc.PrintRequestedDocumentation(std::cout)? 0:1;
-#define cout no_cout_use_cmCTestLog
- }
+ doc.SetSection("Name", cmDocumentationName);
+ doc.SetSection("Usage", cmDocumentationUsage);
+ doc.PrependSection("Options", cmDocumentationOptions);
+ return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
}
+ }
-#ifdef _WIN32
- std::string comspec = "cmw9xcom.exe";
- cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
-#endif
// copy the args to a vector
std::vector<std::string> args;
- for(int i =0; i < argc; ++i)
- {
+ for (int i = 0; i < argc; ++i) {
args.push_back(argv[i]);
- }
+ }
// run ctest
std::string output;
- int res = inst.Run(args,&output);
+ int res = inst.Run(args, &output);
cmCTestLog(&inst, OUTPUT, output);
return res;
}
-
diff --git a/Source/dir.dox b/Source/dir.dox
new file mode 100644
index 000000000..66e3de703
--- /dev/null
+++ b/Source/dir.dox
@@ -0,0 +1,7 @@
+/*!
+
+\dir
+
+\brief Root \c ${CMake_SOURCE_DIR}/Source directory
+
+*/
diff --git a/Source/dir.dox.in b/Source/dir.dox.in
new file mode 100644
index 000000000..78cf58d88
--- /dev/null
+++ b/Source/dir.dox.in
@@ -0,0 +1,7 @@
+/*!
+
+\dir
+
+\brief Generated \c ${CMake_BINARY_DIR}/Source directory
+
+*/
diff --git a/Source/kwsys/.gitattributes b/Source/kwsys/.gitattributes
new file mode 100644
index 000000000..7065eb5cb
--- /dev/null
+++ b/Source/kwsys/.gitattributes
@@ -0,0 +1,13 @@
+.git* export-ignore
+
+*.c kwsys-c-style
+*.c.in kwsys-c-style
+*.cxx kwsys-c-style
+*.h kwsys-c-style
+*.h.in kwsys-c-style
+*.hxx kwsys-c-style
+*.hxx.in kwsys-c-style
+
+*.cmake whitespace=tab-in-indent
+*.rst whitespace=tab-in-indent conflict-marker-size=79
+*.txt whitespace=tab-in-indent
diff --git a/Source/kwsys/Base64.c b/Source/kwsys/Base64.c
index d07bdd01b..99f008e59 100644
--- a/Source/kwsys/Base64.c
+++ b/Source/kwsys/Base64.c
@@ -1,102 +1,76 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Base64.h)
/* 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] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-"abcdefghijklmnopqrstuvwxyz"
-"0123456789+/";
-
-/*--------------------------------------------------------------------------*/
-static const unsigned char kwsysBase64DecodeTable[256] =
-{
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0x3E,0xFF,0xFF,0xFF,0x3F,
- 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,
- 0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,
- 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
- 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
- 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
- 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
- 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
- 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,
- 0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+static const unsigned char kwsysBase64DecodeTable[256] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
+ 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*------------------------------------*/
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
-/*--------------------------------------------------------------------------*/
static unsigned char kwsysBase64EncodeChar(int c)
{
return kwsysBase64EncodeTable[(unsigned char)c];
}
-/*--------------------------------------------------------------------------*/
static unsigned char kwsysBase64DecodeChar(unsigned char c)
{
return kwsysBase64DecodeTable[c];
}
-/*--------------------------------------------------------------------------*/
/* Encode 3 bytes into a 4 byte string. */
-void kwsysBase64_Encode3(const unsigned char *src, unsigned char *dest)
+void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest)
{
dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
- dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30)|((src[1] >> 4) & 0x0F));
- dest[2] = kwsysBase64EncodeChar(((src[1] << 2) & 0x3C)|((src[2] >> 6) & 0x03));
+ dest[1] =
+ kwsysBase64EncodeChar(((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0F));
+ dest[2] =
+ kwsysBase64EncodeChar(((src[1] << 2) & 0x3C) | ((src[2] >> 6) & 0x03));
dest[3] = kwsysBase64EncodeChar(src[2] & 0x3F);
}
-/*--------------------------------------------------------------------------*/
/* Encode 2 bytes into a 4 byte string. */
-void kwsysBase64_Encode2(const unsigned char *src, unsigned char *dest)
+void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest)
{
dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
- dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30)|((src[1] >> 4) & 0x0F));
+ dest[1] =
+ kwsysBase64EncodeChar(((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0F));
dest[2] = kwsysBase64EncodeChar(((src[1] << 2) & 0x3C));
dest[3] = '=';
}
-/*--------------------------------------------------------------------------*/
/* Encode 1 bytes into a 4 byte string. */
-void kwsysBase64_Encode1(const unsigned char *src, unsigned char *dest)
+void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest)
{
dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30));
@@ -104,7 +78,6 @@ void kwsysBase64_Encode1(const unsigned char *src, unsigned char *dest)
dest[3] = '=';
}
-/*--------------------------------------------------------------------------*/
/* Encode 'length' bytes from the input buffer and store the
encoded stream into the output buffer. Return the length of the encoded
buffer (output). Note that the output buffer must be allocated by the caller
@@ -115,54 +88,47 @@ void kwsysBase64_Encode1(const unsigned char *src, unsigned char *dest)
actually knowing how much data to expect (if the input is not a multiple of
3 bytes then the extra padding needed to complete the encode 4 bytes will
stop the decoding anyway). */
-unsigned long kwsysBase64_Encode(const unsigned char *input,
- unsigned long length,
- unsigned char *output,
- int mark_end)
+size_t kwsysBase64_Encode(const unsigned char* input, size_t length,
+ unsigned char* output, int mark_end)
{
- const unsigned char *ptr = input;
- const unsigned char *end = input + length;
- unsigned char *optr = output;
+ const unsigned char* ptr = input;
+ const unsigned char* end = input + length;
+ unsigned char* optr = output;
/* Encode complete triplet */
- while ((end - ptr) >= 3)
- {
+ while ((end - ptr) >= 3) {
kwsysBase64_Encode3(ptr, optr);
ptr += 3;
optr += 4;
- }
+ }
/* Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. */
- if (end - ptr == 2)
- {
+ if (end - ptr == 2) {
kwsysBase64_Encode2(ptr, optr);
optr += 4;
- }
+ }
/* Encodes a 1-byte ending into 2 bytes and 2 pad bytes */
-
- else if (end - ptr == 1)
- {
+
+ else if (end - ptr == 1) {
kwsysBase64_Encode1(ptr, optr);
optr += 4;
- }
+ }
/* Do we need to mark the end */
- else if (mark_end)
- {
+ else if (mark_end) {
optr[0] = optr[1] = optr[2] = optr[3] = '=';
optr += 4;
- }
+ }
- return (unsigned long)(optr - output);
+ return (size_t)(optr - output);
}
-/*--------------------------------------------------------------------------*/
/* Decode 4 bytes into a 3 byte string. */
-int kwsysBase64_Decode3(const unsigned char *src, unsigned char *dest)
+int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest)
{
unsigned char d0, d1, d2, d3;
@@ -170,35 +136,31 @@ int kwsysBase64_Decode3(const unsigned char *src, unsigned char *dest)
d1 = kwsysBase64DecodeChar(src[1]);
d2 = kwsysBase64DecodeChar(src[2]);
d3 = kwsysBase64DecodeChar(src[3]);
-
+
/* Make sure all characters were valid */
- if (d0 == 0xFF || d1 == 0xFF || d2 == 0xFF || d3 == 0xFF)
- {
- return 0;
- }
-
+ if (d0 == 0xFF || d1 == 0xFF || d2 == 0xFF || d3 == 0xFF) {
+ return 0;
+ }
+
/* Decode the 3 bytes */
dest[0] = (unsigned char)(((d0 << 2) & 0xFC) | ((d1 >> 4) & 0x03));
dest[1] = (unsigned char)(((d1 << 4) & 0xF0) | ((d2 >> 2) & 0x0F));
dest[2] = (unsigned char)(((d2 << 6) & 0xC0) | ((d3 >> 0) & 0x3F));
-
+
/* Return the number of bytes actually decoded */
- if (src[2] == '=')
- {
- return 1;
- }
- if (src[3] == '=')
- {
- return 2;
- }
+ if (src[2] == '=') {
+ return 1;
+ }
+ if (src[3] == '=') {
+ return 2;
+ }
return 3;
}
-/*--------------------------------------------------------------------------*/
-/* Decode bytes from the input buffer and store the decoded stream
+/* Decode bytes from the input buffer and store the decoded stream
into the output buffer until 'length' bytes have been decoded. Return the
real length of the decoded stream (which should be equal to 'length'). Note
that the output buffer must be allocated by the caller. If
@@ -207,73 +169,57 @@ int kwsysBase64_Decode3(const unsigned char *src, unsigned char *dest)
'length' parameter is ignored. This enables the caller to decode a stream
without actually knowing how much decoded data to expect (of course, the
buffer must be large enough). */
-unsigned long kwsysBase64_Decode(const unsigned char *input,
- unsigned long length,
- unsigned char *output,
- unsigned long max_input_length)
+size_t kwsysBase64_Decode(const unsigned char* input, size_t length,
+ unsigned char* output, size_t max_input_length)
{
- const unsigned char *ptr = input;
- unsigned char *optr = output;
+ const unsigned char* ptr = input;
+ unsigned char* optr = output;
/* Decode complete triplet */
- if (max_input_length)
- {
- const unsigned char *end = input + max_input_length;
- while (ptr < end)
- {
+ if (max_input_length) {
+ const unsigned char* end = input + max_input_length;
+ while (ptr < end) {
int len = kwsysBase64_Decode3(ptr, optr);
optr += len;
- if(len < 3)
- {
- return (unsigned long)(optr - output);
- }
- ptr += 4;
+ if (len < 3) {
+ return (size_t)(optr - output);
}
- }
- else
- {
- unsigned char *oend = output + length;
- while ((oend - optr) >= 3)
- {
+ ptr += 4;
+ }
+ } else {
+ unsigned char* oend = output + length;
+ while ((oend - optr) >= 3) {
int len = kwsysBase64_Decode3(ptr, optr);
optr += len;
- if(len < 3)
- {
- return (unsigned long)(optr - output);
- }
- ptr += 4;
+ if (len < 3) {
+ return (size_t)(optr - output);
}
+ ptr += 4;
+ }
/* Decode the last triplet */
-
- if (oend - optr == 2)
- {
+
+ if (oend - optr == 2) {
unsigned char temp[3];
int len = kwsysBase64_Decode3(ptr, temp);
- if(len >= 2)
- {
+ if (len >= 2) {
optr[0] = temp[0];
optr[1] = temp[1];
optr += 2;
- }
- else if(len > 0)
- {
+ } else if (len > 0) {
optr[0] = temp[0];
optr += 1;
- }
}
- else if (oend - optr == 1)
- {
+ } else if (oend - optr == 1) {
unsigned char temp[3];
int len = kwsysBase64_Decode3(ptr, temp);
- if(len > 0)
- {
+ if (len > 0) {
optr[0] = temp[0];
optr += 1;
- }
}
}
+ }
- return (unsigned long)(optr - output);
+ return (size_t)(optr - output);
}
diff --git a/Source/kwsys/Base64.h.in b/Source/kwsys/Base64.h.in
index 346800768..35367574a 100644
--- a/Source/kwsys/Base64.h.in
+++ b/Source/kwsys/Base64.h.in
@@ -1,59 +1,51 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Base64_h
#define @KWSYS_NAMESPACE@_Base64_h
#include <@KWSYS_NAMESPACE@/Configure.h>
+#include <stddef.h> /* size_t */
+
/* Redefine all public interface symbol names to be in the proper
namespace. These macros are used internally to kwsys only, and are
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)
-extern "C"
-{
+extern "C" {
#endif
/**
* Encode 3 bytes into a 4 byte string.
*/
-kwsysEXPORT void kwsysBase64_Encode3(const unsigned char *src,
- unsigned char *dest);
+kwsysEXPORT void kwsysBase64_Encode3(const unsigned char* src,
+ unsigned char* dest);
/**
* Encode 2 bytes into a 4 byte string.
*/
-kwsysEXPORT void kwsysBase64_Encode2(const unsigned char *src,
- unsigned char *dest);
+kwsysEXPORT void kwsysBase64_Encode2(const unsigned char* src,
+ unsigned char* dest);
/**
* Encode 1 bytes into a 4 byte string.
*/
-kwsysEXPORT void kwsysBase64_Encode1(const unsigned char *src,
- unsigned char *dest);
+kwsysEXPORT void kwsysBase64_Encode1(const unsigned char* src,
+ unsigned char* dest);
/**
* Encode 'length' bytes from the input buffer and store the encoded
@@ -68,17 +60,16 @@ kwsysEXPORT void kwsysBase64_Encode1(const unsigned char *src,
* the extra padding needed to complete the encode 4 bytes will stop
* the decoding anyway).
*/
-kwsysEXPORT unsigned long kwsysBase64_Encode(const unsigned char *input,
- unsigned long length,
- unsigned char *output,
- int mark_end);
+kwsysEXPORT size_t kwsysBase64_Encode(const unsigned char* input,
+ size_t length, unsigned char* output,
+ int mark_end);
/**
* Decode 4 bytes into a 3 byte string. Returns the number of bytes
* actually decoded.
*/
-kwsysEXPORT int kwsysBase64_Decode3(const unsigned char *src,
- unsigned char *dest);
+kwsysEXPORT int kwsysBase64_Decode3(const unsigned char* src,
+ unsigned char* dest);
/**
* Decode bytes from the input buffer and store the decoded stream
@@ -92,10 +83,9 @@ kwsysEXPORT int kwsysBase64_Decode3(const unsigned char *src,
* much decoded data to expect (of course, the buffer must be large
* enough).
*/
-kwsysEXPORT unsigned long kwsysBase64_Decode(const unsigned char *input,
- unsigned long length,
- unsigned char *output,
- unsigned long max_input_length);
+kwsysEXPORT size_t kwsysBase64_Decode(const unsigned char* input,
+ size_t length, unsigned char* output,
+ size_t max_input_length);
#if defined(__cplusplus)
} /* extern "C" */
@@ -104,17 +94,17 @@ kwsysEXPORT unsigned long 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/CMakeEmptyInputFile.in b/Source/kwsys/CMakeEmptyInputFile.in
deleted file mode 100644
index 40b7ea245..000000000
--- a/Source/kwsys/CMakeEmptyInputFile.in
+++ /dev/null
@@ -1 +0,0 @@
-@CMAKE_EMPTY_INPUT_FILE_CONTENT@
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 0f2783689..e915b1a80 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -1,14 +1,5 @@
-#=============================================================================
-# KWSys - Kitware System Library
-# Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing#kwsys for details.
# The Kitware System Library is intended to be included in other
# projects. It is completely configurable in that the library's
@@ -35,15 +26,6 @@
# SET(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR})
# INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
#
-# KWSYS_IOS_FORCE_OLD = Force use of old non-ANSI C++ streams even if
-# new streams are available. This may be used
-# by projects that cannot configure their
-# streams library.
-# Example:
-#
-# SET(KWSYS_IOS_FORCE_OLD 1)
-#
-#
# Optional settings to setup install rules are as follows:
#
# KWSYS_INSTALL_BIN_DIR = The installation target directories into
@@ -85,6 +67,17 @@
# written.
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 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.
+ )
+ 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.
@@ -93,7 +86,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR)
IF(NOT KWSYS_NAMESPACE)
SET(KWSYS_NAMESPACE "kwsys")
SET(KWSYS_STANDALONE 1)
-ENDIF(NOT KWSYS_NAMESPACE)
+ENDIF()
#-----------------------------------------------------------------------------
# The project name is that of the specified namespace.
@@ -112,6 +105,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_USE_Base64 1)
SET(KWSYS_USE_Directory 1)
SET(KWSYS_USE_DynamicLoader 1)
+ SET(KWSYS_USE_Encoding 1)
SET(KWSYS_USE_Glob 1)
SET(KWSYS_USE_MD5 1)
SET(KWSYS_USE_Process 1)
@@ -119,36 +113,58 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_USE_System 1)
SET(KWSYS_USE_SystemTools 1)
SET(KWSYS_USE_CommandLineArguments 1)
- SET(KWSYS_USE_FundamentalType 1)
SET(KWSYS_USE_Terminal 1)
SET(KWSYS_USE_IOStream 1)
+ SET(KWSYS_USE_FStream 1)
SET(KWSYS_USE_String 1)
SET(KWSYS_USE_SystemInformation 1)
- SET(KWSYS_USE_CPU 1)
-ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
+ SET(KWSYS_USE_ConsoleBuf 1)
+ENDIF()
# Enforce component dependencies.
IF(KWSYS_USE_SystemTools)
SET(KWSYS_USE_Directory 1)
-ENDIF(KWSYS_USE_SystemTools)
+ SET(KWSYS_USE_FStream 1)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
IF(KWSYS_USE_Glob)
SET(KWSYS_USE_Directory 1)
SET(KWSYS_USE_SystemTools 1)
SET(KWSYS_USE_RegularExpression 1)
-ENDIF(KWSYS_USE_Glob)
+ SET(KWSYS_USE_FStream 1)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
IF(KWSYS_USE_Process)
SET(KWSYS_USE_System 1)
-ENDIF(KWSYS_USE_Process)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
IF(KWSYS_USE_SystemInformation)
SET(KWSYS_USE_Process 1)
-ENDIF(KWSYS_USE_SystemInformation)
+ENDIF()
+IF(KWSYS_USE_System)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
+IF(KWSYS_USE_Directory)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
+IF(KWSYS_USE_FStream)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
+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(KWSYS_LFS_DISABLE)
+ELSE()
SET(KWSYS_LFS_REQUESTED 1)
-ENDIF(KWSYS_LFS_DISABLE)
+ENDIF()
+
+# Specify default 8 bit encoding for Windows
+IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE)
+ SET(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP)
+ENDIF()
# Enable testing if building standalone.
IF(KWSYS_STANDALONE)
@@ -156,8 +172,8 @@ IF(KWSYS_STANDALONE)
MARK_AS_ADVANCED(BUILD_TESTING DART_ROOT TCL_TCLSH)
IF(BUILD_TESTING)
ENABLE_TESTING()
- ENDIF(BUILD_TESTING)
-ENDIF(KWSYS_STANDALONE)
+ ENDIF()
+ENDIF()
# Include helper macros.
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake)
@@ -173,15 +189,15 @@ INCLUDE_REGULAR_EXPRESSION("^.*$")
IF(NOT KWSYS_INSTALL_INCLUDE_DIR)
STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_INCLUDE_DIR
"${KWSYS_HEADER_INSTALL_DIR}")
-ENDIF(NOT KWSYS_INSTALL_INCLUDE_DIR)
+ENDIF()
IF(NOT KWSYS_INSTALL_LIB_DIR)
STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_LIB_DIR
"${KWSYS_LIBRARY_INSTALL_DIR}")
-ENDIF(NOT KWSYS_INSTALL_LIB_DIR)
+ENDIF()
IF(NOT KWSYS_INSTALL_BIN_DIR)
STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_BIN_DIR
"${KWSYS_LIBRARY_INSTALL_DIR}")
-ENDIF(NOT KWSYS_INSTALL_BIN_DIR)
+ENDIF()
# Setup header install rules.
SET(KWSYS_INSTALL_INCLUDE_OPTIONS)
@@ -189,7 +205,7 @@ IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT)
SET(KWSYS_INSTALL_INCLUDE_OPTIONS ${KWSYS_INSTALL_INCLUDE_OPTIONS}
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT}
)
-ENDIF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT)
+ENDIF()
# Setup library install rules.
SET(KWSYS_INSTALL_LIBRARY_RULE)
@@ -206,7 +222,7 @@ IF(KWSYS_INSTALL_LIB_DIR)
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME}
)
- ENDIF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME)
+ ENDIF()
# Install the archive to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
@@ -217,8 +233,8 @@ IF(KWSYS_INSTALL_LIB_DIR)
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT}
)
- ENDIF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT)
-ENDIF(KWSYS_INSTALL_LIB_DIR)
+ ENDIF()
+ENDIF()
IF(KWSYS_INSTALL_BIN_DIR)
# Install the runtime library to the bin directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
@@ -229,8 +245,8 @@ IF(KWSYS_INSTALL_BIN_DIR)
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME}
)
- ENDIF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME)
-ENDIF(KWSYS_INSTALL_BIN_DIR)
+ ENDIF()
+ENDIF()
# Do not support old KWSYS_*a_INSTALL_DIR variable names.
SET(KWSYS_HEADER_INSTALL_DIR)
@@ -241,8 +257,8 @@ STRING(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}"
KWSYS_IN_SOURCE_BUILD)
IF(NOT KWSYS_IN_SOURCE_BUILD)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsysPrivate.h
- ${PROJECT_BINARY_DIR}/kwsysPrivate.h COPY_ONLY IMMEDIATE)
-ENDIF(NOT KWSYS_IN_SOURCE_BUILD)
+ ${PROJECT_BINARY_DIR}/kwsysPrivate.h COPYONLY IMMEDIATE)
+ENDIF()
# Select plugin module file name convention.
IF(NOT KWSYS_DynamicLoader_PREFIX)
@@ -256,7 +272,7 @@ ENDIF()
# We require ANSI support from the C compiler. Add any needed flags.
IF(CMAKE_ANSI_CFLAGS)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}")
-ENDIF(CMAKE_ANSI_CFLAGS)
+ENDIF()
#-----------------------------------------------------------------------------
# Adjust compiler flags for some platforms.
@@ -268,15 +284,31 @@ IF(NOT CMAKE_COMPILER_IS_GNUCXX)
KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE "${CMAKE_CXX_FLAGS}")
IF(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local")
- ENDIF(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL)
+ ENDIF()
IF(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no_implicit_include")
- ENDIF(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE)
- ENDIF(CMAKE_SYSTEM MATCHES "OSF1-V.*")
+ ENDIF()
+ ENDIF()
IF(CMAKE_SYSTEM MATCHES "HP-UX")
SET(KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS "+p")
- ENDIF(CMAKE_SYSTEM MATCHES "HP-UX")
-ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX)
+ IF(CMAKE_CXX_COMPILER_ID MATCHES "HP")
+ # it is known that version 3.85 fails and 6.25 works without these flags
+ IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4)
+ # use new C++ library and improved template support
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -AA +hpxstd98")
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ENDIF()
+IF(KWSYS_STANDALONE)
+ IF(CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
+ IF(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03")
+ ELSE()
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -library=stlport4")
+ ENDIF()
+ ENDIF()
+ENDIF()
#-----------------------------------------------------------------------------
# Configure Large File Support.
@@ -296,121 +328,17 @@ IF(KWSYS_LFS_REQUESTED)
IF(KWSYS_LFS_WORKS)
SET(KWSYS_LFS_AVAILABLE 1)
- ENDIF(KWSYS_LFS_WORKS)
-ELSE(KWSYS_LFS_REQUESTED)
+ ENDIF()
+ELSE()
# Large File Support is not requested.
SET(KWSYS_LFS_REQUESTED 0)
-ENDIF(KWSYS_LFS_REQUESTED)
+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.
-KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAVE_STD
- "Checking whether STL classes are in std namespace" DIRECT)
-
-IF(KWSYS_IOS_FORCE_OLD)
- SET(KWSYS_IOS_USE_ANSI 0)
-ELSE(KWSYS_IOS_FORCE_OLD)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_ANSI
- "Checking whether ANSI stream headers are available" DIRECT)
-ENDIF(KWSYS_IOS_FORCE_OLD)
-
-IF(KWSYS_IOS_USE_ANSI)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAVE_STD
- "Checking whether ANSI streams are in std namespace" DIRECT)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_SSTREAM
- "Checking whether ANSI string stream is available" DIRECT)
-ELSE(KWSYS_IOS_USE_ANSI)
- SET(KWSYS_IOS_HAVE_STD 0)
- SET(KWSYS_IOS_USE_SSTREAM 0)
-ENDIF(KWSYS_IOS_USE_ANSI)
-
-IF(KWSYS_IOS_USE_SSTREAM)
- SET(KWSYS_IOS_USE_STRSTREAM_H 0)
- SET(KWSYS_IOS_USE_STRSTREA_H 0)
-ELSE(KWSYS_IOS_USE_SSTREAM)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_STRSTREAM_H
- "Checking whether strstream.h is available" DIRECT)
- IF(KWSYS_IOS_USE_STRSTREAM_H)
- SET(KWSYS_IOS_USE_STRSTREA_H 0)
- ELSE(KWSYS_IOS_USE_STRSTREAM_H)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_STRSTREA_H
- "Checking whether strstrea.h is available" DIRECT)
- ENDIF(KWSYS_IOS_USE_STRSTREAM_H)
-ENDIF(KWSYS_IOS_USE_SSTREAM)
-
-KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CSTDDEF
- "Checking whether header cstddef is available" DIRECT)
-
-SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
- -DKWSYS_STL_HAVE_STD=${KWSYS_STL_HAVE_STD})
-KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_NEQ_CHAR
- "Checking whether stl string has operator!= for char*" DIRECT)
-KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ITERATOR_TRAITS
- "Checking whether stl has iterator_traits" DIRECT)
-IF(KWSYS_STL_HAS_ITERATOR_TRAITS)
- SET(KWSYS_STL_HAS_ITERATOR_CATEGORY 0)
- SET(KWSYS_STL_HAS___ITERATOR_CATEGORY 0)
-ELSE(KWSYS_STL_HAS_ITERATOR_TRAITS)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ITERATOR_CATEGORY
- "Checking whether stl has old iterator_category" DIRECT)
- IF(KWSYS_STL_HAS_ITERATOR_CATEGORY)
- SET(KWSYS_STL_HAS___ITERATOR_CATEGORY 0)
- ELSE(KWSYS_STL_HAS_ITERATOR_CATEGORY)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS___ITERATOR_CATEGORY
- "Checking whether stl has internal __iterator_category" DIRECT)
- ENDIF(KWSYS_STL_HAS_ITERATOR_CATEGORY)
-ENDIF(KWSYS_STL_HAS_ITERATOR_TRAITS)
-KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE
- "Checking whether stl has standard template allocator" DIRECT)
-IF(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE)
- SET(KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE 0)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_REBIND
- "Checking for rebind member of stl allocator" DIRECT)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT
- "Checking for non-standard argument to stl allocator<>::max_size" DIRECT)
-ELSE(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE
- "Checking whether stl has old non-template allocator" DIRECT)
- SET(KWSYS_STL_HAS_ALLOCATOR_REBIND 0)
- SET(KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT 0)
-ENDIF(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE)
-KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_OBJECTS
- "Checking whether stl containers support allocator objects." DIRECT)
-IF(KWSYS_IOS_USE_ANSI AND NOT WATCOM)
- # ANSI streams always have string operators.
- SET(KWSYS_STL_STRING_HAVE_OSTREAM 1)
- SET(KWSYS_STL_STRING_HAVE_ISTREAM 1)
-ELSE(KWSYS_IOS_USE_ANSI AND NOT WATCOM)
- # There may not be string operators for old streams.
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_OSTREAM
- "Checking whether stl string has ostream operator<<" DIRECT)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_ISTREAM
- "Checking whether stl string has istream operator>>" DIRECT)
-ENDIF(KWSYS_IOS_USE_ANSI AND NOT WATCOM)
-SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
- -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI}
- -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD})
-KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAVE_BINARY
- "Checking whether ios has binary openmode" DIRECT)
-SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
-
-KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS
- "Checking whether \"<>\" is needed for template friends" INVERT)
-KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_MEMBER_TEMPLATES
- "Checking for member template support" DIRECT)
-KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_FULL_SPECIALIZATION
- "Checking for standard template specialization syntax" DIRECT)
-KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP
- "Checking whether argument dependent lookup is supported" DIRECT)
-
-IF(UNIX)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_STAT_HAS_ST_MTIM
- "Checking whether struct stat has st_mtim member" DIRECT)
-ENDIF(UNIX)
-
# Check existence and uniqueness of long long and __int64.
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_LONG_LONG
"Checking whether C++ compiler has 'long long'" DIRECT)
@@ -444,73 +372,14 @@ IF(KWSYS_CXX_HAS___INT64)
ENDIF()
ENDIF()
-IF(KWSYS_USE_FundamentalType)
+IF(KWSYS_USE_Encoding)
# Look for type size helper macros.
- KWSYS_PLATFORM_INFO_TEST(C KWSYS_C_TYPE_MACROS
- "Checking for C type size macros")
- SET(macro_regex ".*INFO:macro\\[([^]]*)\\].*")
- FOREACH(info ${KWSYS_C_TYPE_MACROS})
- IF("${info}" MATCHES "${macro_regex}")
- STRING(REGEX REPLACE "${macro_regex}" "\\1" macro "${info}")
- SET(KWSYS_C_HAS_MACRO_${macro} 1)
- ENDIF()
- ENDFOREACH()
-
- # Determine type sizes at preprocessing time if possible, and
- # otherwise fall back to a try-compile.
- SET(KWSYS_C_TYPE_NAME_CHAR "char")
- SET(KWSYS_C_TYPE_NAME_SHORT "short")
- SET(KWSYS_C_TYPE_NAME_INT "int")
- SET(KWSYS_C_TYPE_NAME_LONG "long")
- SET(KWSYS_C_TYPE_NAME_LONG_LONG "long long")
- SET(KWSYS_C_TYPE_NAME___INT64 "__int64")
- FOREACH(type CHAR SHORT INT LONG LONG_LONG __INT64)
- IF(KWSYS_C_HAS_MACRO___SIZEOF_${type}__)
- # Use __SIZEOF_${type}__ macro.
- SET(KWSYS_SIZEOF_${type} TRUE)
- SET(KWSYS_C_CODE_SIZEOF_${type} "#define ${KWSYS_NAMESPACE}_SIZEOF_${type} __SIZEOF_${type}__")
- ELSEIF(KWSYS_C_HAS_MACRO___${type}_MAX__)
- # Use __${type}_MAX__ macro.
- SET(KWSYS_SIZEOF_${type} TRUE)
- SET(KWSYS_C_CODE_SIZEOF_${type} "#if __${type}_MAX__ == 0x7f
-# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 1
-#elif __${type}_MAX__ == 0x7fff
-# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 2
-#elif __${type}_MAX__ == 0x7fffffff
-# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 4
-#elif __${type}_MAX__>>32 == 0x7fffffff
-# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 8
-#else
-# error \"Cannot determine sizeof(${KWSYS_C_TYPE_NAME_${type}}).\"
-#endif")
- ELSE()
- # Configure a hard-coded type size.
- CHECK_TYPE_SIZE("${KWSYS_C_TYPE_NAME_${type}}" KWSYS_SIZEOF_${type})
- IF(NOT KWSYS_SIZEOF_${type})
- SET(KWSYS_SIZEOF_${type} 0)
- ENDIF()
- SET(KWSYS_C_CODE_SIZEOF_${type}
- "#define ${KWSYS_NAMESPACE}_SIZEOF_${type} ${KWSYS_SIZEOF_${type}}")
- ENDIF()
- ENDFOREACH()
-
- IF(KWSYS_USE___INT64)
- KWSYS_PLATFORM_CXX_TEST(KWSYS_CAN_CONVERT_UI64_TO_DOUBLE
- "Checking whether unsigned __int64 can convert to double" DIRECT)
- ELSE(KWSYS_USE___INT64)
- SET(KWSYS_CAN_CONVERT_UI64_TO_DOUBLE 1)
- ENDIF(KWSYS_USE___INT64)
-
- # Check signedness of "char" type.
- KWSYS_PLATFORM_CXX_TEST_RUN(KWSYS_CHAR_IS_SIGNED
- "Checking whether char is signed" DIRECT)
-ENDIF(KWSYS_USE_FundamentalType)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_WSTRING
+ "Checking whether wstring is available" DIRECT)
+ENDIF()
IF(KWSYS_USE_IOStream)
# Determine whether iostreams support long long.
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
- -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI}
- -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD})
IF(KWSYS_CXX_HAS_LONG_LONG)
KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM_LONG_LONG
"Checking if istream supports long long" DIRECT)
@@ -529,27 +398,26 @@ IF(KWSYS_USE_IOStream)
SET(KWSYS_IOS_HAS_ISTREAM___INT64 0)
SET(KWSYS_IOS_HAS_OSTREAM___INT64 0)
ENDIF()
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
-ENDIF(KWSYS_USE_IOStream)
+ENDIF()
IF(KWSYS_NAMESPACE MATCHES "^kwsys$")
SET(KWSYS_NAME_IS_KWSYS 1)
-ELSE(KWSYS_NAMESPACE MATCHES "^kwsys$")
+ELSE()
SET(KWSYS_NAME_IS_KWSYS 0)
-ENDIF(KWSYS_NAMESPACE MATCHES "^kwsys$")
+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(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$")
+ENDIF()
IF(KWSYS_BUILD_SHARED)
SET(KWSYS_BUILD_SHARED 1)
SET(KWSYS_LIBRARY_TYPE SHARED)
-ELSE(KWSYS_BUILD_SHARED)
+ELSE()
SET(KWSYS_BUILD_SHARED 0)
SET(KWSYS_LIBRARY_TYPE STATIC)
-ENDIF(KWSYS_BUILD_SHARED)
+ENDIF()
#-----------------------------------------------------------------------------
# Configure some implementation details.
@@ -562,6 +430,17 @@ 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}"
)
+IF(KWSYS_USE_DynamicLoader)
+ GET_PROPERTY(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
+ IF(KWSYS_SUPPORTS_SHARED_LIBS)
+ SET(KWSYS_SUPPORTS_SHARED_LIBS 1)
+ ELSE()
+ SET(KWSYS_SUPPORTS_SHARED_LIBS 0)
+ ENDIF()
+ SET_PROPERTY(SOURCE DynamicLoader.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ KWSYS_SUPPORTS_SHARED_LIBS=${KWSYS_SUPPORTS_SHARED_LIBS})
+ENDIF()
+
IF(KWSYS_USE_SystemTools)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV
"Checking whether CXX compiler has setenv" DIRECT)
@@ -573,12 +452,18 @@ IF(KWSYS_USE_SystemTools)
"Checking whether CXX compiler has utimes" DIRECT)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMENSAT
"Checking whether CXX compiler has utimensat" DIRECT)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_STAT_HAS_ST_MTIM
+ "Checking whether CXX compiler struct stat has st_mtim member" DIRECT)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
+ "Checking whether CXX compiler struct stat has st_mtimespec member" DIRECT)
SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS
KWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV}
KWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV}
KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H}
KWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES}
KWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT}
+ KWSYS_CXX_STAT_HAS_ST_MTIM=${KWSYS_CXX_STAT_HAS_ST_MTIM}
+ KWSYS_CXX_STAT_HAS_ST_MTIMESPEC=${KWSYS_CXX_STAT_HAS_ST_MTIMESPEC}
)
ENDIF()
@@ -655,6 +540,7 @@ IF(KWSYS_USE_SystemInformation)
# usually it's in libc but on FreeBSD
# it's in libexecinfo
FIND_LIBRARY(EXECINFO_LIB "execinfo")
+ MARK_AS_ADVANCED(EXECINFO_LIB)
IF (NOT EXECINFO_LIB)
SET(EXECINFO_LIB "")
ENDIF()
@@ -745,13 +631,27 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1)
ENDIF()
+
+ IF(UNIX AND NOT CYGWIN)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_GETLOADAVG
+ "Checking whether CXX compiler has getloadavg" DIRECT)
+ IF(KWSYS_CXX_HAS_GETLOADAVG)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS_GETLOADAVG=1)
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+IF(KWSYS_USE_FStream)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H
+ "Checking whether <ext/stdio_filebuf.h> is available" DIRECT)
ENDIF()
#-----------------------------------------------------------------------------
# Choose a directory for the generated headers.
IF(NOT KWSYS_HEADER_ROOT)
SET(KWSYS_HEADER_ROOT "${PROJECT_BINARY_DIR}")
-ENDIF(NOT KWSYS_HEADER_ROOT)
+ENDIF()
SET(KWSYS_HEADER_DIR "${KWSYS_HEADER_ROOT}/${KWSYS_NAMESPACE}")
INCLUDE_DIRECTORIES(${KWSYS_HEADER_ROOT})
@@ -763,91 +663,13 @@ IF(KWSYS_INSTALL_DOC_DIR)
SET(KWSYS_INSTALL_LICENSE_OPTIONS ${KWSYS_INSTALL_LICENSE_OPTIONS}
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME}
)
- ENDIF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME)
+ ENDIF()
# Install the license under the documentation directory.
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt
DESTINATION ${KWSYS_INSTALL_DOC_DIR}/${KWSYS_NAMESPACE}
${KWSYS_INSTALL_LICENSE_OPTIONS})
-ENDIF(KWSYS_INSTALL_DOC_DIR)
-
-#-----------------------------------------------------------------------------
-# Create STL header wrappers to block warnings in the STL headers and
-# give standard names by which they may be included.
-SET(KWSYS_STL_HEADER_EXTRA_string 1)
-FOREACH(header
- algorithm
- deque
- exception
- functional
- iterator
- list
- map
- memory
- new
- numeric
- queue
- set
- stack
- stdexcept
- string
- utility
- vector
- )
- # Configure the header wrapper.
- SET(KWSYS_STL_HEADER "${header}")
- IF(KWSYS_STL_HEADER_EXTRA_${header})
- SET(KWSYS_STL_HEADER_EXTRA
- "#define ${KWSYS_NAMESPACE}_stl_${header}_including_hxx\n# include <${KWSYS_NAMESPACE}/stl/${header}.hxx>\n#undef ${KWSYS_NAMESPACE}_stl_${header}_including_hxx\n")
- CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_stl_${header}.hxx.in
- ${KWSYS_HEADER_DIR}/stl/${header}.hxx
- @ONLY IMMEDIATE)
- IF(KWSYS_INSTALL_INCLUDE_DIR)
- INSTALL(FILES ${KWSYS_HEADER_DIR}/stl/${header}.hxx
- DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}/stl
- ${KWSYS_INSTALL_INCLUDE_OPTIONS})
- ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
- ELSE(KWSYS_STL_HEADER_EXTRA_${header})
- SET(KWSYS_STL_HEADER_EXTRA "")
- ENDIF(KWSYS_STL_HEADER_EXTRA_${header})
- CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_stl.hxx.in
- ${KWSYS_HEADER_DIR}/stl/${header}
- @ONLY IMMEDIATE)
-
- # Create an install target for the header wrapper.
- IF(KWSYS_INSTALL_INCLUDE_DIR)
- INSTALL(FILES ${KWSYS_HEADER_DIR}/stl/${header}
- DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}/stl
- ${KWSYS_INSTALL_INCLUDE_OPTIONS})
- ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
-ENDFOREACH(header)
-
-# Provide cstddef header.
-CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_cstddef.hxx.in
- ${KWSYS_HEADER_DIR}/cstddef
- @ONLY IMMEDIATE)
-IF(KWSYS_INSTALL_INCLUDE_DIR)
- INSTALL(FILES ${KWSYS_HEADER_DIR}/cstddef
- DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}
- ${KWSYS_INSTALL_INCLUDE_OPTIONS})
-ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
-
-#-----------------------------------------------------------------------------
-# Create streams header wrappers to give standard names by which they
-# may be included.
-FOREACH(header iostream fstream sstream iosfwd)
- # Configure the header wrapper.
- CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_ios_${header}.h.in
- ${KWSYS_HEADER_DIR}/ios/${header}
- @ONLY IMMEDIATE)
-
- # Create an install target for the header wrapper.
- IF(KWSYS_INSTALL_INCLUDE_DIR)
- INSTALL(FILES ${KWSYS_HEADER_DIR}/ios/${header}
- DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}/ios
- ${KWSYS_INSTALL_INCLUDE_OPTIONS})
- ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
-ENDFOREACH(header)
+ENDIF()
#-----------------------------------------------------------------------------
# Build a list of classes and headers we need to implement the
@@ -856,13 +678,12 @@ SET(KWSYS_CLASSES)
SET(KWSYS_H_FILES Configure SharedForward)
SET(KWSYS_HXX_FILES Configure String
hashtable hash_fun hash_map hash_set
- auto_ptr
)
# Add selected C++ classes.
SET(cppclasses
- Directory DynamicLoader Glob RegularExpression SystemTools
- CommandLineArguments IOStream SystemInformation
+ Directory DynamicLoader Encoding Glob RegularExpression SystemTools
+ CommandLineArguments IOStream FStream SystemInformation ConsoleBuf
)
FOREACH(cpp ${cppclasses})
IF(KWSYS_USE_${cpp})
@@ -872,13 +693,13 @@ FOREACH(cpp ${cppclasses})
# Load component-specific CMake code.
IF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake)
INCLUDE(${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake)
- ENDIF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake)
- ENDIF(KWSYS_USE_${cpp})
-ENDFOREACH(cpp)
+ ENDIF()
+ ENDIF()
+ENDFOREACH()
# Add selected C components.
FOREACH(c
- Process Base64 FundamentalType MD5 Terminal System String CPU
+ Process Base64 Encoding MD5 Terminal System String
)
IF(KWSYS_USE_${c})
# Use the corresponding header file.
@@ -887,9 +708,9 @@ FOREACH(c
# Load component-specific CMake code.
IF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${c}.cmake)
INCLUDE(${PROJECT_SOURCE_DIR}/kwsys${c}.cmake)
- ENDIF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${c}.cmake)
- ENDIF(KWSYS_USE_${c})
-ENDFOREACH(c)
+ ENDIF()
+ ENDIF()
+ENDFOREACH()
#-----------------------------------------------------------------------------
# Build a list of sources for the library based on components that are
@@ -902,23 +723,31 @@ IF(KWSYS_USE_Process)
IF(NOT UNIX)
# Use the Windows implementation.
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
- ELSE(NOT UNIX)
+ ELSE()
# Use the UNIX implementation.
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
- ENDIF(NOT UNIX)
-ENDIF(KWSYS_USE_Process)
+ ENDIF()
+ENDIF()
# Add selected C sources.
-FOREACH(c Base64 MD5 Terminal System String)
+FOREACH(c Base64 Encoding MD5 Terminal System String)
IF(KWSYS_USE_${c})
- SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${c}.c)
- ENDIF(KWSYS_USE_${c})
-ENDFOREACH(c)
+ IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}C.c)
+ LIST(APPEND KWSYS_C_SRCS ${c}C.c)
+ ELSE()
+ LIST(APPEND KWSYS_C_SRCS ${c}.c)
+ ENDIF()
+ ENDIF()
+ENDFOREACH()
# Configure headers of C++ classes and construct the list of sources.
FOREACH(c ${KWSYS_CLASSES})
# Add this source to the list of source files for the library.
- SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${c}.cxx)
+ IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}CXX.cxx)
+ LIST(APPEND KWSYS_CXX_SRCS ${c}CXX.cxx)
+ ELSEIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}.cxx)
+ LIST(APPEND KWSYS_CXX_SRCS ${c}.cxx)
+ ENDIF()
# Configure the header for this class.
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx
@@ -930,8 +759,8 @@ FOREACH(c ${KWSYS_CLASSES})
INSTALL(FILES ${KWSYS_HEADER_DIR}/${c}.hxx
DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}
${KWSYS_INSTALL_INCLUDE_OPTIONS})
- ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
-ENDFOREACH(c)
+ ENDIF()
+ENDFOREACH()
# Configure C headers.
FOREACH(h ${KWSYS_H_FILES})
@@ -945,8 +774,8 @@ FOREACH(h ${KWSYS_H_FILES})
INSTALL(FILES ${KWSYS_HEADER_DIR}/${h}.h
DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}
${KWSYS_INSTALL_INCLUDE_OPTIONS})
- ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
-ENDFOREACH(h)
+ ENDIF()
+ENDFOREACH()
# Configure other C++ headers.
FOREACH(h ${KWSYS_HXX_FILES})
@@ -960,20 +789,24 @@ FOREACH(h ${KWSYS_HXX_FILES})
INSTALL(FILES ${KWSYS_HEADER_DIR}/${h}.hxx
DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}
${KWSYS_INSTALL_INCLUDE_OPTIONS})
- ENDIF(KWSYS_INSTALL_INCLUDE_DIR)
-ENDFOREACH(h)
+ ENDIF()
+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_USE_DynamicLoader)
IF(UNIX)
TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
- ENDIF(UNIX)
- ENDIF(KWSYS_USE_DynamicLoader)
+ ENDIF()
+ ENDIF()
IF(KWSYS_USE_SystemInformation)
IF(WIN32)
@@ -990,6 +823,9 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
# for symbol lookup using dladdr
TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
ENDIF()
+ IF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} socket)
+ ENDIF()
ENDIF()
ENDIF()
@@ -998,13 +834,13 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE} PROPERTIES
${KWSYS_PROPERTIES_CXX}
)
- ENDIF(KWSYS_PROPERTIES_CXX)
+ ENDIF()
# Create an install target for the library.
IF(KWSYS_INSTALL_LIBRARY_RULE)
INSTALL(TARGETS ${KWSYS_NAMESPACE} ${KWSYS_INSTALL_LIBRARY_RULE})
- ENDIF(KWSYS_INSTALL_LIBRARY_RULE)
-ENDIF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
+ ENDIF()
+ENDIF()
# Add a C-only library if requested.
IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
@@ -1013,23 +849,23 @@ IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
# Apply user-defined target properties to the library.
IF(KWSYS_PROPERTIES_C)
- SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE} PROPERTIES
+ SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE}_c PROPERTIES
${KWSYS_PROPERTIES_C}
)
- ENDIF(KWSYS_PROPERTIES_C)
+ ENDIF()
# Create an install target for the library.
IF(KWSYS_INSTALL_LIBRARY_RULE)
INSTALL(TARGETS ${KWSYS_NAMESPACE}_c ${KWSYS_INSTALL_LIBRARY_RULE})
- ENDIF(KWSYS_INSTALL_LIBRARY_RULE)
-ENDIF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
+ ENDIF()
+ENDIF()
# For building kwsys itself, we use a macro defined on the command
# line to configure the namespace in the C and C++ source files.
ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}")
# Disable deprecation warnings for standard C functions.
-IF(MSVC OR (WIN32 AND "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$"))
+IF(MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Intel"))
ADD_DEFINITIONS(
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE
@@ -1038,11 +874,22 @@ IF(MSVC OR (WIN32 AND "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$"))
)
ENDIF()
+IF(WIN32)
+ # Help enforce the use of wide Windows apis.
+ ADD_DEFINITIONS(-DUNICODE -D_UNICODE)
+ENDIF()
+
IF(KWSYS_USE_String)
# Activate code in "String.c". See the comment in the source.
SET_SOURCE_FILES_PROPERTIES(String.c PROPERTIES
COMPILE_FLAGS "-DKWSYS_STRING_C")
-ENDIF(KWSYS_USE_String)
+ENDIF()
+
+IF(KWSYS_USE_Encoding)
+ # Set default 8 bit encoding in "EndcodingC.c".
+ SET_PROPERTY(SOURCE EncodingC.c EncodingCXX.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
+ENDIF()
#-----------------------------------------------------------------------------
# Setup testing if not being built as part of another project.
@@ -1052,7 +899,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(EXEC_DIR "${CMAKE_CURRENT_BINARY_DIR}")
IF(EXECUTABLE_OUTPUT_PATH)
SET(EXEC_DIR "${EXECUTABLE_OUTPUT_PATH}")
- ENDIF(EXECUTABLE_OUTPUT_PATH)
+ ENDIF()
# C tests
SET(KWSYS_C_TESTS
@@ -1072,42 +919,72 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
FOREACH(test ${KWSYS_C_TESTS})
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(test)
+ ENDFOREACH()
# C++ tests
IF(NOT WATCOM)
SET(KWSYS_CXX_TESTS
- testAutoPtr
testHashSTL
)
- ENDIF(NOT WATCOM)
+ ENDIF()
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
testIOS
testSystemTools
testCommandLineArguments
testCommandLineArguments1
)
+ IF(KWSYS_STL_HAS_WSTRING)
+ SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
+ testEncoding
+ )
+ ENDIF()
+ IF(KWSYS_USE_FStream)
+ SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
+ testFStream
+ )
+ ENDIF()
+ IF(KWSYS_USE_ConsoleBuf)
+ ADD_EXECUTABLE(testConsoleBufChild testConsoleBufChild.cxx)
+ SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_CLANG_TIDY "")
+ SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_CLANG_TIDY "")
+ 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})
+ SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
+ testConsoleBuf
+ )
+ IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506")
+ set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8)
+ ENDIF()
+ SET_PROPERTY(SOURCE testConsoleBuf.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
+ ENDIF()
IF(KWSYS_USE_SystemInformation)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation)
- ENDIF(KWSYS_USE_SystemInformation)
+ ENDIF()
IF(KWSYS_USE_DynamicLoader)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testDynamicLoader)
# 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})
- ENDIF(KWSYS_USE_DynamicLoader)
+ ENDIF()
CREATE_TEST_SOURCELIST(
KWSYS_CXX_TEST_SRCS ${KWSYS_NAMESPACE}TestsCxx.cxx
${KWSYS_CXX_TESTS}
)
ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS})
+ SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_CLANG_TIDY "")
+ SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_CLANG_TIDY "")
+ 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})
- SET(TEST_SYSTEMTOOLS_BIN_FILE
- "${CMAKE_CURRENT_SOURCE_DIR}/testSystemTools.bin")
- SET(TEST_SYSTEMTOOLS_SRC_FILE
- "${CMAKE_CURRENT_SOURCE_DIR}/testSystemTools.cxx")
+
+ SET(TEST_SYSTEMTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+ SET(TEST_SYSTEMTOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
CONFIGURE_FILE(
${PROJECT_SOURCE_DIR}/testSystemTools.h.in
${PROJECT_BINARY_DIR}/testSystemTools.h)
@@ -1117,7 +994,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/ExtraTest.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake")
SET_DIRECTORY_PROPERTIES(PROPERTIES TEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake")
- ENDIF(CTEST_TEST_KWSYS)
+ ENDIF()
SET(KWSYS_TEST_ARGS_testCommandLineArguments
--another-bool-variable
@@ -1150,7 +1027,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
FOREACH(test ${KWSYS_CXX_TESTS})
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(test)
+ ENDFOREACH()
# Process tests.
ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestProcess testProcess.c)
@@ -1158,16 +1035,23 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestProcess ${KWSYS_NAMESPACE}_c)
IF(NOT CYGWIN)
SET(KWSYS_TEST_PROCESS_7 7)
- ENDIF(NOT CYGWIN)
- FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7})
+ ENDIF()
+ FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7} 9 10)
ADD_TEST(kwsys.testProcess-${n} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestProcess ${n})
SET_PROPERTY(TEST kwsys.testProcess-${n} PROPERTY LABELS ${KWSYS_LABELS_TEST})
SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120)
- ENDFOREACH(n)
+ ENDFOREACH()
# Some Apple compilers produce bad optimizations in this source.
- IF(APPLE AND "${CMAKE_C_COMPILER_ID}" MATCHES "^(GNU|LLVM)$")
+ 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"))
+ # 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)
ENDIF()
# Test SharedForward
@@ -1189,10 +1073,14 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
ENDIF()
+ # Set up ctest custom configuration file.
+ CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/CTestCustom.cmake.in
+ ${PROJECT_BINARY_DIR}/CTestCustom.cmake @ONLY)
+
# Suppress known consistent failures on buggy systems.
IF(KWSYS_TEST_BOGUS_FAILURES)
SET_TESTS_PROPERTIES(${KWSYS_TEST_BOGUS_FAILURES} PROPERTIES WILL_FAIL ON)
ENDIF()
- ENDIF(BUILD_TESTING)
-ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
+ ENDIF()
+ENDIF()
diff --git a/Source/kwsys/CONTRIBUTING.rst b/Source/kwsys/CONTRIBUTING.rst
new file mode 100644
index 000000000..70a313e05
--- /dev/null
+++ b/Source/kwsys/CONTRIBUTING.rst
@@ -0,0 +1,49 @@
+Contributing to KWSys
+*********************
+
+Patches
+=======
+
+KWSys is kept in its own Git repository and shared by several projects
+via copies in their source trees. Changes to KWSys should not be made
+directly in a host project, except perhaps in maintenance branches.
+
+KWSys uses `Kitware's GitLab Instance`_ to manage development and code review.
+To contribute patches:
+
+#. Fork the upstream `KWSys Repository`_ into a personal account.
+#. Base all new work on the upstream ``master`` branch.
+#. Run ``./SetupForDevelopment.sh`` in new local work trees.
+#. Create commits making incremental, distinct, logically complete changes.
+#. Push a topic branch to a personal repository fork on GitLab.
+#. Create a GitLab Merge Request targeting the upstream ``master`` branch.
+
+Once changes are reviewed, tested, and integrated to KWSys upstream then
+copies of KWSys within dependent projects can be updated to get the changes.
+
+.. _`Kitware's GitLab Instance`: https://gitlab.kitware.com
+.. _`KWSys Repository`: https://gitlab.kitware.com/utils/kwsys
+
+Code Style
+==========
+
+We use `clang-format`_ version **3.8** 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
+for which we enforce style. The script also has options to format only
+a subset of files, such as those that are locally modified.
+
+.. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html
+.. _`.clang-format`: .clang-format
+.. _`clang-format.bash`: clang-format.bash
+
+License
+=======
+
+We do not require any formal copyright assignment or contributor license
+agreement. Any contributions intentionally sent upstream are presumed
+to be offered under terms of the OSI-approved BSD 3-clause License.
+See `Copyright.txt`_ for details.
+
+.. _`Copyright.txt`: Copyright.txt
diff --git a/Source/kwsys/CPU.h.in b/Source/kwsys/CPU.h.in
deleted file mode 100644
index 2e1a584b1..000000000
--- a/Source/kwsys/CPU.h.in
+++ /dev/null
@@ -1,125 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_CPU_h
-#define @KWSYS_NAMESPACE@_CPU_h
-
-#include <@KWSYS_NAMESPACE@/Configure.h>
-
-/* Identify possible endian cases. The macro
- @KWSYS_NAMESPACE@_CPU_ENDIAN_ID will be defined to one of these, or
- 0 if unknown. */
-#define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG 4321
-#define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE 1234
-
-/* Apple always defines one of these. */
-#if defined(__LITTLE_ENDIAN__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-#elif defined(__BIG_ENDIAN__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* Alpha */
-#elif defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-
-/* Arm */
-#elif defined(__arm__)
-# if !defined(__ARMEB__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-# else
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-# endif
-
-/* Intel x86 */
-#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-#elif defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-#elif defined(__MWERKS__) && defined(__INTEL__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-
-/* Intel x86-64 */
-#elif defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-#elif defined(__amd64) || defined(__amd64__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-
-/* Intel Architecture-64 (Itanium) */
-#elif defined(__ia64) || defined(__ia64__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-#elif defined(_IA64) || defined(__IA64__) || defined(_M_IA64)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-
-/* PowerPC */
-#elif defined(__powerpc) || defined(__powerpc__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-#elif defined(__ppc) || defined(__ppc__) || defined(__POWERPC__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* SPARC */
-#elif defined(__sparc) || defined(__sparc__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* HP/PA RISC */
-#elif defined(__hppa) || defined(__hppa__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* Motorola 68k */
-#elif defined(__m68k__) || defined(M68000)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* MIPS */
-#elif defined(__mips) || defined(__mips__) || defined(__MIPS__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* RS/6000 */
-#elif defined(__THW_RS600) || defined(_IBMR2) || defined(_POWER)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-#elif defined(_ARCH_PWR) || defined(_ARCH_PWR2)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* System/370 */
-#elif defined(__370__) || defined(__THW_370__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* System/390 */
-#elif defined(__s390__) || defined(__s390x__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* z/Architecture */
-#elif defined(__SYSC_ZARCH__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-
-/* Aarch64 */
-#elif defined(__aarch64__)
-# if !defined(__AARCH64EB__)
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-# else
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-# endif
-
-/* Unknown CPU */
-#else
-# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID 0
-# if !defined(@KWSYS_NAMESPACE@_CPU_UNKNOWN_OKAY)
-# error "The target CPU architecture is not known."
-# endif
-#endif
-
-/* If building a C or C++ file in kwsys itself, give the source file
- access to the macros without a configured namespace. */
-#if defined(KWSYS_NAMESPACE)
-# define KWSYS_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID
-# define KWSYS_CPU_ENDIAN_ID_BIG @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
-# define KWSYS_CPU_ENDIAN_ID_LITTLE @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
-#endif
-
-#endif
diff --git a/Source/kwsys/CTestConfig.cmake b/Source/kwsys/CTestConfig.cmake
index d977b472a..33ea84c9d 100644
--- a/Source/kwsys/CTestConfig.cmake
+++ b/Source/kwsys/CTestConfig.cmake
@@ -1,14 +1,6 @@
-#=============================================================================
-# KWSys - Kitware System Library
-# Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing#kwsys for details.
+
set(CTEST_PROJECT_NAME "KWSys")
set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
set(CTEST_DROP_METHOD "http")
diff --git a/Source/kwsys/CTestCustom.cmake.in b/Source/kwsys/CTestCustom.cmake.in
new file mode 100644
index 000000000..760221b12
--- /dev/null
+++ b/Source/kwsys/CTestCustom.cmake.in
@@ -0,0 +1,14 @@
+# kwsys.testProcess-10 involves sending SIGINT to a child process, which then
+# exits abnormally via a call to _exit(). (On Windows, a call to ExitProcess).
+# Naturally, this results in plenty of memory being "leaked" by this child
+# process - the memory check results are not meaningful in this case.
+#
+# kwsys.testProcess-9 also tests sending SIGINT to a child process. However,
+# normal operation of that test involves the child process timing out, and the
+# host process kills (SIGKILL) it as a result. Since it was SIGKILL'ed, the
+# resulting memory leaks are not logged by valgrind anyway. Therefore, we
+# don't have to exclude it.
+
+list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE
+ kwsys.testProcess-10
+ )
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index ece88ae89..5613bd7ab 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -1,60 +1,46 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(CommandLineArguments.hxx)
#include KWSYS_HEADER(Configure.hxx)
#include KWSYS_HEADER(String.hxx)
-#include KWSYS_HEADER(stl/vector)
-#include KWSYS_HEADER(stl/map)
-#include KWSYS_HEADER(stl/set)
-#include KWSYS_HEADER(ios/sstream)
-#include KWSYS_HEADER(ios/iostream)
-
// 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 "kwsys_stl.hxx.in"
-# include "kwsys_ios_sstream.h.in"
-# include "kwsys_ios_iostream.h.in"
+#include "CommandLineArguments.hxx.in"
+#include "Configure.hxx.in"
+#include "String.hxx.in"
#endif
+#include <iostream>
+#include <map>
+#include <set>
+#include <sstream>
+#include <vector>
+
#include <stdio.h>
#include <stdlib.h>
#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) \
- kwsys_ios::cout << __LINE__ << " CLA: " << x << kwsys_ios::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
-{
+namespace KWSYS_NAMESPACE {
-//----------------------------------------------------------------------------
-//============================================================================
struct CommandLineArgumentsCallbackStructure
{
const char* Argument;
@@ -65,24 +51,27 @@ struct CommandLineArgumentsCallbackStructure
int VariableType;
const char* Help;
};
-
-class CommandLineArgumentsVectorOfStrings :
- public kwsys_stl::vector<kwsys::String> {};
-class CommandLineArgumentsSetOfStrings :
- public kwsys_stl::set<kwsys::String> {};
-class CommandLineArgumentsMapOfStrucs :
- public kwsys_stl::map<kwsys::String,
- CommandLineArgumentsCallbackStructure> {};
+
+class CommandLineArgumentsVectorOfStrings : public std::vector<kwsys::String>
+{
+};
+class CommandLineArgumentsSetOfStrings : public std::set<kwsys::String>
+{
+};
+class CommandLineArgumentsMapOfStrucs
+ : public std::map<kwsys::String, CommandLineArgumentsCallbackStructure>
+{
+};
class CommandLineArgumentsInternal
{
public:
CommandLineArgumentsInternal()
- {
+ {
this->UnknownArgumentCallback = 0;
this->ClientData = 0;
this->LastArgument = 0;
- }
+ }
typedef CommandLineArgumentsVectorOfStrings VectorOfStrings;
typedef CommandLineArgumentsMapOfStrucs CallbacksMap;
@@ -94,16 +83,13 @@ public:
CallbacksMap Callbacks;
CommandLineArguments::ErrorCallbackType UnknownArgumentCallback;
- void* ClientData;
+ void* ClientData;
VectorOfStrings::size_type LastArgument;
VectorOfStrings UnusedArguments;
};
-//============================================================================
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
CommandLineArguments::CommandLineArguments()
{
this->Internals = new CommandLineArguments::Internal;
@@ -112,483 +98,436 @@ CommandLineArguments::CommandLineArguments()
this->StoreUnusedArgumentsFlag = false;
}
-//----------------------------------------------------------------------------
CommandLineArguments::~CommandLineArguments()
{
delete this->Internals;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::Initialize(int argc, const char* const argv[])
{
int cc;
this->Initialize();
this->Internals->Argv0 = argv[0];
- for ( cc = 1; cc < argc; cc ++ )
- {
+ for (cc = 1; cc < argc; cc++) {
this->ProcessArgument(argv[cc]);
- }
+ }
}
-//----------------------------------------------------------------------------
void CommandLineArguments::Initialize(int argc, char* argv[])
{
this->Initialize(argc, static_cast<const char* const*>(argv));
}
-//----------------------------------------------------------------------------
void CommandLineArguments::Initialize()
{
this->Internals->Argv.clear();
this->Internals->LastArgument = 0;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::ProcessArgument(const char* arg)
{
this->Internals->Argv.push_back(arg);
}
-//----------------------------------------------------------------------------
bool CommandLineArguments::GetMatchedArguments(
- kwsys_stl::vector<kwsys_stl::string>* matches,
- const kwsys_stl::string& arg)
+ std::vector<std::string>* matches, const std::string& arg)
{
matches->clear();
CommandLineArguments::Internal::CallbacksMap::iterator it;
// Does the argument match to any we know about?
- for ( it = this->Internals->Callbacks.begin();
- it != this->Internals->Callbacks.end();
- it ++ )
- {
+ for (it = this->Internals->Callbacks.begin();
+ it != this->Internals->Callbacks.end(); it++) {
const CommandLineArguments::Internal::String& parg = it->first;
- CommandLineArgumentsCallbackStructure *cs = &it->second;
+ CommandLineArgumentsCallbackStructure* cs = &it->second;
if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT ||
- cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT)
- {
- if ( arg == parg )
- {
+ cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT) {
+ if (arg == parg) {
matches->push_back(parg);
- }
}
- else if ( arg.find( parg ) == 0 )
- {
+ } else if (arg.find(parg) == 0) {
matches->push_back(parg);
- }
}
- return matches->size() > 0;
+ }
+ return !matches->empty();
}
-//----------------------------------------------------------------------------
int CommandLineArguments::Parse()
{
- kwsys_stl::vector<kwsys_stl::string>::size_type cc;
- kwsys_stl::vector<kwsys_stl::string> matches;
- if ( this->StoreUnusedArgumentsFlag )
- {
+ std::vector<std::string>::size_type cc;
+ std::vector<std::string> matches;
+ if (this->StoreUnusedArgumentsFlag) {
this->Internals->UnusedArguments.clear();
- }
- for ( cc = 0; cc < this->Internals->Argv.size(); cc ++ )
- {
- const kwsys_stl::string& arg = this->Internals->Argv[cc];
+ }
+ for (cc = 0; cc < this->Internals->Argv.size(); cc++) {
+ const std::string& arg = this->Internals->Argv[cc];
CommandLineArguments_DEBUG("Process argument: " << arg);
this->Internals->LastArgument = cc;
- if ( this->GetMatchedArguments(&matches, arg) )
- {
+ if (this->GetMatchedArguments(&matches, arg)) {
// Ok, we found one or more arguments that match what user specified.
// Let's find the longest one.
CommandLineArguments::Internal::VectorOfStrings::size_type kk;
CommandLineArguments::Internal::VectorOfStrings::size_type maxidx = 0;
CommandLineArguments::Internal::String::size_type maxlen = 0;
- for ( kk = 0; kk < matches.size(); kk ++ )
- {
- if ( matches[kk].size() > maxlen )
- {
+ for (kk = 0; kk < matches.size(); kk++) {
+ if (matches[kk].size() > maxlen) {
maxlen = matches[kk].size();
maxidx = kk;
- }
}
+ }
// So, the longest one is probably the right one. Now see if it has any
// additional value
- CommandLineArgumentsCallbackStructure *cs
- = &this->Internals->Callbacks[matches[maxidx]];
- const kwsys_stl::string& sarg = matches[maxidx];
- if ( cs->Argument != sarg )
- {
+ CommandLineArgumentsCallbackStructure* cs =
+ &this->Internals->Callbacks[matches[maxidx]];
+ const std::string& sarg = matches[maxidx];
+ if (cs->Argument != sarg) {
abort();
- }
- switch ( cs->ArgumentType )
- {
- case NO_ARGUMENT:
- // No value
- if ( !this->PopulateVariable(cs, 0) )
- {
- return 0;
+ }
+ switch (cs->ArgumentType) {
+ case NO_ARGUMENT:
+ // No value
+ if (!this->PopulateVariable(cs, 0)) {
+ return 0;
}
- break;
- case SPACE_ARGUMENT:
- if ( cc == this->Internals->Argv.size()-1 )
- {
- this->Internals->LastArgument --;
- return 0;
+ break;
+ case SPACE_ARGUMENT:
+ if (cc == this->Internals->Argv.size() - 1) {
+ this->Internals->LastArgument--;
+ return 0;
}
- CommandLineArguments_DEBUG("This is a space argument: " << arg
- << " value: " << this->Internals->Argv[cc+1].c_str());
- // Value is the next argument
- if ( !this->PopulateVariable(cs, this->Internals->Argv[cc+1].c_str()) )
- {
- return 0;
+ CommandLineArguments_DEBUG("This is a space argument: "
+ << arg << " value: "
+ << this->Internals->Argv[cc + 1]);
+ // Value is the next argument
+ if (!this->PopulateVariable(cs,
+ this->Internals->Argv[cc + 1].c_str())) {
+ return 0;
}
- cc ++;
- break;
- case EQUAL_ARGUMENT:
- if ( arg.size() == sarg.size() || *(arg.c_str() + sarg.size()) != '=' )
- {
- this->Internals->LastArgument --;
- return 0;
+ cc++;
+ break;
+ case EQUAL_ARGUMENT:
+ if (arg.size() == sarg.size() || arg.at(sarg.size()) != '=') {
+ this->Internals->LastArgument--;
+ return 0;
}
- // Value is everythng followed the '=' sign
- if ( !this->PopulateVariable(cs, arg.c_str() + sarg.size() + 1) )
- {
- return 0;
+ // Value is everythng followed the '=' sign
+ if (!this->PopulateVariable(cs, arg.c_str() + sarg.size() + 1)) {
+ return 0;
}
- break;
- case CONCAT_ARGUMENT:
- // Value is whatever follows the argument
- if ( !this->PopulateVariable(cs, arg.c_str() + sarg.size()) )
- {
- return 0;
+ break;
+ case CONCAT_ARGUMENT:
+ // Value is whatever follows the argument
+ if (!this->PopulateVariable(cs, arg.c_str() + sarg.size())) {
+ return 0;
}
- break;
- case MULTI_ARGUMENT:
- // Suck in all the rest of the arguments
- CommandLineArguments_DEBUG("This is a multi argument: " << arg);
- for (cc++; cc < this->Internals->Argv.size(); ++ cc )
- {
- const kwsys_stl::string& marg = this->Internals->Argv[cc];
- CommandLineArguments_DEBUG(" check multi argument value: " << marg);
- if ( this->GetMatchedArguments(&matches, marg) )
- {
- CommandLineArguments_DEBUG("End of multi argument " << arg << " with value: " << marg);
- break;
+ break;
+ case MULTI_ARGUMENT:
+ // Suck in all the rest of the arguments
+ CommandLineArguments_DEBUG("This is a multi argument: " << arg);
+ for (cc++; cc < this->Internals->Argv.size(); ++cc) {
+ const std::string& marg = this->Internals->Argv[cc];
+ CommandLineArguments_DEBUG(
+ " check multi argument value: " << marg);
+ if (this->GetMatchedArguments(&matches, marg)) {
+ CommandLineArguments_DEBUG("End of multi argument "
+ << arg << " with value: " << marg);
+ break;
}
- CommandLineArguments_DEBUG(" populate multi argument value: " << marg);
- if ( !this->PopulateVariable(cs, marg.c_str()) )
- {
- return 0;
+ CommandLineArguments_DEBUG(
+ " populate multi argument value: " << marg);
+ if (!this->PopulateVariable(cs, marg.c_str())) {
+ return 0;
}
}
- if ( cc != this->Internals->Argv.size() )
- {
- CommandLineArguments_DEBUG("Again End of multi argument " << arg);
- cc--;
- continue;
+ if (cc != this->Internals->Argv.size()) {
+ CommandLineArguments_DEBUG("Again End of multi argument " << arg);
+ cc--;
+ continue;
}
- break;
- default:
- kwsys_ios::cerr << "Got unknown argument type: \"" << cs->ArgumentType << "\"" << kwsys_ios::endl;
- this->Internals->LastArgument --;
- return 0;
- }
+ break;
+ default:
+ std::cerr << "Got unknown argument type: \"" << cs->ArgumentType
+ << "\"" << std::endl;
+ this->Internals->LastArgument--;
+ return 0;
}
- else
- {
+ } else {
// Handle unknown arguments
- if ( this->Internals->UnknownArgumentCallback )
- {
- if ( !this->Internals->UnknownArgumentCallback(arg.c_str(),
- this->Internals->ClientData) )
- {
- this->Internals->LastArgument --;
+ if (this->Internals->UnknownArgumentCallback) {
+ if (!this->Internals->UnknownArgumentCallback(
+ arg.c_str(), this->Internals->ClientData)) {
+ this->Internals->LastArgument--;
return 0;
- }
- return 1;
}
- else if ( this->StoreUnusedArgumentsFlag )
- {
+ return 1;
+ } else if (this->StoreUnusedArgumentsFlag) {
CommandLineArguments_DEBUG("Store unused argument " << arg);
- this->Internals->UnusedArguments.push_back(arg.c_str());
- }
- else
- {
- kwsys_ios::cerr << "Got unknown argument: \"" << arg.c_str() << "\"" << kwsys_ios::endl;
- this->Internals->LastArgument --;
+ this->Internals->UnusedArguments.push_back(arg);
+ } else {
+ std::cerr << "Got unknown argument: \"" << arg << "\"" << std::endl;
+ this->Internals->LastArgument--;
return 0;
- }
}
}
+ }
return 1;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv)
{
- CommandLineArguments::Internal::VectorOfStrings::size_type size
- = this->Internals->Argv.size() - this->Internals->LastArgument + 1;
+ CommandLineArguments::Internal::VectorOfStrings::size_type size =
+ this->Internals->Argv.size() - this->Internals->LastArgument + 1;
CommandLineArguments::Internal::VectorOfStrings::size_type cc;
// Copy Argv0 as the first argument
- char** args = new char*[ size ];
- args[0] = new char[ this->Internals->Argv0.size() + 1 ];
+ char** args = new char*[size];
+ args[0] = new char[this->Internals->Argv0.size() + 1];
strcpy(args[0], this->Internals->Argv0.c_str());
int cnt = 1;
// Copy everything after the LastArgument, since that was not parsed.
- for ( cc = this->Internals->LastArgument+1;
- cc < this->Internals->Argv.size(); cc ++ )
- {
- args[cnt] = new char[ this->Internals->Argv[cc].size() + 1];
+ for (cc = this->Internals->LastArgument + 1;
+ cc < this->Internals->Argv.size(); cc++) {
+ args[cnt] = new char[this->Internals->Argv[cc].size() + 1];
strcpy(args[cnt], this->Internals->Argv[cc].c_str());
- cnt ++;
- }
+ cnt++;
+ }
*argc = cnt;
*argv = args;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv)
{
- CommandLineArguments::Internal::VectorOfStrings::size_type size
- = this->Internals->UnusedArguments.size() + 1;
+ CommandLineArguments::Internal::VectorOfStrings::size_type size =
+ this->Internals->UnusedArguments.size() + 1;
CommandLineArguments::Internal::VectorOfStrings::size_type cc;
// Copy Argv0 as the first argument
- char** args = new char*[ size ];
- args[0] = new char[ this->Internals->Argv0.size() + 1 ];
+ char** args = new char*[size];
+ args[0] = new char[this->Internals->Argv0.size() + 1];
strcpy(args[0], this->Internals->Argv0.c_str());
int cnt = 1;
// Copy everything after the LastArgument, since that was not parsed.
- for ( cc = 0;
- cc < this->Internals->UnusedArguments.size(); cc ++ )
- {
- kwsys::String &str = this->Internals->UnusedArguments[cc];
- args[cnt] = new char[ str.size() + 1];
+ for (cc = 0; cc < this->Internals->UnusedArguments.size(); cc++) {
+ kwsys::String& str = this->Internals->UnusedArguments[cc];
+ args[cnt] = new char[str.size() + 1];
strcpy(args[cnt], str.c_str());
- cnt ++;
- }
+ cnt++;
+ }
*argc = cnt;
*argv = args;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv)
{
int cc;
- for ( cc = 0; cc < argc; ++ cc )
- {
- delete [] (*argv)[cc];
- }
- delete [] *argv;
+ for (cc = 0; cc < argc; ++cc) {
+ delete[](*argv)[cc];
+ }
+ delete[] * argv;
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::AddCallback(const char* argument, ArgumentTypeEnum type,
- CallbackType callback, void* call_data, const char* help)
+void CommandLineArguments::AddCallback(const char* argument,
+ ArgumentTypeEnum type,
+ CallbackType callback, void* call_data,
+ const char* help)
{
CommandLineArgumentsCallbackStructure s;
- s.Argument = argument;
+ s.Argument = argument;
s.ArgumentType = type;
- s.Callback = callback;
- s.CallData = call_data;
+ s.Callback = callback;
+ s.CallData = call_data;
s.VariableType = CommandLineArguments::NO_VARIABLE_TYPE;
- s.Variable = 0;
- s.Help = help;
+ s.Variable = 0;
+ s.Help = help;
this->Internals->Callbacks[argument] = s;
this->GenerateHelp();
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
- VariableTypeEnum vtype, void* variable, const char* help)
+void CommandLineArguments::AddArgument(const char* argument,
+ ArgumentTypeEnum type,
+ VariableTypeEnum vtype, void* variable,
+ const char* help)
{
CommandLineArgumentsCallbackStructure s;
- s.Argument = argument;
+ s.Argument = argument;
s.ArgumentType = type;
- s.Callback = 0;
- s.CallData = 0;
+ s.Callback = 0;
+ s.CallData = 0;
s.VariableType = vtype;
- s.Variable = variable;
- s.Help = help;
+ s.Variable = variable;
+ s.Help = help;
this->Internals->Callbacks[argument] = s;
this->GenerateHelp();
}
-//----------------------------------------------------------------------------
-#define CommandLineArgumentsAddArgumentMacro(type, ctype) \
- void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, \
- ctype* variable, const char* help) \
- { \
- this->AddArgument(argument, type, CommandLineArguments::type##_TYPE, variable, help); \
+#define CommandLineArgumentsAddArgumentMacro(type, ctype) \
+ void CommandLineArguments::AddArgument(const char* argument, \
+ ArgumentTypeEnum type, \
+ ctype* variable, const char* help) \
+ { \
+ this->AddArgument(argument, type, CommandLineArguments::type##_TYPE, \
+ variable, help); \
}
-CommandLineArgumentsAddArgumentMacro(BOOL, bool)
-CommandLineArgumentsAddArgumentMacro(INT, int)
-CommandLineArgumentsAddArgumentMacro(DOUBLE, double)
-CommandLineArgumentsAddArgumentMacro(STRING, char*)
-CommandLineArgumentsAddArgumentMacro(STL_STRING, kwsys_stl::string)
-
-CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, kwsys_stl::vector<bool>)
-CommandLineArgumentsAddArgumentMacro(VECTOR_INT, kwsys_stl::vector<int>)
-CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, kwsys_stl::vector<double>)
-CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, kwsys_stl::vector<char*>)
-CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING, kwsys_stl::vector<kwsys_stl::string>)
-
-//----------------------------------------------------------------------------
-#define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype) \
- void CommandLineArguments::AddBooleanArgument(const char* argument, \
- ctype* variable, const char* help) \
- { \
- this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, \
- CommandLineArguments::type##_TYPE, variable, help); \
+/* clang-format off */
+CommandLineArgumentsAddArgumentMacro(BOOL, bool)
+CommandLineArgumentsAddArgumentMacro(INT, int)
+CommandLineArgumentsAddArgumentMacro(DOUBLE, double)
+CommandLineArgumentsAddArgumentMacro(STRING, char*)
+CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string)
+
+CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector<bool>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector<int>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, std::vector<double>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, std::vector<char*>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING,
+ std::vector<std::string>)
+#ifdef HELP_CLANG_FORMAT
+;
+#endif
+/* clang-format on */
+
+#define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype) \
+ void CommandLineArguments::AddBooleanArgument( \
+ const char* argument, ctype* variable, const char* help) \
+ { \
+ this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, \
+ CommandLineArguments::type##_TYPE, variable, help); \
}
-CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool)
-CommandLineArgumentsAddBooleanArgumentMacro(INT, int)
-CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double)
-CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*)
-CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, kwsys_stl::string)
+/* clang-format off */
+CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool)
+CommandLineArgumentsAddBooleanArgumentMacro(INT, int)
+CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double)
+CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*)
+CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, std::string)
+#ifdef HELP_CLANG_FORMAT
+;
+#endif
+/* clang-format on */
-//----------------------------------------------------------------------------
void CommandLineArguments::SetClientData(void* client_data)
{
this->Internals->ClientData = client_data;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::SetUnknownArgumentCallback(
CommandLineArguments::ErrorCallbackType callback)
{
this->Internals->UnknownArgumentCallback = callback;
}
-//----------------------------------------------------------------------------
const char* CommandLineArguments::GetHelp(const char* arg)
{
- CommandLineArguments::Internal::CallbacksMap::iterator it
- = this->Internals->Callbacks.find(arg);
- if ( it == this->Internals->Callbacks.end() )
- {
+ CommandLineArguments::Internal::CallbacksMap::iterator it =
+ this->Internals->Callbacks.find(arg);
+ if (it == this->Internals->Callbacks.end()) {
return 0;
- }
+ }
// Since several arguments may point to the same argument, find the one this
// one point to if this one is pointing to another argument.
- CommandLineArgumentsCallbackStructure *cs = &(it->second);
- for(;;)
- {
- CommandLineArguments::Internal::CallbacksMap::iterator hit
- = this->Internals->Callbacks.find(cs->Help);
- if ( hit == this->Internals->Callbacks.end() )
- {
+ CommandLineArgumentsCallbackStructure* cs = &(it->second);
+ for (;;) {
+ CommandLineArguments::Internal::CallbacksMap::iterator hit =
+ this->Internals->Callbacks.find(cs->Help);
+ if (hit == this->Internals->Callbacks.end()) {
break;
- }
- cs = &(hit->second);
}
+ cs = &(hit->second);
+ }
return cs->Help;
}
-//----------------------------------------------------------------------------
void CommandLineArguments::SetLineLength(unsigned int ll)
{
- if ( ll < 9 || ll > 1000 )
- {
+ if (ll < 9 || ll > 1000) {
return;
- }
+ }
this->LineLength = ll;
this->GenerateHelp();
}
-//----------------------------------------------------------------------------
const char* CommandLineArguments::GetArgv0()
{
return this->Internals->Argv0.c_str();
}
-//----------------------------------------------------------------------------
unsigned int CommandLineArguments::GetLastArgument()
{
return static_cast<unsigned int>(this->Internals->LastArgument + 1);
}
-//----------------------------------------------------------------------------
void CommandLineArguments::GenerateHelp()
{
- kwsys_ios::ostringstream str;
-
+ std::ostringstream str;
+
// Collapse all arguments into the map of vectors of all arguments that do
// the same thing.
CommandLineArguments::Internal::CallbacksMap::iterator it;
- typedef kwsys_stl::map<CommandLineArguments::Internal::String,
- CommandLineArguments::Internal::SetOfStrings > MapArgs;
+ typedef std::map<CommandLineArguments::Internal::String,
+ CommandLineArguments::Internal::SetOfStrings>
+ MapArgs;
MapArgs mp;
MapArgs::iterator mpit, smpit;
- for ( it = this->Internals->Callbacks.begin();
- it != this->Internals->Callbacks.end();
- it ++ )
- {
- CommandLineArgumentsCallbackStructure *cs = &(it->second);
+ for (it = this->Internals->Callbacks.begin();
+ it != this->Internals->Callbacks.end(); it++) {
+ CommandLineArgumentsCallbackStructure* cs = &(it->second);
mpit = mp.find(cs->Help);
- if ( mpit != mp.end() )
- {
+ if (mpit != mp.end()) {
mpit->second.insert(it->first);
mp[it->first].insert(it->first);
- }
- else
- {
+ } else {
mp[it->first].insert(it->first);
- }
}
- for ( it = this->Internals->Callbacks.begin();
- it != this->Internals->Callbacks.end();
- it ++ )
- {
- CommandLineArgumentsCallbackStructure *cs = &(it->second);
+ }
+ for (it = this->Internals->Callbacks.begin();
+ it != this->Internals->Callbacks.end(); it++) {
+ CommandLineArgumentsCallbackStructure* cs = &(it->second);
mpit = mp.find(cs->Help);
- if ( mpit != mp.end() )
- {
+ if (mpit != mp.end()) {
mpit->second.insert(it->first);
smpit = mp.find(it->first);
CommandLineArguments::Internal::SetOfStrings::iterator sit;
- for ( sit = smpit->second.begin(); sit != smpit->second.end(); sit++ )
- {
+ for (sit = smpit->second.begin(); sit != smpit->second.end(); sit++) {
mpit->second.insert(*sit);
- }
- mp.erase(smpit);
}
- else
- {
+ mp.erase(smpit);
+ } else {
mp[it->first].insert(it->first);
- }
}
-
+ }
+
// Find the length of the longest string
CommandLineArguments::Internal::String::size_type maxlen = 0;
- for ( mpit = mp.begin();
- mpit != mp.end();
- mpit ++ )
- {
+ for (mpit = mp.begin(); mpit != mp.end(); mpit++) {
CommandLineArguments::Internal::SetOfStrings::iterator sit;
- for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ )
- {
+ for (sit = mpit->second.begin(); sit != mpit->second.end(); sit++) {
CommandLineArguments::Internal::String::size_type clen = sit->size();
- switch ( this->Internals->Callbacks[*sit].ArgumentType )
- {
- case CommandLineArguments::NO_ARGUMENT: clen += 0; break;
- case CommandLineArguments::CONCAT_ARGUMENT: clen += 3; break;
- case CommandLineArguments::SPACE_ARGUMENT: clen += 4; break;
- case CommandLineArguments::EQUAL_ARGUMENT: clen += 4; break;
- }
- if ( clen > maxlen )
- {
+ switch (this->Internals->Callbacks[*sit].ArgumentType) {
+ case CommandLineArguments::NO_ARGUMENT:
+ clen += 0;
+ break;
+ case CommandLineArguments::CONCAT_ARGUMENT:
+ clen += 3;
+ break;
+ case CommandLineArguments::SPACE_ARGUMENT:
+ clen += 4;
+ break;
+ case CommandLineArguments::EQUAL_ARGUMENT:
+ clen += 4;
+ break;
+ }
+ if (clen > maxlen) {
maxlen = clen;
- }
}
}
+ }
// Create format for that string
char format[80];
@@ -597,74 +536,69 @@ void CommandLineArguments::GenerateHelp()
maxlen += 4; // For the space before and after the option
// Print help for each option
- for ( mpit = mp.begin();
- mpit != mp.end();
- mpit ++ )
- {
+ for (mpit = mp.begin(); mpit != mp.end(); mpit++) {
CommandLineArguments::Internal::SetOfStrings::iterator sit;
- for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ )
- {
- str << kwsys_ios::endl;
+ for (sit = mpit->second.begin(); sit != mpit->second.end(); sit++) {
+ str << std::endl;
char argument[100];
sprintf(argument, "%s", sit->c_str());
- switch ( this->Internals->Callbacks[*sit].ArgumentType )
- {
- case CommandLineArguments::NO_ARGUMENT: break;
- case CommandLineArguments::CONCAT_ARGUMENT: strcat(argument, "opt"); break;
- case CommandLineArguments::SPACE_ARGUMENT: strcat(argument, " opt"); break;
- case CommandLineArguments::EQUAL_ARGUMENT: strcat(argument, "=opt"); break;
- case CommandLineArguments::MULTI_ARGUMENT: strcat(argument, " opt opt ..."); break;
- }
+ switch (this->Internals->Callbacks[*sit].ArgumentType) {
+ case CommandLineArguments::NO_ARGUMENT:
+ break;
+ case CommandLineArguments::CONCAT_ARGUMENT:
+ strcat(argument, "opt");
+ break;
+ case CommandLineArguments::SPACE_ARGUMENT:
+ strcat(argument, " opt");
+ break;
+ case CommandLineArguments::EQUAL_ARGUMENT:
+ strcat(argument, "=opt");
+ break;
+ case CommandLineArguments::MULTI_ARGUMENT:
+ strcat(argument, " opt opt ...");
+ break;
+ }
char buffer[80];
sprintf(buffer, format, argument);
str << buffer;
- }
+ }
const char* ptr = this->Internals->Callbacks[mpit->first].Help;
size_t len = strlen(ptr);
int cnt = 0;
- while ( len > 0)
- {
+ while (len > 0) {
// If argument with help is longer than line length, split it on previous
// space (or tab) and continue on the next line
CommandLineArguments::Internal::String::size_type cc;
- for ( cc = 0; ptr[cc]; cc ++ )
- {
- if ( *ptr == ' ' || *ptr == '\t' )
- {
- ptr ++;
- len --;
- }
+ for (cc = 0; ptr[cc]; cc++) {
+ if (*ptr == ' ' || *ptr == '\t') {
+ ptr++;
+ len--;
}
- if ( cnt > 0 )
- {
- for ( cc = 0; cc < maxlen; cc ++ )
- {
+ }
+ if (cnt > 0) {
+ for (cc = 0; cc < maxlen; cc++) {
str << " ";
- }
}
+ }
CommandLineArguments::Internal::String::size_type skip = len;
- if ( skip > this->LineLength - maxlen )
- {
+ if (skip > this->LineLength - maxlen) {
skip = this->LineLength - maxlen;
- for ( cc = skip-1; cc > 0; cc -- )
- {
- if ( ptr[cc] == ' ' || ptr[cc] == '\t' )
- {
+ for (cc = skip - 1; cc > 0; cc--) {
+ if (ptr[cc] == ' ' || ptr[cc] == '\t') {
break;
- }
}
- if ( cc != 0 )
- {
+ }
+ if (cc != 0) {
skip = cc;
- }
}
- str.write(ptr, static_cast<kwsys_ios::streamsize>(skip));
- str << kwsys_ios::endl;
+ }
+ str.write(ptr, static_cast<std::streamsize>(skip));
+ str << std::endl;
ptr += skip;
len -= skip;
- cnt ++;
- }
+ cnt++;
}
+ }
/*
// This can help debugging help string
str << endl;
@@ -678,182 +612,166 @@ void CommandLineArguments::GenerateHelp()
this->Help = str.str();
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- bool* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(bool* variable,
+ const std::string& value)
{
- if ( value == "1" || value == "ON" || value == "on" || value == "On" ||
- value == "TRUE" || value == "true" || value == "True" ||
- value == "yes" || value == "Yes" || value == "YES" )
- {
+ if (value == "1" || value == "ON" || value == "on" || value == "On" ||
+ value == "TRUE" || value == "true" || value == "True" ||
+ value == "yes" || value == "Yes" || value == "YES") {
*variable = true;
- }
- else
- {
+ } else {
*variable = false;
- }
+ }
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- int* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(int* variable,
+ const std::string& value)
{
char* res = 0;
*variable = static_cast<int>(strtol(value.c_str(), &res, 10));
- //if ( res && *res )
+ // if ( res && *res )
// {
// Can handle non-int
// }
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- double* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(double* variable,
+ const std::string& value)
{
char* res = 0;
*variable = strtod(value.c_str(), &res);
- //if ( res && *res )
+ // if ( res && *res )
// {
// Can handle non-double
// }
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- char** variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(char** variable,
+ const std::string& value)
{
- if ( *variable )
- {
- delete [] *variable;
+ if (*variable) {
+ delete[] * variable;
*variable = 0;
- }
- *variable = new char[ value.size() + 1 ];
+ }
+ *variable = new char[value.size() + 1];
strcpy(*variable, value.c_str());
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- kwsys_stl::string* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(std::string* variable,
+ const std::string& value)
{
*variable = value;
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- kwsys_stl::vector<bool>* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(std::vector<bool>* variable,
+ const std::string& value)
{
bool val = false;
- if ( value == "1" || value == "ON" || value == "on" || value == "On" ||
- value == "TRUE" || value == "true" || value == "True" ||
- value == "yes" || value == "Yes" || value == "YES" )
- {
+ if (value == "1" || value == "ON" || value == "on" || value == "On" ||
+ value == "TRUE" || value == "true" || value == "True" ||
+ value == "yes" || value == "Yes" || value == "YES") {
val = true;
- }
+ }
variable->push_back(val);
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- kwsys_stl::vector<int>* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(std::vector<int>* variable,
+ const std::string& value)
{
char* res = 0;
variable->push_back(static_cast<int>(strtol(value.c_str(), &res, 10)));
- //if ( res && *res )
+ // if ( res && *res )
// {
// Can handle non-int
// }
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- kwsys_stl::vector<double>* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(std::vector<double>* variable,
+ const std::string& value)
{
char* res = 0;
variable->push_back(strtod(value.c_str(), &res));
- //if ( res && *res )
+ // if ( res && *res )
// {
// Can handle non-int
// }
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- kwsys_stl::vector<char*>* variable, const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(std::vector<char*>* variable,
+ const std::string& value)
{
- char* var = new char[ value.size() + 1 ];
+ char* var = new char[value.size() + 1];
strcpy(var, value.c_str());
variable->push_back(var);
}
-//----------------------------------------------------------------------------
-void CommandLineArguments::PopulateVariable(
- kwsys_stl::vector<kwsys_stl::string>* variable,
- const kwsys_stl::string& value)
+void CommandLineArguments::PopulateVariable(std::vector<std::string>* variable,
+ const std::string& value)
{
variable->push_back(value);
}
-//----------------------------------------------------------------------------
-bool CommandLineArguments::PopulateVariable(CommandLineArgumentsCallbackStructure* cs,
- const char* value)
+bool CommandLineArguments::PopulateVariable(
+ CommandLineArgumentsCallbackStructure* cs, const char* value)
{
// Call the callback
- if ( cs->Callback )
- {
- if ( !cs->Callback(cs->Argument, value, cs->CallData) )
- {
- this->Internals->LastArgument --;
+ if (cs->Callback) {
+ if (!cs->Callback(cs->Argument, value, cs->CallData)) {
+ this->Internals->LastArgument--;
return 0;
- }
}
- CommandLineArguments_DEBUG("Set argument: " << cs->Argument << " to " << value);
- if ( cs->Variable )
- {
- kwsys_stl::string var = "1";
- if ( value )
- {
+ }
+ CommandLineArguments_DEBUG("Set argument: " << cs->Argument << " to "
+ << value);
+ if (cs->Variable) {
+ std::string var = "1";
+ if (value) {
var = value;
- }
- switch ( cs->VariableType )
- {
- case CommandLineArguments::INT_TYPE:
- this->PopulateVariable(static_cast<int*>(cs->Variable), var);
- break;
- case CommandLineArguments::DOUBLE_TYPE:
- this->PopulateVariable(static_cast<double*>(cs->Variable), var);
- break;
- case CommandLineArguments::STRING_TYPE:
- this->PopulateVariable(static_cast<char**>(cs->Variable), var);
- break;
- case CommandLineArguments::STL_STRING_TYPE:
- this->PopulateVariable(static_cast<kwsys_stl::string*>(cs->Variable), var);
- break;
- case CommandLineArguments::BOOL_TYPE:
- this->PopulateVariable(static_cast<bool*>(cs->Variable), var);
- break;
- case CommandLineArguments::VECTOR_BOOL_TYPE:
- this->PopulateVariable(static_cast<kwsys_stl::vector<bool>*>(cs->Variable), var);
- break;
- case CommandLineArguments::VECTOR_INT_TYPE:
- this->PopulateVariable(static_cast<kwsys_stl::vector<int>*>(cs->Variable), var);
- break;
- case CommandLineArguments::VECTOR_DOUBLE_TYPE:
- this->PopulateVariable(static_cast<kwsys_stl::vector<double>*>(cs->Variable), var);
- break;
- case CommandLineArguments::VECTOR_STRING_TYPE:
- this->PopulateVariable(static_cast<kwsys_stl::vector<char*>*>(cs->Variable), var);
- break;
- case CommandLineArguments::VECTOR_STL_STRING_TYPE:
- this->PopulateVariable(static_cast<kwsys_stl::vector<kwsys_stl::string>*>(cs->Variable), var);
- break;
- default:
- kwsys_ios::cerr << "Got unknown variable type: \"" << cs->VariableType << "\"" << kwsys_ios::endl;
- this->Internals->LastArgument --;
- return 0;
- }
}
+ switch (cs->VariableType) {
+ case CommandLineArguments::INT_TYPE:
+ this->PopulateVariable(static_cast<int*>(cs->Variable), var);
+ break;
+ case CommandLineArguments::DOUBLE_TYPE:
+ this->PopulateVariable(static_cast<double*>(cs->Variable), var);
+ break;
+ case CommandLineArguments::STRING_TYPE:
+ this->PopulateVariable(static_cast<char**>(cs->Variable), var);
+ break;
+ case CommandLineArguments::STL_STRING_TYPE:
+ this->PopulateVariable(static_cast<std::string*>(cs->Variable), var);
+ break;
+ case CommandLineArguments::BOOL_TYPE:
+ this->PopulateVariable(static_cast<bool*>(cs->Variable), var);
+ break;
+ case CommandLineArguments::VECTOR_BOOL_TYPE:
+ this->PopulateVariable(static_cast<std::vector<bool>*>(cs->Variable),
+ var);
+ break;
+ case CommandLineArguments::VECTOR_INT_TYPE:
+ this->PopulateVariable(static_cast<std::vector<int>*>(cs->Variable),
+ var);
+ break;
+ case CommandLineArguments::VECTOR_DOUBLE_TYPE:
+ this->PopulateVariable(static_cast<std::vector<double>*>(cs->Variable),
+ var);
+ break;
+ case CommandLineArguments::VECTOR_STRING_TYPE:
+ this->PopulateVariable(static_cast<std::vector<char*>*>(cs->Variable),
+ var);
+ break;
+ case CommandLineArguments::VECTOR_STL_STRING_TYPE:
+ this->PopulateVariable(
+ static_cast<std::vector<std::string>*>(cs->Variable), var);
+ break;
+ default:
+ std::cerr << "Got unknown variable type: \"" << cs->VariableType
+ << "\"" << std::endl;
+ this->Internals->LastArgument--;
+ return 0;
+ }
+ }
return 1;
}
-
} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/CommandLineArguments.hxx.in b/Source/kwsys/CommandLineArguments.hxx.in
index cbf6ee393..31115e51f 100644
--- a/Source/kwsys/CommandLineArguments.hxx.in
+++ b/Source/kwsys/CommandLineArguments.hxx.in
@@ -1,30 +1,15 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_CommandLineArguments_hxx
#define @KWSYS_NAMESPACE@_CommandLineArguments_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/Configure.hxx>
-#include <@KWSYS_NAMESPACE@/stl/string>
-#include <@KWSYS_NAMESPACE@/stl/vector>
-
-/* Define this macro temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsys_stl @KWSYS_NAMESPACE@_stl
-#endif
+#include <string>
+#include <vector>
-namespace @KWSYS_NAMESPACE@
-{
+namespace @KWSYS_NAMESPACE@ {
class CommandLineArgumentsInternal;
struct CommandLineArgumentsCallbackStructure;
@@ -46,28 +31,29 @@ struct CommandLineArgumentsCallbackStructure;
* the argument is specified, the variable is set to the specified value casted
* to the appropriate type. For boolean (NO_ARGUMENT), the value is "1".
*
- * Both interfaces can be used at the same time.
+ * Both interfaces can be used at the same time.
*
* Possible argument types are:
* NO_ARGUMENT - The argument takes no value : --A
* CONCAT_ARGUMENT - The argument takes value after no space : --Aval
- * SPACE_ARGUMENT - The argument takes value after space : --A val
+ * SPACE_ARGUMENT - The argument takes value after space : --A val
* EQUAL_ARGUMENT - The argument takes value after equal : --A=val
- * MULTI_ARGUMENT - The argument takes values after space : --A val1 val2 val3 ...
+ * MULTI_ARGUMENT - The argument takes values after space : --A val1 val2
+ * val3 ...
*
* Example use:
*
* kwsys::CommandLineArguments arg;
* arg.Initialize(argc, argv);
* typedef kwsys::CommandLineArguments argT;
- * arg.AddArgument("--something", argT::EQUAL_ARGUMENT, &some_variable,
+ * arg.AddArgument("--something", argT::EQUAL_ARGUMENT, &some_variable,
* "This is help string for --something");
* if ( !arg.Parse() )
* {
- * kwsys_ios::cerr << "Problem parsing arguments" << kwsys_ios::endl;
+ * std::cerr << "Problem parsing arguments" << std::endl;
* res = 1;
* }
- *
+ *
*/
class @KWSYS_NAMESPACE@_EXPORT CommandLineArguments
@@ -79,7 +65,8 @@ public:
/**
* Various argument types.
*/
- enum ArgumentTypeEnum {
+ enum ArgumentTypeEnum
+ {
NO_ARGUMENT,
CONCAT_ARGUMENT,
SPACE_ARGUMENT,
@@ -91,27 +78,28 @@ public:
* Various variable types. When using the variable interface, this specifies
* what type the variable is.
*/
- enum VariableTypeEnum {
- NO_VARIABLE_TYPE = 0, // The variable is not specified
- INT_TYPE, // The variable is integer (int)
- BOOL_TYPE, // The variable is boolean (bool)
- DOUBLE_TYPE, // The variable is float (double)
- STRING_TYPE, // The variable is string (char*)
- STL_STRING_TYPE, // The variable is string (char*)
- VECTOR_INT_TYPE, // The variable is integer (int)
- VECTOR_BOOL_TYPE, // The variable is boolean (bool)
- VECTOR_DOUBLE_TYPE, // The variable is float (double)
- VECTOR_STRING_TYPE, // The variable is string (char*)
- VECTOR_STL_STRING_TYPE, // The variable is string (char*)
+ enum VariableTypeEnum
+ {
+ NO_VARIABLE_TYPE = 0, // The variable is not specified
+ INT_TYPE, // The variable is integer (int)
+ BOOL_TYPE, // The variable is boolean (bool)
+ DOUBLE_TYPE, // The variable is float (double)
+ STRING_TYPE, // The variable is string (char*)
+ STL_STRING_TYPE, // The variable is string (char*)
+ VECTOR_INT_TYPE, // The variable is integer (int)
+ VECTOR_BOOL_TYPE, // The variable is boolean (bool)
+ VECTOR_DOUBLE_TYPE, // The variable is float (double)
+ VECTOR_STRING_TYPE, // The variable is string (char*)
+ VECTOR_STL_STRING_TYPE, // The variable is string (char*)
LAST_VARIABLE_TYPE
};
/**
* Prototypes for callbacks for callback interface.
*/
- typedef int(*CallbackType)(const char* argument, const char* value,
- void* call_data);
- typedef int(*ErrorCallbackType)(const char* argument, void* client_data);
+ typedef int (*CallbackType)(const char* argument, const char* value,
+ void* call_data);
+ typedef int (*ErrorCallbackType)(const char* argument, void* client_data);
/**
* Initialize internal data structures. This should be called before parsing.
@@ -138,24 +126,24 @@ public:
* argument help specifies the help string used with this option. The
* callback and call_data can be skipped.
*/
- void AddCallback(const char* argument, ArgumentTypeEnum type,
- CallbackType callback, void* call_data, const char* help);
+ void AddCallback(const char* argument, ArgumentTypeEnum type,
+ CallbackType callback, void* call_data, const char* help);
/**
* Add handler for argument which is going to set the variable to the
* specified value. If the argument is specified, the option is casted to the
* appropriate type.
*/
+ void AddArgument(const char* argument, ArgumentTypeEnum type, bool* variable,
+ const char* help);
+ void AddArgument(const char* argument, ArgumentTypeEnum type, int* variable,
+ const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
- bool* variable, const char* help);
+ double* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
- int* variable, const char* help);
- void AddArgument(const char* argument, ArgumentTypeEnum type,
- double* variable, const char* help);
- void AddArgument(const char* argument, ArgumentTypeEnum type,
- char** variable, const char* help);
+ char** variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
- kwsys_stl::string* variable, const char* help);
+ std::string* variable, const char* help);
/**
* Add handler for argument which is going to set the variable to the
@@ -163,31 +151,31 @@ public:
* appropriate type. This will handle the multi argument values.
*/
void AddArgument(const char* argument, ArgumentTypeEnum type,
- kwsys_stl::vector<bool>* variable, const char* help);
+ std::vector<bool>* variable, const char* help);
+ void AddArgument(const char* argument, ArgumentTypeEnum type,
+ std::vector<int>* variable, const char* help);
+ void AddArgument(const char* argument, ArgumentTypeEnum type,
+ std::vector<double>* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
- kwsys_stl::vector<int>* variable, const char* help);
- void AddArgument(const char* argument, ArgumentTypeEnum type,
- kwsys_stl::vector<double>* variable, const char* help);
- void AddArgument(const char* argument, ArgumentTypeEnum type,
- kwsys_stl::vector<char*>* variable, const char* help);
+ std::vector<char*>* variable, const char* help);
void AddArgument(const char* argument, ArgumentTypeEnum type,
- kwsys_stl::vector<kwsys_stl::string>* variable, const char* help);
+ std::vector<std::string>* variable, const char* help);
/**
* Add handler for boolean argument. The argument does not take any option
* and if it is specified, the value of the variable is true/1, otherwise it
* is false/0.
*/
- void AddBooleanArgument(const char* argument,
- bool* variable, const char* help);
- void AddBooleanArgument(const char* argument,
- int* variable, const char* help);
- void AddBooleanArgument(const char* argument,
- double* variable, const char* help);
- void AddBooleanArgument(const char* argument,
- char** variable, const char* help);
- void AddBooleanArgument(const char* argument,
- kwsys_stl::string* variable, const char* help);
+ void AddBooleanArgument(const char* argument, bool* variable,
+ const char* help);
+ void AddBooleanArgument(const char* argument, int* variable,
+ const char* help);
+ void AddBooleanArgument(const char* argument, double* variable,
+ const char* help);
+ void AddBooleanArgument(const char* argument, char** variable,
+ const char* help);
+ void AddBooleanArgument(const char* argument, std::string* variable,
+ const char* help);
/**
* Set the callbacks for error handling.
@@ -241,30 +229,33 @@ protected:
//! This is internal method that registers variable with argument
void AddArgument(const char* argument, ArgumentTypeEnum type,
- VariableTypeEnum vtype, void* variable, const char* help);
+ VariableTypeEnum vtype, void* variable, const char* help);
- bool GetMatchedArguments(kwsys_stl::vector<kwsys_stl::string>* matches,
- const kwsys_stl::string& arg);
+ bool GetMatchedArguments(std::vector<std::string>* matches,
+ const std::string& arg);
//! Populate individual variables
bool PopulateVariable(CommandLineArgumentsCallbackStructure* cs,
- const char* value);
+ const char* value);
//! Populate individual variables of type ...
- void PopulateVariable(bool* variable, const kwsys_stl::string& value);
- void PopulateVariable(int* variable, const kwsys_stl::string& value);
- void PopulateVariable(double* variable, const kwsys_stl::string& value);
- void PopulateVariable(char** variable, const kwsys_stl::string& value);
- void PopulateVariable(kwsys_stl::string* variable, const kwsys_stl::string& value);
- void PopulateVariable(kwsys_stl::vector<bool>* variable, const kwsys_stl::string& value);
- void PopulateVariable(kwsys_stl::vector<int>* variable, const kwsys_stl::string& value);
- void PopulateVariable(kwsys_stl::vector<double>* variable, const kwsys_stl::string& value);
- void PopulateVariable(kwsys_stl::vector<char*>* variable, const kwsys_stl::string& value);
- void PopulateVariable(kwsys_stl::vector<kwsys_stl::string>* variable, const kwsys_stl::string& value);
+ void PopulateVariable(bool* variable, const std::string& value);
+ void PopulateVariable(int* variable, const std::string& value);
+ void PopulateVariable(double* variable, const std::string& value);
+ void PopulateVariable(char** variable, const std::string& value);
+ void PopulateVariable(std::string* variable, const std::string& value);
+ void PopulateVariable(std::vector<bool>* variable, const std::string& value);
+ void PopulateVariable(std::vector<int>* variable, const std::string& value);
+ void PopulateVariable(std::vector<double>* variable,
+ const std::string& value);
+ void PopulateVariable(std::vector<char*>* variable,
+ const std::string& value);
+ void PopulateVariable(std::vector<std::string>* variable,
+ const std::string& value);
typedef CommandLineArgumentsInternal Internal;
Internal* Internals;
- kwsys_stl::string Help;
+ std::string Help;
unsigned int LineLength;
@@ -273,14 +264,4 @@ protected:
} // namespace @KWSYS_NAMESPACE@
-/* Undefine temporary macro. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# undef kwsys_stl
#endif
-
-#endif
-
-
-
-
-
diff --git a/Source/kwsys/Configure.h.in b/Source/kwsys/Configure.h.in
index 70cf8442b..0afcae781 100644
--- a/Source/kwsys/Configure.h.in
+++ b/Source/kwsys/Configure.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Configure_h
#define @KWSYS_NAMESPACE@_Configure_h
@@ -16,22 +7,22 @@
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". */
@@ -42,79 +33,84 @@
/* Whether Large File Support is available. */
#if @KWSYS_NAMESPACE@_LFS_REQUESTED
-# define @KWSYS_NAMESPACE@_LFS_AVAILABLE @KWSYS_LFS_AVAILABLE@
+#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
+/* 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)
-# else
-# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport)
-# endif
-# elif __GNUC__ >= 4
-# define @KWSYS_NAMESPACE@_EXPORT __attribute__ ((visibility("default")))
-# else
-# define @KWSYS_NAMESPACE@_EXPORT
-# endif
+#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
+#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(_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
#endif
/* MSVC 6.0 in release mode will warn about code it produces with its
@@ -122,10 +118,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 716b84f09..1c07a4ef7 100644
--- a/Source/kwsys/Configure.hxx.in
+++ b/Source/kwsys/Configure.hxx.in
@@ -1,175 +1,27 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Configure_hxx
#define @KWSYS_NAMESPACE@_Configure_hxx
/* Include C configuration. */
#include <@KWSYS_NAMESPACE@/Configure.h>
-/* Whether ANSI C++ stream headers are to be used. */
-#define @KWSYS_NAMESPACE@_IOS_USE_ANSI @KWSYS_IOS_USE_ANSI@
-
-/* Whether ANSI C++ streams are in std namespace. */
-#define @KWSYS_NAMESPACE@_IOS_HAVE_STD @KWSYS_IOS_HAVE_STD@
-
-/* Whether ANSI C++ <sstream> header is to be used. */
-#define @KWSYS_NAMESPACE@_IOS_USE_SSTREAM @KWSYS_IOS_USE_SSTREAM@
-
-/* Whether old C++ <strstream.h> header is to be used. */
-#define @KWSYS_NAMESPACE@_IOS_USE_STRSTREAM_H @KWSYS_IOS_USE_STRSTREAM_H@
-
-/* Whether old C++ <strstrea.h> header is to be used. */
-#define @KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H @KWSYS_IOS_USE_STRSTREA_H@
-
-/* Whether C++ streams support the ios::binary openmode. */
-#define @KWSYS_NAMESPACE@_IOS_HAVE_BINARY @KWSYS_IOS_HAVE_BINARY@
-
-/* Whether STL is in std namespace. */
-#define @KWSYS_NAMESPACE@_STL_HAVE_STD @KWSYS_STL_HAVE_STD@
-
-/* Whether the STL string has operator<< for ostream. */
-#define @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM @KWSYS_STL_STRING_HAVE_OSTREAM@
-
-/* Whether the STL string has operator>> for istream. */
-#define @KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM @KWSYS_STL_STRING_HAVE_ISTREAM@
-
-/* Whether the STL string has operator!= for char*. */
-#define @KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR @KWSYS_STL_STRING_HAVE_NEQ_CHAR@
-
-/* Define the stl namespace macro. */
-#if @KWSYS_NAMESPACE@_STL_HAVE_STD
-# define @KWSYS_NAMESPACE@_stl std
-#else
-# define @KWSYS_NAMESPACE@_stl
-#endif
-
-/* Define the ios namespace macro. */
-#if @KWSYS_NAMESPACE@_IOS_HAVE_STD
-# define @KWSYS_NAMESPACE@_ios_namespace std
-#else
-# define @KWSYS_NAMESPACE@_ios_namespace
-#endif
-#if @KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-# define @KWSYS_NAMESPACE@_ios @KWSYS_NAMESPACE@_ios_namespace
-#else
-# define @KWSYS_NAMESPACE@_ios @KWSYS_NAMESPACE@_ios
-#endif
-
-/* Define the ios::binary openmode macro. */
-#if @KWSYS_NAMESPACE@_IOS_HAVE_BINARY
-# define @KWSYS_NAMESPACE@_ios_binary @KWSYS_NAMESPACE@_ios::ios::binary
-#else
-# define @KWSYS_NAMESPACE@_ios_binary 0
-#endif
-
-/* Whether the cstddef header is available. */
-#define @KWSYS_NAMESPACE@_CXX_HAS_CSTDDEF @KWSYS_CXX_HAS_CSTDDEF@
-
-/* Whether the compiler supports null template arguments. */
-#define @KWSYS_NAMESPACE@_CXX_HAS_NULL_TEMPLATE_ARGS @KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS@
-
-/* Define the null template arguments macro. */
-#if @KWSYS_NAMESPACE@_CXX_HAS_NULL_TEMPLATE_ARGS
-# define @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS <>
-#else
-# define @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS
-#endif
-
-/* Whether the compiler supports member templates. */
-#define @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES @KWSYS_CXX_HAS_MEMBER_TEMPLATES@
-
-/* Whether the compiler supports argument dependent lookup. */
-#define @KWSYS_NAMESPACE@_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP @KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP@
-
-/* Whether the compiler supports standard full specialization syntax. */
-#define @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION @KWSYS_CXX_HAS_FULL_SPECIALIZATION@
-
-/* Define the specialization definition macro. */
-#if @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION
-# define @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION template <>
-#else
-# define @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-#endif
-
-/* Define typename keyword macro for use in declarations. */
-#if defined(_MSC_VER) && _MSC_VER < 1300
-# define @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME
-#else
-# define @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME typename
-#endif
-
-/* Whether the stl has iterator_traits. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_TRAITS @KWSYS_STL_HAS_ITERATOR_TRAITS@
-
-/* Whether the stl has iterator_category. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_CATEGORY @KWSYS_STL_HAS_ITERATOR_CATEGORY@
-
-/* Whether the stl has __iterator_category. */
-#define @KWSYS_NAMESPACE@_STL_HAS___ITERATOR_CATEGORY @KWSYS_STL_HAS___ITERATOR_CATEGORY@
-
-/* Whether the stl allocator is the standard template. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE @KWSYS_STL_HAS_ALLOCATOR_TEMPLATE@
-
-/* Whether the stl allocator is not a template. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE @KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE@
-
-/* Whether the stl allocator has rebind. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND @KWSYS_STL_HAS_ALLOCATOR_REBIND@
-
-/* Whether the stl allocator has a size argument for max_size. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT @KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT@
-
-/* Whether the stl containers support allocator objects. */
-#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS @KWSYS_STL_HAS_ALLOCATOR_OBJECTS@
-
-/* Whether struct stat has the st_mtim member for high resolution times. */
-#define @KWSYS_NAMESPACE@_STAT_HAS_ST_MTIM @KWSYS_STAT_HAS_ST_MTIM@
+/* Whether wstring is available. */
+#define @KWSYS_NAMESPACE@_STL_HAS_WSTRING @KWSYS_STL_HAS_WSTRING@
+/* Whether <ext/stdio_filebuf.h> is available. */
+#define @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H \
+ @KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@
/* 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_stl @KWSYS_NAMESPACE@_stl
-# define kwsys_ios @KWSYS_NAMESPACE@_ios
-# define kwsys @KWSYS_NAMESPACE@
-# define kwsys_ios_binary @KWSYS_NAMESPACE@_ios_binary
-# endif
-# define KWSYS_NAME_IS_KWSYS @KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define KWSYS_STL_HAVE_STD @KWSYS_NAMESPACE@_STL_HAVE_STD
-# define KWSYS_IOS_HAVE_STD @KWSYS_NAMESPACE@_IOS_HAVE_STD
-# define KWSYS_IOS_USE_ANSI @KWSYS_NAMESPACE@_IOS_USE_ANSI
-# define KWSYS_IOS_USE_SSTREAM @KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-# define KWSYS_IOS_USE_STRSTREAM_H @KWSYS_NAMESPACE@_IOS_USE_STRSTREAM_H
-# define KWSYS_IOS_USE_STRSTREA_H @KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H
-# define KWSYS_IOS_HAVE_BINARY @KWSYS_NAMESPACE@_IOS_HAVE_BINARY
-# define KWSYS_STAT_HAS_ST_MTIM @KWSYS_NAMESPACE@_STAT_HAS_ST_MTIM
-# define KWSYS_CXX_HAS_CSTDDEF @KWSYS_NAMESPACE@_CXX_HAS_CSTDDEF
-# define KWSYS_STL_STRING_HAVE_OSTREAM @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM
-# define KWSYS_STL_STRING_HAVE_ISTREAM @KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM
-# define KWSYS_STL_STRING_HAVE_NEQ_CHAR @KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR
-# define KWSYS_CXX_NULL_TEMPLATE_ARGS @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS
-# define KWSYS_CXX_HAS_MEMBER_TEMPLATES @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
-# define KWSYS_CXX_HAS_FULL_SPECIALIZATION @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION
-# define KWSYS_CXX_DEFINE_SPECIALIZATION @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-# define KWSYS_CXX_DECL_TYPENAME @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME
-# define KWSYS_STL_HAS_ALLOCATOR_REBIND @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND
-# define KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT
-# define KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP @KWSYS_NAMESPACE@_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP
-# define KWSYS_STL_HAS_ITERATOR_TRAITS @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_TRAITS
-# define KWSYS_STL_HAS_ITERATOR_CATEGORY @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_CATEGORY
-# define KWSYS_STL_HAS___ITERATOR_CATEGORY @KWSYS_NAMESPACE@_STL_HAS___ITERATOR_CATEGORY
-# define KWSYS_STL_HAS_ALLOCATOR_TEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE
-# define KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE
-# define KWSYS_STL_HAS_ALLOCATOR_OBJECTS @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS
+#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
#endif
#endif
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
new file mode 100644
index 000000000..46d65a865
--- /dev/null
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -0,0 +1,394 @@
+/* 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@_ConsoleBuf_hxx
+#define @KWSYS_NAMESPACE@_ConsoleBuf_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <@KWSYS_NAMESPACE@/Encoding.hxx>
+
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <streambuf>
+#include <string>
+
+#if defined(_WIN32)
+#include <windows.h>
+#if __cplusplus >= 201103L
+#include <system_error>
+#endif
+#endif
+
+namespace @KWSYS_NAMESPACE@ {
+#if defined(_WIN32)
+
+template <class CharT, class Traits = std::char_traits<CharT> >
+class BasicConsoleBuf : public std::basic_streambuf<CharT, Traits>
+{
+public:
+ typedef typename Traits::int_type int_type;
+ typedef typename Traits::char_type char_type;
+
+ class Manager
+ {
+ public:
+ Manager(std::basic_ios<CharT, Traits>& ios, const bool err = false)
+ : m_consolebuf(0)
+ {
+ m_ios = &ios;
+ try {
+ m_consolebuf = new BasicConsoleBuf<CharT, Traits>(err);
+ m_streambuf = m_ios->rdbuf(m_consolebuf);
+ } catch (const std::runtime_error& ex) {
+ std::cerr << "Failed to create ConsoleBuf!" << std::endl
+ << ex.what() << std::endl;
+ };
+ }
+
+ BasicConsoleBuf<CharT, Traits>* GetConsoleBuf() { return m_consolebuf; }
+
+ void SetUTF8Pipes()
+ {
+ if (m_consolebuf) {
+ m_consolebuf->input_pipe_codepage = CP_UTF8;
+ m_consolebuf->output_pipe_codepage = CP_UTF8;
+ m_consolebuf->activateCodepageChange();
+ }
+ }
+
+ ~Manager()
+ {
+ if (m_consolebuf) {
+ delete m_consolebuf;
+ m_ios->rdbuf(m_streambuf);
+ }
+ }
+
+ private:
+ std::basic_ios<CharT, Traits>* m_ios;
+ std::basic_streambuf<CharT, Traits>* m_streambuf;
+ BasicConsoleBuf<CharT, Traits>* m_consolebuf;
+ };
+
+ BasicConsoleBuf(const bool err = false)
+ : flush_on_newline(true)
+ , input_pipe_codepage(0)
+ , output_pipe_codepage(0)
+ , input_file_codepage(CP_UTF8)
+ , output_file_codepage(CP_UTF8)
+ , m_consolesCodepage(0)
+ {
+ m_hInput = ::GetStdHandle(STD_INPUT_HANDLE);
+ checkHandle(true, "STD_INPUT_HANDLE");
+ if (!setActiveInputCodepage()) {
+ throw std::runtime_error("setActiveInputCodepage failed!");
+ }
+ m_hOutput = err ? ::GetStdHandle(STD_ERROR_HANDLE)
+ : ::GetStdHandle(STD_OUTPUT_HANDLE);
+ checkHandle(false, err ? "STD_ERROR_HANDLE" : "STD_OUTPUT_HANDLE");
+ if (!setActiveOutputCodepage()) {
+ throw std::runtime_error("setActiveOutputCodepage failed!");
+ }
+ _setg();
+ _setp();
+ }
+
+ ~BasicConsoleBuf() throw() { sync(); }
+
+ bool activateCodepageChange()
+ {
+ return setActiveInputCodepage() && setActiveOutputCodepage();
+ }
+
+protected:
+ virtual int sync()
+ {
+ bool success = true;
+ if (m_hInput && m_isConsoleInput &&
+ ::FlushConsoleInputBuffer(m_hInput) == 0) {
+ success = false;
+ }
+ if (m_hOutput && !m_obuffer.empty()) {
+ const std::wstring wbuffer = getBuffer(m_obuffer);
+ if (m_isConsoleOutput) {
+ DWORD charsWritten;
+ success =
+ ::WriteConsoleW(m_hOutput, wbuffer.c_str(), (DWORD)wbuffer.size(),
+ &charsWritten, NULL) == 0
+ ? false
+ : true;
+ } else {
+ DWORD bytesWritten;
+ std::string buffer;
+ success = encodeOutputBuffer(wbuffer, buffer);
+ if (success) {
+ success = ::WriteFile(m_hOutput, buffer.c_str(),
+ (DWORD)buffer.size(), &bytesWritten, NULL) == 0
+ ? false
+ : true;
+ }
+ }
+ }
+ m_ibuffer.clear();
+ m_obuffer.clear();
+ _setg();
+ _setp();
+ return success ? 0 : -1;
+ }
+
+ virtual int_type underflow()
+ {
+ if (this->gptr() >= this->egptr()) {
+ if (!m_hInput) {
+ _setg(true);
+ return Traits::eof();
+ }
+ if (m_isConsoleInput) {
+ // ReadConsole doesn't tell if there's more input available
+ // don't support reading more characters than this
+ wchar_t wbuffer[8192];
+ DWORD charsRead;
+ if (ReadConsoleW(m_hInput, wbuffer,
+ (sizeof(wbuffer) / sizeof(wbuffer[0])), &charsRead,
+ NULL) == 0 ||
+ charsRead == 0) {
+ _setg(true);
+ return Traits::eof();
+ }
+ setBuffer(std::wstring(wbuffer, charsRead), m_ibuffer);
+ } else {
+ std::wstring wbuffer;
+ std::string strbuffer;
+ DWORD bytesRead;
+ LARGE_INTEGER size;
+ if (GetFileSizeEx(m_hInput, &size) == 0) {
+ _setg(true);
+ return Traits::eof();
+ }
+ char* buffer = new char[size.LowPart];
+ while (ReadFile(m_hInput, buffer, size.LowPart, &bytesRead, NULL) ==
+ 0) {
+ if (GetLastError() == ERROR_MORE_DATA) {
+ strbuffer += std::string(buffer, bytesRead);
+ continue;
+ }
+ _setg(true);
+ delete[] buffer;
+ return Traits::eof();
+ }
+ if (bytesRead > 0) {
+ strbuffer += std::string(buffer, bytesRead);
+ }
+ delete[] buffer;
+ if (!decodeInputBuffer(strbuffer, wbuffer)) {
+ _setg(true);
+ return Traits::eof();
+ }
+ setBuffer(wbuffer, m_ibuffer);
+ }
+ _setg();
+ }
+ return Traits::to_int_type(*this->gptr());
+ }
+
+ virtual int_type overflow(int_type ch = Traits::eof())
+ {
+ if (!Traits::eq_int_type(ch, Traits::eof())) {
+ char_type chr = Traits::to_char_type(ch);
+ m_obuffer += chr;
+ if ((flush_on_newline && Traits::eq(chr, '\n')) ||
+ Traits::eq_int_type(ch, 0x00)) {
+ sync();
+ }
+ return ch;
+ }
+ sync();
+ return Traits::eof();
+ }
+
+public:
+ bool flush_on_newline;
+ UINT input_pipe_codepage;
+ UINT output_pipe_codepage;
+ UINT input_file_codepage;
+ UINT output_file_codepage;
+
+private:
+ HANDLE m_hInput;
+ HANDLE m_hOutput;
+ std::basic_string<char_type> m_ibuffer;
+ std::basic_string<char_type> m_obuffer;
+ bool m_isConsoleInput;
+ bool m_isConsoleOutput;
+ UINT m_activeInputCodepage;
+ UINT m_activeOutputCodepage;
+ UINT m_consolesCodepage;
+ void checkHandle(bool input, std::string handleName)
+ {
+ if ((input && m_hInput == INVALID_HANDLE_VALUE) ||
+ (!input && m_hOutput == INVALID_HANDLE_VALUE)) {
+ std::string errmsg =
+ "GetStdHandle(" + handleName + ") returned INVALID_HANDLE_VALUE";
+#if __cplusplus >= 201103L
+ throw std::system_error(::GetLastError(), std::system_category(),
+ errmsg);
+#else
+ throw std::runtime_error(errmsg);
+#endif
+ }
+ }
+ UINT getConsolesCodepage()
+ {
+ if (!m_consolesCodepage) {
+ m_consolesCodepage = GetConsoleCP();
+ if (!m_consolesCodepage) {
+ m_consolesCodepage = GetACP();
+ }
+ }
+ return m_consolesCodepage;
+ }
+ bool setActiveInputCodepage()
+ {
+ m_isConsoleInput = false;
+ switch (GetFileType(m_hInput)) {
+ case FILE_TYPE_DISK:
+ m_activeInputCodepage = input_file_codepage;
+ break;
+ case FILE_TYPE_CHAR:
+ // Check for actual console.
+ DWORD consoleMode;
+ m_isConsoleInput =
+ GetConsoleMode(m_hInput, &consoleMode) == 0 ? false : true;
+ if (m_isConsoleInput) {
+ break;
+ }
+ case FILE_TYPE_PIPE:
+ m_activeInputCodepage = input_pipe_codepage;
+ break;
+ default:
+ return false;
+ }
+ if (!m_isConsoleInput && m_activeInputCodepage == 0) {
+ m_activeInputCodepage = getConsolesCodepage();
+ }
+ return true;
+ }
+ bool setActiveOutputCodepage()
+ {
+ m_isConsoleOutput = false;
+ switch (GetFileType(m_hOutput)) {
+ case FILE_TYPE_DISK:
+ m_activeOutputCodepage = output_file_codepage;
+ break;
+ case FILE_TYPE_CHAR:
+ // Check for actual console.
+ DWORD consoleMode;
+ m_isConsoleOutput =
+ GetConsoleMode(m_hOutput, &consoleMode) == 0 ? false : true;
+ if (m_isConsoleOutput) {
+ break;
+ }
+ case FILE_TYPE_PIPE:
+ m_activeOutputCodepage = output_pipe_codepage;
+ break;
+ default:
+ return false;
+ }
+ if (!m_isConsoleOutput && m_activeOutputCodepage == 0) {
+ m_activeOutputCodepage = getConsolesCodepage();
+ }
+ return true;
+ }
+ void _setg(bool empty = false)
+ {
+ if (!empty) {
+ this->setg((char_type*)m_ibuffer.data(), (char_type*)m_ibuffer.data(),
+ (char_type*)m_ibuffer.data() + m_ibuffer.size());
+ } else {
+ this->setg((char_type*)m_ibuffer.data(),
+ (char_type*)m_ibuffer.data() + m_ibuffer.size(),
+ (char_type*)m_ibuffer.data() + m_ibuffer.size());
+ }
+ }
+ void _setp()
+ {
+ this->setp((char_type*)m_obuffer.data(),
+ (char_type*)m_obuffer.data() + m_obuffer.size());
+ }
+ bool encodeOutputBuffer(const std::wstring wbuffer, std::string& buffer)
+ {
+ if (wbuffer.size() == 0) {
+ buffer = std::string();
+ return true;
+ }
+ const int length =
+ WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
+ (int)wbuffer.size(), NULL, 0, NULL, NULL);
+ char* buf = new char[length];
+ const bool success =
+ WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
+ (int)wbuffer.size(), buf, length, NULL, NULL) > 0
+ ? true
+ : false;
+ buffer = std::string(buf, length);
+ delete[] buf;
+ return success;
+ }
+ bool decodeInputBuffer(const std::string buffer, std::wstring& wbuffer)
+ {
+ size_t length = buffer.length();
+ if (length == 0) {
+ wbuffer = std::wstring();
+ return true;
+ }
+ int actualCodepage = m_activeInputCodepage;
+ const char BOM_UTF8[] = { char(0xEF), char(0xBB), char(0xBF) };
+ const char* data = buffer.data();
+ const size_t BOMsize = sizeof(BOM_UTF8);
+ if (length >= BOMsize && std::memcmp(data, BOM_UTF8, BOMsize) == 0) {
+ // PowerShell uses UTF-8 with BOM for pipes
+ actualCodepage = CP_UTF8;
+ data += BOMsize;
+ length -= BOMsize;
+ }
+ const size_t wlength = static_cast<size_t>(MultiByteToWideChar(
+ actualCodepage, 0, data, static_cast<int>(length), NULL, 0));
+ wchar_t* wbuf = new wchar_t[wlength];
+ const bool success =
+ MultiByteToWideChar(actualCodepage, 0, data, static_cast<int>(length),
+ wbuf, static_cast<int>(wlength)) > 0
+ ? true
+ : false;
+ wbuffer = std::wstring(wbuf, wlength);
+ delete[] wbuf;
+ return success;
+ }
+ std::wstring getBuffer(const std::basic_string<char> buffer)
+ {
+ return Encoding::ToWide(buffer);
+ }
+ std::wstring getBuffer(const std::basic_string<wchar_t> buffer)
+ {
+ return buffer;
+ }
+ void setBuffer(const std::wstring wbuffer, std::basic_string<char>& target)
+ {
+ target = Encoding::ToNarrow(wbuffer);
+ }
+ void setBuffer(const std::wstring wbuffer,
+ std::basic_string<wchar_t>& target)
+ {
+ target = wbuffer;
+ }
+
+}; // BasicConsoleBuf class
+
+typedef BasicConsoleBuf<char> ConsoleBuf;
+typedef BasicConsoleBuf<wchar_t> WConsoleBuf;
+
+#endif
+} // KWSYS_NAMESPACE
+
+#endif
diff --git a/Source/kwsys/Copyright.txt b/Source/kwsys/Copyright.txt
index 1549a7d5f..33d7fb472 100644
--- a/Source/kwsys/Copyright.txt
+++ b/Source/kwsys/Copyright.txt
@@ -1,5 +1,5 @@
KWSys - Kitware System Library
-Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+Copyright 2000-2016 Kitware, Inc. and Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -13,10 +13,9 @@ are met:
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-* Neither the names of Kitware, Inc., the Insight Software Consortium,
- nor the names of their contributors may be used to endorse or promote
- products derived from this software without specific prior written
- permission.
+* Neither the name of Kitware, Inc. nor the names of Contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -29,3 +28,11 @@ 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.
+
+------------------------------------------------------------------------------
+
+The following individuals and institutions are among the Contributors:
+
+* Insight Software Consortium <insightsoftwareconsortium.org>
+
+See version control history for details of individual contributions.
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index b88474781..5141d4519 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -1,81 +1,63 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Configure.hxx)
-#include KWSYS_HEADER(stl/string)
-#include KWSYS_HEADER(stl/vector)
+#include KWSYS_HEADER(Encoding.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "Directory.hxx.in"
-# include "Configure.hxx.in"
-# include "kwsys_stl.hxx.in"
-# include "kwsys_stl_string.hxx.in"
-# include "kwsys_stl_vector.hxx.in"
+#include "Configure.hxx.in"
+#include "Directory.hxx.in"
+#include "Encoding.hxx.in"
#endif
-namespace KWSYS_NAMESPACE
-{
+#include <string>
+#include <vector>
+
+namespace KWSYS_NAMESPACE {
-//----------------------------------------------------------------------------
class DirectoryInternals
{
public:
// Array of Files
- kwsys_stl::vector<kwsys_stl::string> Files;
+ std::vector<std::string> Files;
// Path to Open'ed directory
- kwsys_stl::string Path;
+ std::string Path;
};
-//----------------------------------------------------------------------------
Directory::Directory()
{
this->Internal = new DirectoryInternals;
}
-//----------------------------------------------------------------------------
Directory::~Directory()
{
delete this->Internal;
}
-//----------------------------------------------------------------------------
unsigned long Directory::GetNumberOfFiles() const
{
return static_cast<unsigned long>(this->Internal->Files.size());
}
-//----------------------------------------------------------------------------
const char* Directory::GetFile(unsigned long dindex) const
{
- if ( dindex >= this->Internal->Files.size() )
- {
+ if (dindex >= this->Internal->Files.size()) {
return 0;
- }
+ }
return this->Internal->Files[dindex].c_str();
}
-//----------------------------------------------------------------------------
const char* Directory::GetPath() const
{
return this->Internal->Path.c_str();
}
-//----------------------------------------------------------------------------
void Directory::Clear()
{
this->Internal->Path.resize(0);
@@ -84,100 +66,107 @@ void Directory::Clear()
} // namespace KWSYS_NAMESPACE
-// First microsoft compilers
+// First Windows platforms
-#if defined(_MSC_VER) || defined(__WATCOMC__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
-#include <io.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>
-namespace KWSYS_NAMESPACE
-{
+// 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
+
+namespace KWSYS_NAMESPACE {
-bool Directory::Load(const char* name)
+bool Directory::Load(const std::string& name)
{
this->Clear();
-#if _MSC_VER < 1300
+#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
+ // Older Visual C++ and Embarcadero compilers.
long srchHandle;
-#else
+#else // Newer Visual C++
intptr_t srchHandle;
#endif
char* buf;
- size_t n = strlen(name);
- if ( name[n - 1] == '/' )
- {
+ size_t n = name.size();
+ if (*name.rbegin() == '/' || *name.rbegin() == '\\') {
buf = new char[n + 1 + 1];
- sprintf(buf, "%s*", name);
- }
- else
- {
+ sprintf(buf, "%s*", name.c_str());
+ } else {
+ // Make sure the slashes in the wildcard suffix are consistent with the
+ // rest of the path
buf = new char[n + 2 + 1];
- sprintf(buf, "%s/*", name);
+ if (name.find('\\') != std::string::npos) {
+ sprintf(buf, "%s\\*", name.c_str());
+ } else {
+ sprintf(buf, "%s/*", name.c_str());
}
- struct _finddata_t data; // data of current file
+ }
+ struct _wfinddata_t data; // data of current file
// Now put them into the file array
- srchHandle = _findfirst(buf, &data);
- delete [] buf;
+ srchHandle =
+ _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+ delete[] buf;
- if ( srchHandle == -1 )
- {
+ if (srchHandle == -1) {
return 0;
- }
+ }
// Loop through names
- do
- {
- this->Internal->Files.push_back(data.name);
- }
- while ( _findnext(srchHandle, &data) != -1 );
+ do {
+ this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
+ } while (_wfindnext_func(srchHandle, &data) != -1);
this->Internal->Path = name;
return _findclose(srchHandle) != -1;
}
-unsigned long Directory::GetNumberOfFilesInDirectory(const char* name)
+unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
{
-#if _MSC_VER < 1300
+#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
+ // Older Visual C++ and Embarcadero compilers.
long srchHandle;
-#else
+#else // Newer Visual C++
intptr_t srchHandle;
#endif
char* buf;
- size_t n = strlen(name);
- if ( name[n - 1] == '/' )
- {
+ size_t n = name.size();
+ if (*name.rbegin() == '/') {
buf = new char[n + 1 + 1];
- sprintf(buf, "%s*", name);
- }
- else
- {
+ sprintf(buf, "%s*", name.c_str());
+ } else {
buf = new char[n + 2 + 1];
- sprintf(buf, "%s/*", name);
- }
- struct _finddata_t data; // data of current file
+ sprintf(buf, "%s/*", name.c_str());
+ }
+ struct _wfinddata_t data; // data of current file
// Now put them into the file array
- srchHandle = _findfirst(buf, &data);
- delete [] buf;
+ srchHandle =
+ _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+ delete[] buf;
- if ( srchHandle == -1 )
- {
+ if (srchHandle == -1) {
return 0;
- }
+ }
// Loop through names
unsigned long count = 0;
- do
- {
+ do {
count++;
- }
- while ( _findnext(srchHandle, &data) != -1 );
+ } while (_wfindnext_func(srchHandle, &data) != -1);
_findclose(srchHandle);
return count;
}
@@ -189,58 +178,55 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const char* name)
// Now the POSIX style directory access
#include <sys/types.h>
+
#include <dirent.h>
-/* There is a problem with the Portland compiler, large file
-support and glibc/Linux system headers:
-http://www.pgroup.com/userforum/viewtopic.php?
-p=1992&sid=f16167f51964f1a68fe5041b8eb213b6
-*/
-#if defined(__PGI) && defined(__USE_FILE_OFFSET64)
-# define dirent dirent64
+// 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
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
-bool Directory::Load(const char* name)
+bool Directory::Load(const std::string& name)
{
this->Clear();
-
- if (!name)
- {
- return 0;
- }
- DIR* dir = opendir(name);
- if (!dir)
- {
+ DIR* dir = opendir(name.c_str());
+
+ if (!dir) {
return 0;
- }
+ }
- for (dirent* d = readdir(dir); d; d = readdir(dir) )
- {
+ for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
this->Internal->Files.push_back(d->d_name);
- }
+ }
this->Internal->Path = name;
closedir(dir);
return 1;
}
-unsigned long Directory::GetNumberOfFilesInDirectory(const char* name)
+unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
{
- DIR* dir = opendir(name);
+ DIR* dir = opendir(name.c_str());
- if (!dir)
- {
+ if (!dir) {
return 0;
- }
+ }
unsigned long count = 0;
- for (dirent* d = readdir(dir); d; d = readdir(dir) )
- {
+ for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
count++;
- }
+ }
closedir(dir);
return count;
}
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
index 05217c46d..ad8c51b86 100644
--- a/Source/kwsys/Directory.hxx.in
+++ b/Source/kwsys/Directory.hxx.in
@@ -1,21 +1,13 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Directory_hxx
#define @KWSYS_NAMESPACE@_Directory_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
-namespace @KWSYS_NAMESPACE@
-{
+#include <string>
+
+namespace @KWSYS_NAMESPACE@ {
class DirectoryInternals;
@@ -38,7 +30,7 @@ public:
* in that directory. 0 is returned if the directory can not be
* opened, 1 if it is opened.
*/
- bool Load(const char*);
+ bool Load(const std::string&);
/**
* Return the number of files in the current directory.
@@ -49,7 +41,7 @@ public:
* Return the number of files in the specified directory.
* A higher performance static method.
*/
- static unsigned long GetNumberOfFilesInDirectory(const char*);
+ static unsigned long GetNumberOfFilesInDirectory(const std::string&);
/**
* Return the file at the given index, the indexing is 0 based
@@ -71,9 +63,9 @@ private:
// Private implementation details.
DirectoryInternals* Internal;
- Directory(const Directory&); // Not implemented.
- void operator=(const Directory&); // Not implemented.
-}; // End Class: Directory
+ Directory(const Directory&); // Not implemented.
+ void operator=(const Directory&); // Not implemented.
+}; // End Class: Directory
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index fd83752c0..1b4596a4e 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(DynamicLoader.hxx)
@@ -17,52 +8,90 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "DynamicLoader.hxx.in"
-# include "Configure.hxx.in"
+#include "Configure.hxx.in"
+#include "DynamicLoader.hxx.in"
#endif
-// This file is actually 3 different implementations.
-// 1. HP machines which uses shl_load
-// 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
-// 3. Windows which uses LoadLibrary
-// 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen
-// (default) Each part of the ifdef contains a complete implementation for
+// This file actually contains several different implementations:
+// * NOOP for environments without dynamic libs
+// * HP machines which uses shl_load
+// * Mac OS X 10.2.x and earlier which uses NSLinkModule
+// * Windows which uses LoadLibrary
+// * BeOS / Haiku
+// * FreeMiNT for Atari
+// * Default implementation for *NIX systems (including Mac OS X 10.3 and
+// later) which use dlopen
+//
+// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.
-// ---------------------------------------------------------------
-// 1. Implementation for HPUX machines
-#ifdef __hpux
-#include <errno.h>
-#include <dl.h>
-#define DYNAMICLOADER_DEFINED 1
+#if !KWSYS_SUPPORTS_SHARED_LIBS
+// Implementation for environments without dynamic libs
+#include <string.h> // for strerror()
+
+namespace KWSYS_NAMESPACE {
-namespace KWSYS_NAMESPACE
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
+ return 0;
+}
+
+int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
+{
+ if (!lib) {
+ return 0;
+ }
+
+ return 1;
+}
+
+DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
+{
+ return 0;
+}
+
+const char* DynamicLoader::LastError()
+{
+ return "General error";
+}
+
+} // namespace KWSYS_NAMESPACE
+
+#elif defined(__hpux)
+// Implementation for HPUX machines
+#include <dl.h>
+#include <errno.h>
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
+namespace KWSYS_NAMESPACE {
+
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
- return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
+ return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
}
-//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
+ if (!lib) {
+ return 0;
+ }
return !shl_unload(lib);
}
-//----------------------------------------------------------------------------
-DynamicLoader::SymbolPointer
-DynamicLoader::GetSymbolAddress(DynamicLoader::LibraryHandle lib, const char* sym)
+DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
{
void* addr;
int status;
/* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
- * TYPE_DATA Look for a symbol in the data segment (for example, variables).
+ * TYPE_DATA Look for a symbol in the data segment (for example,
+ * variables).
* TYPE_UNDEFINED Look for any symbol.
*/
- status = shl_findsym (&lib, sym, TYPE_UNDEFINED, &addr);
+ status = shl_findsym(&lib, sym.c_str(), TYPE_UNDEFINED, &addr);
void* result = (status < 0) ? (void*)0 : addr;
// Hack to cast pointer-to-data to pointer-to-function.
@@ -84,52 +113,41 @@ const char* DynamicLoader::LastError()
* The specified handle is invalid.
*/
- if( errno == ENOEXEC
- || errno == ENOSYM
- || errno == EINVAL )
- {
+ if (errno == ENOEXEC || errno == ENOSYM || errno == EINVAL) {
return strerror(errno);
- }
+ }
// else
return 0;
}
} // namespace KWSYS_NAMESPACE
-#endif //__hpux
-
-
-// ---------------------------------------------------------------
-// 2. Implementation for Mac OS X 10.2.x and earlier
-#ifdef __APPLE__
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
-#include <string.h> // for strlen
+#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>
-#define DYNAMICLOADER_DEFINED 1
+#include <string.h> // for strlen
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
NSObjectFileImageReturnCode rc;
NSObjectFileImage image = 0;
- rc = NSCreateObjectFileImageFromFile(libname, &image);
+ rc = NSCreateObjectFileImageFromFile(libname.c_str(), &image);
// rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
- if( rc != NSObjectFileImageSuccess )
- {
+ if (rc != NSObjectFileImageSuccess) {
return 0;
- }
- NSModule handle = NSLinkModule(image, libname,
- 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;
}
-//----------------------------------------------------------------------------
-int DynamicLoader::CloseLibrary( DynamicLoader::LibraryHandle lib)
+int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
// NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
// With this option the memory for the module is not deallocated
@@ -140,29 +158,26 @@ int DynamicLoader::CloseLibrary( DynamicLoader::LibraryHandle lib)
return success;
}
-//----------------------------------------------------------------------------
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const char* sym)
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
{
- void *result=0;
+ void* result = 0;
// Need to prepend symbols with '_' on Apple-gcc compilers
- size_t len = strlen(sym);
- char *rsym = new char[len + 1 + 1];
+ size_t len = sym.size();
+ char* rsym = new char[len + 1 + 1];
strcpy(rsym, "_");
- strcat(rsym+1, sym);
+ strcat(rsym + 1, sym.c_str());
NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
- if(symbol)
- {
+ if (symbol) {
result = NSAddressOfSymbol(symbol);
- }
+ }
delete[] rsym;
// Hack to cast pointer-to-data to pointer-to-function.
return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
}
-//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
return 0;
@@ -170,41 +185,32 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1030
-#endif // __APPLE__
-
-// ---------------------------------------------------------------
-// 3. Implementation for Windows win32 code but not cygwin
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#elif defined(_WIN32) && !defined(__CYGWIN__)
+// Implementation for Windows win32 code but not cygwin
#include <windows.h>
-#define DYNAMICLOADER_DEFINED 1
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname)
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
DynamicLoader::LibraryHandle lh;
-#ifdef UNICODE
- wchar_t libn[MB_CUR_MAX];
- mbstowcs(libn, libname, MB_CUR_MAX);
- lh = LoadLibrary(libn);
-#else
- lh = LoadLibrary(libname);
-#endif
+ 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;
}
-//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
return (int)FreeLibrary(lib);
}
-//----------------------------------------------------------------------------
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const char* sym)
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
{
// TODO: The calling convention affects the name of the symbol. We
// should have a tool to help get the symbol with the desired
@@ -228,27 +234,21 @@ 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;
+ void* result;
#if defined(__BORLANDC__) || defined(__WATCOMC__)
// Need to prepend symbols with '_'
- size_t len = strlen(sym);
- char *rsym = new char[len + 1 + 1];
+ size_t len = sym.size();
+ char* rsym = new char[len + 1 + 1];
strcpy(rsym, "_");
- strcat(rsym, sym);
+ strcat(rsym, sym.c_str());
#else
- const char *rsym = sym;
+ const char* rsym = sym.c_str();
#endif
-#ifdef UNICODE
- wchar_t wsym[MB_CUR_MAX];
- mbstowcs(wsym, rsym, MB_CUR_MAX);
- result = GetProcAddress(lib, wsym);
-#else
result = (void*)GetProcAddress(lib, rsym);
-#endif
#if defined(__BORLANDC__) || defined(__WATCOMC__)
delete[] rsym;
#endif
- // Hack to cast pointer-to-data to pointer-to-function.
+// Hack to cast pointer-to-data to pointer-to-function.
#ifdef __WATCOMC__
return *(DynamicLoader::SymbolPointer*)(&result);
#else
@@ -256,97 +256,76 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
#endif
}
-//----------------------------------------------------------------------------
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
- );
-
- if(!lpMsgBuf)
- {
+ 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);
+
+ if (!lpMsgBuf) {
return NULL;
- }
+ }
static char* str = 0;
- delete [] str;
- str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
+ delete[] str;
+ str = strcpy(new char[strlen((char*)lpMsgBuf) + 1], (char*)lpMsgBuf);
// Free the buffer.
- LocalFree( lpMsgBuf );
+ LocalFree(lpMsgBuf);
return str;
}
} // namespace KWSYS_NAMESPACE
-#endif //_WIN32
-
-// ---------------------------------------------------------------
-// 4. Implementation for BeOS
-#if defined __BEOS__
-
+#elif defined(__BEOS__)
+// Implementation for BeOS / Haiku
#include <string.h> // for strerror()
#include <be/kernel/image.h>
#include <be/support/Errors.h>
-#define DYNAMICLOADER_DEFINED 1
-
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
static image_id last_dynamic_err = B_OK;
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
// 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);
- if (rc < 0)
- {
+ image_id rc = load_add_on(libname.c_str());
+ if (rc < 0) {
last_dynamic_err = rc;
return 0;
- }
+ }
- return rc+1;
+ return rc + 1;
}
-//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
- if (!lib)
- {
- last_dynamic_err = B_BAD_VALUE;
- return 0;
- }
- else
- {
+ if (!lib) {
+ last_dynamic_err = B_BAD_VALUE;
+ return 0;
+ } else {
// The function dlclose() returns 0 on success, and non-zero on error.
- status_t rc = unload_add_on(lib-1);
- if (rc != B_OK)
- {
+ status_t rc = unload_add_on(lib - 1);
+ if (rc != B_OK) {
last_dynamic_err = rc;
return 0;
- }
}
+ }
return 1;
}
-//----------------------------------------------------------------------------
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const char* sym)
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
{
// Hack to cast pointer-to-data to pointer-to-function.
- union
+ union
{
void* pvoid;
DynamicLoader::SymbolPointer psym;
@@ -354,112 +333,60 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
result.psym = NULL;
- if (!lib)
- {
- last_dynamic_err = B_BAD_VALUE;
- }
- else
- {
+ if (!lib) {
+ last_dynamic_err = B_BAD_VALUE;
+ } else {
// !!! FIXME: BeOS can do function-only lookups...does this ever
// !!! FIXME: actually _want_ a data symbol lookup, or was this union
// !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
- status_t rc = get_image_symbol(lib-1,sym,B_SYMBOL_TYPE_ANY,&result.pvoid);
- if (rc != B_OK)
- {
+ status_t rc =
+ 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;
- }
}
+ }
return result.psym;
}
-//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
- const char *retval = strerror(last_dynamic_err);
+ const char* retval = strerror(last_dynamic_err);
last_dynamic_err = B_OK;
return retval;
}
} // namespace KWSYS_NAMESPACE
-#endif
-// ---------------------------------------------------------------
-// 5. Implementation for systems without dynamic libs
-// __gnu_blrts__ is IBM BlueGene/L
-// __LIBCATAMOUNT__ is defined on Catamount on Cray compute nodes
-#if defined(__gnu_blrts__) || defined(__LIBCATAMOUNT__) || defined(__CRAYXT_COMPUTE_LINUX_TARGET)
-#include <string.h> // for strerror()
-#define DYNAMICLOADER_DEFINED 1
-
-namespace KWSYS_NAMESPACE
-{
-
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
-{
- return 0;
-}
-
-//----------------------------------------------------------------------------
-int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
-{
- if (!lib)
- {
- return 0;
- }
-
- return 1;
-}
-
-//----------------------------------------------------------------------------
-DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const char* sym)
-{
- return 0;
-}
-
-//----------------------------------------------------------------------------
-const char* DynamicLoader::LastError()
- {
- return "General error";
- }
-
-} // namespace KWSYS_NAMESPACE
-#endif
-
-#ifdef __MINT__
-#define DYNAMICLOADER_DEFINED 1
+#elif defined(__MINT__)
+// Implementation for FreeMiNT on Atari
#define _GNU_SOURCE /* for program_invocation_name */
-#include <string.h>
-#include <malloc.h>
-#include <errno.h>
#include <dld.h>
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
- char *name = (char *)calloc(1, strlen(libname) + 1);
+ char* name = (char*)calloc(1, libname.size() + 1);
dld_init(program_invocation_name);
- strncpy(name, libname, strlen(libname));
- dld_link(libname);
- return (void *)name;
+ strncpy(name, libname.c_str(), libname.size());
+ dld_link(libname.c_str());
+ return (void*)name;
}
-//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
- dld_unlink_by_file((char *)lib, 0);
+ dld_unlink_by_file((char*)lib, 0);
free(lib);
return 0;
}
-//----------------------------------------------------------------------------
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const char* sym)
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
{
// Hack to cast pointer-to-data to pointer-to-function.
union
@@ -467,68 +394,57 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
void* pvoid;
DynamicLoader::SymbolPointer psym;
} result;
- result.pvoid = dld_get_symbol(sym);
+ result.pvoid = dld_get_symbol(sym.c_str());
return result.psym;
}
-//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
return dld_strerror(dld_errno);
}
} // namespace KWSYS_NAMESPACE
-#endif
-// ---------------------------------------------------------------
-// 6. Implementation for default UNIX machines.
-// if nothing has been defined then use this
-#ifndef DYNAMICLOADER_DEFINED
-#define DYNAMICLOADER_DEFINED 1
-// Setup for most unix machines
+#else
+// Default implementation for *NIX systems (including Mac OS X 10.3 and
+// later) which use dlopen
#include <dlfcn.h>
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
{
- return dlopen(libname, RTLD_LAZY);
+ return dlopen(libname.c_str(), RTLD_LAZY);
}
-//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
- if (lib)
- {
+ if (lib) {
// The function dlclose() returns 0 on success, and non-zero on error.
return !dlclose(lib);
- }
+ }
// else
return 0;
}
-//----------------------------------------------------------------------------
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const char* sym)
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
{
// Hack to cast pointer-to-data to pointer-to-function.
- union
+ union
{
void* pvoid;
DynamicLoader::SymbolPointer psym;
} result;
- result.pvoid = dlsym(lib, sym);
+ result.pvoid = dlsym(lib, sym.c_str());
return result.psym;
}
-//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
return dlerror();
}
} // namespace KWSYS_NAMESPACE
-
#endif
diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in
index 64468ecd3..7e71a4593 100644
--- a/Source/kwsys/DynamicLoader.hxx.in
+++ b/Source/kwsys/DynamicLoader.hxx.in
@@ -1,34 +1,26 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_DynamicLoader_hxx
#define @KWSYS_NAMESPACE@_DynamicLoader_hxx
-#include <@KWSYS_NAMESPACE@/Configure.h>
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#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@
-{
+namespace @KWSYS_NAMESPACE@ {
/** \class DynamicLoader
* \brief Portable loading of dynamic libraries or dll's.
*
@@ -60,14 +52,14 @@ public:
#elif defined(_WIN32) && !defined(__CYGWIN__)
typedef HMODULE LibraryHandle;
#elif defined(__APPLE__)
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
- typedef NSModule LibraryHandle;
- #else
- typedef void* LibraryHandle;
- #endif
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+ typedef NSModule LibraryHandle;
+#else
+ typedef void* LibraryHandle;
+#endif
#elif defined(__BEOS__)
typedef image_id LibraryHandle;
-#else // POSIX
+#else // POSIX
typedef void* LibraryHandle;
#endif
@@ -77,14 +69,14 @@ public:
/** Load a dynamic library into the current process.
* The returned LibraryHandle can be used to access the symbols in the
* library. */
- static LibraryHandle OpenLibrary(const char*);
+ static LibraryHandle OpenLibrary(const std::string&);
/** Attempt to detach a dynamic library from the
* process. A value of true is returned if it is sucessful. */
static int CloseLibrary(LibraryHandle);
/** Find the address of the symbol in the given library. */
- static SymbolPointer GetSymbolAddress(LibraryHandle, const char*);
+ static SymbolPointer GetSymbolAddress(LibraryHandle, const std::string&);
/** Return the default module prefix for the current platform. */
static const char* LibPrefix() { return "@KWSYS_DynamicLoader_PREFIX@"; }
diff --git a/Source/kwsys/Encoding.h.in b/Source/kwsys/Encoding.h.in
new file mode 100644
index 000000000..7b6ed10f8
--- /dev/null
+++ b/Source/kwsys/Encoding.h.in
@@ -0,0 +1,69 @@
+/* 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@_Encoding_h
+#define @KWSYS_NAMESPACE@_Encoding_h
+
+#include <@KWSYS_NAMESPACE@/Configure.h>
+
+#include <wchar.h>
+
+/* Redefine all public interface symbol names to be in the proper
+ namespace. These macros are used internally to kwsys only, and are
+ 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
+#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)
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Convert a narrow string to a wide string.
+ On Windows, UTF-8 is assumed, and on other platforms,
+ the current locale is assumed.
+ */
+kwsysEXPORT size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* src,
+ size_t n);
+
+/* Convert a narrow string to a wide string.
+ This can return NULL if the conversion fails. */
+kwsysEXPORT wchar_t* kwsysEncoding_DupToWide(const char* src);
+
+/* Convert a wide string to a narrow string.
+ On Windows, UTF-8 is assumed, and on other platforms,
+ the current locale is assumed. */
+kwsysEXPORT size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* src,
+ size_t n);
+
+/* Convert a wide string to a narrow string.
+ This can return NULL if the conversion fails. */
+kwsysEXPORT char* kwsysEncoding_DupToNarrow(const wchar_t* str);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+/* 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
+#endif
+
+#endif
diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in
new file mode 100644
index 000000000..09691fd3f
--- /dev/null
+++ b/Source/kwsys/Encoding.hxx.in
@@ -0,0 +1,78 @@
+/* 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@_Encoding_hxx
+#define @KWSYS_NAMESPACE@_Encoding_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <string>
+#include <vector>
+
+namespace @KWSYS_NAMESPACE@ {
+class @KWSYS_NAMESPACE@_EXPORT Encoding
+{
+public:
+ // Container class for argc/argv.
+ class @KWSYS_NAMESPACE@_EXPORT CommandLineArguments
+ {
+ public:
+ // On Windows, get the program command line arguments
+ // in this Encoding module's 8 bit encoding.
+ // On other platforms the given argc/argv is used, and
+ // to be consistent, should be the argc/argv from main().
+ static CommandLineArguments Main(int argc, char const* const* argv);
+
+ // Construct CommandLineArguments with the given
+ // argc/argv. It is assumed that the string is already
+ // in the encoding used by this module.
+ CommandLineArguments(int argc, char const* const* argv);
+
+ // Construct CommandLineArguments with the given
+ // argc and wide argv. This is useful if wmain() is used.
+ CommandLineArguments(int argc, wchar_t const* const* argv);
+ ~CommandLineArguments();
+ CommandLineArguments(const CommandLineArguments&);
+ CommandLineArguments& operator=(const CommandLineArguments&);
+
+ int argc() const;
+ char const* const* argv() const;
+
+ protected:
+ std::vector<char*> argv_;
+ };
+
+/**
+ * Convert between char and wchar_t
+ */
+
+#if @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+
+ // Convert a narrow string to a wide string.
+ // On Windows, UTF-8 is assumed, and on other platforms,
+ // the current locale is assumed.
+ static std::wstring ToWide(const std::string& str);
+ static std::wstring ToWide(const char* str);
+
+ // Convert a wide string to a narrow string.
+ // On Windows, UTF-8 is assumed, and on other platforms,
+ // the current locale is assumed.
+ static std::string ToNarrow(const std::wstring& str);
+ static std::string ToNarrow(const wchar_t* str);
+
+#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
+ * prefixed with \\?\; if the input is instead a network path, the result
+ * will be prefixed with \\?\UNC\. All output will also be converted to
+ * absolute paths with Windows-style backslashes.
+ **/
+ static std::wstring ToWindowsExtendedPath(std::string const&);
+#endif
+
+#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+
+}; // class Encoding
+} // namespace @KWSYS_NAMESPACE@
+
+#endif
diff --git a/Source/kwsys/EncodingC.c b/Source/kwsys/EncodingC.c
new file mode 100644
index 000000000..c1315b2d5
--- /dev/null
+++ b/Source/kwsys/EncodingC.c
@@ -0,0 +1,72 @@
+/* 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(Encoding.h)
+
+/* Work-around CMake dependency scanning limitation. This must
+ duplicate the above list of headers. */
+#if 0
+#include "Encoding.h.in"
+#endif
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* str, size_t n)
+{
+ if (str == 0) {
+ return (size_t)-1;
+ }
+#ifdef _WIN32
+ return MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str, -1, dest,
+ (int)n) -
+ 1;
+#else
+ return mbstowcs(dest, str, n);
+#endif
+}
+
+wchar_t* kwsysEncoding_DupToWide(const char* str)
+{
+ wchar_t* ret = NULL;
+ size_t length = kwsysEncoding_mbstowcs(NULL, str, 0) + 1;
+ if (length > 0) {
+ ret = (wchar_t*)malloc((length) * sizeof(wchar_t));
+ if (ret) {
+ ret[0] = 0;
+ kwsysEncoding_mbstowcs(ret, str, length);
+ }
+ }
+ return ret;
+}
+
+size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n)
+{
+ if (str == 0) {
+ return (size_t)-1;
+ }
+#ifdef _WIN32
+ return WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str, -1, dest,
+ (int)n, NULL, NULL) -
+ 1;
+#else
+ return wcstombs(dest, str, n);
+#endif
+}
+
+char* kwsysEncoding_DupToNarrow(const wchar_t* str)
+{
+ char* ret = NULL;
+ size_t length = kwsysEncoding_wcstombs(0, str, 0) + 1;
+ if (length > 0) {
+ ret = (char*)malloc(length);
+ if (ret) {
+ ret[0] = 0;
+ kwsysEncoding_wcstombs(ret, str, length);
+ }
+ }
+ return ret;
+}
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
new file mode 100644
index 000000000..b1e54c958
--- /dev/null
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -0,0 +1,277 @@
+/* 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
+#endif
+
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(Encoding.h)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#include "Encoding.h.in"
+#include "Encoding.hxx.in"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <vector>
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4786)
+#endif
+
+// Windows API.
+#if defined(_WIN32)
+#include <windows.h>
+
+#include <ctype.h>
+#include <shellapi.h>
+#endif
+
+namespace KWSYS_NAMESPACE {
+
+Encoding::CommandLineArguments Encoding::CommandLineArguments::Main(
+ int argc, char const* const* argv)
+{
+#ifdef _WIN32
+ (void)argc;
+ (void)argv;
+
+ int ac;
+ LPWSTR* w_av = CommandLineToArgvW(GetCommandLineW(), &ac);
+
+ std::vector<std::string> av1(ac);
+ std::vector<char const*> av2(ac);
+ for (int i = 0; i < ac; i++) {
+ av1[i] = ToNarrow(w_av[i]);
+ av2[i] = av1[i].c_str();
+ }
+ LocalFree(w_av);
+ return CommandLineArguments(ac, &av2[0]);
+#else
+ return CommandLineArguments(argc, argv);
+#endif
+}
+
+Encoding::CommandLineArguments::CommandLineArguments(int ac,
+ char const* const* av)
+{
+ this->argv_.resize(ac + 1);
+ for (int i = 0; i < ac; i++) {
+ this->argv_[i] = strdup(av[i]);
+ }
+ this->argv_[ac] = 0;
+}
+
+Encoding::CommandLineArguments::CommandLineArguments(int ac,
+ wchar_t const* const* av)
+{
+ this->argv_.resize(ac + 1);
+ for (int i = 0; i < ac; i++) {
+ this->argv_[i] = kwsysEncoding_DupToNarrow(av[i]);
+ }
+ this->argv_[ac] = 0;
+}
+
+Encoding::CommandLineArguments::~CommandLineArguments()
+{
+ for (size_t i = 0; i < this->argv_.size(); i++) {
+ free(argv_[i]);
+ }
+}
+
+Encoding::CommandLineArguments::CommandLineArguments(
+ const CommandLineArguments& other)
+{
+ 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;
+ }
+}
+
+Encoding::CommandLineArguments& Encoding::CommandLineArguments::operator=(
+ const CommandLineArguments& other)
+{
+ if (this != &other) {
+ size_t i;
+ for (i = 0; i < this->argv_.size(); i++) {
+ free(this->argv_[i]);
+ }
+
+ 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;
+ }
+ }
+
+ return *this;
+}
+
+int Encoding::CommandLineArguments::argc() const
+{
+ return static_cast<int>(this->argv_.size() - 1);
+}
+
+char const* const* Encoding::CommandLineArguments::argv() const
+{
+ return &this->argv_[0];
+}
+
+#if KWSYS_STL_HAS_WSTRING
+
+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 (wlength > 0) {
+ wchar_t* wdata = new wchar_t[wlength];
+ int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
+ int(str.size()), wdata, wlength);
+ if (r > 0) {
+ wstr = std::wstring(wdata, wlength);
+ }
+ delete[] wdata;
+ }
+#else
+ size_t pos = 0;
+ size_t nullPos = 0;
+ do {
+ if (pos < str.size() && str.at(pos) != '\0') {
+ wstr += ToWide(str.c_str() + pos);
+ }
+ nullPos = str.find('\0', pos);
+ if (nullPos != std::string::npos) {
+ pos = nullPos + 1;
+ wstr += wchar_t('\0');
+ }
+ } while (nullPos != std::string::npos);
+#endif
+ return wstr;
+}
+
+std::string Encoding::ToNarrow(const std::wstring& str)
+{
+ std::string nstr;
+#if defined(_WIN32)
+ int length =
+ WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
+ int(str.size()), NULL, 0, NULL, NULL);
+ 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);
+ if (r > 0) {
+ nstr = std::string(data, length);
+ }
+ delete[] data;
+ }
+#else
+ size_t pos = 0;
+ size_t nullPos = 0;
+ do {
+ if (pos < str.size() && str.at(pos) != '\0') {
+ nstr += ToNarrow(str.c_str() + pos);
+ }
+ nullPos = str.find(wchar_t('\0'), pos);
+ if (nullPos != std::string::npos) {
+ pos = nullPos + 1;
+ nstr += '\0';
+ }
+ } while (nullPos != std::string::npos);
+#endif
+ return nstr;
+}
+
+std::wstring Encoding::ToWide(const char* cstr)
+{
+ std::wstring wstr;
+ size_t length = kwsysEncoding_mbstowcs(0, cstr, 0) + 1;
+ if (length > 0) {
+ std::vector<wchar_t> wchars(length);
+ if (kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0) {
+ wstr = &wchars[0];
+ }
+ }
+ return wstr;
+}
+
+std::string Encoding::ToNarrow(const wchar_t* wcstr)
+{
+ std::string str;
+ size_t length = kwsysEncoding_wcstombs(0, wcstr, 0) + 1;
+ if (length > 0) {
+ std::vector<char> chars(length);
+ if (kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0) {
+ str = &chars[0];
+ }
+ }
+ return str;
+}
+
+#if defined(_WIN32)
+// Convert local paths to UNC style paths
+std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
+{
+ std::wstring wsource = Encoding::ToWide(source);
+
+ // Resolve any relative paths
+ DWORD wfull_len;
+
+ /* 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;
+ std::vector<wchar_t> wfull(wfull_len);
+ GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL);
+
+ /* This should get the correct size without any extra padding from the
+ * previous size workaround. */
+ wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));
+
+ if (wfull_len >= 2 && isalpha(wfull[0]) &&
+ wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
+ return L"\\\\?\\" + std::wstring(&wfull[0]);
+ } else if (wfull_len >= 2 && wfull[0] == L'\\' &&
+ wfull[1] == L'\\') { /* Starts with \\ */
+ if (wfull_len >= 4 && wfull[2] == L'?' &&
+ wfull[3] == L'\\') { /* Starts with \\?\ */
+ if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
+ wfull[6] == L'C' &&
+ wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
+ return std::wstring(&wfull[0]);
+ } else if (wfull_len >= 6 && isalpha(wfull[4]) &&
+ wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
+ return std::wstring(&wfull[0]);
+ } else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
+ return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
+ }
+ } else if (wfull_len >= 4 && wfull[2] == L'.' &&
+ wfull[3] == L'\\') { /* Starts with \\.\ a device name */
+ if (wfull_len >= 6 && isalpha(wfull[4]) &&
+ wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
+ return L"\\\\?\\" + std::wstring(&wfull[4]);
+ } else if (wfull_len >=
+ 5) { /* \\.\Foo\bar\ Device name is left unchanged */
+ return std::wstring(&wfull[0]);
+ }
+ } else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
+ return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
+ }
+ }
+
+ // If this case has been reached, then the path is invalid. Leave it
+ // unchanged
+ return Encoding::ToWide(source);
+}
+#endif
+
+#endif // KWSYS_STL_HAS_WSTRING
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/FStream.cxx b/Source/kwsys/FStream.cxx
new file mode 100644
index 000000000..3c44a6fa0
--- /dev/null
+++ b/Source/kwsys/FStream.cxx
@@ -0,0 +1,55 @@
+/* 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(FStream.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#include "FStream.hxx.in"
+#endif
+
+namespace KWSYS_NAMESPACE {
+namespace FStream {
+
+BOM ReadBOM(std::istream& in)
+{
+ if (!in.good()) {
+ return BOM_None;
+ }
+ unsigned long orig = in.tellg();
+ unsigned char bom[4];
+ in.read(reinterpret_cast<char*>(bom), 2);
+ if (!in.good()) {
+ in.clear();
+ in.seekg(orig);
+ return BOM_None;
+ }
+ if (bom[0] == 0xEF && bom[1] == 0xBB) {
+ in.read(reinterpret_cast<char*>(bom + 2), 1);
+ if (in.good() && bom[2] == 0xBF) {
+ return BOM_UTF8;
+ }
+ } else if (bom[0] == 0xFE && bom[1] == 0xFF) {
+ return BOM_UTF16BE;
+ } else if (bom[0] == 0x00 && bom[1] == 0x00) {
+ in.read(reinterpret_cast<char*>(bom + 2), 2);
+ if (in.good() && bom[2] == 0xFE && bom[3] == 0xFF) {
+ return BOM_UTF32BE;
+ }
+ } else if (bom[0] == 0xFF && bom[1] == 0xFE) {
+ unsigned long p = in.tellg();
+ in.read(reinterpret_cast<char*>(bom + 2), 2);
+ if (in.good() && bom[2] == 0x00 && bom[3] == 0x00) {
+ return BOM_UTF32LE;
+ }
+ in.seekg(p);
+ return BOM_UTF16LE;
+ }
+ in.clear();
+ in.seekg(orig);
+ return BOM_None;
+}
+
+} // FStream namespace
+} // KWSYS_NAMESPACE
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
new file mode 100644
index 000000000..a4c65fe30
--- /dev/null
+++ b/Source/kwsys/FStream.hxx.in
@@ -0,0 +1,276 @@
+/* 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@_FStream_hxx
+#define @KWSYS_NAMESPACE@_FStream_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <@KWSYS_NAMESPACE@/Encoding.hxx>
+
+#include <fstream>
+#if defined(_WIN32)
+#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(_MSC_VER)
+
+template <typename CharType, typename Traits>
+class basic_filebuf : public std::basic_filebuf<CharType, Traits>
+{
+#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)
+ {
+ const std::wstring wstr = Encoding::ToWindowsExtendedPath(s);
+ return static_cast<basic_filebuf*>(my_base_type::open(wstr.c_str(), mode));
+ }
+#endif
+};
+
+#else
+
+inline std::wstring getcmode(const std::ios_base::openmode mode)
+{
+ std::wstring cmode;
+ bool plus = false;
+ if (mode & std::ios_base::app) {
+ cmode += L"a";
+ plus = mode & std::ios_base::in ? true : false;
+ } else if (mode & std::ios_base::trunc ||
+ (mode & std::ios_base::out && (mode & std::ios_base::in) == 0)) {
+ cmode += L"w";
+ plus = mode & std::ios_base::in ? true : false;
+ } else {
+ cmode += L"r";
+ plus = mode & std::ios_base::out ? true : false;
+ }
+ if (plus) {
+ cmode += L"+";
+ }
+ if (mode & std::ios_base::binary) {
+ cmode += L"b";
+ } else {
+ cmode += L"t";
+ }
+ return cmode;
+};
+
+#endif
+
+template <typename CharType, typename Traits = std::char_traits<CharType> >
+class basic_efilebuf
+{
+public:
+#if defined(_MSC_VER)
+ typedef basic_filebuf<CharType, Traits> internal_buffer_type;
+#else
+ typedef __gnu_cxx::stdio_filebuf<CharType, Traits> internal_buffer_type;
+#endif
+
+ basic_efilebuf()
+ : file_(0)
+ {
+ buf_ = 0;
+ }
+
+ bool _open(char const* file_name, std::ios_base::openmode mode)
+ {
+ if (is_open() || file_) {
+ return false;
+ }
+#if defined(_MSC_VER)
+ const bool success = buf_->open(file_name, mode) != 0;
+#else
+ const std::wstring wstr = Encoding::ToWindowsExtendedPath(file_name);
+ bool success = false;
+ std::wstring cmode = getcmode(mode);
+ file_ = _wfopen(wstr.c_str(), cmode.c_str());
+ if (file_) {
+ if (buf_) {
+ delete buf_;
+ }
+ buf_ = new internal_buffer_type(file_, mode);
+ success = true;
+ }
+#endif
+ return success;
+ }
+
+ bool is_open()
+ {
+ if (!buf_) {
+ return false;
+ }
+ return buf_->is_open();
+ }
+
+ bool is_open() const
+ {
+ if (!buf_) {
+ return false;
+ }
+ return buf_->is_open();
+ }
+
+ bool _close()
+ {
+ bool success = false;
+ if (buf_) {
+ success = buf_->close() != 0;
+#if !defined(_MSC_VER)
+ if (file_) {
+ success = fclose(file_) == 0 ? success : false;
+ file_ = 0;
+ }
+#endif
+ }
+ return success;
+ }
+
+ static void _set_state(bool success, std::basic_ios<CharType, Traits>* ios,
+ basic_efilebuf* efilebuf)
+ {
+#if !defined(_MSC_VER)
+ ios->rdbuf(efilebuf->buf_);
+#else
+ static_cast<void>(efilebuf);
+#endif
+ if (!success) {
+ ios->setstate(std::ios_base::failbit);
+ } else {
+ ios->clear();
+ }
+ }
+
+ ~basic_efilebuf()
+ {
+ if (buf_) {
+ delete buf_;
+ }
+ }
+
+protected:
+ internal_buffer_type* buf_;
+ FILE* file_;
+};
+
+template <typename CharType, typename Traits = std::char_traits<CharType> >
+class basic_ifstream : public std::basic_istream<CharType, Traits>,
+ public basic_efilebuf<CharType, Traits>
+{
+public:
+ typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
+ internal_buffer_type;
+ typedef std::basic_istream<CharType, Traits> internal_stream_type;
+
+ basic_ifstream()
+ : internal_stream_type(new internal_buffer_type())
+ {
+ this->buf_ =
+ static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
+ }
+ explicit basic_ifstream(char const* file_name,
+ std::ios_base::openmode mode = std::ios_base::in)
+ : internal_stream_type(new internal_buffer_type())
+ {
+ this->buf_ =
+ static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
+ open(file_name, mode);
+ }
+
+ void open(char const* file_name,
+ std::ios_base::openmode mode = std::ios_base::in)
+ {
+ mode = mode | std::ios_base::in;
+ this->_set_state(this->_open(file_name, mode), this, this);
+ }
+
+ void close() { this->_set_state(this->_close(), this, this); }
+
+ using basic_efilebuf<CharType, Traits>::is_open;
+
+ internal_buffer_type* rdbuf() const { return this->buf_; }
+
+ ~basic_ifstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
+};
+
+template <typename CharType, typename Traits = std::char_traits<CharType> >
+class basic_ofstream : public std::basic_ostream<CharType, Traits>,
+ public basic_efilebuf<CharType, Traits>
+{
+ using basic_efilebuf<CharType, Traits>::is_open;
+
+public:
+ typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
+ internal_buffer_type;
+ typedef std::basic_ostream<CharType, Traits> internal_stream_type;
+
+ basic_ofstream()
+ : internal_stream_type(new internal_buffer_type())
+ {
+ this->buf_ =
+ static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
+ }
+ explicit basic_ofstream(char const* file_name,
+ std::ios_base::openmode mode = std::ios_base::out)
+ : internal_stream_type(new internal_buffer_type())
+ {
+ this->buf_ =
+ static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
+ open(file_name, mode);
+ }
+ void open(char const* file_name,
+ std::ios_base::openmode mode = std::ios_base::out)
+ {
+ mode = mode | std::ios_base::out;
+ this->_set_state(this->_open(file_name, mode), this, this);
+ }
+
+ void close() { this->_set_state(this->_close(), this, this); }
+
+ internal_buffer_type* rdbuf() const { return this->buf_; }
+
+ ~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
+};
+
+typedef basic_ifstream<char> ifstream;
+typedef basic_ofstream<char> ofstream;
+
+#undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
+#else
+using std::ofstream;
+using std::ifstream;
+#endif
+
+namespace FStream {
+enum BOM
+{
+ BOM_None,
+ BOM_UTF8,
+ BOM_UTF16BE,
+ BOM_UTF16LE,
+ BOM_UTF32BE,
+ BOM_UTF32LE
+};
+
+// Read a BOM, if one exists.
+// If a BOM exists, the stream is advanced to after the BOM.
+// This function requires a seekable stream (but not a relative
+// seekable stream).
+@KWSYS_NAMESPACE@_EXPORT BOM ReadBOM(std::istream& in);
+}
+}
+
+#endif
diff --git a/Source/kwsys/FundamentalType.h.in b/Source/kwsys/FundamentalType.h.in
deleted file mode 100644
index ff200633a..000000000
--- a/Source/kwsys/FundamentalType.h.in
+++ /dev/null
@@ -1,146 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_FundamentalType_h
-#define @KWSYS_NAMESPACE@_FundamentalType_h
-
-#include <@KWSYS_NAMESPACE@/Configure.h>
-
-/* Redefine all public interface symbol names to be in the proper
- namespace. These macros are used internally to kwsys only, and are
- 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
-#endif
-
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsysFundamentalType kwsys_ns(FundamentalType)
-# define kwsysFundamentalType_Int8 kwsys_ns(FundamentalType_Int8)
-# define kwsysFundamentalType_UInt8 kwsys_ns(FundamentalType_UInt8)
-# define kwsysFundamentalType_Int16 kwsys_ns(FundamentalType_Int16)
-# define kwsysFundamentalType_UInt16 kwsys_ns(FundamentalType_UInt16)
-# define kwsysFundamentalType_Int32 kwsys_ns(FundamentalType_Int32)
-# define kwsysFundamentalType_UInt32 kwsys_ns(FundamentalType_UInt32)
-# define kwsysFundamentalType_Int64 kwsys_ns(FundamentalType_Int64)
-# define kwsysFundamentalType_UInt64 kwsys_ns(FundamentalType_UInt64)
-#endif
-
-/* The size of fundamental types. Types that do not exist have size 0. */
-@KWSYS_C_CODE_SIZEOF_CHAR@
-@KWSYS_C_CODE_SIZEOF_SHORT@
-@KWSYS_C_CODE_SIZEOF_INT@
-@KWSYS_C_CODE_SIZEOF_LONG@
-@KWSYS_C_CODE_SIZEOF_LONG_LONG@
-@KWSYS_C_CODE_SIZEOF___INT64@
-
-/* Whether types "long long" and "__int64" are enabled. If a type is
- enabled then it is a unique fundamental type. */
-#define @KWSYS_NAMESPACE@_USE_LONG_LONG @KWSYS_USE_LONG_LONG@
-#define @KWSYS_NAMESPACE@_USE___INT64 @KWSYS_USE___INT64@
-
-/* Whether type "char" is signed (it may be signed or unsigned). */
-#define @KWSYS_NAMESPACE@_CHAR_IS_SIGNED @KWSYS_CHAR_IS_SIGNED@
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-/* Select an 8-bit integer type. */
-#if @KWSYS_NAMESPACE@_SIZEOF_CHAR == 1
-typedef signed char kwsysFundamentalType_Int8;
-typedef unsigned char kwsysFundamentalType_UInt8;
-#else
-# error "No native data type can represent an 8-bit integer."
-#endif
-
-/* Select a 16-bit integer type. */
-#if @KWSYS_NAMESPACE@_SIZEOF_SHORT == 2
-typedef short kwsysFundamentalType_Int16;
-typedef unsigned short kwsysFundamentalType_UInt16;
-#elif @KWSYS_NAMESPACE@_SIZEOF_INT == 2
-typedef int kwsysFundamentalType_Int16;
-typedef unsigned int kwsysFundamentalType_UInt16;
-#else
-# error "No native data type can represent a 16-bit integer."
-#endif
-
-/* Select a 32-bit integer type. */
-#if @KWSYS_NAMESPACE@_SIZEOF_INT == 4
-typedef int kwsysFundamentalType_Int32;
-typedef unsigned int kwsysFundamentalType_UInt32;
-#elif @KWSYS_NAMESPACE@_SIZEOF_LONG == 4
-typedef long kwsysFundamentalType_Int32;
-typedef unsigned long kwsysFundamentalType_UInt32;
-#else
-# error "No native data type can represent a 32-bit integer."
-#endif
-
-/* Select a 64-bit integer type. */
-#if @KWSYS_NAMESPACE@_SIZEOF_LONG == 8
-typedef signed long kwsysFundamentalType_Int64;
-typedef unsigned long kwsysFundamentalType_UInt64;
-/* Whether UInt64 can be converted to double. */
-# define @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE 1
-#elif @KWSYS_NAMESPACE@_USE_LONG_LONG && @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG == 8
-typedef signed long long kwsysFundamentalType_Int64;
-typedef unsigned long long kwsysFundamentalType_UInt64;
-/* Whether UInt64 can be converted to double. */
-# define @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE 1
-#elif @KWSYS_NAMESPACE@_USE___INT64 && @KWSYS_NAMESPACE@_SIZEOF___INT64 == 8
-typedef signed __int64 kwsysFundamentalType_Int64;
-typedef unsigned __int64 kwsysFundamentalType_UInt64;
-/* Whether UInt64 can be converted to double. */
-# define @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE @KWSYS_CAN_CONVERT_UI64_TO_DOUBLE@
-#else
-# error "No native data type can represent a 64-bit integer."
-#endif
-
-#if defined(__cplusplus)
-} /* extern "C" */
-#endif
-
-/* 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 kwsysFundamentalType
-# undef kwsysFundamentalType_Int8
-# undef kwsysFundamentalType_UInt8
-# undef kwsysFundamentalType_Int16
-# undef kwsysFundamentalType_UInt16
-# undef kwsysFundamentalType_Int32
-# undef kwsysFundamentalType_UInt32
-# undef kwsysFundamentalType_Int64
-# undef kwsysFundamentalType_UInt64
-# endif
-#endif
-
-/* If building a C or C++ file in kwsys itself, give the source file
- access to the configured macros without a configured namespace. */
-#if defined(KWSYS_NAMESPACE)
-# define KWSYS_SIZEOF_CHAR @KWSYS_NAMESPACE@_SIZEOF_CHAR
-# define KWSYS_SIZEOF_SHORT @KWSYS_NAMESPACE@_SIZEOF_SHORT
-# define KWSYS_SIZEOF_INT @KWSYS_NAMESPACE@_SIZEOF_INT
-# define KWSYS_SIZEOF_LONG @KWSYS_NAMESPACE@_SIZEOF_LONG
-# define KWSYS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG
-# define KWSYS_SIZEOF___INT64 @KWSYS_NAMESPACE@_SIZEOF___INT64
-# define KWSYS_USE_LONG_LONG @KWSYS_NAMESPACE@_USE_LONG_LONG
-# define KWSYS_USE___INT64 @KWSYS_NAMESPACE@_USE___INT64
-# define KWSYS_CHAR_IS_SIGNED @KWSYS_NAMESPACE@_CHAR_IS_SIGNED
-# define KWSYS_CAN_CONVERT_UI64_TO_DOUBLE @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE
-#endif
-
-#endif
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 46a7e4f44..d2f0b8516 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Glob.hxx)
@@ -17,45 +8,42 @@
#include KWSYS_HEADER(RegularExpression.hxx)
#include KWSYS_HEADER(SystemTools.hxx)
#include KWSYS_HEADER(Directory.hxx)
-#include KWSYS_HEADER(stl/string)
-#include KWSYS_HEADER(stl/vector)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "Glob.hxx.in"
-# include "Directory.hxx.in"
-# include "Configure.hxx.in"
-# include "RegularExpression.hxx.in"
-# include "SystemTools.hxx.in"
-# include "kwsys_stl.hxx.in"
-# include "kwsys_stl_string.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>
+#include <string>
+#include <vector>
+
#include <ctype.h>
#include <stdio.h>
#include <string.h>
-namespace KWSYS_NAMESPACE
-{
+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
+#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
{
public:
- kwsys_stl::vector<kwsys_stl::string> Files;
- kwsys_stl::vector<kwsys::RegularExpression> Expressions;
+ std::vector<std::string> Files;
+ std::vector<kwsys::RegularExpression> Expressions;
};
-//----------------------------------------------------------------------------
Glob::Glob()
{
this->Internals = new GlobInternals;
@@ -63,454 +51,397 @@ Glob::Glob()
this->Relative = "";
this->RecurseThroughSymlinks = true;
- // RecurseThroughSymlinks is true by default for backwards compatibility,
- // not because it's a good idea...
+ // RecurseThroughSymlinks is true by default for backwards compatibility,
+ // not because it's a good idea...
this->FollowedSymlinkCount = 0;
+
+ // Keep separate variables for directory listing for back compatibility
+ this->ListDirs = true;
+ this->RecurseListDirs = false;
}
-//----------------------------------------------------------------------------
Glob::~Glob()
{
delete this->Internals;
}
-//----------------------------------------------------------------------------
-kwsys_stl::vector<kwsys_stl::string>& Glob::GetFiles()
+std::vector<std::string>& Glob::GetFiles()
{
return this->Internals->Files;
}
-//----------------------------------------------------------------------------
-kwsys_stl::string Glob::PatternToRegex(const kwsys_stl::string& pattern,
- bool require_whole_string,
- bool preserve_case)
+std::string Glob::PatternToRegex(const std::string& pattern,
+ bool require_whole_string, bool preserve_case)
{
// Incrementally build the regular expression from the pattern.
- kwsys_stl::string regex = require_whole_string? "^" : "";
- kwsys_stl::string::const_iterator pattern_first = pattern.begin();
- kwsys_stl::string::const_iterator pattern_last = pattern.end();
- for(kwsys_stl::string::const_iterator i = pattern_first;
- i != pattern_last; ++i)
- {
+ std::string regex = require_whole_string ? "^" : "";
+ std::string::const_iterator pattern_first = pattern.begin();
+ std::string::const_iterator pattern_last = pattern.end();
+ for (std::string::const_iterator i = pattern_first; i != pattern_last; ++i) {
int c = *i;
- if(c == '*')
- {
+ if (c == '*') {
// A '*' (not between brackets) matches any string.
// We modify this to not match slashes since the orignal glob
// pattern documentation was meant for matching file name
// components separated by slashes.
regex += "[^/]*";
- }
- else if(c == '?')
- {
+ } else if (c == '?') {
// A '?' (not between brackets) matches any single character.
// We modify this to not match slashes since the orignal glob
// pattern documentation was meant for matching file name
// components separated by slashes.
regex += "[^/]";
- }
- else if(c == '[')
- {
+ } else if (c == '[') {
// Parse out the bracket expression. It begins just after the
// opening character.
- kwsys_stl::string::const_iterator bracket_first = i+1;
- kwsys_stl::string::const_iterator bracket_last = bracket_first;
+ std::string::const_iterator bracket_first = i + 1;
+ std::string::const_iterator bracket_last = bracket_first;
// The first character may be complementation '!' or '^'.
- if(bracket_last != pattern_last &&
- (*bracket_last == '!' || *bracket_last == '^'))
- {
+ if (bracket_last != pattern_last &&
+ (*bracket_last == '!' || *bracket_last == '^')) {
++bracket_last;
- }
+ }
// If the next character is a ']' it is included in the brackets
// because the bracket string may not be empty.
- if(bracket_last != pattern_last && *bracket_last == ']')
- {
+ if (bracket_last != pattern_last && *bracket_last == ']') {
++bracket_last;
- }
+ }
// Search for the closing ']'.
- while(bracket_last != pattern_last && *bracket_last != ']')
- {
+ while (bracket_last != pattern_last && *bracket_last != ']') {
++bracket_last;
- }
+ }
// Check whether we have a complete bracket string.
- if(bracket_last == pattern_last)
- {
+ if (bracket_last == pattern_last) {
// The bracket string did not end, so it was opened simply by
// a '[' that is supposed to be matched literally.
regex += "\\[";
- }
- else
- {
+ } else {
// Convert the bracket string to its regex equivalent.
- kwsys_stl::string::const_iterator k = bracket_first;
+ std::string::const_iterator k = bracket_first;
// Open the regex block.
regex += "[";
// A regex range complement uses '^' instead of '!'.
- if(k != bracket_last && *k == '!')
- {
+ if (k != bracket_last && *k == '!') {
regex += "^";
++k;
- }
+ }
// Convert the remaining characters.
- for(; k != bracket_last; ++k)
- {
+ for (; k != bracket_last; ++k) {
// Backslashes must be escaped.
- if(*k == '\\')
- {
+ if (*k == '\\') {
regex += "\\";
- }
+ }
// Store this character.
regex += *k;
- }
+ }
// Close the regex block.
regex += "]";
// Jump to the end of the bracket string.
i = bracket_last;
- }
}
- else
- {
+ } else {
// A single character matches itself.
int ch = c;
- if(!(('a' <= ch && ch <= 'z') ||
- ('A' <= ch && ch <= 'Z') ||
- ('0' <= ch && ch <= '9')))
- {
+ if (!(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+ ('0' <= ch && ch <= '9'))) {
// Escape the non-alphanumeric character.
regex += "\\";
- }
+ }
#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
- else
- {
+ else {
// On case-insensitive systems file names are converted to lower
// case before matching.
- if(!preserve_case)
- {
+ if (!preserve_case) {
ch = tolower(ch);
- }
}
+ }
#endif
(void)preserve_case;
// Store the character.
regex.append(1, static_cast<char>(ch));
- }
}
+ }
- if(require_whole_string)
- {
+ if (require_whole_string) {
regex += "$";
- }
+ }
return regex;
}
-//----------------------------------------------------------------------------
-void Glob::RecurseDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir)
+bool Glob::RecurseDirectory(std::string::size_type start,
+ const std::string& dir, GlobMessages* messages)
{
kwsys::Directory d;
- if ( !d.Load(dir.c_str()) )
- {
- return;
- }
+ if (!d.Load(dir)) {
+ return true;
+ }
unsigned long cc;
- kwsys_stl::string fullname;
- kwsys_stl::string realname;
- kwsys_stl::string fname;
- for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
- {
+ std::string realname;
+ std::string fname;
+ for (cc = 0; cc < d.GetNumberOfFiles(); cc++) {
fname = d.GetFile(cc);
- if ( strcmp(fname.c_str(), ".") == 0 ||
- strcmp(fname.c_str(), "..") == 0 )
- {
+ if (fname == "." || fname == "..") {
continue;
- }
+ }
- if ( start == 0 )
- {
+ if (start == 0) {
realname = dir + fname;
- }
- else
- {
+ } else {
realname = dir + "/" + fname;
- }
+ }
-#if defined( KWSYS_GLOB_CASE_INDEPENDENT )
+#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
// On Windows and apple, no difference between lower and upper case
fname = kwsys::SystemTools::LowerCase(fname);
#endif
- if ( start == 0 )
- {
- fullname = dir + fname;
- }
- else
- {
- fullname = dir + "/" + fname;
- }
-
- bool isDir = kwsys::SystemTools::FileIsDirectory(realname.c_str());
- bool isSymLink = kwsys::SystemTools::FileIsSymlink(realname.c_str());
+ bool isDir = kwsys::SystemTools::FileIsDirectory(realname);
+ bool isSymLink = kwsys::SystemTools::FileIsSymlink(realname);
- if ( isDir && (!isSymLink || this->RecurseThroughSymlinks) )
- {
- if (isSymLink)
- {
+ if (isDir && (!isSymLink || this->RecurseThroughSymlinks)) {
+ if (isSymLink) {
++this->FollowedSymlinkCount;
+ std::string realPathErrorMessage;
+ std::string canonicalPath(
+ SystemTools::GetRealPath(dir, &realPathErrorMessage));
+
+ if (!realPathErrorMessage.empty()) {
+ if (messages) {
+ messages->push_back(Message(
+ Glob::error, "Canonical path generation from path '" + dir +
+ "' failed! Reason: '" + realPathErrorMessage + "'"));
+ }
+ return false;
}
- this->RecurseDirectory(start+1, realname);
- }
- else
- {
- if ( (this->Internals->Expressions.size() > 0) &&
- this->Internals->Expressions[
- this->Internals->Expressions.size()-1].find(fname.c_str()) )
- {
- this->AddFile(this->Internals->Files, realname.c_str());
+
+ if (std::find(this->VisitedSymlinks.begin(),
+ this->VisitedSymlinks.end(),
+ canonicalPath) == this->VisitedSymlinks.end()) {
+ if (this->RecurseListDirs) {
+ // symlinks are treated as directories
+ this->AddFile(this->Internals->Files, realname);
+ }
+
+ this->VisitedSymlinks.push_back(canonicalPath);
+ if (!this->RecurseDirectory(start + 1, realname, messages)) {
+ this->VisitedSymlinks.pop_back();
+
+ return false;
+ }
+ this->VisitedSymlinks.pop_back();
}
+ // else we have already visited this symlink - prevent cyclic recursion
+ else if (messages) {
+ std::string message;
+ for (std::vector<std::string>::const_iterator pathIt =
+ std::find(this->VisitedSymlinks.begin(),
+ this->VisitedSymlinks.end(), canonicalPath);
+ pathIt != this->VisitedSymlinks.end(); ++pathIt) {
+ message += *pathIt + "\n";
+ }
+ message += canonicalPath + "/" + fname;
+ messages->push_back(Message(Glob::cyclicRecursion, message));
+ }
+ } else {
+ if (this->RecurseListDirs) {
+ this->AddFile(this->Internals->Files, realname);
+ }
+ if (!this->RecurseDirectory(start + 1, realname, messages)) {
+ return false;
+ }
+ }
+ } else {
+ if (!this->Internals->Expressions.empty() &&
+ this->Internals->Expressions.rbegin()->find(fname)) {
+ this->AddFile(this->Internals->Files, realname);
}
}
+ }
+
+ return true;
}
-//----------------------------------------------------------------------------
-void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir)
+void Glob::ProcessDirectory(std::string::size_type start,
+ const std::string& dir, GlobMessages* messages)
{
- //kwsys_ios::cout << "ProcessDirectory: " << dir << kwsys_ios::endl;
- bool last = ( start == this->Internals->Expressions.size()-1 );
- if ( last && this->Recurse )
- {
- this->RecurseDirectory(start, dir);
+ // std::cout << "ProcessDirectory: " << dir << std::endl;
+ bool last = (start == this->Internals->Expressions.size() - 1);
+ if (last && this->Recurse) {
+ this->RecurseDirectory(start, dir, messages);
return;
- }
+ }
- if ( start >= this->Internals->Expressions.size() )
- {
+ if (start >= this->Internals->Expressions.size()) {
return;
- }
+ }
kwsys::Directory d;
- if ( !d.Load(dir.c_str()) )
- {
+ if (!d.Load(dir)) {
return;
- }
+ }
unsigned long cc;
- kwsys_stl::string fullname;
- kwsys_stl::string realname;
- kwsys_stl::string fname;
- for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
- {
+ std::string realname;
+ std::string fname;
+ for (cc = 0; cc < d.GetNumberOfFiles(); cc++) {
fname = d.GetFile(cc);
- if ( strcmp(fname.c_str(), ".") == 0 ||
- strcmp(fname.c_str(), "..") == 0 )
- {
+ if (fname == "." || fname == "..") {
continue;
- }
+ }
- if ( start == 0 )
- {
+ if (start == 0) {
realname = dir + fname;
- }
- else
- {
+ } else {
realname = dir + "/" + fname;
- }
+ }
#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
// On case-insensitive file systems convert to lower case for matching.
fname = kwsys::SystemTools::LowerCase(fname);
#endif
- if ( start == 0 )
- {
- fullname = dir + fname;
- }
- else
- {
- fullname = dir + "/" + fname;
- }
+ // std::cout << "Look at file: " << fname << std::endl;
+ // std::cout << "Match: "
+ // << this->Internals->TextExpressions[start].c_str() << std::endl;
+ // std::cout << "Real name: " << realname << std::endl;
- //kwsys_ios::cout << "Look at file: " << fname << kwsys_ios::endl;
- //kwsys_ios::cout << "Match: "
- // << this->Internals->TextExpressions[start].c_str() << kwsys_ios::endl;
- //kwsys_ios::cout << "Full name: " << fullname << kwsys_ios::endl;
-
- if ( !last &&
- !kwsys::SystemTools::FileIsDirectory(realname.c_str()) )
- {
+ if ((!last && !kwsys::SystemTools::FileIsDirectory(realname)) ||
+ (!this->ListDirs && last &&
+ kwsys::SystemTools::FileIsDirectory(realname))) {
continue;
- }
+ }
- if ( this->Internals->Expressions[start].find(fname.c_str()) )
- {
- if ( last )
- {
- this->AddFile(this->Internals->Files, realname.c_str());
- }
- else
- {
- this->ProcessDirectory(start+1, realname + "/");
- }
+ if (this->Internals->Expressions[start].find(fname)) {
+ if (last) {
+ this->AddFile(this->Internals->Files, realname);
+ } else {
+ this->ProcessDirectory(start + 1, realname, messages);
}
}
+ }
}
-//----------------------------------------------------------------------------
-bool Glob::FindFiles(const kwsys_stl::string& inexpr)
+bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages)
{
- kwsys_stl::string cexpr;
- kwsys_stl::string::size_type cc;
- kwsys_stl::string expr = inexpr;
+ std::string cexpr;
+ std::string::size_type cc;
+ std::string expr = inexpr;
this->Internals->Expressions.clear();
this->Internals->Files.clear();
- if ( !kwsys::SystemTools::FileIsFullPath(expr.c_str()) )
- {
+ if (!kwsys::SystemTools::FileIsFullPath(expr)) {
expr = kwsys::SystemTools::GetCurrentWorkingDirectory();
expr += "/" + inexpr;
- }
- kwsys_stl::string fexpr = expr;
-
- kwsys_stl::string::size_type skip = 0;
- kwsys_stl::string::size_type last_slash = 0;
- for ( cc = 0; cc < expr.size(); cc ++ )
- {
- if ( cc > 0 && expr[cc] == '/' && expr[cc-1] != '\\' )
- {
+ }
+ std::string fexpr = expr;
+
+ std::string::size_type skip = 0;
+ std::string::size_type last_slash = 0;
+ for (cc = 0; cc < expr.size(); cc++) {
+ if (cc > 0 && expr[cc] == '/' && expr[cc - 1] != '\\') {
last_slash = cc;
- }
- if ( cc > 0 &&
- (expr[cc] == '[' || expr[cc] == '?' || expr[cc] == '*') &&
- expr[cc-1] != '\\' )
- {
+ }
+ if (cc > 0 && (expr[cc] == '[' || expr[cc] == '?' || expr[cc] == '*') &&
+ expr[cc - 1] != '\\') {
break;
- }
}
- if ( last_slash > 0 )
- {
- //kwsys_ios::cout << "I can skip: " << fexpr.substr(0, last_slash)
- // << kwsys_ios::endl;
+ }
+ if (last_slash > 0) {
+ // std::cout << "I can skip: " << fexpr.substr(0, last_slash)
+ // << std::endl;
skip = last_slash;
- }
- if ( skip == 0 )
- {
-#if defined( KWSYS_GLOB_SUPPORT_NETWORK_PATHS )
+ }
+ if (skip == 0) {
+#if defined(KWSYS_GLOB_SUPPORT_NETWORK_PATHS)
// Handle network paths
- if ( expr[0] == '/' && expr[1] == '/' )
- {
+ if (expr[0] == '/' && expr[1] == '/') {
int cnt = 0;
- for ( cc = 2; cc < expr.size(); cc ++ )
- {
- if ( expr[cc] == '/' )
- {
- cnt ++;
- if ( cnt == 2 )
- {
+ for (cc = 2; cc < expr.size(); cc++) {
+ if (expr[cc] == '/') {
+ cnt++;
+ if (cnt == 2) {
break;
- }
}
}
- skip = int(cc + 1);
}
- else
+ skip = int(cc + 1);
+ } else
#endif
// Handle drive letters on Windows
- if ( expr[1] == ':' && expr[0] != '/' )
- {
- skip = 2;
- }
+ if (expr[1] == ':' && expr[0] != '/') {
+ skip = 2;
}
+ }
- if ( skip > 0 )
- {
+ if (skip > 0) {
expr = expr.substr(skip);
- }
+ }
cexpr = "";
- for ( cc = 0; cc < expr.size(); cc ++ )
- {
+ for (cc = 0; cc < expr.size(); cc++) {
int ch = expr[cc];
- if ( ch == '/' )
- {
- if ( cexpr.size() > 0 )
- {
- this->AddExpression(cexpr.c_str());
- }
- cexpr = "";
+ if (ch == '/') {
+ if (!cexpr.empty()) {
+ this->AddExpression(cexpr);
}
- else
- {
+ cexpr = "";
+ } else {
cexpr.append(1, static_cast<char>(ch));
- }
- }
- if ( cexpr.size() > 0 )
- {
- this->AddExpression(cexpr.c_str());
}
+ }
+ if (!cexpr.empty()) {
+ this->AddExpression(cexpr);
+ }
// Handle network paths
- if ( skip > 0 )
- {
- this->ProcessDirectory(0, fexpr.substr(0, skip) + "/");
- }
- else
- {
- this->ProcessDirectory(0, "/");
- }
+ if (skip > 0) {
+ this->ProcessDirectory(0, fexpr.substr(0, skip) + "/", messages);
+ } else {
+ this->ProcessDirectory(0, "/", messages);
+ }
return true;
}
-//----------------------------------------------------------------------------
-void Glob::AddExpression(const char* expr)
+void Glob::AddExpression(const std::string& expr)
{
this->Internals->Expressions.push_back(
- kwsys::RegularExpression(
- this->PatternToRegex(expr).c_str()));
+ kwsys::RegularExpression(this->PatternToRegex(expr)));
}
-//----------------------------------------------------------------------------
void Glob::SetRelative(const char* dir)
{
- if ( !dir )
- {
+ if (!dir) {
this->Relative = "";
return;
- }
+ }
this->Relative = dir;
}
-//----------------------------------------------------------------------------
const char* Glob::GetRelative()
{
- if ( this->Relative.empty() )
- {
+ if (this->Relative.empty()) {
return 0;
- }
+ }
return this->Relative.c_str();
}
-//----------------------------------------------------------------------------
-void Glob::AddFile(kwsys_stl::vector<kwsys_stl::string>& files, const char* file)
+void Glob::AddFile(std::vector<std::string>& files, const std::string& file)
{
- if ( !this->Relative.empty() )
- {
- files.push_back(kwsys::SystemTools::RelativePath(this->Relative.c_str(), file));
- }
- else
- {
+ if (!this->Relative.empty()) {
+ files.push_back(kwsys::SystemTools::RelativePath(this->Relative, file));
+ } else {
files.push_back(file);
- }
+ }
}
} // namespace KWSYS_NAMESPACE
-
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index 88c343ce0..bd4a17616 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -1,30 +1,15 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Glob_hxx
#define @KWSYS_NAMESPACE@_Glob_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/Configure.hxx>
-#include <@KWSYS_NAMESPACE@/stl/string>
-#include <@KWSYS_NAMESPACE@/stl/vector>
+#include <string>
+#include <vector>
-/* Define this macro temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsys_stl @KWSYS_NAMESPACE@_stl
-#endif
-
-namespace @KWSYS_NAMESPACE@
-{
+namespace @KWSYS_NAMESPACE@ {
class GlobInternals;
@@ -40,14 +25,47 @@ class GlobInternals;
class @KWSYS_NAMESPACE@_EXPORT Glob
{
public:
+ enum MessageType
+ {
+ error,
+ cyclicRecursion
+ };
+
+ struct Message
+ {
+ MessageType type;
+ std::string content;
+
+ Message(MessageType t, const std::string& c)
+ : type(t)
+ , 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;
+ }
+ };
+
+ typedef std::vector<Message> GlobMessages;
+ typedef std::vector<Message>::iterator GlobMessagesIterator;
+
+public:
Glob();
~Glob();
//! Find all files that match the pattern.
- bool FindFiles(const kwsys_stl::string& inexpr);
+ bool FindFiles(const std::string& inexpr, GlobMessages* messages = 0);
//! Return the list of files that matched.
- kwsys_stl::vector<kwsys_stl::string>& GetFiles();
+ std::vector<std::string>& GetFiles();
//! Set recurse to true to match subdirectories.
void RecurseOn() { this->SetRecurse(true); }
@@ -76,42 +94,49 @@ public:
string. This is on by default because patterns always match
whole strings, but may be disabled to support concatenating
expressions more easily (regex1|regex2|etc). */
- static kwsys_stl::string PatternToRegex(const kwsys_stl::string& pattern,
- bool require_whole_string = true,
- bool preserve_case = false);
+ static std::string PatternToRegex(const std::string& pattern,
+ bool require_whole_string = true,
+ bool preserve_case = false);
+
+ /** Getters and setters for enabling and disabling directory
+ listing in recursive and non recursive globbing mode.
+ If listing is enabled in recursive mode it also lists
+ directory symbolic links even if follow symlinks is enabled. */
+ void SetListDirs(bool list) { this->ListDirs = list; }
+ bool GetListDirs() const { return this->ListDirs; }
+ void SetRecurseListDirs(bool list) { this->RecurseListDirs = list; }
+ bool GetRecurseListDirs() const { return this->RecurseListDirs; }
protected:
//! Process directory
- void ProcessDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir);
+ void ProcessDirectory(std::string::size_type start, const std::string& dir,
+ GlobMessages* messages);
//! Process last directory, but only when recurse flags is on. That is
// effectively like saying: /path/to/file/**/file
- void RecurseDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir);
+ bool RecurseDirectory(std::string::size_type start, const std::string& dir,
+ GlobMessages* messages);
//! Add regular expression
- void AddExpression(const char* expr);
+ void AddExpression(const std::string& expr);
//! Add a file to the list
- void AddFile(kwsys_stl::vector<kwsys_stl::string>& files, const char* file);
+ void AddFile(std::vector<std::string>& files, const std::string& file);
GlobInternals* Internals;
bool Recurse;
- kwsys_stl::string Relative;
+ std::string Relative;
bool RecurseThroughSymlinks;
unsigned int FollowedSymlinkCount;
+ std::vector<std::string> VisitedSymlinks;
+ bool ListDirs;
+ bool RecurseListDirs;
private:
- Glob(const Glob&); // Not implemented.
- void operator=(const Glob&); // Not implemented.
+ Glob(const Glob&); // Not implemented.
+ void operator=(const Glob&); // Not implemented.
};
} // namespace @KWSYS_NAMESPACE@
-/* Undefine temporary macro. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# undef kwsys_stl
-#endif
-
#endif
diff --git a/Source/kwsys/IOStream.cxx b/Source/kwsys/IOStream.cxx
index a31f8c846..01ada1f2f 100644
--- a/Source/kwsys/IOStream.cxx
+++ b/Source/kwsys/IOStream.cxx
@@ -1,130 +1,103 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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)
-// Configure the implementation for the current streams library.
-#if !KWSYS_IOS_USE_ANSI
-# define ios_base ios
-# if defined(__HP_aCC)
-# define protected public
-# include <iostream.h> // Hack access to some private stream methods.
-# undef protected
-# endif
-#endif
-
// Include the streams library.
-#include KWSYS_HEADER(ios/iostream)
+#include <iostream>
#include KWSYS_HEADER(IOStream.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "Configure.hxx.in"
-# include "kwsys_ios_iostream.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
-{
+namespace KWSYS_NAMESPACE {
// Scan an input stream for an integer value.
-static int IOStreamScanStream(kwsys_ios::istream& is, char* buffer)
+static int IOStreamScanStream(std::istream& is, char* buffer)
{
// Prepare to write to buffer.
char* out = buffer;
char* end = buffer + KWSYS_IOS_INT64_MAX_DIG - 1;
// Look for leading sign.
- if(is.peek() == '+') { *out++ = '+'; is.ignore(); }
- else if(is.peek() == '-') { *out++ = '-'; is.ignore(); }
+ if (is.peek() == '+') {
+ *out++ = '+';
+ is.ignore();
+ } else if (is.peek() == '-') {
+ *out++ = '-';
+ is.ignore();
+ }
// Determine the base. If not specified in the stream, try to
// detect it from the input. A leading 0x means hex, and a leading
// 0 alone means octal.
int base = 0;
- int flags = is.flags() & kwsys_ios::ios_base::basefield;
- if(flags == kwsys_ios::ios_base::oct) { base = 8; }
- else if(flags == kwsys_ios::ios_base::dec) { base = 10; }
- else if(flags == kwsys_ios::ios_base::hex) { base = 16; }
+ int flags = is.flags() & std::ios_base::basefield;
+ if (flags == std::ios_base::oct) {
+ base = 8;
+ } else if (flags == std::ios_base::dec) {
+ base = 10;
+ } else if (flags == std::ios_base::hex) {
+ base = 16;
+ }
bool foundDigit = false;
bool foundNonZero = false;
- if(is.peek() == '0')
- {
+ if (is.peek() == '0') {
foundDigit = true;
is.ignore();
- if((is.peek() == 'x' || is.peek() == 'X') && (base == 0 || base == 16))
- {
+ if ((is.peek() == 'x' || is.peek() == 'X') && (base == 0 || base == 16)) {
base = 16;
foundDigit = false;
is.ignore();
- }
- else if (base == 0)
- {
+ } else if (base == 0) {
base = 8;
- }
}
+ }
// Determine the range of digits allowed for this number.
const char* digits = "0123456789abcdefABCDEF";
int maxDigitIndex = 10;
- if(base == 8)
- {
+ if (base == 8) {
maxDigitIndex = 8;
- }
- else if(base == 16)
- {
- maxDigitIndex = 10+6+6;
- }
+ } else if (base == 16) {
+ maxDigitIndex = 10 + 6 + 6;
+ }
// Scan until an invalid digit is found.
- for(;is.peek() != EOF; is.ignore())
- {
- if(memchr(digits, *out = (char)is.peek(), maxDigitIndex) != 0)
- {
- if((foundNonZero || *out != '0') && out < end)
- {
+ for (; is.peek() != EOF; is.ignore()) {
+ if (memchr(digits, *out = (char)is.peek(), maxDigitIndex) != 0) {
+ if ((foundNonZero || *out != '0') && out < end) {
++out;
foundNonZero = true;
- }
- foundDigit = true;
}
- else
- {
+ foundDigit = true;
+ } else {
break;
- }
}
+ }
// Correct the buffer contents for degenerate cases.
- if(foundDigit && !foundNonZero)
- {
+ if (foundDigit && !foundNonZero) {
*out++ = '0';
- }
- else if (!foundDigit)
- {
+ } else if (!foundDigit) {
out = buffer;
- }
+ }
// Terminate the string in the buffer.
*out = '\0';
@@ -134,141 +107,141 @@ static int IOStreamScanStream(kwsys_ios::istream& is, char* buffer)
// Read an integer value from an input stream.
template <class T>
-kwsys_ios::istream&
-IOStreamScanTemplate(kwsys_ios::istream& is, T& value, char type)
+std::istream& IOStreamScanTemplate(std::istream& is, T& value, char type)
{
- int state = kwsys_ios::ios_base::goodbit;
+ int state = std::ios_base::goodbit;
// Skip leading whitespace.
-# if KWSYS_IOS_USE_ANSI
- kwsys_ios::istream::sentry okay(is);
-# else
- is.eatwhite();
- kwsys_ios::istream& okay = is;
-# endif
-
- if(okay)
- {
-# if KWSYS_IOS_USE_ANSI
+ std::istream::sentry okay(is);
+
+ if (okay) {
try {
-# endif
- // Copy the string to a buffer and construct the format string.
- char buffer[KWSYS_IOS_INT64_MAX_DIG];
-# if defined(_MSC_VER)
- char format[] = "%I64_";
- const int typeIndex = 4;
-# else
- char format[] = "%ll_";
- const int typeIndex = 3;
-# endif
- switch(IOStreamScanStream(is, buffer))
- {
- case 8: format[typeIndex] = 'o'; break;
- case 0: // Default to decimal if not told otherwise.
- case 10: format[typeIndex] = type; break;
- case 16: format[typeIndex] = 'x'; break;
+ // Copy the string to a buffer and construct the format string.
+ char buffer[KWSYS_IOS_INT64_MAX_DIG];
+#if defined(_MSC_VER)
+ char format[] = "%I64_";
+ const int typeIndex = 4;
+#else
+ char format[] = "%ll_";
+ const int typeIndex = 3;
+#endif
+ switch (IOStreamScanStream(is, buffer)) {
+ case 8:
+ format[typeIndex] = 'o';
+ break;
+ case 0: // Default to decimal if not told otherwise.
+ case 10:
+ format[typeIndex] = type;
+ break;
+ case 16:
+ format[typeIndex] = 'x';
+ break;
};
- // Use sscanf to parse the number from the buffer.
- T result;
- int success = (sscanf(buffer, format, &result) == 1)?1:0;
-
- // Set flags for resulting state.
- if(is.peek() == EOF) { state |= kwsys_ios::ios_base::eofbit; }
- if(!success) { state |= kwsys_ios::ios_base::failbit; }
- else { value = result; }
-# if KWSYS_IOS_USE_ANSI
- } catch(...) { state |= kwsys_ios::ios_base::badbit; }
-# endif
+ // Use sscanf to parse the number from the buffer.
+ T result;
+ int success = (sscanf(buffer, format, &result) == 1) ? 1 : 0;
+
+ // Set flags for resulting state.
+ if (is.peek() == EOF) {
+ state |= std::ios_base::eofbit;
+ }
+ if (!success) {
+ state |= std::ios_base::failbit;
+ } else {
+ value = result;
+ }
+ } catch (...) {
+ state |= std::ios_base::badbit;
}
+ }
-# if KWSYS_IOS_USE_ANSI
- is.setstate(kwsys_ios::ios_base::iostate(state));
-# else
- is.clear(state);
-# endif
+ is.setstate(std::ios_base::iostate(state));
return is;
}
// Print an integer value to an output stream.
template <class T>
-kwsys_ios::ostream&
-IOStreamPrintTemplate(kwsys_ios::ostream& os, T value, char type)
+std::ostream& IOStreamPrintTemplate(std::ostream& os, T value, char type)
{
-# if KWSYS_IOS_USE_ANSI
- kwsys_ios::ostream::sentry okay(os);
-# else
- kwsys_ios::ostream& okay = os;
-# endif
- if(okay)
- {
-# if KWSYS_IOS_USE_ANSI
+ std::ostream::sentry okay(os);
+ if (okay) {
try {
-# endif
- // Construct the format string.
- char format[8];
- char* f = format;
- *f++ = '%';
- if(os.flags() & kwsys_ios::ios_base::showpos) { *f++ = '+'; }
- if(os.flags() & kwsys_ios::ios_base::showbase) { *f++ = '#'; }
-# if defined(_MSC_VER)
- *f++ = 'I'; *f++ = '6'; *f++ = '4';
-# else
- *f++ = 'l'; *f++ = 'l';
-# endif
- long bflags = os.flags() & kwsys_ios::ios_base::basefield;
- if(bflags == kwsys_ios::ios_base::oct) { *f++ = 'o'; }
- else if(bflags != kwsys_ios::ios_base::hex) { *f++ = type; }
- else if(os.flags() & kwsys_ios::ios_base::uppercase) { *f++ = 'X'; }
- else { *f++ = 'x'; }
- *f = '\0';
-
- // Use sprintf to print to a buffer and then write the
- // buffer to the stream.
- char buffer[2*KWSYS_IOS_INT64_MAX_DIG];
- sprintf(buffer, format, value);
- os << buffer;
-# if KWSYS_IOS_USE_ANSI
- } catch(...) { os.clear(os.rdstate() | kwsys_ios::ios_base::badbit); }
-# endif
+ // Construct the format string.
+ char format[8];
+ char* f = format;
+ *f++ = '%';
+ if (os.flags() & std::ios_base::showpos) {
+ *f++ = '+';
+ }
+ if (os.flags() & std::ios_base::showbase) {
+ *f++ = '#';
+ }
+#if defined(_MSC_VER)
+ *f++ = 'I';
+ *f++ = '6';
+ *f++ = '4';
+#else
+ *f++ = 'l';
+ *f++ = 'l';
+#endif
+ long bflags = os.flags() & std::ios_base::basefield;
+ if (bflags == std::ios_base::oct) {
+ *f++ = 'o';
+ } else if (bflags != std::ios_base::hex) {
+ *f++ = type;
+ } else if (os.flags() & std::ios_base::uppercase) {
+ *f++ = 'X';
+ } else {
+ *f++ = 'x';
+ }
+ *f = '\0';
+
+ // Use sprintf to print to a buffer and then write the
+ // buffer to the stream.
+ char buffer[2 * KWSYS_IOS_INT64_MAX_DIG];
+ sprintf(buffer, format, value);
+ os << buffer;
+ } catch (...) {
+ os.clear(os.rdstate() | std::ios_base::badbit);
}
+ }
return os;
}
-# if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
+#if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
// Implement input stream operator for IOStreamSLL.
-kwsys_ios::istream& IOStreamScan(kwsys_ios::istream& is, IOStreamSLL& value)
+std::istream& IOStreamScan(std::istream& is, IOStreamSLL& value)
{
return IOStreamScanTemplate(is, value, 'd');
}
// Implement input stream operator for IOStreamULL.
-kwsys_ios::istream& IOStreamScan(kwsys_ios::istream& is, IOStreamULL& value)
+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.
-kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream& os, IOStreamSLL value)
+std::ostream& IOStreamPrint(std::ostream& os, IOStreamSLL value)
{
return IOStreamPrintTemplate(os, value, 'd');
}
// Implement output stream operator for IOStreamULL.
-kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream& os, IOStreamULL value)
+std::ostream& IOStreamPrint(std::ostream& os, IOStreamULL value)
{
return IOStreamPrintTemplate(os, value, 'u');
}
-# endif
+#endif
} // namespace KWSYS_NAMESPACE
#else
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
// Create one public symbol in this object file to avoid warnings from
// archivers.
diff --git a/Source/kwsys/IOStream.hxx.in b/Source/kwsys/IOStream.hxx.in
index 2eeedf2ff..de3a2e634 100644
--- a/Source/kwsys/IOStream.hxx.in
+++ b/Source/kwsys/IOStream.hxx.in
@@ -1,142 +1,126 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_IOStream_hxx
#define @KWSYS_NAMESPACE@_IOStream_hxx
-#include <@KWSYS_NAMESPACE@/ios/iosfwd>
+#include <iosfwd>
/* Define these macros temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
-# define kwsys_ios @KWSYS_NAMESPACE@_ios
+#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
/* Whether istream supports long long. */
-#define @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_IOS_HAS_ISTREAM_LONG_LONG@
+#define @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG \
+ @KWSYS_IOS_HAS_ISTREAM_LONG_LONG@
/* Whether ostream supports long long. */
-#define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@
+#define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG \
+ @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@
/* 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
- namespace @KWSYS_NAMESPACE@
- {
- typedef long long IOStreamSLL;
- typedef unsigned long long IOStreamULL;
- }
-# endif
+#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
#elif defined(_MSC_VER) && _MSC_VER < 1300
-# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
- namespace @KWSYS_NAMESPACE@
- {
- typedef __int64 IOStreamSLL;
- typedef unsigned __int64 IOStreamULL;
- }
+#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@
-{
-kwsysEXPORT kwsys_ios::istream& IOStreamScan(kwsys_ios::istream&,
- IOStreamSLL&);
-kwsysEXPORT kwsys_ios::istream& IOStreamScan(kwsys_ios::istream&,
- IOStreamULL&);
+namespace @KWSYS_NAMESPACE@ {
+kwsysEXPORT std::istream& IOStreamScan(std::istream&, IOStreamSLL&);
+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
-inline kwsys_ios::istream&
-operator>>(kwsys_ios::istream& is, @KWSYS_NAMESPACE@::IOStreamSLL& value)
+#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
-inline kwsys_ios::istream&
-operator>>(kwsys_ios::istream& is, @KWSYS_NAMESPACE@::IOStreamULL& value)
+#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@
-{
-kwsysEXPORT kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream&,
- IOStreamSLL);
-kwsysEXPORT kwsys_ios::ostream& IOStreamPrint(kwsys_ios::ostream&,
- IOStreamULL);
+namespace @KWSYS_NAMESPACE@ {
+kwsysEXPORT std::ostream& IOStreamPrint(std::ostream&, IOStreamSLL);
+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
-inline kwsys_ios::ostream&
-operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamSLL value)
+#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
-inline kwsys_ios::ostream&
-operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamULL value)
+#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
+#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 kwsys_ios
+#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+#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 56776a324..3188fb67a 100644
--- a/Source/kwsys/MD5.c
+++ b/Source/kwsys/MD5.c
@@ -1,37 +1,26 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(MD5.h)
/* 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 */
-#include <stdlib.h> /* malloc, free */
-#include <string.h> /* memcpy, strlen */
-
-/*--------------------------------------------------------------------------*/
+#include <stddef.h> /* size_t */
+#include <stdlib.h> /* malloc, free */
+#include <string.h> /* memcpy, strlen */
/* This MD5 implementation has been taken from a third party. Slight
modifications to the arrangement of the code have been made to put
it in a single source file instead of a separate header and
implementation file. */
-#if defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wcast-align"
+#if defined(__clang__) && !defined(__INTEL_COMPILER)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-align"
#endif
/*
@@ -97,401 +86,391 @@
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
+typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
- md5_word_t count[2]; /* message length in bits, lsw first */
- md5_word_t abcd[4]; /* digest buffer */
- md5_byte_t buf[64]; /* accumulate block */
+typedef struct md5_state_s
+{
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
-#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#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)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
+#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
+#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
+#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
+#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
+#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
+#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
+#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
+#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
+#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
+#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
+#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
+#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
+#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
+#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
+#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
+#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
+#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
+#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
+#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
+#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+static void md5_process(md5_state_t* pms, const md5_byte_t* data /*[64]*/)
{
- md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
- md5_word_t t;
+ md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2],
+ d = pms->abcd[3];
+ md5_word_t t;
#if BYTE_ORDER > 0
- /* Define storage only for big-endian CPUs. */
- md5_word_t X[16];
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
#else
- /* Define storage for little-endian or both types of CPUs. */
- md5_word_t xbuf[16];
- const md5_word_t *X;
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t* X;
#endif
- {
+ {
#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t*)&w)) /* dynamic little-endian */
#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t*)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t*)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
#endif
#if BYTE_ORDER == 0
- else /* dynamic big-endian */
+ else /* dynamic big-endian */
#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
-
-# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
-# 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));
- }
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t* xp = data;
+ int i;
+
+#if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+#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));
}
+#endif
+ }
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 1. */
+/* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + F(b, c, d) + X[k] + (Ti); \
a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 7, T1);
- SET(d, a, b, c, 1, 12, T2);
- SET(c, d, a, b, 2, 17, T3);
- SET(b, c, d, a, 3, 22, T4);
- SET(a, b, c, d, 4, 7, T5);
- SET(d, a, b, c, 5, 12, T6);
- SET(c, d, a, b, 6, 17, T7);
- SET(b, c, d, a, 7, 22, T8);
- SET(a, b, c, d, 8, 7, T9);
- SET(d, a, b, c, 9, 12, T10);
- SET(c, d, a, b, 10, 17, T11);
- SET(b, c, d, a, 11, 22, T12);
- SET(a, b, c, d, 12, 7, T13);
- SET(d, a, b, c, 13, 12, T14);
- SET(c, d, a, b, 14, 17, T15);
- SET(b, c, d, a, 15, 22, T16);
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
#undef SET
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 2. */
+/* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + G(b, c, d) + X[k] + (Ti); \
a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 1, 5, T17);
- SET(d, a, b, c, 6, 9, T18);
- SET(c, d, a, b, 11, 14, T19);
- SET(b, c, d, a, 0, 20, T20);
- SET(a, b, c, d, 5, 5, T21);
- SET(d, a, b, c, 10, 9, T22);
- SET(c, d, a, b, 15, 14, T23);
- SET(b, c, d, a, 4, 20, T24);
- SET(a, b, c, d, 9, 5, T25);
- SET(d, a, b, c, 14, 9, T26);
- SET(c, d, a, b, 3, 14, T27);
- SET(b, c, d, a, 8, 20, T28);
- SET(a, b, c, d, 13, 5, T29);
- SET(d, a, b, c, 2, 9, T30);
- SET(c, d, a, b, 7, 14, T31);
- SET(b, c, d, a, 12, 20, T32);
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
#undef SET
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 3. */
+/* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + H(b,c,d) + X[k] + Ti;\
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + H(b, c, d) + X[k] + (Ti); \
a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 5, 4, T33);
- SET(d, a, b, c, 8, 11, T34);
- SET(c, d, a, b, 11, 16, T35);
- SET(b, c, d, a, 14, 23, T36);
- SET(a, b, c, d, 1, 4, T37);
- SET(d, a, b, c, 4, 11, T38);
- SET(c, d, a, b, 7, 16, T39);
- SET(b, c, d, a, 10, 23, T40);
- SET(a, b, c, d, 13, 4, T41);
- SET(d, a, b, c, 0, 11, T42);
- SET(c, d, a, b, 3, 16, T43);
- SET(b, c, d, a, 6, 23, T44);
- SET(a, b, c, d, 9, 4, T45);
- SET(d, a, b, c, 12, 11, T46);
- SET(c, d, a, b, 15, 16, T47);
- SET(b, c, d, a, 2, 23, T48);
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
#undef SET
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+/* Round 4. */
+/* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + I(b, c, d) + X[k] + (Ti); \
a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 6, T49);
- SET(d, a, b, c, 7, 10, T50);
- SET(c, d, a, b, 14, 15, T51);
- SET(b, c, d, a, 5, 21, T52);
- SET(a, b, c, d, 12, 6, T53);
- SET(d, a, b, c, 3, 10, T54);
- SET(c, d, a, b, 10, 15, T55);
- SET(b, c, d, a, 1, 21, T56);
- SET(a, b, c, d, 8, 6, T57);
- SET(d, a, b, c, 15, 10, T58);
- SET(c, d, a, b, 6, 15, T59);
- SET(b, c, d, a, 13, 21, T60);
- SET(a, b, c, d, 4, 6, T61);
- SET(d, a, b, c, 11, 10, T62);
- SET(c, d, a, b, 2, 15, T63);
- SET(b, c, d, a, 9, 21, T64);
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
#undef SET
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- pms->abcd[0] += a;
- pms->abcd[1] += b;
- pms->abcd[2] += c;
- pms->abcd[3] += d;
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
}
/* Initialize the algorithm. */
-static void md5_init(md5_state_t *pms)
+static void md5_init(md5_state_t* pms)
{
- pms->count[0] = pms->count[1] = 0;
- pms->abcd[0] = 0x67452301;
- pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- pms->abcd[3] = 0x10325476;
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
}
/* Append a string to the message. */
-static void md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes)
+static void md5_append(md5_state_t* pms, const md5_byte_t* data, size_t nbytes)
{
- const md5_byte_t *p = data;
- size_t left = nbytes;
- size_t offset = (pms->count[0] >> 3) & 63;
- md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
- if (nbytes <= 0)
- return;
-
- /* Update the message length. */
- pms->count[1] += (md5_word_t)(nbytes >> 29);
- pms->count[0] += nbits;
- if (pms->count[0] < nbits)
- pms->count[1]++;
-
- /* Process an initial partial block. */
- if (offset) {
- size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
- }
+ const md5_byte_t* p = data;
+ size_t left = nbytes;
+ size_t offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
- /* Process full blocks. */
- for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
+ if (nbytes <= 0)
+ return;
- /* Process a final partial block. */
- if (left)
- memcpy(pms->buf, p, left);
+ /* Update the message length. */
+ pms->count[1] += (md5_word_t)(nbytes >> 29);
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
}
/* Finish the message and return the digest. */
-static void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+static void md5_finish(md5_state_t* pms, md5_byte_t digest[16])
{
- static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- md5_byte_t data[8];
- int i;
-
- /* Save the length before padding. */
- for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
- /* Pad to 56 bytes mod 64. */
- md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- md5_append(pms, data, 8);
- for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+ static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}
-#if defined(__clang__)
-# pragma clang diagnostic pop
+#if defined(__clang__) && !defined(__INTEL_COMPILER)
+#pragma clang diagnostic pop
#endif
-/*--------------------------------------------------------------------------*/
/* Wrap up the MD5 state in our opaque structure. */
struct kwsysMD5_s
{
md5_state_t md5_state;
};
-/*--------------------------------------------------------------------------*/
kwsysMD5* kwsysMD5_New(void)
{
/* Allocate a process control structure. */
kwsysMD5* md5 = (kwsysMD5*)malloc(sizeof(kwsysMD5));
- if(!md5)
- {
+ if (!md5) {
return 0;
- }
+ }
return md5;
}
-/*--------------------------------------------------------------------------*/
void kwsysMD5_Delete(kwsysMD5* md5)
{
/* Make sure we have an instance. */
- if(!md5)
- {
+ if (!md5) {
return;
- }
+ }
/* Free memory. */
free(md5);
}
-/*--------------------------------------------------------------------------*/
void kwsysMD5_Initialize(kwsysMD5* md5)
{
md5_init(&md5->md5_state);
}
-/*--------------------------------------------------------------------------*/
void kwsysMD5_Append(kwsysMD5* md5, unsigned char const* data, int length)
{
- if(length < 0)
- {
- length = (int)strlen((char const*)data);
- }
- md5_append(&md5->md5_state, (md5_byte_t const*)data, (size_t)length);
+ size_t dlen;
+ if (length < 0) {
+ dlen = strlen((char const*)data);
+ } else {
+ dlen = (size_t)length;
+ }
+ md5_append(&md5->md5_state, (md5_byte_t const*)data, dlen);
}
-/*--------------------------------------------------------------------------*/
void kwsysMD5_Finalize(kwsysMD5* md5, unsigned char digest[16])
{
md5_finish(&md5->md5_state, (md5_byte_t*)digest);
}
-/*--------------------------------------------------------------------------*/
void kwsysMD5_FinalizeHex(kwsysMD5* md5, char buffer[32])
{
unsigned char digest[16];
@@ -499,20 +478,17 @@ void kwsysMD5_FinalizeHex(kwsysMD5* md5, char buffer[32])
kwsysMD5_DigestToHex(digest, buffer);
}
-/*--------------------------------------------------------------------------*/
void kwsysMD5_DigestToHex(unsigned char const digest[16], char buffer[32])
{
/* Map from 4-bit index to hexadecimal representation. */
- static char const hex[16] =
- {'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ static char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/* Map each 4-bit block separately. */
char* out = buffer;
int i;
- for(i=0; i < 16; ++i)
- {
+ for (i = 0; i < 16; ++i) {
*out++ = hex[digest[i] >> 4];
*out++ = hex[digest[i] & 0xF];
- }
+ }
}
diff --git a/Source/kwsys/MD5.h.in b/Source/kwsys/MD5.h.in
index 33344317d..c257f7f9a 100644
--- a/Source/kwsys/MD5.h.in
+++ b/Source/kwsys/MD5.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_MD5_h
#define @KWSYS_NAMESPACE@_MD5_h
@@ -19,24 +10,23 @@
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)
-extern "C"
-{
+extern "C" {
#endif
/**
@@ -89,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 c5995eac1..237001c60 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Process_h
#define @KWSYS_NAMESPACE@_Process_h
@@ -19,66 +10,78 @@
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_Verbatim kwsys_ns(Process_Option_Verbatim)
-# 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_GetState kwsys_ns(Process_GetState)
-# 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_GetExitException kwsys_ns(Process_GetExitException)
-# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
-# 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_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_Kill kwsys_ns(Process_Kill)
+#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)
#endif
#if defined(__cplusplus)
-extern "C"
-{
+extern "C" {
#endif
/**
@@ -186,12 +189,27 @@ kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe,
* 0 = No (default)
* 1 = Yes
*
+ * kwsysProcess_Option_MergeOutput = Whether to merge stdout/stderr.
+ * No content will be returned as stderr.
+ * Any actual stderr will be on stdout.
+ * 0 = No (default)
+ * 1 = Yes
+ *
* kwsysProcess_Option_Verbatim = Whether SetCommand and AddCommand
* should treat the first argument
* as a verbatim command line
* and ignore the rest of the arguments.
* 0 = No (default)
* 1 = Yes
+ *
+ * kwsysProcess_Option_CreateProcessGroup = Whether to place the process in a
+ * new process group. This is
+ * useful if you want to send Ctrl+C
+ * to the process. On UNIX, also
+ * places the process in a new
+ * session.
+ * 0 = No (default)
+ * 1 = Yes
*/
kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId);
kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId,
@@ -200,7 +218,9 @@ enum kwsysProcess_Option_e
{
kwsysProcess_Option_HideWindow,
kwsysProcess_Option_Detach,
- kwsysProcess_Option_Verbatim
+ kwsysProcess_Option_MergeOutput,
+ kwsysProcess_Option_Verbatim,
+ kwsysProcess_Option_CreateProcessGroup
};
/**
@@ -235,9 +255,12 @@ enum kwsysProcess_State_e
*
* 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_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_GetExitException(kwsysProcess* cp);
@@ -283,6 +306,67 @@ 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.
+*/
+kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx);
+enum kwsysProcess_StateByIndex_e
+{
+ kwsysProcess_StateByIndex_Starting = kwsysProcess_State_Starting,
+ kwsysProcess_StateByIndex_Exception = kwsysProcess_State_Exception,
+ kwsysProcess_StateByIndex_Exited = kwsysProcess_State_Exited,
+ kwsysProcess_StateByIndex_Error = kwsysProcess_State_Error
+};
+
+/**
+* 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.
+*/
+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).
+*/
+kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx);
+
+/**
+* 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);
+
+/**
* Start executing the child process.
*/
kwsysEXPORT void kwsysProcess_Execute(kwsysProcess* cp);
@@ -331,7 +415,7 @@ enum kwsysProcess_Pipes_e
kwsysProcess_Pipe_STDIN,
kwsysProcess_Pipe_STDOUT,
kwsysProcess_Pipe_STDERR,
- kwsysProcess_Pipe_Timeout=255
+ kwsysProcess_Pipe_Timeout = 255
};
/**
@@ -355,12 +439,28 @@ enum kwsysProcess_Pipes_e
kwsysEXPORT int kwsysProcess_WaitForExit(kwsysProcess* cp, double* timeout);
/**
+ * Interrupt the process group for the child process that is currently
+ * running by sending it the appropriate operating-system specific signal.
+ * The caller should call WaitForExit after this returns to wait for the
+ * child to terminate.
+ *
+ * WARNING: If you didn't specify kwsysProcess_Option_CreateProcessGroup,
+ * you will interrupt your own process group.
+ */
+kwsysEXPORT void kwsysProcess_Interrupt(kwsysProcess* cp);
+
+/**
* Forcefully terminate the child process that is currently running.
* The caller should call WaitForExit after this returns to wait for
* the child to terminate.
*/
kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
+/**
+ * Reset the start time of the child process to the current time.
+ */
+kwsysEXPORT void kwsysProcess_ResetStartTime(kwsysProcess* cp);
+
#if defined(__cplusplus)
} /* extern "C" */
#endif
@@ -368,61 +468,65 @@ kwsysEXPORT void kwsysProcess_Kill(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_Verbatim
-# 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_Kill
-# 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 b9af2f1f5..9ebcfce59 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Process.h)
#include KWSYS_HEADER(System.h)
@@ -16,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
/*
@@ -35,7 +26,6 @@ races.
*/
-
/*
TODO:
@@ -50,29 +40,30 @@ 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 */
+#include <ctype.h> /* isspace */
+#include <dirent.h> /* DIR, dirent */
+#include <errno.h> /* errno */
+#include <fcntl.h> /* fcntl */
+#include <signal.h> /* sigaction */
#include <stddef.h> /* ptrdiff_t */
#include <stdio.h> /* snprintf */
#include <stdlib.h> /* malloc, free */
#include <string.h> /* strdup, strerror, memset */
+#include <sys/stat.h> /* open mode */
#include <sys/time.h> /* struct timeval */
#include <sys/types.h> /* pid_t, fd_set */
#include <sys/wait.h> /* waitpid */
-#include <sys/stat.h> /* open mode */
-#include <unistd.h> /* pipe, close, fork, execvp, select, _exit */
-#include <fcntl.h> /* fcntl */
-#include <errno.h> /* errno */
#include <time.h> /* gettimeofday */
-#include <signal.h> /* sigaction */
-#include <dirent.h> /* DIR, dirent */
-#include <ctype.h> /* isspace */
+#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
@@ -87,15 +78,15 @@ typedef ssize_t kwsysProcess_ssize_t;
typedef int kwsysProcess_ssize_t;
#endif
-#if defined(__BEOS__) && !defined(__ZETA__)
+#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
/*
@@ -109,12 +100,12 @@ static inline void kwsysProcess_usleep(unsigned int msec)
* without select().
*/
#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__)
-# define KWSYSPE_USE_SELECT 1
+#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
@@ -149,14 +140,14 @@ typedef struct kwsysProcessCreateInformation_s
int ErrorPipe[2];
} kwsysProcessCreateInformation;
-/*--------------------------------------------------------------------------*/
+static void kwsysProcessVolatileFree(volatile void* p);
static int kwsysProcessInitialize(kwsysProcess* cp);
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanupDescriptor(int* pfd);
static void kwsysProcessClosePipes(kwsysProcess* cp);
static int kwsysProcessSetNonBlocking(int fd);
static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
- kwsysProcessCreateInformation* si, int* readEnd);
+ kwsysProcessCreateInformation* si);
static void kwsysProcessDestroy(kwsysProcess* cp);
static int kwsysProcessSetupOutputPipeFile(int* p, const char* name);
static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]);
@@ -170,9 +161,12 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void);
static double kwsysProcessTimeToDouble(kwsysProcessTime t);
static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
-static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
-static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
-static void kwsysProcessSetExitException(kwsysProcess* cp, int sig);
+static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
+ kwsysProcessTime in2);
+static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
+ kwsysProcessTime in2);
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
+ int idx);
static void kwsysProcessChildErrorExit(int errorPipe);
static void kwsysProcessRestoreDefaultSignalHandlers(void);
static pid_t kwsysProcessFork(kwsysProcess* cp,
@@ -190,26 +184,51 @@ static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
static void kwsysProcessesSignalHandler(int signum);
#endif
-/*--------------------------------------------------------------------------*/
+/* A structure containing results data for each process. */
+typedef struct kwsysProcessResults_s kwsysProcessResults;
+struct kwsysProcessResults_s
+{
+ /* The status of the child process. */
+ int State;
+
+ /* The exceptional behavior that terminated the process, if any. */
+ int ExitException;
+
+ /* The process exit code. */
+ int ExitCode;
+
+ /* The process return code, if any. */
+ int ExitValue;
+
+ /* Description for the ExitException. */
+ char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+};
+
/* Structure containing data used to implement the child's execution. */
struct kwsysProcess_s
{
/* The command lines to execute. */
char*** Commands;
- int NumberOfCommands;
+ volatile int NumberOfCommands;
/* Descriptors for the read ends of the child's output pipes and
the signal pipe. */
int PipeReadEnds[KWSYSPE_PIPE_COUNT];
+ /* Descriptors for the child's ends of the pipes.
+ Used temporarily during process creation. */
+ int PipeChildStd[3];
+
/* Write descriptor for child termination signal pipe. */
int SignalPipe;
/* Buffer for pipe data. */
char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE];
- /* Process IDs returned by the calls to fork. */
- pid_t* ForkPIDs;
+ /* Process IDs returned by the calls to fork. Everything is volatile
+ because the signal handler accesses them. You must be very careful
+ 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. */
int SelectError;
@@ -229,6 +248,12 @@ struct kwsysProcess_s
/* Whether to treat command lines as verbatim. */
int Verbatim;
+ /* Whether to merge stdout/stderr of the child. */
+ int MergeOutput;
+
+ /* Whether to create the process in a new process group. */
+ volatile sig_atomic_t CreateProcessGroup;
+
/* Time at which the child started. Negative for no timeout. */
kwsysProcessTime StartTime;
@@ -249,27 +274,18 @@ struct kwsysProcess_s
/* The number of children still executing. */
int CommandsLeft;
- /* The current status of the child process. */
- int State;
-
- /* The exceptional behavior that terminated the child process, if
- * any. */
- int ExitException;
-
- /* The exit code of the child process. */
- int ExitCode;
-
- /* The exit value of the child process, if any. */
- int ExitValue;
+ /* The status of the process structure. Must be atomic because
+ the signal handler checks this to avoid a race. */
+ volatile sig_atomic_t State;
/* Whether the process was killed. */
- int Killed;
+ volatile sig_atomic_t Killed;
/* Buffer for error message in case of failure. */
- char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
+ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
- /* Description for the ExitException. */
- char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1];
+ /* process results. */
+ kwsysProcessResults* ProcessResults;
/* The exit codes of each child process in the pipeline. */
int* CommandExitCodes;
@@ -294,15 +310,13 @@ struct kwsysProcess_s
char* RealWorkingDirectory;
};
-/*--------------------------------------------------------------------------*/
kwsysProcess* kwsysProcess_New(void)
{
/* Allocate a process control structure. */
kwsysProcess* cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
+ }
memset(cp, 0, sizeof(kwsysProcess));
/* Share stdin with the parent process by default. */
@@ -322,27 +336,21 @@ kwsysProcess* kwsysProcess_New(void)
return cp;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_Delete(kwsysProcess* cp)
{
/* Make sure we have an instance. */
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
/* If the process is executing, wait for it to finish. */
- if(cp->State == kwsysProcess_State_Executing)
- {
- if(cp->Detached)
- {
+ if (cp->State == kwsysProcess_State_Executing) {
+ if (cp->Detached) {
kwsysProcess_Disown(cp);
- }
- else
- {
+ } else {
kwsysProcess_WaitForExit(cp, 0);
- }
}
+ }
/* Free memory. */
kwsysProcess_SetCommand(cp, 0);
@@ -350,124 +358,107 @@ 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)
- {
+ if (cp->CommandExitCodes) {
free(cp->CommandExitCodes);
- }
+ }
+ free(cp->ProcessResults);
free(cp);
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
{
int i;
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ }
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
char** c = cp->Commands[i];
- while(*c)
- {
+ while (*c) {
free(*c++);
- }
- free(cp->Commands[i]);
}
+ free(cp->Commands[i]);
+ }
cp->NumberOfCommands = 0;
- if(cp->Commands)
- {
+ if (cp->Commands) {
free(cp->Commands);
cp->Commands = 0;
- }
- if(command)
- {
+ }
+ if (command) {
return kwsysProcess_AddCommand(cp, command);
- }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
{
int newNumberOfCommands;
char*** newCommands;
/* Make sure we have a command to add. */
- if(!cp || !command || !*command)
- {
+ if (!cp || !command || !*command) {
return 0;
- }
+ }
/* Allocate a new array for command pointers. */
newNumberOfCommands = cp->NumberOfCommands + 1;
- if(!(newCommands =
- (char***)malloc(sizeof(char**) *(size_t)(newNumberOfCommands))))
- {
+ if (!(newCommands =
+ (char***)malloc(sizeof(char**) * (size_t)(newNumberOfCommands)))) {
/* Out of memory. */
return 0;
- }
+ }
/* Copy any existing commands into the new array. */
{
- int i;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- newCommands[i] = cp->Commands[i];
+ int i;
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ newCommands[i] = cp->Commands[i];
}
}
/* Add the new command. */
- if(cp->Verbatim)
- {
+ if (cp->Verbatim) {
/* In order to run the given command line verbatim we need to
parse it. */
newCommands[cp->NumberOfCommands] =
kwsysSystem_Parse_CommandForUnix(*command, 0);
- if(!newCommands[cp->NumberOfCommands] ||
- !newCommands[cp->NumberOfCommands][0])
- {
+ if (!newCommands[cp->NumberOfCommands] ||
+ !newCommands[cp->NumberOfCommands][0]) {
/* Out of memory or no command parsed. */
free(newCommands);
return 0;
- }
}
- else
- {
+ } else {
/* Copy each argument string individually. */
char const* const* c = command;
kwsysProcess_ptrdiff_t n = 0;
kwsysProcess_ptrdiff_t i = 0;
- while(*c++);
+ while (*c++)
+ ;
n = c - command - 1;
newCommands[cp->NumberOfCommands] =
- (char**)malloc((size_t)(n+1)*sizeof(char*));
- if(!newCommands[cp->NumberOfCommands])
- {
+ (char**)malloc((size_t)(n + 1) * sizeof(char*));
+ if (!newCommands[cp->NumberOfCommands]) {
/* Out of memory. */
free(newCommands);
return 0;
- }
- for(i=0; i < n; ++i)
- {
+ }
+ for (i = 0; i < n; ++i) {
+ assert(command[i]); /* Quiet Clang scan-build. */
newCommands[cp->NumberOfCommands][i] = strdup(command[i]);
- if(!newCommands[cp->NumberOfCommands][i])
- {
+ if (!newCommands[cp->NumberOfCommands][i]) {
break;
- }
}
- if(i < n)
- {
+ }
+ if (i < n) {
/* Out of memory. */
- for(;i > 0; --i)
- {
- free(newCommands[cp->NumberOfCommands][i-1]);
- }
+ for (; i > 0; --i) {
+ free(newCommands[cp->NumberOfCommands][i - 1]);
+ }
free(newCommands);
return 0;
- }
- newCommands[cp->NumberOfCommands][n] = 0;
}
+ newCommands[cp->NumberOfCommands][n] = 0;
+ }
/* Successfully allocated new command array. Free the old array. */
free(cp->Commands);
@@ -477,379 +468,476 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
return 1;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
{
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
cp->Timeout = timeout;
- if(cp->Timeout < 0)
- {
+ if (cp->Timeout < 0) {
cp->Timeout = 0;
- }
+ }
+ // Force recomputation of TimeoutTime.
+ cp->TimeoutTime.tv_sec = -1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
{
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
- if(cp->WorkingDirectory == dir)
- {
+ }
+ if (cp->WorkingDirectory == dir) {
return 1;
- }
- if(cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0)
- {
+ }
+ if (cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0) {
return 1;
- }
- if(cp->WorkingDirectory)
- {
+ }
+ if (cp->WorkingDirectory) {
free(cp->WorkingDirectory);
cp->WorkingDirectory = 0;
- }
- if(dir)
- {
+ }
+ if (dir) {
cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1);
- if(!cp->WorkingDirectory)
- {
+ if (!cp->WorkingDirectory) {
return 0;
- }
- strcpy(cp->WorkingDirectory, dir);
}
+ strcpy(cp->WorkingDirectory, dir);
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file)
{
char** pfile;
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
- switch(prPipe)
- {
- case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break;
- case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break;
- case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break;
- default: return 0;
- }
- if(*pfile)
- {
+ }
+ switch (prPipe) {
+ case kwsysProcess_Pipe_STDIN:
+ pfile = &cp->PipeFileSTDIN;
+ break;
+ case kwsysProcess_Pipe_STDOUT:
+ pfile = &cp->PipeFileSTDOUT;
+ break;
+ case kwsysProcess_Pipe_STDERR:
+ pfile = &cp->PipeFileSTDERR;
+ break;
+ default:
+ return 0;
+ }
+ if (*pfile) {
free(*pfile);
*pfile = 0;
- }
- if(file)
- {
- *pfile = malloc(strlen(file)+1);
- if(!*pfile)
- {
+ }
+ if (file) {
+ *pfile = (char*)malloc(strlen(file) + 1);
+ if (!*pfile) {
return 0;
- }
- strcpy(*pfile, file);
}
+ strcpy(*pfile, file);
+ }
/* If we are redirecting the pipe, do not share it or use a native
pipe. */
- if(*pfile)
- {
+ if (*pfile) {
kwsysProcess_SetPipeNative(cp, prPipe, 0);
kwsysProcess_SetPipeShared(cp, prPipe, 0);
- }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared)
{
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
- switch(prPipe)
- {
- case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break;
- case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break;
- case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break;
- default: return;
- }
+ switch (prPipe) {
+ case kwsysProcess_Pipe_STDIN:
+ cp->PipeSharedSTDIN = shared ? 1 : 0;
+ break;
+ case kwsysProcess_Pipe_STDOUT:
+ cp->PipeSharedSTDOUT = shared ? 1 : 0;
+ break;
+ case kwsysProcess_Pipe_STDERR:
+ cp->PipeSharedSTDERR = shared ? 1 : 0;
+ break;
+ default:
+ return;
+ }
/* If we are sharing the pipe, do not redirect it to a file or use a
native pipe. */
- if(shared)
- {
+ if (shared) {
kwsysProcess_SetPipeFile(cp, prPipe, 0);
kwsysProcess_SetPipeNative(cp, prPipe, 0);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2])
{
int* pPipeNative = 0;
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
- switch(prPipe)
- {
- case kwsysProcess_Pipe_STDIN: pPipeNative = cp->PipeNativeSTDIN; break;
- case kwsysProcess_Pipe_STDOUT: pPipeNative = cp->PipeNativeSTDOUT; break;
- case kwsysProcess_Pipe_STDERR: pPipeNative = cp->PipeNativeSTDERR; break;
- default: return;
- }
+ switch (prPipe) {
+ case kwsysProcess_Pipe_STDIN:
+ pPipeNative = cp->PipeNativeSTDIN;
+ break;
+ case kwsysProcess_Pipe_STDOUT:
+ pPipeNative = cp->PipeNativeSTDOUT;
+ break;
+ case kwsysProcess_Pipe_STDERR:
+ pPipeNative = cp->PipeNativeSTDERR;
+ break;
+ default:
+ return;
+ }
/* Copy the native pipe descriptors provided. */
- if(p)
- {
+ if (p) {
pPipeNative[0] = p[0];
pPipeNative[1] = p[1];
- }
- else
- {
+ } else {
pPipeNative[0] = -1;
pPipeNative[1] = -1;
- }
+ }
/* If we are using a native pipe, do not share it or redirect it to
a file. */
- if(p)
- {
+ if (p) {
kwsysProcess_SetPipeFile(cp, prPipe, 0);
kwsysProcess_SetPipeShared(cp, prPipe, 0);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
+ }
- switch(optionId)
- {
- case kwsysProcess_Option_Detach: return cp->OptionDetach;
- case kwsysProcess_Option_Verbatim: return cp->Verbatim;
- default: return 0;
- }
+ switch (optionId) {
+ case kwsysProcess_Option_Detach:
+ return cp->OptionDetach;
+ case kwsysProcess_Option_MergeOutput:
+ return cp->MergeOutput;
+ case kwsysProcess_Option_Verbatim:
+ return cp->Verbatim;
+ case kwsysProcess_Option_CreateProcessGroup:
+ return cp->CreateProcessGroup;
+ default:
+ return 0;
+ }
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
{
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
- switch(optionId)
- {
- case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
- case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
- default: break;
- }
+ switch (optionId) {
+ case kwsysProcess_Option_Detach:
+ cp->OptionDetach = value;
+ break;
+ case kwsysProcess_Option_MergeOutput:
+ cp->MergeOutput = value;
+ break;
+ case kwsysProcess_Option_Verbatim:
+ cp->Verbatim = value;
+ break;
+ case kwsysProcess_Option_CreateProcessGroup:
+ cp->CreateProcessGroup = value;
+ break;
+ default:
+ break;
+ }
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetState(kwsysProcess* cp)
{
- return cp? cp->State : kwsysProcess_State_Error;
+ return cp ? cp->State : kwsysProcess_State_Error;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetExitException(kwsysProcess* cp)
{
- return cp? cp->ExitException : kwsysProcess_Exception_Other;
+ return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+ ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
+ : kwsysProcess_Exception_Other;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetExitCode(kwsysProcess* cp)
{
- return cp? cp->ExitCode : 0;
+ return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+ ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
+ : 0;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetExitValue(kwsysProcess* cp)
{
- return cp? cp->ExitValue : -1;
+ return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+ ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
+ : -1;
}
-/*--------------------------------------------------------------------------*/
const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
{
- if(!cp)
- {
+ if (!cp) {
return "Process management structure could not be allocated";
- }
- else if(cp->State == kwsysProcess_State_Error)
- {
+ } else if (cp->State == kwsysProcess_State_Error) {
return cp->ErrorMessage;
- }
+ }
return "Success";
}
-/*--------------------------------------------------------------------------*/
const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
{
- if(!cp)
- {
+ if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
return "GetExceptionString called with NULL process management structure";
- }
- else if(cp->State == kwsysProcess_State_Exception)
- {
- return cp->ExitExceptionString;
- }
+ } else if (cp->State == kwsysProcess_State_Exception) {
+ return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
+ }
return "No exception";
}
-/*--------------------------------------------------------------------------*/
+/* the index should be in array bound. */
+#define KWSYSPE_IDX_CHK(RET) \
+ if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \
+ return RET; \
+ }
+
+int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(kwsysProcess_State_Error)
+ return cp->ProcessResults[idx].State;
+}
+
+int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other)
+ return cp->ProcessResults[idx].ExitException;
+}
+
+int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(-1)
+ return cp->ProcessResults[idx].ExitValue;
+}
+
+int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(-1)
+ return cp->CommandExitCodes[idx];
+}
+
+const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management "
+ "structure or index out of bound")
+ if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) {
+ return cp->ProcessResults[idx].ExitExceptionString;
+ }
+ return "No exception";
+}
+
+#undef KWSYSPE_IDX_CHK
+
void kwsysProcess_Execute(kwsysProcess* cp)
{
int i;
- kwsysProcessCreateInformation si = {-1, -1, -1, {-1, -1}};
/* Do not execute a second copy simultaneously. */
- if(!cp || cp->State == kwsysProcess_State_Executing)
- {
+ if (!cp || cp->State == kwsysProcess_State_Executing) {
return;
- }
+ }
/* Make sure we have something to run. */
- if(cp->NumberOfCommands < 1)
- {
+ if (cp->NumberOfCommands < 1) {
strcpy(cp->ErrorMessage, "No command");
cp->State = kwsysProcess_State_Error;
return;
- }
+ }
/* Initialize the control structure for a new process. */
- if(!kwsysProcessInitialize(cp))
- {
+ if (!kwsysProcessInitialize(cp)) {
strcpy(cp->ErrorMessage, "Out of memory");
cp->State = kwsysProcess_State_Error;
return;
- }
+ }
#if defined(__VMS)
/* Make sure pipes behave like streams on VMS. */
- if(!kwsysProcessSetVMSFeature("DECC$STREAM_PIPE", 1))
- {
+ if (!kwsysProcessSetVMSFeature("DECC$STREAM_PIPE", 1)) {
kwsysProcessCleanup(cp, 1);
return;
- }
+ }
#endif
/* Save the real working directory of this process and change to
the working directory for the child processes. This is needed
to make pipe file paths evaluate correctly. */
- if(cp->WorkingDirectory)
- {
+ if (cp->WorkingDirectory) {
int r;
- if(!getcwd(cp->RealWorkingDirectory,
- (size_t)(cp->RealWorkingDirectoryLength)))
- {
+ if (!getcwd(cp->RealWorkingDirectory,
+ (size_t)(cp->RealWorkingDirectoryLength))) {
kwsysProcessCleanup(cp, 1);
return;
- }
+ }
/* Some platforms specify that the chdir call may be
interrupted. Repeat the call until it finishes. */
- while(((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR));
- if(r < 0)
- {
+ while (((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR))
+ ;
+ if (r < 0) {
kwsysProcessCleanup(cp, 1);
return;
- }
}
+ }
/* If not running a detached child, add this object to the global
set of process objects that wish to be notified when a child
exits. */
- if(!cp->OptionDetach)
- {
- if(!kwsysProcessesAdd(cp))
- {
+ if (!cp->OptionDetach) {
+ if (!kwsysProcessesAdd(cp)) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ }
+
+ /* Setup the stdin pipe for the first process. */
+ if (cp->PipeFileSTDIN) {
+ /* Open a file for the child's stdin to read. */
+ cp->PipeChildStd[0] = open(cp->PipeFileSTDIN, O_RDONLY);
+ if (cp->PipeChildStd[0] < 0) {
kwsysProcessCleanup(cp, 1);
return;
- }
}
- /* Setup the stderr pipe to be shared by all processes. */
+ /* Set close-on-exec flag on the pipe's end. */
+ if (fcntl(cp->PipeChildStd[0], F_SETFD, FD_CLOEXEC) < 0) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ } else if (cp->PipeSharedSTDIN) {
+ cp->PipeChildStd[0] = 0;
+ } else if (cp->PipeNativeSTDIN[0] >= 0) {
+ cp->PipeChildStd[0] = cp->PipeNativeSTDIN[0];
+
+ /* Set close-on-exec flag on the pipe's ends. The read end will
+ be dup2-ed into the stdin descriptor after the fork but before
+ the exec. */
+ if ((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) ||
+ (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ } else {
+ cp->PipeChildStd[0] = -1;
+ }
+
+ /* Create the output pipe for the last process.
+ We always create this so the pipe can be passed to select even if
+ it will report closed immediately. */
{
- /* Create the pipe. */
- int p[2];
- if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0)
- {
- kwsysProcessCleanup(cp, 1);
- return;
+ /* Create the pipe. */
+ int p[2];
+ if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
+ kwsysProcessCleanup(cp, 1);
+ return;
}
- /* Store the pipe. */
- cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0];
- si.StdErr = p[1];
+ /* Store the pipe. */
+ cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = p[0];
+ cp->PipeChildStd[1] = p[1];
- /* Set close-on-exec flag on the pipe's ends. */
- if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
- (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0))
- {
- kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupDescriptor(&si.StdErr);
- return;
+ /* Set close-on-exec flag on the pipe's ends. */
+ if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
+ (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) {
+ kwsysProcessCleanup(cp, 1);
+ return;
}
- /* Set to non-blocking in case select lies, or for the polling
- implementation. */
- if(!kwsysProcessSetNonBlocking(p[0]))
- {
- kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupDescriptor(&si.StdErr);
- return;
+ /* Set to non-blocking in case select lies, or for the polling
+ implementation. */
+ if (!kwsysProcessSetNonBlocking(p[0])) {
+ kwsysProcessCleanup(cp, 1);
+ return;
}
}
- /* Replace the stderr pipe with a file if requested. In this case
- the select call will report that stderr is closed immediately. */
- if(cp->PipeFileSTDERR)
- {
- if(!kwsysProcessSetupOutputPipeFile(&si.StdErr, cp->PipeFileSTDERR))
- {
+ if (cp->PipeFileSTDOUT) {
+ /* Use a file for stdout. */
+ if (!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1],
+ cp->PipeFileSTDOUT)) {
kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupDescriptor(&si.StdErr);
return;
- }
}
+ } else if (cp->PipeSharedSTDOUT) {
+ /* Use the parent stdout. */
+ kwsysProcessCleanupDescriptor(&cp->PipeChildStd[1]);
+ cp->PipeChildStd[1] = 1;
+ } else if (cp->PipeNativeSTDOUT[1] >= 0) {
+ /* Use the given descriptor for stdout. */
+ if (!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[1],
+ cp->PipeNativeSTDOUT)) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ }
- /* Replace the stderr pipe with the parent's if requested. In this
- case the select call will report that stderr is closed
- immediately. */
- if(cp->PipeSharedSTDERR)
- {
- kwsysProcessCleanupDescriptor(&si.StdErr);
- si.StdErr = 2;
+ /* Create stderr pipe to be shared by all processes in the pipeline.
+ We always create this so the pipe can be passed to select even if
+ it will report closed immediately. */
+ {
+ /* Create the pipe. */
+ int p[2];
+ if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
+ kwsysProcessCleanup(cp, 1);
+ return;
}
- /* Replace the stderr pipe with the native pipe provided if any. In
- this case the select call will report that stderr is closed
- immediately. */
- if(cp->PipeNativeSTDERR[1] >= 0)
- {
- if(!kwsysProcessSetupOutputPipeNative(&si.StdErr, cp->PipeNativeSTDERR))
- {
+ /* Store the pipe. */
+ cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0];
+ cp->PipeChildStd[2] = p[1];
+
+ /* Set close-on-exec flag on the pipe's ends. */
+ if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
+ (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) {
kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupDescriptor(&si.StdErr);
return;
- }
}
+ /* Set to non-blocking in case select lies, or for the polling
+ implementation. */
+ if (!kwsysProcessSetNonBlocking(p[0])) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ }
+
+ if (cp->PipeFileSTDERR) {
+ /* Use a file for stderr. */
+ if (!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2],
+ cp->PipeFileSTDERR)) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ } else if (cp->PipeSharedSTDERR) {
+ /* Use the parent stderr. */
+ kwsysProcessCleanupDescriptor(&cp->PipeChildStd[2]);
+ cp->PipeChildStd[2] = 2;
+ } else if (cp->PipeNativeSTDERR[1] >= 0) {
+ /* Use the given handle for stderr. */
+ if (!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[2],
+ cp->PipeNativeSTDERR)) {
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ }
+
/* The timeout period starts now. */
cp->StartTime = kwsysProcessTimeGetCurrent();
cp->TimeoutTime.tv_sec = -1;
@@ -857,65 +945,82 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* Create the pipeline of processes. */
{
- int readEnd = -1;
- int failed = 0;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- if(!kwsysProcessCreate(cp, i, &si, &readEnd))
- {
- failed = 1;
- }
+ kwsysProcessCreateInformation si = { -1, -1, -1, { -1, -1 } };
+ int nextStdIn = cp->PipeChildStd[0];
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ /* Setup the process's pipes. */
+ si.StdIn = nextStdIn;
+ if (i == cp->NumberOfCommands - 1) {
+ nextStdIn = -1;
+ si.StdOut = cp->PipeChildStd[1];
+ } else {
+ /* Create a pipe to sit between the children. */
+ int p[2] = { -1, -1 };
+ if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
+ if (nextStdIn != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupDescriptor(&nextStdIn);
+ }
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
- /* Set the output pipe of the last process to be non-blocking in
- case select lies, or for the polling implementation. */
- if(i == (cp->NumberOfCommands-1) && !kwsysProcessSetNonBlocking(readEnd))
- {
- failed = 1;
+ /* Set close-on-exec flag on the pipe's ends. */
+ if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
+ (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) {
+ close(p[0]);
+ close(p[1]);
+ if (nextStdIn != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupDescriptor(&nextStdIn);
+ }
+ kwsysProcessCleanup(cp, 1);
+ return;
+ }
+ nextStdIn = p[0];
+ si.StdOut = p[1];
}
+ si.StdErr = cp->MergeOutput ? cp->PipeChildStd[1] : cp->PipeChildStd[2];
- if(failed)
{
- kwsysProcessCleanup(cp, 1);
+ int res = kwsysProcessCreate(cp, i, &si);
- /* Release resources that may have been allocated for this
- process before an error occurred. */
- kwsysProcessCleanupDescriptor(&readEnd);
- if(si.StdIn != 0)
- {
- kwsysProcessCleanupDescriptor(&si.StdIn);
+ /* Close our copies of pipes used between children. */
+ if (si.StdIn != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupDescriptor(&si.StdIn);
}
- if(si.StdOut != 1)
- {
- kwsysProcessCleanupDescriptor(&si.StdOut);
+ if (si.StdOut != cp->PipeChildStd[1]) {
+ kwsysProcessCleanupDescriptor(&si.StdOut);
}
- if(si.StdErr != 2)
- {
- kwsysProcessCleanupDescriptor(&si.StdErr);
+ if (si.StdErr != cp->PipeChildStd[2] && !cp->MergeOutput) {
+ kwsysProcessCleanupDescriptor(&si.StdErr);
+ }
+
+ if (!res) {
+ kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]);
+ kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]);
+ if (nextStdIn != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupDescriptor(&nextStdIn);
+ }
+ kwsysProcessCleanup(cp, 1);
+ return;
}
- kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]);
- kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]);
- return;
}
}
- /* Save a handle to the output pipe for the last process. */
- cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = readEnd;
}
- /* The parent process does not need the output pipe write ends. */
- if(si.StdErr != 2)
- {
- kwsysProcessCleanupDescriptor(&si.StdErr);
- }
+ /* The parent process does not need the child's pipe ends. */
+ for (i = 0; i < 3; ++i) {
+ kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]);
+ }
/* Restore the working directory. */
- if(cp->RealWorkingDirectory)
- {
+ if (cp->RealWorkingDirectory) {
/* Some platforms specify that the chdir call may be
interrupted. Repeat the call until it finishes. */
- while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR));
+ while ((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR))
+ ;
free(cp->RealWorkingDirectory);
cp->RealWorkingDirectory = 0;
- }
+ }
/* All the pipes are now open. */
cp->PipesLeft = KWSYSPE_PIPE_COUNT;
@@ -925,15 +1030,13 @@ void kwsysProcess_Execute(kwsysProcess* cp)
cp->Detached = cp->OptionDetach;
}
-/*--------------------------------------------------------------------------*/
kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
{
/* Make sure a detached child process is running. */
- if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing ||
- cp->TimeoutExpired || cp->Killed)
- {
+ if (!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing ||
+ cp->TimeoutExpired || cp->Killed) {
return;
- }
+ }
/* Close all the pipes safely. */
kwsysProcessClosePipes(cp);
@@ -945,7 +1048,6 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
cp->State = kwsysProcess_State_Disowned;
}
-/*--------------------------------------------------------------------------*/
typedef struct kwsysProcessWaitData_s
{
int Expired;
@@ -957,88 +1059,67 @@ typedef struct kwsysProcessWaitData_s
static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
kwsysProcessWaitData* wd);
-/*--------------------------------------------------------------------------*/
int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
double* userTimeout)
{
- kwsysProcessTime userStartTime = {0, 0};
- kwsysProcessWaitData wd =
- {
- 0,
- kwsysProcess_Pipe_None,
- 0,
- 0,
- {0, 0}
- };
+ kwsysProcessTime userStartTime = { 0, 0 };
+ kwsysProcessWaitData wd = { 0, kwsysProcess_Pipe_None, 0, 0, { 0, 0 } };
wd.UserTimeout = userTimeout;
/* Make sure we are executing a process. */
- if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed ||
- cp->TimeoutExpired)
- {
+ if (!cp || cp->State != kwsysProcess_State_Executing || cp->Killed ||
+ cp->TimeoutExpired) {
return kwsysProcess_Pipe_None;
- }
+ }
/* Record the time at which user timeout period starts. */
- if(userTimeout)
- {
+ if (userTimeout) {
userStartTime = kwsysProcessTimeGetCurrent();
- }
+ }
/* Calculate the time at which a timeout will expire, and whether it
is the user or process timeout. */
- wd.User = kwsysProcessGetTimeoutTime(cp, userTimeout,
- &wd.TimeoutTime);
+ wd.User = kwsysProcessGetTimeoutTime(cp, userTimeout, &wd.TimeoutTime);
/* Data can only be available when pipes are open. If the process
is not running, cp->PipesLeft will be 0. */
- while(cp->PipesLeft > 0 &&
- !kwsysProcessWaitForPipe(cp, data, length, &wd)) {}
+ while (cp->PipesLeft > 0 &&
+ !kwsysProcessWaitForPipe(cp, data, length, &wd)) {
+ }
/* Update the user timeout. */
- if(userTimeout)
- {
+ if (userTimeout) {
kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
- kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
- userStartTime);
+ kwsysProcessTime difference =
+ kwsysProcessTimeSubtract(userEndTime, userStartTime);
double d = kwsysProcessTimeToDouble(difference);
*userTimeout -= d;
- if(*userTimeout < 0)
- {
+ if (*userTimeout < 0) {
*userTimeout = 0;
- }
}
+ }
/* Check what happened. */
- if(wd.PipeId)
- {
+ if (wd.PipeId) {
/* Data are ready on a pipe. */
return wd.PipeId;
- }
- else if(wd.Expired)
- {
+ } else if (wd.Expired) {
/* A timeout has expired. */
- if(wd.User)
- {
+ if (wd.User) {
/* The user timeout has expired. It has no time left. */
return kwsysProcess_Pipe_Timeout;
- }
- else
- {
+ } else {
/* The process timeout has expired. Kill the children now. */
kwsysProcess_Kill(cp);
cp->Killed = 0;
cp->TimeoutExpired = 1;
return kwsysProcess_Pipe_None;
- }
}
- else
- {
+ } else {
/* No pipes are left open. */
return kwsysProcess_Pipe_None;
- }
+ }
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
kwsysProcessWaitData* wd)
{
@@ -1054,11 +1135,9 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
call to select. According to "man select_tut" we must deal
with all descriptors reported by a call to select before
passing them to another select call. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
- if(cp->PipeReadEnds[i] >= 0 &&
- FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet))
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
+ if (cp->PipeReadEnds[i] >= 0 &&
+ FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) {
kwsysProcess_ssize_t n;
/* We are handling this pipe now. Remove it from the set. */
@@ -1066,108 +1145,91 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
/* The pipe is ready to read without blocking. Keep trying to
read until the operation is not interrupted. */
- while(((n = read(cp->PipeReadEnds[i], cp->PipeBuffer,
- KWSYSPE_PIPE_BUFFER_SIZE)) < 0) && (errno == EINTR));
- if(n > 0)
- {
+ while (((n = read(cp->PipeReadEnds[i], cp->PipeBuffer,
+ KWSYSPE_PIPE_BUFFER_SIZE)) < 0) &&
+ (errno == EINTR))
+ ;
+ if (n > 0) {
/* We have data on this pipe. */
- if(i == KWSYSPE_PIPE_SIGNAL)
- {
+ if (i == KWSYSPE_PIPE_SIGNAL) {
/* A child process has terminated. */
kwsysProcessDestroy(cp);
- }
- else if(data && length)
- {
+ } else if (data && length) {
/* Report this data. */
*data = cp->PipeBuffer;
*length = (int)(n);
- switch(i)
- {
+ switch (i) {
case KWSYSPE_PIPE_STDOUT:
- wd->PipeId = kwsysProcess_Pipe_STDOUT; break;
+ wd->PipeId = kwsysProcess_Pipe_STDOUT;
+ break;
case KWSYSPE_PIPE_STDERR:
- wd->PipeId = kwsysProcess_Pipe_STDERR; break;
- };
+ wd->PipeId = kwsysProcess_Pipe_STDERR;
+ break;
+ };
return 1;
- }
}
- else if(n < 0 && errno == EAGAIN)
- {
+ } else if (n < 0 && errno == EAGAIN) {
/* No data are really ready. The select call lied. See the
"man select" page on Linux for cases when this occurs. */
- }
- else
- {
+ } else {
/* We are done reading from this pipe. */
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
- }
}
}
+ }
/* If we have data, break early. */
- if(wd->PipeId)
- {
+ if (wd->PipeId) {
return 1;
- }
+ }
/* Make sure the set is empty (it should always be empty here
anyway). */
FD_ZERO(&cp->PipeSet);
/* Setup a timeout if required. */
- if(wd->TimeoutTime.tv_sec < 0)
- {
+ if (wd->TimeoutTime.tv_sec < 0) {
timeout = 0;
- }
- else
- {
+ } else {
timeout = &timeoutLength;
- }
- if(kwsysProcessGetTimeoutLeft(&wd->TimeoutTime,
- wd->User?wd->UserTimeout:0,
- &timeoutLength, 0))
- {
+ }
+ if (kwsysProcessGetTimeoutLeft(
+ &wd->TimeoutTime, wd->User ? wd->UserTimeout : 0, &timeoutLength, 0)) {
/* Timeout has already expired. */
wd->Expired = 1;
return 1;
- }
+ }
/* Add the pipe reading ends that are still open. */
max = -1;
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
- if(cp->PipeReadEnds[i] >= 0)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
+ if (cp->PipeReadEnds[i] >= 0) {
FD_SET(cp->PipeReadEnds[i], &cp->PipeSet);
- if(cp->PipeReadEnds[i] > max)
- {
+ if (cp->PipeReadEnds[i] > max) {
max = cp->PipeReadEnds[i];
- }
}
}
+ }
/* Make sure we have a non-empty set. */
- if(max < 0)
- {
+ if (max < 0) {
/* All pipes have closed. Child has terminated. */
return 1;
- }
+ }
/* Run select to block until data are available. Repeat call
until it is not interrupted. */
- while(((numReady = select(max+1, &cp->PipeSet, 0, 0, timeout)) < 0) &&
- (errno == EINTR));
+ while (((numReady = select(max + 1, &cp->PipeSet, 0, 0, timeout)) < 0) &&
+ (errno == EINTR))
+ ;
/* Check result of select. */
- if(numReady == 0)
- {
+ if (numReady == 0) {
/* Select's timeout expired. */
wd->Expired = 1;
return 1;
- }
- else if(numReady < 0)
- {
+ } else if (numReady < 0) {
/* Select returned an error. Leave the error description in the
pipe buffer. */
strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
@@ -1176,194 +1238,197 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
kwsysProcess_Kill(cp);
cp->Killed = 0;
cp->SelectError = 1;
- }
+ }
return 0;
#else
/* Poll pipes for data since we do not have select. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
- if(cp->PipeReadEnds[i] >= 0)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
+ if (cp->PipeReadEnds[i] >= 0) {
const int fd = cp->PipeReadEnds[i];
int n = read(fd, cp->PipeBuffer, KWSYSPE_PIPE_BUFFER_SIZE);
- if(n > 0)
- {
+ if (n > 0) {
/* We have data on this pipe. */
- if(i == KWSYSPE_PIPE_SIGNAL)
- {
+ if (i == KWSYSPE_PIPE_SIGNAL) {
/* A child process has terminated. */
kwsysProcessDestroy(cp);
- }
- else if(data && length)
- {
+ } else if (data && length) {
/* Report this data. */
*data = cp->PipeBuffer;
*length = n;
- switch(i)
- {
+ switch (i) {
case KWSYSPE_PIPE_STDOUT:
- wd->PipeId = kwsysProcess_Pipe_STDOUT; break;
+ wd->PipeId = kwsysProcess_Pipe_STDOUT;
+ break;
case KWSYSPE_PIPE_STDERR:
- wd->PipeId = kwsysProcess_Pipe_STDERR; break;
- };
- }
- return 1;
+ wd->PipeId = kwsysProcess_Pipe_STDERR;
+ break;
+ };
}
- else if (n == 0) /* EOF */
- {
- /* We are done reading from this pipe. */
+ return 1;
+ } else if (n == 0) /* EOF */
+ {
+/* We are done reading from this pipe. */
#if defined(__VMS)
- if(!cp->CommandsLeft)
+ if (!cp->CommandsLeft)
#endif
- {
+ {
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
- }
}
- else if (n < 0) /* error */
- {
+ } else if (n < 0) /* error */
+ {
#if defined(__VMS)
- if(!cp->CommandsLeft)
- {
+ if (!cp->CommandsLeft) {
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
- }
- else
+ } else
#endif
- if((errno != EINTR) && (errno != EAGAIN))
- {
- strncpy(cp->ErrorMessage,strerror(errno),
- KWSYSPE_PIPE_BUFFER_SIZE);
+ if ((errno != EINTR) && (errno != EAGAIN)) {
+ strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
/* Kill the children now. */
kwsysProcess_Kill(cp);
cp->Killed = 0;
cp->SelectError = 1;
return 1;
- }
}
}
}
+ }
/* If we have data, break early. */
- if(wd->PipeId)
- {
+ if (wd->PipeId) {
return 1;
- }
+ }
- if(kwsysProcessGetTimeoutLeft(&wd->TimeoutTime, wd->User?wd->UserTimeout:0,
- &timeoutLength, 1))
- {
+ if (kwsysProcessGetTimeoutLeft(
+ &wd->TimeoutTime, wd->User ? wd->UserTimeout : 0, &timeoutLength, 1)) {
/* Timeout has already expired. */
wd->Expired = 1;
return 1;
- }
+ }
/* Sleep a little, try again. */
{
- unsigned int msec = ((timeoutLength.tv_sec * 1000) +
- (timeoutLength.tv_usec / 1000));
- if (msec > 100000)
- {
- msec = 100000; /* do not sleep more than 100 milliseconds at a time */
+ unsigned int msec =
+ ((timeoutLength.tv_sec * 1000) + (timeoutLength.tv_usec / 1000));
+ if (msec > 100000) {
+ msec = 100000; /* do not sleep more than 100 milliseconds at a time */
}
- kwsysProcess_usleep(msec);
+ kwsysProcess_usleep(msec);
}
return 0;
#endif
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
{
- int status = 0;
int prPipe = 0;
/* Make sure we are executing a process. */
- if(!cp || cp->State != kwsysProcess_State_Executing)
- {
+ if (!cp || cp->State != kwsysProcess_State_Executing) {
return 1;
- }
+ }
/* Wait for all the pipes to close. Ignore all data. */
- while((prPipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0)
- {
- if(prPipe == kwsysProcess_Pipe_Timeout)
- {
+ while ((prPipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) {
+ if (prPipe == kwsysProcess_Pipe_Timeout) {
return 0;
- }
}
+ }
/* Check if there was an error in one of the waitpid calls. */
- if(cp->State == kwsysProcess_State_Error)
- {
+ if (cp->State == kwsysProcess_State_Error) {
/* The error message is already in its buffer. Tell
kwsysProcessCleanup to not create it. */
kwsysProcessCleanup(cp, 0);
return 1;
- }
+ }
/* Check whether the child reported an error invoking the process. */
- if(cp->SelectError)
- {
+ if (cp->SelectError) {
/* The error message is already in its buffer. Tell
kwsysProcessCleanup to not create it. */
kwsysProcessCleanup(cp, 0);
cp->State = kwsysProcess_State_Error;
return 1;
- }
-
- /* Use the status of the last process in the pipeline. */
- status = cp->CommandExitCodes[cp->NumberOfCommands-1];
-
+ }
/* Determine the outcome. */
- if(cp->Killed)
- {
+ if (cp->Killed) {
/* We killed the child. */
cp->State = kwsysProcess_State_Killed;
- }
- else if(cp->TimeoutExpired)
- {
+ } else if (cp->TimeoutExpired) {
/* The timeout expired. */
cp->State = kwsysProcess_State_Expired;
+ } else {
+ /* The children exited. Report the outcome of the child processes. */
+ for (prPipe = 0; prPipe < cp->NumberOfCommands; ++prPipe) {
+ cp->ProcessResults[prPipe].ExitCode = cp->CommandExitCodes[prPipe];
+ if (WIFEXITED(cp->ProcessResults[prPipe].ExitCode)) {
+ /* The child exited normally. */
+ cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Exited;
+ cp->ProcessResults[prPipe].ExitException = kwsysProcess_Exception_None;
+ cp->ProcessResults[prPipe].ExitValue =
+ (int)WEXITSTATUS(cp->ProcessResults[prPipe].ExitCode);
+ } else if (WIFSIGNALED(cp->ProcessResults[prPipe].ExitCode)) {
+ /* The child received an unhandled signal. */
+ cp->ProcessResults[prPipe].State = kwsysProcess_State_Exception;
+ kwsysProcessSetExitExceptionByIndex(
+ cp, (int)WTERMSIG(cp->ProcessResults[prPipe].ExitCode), prPipe);
+ } else {
+ /* Error getting the child return code. */
+ strcpy(cp->ProcessResults[prPipe].ExitExceptionString,
+ "Error getting child return code.");
+ cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Error;
+ }
}
- else if(WIFEXITED(status))
- {
- /* The child exited normally. */
- cp->State = kwsysProcess_State_Exited;
- cp->ExitException = kwsysProcess_Exception_None;
- cp->ExitCode = status;
- cp->ExitValue = (int)WEXITSTATUS(status);
- }
- else if(WIFSIGNALED(status))
- {
- /* The child received an unhandled signal. */
- cp->State = kwsysProcess_State_Exception;
- cp->ExitCode = status;
- kwsysProcessSetExitException(cp, (int)WTERMSIG(status));
- }
- else
- {
- /* Error getting the child return code. */
- strcpy(cp->ErrorMessage, "Error getting child return code.");
- cp->State = kwsysProcess_State_Error;
- }
-
+ /* support legacy state status value */
+ cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
+ }
/* Normal cleanup. */
kwsysProcessCleanup(cp, 0);
return 1;
}
-/*--------------------------------------------------------------------------*/
+void kwsysProcess_Interrupt(kwsysProcess* cp)
+{
+ int i;
+ /* Make sure we are executing a process. */
+ if (!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
+ cp->Killed) {
+ return;
+ }
+
+ /* Interrupt the children. */
+ if (cp->CreateProcessGroup) {
+ if (cp->ForkPIDs) {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ /* Make sure the PID is still valid. */
+ if (cp->ForkPIDs[i]) {
+ /* The user created a process group for this process. The group ID
+ is the process ID for the original process in the group. */
+ kill(-cp->ForkPIDs[i], SIGINT);
+ }
+ }
+ }
+ } else {
+ /* No process group was created. Kill our own process group.
+ NOTE: While one could argue that we could call kill(cp->ForkPIDs[i],
+ SIGINT) as a way to still interrupt the process even though it's not in
+ a special group, this is not an option on Windows. Therefore, we kill
+ the current process group for consistency with Windows. */
+ kill(0, SIGINT);
+ }
+}
+
void kwsysProcess_Kill(kwsysProcess* cp)
{
int i;
/* Make sure we are executing a process. */
- if(!cp || cp->State != kwsysProcess_State_Executing)
- {
+ if (!cp || cp->State != kwsysProcess_State_Executing) {
return;
- }
+ }
/* First close the child exit report pipe write end to avoid causing a
SIGPIPE when the child terminates and our signal handler tries to
@@ -1379,19 +1444,18 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Kill the children. */
cp->Killed = 1;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
int status;
- if(cp->ForkPIDs[i])
- {
+ if (cp->ForkPIDs[i]) {
/* Kill the child. */
kwsysProcessKill(cp->ForkPIDs[i]);
/* Reap the child. Keep trying until the call is not
interrupted. */
- while((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && (errno == EINTR));
- }
+ while ((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && (errno == EINTR))
+ ;
}
+ }
#if defined(__APPLE__)
/* Close all the pipe read ends. Do this after killing the
@@ -1403,15 +1467,33 @@ void kwsysProcess_Kill(kwsysProcess* cp)
cp->CommandsLeft = 0;
}
-/*--------------------------------------------------------------------------*/
+/* Call the free() function with a pointer to volatile without causing
+ compiler warnings. */
+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"
+#endif
+ free((void*)p); /* The cast will silence most compilers, but not clang. */
+#if defined(__clang__) && !defined(__INTEL_COMPILER)
+#pragma clang diagnostic pop
+#endif
+}
+
/* Initialize a process control structure for kwsysProcess_Execute. */
static int kwsysProcessInitialize(kwsysProcess* cp)
{
int i;
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ volatile pid_t* oldForkPIDs;
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
cp->PipeReadEnds[i] = -1;
- }
+ }
+ for (i = 0; i < 3; ++i) {
+ cp->PipeChildStd[i] = -1;
+ }
cp->SignalPipe = -1;
cp->SelectError = 0;
cp->StartTime.tv_sec = -1;
@@ -1426,38 +1508,51 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
#endif
cp->State = kwsysProcess_State_Starting;
cp->Killed = 0;
- cp->ExitException = kwsysProcess_Exception_None;
- cp->ExitCode = 1;
- cp->ExitValue = 1;
cp->ErrorMessage[0] = 0;
- strcpy(cp->ExitExceptionString, "No exception");
- if(cp->ForkPIDs)
- {
- free(cp->ForkPIDs);
- }
- cp->ForkPIDs = (pid_t*)malloc(sizeof(pid_t)*(size_t)(cp->NumberOfCommands));
- if(!cp->ForkPIDs)
- {
+ oldForkPIDs = cp->ForkPIDs;
+ cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) *
+ (size_t)(cp->NumberOfCommands));
+ if (oldForkPIDs) {
+ kwsysProcessVolatileFree(oldForkPIDs);
+ }
+ if (!cp->ForkPIDs) {
return 0;
- }
- memset(cp->ForkPIDs, 0, sizeof(pid_t)*(size_t)(cp->NumberOfCommands));
+ }
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */
+ }
- if(cp->CommandExitCodes)
- {
+ if (cp->CommandExitCodes) {
free(cp->CommandExitCodes);
- }
- cp->CommandExitCodes = (int*)malloc(sizeof(int)*
- (size_t)(cp->NumberOfCommands));
- if(!cp->CommandExitCodes)
- {
+ }
+ cp->CommandExitCodes =
+ (int*)malloc(sizeof(int) * (size_t)(cp->NumberOfCommands));
+ if (!cp->CommandExitCodes) {
return 0;
- }
- memset(cp->CommandExitCodes, 0, sizeof(int)*(size_t)(cp->NumberOfCommands));
+ }
+ memset(cp->CommandExitCodes, 0,
+ sizeof(int) * (size_t)(cp->NumberOfCommands));
+
+ /* Allocate process result information for each process. */
+ free(cp->ProcessResults);
+ cp->ProcessResults = (kwsysProcessResults*)malloc(
+ sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands));
+ if (!cp->ProcessResults) {
+ return 0;
+ }
+ memset(cp->ProcessResults, 0,
+ sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands));
+ for (i = 0; i < cp->NumberOfCommands; i++) {
+ cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+ cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting;
+ cp->ProcessResults[i].ExitCode = 1;
+ cp->ProcessResults[i].ExitValue = 1;
+ strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception");
+ }
/* Allocate memory to save the real working directory. */
- if ( cp->WorkingDirectory )
- {
+ if (cp->WorkingDirectory) {
#if defined(MAXPATHLEN)
cp->RealWorkingDirectoryLength = MAXPATHLEN;
#elif defined(PATH_MAX)
@@ -1466,299 +1561,224 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
cp->RealWorkingDirectoryLength = 4096;
#endif
cp->RealWorkingDirectory =
- malloc((size_t)(cp->RealWorkingDirectoryLength));
- if(!cp->RealWorkingDirectory)
- {
+ (char*)malloc((size_t)(cp->RealWorkingDirectoryLength));
+ if (!cp->RealWorkingDirectory) {
return 0;
- }
}
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
/* Free all resources used by the given kwsysProcess instance that were
allocated by kwsysProcess_Execute. */
static void kwsysProcessCleanup(kwsysProcess* cp, int error)
{
int i;
- if(error)
- {
+ if (error) {
/* We are cleaning up due to an error. Report the error message
if one has not been provided already. */
- if(cp->ErrorMessage[0] == 0)
- {
+ if (cp->ErrorMessage[0] == 0) {
strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
- }
+ }
/* Set the error state. */
cp->State = kwsysProcess_State_Error;
/* Kill any children already started. */
- if(cp->ForkPIDs)
- {
+ if (cp->ForkPIDs) {
int status;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- if(cp->ForkPIDs[i])
- {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ if (cp->ForkPIDs[i]) {
/* Kill the child. */
kwsysProcessKill(cp->ForkPIDs[i]);
/* Reap the child. Keep trying until the call is not
interrupted. */
- while((waitpid(cp->ForkPIDs[i], &status, 0) < 0) &&
- (errno == EINTR));
- }
+ while ((waitpid(cp->ForkPIDs[i], &status, 0) < 0) &&
+ (errno == EINTR))
+ ;
}
}
+ }
/* Restore the working directory. */
- if(cp->RealWorkingDirectory)
- {
- while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR));
- }
+ if (cp->RealWorkingDirectory) {
+ while ((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR))
+ ;
}
+ }
/* If not creating a detached child, remove this object from the
global set of process objects that wish to be notified when a
child exits. */
- if(!cp->OptionDetach)
- {
+ if (!cp->OptionDetach) {
kwsysProcessesRemove(cp);
- }
+ }
/* Free memory. */
- if(cp->ForkPIDs)
- {
- free(cp->ForkPIDs);
+ if (cp->ForkPIDs) {
+ kwsysProcessVolatileFree(cp->ForkPIDs);
cp->ForkPIDs = 0;
- }
- if(cp->RealWorkingDirectory)
- {
+ }
+ if (cp->RealWorkingDirectory) {
free(cp->RealWorkingDirectory);
cp->RealWorkingDirectory = 0;
- }
+ }
/* Close pipe handles. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
- }
+ }
+ for (i = 0; i < 3; ++i) {
+ kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]);
+ }
}
-/*--------------------------------------------------------------------------*/
/* Close the given file descriptor if it is open. Reset its value to -1. */
static void kwsysProcessCleanupDescriptor(int* pfd)
{
- if(pfd && *pfd >= 0)
- {
+ if (pfd && *pfd > 2) {
/* Keep trying to close until it is not interrupted by a
* signal. */
- while((close(*pfd) < 0) && (errno == EINTR));
+ while ((close(*pfd) < 0) && (errno == EINTR))
+ ;
*pfd = -1;
- }
+ }
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessClosePipes(kwsysProcess* cp)
{
int i;
/* Close any pipes that are still open. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
- if(cp->PipeReadEnds[i] >= 0)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
+ if (cp->PipeReadEnds[i] >= 0) {
#if KWSYSPE_USE_SELECT
/* If the pipe was reported by the last call to select, we must
read from it. This is needed to satisfy the suggestions from
"man select_tut" and is not needed for the polling
implementation. Ignore the data. */
- if(FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet))
- {
+ if (FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) {
/* We are handling this pipe now. Remove it from the set. */
FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet);
/* The pipe is ready to read without blocking. Keep trying to
read until the operation is not interrupted. */
- while((read(cp->PipeReadEnds[i], cp->PipeBuffer,
- KWSYSPE_PIPE_BUFFER_SIZE) < 0) && (errno == EINTR));
- }
+ while ((read(cp->PipeReadEnds[i], cp->PipeBuffer,
+ KWSYSPE_PIPE_BUFFER_SIZE) < 0) &&
+ (errno == EINTR))
+ ;
+ }
#endif
/* We are done reading from this pipe. */
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
- }
}
+ }
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcessSetNonBlocking(int fd)
{
int flags = fcntl(fd, F_GETFL);
- if(flags >= 0)
- {
+ if (flags >= 0) {
flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- }
+ }
return flags >= 0;
}
-/*--------------------------------------------------------------------------*/
#if defined(__VMS)
int decc$set_child_standard_streams(int fd1, int fd2, int fd3);
#endif
-/*--------------------------------------------------------------------------*/
static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
- kwsysProcessCreateInformation* si, int* readEnd)
+ kwsysProcessCreateInformation* si)
{
- /* Setup the process's stdin. */
- if(prIndex > 0)
- {
- si->StdIn = *readEnd;
- *readEnd = 0;
- }
- else if(cp->PipeFileSTDIN)
- {
- /* Open a file for the child's stdin to read. */
- si->StdIn = open(cp->PipeFileSTDIN, O_RDONLY);
- if(si->StdIn < 0)
- {
- return 0;
- }
-
- /* Set close-on-exec flag on the pipe's end. */
- if(fcntl(si->StdIn, F_SETFD, FD_CLOEXEC) < 0)
- {
- return 0;
- }
- }
- else if(cp->PipeSharedSTDIN)
- {
- si->StdIn = 0;
- }
- else if(cp->PipeNativeSTDIN[0] >= 0)
- {
- si->StdIn = cp->PipeNativeSTDIN[0];
+ sigset_t mask, old_mask;
+ int pgidPipe[2];
+ char tmp;
+ ssize_t readRes;
- /* Set close-on-exec flag on the pipe's ends. The read end will
- be dup2-ed into the stdin descriptor after the fork but before
- the exec. */
- if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) ||
- (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0))
- {
- return 0;
- }
- }
- else
- {
- si->StdIn = -1;
- }
-
- /* Setup the process's stdout. */
- {
- /* Create the pipe. */
- int p[2];
- if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0)
- {
+ /* Create the error reporting pipe. */
+ if (pipe(si->ErrorPipe) < 0) {
return 0;
- }
- *readEnd = p[0];
- si->StdOut = p[1];
+ }
- /* Set close-on-exec flag on the pipe's ends. */
- if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
- (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0))
- {
+ /* Create a pipe for detecting that the child process has created a process
+ group and session. */
+ if (pipe(pgidPipe) < 0) {
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
return 0;
- }
}
- /* Replace the stdout pipe with a file if requested. In this case
- the select call will report that stdout is closed immediately. */
- if(prIndex == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT)
- {
- if(!kwsysProcessSetupOutputPipeFile(&si->StdOut, cp->PipeFileSTDOUT))
- {
- return 0;
- }
- }
-
- /* Replace the stdout pipe with the parent's if requested. In this
- case the select call will report that stderr is closed
- immediately. */
- if(prIndex == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT)
- {
- kwsysProcessCleanupDescriptor(&si->StdOut);
- si->StdOut = 1;
- }
-
- /* Replace the stdout pipe with the native pipe provided if any. In
- this case the select call will report that stdout is closed
- immediately. */
- if(prIndex == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1] >= 0)
- {
- if(!kwsysProcessSetupOutputPipeNative(&si->StdOut, cp->PipeNativeSTDOUT))
- {
- return 0;
- }
- }
-
- /* Create the error reporting pipe. */
- if(pipe(si->ErrorPipe) < 0)
- {
+ /* Set close-on-exec flag on the pipe's write end. */
+ if (fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0 ||
+ fcntl(pgidPipe[1], F_SETFD, FD_CLOEXEC) < 0) {
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[1]);
return 0;
- }
+ }
- /* Set close-on-exec flag on the error pipe's write end. */
- if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0)
- {
+ /* Block SIGINT / SIGTERM while we start. The purpose is so that our signal
+ handler doesn't get called from the child process after the fork and
+ before the exec, and subsequently start kill()'ing PIDs from ForkPIDs. */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+ if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[1]);
return 0;
- }
+ }
- /* Fork off a child process. */
+/* Fork off a child process. */
#if defined(__VMS)
/* VMS needs vfork and execvp to be in the same function because
they use setjmp/longjmp to run the child startup code in the
- parent! TODO: OptionDetach. */
+ parent! TODO: OptionDetach. Also
+ TODO: CreateProcessGroup. */
cp->ForkPIDs[prIndex] = vfork();
#else
cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si);
#endif
- if(cp->ForkPIDs[prIndex] < 0)
- {
+ if (cp->ForkPIDs[prIndex] < 0) {
+ sigprocmask(SIG_SETMASK, &old_mask, 0);
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[1]);
return 0;
- }
+ }
- if(cp->ForkPIDs[prIndex] == 0)
- {
+ if (cp->ForkPIDs[prIndex] == 0) {
#if defined(__VMS)
/* Specify standard pipes for child process. */
decc$set_child_standard_streams(si->StdIn, si->StdOut, si->StdErr);
#else
- /* Close the read end of the error reporting pipe. */
+ /* Close the read end of the error reporting / process group
+ setup pipe. */
close(si->ErrorPipe[0]);
+ close(pgidPipe[0]);
/* Setup the stdin, stdout, and stderr pipes. */
- if(si->StdIn > 0)
- {
+ if (si->StdIn > 0) {
dup2(si->StdIn, 0);
- }
- else if(si->StdIn < 0)
- {
+ } else if (si->StdIn < 0) {
close(0);
- }
- if(si->StdOut != 1)
- {
+ }
+ if (si->StdOut != 1) {
dup2(si->StdOut, 1);
- }
- if(si->StdErr != 2)
- {
+ }
+ if (si->StdErr != 2) {
dup2(si->StdErr, 2);
- }
+ }
/* Clear the close-on-exec flag for stdin, stdout, and stderr.
All other pipe handles will be closed when exec succeeds. */
@@ -1768,91 +1788,116 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
/* Restore all default signal handlers. */
kwsysProcessRestoreDefaultSignalHandlers();
+
+ /* Now that we have restored default signal handling and created the
+ process group, restore mask. */
+ sigprocmask(SIG_SETMASK, &old_mask, 0);
+
+ /* Create new process group. We use setsid instead of setpgid to avoid
+ the child getting hung up on signals like SIGTTOU. (In the real world,
+ this has been observed where "git svn" ends up calling the "resize"
+ program which opens /dev/tty. */
+ if (cp->CreateProcessGroup && setsid() < 0) {
+ kwsysProcessChildErrorExit(si->ErrorPipe[1]);
+ }
#endif
/* Execute the real process. If successful, this does not return. */
execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]);
/* TODO: What does VMS do if the child fails to start? */
+ /* TODO: On VMS, how do we put the process in a new group? */
/* Failure. Report error to parent and terminate. */
kwsysProcessChildErrorExit(si->ErrorPipe[1]);
- }
+ }
#if defined(__VMS)
/* Restore the standard pipes of this process. */
decc$set_child_standard_streams(0, 1, 2);
#endif
+ /* We are done with the error reporting pipe and process group setup pipe
+ write end. */
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[1]);
+
+ /* Make sure the child is in the process group before we proceed. This
+ avoids race conditions with calls to the kill function that we make for
+ signalling process groups. */
+ while ((readRes = read(pgidPipe[0], &tmp, 1)) > 0)
+ ;
+ if (readRes < 0) {
+ sigprocmask(SIG_SETMASK, &old_mask, 0);
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+ return 0;
+ }
+ kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+
+ /* Unmask signals. */
+ if (sigprocmask(SIG_SETMASK, &old_mask, 0) < 0) {
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ return 0;
+ }
+
/* A child has been created. */
++cp->CommandsLeft;
- /* We are done with the error reporting pipe write end. */
- kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
-
/* Block until the child's exec call succeeds and closes the error
pipe or writes data to the pipe to report an error. */
{
- kwsysProcess_ssize_t total = 0;
- kwsysProcess_ssize_t n = 1;
- /* Read the entire error message up to the length of our buffer. */
- while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0)
- {
- /* Keep trying to read until the operation is not interrupted. */
- while(((n = read(si->ErrorPipe[0], cp->ErrorMessage+total,
- (size_t)(KWSYSPE_PIPE_BUFFER_SIZE-total))) < 0) &&
- (errno == EINTR));
- if(n > 0)
- {
- total += n;
+ kwsysProcess_ssize_t total = 0;
+ kwsysProcess_ssize_t n = 1;
+ /* Read the entire error message up to the length of our buffer. */
+ while (total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) {
+ /* Keep trying to read until the operation is not interrupted. */
+ while (((n = read(si->ErrorPipe[0], cp->ErrorMessage + total,
+ (size_t)(KWSYSPE_PIPE_BUFFER_SIZE - total))) < 0) &&
+ (errno == EINTR))
+ ;
+ if (n > 0) {
+ total += n;
}
}
- /* We are done with the error reporting pipe read end. */
- kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+ /* We are done with the error reporting pipe read end. */
+ kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
- if(total > 0)
- {
- /* The child failed to execute the process. */
- return 0;
+ if (total > 0) {
+ /* The child failed to execute the process. */
+ return 0;
}
}
- /* Successfully created this child process. */
- if(prIndex > 0 || si->StdIn > 0)
- {
- /* The parent process does not need the input pipe read end. */
- kwsysProcessCleanupDescriptor(&si->StdIn);
- }
-
- /* The parent process does not need the output pipe write ends. */
- if(si->StdOut != 1)
- {
- kwsysProcessCleanupDescriptor(&si->StdOut);
- }
-
return 1;
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessDestroy(kwsysProcess* cp)
{
/* A child process has terminated. Reap it if it is one handled by
this object. */
int i;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- if(cp->ForkPIDs[i])
- {
+ /* Temporarily disable signals that access ForkPIDs. We don't want them to
+ read a reaped PID, and writes to ForkPIDs are not atomic. */
+ sigset_t mask, old_mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+ if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
+ return;
+ }
+
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ if (cp->ForkPIDs[i]) {
int result;
- while(((result = waitpid(cp->ForkPIDs[i],
- &cp->CommandExitCodes[i], WNOHANG)) < 0) &&
- (errno == EINTR));
- if(result > 0)
- {
+ while (((result = waitpid(cp->ForkPIDs[i], &cp->CommandExitCodes[i],
+ WNOHANG)) < 0) &&
+ (errno == EINTR))
+ ;
+ if (result > 0) {
/* This child has termianted. */
cp->ForkPIDs[i] = 0;
- if(--cp->CommandsLeft == 0)
- {
+ if (--cp->CommandsLeft == 0) {
/* All children have terminated. Close the signal pipe
write end so that no more notifications are sent to this
object. */
@@ -1862,48 +1907,44 @@ static void kwsysProcessDestroy(kwsysProcess* cp)
WaitForData to use a non-blocking read to get the
rest of the data from the pipe. This is needed when
grandchildren keep the output pipes open. */
- }
}
- else if(result < 0 && cp->State != kwsysProcess_State_Error)
- {
+ } else if (result < 0 && cp->State != kwsysProcess_State_Error) {
/* Unexpected error. Report the first time this happens. */
strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
cp->State = kwsysProcess_State_Error;
- }
}
}
+ }
+
+ /* Re-enable signals. */
+ sigprocmask(SIG_SETMASK, &old_mask, 0);
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
{
int fout;
- if(!name)
- {
+ if (!name) {
return 1;
- }
+ }
/* Close the existing descriptor. */
kwsysProcessCleanupDescriptor(p);
/* Open a file for the pipe to write. */
- if((fout = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
- {
+ if ((fout = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
return 0;
- }
+ }
/* Set close-on-exec flag on the pipe's end. */
- if(fcntl(fout, F_SETFD, FD_CLOEXEC) < 0)
- {
+ if (fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) {
return 0;
- }
+ }
/* Assign the replacement descriptor. */
*p = fout;
- return 1;
+ return 1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcessSetupOutputPipeNative(int* p, int des[2])
{
/* Close the existing descriptor. */
@@ -1912,18 +1953,16 @@ static int kwsysProcessSetupOutputPipeNative(int* p, int des[2])
/* Set close-on-exec flag on the pipe's ends. The proper end will
be dup2-ed into the standard descriptor number after fork but
before exec. */
- if((fcntl(des[0], F_SETFD, FD_CLOEXEC) < 0) ||
- (fcntl(des[1], F_SETFD, FD_CLOEXEC) < 0))
- {
+ if ((fcntl(des[0], F_SETFD, FD_CLOEXEC) < 0) ||
+ (fcntl(des[1], F_SETFD, FD_CLOEXEC) < 0)) {
return 0;
- }
+ }
/* Assign the replacement descriptor. */
*p = des[1];
return 1;
}
-/*--------------------------------------------------------------------------*/
/* Get the time at which either the process or user timeout will
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
@@ -1931,33 +1970,30 @@ static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
{
/* The first time this is called, we need to calculate the time at
which the child will timeout. */
- if(cp->Timeout > 0 && cp->TimeoutTime.tv_sec < 0)
- {
+ if (cp->Timeout > 0 && cp->TimeoutTime.tv_sec < 0) {
kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout);
cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length);
- }
+ }
/* Start with process timeout. */
*timeoutTime = cp->TimeoutTime;
/* Check if the user timeout is earlier. */
- if(userTimeout)
- {
+ if (userTimeout) {
kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
- kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout);
- kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime,
- userTimeoutLength);
- if(timeoutTime->tv_sec < 0 ||
- kwsysProcessTimeLess(userTimeoutTime, *timeoutTime))
- {
+ kwsysProcessTime userTimeoutLength =
+ kwsysProcessTimeFromDouble(*userTimeout);
+ kwsysProcessTime userTimeoutTime =
+ kwsysProcessTimeAdd(currentTime, userTimeoutLength);
+ if (timeoutTime->tv_sec < 0 ||
+ kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) {
*timeoutTime = userTimeoutTime;
return 1;
- }
}
+ }
return 0;
}
-/*--------------------------------------------------------------------------*/
/* Get the length of time before the given timeout time arrives.
Returns 1 if the time has already arrived, and 0 otherwise. */
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -1965,41 +2001,33 @@ static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
kwsysProcessTimeNative* timeoutLength,
int zeroIsExpired)
{
- if(timeoutTime->tv_sec < 0)
- {
+ if (timeoutTime->tv_sec < 0) {
/* No timeout time has been requested. */
return 0;
- }
- else
- {
+ } else {
/* Calculate the remaining time. */
kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
- kwsysProcessTime timeLeft = kwsysProcessTimeSubtract(*timeoutTime,
- currentTime);
- if(timeLeft.tv_sec < 0 && userTimeout && *userTimeout <= 0)
- {
+ kwsysProcessTime timeLeft =
+ kwsysProcessTimeSubtract(*timeoutTime, currentTime);
+ if (timeLeft.tv_sec < 0 && userTimeout && *userTimeout <= 0) {
/* Caller has explicitly requested a zero timeout. */
timeLeft.tv_sec = 0;
timeLeft.tv_usec = 0;
- }
+ }
- if(timeLeft.tv_sec < 0 ||
- (timeLeft.tv_sec == 0 && timeLeft.tv_usec == 0 && zeroIsExpired))
- {
+ if (timeLeft.tv_sec < 0 ||
+ (timeLeft.tv_sec == 0 && timeLeft.tv_usec == 0 && zeroIsExpired)) {
/* Timeout has already expired. */
return 1;
- }
- else
- {
+ } else {
/* There is some time left. */
timeoutLength->tv_sec = timeLeft.tv_sec;
timeoutLength->tv_usec = timeLeft.tv_usec;
return 0;
- }
}
+ }
}
-/*--------------------------------------------------------------------------*/
static kwsysProcessTime kwsysProcessTimeGetCurrent(void)
{
kwsysProcessTime current;
@@ -2010,185 +2038,248 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void)
return current;
}
-/*--------------------------------------------------------------------------*/
static double kwsysProcessTimeToDouble(kwsysProcessTime t)
{
- return (double)t.tv_sec + (double)(t.tv_usec)*0.000001;
+ return (double)t.tv_sec + (double)(t.tv_usec) * 0.000001;
}
-/*--------------------------------------------------------------------------*/
static kwsysProcessTime kwsysProcessTimeFromDouble(double d)
{
kwsysProcessTime t;
t.tv_sec = (long)d;
- t.tv_usec = (long)((d-(double)(t.tv_sec))*1000000);
+ t.tv_usec = (long)((d - (double)(t.tv_sec)) * 1000000);
return t;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
{
return ((in1.tv_sec < in2.tv_sec) ||
((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec)));
}
-/*--------------------------------------------------------------------------*/
-static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2)
+static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
+ kwsysProcessTime in2)
{
kwsysProcessTime out;
out.tv_sec = in1.tv_sec + in2.tv_sec;
out.tv_usec = in1.tv_usec + in2.tv_usec;
- if(out.tv_usec > 1000000)
- {
+ if (out.tv_usec >= 1000000) {
out.tv_usec -= 1000000;
out.tv_sec += 1;
- }
+ }
return out;
}
-/*--------------------------------------------------------------------------*/
-static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2)
+static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
+ kwsysProcessTime in2)
{
kwsysProcessTime out;
out.tv_sec = in1.tv_sec - in2.tv_sec;
out.tv_usec = in1.tv_usec - in2.tv_usec;
- if(out.tv_usec < 0)
- {
+ if (out.tv_usec < 0) {
out.tv_usec += 1000000;
out.tv_sec -= 1;
- }
+ }
return out;
}
-/*--------------------------------------------------------------------------*/
-#define KWSYSPE_CASE(type, str) \
- cp->ExitException = kwsysProcess_Exception_##type; \
- strcpy(cp->ExitExceptionString, str)
-static void kwsysProcessSetExitException(kwsysProcess* cp, int sig)
+#define KWSYSPE_CASE(type, str) \
+ cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type; \
+ strcpy(cp->ProcessResults[idx].ExitExceptionString, str)
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
+ int idx)
{
- switch (sig)
- {
+ switch (sig) {
#ifdef SIGSEGV
- case SIGSEGV: KWSYSPE_CASE(Fault, "Segmentation fault"); break;
+ case SIGSEGV:
+ KWSYSPE_CASE(Fault, "Segmentation fault");
+ break;
#endif
#ifdef SIGBUS
-# if !defined(SIGSEGV) || SIGBUS != SIGSEGV
- case SIGBUS: KWSYSPE_CASE(Fault, "Bus error"); break;
-# endif
+#if !defined(SIGSEGV) || SIGBUS != SIGSEGV
+ case SIGBUS:
+ KWSYSPE_CASE(Fault, "Bus error");
+ break;
+#endif
#endif
#ifdef SIGFPE
- case SIGFPE: KWSYSPE_CASE(Numerical, "Floating-point exception"); break;
+ case SIGFPE:
+ KWSYSPE_CASE(Numerical, "Floating-point exception");
+ break;
#endif
#ifdef SIGILL
- case SIGILL: KWSYSPE_CASE(Illegal, "Illegal instruction"); break;
+ case SIGILL:
+ KWSYSPE_CASE(Illegal, "Illegal instruction");
+ break;
#endif
#ifdef SIGINT
- case SIGINT: KWSYSPE_CASE(Interrupt, "User interrupt"); break;
+ case SIGINT:
+ KWSYSPE_CASE(Interrupt, "User interrupt");
+ break;
#endif
#ifdef SIGABRT
- case SIGABRT: KWSYSPE_CASE(Other, "Child aborted"); break;
+ case SIGABRT:
+ KWSYSPE_CASE(Other, "Child aborted");
+ break;
#endif
#ifdef SIGKILL
- case SIGKILL: KWSYSPE_CASE(Other, "Child killed"); break;
+ case SIGKILL:
+ KWSYSPE_CASE(Other, "Child killed");
+ break;
#endif
#ifdef SIGTERM
- case SIGTERM: KWSYSPE_CASE(Other, "Child terminated"); break;
+ case SIGTERM:
+ KWSYSPE_CASE(Other, "Child terminated");
+ break;
#endif
#ifdef SIGHUP
- case SIGHUP: KWSYSPE_CASE(Other, "SIGHUP"); break;
+ case SIGHUP:
+ KWSYSPE_CASE(Other, "SIGHUP");
+ break;
#endif
#ifdef SIGQUIT
- case SIGQUIT: KWSYSPE_CASE(Other, "SIGQUIT"); break;
+ case SIGQUIT:
+ KWSYSPE_CASE(Other, "SIGQUIT");
+ break;
#endif
#ifdef SIGTRAP
- case SIGTRAP: KWSYSPE_CASE(Other, "SIGTRAP"); break;
+ case SIGTRAP:
+ KWSYSPE_CASE(Other, "SIGTRAP");
+ break;
#endif
#ifdef SIGIOT
-# if !defined(SIGABRT) || SIGIOT != SIGABRT
- case SIGIOT: KWSYSPE_CASE(Other, "SIGIOT"); break;
-# endif
+#if !defined(SIGABRT) || SIGIOT != SIGABRT
+ case SIGIOT:
+ KWSYSPE_CASE(Other, "SIGIOT");
+ break;
+#endif
#endif
#ifdef SIGUSR1
- case SIGUSR1: KWSYSPE_CASE(Other, "SIGUSR1"); break;
+ case SIGUSR1:
+ KWSYSPE_CASE(Other, "SIGUSR1");
+ break;
#endif
#ifdef SIGUSR2
- case SIGUSR2: KWSYSPE_CASE(Other, "SIGUSR2"); break;
+ case SIGUSR2:
+ KWSYSPE_CASE(Other, "SIGUSR2");
+ break;
#endif
#ifdef SIGPIPE
- case SIGPIPE: KWSYSPE_CASE(Other, "SIGPIPE"); break;
+ case SIGPIPE:
+ KWSYSPE_CASE(Other, "SIGPIPE");
+ break;
#endif
#ifdef SIGALRM
- case SIGALRM: KWSYSPE_CASE(Other, "SIGALRM"); break;
+ case SIGALRM:
+ KWSYSPE_CASE(Other, "SIGALRM");
+ break;
#endif
#ifdef SIGSTKFLT
- case SIGSTKFLT: KWSYSPE_CASE(Other, "SIGSTKFLT"); break;
+ case SIGSTKFLT:
+ KWSYSPE_CASE(Other, "SIGSTKFLT");
+ break;
#endif
#ifdef SIGCHLD
- case SIGCHLD: KWSYSPE_CASE(Other, "SIGCHLD"); break;
+ case SIGCHLD:
+ KWSYSPE_CASE(Other, "SIGCHLD");
+ break;
#elif defined(SIGCLD)
- case SIGCLD: KWSYSPE_CASE(Other, "SIGCLD"); break;
+ case SIGCLD:
+ KWSYSPE_CASE(Other, "SIGCLD");
+ break;
#endif
#ifdef SIGCONT
- case SIGCONT: KWSYSPE_CASE(Other, "SIGCONT"); break;
+ case SIGCONT:
+ KWSYSPE_CASE(Other, "SIGCONT");
+ break;
#endif
#ifdef SIGSTOP
- case SIGSTOP: KWSYSPE_CASE(Other, "SIGSTOP"); break;
+ case SIGSTOP:
+ KWSYSPE_CASE(Other, "SIGSTOP");
+ break;
#endif
#ifdef SIGTSTP
- case SIGTSTP: KWSYSPE_CASE(Other, "SIGTSTP"); break;
+ case SIGTSTP:
+ KWSYSPE_CASE(Other, "SIGTSTP");
+ break;
#endif
#ifdef SIGTTIN
- case SIGTTIN: KWSYSPE_CASE(Other, "SIGTTIN"); break;
+ case SIGTTIN:
+ KWSYSPE_CASE(Other, "SIGTTIN");
+ break;
#endif
#ifdef SIGTTOU
- case SIGTTOU: KWSYSPE_CASE(Other, "SIGTTOU"); break;
+ case SIGTTOU:
+ KWSYSPE_CASE(Other, "SIGTTOU");
+ break;
#endif
#ifdef SIGURG
- case SIGURG: KWSYSPE_CASE(Other, "SIGURG"); break;
+ case SIGURG:
+ KWSYSPE_CASE(Other, "SIGURG");
+ break;
#endif
#ifdef SIGXCPU
- case SIGXCPU: KWSYSPE_CASE(Other, "SIGXCPU"); break;
+ case SIGXCPU:
+ KWSYSPE_CASE(Other, "SIGXCPU");
+ break;
#endif
#ifdef SIGXFSZ
- case SIGXFSZ: KWSYSPE_CASE(Other, "SIGXFSZ"); break;
+ case SIGXFSZ:
+ KWSYSPE_CASE(Other, "SIGXFSZ");
+ break;
#endif
#ifdef SIGVTALRM
- case SIGVTALRM: KWSYSPE_CASE(Other, "SIGVTALRM"); break;
+ case SIGVTALRM:
+ KWSYSPE_CASE(Other, "SIGVTALRM");
+ break;
#endif
#ifdef SIGPROF
- case SIGPROF: KWSYSPE_CASE(Other, "SIGPROF"); break;
+ case SIGPROF:
+ KWSYSPE_CASE(Other, "SIGPROF");
+ break;
#endif
#ifdef SIGWINCH
- case SIGWINCH: KWSYSPE_CASE(Other, "SIGWINCH"); break;
+ case SIGWINCH:
+ KWSYSPE_CASE(Other, "SIGWINCH");
+ break;
#endif
#ifdef SIGPOLL
- case SIGPOLL: KWSYSPE_CASE(Other, "SIGPOLL"); break;
+ case SIGPOLL:
+ KWSYSPE_CASE(Other, "SIGPOLL");
+ break;
#endif
#ifdef SIGIO
-# if !defined(SIGPOLL) || SIGIO != SIGPOLL
- case SIGIO: KWSYSPE_CASE(Other, "SIGIO"); break;
-# endif
+#if !defined(SIGPOLL) || SIGIO != SIGPOLL
+ case SIGIO:
+ KWSYSPE_CASE(Other, "SIGIO");
+ break;
+#endif
#endif
#ifdef SIGPWR
- case SIGPWR: KWSYSPE_CASE(Other, "SIGPWR"); break;
+ case SIGPWR:
+ KWSYSPE_CASE(Other, "SIGPWR");
+ break;
#endif
#ifdef SIGSYS
- case SIGSYS: KWSYSPE_CASE(Other, "SIGSYS"); break;
+ case SIGSYS:
+ KWSYSPE_CASE(Other, "SIGSYS");
+ break;
#endif
#ifdef SIGUNUSED
-# if !defined(SIGSYS) || SIGUNUSED != SIGSYS
- case SIGUNUSED: KWSYSPE_CASE(Other, "SIGUNUSED"); break;
-# endif
+#if !defined(SIGSYS) || SIGUNUSED != SIGSYS
+ case SIGUNUSED:
+ KWSYSPE_CASE(Other, "SIGUNUSED");
+ break;
+#endif
#endif
default:
- cp->ExitException = kwsysProcess_Exception_Other;
- sprintf(cp->ExitExceptionString, "Signal %d", sig);
+ cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
+ sprintf(cp->ProcessResults[idx].ExitExceptionString, "Signal %d", sig);
break;
- }
+ }
}
#undef KWSYSPE_CASE
-/*--------------------------------------------------------------------------*/
/* When the child process encounters an error before its program is
invoked, this is called to report the error to the parent and
exit. */
@@ -2200,14 +2291,13 @@ static void kwsysProcessChildErrorExit(int errorPipe)
strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
/* Report the error to the parent through the special pipe. */
- result=write(errorPipe, buffer, strlen(buffer));
+ result = write(errorPipe, buffer, strlen(buffer));
(void)result;
/* Terminate without cleanup. */
_exit(1);
}
-/*--------------------------------------------------------------------------*/
/* Restores all signal handlers to their default values. */
static void kwsysProcessRestoreDefaultSignalHandlers(void)
{
@@ -2315,95 +2405,83 @@ static void kwsysProcessRestoreDefaultSignalHandlers(void)
#endif
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessExit(void)
{
_exit(0);
}
-/*--------------------------------------------------------------------------*/
#if !defined(__VMS)
static pid_t kwsysProcessFork(kwsysProcess* cp,
kwsysProcessCreateInformation* si)
{
/* Create a detached process if requested. */
- if(cp->OptionDetach)
- {
+ if (cp->OptionDetach) {
/* Create an intermediate process. */
pid_t middle_pid = fork();
- if(middle_pid < 0)
- {
+ if (middle_pid < 0) {
/* Fork failed. Return as if we were not detaching. */
return middle_pid;
- }
- else if(middle_pid == 0)
- {
+ } else if (middle_pid == 0) {
/* This is the intermediate process. Create the real child. */
pid_t child_pid = fork();
- if(child_pid == 0)
- {
+ if (child_pid == 0) {
/* This is the real child process. There is nothing to do here. */
return 0;
- }
- else
- {
+ } else {
/* Use the error pipe to report the pid to the real parent. */
- while((write(si->ErrorPipe[1], &child_pid, sizeof(child_pid)) < 0) &&
- (errno == EINTR));
+ while ((write(si->ErrorPipe[1], &child_pid, sizeof(child_pid)) < 0) &&
+ (errno == EINTR))
+ ;
/* Exit without cleanup. The parent holds all resources. */
kwsysProcessExit();
return 0; /* Never reached, but avoids SunCC warning. */
- }
}
- else
- {
+ } else {
/* This is the original parent process. The intermediate
process will use the error pipe to report the pid of the
detached child. */
pid_t child_pid;
int status;
- while((read(si->ErrorPipe[0], &child_pid, sizeof(child_pid)) < 0) &&
- (errno == EINTR));
+ while ((read(si->ErrorPipe[0], &child_pid, sizeof(child_pid)) < 0) &&
+ (errno == EINTR))
+ ;
/* Wait for the intermediate process to exit and clean it up. */
- while((waitpid(middle_pid, &status, 0) < 0) && (errno == EINTR));
+ while ((waitpid(middle_pid, &status, 0) < 0) && (errno == EINTR))
+ ;
return child_pid;
- }
}
- else
- {
+ } else {
/* Not creating a detached process. Use normal fork. */
return fork();
- }
+ }
}
#endif
-/*--------------------------------------------------------------------------*/
/* We try to obtain process information by invoking the ps command.
Here we define the command to call on each platform and the
corresponding parsing format string. The parsing format should
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"
+#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"
#elif defined(__sun) && (defined(__SVR4) || defined(__svr4__)) /* Solaris */
-# 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 -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"
#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
-/*--------------------------------------------------------------------------*/
static void kwsysProcessKill(pid_t process_id)
{
#if defined(__linux__) || defined(__CYGWIN__)
@@ -2413,11 +2491,16 @@ static void kwsysProcessKill(pid_t process_id)
/* Suspend the process to be sure it will not create more children. */
kill(process_id, SIGSTOP);
- /* Kill all children if we can find them. */
+#if defined(__CYGWIN__)
+ /* Some Cygwin versions seem to need help here. Give up our time slice
+ so that the child can process SIGSTOP before we send SIGKILL. */
+ usleep(1);
+#endif
+
+/* Kill all children if we can find them. */
#if defined(__linux__) || defined(__CYGWIN__)
/* First try using the /proc filesystem. */
- if((procdir = opendir("/proc")) != NULL)
- {
+ if ((procdir = opendir("/proc")) != NULL) {
#if defined(MAXPATHLEN)
char fname[MAXPATHLEN];
#elif defined(PATH_MAX)
@@ -2425,7 +2508,7 @@ static void kwsysProcessKill(pid_t process_id)
#else
char fname[4096];
#endif
- char buffer[KWSYSPE_PIPE_BUFFER_SIZE+1];
+ char buffer[KWSYSPE_PIPE_BUFFER_SIZE + 1];
struct dirent* d;
/* Each process has a directory in /proc whose name is the pid.
@@ -2436,69 +2519,57 @@ static void kwsysProcessKill(pid_t process_id)
We want to get the ppid for all processes. Those that have
process_id as their parent should be recursively killed. */
- for(d = readdir(procdir); d; d = readdir(procdir))
- {
+ for (d = readdir(procdir); d; d = readdir(procdir)) {
int pid;
- if(sscanf(d->d_name, "%d", &pid) == 1 && pid != 0)
- {
+ if (sscanf(d->d_name, "%d", &pid) == 1 && pid != 0) {
struct stat finfo;
sprintf(fname, "/proc/%d/stat", pid);
- if(stat(fname, &finfo) == 0)
- {
+ if (stat(fname, &finfo) == 0) {
FILE* f = fopen(fname, "r");
- if(f)
- {
+ if (f) {
size_t nread = fread(buffer, 1, KWSYSPE_PIPE_BUFFER_SIZE, f);
+ fclose(f);
buffer[nread] = '\0';
- if(nread > 0)
- {
+ if (nread > 0) {
const char* rparen = strrchr(buffer, ')');
int ppid;
- if(rparen && (sscanf(rparen+1, "%*s %d", &ppid) == 1))
- {
- if(ppid == process_id)
- {
+ if (rparen && (sscanf(rparen + 1, "%*s %d", &ppid) == 1)) {
+ if (ppid == process_id) {
/* Recursively kill this child and its children. */
kwsysProcessKill(pid);
- }
}
}
- fclose(f);
}
}
}
}
- closedir(procdir);
}
- else
+ closedir(procdir);
+ } else
#endif
- {
+ {
#if defined(KWSYSPE_PS_COMMAND)
/* Try running "ps" to get the process information. */
FILE* ps = popen(KWSYSPE_PS_COMMAND, "r");
/* Make sure the process started and provided a valid header. */
- if(ps && fscanf(ps, "%*[^\n]\n") != EOF)
- {
+ if (ps && fscanf(ps, "%*[^\n]\n") != EOF) {
/* Look for processes whose parent is the process being killed. */
int pid, ppid;
- while(fscanf(ps, KWSYSPE_PS_FORMAT, &pid, &ppid) == 2)
- {
- if(ppid == process_id)
- {
+ while (fscanf(ps, KWSYSPE_PS_FORMAT, &pid, &ppid) == 2) {
+ if (ppid == process_id) {
/* Recursively kill this child and its children. */
kwsysProcessKill(pid);
- }
}
}
+ }
/* We are done with the ps process. */
- if(ps)
- {
+ if (ps) {
pclose(ps);
- }
-#endif
}
+#endif
+ }
/* Kill the process. */
kill(process_id, SIGKILL);
@@ -2514,7 +2585,6 @@ static void kwsysProcessKill(pid_t process_id)
#endif
}
-/*--------------------------------------------------------------------------*/
#if defined(__VMS)
int decc$feature_get_index(const char* name);
int decc$feature_set_value(int index, int mode, int value);
@@ -2527,7 +2597,6 @@ static int kwsysProcessSetVMSFeature(const char* name, int value)
}
#endif
-/*--------------------------------------------------------------------------*/
/* Global set of executing processes for use by the signal handler.
This global instance will be zero-initialized by the compiler. */
typedef struct kwsysProcessInstances_s
@@ -2538,19 +2607,22 @@ typedef struct kwsysProcessInstances_s
} kwsysProcessInstances;
static kwsysProcessInstances kwsysProcesses;
-/* The old SIGCHLD handler. */
+/* The old SIGCHLD / SIGINT / SIGTERM handlers. */
static struct sigaction kwsysProcessesOldSigChldAction;
+static struct sigaction kwsysProcessesOldSigIntAction;
+static struct sigaction kwsysProcessesOldSigTermAction;
-/*--------------------------------------------------------------------------*/
static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses)
{
- /* Block SIGCHLD while we update the set of pipes to check.
+ /* Block signals while we update the set of pipes to check.
TODO: sigprocmask is undefined for threaded apps. See
pthread_sigmask. */
sigset_t newset;
sigset_t oldset;
sigemptyset(&newset);
sigaddset(&newset, SIGCHLD);
+ sigaddset(&newset, SIGINT);
+ sigaddset(&newset, SIGTERM);
sigprocmask(SIG_BLOCK, &newset, &oldset);
/* Store the new set in that seen by the signal handler. */
@@ -2560,150 +2632,157 @@ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses)
sigprocmask(SIG_SETMASK, &oldset, 0);
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcessesAdd(kwsysProcess* cp)
{
/* Create a pipe through which the signal handler can notify the
given process object that a child has exited. */
{
- /* Create the pipe. */
- int p[2];
- if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0)
- {
- return 0;
+ /* Create the pipe. */
+ int p[2];
+ if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) {
+ return 0;
}
- /* Store the pipes now to be sure they are cleaned up later. */
- cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL] = p[0];
- cp->SignalPipe = p[1];
+ /* Store the pipes now to be sure they are cleaned up later. */
+ cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL] = p[0];
+ cp->SignalPipe = p[1];
- /* Switch the pipe to non-blocking mode so that reading a byte can
- be an atomic test-and-set. */
- if(!kwsysProcessSetNonBlocking(p[0]) ||
- !kwsysProcessSetNonBlocking(p[1]))
- {
- return 0;
+ /* Switch the pipe to non-blocking mode so that reading a byte can
+ be an atomic test-and-set. */
+ if (!kwsysProcessSetNonBlocking(p[0]) ||
+ !kwsysProcessSetNonBlocking(p[1])) {
+ return 0;
}
- /* The children do not need this pipe. Set close-on-exec flag on
- the pipe's ends. */
- if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
- (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0))
- {
- return 0;
+ /* The children do not need this pipe. Set close-on-exec flag on
+ the pipe's ends. */
+ if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) ||
+ (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) {
+ return 0;
}
}
/* Attempt to add the given signal pipe to the signal handler set. */
{
- /* Make sure there is enough space for the new signal pipe. */
- kwsysProcessInstances oldProcesses = kwsysProcesses;
- kwsysProcessInstances newProcesses = oldProcesses;
- if(oldProcesses.Count == oldProcesses.Size)
- {
- /* Start with enough space for a small number of process instances
- and double the size each time more is needed. */
- newProcesses.Size = oldProcesses.Size? oldProcesses.Size*2 : 4;
-
- /* Try allocating the new block of memory. */
- if((newProcesses.Processes = ((kwsysProcess**)
- malloc((size_t)(newProcesses.Size)*
- sizeof(kwsysProcess*)))))
- {
- /* Copy the old pipe set to the new memory. */
- if(oldProcesses.Count > 0)
- {
- memcpy(newProcesses.Processes, oldProcesses.Processes,
- ((size_t)(oldProcesses.Count) * sizeof(kwsysProcess*)));
+ /* Make sure there is enough space for the new signal pipe. */
+ kwsysProcessInstances oldProcesses = kwsysProcesses;
+ kwsysProcessInstances newProcesses = oldProcesses;
+ if (oldProcesses.Count == oldProcesses.Size) {
+ /* Start with enough space for a small number of process instances
+ and double the size each time more is needed. */
+ newProcesses.Size = oldProcesses.Size ? oldProcesses.Size * 2 : 4;
+
+ /* Try allocating the new block of memory. */
+ if ((newProcesses.Processes = ((kwsysProcess**)malloc(
+ (size_t)(newProcesses.Size) * sizeof(kwsysProcess*))))) {
+ /* Copy the old pipe set to the new memory. */
+ if (oldProcesses.Count > 0) {
+ memcpy(newProcesses.Processes, oldProcesses.Processes,
+ ((size_t)(oldProcesses.Count) * sizeof(kwsysProcess*)));
}
- }
- else
- {
- /* Failed to allocate memory for the new signal pipe set. */
- return 0;
+ } else {
+ /* Failed to allocate memory for the new signal pipe set. */
+ return 0;
}
}
- /* Append the new signal pipe to the set. */
- newProcesses.Processes[newProcesses.Count++] = cp;
+ /* Append the new signal pipe to the set. */
+ newProcesses.Processes[newProcesses.Count++] = cp;
- /* Store the new set in that seen by the signal handler. */
- kwsysProcessesUpdate(&newProcesses);
+ /* Store the new set in that seen by the signal handler. */
+ kwsysProcessesUpdate(&newProcesses);
- /* Free the original pipes if new ones were allocated. */
- if(newProcesses.Processes != oldProcesses.Processes)
- {
- free(oldProcesses.Processes);
+ /* Free the original pipes if new ones were allocated. */
+ if (newProcesses.Processes != oldProcesses.Processes) {
+ free(oldProcesses.Processes);
}
- /* If this is the first process, enable the signal handler. */
- if(newProcesses.Count == 1)
- {
- /* Install our handler for SIGCHLD. Repeat call until it is not
- interrupted. */
- struct sigaction newSigChldAction;
- memset(&newSigChldAction, 0, sizeof(struct sigaction));
+ /* If this is the first process, enable the signal handler. */
+ if (newProcesses.Count == 1) {
+ /* Install our handler for SIGCHLD. Repeat call until it is not
+ interrupted. */
+ struct sigaction newSigAction;
+ memset(&newSigAction, 0, sizeof(struct sigaction));
#if KWSYSPE_USE_SIGINFO
- newSigChldAction.sa_sigaction = kwsysProcessesSignalHandler;
- newSigChldAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
-# ifdef SA_RESTART
- newSigChldAction.sa_flags |= SA_RESTART;
-# endif
-#else
- newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
- newSigChldAction.sa_flags = SA_NOCLDSTOP;
+ newSigAction.sa_sigaction = kwsysProcessesSignalHandler;
+ newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
+#ifdef SA_RESTART
+ newSigAction.sa_flags |= SA_RESTART;
#endif
- while((sigaction(SIGCHLD, &newSigChldAction,
- &kwsysProcessesOldSigChldAction) < 0) &&
- (errno == EINTR));
+#else
+ newSigAction.sa_handler = kwsysProcessesSignalHandler;
+ newSigAction.sa_flags = SA_NOCLDSTOP;
+#endif
+ sigemptyset(&newSigAction.sa_mask);
+ while ((sigaction(SIGCHLD, &newSigAction,
+ &kwsysProcessesOldSigChldAction) < 0) &&
+ (errno == EINTR))
+ ;
+
+ /* Install our handler for SIGINT / SIGTERM. Repeat call until
+ it is not interrupted. */
+ sigemptyset(&newSigAction.sa_mask);
+ sigaddset(&newSigAction.sa_mask, SIGTERM);
+ while ((sigaction(SIGINT, &newSigAction,
+ &kwsysProcessesOldSigIntAction) < 0) &&
+ (errno == EINTR))
+ ;
+
+ sigemptyset(&newSigAction.sa_mask);
+ sigaddset(&newSigAction.sa_mask, SIGINT);
+ while ((sigaction(SIGTERM, &newSigAction,
+ &kwsysProcessesOldSigIntAction) < 0) &&
+ (errno == EINTR))
+ ;
}
}
return 1;
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessesRemove(kwsysProcess* cp)
{
/* Attempt to remove the given signal pipe from the signal handler set. */
{
- /* Find the given process in the set. */
- kwsysProcessInstances newProcesses = kwsysProcesses;
- int i;
- for(i=0; i < newProcesses.Count; ++i)
- {
- if(newProcesses.Processes[i] == cp)
- {
- break;
+ /* Find the given process in the set. */
+ kwsysProcessInstances newProcesses = kwsysProcesses;
+ int i;
+ for (i = 0; i < newProcesses.Count; ++i) {
+ if (newProcesses.Processes[i] == cp) {
+ break;
}
}
- if(i < newProcesses.Count)
- {
- /* Remove the process from the set. */
- --newProcesses.Count;
- for(; i < newProcesses.Count; ++i)
- {
- newProcesses.Processes[i] = newProcesses.Processes[i+1];
+ if (i < newProcesses.Count) {
+ /* Remove the process from the set. */
+ --newProcesses.Count;
+ for (; i < newProcesses.Count; ++i) {
+ newProcesses.Processes[i] = newProcesses.Processes[i + 1];
}
- /* If this was the last process, disable the signal handler. */
- if(newProcesses.Count == 0)
- {
- /* Restore the SIGCHLD handler. Repeat call until it is not
- interrupted. */
- while((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) &&
- (errno == EINTR));
-
- /* Free the table of process pointers since it is now empty.
- This is safe because the signal handler has been removed. */
- newProcesses.Size = 0;
- free(newProcesses.Processes);
- newProcesses.Processes = 0;
+ /* If this was the last process, disable the signal handler. */
+ if (newProcesses.Count == 0) {
+ /* Restore the signal handlers. Repeat call until it is not
+ interrupted. */
+ while ((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) &&
+ (errno == EINTR))
+ ;
+ while ((sigaction(SIGINT, &kwsysProcessesOldSigIntAction, 0) < 0) &&
+ (errno == EINTR))
+ ;
+ while ((sigaction(SIGTERM, &kwsysProcessesOldSigTermAction, 0) < 0) &&
+ (errno == EINTR))
+ ;
+
+ /* Free the table of process pointers since it is now empty.
+ This is safe because the signal handler has been removed. */
+ newProcesses.Size = 0;
+ free(newProcesses.Processes);
+ newProcesses.Processes = 0;
}
- /* Store the new set in that seen by the signal handler. */
- kwsysProcessesUpdate(&newProcesses);
+ /* Store the new set in that seen by the signal handler. */
+ kwsysProcessesUpdate(&newProcesses);
}
}
@@ -2712,46 +2791,122 @@ static void kwsysProcessesRemove(kwsysProcess* cp)
kwsysProcessCleanupDescriptor(&cp->SignalPipe);
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessesSignalHandler(int signum
#if KWSYSPE_USE_SIGINFO
- , siginfo_t* info, void* ucontext
+ ,
+ siginfo_t* info, void* ucontext
#endif
- )
+ )
{
- (void)signum;
+ int i, j, procStatus, old_errno = errno;
#if KWSYSPE_USE_SIGINFO
(void)info;
(void)ucontext;
#endif
/* Signal all process objects that a child has terminated. */
- {
- int i;
- for(i=0; i < kwsysProcesses.Count; ++i)
- {
- /* Set the pipe in a signalled state. */
- char buf = 1;
- kwsysProcess* cp = kwsysProcesses.Processes[i];
- kwsysProcess_ssize_t status=
- read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1);
- (void)status;
- status=write(cp->SignalPipe, &buf, 1);
- (void)status;
- }
+ switch (signum) {
+ case SIGCHLD:
+ for (i = 0; i < kwsysProcesses.Count; ++i) {
+ /* Set the pipe in a signalled state. */
+ char buf = 1;
+ kwsysProcess* cp = kwsysProcesses.Processes[i];
+ kwsysProcess_ssize_t pipeStatus =
+ read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1);
+ (void)pipeStatus;
+ pipeStatus = write(cp->SignalPipe, &buf, 1);
+ (void)pipeStatus;
+ }
+ break;
+ case SIGINT:
+ case SIGTERM:
+ /* Signal child processes that are running in new process groups. */
+ for (i = 0; i < kwsysProcesses.Count; ++i) {
+ kwsysProcess* cp = kwsysProcesses.Processes[i];
+ /* Check Killed to avoid data race condition when killing.
+ Check State to avoid data race condition in kwsysProcessCleanup
+ when there is an error (it leaves a reaped PID). */
+ if (cp->CreateProcessGroup && !cp->Killed &&
+ cp->State != kwsysProcess_State_Error && cp->ForkPIDs) {
+ for (j = 0; j < cp->NumberOfCommands; ++j) {
+ /* Make sure the PID is still valid. */
+ if (cp->ForkPIDs[j]) {
+ /* The user created a process group for this process. The group
+ ID
+ is the process ID for the original process in the group. */
+ kill(-cp->ForkPIDs[j], SIGINT);
+ }
+ }
+ }
+ }
+
+ /* Wait for all processes to terminate. */
+ while (wait(&procStatus) >= 0 || errno != ECHILD) {
+ }
+
+ /* Terminate the process, which is now in an inconsistent state
+ because we reaped all the PIDs that it may have been reaping
+ or may have reaped in the future. Reraise the signal so that
+ the proper exit code is returned. */
+ {
+ /* Install default signal handler. */
+ struct sigaction defSigAction;
+ sigset_t unblockSet;
+ memset(&defSigAction, 0, sizeof(defSigAction));
+ defSigAction.sa_handler = SIG_DFL;
+ sigemptyset(&defSigAction.sa_mask);
+ while ((sigaction(signum, &defSigAction, 0) < 0) && (errno == EINTR))
+ ;
+ /* Unmask the signal. */
+ sigemptyset(&unblockSet);
+ sigaddset(&unblockSet, signum);
+ sigprocmask(SIG_UNBLOCK, &unblockSet, 0);
+ /* Raise the signal again. */
+ raise(signum);
+ /* We shouldn't get here... but if we do... */
+ _exit(1);
+ }
+ /* break omitted to silence unreachable code clang compiler warning. */
}
#if !KWSYSPE_USE_SIGINFO
- /* Re-Install our handler for SIGCHLD. Repeat call until it is not
- interrupted. */
+ /* Re-Install our handler. Repeat call until it is not interrupted. */
{
- struct sigaction newSigChldAction;
- memset(&newSigChldAction, 0, sizeof(struct sigaction));
- newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
- newSigChldAction.sa_flags = SA_NOCLDSTOP;
- while((sigaction(SIGCHLD, &newSigChldAction,
- &kwsysProcessesOldSigChldAction) < 0) &&
- (errno == EINTR));
+ struct sigaction newSigAction;
+ struct sigaction& oldSigAction;
+ memset(&newSigAction, 0, sizeof(struct sigaction));
+ newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
+ newSigChldAction.sa_flags = SA_NOCLDSTOP;
+ sigemptyset(&newSigAction.sa_mask);
+ switch (signum) {
+ case SIGCHLD:
+ oldSigAction = &kwsysProcessesOldSigChldAction;
+ break;
+ case SIGINT:
+ sigaddset(&newSigAction.sa_mask, SIGTERM);
+ oldSigAction = &kwsysProcessesOldSigIntAction;
+ break;
+ case SIGTERM:
+ sigaddset(&newSigAction.sa_mask, SIGINT);
+ oldSigAction = &kwsysProcessesOldSigTermAction;
+ break;
+ default:
+ return 0;
+ }
+ while ((sigaction(signum, &newSigAction, oldSigAction) < 0) &&
+ (errno == EINTR))
+ ;
}
#endif
+
+ errno = old_errno;
+}
+
+void kwsysProcess_ResetStartTime(kwsysProcess* cp)
+{
+ if (!cp) {
+ return;
+ }
+ /* Reset start time. */
+ cp->StartTime = kwsysProcessTimeGetCurrent();
}
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index c836f9b08..5183e3d2c 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -1,23 +1,14 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Process.h)
-#include KWSYS_HEADER(System.h)
+#include KWSYS_HEADER(Encoding.h)
/* 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 "Encoding.h.in"
+#include "Process.h.in"
#endif
/*
@@ -31,12 +22,15 @@ a UNIX-style select system call.
*/
#ifdef _MSC_VER
-#pragma warning (push, 1)
+#pragma warning(push, 1)
#endif
#include <windows.h> /* Windows API */
-#include <string.h> /* strlen, strdup */
-#include <stdio.h> /* sprintf */
-#include <io.h> /* _unlink */
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#endif
+#include <io.h> /* _unlink */
+#include <stdio.h> /* sprintf */
+#include <string.h> /* strlen, strdup */
#ifdef __WATCOMC__
#define _unlink unlink
#endif
@@ -49,14 +43,14 @@ a UNIX-style select system call.
#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. */
@@ -69,18 +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;
@@ -88,10 +78,14 @@ typedef LARGE_INTEGER kwsysProcessTime;
typedef struct kwsysProcessCreateInformation_s
{
/* Windows child startup control data. */
- STARTUPINFO StartupInfo;
+ STARTUPINFOW StartupInfo;
+
+ /* Original handles before making inherited duplicates. */
+ HANDLE hStdInput;
+ HANDLE hStdOutput;
+ HANDLE hStdError;
} kwsysProcessCreateInformation;
-/*--------------------------------------------------------------------------*/
typedef struct kwsysProcessPipeData_s kwsysProcessPipeData;
static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd);
static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp,
@@ -100,23 +94,15 @@ static DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd);
static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp,
kwsysProcessPipeData* td);
static int kwsysProcessInitialize(kwsysProcess* cp);
-static int kwsysProcessCreate(kwsysProcess* cp, int index,
- kwsysProcessCreateInformation* si,
- PHANDLE readEnd);
+static DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
+ kwsysProcessCreateInformation* si);
static void kwsysProcessDestroy(kwsysProcess* cp, int event);
-static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
-static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
-static int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2],
- int isWrite);
+static DWORD kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
+static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
+static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle);
static void kwsysProcessCleanupHandle(PHANDLE h);
-static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle);
-static void kwsysProcessCleanup(kwsysProcess* cp, int error);
+static void kwsysProcessCleanup(kwsysProcess* cp, DWORD error);
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
-static int kwsysProcessComputeCommandLength(kwsysProcess* cp,
- char const* const* command);
-static void kwsysProcessComputeCommandLine(kwsysProcess* cp,
- char const* const* command,
- char* cmd);
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
kwsysProcessTime* timeoutTime);
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -127,13 +113,23 @@ static DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t);
static double kwsysProcessTimeToDouble(kwsysProcessTime t);
static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
-static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
-static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
+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);
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
+static int kwsysProcessesInitialize(void);
+static int kwsysTryEnterCreateProcessSection(void);
+static void kwsysLeaveCreateProcessSection(void);
+static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId,
+ int newProcessGroup);
+static void kwsysProcessesRemove(HANDLE hProcess);
+static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType);
-/*--------------------------------------------------------------------------*/
/* A structure containing synchronization data for each thread. */
typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync;
struct kwsysProcessPipeSync_s
@@ -151,7 +147,6 @@ struct kwsysProcessPipeSync_s
HANDLE Reset;
};
-/*--------------------------------------------------------------------------*/
/* A structure containing data for each pipe's threads. */
struct kwsysProcessPipeData_s
{
@@ -187,7 +182,26 @@ struct kwsysProcessPipeData_s
HANDLE Write;
};
-/*--------------------------------------------------------------------------*/
+/* A structure containing results data for each process. */
+typedef struct kwsysProcessResults_s kwsysProcessResults;
+struct kwsysProcessResults_s
+{
+ /* The status of the process. */
+ int State;
+
+ /* The exceptional behavior that terminated the process, if any. */
+ int ExitException;
+
+ /* The process exit code. */
+ DWORD ExitCode;
+
+ /* The process return code, if any. */
+ int ExitValue;
+
+ /* Description for the ExitException. */
+ char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+};
+
/* Structure containing data used to implement the child's execution. */
struct kwsysProcess_s
{
@@ -197,14 +211,14 @@ struct kwsysProcess_s
int State;
/* The command lines to execute. */
- char** Commands;
+ wchar_t** Commands;
int NumberOfCommands;
/* The exit code of each command. */
DWORD* CommandExitCodes;
/* The working directory for the child process. */
- char* WorkingDirectory;
+ wchar_t* WorkingDirectory;
/* Whether to create the child as a detached process. */
int OptionDetach;
@@ -218,6 +232,12 @@ struct kwsysProcess_s
/* Whether to treat command lines as verbatim. */
int Verbatim;
+ /* Whether to merge stdout/stderr of the child. */
+ int MergeOutput;
+
+ /* Whether to create the process in a new process group. */
+ int CreateProcessGroup;
+
/* Mutex to protect the shared index used by threads to report data. */
HANDLE SharedIndexMutex;
@@ -247,15 +267,6 @@ struct kwsysProcess_s
/* ------------- Data managed per call to Execute ------------- */
- /* The exceptional behavior that terminated the process, if any. */
- int ExitException;
-
- /* The process exit code. */
- DWORD ExitCode;
-
- /* The process return code, if any. */
- int ExitValue;
-
/* Index of last pipe to report data, if any. */
int CurrentIndex;
@@ -285,10 +296,10 @@ struct kwsysProcess_s
int PipesLeft;
/* Buffer for error messages. */
- char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
+ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
- /* Description for the ExitException. */
- char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1];
+ /* process results. */
+ kwsysProcessResults* ProcessResults;
/* Windows process information data. */
PROCESS_INFORMATION* ProcessInformation;
@@ -299,10 +310,13 @@ struct kwsysProcess_s
/* Real working directory of our own process. */
DWORD RealWorkingDirectoryLength;
- char* RealWorkingDirectory;
+ wchar_t* RealWorkingDirectory;
+
+ /* Own handles for the child's ends of the pipes in the parent process.
+ Used temporarily during process creation. */
+ HANDLE PipeChildStd[3];
};
-/*--------------------------------------------------------------------------*/
kwsysProcess* kwsysProcess_New(void)
{
int i;
@@ -313,13 +327,21 @@ kwsysProcess* kwsysProcess_New(void)
/* Windows version number data. */
OSVERSIONINFO osv;
+ /* Initialize list of processes before we get any farther. It's especially
+ important that the console Ctrl handler be added BEFORE starting the
+ first process. This prevents the risk of an orphaned process being
+ started by the main thread while the default Ctrl handler is in
+ progress. */
+ if (!kwsysProcessesInitialize()) {
+ return 0;
+ }
+
/* Allocate a process control structure. */
cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
- if(!cp)
- {
+ if (!cp) {
/* Could not allocate memory for the control structure. */
return 0;
- }
+ }
ZeroMemory(cp, sizeof(*cp));
/* Share stdin with the parent process by default. */
@@ -332,32 +354,39 @@ kwsysProcess* kwsysProcess_New(void)
windows. */
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
+#endif
GetVersionEx(&osv);
- if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
- {
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(pop)
+#endif
+ if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
/* Win9x no longer supported. */
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* Initially no thread owns the mutex. Initialize semaphore to 1. */
- if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
- {
+ if (!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* Initially no data are available. Initialize semaphore to 0. */
- if(!(cp->Full = CreateSemaphore(0, 0, 1, 0)))
- {
+ if (!(cp->Full = CreateSemaphore(0, 0, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* Create the thread to read each pipe. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
- DWORD dummy=0;
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
+ DWORD dummy = 0;
/* Assign the thread its index. */
cp->Pipe[i].Index = i;
@@ -366,106 +395,91 @@ kwsysProcess* kwsysProcess_New(void)
cp->Pipe[i].Process = cp;
/* No process is yet running. Initialize semaphore to 0. */
- if(!(cp->Pipe[i].Reader.Ready = CreateSemaphore(0, 0, 1, 0)))
- {
+ if (!(cp->Pipe[i].Reader.Ready = CreateSemaphore(0, 0, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* The pipe is not yet reset. Initialize semaphore to 0. */
- if(!(cp->Pipe[i].Reader.Reset = CreateSemaphore(0, 0, 1, 0)))
- {
+ if (!(cp->Pipe[i].Reader.Reset = CreateSemaphore(0, 0, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* The thread's buffer is initially empty. Initialize semaphore to 1. */
- if(!(cp->Pipe[i].Reader.Go = CreateSemaphore(0, 1, 1, 0)))
- {
+ if (!(cp->Pipe[i].Reader.Go = CreateSemaphore(0, 1, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* Create the reading thread. It will block immediately. The
thread will not make deeply nested calls, so we need only a
small stack. */
- if(!(cp->Pipe[i].Reader.Thread = CreateThread(0, 1024,
- kwsysProcessPipeThreadRead,
- &cp->Pipe[i], 0, &dummy)))
- {
+ if (!(cp->Pipe[i].Reader.Thread = CreateThread(
+ 0, 1024, kwsysProcessPipeThreadRead, &cp->Pipe[i], 0, &dummy))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* No process is yet running. Initialize semaphore to 0. */
- if(!(cp->Pipe[i].Waker.Ready = CreateSemaphore(0, 0, 1, 0)))
- {
+ if (!(cp->Pipe[i].Waker.Ready = CreateSemaphore(0, 0, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* The pipe is not yet reset. Initialize semaphore to 0. */
- if(!(cp->Pipe[i].Waker.Reset = CreateSemaphore(0, 0, 1, 0)))
- {
+ if (!(cp->Pipe[i].Waker.Reset = CreateSemaphore(0, 0, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* The waker should not wake immediately. Initialize semaphore to 0. */
- if(!(cp->Pipe[i].Waker.Go = CreateSemaphore(0, 0, 1, 0)))
- {
+ if (!(cp->Pipe[i].Waker.Go = CreateSemaphore(0, 0, 1, 0))) {
kwsysProcess_Delete(cp);
return 0;
- }
+ }
/* Create the waking thread. It will block immediately. The
thread will not make deeply nested calls, so we need only a
small stack. */
- if(!(cp->Pipe[i].Waker.Thread = CreateThread(0, 1024,
- kwsysProcessPipeThreadWake,
- &cp->Pipe[i], 0, &dummy)))
- {
+ if (!(cp->Pipe[i].Waker.Thread = CreateThread(
+ 0, 1024, kwsysProcessPipeThreadWake, &cp->Pipe[i], 0, &dummy))) {
kwsysProcess_Delete(cp);
return 0;
- }
}
+ }
+ for (i = 0; i < 3; ++i) {
+ cp->PipeChildStd[i] = INVALID_HANDLE_VALUE;
+ }
return cp;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_Delete(kwsysProcess* cp)
{
int i;
/* Make sure we have an instance. */
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
/* If the process is executing, wait for it to finish. */
- if(cp->State == kwsysProcess_State_Executing)
- {
- if(cp->Detached)
- {
+ if (cp->State == kwsysProcess_State_Executing) {
+ if (cp->Detached) {
kwsysProcess_Disown(cp);
- }
- else
- {
+ } else {
kwsysProcess_WaitForExit(cp, 0);
- }
}
+ }
/* We are deleting the kwsysProcess instance. */
cp->Deleting = 1;
/* Terminate each of the threads. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
/* Terminate this reading thread. */
- if(cp->Pipe[i].Reader.Thread)
- {
+ if (cp->Pipe[i].Reader.Thread) {
/* Signal the thread we are ready for it. It will terminate
immediately since Deleting is set. */
ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0);
@@ -475,11 +489,10 @@ void kwsysProcess_Delete(kwsysProcess* cp)
/* Close the handle to the thread. */
kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Thread);
- }
+ }
/* Terminate this waking thread. */
- if(cp->Pipe[i].Waker.Thread)
- {
+ if (cp->Pipe[i].Waker.Thread) {
/* Signal the thread we are ready for it. It will terminate
immediately since Deleting is set. */
ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0);
@@ -489,7 +502,7 @@ void kwsysProcess_Delete(kwsysProcess* cp)
/* Close the handle to the thread. */
kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Thread);
- }
+ }
/* Cleanup the pipe's semaphores. */
kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Ready);
@@ -498,7 +511,7 @@ void kwsysProcess_Delete(kwsysProcess* cp)
kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Ready);
kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Go);
kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Reset);
- }
+ }
/* Close the shared semaphores. */
kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
@@ -510,92 +523,119 @@ 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)
- {
+ if (cp->CommandExitCodes) {
free(cp->CommandExitCodes);
- }
+ }
+ free(cp->ProcessResults);
free(cp);
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
{
int i;
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ }
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
free(cp->Commands[i]);
- }
+ }
cp->NumberOfCommands = 0;
- if(cp->Commands)
- {
+ if (cp->Commands) {
free(cp->Commands);
cp->Commands = 0;
- }
- if(command)
- {
+ }
+ if (command) {
return kwsysProcess_AddCommand(cp, command);
- }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
{
int newNumberOfCommands;
- char** newCommands;
+ wchar_t** newCommands;
/* Make sure we have a command to add. */
- if(!cp || !command || !*command)
- {
+ if (!cp || !command || !*command) {
return 0;
- }
+ }
/* Allocate a new array for command pointers. */
newNumberOfCommands = cp->NumberOfCommands + 1;
- if(!(newCommands = (char**)malloc(sizeof(char*) * newNumberOfCommands)))
- {
+ if (!(newCommands =
+ (wchar_t**)malloc(sizeof(wchar_t*) * newNumberOfCommands))) {
/* Out of memory. */
return 0;
- }
+ }
/* Copy any existing commands into the new array. */
{
- int i;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- newCommands[i] = cp->Commands[i];
+ int i;
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ newCommands[i] = cp->Commands[i];
}
}
- /* We need to construct a single string representing the command
- and its arguments. We will surround each argument containing
- spaces with double-quotes. Inside a double-quoted argument, we
- need to escape double-quotes and all backslashes before them.
- We also need to escape backslashes at the end of an argument
- because they come before the closing double-quote for the
- argument. */
- {
- /* First determine the length of the final string. */
- int length = kwsysProcessComputeCommandLength(cp, command);
-
- /* Allocate enough space for the command. We do not need an extra
- byte for the terminating null because we allocated a space for
- the first argument that we will not use. */
- newCommands[cp->NumberOfCommands] = (char*)malloc(length);
- if(!newCommands[cp->NumberOfCommands])
- {
- /* Out of memory. */
+ if (cp->Verbatim) {
+ /* Copy the verbatim command line into the buffer. */
+ newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(*command);
+ } else {
+ /* Encode the arguments so CommandLineToArgvW can decode
+ them from the command line string in the child. */
+ char buffer[32768]; /* CreateProcess max command-line length. */
+ char* end = buffer + sizeof(buffer);
+ char* out = buffer;
+ char const* const* a;
+ for (a = command; *a; ++a) {
+ int quote = !**a; /* Quote the empty string. */
+ int slashes = 0;
+ char const* c;
+ if (a != command && out != end) {
+ *out++ = ' ';
+ }
+ for (c = *a; !quote && *c; ++c) {
+ quote = (*c == ' ' || *c == '\t');
+ }
+ if (quote && out != end) {
+ *out++ = '"';
+ }
+ for (c = *a; *c; ++c) {
+ if (*c == '\\') {
+ ++slashes;
+ } else {
+ if (*c == '"') {
+ // Add n+1 backslashes to total 2n+1 before internal '"'.
+ while (slashes-- >= 0 && out != end) {
+ *out++ = '\\';
+ }
+ }
+ slashes = 0;
+ }
+ if (out != end) {
+ *out++ = *c;
+ }
+ }
+ if (quote) {
+ // Add n backslashes to total 2n before ending '"'.
+ while (slashes-- > 0 && out != end) {
+ *out++ = '\\';
+ }
+ if (out != end) {
+ *out++ = '"';
+ }
+ }
+ }
+ if (out != end) {
+ *out = '\0';
+ newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(buffer);
+ } else {
+ newCommands[cp->NumberOfCommands] = 0;
+ }
+ }
+ if (!newCommands[cp->NumberOfCommands]) {
+ /* Out of memory or command line too long. */
free(newCommands);
return 0;
- }
-
- /* Construct the command line in the allocated buffer. */
- kwsysProcessComputeCommandLine(cp, command,
- newCommands[cp->NumberOfCommands]);
}
/* Save the new array of commands. */
@@ -605,408 +645,505 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
return 1;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
{
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
cp->Timeout = timeout;
- if(cp->Timeout < 0)
- {
+ if (cp->Timeout < 0) {
cp->Timeout = 0;
- }
+ }
+ // Force recomputation of TimeoutTime.
+ cp->TimeoutTime.QuadPart = -1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
{
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
- if(cp->WorkingDirectory)
- {
+ }
+ if (cp->WorkingDirectory) {
free(cp->WorkingDirectory);
cp->WorkingDirectory = 0;
- }
- if(dir && dir[0])
- {
+ }
+ if (dir && dir[0]) {
+ wchar_t* wdir = kwsysEncoding_DupToWide(dir);
/* We must convert the working directory to a full path. */
- DWORD length = GetFullPathName(dir, 0, 0, 0);
- if(length > 0)
- {
- cp->WorkingDirectory = (char*)malloc(length);
- if(!cp->WorkingDirectory)
- {
+ DWORD length = GetFullPathNameW(wdir, 0, 0, 0);
+ if (length > 0) {
+ wchar_t* work_dir = malloc(length * sizeof(wchar_t));
+ if (!work_dir) {
+ free(wdir);
return 0;
- }
- if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0))
- {
- free(cp->WorkingDirectory);
- cp->WorkingDirectory = 0;
+ }
+ if (!GetFullPathNameW(wdir, length, work_dir, 0)) {
+ free(work_dir);
+ free(wdir);
return 0;
- }
}
+ cp->WorkingDirectory = work_dir;
}
+ free(wdir);
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
{
char** pfile;
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
- switch(pipe)
- {
- case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break;
- case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break;
- case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break;
- default: return 0;
- }
- if(*pfile)
- {
+ }
+ switch (pipe) {
+ case kwsysProcess_Pipe_STDIN:
+ pfile = &cp->PipeFileSTDIN;
+ break;
+ case kwsysProcess_Pipe_STDOUT:
+ pfile = &cp->PipeFileSTDOUT;
+ break;
+ case kwsysProcess_Pipe_STDERR:
+ pfile = &cp->PipeFileSTDERR;
+ break;
+ default:
+ return 0;
+ }
+ if (*pfile) {
free(*pfile);
*pfile = 0;
- }
- if(file)
- {
- *pfile = (char*)malloc(strlen(file)+1);
- if(!*pfile)
- {
+ }
+ if (file) {
+ *pfile = (char*)malloc(strlen(file) + 1);
+ if (!*pfile) {
return 0;
- }
- strcpy(*pfile, file);
}
+ strcpy(*pfile, file);
+ }
/* If we are redirecting the pipe, do not share it or use a native
pipe. */
- if(*pfile)
- {
+ if (*pfile) {
kwsysProcess_SetPipeNative(cp, pipe, 0);
kwsysProcess_SetPipeShared(cp, pipe, 0);
- }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
{
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
- switch(pipe)
- {
- case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break;
- case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break;
- case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break;
- default: return;
- }
+ switch (pipe) {
+ case kwsysProcess_Pipe_STDIN:
+ cp->PipeSharedSTDIN = shared ? 1 : 0;
+ break;
+ case kwsysProcess_Pipe_STDOUT:
+ cp->PipeSharedSTDOUT = shared ? 1 : 0;
+ break;
+ case kwsysProcess_Pipe_STDERR:
+ cp->PipeSharedSTDERR = shared ? 1 : 0;
+ break;
+ default:
+ return;
+ }
/* If we are sharing the pipe, do not redirect it to a file or use a
native pipe. */
- if(shared)
- {
+ if (shared) {
kwsysProcess_SetPipeFile(cp, pipe, 0);
kwsysProcess_SetPipeNative(cp, pipe, 0);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2])
{
HANDLE* pPipeNative = 0;
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
- switch(pipe)
- {
- case kwsysProcess_Pipe_STDIN: pPipeNative = cp->PipeNativeSTDIN; break;
- case kwsysProcess_Pipe_STDOUT: pPipeNative = cp->PipeNativeSTDOUT; break;
- case kwsysProcess_Pipe_STDERR: pPipeNative = cp->PipeNativeSTDERR; break;
- default: return;
- }
+ switch (pipe) {
+ case kwsysProcess_Pipe_STDIN:
+ pPipeNative = cp->PipeNativeSTDIN;
+ break;
+ case kwsysProcess_Pipe_STDOUT:
+ pPipeNative = cp->PipeNativeSTDOUT;
+ break;
+ case kwsysProcess_Pipe_STDERR:
+ pPipeNative = cp->PipeNativeSTDERR;
+ break;
+ default:
+ return;
+ }
/* Copy the native pipe handles provided. */
- if(p)
- {
+ if (p) {
pPipeNative[0] = p[0];
pPipeNative[1] = p[1];
- }
- else
- {
+ } else {
pPipeNative[0] = 0;
pPipeNative[1] = 0;
- }
+ }
/* If we are using a native pipe, do not share it or redirect it to
a file. */
- if(p)
- {
+ if (p) {
kwsysProcess_SetPipeFile(cp, pipe, 0);
kwsysProcess_SetPipeShared(cp, pipe, 0);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
- if(!cp)
- {
+ if (!cp) {
return 0;
- }
+ }
- switch(optionId)
- {
- case kwsysProcess_Option_Detach: return cp->OptionDetach;
- case kwsysProcess_Option_HideWindow: return cp->HideWindow;
- case kwsysProcess_Option_Verbatim: return cp->Verbatim;
- default: return 0;
- }
+ switch (optionId) {
+ case kwsysProcess_Option_Detach:
+ return cp->OptionDetach;
+ case kwsysProcess_Option_HideWindow:
+ return cp->HideWindow;
+ case kwsysProcess_Option_MergeOutput:
+ return cp->MergeOutput;
+ case kwsysProcess_Option_Verbatim:
+ return cp->Verbatim;
+ case kwsysProcess_Option_CreateProcessGroup:
+ return cp->CreateProcessGroup;
+ default:
+ return 0;
+ }
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
{
- if(!cp)
- {
+ if (!cp) {
return;
- }
+ }
- switch(optionId)
- {
- case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
- case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break;
- case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
- default: break;
- }
+ switch (optionId) {
+ case kwsysProcess_Option_Detach:
+ cp->OptionDetach = value;
+ break;
+ case kwsysProcess_Option_HideWindow:
+ cp->HideWindow = value;
+ break;
+ case kwsysProcess_Option_MergeOutput:
+ cp->MergeOutput = value;
+ break;
+ case kwsysProcess_Option_Verbatim:
+ cp->Verbatim = value;
+ break;
+ case kwsysProcess_Option_CreateProcessGroup:
+ cp->CreateProcessGroup = value;
+ break;
+ default:
+ break;
+ }
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetState(kwsysProcess* cp)
{
- return cp? cp->State : kwsysProcess_State_Error;
+ return cp ? cp->State : kwsysProcess_State_Error;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetExitException(kwsysProcess* cp)
{
- return cp? cp->ExitException : kwsysProcess_Exception_Other;
+ return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+ ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
+ : kwsysProcess_Exception_Other;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetExitValue(kwsysProcess* cp)
{
- return cp? cp->ExitValue : -1;
+ return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+ ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
+ : -1;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_GetExitCode(kwsysProcess* cp)
{
- return cp? cp->ExitCode : 0;
+ return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+ ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
+ : 0;
}
-/*--------------------------------------------------------------------------*/
const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
{
- if(!cp)
- {
+ if (!cp) {
return "Process management structure could not be allocated";
- }
- else if(cp->State == kwsysProcess_State_Error)
- {
+ } else if (cp->State == kwsysProcess_State_Error) {
return cp->ErrorMessage;
- }
+ }
return "Success";
}
-/*--------------------------------------------------------------------------*/
const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
{
- if(!cp)
- {
+ if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
return "GetExceptionString called with NULL process management structure";
- }
- else if(cp->State == kwsysProcess_State_Exception)
- {
- return cp->ExitExceptionString;
- }
+ } else if (cp->State == kwsysProcess_State_Exception) {
+ return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
+ }
+ return "No exception";
+}
+
+/* the index should be in array bound. */
+#define KWSYSPE_IDX_CHK(RET) \
+ if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \
+ KWSYSPE_DEBUG((stderr, "array index out of bound\n")); \
+ return RET; \
+ }
+
+int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(kwsysProcess_State_Error)
+ return cp->ProcessResults[idx].State;
+}
+
+int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other)
+ return cp->ProcessResults[idx].ExitException;
+}
+
+int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(-1)
+ return cp->ProcessResults[idx].ExitValue;
+}
+
+int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK(-1)
+ return cp->CommandExitCodes[idx];
+}
+
+const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx)
+{
+ KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management "
+ "structure or index out of bound")
+ if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) {
+ return cp->ProcessResults[idx].ExitExceptionString;
+ }
return "No exception";
}
-/*--------------------------------------------------------------------------*/
+#undef KWSYSPE_IDX_CHK
+
void kwsysProcess_Execute(kwsysProcess* cp)
{
int i;
- /* Child startup control data. */
- kwsysProcessCreateInformation si;
-
/* Do not execute a second time. */
- if(!cp || cp->State == kwsysProcess_State_Executing)
- {
+ if (!cp || cp->State == kwsysProcess_State_Executing) {
return;
- }
+ }
/* Make sure we have something to run. */
- if(cp->NumberOfCommands < 1)
- {
+ if (cp->NumberOfCommands < 1) {
strcpy(cp->ErrorMessage, "No command");
cp->State = kwsysProcess_State_Error;
return;
- }
+ }
/* Initialize the control structure for a new process. */
- if(!kwsysProcessInitialize(cp))
- {
+ if (!kwsysProcessInitialize(cp)) {
strcpy(cp->ErrorMessage, "Out of memory");
cp->State = kwsysProcess_State_Error;
return;
- }
+ }
/* Save the real working directory of this process and change to
the working directory for the child processes. This is needed
to make pipe file paths evaluate correctly. */
- if(cp->WorkingDirectory)
- {
- if(!GetCurrentDirectory(cp->RealWorkingDirectoryLength,
- cp->RealWorkingDirectory))
- {
- kwsysProcessCleanup(cp, 1);
+ if (cp->WorkingDirectory) {
+ if (!GetCurrentDirectoryW(cp->RealWorkingDirectoryLength,
+ cp->RealWorkingDirectory)) {
+ kwsysProcessCleanup(cp, GetLastError());
return;
- }
- SetCurrentDirectory(cp->WorkingDirectory);
}
+ SetCurrentDirectoryW(cp->WorkingDirectory);
+ }
- /* Initialize startup info data. */
- ZeroMemory(&si, sizeof(si));
- si.StartupInfo.cb = sizeof(si.StartupInfo);
-
- /* Decide whether a child window should be shown. */
- si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
- si.StartupInfo.wShowWindow =
- (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT);
-
- /* Connect the child's output pipes to the threads. */
- si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- /* Create stderr pipe to be shared by all processes in the pipeline.
- Neither end is directly inherited. */
- if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read,
- &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0))
- {
- kwsysProcessCleanup(cp, 1);
- return;
+ /* Setup the stdin pipe for the first process. */
+ if (cp->PipeFileSTDIN) {
+ /* Create a handle to read a file for stdin. */
+ 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);
+ error = GetLastError(); /* Check now in case free changes this. */
+ free(wstdin);
+ if (cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) {
+ kwsysProcessCleanup(cp, error);
+ return;
}
+ } else if (cp->PipeSharedSTDIN) {
+ /* Share this process's stdin with the child. */
+ kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE, &cp->PipeChildStd[0]);
+ } else if (cp->PipeNativeSTDIN[0]) {
+ /* Use the provided native pipe. */
+ kwsysProcessSetupPipeNative(cp->PipeNativeSTDIN[0], &cp->PipeChildStd[0]);
+ } else {
+ /* Explicitly give the child no stdin. */
+ cp->PipeChildStd[0] = INVALID_HANDLE_VALUE;
+ }
- /* Create an inherited duplicate of the write end, but do not
- close the non-inherited version. We need to keep it open
- to use in waking up the pipe threads. */
- if(!DuplicateHandle(GetCurrentProcess(), cp->Pipe[KWSYSPE_PIPE_STDERR].Write,
- GetCurrentProcess(), &si.StartupInfo.hStdError,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ /* Create the output pipe for the last process.
+ We always create this so the pipe thread can run even if we
+ do not end up giving the write end to the child below. */
+ if (!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDOUT].Read,
+ &cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, 0, 0)) {
+ kwsysProcessCleanup(cp, GetLastError());
return;
- }
+ }
- /* Replace the stderr pipe with a file if requested. In this case
- the pipe thread will still run but never report data. */
- if(cp->PipeFileSTDERR)
- {
- if(!kwsysProcessSetupOutputPipeFile(&si.StartupInfo.hStdError,
- cp->PipeFileSTDERR))
- {
- kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ if (cp->PipeFileSTDOUT) {
+ /* Use a file for stdout. */
+ DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1],
+ cp->PipeFileSTDOUT);
+ if (error) {
+ kwsysProcessCleanup(cp, error);
return;
- }
}
-
- /* Replace the stderr pipe with the parent process's if requested.
- In this case the pipe thread will still run but never report
- data. */
- if(cp->PipeSharedSTDERR)
- {
- if(!kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE,
- &si.StartupInfo.hStdError))
- {
- kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
- STD_ERROR_HANDLE);
+ } else if (cp->PipeSharedSTDOUT) {
+ /* Use the parent stdout. */
+ kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE, &cp->PipeChildStd[1]);
+ } else if (cp->PipeNativeSTDOUT[1]) {
+ /* Use the given handle for stdout. */
+ kwsysProcessSetupPipeNative(cp->PipeNativeSTDOUT[1], &cp->PipeChildStd[1]);
+ } else {
+ /* Use our pipe for stdout. Duplicate the handle since our waker
+ thread will use the original. Do not make it inherited yet. */
+ if (!DuplicateHandle(GetCurrentProcess(),
+ cp->Pipe[KWSYSPE_PIPE_STDOUT].Write,
+ GetCurrentProcess(), &cp->PipeChildStd[1], 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ kwsysProcessCleanup(cp, GetLastError());
return;
- }
}
+ }
- /* Replace the stderr pipe with the native pipe provided if any. In
- this case the pipe thread will still run but never report
- data. */
- if(cp->PipeNativeSTDERR[1])
- {
- if(!kwsysProcessSetupPipeNative(&si.StartupInfo.hStdError,
- cp->PipeNativeSTDERR, 1))
- {
- kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
- STD_ERROR_HANDLE);
+ /* Create stderr pipe to be shared by all processes in the pipeline.
+ We always create this so the pipe thread can run even if we do not
+ end up giving the write end to the child below. */
+ if (!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read,
+ &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) {
+ kwsysProcessCleanup(cp, GetLastError());
+ return;
+ }
+
+ if (cp->PipeFileSTDERR) {
+ /* Use a file for stderr. */
+ DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2],
+ cp->PipeFileSTDERR);
+ if (error) {
+ kwsysProcessCleanup(cp, error);
+ return;
+ }
+ } else if (cp->PipeSharedSTDERR) {
+ /* Use the parent stderr. */
+ kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE, &cp->PipeChildStd[2]);
+ } else if (cp->PipeNativeSTDERR[1]) {
+ /* Use the given handle for stderr. */
+ kwsysProcessSetupPipeNative(cp->PipeNativeSTDERR[1], &cp->PipeChildStd[2]);
+ } else {
+ /* Use our pipe for stderr. Duplicate the handle since our waker
+ thread will use the original. Do not make it inherited yet. */
+ if (!DuplicateHandle(GetCurrentProcess(),
+ cp->Pipe[KWSYSPE_PIPE_STDERR].Write,
+ GetCurrentProcess(), &cp->PipeChildStd[2], 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ kwsysProcessCleanup(cp, GetLastError());
return;
- }
}
+ }
/* Create the pipeline of processes. */
{
- HANDLE readEnd = 0;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- if(kwsysProcessCreate(cp, i, &si, &readEnd))
- {
- cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess;
+ /* Child startup control data. */
+ kwsysProcessCreateInformation si;
+ HANDLE nextStdInput = cp->PipeChildStd[0];
+
+ /* Initialize startup info data. */
+ ZeroMemory(&si, sizeof(si));
+ si.StartupInfo.cb = sizeof(si.StartupInfo);
+
+ /* Decide whether a child window should be shown. */
+ si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
+ si.StartupInfo.wShowWindow =
+ (unsigned short)(cp->HideWindow ? SW_HIDE : SW_SHOWDEFAULT);
+
+ /* Connect the child's output pipes to the threads. */
+ si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ /* Setup the process's pipes. */
+ si.hStdInput = nextStdInput;
+ if (i == cp->NumberOfCommands - 1) {
+ /* The last child gets the overall stdout. */
+ nextStdInput = INVALID_HANDLE_VALUE;
+ si.hStdOutput = cp->PipeChildStd[1];
+ } else {
+ /* Create a pipe to sit between the children. */
+ HANDLE p[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
+ if (!CreatePipe(&p[0], &p[1], 0, 0)) {
+ DWORD error = GetLastError();
+ if (nextStdInput != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupHandle(&nextStdInput);
+ }
+ kwsysProcessCleanup(cp, error);
+ return;
+ }
+ nextStdInput = p[0];
+ si.hStdOutput = p[1];
}
- else
+ si.hStdError =
+ cp->MergeOutput ? cp->PipeChildStd[1] : cp->PipeChildStd[2];
+
{
- kwsysProcessCleanup(cp, 1);
-
- /* Release resources that may have been allocated for this
- process before an error occurred. */
- kwsysProcessCleanupHandle(&readEnd);
- kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdInput,
- STD_INPUT_HANDLE);
- kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdOutput,
- STD_OUTPUT_HANDLE);
- kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
- STD_ERROR_HANDLE);
- return;
+ DWORD error = kwsysProcessCreate(cp, i, &si);
+
+ /* Close our copies of pipes used between children. */
+ if (si.hStdInput != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupHandle(&si.hStdInput);
+ }
+ if (si.hStdOutput != cp->PipeChildStd[1]) {
+ kwsysProcessCleanupHandle(&si.hStdOutput);
+ }
+ if (si.hStdError != cp->PipeChildStd[2] && !cp->MergeOutput) {
+ kwsysProcessCleanupHandle(&si.hStdError);
+ }
+ if (!error) {
+ cp->ProcessEvents[i + 1] = cp->ProcessInformation[i].hProcess;
+ } else {
+ if (nextStdInput != cp->PipeChildStd[0]) {
+ kwsysProcessCleanupHandle(&nextStdInput);
+ }
+ kwsysProcessCleanup(cp, error);
+ return;
+ }
}
}
-
- /* Save a handle to the output pipe for the last process. */
- cp->Pipe[KWSYSPE_PIPE_STDOUT].Read = readEnd;
}
- /* Close the inherited handles to the stderr pipe shared by all
- processes in the pipeline. The stdout and stdin pipes are not
- shared among all children and are therefore closed by
- kwsysProcessCreate after each child is created. */
- kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE);
+ /* The parent process does not need the child's pipe ends. */
+ for (i = 0; i < 3; ++i) {
+ kwsysProcessCleanupHandle(&cp->PipeChildStd[i]);
+ }
/* Restore the working directory. */
- if(cp->RealWorkingDirectory)
- {
- SetCurrentDirectory(cp->RealWorkingDirectory);
+ if (cp->RealWorkingDirectory) {
+ SetCurrentDirectoryW(cp->RealWorkingDirectory);
free(cp->RealWorkingDirectory);
cp->RealWorkingDirectory = 0;
- }
+ }
/* The timeout period starts now. */
cp->StartTime = kwsysProcessTimeGetCurrent();
@@ -1014,24 +1151,21 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* All processes in the pipeline have been started in suspended
mode. Resume them all now. */
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
ResumeThread(cp->ProcessInformation[i].hThread);
- }
+ }
/* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
/* Tell the pipe threads that a process has started. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0);
ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0);
- }
+ }
/* We don't care about the children's main threads. */
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
- }
+ }
/* No pipe has reported data. */
cp->CurrentIndex = KWSYSPE_PIPE_COUNT;
@@ -1042,27 +1176,24 @@ void kwsysProcess_Execute(kwsysProcess* cp)
cp->Detached = cp->OptionDetach;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcess_Disown(kwsysProcess* cp)
{
int i;
/* Make sure we are executing a detached process. */
- if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing ||
- cp->TimeoutExpired || cp->Killed || cp->Terminated)
- {
+ if (!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing ||
+ cp->TimeoutExpired || cp->Killed || cp->Terminated) {
return;
- }
+ }
/* Disable the reading threads. */
kwsysProcessDisablePipeThreads(cp);
/* Wait for all pipe threads to reset. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE);
WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE);
- }
+ }
/* We will not wait for exit, so cleanup now. */
kwsysProcessCleanup(cp, 0);
@@ -1071,8 +1202,6 @@ void kwsysProcess_Disown(kwsysProcess* cp)
cp->State = kwsysProcess_State_Disowned;
}
-/*--------------------------------------------------------------------------*/
-
int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
double* userTimeout)
{
@@ -1087,11 +1216,10 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
DWORD w;
/* Make sure we are executing a process. */
- if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed ||
- cp->TimeoutExpired)
- {
+ if (!cp || cp->State != kwsysProcess_State_Executing || cp->Killed ||
+ cp->TimeoutExpired) {
return kwsysProcess_Pipe_None;
- }
+ }
/* Record the time at which user timeout period starts. */
userStartTime = kwsysProcessTimeGetCurrent();
@@ -1101,246 +1229,246 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime);
/* Loop until we have a reason to return. */
- while(!done && cp->PipesLeft > 0)
- {
+ while (!done && cp->PipesLeft > 0) {
/* If we previously got data from a thread, let it know we are
done with the data. */
- if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT)
- {
+ if (cp->CurrentIndex < KWSYSPE_PIPE_COUNT) {
KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex));
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0);
cp->CurrentIndex = KWSYSPE_PIPE_COUNT;
- }
+ }
/* Setup a timeout if required. */
- if(kwsysProcessGetTimeoutLeft(&timeoutTime, user?userTimeout:0,
- &timeoutLength))
- {
+ if (kwsysProcessGetTimeoutLeft(&timeoutTime, user ? userTimeout : 0,
+ &timeoutLength)) {
/* Timeout has already expired. */
expired = 1;
break;
- }
- if(timeoutTime.QuadPart < 0)
- {
+ }
+ if (timeoutTime.QuadPart < 0) {
timeout = INFINITE;
- }
- else
- {
+ } else {
timeout = kwsysProcessTimeToDWORD(timeoutLength);
- }
+ }
/* Wait for a pipe's thread to signal or a process to terminate. */
- w = WaitForMultipleObjects(cp->ProcessEventsLength, cp->ProcessEvents,
- 0, timeout);
- if(w == WAIT_TIMEOUT)
- {
+ w = WaitForMultipleObjects(cp->ProcessEventsLength, cp->ProcessEvents, 0,
+ timeout);
+ if (w == WAIT_TIMEOUT) {
/* Timeout has expired. */
expired = 1;
done = 1;
- }
- else if(w == WAIT_OBJECT_0)
- {
+ } else if (w == WAIT_OBJECT_0) {
/* Save the index of the reporting thread and release the mutex.
The thread will block until we signal its Empty mutex. */
cp->CurrentIndex = cp->SharedIndex;
ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
/* Data are available or a pipe closed. */
- if(cp->Pipe[cp->CurrentIndex].Closed)
- {
+ if (cp->Pipe[cp->CurrentIndex].Closed) {
/* The pipe closed at the write end. Close the read end and
inform the wakeup thread it is done with this process. */
kwsysProcessCleanupHandle(&cp->Pipe[cp->CurrentIndex].Read);
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Waker.Go, 1, 0);
KWSYSPE_DEBUG((stderr, "wakeup %d\n", cp->CurrentIndex));
--cp->PipesLeft;
- }
- else if(data && length)
- {
+ } else if (data && length) {
/* Report this data. */
*data = cp->Pipe[cp->CurrentIndex].DataBuffer;
*length = cp->Pipe[cp->CurrentIndex].DataLength;
- switch(cp->CurrentIndex)
- {
+ switch (cp->CurrentIndex) {
case KWSYSPE_PIPE_STDOUT:
- pipeId = kwsysProcess_Pipe_STDOUT; break;
+ pipeId = kwsysProcess_Pipe_STDOUT;
+ break;
case KWSYSPE_PIPE_STDERR:
- pipeId = kwsysProcess_Pipe_STDERR; break;
- }
- done = 1;
+ pipeId = kwsysProcess_Pipe_STDERR;
+ break;
}
+ done = 1;
}
- else
- {
+ } else {
/* A process has terminated. */
- kwsysProcessDestroy(cp, w-WAIT_OBJECT_0);
- }
+ kwsysProcessDestroy(cp, w - WAIT_OBJECT_0);
}
+ }
/* Update the user timeout. */
- if(userTimeout)
- {
+ if (userTimeout) {
kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
- kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
- userStartTime);
+ kwsysProcessTime difference =
+ kwsysProcessTimeSubtract(userEndTime, userStartTime);
double d = kwsysProcessTimeToDouble(difference);
*userTimeout -= d;
- if(*userTimeout < 0)
- {
+ if (*userTimeout < 0) {
*userTimeout = 0;
- }
}
+ }
/* Check what happened. */
- if(pipeId)
- {
+ if (pipeId) {
/* Data are ready on a pipe. */
return pipeId;
- }
- else if(expired)
- {
+ } else if (expired) {
/* A timeout has expired. */
- if(user)
- {
+ if (user) {
/* The user timeout has expired. It has no time left. */
return kwsysProcess_Pipe_Timeout;
- }
- else
- {
+ } else {
/* The process timeout has expired. Kill the child now. */
KWSYSPE_DEBUG((stderr, "killing child because timeout expired\n"));
kwsysProcess_Kill(cp);
cp->TimeoutExpired = 1;
cp->Killed = 0;
return kwsysProcess_Pipe_None;
- }
}
- else
- {
+ } else {
/* The children have terminated and no more data are available. */
return kwsysProcess_Pipe_None;
- }
+ }
}
-/*--------------------------------------------------------------------------*/
int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
{
int i;
int pipe;
/* Make sure we are executing a process. */
- if(!cp || cp->State != kwsysProcess_State_Executing)
- {
+ if (!cp || cp->State != kwsysProcess_State_Executing) {
return 1;
- }
+ }
/* Wait for the process to terminate. Ignore all data. */
- while((pipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0)
- {
- if(pipe == kwsysProcess_Pipe_Timeout)
- {
+ while ((pipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) {
+ if (pipe == kwsysProcess_Pipe_Timeout) {
/* The user timeout has expired. */
return 0;
- }
}
+ }
KWSYSPE_DEBUG((stderr, "no more data\n"));
/* When the last pipe closes in WaitForData, the loop terminates
without releasing the pipe's thread. Release it now. */
- if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT)
- {
+ if (cp->CurrentIndex < KWSYSPE_PIPE_COUNT) {
KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex));
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0);
cp->CurrentIndex = KWSYSPE_PIPE_COUNT;
- }
+ }
/* Wait for all pipe threads to reset. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
KWSYSPE_DEBUG((stderr, "waiting reader reset %d\n", i));
WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE);
KWSYSPE_DEBUG((stderr, "waiting waker reset %d\n", i));
WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE);
- }
+ }
/* ---- It is now safe again to call kwsysProcessCleanup. ----- */
/* Close all the pipes. */
kwsysProcessCleanup(cp, 0);
/* Determine the outcome. */
- if(cp->Killed)
- {
+ if (cp->Killed) {
/* We killed the child. */
cp->State = kwsysProcess_State_Killed;
- }
- else if(cp->TimeoutExpired)
- {
+ } else if (cp->TimeoutExpired) {
/* The timeout expired. */
cp->State = kwsysProcess_State_Expired;
- }
- else
- {
- /* The children exited. Report the outcome of the last process. */
- cp->ExitCode = cp->CommandExitCodes[cp->NumberOfCommands-1];
- if((cp->ExitCode & 0xF0000000) == 0xC0000000)
- {
- /* Child terminated due to exceptional behavior. */
- cp->State = kwsysProcess_State_Exception;
- cp->ExitValue = 1;
- kwsysProcessSetExitException(cp, cp->ExitCode);
- }
- else
- {
- /* Child exited without exception. */
- cp->State = kwsysProcess_State_Exited;
- cp->ExitException = kwsysProcess_Exception_None;
- cp->ExitValue = cp->ExitCode;
- }
- }
+ } else {
+ /* The children exited. Report the outcome of the child processes. */
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ cp->ProcessResults[i].ExitCode = cp->CommandExitCodes[i];
+ if ((cp->ProcessResults[i].ExitCode & 0xF0000000) == 0xC0000000) {
+ /* Child terminated due to exceptional behavior. */
+ cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exception;
+ cp->ProcessResults[i].ExitValue = 1;
+ kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode,
+ i);
+ } else {
+ /* Child exited without exception. */
+ cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exited;
+ cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+ cp->ProcessResults[i].ExitValue = cp->ProcessResults[i].ExitCode;
+ }
+ }
+ /* support legacy state status value */
+ cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
+void kwsysProcess_Interrupt(kwsysProcess* cp)
+{
+ int i;
+ /* Make sure we are executing a process. */
+ if (!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
+ cp->Killed) {
+ KWSYSPE_DEBUG((stderr, "interrupt: child not executing\n"));
+ return;
+ }
+
+ /* Skip actually interrupting the child if it has already terminated. */
+ if (cp->Terminated) {
+ KWSYSPE_DEBUG((stderr, "interrupt: child already terminated\n"));
+ return;
+ }
+
+ /* Interrupt the children. */
+ if (cp->CreateProcessGroup) {
+ if (cp->ProcessInformation) {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ /* Make sure the process handle isn't closed (e.g. from disowning). */
+ if (cp->ProcessInformation[i].hProcess) {
+ /* The user created a process group for this process. The group ID
+ is the process ID for the original process in the group. Note
+ that we have to use Ctrl+Break: Ctrl+C is not allowed for process
+ groups. */
+ GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,
+ cp->ProcessInformation[i].dwProcessId);
+ }
+ }
+ }
+ } else {
+ /* No process group was created. Kill our own process group... */
+ GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
+ }
+}
+
void kwsysProcess_Kill(kwsysProcess* cp)
{
int i;
/* Make sure we are executing a process. */
- if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
- cp->Killed)
- {
+ if (!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
+ cp->Killed) {
KWSYSPE_DEBUG((stderr, "kill: child not executing\n"));
return;
- }
+ }
/* Disable the reading threads. */
KWSYSPE_DEBUG((stderr, "kill: disabling pipe threads\n"));
kwsysProcessDisablePipeThreads(cp);
/* Skip actually killing the child if it has already terminated. */
- if(cp->Terminated)
- {
+ if (cp->Terminated) {
KWSYSPE_DEBUG((stderr, "kill: child already terminated\n"));
return;
- }
+ }
/* Kill the children. */
cp->Killed = 1;
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
- // close the handle if we kill it
+ /* Remove from global list of processes and close handles. */
+ kwsysProcessesRemove(cp->ProcessInformation[i].hProcess);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
- }
+ }
/* We are killing the children and ignoring all data. Do not wait
for them to exit. */
}
-/*--------------------------------------------------------------------------*/
-
/*
Function executed for each pipe's thread. Argument is a pointer to
the kwsysProcessPipeData instance for this thread.
@@ -1351,19 +1479,16 @@ DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd)
kwsysProcess* cp = td->Process;
/* Wait for a process to be ready. */
- while((WaitForSingleObject(td->Reader.Ready, INFINITE), !cp->Deleting))
- {
+ while ((WaitForSingleObject(td->Reader.Ready, INFINITE), !cp->Deleting)) {
/* Read output from the process for this thread's pipe. */
kwsysProcessPipeThreadReadPipe(cp, td);
/* Signal the main thread we have reset for a new process. */
ReleaseSemaphore(td->Reader.Reset, 1, 0);
- }
+ }
return 0;
}
-/*--------------------------------------------------------------------------*/
-
/*
Function called in each pipe's thread to handle data for one
execution of a subprocess.
@@ -1371,24 +1496,21 @@ DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd)
void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
{
/* Wait for space in the thread's buffer. */
- while((KWSYSPE_DEBUG((stderr, "wait for read %d\n", td->Index)),
- WaitForSingleObject(td->Reader.Go, INFINITE), !td->Closed))
- {
+ while ((KWSYSPE_DEBUG((stderr, "wait for read %d\n", td->Index)),
+ WaitForSingleObject(td->Reader.Go, INFINITE), !td->Closed)) {
KWSYSPE_DEBUG((stderr, "reading %d\n", td->Index));
/* Read data from the pipe. This may block until data are available. */
- if(!ReadFile(td->Read, td->DataBuffer, KWSYSPE_PIPE_BUFFER_SIZE,
- &td->DataLength, 0))
- {
- if(GetLastError() != ERROR_BROKEN_PIPE)
- {
+ if (!ReadFile(td->Read, td->DataBuffer, KWSYSPE_PIPE_BUFFER_SIZE,
+ &td->DataLength, 0)) {
+ if (GetLastError() != ERROR_BROKEN_PIPE) {
/* UNEXPECTED failure to read the pipe. */
- }
+ }
/* The pipe closed. There are no more data to read. */
td->Closed = 1;
KWSYSPE_DEBUG((stderr, "read closed %d\n", td->Index));
- }
+ }
KWSYSPE_DEBUG((stderr, "read %d\n", td->Index));
@@ -1400,7 +1522,7 @@ void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
/* Tell the main thread we have something to report. */
cp->SharedIndex = td->Index;
ReleaseSemaphore(cp->Full, 1, 0);
- }
+ }
/* We were signalled to exit with our buffer empty. Reset the
mutex for a new process. */
@@ -1408,8 +1530,6 @@ void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
ReleaseSemaphore(td->Reader.Go, 1, 0);
}
-/*--------------------------------------------------------------------------*/
-
/*
Function executed for each pipe's thread. Argument is a pointer to
the kwsysProcessPipeData instance for this thread.
@@ -1420,19 +1540,16 @@ DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd)
kwsysProcess* cp = td->Process;
/* Wait for a process to be ready. */
- while((WaitForSingleObject(td->Waker.Ready, INFINITE), !cp->Deleting))
- {
+ while ((WaitForSingleObject(td->Waker.Ready, INFINITE), !cp->Deleting)) {
/* Wait for a possible wakeup. */
kwsysProcessPipeThreadWakePipe(cp, td);
/* Signal the main thread we have reset for a new process. */
ReleaseSemaphore(td->Waker.Reset, 1, 0);
- }
+ }
return 0;
}
-/*--------------------------------------------------------------------------*/
-
/*
Function called in each pipe's thread to handle reading thread
wakeup for one execution of a subprocess.
@@ -1447,270 +1564,223 @@ void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td)
KWSYSPE_DEBUG((stderr, "waking %d\n", td->Index));
/* If the pipe is not closed, we need to wake up the reading thread. */
- if(!td->Closed)
- {
+ if (!td->Closed) {
DWORD dummy;
KWSYSPE_DEBUG((stderr, "waker %d writing byte\n", td->Index));
WriteFile(td->Write, "", 1, &dummy, 0);
KWSYSPE_DEBUG((stderr, "waker %d wrote byte\n", td->Index));
- }
+ }
}
-/*--------------------------------------------------------------------------*/
/* Initialize a process control structure for kwsysProcess_Execute. */
int kwsysProcessInitialize(kwsysProcess* cp)
{
+ int i;
/* Reset internal status flags. */
cp->TimeoutExpired = 0;
cp->Terminated = 0;
cp->Killed = 0;
- cp->ExitException = kwsysProcess_Exception_None;
- cp->ExitCode = 1;
- cp->ExitValue = 1;
- /* Reset error data. */
- cp->ErrorMessage[0] = 0;
- strcpy(cp->ExitExceptionString, "No exception");
+ free(cp->ProcessResults);
+ /* Allocate process result information for each process. */
+ cp->ProcessResults = (kwsysProcessResults*)malloc(
+ sizeof(kwsysProcessResults) * (cp->NumberOfCommands));
+ if (!cp->ProcessResults) {
+ return 0;
+ }
+ ZeroMemory(cp->ProcessResults,
+ sizeof(kwsysProcessResults) * cp->NumberOfCommands);
+ for (i = 0; i < cp->NumberOfCommands; i++) {
+ cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+ cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting;
+ cp->ProcessResults[i].ExitCode = 1;
+ cp->ProcessResults[i].ExitValue = 1;
+ strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception");
+ }
/* Allocate process information for each process. */
- cp->ProcessInformation =
- (PROCESS_INFORMATION*)malloc(sizeof(PROCESS_INFORMATION) *
- cp->NumberOfCommands);
- if(!cp->ProcessInformation)
- {
+ free(cp->ProcessInformation);
+ cp->ProcessInformation = (PROCESS_INFORMATION*)malloc(
+ sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands);
+ if (!cp->ProcessInformation) {
return 0;
- }
+ }
ZeroMemory(cp->ProcessInformation,
sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands);
- if(cp->CommandExitCodes)
- {
+ if (cp->CommandExitCodes) {
free(cp->CommandExitCodes);
- }
- cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD)*cp->NumberOfCommands);
- if(!cp->CommandExitCodes)
- {
+ }
+ cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD) * cp->NumberOfCommands);
+ if (!cp->CommandExitCodes) {
return 0;
- }
- ZeroMemory(cp->CommandExitCodes, sizeof(DWORD)*cp->NumberOfCommands);
+ }
+ ZeroMemory(cp->CommandExitCodes, sizeof(DWORD) * cp->NumberOfCommands);
/* Allocate event wait array. The first event is cp->Full, the rest
are the process termination events. */
- cp->ProcessEvents = (PHANDLE)malloc(sizeof(HANDLE)*(cp->NumberOfCommands+1));
- if(!cp->ProcessEvents)
- {
+ cp->ProcessEvents =
+ (PHANDLE)malloc(sizeof(HANDLE) * (cp->NumberOfCommands + 1));
+ if (!cp->ProcessEvents) {
return 0;
- }
- ZeroMemory(cp->ProcessEvents, sizeof(HANDLE) * (cp->NumberOfCommands+1));
+ }
+ ZeroMemory(cp->ProcessEvents, sizeof(HANDLE) * (cp->NumberOfCommands + 1));
cp->ProcessEvents[0] = cp->Full;
- cp->ProcessEventsLength = cp->NumberOfCommands+1;
+ cp->ProcessEventsLength = cp->NumberOfCommands + 1;
/* Allocate space to save the real working directory of this process. */
- if(cp->WorkingDirectory)
- {
- cp->RealWorkingDirectoryLength = GetCurrentDirectory(0, 0);
- if(cp->RealWorkingDirectoryLength > 0)
- {
- cp->RealWorkingDirectory = (char*)malloc(cp->RealWorkingDirectoryLength);
- if(!cp->RealWorkingDirectory)
- {
+ if (cp->WorkingDirectory) {
+ cp->RealWorkingDirectoryLength = GetCurrentDirectoryW(0, 0);
+ if (cp->RealWorkingDirectoryLength > 0) {
+ cp->RealWorkingDirectory =
+ malloc(cp->RealWorkingDirectoryLength * sizeof(wchar_t));
+ if (!cp->RealWorkingDirectory) {
return 0;
- }
}
}
+ }
+ {
+ for (i = 0; i < 3; ++i) {
+ cp->PipeChildStd[i] = INVALID_HANDLE_VALUE;
+ }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
-int kwsysProcessCreate(kwsysProcess* cp, int index,
- kwsysProcessCreateInformation* si,
- PHANDLE readEnd)
-{
- /* Setup the process's stdin. */
- if(*readEnd)
- {
- /* Create an inherited duplicate of the read end from the output
- pipe of the previous process. This also closes the
- non-inherited version. */
- if(!DuplicateHandle(GetCurrentProcess(), *readEnd,
- GetCurrentProcess(), readEnd,
- 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
- DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
- si->StartupInfo.hStdInput = *readEnd;
-
- /* This function is done with this handle. */
- *readEnd = 0;
- }
- else if(cp->PipeFileSTDIN)
- {
- /* Create a handle to read a file for stdin. */
- HANDLE fin = CreateFile(cp->PipeFileSTDIN, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- 0, OPEN_EXISTING, 0, 0);
- if(fin == INVALID_HANDLE_VALUE)
- {
- return 0;
- }
- /* Create an inherited duplicate of the handle. This also closes
- the non-inherited version. */
- if(!DuplicateHandle(GetCurrentProcess(), fin,
- GetCurrentProcess(), &fin,
- 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
- DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
- si->StartupInfo.hStdInput = fin;
- }
- else if(cp->PipeSharedSTDIN)
- {
- /* Share this process's stdin with the child. */
- if(!kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE,
- &si->StartupInfo.hStdInput))
- {
- return 0;
- }
- }
- else if(cp->PipeNativeSTDIN[0])
- {
- /* Use the provided native pipe. */
- if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdInput,
- cp->PipeNativeSTDIN, 0))
- {
- return 0;
- }
- }
- else
- {
- /* Explicitly give the child no stdin. */
- si->StartupInfo.hStdInput = INVALID_HANDLE_VALUE;
- }
-
- /* Setup the process's stdout. */
- {
- DWORD maybeClose = DUPLICATE_CLOSE_SOURCE;
- HANDLE writeEnd;
-
- /* Create the output pipe for this process. Neither end is directly
- inherited. */
- if(!CreatePipe(readEnd, &writeEnd, 0, 0))
- {
- return 0;
- }
+static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
+{
+ DWORD flags;
- /* Create an inherited duplicate of the write end. Close the
- non-inherited version unless this is the last process. Save the
- non-inherited write end of the last process. */
- if(index == cp->NumberOfCommands-1)
- {
- cp->Pipe[KWSYSPE_PIPE_STDOUT].Write = writeEnd;
- maybeClose = 0;
- }
- if(!DuplicateHandle(GetCurrentProcess(), writeEnd,
- GetCurrentProcess(), &writeEnd,
- 0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
- si->StartupInfo.hStdOutput = writeEnd;
+ /* Check whether the handle is valid for this process. */
+ if (in != INVALID_HANDLE_VALUE && GetHandleInformation(in, &flags)) {
+ /* Use the handle as-is if it is already inherited. */
+ if (flags & HANDLE_FLAG_INHERIT) {
+ *out = in;
+ return ERROR_SUCCESS;
+ }
+
+ /* Create an inherited copy of this handle. */
+ if (DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), out, 0,
+ TRUE, DUPLICATE_SAME_ACCESS)) {
+ return ERROR_SUCCESS;
+ } else {
+ return GetLastError();
+ }
+ } else {
+ /* The given handle is not valid for this process. Some child
+ processes may break if they do not have a valid standard handle,
+ so open NUL to give to the child. */
+ SECURITY_ATTRIBUTES sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.nLength = (DWORD)sizeof(sa);
+ sa.bInheritHandle = 1;
+ *out = CreateFileW(
+ L"NUL",
+ (isStdIn ? GENERIC_READ : (GENERIC_WRITE | FILE_READ_ATTRIBUTES)),
+ FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, 0);
+ return (*out != INVALID_HANDLE_VALUE) ? ERROR_SUCCESS : GetLastError();
}
+}
- /* Replace the stdout pipe with a file if requested. In this case
- the pipe thread will still run but never report data. */
- if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT)
- {
- if(!kwsysProcessSetupOutputPipeFile(&si->StartupInfo.hStdOutput,
- cp->PipeFileSTDOUT))
- {
- return 0;
- }
- }
-
- /* Replace the stdout pipe of the last child with the parent
- process's if requested. In this case the pipe thread will still
- run but never report data. */
- if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT)
- {
- if(!kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE,
- &si->StartupInfo.hStdOutput))
- {
- return 0;
- }
- }
+DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
+ kwsysProcessCreateInformation* si)
+{
+ DWORD creationFlags;
+ DWORD error = ERROR_SUCCESS;
- /* Replace the stdout pipe with the native pipe provided if any. In
- this case the pipe thread will still run but never report
- data. */
- if(index == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1])
- {
- if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdOutput,
- cp->PipeNativeSTDOUT, 1))
- {
- return 0;
- }
- }
+ /* Check if we are currently exiting. */
+ if (!kwsysTryEnterCreateProcessSection()) {
+ /* The Ctrl handler is currently working on exiting our process. Rather
+ than return an error code, which could cause incorrect conclusions to be
+ reached by the caller, we simply hang. (For example, a CMake try_run
+ configure step might cause the project to configure wrong.) */
+ Sleep(INFINITE);
+ }
/* Create the child in a suspended state so we can wait until all
children have been created before running any one. */
- if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
- 0, &si->StartupInfo, &cp->ProcessInformation[index]))
- {
- return 0;
- }
+ creationFlags = CREATE_SUSPENDED;
+ if (cp->CreateProcessGroup) {
+ creationFlags |= CREATE_NEW_PROCESS_GROUP;
+ }
+
+ /* Create inherited copies of the handles. */
+ (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput,
+ si->hStdInput, 1)) ||
+ (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput,
+ si->hStdOutput, 0)) ||
+ (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError,
+ si->hStdError, 0)) ||
+ /* Create the process. */
+ (!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, creationFlags, 0, 0,
+ &si->StartupInfo, &cp->ProcessInformation[index]) &&
+ (error = GetLastError()));
+
+ /* Close the inherited copies of the handles. */
+ if (si->StartupInfo.hStdInput != si->hStdInput) {
+ kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput);
+ }
+ if (si->StartupInfo.hStdOutput != si->hStdOutput) {
+ kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
+ }
+ if (si->StartupInfo.hStdError != si->hStdError) {
+ kwsysProcessCleanupHandle(&si->StartupInfo.hStdError);
+ }
- /* Successfully created this child process. Close the current
- process's copies of the inherited stdout and stdin handles. The
- stderr handle is shared among all children and is closed by
- kwsysProcess_Execute after all children have been created. */
- kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdInput,
- STD_INPUT_HANDLE);
- kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdOutput,
- STD_OUTPUT_HANDLE);
+ /* Add the process to the global list of processes. */
+ if (!error &&
+ !kwsysProcessesAdd(cp->ProcessInformation[index].hProcess,
+ cp->ProcessInformation[index].dwProcessId,
+ cp->CreateProcessGroup)) {
+ /* This failed for some reason. Kill the suspended process. */
+ TerminateProcess(cp->ProcessInformation[index].hProcess, 1);
+ /* And clean up... */
+ kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
+ kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread);
+ strcpy(cp->ErrorMessage, "kwsysProcessesAdd function failed");
+ error = ERROR_NOT_ENOUGH_MEMORY; /* Most likely reason. */
+ }
- return 1;
+ /* If the console Ctrl handler is waiting for us, this will release it... */
+ kwsysLeaveCreateProcessSection();
+ return error;
}
-/*--------------------------------------------------------------------------*/
void kwsysProcessDestroy(kwsysProcess* cp, int event)
{
int i;
int index;
/* Find the process index for the termination event. */
- for(index=0; index < cp->NumberOfCommands; ++index)
- {
- if(cp->ProcessInformation[index].hProcess == cp->ProcessEvents[event])
- {
+ for (index = 0; index < cp->NumberOfCommands; ++index) {
+ if (cp->ProcessInformation[index].hProcess == cp->ProcessEvents[event]) {
break;
- }
}
+ }
/* Check the exit code of the process. */
GetExitCodeProcess(cp->ProcessInformation[index].hProcess,
&cp->CommandExitCodes[index]);
+ /* Remove from global list of processes. */
+ kwsysProcessesRemove(cp->ProcessInformation[index].hProcess);
+
/* Close the process handle for the terminated process. */
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
/* Remove the process from the available events. */
cp->ProcessEventsLength -= 1;
- for(i=event; i < cp->ProcessEventsLength; ++i)
- {
- cp->ProcessEvents[i] = cp->ProcessEvents[i+1];
- }
+ for (i = event; i < cp->ProcessEventsLength; ++i) {
+ cp->ProcessEvents[i] = cp->ProcessEvents[i + 1];
+ }
/* Check if all processes have terminated. */
- if(cp->ProcessEventsLength == 1)
- {
+ if (cp->ProcessEventsLength == 1) {
cp->Terminated = 1;
/* Close our copies of the pipe write handles so the pipe threads
can detect end-of-data. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
/* TODO: If the child created its own child (our grandchild)
which inherited a copy of the pipe write-end then the pipe
may not close and we will still need the waker write pipe.
@@ -1721,181 +1791,95 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
read on posix. */
KWSYSPE_DEBUG((stderr, "closing wakeup write %d\n", i));
kwsysProcessCleanupHandle(&cp->Pipe[i].Write);
- }
}
+ }
}
-/*--------------------------------------------------------------------------*/
-int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
+DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
{
HANDLE fout;
- if(!name)
- {
- return 1;
- }
+ wchar_t* wname;
+ DWORD error;
+ if (!name) {
+ return ERROR_INVALID_PARAMETER;
+ }
- /* Close the existing inherited handle. */
+ /* Close the existing handle. */
kwsysProcessCleanupHandle(phandle);
/* Create a handle to write a file for the pipe. */
- fout = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, 0,
- CREATE_ALWAYS, 0, 0);
- if(fout == INVALID_HANDLE_VALUE)
- {
- return 0;
- }
-
- /* Create an inherited duplicate of the handle. This also closes
- the non-inherited version. */
- if(!DuplicateHandle(GetCurrentProcess(), fout,
- GetCurrentProcess(), &fout,
- 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
- DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
+ wname = kwsysEncoding_DupToWide(name);
+ fout =
+ CreateFileW(wname, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
+ error = GetLastError();
+ free(wname);
+ if (fout == INVALID_HANDLE_VALUE) {
+ return error;
+ }
/* Assign the replacement handle. */
*phandle = fout;
- return 1;
+ return ERROR_SUCCESS;
}
-/*--------------------------------------------------------------------------*/
-int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle)
+void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle)
{
- /* Check whether the handle to be shared is already inherited. */
- DWORD flags;
- int inherited = 0;
- if(GetHandleInformation(GetStdHandle(nStdHandle), &flags) &&
- (flags & HANDLE_FLAG_INHERIT))
- {
- inherited = 1;
- }
-
- /* Cleanup the previous handle. */
+ /* Close the existing handle. */
kwsysProcessCleanupHandle(handle);
-
- /* If the standard handle is not inherited then duplicate it to
- create an inherited copy. Do not close the original handle when
- duplicating! */
- if(inherited)
- {
- *handle = GetStdHandle(nStdHandle);
- return 1;
- }
- else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle),
- GetCurrentProcess(), handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- return 1;
- }
- else
- {
- /* The given standard handle is not valid for this process. Some
- child processes may break if they do not have a valid standard
- pipe, so give the child an empty pipe. For the stdin pipe we
- want to close the write end and give the read end to the child.
- For stdout and stderr we want to close the read end and give
- the write end to the child. */
- int child_end = (nStdHandle == STD_INPUT_HANDLE)? 0:1;
- int parent_end = (nStdHandle == STD_INPUT_HANDLE)? 1:0;
- HANDLE emptyPipe[2];
- if(!CreatePipe(&emptyPipe[0], &emptyPipe[1], 0, 0))
- {
- return 0;
- }
-
- /* Close the non-inherited end so the pipe will be broken
- immediately. */
- CloseHandle(emptyPipe[parent_end]);
-
- /* Create an inherited duplicate of the handle. This also
- closes the non-inherited version. */
- if(!DuplicateHandle(GetCurrentProcess(), emptyPipe[child_end],
- GetCurrentProcess(), &emptyPipe[child_end],
- 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
- DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
-
- /* Give the inherited handle to the child. */
- *handle = emptyPipe[child_end];
- return 1;
- }
+ /* Store the new standard handle. */
+ *handle = GetStdHandle(nStdHandle);
}
-/*--------------------------------------------------------------------------*/
-int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], int isWrite)
+void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle)
{
- /* Close the existing inherited handle. */
+ /* Close the existing handle. */
kwsysProcessCleanupHandle(handle);
-
- /* Create an inherited duplicate of the handle. This also closes
- the non-inherited version. */
- if(!DuplicateHandle(GetCurrentProcess(), p[isWrite? 1:0],
- GetCurrentProcess(), handle,
- 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
- DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
-
- return 1;
+ /* Store the new given handle. */
+ *handle = native;
}
-/*--------------------------------------------------------------------------*/
-
/* Close the given handle if it is open. Reset its value to 0. */
void kwsysProcessCleanupHandle(PHANDLE h)
{
- if(h && *h)
- {
+ if (h && *h && *h != INVALID_HANDLE_VALUE &&
+ *h != GetStdHandle(STD_INPUT_HANDLE) &&
+ *h != GetStdHandle(STD_OUTPUT_HANDLE) &&
+ *h != GetStdHandle(STD_ERROR_HANDLE)) {
CloseHandle(*h);
- *h = 0;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-/* Close the given handle if it is open and not a standard handle.
- Reset its value to 0. */
-void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle)
-{
- if(h && *h && (*h != GetStdHandle(nStdHandle)))
- {
- CloseHandle(*h);
- *h = 0;
- }
+ *h = INVALID_HANDLE_VALUE;
+ }
}
-/*--------------------------------------------------------------------------*/
-
/* Close all handles created by kwsysProcess_Execute. */
-void kwsysProcessCleanup(kwsysProcess* cp, int error)
+void kwsysProcessCleanup(kwsysProcess* cp, DWORD error)
{
int i;
/* If this is an error case, report the error. */
- if(error)
- {
+ if (error) {
/* Construct an error message if one has not been provided already. */
- if(cp->ErrorMessage[0] == 0)
- {
+ if (cp->ErrorMessage[0] == 0) {
/* Format the error message. */
- DWORD original = GetLastError();
- DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, 0);
- if(length < 1)
- {
+ wchar_t err_msg[KWSYSPE_PIPE_BUFFER_SIZE];
+ DWORD length = FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_msg,
+ KWSYSPE_PIPE_BUFFER_SIZE, 0);
+ if (length < 1) {
/* FormatMessage failed. Use a default message. */
_snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
"Process execution failed with error 0x%X. "
"FormatMessage failed with error 0x%X",
- original, GetLastError());
- }
+ error, GetLastError());
+ }
+ if (!WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage,
+ KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL)) {
+ /* WideCharToMultiByte failed. Use a default message. */
+ _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
+ "Process execution failed with error 0x%X. "
+ "WideCharToMultiByte failed with error 0x%X",
+ error, GetLastError());
}
+ }
/* Remove trailing period and newline, if any. */
kwsysProcessCleanErrorMessage(cp);
@@ -1904,138 +1888,69 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
cp->State = kwsysProcess_State_Error;
/* Cleanup any processes already started in a suspended state. */
- if(cp->ProcessInformation)
- {
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- if(cp->ProcessInformation[i].hProcess)
- {
+ if (cp->ProcessInformation) {
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ if (cp->ProcessInformation[i].hProcess) {
TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
- }
}
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
+ }
+ for (i = 0; i < cp->NumberOfCommands; ++i) {
+ /* Remove from global list of processes and close handles. */
+ kwsysProcessesRemove(cp->ProcessInformation[i].hProcess);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
- }
}
+ }
/* Restore the working directory. */
- if(cp->RealWorkingDirectory)
- {
- SetCurrentDirectory(cp->RealWorkingDirectory);
- }
+ if (cp->RealWorkingDirectory) {
+ SetCurrentDirectoryW(cp->RealWorkingDirectory);
}
+ }
/* Free memory. */
- if(cp->ProcessInformation)
- {
+ if (cp->ProcessInformation) {
free(cp->ProcessInformation);
cp->ProcessInformation = 0;
- }
- if(cp->ProcessEvents)
- {
+ }
+ if (cp->ProcessEvents) {
free(cp->ProcessEvents);
cp->ProcessEvents = 0;
- }
- if(cp->RealWorkingDirectory)
- {
+ }
+ if (cp->RealWorkingDirectory) {
free(cp->RealWorkingDirectory);
cp->RealWorkingDirectory = 0;
- }
+ }
/* Close each pipe. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
kwsysProcessCleanupHandle(&cp->Pipe[i].Write);
kwsysProcessCleanupHandle(&cp->Pipe[i].Read);
cp->Pipe[i].Closed = 0;
- }
+ }
+ for (i = 0; i < 3; ++i) {
+ kwsysProcessCleanupHandle(&cp->PipeChildStd[i]);
+ }
}
-/*--------------------------------------------------------------------------*/
void kwsysProcessCleanErrorMessage(kwsysProcess* cp)
{
/* Remove trailing period and newline, if any. */
size_t length = strlen(cp->ErrorMessage);
- if(cp->ErrorMessage[length-1] == '\n')
- {
- cp->ErrorMessage[length-1] = 0;
+ if (cp->ErrorMessage[length - 1] == '\n') {
+ cp->ErrorMessage[length - 1] = 0;
--length;
- if(length > 0 && cp->ErrorMessage[length-1] == '\r')
- {
- cp->ErrorMessage[length-1] = 0;
+ if (length > 0 && cp->ErrorMessage[length - 1] == '\r') {
+ cp->ErrorMessage[length - 1] = 0;
--length;
- }
- }
- if(length > 0 && cp->ErrorMessage[length-1] == '.')
- {
- cp->ErrorMessage[length-1] = 0;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-int kwsysProcessComputeCommandLength(kwsysProcess* cp,
- char const* const* command)
-{
- int length = 0;
- if(cp->Verbatim)
- {
- /* Treat the first argument as a verbatim command line. Use its
- length directly and add space for the null-terminator. */
- length = (int)strlen(*command)+1;
- }
- else
- {
- /* Compute the length of the command line when it is converted to
- a single string. Space for the null-terminator is allocated by
- the whitespace character allocated for the first argument that
- will not be used. */
- char const* const* arg;
- for(arg = command; *arg; ++arg)
- {
- /* Add the length of this argument. It already includes room
- for a separating space or terminating null. */
- length += kwsysSystem_Shell_GetArgumentSizeForWindows(*arg, 0);
- }
- }
-
- return length;
-}
-
-/*--------------------------------------------------------------------------*/
-void kwsysProcessComputeCommandLine(kwsysProcess* cp,
- char const* const* command,
- char* cmd)
-{
- if(cp->Verbatim)
- {
- /* Copy the verbatim command line into the buffer. */
- strcpy(cmd, *command);
- }
- else
- {
- /* Construct the command line in the allocated buffer. */
- char const* const* arg;
- for(arg = command; *arg; ++arg)
- {
- /* Add the separating space if this is not the first argument. */
- if(arg != command)
- {
- *cmd++ = ' ';
- }
-
- /* Add the current argument. */
- cmd = kwsysSystem_Shell_GetArgumentForWindows(*arg, cmd, 0);
- }
-
- /* Add the terminating null character to the command line. */
- *cmd = 0;
}
+ }
+ if (length > 0 && cp->ErrorMessage[length - 1] == '.') {
+ cp->ErrorMessage[length - 1] = 0;
+ }
}
-/*--------------------------------------------------------------------------*/
/* Get the time at which either the process or user timeout will
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
@@ -2043,70 +1958,59 @@ int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
{
/* The first time this is called, we need to calculate the time at
which the child will timeout. */
- if(cp->Timeout && cp->TimeoutTime.QuadPart < 0)
- {
+ if (cp->Timeout && cp->TimeoutTime.QuadPart < 0) {
kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout);
cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length);
- }
+ }
/* Start with process timeout. */
*timeoutTime = cp->TimeoutTime;
/* Check if the user timeout is earlier. */
- if(userTimeout)
- {
+ if (userTimeout) {
kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
- kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout);
- kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime,
- userTimeoutLength);
- if(timeoutTime->QuadPart < 0 ||
- kwsysProcessTimeLess(userTimeoutTime, *timeoutTime))
- {
+ kwsysProcessTime userTimeoutLength =
+ kwsysProcessTimeFromDouble(*userTimeout);
+ kwsysProcessTime userTimeoutTime =
+ kwsysProcessTimeAdd(currentTime, userTimeoutLength);
+ if (timeoutTime->QuadPart < 0 ||
+ kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) {
*timeoutTime = userTimeoutTime;
return 1;
- }
}
+ }
return 0;
}
-/*--------------------------------------------------------------------------*/
/* Get the length of time before the given timeout time arrives.
Returns 1 if the time has already arrived, and 0 otherwise. */
int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
double* userTimeout,
kwsysProcessTime* timeoutLength)
{
- if(timeoutTime->QuadPart < 0)
- {
+ if (timeoutTime->QuadPart < 0) {
/* No timeout time has been requested. */
return 0;
- }
- else
- {
+ } else {
/* Calculate the remaining time. */
kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
*timeoutLength = kwsysProcessTimeSubtract(*timeoutTime, currentTime);
- if(timeoutLength->QuadPart < 0 && userTimeout && *userTimeout <= 0)
- {
+ if (timeoutLength->QuadPart < 0 && userTimeout && *userTimeout <= 0) {
/* Caller has explicitly requested a zero timeout. */
timeoutLength->QuadPart = 0;
- }
+ }
- if(timeoutLength->QuadPart < 0)
- {
+ if (timeoutLength->QuadPart < 0) {
/* Timeout has already expired. */
return 1;
- }
- else
- {
+ } else {
/* There is some time left. */
return 0;
- }
}
+ }
}
-/*--------------------------------------------------------------------------*/
kwsysProcessTime kwsysProcessTimeGetCurrent()
{
kwsysProcessTime current;
@@ -2117,114 +2021,132 @@ kwsysProcessTime kwsysProcessTimeGetCurrent()
return current;
}
-/*--------------------------------------------------------------------------*/
DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t)
{
return (DWORD)(t.QuadPart * 0.0001);
}
-/*--------------------------------------------------------------------------*/
double kwsysProcessTimeToDouble(kwsysProcessTime t)
{
return t.QuadPart * 0.0000001;
}
-/*--------------------------------------------------------------------------*/
kwsysProcessTime kwsysProcessTimeFromDouble(double d)
{
kwsysProcessTime t;
- t.QuadPart = (LONGLONG)(d*10000000);
+ t.QuadPart = (LONGLONG)(d * 10000000);
return t;
}
-/*--------------------------------------------------------------------------*/
int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
{
return in1.QuadPart < in2.QuadPart;
}
-/*--------------------------------------------------------------------------*/
-kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2)
+kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
+ kwsysProcessTime in2)
{
kwsysProcessTime out;
out.QuadPart = in1.QuadPart + in2.QuadPart;
return out;
}
-/*--------------------------------------------------------------------------*/
-kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2)
+kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
+ kwsysProcessTime in2)
{
kwsysProcessTime out;
out.QuadPart = in1.QuadPart - in2.QuadPart;
return out;
}
-/*--------------------------------------------------------------------------*/
-#define KWSYSPE_CASE(type, str) \
- cp->ExitException = kwsysProcess_Exception_##type; \
- strcpy(cp->ExitExceptionString, str)
-static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
+#define KWSYSPE_CASE(type, str) \
+ cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type; \
+ strcpy(cp->ProcessResults[idx].ExitExceptionString, str)
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
+ int idx)
{
- switch (code)
- {
+ switch (code) {
case STATUS_CONTROL_C_EXIT:
- KWSYSPE_CASE(Interrupt, "User interrupt"); break;
+ KWSYSPE_CASE(Interrupt, "User interrupt");
+ break;
case STATUS_FLOAT_DENORMAL_OPERAND:
- KWSYSPE_CASE(Numerical, "Floating-point exception (denormal operand)"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point exception (denormal operand)");
+ break;
case STATUS_FLOAT_DIVIDE_BY_ZERO:
- KWSYSPE_CASE(Numerical, "Divide-by-zero"); break;
+ KWSYSPE_CASE(Numerical, "Divide-by-zero");
+ break;
case STATUS_FLOAT_INEXACT_RESULT:
- KWSYSPE_CASE(Numerical, "Floating-point exception (inexact result)"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point exception (inexact result)");
+ break;
case STATUS_FLOAT_INVALID_OPERATION:
- KWSYSPE_CASE(Numerical, "Invalid floating-point operation"); break;
+ KWSYSPE_CASE(Numerical, "Invalid floating-point operation");
+ break;
case STATUS_FLOAT_OVERFLOW:
- KWSYSPE_CASE(Numerical, "Floating-point overflow"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point overflow");
+ break;
case STATUS_FLOAT_STACK_CHECK:
- KWSYSPE_CASE(Numerical, "Floating-point stack check failed"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point stack check failed");
+ break;
case STATUS_FLOAT_UNDERFLOW:
- KWSYSPE_CASE(Numerical, "Floating-point underflow"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point underflow");
+ break;
#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
case STATUS_FLOAT_MULTIPLE_FAULTS:
- KWSYSPE_CASE(Numerical, "Floating-point exception (multiple faults)"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point exception (multiple faults)");
+ break;
#endif
#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
case STATUS_FLOAT_MULTIPLE_TRAPS:
- KWSYSPE_CASE(Numerical, "Floating-point exception (multiple traps)"); break;
+ KWSYSPE_CASE(Numerical, "Floating-point exception (multiple traps)");
+ break;
#endif
case STATUS_INTEGER_DIVIDE_BY_ZERO:
- KWSYSPE_CASE(Numerical, "Integer divide-by-zero"); break;
+ KWSYSPE_CASE(Numerical, "Integer divide-by-zero");
+ break;
case STATUS_INTEGER_OVERFLOW:
- KWSYSPE_CASE(Numerical, "Integer overflow"); break;
+ KWSYSPE_CASE(Numerical, "Integer overflow");
+ break;
case STATUS_DATATYPE_MISALIGNMENT:
- KWSYSPE_CASE(Fault, "Datatype misalignment"); break;
+ KWSYSPE_CASE(Fault, "Datatype misalignment");
+ break;
case STATUS_ACCESS_VIOLATION:
- KWSYSPE_CASE(Fault, "Access violation"); break;
+ KWSYSPE_CASE(Fault, "Access violation");
+ break;
case STATUS_IN_PAGE_ERROR:
- KWSYSPE_CASE(Fault, "In-page error"); break;
+ KWSYSPE_CASE(Fault, "In-page error");
+ break;
case STATUS_INVALID_HANDLE:
- KWSYSPE_CASE(Fault, "Invalid hanlde"); break;
+ KWSYSPE_CASE(Fault, "Invalid hanlde");
+ break;
case STATUS_NONCONTINUABLE_EXCEPTION:
- KWSYSPE_CASE(Fault, "Noncontinuable exception"); break;
+ KWSYSPE_CASE(Fault, "Noncontinuable exception");
+ break;
case STATUS_INVALID_DISPOSITION:
- KWSYSPE_CASE(Fault, "Invalid disposition"); break;
+ KWSYSPE_CASE(Fault, "Invalid disposition");
+ break;
case STATUS_ARRAY_BOUNDS_EXCEEDED:
- KWSYSPE_CASE(Fault, "Array bounds exceeded"); break;
+ KWSYSPE_CASE(Fault, "Array bounds exceeded");
+ break;
case STATUS_STACK_OVERFLOW:
- KWSYSPE_CASE(Fault, "Stack overflow"); break;
+ KWSYSPE_CASE(Fault, "Stack overflow");
+ break;
case STATUS_ILLEGAL_INSTRUCTION:
- KWSYSPE_CASE(Illegal, "Illegal instruction"); break;
+ KWSYSPE_CASE(Illegal, "Illegal instruction");
+ break;
case STATUS_PRIVILEGED_INSTRUCTION:
- KWSYSPE_CASE(Illegal, "Privileged instruction"); break;
+ KWSYSPE_CASE(Illegal, "Privileged instruction");
+ break;
case STATUS_NO_MEMORY:
default:
- cp->ExitException = kwsysProcess_Exception_Other;
- sprintf(cp->ExitExceptionString, "Exit code 0x%x\n", code);
+ cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
+ _snprintf(cp->ProcessResults[idx].ExitExceptionString,
+ KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code);
break;
- }
+ }
}
#undef KWSYSPE_CASE
@@ -2236,7 +2158,6 @@ static int kwsysProcess_List_NextProcess(kwsysProcess_List* self);
static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self);
static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self);
-/*--------------------------------------------------------------------------*/
/* Windows NT 4 API definitions. */
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
typedef LONG NTSTATUS;
@@ -2256,21 +2177,20 @@ typedef struct _SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION;
typedef SYSTEM_PROCESS_INFORMATION* PSYSTEM_PROCESS_INFORMATION;
struct _SYSTEM_PROCESS_INFORMATION
{
- ULONG NextEntryDelta;
- ULONG ThreadCount;
- ULONG Reserved1[6];
- LARGE_INTEGER CreateTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER KernelTime;
+ ULONG NextEntryDelta;
+ ULONG ThreadCount;
+ ULONG Reserved1[6];
+ LARGE_INTEGER CreateTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
- KPRIORITY BasePriority;
- ULONG ProcessId;
- ULONG InheritedFromProcessId;
+ KPRIORITY BasePriority;
+ ULONG ProcessId;
+ ULONG InheritedFromProcessId;
};
-/*--------------------------------------------------------------------------*/
/* Toolhelp32 API definitions. */
-#define TH32CS_SNAPPROCESS 0x00000002
+#define TH32CS_SNAPPROCESS 0x00000002
#if defined(_WIN64)
typedef unsigned __int64 ProcessULONG_PTR;
#else
@@ -2287,21 +2207,18 @@ struct tagPROCESSENTRY32
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
- LONG pcPriClassBase;
+ LONG pcPriClassBase;
DWORD dwFlags;
char szExeFile[MAX_PATH];
};
-/*--------------------------------------------------------------------------*/
/* Windows API function types. */
-typedef HANDLE (WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD);
-typedef BOOL (WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32);
-typedef BOOL (WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32);
-typedef NTSTATUS (WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID,
- ULONG, PULONG);
+typedef HANDLE(WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD);
+typedef BOOL(WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32);
+typedef BOOL(WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32);
+typedef NTSTATUS(WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID, ULONG,
+ PULONG);
-
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__New_NT4(kwsysProcess_List* self);
static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self);
static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self);
@@ -2334,330 +2251,282 @@ struct kwsysProcess_List_s
PROCESSENTRY32 CurrentEntry;
};
-/*--------------------------------------------------------------------------*/
static kwsysProcess_List* kwsysProcess_List_New(void)
{
OSVERSIONINFO osv;
kwsysProcess_List* self;
/* Allocate and initialize the list object. */
- if(!(self = (kwsysProcess_List*)malloc(sizeof(kwsysProcess_List))))
- {
+ if (!(self = (kwsysProcess_List*)malloc(sizeof(kwsysProcess_List)))) {
return 0;
- }
+ }
memset(self, 0, sizeof(*self));
/* Select an implementation. */
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
+#endif
GetVersionEx(&osv);
- self->NT4 = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT &&
- osv.dwMajorVersion < 5)? 1:0;
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(pop)
+#endif
+ self->NT4 =
+ (osv.dwPlatformId == VER_PLATFORM_WIN32_NT && osv.dwMajorVersion < 5) ? 1
+ : 0;
/* Initialize the selected implementation. */
- if(!(self->NT4?
- kwsysProcess_List__New_NT4(self) :
- kwsysProcess_List__New_Snapshot(self)))
- {
+ if (!(self->NT4 ? kwsysProcess_List__New_NT4(self)
+ : kwsysProcess_List__New_Snapshot(self))) {
kwsysProcess_List_Delete(self);
return 0;
- }
+ }
/* Update to the current set of processes. */
- if(!kwsysProcess_List_Update(self))
- {
+ if (!kwsysProcess_List_Update(self)) {
kwsysProcess_List_Delete(self);
return 0;
- }
+ }
return self;
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcess_List_Delete(kwsysProcess_List* self)
{
- if(self)
- {
- if(self->NT4)
- {
+ if (self) {
+ if (self->NT4) {
kwsysProcess_List__Delete_NT4(self);
- }
- else
- {
+ } else {
kwsysProcess_List__Delete_Snapshot(self);
- }
- free(self);
}
+ free(self);
+ }
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List_Update(kwsysProcess_List* self)
{
- return self? (self->NT4?
- kwsysProcess_List__Update_NT4(self) :
- kwsysProcess_List__Update_Snapshot(self)) : 0;
+ return self ? (self->NT4 ? kwsysProcess_List__Update_NT4(self)
+ : kwsysProcess_List__Update_Snapshot(self))
+ : 0;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self)
{
- return self? (self->NT4?
- kwsysProcess_List__GetProcessId_NT4(self) :
- kwsysProcess_List__GetProcessId_Snapshot(self)) : -1;
-
+ return self ? (self->NT4 ? kwsysProcess_List__GetProcessId_NT4(self)
+ : kwsysProcess_List__GetProcessId_Snapshot(self))
+ : -1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self)
{
- return self? (self->NT4?
- kwsysProcess_List__GetParentId_NT4(self) :
- kwsysProcess_List__GetParentId_Snapshot(self)) : -1;
-
+ return self ? (self->NT4 ? kwsysProcess_List__GetParentId_NT4(self)
+ : kwsysProcess_List__GetParentId_Snapshot(self))
+ : -1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List_NextProcess(kwsysProcess_List* self)
{
- return (self? (self->NT4?
- kwsysProcess_List__Next_NT4(self) :
- kwsysProcess_List__Next_Snapshot(self)) : 0);
+ return (self ? (self->NT4 ? kwsysProcess_List__Next_NT4(self)
+ : kwsysProcess_List__Next_Snapshot(self))
+ : 0);
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__New_NT4(kwsysProcess_List* self)
{
/* Get a handle to the NT runtime module that should already be
loaded in this program. This does not actually increment the
reference count to the module so we do not need to close the
handle. */
- HMODULE hNT = GetModuleHandle("ntdll.dll");
- if(hNT)
- {
+ HMODULE hNT = GetModuleHandleW(L"ntdll.dll");
+ if (hNT) {
/* Get pointers to the needed API functions. */
self->P_ZwQuerySystemInformation =
- ((ZwQuerySystemInformationType)
- GetProcAddress(hNT, "ZwQuerySystemInformation"));
- }
- if(!self->P_ZwQuerySystemInformation)
- {
+ ((ZwQuerySystemInformationType)GetProcAddress(
+ hNT, "ZwQuerySystemInformation"));
+ }
+ if (!self->P_ZwQuerySystemInformation) {
return 0;
- }
+ }
/* Allocate an initial process information buffer. */
self->BufferSize = 32768;
self->Buffer = (char*)malloc(self->BufferSize);
- return self->Buffer? 1:0;
+ return self->Buffer ? 1 : 0;
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self)
{
/* Free the process information buffer. */
- if(self->Buffer)
- {
+ if (self->Buffer) {
free(self->Buffer);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self)
{
self->CurrentInfo = 0;
- for(;;)
- {
+ for (;;) {
/* Query number 5 is for system process list. */
NTSTATUS status =
self->P_ZwQuerySystemInformation(5, self->Buffer, self->BufferSize, 0);
- if(status == STATUS_INFO_LENGTH_MISMATCH)
- {
+ if (status == STATUS_INFO_LENGTH_MISMATCH) {
/* The query requires a bigger buffer. */
int newBufferSize = self->BufferSize * 2;
char* newBuffer = (char*)malloc(newBufferSize);
- if(newBuffer)
- {
+ if (newBuffer) {
free(self->Buffer);
self->Buffer = newBuffer;
self->BufferSize = newBufferSize;
- }
- else
- {
+ } else {
return 0;
- }
}
- else if(status >= 0)
- {
+ } else if (status >= 0) {
/* The query succeeded. Initialize traversal of the process list. */
self->CurrentInfo = (PSYSTEM_PROCESS_INFORMATION)self->Buffer;
return 1;
- }
- else
- {
+ } else {
/* The query failed. */
return 0;
- }
}
+ }
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self)
{
- if(self->CurrentInfo)
- {
- if(self->CurrentInfo->NextEntryDelta > 0)
- {
- self->CurrentInfo = ((PSYSTEM_PROCESS_INFORMATION)
- ((char*)self->CurrentInfo +
- self->CurrentInfo->NextEntryDelta));
+ if (self->CurrentInfo) {
+ if (self->CurrentInfo->NextEntryDelta > 0) {
+ self->CurrentInfo = ((PSYSTEM_PROCESS_INFORMATION)(
+ (char*)self->CurrentInfo + self->CurrentInfo->NextEntryDelta));
return 1;
- }
- self->CurrentInfo = 0;
}
+ self->CurrentInfo = 0;
+ }
return 0;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self)
{
- return self->CurrentInfo? self->CurrentInfo->ProcessId : -1;
+ return self->CurrentInfo ? self->CurrentInfo->ProcessId : -1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self)
{
- return self->CurrentInfo? self->CurrentInfo->InheritedFromProcessId : -1;
+ return self->CurrentInfo ? self->CurrentInfo->InheritedFromProcessId : -1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self)
{
/* Get a handle to the Windows runtime module that should already be
loaded in this program. This does not actually increment the
reference count to the module so we do not need to close the
handle. */
- HMODULE hKernel = GetModuleHandle("kernel32.dll");
- if(hKernel)
- {
+ HMODULE hKernel = GetModuleHandleW(L"kernel32.dll");
+ if (hKernel) {
self->P_CreateToolhelp32Snapshot =
- ((CreateToolhelp32SnapshotType)
- GetProcAddress(hKernel, "CreateToolhelp32Snapshot"));
+ ((CreateToolhelp32SnapshotType)GetProcAddress(
+ hKernel, "CreateToolhelp32Snapshot"));
self->P_Process32First =
- ((Process32FirstType)
- GetProcAddress(hKernel, "Process32First"));
+ ((Process32FirstType)GetProcAddress(hKernel, "Process32First"));
self->P_Process32Next =
- ((Process32NextType)
- GetProcAddress(hKernel, "Process32Next"));
- }
- return (self->P_CreateToolhelp32Snapshot &&
- self->P_Process32First &&
- self->P_Process32Next)? 1:0;
+ ((Process32NextType)GetProcAddress(hKernel, "Process32Next"));
+ }
+ return (self->P_CreateToolhelp32Snapshot && self->P_Process32First &&
+ self->P_Process32Next)
+ ? 1
+ : 0;
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self)
{
- if(self->Snapshot)
- {
+ if (self->Snapshot) {
CloseHandle(self->Snapshot);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self)
{
- if(self->Snapshot)
- {
+ if (self->Snapshot) {
CloseHandle(self->Snapshot);
- }
- if(!(self->Snapshot =
- self->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)))
- {
+ }
+ if (!(self->Snapshot =
+ self->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) {
return 0;
- }
+ }
ZeroMemory(&self->CurrentEntry, sizeof(self->CurrentEntry));
self->CurrentEntry.dwSize = sizeof(self->CurrentEntry);
- if(!self->P_Process32First(self->Snapshot, &self->CurrentEntry))
- {
+ if (!self->P_Process32First(self->Snapshot, &self->CurrentEntry)) {
CloseHandle(self->Snapshot);
self->Snapshot = 0;
return 0;
- }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self)
{
- if(self->Snapshot)
- {
- if(self->P_Process32Next(self->Snapshot, &self->CurrentEntry))
- {
+ if (self->Snapshot) {
+ if (self->P_Process32Next(self->Snapshot, &self->CurrentEntry)) {
return 1;
- }
+ }
CloseHandle(self->Snapshot);
self->Snapshot = 0;
- }
+ }
return 0;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self)
{
- return self->Snapshot? self->CurrentEntry.th32ProcessID : -1;
+ return self->Snapshot ? self->CurrentEntry.th32ProcessID : -1;
}
-/*--------------------------------------------------------------------------*/
static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self)
{
- return self->Snapshot? self->CurrentEntry.th32ParentProcessID : -1;
+ return self->Snapshot ? self->CurrentEntry.th32ParentProcessID : -1;
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessKill(DWORD pid)
{
HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid);
- if(h)
- {
+ if (h) {
TerminateProcess(h, 255);
WaitForSingleObject(h, INFINITE);
CloseHandle(h);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessKillTree(int pid)
{
kwsysProcess_List* plist = kwsysProcess_List_New();
kwsysProcessKill(pid);
- if(plist)
- {
- do
- {
- if(kwsysProcess_List_GetCurrentParentId(plist) == pid)
- {
+ if (plist) {
+ do {
+ if (kwsysProcess_List_GetCurrentParentId(plist) == pid) {
int ppid = kwsysProcess_List_GetCurrentProcessId(plist);
kwsysProcessKillTree(ppid);
- }
- } while(kwsysProcess_List_NextProcess(plist));
+ }
+ } while (kwsysProcess_List_NextProcess(plist));
kwsysProcess_List_Delete(plist);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
{
int i;
/* If data were just reported data, release the pipe's thread. */
- if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT)
- {
+ if (cp->CurrentIndex < KWSYSPE_PIPE_COUNT) {
KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex));
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0);
cp->CurrentIndex = KWSYSPE_PIPE_COUNT;
- }
+ }
/* Wakeup all reading threads that are not on closed pipes. */
- for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
- {
+ for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) {
/* The wakeup threads will write one byte to the pipe write ends.
If there are no data in the pipe then this is enough to wakeup
the reading threads. If there are already data in the pipe
@@ -2669,16 +2538,14 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
thread to call WriteFile. If it blocks, that is okay because
it will unblock when we close the read end and break the pipe
below. */
- if(cp->Pipe[i].Read)
- {
+ if (cp->Pipe[i].Read) {
KWSYSPE_DEBUG((stderr, "releasing waker %d\n", i));
ReleaseSemaphore(cp->Pipe[i].Waker.Go, 1, 0);
- }
}
+ }
/* Tell pipe threads to reset until we run another process. */
- while(cp->PipesLeft > 0)
- {
+ while (cp->PipesLeft > 0) {
/* The waking threads will cause all reading threads to report.
Wait for the next one and save its index. */
KWSYSPE_DEBUG((stderr, "waiting for reader\n"));
@@ -2695,5 +2562,213 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
/* Tell the reading thread we are done with the data. It will
reset immediately because the pipe is closed. */
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0);
+ }
+}
+
+/* Global set of executing processes for use by the Ctrl handler.
+ This global instance will be zero-initialized by the compiler.
+
+ Note that the console Ctrl handler runs on a background thread and so
+ everything it does must be thread safe. Here, we track the hProcess
+ HANDLEs directly instead of kwsysProcess instances, so that we don't have
+ to make kwsysProcess thread safe. */
+typedef struct kwsysProcessInstance_s
+{
+ HANDLE hProcess;
+ DWORD dwProcessId;
+ int NewProcessGroup; /* Whether the process was created in a new group. */
+} kwsysProcessInstance;
+
+typedef struct kwsysProcessInstances_s
+{
+ /* Whether we have initialized key fields below, like critical sections. */
+ int Initialized;
+
+ /* Ctrl handler runs on a different thread, so we must sync access. */
+ CRITICAL_SECTION Lock;
+
+ int Exiting;
+ size_t Count;
+ size_t Size;
+ kwsysProcessInstance* Processes;
+} kwsysProcessInstances;
+static kwsysProcessInstances kwsysProcesses;
+
+/* Initialize critial section and set up console Ctrl handler. You MUST call
+ this before using any other kwsysProcesses* functions below. */
+static int kwsysProcessesInitialize(void)
+{
+ /* Initialize everything if not done already. */
+ if (!kwsysProcesses.Initialized) {
+ InitializeCriticalSection(&kwsysProcesses.Lock);
+
+ /* Set up console ctrl handler. */
+ if (!SetConsoleCtrlHandler(kwsysCtrlHandler, TRUE)) {
+ return 0;
+ }
+
+ kwsysProcesses.Initialized = 1;
+ }
+ return 1;
+}
+
+/* The Ctrl handler waits on the global list of processes. To prevent an
+ orphaned process, do not create a new process if the Ctrl handler is
+ already running. Do so by using this function to check if it is ok to
+ create a process. */
+static int kwsysTryEnterCreateProcessSection(void)
+{
+ /* Enter main critical section; this means creating a process and the Ctrl
+ handler are mutually exclusive. */
+ EnterCriticalSection(&kwsysProcesses.Lock);
+ /* Indicate to the caller if they can create a process. */
+ if (kwsysProcesses.Exiting) {
+ LeaveCriticalSection(&kwsysProcesses.Lock);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/* Matching function on successful kwsysTryEnterCreateProcessSection return.
+ Make sure you called kwsysProcessesAdd if applicable before calling this.*/
+static void kwsysLeaveCreateProcessSection(void)
+{
+ LeaveCriticalSection(&kwsysProcesses.Lock);
+}
+
+/* Add new process to global process list. The Ctrl handler will wait for
+ the process to exit before it returns. Do not close the process handle
+ until after calling kwsysProcessesRemove. The newProcessGroup parameter
+ must be set if the process was created with CREATE_NEW_PROCESS_GROUP. */
+static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid,
+ int newProcessGroup)
+{
+ if (!kwsysProcessesInitialize() || !hProcess ||
+ hProcess == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
+
+ /* Enter the critical section. */
+ EnterCriticalSection(&kwsysProcesses.Lock);
+
+ /* Make sure there is enough space for the new process handle. */
+ if (kwsysProcesses.Count == kwsysProcesses.Size) {
+ size_t newSize;
+ kwsysProcessInstance* newArray;
+ /* Start with enough space for a small number of process handles
+ and double the size each time more is needed. */
+ newSize = kwsysProcesses.Size ? kwsysProcesses.Size * 2 : 4;
+
+ /* Try allocating the new block of memory. */
+ if (newArray = (kwsysProcessInstance*)malloc(
+ newSize * sizeof(kwsysProcessInstance))) {
+ /* Copy the old process handles to the new memory. */
+ if (kwsysProcesses.Count > 0) {
+ memcpy(newArray, kwsysProcesses.Processes,
+ kwsysProcesses.Count * sizeof(kwsysProcessInstance));
+ }
+ } else {
+ /* Failed to allocate memory for the new process handle set. */
+ LeaveCriticalSection(&kwsysProcesses.Lock);
+ return 0;
+ }
+
+ /* Free original array. */
+ free(kwsysProcesses.Processes);
+
+ /* Update original structure with new allocation. */
+ kwsysProcesses.Size = newSize;
+ kwsysProcesses.Processes = newArray;
+ }
+
+ /* Append the new process information to the set. */
+ kwsysProcesses.Processes[kwsysProcesses.Count].hProcess = hProcess;
+ kwsysProcesses.Processes[kwsysProcesses.Count].dwProcessId = dwProcessid;
+ kwsysProcesses.Processes[kwsysProcesses.Count++].NewProcessGroup =
+ newProcessGroup;
+
+ /* Leave critical section and return success. */
+ LeaveCriticalSection(&kwsysProcesses.Lock);
+
+ return 1;
+}
+
+/* Removes process to global process list. */
+static void kwsysProcessesRemove(HANDLE hProcess)
+{
+ size_t i;
+
+ if (!hProcess || hProcess == INVALID_HANDLE_VALUE) {
+ return;
+ }
+
+ EnterCriticalSection(&kwsysProcesses.Lock);
+
+ /* Find the given process in the set. */
+ for (i = 0; i < kwsysProcesses.Count; ++i) {
+ if (kwsysProcesses.Processes[i].hProcess == hProcess) {
+ break;
+ }
+ }
+ if (i < kwsysProcesses.Count) {
+ /* Found it! Remove the process from the set. */
+ --kwsysProcesses.Count;
+ for (; i < kwsysProcesses.Count; ++i) {
+ kwsysProcesses.Processes[i] = kwsysProcesses.Processes[i + 1];
}
+
+ /* If this was the last process, free the array. */
+ if (kwsysProcesses.Count == 0) {
+ kwsysProcesses.Size = 0;
+ free(kwsysProcesses.Processes);
+ kwsysProcesses.Processes = 0;
+ }
+ }
+
+ LeaveCriticalSection(&kwsysProcesses.Lock);
+}
+
+static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType)
+{
+ size_t i;
+ (void)dwCtrlType;
+ /* Enter critical section. */
+ EnterCriticalSection(&kwsysProcesses.Lock);
+
+ /* Set flag indicating that we are exiting. */
+ kwsysProcesses.Exiting = 1;
+
+ /* If some of our processes were created in a new process group, we must
+ manually interrupt them. They won't otherwise receive a Ctrl+C/Break. */
+ for (i = 0; i < kwsysProcesses.Count; ++i) {
+ if (kwsysProcesses.Processes[i].NewProcessGroup) {
+ DWORD groupId = kwsysProcesses.Processes[i].dwProcessId;
+ if (groupId) {
+ GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, groupId);
+ }
+ }
+ }
+
+ /* Wait for each child process to exit. This is the key step that prevents
+ us from leaving several orphaned children processes running in the
+ background when the user presses Ctrl+C. */
+ for (i = 0; i < kwsysProcesses.Count; ++i) {
+ WaitForSingleObject(kwsysProcesses.Processes[i].hProcess, INFINITE);
+ }
+
+ /* Leave critical section. */
+ LeaveCriticalSection(&kwsysProcesses.Lock);
+
+ /* Continue on to default Ctrl handler (which calls ExitProcess). */
+ return FALSE;
+}
+
+void kwsysProcess_ResetStartTime(kwsysProcess* cp)
+{
+ if (!cp) {
+ return;
+ }
+ /* Reset start time. */
+ cp->StartTime = kwsysProcessTimeGetCurrent();
}
diff --git a/Source/kwsys/README.rst b/Source/kwsys/README.rst
new file mode 100644
index 000000000..fc6b5902e
--- /dev/null
+++ b/Source/kwsys/README.rst
@@ -0,0 +1,37 @@
+KWSys
+*****
+
+Introduction
+============
+
+KWSys is the Kitware System Library. It provides platform-independent
+APIs to many common system features that are implemented differently on
+every platform. This library is intended to be shared among many
+projects at the source level, so it has a configurable namespace.
+Each project should configure KWSys to use a namespace unique to itself.
+See comments in `CMakeLists.txt`_ for details.
+
+.. _`CMakeLists.txt`: CMakeLists.txt
+
+License
+=======
+
+KWSys is distributed under the OSI-approved BSD 3-clause License.
+See `Copyright.txt`_ for details.
+
+.. _`Copyright.txt`: Copyright.txt
+
+Reporting Bugs
+==============
+
+KWSys has no independent issue tracker. After encountering an issue
+(bug) please submit a patch using the instructions for `Contributing`_.
+Otherwise please report the issue to the tracker for the project that
+hosts the copy of KWSys in which the problem was found.
+
+Contributing
+============
+
+See `CONTRIBUTING.rst`_ for instructions to contribute.
+
+.. _`CONTRIBUTING.rst`: CONTRIBUTING.rst
diff --git a/Source/kwsys/README.txt b/Source/kwsys/README.txt
deleted file mode 100644
index ba03f8dde..000000000
--- a/Source/kwsys/README.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-KWSys provides a platform-independent API to many common system
-features that are implemented differently on every platform. This
-library is intended to be shared among many projects, so it has a
-configurable namespace. Each project should configure KWSys to use a
-namespace unique to itself. See comments in CMakeLists.txt for
-details.
-
-You are probably reading this file in the source tree of a surrounding
-project. In that case, see "../README.kwsys" for details of using
-KWSys in your project.
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
index c8297873f..6d7f83295 100644
--- a/Source/kwsys/RegularExpression.cxx
+++ b/Source/kwsys/RegularExpression.cxx
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
@@ -34,30 +25,29 @@
// 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>
#include <string.h>
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
// RegularExpression -- Copies the given regular expression.
-RegularExpression::RegularExpression (const RegularExpression& rxp) {
- if ( !rxp.program )
- {
+RegularExpression::RegularExpression(const RegularExpression& rxp)
+{
+ if (!rxp.program) {
this->program = 0;
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
+ 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
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
+ 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) {
char* dum = rxp.program;
ind = 0;
@@ -67,32 +57,30 @@ RegularExpression::RegularExpression (const RegularExpression& rxp) {
}
this->regmust = this->program + ind;
}
- this->regstart = rxp.regstart; // Copy starting index
- this->reganch = rxp.reganch; // Copy remaining private data
- this->regmlen = rxp.regmlen; // Copy remaining private data
+ this->regstart = rxp.regstart; // Copy starting index
+ this->reganch = rxp.reganch; // Copy remaining private data
+ this->regmlen = rxp.regmlen; // Copy remaining private data
}
// operator= -- Copies the given regular expression.
-RegularExpression& RegularExpression::operator= (const RegularExpression& rxp)
+RegularExpression& RegularExpression::operator=(const RegularExpression& rxp)
{
- if(this == &rxp)
- {
+ if (this == &rxp) {
return *this;
- }
- if ( !rxp.program )
- {
+ }
+ if (!rxp.program) {
this->program = 0;
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
+ 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
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
+ 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) {
char* dum = rxp.program;
ind = 0;
@@ -102,37 +90,38 @@ RegularExpression& RegularExpression::operator= (const RegularExpression& rxp)
}
this->regmust = this->program + ind;
}
- this->regstart = rxp.regstart; // Copy starting index
- this->reganch = rxp.reganch; // Copy remaining private data
- this->regmlen = rxp.regmlen; // Copy remaining private data
+ this->regstart = rxp.regstart; // Copy starting index
+ this->reganch = rxp.reganch; // Copy remaining private data
+ this->regmlen = rxp.regmlen; // Copy remaining private data
return *this;
}
// operator== -- Returns true if two regular expressions have the same
// compiled program for pattern matching.
-bool RegularExpression::operator== (const RegularExpression& rxp) const {
- if (this != &rxp) { // Same address?
- int ind = this->progsize; // Get regular expression size
- if (ind != rxp.progsize) // If different size regexp
- return false; // Return failure
- while(ind-- != 0) // Else while still characters
- if(this->program[ind] != rxp.program[ind]) // If regexp are different
- return false; // Return failure
+bool RegularExpression::operator==(const RegularExpression& rxp) const
+{
+ if (this != &rxp) { // Same address?
+ int ind = this->progsize; // Get regular expression size
+ if (ind != rxp.progsize) // If different size regexp
+ return false; // Return failure
+ while (ind-- != 0) // Else while still characters
+ if (this->program[ind] != rxp.program[ind]) // If regexp are different
+ return false; // Return failure
}
- return true; // Else same, return success
+ return true; // Else same, return success
}
-
// deep_equal -- Returns true if have the same compiled regular expressions
// and the same start and end pointers.
-bool RegularExpression::deep_equal (const RegularExpression& rxp) const {
+bool RegularExpression::deep_equal(const RegularExpression& rxp) const
+{
int ind = this->progsize; // Get regular expression size
if (ind != rxp.progsize) // If different size regexp
return false; // Return failure
- while(ind-- != 0) // Else while still characters
- if(this->program[ind] != rxp.program[ind]) // If regexp are different
+ 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
@@ -204,26 +193,26 @@ 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
- // 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 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.
// OPEN+1 is number 1, etc.
-#define CLOSE 30 // no Analogous to OPEN.
+#define CLOSE 30 // no Analogous to OPEN.
/*
* Opcode notes:
@@ -258,32 +247,32 @@ bool RegularExpression::deep_equal (const RegularExpression& rxp) const {
* but allows patterns to get big without disasters.
*/
-#define OP(p) (*(p))
-#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
-#define OPERAND(p) ((p) + 3)
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p) + 1) & 0377) << 8) + (*((p) + 2) & 0377))
+#define OPERAND(p) ((p) + 3)
const unsigned char MAGIC = 0234;
/*
* Utility definitions.
*/
-#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 "^$.[()|?+*\\"
+#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 "^$.[()|?+*\\"
/*
* Flags to be passed up and down.
*/
-#define HASWIDTH 01 // Known never to match null string.
-#define SIMPLE 02 // Simple enough to be STAR/PLUS operand.
-#define SPSTART 04 // Starts with * or +.
-#define WORST 0 // Worst case.
-
-
+#define HASWIDTH 01 // Known never to match null string.
+#define SIMPLE 02 // Simple enough to be STAR/PLUS operand.
+#define SPSTART 04 // Starts with * or +.
+#define WORST 0 // Worst case.
/////////////////////////////////////////////////////////////////////////
//
@@ -291,15 +280,14 @@ const unsigned char MAGIC = 0234;
//
/////////////////////////////////////////////////////////////////////////
-
/*
* Global work variables for compile().
*/
-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 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.
/*
* Forward declarations for compile()'s friends.
@@ -307,24 +295,22 @@ static long regsize; // Code size.
// #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);
-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*);
+static char* reg(int, int*);
+static char* regbranch(int*);
+static char* regpiece(int*);
+static char* regatom(int*);
+static char* regnode(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 ();
+static int strcspn();
#endif
-
-
/*
* We can't allocate space until we know how big the compiled form will be,
* but we can't compile it (and thus know how big it is) until we've got a
@@ -339,101 +325,100 @@ static int strcspn ();
* of the structure of the compiled regexp.
*/
-
// compile -- compile a regular expression into internal code
// for later pattern matching.
-bool RegularExpression::compile (const char* exp) {
- const char* scan;
- const char* longest;
- size_t len;
- int flags;
+bool RegularExpression::compile(const char* exp)
+{
+ const char* scan;
+ const char* longest;
+ size_t len;
+ int flags;
+
+ if (exp == 0) {
+ // RAISE Error, SYM(RegularExpression), SYM(No_Expr),
+ printf("RegularExpression::compile(): No expression supplied.\n");
+ return false;
+ }
- if (exp == 0) {
- //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)) {
+ printf("RegularExpression::compile(): Error in compile.\n");
+ return false;
+ }
+ this->startp[0] = this->endp[0] = this->searchstring = 0;
- // First pass: determine size, legality.
- regparse = exp;
- regnpar = 1;
- regsize = 0L;
- regcode = &regdummy;
- regc(static_cast<char>(MAGIC));
- if(!reg(0, &flags))
- {
- printf ("RegularExpression::compile(): Error in compile.\n");
- return false;
- }
- this->startp[0] = this->endp[0] = this->searchstring = 0;
+ // Small enough for pointer-storage convention?
+ if (regsize >= 32767L) { // Probably could be 65535L.
+ // RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big),
+ printf("RegularExpression::compile(): Expression too big.\n");
+ return false;
+ }
- // Small enough for pointer-storage convention?
- if (regsize >= 32767L) { // Probably could be 65535L.
- //RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big),
- printf ("RegularExpression::compile(): Expression too big.\n");
- return false;
- }
+ // Allocate space.
+ //#ifndef _WIN32
+ if (this->program != 0)
+ delete[] this->program;
+ //#endif
+ this->program = new char[regsize];
+ this->progsize = static_cast<int>(regsize);
+
+ if (this->program == 0) {
+ // RAISE Error, SYM(RegularExpression), SYM(Out_Of_Memory),
+ printf("RegularExpression::compile(): Out of memory.\n");
+ return false;
+ }
- // Allocate space.
-//#ifndef WIN32
- if (this->program != 0) delete [] this->program;
-//#endif
- this->program = new char[regsize];
- this->progsize = static_cast<int>(regsize);
-
- if (this->program == 0) {
- //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);
+
+ // Dig out information for optimizations.
+ this->regstart = '\0'; // Worst-case defaults.
+ this->reganch = 0;
+ this->regmust = 0;
+ this->regmlen = 0;
+ scan = this->program + 1; // First BRANCH.
+ if (OP(regnext(scan)) == END) { // Only one top-level choice.
+ scan = OPERAND(scan);
+
+ // Starting-point info.
+ if (OP(scan) == EXACTLY)
+ this->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ this->reganch++;
- // Second pass: emit code.
- regparse = exp;
- regnpar = 1;
- regcode = this->program;
- regc(static_cast<char>(MAGIC));
- reg(0, &flags);
-
- // Dig out information for optimizations.
- this->regstart = '\0'; // Worst-case defaults.
- this->reganch = 0;
- this->regmust = 0;
- this->regmlen = 0;
- scan = this->program + 1; // First BRANCH.
- if (OP(regnext(scan)) == END) { // Only one top-level choice.
- scan = OPERAND(scan);
-
- // Starting-point info.
- if (OP(scan) == EXACTLY)
- this->regstart = *OPERAND(scan);
- else if (OP(scan) == BOL)
- this->reganch++;
-
- //
- // If there's something expensive in the r.e., find the longest
- // literal string that must appear and make it the regmust. Resolve
- // ties in favor of later strings, since the regstart check works
- // with the beginning of the r.e. and avoiding duplication
- // strengthens checking. Not a strong reason, but sufficient in the
- // absence of others.
- //
- if (flags & SPSTART) {
- longest = 0;
- len = 0;
- for (; scan != 0; scan = regnext(scan))
- if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
- longest = OPERAND(scan);
- len = strlen(OPERAND(scan));
- }
- this->regmust = longest;
- this->regmlen = len;
+ //
+ // If there's something expensive in the r.e., find the longest
+ // literal string that must appear and make it the regmust. Resolve
+ // ties in favor of later strings, since the regstart check works
+ // with the beginning of the r.e. and avoiding duplication
+ // strengthens checking. Not a strong reason, but sufficient in the
+ // absence of others.
+ //
+ if (flags & SPSTART) {
+ longest = 0;
+ len = 0;
+ for (; scan != 0; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
}
+ this->regmust = longest;
+ this->regmlen = len;
}
- return true;
+ }
+ return true;
}
-
/*
- reg - regular expression, i.e. main body or parenthesized thing
*
@@ -443,115 +428,112 @@ 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* ret;
- char* br;
- char* ender;
- int parno =0;
- int flags;
-
- *flagp = HASWIDTH; // Tentatively.
-
- // Make an OPEN node, if parenthesized.
- if (paren) {
- if (regnpar >= RegularExpression::NSUBEXP) {
- //RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens),
- printf ("RegularExpression::compile(): Too many parentheses.\n");
- return 0;
- }
- parno = regnpar;
- regnpar++;
- ret = regnode(static_cast<char>(OPEN + parno));
+static char* reg(int paren, int* flagp)
+{
+ char* ret;
+ char* br;
+ char* ender;
+ int parno = 0;
+ int flags;
+
+ *flagp = HASWIDTH; // Tentatively.
+
+ // Make an OPEN node, if parenthesized.
+ if (paren) {
+ if (regnpar >= RegularExpression::NSUBEXP) {
+ // RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens),
+ printf("RegularExpression::compile(): Too many parentheses.\n");
+ return 0;
}
- else
- ret = 0;
-
- // Pick up the branches, linking them together.
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(static_cast<char>(OPEN + parno));
+ } else
+ ret = 0;
+
+ // Pick up the branches, linking them together.
+ br = regbranch(&flags);
+ if (br == 0)
+ return (0);
+ if (ret != 0)
+ regtail(ret, br); // OPEN -> first.
+ else
+ ret = br;
+ if (!(flags & HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags & SPSTART;
+ while (*regparse == '|') {
+ regparse++;
br = regbranch(&flags);
if (br == 0)
- return (0);
- if (ret != 0)
- regtail(ret, br); // OPEN -> first.
- else
- ret = br;
+ return (0);
+ regtail(ret, br); // BRANCH -> BRANCH.
if (!(flags & HASWIDTH))
- *flagp &= ~HASWIDTH;
+ *flagp &= ~HASWIDTH;
*flagp |= flags & SPSTART;
- while (*regparse == '|') {
- regparse++;
- br = regbranch(&flags);
- if (br == 0)
- return (0);
- regtail(ret, br); // BRANCH -> BRANCH.
- if (!(flags & HASWIDTH))
- *flagp &= ~HASWIDTH;
- *flagp |= flags & SPSTART;
- }
-
- // Make a closing node, and hook it on the end.
- ender = regnode(static_cast<char>((paren) ? CLOSE + parno : END));
- regtail(ret, ender);
-
- // Hook the tails of the branches to the closing node.
- for (br = ret; br != 0; 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;
+ // Make a closing node, and hook it on the end.
+ ender = regnode(static_cast<char>((paren) ? CLOSE + parno : END));
+ regtail(ret, ender);
+
+ // Hook the tails of the branches to the closing node.
+ for (br = ret; br != 0; 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;
+ } else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ // RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
+ printf("RegularExpression::compile(): Unmatched parentheses.\n");
+ return 0;
+ } else {
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf("RegularExpression::compile(): Internal error.\n");
+ return 0;
}
- else if (!paren && *regparse != '\0') {
- if (*regparse == ')') {
- //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
- printf ("RegularExpression::compile(): Unmatched parentheses.\n");
- return 0;
- }
- else {
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("RegularExpression::compile(): Internal error.\n");
- return 0;
- }
- // NOTREACHED
- }
- return (ret);
+ // NOTREACHED
+ }
+ return (ret);
}
-
/*
- regbranch - one alternative of an | operator
*
* Implements the concatenation operator.
*/
-static char* regbranch (int *flagp) {
- char* ret;
- char* chain;
- char* latest;
- int flags;
-
- *flagp = WORST; // Tentatively.
-
- ret = regnode(BRANCH);
- chain = 0;
- while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
- latest = regpiece(&flags);
- if (latest == 0)
- return (0);
- *flagp |= flags & HASWIDTH;
- if (chain == 0) // First piece.
- *flagp |= flags & SPSTART;
- else
- regtail(chain, latest);
- chain = latest;
- }
- if (chain == 0) // Loop ran zero times.
- regnode(NOTHING);
+static char* regbranch(int* flagp)
+{
+ char* ret;
+ char* chain;
+ char* latest;
+ int flags;
+
+ *flagp = WORST; // Tentatively.
+
+ ret = regnode(BRANCH);
+ chain = 0;
+ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+ latest = regpiece(&flags);
+ if (latest == 0)
+ return (0);
+ *flagp |= flags & HASWIDTH;
+ if (chain == 0) // First piece.
+ *flagp |= flags & SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == 0) // Loop ran zero times.
+ regnode(NOTHING);
- return (ret);
+ return (ret);
}
-
/*
- regpiece - something followed by possible [*+?]
*
@@ -561,66 +543,64 @@ 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* ret;
- char op;
- char* next;
- int flags;
-
- ret = regatom(&flags);
- if (ret == 0)
- return (0);
+static char* regpiece(int* flagp)
+{
+ char* ret;
+ char op;
+ char* next;
+ int flags;
- op = *regparse;
- if (!ISMULT(op)) {
- *flagp = flags;
- return (ret);
- }
+ ret = regatom(&flags);
+ if (ret == 0)
+ return (0);
- if (!(flags & HASWIDTH) && op != '?') {
- //RAISE Error, SYM(RegularExpression), SYM(Empty_Operand),
- printf ("RegularExpression::compile() : *+ operand could be empty.\n");
- return 0;
- }
- *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
-
- if (op == '*' && (flags & SIMPLE))
- reginsert(STAR, ret);
- else if (op == '*') {
- // Emit x* as (x&|), where & means "self".
- reginsert(BRANCH, ret); // Either x
- regoptail(ret, regnode(BACK)); // and loop
- regoptail(ret, ret); // back
- regtail(ret, regnode(BRANCH)); // or
- regtail(ret, regnode(NOTHING)); // null.
- }
- else if (op == '+' && (flags & SIMPLE))
- reginsert(PLUS, ret);
- else if (op == '+') {
- // Emit x+ as x(&|), where & means "self".
- next = regnode(BRANCH); // Either
- regtail(ret, next);
- regtail(regnode(BACK), ret); // loop back
- regtail(next, regnode(BRANCH)); // or
- regtail(ret, regnode(NOTHING)); // null.
- }
- else if (op == '?') {
- // Emit x? as (x|)
- reginsert(BRANCH, ret); // Either x
- regtail(ret, regnode(BRANCH)); // or
- next = regnode(NOTHING);// null.
- regtail(ret, next);
- regoptail(ret, next);
- }
- regparse++;
- if (ISMULT(*regparse)) {
- //RAISE Error, SYM(RegularExpression), SYM(Nested_Operand),
- printf ("RegularExpression::compile(): Nested *?+.\n");
- return 0;
- }
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
return (ret);
-}
+ }
+ if (!(flags & HASWIDTH) && op != '?') {
+ // RAISE Error, SYM(RegularExpression), SYM(Empty_Operand),
+ printf("RegularExpression::compile() : *+ operand could be empty.\n");
+ return 0;
+ }
+ *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
+
+ if (op == '*' && (flags & SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ // Emit x* as (x&|), where & means "self".
+ reginsert(BRANCH, ret); // Either x
+ regoptail(ret, regnode(BACK)); // and loop
+ regoptail(ret, ret); // back
+ regtail(ret, regnode(BRANCH)); // or
+ regtail(ret, regnode(NOTHING)); // null.
+ } else if (op == '+' && (flags & SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ // Emit x+ as x(&|), where & means "self".
+ next = regnode(BRANCH); // Either
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); // loop back
+ regtail(next, regnode(BRANCH)); // or
+ regtail(ret, regnode(NOTHING)); // null.
+ } else if (op == '?') {
+ // Emit x? as (x|)
+ reginsert(BRANCH, ret); // Either x
+ regtail(ret, regnode(BRANCH)); // or
+ next = regnode(NOTHING); // null.
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse)) {
+ // RAISE Error, SYM(RegularExpression), SYM(Nested_Operand),
+ printf("RegularExpression::compile(): Nested *?+.\n");
+ return 0;
+ }
+ return (ret);
+}
/*
- regatom - the lowest level
@@ -630,356 +610,340 @@ 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* ret;
- int flags;
-
- *flagp = WORST; // Tentatively.
-
- switch (*regparse++) {
- case '^':
- ret = regnode(BOL);
- break;
- case '$':
- ret = regnode(EOL);
- break;
- case '.':
- ret = regnode(ANY);
- *flagp |= HASWIDTH | SIMPLE;
- break;
- case '[':{
- int rxpclass;
- int rxpclassend;
-
- if (*regparse == '^') { // Complement of range.
- ret = regnode(ANYBUT);
- regparse++;
- }
- else
- ret = regnode(ANYOF);
- if (*regparse == ']' || *regparse == '-')
- regc(*regparse++);
- while (*regparse != '\0' && *regparse != ']') {
- if (*regparse == '-') {
- regparse++;
- if (*regparse == ']' || *regparse == '\0')
- regc('-');
- else {
- rxpclass = UCHARAT(regparse - 2) + 1;
- rxpclassend = UCHARAT(regparse);
- if (rxpclass > rxpclassend + 1) {
- //RAISE Error, SYM(RegularExpression), SYM(Invalid_Range),
- printf ("RegularExpression::compile(): Invalid range in [].\n");
- return 0;
- }
- for (; rxpclass <= rxpclassend; rxpclass++)
- regc(static_cast<char>(rxpclass));
- regparse++;
- }
- }
- else
- regc(*regparse++);
- }
- regc('\0');
- if (*regparse != ']') {
- //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Bracket),
- printf ("RegularExpression::compile(): Unmatched [].\n");
- return 0;
- }
- regparse++;
- *flagp |= HASWIDTH | SIMPLE;
- }
- break;
- case '(':
- ret = reg(1, &flags);
- if (ret == 0)
- return (0);
- *flagp |= flags & (HASWIDTH | SPSTART);
- break;
- case '\0':
- case '|':
- case ')':
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("RegularExpression::compile(): Internal error.\n"); // Never here
- return 0;
- case '?':
- case '+':
- case '*':
- //RAISE Error, SYM(RegularExpression), SYM(No_Operand),
- printf ("RegularExpression::compile(): ?+* follows nothing.\n");
- return 0;
- case '\\':
- if (*regparse == '\0') {
- //RAISE Error, SYM(RegularExpression), SYM(Trailing_Backslash),
- printf ("RegularExpression::compile(): Trailing backslash.\n");
- return 0;
- }
- ret = regnode(EXACTLY);
- regc(*regparse++);
- regc('\0');
- *flagp |= HASWIDTH | SIMPLE;
- break;
- default:{
- int len;
- char ender;
-
- regparse--;
- len = int(strcspn(regparse, META));
- if (len <= 0) {
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("RegularExpression::compile(): Internal error.\n");
- return 0;
- }
- ender = *(regparse + len);
- if (len > 1 && ISMULT(ender))
- len--; // Back off clear of ?+* operand.
- *flagp |= HASWIDTH;
- if (len == 1)
- *flagp |= SIMPLE;
- ret = regnode(EXACTLY);
- while (len > 0) {
- regc(*regparse++);
- len--;
- }
- regc('\0');
+static char* regatom(int* flagp)
+{
+ char* ret;
+ int flags;
+
+ *flagp = WORST; // Tentatively.
+
+ switch (*regparse++) {
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+ case '[': {
+ int rxpclass;
+ int rxpclassend;
+
+ if (*regparse == '^') { // Complement of range.
+ ret = regnode(ANYBUT);
+ regparse++;
+ } else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ rxpclass = UCHARAT(regparse - 2) + 1;
+ rxpclassend = UCHARAT(regparse);
+ if (rxpclass > rxpclassend + 1) {
+ // RAISE Error, SYM(RegularExpression), SYM(Invalid_Range),
+ printf("RegularExpression::compile(): Invalid range in [].\n");
+ return 0;
}
- break;
- }
- return (ret);
+ for (; rxpclass <= rxpclassend; rxpclass++)
+ regc(static_cast<char>(rxpclass));
+ regparse++;
+ }
+ } else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']') {
+ // RAISE Error, SYM(RegularExpression), SYM(Unmatched_Bracket),
+ printf("RegularExpression::compile(): Unmatched [].\n");
+ return 0;
+ }
+ regparse++;
+ *flagp |= HASWIDTH | SIMPLE;
+ } break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == 0)
+ return (0);
+ *flagp |= flags & (HASWIDTH | SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case ')':
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf("RegularExpression::compile(): Internal error.\n"); // Never here
+ return 0;
+ case '?':
+ case '+':
+ case '*':
+ // RAISE Error, SYM(RegularExpression), SYM(No_Operand),
+ printf("RegularExpression::compile(): ?+* follows nothing.\n");
+ return 0;
+ case '\\':
+ if (*regparse == '\0') {
+ // RAISE Error, SYM(RegularExpression), SYM(Trailing_Backslash),
+ printf("RegularExpression::compile(): Trailing backslash.\n");
+ return 0;
+ }
+ ret = regnode(EXACTLY);
+ regc(*regparse++);
+ regc('\0');
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+ default: {
+ int len;
+ char ender;
+
+ regparse--;
+ len = int(strcspn(regparse, META));
+ if (len <= 0) {
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf("RegularExpression::compile(): Internal error.\n");
+ return 0;
+ }
+ ender = *(regparse + len);
+ if (len > 1 && ISMULT(ender))
+ len--; // Back off clear of ?+* operand.
+ *flagp |= HASWIDTH;
+ if (len == 1)
+ *flagp |= SIMPLE;
+ ret = regnode(EXACTLY);
+ while (len > 0) {
+ regc(*regparse++);
+ len--;
+ }
+ regc('\0');
+ } break;
+ }
+ return (ret);
}
-
/*
- regnode - emit a node
Location.
*/
-static char* regnode (char op) {
- char* ret;
- char* ptr;
-
- ret = regcode;
- if (ret == &regdummy) {
- regsize += 3;
- return (ret);
- }
-
- ptr = ret;
- *ptr++ = op;
- *ptr++ = '\0'; // Null "next" pointer.
- *ptr++ = '\0';
- regcode = ptr;
+static char* regnode(char op)
+{
+ char* ret;
+ char* ptr;
+ ret = regcode;
+ if (ret == &regdummy) {
+ regsize += 3;
return (ret);
-}
+ }
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; // Null "next" pointer.
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return (ret);
+}
/*
- regc - emit (if appropriate) a byte of code
*/
-static void regc (char b) {
- if (regcode != &regdummy)
- *regcode++ = b;
- else
- regsize++;
+static void regc(char b)
+{
+ if (regcode != &regdummy)
+ *regcode++ = b;
+ else
+ regsize++;
}
-
/*
- reginsert - insert an operator in front of already-emitted operand
*
* Means relocating the operand.
*/
-static void reginsert (char op, char* opnd) {
- char* src;
- char* dst;
- char* place;
-
- if (regcode == &regdummy) {
- regsize += 3;
- return;
- }
+static void reginsert(char op, char* opnd)
+{
+ char* src;
+ char* dst;
+ char* place;
- src = regcode;
- regcode += 3;
- dst = regcode;
- while (src > opnd)
- *--dst = *--src;
+ if (regcode == &regdummy) {
+ regsize += 3;
+ return;
+ }
- place = opnd; // Op node, where operand used to be.
- *place++ = op;
- *place++ = '\0';
- *place = '\0';
-}
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+ place = opnd; // Op node, where operand used to be.
+ *place++ = op;
+ *place++ = '\0';
+ *place = '\0';
+}
/*
- regtail - set the next-pointer at the end of a node chain
*/
-static void regtail (char* p, const char* val) {
- char* scan;
- char* temp;
- int offset;
-
- if (p == &regdummy)
- return;
-
- // Find last node.
- scan = p;
- for (;;) {
- temp = regnext(scan);
- if (temp == 0)
- break;
- scan = temp;
- }
+static void regtail(char* p, const char* val)
+{
+ char* scan;
+ char* temp;
+ int offset;
- if (OP(scan) == BACK)
- offset = int(scan - val);
- else
- offset = int(val - scan);
- *(scan + 1) = static_cast<char>((offset >> 8) & 0377);
- *(scan + 2) = static_cast<char>(offset & 0377);
-}
+ if (p == &regdummy)
+ return;
+
+ // Find last node.
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == 0)
+ break;
+ scan = temp;
+ }
+ if (OP(scan) == BACK)
+ offset = int(scan - val);
+ else
+ offset = int(val - scan);
+ *(scan + 1) = static_cast<char>((offset >> 8) & 0377);
+ *(scan + 2) = static_cast<char>(offset & 0377);
+}
/*
- regoptail - regtail on operand of first argument; nop if operandless
*/
-static void regoptail (char* p, const char* val) {
- // "Operandless" and "op != BRANCH" are synonymous in practice.
- if (p == 0 || p == &regdummy || OP(p) != BRANCH)
- return;
- regtail(OPERAND(p), val);
+static void regoptail(char* p, const char* val)
+{
+ // "Operandless" and "op != BRANCH" are synonymous in practice.
+ if (p == 0 || p == &regdummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
}
-
-
////////////////////////////////////////////////////////////////////////
-//
+//
// find and friends
-//
+//
////////////////////////////////////////////////////////////////////////
-
/*
* Global work variables for 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.
+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.
/*
* Forwards.
*/
-static int regtry (const char*, const char* *,
- const char* *, const char*);
-static int regmatch (const char*);
-static int regrepeat (const char*);
+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 ();
+int regnarrate = 0;
+void regdump();
+static char* regprop();
#endif
-bool RegularExpression::find (kwsys_stl::string const& s)
-{
- return find(s.c_str());
-}
-
-
-
// 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) {
- const char* s;
+bool RegularExpression::find(const char* string)
+{
+ const char* s;
- this->searchstring = string;
+ this->searchstring = string;
- if (!this->program)
- {
- return false;
- }
+ if (!this->program) {
+ return false;
+ }
- // Check validity of program.
- if (UCHARAT(this->program) != MAGIC) {
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("RegularExpression::find(): Compiled regular expression corrupted.\n");
- return 0;
- }
+ // Check validity of program.
+ if (UCHARAT(this->program) != MAGIC) {
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf(
+ "RegularExpression::find(): Compiled regular expression corrupted.\n");
+ return 0;
+ }
- // If there is a "must appear" string, look for it.
- if (this->regmust != 0) {
- s = string;
- while ((s = strchr(s, this->regmust[0])) != 0) {
- if (strncmp(s, this->regmust, this->regmlen) == 0)
- break; // Found it.
- s++;
- }
- if (s == 0) // Not present.
- return (0);
+ // If there is a "must appear" string, look for it.
+ if (this->regmust != 0) {
+ s = string;
+ while ((s = strchr(s, this->regmust[0])) != 0) {
+ if (strncmp(s, this->regmust, this->regmlen) == 0)
+ break; // Found it.
+ s++;
}
+ if (s == 0) // Not present.
+ return (0);
+ }
- // Mark beginning of line for ^ .
- regbol = string;
-
- // Simplest case: anchored match need be tried only once.
- if (this->reganch)
- return (regtry(string, this->startp, this->endp, this->program) != 0);
+ // Mark beginning of line for ^ .
+ regbol = string;
- // 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);
- s++;
+ // Simplest case: anchored match need be tried only once.
+ if (this->reganch)
+ return (regtry(string, this->startp, this->endp, this->program) != 0);
- }
- else
- // We don't -- general case.
- do {
- if (regtry(s, this->startp, this->endp, this->program))
- return (1);
- } while (*s++ != '\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);
+ s++;
+ }
+ else
+ // We don't -- general case.
+ do {
+ if (regtry(s, this->startp, this->endp, this->program))
+ return (1);
+ } while (*s++ != '\0');
- // Failure.
- return (0);
+ // Failure.
+ return (0);
}
-
/*
- 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 i;
- const char* *sp1;
- const char* *ep;
-
- reginput = string;
- regstartp = start;
- regendp = end;
-
- sp1 = start;
- ep = end;
- for (i = RegularExpression::NSUBEXP; i > 0; i--) {
- *sp1++ = 0;
- *ep++ = 0;
- }
- if (regmatch(prog + 1)) {
- start[0] = string;
- end[0] = reginput;
- return (1);
- }
- else
- return (0);
+static int regtry(const char* string, const char** start, const char** end,
+ const char* prog)
+{
+ int i;
+ const char** sp1;
+ const char** ep;
+
+ reginput = string;
+ regstartp = start;
+ regendp = end;
+
+ sp1 = start;
+ ep = end;
+ for (i = RegularExpression::NSUBEXP; i > 0; i--) {
+ *sp1++ = 0;
+ *ep++ = 0;
+ }
+ if (regmatch(prog + 1)) {
+ start[0] = string;
+ end[0] = reginput;
+ return (1);
+ } else
+ return (0);
}
-
/*
- regmatch - main matching routine
*
@@ -991,261 +955,260 @@ static int regtry (const char* string, const char* *start,
* by recursion.
* 0 failure, 1 success
*/
-static int regmatch (const char* prog) {
- const char* scan; // Current node.
- const char* next; // Next node.
-
- scan = prog;
-
- while (scan != 0) {
-
- next = regnext(scan);
-
- switch (OP(scan)) {
- case BOL:
- if (reginput != regbol)
- return (0);
- break;
- case EOL:
- if (*reginput != '\0')
- return (0);
- break;
- case ANY:
- if (*reginput == '\0')
- return (0);
- reginput++;
- break;
- case EXACTLY:{
- size_t len;
- const char* opnd;
-
- opnd = OPERAND(scan);
- // Inline the first character, for speed.
- if (*opnd != *reginput)
- return (0);
- len = strlen(opnd);
- if (len > 1 && strncmp(opnd, reginput, len) != 0)
- return (0);
- reginput += len;
- }
- break;
- case ANYOF:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == 0)
- return (0);
- reginput++;
- break;
- case ANYBUT:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != 0)
- return (0);
- reginput++;
- break;
- case NOTHING:
- break;
- case BACK:
- break;
- case OPEN + 1:
- case OPEN + 2:
- case OPEN + 3:
- case OPEN + 4:
- case OPEN + 5:
- case OPEN + 6:
- case OPEN + 7:
- case OPEN + 8:
- case OPEN + 9:{
- int no;
- const char* save;
-
- no = OP(scan) - OPEN;
- save = reginput;
-
- if (regmatch(next)) {
-
- //
- // Don't set startp if some later invocation of the
- // same parentheses already has.
- //
- if (regstartp[no] == 0)
- regstartp[no] = save;
- return (1);
- }
- else
- return (0);
- }
-// break;
- case CLOSE + 1:
- case CLOSE + 2:
- case CLOSE + 3:
- case CLOSE + 4:
- case CLOSE + 5:
- case CLOSE + 6:
- case CLOSE + 7:
- case CLOSE + 8:
- case CLOSE + 9:{
- int no;
- const char* save;
-
- no = OP(scan) - CLOSE;
- save = reginput;
-
- if (regmatch(next)) {
-
- //
- // Don't set endp if some later invocation of the
- // same parentheses already has.
- //
- if (regendp[no] == 0)
- regendp[no] = save;
- return (1);
- }
- else
- return (0);
- }
-// break;
- case BRANCH:{
-
- const char* save;
-
- if (OP(next) != BRANCH) // No choice.
- next = OPERAND(scan); // Avoid recursion.
- else {
- do {
- save = reginput;
- if (regmatch(OPERAND(scan)))
- return (1);
- reginput = save;
- scan = regnext(scan);
- } while (scan != 0 && OP(scan) == BRANCH);
- return (0);
- // NOTREACHED
- }
- }
- break;
- case STAR:
- case PLUS:{
- char nextch;
- int no;
- const char* save;
- int min_no;
-
- //
- // Lookahead to avoid useless match attempts when we know
- // what character comes next.
- //
- nextch = '\0';
- if (OP(next) == EXACTLY)
- nextch = *OPERAND(next);
- min_no = (OP(scan) == STAR) ? 0 : 1;
- save = reginput;
- no = regrepeat(OPERAND(scan));
- while (no >= min_no) {
- // If it could work, try it.
- if (nextch == '\0' || *reginput == nextch)
- if (regmatch(next))
- return (1);
- // Couldn't or didn't -- back up.
- no--;
- reginput = save + no;
- }
- return (0);
- }
-// break;
- case END:
- return (1); // Success!
-
- default:
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("RegularExpression::find(): Internal error -- memory corrupted.\n");
- return 0;
+static int regmatch(const char* prog)
+{
+ const char* scan; // Current node.
+ const char* next; // Next node.
+
+ scan = prog;
+
+ while (scan != 0) {
+
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+ if (reginput != regbol)
+ return (0);
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return (0);
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return (0);
+ reginput++;
+ break;
+ case EXACTLY: {
+ size_t len;
+ const char* opnd;
+
+ opnd = OPERAND(scan);
+ // Inline the first character, for speed.
+ if (*opnd != *reginput)
+ return (0);
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return (0);
+ reginput += len;
+ } break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == 0)
+ return (0);
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != 0)
+ return (0);
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN + 1:
+ case OPEN + 2:
+ case OPEN + 3:
+ case OPEN + 4:
+ case OPEN + 5:
+ case OPEN + 6:
+ case OPEN + 7:
+ case OPEN + 8:
+ case OPEN + 9: {
+ int no;
+ const char* save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+
+ //
+ // Don't set startp if some later invocation of the
+ // same parentheses already has.
+ //
+ if (regstartp[no] == 0)
+ regstartp[no] = save;
+ return (1);
+ } else
+ return (0);
+ }
+ // break;
+ case CLOSE + 1:
+ case CLOSE + 2:
+ case CLOSE + 3:
+ case CLOSE + 4:
+ case CLOSE + 5:
+ case CLOSE + 6:
+ case CLOSE + 7:
+ case CLOSE + 8:
+ case CLOSE + 9: {
+ int no;
+ const char* save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+
+ //
+ // Don't set endp if some later invocation of the
+ // same parentheses already has.
+ //
+ if (regendp[no] == 0)
+ regendp[no] = save;
+ return (1);
+ } else
+ return (0);
+ }
+ // break;
+ case BRANCH: {
+
+ const char* save;
+
+ if (OP(next) != BRANCH) // No choice.
+ next = OPERAND(scan); // Avoid recursion.
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return (1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != 0 && OP(scan) == BRANCH);
+ return (0);
+ // NOTREACHED
+ }
+ } break;
+ case STAR:
+ case PLUS: {
+ char nextch;
+ int no;
+ const char* save;
+ int min_no;
+
+ //
+ // Lookahead to avoid useless match attempts when we know
+ // what character comes next.
+ //
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min_no = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min_no) {
+ // If it could work, try it.
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return (1);
+ // Couldn't or didn't -- back up.
+ no--;
+ reginput = save + no;
}
- scan = next;
+ return (0);
+ }
+ // break;
+ case END:
+ return (1); // Success!
+
+ default:
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf(
+ "RegularExpression::find(): Internal error -- memory corrupted.\n");
+ return 0;
}
+ scan = next;
+ }
- //
- // We get here only if there's trouble -- normally "case END" is the
- // terminating point.
- //
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("RegularExpression::find(): Internal error -- corrupted pointers.\n");
- return (0);
+ //
+ // We get here only if there's trouble -- normally "case END" is the
+ // terminating point.
+ //
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf("RegularExpression::find(): Internal error -- corrupted pointers.\n");
+ return (0);
}
-
/*
- regrepeat - repeatedly match something simple, report how many
*/
-static int regrepeat (const char* p) {
- int count = 0;
- const char* scan;
- const char* opnd;
-
- scan = reginput;
- opnd = OPERAND(p);
- switch (OP(p)) {
- case ANY:
- count = int(strlen(scan));
- scan += count;
- break;
- case EXACTLY:
- while (*opnd == *scan) {
- count++;
- scan++;
- }
- break;
- case ANYOF:
- while (*scan != '\0' && strchr(opnd, *scan) != 0) {
- count++;
- scan++;
- }
- break;
- case ANYBUT:
- while (*scan != '\0' && strchr(opnd, *scan) == 0) {
- count++;
- scan++;
- }
- break;
- default: // Oh dear. Called inappropriately.
- //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
- printf ("cm RegularExpression::find(): Internal error.\n");
- return 0;
- }
- reginput = scan;
- return (count);
+static int regrepeat(const char* p)
+{
+ int count = 0;
+ const char* scan;
+ const char* opnd;
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+ count = int(strlen(scan));
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != 0) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+ while (*scan != '\0' && strchr(opnd, *scan) == 0) {
+ count++;
+ scan++;
+ }
+ break;
+ default: // Oh dear. Called inappropriately.
+ // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf("cm RegularExpression::find(): Internal error.\n");
+ return 0;
+ }
+ reginput = scan;
+ return (count);
}
-
/*
- regnext - dig the "next" pointer out of a node
*/
-static const char* regnext (const char* p) {
- int offset;
+static const char* regnext(const char* p)
+{
+ int offset;
- if (p == &regdummy)
- return (0);
+ if (p == &regdummy)
+ return (0);
- offset = NEXT(p);
- if (offset == 0)
- return (0);
+ offset = NEXT(p);
+ if (offset == 0)
+ return (0);
- if (OP(p) == BACK)
- return (p - offset);
- else
- return (p + offset);
+ if (OP(p) == BACK)
+ return (p - offset);
+ else
+ return (p + offset);
}
-static char* regnext (char* p) {
- int offset;
+static char* regnext(char* p)
+{
+ int offset;
- if (p == &regdummy)
- return (0);
+ if (p == &regdummy)
+ return (0);
- offset = NEXT(p);
- if (offset == 0)
- return (0);
+ offset = NEXT(p);
+ if (offset == 0)
+ return (0);
- if (OP(p) == BACK)
- return (p - offset);
- else
- return (p + offset);
+ if (OP(p) == BACK)
+ return (p - offset);
+ else
+ return (p + offset);
}
} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index 62e9cad23..606e3da6e 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
// Original Copyright notice:
// Copyright (C) 1991 Texas Instruments Incorporated.
//
@@ -33,21 +24,15 @@
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/Configure.hxx>
-#include <@KWSYS_NAMESPACE@/stl/string>
-
-/* Define this macro temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsys_stl @KWSYS_NAMESPACE@_stl
-#endif
+#include <string>
/* 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@
-{
+namespace @KWSYS_NAMESPACE@ {
/** \class RegularExpression
* \brief Implements pattern matching with regular expressions.
@@ -73,10 +58,10 @@ namespace @KWSYS_NAMESPACE@
* and utilities.
*
* Example: The perl code
- *
+ *
* $filename =~ m"([a-z]+)\.cc";
* print $1;
- *
+ *
* Is written as follows in C++
*
* RegularExpression re("([a-z]+)\\.cc");
@@ -186,23 +171,28 @@ namespace @KWSYS_NAMESPACE@
* the line. It would match "drepa qrepb" in "rep drepa qrepb".
*
*/
-class @KWSYS_NAMESPACE@_EXPORT RegularExpression
+class @KWSYS_NAMESPACE@_EXPORT RegularExpression
{
public:
/**
* Instantiate RegularExpression with program=NULL.
*/
- inline RegularExpression ();
+ inline RegularExpression();
/**
* Instantiate RegularExpression with compiled char*.
*/
- inline RegularExpression (char const*);
-
+ inline RegularExpression(char const*);
+
/**
* Instantiate RegularExpression as a copy of another regular expression.
*/
- RegularExpression (RegularExpression const&);
+ RegularExpression(RegularExpression const&);
+
+ /**
+ * Instantiate RegularExpression with compiled string.
+ */
+ inline RegularExpression(std::string const&);
/**
* Destructor.
@@ -213,53 +203,59 @@ public:
* Compile a regular expression into internal code
* for later pattern matching.
*/
- bool compile (char const*);
+ bool compile(char const*);
+
+ /**
+ * Compile a regular expression into internal code
+ * for later pattern matching.
+ */
+ inline bool compile(std::string const&);
/**
* Matches the regular expression to the given string.
* Returns true if found, and sets start and end indexes accordingly.
*/
- bool find (char const*);
+ bool find(char const*);
/**
* Matches the regular expression to the given std string.
* Returns true if found, and sets start and end indexes accordingly.
*/
- bool find (kwsys_stl::string const&);
+ inline bool find(std::string const&);
/**
* Index to start of first find.
*/
- inline kwsys_stl::string::size_type start() const;
+ inline std::string::size_type start() const;
/**
* Index to end of first find.
*/
- inline kwsys_stl::string::size_type end() const;
+ inline std::string::size_type end() const;
/**
* Copy the given regular expression.
*/
- RegularExpression& operator= (const RegularExpression& rxp);
+ RegularExpression& operator=(const RegularExpression& rxp);
/**
* Returns true if two regular expressions have the same
* compiled program for pattern matching.
*/
- bool operator== (RegularExpression const&) const;
+ bool operator==(RegularExpression const&) const;
/**
* Returns true if two regular expressions have different
* compiled program for pattern matching.
*/
- inline bool operator!= (RegularExpression const&) const;
+ inline bool operator!=(RegularExpression const&) const;
/**
* Returns true if have the same compiled regular expressions
* and the same start and end pointers.
*/
- bool deep_equal (RegularExpression const&) const;
-
+ bool deep_equal(RegularExpression const&) const;
+
/**
* True if the compiled regexp is valid.
*/
@@ -268,34 +264,38 @@ public:
/**
* Marks the regular expression as invalid.
*/
- inline void set_invalid();
+ inline void set_invalid();
/**
* Destructor.
*/
// awf added
- kwsys_stl::string::size_type start(int n) const;
- kwsys_stl::string::size_type end(int n) const;
- kwsys_stl::string match(int n) const;
-
- enum { NSUBEXP = 10 };
-private:
+ 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];
- char regstart; // Internal use only
- char reganch; // Internal use only
- const char* regmust; // Internal use only
- kwsys_stl::string::size_type regmlen; // Internal use only
- char* program;
- int progsize;
+ 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 ()
-{
+inline RegularExpression::RegularExpression()
+{
this->program = 0;
}
@@ -303,112 +303,123 @@ inline RegularExpression::RegularExpression ()
* Creates a regular expression from string s, and
* compiles s.
*/
-inline RegularExpression::RegularExpression (const char* s)
-{
+inline RegularExpression::RegularExpression(const char* s)
+{
this->program = 0;
- if ( s )
- {
+ if (s) {
this->compile(s);
- }
+ }
+}
+
+/**
+ * Creates a regular expression from string s, and
+ * compiles s.
+ */
+inline RegularExpression::RegularExpression(const std::string& s)
+{
+ this->program = 0;
+ this->compile(s);
}
/**
* Destroys and frees space allocated for the regular expression.
*/
-inline RegularExpression::~RegularExpression ()
+inline RegularExpression::~RegularExpression()
{
-//#ifndef WIN32
- delete [] this->program;
-//#endif
+ //#ifndef _WIN32
+ delete[] this->program;
+ //#endif
}
/**
- * Set the start position for the regular expression.
+ * Compile a regular expression into internal code
+ * for later pattern matching.
+ */
+inline bool RegularExpression::compile(std::string const& s)
+{
+ return this->compile(s.c_str());
+}
+
+/**
+ * Matches the regular expression to the given std string.
+ * Returns true if found, and sets start and end indexes accordingly.
*/
-inline kwsys_stl::string::size_type RegularExpression::start () const
+inline bool RegularExpression::find(std::string const& s)
{
- return static_cast<kwsys_stl::string::size_type>(
- this->startp[0] - searchstring);
+ return this->find(s.c_str());
}
+/**
+ * Set the start position for the regular expression.
+ */
+inline std::string::size_type RegularExpression::start() const
+{
+ return static_cast<std::string::size_type>(this->startp[0] - searchstring);
+}
/**
* Returns the start/end index of the last item found.
*/
-inline kwsys_stl::string::size_type RegularExpression::end () const
+inline std::string::size_type RegularExpression::end() const
{
- return static_cast<kwsys_stl::string::size_type>(
- this->endp[0] - searchstring);
+ return static_cast<std::string::size_type>(this->endp[0] - searchstring);
}
/**
* Returns true if two regular expressions have different
* compiled program for pattern matching.
*/
-inline bool RegularExpression::operator!= (const RegularExpression& r) const
+inline bool RegularExpression::operator!=(const RegularExpression& r) const
{
- return(!(*this == r));
+ return (!(*this == r));
}
/**
* Returns true if a valid regular expression is compiled
* and ready for pattern matching.
*/
-inline bool RegularExpression::is_valid () const
+inline bool RegularExpression::is_valid() const
{
return (this->program != 0);
}
-
-inline void RegularExpression::set_invalid ()
+inline void RegularExpression::set_invalid()
{
-//#ifndef WIN32
- delete [] this->program;
-//#endif
+ //#ifndef _WIN32
+ delete[] this->program;
+ //#endif
this->program = 0;
}
/**
* Return start index of nth submatch. start(0) is the start of the full match.
*/
-inline kwsys_stl::string::size_type RegularExpression::start(int n) const
+inline std::string::size_type RegularExpression::start(int n) const
{
- return static_cast<kwsys_stl::string::size_type>(
- this->startp[n] - searchstring);
+ return static_cast<std::string::size_type>(this->startp[n] - searchstring);
}
-
/**
* Return end index of nth submatch. end(0) is the end of the full match.
*/
-inline kwsys_stl::string::size_type RegularExpression::end(int n) const
+inline std::string::size_type RegularExpression::end(int n) const
{
- return static_cast<kwsys_stl::string::size_type>(
- this->endp[n] - searchstring);
+ return static_cast<std::string::size_type>(this->endp[n] - searchstring);
}
/**
* Return nth submatch as a string.
*/
-inline kwsys_stl::string RegularExpression::match(int n) const
+inline std::string RegularExpression::match(int n) const
{
- if (this->startp[n]==0)
- {
- return kwsys_stl::string("");
- }
- else
- {
- return kwsys_stl::string(this->startp[n],
- static_cast<kwsys_stl::string::size_type>(
- this->endp[n] - this->startp[n]));
- }
+ 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]));
+ }
}
} // namespace @KWSYS_NAMESPACE@
-/* Undefine temporary macro. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# undef kwsys_stl
-#endif
-
#endif
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in
index 8bbc74ac2..f638267ec 100644
--- a/Source/kwsys/SharedForward.h.in
+++ b/Source/kwsys/SharedForward.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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
@@ -30,7 +21,8 @@
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD "." CONFIG_DIR_POST
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL "../lib/foo-1.2"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD CONFIG_DIR_PRE "foo-real"
- #define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL "../lib/foo-1.2/foo-real"
+ #define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
+ "../lib/foo-1.2/foo-real"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND "--command"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT "--print"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD "--ldd"
@@ -65,124 +57,150 @@
See the comments below for specific explanations of each macro.
*/
-/*--------------------------------------------------------------------------*/
+/* 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)
+/* 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
/* 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"
+#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
+#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"
+#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
+#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"
+#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
+#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"
+#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
+#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"
+#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
+#define KWSYS_SHARED_FORWARD_EXE_INSTALL \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
#endif
-/* The configuration name with which this executable was built (Debug/Release). */
+/* 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
+#define KWSYS_SHARED_FORWARD_CONFIG_NAME \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME
#else
-# undef KWSYS_SHARED_FORWARD_CONFIG_NAME
+#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
+#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
+#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
+#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
+#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
+#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
+#undef KWSYS_SHARED_FORWARD_OPTION_LDD
#endif
-/*--------------------------------------------------------------------------*/
/* Include needed system headers. */
-#include <stddef.h> /* size_t */
+#include <errno.h>
#include <limits.h>
+#include <stddef.h> /* size_t */
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-#include <stdio.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <io.h>
-# include <windows.h>
-# include <process.h>
-# define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
+#include <windows.h>
+
+#include <io.h>
+#include <process.h>
+#define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
#else
-# include <unistd.h>
-# include <sys/stat.h>
+#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 '\\'
+#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 '/'
+#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};
-static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PATH_SLASH, 0};
+static const char kwsys_shared_forward_path_sep[2] = {
+ KWSYS_SHARED_FORWARD_PATH_SEP, 0
+};
+static const char kwsys_shared_forward_path_slash[2] = {
+ KWSYS_SHARED_FORWARD_PATH_SLASH, 0
+};
/* The maximum length of a file name. */
#if defined(PATH_MAX)
-# define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
+#define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
-# define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
+#define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
#else
-# define KWSYS_SHARED_FORWARD_MAXPATH 16384
+#define KWSYS_SHARED_FORWARD_MAXPATH 16384
#endif
/* Select the environment variable holding the shared library runtime
@@ -191,86 +209,85 @@ static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PAT
/* 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"
+#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"
+#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"
+#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"
+#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"
+#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
+#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
+#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
+#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"
+#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"
+#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"
+#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
-/*--------------------------------------------------------------------------*/
typedef struct kwsys_sf_arg_info_s
{
const char* arg;
@@ -278,7 +295,6 @@ typedef struct kwsys_sf_arg_info_s
int quote;
} kwsys_sf_arg_info;
-/*--------------------------------------------------------------------------*/
static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
{
/* Initialize information. */
@@ -297,50 +313,41 @@ static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
info.quote = 0;
/* Scan the string for characters that require escaping or quoting. */
- for(c=in; *c; ++c)
- {
+ for (c = in; *c; ++c) {
/* Check whether this character needs quotes. */
- if(strchr(" \t?'#&<>|^", *c))
- {
+ if (strchr(" \t?'#&<>|^", *c)) {
info.quote = 1;
- }
+ }
/* On Windows only backslashes and double-quotes need escaping. */
- if(*c == '\\')
- {
+ if (*c == '\\') {
/* Found a backslash. It may need to be escaped later. */
++windows_backslashes;
- }
- else if(*c == '"')
- {
+ } else if (*c == '"') {
/* Found a double-quote. We need to escape it and all
immediately preceding backslashes. */
info.size += windows_backslashes + 1;
windows_backslashes = 0;
- }
- else
- {
+ } else {
/* Found another character. This eliminates the possibility
that any immediately preceding backslashes will be
escaped. */
windows_backslashes = 0;
- }
}
+ }
/* Check whether the argument needs surrounding quotes. */
- if(info.quote)
- {
+ if (info.quote) {
/* Surrounding quotes are needed. Allocate space for them. */
info.size += 2;
/* We must escape all ending backslashes when quoting on windows. */
info.size += windows_backslashes;
- }
+ }
return info;
}
-/*--------------------------------------------------------------------------*/
static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
{
/* String iterator. */
@@ -350,57 +357,47 @@ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
int windows_backslashes = 0;
/* Whether the argument must be quoted. */
- if(info.quote)
- {
+ if (info.quote) {
/* Add the opening quote for this argument. */
*out++ = '"';
- }
+ }
/* Scan the string for characters that require escaping or quoting. */
- for(c=info.arg; *c; ++c)
- {
+ for (c = info.arg; *c; ++c) {
/* On Windows only backslashes and double-quotes need escaping. */
- if(*c == '\\')
- {
+ if (*c == '\\') {
/* Found a backslash. It may need to be escaped later. */
++windows_backslashes;
- }
- else if(*c == '"')
- {
+ } else if (*c == '"') {
/* Found a double-quote. Escape all immediately preceding
backslashes. */
- while(windows_backslashes > 0)
- {
+ while (windows_backslashes > 0) {
--windows_backslashes;
*out++ = '\\';
- }
+ }
/* Add the backslash to escape the double-quote. */
*out++ = '\\';
- }
- else
- {
+ } else {
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */
windows_backslashes = 0;
- }
+ }
/* Store this character. */
*out++ = *c;
- }
+ }
- if(info.quote)
- {
+ if (info.quote) {
/* Add enough backslashes to escape any trailing ones. */
- while(windows_backslashes > 0)
- {
+ while (windows_backslashes > 0) {
--windows_backslashes;
*out++ = '\\';
- }
+ }
/* Add the closing quote for this argument. */
*out++ = '"';
- }
+ }
/* Store a terminating null without incrementing. */
*out = 0;
@@ -409,14 +406,13 @@ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
}
#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__)
/* Implementation for Windows. */
- DWORD n = GetFullPathName(in_path, KWSYS_SHARED_FORWARD_MAXPATH,
- out_path, 0);
+ DWORD n =
+ GetFullPathNameA(in_path, KWSYS_SHARED_FORWARD_MAXPATH, out_path, 0);
return n > 0 && n <= KWSYS_SHARED_FORWARD_MAXPATH;
#else
/* Implementation for UNIX. */
@@ -424,17 +420,15 @@ static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
#endif
}
-/*--------------------------------------------------------------------------*/
static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
{
#if defined(_WIN32)
int result = 0;
- HANDLE h1 = CreateFile(file1, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- HANDLE h2 = CreateFile(file2, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if(h1 != INVALID_HANDLE_VALUE && h2 != INVALID_HANDLE_VALUE)
- {
+ HANDLE h1 = CreateFileA(file1, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ HANDLE h2 = CreateFileA(file2, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (h1 != INVALID_HANDLE_VALUE && h2 != INVALID_HANDLE_VALUE) {
BY_HANDLE_FILE_INFORMATION fi1;
BY_HANDLE_FILE_INFORMATION fi2;
GetFileInformationByHandle(h1, &fi1);
@@ -442,10 +436,10 @@ static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
result = (fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber &&
fi1.nFileIndexHigh == fi2.nFileIndexHigh &&
fi1.nFileIndexLow == fi2.nFileIndexLow);
- }
- CloseHandle(h1);
- CloseHandle(h2);
- return result;
+ }
+ CloseHandle(h1);
+ CloseHandle(h2);
+ return result;
#else
struct stat fs1, fs2;
return (stat(file1, &fs1) == 0 && stat(file2, &fs2) == 0 &&
@@ -455,31 +449,28 @@ static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
#endif
}
-/*--------------------------------------------------------------------------*/
/* Function to report a system error message. */
static void kwsys_shared_forward_strerror(char* message)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Implementation for Windows. */
DWORD original = GetLastError();
- DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- message, KWSYS_SHARED_FORWARD_MAXPATH, 0);
- if(length < 1 || length > KWSYS_SHARED_FORWARD_MAXPATH)
- {
+ DWORD length =
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ 0, original, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ message, KWSYS_SHARED_FORWARD_MAXPATH, 0);
+ if (length < 1 || length > KWSYS_SHARED_FORWARD_MAXPATH) {
/* FormatMessage failed. Use a default message. */
_snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH,
- "Error 0x%X (FormatMessage failed with error 0x%X)",
- original, GetLastError());
- }
+ "Error 0x%X (FormatMessage failed with error 0x%X)", original,
+ GetLastError());
+ }
#else
/* Implementation for UNIX. */
strcpy(message, strerror(errno));
#endif
}
-/*--------------------------------------------------------------------------*/
/* Functions to execute a child process. */
static void kwsys_shared_forward_execvp(const char* cmd,
char const* const* argv)
@@ -488,236 +479,213 @@ static void kwsys_shared_forward_execvp(const char* cmd,
/* Count the number of arguments. */
int argc = 0;
{
- char const* const* argvc;
- for(argvc = argv; *argvc; ++argvc,++argc) {}
+ char const* const* argvc;
+ for (argvc = argv; *argvc; ++argvc, ++argc) {
+ }
}
/* Create the escaped arguments. */
{
- char** nargv = (char**)malloc((argc+1) * sizeof(char*));
- int i;
- for(i=0; i < argc; ++i)
- {
- kwsys_sf_arg_info info = kwsys_sf_get_arg_info(argv[i]);
- nargv[i] = (char*)malloc(info.size);
- kwsys_sf_get_arg(info, nargv[i]);
+ char** nargv = (char**)malloc((argc + 1) * sizeof(char*));
+ int i;
+ for (i = 0; i < argc; ++i) {
+ kwsys_sf_arg_info info = kwsys_sf_get_arg_info(argv[i]);
+ nargv[i] = (char*)malloc(info.size);
+ kwsys_sf_get_arg(info, nargv[i]);
}
- nargv[argc] = 0;
+ nargv[argc] = 0;
- /* Replace the command line to be used. */
- argv = (char const* const*)nargv;
+ /* Replace the command line to be used. */
+ argv = (char const* const*)nargv;
}
#endif
- /* Invoke the child process. */
+/* Invoke the child process. */
#if defined(_MSC_VER)
_execvp(cmd, argv);
-#elif defined(__MINGW32__)
+#elif defined(__MINGW32__) && !defined(__MINGW64__)
execvp(cmd, argv);
#else
execvp(cmd, (char* const*)argv);
#endif
}
-/*--------------------------------------------------------------------------*/
/* Function to get the directory containing the given file or directory. */
static void kwsys_shared_forward_dirname(const char* begin, char* result)
{
/* Find the location of the last slash. */
int last_slash_index = -1;
const char* end = begin + strlen(begin);
- for(;begin <= end && last_slash_index < 0; --end)
- {
- if(*end == '/' || *end == '\\')
- {
- last_slash_index = (int)(end-begin);
- }
+ for (; begin <= end && last_slash_index < 0; --end) {
+ if (*end == '/' || *end == '\\') {
+ last_slash_index = (int)(end - begin);
}
+ }
/* Handle each case of the index of the last slash. */
- if(last_slash_index < 0)
- {
+ if (last_slash_index < 0) {
/* No slashes. */
strcpy(result, ".");
- }
- else if(last_slash_index == 0)
- {
+ } else if (last_slash_index == 0) {
/* Only one leading slash. */
strcpy(result, kwsys_shared_forward_path_slash);
- }
+ }
#if defined(_WIN32)
- else if(last_slash_index == 2 && begin[1] == ':')
- {
+ 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;
- }
+ result[last_slash_index + 1] = 0;
+ }
#endif
- else
- {
+ else {
/* A non-leading slash. */
strncpy(result, begin, (size_t)last_slash_index);
result[last_slash_index] = 0;
- }
+ }
}
-/*--------------------------------------------------------------------------*/
/* 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
+#define KWSYS_SHARED_FORWARD_ACCESS _access
#else
-# define KWSYS_SHARED_FORWARD_ACCESS access
+#define KWSYS_SHARED_FORWARD_ACCESS access
#endif
#if defined(X_OK)
-# define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
+#define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
#else
-# define KWSYS_SHARED_FORWARD_ACCESS_OK 04
+#define KWSYS_SHARED_FORWARD_ACCESS_OK 04
#endif
- if(KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0)
- {
+ if (KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0) {
return 1;
- }
- else
- {
+ } else {
return 0;
- }
+ }
}
-/*--------------------------------------------------------------------------*/
/* Function to locate the executable currently running. */
static int kwsys_shared_forward_self_path(const char* argv0, char* result)
{
/* Check whether argv0 has a slash. */
int has_slash = 0;
const char* p = argv0;
- for(;*p && !has_slash; ++p)
- {
- if(*p == '/' || *p == '\\')
- {
+ for (; *p && !has_slash; ++p) {
+ if (*p == '/' || *p == '\\') {
has_slash = 1;
- }
}
+ }
- if(has_slash)
- {
+ if (has_slash) {
/* There is a slash. Use the dirname of the given location. */
kwsys_shared_forward_dirname(argv0, result);
return 1;
- }
- else
- {
+ } else {
/* There is no slash. Search the PATH for the executable. */
const char* path = getenv("PATH");
const char* begin = path;
- const char* end = begin + (begin?strlen(begin):0);
+ const char* end = begin + (begin ? strlen(begin) : 0);
const char* first = begin;
- while(first != end)
- {
+ while (first != end) {
/* Store the end of this path entry. */
const char* last;
/* Skip all path separators. */
- for(;*first && *first == KWSYS_SHARED_FORWARD_PATH_SEP; ++first);
+ for (; *first && *first == KWSYS_SHARED_FORWARD_PATH_SEP; ++first)
+ ;
/* Find the next separator. */
- for(last = first;*last && *last != KWSYS_SHARED_FORWARD_PATH_SEP; ++last);
+ for (last = first; *last && *last != KWSYS_SHARED_FORWARD_PATH_SEP;
+ ++last)
+ ;
/* If we got a non-empty directory, look for the executable there. */
- if(first < last)
- {
+ if (first < last) {
/* Determine the length without trailing slash. */
- size_t length = (size_t)(last-first);
- if(*(last-1) == '/' || *(last-1) == '\\')
- {
+ size_t length = (size_t)(last - first);
+ if (*(last - 1) == '/' || *(last - 1) == '\\') {
--length;
- }
+ }
/* Construct the name of the executable in this location. */
strncpy(result, first, length);
result[length] = KWSYS_SHARED_FORWARD_PATH_SLASH;
- strcpy(result+(length)+1, argv0);
+ strcpy(result + (length) + 1, argv0);
/* Check if it exists and is executable. */
- if(kwsys_shared_forward_is_executable(result))
- {
+ if (kwsys_shared_forward_is_executable(result)) {
/* Found it. */
result[length] = 0;
return 1;
- }
}
+ }
/* Move to the next directory in the path. */
first = last;
- }
}
+ }
/* We could not find the executable. */
return 0;
}
-/*--------------------------------------------------------------------------*/
/* Function to convert a specified path to a full path. If it is not
already full, it is taken relative to the self path. */
static int kwsys_shared_forward_fullpath(const char* self_path,
- const char* in_path,
- char* result,
+ const char* in_path, char* result,
const char* desc)
{
/* Check the specified path type. */
- if(in_path[0] == '/')
- {
+ if (in_path[0] == '/') {
/* Already a full path. */
strcpy(result, in_path);
- }
+ }
#if defined(_WIN32)
- else if(in_path[0] && in_path[1] == ':')
- {
+ else if (in_path[0] && in_path[1] == ':') {
/* Already a full path. */
strcpy(result, in_path);
- }
+ }
#endif
- else
- {
+ else {
/* Relative to self path. */
char temp_path[KWSYS_SHARED_FORWARD_MAXPATH];
strcpy(temp_path, self_path);
strcat(temp_path, kwsys_shared_forward_path_slash);
strcat(temp_path, in_path);
- if(!kwsys_shared_forward_realpath(temp_path, result))
- {
- if(desc)
- {
+ if (!kwsys_shared_forward_realpath(temp_path, result)) {
+ if (desc) {
char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH];
kwsys_shared_forward_strerror(msgbuf);
- fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n",
- desc, temp_path, msgbuf);
- }
- return 0;
+ fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n", desc,
+ temp_path, msgbuf);
}
+ return 0;
}
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
/* Function to compute the library search path and executable name
based on the self path. */
static int kwsys_shared_forward_get_settings(const char* self_path,
char* ldpath, char* exe)
{
/* Possible search paths. */
- static const char* search_path_build[] = {KWSYS_SHARED_FORWARD_PATH_BUILD, 0};
- static const char* search_path_install[] = {KWSYS_SHARED_FORWARD_PATH_INSTALL, 0};
+ static const char* search_path_build[] = { KWSYS_SHARED_FORWARD_PATH_BUILD,
+ 0 };
+ static const char* search_path_install[] = {
+ KWSYS_SHARED_FORWARD_PATH_INSTALL, 0
+ };
/* Chosen paths. */
const char** search_path;
const char* exe_path;
- /* Get the real name of the build and self paths. */
+/* Get the real name of the build and self paths. */
#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
- char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD "/" 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
char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD;
@@ -725,19 +693,17 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
#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))
- {
+ if (!kwsys_shared_forward_realpath(self_path, self_path_real)) {
char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH];
kwsys_shared_forward_strerror(msgbuf);
fprintf(stderr, "Error converting self path \"%s\" to real path: %s\n",
self_path, msgbuf);
return 0;
- }
+ }
/* Check whether we are running in the build tree or an install tree. */
- if(kwsys_shared_forward_realpath(build_path, build_path_real) &&
- kwsys_shared_forward_samepath(self_path_real, build_path_real))
- {
+ if (kwsys_shared_forward_realpath(build_path, build_path_real) &&
+ 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)
@@ -750,9 +716,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
/* Remove the configuration directory from self_path. */
kwsys_shared_forward_dirname(self_path, self_path_logical);
#endif
- }
- else
- {
+ } else {
/* Running in install tree. Use the install path and exe. */
search_path = search_path_install;
#if defined(_WIN32)
@@ -765,39 +729,34 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
/* Use the original self path directory. */
strcpy(self_path_logical, self_path);
#endif
- }
+ }
/* Construct the runtime search path. */
{
- const char** dir;
- for(dir = search_path; *dir; ++dir)
- {
- /* Add separator between path components. */
- if(dir != search_path)
- {
- strcat(ldpath, kwsys_shared_forward_path_sep);
+ const char** dir;
+ for (dir = search_path; *dir; ++dir) {
+ /* Add separator between path components. */
+ if (dir != search_path) {
+ strcat(ldpath, kwsys_shared_forward_path_sep);
}
- /* Add this path component. */
- if(!kwsys_shared_forward_fullpath(self_path_logical, *dir,
- ldpath+strlen(ldpath),
- "runtime path entry"))
- {
- return 0;
+ /* Add this path component. */
+ if (!kwsys_shared_forward_fullpath(self_path_logical, *dir,
+ ldpath + strlen(ldpath),
+ "runtime path entry")) {
+ return 0;
}
}
}
/* Construct the executable location. */
- if(!kwsys_shared_forward_fullpath(self_path_logical, exe_path, exe,
- "executable file"))
- {
+ if (!kwsys_shared_forward_fullpath(self_path_logical, exe_path, exe,
+ "executable file")) {
return 0;
- }
+ }
return 1;
}
-/*--------------------------------------------------------------------------*/
/* Function to print why execution of a command line failed. */
static void kwsys_shared_forward_print_failure(char const* const* argv)
{
@@ -805,91 +764,83 @@ static void kwsys_shared_forward_print_failure(char const* const* argv)
char const* const* arg = argv;
kwsys_shared_forward_strerror(msg);
fprintf(stderr, "Error running");
- for(; *arg; ++arg)
- {
+ for (; *arg; ++arg) {
fprintf(stderr, " \"%s\"", *arg);
- }
+ }
fprintf(stderr, ": %s\n", msg);
}
/* Static storage space to store the updated environment variable. */
-static char kwsys_shared_forward_ldpath[KWSYS_SHARED_FORWARD_MAXPATH*16] = KWSYS_SHARED_FORWARD_LDPATH "=";
+static char kwsys_shared_forward_ldpath[65535] =
+ KWSYS_SHARED_FORWARD_LDPATH "=";
-/*--------------------------------------------------------------------------*/
/* Main driver function to be called from main. */
static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
{
char const** argv = (char const**)argv_in;
/* Get the directory containing this executable. */
char self_path[KWSYS_SHARED_FORWARD_MAXPATH];
- if(kwsys_shared_forward_self_path(argv[0], self_path))
- {
+ if (kwsys_shared_forward_self_path(argv[0], self_path)) {
/* Found this executable. Use it to get the library directory. */
char exe[KWSYS_SHARED_FORWARD_MAXPATH];
- if(kwsys_shared_forward_get_settings(self_path,
- kwsys_shared_forward_ldpath, exe))
- {
+ if (kwsys_shared_forward_get_settings(self_path,
+ kwsys_shared_forward_ldpath, exe)) {
/* Append the old runtime search path. */
const char* old_ldpath = getenv(KWSYS_SHARED_FORWARD_LDPATH);
- if(old_ldpath)
- {
+ if (old_ldpath) {
strcat(kwsys_shared_forward_ldpath, kwsys_shared_forward_path_sep);
strcat(kwsys_shared_forward_ldpath, old_ldpath);
- }
+ }
/* Store the environment variable. */
putenv(kwsys_shared_forward_ldpath);
#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)
- {
- if(argc > 2)
- {
+ if (argc > 1 &&
+ strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_COMMAND) == 0) {
+ if (argc > 2) {
/* Use the command line given. */
strcpy(exe, argv[2]);
argv += 2;
argc -= 2;
- }
- else
- {
+ } else {
/* The option was not given an executable. */
fprintf(stderr, "Option " KWSYS_SHARED_FORWARD_OPTION_COMMAND
- " must be followed by a command line.\n");
+ " must be followed by a command line.\n");
return 1;
- }
}
+ }
#endif
#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)
- {
+ if (argc > 1 &&
+ strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_PRINT) == 0) {
fprintf(stdout, "%s\n", kwsys_shared_forward_ldpath);
fprintf(stdout, "%s\n", exe);
return 0;
- }
+ }
#endif
#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 (argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_LDD) == 0) {
+#if defined(KWSYS_SHARED_FORWARD_LDD)
/* Use the named ldd-like executable and arguments. */
- char const* ldd_argv[] = {KWSYS_SHARED_FORWARD_LDD, 0, 0};
+ char const* ldd_argv[] = { KWSYS_SHARED_FORWARD_LDD, 0, 0 };
ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe;
kwsys_shared_forward_execvp(ldd_argv[0], ldd_argv);
/* 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
/* Replace this process with the real executable. */
@@ -898,17 +849,13 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
/* Report why execution failed. */
kwsys_shared_forward_print_failure(argv);
- }
- else
- {
+ } else {
/* Could not convert self path to the library directory. */
- }
}
- else
- {
+ } else {
/* Could not find this executable. */
fprintf(stderr, "Error locating executable \"%s\".\n", argv[0]);
- }
+ }
/* Avoid unused argument warning. */
(void)argc;
@@ -917,6 +864,13 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
return 1;
}
+/* Restore warning stack. */
+#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 ed4a6c52a..048222968 100644
--- a/Source/kwsys/String.c
+++ b/Source/kwsys/String.c
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef KWSYS_STRING_C
/*
All code in this source file is conditionally compiled to work-around
@@ -23,53 +14,49 @@ condition blocks the compiler from seeing the symbols defined here.
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-# include "String.h.in"
+#include "String.h.in"
#endif
/* Select an implementation for strcasecmp. */
#if defined(_MSC_VER)
-# define KWSYS_STRING_USE_STRICMP
-# include <string.h>
+#define KWSYS_STRING_USE_STRICMP
+#include <string.h>
#elif defined(__GNUC__)
-# define KWSYS_STRING_USE_STRCASECMP
-# include <strings.h>
+#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[] =
-{
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
+static char kwsysString_strcasecmp_tolower[] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010',
+ '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021',
+ '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032',
+ '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043',
+ '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054',
+ '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065',
+ '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076',
+ '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160',
+ '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171',
+ '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142',
+ '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153',
+ '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164',
+ '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175',
+ '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206',
+ '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230',
+ '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241',
+ '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252',
+ '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263',
+ '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274',
+ '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305',
+ '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316',
+ '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340',
+ '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351',
+ '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362',
+ '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373',
+ '\374', '\375', '\376', '\377'
};
#endif
@@ -85,9 +72,8 @@ int kwsysString_strcasecmp(const char* lhs, const char* rhs)
unsigned char const* us1 = (unsigned char const*)lhs;
unsigned char const* us2 = (unsigned char const*)rhs;
int result;
- while((result = lower[*us1] - lower[*us2++], result == 0) && *us1++)
- {
- }
+ while ((result = lower[*us1] - lower[*us2++], result == 0) && *us1++) {
+ }
return result;
#endif
}
@@ -104,10 +90,9 @@ int kwsysString_strncasecmp(const char* lhs, const char* rhs, size_t n)
unsigned char const* us1 = (unsigned char const*)lhs;
unsigned char const* us2 = (unsigned char const*)rhs;
int result = 0;
- while(n && (result = lower[*us1] - lower[*us2++], result == 0) && *us1++)
- {
+ while (n && (result = lower[*us1] - lower[*us2++], result == 0) && *us1++) {
--n;
- }
+ }
return result;
#endif
}
diff --git a/Source/kwsys/String.h.in b/Source/kwsys/String.h.in
index f5bab6e1a..3c1d571c0 100644
--- a/Source/kwsys/String.h.in
+++ b/Source/kwsys/String.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_String_h
#define @KWSYS_NAMESPACE@_String_h
@@ -21,17 +12,16 @@
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)
-extern "C"
-{
+extern "C" {
#endif
/**
@@ -56,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/String.hxx.in b/Source/kwsys/String.hxx.in
index 4386c9eb7..db1cf22a9 100644
--- a/Source/kwsys/String.hxx.in
+++ b/Source/kwsys/String.hxx.in
@@ -1,21 +1,11 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_String_hxx
#define @KWSYS_NAMESPACE@_String_hxx
-#include <@KWSYS_NAMESPACE@/stl/string>
+#include <string>
-namespace @KWSYS_NAMESPACE@
-{
+namespace @KWSYS_NAMESPACE@ {
/** \class String
* \brief Short-name version of the STL basic_string class template.
@@ -25,39 +15,49 @@ namespace @KWSYS_NAMESPACE@
* simply a subclass of this type with the same interface so that the
* name is shorter in debugging symbols and error messages.
*/
-class String: public @KWSYS_NAMESPACE@_stl::string
+class String : public std::string
{
/** The original string type. */
- typedef @KWSYS_NAMESPACE@_stl::string stl_string;
+ typedef std::string stl_string;
public:
-
/** String member types. */
- typedef stl_string::value_type value_type;
- typedef stl_string::pointer pointer;
- typedef stl_string::reference reference;
- typedef stl_string::const_reference const_reference;
- typedef stl_string::size_type size_type;
- typedef stl_string::difference_type difference_type;
- typedef stl_string::iterator iterator;
- typedef stl_string::const_iterator const_iterator;
- typedef stl_string::reverse_iterator reverse_iterator;
+ typedef stl_string::value_type value_type;
+ typedef stl_string::pointer pointer;
+ typedef stl_string::reference reference;
+ typedef stl_string::const_reference const_reference;
+ typedef stl_string::size_type size_type;
+ typedef stl_string::difference_type difference_type;
+ typedef stl_string::iterator iterator;
+ typedef stl_string::const_iterator const_iterator;
+ typedef stl_string::reverse_iterator reverse_iterator;
typedef stl_string::const_reverse_iterator const_reverse_iterator;
/** String constructors. */
- String(): stl_string() {}
- String(const value_type* s): stl_string(s) {}
- String(const value_type* s, size_type n): stl_string(s, n) {}
- String(const stl_string& s, size_type pos=0, size_type n=npos):
- stl_string(s, pos, n) {}
+ String()
+ : stl_string()
+ {
+ }
+ String(const value_type* s)
+ : stl_string(s)
+ {
+ }
+ String(const value_type* s, size_type n)
+ : stl_string(s, n)
+ {
+ }
+ String(const stl_string& s, size_type pos = 0, size_type n = npos)
+ : stl_string(s, pos, n)
+ {
+ }
}; // End Class: String
#if defined(__WATCOMC__)
inline bool operator<(String const& l, String const& r)
- {
- return (static_cast<@KWSYS_NAMESPACE@_stl::string const&>(l) <
- static_cast<@KWSYS_NAMESPACE@_stl::string const&>(r));
- }
+{
+ return (static_cast<std::string const&>(l) <
+ static_cast<std::string const&>(r));
+}
#endif
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/System.c b/Source/kwsys/System.c
index 5d178bfa2..b9af8e9d9 100644
--- a/Source/kwsys/System.c
+++ b/Source/kwsys/System.c
@@ -1,27 +1,18 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(System.h)
/* 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 */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* malloc, free */
-#include <string.h> /* strlen */
-#include <ctype.h> /* isalpha */
+#include <string.h> /* memcpy */
#include <stdio.h>
@@ -31,632 +22,65 @@ typedef ptrdiff_t kwsysSystem_ptrdiff_t;
typedef int kwsysSystem_ptrdiff_t;
#endif
-/*
-
-Notes:
-
-Make variable replacements open a can of worms. Sometimes they should
-be quoted and sometimes not. Sometimes their replacement values are
-already quoted.
-
-VS variables cause problems. In order to pass the referenced value
-with spaces the reference must be quoted. If the variable value ends
-in a backslash then it will escape the ending quote! In order to make
-the ending backslash appear we need this:
-
- "$(InputDir)\"
-
-However if there is not a trailing backslash then this will put a
-quote in the value so we need:
-
- "$(InputDir)"
-
-Make variable references are platform specific so we should probably
-just NOT quote them and let the listfile author deal with it.
-
-*/
-
-/*
-TODO: For windows echo:
-
-To display a pipe (|) or redirection character (< or >) when using the
-echo command, use a caret character immediately before the pipe or
-redirection character (for example, ^>, ^<, or ^| ). If you need to
-use the caret character itself (^), use two in a row (^^).
-*/
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__CharIsWhitespace(char c)
-{
- return ((c == ' ') || (c == '\t'));
-}
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__CharNeedsQuotesOnUnix(char c)
-{
- return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
- (c == '&') || (c == '$') || (c == '(') || (c == ')') ||
- (c == '~') || (c == '<') || (c == '>') || (c == '|') ||
- (c == '*') || (c == '^') || (c == '\\'));
-}
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__CharNeedsQuotesOnWindows(char c)
-{
- return ((c == '\'') || (c == '#') || (c == '&') ||
- (c == '<') || (c == '>') || (c == '|') || (c == '^'));
-}
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__CharNeedsQuotes(char c, int isUnix, int flags)
-{
- /* On Windows the built-in command shell echo never needs quotes. */
- if(!isUnix && (flags & kwsysSystem_Shell_Flag_EchoWindows))
- {
- return 0;
- }
-
- /* On all platforms quotes are needed to preserve whitespace. */
- if(kwsysSystem_Shell__CharIsWhitespace(c))
- {
- return 1;
- }
-
- if(isUnix)
- {
- /* On UNIX several special characters need quotes to preserve them. */
- if(kwsysSystem_Shell__CharNeedsQuotesOnUnix(c))
- {
- return 1;
- }
- }
- else
- {
- /* On Windows several special characters need quotes to preserve them. */
- if(kwsysSystem_Shell__CharNeedsQuotesOnWindows(c))
- {
- return 1;
- }
- }
- return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__CharIsMakeVariableName(char c)
-{
- return c && (c == '_' || isalpha(((int)c)));
-}
-
-/*--------------------------------------------------------------------------*/
-static const char* kwsysSystem_Shell__SkipMakeVariables(const char* c)
-{
- while(*c == '$' && *(c+1) == '(')
- {
- const char* skip = c+2;
- while(kwsysSystem_Shell__CharIsMakeVariableName(*skip))
- {
- ++skip;
- }
- if(*skip == ')')
- {
- c = skip+1;
- }
- else
- {
- break;
- }
- }
- return c;
-}
-
-/*
-Allowing make variable replacements opens a can of worms. Sometimes
-they should be quoted and sometimes not. Sometimes their replacement
-values are already quoted or contain escapes.
-
-Some Visual Studio variables cause problems. In order to pass the
-referenced value with spaces the reference must be quoted. If the
-variable value ends in a backslash then it will escape the ending
-quote! In order to make the ending backslash appear we need this:
-
- "$(InputDir)\"
-
-However if there is not a trailing backslash then this will put a
-quote in the value so we need:
-
- "$(InputDir)"
-
-This macro decides whether we quote an argument just because it
-contains a make variable reference. This should be replaced with a
-flag later when we understand applications of this better.
-*/
-#define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__ArgumentNeedsQuotes(const char* in, int isUnix,
- int flags)
-{
- /* The empty string needs quotes. */
- if(!*in)
- {
- return 1;
- }
-
- /* Scan the string for characters that require quoting. */
- {
- const char* c;
- for(c=in; *c; ++c)
- {
- /* Look for $(MAKEVAR) syntax if requested. */
- if(flags & kwsysSystem_Shell_Flag_AllowMakeVariables)
- {
-#if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
- const char* skip = kwsysSystem_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;
- }
-#else
- /* Skip over the make variable references if any are present. */
- c = kwsysSystem_Shell__SkipMakeVariables(c);
-
- /* Stop if we have reached the end of the string. */
- if(!*c)
- {
- break;
- }
-#endif
- }
-
- /* Check whether this character needs quotes. */
- if(kwsysSystem_Shell__CharNeedsQuotes(*c, isUnix, flags))
- {
- return 1;
- }
- }
- }
-
- /* On Windows some single character arguments need quotes. */
- if(!isUnix && *in && !*(in+1))
- {
- char c = *in;
- if((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#'))
- {
- return 1;
- }
- }
-
- return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem_Shell__GetArgumentSize(const char* in,
- int isUnix, int flags)
-{
- /* Start with the length of the original argument, plus one for
- either a terminating null or a separating space. */
- int size = (int)strlen(in) + 1;
-
- /* String iterator. */
- const char* c;
-
- /* Keep track of how many backslashes have been encountered in a row. */
- int windows_backslashes = 0;
-
- /* Scan the string for characters that require escaping or quoting. */
- for(c=in; *c; ++c)
- {
- /* Look for $(MAKEVAR) syntax if requested. */
- if(flags & kwsysSystem_Shell_Flag_AllowMakeVariables)
- {
- /* Skip over the make variable references if any are present. */
- c = kwsysSystem_Shell__SkipMakeVariables(c);
-
- /* Stop if we have reached the end of the string. */
- if(!*c)
- {
- break;
- }
- }
-
- /* Check whether this character needs escaping for the shell. */
- if(isUnix)
- {
- /* On Unix a few special characters need escaping even inside a
- quoted argument. */
- if(*c == '\\' || *c == '"' || *c == '`' || *c == '$')
- {
- /* This character needs a backslash to escape it. */
- ++size;
- }
- }
- else if(flags & kwsysSystem_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 == '\\')
- {
- /* Found a backslash. It may need to be escaped later. */
- ++windows_backslashes;
- }
- else if(*c == '"')
- {
- /* Found a double-quote. We need to escape it and all
- immediately preceding backslashes. */
- size += windows_backslashes + 1;
- windows_backslashes = 0;
- }
- else
- {
- /* Found another character. This eliminates the possibility
- that any immediately preceding backslashes will be
- escaped. */
- windows_backslashes = 0;
- }
- }
-
- /* Check whether this character needs escaping for a make tool. */
- if(*c == '$')
- {
- if(flags & kwsysSystem_Shell_Flag_Make)
- {
- /* In Makefiles a dollar is written $$ so we need one extra
- character. */
- ++size;
- }
- else if(flags & kwsysSystem_Shell_Flag_VSIDE)
- {
- /* In a VS IDE a dollar is written "$" so we need two extra
- characters. */
- size += 2;
- }
- }
- else if(*c == '#')
- {
- if((flags & kwsysSystem_Shell_Flag_Make) &&
- (flags & kwsysSystem_Shell_Flag_WatcomWMake))
- {
- /* In Watcom WMake makefiles a pound is written $# so we need
- one extra character. */
- ++size;
- }
- }
- else if(*c == '%')
- {
- if((flags & kwsysSystem_Shell_Flag_VSIDE) ||
- ((flags & kwsysSystem_Shell_Flag_Make) &&
- ((flags & kwsysSystem_Shell_Flag_MinGWMake) ||
- (flags & kwsysSystem_Shell_Flag_NMake))))
- {
- /* In the VS IDE, NMake, or MinGW make a percent is written %%
- so we need one extra characters. */
- size += 1;
- }
- }
- else if(*c == ';')
- {
- if(flags & kwsysSystem_Shell_Flag_VSIDE)
- {
- /* In a VS IDE a semicolon is written ";" so we need two extra
- characters. */
- size += 2;
- }
- }
- }
-
- /* Check whether the argument needs surrounding quotes. */
- if(kwsysSystem_Shell__ArgumentNeedsQuotes(in, isUnix, flags))
- {
- /* Surrounding quotes are needed. Allocate space for them. */
- size += 2;
-
- /* We must escape all ending backslashes when quoting on windows. */
- size += windows_backslashes;
- }
-
- return size;
-}
-
-/*--------------------------------------------------------------------------*/
-static char* kwsysSystem_Shell__GetArgument(const char* in, char* out,
- int isUnix, int flags)
-{
- /* String iterator. */
- const char* c;
-
- /* Keep track of how many backslashes have been encountered in a row. */
- int windows_backslashes = 0;
-
- /* Whether the argument must be quoted. */
- int needQuotes = kwsysSystem_Shell__ArgumentNeedsQuotes(in, isUnix, flags);
- if(needQuotes)
- {
- /* Add the opening quote for this argument. */
- *out++ = '"';
- }
-
- /* Scan the string for characters that require escaping or quoting. */
- for(c=in; *c; ++c)
- {
- /* Look for $(MAKEVAR) syntax if requested. */
- if(flags & kwsysSystem_Shell_Flag_AllowMakeVariables)
- {
- const char* skip = kwsysSystem_Shell__SkipMakeVariables(c);
- if(skip != c)
- {
- /* Copy to the end of the make variable references. */
- while(c != skip)
- {
- *out++ = *c++;
- }
-
- /* The make variable reference eliminates any escaping needed
- for preceding backslashes. */
- windows_backslashes = 0;
-
- /* Stop if we have reached the end of the string. */
- if(!*c)
- {
- break;
- }
- }
- }
-
- /* Check whether this character needs escaping for the shell. */
- if(isUnix)
- {
- /* On Unix a few special characters need escaping even inside a
- quoted argument. */
- if(*c == '\\' || *c == '"' || *c == '`' || *c == '$')
- {
- /* This character needs a backslash to escape it. */
- *out++ = '\\';
- }
- }
- else if(flags & kwsysSystem_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 == '\\')
- {
- /* Found a backslash. It may need to be escaped later. */
- ++windows_backslashes;
- }
- else if(*c == '"')
- {
- /* Found a double-quote. Escape all immediately preceding
- backslashes. */
- while(windows_backslashes > 0)
- {
- --windows_backslashes;
- *out++ = '\\';
- }
-
- /* Add the backslash to escape the double-quote. */
- *out++ = '\\';
- }
- else
- {
- /* We encountered a normal character. This eliminates any
- escaping needed for preceding backslashes. */
- windows_backslashes = 0;
- }
- }
-
- /* Check whether this character needs escaping for a make tool. */
- if(*c == '$')
- {
- if(flags & kwsysSystem_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 & kwsysSystem_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
- 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 from surrounding
- text to avoid looking like a variable reference. */
- *out++ = '"';
- *out++ = '$';
- *out++ = '"';
- }
- else
- {
- /* Otherwise a dollar is written just $. */
- *out++ = '$';
- }
- }
- else if(*c == '#')
- {
- if((flags & kwsysSystem_Shell_Flag_Make) &&
- (flags & kwsysSystem_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++ = '#';
- }
- }
- else if(*c == '%')
- {
- if((flags & kwsysSystem_Shell_Flag_VSIDE) ||
- ((flags & kwsysSystem_Shell_Flag_Make) &&
- ((flags & kwsysSystem_Shell_Flag_MinGWMake) ||
- (flags & kwsysSystem_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++ = '%';
- }
- }
- else if(*c == ';')
- {
- if(flags & kwsysSystem_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++ = ';';
- *out++ = '"';
- }
- else
- {
- /* Otherwise a semicolon is written just ;. */
- *out++ = ';';
- }
- }
- else
- {
- /* Store this character. */
- *out++ = *c;
- }
- }
-
- if(needQuotes)
- {
- /* Add enough backslashes to escape any trailing ones. */
- while(windows_backslashes > 0)
- {
- --windows_backslashes;
- *out++ = '\\';
- }
-
- /* Add the closing quote for this argument. */
- *out++ = '"';
- }
-
- /* Store a terminating null without incrementing. */
- *out = 0;
-
- return out;
-}
-
-/*--------------------------------------------------------------------------*/
-char* kwsysSystem_Shell_GetArgumentForWindows(const char* in,
- char* out,
- int flags)
-{
- return kwsysSystem_Shell__GetArgument(in, out, 0, flags);
-}
-
-/*--------------------------------------------------------------------------*/
-char* kwsysSystem_Shell_GetArgumentForUnix(const char* in,
- char* out,
- int flags)
-{
- return kwsysSystem_Shell__GetArgument(in, out, 1, flags);
-}
-
-/*--------------------------------------------------------------------------*/
-int kwsysSystem_Shell_GetArgumentSizeForWindows(const char* in, int flags)
-{
- return kwsysSystem_Shell__GetArgumentSize(in, 0, flags);
-}
-
-/*--------------------------------------------------------------------------*/
-int kwsysSystem_Shell_GetArgumentSizeForUnix(const char* in, int flags)
-{
- return kwsysSystem_Shell__GetArgumentSize(in, 1, flags);
-}
-
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem__AppendByte(char* local,
- char** begin, char** end,
+static int kwsysSystem__AppendByte(char* local, char** begin, char** end,
int* size, char c)
{
/* Allocate space for the character. */
- if((*end - *begin) >= *size)
- {
+ if ((*end - *begin) >= *size) {
kwsysSystem_ptrdiff_t length = *end - *begin;
- char* newBuffer = (char*)malloc((size_t)(*size*2));
- if(!newBuffer)
- {
+ char* newBuffer = (char*)malloc((size_t)(*size * 2));
+ if (!newBuffer) {
return 0;
- }
- memcpy(newBuffer, *begin, (size_t)(length)*sizeof(char));
- if(*begin != local)
- {
+ }
+ memcpy(newBuffer, *begin, (size_t)(length) * sizeof(char));
+ if (*begin != local) {
free(*begin);
- }
+ }
*begin = newBuffer;
*end = *begin + length;
*size *= 2;
- }
+ }
/* Store the character. */
*(*end)++ = c;
return 1;
}
-/*--------------------------------------------------------------------------*/
-static int kwsysSystem__AppendArgument(char** local,
- char*** begin, char*** end,
- int* size,
- char* arg_local,
+static int kwsysSystem__AppendArgument(char** local, char*** begin,
+ char*** end, int* size, char* arg_local,
char** arg_begin, char** arg_end,
int* arg_size)
{
/* Append a null-terminator to the argument string. */
- if(!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size, '\0'))
- {
+ if (!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size,
+ '\0')) {
return 0;
- }
+ }
/* Allocate space for the argument pointer. */
- if((*end - *begin) >= *size)
- {
+ if ((*end - *begin) >= *size) {
kwsysSystem_ptrdiff_t length = *end - *begin;
- char** newPointers = (char**)malloc((size_t)(*size)*2*sizeof(char*));
- if(!newPointers)
- {
+ char** newPointers = (char**)malloc((size_t)(*size) * 2 * sizeof(char*));
+ if (!newPointers) {
return 0;
- }
- memcpy(newPointers, *begin, (size_t)(length)*sizeof(char*));
- if(*begin != local)
- {
+ }
+ memcpy(newPointers, *begin, (size_t)(length) * sizeof(char*));
+ if (*begin != local) {
free(*begin);
- }
+ }
*begin = newPointers;
*end = *begin + length;
*size *= 2;
- }
+ }
/* Allocate space for the argument string. */
**end = (char*)malloc((size_t)(*arg_end - *arg_begin));
- if(!**end)
- {
+ if (!**end) {
return 0;
- }
+ }
/* Store the argument in the command array. */
- memcpy(**end, *arg_begin,(size_t)(*arg_end - *arg_begin));
+ memcpy(**end, *arg_begin, (size_t)(*arg_end - *arg_begin));
++(*end);
/* Reset the argument to be empty. */
@@ -665,7 +89,6 @@ static int kwsysSystem__AppendArgument(char** local,
return 1;
}
-/*--------------------------------------------------------------------------*/
#define KWSYSPE_LOCAL_BYTE_COUNT 1024
#define KWSYSPE_LOCAL_ARGS_COUNT 32
static char** kwsysSystem__ParseUnixCommand(const char* command, int flags)
@@ -690,150 +113,109 @@ static char** kwsysSystem__ParseUnixCommand(const char* command, int flags)
int in_single = 0;
int in_double = 0;
int failed = 0;
- for(;*c; ++c)
- {
- if(in_escape)
- {
+ for (; *c; ++c) {
+ if (in_escape) {
/* This character is escaped so do no special handling. */
- if(!in_argument)
- {
+ if (!in_argument) {
in_argument = 1;
- }
- if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
- &buffer_end, &buffer_size, *c))
- {
+ }
+ if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
+ &buffer_size, *c)) {
failed = 1;
break;
- }
- in_escape = 0;
}
- else if(*c == '\\')
- {
+ in_escape = 0;
+ } else if (*c == '\\') {
/* The next character should be escaped. */
in_escape = 1;
- }
- else if(*c == '\'' && !in_double)
- {
+ } else if (*c == '\'' && !in_double) {
/* Enter or exit single-quote state. */
- if(in_single)
- {
+ if (in_single) {
in_single = 0;
- }
- else
- {
+ } else {
in_single = 1;
- if(!in_argument)
- {
+ if (!in_argument) {
in_argument = 1;
- }
}
}
- else if(*c == '"' && !in_single)
- {
+ } else if (*c == '"' && !in_single) {
/* Enter or exit double-quote state. */
- if(in_double)
- {
+ if (in_double) {
in_double = 0;
- }
- else
- {
+ } else {
in_double = 1;
- if(!in_argument)
- {
+ if (!in_argument) {
in_argument = 1;
- }
}
}
- else if(isspace((unsigned char) *c))
- {
- if(in_argument)
- {
- if(in_single || in_double)
- {
+ } else if (isspace((unsigned char)*c)) {
+ if (in_argument) {
+ if (in_single || in_double) {
/* This space belongs to a quoted argument. */
- if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
- &buffer_end, &buffer_size, *c))
- {
+ if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
+ &buffer_end, &buffer_size, *c)) {
failed = 1;
break;
- }
}
- else
- {
+ } else {
/* This argument has been terminated by whitespace. */
- if(!kwsysSystem__AppendArgument(local_pointers, &pointer_begin,
- &pointer_end, &pointers_size,
- local_buffer, &buffer_begin,
- &buffer_end, &buffer_size))
- {
+ if (!kwsysSystem__AppendArgument(
+ local_pointers, &pointer_begin, &pointer_end, &pointers_size,
+ local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
failed = 1;
break;
- }
- in_argument = 0;
}
+ in_argument = 0;
}
}
- else
- {
+ } else {
/* This character belong to an argument. */
- if(!in_argument)
- {
+ if (!in_argument) {
in_argument = 1;
- }
- if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
- &buffer_end, &buffer_size, *c))
- {
+ }
+ if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
+ &buffer_size, *c)) {
failed = 1;
break;
- }
}
}
+ }
/* Finish the last argument. */
- if(in_argument)
- {
- if(!kwsysSystem__AppendArgument(local_pointers, &pointer_begin,
- &pointer_end, &pointers_size,
- local_buffer, &buffer_begin,
- &buffer_end, &buffer_size))
- {
+ if (in_argument) {
+ if (!kwsysSystem__AppendArgument(
+ local_pointers, &pointer_begin, &pointer_end, &pointers_size,
+ local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
failed = 1;
- }
}
+ }
/* If we still have memory allocate space for the new command
buffer. */
- if(!failed)
- {
+ if (!failed) {
kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
- newCommand = (char**)malloc((size_t)(n+1)*sizeof(char*));
- }
+ newCommand = (char**)malloc((size_t)(n + 1) * sizeof(char*));
+ }
- if(newCommand)
- {
+ if (newCommand) {
/* Copy the arguments into the new command buffer. */
kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
- memcpy(newCommand, pointer_begin, sizeof(char*)*(size_t)(n));
+ memcpy(newCommand, pointer_begin, sizeof(char*) * (size_t)(n));
newCommand[n] = 0;
- }
- else
- {
+ } else {
/* Free arguments already allocated. */
- while(pointer_end != pointer_begin)
- {
+ while (pointer_end != pointer_begin) {
free(*(--pointer_end));
- }
}
+ }
/* Free temporary buffers. */
- if(pointer_begin != local_pointers)
- {
+ if (pointer_begin != local_pointers) {
free(pointer_begin);
- }
- if(buffer_begin != local_buffer)
- {
+ }
+ if (buffer_begin != local_buffer) {
free(buffer_begin);
- }
+ }
/* The flags argument is currently unused. */
(void)flags;
@@ -842,14 +224,12 @@ static char** kwsysSystem__ParseUnixCommand(const char* command, int flags)
return newCommand;
}
-/*--------------------------------------------------------------------------*/
char** kwsysSystem_Parse_CommandForUnix(const char* command, int flags)
{
/* Validate the flags. */
- if(flags != 0)
- {
+ if (flags != 0) {
return 0;
- }
+ }
/* Forward to our internal implementation. */
return kwsysSystem__ParseUnixCommand(command, flags);
diff --git a/Source/kwsys/System.h.in b/Source/kwsys/System.h.in
index 549db900c..102974db7 100644
--- a/Source/kwsys/System.h.in
+++ b/Source/kwsys/System.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_System_h
#define @KWSYS_NAMESPACE@_System_h
@@ -19,100 +10,18 @@
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_Shell_GetArgumentForWindows kwsys_ns(System_Shell_GetArgumentForWindows)
-# define kwsysSystem_Shell_GetArgumentForUnix kwsys_ns(System_Shell_GetArgumentForUnix)
-# define kwsysSystem_Shell_GetArgumentSizeForWindows kwsys_ns(System_Shell_GetArgumentSizeForWindows)
-# define kwsysSystem_Shell_GetArgumentSizeForUnix kwsys_ns(System_Shell_GetArgumentSizeForUnix)
-# define kwsysSystem_Shell_Flag_e kwsys_ns(System_Shell_Flag_e)
-# define kwsysSystem_Shell_Flag_Make kwsys_ns(System_Shell_Flag_Make)
-# define kwsysSystem_Shell_Flag_VSIDE kwsys_ns(System_Shell_Flag_VSIDE)
-# define kwsysSystem_Shell_Flag_EchoWindows kwsys_ns(System_Shell_Flag_EchoWindows)
-# define kwsysSystem_Shell_Flag_WatcomWMake kwsys_ns(System_Shell_Flag_WatcomWMake)
-# define kwsysSystem_Shell_Flag_MinGWMake kwsys_ns(System_Shell_Flag_MinGWMake)
-# define kwsysSystem_Shell_Flag_NMake kwsys_ns(System_Shell_Flag_NMake)
-# define kwsysSystem_Shell_Flag_AllowMakeVariables kwsys_ns(System_Shell_Flag_AllowMakeVariables)
-#endif
-
-#ifdef __VMS
-#define @KWSYS_NAMESPACE@System_Shell_GetArgumentForUnix \
- @KWSYS_NAMESPACE@System_Shell_UnixGA
-#define @KWSYS_NAMESPACE@System_Shell_GetArgumentSizeForUnix \
- @KWSYS_NAMESPACE@System_Shell_UnixGAS
-#define @KWSYS_NAMESPACE@System_Shell_GetArgumentForWindows \
- @KWSYS_NAMESPACE@System_Shell_WindowsGA
+#define kwsysSystem_Parse_CommandForUnix kwsys_ns(System_Parse_CommandForUnix)
#endif
#if defined(__cplusplus)
-extern "C"
-{
+extern "C" {
#endif
/**
- * Transform the given command line argument for use in a Windows or
- * Unix shell. Returns a pointer to the end of the command line
- * argument in the provided output buffer. Flags may be passed to
- * modify the generated quoting and escape sequences to work under
- * alternative environments.
- */
-kwsysEXPORT char* kwsysSystem_Shell_GetArgumentForWindows(const char* in,
- char* out,
- int flags);
-kwsysEXPORT char* kwsysSystem_Shell_GetArgumentForUnix(const char* in,
- char* out,
- int flags);
-
-/**
- * Compute the size of the buffer required to store the output from
- * kwsysSystem_Shell_GetArgumentForWindows or
- * kwsysSystem_Shell_GetArgumentForUnix. The flags passed must be
- * identical between the two calls.
- */
-kwsysEXPORT int kwsysSystem_Shell_GetArgumentSizeForWindows(const char* in,
- int flags);
-kwsysEXPORT int kwsysSystem_Shell_GetArgumentSizeForUnix(const char* in,
- int flags);
-
-/**
- * Flags to pass to kwsysSystem_Shell_GetArgumentForWindows or
- * kwsysSystem_Shell_GetArgumentForUnix. These modify the generated
- * quoting and escape sequences to work under alternative
- * environments.
- */
-enum kwsysSystem_Shell_Flag_e
-{
- /** The target shell is in a makefile. */
- kwsysSystem_Shell_Flag_Make = (1<<0),
-
- /** The target shell is in a VS project file. Do not use with
- Shell_Flag_Make. */
- kwsysSystem_Shell_Flag_VSIDE = (1<<1),
-
- /** In a windows shell the argument is being passed to "echo". */
- kwsysSystem_Shell_Flag_EchoWindows = (1<<2),
-
- /** The target shell is in a Watcom WMake makefile. */
- kwsysSystem_Shell_Flag_WatcomWMake = (1<<3),
-
- /** The target shell is in a MinGW Make makefile. */
- kwsysSystem_Shell_Flag_MinGWMake = (1<<4),
-
- /** The target shell is in a NMake makefile. */
- kwsysSystem_Shell_Flag_NMake = (1<<6),
-
- /** Make variable reference syntax $(MAKEVAR) should not be escaped
- to allow a build tool to replace it. Replacement values
- containing spaces, quotes, backslashes, or other
- non-alphanumeric characters that have significance to some makes
- or shells produce undefined behavior. */
- kwsysSystem_Shell_Flag_AllowMakeVariables = (1<<5)
-};
-
-/**
* Parse a unix-style command line string into separate arguments.
*
* On success, returns a pointer to an array of pointers to individual
@@ -140,23 +49,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
-# undef kwsysSystem_Shell_GetArgumentForWindows
-# undef kwsysSystem_Shell_GetArgumentForUnix
-# undef kwsysSystem_Shell_GetArgumentSizeForWindows
-# undef kwsysSystem_Shell_GetArgumentSizeForUnix
-# undef kwsysSystem_Shell_Flag_e
-# undef kwsysSystem_Shell_Flag_Make
-# undef kwsysSystem_Shell_Flag_VSIDE
-# undef kwsysSystem_Shell_Flag_EchoWindows
-# undef kwsysSystem_Shell_Flag_WatcomWMake
-# undef kwsysSystem_Shell_Flag_MinGWMake
-# undef kwsysSystem_Shell_Flag_NMake
-# undef kwsysSystem_Shell_Flag_AllowMakeVariables
-# 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 beefd7d73..86fdccdc7 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1,25 +1,15 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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 < 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:
@@ -35,191 +25,191 @@
// http://msdn.microsoft.com/en-us/library/ms683219(VS.85).aspx
#include "kwsysPrivate.h"
-#include KWSYS_HEADER(stl/string)
-#include KWSYS_HEADER(stl/vector)
-#include KWSYS_HEADER(ios/iosfwd)
#include KWSYS_HEADER(SystemInformation.hxx)
#include KWSYS_HEADER(Process.h)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(ios/sstream)
-#include KWSYS_HEADER(ios/fstream)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "SystemInformation.hxx.in"
-# include "Process.h.in"
-# include "Configure.hxx.in"
-# include "kwsys_stl.hxx.in"
-# include "kwsys_stl_vector.in"
-# include "kwsys_stl_iosfwd.in"
-# include "kwsys_ios_sstream.h.in"
-# include "kwsys_ios_iostream.h.in"
-# include "kwsys_ios_fstream.h.in"
+#include "Process.h.in"
+#include "SystemInformation.hxx.in"
#endif
+#include <algorithm>
+#include <bitset>
+#include <cassert>
+#include <fstream>
+#include <iostream>
+#include <limits>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
#if defined(_WIN32)
-# include <windows.h>
-# 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 <sys/time.h>
-# include <sys/utsname.h> // int uname(struct utsname *buf);
-# include <sys/resource.h> // getrlimit
-# include <unistd.h>
-# include <signal.h>
-# include <fcntl.h>
-# include <errno.h> // extern int errno;
+#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
-#ifdef __FreeBSD__
-# include <sys/sysctl.h>
-# include <fenv.h>
-# include <sys/socket.h>
-# include <netdb.h>
-# include <netinet/in.h>
-# if defined(KWSYS_SYS_HAS_IFADDRS_H)
-# include <ifaddrs.h>
-# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-# endif
+#if defined(__CYGWIN__) && !defined(_WIN32)
+#include <windows.h>
+#undef _WIN32
#endif
-#if defined(__OpenBSD__) || defined(__NetBSD__)
-# include <sys/param.h>
-# include <sys/sysctl.h>
+#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
-
-#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
-# include <machine/cpu.h>
#endif
-#if defined(__DragonFly__)
-# include <sys/sysctl.h>
+#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
+#include <machine/cpu.h>
#endif
#ifdef __APPLE__
-# include <sys/sysctl.h>
-# include <mach/vm_statistics.h>
-# include <mach/host_info.h>
-# include <mach/mach.h>
-# include <mach/mach_types.h>
-# include <fenv.h>
-# include <sys/socket.h>
-# include <netdb.h>
-# include <netinet/in.h>
-# if defined(KWSYS_SYS_HAS_IFADDRS_H)
-# include <ifaddrs.h>
-# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-# endif
-# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050
-# 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
-# endif
-# endif
+#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
-#ifdef __linux
-# include <fenv.h>
-# include <sys/socket.h>
-# include <netdb.h>
-# include <netinet/in.h>
-# if defined(KWSYS_SYS_HAS_IFADDRS_H)
-# include <ifaddrs.h>
-# if !defined(__LSB_VERSION__) /* LSB has no getifaddrs */
-# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-# endif
-# 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
-# endif
-# if defined(KWSYS_CXX_HAS_RLIMIT64)
+#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)
typedef struct rlimit64 ResourceLimitType;
-# define GetResourceLimit getrlimit64
-# else
+#define GetResourceLimit getrlimit64
+#else
typedef struct rlimit ResourceLimitType;
-# 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
+#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
#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
+#else
+#undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
+#undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
#endif
+#include <ctype.h> // int isdigit(int c);
#include <memory.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <ctype.h> // int isdigit(int c);
#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)
-# else
-# define iostreamLongLong(x) ((long)x)
-# endif
+#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+#define iostreamLongLong(x) (x)
#else
-# error "No Long Long"
+#define iostreamLongLong(x) ((long)(x))
+#endif
+#else
+#error "No Long Long"
#endif
#if defined(KWSYS_CXX_HAS_ATOLL)
-# define atoLongLong atoll
+#define atoLongLong atoll
#else
-# if defined(KWSYS_CXX_HAS__ATOI64)
-# define atoLongLong _atoi64
-# elif defined(KWSYS_CXX_HAS_ATOL)
-# define atoLongLong atol
-# 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)
+#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) && \
+ !defined(__clang__)
#define USE_ASM_INSTRUCTIONS 1
#else
#define USE_ASM_INSTRUCTIONS 0
#endif
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__clang__)
#include <intrin.h>
#define USE_CPUID_INTRINSICS 1
#else
#define USE_CPUID_INTRINSICS 0
#endif
-#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
-# define USE_CPUID 1
+#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || \
+ defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+#define USE_CPUID 1
#else
-# define USE_CPUID 0
+#define USE_CPUID 0
#endif
#if USE_CPUID
@@ -244,7 +234,7 @@ static bool call_cpuid(int select, int result[4])
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
+ ; optimiser does not know about <<CPUID>>, and so does not expect
; these registers to change.
push eax
push ebx
@@ -270,14 +260,12 @@ static bool call_cpuid(int select, int result[4])
pop ebx
pop eax
#endif
- }
}
- __except(1)
- {
+ } __except (1) {
return false;
- }
+ }
- memcpy(result, tmp, sizeof(tmp));
+ memcpy(result, tmp, sizeof(tmp));
#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
unsigned int a, b, c, d;
__asm {
@@ -301,33 +289,36 @@ static bool call_cpuid(int select, int result[4])
}
#endif
-
-namespace KWSYS_NAMESPACE
+namespace KWSYS_NAMESPACE {
+template <typename T>
+T min(T a, T b)
{
-template<typename T>
-T min(T a, T b){ return a<b ? a : b; }
+ return a < b ? a : b;
+}
-extern "C" { typedef void (*SigAction)(int,siginfo_t*,void*); }
+extern "C" {
+typedef void (*SigAction)(int, siginfo_t*, void*);
+}
// Define SystemInformationImplementation class
-typedef void (*DELAY_FUNC)(unsigned int uiMS);
+typedef void (*DELAY_FUNC)(unsigned int uiMS);
class SystemInformationImplementation
{
public:
typedef SystemInformation::LongLong LongLong;
- SystemInformationImplementation ();
- ~SystemInformationImplementation ();
-
- const char * GetVendorString();
- const char * GetVendorID();
- kwsys_stl::string GetTypeID();
- kwsys_stl::string GetFamilyID();
- kwsys_stl::string GetModelID();
- kwsys_stl::string GetModelName();
- kwsys_stl::string GetSteppingCode();
- const char * GetExtendedProcessorName();
- const char * GetProcessorSerialNumber();
+ SystemInformationImplementation();
+ ~SystemInformationImplementation();
+
+ const char* GetVendorString();
+ const char* GetVendorID();
+ std::string GetTypeID();
+ std::string GetFamilyID();
+ std::string GetModelID();
+ std::string GetModelName();
+ std::string GetSteppingCode();
+ const char* GetExtendedProcessorName();
+ const char* GetProcessorSerialNumber();
int GetProcessorCacheSize();
unsigned int GetLogicalProcessorsPerPhysical();
float GetProcessorClockFrequency();
@@ -335,12 +326,12 @@ public:
int GetProcessorCacheXSize(long int);
bool DoesCPUSupportFeature(long int);
- const char * GetOSName();
- const char * GetHostname();
- int GetFullyQualifiedDomainName(kwsys_stl::string &fqdn);
- const char * GetOSRelease();
- const char * GetOSVersion();
- const char * GetOSPlatform();
+ const char* GetOSName();
+ const char* GetHostname();
+ int GetFullyQualifiedDomainName(std::string& fqdn);
+ const char* GetOSRelease();
+ const char* GetOSVersion();
+ const char* GetOSPlatform();
bool Is64Bits();
@@ -359,21 +350,20 @@ public:
// Retrieve memory information in kib
LongLong GetHostMemoryTotal();
- LongLong GetHostMemoryAvailable(const char *envVarName);
+ LongLong GetHostMemoryAvailable(const char* envVarName);
LongLong GetHostMemoryUsed();
- LongLong GetProcMemoryAvailable(
- const char *hostLimitEnvVarName,
- const char *procLimitEnvVarName);
+ LongLong GetProcMemoryAvailable(const char* hostLimitEnvVarName,
+ const char* procLimitEnvVarName);
LongLong GetProcMemoryUsed();
+ double GetLoadAverage();
+
// enable/disable stack trace signal handler.
- static
- void SetStackTraceOnError(int enable);
+ static void SetStackTraceOnError(int enable);
// get current stack
- static
- kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);
+ static std::string GetProgramStack(int firstFrame, int wholePath);
/** Run the different checks */
void RunCPUCheck();
@@ -382,41 +372,40 @@ public:
public:
typedef struct tagID
- {
+ {
int Type;
int Family;
int Model;
int Revision;
int ExtendedFamily;
int ExtendedModel;
- kwsys_stl::string ProcessorName;
- kwsys_stl::string Vendor;
- kwsys_stl::string SerialNumber;
- kwsys_stl::string ModelName;
- } ID;
+ std::string ProcessorName;
+ std::string Vendor;
+ std::string SerialNumber;
+ std::string ModelName;
+ } ID;
typedef struct tagCPUPowerManagement
- {
+ {
bool HasVoltageID;
bool HasFrequencyID;
bool HasTempSenseDiode;
- } CPUPowerManagement;
+ } CPUPowerManagement;
typedef struct tagCPUExtendedFeatures
- {
+ {
bool Has3DNow;
bool Has3DNowPlus;
bool SupportsMP;
bool HasMMXPlus;
bool HasSSEMMX;
- bool SupportsHyperthreading;
unsigned int LogicalProcessorsPerPhysical;
int APIC_ID;
CPUPowerManagement PowerManagement;
- } CPUExtendedFeatures;
+ } CPUExtendedFeatures;
typedef struct CPUtagFeatures
- {
+ {
bool HasFPU;
bool HasTSC;
bool HasMMX;
@@ -435,16 +424,28 @@ public:
int L2CacheSize;
int L3CacheSize;
CPUExtendedFeatures ExtendedFeatures;
- } CPUFeatures;
+ } CPUFeatures;
enum Manufacturer
- {
- AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
- Motorola, HP, UnknownManufacturer
- };
+ {
+ AMD,
+ Intel,
+ NSC,
+ UMC,
+ Cyrix,
+ NexGen,
+ IDT,
+ Rise,
+ Transmeta,
+ Sun,
+ IBM,
+ Motorola,
+ HP,
+ UnknownManufacturer
+ };
protected:
- // Functions.
+ // For windows
bool RetrieveCPUFeatures();
bool RetrieveCPUIdentity();
bool RetrieveCPUCacheDetails();
@@ -458,64 +459,64 @@ protected:
bool RetrieveClassicalCPUIdentity();
bool RetrieveExtendedCPUIdentity();
- Manufacturer ChipManufacturer;
- CPUFeatures Features;
- ID ChipID;
- float CPUSpeedInMHz;
- unsigned int NumberOfLogicalCPU;
- unsigned int NumberOfPhysicalCPU;
+ // Processor information
+ Manufacturer ChipManufacturer;
+ CPUFeatures Features;
+ ID ChipID;
+ float CPUSpeedInMHz;
+ unsigned int NumberOfLogicalCPU;
+ unsigned int NumberOfPhysicalCPU;
- int CPUCount();
- unsigned char LogicalCPUPerPhysicalCPU();
- unsigned char GetAPICId();
- bool IsHyperThreadingSupported();
- static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int);
+ void CPUCountWindows(); // For windows
+ unsigned char GetAPICId(); // For windows
+ bool IsSMTSupported();
+ static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
bool RetreiveInformationFromCpuInfoFile();
- kwsys_stl::string ExtractValueFromCpuInfoFile(kwsys_stl::string buffer,
- const char* word, size_t init=0);
+ std::string ExtractValueFromCpuInfoFile(std::string buffer, const char* word,
+ size_t init = 0);
bool QueryLinuxMemory();
bool QueryCygwinMemory();
- static void Delay (unsigned int);
- static void DelayOverhead (unsigned int);
+ static void Delay(unsigned int);
+ static void DelayOverhead(unsigned int);
- void FindManufacturer(const kwsys_stl::string &family = "");
+ void FindManufacturer(const std::string& family = "");
// For Mac
bool ParseSysCtl();
- int CallSwVers(const char *arg, kwsys_stl::string &ver);
- void TrimNewline(kwsys_stl::string&);
- kwsys_stl::string ExtractValueFromSysCtl(const char* word);
- kwsys_stl::string SysCtlBuffer;
+ int CallSwVers(const char* arg, std::string& ver);
+ void TrimNewline(std::string&);
+ std::string ExtractValueFromSysCtl(const char* word);
+ std::string SysCtlBuffer;
// For Solaris
bool QuerySolarisMemory();
bool QuerySolarisProcessor();
- kwsys_stl::string ParseValueFromKStat(const char* arguments);
- kwsys_stl::string RunProcess(kwsys_stl::vector<const char*> args);
+ std::string ParseValueFromKStat(const char* arguments);
+ std::string RunProcess(std::vector<const char*> args);
- //For Haiku OS
+ // For Haiku OS
bool QueryHaikuInfo();
- //For QNX
+ // For QNX
bool QueryQNXMemory();
bool QueryQNXProcessor();
- //For OpenBSD, FreeBSD, NetBSD, DragonFly
+ // For OpenBSD, FreeBSD, NetBSD, DragonFly
bool QueryBSDMemory();
bool QueryBSDProcessor();
- //For HP-UX
+ // For HP-UX
bool QueryHPUXMemory();
bool QueryHPUXProcessor();
- //For Microsoft Windows
+ // For Microsoft Windows
bool QueryWindowsMemory();
- //For AIX
+ // For AIX
bool QueryAIXMemory();
bool QueryProcessorBySysconf();
@@ -533,14 +534,14 @@ protected:
// Operating System information
bool QueryOSInformation();
- kwsys_stl::string OSName;
- kwsys_stl::string Hostname;
- kwsys_stl::string OSRelease;
- kwsys_stl::string OSVersion;
- kwsys_stl::string OSPlatform;
+ std::string OSName;
+ std::string Hostname;
+ std::string OSRelease;
+ std::string OSVersion;
+ std::string OSPlatform;
+ bool OSIs64Bit;
};
-
SystemInformation::SystemInformation()
{
this->Implementation = new SystemInformationImplementation;
@@ -551,47 +552,47 @@ SystemInformation::~SystemInformation()
delete this->Implementation;
}
-const char * SystemInformation::GetVendorString()
+const char* SystemInformation::GetVendorString()
{
return this->Implementation->GetVendorString();
}
-const char * SystemInformation::GetVendorID()
+const char* SystemInformation::GetVendorID()
{
return this->Implementation->GetVendorID();
}
-kwsys_stl::string SystemInformation::GetTypeID()
+std::string SystemInformation::GetTypeID()
{
return this->Implementation->GetTypeID();
}
-kwsys_stl::string SystemInformation::GetFamilyID()
+std::string SystemInformation::GetFamilyID()
{
return this->Implementation->GetFamilyID();
}
-kwsys_stl::string SystemInformation::GetModelID()
+std::string SystemInformation::GetModelID()
{
return this->Implementation->GetModelID();
}
-kwsys_stl::string SystemInformation::GetModelName()
+std::string SystemInformation::GetModelName()
{
return this->Implementation->GetModelName();
}
-kwsys_stl::string SystemInformation::GetSteppingCode()
+std::string SystemInformation::GetSteppingCode()
{
return this->Implementation->GetSteppingCode();
}
-const char * SystemInformation::GetExtendedProcessorName()
+const char* SystemInformation::GetExtendedProcessorName()
{
return this->Implementation->GetExtendedProcessorName();
}
-const char * SystemInformation::GetProcessorSerialNumber()
+const char* SystemInformation::GetProcessorSerialNumber()
{
return this->Implementation->GetProcessorSerialNumber();
}
@@ -626,65 +627,55 @@ bool SystemInformation::DoesCPUSupportFeature(long int i)
return this->Implementation->DoesCPUSupportFeature(i);
}
-kwsys_stl::string SystemInformation::GetCPUDescription()
+std::string SystemInformation::GetCPUDescription()
{
- kwsys_ios::ostringstream oss;
- oss
- << this->GetNumberOfPhysicalCPU()
- << " core ";
- if (this->GetModelName().empty())
- {
- oss
- << this->GetProcessorClockFrequency()
- << " MHz "
- << this->GetVendorString()
- << " "
- << this->GetExtendedProcessorName();
- }
- else
- {
+ std::ostringstream oss;
+ oss << this->GetNumberOfPhysicalCPU() << " core ";
+ if (this->GetModelName().empty()) {
+ oss << this->GetProcessorClockFrequency() << " MHz "
+ << this->GetVendorString() << " " << this->GetExtendedProcessorName();
+ } else {
oss << this->GetModelName();
- }
+ }
// remove extra spaces
- kwsys_stl::string tmp=oss.str();
+ std::string tmp = oss.str();
size_t pos;
- while( (pos=tmp.find(" "))!=kwsys_stl::string::npos)
- {
- tmp.replace(pos,2," ");
- }
+ while ((pos = tmp.find(" ")) != std::string::npos) {
+ tmp.replace(pos, 2, " ");
+ }
return tmp;
}
-const char * SystemInformation::GetOSName()
+const char* SystemInformation::GetOSName()
{
return this->Implementation->GetOSName();
}
-const char * SystemInformation::GetHostname()
+const char* SystemInformation::GetHostname()
{
return this->Implementation->GetHostname();
}
-kwsys_stl::string SystemInformation::GetFullyQualifiedDomainName()
+std::string SystemInformation::GetFullyQualifiedDomainName()
{
- kwsys_stl::string fqdn;
+ std::string fqdn;
this->Implementation->GetFullyQualifiedDomainName(fqdn);
return fqdn;
}
-const char * SystemInformation::GetOSRelease()
+const char* SystemInformation::GetOSRelease()
{
return this->Implementation->GetOSRelease();
}
-const char * SystemInformation::GetOSVersion()
+const char* SystemInformation::GetOSVersion()
{
return this->Implementation->GetOSVersion();
}
-const char * SystemInformation::GetOSPlatform()
+const char* SystemInformation::GetOSPlatform()
{
return this->Implementation->GetOSPlatform();
}
@@ -716,15 +707,11 @@ int SystemInformation::GetOSIsApple()
#endif
}
-kwsys_stl::string SystemInformation::GetOSDescription()
+std::string SystemInformation::GetOSDescription()
{
- kwsys_ios::ostringstream oss;
- oss
- << this->GetOSName()
- << " "
- << this->GetOSRelease()
- << " "
- << this->GetOSVersion();
+ std::ostringstream oss;
+ oss << this->GetOSName() << " " << this->GetOSRelease() << " "
+ << this->GetOSVersion();
return oss.str();
}
@@ -770,20 +757,17 @@ size_t SystemInformation::GetAvailablePhysicalMemory()
return this->Implementation->GetAvailablePhysicalMemory();
}
-kwsys_stl::string SystemInformation::GetMemoryDescription(
- const char *hostLimitEnvVarName,
- const char *procLimitEnvVarName)
-{
- kwsys_ios::ostringstream oss;
- oss
- << "Host Total: "
- << iostreamLongLong(this->GetHostMemoryTotal())
- << " KiB, Host Available: "
- << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
- << " KiB, Process Available: "
- << iostreamLongLong(
- this->GetProcMemoryAvailable(hostLimitEnvVarName,procLimitEnvVarName))
- << " KiB";
+std::string SystemInformation::GetMemoryDescription(
+ const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
+{
+ std::ostringstream oss;
+ oss << "Host Total: " << iostreamLongLong(this->GetHostMemoryTotal())
+ << " KiB, Host Available: "
+ << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
+ << " KiB, Process Available: "
+ << iostreamLongLong(this->GetProcMemoryAvailable(hostLimitEnvVarName,
+ procLimitEnvVarName))
+ << " KiB";
return oss.str();
}
@@ -793,8 +777,8 @@ SystemInformation::LongLong SystemInformation::GetHostMemoryTotal()
return this->Implementation->GetHostMemoryTotal();
}
-SystemInformation::LongLong
-SystemInformation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
+SystemInformation::LongLong SystemInformation::GetHostMemoryAvailable(
+ const char* hostLimitEnvVarName)
{
return this->Implementation->GetHostMemoryAvailable(hostLimitEnvVarName);
}
@@ -805,14 +789,11 @@ SystemInformation::LongLong SystemInformation::GetHostMemoryUsed()
}
// process memory info in units of KiB.
-SystemInformation::LongLong
-SystemInformation::GetProcMemoryAvailable(
- const char *hostLimitEnvVarName,
- const char *procLimitEnvVarName)
+SystemInformation::LongLong SystemInformation::GetProcMemoryAvailable(
+ const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
{
- return this->Implementation->GetProcMemoryAvailable(
- hostLimitEnvVarName,
- procLimitEnvVarName);
+ return this->Implementation->GetProcMemoryAvailable(hostLimitEnvVarName,
+ procLimitEnvVarName);
}
SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
@@ -820,6 +801,11 @@ SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
return this->Implementation->GetProcMemoryUsed();
}
+double SystemInformation::GetLoadAverage()
+{
+ return this->Implementation->GetLoadAverage();
+}
+
SystemInformation::LongLong SystemInformation::GetProcessId()
{
return this->Implementation->GetProcessId();
@@ -830,9 +816,10 @@ void SystemInformation::SetStackTraceOnError(int enable)
SystemInformationImplementation::SetStackTraceOnError(enable);
}
-kwsys_stl::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
+std::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
{
- return SystemInformationImplementation::GetProgramStack(firstFrame, wholePath);
+ return SystemInformationImplementation::GetProgramStack(firstFrame,
+ wholePath);
}
/** Run the different checks */
@@ -851,60 +838,34 @@ void SystemInformation::RunMemoryCheck()
this->Implementation->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
-
-#define MMX_FEATURE 0x00000001
-#define MMX_PLUS_FEATURE 0x00000002
-#define SSE_FEATURE 0x00000004
-#define SSE2_FEATURE 0x00000008
-#define AMD_3DNOW_FEATURE 0x00000010
-#define AMD_3DNOW_PLUS_FEATURE 0x00000020
-#define IA64_FEATURE 0x00000040
-#define MP_CAPABLE 0x00000080
-#define HYPERTHREAD_FEATURE 0x00000100
-#define SERIALNUMBER_FEATURE 0x00000200
-#define APIC_FEATURE 0x00000400
-#define SSE_FP_FEATURE 0x00000800
-#define SSE_MMX_FEATURE 0x00001000
-#define CMOV_FEATURE 0x00002000
-#define MTRR_FEATURE 0x00004000
-#define L1CACHE_FEATURE 0x00008000
-#define L2CACHE_FEATURE 0x00010000
-#define L3CACHE_FEATURE 0x00020000
-#define ACPI_FEATURE 0x00040000
-#define THERMALMONITOR_FEATURE 0x00080000
-#define TEMPSENSEDIODE_FEATURE 0x00100000
-#define FREQUENCYID_FEATURE 0x00200000
-#define VOLTAGEID_FREQUENCY 0x00400000
+#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_NOT_CAPABLE 0
+#define HT_ENABLED 1
+#define HT_DISABLED 2
#define HT_SUPPORTED_NOT_ENABLED 3
-#define HT_CANNOT_DETECT 4
+#define HT_CANNOT_DETECT 4
// EDX[28] Bit 28 is set if HT is supported
-#define HT_BIT 0x10000000
+#define HT_BIT 0x10000000
// EAX[11:8] Bit 8-11 contains family processor ID.
-#define FAMILY_ID 0x0F00
-#define PENTIUM4_ID 0x0F00
+#define FAMILY_ID 0x0F00
+#define PENTIUM4_ID 0x0F00
// EAX[23:20] Bit 20-23 contains extended family processor ID
-#define EXT_FAMILY_ID 0x0F00000
+#define EXT_FAMILY_ID 0x0F00000
// EBX[23:16] Bit 16-23 in ebx contains the number of logical
-#define NUM_LOGICAL_BITS 0x00FF0000
+#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
-#define INITIAL_APIC_ID_BITS 0xFF000000
+#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
@@ -912,174 +873,143 @@ void SystemInformation::RunMemoryCheck()
namespace {
// *****************************************************************************
#if defined(__linux) || defined(__APPLE__)
-int LoadLines(
- FILE *file,
- kwsys_stl::vector<kwsys_stl::string> &lines)
+int LoadLines(FILE* file, std::vector<std::string>& lines)
{
// Load each line in the given file into a the vector.
- int nRead=0;
- const int bufSize=1024;
- char buf[bufSize]={'\0'};
- while (!feof(file) && !ferror(file))
- {
- errno=0;
- if (fgets(buf,bufSize,file) == 0)
- {
- if (ferror(file) && (errno==EINTR))
- {
+ int nRead = 0;
+ const int bufSize = 1024;
+ char buf[bufSize] = { '\0' };
+ while (!feof(file) && !ferror(file)) {
+ errno = 0;
+ if (fgets(buf, bufSize, file) == 0) {
+ if (ferror(file) && (errno == EINTR)) {
clearerr(file);
- }
- continue;
- }
- char *pBuf=buf;
- while(*pBuf)
- {
- if (*pBuf=='\n') *pBuf='\0';
- pBuf+=1;
}
+ continue;
+ }
+ char* pBuf = buf;
+ while (*pBuf) {
+ if (*pBuf == '\n')
+ *pBuf = '\0';
+ pBuf += 1;
+ }
lines.push_back(buf);
++nRead;
- }
- if (ferror(file))
- {
+ }
+ if (ferror(file)) {
return 0;
- }
+ }
return nRead;
}
-# if defined(__linux)
+#if defined(__linux)
// *****************************************************************************
-int LoadLines(
- const char *fileName,
- kwsys_stl::vector<kwsys_stl::string> &lines)
+int LoadLines(const char* fileName, std::vector<std::string>& lines)
{
- FILE *file=fopen(fileName,"r");
- if (file==0)
- {
+ FILE* file = fopen(fileName, "r");
+ if (file == 0) {
return 0;
- }
- int nRead=LoadLines(file,lines);
+ }
+ int nRead = LoadLines(file, lines);
fclose(file);
return nRead;
}
-# endif
+#endif
// ****************************************************************************
-template<typename T>
-int NameValue(
- kwsys_stl::vector<kwsys_stl::string> &lines,
- kwsys_stl::string name, T &value)
-{
- size_t nLines=lines.size();
- for (size_t i=0; i<nLines; ++i)
- {
- size_t at=lines[i].find(name);
- if (at==kwsys_stl::string::npos)
- {
+template <typename T>
+int NameValue(std::vector<std::string> const& lines, std::string const& name,
+ T& value)
+{
+ size_t nLines = lines.size();
+ for (size_t i = 0; i < nLines; ++i) {
+ size_t at = lines[i].find(name);
+ if (at == std::string::npos) {
continue;
- }
- kwsys_ios::istringstream is(lines[i].substr(at+name.size()));
+ }
+ std::istringstream is(lines[i].substr(at + name.size()));
is >> value;
return 0;
- }
+ }
return -1;
}
#endif
#if defined(__linux)
// ****************************************************************************
-template<typename T>
-int GetFieldsFromFile(
- const char *fileName,
- const char **fieldNames,
- T *values)
-{
- kwsys_stl::vector<kwsys_stl::string> fields;
- if (!LoadLines(fileName,fields))
- {
+template <typename T>
+int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values)
+{
+ std::vector<std::string> fields;
+ if (!LoadLines(fileName, fields)) {
return -1;
+ }
+ int i = 0;
+ while (fieldNames[i] != NULL) {
+ int ierr = NameValue(fields, fieldNames[i], values[i]);
+ if (ierr) {
+ return -(i + 2);
}
- int i=0;
- while (fieldNames[i]!=NULL)
- {
- int ierr=NameValue(fields,fieldNames[i],values[i]);
- if (ierr)
- {
- return -(i+2);
- }
- i+=1;
- }
+ i += 1;
+ }
return 0;
}
// ****************************************************************************
-template<typename T>
-int GetFieldFromFile(
- const char *fileName,
- const char *fieldName,
- T &value)
-{
- const char *fieldNames[2]={fieldName,NULL};
- T values[1]={T(0)};
- int ierr=GetFieldsFromFile(fileName,fieldNames,values);
- if (ierr)
- {
+template <typename T>
+int GetFieldFromFile(const char* fileName, const char* fieldName, T& value)
+{
+ const char* fieldNames[2] = { fieldName, NULL };
+ T values[1] = { T(0) };
+ int ierr = GetFieldsFromFile(fileName, fieldNames, values);
+ if (ierr) {
return ierr;
- }
- value=values[0];
+ }
+ value = values[0];
return 0;
}
#endif
// ****************************************************************************
#if defined(__APPLE__)
-template<typename T>
-int GetFieldsFromCommand(
- const char *command,
- const char **fieldNames,
- T *values)
-{
- FILE *file=popen(command,"r");
- if (file==0)
- {
+template <typename T>
+int GetFieldsFromCommand(const char* command, const char** fieldNames,
+ T* values)
+{
+ FILE* file = popen(command, "r");
+ if (file == 0) {
return -1;
- }
- kwsys_stl::vector<kwsys_stl::string> fields;
- int nl=LoadLines(file,fields);
+ }
+ std::vector<std::string> fields;
+ int nl = LoadLines(file, fields);
pclose(file);
- if (nl==0)
- {
+ if (nl == 0) {
return -1;
+ }
+ int i = 0;
+ while (fieldNames[i] != NULL) {
+ int ierr = NameValue(fields, fieldNames[i], values[i]);
+ if (ierr) {
+ return -(i + 2);
}
- int i=0;
- while (fieldNames[i]!=NULL)
- {
- int ierr=NameValue(fields,fieldNames[i],values[i]);
- if (ierr)
- {
- return -(i+2);
- }
- i+=1;
- }
+ i += 1;
+ }
return 0;
}
#endif
// ****************************************************************************
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
-void StacktraceSignalHandler(
- int sigNo,
- siginfo_t *sigInfo,
- void * /*sigContext*/)
+void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
+ void* /*sigContext*/)
{
#if defined(__linux) || defined(__APPLE__)
- kwsys_ios::ostringstream oss;
- oss
- << kwsys_ios::endl
- << "=========================================================" << kwsys_ios::endl
- << "Process id " << getpid() << " ";
- switch (sigNo)
- {
+ std::ostringstream oss;
+ oss << std::endl
+ << "========================================================="
+ << std::endl
+ << "Process id " << getpid() << " ";
+ switch (sigNo) {
case SIGINT:
oss << "Caught SIGINT";
break;
@@ -1093,24 +1023,20 @@ void StacktraceSignalHandler(
break;
case SIGFPE:
- oss
- << "Caught SIGFPE at "
- << (sigInfo->si_addr==0?"0x":"")
- << sigInfo->si_addr
- << " ";
- switch (sigInfo->si_code)
- {
-# if defined(FPE_INTDIV)
+ oss << "Caught SIGFPE at " << (sigInfo->si_addr == 0 ? "0x" : "")
+ << sigInfo->si_addr << " ";
+ switch (sigInfo->si_code) {
+#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";
@@ -1141,17 +1067,13 @@ void StacktraceSignalHandler(
default:
oss << "code " << sigInfo->si_code;
break;
- }
+ }
break;
case SIGSEGV:
- oss
- << "Caught SIGSEGV at "
- << (sigInfo->si_addr==0?"0x":"")
- << sigInfo->si_addr
- << " ";
- switch (sigInfo->si_code)
- {
+ oss << "Caught SIGSEGV at " << (sigInfo->si_addr == 0 ? "0x" : "")
+ << sigInfo->si_addr << " ";
+ switch (sigInfo->si_code) {
case SEGV_MAPERR:
oss << "address not mapped to object";
break;
@@ -1163,116 +1085,111 @@ void StacktraceSignalHandler(
default:
oss << "code " << sigInfo->si_code;
break;
- }
+ }
break;
case SIGBUS:
- oss
- << "Caught SIGBUS at "
- << (sigInfo->si_addr==0?"0x":"")
- << sigInfo->si_addr
- << " ";
- switch (sigInfo->si_code)
- {
+ oss << "Caught SIGBUS at " << (sigInfo->si_addr == 0 ? "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.";
+ 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.";
+ oss << "Hardware memory error detected in process but not consumed; "
+ "action optional.";
break;
-# endif
+#endif
default:
oss << "code " << sigInfo->si_code;
break;
- }
+ }
break;
case SIGILL:
- oss
- << "Caught SIGILL at "
- << (sigInfo->si_addr==0?"0x":"")
- << sigInfo->si_addr
- << " ";
- switch (sigInfo->si_code)
- {
+ oss << "Caught SIGILL at " << (sigInfo->si_addr == 0 ? "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";
+ break;
case ILL_PRVOPC:
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;
break;
- }
+ }
break;
default:
oss << "Caught " << sigNo << " code " << sigInfo->si_code;
break;
- }
- oss
- << kwsys_ios::endl
- << "Program Stack:" << kwsys_ios::endl
- << SystemInformationImplementation::GetProgramStack(2,0)
- << "=========================================================" << kwsys_ios::endl;
- kwsys_ios::cerr << oss.str() << kwsys_ios::endl;
+ }
+ oss << std::endl
+ << "Program Stack:" << std::endl
+ << SystemInformationImplementation::GetProgramStack(2, 0)
+ << "========================================================="
+ << std::endl;
+ std::cerr << oss.str() << std::endl;
// restore the previously registered handlers
// and abort
@@ -1287,7 +1204,7 @@ void StacktraceSignalHandler(
#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
@@ -1300,86 +1217,88 @@ public:
// Description:
// The SymbolProperties instance must be initialized by
// passing a stack address.
- void Initialize(void *address);
+ void Initialize(void* address);
// Description:
// Get the symbol's stack address.
- void *GetAddress() const { return this->Address; }
+ void* GetAddress() const { return this->Address; }
// Description:
// If not set paths will be removed. eg, from a binary
// or source file.
- void SetReportPath(int rp){ this->ReportPath=rp; }
+ void SetReportPath(int rp) { this->ReportPath = rp; }
// Description:
// Set/Get the name of the binary file that the symbol
// is found in.
- void SetBinary(const char *binary)
- { this->Binary=safes(binary); }
+ void SetBinary(const char* binary) { this->Binary = safes(binary); }
- kwsys_stl::string GetBinary() const;
+ std::string GetBinary() const;
// Description:
// Set the name of the function that the symbol is found in.
// If c++ demangling is supported it will be demangled.
- void SetFunction(const char *function)
- { this->Function=this->Demangle(function); }
+ void SetFunction(const char* function)
+ {
+ this->Function = this->Demangle(function);
+ }
- kwsys_stl::string GetFunction() const
- { return this->Function; }
+ std::string GetFunction() const { return this->Function; }
// Description:
// Set/Get the name of the source file where the symbol
// is defined.
- void SetSourceFile(const char *sourcefile)
- { this->SourceFile=safes(sourcefile); }
+ void SetSourceFile(const char* sourcefile)
+ {
+ this->SourceFile = safes(sourcefile);
+ }
- kwsys_stl::string GetSourceFile() const
- { return this->GetFileName(this->SourceFile); }
+ std::string GetSourceFile() const
+ {
+ return this->GetFileName(this->SourceFile);
+ }
// Description:
// Set/Get the line number where the symbol is defined
- void SetLineNumber(long linenumber){ this->LineNumber=linenumber; }
+ void SetLineNumber(long linenumber) { this->LineNumber = linenumber; }
long GetLineNumber() const { return this->LineNumber; }
// Description:
// Set the address where the biinary image is mapped
// into memory.
- void SetBinaryBaseAddress(void *address)
- { this->BinaryBaseAddress=address; }
+ void SetBinaryBaseAddress(void* address)
+ {
+ this->BinaryBaseAddress = address;
+ }
private:
- void *GetRealAddress() const
- { return (void*)((char*)this->Address-(char*)this->BinaryBaseAddress); }
+ void* GetRealAddress() const
+ {
+ return (void*)((char*)this->Address - (char*)this->BinaryBaseAddress);
+ }
- kwsys_stl::string GetFileName(const kwsys_stl::string &path) const;
- kwsys_stl::string Demangle(const char *symbol) const;
+ std::string GetFileName(const std::string& path) const;
+ std::string Demangle(const char* symbol) const;
private:
- kwsys_stl::string Binary;
- void *BinaryBaseAddress;
- void *Address;
- kwsys_stl::string SourceFile;
- kwsys_stl::string Function;
+ std::string Binary;
+ void* BinaryBaseAddress;
+ void* Address;
+ std::string SourceFile;
+ std::string Function;
long LineNumber;
int ReportPath;
};
-// --------------------------------------------------------------------------
-kwsys_ios::ostream &operator<<(
- kwsys_ios::ostream &os,
- const SymbolProperties &sp)
+std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp)
{
#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
- os
- << kwsys_ios::hex << sp.GetAddress() << " : "
- << sp.GetFunction()
- << " [(" << sp.GetBinary() << ") "
- << sp.GetSourceFile() << ":"
- << kwsys_ios::dec << sp.GetLineNumber() << "]";
+ os << std::hex << sp.GetAddress() << " : " << sp.GetFunction() << " [("
+ << sp.GetBinary() << ") " << sp.GetSourceFile() << ":" << std::dec
+ << sp.GetLineNumber() << "]";
#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
- void *addr = sp.GetAddress();
- char **syminfo = backtrace_symbols(&addr,1);
+ void* addr = sp.GetAddress();
+ char** syminfo = backtrace_symbols(&addr, 1);
os << safes(syminfo[0]);
free(syminfo);
#else
@@ -1389,7 +1308,6 @@ kwsys_ios::ostream &operator<<(
return os;
}
-// --------------------------------------------------------------------------
SymbolProperties::SymbolProperties()
{
// not using an initializer list
@@ -1408,60 +1326,50 @@ SymbolProperties::SymbolProperties()
this->GetLineNumber();
}
-// --------------------------------------------------------------------------
-kwsys_stl::string SymbolProperties::GetFileName(const kwsys_stl::string &path) const
+std::string SymbolProperties::GetFileName(const std::string& path) const
{
- kwsys_stl::string file(path);
- if (!this->ReportPath)
- {
+ std::string file(path);
+ if (!this->ReportPath) {
size_t at = file.rfind("/");
- if (at!=kwsys_stl::string::npos)
- {
- file = file.substr(at+1,kwsys_stl::string::npos);
- }
+ if (at != std::string::npos) {
+ file = file.substr(at + 1);
}
+ }
return file;
}
-// --------------------------------------------------------------------------
-kwsys_stl::string SymbolProperties::GetBinary() const
+std::string SymbolProperties::GetBinary() const
{
// only linux has proc fs
#if defined(__linux__)
- if (this->Binary=="/proc/self/exe")
- {
- kwsys_stl::string binary;
- char buf[1024]={'\0'};
- ssize_t ll=0;
- if ((ll=readlink("/proc/self/exe",buf,1024))>0)
- {
- buf[ll]='\0';
- binary=buf;
- }
- else
- {
- binary="/proc/self/exe";
- }
- return this->GetFileName(binary);
+ 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) {
+ buf[ll] = '\0';
+ binary = buf;
+ } else {
+ binary = "/proc/self/exe";
}
+ return this->GetFileName(binary);
+ }
#endif
return this->GetFileName(this->Binary);
}
-// --------------------------------------------------------------------------
-kwsys_stl::string SymbolProperties::Demangle(const char *symbol) const
+std::string SymbolProperties::Demangle(const char* symbol) const
{
- kwsys_stl::string result = safes(symbol);
+ std::string result = safes(symbol);
#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
int status = 0;
size_t bufferLen = 1024;
- char *buffer = (char*)malloc(1024);
- char *demangledSymbol =
+ char* buffer = (char*)malloc(1024);
+ char* demangledSymbol =
abi::__cxa_demangle(symbol, buffer, &bufferLen, &status);
- if (!status)
- {
+ if (!status) {
result = demangledSymbol;
- }
+ }
free(buffer);
#else
(void)symbol;
@@ -1469,28 +1377,74 @@ kwsys_stl::string SymbolProperties::Demangle(const char *symbol) const
return result;
}
-// --------------------------------------------------------------------------
-void SymbolProperties::Initialize(void *address)
+void SymbolProperties::Initialize(void* address)
{
this->Address = address;
#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
// first fallback option can demangle c++ functions
Dl_info info;
- int ierr=dladdr(this->Address,&info);
- if (ierr && info.dli_sname && info.dli_saddr)
- {
+ int ierr = dladdr(this->Address, &info);
+ if (ierr && info.dli_sname && info.dli_saddr) {
this->SetBinary(info.dli_fname);
this->SetFunction(info.dli_sname);
- }
+ }
#else
- // second fallback use builtin backtrace_symbols
- // to decode the bactrace.
+// second fallback use builtin backtrace_symbols
+// to decode the bactrace.
#endif
}
#endif // don't define this class if we're not using it
-} // anonymous namespace
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
+#endif
+#if defined(_MSC_VER) && _MSC_VER < 1310
+#undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
+#endif
+#if defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes)
+double calculateCPULoad(unsigned __int64 idleTicks,
+ unsigned __int64 totalTicks)
+{
+ static double previousLoad = -0.0;
+ static unsigned __int64 previousIdleTicks = 0;
+ static unsigned __int64 previousTotalTicks = 0;
+
+ unsigned __int64 const idleTicksSinceLastTime =
+ idleTicks - previousIdleTicks;
+ unsigned __int64 const totalTicksSinceLastTime =
+ totalTicks - previousTotalTicks;
+
+ double load;
+ if (previousTotalTicks == 0 || totalTicksSinceLastTime == 0) {
+ // No new information. Use previous result.
+ load = previousLoad;
+ } else {
+ // Calculate load since last time.
+ load = 1.0 - double(idleTicksSinceLastTime) / totalTicksSinceLastTime;
+
+ // Smooth if possible.
+ if (previousLoad > 0) {
+ load = 0.25 * load + 0.75 * previousLoad;
+ }
+ }
+ previousLoad = load;
+ previousIdleTicks = idleTicks;
+ previousTotalTicks = totalTicks;
+
+ return load;
+}
+
+unsigned __int64 fileTimeToUInt64(FILETIME const& ft)
+{
+ LARGE_INTEGER out;
+ out.HighPart = ft.dwHighDateTime;
+ out.LowPart = ft.dwLowDateTime;
+ return out.QuadPart;
+}
+#endif
+
+} // anonymous namespace
SystemInformationImplementation::SystemInformationImplementation()
{
@@ -1515,6 +1469,7 @@ SystemInformationImplementation::SystemInformationImplementation()
this->OSRelease = "";
this->OSVersion = "";
this->OSPlatform = "";
+ this->OSIs64Bit = (sizeof(void*) == 8);
}
SystemInformationImplementation::~SystemInformationImplementation()
@@ -1523,60 +1478,56 @@ SystemInformationImplementation::~SystemInformationImplementation()
void SystemInformationImplementation::RunCPUCheck()
{
-#ifdef WIN32
+#ifdef _WIN32
// Check to see if this processor supports CPUID.
bool supportsCPUID = DoesCPUSupportCPUID();
- if (supportsCPUID)
- {
+ if (supportsCPUID) {
// Retrieve the CPU details.
RetrieveCPUIdentity();
this->FindManufacturer();
RetrieveCPUFeatures();
- }
+ }
// These two may be called without support for the CPUID instruction.
// (But if the instruction is there, they should be called *after*
// the above call to RetrieveCPUIdentity... that's why the two if
// blocks exist with the same "if (supportsCPUID)" logic...
//
- if (!RetrieveCPUClockSpeed())
- {
+ if (!RetrieveCPUClockSpeed()) {
RetrieveClassicalCPUClockSpeed();
- }
+ }
- if (supportsCPUID)
- {
+ if (supportsCPUID) {
// Retrieve cache information.
- if (!RetrieveCPUCacheDetails())
- {
+ if (!RetrieveCPUCacheDetails()) {
RetrieveClassicalCPUCacheDetails();
- }
+ }
// Retrieve the extended CPU details.
- if (!RetrieveExtendedCPUIdentity())
- {
+ if (!RetrieveExtendedCPUIdentity()) {
RetrieveClassicalCPUIdentity();
- }
+ }
RetrieveExtendedCPUFeatures();
RetrieveCPUPowerManagement();
// Now attempt to retrieve the serial number (if possible).
RetrieveProcessorSerialNumber();
- }
+ }
- this->CPUCount();
+ this->CPUCountWindows();
#elif defined(__APPLE__)
this->ParseSysCtl();
-#elif defined (__SVR4) && defined (__sun)
+#elif defined(__SVR4) && defined(__sun)
this->QuerySolarisProcessor();
#elif defined(__HAIKU__)
this->QueryHaikuInfo();
#elif defined(__QNX__)
this->QueryQNXProcessor();
-#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__DragonFly__)
this->QueryBSDProcessor();
#elif defined(__hpux)
this->QueryHPUXProcessor();
@@ -1596,13 +1547,14 @@ void SystemInformationImplementation::RunMemoryCheck()
{
#if defined(__APPLE__)
this->ParseSysCtl();
-#elif defined (__SVR4) && defined (__sun)
+#elif defined(__SVR4) && defined(__sun)
this->QuerySolarisMemory();
#elif defined(__HAIKU__)
this->QueryHaikuInfo();
#elif defined(__QNX__)
this->QueryQNXMemory();
-#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__DragonFly__)
this->QueryBSDMemory();
#elif defined(__CYGWIN__)
this->QueryCygwinMemory();
@@ -1620,13 +1572,13 @@ void SystemInformationImplementation::RunMemoryCheck()
}
/** Get the vendor string */
-const char * SystemInformationImplementation::GetVendorString()
+const char* SystemInformationImplementation::GetVendorString()
{
return this->ChipID.Vendor.c_str();
}
/** Get the OS Name */
-const char * SystemInformationImplementation::GetOSName()
+const char* SystemInformationImplementation::GetOSName()
{
return this->OSName.c_str();
}
@@ -1634,65 +1586,59 @@ const char * SystemInformationImplementation::GetOSName()
/** Get the hostname */
const char* SystemInformationImplementation::GetHostname()
{
- if (this->Hostname.empty())
- {
- this->Hostname="localhost";
+ if (this->Hostname.empty()) {
+ this->Hostname = "localhost";
#if defined(_WIN32)
WORD wVersionRequested;
WSADATA wsaData;
char name[255];
- wVersionRequested = MAKEWORD(2,0);
- if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
- {
- gethostname(name,sizeof(name));
- WSACleanup( );
- }
+ wVersionRequested = MAKEWORD(2, 0);
+ if (WSAStartup(wVersionRequested, &wsaData) == 0) {
+ gethostname(name, sizeof(name));
+ WSACleanup();
+ }
this->Hostname = name;
#else
struct utsname unameInfo;
int errorFlag = uname(&unameInfo);
- if(errorFlag == 0)
- {
+ if (errorFlag == 0) {
this->Hostname = unameInfo.nodename;
- }
-#endif
}
+#endif
+ }
return this->Hostname.c_str();
}
/** Get the FQDN */
int SystemInformationImplementation::GetFullyQualifiedDomainName(
- kwsys_stl::string &fqdn)
+ std::string& fqdn)
{
// in the event of absolute failure return localhost.
- fqdn="localhost";
+ fqdn = "localhost";
#if defined(_WIN32)
int ierr;
// TODO - a more robust implementation for windows, see comments
// in unix implementation.
WSADATA wsaData;
- WORD ver=MAKEWORD(2,0);
- ierr=WSAStartup(ver,&wsaData);
- if (ierr)
- {
+ WORD ver = MAKEWORD(2, 0);
+ ierr = WSAStartup(ver, &wsaData);
+ if (ierr) {
return -1;
- }
+ }
- char base[256]={'\0'};
- ierr=gethostname(base,256);
- if (ierr)
- {
+ char base[256] = { '\0' };
+ ierr = gethostname(base, 256);
+ if (ierr) {
WSACleanup();
return -2;
- }
- fqdn=base;
+ }
+ fqdn = base;
- HOSTENT *hent=gethostbyname(base);
- if (hent)
- {
- fqdn=hent->h_name;
- }
+ HOSTENT* hent = gethostbyname(base);
+ if (hent) {
+ fqdn = hent->h_name;
+ }
WSACleanup();
return 0;
@@ -1709,66 +1655,57 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
// system lives on a private network such as in the case of a cluster
// node.
- int ierr=0;
+ int ierr = 0;
char base[NI_MAXHOST];
- ierr=gethostname(base,NI_MAXHOST);
- if (ierr)
- {
+ ierr = gethostname(base, NI_MAXHOST);
+ if (ierr) {
return -1;
- }
- size_t baseSize=strlen(base);
- fqdn=base;
+ }
+ size_t baseSize = strlen(base);
+ fqdn = base;
- struct ifaddrs *ifas;
- struct ifaddrs *ifa;
- ierr=getifaddrs(&ifas);
- if (ierr)
- {
+ struct ifaddrs* ifas;
+ struct ifaddrs* ifa;
+ ierr = getifaddrs(&ifas);
+ if (ierr) {
return -2;
- }
+ }
- for (ifa=ifas; ifa!=NULL; ifa=ifa->ifa_next)
- {
- int fam = ifa->ifa_addr? ifa->ifa_addr->sa_family : -1;
- if ((fam==AF_INET) || (fam==AF_INET6))
- {
- char host[NI_MAXHOST]={'\0'};
-
- socklen_t addrlen
- = (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6));
-
- ierr=getnameinfo(
- ifa->ifa_addr,
- addrlen,
- host,
- NI_MAXHOST,
- NULL,
- 0,
- NI_NAMEREQD);
- if (ierr)
- {
+ for (ifa = ifas; ifa != NULL; 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)) &&
+ !(ifa->ifa_flags & IFF_LOOPBACK)) {
+ char host[NI_MAXHOST] = { '\0' };
+
+ const size_t addrlen = (fam == AF_INET ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6));
+
+ ierr = getnameinfo(ifa->ifa_addr, static_cast<socklen_t>(addrlen), host,
+ NI_MAXHOST, NULL, 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.
- ierr=-3;
+ ierr = -3;
continue;
- }
+ }
- kwsys_stl::string candidate=host;
- if ((candidate.find(base)!=kwsys_stl::string::npos) && baseSize<candidate.size())
- {
+ std::string candidate = host;
+ if ((candidate.find(base) != std::string::npos) &&
+ baseSize < candidate.size()) {
// success, stop now.
- ierr=0;
- fqdn=candidate;
+ ierr = 0;
+ fqdn = candidate;
break;
- }
}
}
+ }
freeifaddrs(ifas);
return ierr;
#else
/* TODO: Implement on more platforms. */
- fqdn=this->GetHostname();
+ fqdn = this->GetHostname();
return -1;
#endif
}
@@ -1792,11 +1729,10 @@ const char* SystemInformationImplementation::GetOSPlatform()
}
/** Get the vendor ID */
-const char * SystemInformationImplementation::GetVendorID()
+const char* SystemInformationImplementation::GetVendorID()
{
// Return the vendor ID.
- switch (this->ChipManufacturer)
- {
+ switch (this->ChipManufacturer) {
case Intel:
return "Intel Corporation";
case AMD:
@@ -1823,58 +1759,59 @@ const char * SystemInformationImplementation::GetVendorID()
return "Motorola";
case HP:
return "Hewlett-Packard";
+ case UnknownManufacturer:
default:
return "Unknown Manufacturer";
- }
+ }
}
/** Return the type ID of the CPU */
-kwsys_stl::string SystemInformationImplementation::GetTypeID()
+std::string SystemInformationImplementation::GetTypeID()
{
- kwsys_ios::ostringstream str;
+ std::ostringstream str;
str << this->ChipID.Type;
return str.str();
}
/** Return the family of the CPU present */
-kwsys_stl::string SystemInformationImplementation::GetFamilyID()
+std::string SystemInformationImplementation::GetFamilyID()
{
- kwsys_ios::ostringstream str;
+ std::ostringstream str;
str << this->ChipID.Family;
return str.str();
}
// Return the model of CPU present */
-kwsys_stl::string SystemInformationImplementation::GetModelID()
+std::string SystemInformationImplementation::GetModelID()
{
- kwsys_ios::ostringstream str;
+ std::ostringstream str;
str << this->ChipID.Model;
return str.str();
}
// Return the model name of CPU present */
-kwsys_stl::string SystemInformationImplementation::GetModelName()
+std::string SystemInformationImplementation::GetModelName()
{
return this->ChipID.ModelName;
}
/** Return the stepping code of the CPU present. */
-kwsys_stl::string SystemInformationImplementation::GetSteppingCode()
+std::string SystemInformationImplementation::GetSteppingCode()
{
- kwsys_ios::ostringstream str;
+ std::ostringstream str;
str << this->ChipID.Revision;
return str.str();
}
/** Return the stepping code of the CPU present. */
-const char * SystemInformationImplementation::GetExtendedProcessorName()
+const char* SystemInformationImplementation::GetExtendedProcessorName()
{
return this->ChipID.ProcessorName.c_str();
}
/** Return the serial number of the processor
* in hexadecimal: xxxx-xxxx-xxxx-xxxx-xxxx-xxxx. */
-const char * SystemInformationImplementation::GetProcessorSerialNumber()
+const char* SystemInformationImplementation::GetProcessorSerialNumber()
{
return this->ChipID.SerialNumber.c_str();
}
@@ -1906,115 +1843,162 @@ int SystemInformationImplementation::GetProcessorCacheSize()
/** Return the chosen cache size. */
int SystemInformationImplementation::GetProcessorCacheXSize(long int dwCacheID)
{
- switch (dwCacheID)
- {
- case L1CACHE_FEATURE:
+ switch (dwCacheID) {
+ case SystemInformation::CPU_FEATURE_L1CACHE:
return this->Features.L1CacheSize;
- case L2CACHE_FEATURE:
+ case SystemInformation::CPU_FEATURE_L2CACHE:
return this->Features.L2CacheSize;
- case L3CACHE_FEATURE:
+ case SystemInformation::CPU_FEATURE_L3CACHE:
return this->Features.L3CacheSize;
- }
+ }
return -1;
}
-
bool SystemInformationImplementation::DoesCPUSupportFeature(long int dwFeature)
{
bool bHasFeature = false;
// Check for MMX instructions.
- if (((dwFeature & MMX_FEATURE) != 0) && this->Features.HasMMX) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_MMX) != 0) &&
+ this->Features.HasMMX)
+ bHasFeature = true;
// Check for MMX+ instructions.
- if (((dwFeature & MMX_PLUS_FEATURE) != 0) && this->Features.ExtendedFeatures.HasMMXPlus) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_MMX_PLUS) != 0) &&
+ this->Features.ExtendedFeatures.HasMMXPlus)
+ bHasFeature = true;
// Check for SSE FP instructions.
- if (((dwFeature & SSE_FEATURE) != 0) && this->Features.HasSSE) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_SSE) != 0) &&
+ this->Features.HasSSE)
+ bHasFeature = true;
// Check for SSE FP instructions.
- if (((dwFeature & SSE_FP_FEATURE) != 0) && this->Features.HasSSEFP) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_SSE_FP) != 0) &&
+ this->Features.HasSSEFP)
+ bHasFeature = true;
// Check for SSE MMX instructions.
- if (((dwFeature & SSE_MMX_FEATURE) != 0) && this->Features.ExtendedFeatures.HasSSEMMX) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_SSE_MMX) != 0) &&
+ this->Features.ExtendedFeatures.HasSSEMMX)
+ bHasFeature = true;
// Check for SSE2 instructions.
- if (((dwFeature & SSE2_FEATURE) != 0) && this->Features.HasSSE2) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_SSE2) != 0) &&
+ this->Features.HasSSE2)
+ bHasFeature = true;
// Check for 3DNow! instructions.
- if (((dwFeature & AMD_3DNOW_FEATURE) != 0) && this->Features.ExtendedFeatures.Has3DNow) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_AMD_3DNOW) != 0) &&
+ this->Features.ExtendedFeatures.Has3DNow)
+ bHasFeature = true;
// Check for 3DNow+ instructions.
- if (((dwFeature & AMD_3DNOW_PLUS_FEATURE) != 0) && this->Features.ExtendedFeatures.Has3DNowPlus) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS) != 0) &&
+ this->Features.ExtendedFeatures.Has3DNowPlus)
+ bHasFeature = true;
// Check for IA64 instructions.
- if (((dwFeature & IA64_FEATURE) != 0) && this->Features.HasIA64) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_IA64) != 0) &&
+ this->Features.HasIA64)
+ bHasFeature = true;
// Check for MP capable.
- if (((dwFeature & MP_CAPABLE) != 0) && this->Features.ExtendedFeatures.SupportsMP) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_MP_CAPABLE) != 0) &&
+ this->Features.ExtendedFeatures.SupportsMP)
+ bHasFeature = true;
// Check for a serial number for the processor.
- if (((dwFeature & SERIALNUMBER_FEATURE) != 0) && this->Features.HasSerial) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_SERIALNUMBER) != 0) &&
+ this->Features.HasSerial)
+ bHasFeature = true;
// Check for a local APIC in the processor.
- if (((dwFeature & APIC_FEATURE) != 0) && this->Features.HasAPIC) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_APIC) != 0) &&
+ this->Features.HasAPIC)
+ bHasFeature = true;
// Check for CMOV instructions.
- if (((dwFeature & CMOV_FEATURE) != 0) && this->Features.HasCMOV) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_CMOV) != 0) &&
+ this->Features.HasCMOV)
+ bHasFeature = true;
// Check for MTRR instructions.
- if (((dwFeature & MTRR_FEATURE) != 0) && this->Features.HasMTRR) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_MTRR) != 0) &&
+ this->Features.HasMTRR)
+ bHasFeature = true;
// Check for L1 cache size.
- if (((dwFeature & L1CACHE_FEATURE) != 0) && (this->Features.L1CacheSize != -1)) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_L1CACHE) != 0) &&
+ (this->Features.L1CacheSize != -1))
+ bHasFeature = true;
// Check for L2 cache size.
- if (((dwFeature & L2CACHE_FEATURE) != 0) && (this->Features.L2CacheSize != -1)) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_L2CACHE) != 0) &&
+ (this->Features.L2CacheSize != -1))
+ bHasFeature = true;
// Check for L3 cache size.
- if (((dwFeature & L3CACHE_FEATURE) != 0) && (this->Features.L3CacheSize != -1)) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_L3CACHE) != 0) &&
+ (this->Features.L3CacheSize != -1))
+ bHasFeature = true;
// Check for ACPI capability.
- if (((dwFeature & ACPI_FEATURE) != 0) && this->Features.HasACPI) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_ACPI) != 0) &&
+ this->Features.HasACPI)
+ bHasFeature = true;
// Check for thermal monitor support.
- if (((dwFeature & THERMALMONITOR_FEATURE) != 0) && this->Features.HasThermal) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_THERMALMONITOR) != 0) &&
+ this->Features.HasThermal)
+ bHasFeature = true;
// Check for temperature sensing diode support.
- if (((dwFeature & TEMPSENSEDIODE_FEATURE) != 0) && this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_TEMPSENSEDIODE) != 0) &&
+ this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode)
+ bHasFeature = true;
// Check for frequency ID support.
- if (((dwFeature & FREQUENCYID_FEATURE) != 0) && this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_FREQUENCYID) != 0) &&
+ this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID)
+ bHasFeature = true;
// Check for voltage ID support.
- if (((dwFeature & VOLTAGEID_FREQUENCY) != 0) && this->Features.ExtendedFeatures.PowerManagement.HasVoltageID) bHasFeature = true;
+ if (((dwFeature & SystemInformation::CPU_FEATURE_VOLTAGEID_FREQUENCY) !=
+ 0) &&
+ this->Features.ExtendedFeatures.PowerManagement.HasVoltageID)
+ bHasFeature = true;
+
+ // Check for FPU support.
+ if (((dwFeature & SystemInformation::CPU_FEATURE_FPU) != 0) &&
+ this->Features.HasFPU)
+ bHasFeature = true;
return bHasFeature;
}
-
void SystemInformationImplementation::Delay(unsigned int uiMS)
{
-#ifdef WIN32
+#ifdef _WIN32
LARGE_INTEGER Frequency, StartCounter, EndCounter;
__int64 x;
// Get the frequency of the high performance counter.
- if (!QueryPerformanceFrequency (&Frequency)) return;
+ if (!QueryPerformanceFrequency(&Frequency))
+ return;
x = Frequency.QuadPart / 1000 * uiMS;
// Get the starting position of the counter.
- QueryPerformanceCounter (&StartCounter);
+ QueryPerformanceCounter(&StartCounter);
do {
// Get the ending position of the counter.
- QueryPerformanceCounter (&EndCounter);
- } while (EndCounter.QuadPart - StartCounter.QuadPart < x);
+ QueryPerformanceCounter(&EndCounter);
+ } while (EndCounter.QuadPart - StartCounter.QuadPart < x);
#endif
(void)uiMS;
}
-
bool SystemInformationImplementation::DoesCPUSupportCPUID()
{
#if USE_CPUID
@@ -2032,76 +2016,80 @@ bool SystemInformationImplementation::DoesCPUSupportCPUID()
#endif
}
-
bool SystemInformationImplementation::RetrieveCPUFeatures()
{
#if USE_CPUID
int cpuinfo[4] = { 0, 0, 0, 0 };
- if (!call_cpuid(1, cpuinfo))
- {
+ if (!call_cpuid(1, cpuinfo)) {
return false;
- }
+ }
// Retrieve the features of CPU present.
- this->Features.HasFPU = ((cpuinfo[3] & 0x00000001) != 0); // FPU Present --> Bit 0
- this->Features.HasTSC = ((cpuinfo[3] & 0x00000010) != 0); // TSC Present --> Bit 4
- this->Features.HasAPIC = ((cpuinfo[3] & 0x00000200) != 0); // APIC Present --> Bit 9
- this->Features.HasMTRR = ((cpuinfo[3] & 0x00001000) != 0); // MTRR Present --> Bit 12
- this->Features.HasCMOV = ((cpuinfo[3] & 0x00008000) != 0); // CMOV Present --> Bit 15
- this->Features.HasSerial = ((cpuinfo[3] & 0x00040000) != 0); // Serial Present --> Bit 18
- this->Features.HasACPI = ((cpuinfo[3] & 0x00400000) != 0); // ACPI Capable --> Bit 22
- this->Features.HasMMX = ((cpuinfo[3] & 0x00800000) != 0); // MMX Present --> Bit 23
- this->Features.HasSSE = ((cpuinfo[3] & 0x02000000) != 0); // SSE Present --> Bit 25
- this->Features.HasSSE2 = ((cpuinfo[3] & 0x04000000) != 0); // SSE2 Present --> Bit 26
- this->Features.HasThermal = ((cpuinfo[3] & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29
- this->Features.HasIA64 = ((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30
+ this->Features.HasFPU =
+ ((cpuinfo[3] & 0x00000001) != 0); // FPU Present --> Bit 0
+ this->Features.HasTSC =
+ ((cpuinfo[3] & 0x00000010) != 0); // TSC Present --> Bit 4
+ this->Features.HasAPIC =
+ ((cpuinfo[3] & 0x00000200) != 0); // APIC Present --> Bit 9
+ this->Features.HasMTRR =
+ ((cpuinfo[3] & 0x00001000) != 0); // MTRR Present --> Bit 12
+ this->Features.HasCMOV =
+ ((cpuinfo[3] & 0x00008000) != 0); // CMOV Present --> Bit 15
+ this->Features.HasSerial =
+ ((cpuinfo[3] & 0x00040000) != 0); // Serial Present --> Bit 18
+ this->Features.HasACPI =
+ ((cpuinfo[3] & 0x00400000) != 0); // ACPI Capable --> Bit 22
+ this->Features.HasMMX =
+ ((cpuinfo[3] & 0x00800000) != 0); // MMX Present --> Bit 23
+ this->Features.HasSSE =
+ ((cpuinfo[3] & 0x02000000) != 0); // SSE Present --> Bit 25
+ this->Features.HasSSE2 =
+ ((cpuinfo[3] & 0x04000000) != 0); // SSE2 Present --> Bit 26
+ this->Features.HasThermal =
+ ((cpuinfo[3] & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29
+ this->Features.HasIA64 =
+ ((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30
#if USE_ASM_INSTRUCTIONS
// Retrieve extended SSE capabilities if SSE is available.
if (this->Features.HasSSE) {
// Attempt to __try some SSE FP instructions.
- __try
- {
+ __try {
// Perform: orps xmm0, xmm0
_asm
- {
+ {
_emit 0x0f
_emit 0x56
_emit 0xc0
- }
+ }
// SSE FP capable processor.
this->Features.HasSSEFP = true;
- }
- __except(1)
- {
+ } __except (1) {
// bad instruction - processor or OS cannot handle SSE FP.
this->Features.HasSSEFP = false;
- }
}
- else
- {
+ } else {
// Set the advanced SSE capabilities to not available.
this->Features.HasSSEFP = false;
- }
+ }
#else
this->Features.HasSSEFP = false;
#endif
// Retrieve Intel specific extended features.
- if (this->ChipManufacturer == Intel)
- {
- this->Features.ExtendedFeatures.SupportsHyperthreading = ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28
- this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((cpuinfo[1] & 0x00FF0000) >> 16) : 1;
+ if (this->ChipManufacturer == Intel) {
+ bool SupportsSMT =
+ ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28
- if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && (this->Features.HasAPIC))
- {
+ if ((SupportsSMT) && (this->Features.HasAPIC)) {
// Retrieve APIC information if there is one present.
- this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24);
- }
+ this->Features.ExtendedFeatures.APIC_ID =
+ ((cpuinfo[1] & 0xFF000000) >> 24);
}
+ }
return true;
@@ -2110,30 +2098,46 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
#endif
}
-
/** Find the manufacturer given the vendor id */
-void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& family)
-{
- if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp.
- else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp.
- else if (this->ChipID.Vendor == "AuthenticAMD") 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 == "CyrixInstead") this->ChipManufacturer = Cyrix; // Cyrix Corp., VIA Inc.
- else if (this->ChipID.Vendor == "NexGenDriven") this->ChipManufacturer = NexGen; // NexGen Inc. (now AMD)
- else if (this->ChipID.Vendor == "CentaurHauls") this->ChipManufacturer = IDT; // IDT/Centaur (now VIA)
- else if (this->ChipID.Vendor == "RiseRiseRise") this->ChipManufacturer = Rise; // Rise
- else if (this->ChipID.Vendor == "GenuineTMx86") this->ChipManufacturer = Transmeta; // Transmeta
- else if (this->ChipID.Vendor == "TransmetaCPU") this->ChipManufacturer = Transmeta; // Transmeta
- else if (this->ChipID.Vendor == "Geode By NSC") this->ChipManufacturer = NSC; // National Semiconductor
- else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics
- else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics
- else if (this->ChipID.Vendor == "Hewlett-Packard") this->ChipManufacturer = HP; // Hewlett-Packard
- else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics
- else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard
- else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
+void SystemInformationImplementation::FindManufacturer(
+ const std::string& family)
+{
+ if (this->ChipID.Vendor == "GenuineIntel")
+ this->ChipManufacturer = Intel; // Intel Corp.
+ else if (this->ChipID.Vendor == "UMC UMC UMC ")
+ this->ChipManufacturer = UMC; // United Microelectronics Corp.
+ else if (this->ChipID.Vendor == "AuthenticAMD")
+ 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 == "CyrixInstead")
+ this->ChipManufacturer = Cyrix; // Cyrix Corp., VIA Inc.
+ else if (this->ChipID.Vendor == "NexGenDriven")
+ this->ChipManufacturer = NexGen; // NexGen Inc. (now AMD)
+ else if (this->ChipID.Vendor == "CentaurHauls")
+ this->ChipManufacturer = IDT; // IDT/Centaur (now VIA)
+ else if (this->ChipID.Vendor == "RiseRiseRise")
+ this->ChipManufacturer = Rise; // Rise
+ else if (this->ChipID.Vendor == "GenuineTMx86")
+ this->ChipManufacturer = Transmeta; // Transmeta
+ else if (this->ChipID.Vendor == "TransmetaCPU")
+ this->ChipManufacturer = Transmeta; // Transmeta
+ else if (this->ChipID.Vendor == "Geode By NSC")
+ this->ChipManufacturer = NSC; // National Semiconductor
+ else if (this->ChipID.Vendor == "Sun")
+ this->ChipManufacturer = Sun; // Sun Microelectronics
+ else if (this->ChipID.Vendor == "IBM")
+ this->ChipManufacturer = IBM; // IBM Microelectronics
+ else if (this->ChipID.Vendor == "Hewlett-Packard")
+ this->ChipManufacturer = HP; // Hewlett-Packard
+ else if (this->ChipID.Vendor == "Motorola")
+ this->ChipManufacturer = Motorola; // Motorola Microelectronics
+ else if (family.substr(0, 7) == "PA-RISC")
+ this->ChipManufacturer = HP; // Hewlett-Packard
+ else
+ this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
}
-
/** */
bool SystemInformationImplementation::RetrieveCPUIdentity()
{
@@ -2141,14 +2145,12 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
int localCPUVendor[4];
int localCPUSignature[4];
- if (!call_cpuid(0, localCPUVendor))
- {
+ if (!call_cpuid(0, localCPUVendor)) {
return false;
- }
- if (!call_cpuid(1, localCPUSignature))
- {
+ }
+ if (!call_cpuid(1, localCPUSignature)) {
return false;
- }
+ }
// Process the returned information.
// ; eax = 0 --> eax: maximum value of CPUID instruction.
@@ -2156,22 +2158,30 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
// ; edx: part 2 of 3; CPU signature.
// ; ecx: part 3 of 3; CPU signature.
char vbuf[13];
- memcpy (&(vbuf[0]), &(localCPUVendor[1]), sizeof (int));
- memcpy (&(vbuf[4]), &(localCPUVendor[3]), sizeof (int));
- memcpy (&(vbuf[8]), &(localCPUVendor[2]), sizeof (int));
+ memcpy(&(vbuf[0]), &(localCPUVendor[1]), sizeof(int));
+ memcpy(&(vbuf[4]), &(localCPUVendor[3]), sizeof(int));
+ memcpy(&(vbuf[8]), &(localCPUVendor[2]), sizeof(int));
vbuf[12] = '\0';
this->ChipID.Vendor = vbuf;
// Retrieve the family of CPU present.
- // ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
- // ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
+ // ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type,
+ // bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
+ // ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID,
+ // 15..8 - CFLUSH chunk size , 7..0 - brand ID
// ; edx: CPU feature flags
- this->ChipID.ExtendedFamily = ((localCPUSignature[0] & 0x0FF00000) >> 20); // Bits 27..20 Used
- this->ChipID.ExtendedModel = ((localCPUSignature[0] & 0x000F0000) >> 16); // Bits 19..16 Used
- this->ChipID.Type = ((localCPUSignature[0] & 0x0000F000) >> 12); // Bits 15..12 Used
- this->ChipID.Family = ((localCPUSignature[0] & 0x00000F00) >> 8); // Bits 11..8 Used
- this->ChipID.Model = ((localCPUSignature[0] & 0x000000F0) >> 4); // Bits 7..4 Used
- this->ChipID.Revision = ((localCPUSignature[0] & 0x0000000F) >> 0); // Bits 3..0 Used
+ this->ChipID.ExtendedFamily =
+ ((localCPUSignature[0] & 0x0FF00000) >> 20); // Bits 27..20 Used
+ this->ChipID.ExtendedModel =
+ ((localCPUSignature[0] & 0x000F0000) >> 16); // Bits 19..16 Used
+ this->ChipID.Type =
+ ((localCPUSignature[0] & 0x0000F000) >> 12); // Bits 15..12 Used
+ this->ChipID.Family =
+ ((localCPUSignature[0] & 0x00000F00) >> 8); // Bits 11..8 Used
+ this->ChipID.Model =
+ ((localCPUSignature[0] & 0x000000F0) >> 4); // Bits 7..4 Used
+ this->ChipID.Revision =
+ ((localCPUSignature[0] & 0x0000000F) >> 0); // Bits 3..0 Used
return true;
@@ -2180,7 +2190,6 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
#endif
}
-
/** */
bool SystemInformationImplementation::RetrieveCPUCacheDetails()
{
@@ -2189,37 +2198,30 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails()
int L2Cache[4] = { 0, 0, 0, 0 };
// Check to see if what we are about to do is supported...
- if (RetrieveCPUExtendedLevelSupport (0x80000005))
- {
- if (!call_cpuid(0x80000005, L1Cache))
- {
+ if (RetrieveCPUExtendedLevelSupport(0x80000005)) {
+ if (!call_cpuid(0x80000005, L1Cache)) {
return false;
- }
- // Save the L1 data cache size (in KB) from ecx: bits 31..24 as well as data cache size from edx: bits 31..24.
+ }
+ // Save the L1 data cache size (in KB) from ecx: bits 31..24 as well as
+ // data cache size from edx: bits 31..24.
this->Features.L1CacheSize = ((L1Cache[2] & 0xFF000000) >> 24);
this->Features.L1CacheSize += ((L1Cache[3] & 0xFF000000) >> 24);
- }
- else
- {
+ } else {
// Store -1 to indicate the cache could not be queried.
this->Features.L1CacheSize = -1;
- }
+ }
// Check to see if what we are about to do is supported...
- if (RetrieveCPUExtendedLevelSupport (0x80000006))
- {
- if (!call_cpuid(0x80000006, L2Cache))
- {
+ if (RetrieveCPUExtendedLevelSupport(0x80000006)) {
+ if (!call_cpuid(0x80000006, L2Cache)) {
return false;
- }
+ }
// Save the L2 unified cache size (in KB) from ecx: bits 31..16.
this->Features.L2CacheSize = ((L2Cache[2] & 0xFFFF0000) >> 16);
- }
- else
- {
+ } else {
// Store -1 to indicate the cache could not be queried.
this->Features.L2CacheSize = -1;
- }
+ }
// Define L3 as being not present as we cannot test for it.
this->Features.L3CacheSize = -1;
@@ -2227,173 +2229,294 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails()
#endif
// Return failure if we cannot detect either cache with this method.
- return ((this->Features.L1CacheSize == -1) && (this->Features.L2CacheSize == -1)) ? false : true;
+ return ((this->Features.L1CacheSize == -1) &&
+ (this->Features.L2CacheSize == -1))
+ ? false
+ : true;
}
-
/** */
bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
{
#if USE_CPUID
- int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1;
+ int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1,
+ L2Unified = -1, L3Unified = -1;
int TLBCacheData[4] = { 0, 0, 0, 0 };
int TLBPassCounter = 0;
int TLBCacheUnit = 0;
-
do {
- if (!call_cpuid(2, TLBCacheData))
- {
+ if (!call_cpuid(2, TLBCacheData)) {
return false;
- }
+ }
int bob = ((TLBCacheData[0] & 0x00FF0000) >> 16);
(void)bob;
// Process the returned TLB and cache information.
- for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter ++)
- {
+ for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter++) {
// First of all - decide which unit we are dealing with.
- switch (nCounter)
- {
+ switch (nCounter) {
// eax: bits 8..15 : bits 16..23 : bits 24..31
- case 0: TLBCacheUnit = ((TLBCacheData[0] & 0x0000FF00) >> 8); break;
- case 1: TLBCacheUnit = ((TLBCacheData[0] & 0x00FF0000) >> 16); break;
- case 2: TLBCacheUnit = ((TLBCacheData[0] & 0xFF000000) >> 24); break;
+ case 0:
+ TLBCacheUnit = ((TLBCacheData[0] & 0x0000FF00) >> 8);
+ break;
+ case 1:
+ TLBCacheUnit = ((TLBCacheData[0] & 0x00FF0000) >> 16);
+ break;
+ case 2:
+ TLBCacheUnit = ((TLBCacheData[0] & 0xFF000000) >> 24);
+ break;
// ebx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
- case 3: TLBCacheUnit = ((TLBCacheData[1] & 0x000000FF) >> 0); break;
- case 4: TLBCacheUnit = ((TLBCacheData[1] & 0x0000FF00) >> 8); break;
- case 5: TLBCacheUnit = ((TLBCacheData[1] & 0x00FF0000) >> 16); break;
- case 6: TLBCacheUnit = ((TLBCacheData[1] & 0xFF000000) >> 24); break;
+ case 3:
+ TLBCacheUnit = ((TLBCacheData[1] & 0x000000FF) >> 0);
+ break;
+ case 4:
+ TLBCacheUnit = ((TLBCacheData[1] & 0x0000FF00) >> 8);
+ break;
+ case 5:
+ TLBCacheUnit = ((TLBCacheData[1] & 0x00FF0000) >> 16);
+ break;
+ case 6:
+ TLBCacheUnit = ((TLBCacheData[1] & 0xFF000000) >> 24);
+ break;
// ecx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
- case 7: TLBCacheUnit = ((TLBCacheData[2] & 0x000000FF) >> 0); break;
- case 8: TLBCacheUnit = ((TLBCacheData[2] & 0x0000FF00) >> 8); break;
- case 9: TLBCacheUnit = ((TLBCacheData[2] & 0x00FF0000) >> 16); break;
- case 10: TLBCacheUnit = ((TLBCacheData[2] & 0xFF000000) >> 24); break;
+ case 7:
+ TLBCacheUnit = ((TLBCacheData[2] & 0x000000FF) >> 0);
+ break;
+ case 8:
+ TLBCacheUnit = ((TLBCacheData[2] & 0x0000FF00) >> 8);
+ break;
+ case 9:
+ TLBCacheUnit = ((TLBCacheData[2] & 0x00FF0000) >> 16);
+ break;
+ case 10:
+ TLBCacheUnit = ((TLBCacheData[2] & 0xFF000000) >> 24);
+ break;
// edx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
- case 11: TLBCacheUnit = ((TLBCacheData[3] & 0x000000FF) >> 0); break;
- case 12: TLBCacheUnit = ((TLBCacheData[3] & 0x0000FF00) >> 8); break;
- case 13: TLBCacheUnit = ((TLBCacheData[3] & 0x00FF0000) >> 16); break;
- case 14: TLBCacheUnit = ((TLBCacheData[3] & 0xFF000000) >> 24); break;
+ case 11:
+ TLBCacheUnit = ((TLBCacheData[3] & 0x000000FF) >> 0);
+ break;
+ case 12:
+ TLBCacheUnit = ((TLBCacheData[3] & 0x0000FF00) >> 8);
+ break;
+ case 13:
+ TLBCacheUnit = ((TLBCacheData[3] & 0x00FF0000) >> 16);
+ break;
+ case 14:
+ TLBCacheUnit = ((TLBCacheData[3] & 0xFF000000) >> 24);
+ break;
- // Default case - an error has occured.
- default: return false;
- }
+ // Default case - an error has occurred.
+ default:
+ return false;
+ }
// Now process the resulting unit to see what it means....
- switch (TLBCacheUnit)
- {
- case 0x00: break;
- case 0x01: STORE_TLBCACHE_INFO (TLBCode, 4); break;
- case 0x02: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
- case 0x03: STORE_TLBCACHE_INFO (TLBData, 4); break;
- case 0x04: STORE_TLBCACHE_INFO (TLBData, 4096); break;
- case 0x06: STORE_TLBCACHE_INFO (L1Code, 8); break;
- case 0x08: STORE_TLBCACHE_INFO (L1Code, 16); break;
- case 0x0a: STORE_TLBCACHE_INFO (L1Data, 8); break;
- case 0x0c: STORE_TLBCACHE_INFO (L1Data, 16); break;
- case 0x10: STORE_TLBCACHE_INFO (L1Data, 16); break; // <-- FIXME: IA-64 Only
- case 0x15: STORE_TLBCACHE_INFO (L1Code, 16); break; // <-- FIXME: IA-64 Only
- case 0x1a: STORE_TLBCACHE_INFO (L2Unified, 96); break; // <-- FIXME: IA-64 Only
- case 0x22: STORE_TLBCACHE_INFO (L3Unified, 512); break;
- case 0x23: STORE_TLBCACHE_INFO (L3Unified, 1024); break;
- case 0x25: STORE_TLBCACHE_INFO (L3Unified, 2048); break;
- case 0x29: STORE_TLBCACHE_INFO (L3Unified, 4096); break;
- case 0x39: STORE_TLBCACHE_INFO (L2Unified, 128); break;
- case 0x3c: STORE_TLBCACHE_INFO (L2Unified, 256); break;
- case 0x40: STORE_TLBCACHE_INFO (L2Unified, 0); break; // <-- FIXME: No integrated L2 cache (P6 core) or L3 cache (P4 core).
- case 0x41: STORE_TLBCACHE_INFO (L2Unified, 128); break;
- case 0x42: STORE_TLBCACHE_INFO (L2Unified, 256); break;
- case 0x43: STORE_TLBCACHE_INFO (L2Unified, 512); break;
- case 0x44: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
- case 0x45: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
- case 0x50: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
- case 0x51: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
- case 0x52: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
- case 0x5b: STORE_TLBCACHE_INFO (TLBData, 4096); break;
- case 0x5c: STORE_TLBCACHE_INFO (TLBData, 4096); break;
- case 0x5d: STORE_TLBCACHE_INFO (TLBData, 4096); break;
- case 0x66: STORE_TLBCACHE_INFO (L1Data, 8); break;
- case 0x67: STORE_TLBCACHE_INFO (L1Data, 16); break;
- case 0x68: STORE_TLBCACHE_INFO (L1Data, 32); break;
- case 0x70: STORE_TLBCACHE_INFO (L1Trace, 12); break;
- case 0x71: STORE_TLBCACHE_INFO (L1Trace, 16); break;
- case 0x72: STORE_TLBCACHE_INFO (L1Trace, 32); break;
- case 0x77: STORE_TLBCACHE_INFO (L1Code, 16); break; // <-- FIXME: IA-64 Only
- case 0x79: STORE_TLBCACHE_INFO (L2Unified, 128); break;
- case 0x7a: STORE_TLBCACHE_INFO (L2Unified, 256); break;
- case 0x7b: STORE_TLBCACHE_INFO (L2Unified, 512); break;
- case 0x7c: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
- case 0x7e: STORE_TLBCACHE_INFO (L2Unified, 256); break;
- case 0x81: STORE_TLBCACHE_INFO (L2Unified, 128); break;
- case 0x82: STORE_TLBCACHE_INFO (L2Unified, 256); break;
- case 0x83: STORE_TLBCACHE_INFO (L2Unified, 512); break;
- case 0x84: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
- case 0x85: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
- case 0x88: STORE_TLBCACHE_INFO (L3Unified, 2048); break; // <-- FIXME: IA-64 Only
- case 0x89: STORE_TLBCACHE_INFO (L3Unified, 4096); break; // <-- FIXME: IA-64 Only
- case 0x8a: STORE_TLBCACHE_INFO (L3Unified, 8192); break; // <-- FIXME: IA-64 Only
- case 0x8d: STORE_TLBCACHE_INFO (L3Unified, 3096); break; // <-- FIXME: IA-64 Only
- case 0x90: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
- case 0x96: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
- case 0x9b: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
-
- // Default case - an error has occured.
- default: return false;
- }
+ switch (TLBCacheUnit) {
+ case 0x00:
+ break;
+ case 0x01:
+ STORE_TLBCACHE_INFO(TLBCode, 4);
+ break;
+ case 0x02:
+ STORE_TLBCACHE_INFO(TLBCode, 4096);
+ break;
+ case 0x03:
+ STORE_TLBCACHE_INFO(TLBData, 4);
+ break;
+ case 0x04:
+ STORE_TLBCACHE_INFO(TLBData, 4096);
+ break;
+ case 0x06:
+ STORE_TLBCACHE_INFO(L1Code, 8);
+ break;
+ case 0x08:
+ STORE_TLBCACHE_INFO(L1Code, 16);
+ break;
+ case 0x0a:
+ STORE_TLBCACHE_INFO(L1Data, 8);
+ break;
+ case 0x0c:
+ STORE_TLBCACHE_INFO(L1Data, 16);
+ break;
+ case 0x10:
+ STORE_TLBCACHE_INFO(L1Data, 16);
+ break; // <-- FIXME: IA-64 Only
+ case 0x15:
+ STORE_TLBCACHE_INFO(L1Code, 16);
+ break; // <-- FIXME: IA-64 Only
+ case 0x1a:
+ STORE_TLBCACHE_INFO(L2Unified, 96);
+ break; // <-- FIXME: IA-64 Only
+ case 0x22:
+ STORE_TLBCACHE_INFO(L3Unified, 512);
+ break;
+ case 0x23:
+ STORE_TLBCACHE_INFO(L3Unified, 1024);
+ break;
+ case 0x25:
+ STORE_TLBCACHE_INFO(L3Unified, 2048);
+ break;
+ case 0x29:
+ STORE_TLBCACHE_INFO(L3Unified, 4096);
+ break;
+ case 0x39:
+ STORE_TLBCACHE_INFO(L2Unified, 128);
+ break;
+ case 0x3c:
+ STORE_TLBCACHE_INFO(L2Unified, 256);
+ break;
+ case 0x40:
+ STORE_TLBCACHE_INFO(L2Unified, 0);
+ break; // <-- FIXME: No integrated L2 cache (P6 core) or L3 cache (P4
+ // core).
+ case 0x41:
+ STORE_TLBCACHE_INFO(L2Unified, 128);
+ break;
+ case 0x42:
+ STORE_TLBCACHE_INFO(L2Unified, 256);
+ break;
+ case 0x43:
+ STORE_TLBCACHE_INFO(L2Unified, 512);
+ break;
+ case 0x44:
+ STORE_TLBCACHE_INFO(L2Unified, 1024);
+ break;
+ case 0x45:
+ STORE_TLBCACHE_INFO(L2Unified, 2048);
+ break;
+ case 0x50:
+ STORE_TLBCACHE_INFO(TLBCode, 4096);
+ break;
+ case 0x51:
+ STORE_TLBCACHE_INFO(TLBCode, 4096);
+ break;
+ case 0x52:
+ STORE_TLBCACHE_INFO(TLBCode, 4096);
+ break;
+ case 0x5b:
+ STORE_TLBCACHE_INFO(TLBData, 4096);
+ break;
+ case 0x5c:
+ STORE_TLBCACHE_INFO(TLBData, 4096);
+ break;
+ case 0x5d:
+ STORE_TLBCACHE_INFO(TLBData, 4096);
+ break;
+ case 0x66:
+ STORE_TLBCACHE_INFO(L1Data, 8);
+ break;
+ case 0x67:
+ STORE_TLBCACHE_INFO(L1Data, 16);
+ break;
+ case 0x68:
+ STORE_TLBCACHE_INFO(L1Data, 32);
+ break;
+ case 0x70:
+ STORE_TLBCACHE_INFO(L1Trace, 12);
+ break;
+ case 0x71:
+ STORE_TLBCACHE_INFO(L1Trace, 16);
+ break;
+ case 0x72:
+ STORE_TLBCACHE_INFO(L1Trace, 32);
+ break;
+ case 0x77:
+ STORE_TLBCACHE_INFO(L1Code, 16);
+ break; // <-- FIXME: IA-64 Only
+ case 0x79:
+ STORE_TLBCACHE_INFO(L2Unified, 128);
+ break;
+ case 0x7a:
+ STORE_TLBCACHE_INFO(L2Unified, 256);
+ break;
+ case 0x7b:
+ STORE_TLBCACHE_INFO(L2Unified, 512);
+ break;
+ case 0x7c:
+ STORE_TLBCACHE_INFO(L2Unified, 1024);
+ break;
+ case 0x7e:
+ STORE_TLBCACHE_INFO(L2Unified, 256);
+ break;
+ case 0x81:
+ STORE_TLBCACHE_INFO(L2Unified, 128);
+ break;
+ case 0x82:
+ STORE_TLBCACHE_INFO(L2Unified, 256);
+ break;
+ case 0x83:
+ STORE_TLBCACHE_INFO(L2Unified, 512);
+ break;
+ case 0x84:
+ STORE_TLBCACHE_INFO(L2Unified, 1024);
+ break;
+ case 0x85:
+ STORE_TLBCACHE_INFO(L2Unified, 2048);
+ break;
+ case 0x88:
+ STORE_TLBCACHE_INFO(L3Unified, 2048);
+ break; // <-- FIXME: IA-64 Only
+ case 0x89:
+ STORE_TLBCACHE_INFO(L3Unified, 4096);
+ break; // <-- FIXME: IA-64 Only
+ case 0x8a:
+ STORE_TLBCACHE_INFO(L3Unified, 8192);
+ break; // <-- FIXME: IA-64 Only
+ case 0x8d:
+ STORE_TLBCACHE_INFO(L3Unified, 3096);
+ break; // <-- FIXME: IA-64 Only
+ case 0x90:
+ STORE_TLBCACHE_INFO(TLBCode, 262144);
+ break; // <-- FIXME: IA-64 Only
+ case 0x96:
+ STORE_TLBCACHE_INFO(TLBCode, 262144);
+ break; // <-- FIXME: IA-64 Only
+ case 0x9b:
+ STORE_TLBCACHE_INFO(TLBCode, 262144);
+ break; // <-- FIXME: IA-64 Only
+
+ // Default case - an error has occurred.
+ default:
+ return false;
}
+ }
// Increment the TLB pass counter.
- TLBPassCounter ++;
- } while ((TLBCacheData[0] & 0x000000FF) > TLBPassCounter);
+ TLBPassCounter++;
+ } while ((TLBCacheData[0] & 0x000000FF) > TLBPassCounter);
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
- if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1))
- {
+ if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1)) {
this->Features.L1CacheSize = -1;
- }
- else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1))
- {
+ } else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1)) {
this->Features.L1CacheSize = L1Trace;
- }
- else if ((L1Code != -1) && (L1Data == -1))
- {
+ } else if ((L1Code != -1) && (L1Data == -1)) {
this->Features.L1CacheSize = L1Code;
- }
- else if ((L1Code == -1) && (L1Data != -1))
- {
+ } else if ((L1Code == -1) && (L1Data != -1)) {
this->Features.L1CacheSize = L1Data;
- }
- else if ((L1Code != -1) && (L1Data != -1))
- {
+ } else if ((L1Code != -1) && (L1Data != -1)) {
this->Features.L1CacheSize = L1Code + L1Data;
- }
- else
- {
+ } else {
this->Features.L1CacheSize = -1;
- }
+ }
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
- if (L2Unified == -1)
- {
+ if (L2Unified == -1) {
this->Features.L2CacheSize = -1;
- }
- else
- {
+ } else {
this->Features.L2CacheSize = L2Unified;
- }
+ }
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
- if (L3Unified == -1)
- {
+ if (L3Unified == -1) {
this->Features.L3CacheSize = -1;
- }
- else
- {
+ } else {
this->Features.L3CacheSize = L3Unified;
- }
+ }
return true;
@@ -2402,7 +2525,6 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
#endif
}
-
/** */
bool SystemInformationImplementation::RetrieveCPUClockSpeed()
{
@@ -2411,22 +2533,19 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
#if defined(_WIN32)
unsigned int uiRepetitions = 1;
unsigned int uiMSecPerRepetition = 50;
- __int64 i64Total = 0;
+ __int64 i64Total = 0;
__int64 i64Overhead = 0;
// Check if the TSC implementation works at all
if (this->Features.HasTSC &&
GetCyclesDifference(SystemInformationImplementation::Delay,
- uiMSecPerRepetition) > 0)
- {
- for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++)
- {
- i64Total += GetCyclesDifference (SystemInformationImplementation::Delay,
- uiMSecPerRepetition);
- i64Overhead +=
- GetCyclesDifference (SystemInformationImplementation::DelayOverhead,
- uiMSecPerRepetition);
- }
+ uiMSecPerRepetition) > 0) {
+ for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter++) {
+ i64Total += GetCyclesDifference(SystemInformationImplementation::Delay,
+ uiMSecPerRepetition);
+ i64Overhead += GetCyclesDifference(
+ SystemInformationImplementation::DelayOverhead, uiMSecPerRepetition);
+ }
// Calculate the MHz speed.
i64Total -= i64Overhead;
@@ -2435,45 +2554,42 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
i64Total /= 1000;
// Save the CPU speed.
- this->CPUSpeedInMHz = (float) i64Total;
+ this->CPUSpeedInMHz = (float)i64Total;
retrieved = true;
- }
+ }
// If RDTSC is not supported, we fallback to trying to read this value
// from the registry:
- if (!retrieved)
- {
+ if (!retrieved) {
HKEY hKey = NULL;
- LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
- KEY_READ, &hKey);
+ LONG err =
+ RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
+ KEY_READ, &hKey);
- if (ERROR_SUCCESS == err)
- {
+ if (ERROR_SUCCESS == err) {
DWORD dwType = 0;
DWORD data = 0;
DWORD dwSize = sizeof(DWORD);
- err = RegQueryValueEx(hKey, "~MHz", 0,
- &dwType, (LPBYTE) &data, &dwSize);
+ err =
+ RegQueryValueExW(hKey, L"~MHz", 0, &dwType, (LPBYTE)&data, &dwSize);
- if (ERROR_SUCCESS == err)
- {
- this->CPUSpeedInMHz = (float) data;
+ if (ERROR_SUCCESS == err) {
+ this->CPUSpeedInMHz = (float)data;
retrieved = true;
- }
+ }
RegCloseKey(hKey);
hKey = NULL;
- }
}
+ }
#endif
return retrieved;
}
-
/** */
bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed()
{
@@ -2482,51 +2598,43 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed()
double dFrequency, dDifference;
// Attempt to get a starting tick count.
- QueryPerformanceCounter (&liStart);
+ QueryPerformanceCounter(&liStart);
- __try
- {
- _asm
- {
+ __try {
+ _asm {
mov eax, 0x80000000
mov ebx, CLASSICAL_CPU_FREQ_LOOP
Timer_Loop:
bsf ecx,eax
dec ebx
jnz Timer_Loop
- }
}
- __except(1)
- {
+ } __except (1) {
return false;
- }
+ }
// Attempt to get a starting tick count.
- QueryPerformanceCounter (&liEnd);
+ QueryPerformanceCounter(&liEnd);
// Get the difference... NB: This is in seconds....
- QueryPerformanceFrequency (&liCountsPerSecond);
- dDifference = (((double) liEnd.QuadPart - (double) liStart.QuadPart) / (double) liCountsPerSecond.QuadPart);
+ QueryPerformanceFrequency(&liCountsPerSecond);
+ dDifference = (((double)liEnd.QuadPart - (double)liStart.QuadPart) /
+ (double)liCountsPerSecond.QuadPart);
// Calculate the clock speed.
- if (this->ChipID.Family == 3)
- {
+ if (this->ChipID.Family == 3) {
// 80386 processors.... Loop time is 115 cycles!
dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 115) / dDifference) / 1000000);
- }
- else if (this->ChipID.Family == 4)
- {
+ } else if (this->ChipID.Family == 4) {
// 80486 processors.... Loop time is 47 cycles!
dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 47) / dDifference) / 1000000);
- }
- else if (this->ChipID.Family == 5)
- {
+ } else if (this->ChipID.Family == 5) {
// Pentium processors.... Loop time is 43 cycles!
dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 43) / dDifference) / 1000000);
- }
+ }
// Save the clock speed.
- this->Features.CPUSpeed = (int) dFrequency;
+ this->Features.CPUSpeed = (int)dFrequency;
return true;
@@ -2535,13 +2643,14 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed()
#endif
}
-
/** */
-bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULevelToCheck)
+bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(
+ int CPULevelToCheck)
{
int cpuinfo[4] = { 0, 0, 0, 0 };
- // The extended CPUID is supported by various vendors starting with the following CPU models:
+ // The extended CPUID is supported by various vendors starting with the
+ // following CPU models:
//
// Manufacturer & Chip Name | Family Model Revision
//
@@ -2554,39 +2663,36 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev
//
// We check to see if a supported processor is present...
- if (this->ChipManufacturer == AMD)
- {
- if (this->ChipID.Family < 5) return false;
- if ((this->ChipID.Family == 5) && (this->ChipID.Model < 6)) return false;
- }
- else if (this->ChipManufacturer == Cyrix)
- {
- if (this->ChipID.Family < 5) return false;
- if ((this->ChipID.Family == 5) && (this->ChipID.Model < 4)) return false;
- if ((this->ChipID.Family == 6) && (this->ChipID.Model < 5)) return false;
- }
- else if (this->ChipManufacturer == IDT)
- {
- if (this->ChipID.Family < 5) return false;
- if ((this->ChipID.Family == 5) && (this->ChipID.Model < 8)) return false;
- }
- else if (this->ChipManufacturer == Transmeta)
- {
- if (this->ChipID.Family < 5) return false;
- }
- else if (this->ChipManufacturer == Intel)
- {
- if (this->ChipID.Family < 0xf)
- {
+ if (this->ChipManufacturer == AMD) {
+ if (this->ChipID.Family < 5)
+ return false;
+ if ((this->ChipID.Family == 5) && (this->ChipID.Model < 6))
+ return false;
+ } else if (this->ChipManufacturer == Cyrix) {
+ if (this->ChipID.Family < 5)
+ return false;
+ if ((this->ChipID.Family == 5) && (this->ChipID.Model < 4))
+ return false;
+ if ((this->ChipID.Family == 6) && (this->ChipID.Model < 5))
+ return false;
+ } else if (this->ChipManufacturer == IDT) {
+ if (this->ChipID.Family < 5)
+ return false;
+ if ((this->ChipID.Family == 5) && (this->ChipID.Model < 8))
+ return false;
+ } else if (this->ChipManufacturer == Transmeta) {
+ if (this->ChipID.Family < 5)
+ return false;
+ } else if (this->ChipManufacturer == Intel) {
+ if (this->ChipID.Family < 0xf) {
return false;
- }
}
+ }
#if USE_CPUID
- if (!call_cpuid(0x80000000, cpuinfo))
- {
+ if (!call_cpuid(0x80000000, cpuinfo)) {
return false;
- }
+ }
#endif
// Now we have to check the level wanted vs level returned...
@@ -2594,56 +2700,62 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev
int nLevelReturn = (cpuinfo[0] & 0x7FFFFFFF);
// Check to see if the level provided is supported...
- if (nLevelWanted > nLevelReturn)
- {
+ if (nLevelWanted > nLevelReturn) {
return false;
- }
+ }
return true;
}
-
/** */
bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
{
- // Check that we are not using an Intel processor as it does not support this.
- if (this->ChipManufacturer == Intel)
- {
+ // Check that we are not using an Intel processor as it does not support
+ // this.
+ if (this->ChipManufacturer == Intel) {
return false;
- }
+ }
// Check to see if what we are about to do is supported...
- if (!RetrieveCPUExtendedLevelSupport(static_cast<int>(0x80000001)))
- {
+ if (!RetrieveCPUExtendedLevelSupport(static_cast<int>(0x80000001))) {
return false;
- }
+ }
#if USE_CPUID
int localCPUExtendedFeatures[4] = { 0, 0, 0, 0 };
- if (!call_cpuid(0x80000001, localCPUExtendedFeatures))
- {
+ if (!call_cpuid(0x80000001, localCPUExtendedFeatures)) {
return false;
- }
+ }
// Retrieve the extended features of CPU present.
- this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures[3] & 0x80000000) != 0); // 3DNow Present --> Bit 31.
- this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures[3] & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30.
- this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // SSE MMX Present --> Bit 22.
- this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures[3] & 0x00080000) != 0); // MP Capable -- > Bit 19.
+ this->Features.ExtendedFeatures.Has3DNow =
+ ((localCPUExtendedFeatures[3] & 0x80000000) !=
+ 0); // 3DNow Present --> Bit 31.
+ this->Features.ExtendedFeatures.Has3DNowPlus =
+ ((localCPUExtendedFeatures[3] & 0x40000000) !=
+ 0); // 3DNow+ Present -- > Bit 30.
+ this->Features.ExtendedFeatures.HasSSEMMX =
+ ((localCPUExtendedFeatures[3] & 0x00400000) !=
+ 0); // SSE MMX Present --> Bit 22.
+ this->Features.ExtendedFeatures.SupportsMP =
+ ((localCPUExtendedFeatures[3] & 0x00080000) !=
+ 0); // MP Capable -- > Bit 19.
// Retrieve AMD specific extended features.
- if (this->ChipManufacturer == AMD)
- {
- this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22
- }
+ if (this->ChipManufacturer == AMD) {
+ this->Features.ExtendedFeatures.HasMMXPlus =
+ ((localCPUExtendedFeatures[3] & 0x00400000) !=
+ 0); // AMD specific: MMX-SSE --> Bit 22
+ }
// Retrieve Cyrix specific extended features.
- if (this->ChipManufacturer == Cyrix)
- {
- this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24
- }
+ if (this->ChipManufacturer == Cyrix) {
+ this->Features.ExtendedFeatures.HasMMXPlus =
+ ((localCPUExtendedFeatures[3] & 0x01000000) !=
+ 0); // Cyrix specific: Extended MMX --> Bit 24
+ }
return true;
@@ -2652,42 +2764,40 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
#endif
}
-
/** */
bool SystemInformationImplementation::RetrieveProcessorSerialNumber()
{
// Check to see if the processor supports the processor serial number.
- if (!this->Features.HasSerial)
- {
+ if (!this->Features.HasSerial) {
return false;
- }
+ }
#if USE_CPUID
int SerialNumber[4];
- if (!call_cpuid(3, SerialNumber))
- {
+ if (!call_cpuid(3, SerialNumber)) {
return false;
- }
+ }
// Process the returned information.
- // ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!?
+ // ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB:
+ // Transmeta only ?!?
// ; ecx: middle 32 bits are the processor signature bits
// ; edx: bottom 32 bits are the processor signature bits
char sn[128];
- sprintf (sn, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x",
- ((SerialNumber[1] & 0xff000000) >> 24),
- ((SerialNumber[1] & 0x00ff0000) >> 16),
- ((SerialNumber[1] & 0x0000ff00) >> 8),
- ((SerialNumber[1] & 0x000000ff) >> 0),
- ((SerialNumber[2] & 0xff000000) >> 24),
- ((SerialNumber[2] & 0x00ff0000) >> 16),
- ((SerialNumber[2] & 0x0000ff00) >> 8),
- ((SerialNumber[2] & 0x000000ff) >> 0),
- ((SerialNumber[3] & 0xff000000) >> 24),
- ((SerialNumber[3] & 0x00ff0000) >> 16),
- ((SerialNumber[3] & 0x0000ff00) >> 8),
- ((SerialNumber[3] & 0x000000ff) >> 0));
+ sprintf(sn, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x",
+ ((SerialNumber[1] & 0xff000000) >> 24),
+ ((SerialNumber[1] & 0x00ff0000) >> 16),
+ ((SerialNumber[1] & 0x0000ff00) >> 8),
+ ((SerialNumber[1] & 0x000000ff) >> 0),
+ ((SerialNumber[2] & 0xff000000) >> 24),
+ ((SerialNumber[2] & 0x00ff0000) >> 16),
+ ((SerialNumber[2] & 0x0000ff00) >> 8),
+ ((SerialNumber[2] & 0x000000ff) >> 0),
+ ((SerialNumber[3] & 0xff000000) >> 24),
+ ((SerialNumber[3] & 0x00ff0000) >> 16),
+ ((SerialNumber[3] & 0x0000ff00) >> 8),
+ ((SerialNumber[3] & 0x000000ff) >> 0));
this->ChipID.SerialNumber = sn;
return true;
@@ -2696,31 +2806,31 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber()
#endif
}
-
/** */
bool SystemInformationImplementation::RetrieveCPUPowerManagement()
{
// Check to see if what we are about to do is supported...
- if (!RetrieveCPUExtendedLevelSupport(static_cast<int>(0x80000007)))
- {
+ if (!RetrieveCPUExtendedLevelSupport(static_cast<int>(0x80000007))) {
this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = false;
this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = false;
this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = false;
return false;
- }
+ }
#if USE_CPUID
int localCPUPowerManagement[4] = { 0, 0, 0, 0 };
- if (!call_cpuid(0x80000007, localCPUPowerManagement))
- {
+ if (!call_cpuid(0x80000007, localCPUPowerManagement)) {
return false;
- }
+ }
// Check for the power management capabilities of the CPU.
- this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement[3] & 0x00000001) != 0);
- this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement[3] & 0x00000002) != 0);
- this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement[3] & 0x00000004) != 0);
+ this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode =
+ ((localCPUPowerManagement[3] & 0x00000001) != 0);
+ this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID =
+ ((localCPUPowerManagement[3] & 0x00000002) != 0);
+ this->Features.ExtendedFeatures.PowerManagement.HasVoltageID =
+ ((localCPUPowerManagement[3] & 0x00000004) != 0);
return true;
@@ -2731,14 +2841,14 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement()
#if USE_CPUID
// Used only in USE_CPUID implementation below.
-static void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
+static void SystemInformationStripLeadingSpace(std::string& str)
{
- // Because some manufacturers have leading white space - we have to post-process the name.
- kwsys_stl::string::size_type pos = str.find_first_not_of(" ");
- if(pos != kwsys_stl::string::npos)
- {
+ // Because some manufacturers have leading white space - we have to
+ // post-process the name.
+ std::string::size_type pos = str.find_first_not_of(" ");
+ if (pos != std::string::npos) {
str = str.substr(pos);
- }
+ }
}
#endif
@@ -2756,38 +2866,36 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()
#if USE_CPUID
int CPUExtendedIdentity[12];
- if (!call_cpuid(0x80000002, CPUExtendedIdentity))
- {
+ if (!call_cpuid(0x80000002, CPUExtendedIdentity)) {
return false;
- }
- if (!call_cpuid(0x80000003, CPUExtendedIdentity + 4))
- {
+ }
+ if (!call_cpuid(0x80000003, CPUExtendedIdentity + 4)) {
return false;
- }
- if (!call_cpuid(0x80000004, CPUExtendedIdentity + 8))
- {
+ }
+ if (!call_cpuid(0x80000004, CPUExtendedIdentity + 8)) {
return false;
- }
+ }
// Process the returned information.
char nbuf[49];
- memcpy (&(nbuf[0]), &(CPUExtendedIdentity[0]), sizeof (int));
- memcpy (&(nbuf[4]), &(CPUExtendedIdentity[1]), sizeof (int));
- memcpy (&(nbuf[8]), &(CPUExtendedIdentity[2]), sizeof (int));
- memcpy (&(nbuf[12]), &(CPUExtendedIdentity[3]), sizeof (int));
- memcpy (&(nbuf[16]), &(CPUExtendedIdentity[4]), sizeof (int));
- memcpy (&(nbuf[20]), &(CPUExtendedIdentity[5]), sizeof (int));
- memcpy (&(nbuf[24]), &(CPUExtendedIdentity[6]), sizeof (int));
- memcpy (&(nbuf[28]), &(CPUExtendedIdentity[7]), sizeof (int));
- memcpy (&(nbuf[32]), &(CPUExtendedIdentity[8]), sizeof (int));
- memcpy (&(nbuf[36]), &(CPUExtendedIdentity[9]), sizeof (int));
- memcpy (&(nbuf[40]), &(CPUExtendedIdentity[10]), sizeof (int));
- memcpy (&(nbuf[44]), &(CPUExtendedIdentity[11]), sizeof (int));
+ memcpy(&(nbuf[0]), &(CPUExtendedIdentity[0]), sizeof(int));
+ memcpy(&(nbuf[4]), &(CPUExtendedIdentity[1]), sizeof(int));
+ memcpy(&(nbuf[8]), &(CPUExtendedIdentity[2]), sizeof(int));
+ memcpy(&(nbuf[12]), &(CPUExtendedIdentity[3]), sizeof(int));
+ memcpy(&(nbuf[16]), &(CPUExtendedIdentity[4]), sizeof(int));
+ memcpy(&(nbuf[20]), &(CPUExtendedIdentity[5]), sizeof(int));
+ memcpy(&(nbuf[24]), &(CPUExtendedIdentity[6]), sizeof(int));
+ memcpy(&(nbuf[28]), &(CPUExtendedIdentity[7]), sizeof(int));
+ memcpy(&(nbuf[32]), &(CPUExtendedIdentity[8]), sizeof(int));
+ memcpy(&(nbuf[36]), &(CPUExtendedIdentity[9]), sizeof(int));
+ memcpy(&(nbuf[40]), &(CPUExtendedIdentity[10]), sizeof(int));
+ memcpy(&(nbuf[44]), &(CPUExtendedIdentity[11]), sizeof(int));
nbuf[48] = '\0';
this->ChipID.ProcessorName = nbuf;
this->ChipID.ModelName = nbuf;
- // Because some manufacturers have leading white space - we have to post-process the name.
+ // Because some manufacturers have leading white space - we have to
+ // post-process the name.
SystemInformationStripLeadingSpace(this->ChipID.ProcessorName);
return true;
#else
@@ -2795,309 +2903,465 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()
#endif
}
-
/** */
bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
{
// Start by decided which manufacturer we are using....
- switch (this->ChipManufacturer)
- {
+ switch (this->ChipManufacturer) {
case Intel:
// Check the family / model / revision to determine the CPU ID.
switch (this->ChipID.Family) {
case 3:
- this->ChipID.ProcessorName = "Newer i80386 family";
+ this->ChipID.ProcessorName = "Newer i80386 family";
break;
case 4:
switch (this->ChipID.Model) {
- case 0: this->ChipID.ProcessorName = "i80486DX-25/33"; break;
- case 1: this->ChipID.ProcessorName = "i80486DX-50"; break;
- case 2: this->ChipID.ProcessorName = "i80486SX"; break;
- case 3: this->ChipID.ProcessorName = "i80486DX2"; break;
- case 4: this->ChipID.ProcessorName = "i80486SL"; break;
- case 5: this->ChipID.ProcessorName = "i80486SX2"; break;
- case 7: this->ChipID.ProcessorName = "i80486DX2 WriteBack"; break;
- case 8: this->ChipID.ProcessorName = "i80486DX4"; break;
- case 9: this->ChipID.ProcessorName = "i80486DX4 WriteBack"; break;
- default: this->ChipID.ProcessorName = "Unknown 80486 family"; return false;
- }
+ case 0:
+ this->ChipID.ProcessorName = "i80486DX-25/33";
+ break;
+ case 1:
+ this->ChipID.ProcessorName = "i80486DX-50";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "i80486SX";
+ break;
+ case 3:
+ this->ChipID.ProcessorName = "i80486DX2";
+ break;
+ case 4:
+ this->ChipID.ProcessorName = "i80486SL";
+ break;
+ case 5:
+ this->ChipID.ProcessorName = "i80486SX2";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "i80486DX2 WriteBack";
+ break;
+ case 8:
+ this->ChipID.ProcessorName = "i80486DX4";
+ break;
+ case 9:
+ this->ChipID.ProcessorName = "i80486DX4 WriteBack";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown 80486 family";
+ return false;
+ }
break;
case 5:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "P5 A-Step"; break;
- case 1: this->ChipID.ProcessorName = "P5"; break;
- case 2: this->ChipID.ProcessorName = "P54C"; break;
- case 3: this->ChipID.ProcessorName = "P24T OverDrive"; break;
- case 4: this->ChipID.ProcessorName = "P55C"; break;
- case 7: this->ChipID.ProcessorName = "P54C"; break;
- case 8: this->ChipID.ProcessorName = "P55C (0.25micron)"; break;
- default: this->ChipID.ProcessorName = "Unknown Pentium family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "P5 A-Step";
+ break;
+ case 1:
+ this->ChipID.ProcessorName = "P5";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "P54C";
+ break;
+ case 3:
+ this->ChipID.ProcessorName = "P24T OverDrive";
+ break;
+ case 4:
+ this->ChipID.ProcessorName = "P55C";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "P54C";
+ break;
+ case 8:
+ this->ChipID.ProcessorName = "P55C (0.25micron)";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Pentium family";
+ return false;
+ }
break;
case 6:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "P6 A-Step"; break;
- case 1: this->ChipID.ProcessorName = "P6"; break;
- case 3: this->ChipID.ProcessorName = "Pentium II (0.28 micron)"; break;
- case 5: this->ChipID.ProcessorName = "Pentium II (0.25 micron)"; break;
- case 6: this->ChipID.ProcessorName = "Pentium II With On-Die L2 Cache"; break;
- case 7: this->ChipID.ProcessorName = "Pentium III (0.25 micron)"; break;
- case 8: this->ChipID.ProcessorName = "Pentium III (0.18 micron) With 256 KB On-Die L2 Cache "; break;
- case 0xa: this->ChipID.ProcessorName = "Pentium III (0.18 micron) With 1 Or 2 MB On-Die L2 Cache "; break;
- case 0xb: this->ChipID.ProcessorName = "Pentium III (0.13 micron) With 256 Or 512 KB On-Die L2 Cache "; break;
- case 23: this->ChipID.ProcessorName = "Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz"; break;
- default: this->ChipID.ProcessorName = "Unknown P6 family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "P6 A-Step";
+ break;
+ case 1:
+ this->ChipID.ProcessorName = "P6";
+ break;
+ case 3:
+ this->ChipID.ProcessorName = "Pentium II (0.28 micron)";
+ break;
+ case 5:
+ this->ChipID.ProcessorName = "Pentium II (0.25 micron)";
+ break;
+ case 6:
+ this->ChipID.ProcessorName = "Pentium II With On-Die L2 Cache";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "Pentium III (0.25 micron)";
+ break;
+ case 8:
+ this->ChipID.ProcessorName =
+ "Pentium III (0.18 micron) With 256 KB On-Die L2 Cache ";
+ break;
+ case 0xa:
+ this->ChipID.ProcessorName =
+ "Pentium III (0.18 micron) With 1 Or 2 MB On-Die L2 Cache ";
+ break;
+ case 0xb:
+ this->ChipID.ProcessorName = "Pentium III (0.13 micron) With "
+ "256 Or 512 KB On-Die L2 Cache ";
+ break;
+ case 23:
+ this->ChipID.ProcessorName =
+ "Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown P6 family";
+ return false;
+ }
break;
case 7:
this->ChipID.ProcessorName = "Intel Merced (IA-64)";
break;
case 0xf:
// Check the extended family bits...
- switch (this->ChipID.ExtendedFamily)
- {
+ switch (this->ChipID.ExtendedFamily) {
case 0:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "Pentium IV (0.18 micron)"; break;
- case 1: this->ChipID.ProcessorName = "Pentium IV (0.18 micron)"; break;
- case 2: this->ChipID.ProcessorName = "Pentium IV (0.13 micron)"; break;
- default: this->ChipID.ProcessorName = "Unknown Pentium 4 family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "Pentium IV (0.18 micron)";
+ break;
+ case 1:
+ this->ChipID.ProcessorName = "Pentium IV (0.18 micron)";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "Pentium IV (0.13 micron)";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Pentium 4 family";
+ return false;
+ }
break;
case 1:
this->ChipID.ProcessorName = "Intel McKinley (IA-64)";
break;
default:
this->ChipID.ProcessorName = "Pentium";
- }
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown Intel family";
return false;
- }
+ }
break;
case AMD:
// Check the family / model / revision to determine the CPU ID.
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 4:
- switch (this->ChipID.Model)
- {
- case 3: this->ChipID.ProcessorName = "80486DX2"; break;
- case 7: this->ChipID.ProcessorName = "80486DX2 WriteBack"; break;
- case 8: this->ChipID.ProcessorName = "80486DX4"; break;
- case 9: this->ChipID.ProcessorName = "80486DX4 WriteBack"; break;
- case 0xe: this->ChipID.ProcessorName = "5x86"; break;
- case 0xf: this->ChipID.ProcessorName = "5x86WB"; break;
- default: this->ChipID.ProcessorName = "Unknown 80486 family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 3:
+ this->ChipID.ProcessorName = "80486DX2";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "80486DX2 WriteBack";
+ break;
+ case 8:
+ this->ChipID.ProcessorName = "80486DX4";
+ break;
+ case 9:
+ this->ChipID.ProcessorName = "80486DX4 WriteBack";
+ break;
+ case 0xe:
+ this->ChipID.ProcessorName = "5x86";
+ break;
+ case 0xf:
+ this->ChipID.ProcessorName = "5x86WB";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown 80486 family";
+ return false;
+ }
break;
case 5:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "SSA5 (PR75, PR90 = PR100)"; break;
- case 1: this->ChipID.ProcessorName = "5k86 (PR120 = PR133)"; break;
- case 2: this->ChipID.ProcessorName = "5k86 (PR166)"; break;
- case 3: this->ChipID.ProcessorName = "5k86 (PR200)"; break;
- case 6: this->ChipID.ProcessorName = "K6 (0.30 micron)"; break;
- case 7: this->ChipID.ProcessorName = "K6 (0.25 micron)"; break;
- case 8: this->ChipID.ProcessorName = "K6-2"; break;
- case 9: this->ChipID.ProcessorName = "K6-III"; break;
- case 0xd: this->ChipID.ProcessorName = "K6-2+ or K6-III+ (0.18 micron)"; break;
- default: this->ChipID.ProcessorName = "Unknown 80586 family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "SSA5 (PR75, PR90 = PR100)";
+ break;
+ case 1:
+ this->ChipID.ProcessorName = "5k86 (PR120 = PR133)";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "5k86 (PR166)";
+ break;
+ case 3:
+ this->ChipID.ProcessorName = "5k86 (PR200)";
+ break;
+ case 6:
+ this->ChipID.ProcessorName = "K6 (0.30 micron)";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "K6 (0.25 micron)";
+ break;
+ case 8:
+ this->ChipID.ProcessorName = "K6-2";
+ break;
+ case 9:
+ this->ChipID.ProcessorName = "K6-III";
+ break;
+ case 0xd:
+ this->ChipID.ProcessorName = "K6-2+ or K6-III+ (0.18 micron)";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown 80586 family";
+ return false;
+ }
break;
case 6:
- switch (this->ChipID.Model)
- {
- case 1: this->ChipID.ProcessorName = "Athlon- (0.25 micron)"; break;
- case 2: this->ChipID.ProcessorName = "Athlon- (0.18 micron)"; break;
- case 3: this->ChipID.ProcessorName = "Duron- (SF core)"; break;
- case 4: this->ChipID.ProcessorName = "Athlon- (Thunderbird core)"; break;
- case 6: this->ChipID.ProcessorName = "Athlon- (Palomino core)"; break;
- case 7: this->ChipID.ProcessorName = "Duron- (Morgan core)"; break;
+ switch (this->ChipID.Model) {
+ case 1:
+ this->ChipID.ProcessorName = "Athlon- (0.25 micron)";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "Athlon- (0.18 micron)";
+ break;
+ case 3:
+ this->ChipID.ProcessorName = "Duron- (SF core)";
+ break;
+ case 4:
+ this->ChipID.ProcessorName = "Athlon- (Thunderbird core)";
+ break;
+ case 6:
+ this->ChipID.ProcessorName = "Athlon- (Palomino core)";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "Duron- (Morgan core)";
+ break;
case 8:
if (this->Features.ExtendedFeatures.SupportsMP)
this->ChipID.ProcessorName = "Athlon - MP (Thoroughbred core)";
- else this->ChipID.ProcessorName = "Athlon - XP (Thoroughbred core)";
+ else
+ this->ChipID.ProcessorName = "Athlon - XP (Thoroughbred core)";
break;
- default: this->ChipID.ProcessorName = "Unknown K7 family"; return false;
- }
+ default:
+ this->ChipID.ProcessorName = "Unknown K7 family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown AMD family";
return false;
- }
+ }
break;
case Transmeta:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 5:
- switch (this->ChipID.Model)
- {
- case 4: this->ChipID.ProcessorName = "Crusoe TM3x00 and TM5x00"; break;
- default: this->ChipID.ProcessorName = "Unknown Crusoe family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 4:
+ this->ChipID.ProcessorName = "Crusoe TM3x00 and TM5x00";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Crusoe family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown Transmeta family";
return false;
- }
+ }
break;
case Rise:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 5:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "mP6 (0.25 micron)"; break;
- case 2: this->ChipID.ProcessorName = "mP6 (0.18 micron)"; break;
- default: this->ChipID.ProcessorName = "Unknown Rise family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "mP6 (0.25 micron)";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "mP6 (0.18 micron)";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Rise family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown Rise family";
return false;
- }
+ }
break;
case UMC:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 4:
- switch (this->ChipID.Model)
- {
- case 1: this->ChipID.ProcessorName = "U5D"; break;
- case 2: this->ChipID.ProcessorName = "U5S"; break;
- default: this->ChipID.ProcessorName = "Unknown UMC family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 1:
+ this->ChipID.ProcessorName = "U5D";
+ break;
+ case 2:
+ this->ChipID.ProcessorName = "U5S";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown UMC family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown UMC family";
return false;
- }
+ }
break;
case IDT:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 5:
- switch (this->ChipID.Model)
- {
- case 4: this->ChipID.ProcessorName = "C6"; break;
- case 8: this->ChipID.ProcessorName = "C2"; break;
- case 9: this->ChipID.ProcessorName = "C3"; break;
- default: this->ChipID.ProcessorName = "Unknown IDT\\Centaur family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 4:
+ this->ChipID.ProcessorName = "C6";
+ break;
+ case 8:
+ this->ChipID.ProcessorName = "C2";
+ break;
+ case 9:
+ this->ChipID.ProcessorName = "C3";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown IDT\\Centaur family";
+ return false;
+ }
break;
case 6:
- switch (this->ChipID.Model)
- {
- case 6: this->ChipID.ProcessorName = "VIA Cyrix III - Samuel"; break;
- default: this->ChipID.ProcessorName = "Unknown IDT\\Centaur family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 6:
+ this->ChipID.ProcessorName = "VIA Cyrix III - Samuel";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown IDT\\Centaur family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown IDT\\Centaur family";
return false;
- }
+ }
break;
case Cyrix:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 4:
- switch (this->ChipID.Model)
- {
- case 4: this->ChipID.ProcessorName = "MediaGX GX = GXm"; break;
- case 9: this->ChipID.ProcessorName = "5x86"; break;
- default: this->ChipID.ProcessorName = "Unknown Cx5x86 family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 4:
+ this->ChipID.ProcessorName = "MediaGX GX = GXm";
+ break;
+ case 9:
+ this->ChipID.ProcessorName = "5x86";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Cx5x86 family";
+ return false;
+ }
break;
case 5:
- switch (this->ChipID.Model)
- {
- case 2: this->ChipID.ProcessorName = "Cx6x86"; break;
- case 4: this->ChipID.ProcessorName = "MediaGX GXm"; break;
- default: this->ChipID.ProcessorName = "Unknown Cx6x86 family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 2:
+ this->ChipID.ProcessorName = "Cx6x86";
+ break;
+ case 4:
+ this->ChipID.ProcessorName = "MediaGX GXm";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Cx6x86 family";
+ return false;
+ }
break;
case 6:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "6x86MX"; break;
- case 5: this->ChipID.ProcessorName = "Cyrix M2 Core"; break;
- case 6: this->ChipID.ProcessorName = "WinChip C5A Core"; break;
- case 7: this->ChipID.ProcessorName = "WinChip C5B\\C5C Core"; break;
- case 8: this->ChipID.ProcessorName = "WinChip C5C-T Core"; break;
- default: this->ChipID.ProcessorName = "Unknown 6x86MX\\Cyrix III family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "6x86MX";
+ break;
+ case 5:
+ this->ChipID.ProcessorName = "Cyrix M2 Core";
+ break;
+ case 6:
+ this->ChipID.ProcessorName = "WinChip C5A Core";
+ break;
+ case 7:
+ this->ChipID.ProcessorName = "WinChip C5B\\C5C Core";
+ break;
+ case 8:
+ this->ChipID.ProcessorName = "WinChip C5C-T Core";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown 6x86MX\\Cyrix III family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown Cyrix family";
return false;
- }
+ }
break;
case NexGen:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family) {
case 5:
- switch (this->ChipID.Model)
- {
- case 0: this->ChipID.ProcessorName = "Nx586 or Nx586FPU"; break;
- default: this->ChipID.ProcessorName = "Unknown NexGen family"; return false;
- }
+ switch (this->ChipID.Model) {
+ case 0:
+ this->ChipID.ProcessorName = "Nx586 or Nx586FPU";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown NexGen family";
+ return false;
+ }
break;
default:
this->ChipID.ProcessorName = "Unknown NexGen family";
return false;
- }
+ }
break;
case NSC:
this->ChipID.ProcessorName = "Cx486SLC \\ DLC \\ Cx486S A-Step";
break;
+
+ case Sun:
+ case IBM:
+ case Motorola:
+ case HP:
+ case UnknownManufacturer:
default:
- this->ChipID.ProcessorName = "Unknown family"; // We cannot identify the processor.
+ this->ChipID.ProcessorName =
+ "Unknown family"; // We cannot identify the processor.
return false;
- }
+ }
return true;
}
-
/** Extract a value from the CPUInfo file */
-kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(kwsys_stl::string buffer,const char* word,size_t init)
+std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(
+ std::string buffer, const char* word, size_t init)
{
- size_t pos = buffer.find(word,init);
- if(pos != buffer.npos)
- {
+ size_t pos = buffer.find(word, init);
+ if (pos != std::string::npos) {
this->CurrentPositionInFile = pos;
- pos = buffer.find(":",pos);
- size_t pos2 = buffer.find("\n",pos);
- if(pos!=buffer.npos && pos2!=buffer.npos)
- {
- // It may happen that the beginning matches, but this is still not the requested key.
- // An example is looking for "cpu" when "cpu family" comes first. So we check that
+ pos = buffer.find(":", pos);
+ size_t pos2 = buffer.find("\n", pos);
+ if (pos != std::string::npos && pos2 != std::string::npos) {
+ // It may happen that the beginning matches, but this is still not the
+ // requested key.
+ // An example is looking for "cpu" when "cpu family" comes first. So we
+ // check that
// we have only spaces from here to pos, otherwise we search again.
- for(size_t i=this->CurrentPositionInFile+strlen(word); i < pos; ++i)
- {
- if(buffer[i] != ' ' && buffer[i] != '\t')
- {
+ for (size_t i = this->CurrentPositionInFile + strlen(word); i < pos;
+ ++i) {
+ if (buffer[i] != ' ' && buffer[i] != '\t') {
return this->ExtractValueFromCpuInfoFile(buffer, word, pos2);
- }
}
- return buffer.substr(pos+2,pos2-pos-2);
}
+ return buffer.substr(pos + 2, pos2 - pos - 2);
}
- this->CurrentPositionInFile = buffer.npos;
+ }
+ this->CurrentPositionInFile = std::string::npos;
return "";
}
@@ -3106,94 +3370,95 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
{
this->NumberOfLogicalCPU = 0;
this->NumberOfPhysicalCPU = 0;
- kwsys_stl::string buffer;
+ std::string buffer;
- FILE *fd = fopen("/proc/cpuinfo", "r" );
- if ( !fd )
- {
- kwsys_ios::cout << "Problem opening /proc/cpuinfo" << kwsys_ios::endl;
+ FILE* fd = fopen("/proc/cpuinfo", "r");
+ if (!fd) {
+ std::cout << "Problem opening /proc/cpuinfo" << std::endl;
return false;
- }
+ }
size_t fileSize = 0;
- while(!feof(fd))
- {
+ while (!feof(fd)) {
buffer += static_cast<char>(fgetc(fd));
fileSize++;
- }
- fclose( fd );
- buffer.resize(fileSize-2);
+ }
+ fclose(fd);
+ buffer.resize(fileSize - 2);
// Number of logical CPUs (combination of multiple processors, multi-core
- // and hyperthreading)
+ // and SMT)
size_t pos = buffer.find("processor\t");
- while(pos != buffer.npos)
- {
+ while (pos != std::string::npos) {
this->NumberOfLogicalCPU++;
- pos = buffer.find("processor\t",pos+1);
- }
+ pos = buffer.find("processor\t", pos + 1);
+ }
#ifdef __linux
- // Find the largest physical id.
- int maxId = -1;
- kwsys_stl::string idc =
- this->ExtractValueFromCpuInfoFile(buffer,"physical id");
- while(this->CurrentPositionInFile != buffer.npos)
- {
- int id = atoi(idc.c_str());
- if(id > maxId)
- {
- maxId=id;
- }
- idc = this->ExtractValueFromCpuInfoFile(buffer,"physical id",
- this->CurrentPositionInFile+1);
- }
+ // Count sockets.
+ std::set<int> PhysicalIDs;
+ std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id");
+ while (this->CurrentPositionInFile != std::string::npos) {
+ int id = atoi(idc.c_str());
+ PhysicalIDs.insert(id);
+ idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id",
+ this->CurrentPositionInFile + 1);
+ }
+ uint64_t NumberOfSockets = PhysicalIDs.size();
+ NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1);
// Physical ids returned by Linux don't distinguish cores.
// We want to record the total number of cores in this->NumberOfPhysicalCPU
// (checking only the first proc)
- kwsys_stl::string cores =
- this->ExtractValueFromCpuInfoFile(buffer,"cpu cores");
- int numberOfCoresPerCPU=atoi(cores.c_str());
- this->NumberOfPhysicalCPU=static_cast<unsigned int>(
- numberOfCoresPerCPU*(maxId+1));
+ std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
+ unsigned int NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str());
+ NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u);
+ this->NumberOfPhysicalCPU =
+ NumberOfCoresPerSocket * (unsigned int)NumberOfSockets;
#else // __CYGWIN__
// does not have "physical id" entries, neither "cpu cores"
// this has to be fixed for hyper-threading.
- kwsys_stl::string cpucount =
- this->ExtractValueFromCpuInfoFile(buffer,"cpu count");
- this->NumberOfPhysicalCPU=
- this->NumberOfLogicalCPU = atoi(cpucount.c_str());
+ std::string cpucount =
+ this->ExtractValueFromCpuInfoFile(buffer, "cpu count");
+ this->NumberOfPhysicalCPU = this->NumberOfLogicalCPU =
+ atoi(cpucount.c_str());
#endif
// gotta have one, and if this is 0 then we get a / by 0n
// better to have a bad answer than a crash
- if(this->NumberOfPhysicalCPU <= 0)
- {
+ if (this->NumberOfPhysicalCPU <= 0) {
this->NumberOfPhysicalCPU = 1;
- }
- // LogicalProcessorsPerPhysical>1 => hyperthreading.
- this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical=
- this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU;
+ }
+ // LogicalProcessorsPerPhysical>1 => SMT.
+ this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
+ this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
// CPU speed (checking only the first processor)
- kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz");
- this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
+ std::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "cpu MHz");
+ if (!CPUSpeed.empty()) {
+ this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
+ }
+#ifdef __linux
+ else {
+ // Linux Sparc: CPU speed is in Hz and encoded in hexadecimal
+ CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "Cpu0ClkTck");
+ this->CPUSpeedInMHz =
+ static_cast<float>(strtoull(CPUSpeed.c_str(), 0, 16)) / 1000000.0f;
+ }
+#endif
// Chip family
- kwsys_stl::string familyStr =
- this->ExtractValueFromCpuInfoFile(buffer,"cpu family");
- if(familyStr.empty())
- {
- familyStr = this->ExtractValueFromCpuInfoFile(buffer,"CPU architecture");
- }
+ std::string familyStr =
+ this->ExtractValueFromCpuInfoFile(buffer, "cpu family");
+ if (familyStr.empty()) {
+ familyStr = this->ExtractValueFromCpuInfoFile(buffer, "CPU architecture");
+ }
this->ChipID.Family = atoi(familyStr.c_str());
// Chip Vendor
- this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id");
+ this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer, "vendor_id");
this->FindManufacturer(familyStr);
// second try for setting family
- if (this->ChipID.Family == 0 && this->ChipManufacturer == HP)
- {
+ if (this->ChipID.Family == 0 && this->ChipManufacturer == HP) {
if (familyStr == "PA-RISC 1.1a")
this->ChipID.Family = 0x11a;
else if (familyStr == "PA-RISC 2.0")
@@ -3201,104 +3466,90 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
// If you really get CMake to work on a machine not belonging to
// any of those families I owe you a dinner if you get it to
// contribute nightly builds regularly.
- }
+ }
// Chip Model
- this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str());
- if(!this->RetrieveClassicalCPUIdentity())
- {
+ this->ChipID.Model =
+ atoi(this->ExtractValueFromCpuInfoFile(buffer, "model").c_str());
+ if (!this->RetrieveClassicalCPUIdentity()) {
// Some platforms (e.g. PA-RISC) tell us their CPU name here.
// Note: x86 does not.
- kwsys_stl::string cpuname = this->ExtractValueFromCpuInfoFile(buffer,"cpu");
- if(!cpuname.empty())
- {
+ std::string cpuname = this->ExtractValueFromCpuInfoFile(buffer, "cpu");
+ if (!cpuname.empty()) {
this->ChipID.ProcessorName = cpuname;
- }
}
+ }
// Chip revision
- kwsys_stl::string cpurev = this->ExtractValueFromCpuInfoFile(buffer,"stepping");
- if(cpurev.empty())
- {
- cpurev = this->ExtractValueFromCpuInfoFile(buffer,"CPU revision");
- }
+ std::string cpurev = this->ExtractValueFromCpuInfoFile(buffer, "stepping");
+ if (cpurev.empty()) {
+ cpurev = this->ExtractValueFromCpuInfoFile(buffer, "CPU revision");
+ }
this->ChipID.Revision = atoi(cpurev.c_str());
// Chip Model Name
- this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str();
+ this->ChipID.ModelName =
+ this->ExtractValueFromCpuInfoFile(buffer, "model name").c_str();
// L1 Cache size
// Different architectures may show different names for the caches.
// Sum up everything we find.
- kwsys_stl::vector<const char*> cachename;
+ std::vector<const char*> cachename;
cachename.clear();
cachename.push_back("cache size"); // e.g. x86
- cachename.push_back("I-cache"); // e.g. PA-RISC
- cachename.push_back("D-cache"); // e.g. PA-RISC
+ cachename.push_back("I-cache"); // e.g. PA-RISC
+ cachename.push_back("D-cache"); // e.g. PA-RISC
this->Features.L1CacheSize = 0;
- for (size_t index = 0; index < cachename.size(); index ++)
- {
- kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]);
- if (!cacheSize.empty())
- {
+ for (size_t index = 0; index < cachename.size(); index++) {
+ std::string cacheSize =
+ this->ExtractValueFromCpuInfoFile(buffer, cachename[index]);
+ if (!cacheSize.empty()) {
pos = cacheSize.find(" KB");
- if(pos!=cacheSize.npos)
- {
- cacheSize = cacheSize.substr(0,pos);
- }
- this->Features.L1CacheSize += atoi(cacheSize.c_str());
+ if (pos != std::string::npos) {
+ cacheSize = cacheSize.substr(0, pos);
}
+ this->Features.L1CacheSize += atoi(cacheSize.c_str());
}
+ }
// processor feature flags (probably x86 specific)
- kwsys_stl::string cpuflags = this->ExtractValueFromCpuInfoFile(buffer,"flags");
- if(!cpurev.empty())
- {
+ std::string cpuflags = this->ExtractValueFromCpuInfoFile(buffer, "flags");
+ if (!cpurev.empty()) {
// now we can match every flags as space + flag + space
cpuflags = " " + cpuflags + " ";
- if ((cpuflags.find(" fpu ")!=kwsys_stl::string::npos))
- {
+ if ((cpuflags.find(" fpu ") != std::string::npos)) {
this->Features.HasFPU = true;
- }
- if ((cpuflags.find(" tsc ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" tsc ") != std::string::npos)) {
this->Features.HasTSC = true;
- }
- if ((cpuflags.find(" mmx ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" mmx ") != std::string::npos)) {
this->Features.HasMMX = true;
- }
- if ((cpuflags.find(" sse ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" sse ") != std::string::npos)) {
this->Features.HasSSE = true;
- }
- if ((cpuflags.find(" sse2 ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" sse2 ") != std::string::npos)) {
this->Features.HasSSE2 = true;
- }
- if ((cpuflags.find(" apic ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" apic ") != std::string::npos)) {
this->Features.HasAPIC = true;
- }
- if ((cpuflags.find(" cmov ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" cmov ") != std::string::npos)) {
this->Features.HasCMOV = true;
- }
- if ((cpuflags.find(" mtrr ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" mtrr ") != std::string::npos)) {
this->Features.HasMTRR = true;
- }
- if ((cpuflags.find(" acpi ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" acpi ") != std::string::npos)) {
this->Features.HasACPI = true;
- }
- if ((cpuflags.find(" 3dnow ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" 3dnow ") != std::string::npos)) {
this->Features.ExtendedFeatures.Has3DNow = true;
- }
}
+ }
return true;
}
@@ -3307,15 +3558,14 @@ 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
long c = sysconf(_SC_NPROCESSORS_ONLN);
- if (c <= 0)
- {
+ if (c <= 0) {
return false;
- }
+ }
this->NumberOfPhysicalCPU = static_cast<unsigned int>(c);
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
@@ -3338,34 +3588,32 @@ 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
+ return stat.dwTotalPhys / 1024;
+#else
MEMORYSTATUSEX statex;
- statex.dwLength=sizeof(statex);
+ statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
- return statex.ullTotalPhys/1024;
-# endif
+ return statex.ullTotalPhys / 1024;
+#endif
#elif defined(__linux)
- SystemInformation::LongLong memTotal=0;
- int ierr=GetFieldFromFile("/proc/meminfo","MemTotal:",memTotal);
- if (ierr)
- {
+ SystemInformation::LongLong memTotal = 0;
+ int ierr = GetFieldFromFile("/proc/meminfo", "MemTotal:", memTotal);
+ if (ierr) {
return -1;
- }
+ }
return memTotal;
#elif defined(__APPLE__)
uint64_t mem;
size_t len = sizeof(mem);
- int ierr=sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
- if (ierr)
- {
+ int ierr = sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
+ if (ierr) {
return -1;
- }
- return mem/1024;
+ }
+ return mem / 1024;
#else
return 0;
#endif
@@ -3376,9 +3624,10 @@ Get total system RAM in units of KiB. This may differ from the
host total if a host-wide resource limit is applied.
*/
SystemInformation::LongLong
-SystemInformationImplementation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
+SystemInformationImplementation::GetHostMemoryAvailable(
+ const char* hostLimitEnvVarName)
{
- SystemInformation::LongLong memTotal=this->GetHostMemoryTotal();
+ SystemInformation::LongLong memTotal = this->GetHostMemoryTotal();
// the following mechanism is provided for systems that
// apply resource limits across groups of processes.
@@ -3386,18 +3635,16 @@ SystemInformationImplementation::GetHostMemoryAvailable(const char *hostLimitEnv
// where the host has a large amount of ram but a given user's
// access to it is severly restricted. The system will
// apply a limit across a set of processes. Units are in KiB.
- if (hostLimitEnvVarName)
- {
- const char *hostLimitEnvVarValue=getenv(hostLimitEnvVarName);
- if (hostLimitEnvVarValue)
- {
- SystemInformation::LongLong hostLimit=atoLongLong(hostLimitEnvVarValue);
- if (hostLimit>0)
- {
- memTotal=min(hostLimit,memTotal);
- }
+ if (hostLimitEnvVarName) {
+ const char* hostLimitEnvVarValue = getenv(hostLimitEnvVarName);
+ if (hostLimitEnvVarValue) {
+ SystemInformation::LongLong hostLimit =
+ atoLongLong(hostLimitEnvVarValue);
+ if (hostLimit > 0) {
+ memTotal = min(hostLimit, memTotal);
}
}
+ }
return memTotal;
}
@@ -3408,55 +3655,52 @@ host total if a per-process resource limit is applied.
*/
SystemInformation::LongLong
SystemInformationImplementation::GetProcMemoryAvailable(
- const char *hostLimitEnvVarName,
- const char *procLimitEnvVarName)
+ const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
{
- SystemInformation::LongLong memAvail
- = this->GetHostMemoryAvailable(hostLimitEnvVarName);
+ SystemInformation::LongLong memAvail =
+ this->GetHostMemoryAvailable(hostLimitEnvVarName);
// the following mechanism is provide for systems where rlimits
// are not employed. Units are in KiB.
- if (procLimitEnvVarName)
- {
- const char *procLimitEnvVarValue=getenv(procLimitEnvVarName);
- if (procLimitEnvVarValue)
- {
- SystemInformation::LongLong procLimit=atoLongLong(procLimitEnvVarValue);
- if (procLimit>0)
- {
- memAvail=min(procLimit,memAvail);
- }
+ if (procLimitEnvVarName) {
+ const char* procLimitEnvVarValue = getenv(procLimitEnvVarName);
+ if (procLimitEnvVarValue) {
+ SystemInformation::LongLong procLimit =
+ atoLongLong(procLimitEnvVarValue);
+ if (procLimit > 0) {
+ memAvail = min(procLimit, memAvail);
}
}
+ }
#if defined(__linux)
int ierr;
ResourceLimitType rlim;
- ierr=GetResourceLimit(RLIMIT_DATA,&rlim);
- if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
- {
- memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
- }
+ ierr = GetResourceLimit(RLIMIT_DATA, &rlim);
+ if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
+ memAvail =
+ min((SystemInformation::LongLong)rlim.rlim_cur / 1024, memAvail);
+ }
- ierr=GetResourceLimit(RLIMIT_AS,&rlim);
- if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
- {
- memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
- }
+ ierr = GetResourceLimit(RLIMIT_AS, &rlim);
+ if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
+ memAvail =
+ min((SystemInformation::LongLong)rlim.rlim_cur / 1024, memAvail);
+ }
#elif defined(__APPLE__)
struct rlimit rlim;
int ierr;
- ierr=getrlimit(RLIMIT_DATA,&rlim);
- if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
- {
- memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
- }
+ ierr = getrlimit(RLIMIT_DATA, &rlim);
+ if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
+ memAvail =
+ min((SystemInformation::LongLong)rlim.rlim_cur / 1024, memAvail);
+ }
- ierr=getrlimit(RLIMIT_RSS,&rlim);
- if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
- {
- memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
- }
+ ierr = getrlimit(RLIMIT_RSS, &rlim);
+ if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
+ memAvail =
+ min((SystemInformation::LongLong)rlim.rlim_cur / 1024, memAvail);
+ }
#endif
return memAvail;
@@ -3469,45 +3713,54 @@ 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
+ return (stat.dwTotalPhys - stat.dwAvailPhys) / 1024;
+#else
MEMORYSTATUSEX statex;
- statex.dwLength=sizeof(statex);
+ statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
- return (statex.ullTotalPhys - statex.ullAvailPhys)/1024;
-# endif
+ return (statex.ullTotalPhys - statex.ullAvailPhys) / 1024;
+#endif
#elif defined(__linux)
- const char *names[3]={"MemTotal:","MemFree:",NULL};
- SystemInformation::LongLong values[2]={SystemInformation::LongLong(0)};
- int ierr=GetFieldsFromFile("/proc/meminfo",names,values);
- if (ierr)
- {
- return ierr;
- }
- SystemInformation::LongLong &memTotal=values[0];
- SystemInformation::LongLong &memFree=values[1];
- return memTotal - memFree;
+ // First try to use MemAvailable, but it only works on newer kernels
+ const char* names2[3] = { "MemTotal:", "MemAvailable:", NULL };
+ 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 };
+ SystemInformation::LongLong values4[4] = { SystemInformation::LongLong(
+ 0) };
+ ierr = GetFieldsFromFile("/proc/meminfo", names4, values4);
+ if (ierr) {
+ return ierr;
+ }
+ SystemInformation::LongLong& memTotal = values4[0];
+ SystemInformation::LongLong& memFree = values4[1];
+ SystemInformation::LongLong& memBuffers = values4[2];
+ SystemInformation::LongLong& memCached = values4[3];
+ return memTotal - memFree - memBuffers - memCached;
+ }
+ SystemInformation::LongLong& memTotal = values2[0];
+ SystemInformation::LongLong& memAvail = values2[1];
+ return memTotal - memAvail;
#elif defined(__APPLE__)
- SystemInformation::LongLong psz=getpagesize();
- if (psz<1)
- {
+ SystemInformation::LongLong psz = getpagesize();
+ if (psz < 1) {
return -1;
- }
- const char *names[4]={"Pages active:","Pages inactive:","Pages wired down:",NULL};
- SystemInformation::LongLong values[3]={SystemInformation::LongLong(0)};
- int ierr=GetFieldsFromCommand("vm_stat", names, values);
- if (ierr)
- {
+ }
+ const char* names[3] = { "Pages wired down:", "Pages active:", NULL };
+ SystemInformation::LongLong values[2] = { SystemInformation::LongLong(0) };
+ int ierr = GetFieldsFromCommand("vm_stat", names, values);
+ if (ierr) {
return -1;
- }
- SystemInformation::LongLong &vmActive=values[0];
- SystemInformation::LongLong &vmInactive=values[1];
- SystemInformation::LongLong &vmWired=values[2];
- return ((vmActive+vmInactive+vmWired)*psz)/1024;
+ }
+ SystemInformation::LongLong& vmWired = values[0];
+ SystemInformation::LongLong& vmActive = values[1];
+ return ((vmActive + vmWired) * psz) / 1024;
#else
return 0;
#endif
@@ -3521,61 +3774,52 @@ SystemInformation::LongLong
SystemInformationImplementation::GetProcMemoryUsed()
{
#if defined(_WIN32) && defined(KWSYS_SYS_HAS_PSAPI)
- long pid=GetCurrentProcessId();
+ long pid = GetCurrentProcessId();
HANDLE hProc;
- hProc=OpenProcess(
- PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
- false,
- pid);
- if (hProc==0)
- {
+ hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
+ if (hProc == 0) {
return -1;
- }
+ }
PROCESS_MEMORY_COUNTERS pmc;
- int ok=GetProcessMemoryInfo(hProc,&pmc,sizeof(pmc));
+ int ok = GetProcessMemoryInfo(hProc, &pmc, sizeof(pmc));
CloseHandle(hProc);
- if (!ok)
- {
+ if (!ok) {
return -2;
- }
- return pmc.WorkingSetSize/1024;
+ }
+ return pmc.WorkingSetSize / 1024;
#elif defined(__linux)
- SystemInformation::LongLong memUsed=0;
- int ierr=GetFieldFromFile("/proc/self/status","VmRSS:",memUsed);
- if (ierr)
- {
+ SystemInformation::LongLong memUsed = 0;
+ int ierr = GetFieldFromFile("/proc/self/status", "VmRSS:", memUsed);
+ if (ierr) {
return -1;
- }
+ }
return memUsed;
#elif defined(__APPLE__)
- SystemInformation::LongLong memUsed=0;
- pid_t pid=getpid();
- kwsys_ios::ostringstream oss;
+ SystemInformation::LongLong memUsed = 0;
+ pid_t pid = getpid();
+ std::ostringstream oss;
oss << "ps -o rss= -p " << pid;
- FILE *file=popen(oss.str().c_str(),"r");
- if (file==0)
- {
+ FILE* file = popen(oss.str().c_str(), "r");
+ if (file == 0) {
return -1;
- }
+ }
oss.str("");
- while (!feof(file) && !ferror(file))
- {
- char buf[256]={'\0'};
- errno=0;
- size_t nRead=fread(buf,1,256,file);
- if (ferror(file) && (errno==EINTR))
- {
+ while (!feof(file) && !ferror(file)) {
+ char buf[256] = { '\0' };
+ errno = 0;
+ size_t nRead = fread(buf, 1, 256, file);
+ if (ferror(file) && (errno == EINTR)) {
clearerr(file);
- }
- if (nRead) oss << buf;
}
- int ierr=ferror(file);
+ if (nRead)
+ oss << buf;
+ }
+ int ierr = ferror(file);
pclose(file);
- if (ierr)
- {
+ if (ierr) {
return -2;
- }
- kwsys_ios::istringstream iss(oss.str());
+ }
+ std::istringstream iss(oss.str());
iss >> memUsed;
return memUsed;
#else
@@ -3583,11 +3827,39 @@ SystemInformationImplementation::GetProcMemoryUsed()
#endif
}
+double SystemInformationImplementation::GetLoadAverage()
+{
+#if defined(KWSYS_CXX_HAS_GETLOADAVG)
+ double loadavg[3] = { 0.0, 0.0, 0.0 };
+ if (getloadavg(loadavg, 3) > 0) {
+ return loadavg[0];
+ }
+ return -0.0;
+#elif defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes)
+ // Old windows.h headers do not provide GetSystemTimes.
+ typedef BOOL(WINAPI * GetSystemTimesType)(LPFILETIME, LPFILETIME,
+ LPFILETIME);
+ static GetSystemTimesType pGetSystemTimes =
+ (GetSystemTimesType)GetProcAddress(GetModuleHandleW(L"kernel32"),
+ "GetSystemTimes");
+ FILETIME idleTime, kernelTime, userTime;
+ if (pGetSystemTimes && pGetSystemTimes(&idleTime, &kernelTime, &userTime)) {
+ unsigned __int64 const idleTicks = fileTimeToUInt64(idleTime);
+ unsigned __int64 const totalTicks =
+ fileTimeToUInt64(kernelTime) + fileTimeToUInt64(userTime);
+ return calculateCPULoad(idleTicks, totalTicks) * GetNumberOfPhysicalCPU();
+ }
+ return -0.0;
+#else
+ // Not implemented on this platform.
+ return -0.0;
+#endif
+}
+
/**
Get the process id of the running process.
*/
-SystemInformation::LongLong
-SystemInformationImplementation::GetProcessId()
+SystemInformation::LongLong SystemInformationImplementation::GetProcessId()
{
#if defined(_WIN32)
return GetCurrentProcessId();
@@ -3602,40 +3874,39 @@ SystemInformationImplementation::GetProcessId()
return current program stack in a string
demangle cxx symbols if possible.
*/
-kwsys_stl::string SystemInformationImplementation::GetProgramStack(
- int firstFrame,
- int wholePath)
+std::string SystemInformationImplementation::GetProgramStack(int firstFrame,
+ int wholePath)
{
- kwsys_stl::string programStack = ""
+ std::string programStack = ""
#if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
- "WARNING: The stack could not be examined "
- "because backtrace is not supported.\n"
+ "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"
+ "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
+#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
;
- kwsys_ios::ostringstream oss;
+ std::ostringstream oss;
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
- void *stackSymbols[256];
- int nFrames=backtrace(stackSymbols,256);
- for (int i=firstFrame; i<nFrames; ++i)
- {
+ void* stackSymbols[256];
+ int nFrames = backtrace(stackSymbols, 256);
+ for (int i = firstFrame; i < nFrames; ++i) {
SymbolProperties symProps;
symProps.SetReportPath(wholePath);
symProps.Initialize(stackSymbols[i]);
- oss << symProps << kwsys_ios::endl;
- }
+ oss << symProps << std::endl;
+ }
#else
(void)firstFrame;
(void)wholePath;
@@ -3645,14 +3916,13 @@ kwsys_stl::string SystemInformationImplementation::GetProgramStack(
return programStack;
}
-
/**
when set print stack trace in response to common signals.
*/
void SystemInformationImplementation::SetStackTraceOnError(int enable)
{
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
- static int saOrigValid=0;
+ static int saOrigValid = 0;
static struct sigaction saABRTOrig;
static struct sigaction saSEGVOrig;
static struct sigaction saTERMOrig;
@@ -3661,50 +3931,48 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
static struct sigaction saBUSOrig;
static struct sigaction saFPEOrig;
-
- if (enable && !saOrigValid)
- {
+ 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, 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);
// enable read, disable write
- saOrigValid=1;
+ saOrigValid = 1;
// install ours
struct sigaction sa;
- sa.sa_sigaction=(SigAction)StacktraceSignalHandler;
- sa.sa_flags=SA_SIGINFO|SA_RESTART|SA_RESETHAND;
+ sa.sa_sigaction = (SigAction)StacktraceSignalHandler;
+ sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
+#ifdef SA_RESTART
+ sa.sa_flags |= SA_RESTART;
+#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);
- }
- else
- if (!enable && saOrigValid)
- {
+ 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);
+ } 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, 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);
// enable write, disable read
- saOrigValid=0;
- }
+ saOrigValid = 0;
+ }
#else
// avoid warning C4100
(void)enable;
@@ -3714,30 +3982,29 @@ 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))
- {
+ if (0 == GlobalMemoryStatusEx(&ms)) {
return 0;
}
-# define MEM_VAL(value) ull##value
-# endif
- tv = ms.MEM_VAL(TotalVirtual);
+#define MEM_VAL(value) ull##value
+#endif
+ tv = ms.MEM_VAL(TotalPageFile);
tp = ms.MEM_VAL(TotalPhys);
- av = ms.MEM_VAL(AvailVirtual);
+ av = ms.MEM_VAL(AvailPageFile);
ap = ms.MEM_VAL(AvailPhys);
- this->TotalVirtualMemory = tv>>10>>10;
- this->TotalPhysicalMemory = tp>>10>>10;
- this->AvailableVirtualMemory = av>>10>>10;
- this->AvailablePhysicalMemory = ap>>10>>10;
+ this->TotalVirtualMemory = tv >> 10 >> 10;
+ this->TotalPhysicalMemory = tp >> 10 >> 10;
+ this->AvailableVirtualMemory = av >> 10 >> 10;
+ this->AvailablePhysicalMemory = ap >> 10 >> 10;
return true;
#else
return false;
@@ -3747,10 +4014,10 @@ bool SystemInformationImplementation::QueryWindowsMemory()
bool SystemInformationImplementation::QueryLinuxMemory()
{
#if defined(__linux)
- unsigned long tv=0;
- unsigned long tp=0;
- unsigned long av=0;
- unsigned long ap=0;
+ unsigned long tv = 0;
+ unsigned long tp = 0;
+ unsigned long av = 0;
+ unsigned long ap = 0;
char buffer[1024]; // for reading lines
@@ -3760,108 +4027,99 @@ bool SystemInformationImplementation::QueryLinuxMemory()
// Find the Linux kernel version first
struct utsname unameInfo;
int errorFlag = uname(&unameInfo);
- if( errorFlag!=0 )
- {
- kwsys_ios::cout << "Problem calling uname(): " << strerror(errno) << kwsys_ios::endl;
+ if (errorFlag != 0) {
+ std::cout << "Problem calling uname(): " << strerror(errno) << std::endl;
return false;
- }
+ }
- if( unameInfo.release!=0 && strlen(unameInfo.release)>=3 )
- {
+ if (strlen(unameInfo.release) >= 3) {
// release looks like "2.6.3-15mdk-i686-up-4GB"
- char majorChar=unameInfo.release[0];
- char minorChar=unameInfo.release[2];
+ char majorChar = unameInfo.release[0];
+ char minorChar = unameInfo.release[2];
- if( isdigit(majorChar) )
- {
- linuxMajor=majorChar-'0';
- }
+ if (isdigit(majorChar)) {
+ linuxMajor = majorChar - '0';
+ }
- if( isdigit(minorChar) )
- {
- linuxMinor=minorChar-'0';
- }
+ if (isdigit(minorChar)) {
+ linuxMinor = minorChar - '0';
}
+ }
- FILE *fd = fopen("/proc/meminfo", "r" );
- if ( !fd )
- {
- kwsys_ios::cout << "Problem opening /proc/meminfo" << kwsys_ios::endl;
+ FILE* fd = fopen("/proc/meminfo", "r");
+ if (!fd) {
+ std::cout << "Problem opening /proc/meminfo" << std::endl;
return false;
- }
+ }
- if( linuxMajor>=3 || ( (linuxMajor>=2) && (linuxMinor>=6) ) )
- {
+ 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
// that introduced the new format...
- enum { mMemTotal, mMemFree, mBuffers, mCached, mSwapTotal, mSwapFree };
- const char* format[6] =
- { "MemTotal:%lu kB", "MemFree:%lu kB", "Buffers:%lu kB",
- "Cached:%lu kB", "SwapTotal:%lu kB", "SwapFree:%lu kB" };
+ enum
+ {
+ mMemTotal,
+ mMemFree,
+ mBuffers,
+ mCached,
+ mSwapTotal,
+ mSwapFree
+ };
+ const char* format[6] = { "MemTotal:%lu kB", "MemFree:%lu kB",
+ "Buffers:%lu kB", "Cached:%lu kB",
+ "SwapTotal:%lu kB", "SwapFree:%lu kB" };
bool have[6] = { false, false, false, false, false, false };
unsigned long value[6];
int count = 0;
- while(fgets(buffer, static_cast<int>(sizeof(buffer)), fd))
- {
- for(int i=0; i < 6; ++i)
- {
- if(!have[i] && sscanf(buffer, format[i], &value[i]) == 1)
- {
+ while (fgets(buffer, static_cast<int>(sizeof(buffer)), fd)) {
+ for (int i = 0; i < 6; ++i) {
+ if (!have[i] && sscanf(buffer, format[i], &value[i]) == 1) {
have[i] = true;
++count;
- }
}
}
- if(count == 6)
- {
+ }
+ if (count == 6) {
this->TotalPhysicalMemory = value[mMemTotal] / 1024;
this->AvailablePhysicalMemory =
(value[mMemFree] + value[mBuffers] + value[mCached]) / 1024;
this->TotalVirtualMemory = value[mSwapTotal] / 1024;
this->AvailableVirtualMemory = value[mSwapFree] / 1024;
- }
- else
- {
- kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl;
+ } else {
+ std::cout << "Problem parsing /proc/meminfo" << std::endl;
fclose(fd);
return false;
- }
}
- else
- {
+ } else {
// /proc/meminfo format for kernel older than 2.6.x
unsigned long temp;
unsigned long cachedMem;
unsigned long buffersMem;
- char *r=fgets(buffer, sizeof(buffer), fd); // Skip "total: used:..."
- int status=0;
- if(r==buffer)
- {
- status+=fscanf(fd, "Mem: %lu %lu %lu %lu %lu %lu\n",
- &tp, &temp, &ap, &temp, &buffersMem, &cachedMem);
- }
- if(status==6)
- {
- status+=fscanf(fd, "Swap: %lu %lu %lu\n", &tv, &temp, &av);
- }
- if(status==9)
- {
- this->TotalVirtualMemory = tv>>10>>10;
- this->TotalPhysicalMemory = tp>>10>>10;
- this->AvailableVirtualMemory = av>>10>>10;
- this->AvailablePhysicalMemory = (ap+buffersMem+cachedMem)>>10>>10;
- }
- else
- {
- kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl;
+ // Skip "total: used:..."
+ char* r = fgets(buffer, static_cast<int>(sizeof(buffer)), fd);
+ int status = 0;
+ if (r == buffer) {
+ status += fscanf(fd, "Mem: %lu %lu %lu %lu %lu %lu\n", &tp, &temp, &ap,
+ &temp, &buffersMem, &cachedMem);
+ }
+ if (status == 6) {
+ status += fscanf(fd, "Swap: %lu %lu %lu\n", &tv, &temp, &av);
+ }
+ if (status == 9) {
+ this->TotalVirtualMemory = tv >> 10 >> 10;
+ this->TotalPhysicalMemory = tp >> 10 >> 10;
+ this->AvailableVirtualMemory = av >> 10 >> 10;
+ this->AvailablePhysicalMemory =
+ (ap + buffersMem + cachedMem) >> 10 >> 10;
+ } else {
+ std::cout << "Problem parsing /proc/meminfo" << std::endl;
fclose(fd);
return false;
- }
}
- fclose( fd );
+ }
+ fclose(fd);
return true;
#else
@@ -3876,10 +4134,9 @@ bool SystemInformationImplementation::QueryCygwinMemory()
// see http://cygwin.com/ml/cygwin/2006-06/msg00350.html
// Therefore just use 4096 as the page size of Windows.
long m = sysconf(_SC_PHYS_PAGES);
- if (m < 0)
- {
+ if (m < 0) {
return false;
- }
+ }
this->TotalPhysicalMemory = m >> 8;
return true;
#else
@@ -3889,12 +4146,11 @@ bool SystemInformationImplementation::QueryCygwinMemory()
bool SystemInformationImplementation::QueryAIXMemory()
{
-#if defined(_AIX)
+#if defined(_AIX) && defined(_SC_AIX_REALMEM)
long c = sysconf(_SC_AIX_REALMEM);
- if (c <= 0)
- {
+ if (c <= 0) {
return false;
- }
+ }
this->TotalPhysicalMemory = c / 1024;
@@ -3913,10 +4169,9 @@ bool SystemInformationImplementation::QueryMemoryBySysconf()
long p = sysconf(_SC_PHYS_PAGES);
long m = sysconf(_SC_PAGESIZE);
- if (p < 0 || m < 0)
- {
+ if (p < 0 || m < 0) {
return false;
- }
+ }
// assume pagesize is a power of 2 and smaller 1 MiB
size_t pagediv = (1024 * 1024 / m);
@@ -3926,10 +4181,9 @@ bool SystemInformationImplementation::QueryMemoryBySysconf()
#if defined(_SC_AVPHYS_PAGES)
p = sysconf(_SC_AVPHYS_PAGES);
- if (p < 0)
- {
+ if (p < 0) {
return false;
- }
+ }
this->AvailablePhysicalMemory = p;
this->AvailablePhysicalMemory /= pagediv;
@@ -3972,8 +4226,8 @@ size_t SystemInformationImplementation::GetAvailablePhysicalMemory()
/** Get Cycle differences */
SystemInformation::LongLong
-SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction,
- unsigned int uiParameter)
+SystemInformationImplementation::GetCyclesDifference(DELAY_FUNC DelayFunction,
+ unsigned int uiParameter)
{
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
unsigned __int64 stamp1, stamp2;
@@ -4011,13 +4265,11 @@ SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction,
mov edx1, edi ; edx2 = edi
mov eax1, esi ; eax2 = esi
}
- }
- __except(1)
- {
+ } __except (1) {
return -1;
- }
+ }
- return ((((__int64) edx2 << 32) + eax2) - (((__int64) edx1 << 32) + eax1));
+ return ((((__int64)edx2 << 32) + eax2) - (((__int64)edx1 << 32) + eax1));
#else
(void)DelayFunction;
@@ -4026,7 +4278,6 @@ SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction,
#endif
}
-
/** Compute the delay overhead */
void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
{
@@ -4035,238 +4286,116 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
__int64 x;
// Get the frequency of the high performance counter.
- if(!QueryPerformanceFrequency (&Frequency))
- {
+ if (!QueryPerformanceFrequency(&Frequency)) {
return;
- }
+ }
x = Frequency.QuadPart / 1000 * uiMS;
// Get the starting position of the counter.
- QueryPerformanceCounter (&StartCounter);
+ QueryPerformanceCounter(&StartCounter);
do {
// Get the ending position of the counter.
- QueryPerformanceCounter (&EndCounter);
+ QueryPerformanceCounter(&EndCounter);
} while (EndCounter.QuadPart - StartCounter.QuadPart == x);
#endif
(void)uiMS;
}
-/** Return the number of logical CPU per physical CPUs Works only for windows */
-unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void)
-{
-#ifdef __APPLE__
- size_t len = 4;
- int cores_per_package = 0;
- int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len, NULL, 0);
- if (err != 0)
- {
- return 1; // That name was not found, default to 1
- }
- return static_cast<unsigned char>(cores_per_package);
-#else
- int Regs[4] = { 0, 0, 0, 0 };
-#if USE_CPUID
- if (!this->IsHyperThreadingSupported())
- {
- return static_cast<unsigned char>(1); // HT not supported
- }
- call_cpuid(1, Regs);
-#endif
- return static_cast<unsigned char> ((Regs[1] & NUM_LOGICAL_BITS) >> 16);
-#endif
-}
-
-
/** Works only for windows */
-bool SystemInformationImplementation::IsHyperThreadingSupported()
+bool SystemInformationImplementation::IsSMTSupported()
{
- if (this->Features.ExtendedFeatures.SupportsHyperthreading)
- {
- return true;
- }
-
-#if USE_CPUID
- int Regs[4] = { 0, 0, 0, 0 },
- VendorId[4] = { 0, 0, 0, 0 };
- // Get vendor id string
- if (!call_cpuid(0, VendorId))
- {
- return false;
- }
- // eax contains family processor type
- // edx has info about the availability of hyper-Threading
- if (!call_cpuid(1, Regs))
- {
- return false;
- }
-
- if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID))
- {
- if (VendorId[1] == 0x756e6547) // 'uneG'
- {
- if (VendorId[3] == 0x49656e69) // 'Ieni'
- {
- if (VendorId[2] == 0x6c65746e) // 'letn'
- {
- // Genuine Intel with hyper-Threading technology
- this->Features.ExtendedFeatures.SupportsHyperthreading = ((Regs[3] & HT_BIT) != 0);
- return this->Features.ExtendedFeatures.SupportsHyperthreading;
- }
- }
- }
- }
-#endif
-
- return 0; // Not genuine Intel processor
+ return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1;
}
-
/** Return the APIC Id. Works only for windows. */
unsigned char SystemInformationImplementation::GetAPICId()
{
int Regs[4] = { 0, 0, 0, 0 };
#if USE_CPUID
- if (!this->IsHyperThreadingSupported())
- {
- return static_cast<unsigned char>(-1); // HT not supported
- } // Logical processor = 1
+ if (!this->IsSMTSupported()) {
+ return static_cast<unsigned char>(-1); // HT not supported
+ } // Logical processor = 1
call_cpuid(1, Regs);
#endif
return static_cast<unsigned char>((Regs[1] & INITIAL_APIC_ID_BITS) >> 24);
}
-
/** Count the number of CPUs. Works only on windows. */
-int SystemInformationImplementation::CPUCount()
+void SystemInformationImplementation::CPUCountWindows()
{
#if defined(_WIN32)
- unsigned char StatusFlag = 0;
- SYSTEM_INFO info;
-
this->NumberOfPhysicalCPU = 0;
this->NumberOfLogicalCPU = 0;
- info.dwNumberOfProcessors = 0;
- GetSystemInfo (&info);
- // Number of physical processors in a non-Intel system
- // or in a 32-bit Intel system with Hyper-Threading technology disabled
- this->NumberOfPhysicalCPU = (unsigned char) info.dwNumberOfProcessors;
-
- if (this->IsHyperThreadingSupported())
- {
- unsigned char HT_Enabled = 0;
- this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU();
- if (this->NumberOfLogicalCPU >= 1) // >1 Doesn't mean HT is enabled in the BIOS
- {
- HANDLE hCurrentProcessHandle;
-#ifndef _WIN64
-# define DWORD_PTR DWORD
-#endif
- DWORD_PTR dwProcessAffinity;
- DWORD_PTR dwSystemAffinity;
- DWORD dwAffinityMask;
-
- // Calculate the appropriate shifts and mask based on the
- // number of logical processors.
- unsigned int i = 1;
- unsigned char PHY_ID_MASK = 0xFF;
- //unsigned char PHY_ID_SHIFT = 0;
-
- while (i < this->NumberOfLogicalCPU)
- {
- i *= 2;
- PHY_ID_MASK <<= 1;
- // PHY_ID_SHIFT++;
- }
-
- hCurrentProcessHandle = GetCurrentProcess();
- GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity,
- &dwSystemAffinity);
-
- // Check if available process affinity mask is equal to the
- // available system affinity mask
- if (dwProcessAffinity != dwSystemAffinity)
- {
- StatusFlag = HT_CANNOT_DETECT;
- this->NumberOfPhysicalCPU = (unsigned char)-1;
- return StatusFlag;
- }
+ typedef BOOL(WINAPI * GetLogicalProcessorInformationType)(
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+ static GetLogicalProcessorInformationType pGetLogicalProcessorInformation =
+ (GetLogicalProcessorInformationType)GetProcAddress(
+ GetModuleHandleW(L"kernel32"), "GetLogicalProcessorInformation");
+
+ if (!pGetLogicalProcessorInformation) {
+ // Fallback to approximate implementation on ancient Windows versions.
+ SYSTEM_INFO info;
+ ZeroMemory(&info, sizeof(info));
+ GetSystemInfo(&info);
+ this->NumberOfPhysicalCPU =
+ static_cast<unsigned int>(info.dwNumberOfProcessors);
+ this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+ return;
+ }
- dwAffinityMask = 1;
- while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity)
- {
- // Check if this CPU is available
- if (dwAffinityMask & dwProcessAffinity)
- {
- if (SetProcessAffinityMask(hCurrentProcessHandle,
- dwAffinityMask))
- {
- unsigned char APIC_ID, LOG_ID;
- Sleep(0); // Give OS time to switch CPU
-
- APIC_ID = GetAPICId();
- LOG_ID = APIC_ID & ~PHY_ID_MASK;
-
- if (LOG_ID != 0)
- {
- HT_Enabled = 1;
- }
- }
- }
- dwAffinityMask = dwAffinityMask << 1;
- }
- // Reset the processor affinity
- SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity);
+ std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
+ {
+ DWORD Length = 0;
+ DWORD rc = pGetLogicalProcessorInformation(NULL, &Length);
+ assert(FALSE == rc);
+ (void)rc; // Silence unused variable warning in Borland C++ 5.81
+ assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+ ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
+ rc = pGetLogicalProcessorInformation(&ProcInfo[0], &Length);
+ assert(rc != FALSE);
+ (void)rc; // Silence unused variable warning in Borland C++ 5.81
+ }
- if (this->NumberOfLogicalCPU == 1) // Normal P4 : HT is disabled in hardware
- {
- StatusFlag = HT_DISABLED;
- }
- else
- {
- if (HT_Enabled)
- {
- // Total physical processors in a Hyper-Threading enabled system.
- this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU);
- StatusFlag = HT_ENABLED;
- }
- else
- {
- StatusFlag = HT_SUPPORTED_NOT_ENABLED;
- }
- }
- }
+ typedef std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>::iterator
+ pinfoIt_t;
+ for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) {
+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it;
+ if (PInfo.Relationship != RelationProcessorCore) {
+ continue;
}
- else
- {
- // Processors do not have Hyper-Threading technology
- StatusFlag = HT_NOT_CAPABLE;
- this->NumberOfLogicalCPU = 1;
+
+ std::bitset<std::numeric_limits<ULONG_PTR>::digits> ProcMask(
+ (unsigned long long)PInfo.ProcessorMask);
+ unsigned int count = (unsigned int)ProcMask.count();
+ if (count == 0) { // I think this should never happen, but just to be safe.
+ continue;
}
- return StatusFlag;
+ this->NumberOfPhysicalCPU++;
+ this->NumberOfLogicalCPU += (unsigned int)count;
+ this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count;
+ }
+ this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU);
+ this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU);
#else
- return 0;
#endif
}
-
/** Return the number of logical CPUs on the system */
unsigned int SystemInformationImplementation::GetNumberOfLogicalCPU()
{
return this->NumberOfLogicalCPU;
}
-
/** Return the number of physical CPUs on the system */
unsigned int SystemInformationImplementation::GetNumberOfPhysicalCPU()
{
return this->NumberOfPhysicalCPU;
}
-
/** For Mac use sysctlbyname calls to find system info */
bool SystemInformationImplementation::ParseSysCtl()
{
@@ -4276,20 +4405,20 @@ bool SystemInformationImplementation::ParseSysCtl()
uint64_t value = 0;
size_t len = sizeof(value);
sysctlbyname("hw.memsize", &value, &len, NULL, 0);
- this->TotalPhysicalMemory = static_cast< size_t >( value/1048576 );
+ this->TotalPhysicalMemory = static_cast<size_t>(value / 1048576);
// Parse values for Mac
this->AvailablePhysicalMemory = 0;
- vm_statistics_data_t vmstat;
+ vm_statistics_data_t vmstat;
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
- if ( host_statistics(mach_host_self(), HOST_VM_INFO,
- (host_info_t) &vmstat, &count) == KERN_SUCCESS )
- {
+ 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;
- this->AvailablePhysicalMemory = static_cast< size_t >( available_memory / 1048576 );
- }
+ this->AvailablePhysicalMemory =
+ static_cast<size_t>(available_memory / 1048576);
+ }
#ifdef VM_SWAPUSAGE
// Virtual memory.
@@ -4298,54 +4427,57 @@ bool SystemInformationImplementation::ParseSysCtl()
struct xsw_usage swap;
len = sizeof(swap);
err = sysctl(mib, miblen, &swap, &len, NULL, 0);
- if (err == 0)
- {
- this->AvailableVirtualMemory = static_cast< size_t >( swap.xsu_avail/1048576 );
- this->TotalVirtualMemory = static_cast< size_t >( swap.xsu_total/1048576 );
- }
+ if (err == 0) {
+ this->AvailableVirtualMemory =
+ static_cast<size_t>(swap.xsu_avail / 1048576);
+ this->TotalVirtualMemory = static_cast<size_t>(swap.xsu_total / 1048576);
+ }
#else
- this->AvailableVirtualMemory = 0;
- this->TotalVirtualMemory = 0;
+ this->AvailableVirtualMemory = 0;
+ this->TotalVirtualMemory = 0;
#endif
-// CPU Info
+ // CPU Info
len = sizeof(this->NumberOfPhysicalCPU);
sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
len = sizeof(this->NumberOfLogicalCPU);
sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
+
+ int cores_per_package = 0;
+ len = sizeof(cores_per_package);
+ err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len,
+ NULL, 0);
+ // That name was not found, default to 1
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
- this->LogicalCPUPerPhysicalCPU();
+ err != 0 ? 1 : static_cast<unsigned char>(cores_per_package);
len = sizeof(value);
sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0);
- this->CPUSpeedInMHz = static_cast< float >( value )/ 1000000;
-
+ this->CPUSpeedInMHz = static_cast<float>(value) / 1000000;
// Chip family
len = sizeof(this->ChipID.Family);
- //Seems only the intel chips will have this name so if this fails it is
- //probably a PPC machine
- err = sysctlbyname("machdep.cpu.family",
- &this->ChipID.Family, &len, NULL, 0);
+ // 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);
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);
- kwsys_stl::string machineBuf(retBuf);
- if (machineBuf.find_first_of("Power") != kwsys_stl::string::npos)
- {
+ 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);
len = sizeof(this->ChipID.Model);
err = sysctlbyname("hw.cpusubtype", &this->ChipID.Model, &len, NULL, 0);
this->FindManufacturer();
- }
}
- else // Should be an Intel Chip.
- {
+ } else // Should be an Intel Chip.
+ {
len = sizeof(this->ChipID.Family);
err =
sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len, NULL, 0);
@@ -4360,101 +4492,88 @@ bool SystemInformationImplementation::ParseSysCtl()
// Chip Model
len = sizeof(value);
err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0);
- this->ChipID.Model = static_cast< int >( value );
+ this->ChipID.Model = static_cast<int>(value);
// Chip Stepping
len = sizeof(value);
value = 0;
err = sysctlbyname("machdep.cpu.stepping", &value, &len, NULL, 0);
- if (!err)
- {
- this->ChipID.Revision = static_cast< int >( value );
- }
+ if (!err) {
+ this->ChipID.Revision = static_cast<int>(value);
+ }
// feature string
- char *buf = 0;
+ char* buf = 0;
size_t allocSize = 128;
err = 0;
len = 0;
- // sysctlbyname() will return with err==0 && len==0 if the buffer is too small
- while (err == 0 && len == 0)
- {
+ // sysctlbyname() will return with err==0 && len==0 if the buffer is too
+ // small
+ while (err == 0 && len == 0) {
delete[] buf;
allocSize *= 2;
buf = new char[allocSize];
- if (!buf)
- {
+ if (!buf) {
break;
- }
+ }
buf[0] = ' ';
len = allocSize - 2; // keep space for leading and trailing space
err = sysctlbyname("machdep.cpu.features", buf + 1, &len, NULL, 0);
- }
- if (!err && buf && len)
- {
+ }
+ if (!err && buf && len) {
// now we can match every flags as space + flag + space
buf[len + 1] = ' ';
- kwsys_stl::string cpuflags(buf, len + 2);
+ std::string cpuflags(buf, len + 2);
- if ((cpuflags.find(" FPU ")!=kwsys_stl::string::npos))
- {
+ if ((cpuflags.find(" FPU ") != std::string::npos)) {
this->Features.HasFPU = true;
- }
- if ((cpuflags.find(" TSC ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" TSC ") != std::string::npos)) {
this->Features.HasTSC = true;
- }
- if ((cpuflags.find(" MMX ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" MMX ") != std::string::npos)) {
this->Features.HasMMX = true;
- }
- if ((cpuflags.find(" SSE ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" SSE ") != std::string::npos)) {
this->Features.HasSSE = true;
- }
- if ((cpuflags.find(" SSE2 ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" SSE2 ") != std::string::npos)) {
this->Features.HasSSE2 = true;
- }
- if ((cpuflags.find(" APIC ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" APIC ") != std::string::npos)) {
this->Features.HasAPIC = true;
- }
- if ((cpuflags.find(" CMOV ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" CMOV ") != std::string::npos)) {
this->Features.HasCMOV = true;
- }
- if ((cpuflags.find(" MTRR ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" MTRR ") != std::string::npos)) {
this->Features.HasMTRR = true;
- }
- if ((cpuflags.find(" ACPI ")!=kwsys_stl::string::npos))
- {
+ }
+ if ((cpuflags.find(" ACPI ") != std::string::npos)) {
this->Features.HasACPI = true;
- }
}
- delete[] buf;
}
+ delete[] buf;
+ }
// brand string
::memset(retBuf, 0, sizeof(retBuf));
len = sizeof(retBuf);
err = sysctlbyname("machdep.cpu.brand_string", retBuf, &len, NULL, 0);
- if (!err)
- {
+ if (!err) {
this->ChipID.ProcessorName = retBuf;
this->ChipID.ModelName = retBuf;
- }
+ }
// Cache size
len = sizeof(value);
err = sysctlbyname("hw.l1icachesize", &value, &len, NULL, 0);
- this->Features.L1CacheSize = static_cast< int >( value );
+ this->Features.L1CacheSize = static_cast<int>(value);
len = sizeof(value);
err = sysctlbyname("hw.l2cachesize", &value, &len, NULL, 0);
- this->Features.L2CacheSize = static_cast< int >( value );
+ this->Features.L2CacheSize = static_cast<int>(value);
return true;
#else
@@ -4462,33 +4581,31 @@ bool SystemInformationImplementation::ParseSysCtl()
#endif
}
-
/** Extract a value from sysctl command */
-kwsys_stl::string SystemInformationImplementation::ExtractValueFromSysCtl(const char* word)
+std::string SystemInformationImplementation::ExtractValueFromSysCtl(
+ const char* word)
{
size_t pos = this->SysCtlBuffer.find(word);
- if(pos != this->SysCtlBuffer.npos)
- {
- pos = this->SysCtlBuffer.find(": ",pos);
- size_t pos2 = this->SysCtlBuffer.find("\n",pos);
- if(pos!=this->SysCtlBuffer.npos && pos2!=this->SysCtlBuffer.npos)
- {
- return this->SysCtlBuffer.substr(pos+2,pos2-pos-2);
- }
+ if (pos != std::string::npos) {
+ pos = this->SysCtlBuffer.find(": ", pos);
+ size_t pos2 = this->SysCtlBuffer.find("\n", pos);
+ if (pos != std::string::npos && pos2 != std::string::npos) {
+ return this->SysCtlBuffer.substr(pos + 2, pos2 - pos - 2);
}
+ }
return "";
}
-
/** Run a given process */
-kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector<const char*> args)
+std::string SystemInformationImplementation::RunProcess(
+ std::vector<const char*> args)
{
- kwsys_stl::string buffer = "";
+ std::string buffer = "";
// Run the application
kwsysProcess* gp = kwsysProcess_New();
kwsysProcess_SetCommand(gp, &*args.begin());
- kwsysProcess_SetOption(gp,kwsysProcess_Option_HideWindow,1);
+ kwsysProcess_SetOption(gp, kwsysProcess_Option_HideWindow, 1);
kwsysProcess_Execute(gp);
@@ -4497,136 +4614,122 @@ kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector<
double timeout = 255;
int pipe; // pipe id as returned by kwsysProcess_WaitForData()
- while( ( pipe = kwsysProcess_WaitForData(gp,&data,&length,&timeout),
- (pipe == kwsysProcess_Pipe_STDOUT || pipe == kwsysProcess_Pipe_STDERR) ) ) // wait for 1s
- {
- buffer.append(data, length);
- }
+ while ((static_cast<void>(
+ pipe = kwsysProcess_WaitForData(gp, &data, &length, &timeout)),
+ (pipe == kwsysProcess_Pipe_STDOUT ||
+ pipe == kwsysProcess_Pipe_STDERR))) // wait for 1s
+ {
+ buffer.append(data, length);
+ }
kwsysProcess_WaitForExit(gp, 0);
int result = 0;
- switch(kwsysProcess_GetState(gp))
- {
- case kwsysProcess_State_Exited:
- {
+ switch (kwsysProcess_GetState(gp)) {
+ case kwsysProcess_State_Exited: {
result = kwsysProcess_GetExitValue(gp);
- } break;
- case kwsysProcess_State_Error:
- {
- kwsys_ios::cerr << "Error: Could not run " << args[0] << ":\n";
- kwsys_ios::cerr << kwsysProcess_GetErrorString(gp) << "\n";
- } break;
- case kwsysProcess_State_Exception:
- {
- kwsys_ios::cerr << "Error: " << args[0]
- << " terminated with an exception: "
+ } break;
+ case kwsysProcess_State_Error: {
+ std::cerr << "Error: Could not run " << args[0] << ":\n";
+ std::cerr << kwsysProcess_GetErrorString(gp) << "\n";
+ } break;
+ case kwsysProcess_State_Exception: {
+ std::cerr << "Error: " << args[0] << " terminated with an exception: "
<< kwsysProcess_GetExceptionString(gp) << "\n";
- } break;
+ } break;
case kwsysProcess_State_Starting:
case kwsysProcess_State_Executing:
case kwsysProcess_State_Expired:
- case kwsysProcess_State_Killed:
- {
+ case kwsysProcess_State_Killed: {
// Should not get here.
- kwsys_ios::cerr << "Unexpected ending state after running " << args[0]
- << kwsys_ios::endl;
- } break;
- }
+ std::cerr << "Unexpected ending state after running " << args[0]
+ << std::endl;
+ } break;
+ }
kwsysProcess_Delete(gp);
- if(result)
- {
- kwsys_ios::cerr << "Error " << args[0] << " returned :" << result << "\n";
- }
+ if (result) {
+ std::cerr << "Error " << args[0] << " returned :" << result << "\n";
+ }
return buffer;
}
-
-kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const char* arguments)
+std::string SystemInformationImplementation::ParseValueFromKStat(
+ const char* arguments)
{
- kwsys_stl::vector<const char*> args;
+ std::vector<const char*> args;
args.clear();
args.push_back("kstat");
args.push_back("-p");
- kwsys_stl::string command = arguments;
- size_t start = command.npos;
- size_t pos = command.find(' ',0);
- while(pos!=command.npos)
- {
+ std::string command = arguments;
+ size_t start = std::string::npos;
+ size_t pos = command.find(' ', 0);
+ while (pos != std::string::npos) {
bool inQuotes = false;
// Check if we are between quotes
- size_t b0 = command.find('"',0);
- size_t b1 = command.find('"',b0+1);
- while(b0 != command.npos && b1 != command.npos && b1>b0)
- {
- if(pos>b0 && pos<b1)
- {
+ size_t b0 = command.find('"', 0);
+ size_t b1 = command.find('"', b0 + 1);
+ while (b0 != std::string::npos && b1 != std::string::npos && b1 > b0) {
+ if (pos > b0 && pos < b1) {
inQuotes = true;
break;
- }
- b0 = command.find('"',b1+1);
- b1 = command.find('"',b0+1);
}
+ b0 = command.find('"', b1 + 1);
+ b1 = command.find('"', b0 + 1);
+ }
- if(!inQuotes)
- {
- kwsys_stl::string arg = command.substr(start+1,pos-start-1);
+ if (!inQuotes) {
+ std::string arg = command.substr(start + 1, pos - start - 1);
// Remove the quotes if any
size_t quotes = arg.find('"');
- while(quotes != arg.npos)
- {
- arg.erase(quotes,1);
+ while (quotes != std::string::npos) {
+ arg.erase(quotes, 1);
quotes = arg.find('"');
- }
+ }
args.push_back(arg.c_str());
start = pos;
- }
- pos = command.find(' ',pos+1);
}
- kwsys_stl::string lastArg = command.substr(start+1,command.size()-start-1);
+ pos = command.find(' ', pos + 1);
+ }
+ std::string lastArg = command.substr(start + 1, command.size() - start - 1);
args.push_back(lastArg.c_str());
args.push_back(0);
- kwsys_stl::string buffer = this->RunProcess(args);
+ std::string buffer = this->RunProcess(args);
- kwsys_stl::string value = "";
- for(size_t i=buffer.size()-1;i>0;i--)
- {
- if(buffer[i] == ' ' || buffer[i] == '\t')
- {
+ 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')
- {
- kwsys_stl::string val = value;
+ }
+ if (buffer[i] != '\n' && buffer[i] != '\r') {
+ std::string val = value;
value = buffer[i];
value += val;
- }
}
+ }
return value;
}
/** Querying for system information from Solaris */
bool SystemInformationImplementation::QuerySolarisMemory()
{
-#if defined (__SVR4) && defined (__sun)
- // Solaris allows querying this value by sysconf, but if this is
- // 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 defined(__SVR4) && defined(__sun)
+// Solaris allows querying this value by sysconf, but if this is
+// 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 (this->QueryMemoryBySysconf())
- {
+ if (this->QueryMemoryBySysconf()) {
return true;
- }
+ }
#endif
char* tail;
unsigned long totalMemory =
- strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0);
- this->TotalPhysicalMemory = totalMemory/128;
+ strtoul(this->ParseValueFromKStat("-s physmem").c_str(), &tail, 0);
+ this->TotalPhysicalMemory = totalMemory / 128;
return true;
#else
@@ -4636,13 +4739,13 @@ bool SystemInformationImplementation::QuerySolarisMemory()
bool SystemInformationImplementation::QuerySolarisProcessor()
{
- if (!this->QueryProcessorBySysconf())
- {
+ if (!this->QueryProcessorBySysconf()) {
return false;
- }
+ }
// Parse values
- this->CPUSpeedInMHz = static_cast<float>(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str()));
+ this->CPUSpeedInMHz = static_cast<float>(
+ atoi(this->ParseValueFromKStat("-s clock_MHz").c_str()));
// Chip family
this->ChipID.Family = 0;
@@ -4652,33 +4755,47 @@ bool SystemInformationImplementation::QuerySolarisProcessor()
this->ChipID.Model = 0;
// Chip Vendor
- if (this->ChipID.ProcessorName != "i386")
- {
+ if (this->ChipID.ProcessorName != "i386") {
this->ChipID.Vendor = "Sun";
this->FindManufacturer();
- }
+ }
return true;
}
-
/** Querying for system information from Haiku OS */
bool SystemInformationImplementation::QueryHaikuInfo()
{
#if defined(__HAIKU__)
+ // CPU count
system_info info;
get_system_info(&info);
-
this->NumberOfPhysicalCPU = info.cpu_count;
- this->CPUSpeedInMHz = info.cpu_clock_speed / 1000000.0F;
+
+ // CPU speed
+ uint32 topologyNodeCount = 0;
+ cpu_topology_node_info* topology = 0;
+ get_cpu_topology_info(0, &topologyNodeCount);
+ if (topologyNodeCount != 0)
+ topology = new cpu_topology_node_info[topologyNodeCount];
+ get_cpu_topology_info(topology, &topologyNodeCount);
+
+ for (uint32 i = 0; i < topologyNodeCount; i++) {
+ if (topology[i].type == B_TOPOLOGY_CORE) {
+ this->CPUSpeedInMHz =
+ topology[i].data.core.default_frequency / 1000000.0f;
+ break;
+ }
+ }
+
+ delete[] topology;
// Physical Memory
- this->TotalPhysicalMemory = (info.max_pages * B_PAGE_SIZE) / (1024 * 1024) ;
+ this->TotalPhysicalMemory = (info.max_pages * B_PAGE_SIZE) / (1024 * 1024);
this->AvailablePhysicalMemory = this->TotalPhysicalMemory -
((info.used_pages * B_PAGE_SIZE) / (1024 * 1024));
-
// NOTE: get_system_info_etc is currently a private call so just set to 0
// until it becomes public
this->TotalVirtualMemory = 0;
@@ -4737,8 +4854,8 @@ bool SystemInformationImplementation::QueryHaikuInfo()
bool SystemInformationImplementation::QueryQNXMemory()
{
#if defined(__QNX__)
- kwsys_stl::string buffer;
- kwsys_stl::vector<const char*> args;
+ std::string buffer;
+ std::vector<const char*> args;
args.clear();
args.push_back("showmem");
@@ -4748,11 +4865,11 @@ bool SystemInformationImplementation::QueryQNXMemory()
args.clear();
size_t pos = buffer.find("System RAM:");
- if (pos == buffer.npos)
+ if (pos == std::string::npos)
return false;
pos = buffer.find(":", pos);
size_t pos2 = buffer.find("M (", pos);
- if (pos2 == buffer.npos)
+ if (pos2 == std::string::npos)
return false;
pos++;
@@ -4767,7 +4884,8 @@ bool SystemInformationImplementation::QueryQNXMemory()
bool SystemInformationImplementation::QueryBSDMemory()
{
-#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__DragonFly__)
int ctrl[2] = { CTL_HW, HW_PHYSMEM };
#if defined(HW_PHYSMEM64)
int64_t k;
@@ -4777,12 +4895,11 @@ bool SystemInformationImplementation::QueryBSDMemory()
#endif
size_t sz = sizeof(k);
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
- {
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
return false;
- }
+ }
- this->TotalPhysicalMemory = k>>10>>10;
+ this->TotalPhysicalMemory = k >> 10 >> 10;
return true;
#else
@@ -4795,8 +4912,8 @@ bool SystemInformationImplementation::QueryQNXProcessor()
#if defined(__QNX__)
// the output on my QNX 6.4.1 looks like this:
// Processor1: 686 Pentium II Stepping 3 2175MHz FPU
- kwsys_stl::string buffer;
- kwsys_stl::vector<const char*> args;
+ std::string buffer;
+ std::vector<const char*> args;
args.clear();
args.push_back("pidin");
@@ -4806,11 +4923,11 @@ bool SystemInformationImplementation::QueryQNXProcessor()
args.clear();
size_t pos = buffer.find("Processor1:");
- if (pos == buffer.npos)
+ if (pos == std::string::npos)
return false;
size_t pos2 = buffer.find("MHz", pos);
- if (pos2 == buffer.npos)
+ if (pos2 == std::string::npos)
return false;
size_t pos3 = pos2;
@@ -4820,21 +4937,19 @@ bool SystemInformationImplementation::QueryQNXProcessor()
this->CPUSpeedInMHz = atoi(buffer.substr(pos3 + 1, pos2 - pos3 - 1).c_str());
pos2 = buffer.find(" Stepping", pos);
- if (pos2 != buffer.npos)
- {
+ if (pos2 != std::string::npos) {
pos2 = buffer.find(" ", pos2 + 1);
- if (pos2 != buffer.npos && pos2 < pos3)
- {
- this->ChipID.Revision = atoi(buffer.substr(pos2 + 1, pos3 - pos2).c_str());
- }
+ if (pos2 != std::string::npos && pos2 < pos3) {
+ this->ChipID.Revision =
+ atoi(buffer.substr(pos2 + 1, pos3 - pos2).c_str());
}
+ }
this->NumberOfPhysicalCPU = 0;
- do
- {
+ do {
pos = buffer.find("\nProcessor", pos + 1);
++this->NumberOfPhysicalCPU;
- } while (pos != buffer.npos);
+ } while (pos != std::string::npos);
this->NumberOfLogicalCPU = 1;
return true;
@@ -4845,15 +4960,15 @@ bool SystemInformationImplementation::QueryQNXProcessor()
bool SystemInformationImplementation::QueryBSDProcessor()
{
-#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__DragonFly__)
int k;
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, NULL, 0) != 0) {
return false;
- }
+ }
this->NumberOfPhysicalCPU = k;
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
@@ -4861,22 +4976,20 @@ bool SystemInformationImplementation::QueryBSDProcessor()
#if defined(HW_CPUSPEED)
ctrl[1] = HW_CPUSPEED;
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
- {
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
return false;
- }
+ }
- this->CPUSpeedInMHz = (float) k;
+ this->CPUSpeedInMHz = (float)k;
#endif
#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, NULL, 0) != 0) {
return false;
- }
+ }
this->Features.HasSSE = (k > 0);
#endif
@@ -4885,10 +4998,9 @@ bool SystemInformationImplementation::QueryBSDProcessor()
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE2;
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
- {
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
return false;
- }
+ }
this->Features.HasSSE2 = (k > 0);
#endif
@@ -4899,10 +5011,9 @@ bool SystemInformationImplementation::QueryBSDProcessor()
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, NULL, 0) != 0) {
return false;
- }
+ }
this->ChipID.Vendor = vbuf;
this->FindManufacturer();
@@ -4917,33 +5028,31 @@ bool SystemInformationImplementation::QueryBSDProcessor()
bool SystemInformationImplementation::QueryHPUXMemory()
{
#if defined(__hpux)
- unsigned long tv=0;
- unsigned long tp=0;
- unsigned long av=0;
- unsigned long ap=0;
+ unsigned long tv = 0;
+ unsigned long tp = 0;
+ unsigned long av = 0;
+ unsigned long ap = 0;
struct pst_static pst;
struct pst_dynamic pdy;
unsigned long ps = 0;
- if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) == -1)
- {
+ if (pstat_getstatic(&pst, sizeof(pst), (size_t)1, 0) == -1) {
return false;
- }
+ }
ps = pst.page_size;
- tp = pst.physical_memory *ps;
+ tp = pst.physical_memory * ps;
tv = (pst.physical_memory + pst.pst_maxmem) * ps;
- if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) == -1)
- {
+ if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t)1, 0) == -1) {
return false;
- }
+ }
ap = tp - pdy.psd_rm * ps;
av = tv - pdy.psd_vm;
- this->TotalVirtualMemory = tv>>10>>10;
- this->TotalPhysicalMemory = tp>>10>>10;
- this->AvailableVirtualMemory = av>>10>>10;
- this->AvailablePhysicalMemory = ap>>10>>10;
+ this->TotalVirtualMemory = tv >> 10 >> 10;
+ this->TotalPhysicalMemory = tp >> 10 >> 10;
+ this->AvailableVirtualMemory = av >> 10 >> 10;
+ this->AvailablePhysicalMemory = ap >> 10 >> 10;
return true;
#else
return false;
@@ -4953,48 +5062,55 @@ 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)
- {
+ if (c <= 0) {
return false;
- }
+ }
this->NumberOfPhysicalCPU = c;
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
long t = sysconf(_SC_CPU_VERSION);
- if (t == -1)
- {
+ if (t == -1) {
return false;
- }
+ }
- switch (t)
- {
+ switch (t) {
case CPU_PA_RISC1_0:
this->ChipID.Vendor = "Hewlett-Packard";
this->ChipID.Family = 0x100;
+ break;
case CPU_PA_RISC1_1:
this->ChipID.Vendor = "Hewlett-Packard";
this->ChipID.Family = 0x110;
+ break;
case CPU_PA_RISC2_0:
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
+ case CPU_HP_INTEL_EM_1_0:
+#endif
+#ifdef CPU_IA64_ARCHREV_0
case CPU_IA64_ARCHREV_0:
+#endif
this->ChipID.Vendor = "GenuineIntel";
this->Features.HasIA64 = true;
break;
+#endif
default:
return false;
- }
+ }
this->FindManufacturer();
return true;
-# else
+#else
return false;
-# endif
+#endif
#else
return false;
#endif
@@ -5007,210 +5123,184 @@ bool SystemInformationImplementation::QueryOSInformation()
this->OSName = "Windows";
- OSVERSIONINFOEX osvi;
+ OSVERSIONINFOEXW osvi;
BOOL bIsWindows64Bit;
BOOL bOsVersionInfoEx;
char operatingSystem[256];
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
- ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
- bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
- if (!bOsVersionInfoEx)
- {
- osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- if (!GetVersionEx ((OSVERSIONINFO *) &osvi))
- {
+ 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
+ bOsVersionInfoEx = GetVersionExW((OSVERSIONINFOW*)&osvi);
+ if (!bOsVersionInfoEx) {
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ if (!GetVersionExW((OSVERSIONINFOW*)&osvi)) {
return false;
- }
}
+ }
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(pop)
+#endif
- switch (osvi.dwPlatformId)
- {
+ switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
// Test for the product.
- if (osvi.dwMajorVersion <= 4)
- {
+ if (osvi.dwMajorVersion <= 4) {
this->OSRelease = "NT";
- }
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
- {
+ }
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
this->OSRelease = "2000";
- }
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
+ }
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
this->OSRelease = "XP";
- }
+ }
// XP Professional x64
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
- {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
this->OSRelease = "XP";
- }
+ }
#ifdef VER_NT_WORKSTATION
// Test for product type.
- if (bOsVersionInfoEx)
- {
- if (osvi.wProductType == VER_NT_WORKSTATION)
- {
- if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
- {
+ if (bOsVersionInfoEx) {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) {
this->OSRelease = "Vista";
- }
- if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
- {
+ }
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) {
this->OSRelease = "7";
- }
+ }
// VER_SUITE_PERSONAL may not be defined
#ifdef VER_SUITE_PERSONAL
- else
- {
- if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- {
+ else {
+ if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
this->OSRelease += " Personal";
- }
- else
- {
+ } else {
this->OSRelease += " Professional";
- }
}
-#endif
}
- else if (osvi.wProductType == VER_NT_SERVER)
- {
+#endif
+ } else if (osvi.wProductType == VER_NT_SERVER) {
// Check for .NET Server instead of Windows XP.
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
this->OSRelease = ".NET";
- }
+ }
// Continue with the type detection.
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
this->OSRelease += " DataCenter Server";
- }
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- {
+ } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
this->OSRelease += " Advanced Server";
- }
- else
- {
+ } else {
this->OSRelease += " Server";
- }
}
+ }
- sprintf (operatingSystem, "%s (Build %ld)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
+ sprintf(operatingSystem, "%ls (Build %ld)", osvi.szCSDVersion,
+ osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
- }
- else
-#endif // VER_NT_WORKSTATION
- {
+ } else
+#endif // VER_NT_WORKSTATION
+ {
HKEY hKey;
- char szProductType[80];
+ wchar_t szProductType[80];
DWORD dwBufLen;
// Query the registry to retrieve information.
- RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey);
- RegQueryValueEx (hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
- RegCloseKey (hKey);
-
- if (lstrcmpi ("WINNT", szProductType) == 0)
- {
+ RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0,
+ KEY_QUERY_VALUE, &hKey);
+ RegQueryValueExW(hKey, L"ProductType", NULL, NULL,
+ (LPBYTE)szProductType, &dwBufLen);
+ RegCloseKey(hKey);
+
+ if (lstrcmpiW(L"WINNT", szProductType) == 0) {
this->OSRelease += " Professional";
- }
- if (lstrcmpi ("LANMANNT", szProductType) == 0)
- {
- // Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
+ }
+ if (lstrcmpiW(L"LANMANNT", szProductType) == 0) {
+ // Decide between Windows 2000 Advanced Server and Windows .NET
+ // Enterprise Server.
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
this->OSRelease += " Standard Server";
- }
- else
- {
+ } else {
this->OSRelease += " Server";
- }
}
- if (lstrcmpi ("SERVERNT", szProductType) == 0)
- {
- // Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
+ }
+ if (lstrcmpiW(L"SERVERNT", szProductType) == 0) {
+ // Decide between Windows 2000 Advanced Server and Windows .NET
+ // Enterprise Server.
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
this->OSRelease += " Enterprise Server";
- }
- else
- {
+ } else {
this->OSRelease += " Advanced Server";
- }
}
- }
+ }
+ }
// Display version, service pack (if any), and build number.
- if (osvi.dwMajorVersion <= 4)
- {
+ if (osvi.dwMajorVersion <= 4) {
// NB: NT 4.0 and earlier.
- sprintf (operatingSystem, "version %ld.%ld %s (Build %ld)",
- osvi.dwMajorVersion,
- osvi.dwMinorVersion,
- osvi.szCSDVersion,
- osvi.dwBuildNumber & 0xFFFF);
+ sprintf(operatingSystem, "version %ld.%ld %ls (Build %ld)",
+ osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion,
+ osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
- }
- else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
+ } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
// Windows XP and .NET server.
- typedef BOOL (CALLBACK* LPFNPROC) (HANDLE, BOOL *);
+ typedef BOOL(CALLBACK * LPFNPROC)(HANDLE, BOOL*);
HINSTANCE hKernelDLL;
LPFNPROC DLLProc;
// Load the Kernel32 DLL.
- hKernelDLL = LoadLibrary ("kernel32");
- if (hKernelDLL != NULL) {
- // Only XP and .NET Server support IsWOW64Process so... Load dynamically!
- DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process");
+ hKernelDLL = LoadLibraryW(L"kernel32");
+ if (hKernelDLL != NULL) {
+ // 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) (DLLProc) (GetCurrentProcess (), &bIsWindows64Bit);
- else bIsWindows64Bit = false;
+ if (DLLProc != NULL)
+ (DLLProc)(GetCurrentProcess(), &bIsWindows64Bit);
+ else
+ bIsWindows64Bit = false;
// Free the DLL module.
- FreeLibrary (hKernelDLL);
- }
+ FreeLibrary(hKernelDLL);
}
- else
- {
+ } else {
// Windows 2000 and everything else.
- sprintf (operatingSystem,"%s (Build %ld)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
+ sprintf(operatingSystem, "%ls (Build %ld)", osvi.szCSDVersion,
+ osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
- }
+ }
break;
case VER_PLATFORM_WIN32_WINDOWS:
// Test for the product.
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
- {
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
this->OSRelease = "95";
- if(osvi.szCSDVersion[1] == 'C')
- {
+ if (osvi.szCSDVersion[1] == 'C') {
this->OSRelease += "OSR 2.5";
- }
- else if(osvi.szCSDVersion[1] == 'B')
- {
+ } else if (osvi.szCSDVersion[1] == 'B') {
this->OSRelease += "OSR 2";
- }
+ }
}
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
- {
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
this->OSRelease = "98";
- if (osvi.szCSDVersion[1] == 'A' )
- {
+ if (osvi.szCSDVersion[1] == 'A') {
this->OSRelease += "SE";
- }
}
+ }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
- {
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) {
this->OSRelease = "Me";
- }
+ }
break;
case VER_PLATFORM_WIN32s:
@@ -5226,42 +5316,55 @@ bool SystemInformationImplementation::QueryOSInformation()
WORD wVersionRequested;
WSADATA wsaData;
char name[255];
- wVersionRequested = MAKEWORD(2,0);
+ wVersionRequested = MAKEWORD(2, 0);
- if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
- {
- gethostname(name,sizeof(name));
- WSACleanup( );
- }
+ if (WSAStartup(wVersionRequested, &wsaData) == 0) {
+ gethostname(name, sizeof(name));
+ WSACleanup();
+ }
this->Hostname = name;
const char* arch = getenv("PROCESSOR_ARCHITECTURE");
- if(arch)
- {
+ const char* wow64 = getenv("PROCESSOR_ARCHITEW6432");
+ if (arch) {
this->OSPlatform = arch;
- }
+ }
+
+ if (wow64) {
+ // the PROCESSOR_ARCHITEW6432 is only defined when running 32bit programs
+ // on 64bit OS
+ this->OSIs64Bit = true;
+ } else if (arch) {
+ // all values other than x86 map to 64bit architectures
+ this->OSIs64Bit = (strncmp(arch, "x86", 3) != 0);
+ }
#else
struct utsname unameInfo;
int errorFlag = uname(&unameInfo);
- if(errorFlag == 0)
- {
+ if (errorFlag == 0) {
this->OSName = unameInfo.sysname;
this->Hostname = unameInfo.nodename;
this->OSRelease = unameInfo.release;
this->OSVersion = unameInfo.version;
this->OSPlatform = unameInfo.machine;
+
+ // This is still insufficient to capture 64bit architecture such
+ // powerpc and possible mips and sparc
+ if (this->OSPlatform.find_first_of("64") != std::string::npos) {
+ this->OSIs64Bit = true;
}
+ }
#ifdef __APPLE__
- this->OSName="Unknown Apple OS";
- this->OSRelease="Unknown product version";
- this->OSVersion="Unknown build version";
+ this->OSName = "Unknown Apple OS";
+ this->OSRelease = "Unknown product version";
+ this->OSVersion = "Unknown build version";
- this->CallSwVers("-productName",this->OSName);
- this->CallSwVers("-productVersion",this->OSRelease);
- this->CallSwVers("-buildVersion",this->OSVersion);
+ this->CallSwVers("-productName", this->OSName);
+ this->CallSwVers("-productVersion", this->OSRelease);
+ this->CallSwVers("-buildVersion", this->OSVersion);
#endif
#endif
@@ -5269,12 +5372,11 @@ bool SystemInformationImplementation::QueryOSInformation()
return true;
}
-int SystemInformationImplementation::CallSwVers(
- const char *arg,
- kwsys_stl::string &ver)
+int SystemInformationImplementation::CallSwVers(const char* arg,
+ std::string& ver)
{
#ifdef __APPLE__
- kwsys_stl::vector<const char*> args;
+ std::vector<const char*> args;
args.push_back("sw_vers");
args.push_back(arg);
args.push_back(0);
@@ -5288,29 +5390,24 @@ int SystemInformationImplementation::CallSwVers(
return 0;
}
-void SystemInformationImplementation::TrimNewline(kwsys_stl::string& output)
+void SystemInformationImplementation::TrimNewline(std::string& output)
{
// remove \r
- kwsys_stl::string::size_type pos=0;
- while((pos = output.find("\r", pos)) != kwsys_stl::string::npos)
- {
+ std::string::size_type pos = 0;
+ while ((pos = output.find("\r", pos)) != std::string::npos) {
output.erase(pos);
- }
+ }
// remove \n
pos = 0;
- while((pos = output.find("\n", pos)) != kwsys_stl::string::npos)
- {
+ while ((pos = output.find("\n", pos)) != std::string::npos) {
output.erase(pos);
- }
+ }
}
-
/** Return true if the machine is 64 bits */
bool SystemInformationImplementation::Is64Bits()
{
- return (sizeof(void*) == 8);
+ return this->OSIs64Bit;
+}
}
-
-
-} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index a9fd05def..516c505c5 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -1,28 +1,14 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_SystemInformation_h
#define @KWSYS_NAMESPACE@_SystemInformation_h
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
-/* Define these macros temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsys_stl @KWSYS_NAMESPACE@_stl
-# define kwsys_ios @KWSYS_NAMESPACE@_ios
-#endif
-#include <@KWSYS_NAMESPACE@/stl/string>
#include <stddef.h> /* size_t */
+#include <string>
-namespace @KWSYS_NAMESPACE@
-{
+namespace @KWSYS_NAMESPACE@ {
// forward declare the implementation class
class SystemInformationImplementation;
@@ -34,24 +20,51 @@ 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;
+
public:
+ // possible parameter values for DoesCPUSupportFeature()
+ static const long int CPU_FEATURE_MMX = 1 << 0;
+ static const long int CPU_FEATURE_MMX_PLUS = 1 << 1;
+ static const long int CPU_FEATURE_SSE = 1 << 2;
+ static const long int CPU_FEATURE_SSE2 = 1 << 3;
+ static const long int CPU_FEATURE_AMD_3DNOW = 1 << 4;
+ static const long int CPU_FEATURE_AMD_3DNOW_PLUS = 1 << 5;
+ static const long int CPU_FEATURE_IA64 = 1 << 6;
+ static const long int CPU_FEATURE_MP_CAPABLE = 1 << 7;
+ static const long int CPU_FEATURE_HYPERTHREAD = 1 << 8;
+ static const long int CPU_FEATURE_SERIALNUMBER = 1 << 9;
+ static const long int CPU_FEATURE_APIC = 1 << 10;
+ static const long int CPU_FEATURE_SSE_FP = 1 << 11;
+ static const long int CPU_FEATURE_SSE_MMX = 1 << 12;
+ static const long int CPU_FEATURE_CMOV = 1 << 13;
+ static const long int CPU_FEATURE_MTRR = 1 << 14;
+ static const long int CPU_FEATURE_L1CACHE = 1 << 15;
+ static const long int CPU_FEATURE_L2CACHE = 1 << 16;
+ static const long int CPU_FEATURE_L3CACHE = 1 << 17;
+ static const long int CPU_FEATURE_ACPI = 1 << 18;
+ static const long int CPU_FEATURE_THERMALMONITOR = 1 << 19;
+ static const long int CPU_FEATURE_TEMPSENSEDIODE = 1 << 20;
+ static const long int CPU_FEATURE_FREQUENCYID = 1 << 21;
+ static const long int CPU_FEATURE_VOLTAGEID_FREQUENCY = 1 << 22;
+ static const long int CPU_FEATURE_FPU = 1 << 23;
- SystemInformation ();
- ~SystemInformation ();
-
- const char * GetVendorString();
- const char * GetVendorID();
- kwsys_stl::string GetTypeID();
- kwsys_stl::string GetFamilyID();
- kwsys_stl::string GetModelID();
- kwsys_stl::string GetModelName();
- kwsys_stl::string GetSteppingCode();
- const char * GetExtendedProcessorName();
- const char * GetProcessorSerialNumber();
+public:
+ SystemInformation();
+ ~SystemInformation();
+
+ const char* GetVendorString();
+ const char* GetVendorID();
+ std::string GetTypeID();
+ std::string GetFamilyID();
+ std::string GetModelID();
+ std::string GetModelName();
+ std::string GetSteppingCode();
+ const char* GetExtendedProcessorName();
+ const char* GetProcessorSerialNumber();
int GetProcessorCacheSize();
unsigned int GetLogicalProcessorsPerPhysical();
float GetProcessorClockFrequency();
@@ -61,15 +74,15 @@ public:
// returns an informative general description of the cpu
// on this system.
- kwsys_stl::string GetCPUDescription();
+ std::string GetCPUDescription();
- const char * GetHostname();
- kwsys_stl::string GetFullyQualifiedDomainName();
+ const char* GetHostname();
+ std::string GetFullyQualifiedDomainName();
- const char * GetOSName();
- const char * GetOSRelease();
- const char * GetOSVersion();
- const char * GetOSPlatform();
+ const char* GetOSName();
+ const char* GetOSRelease();
+ const char* GetOSVersion();
+ const char* GetOSPlatform();
int GetOSIsWindows();
int GetOSIsLinux();
@@ -77,11 +90,12 @@ public:
// returns an informative general description of the os
// on this system.
- kwsys_stl::string GetOSDescription();
+ std::string GetOSDescription();
+ // returns if the operating system is 64bit or not.
bool Is64Bits();
- unsigned int GetNumberOfLogicalCPU(); // per physical cpu
+ unsigned int GetNumberOfLogicalCPU();
unsigned int GetNumberOfPhysicalCPU();
bool DoesCPUSupportCPUID();
@@ -98,9 +112,8 @@ public:
// returns an informative general description if the installed and
// available ram on this system. See the GetHostMmeoryTotal, and
// Get{Host,Proc}MemoryAvailable methods for more information.
- kwsys_stl::string GetMemoryDescription(
- const char *hostLimitEnvVarName=NULL,
- const char *procLimitEnvVarName=NULL);
+ std::string GetMemoryDescription(const char* hostLimitEnvVarName = NULL,
+ const char* procLimitEnvVarName = NULL);
// Retrieve amount of physical memory installed on the system in KiB
// units.
@@ -112,7 +125,7 @@ public:
// 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);
+ LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = NULL);
// Get total system RAM in units of KiB available to this process.
// This may differ from the host available if a per-process resource
@@ -120,9 +133,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 = NULL,
+ const char* procLimitEnvVarName = NULL);
// Get the system RAM used by all processes on the host, in units of KiB.
LongLong GetHostMemoryUsed();
@@ -130,17 +142,19 @@ public:
// Get system RAM used by this process id in units of KiB.
LongLong GetProcMemoryUsed();
+ // Return the load average of the machine or -0.0 if it cannot
+ // be determined.
+ double GetLoadAverage();
+
// enable/disable stack trace signal handler. In order to
// produce an informative stack trace the application should
// be dynamically linked and compiled with debug symbols.
- static
- void SetStackTraceOnError(int enable);
+ static void SetStackTraceOnError(int enable);
// format and return the current program stack in a string. In
// order to produce an informative stack trace the application
// should be dynamically linked and compiled with debug symbols.
- static
- kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);
+ static std::string GetProgramStack(int firstFrame, int wholePath);
/** Run the different checks */
void RunCPUCheck();
@@ -150,10 +164,4 @@ public:
} // namespace @KWSYS_NAMESPACE@
-/* Undefine temporary macros. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# undef kwsys_stl
-# undef kwsys_ios
-#endif
-
#endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index e9a1fd37d..1c4fe3389 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -1,105 +1,123 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
+/* 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
+#else
+#if defined(__SUNPRO_CC)
+#include <fcntl.h>
+#endif
#endif
#include "kwsysPrivate.h"
#include KWSYS_HEADER(RegularExpression.hxx)
#include KWSYS_HEADER(SystemTools.hxx)
#include KWSYS_HEADER(Directory.hxx)
+#include KWSYS_HEADER(FStream.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(ios/fstream)
-#include KWSYS_HEADER(ios/sstream)
-
-#include KWSYS_HEADER(stl/set)
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <sstream>
+#include <vector>
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "SystemTools.hxx.in"
-# include "Directory.hxx.in"
-# include "kwsys_ios_iostream.h.in"
-# include "kwsys_ios_fstream.h.in"
-# include "kwsys_ios_sstream.h.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>
#include <string.h>
-#include <sys/stat.h>
#include <time.h>
+#if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__)
+#include <strings.h> /* for strcasecmp */
+#endif
+
+#ifdef _MSC_VER
+#define umask _umask // Note this is still umask on Borland
+#endif
+
// support for realpath call
#ifndef _WIN32
-#include <sys/time.h>
-#include <utime.h>
#include <limits.h>
-#include <sys/wait.h>
+#include <pwd.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
#include <unistd.h>
-#include <pwd.h>
+#include <utime.h>
#ifndef __VMS
#include <sys/param.h>
#include <termios.h>
#endif
-#include <signal.h> /* sigprocmask */
+#include <signal.h> /* sigprocmask */
#endif
// Windows API.
#if defined(_WIN32)
-# include <windows.h>
-#elif defined (__CYGWIN__)
-# include <windows.h>
-# undef _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
+#elif defined(__CYGWIN__)
+#include <windows.h>
+#undef _WIN32
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
-extern char **environ;
+extern char** environ;
#endif
#ifdef __CYGWIN__
-extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
+#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__)
+#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]*)://(.*)"
-#define VTK_URL_REGEX "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/(.+)?"
+#define VTK_URL_REGEX \
+ "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/" \
+ "(.+)?"
#ifdef _MSC_VER
#include <sys/utime.h>
@@ -107,13 +125,11 @@ extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
#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>
-namespace KWSYS_NAMESPACE
-{
+#include <sys/termios.h>
+namespace KWSYS_NAMESPACE {
class SystemToolsHack
{
public:
@@ -123,26 +139,27 @@ public:
Ref2 = sizeof(cfgetispeed(0)),
Ref3 = sizeof(tcgetattr(0, 0)),
Ref4 = sizeof(tcsetattr(0, 0, 0)),
- Ref5 = sizeof(cfsetospeed(0,0)),
- Ref6 = sizeof(cfsetispeed(0,0))
+ Ref5 = sizeof(cfsetospeed(0, 0)),
+ Ref6 = sizeof(cfsetispeed(0, 0))
};
};
}
#endif
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__))
-#include <io.h>
+#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>
@@ -152,11 +169,6 @@ public:
#define _chdir chdir
#endif
-#if defined(__HAIKU__)
-#include <os/kernel/OS.h>
-#include <os/storage/Path.h>
-#endif
-
#if defined(__BEOS__) && !defined(__ZETA__)
#include <be/kernel/OS.h>
#include <be/storage/Path.h>
@@ -168,326 +180,480 @@ static inline void usleep(unsigned int msec)
}
// BeOS 5 also doesn't have realpath(), but its C++ API offers something close.
-static inline char *realpath(const char *path, char *resolved_path)
+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);
- const char *resolved = normalized.Path();
- if (resolved != NULL) // NULL == No such file.
- {
- if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen)
- {
+ const char* resolved = normalized.Path();
+ if (resolved != NULL) // NULL == No such file.
+ {
+ if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen) {
return resolved_path;
- }
}
- return NULL; // something went wrong.
+ }
+ return NULL; // something went wrong.
+}
+#endif
+
+#ifdef _WIN32
+static time_t windows_filetime_to_posix_time(const FILETIME& ft)
+{
+ LARGE_INTEGER date;
+ date.HighPart = ft.dwHighDateTime;
+ date.LowPart = ft.dwLowDateTime;
+
+ // removes the diff between 1970 and 1601
+ date.QuadPart -= ((LONGLONG)(369 * 365 + 89) * 24 * 3600 * 10000000);
+
+ // converts back from 100-nanoseconds to seconds
+ return date.QuadPart / 10000000;
}
#endif
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
-inline int Mkdir(const char* dir)
+#ifdef KWSYS_WINDOWS_DIRS
+#include <wctype.h>
+
+inline int Mkdir(const std::string& dir)
{
- return _mkdir(dir);
+ return _wmkdir(
+ KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
}
-inline int Rmdir(const char* dir)
+inline int Rmdir(const std::string& dir)
{
- return _rmdir(dir);
+ return _wrmdir(
+ KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
}
inline const char* Getcwd(char* buf, unsigned int len)
{
- if(const char* ret = _getcwd(buf, len))
- {
+ std::vector<wchar_t> w_buf(len);
+ if (_wgetcwd(&w_buf[0], len)) {
// make sure the drive letter is capital
- if(strlen(buf) > 1 && buf[1] == ':')
- {
- buf[0] = toupper(buf[0]);
- }
- return ret;
+ if (wcslen(&w_buf[0]) > 1 && w_buf[1] == L':') {
+ w_buf[0] = towupper(w_buf[0]);
}
+ std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]);
+ strcpy(buf, tmp.c_str());
+ return buf;
+ }
return 0;
}
-inline int Chdir(const char* dir)
+inline int Chdir(const std::string& dir)
{
- #if defined(__BORLANDC__)
- return chdir(dir);
- #else
- return _chdir(dir);
- #endif
+#if defined(__BORLANDC__)
+ return chdir(dir.c_str());
+#else
+ return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
+#endif
}
-inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
+inline void Realpath(const std::string& path, std::string& resolved_path,
+ std::string* errorMessage = 0)
{
- char *ptemp;
- char fullpath[MAX_PATH];
- if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
- {
- resolved_path = fullpath;
+ std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
+ wchar_t* ptemp;
+ wchar_t fullpath[MAX_PATH];
+ DWORD bufferLen = GetFullPathNameW(
+ tmp.c_str(), sizeof(fullpath) / sizeof(fullpath[0]), fullpath, &ptemp);
+ if (bufferLen < sizeof(fullpath) / sizeof(fullpath[0])) {
+ resolved_path = KWSYS_NAMESPACE::Encoding::ToNarrow(fullpath);
KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
- }
- else
- {
+ } else if (errorMessage) {
+ if (bufferLen) {
+ *errorMessage = "Destination path buffer size too small.";
+ } else if (unsigned int errorId = GetLastError()) {
+ LPSTR message = NULL;
+ 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);
+ *errorMessage = std::string(message, size);
+ LocalFree(message);
+ } else {
+ *errorMessage = "Unknown error.";
+ }
+
+ resolved_path = "";
+ } else {
resolved_path = path;
- }
+ }
}
#else
#include <sys/types.h>
+
#include <fcntl.h>
#include <unistd.h>
-inline int Mkdir(const char* dir)
+inline int Mkdir(const std::string& dir)
{
- return mkdir(dir, 00777);
+ return mkdir(dir.c_str(), 00777);
}
-inline int Rmdir(const char* dir)
+inline int Rmdir(const std::string& dir)
{
- return rmdir(dir);
+ return rmdir(dir.c_str());
}
inline const char* Getcwd(char* buf, unsigned int len)
{
return getcwd(buf, len);
}
-inline int Chdir(const char* dir)
+inline int Chdir(const std::string& dir)
{
- return chdir(dir);
+ return chdir(dir.c_str());
}
-inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
+inline void Realpath(const std::string& path, std::string& resolved_path,
+ std::string* errorMessage = 0)
{
char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
- char *ret = realpath(path, resolved_name);
- if(ret)
- {
+ errno = 0;
+ char* ret = realpath(path.c_str(), resolved_name);
+ if (ret) {
resolved_path = ret;
+ } else if (errorMessage) {
+ if (errno) {
+ *errorMessage = strerror(errno);
+ } else {
+ *errorMessage = "Unknown error.";
}
- else
- {
+
+ resolved_path = "";
+ } else {
// if path resolution fails, return what was passed in
resolved_path = path;
- }
+ }
}
#endif
#if !defined(_WIN32) && defined(__COMO__)
// Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
-extern "C"
-{
-extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
-extern int pclose (FILE *__stream) __THROW;
-extern char *realpath (__const char *__restrict __name,
- char *__restrict __resolved) __THROW;
-extern char *strdup (__const char *__s) __THROW;
-extern int putenv (char *__string) __THROW;
+extern "C" {
+extern FILE* popen(__const char* __command, __const char* __modes) __THROW;
+extern int pclose(FILE* __stream) __THROW;
+extern char* realpath(__const char* __restrict __name,
+ char* __restrict __resolved) __THROW;
+extern char* strdup(__const char* __s) __THROW;
+extern int putenv(char* __string) __THROW;
}
#endif
-namespace KWSYS_NAMESPACE
-{
+namespace KWSYS_NAMESPACE {
double SystemTools::GetTime(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
- return (429.4967296*ft.dwHighDateTime
- + 0.0000001*ft.dwLowDateTime
- - 11644473600.0);
+ return (429.4967296 * ft.dwHighDateTime + 0.0000001 * ft.dwLowDateTime -
+ 11644473600.0);
#else
struct timeval t;
gettimeofday(&t, 0);
- return 1.0*double(t.tv_sec) + 0.000001*double(t.tv_usec);
+ return 1.0 * double(t.tv_sec) + 0.000001 * double(t.tv_usec);
#endif
}
-class SystemToolsTranslationMap :
- public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
+class SystemToolsTranslationMap : public std::map<std::string, std::string>
{
};
-// adds the elements of the env variable path to the arg passed in
-void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
+/* Type of character storing the environment. */
+#if defined(_WIN32)
+typedef wchar_t envchar;
+#else
+typedef char envchar;
+#endif
+
+/* Order by environment key only (VAR from VAR=VALUE). */
+struct kwsysEnvCompare
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- const char* pathSep = ";";
+ bool operator()(const envchar* l, const envchar* r) const
+ {
+#if defined(_WIN32)
+ const wchar_t* leq = wcschr(l, L'=');
+ const wchar_t* req = wcschr(r, L'=');
+ size_t llen = leq ? (leq - l) : wcslen(l);
+ size_t rlen = req ? (req - r) : wcslen(r);
+ if (llen == rlen) {
+ return wcsncmp(l, r, llen) < 0;
+ } else {
+ return wcscmp(l, r) < 0;
+ }
#else
- const char* pathSep = ":";
+ 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);
+ if (llen == rlen) {
+ return strncmp(l, r, llen) < 0;
+ } else {
+ return strcmp(l, r) < 0;
+ }
#endif
- if(!env)
+ }
+};
+
+class kwsysEnvSet : public std::set<const envchar*, kwsysEnvCompare>
+{
+public:
+ class Free
+ {
+ const envchar* Env;
+
+ public:
+ Free(const envchar* env)
+ : Env(env)
{
- env = "PATH";
}
- const char* cpathEnv = SystemTools::GetEnv(env);
- if ( !cpathEnv )
- {
- return;
+ ~Free() { free(const_cast<envchar*>(this->Env)); }
+ };
+
+ const envchar* Release(const envchar* env)
+ {
+ const envchar* old = 0;
+ iterator i = this->find(env);
+ if (i != this->end()) {
+ old = *i;
+ this->erase(i);
}
+ return old;
+ }
+};
+
+#ifdef _WIN32
+struct SystemToolsPathCaseCmp
+{
+ bool operator()(std::string const& l, std::string const& r) const
+ {
+#ifdef _MSC_VER
+ return _stricmp(l.c_str(), r.c_str()) < 0;
+#elif defined(__GNUC__)
+ return strcasecmp(l.c_str(), r.c_str()) < 0;
+#else
+ return SystemTools::Strucmp(l.c_str(), r.c_str()) < 0;
+#endif
+ }
+};
+
+class SystemToolsPathCaseMap
+ : public std::map<std::string, std::string, SystemToolsPathCaseCmp>
+{
+};
- kwsys_stl::string pathEnv = cpathEnv;
+class SystemToolsEnvMap : public std::map<std::string, std::string>
+{
+};
+#endif
+
+// adds the elements of the env variable path to the arg passed in
+void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
+{
+ size_t const old_size = path.size();
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const char pathSep = ';';
+#else
+ const char pathSep = ':';
+#endif
+ if (!env) {
+ env = "PATH";
+ }
+ std::string pathEnv;
+ if (!SystemTools::GetEnv(env, pathEnv)) {
+ return;
+ }
// A hack to make the below algorithm work.
- if(!pathEnv.empty() && pathEnv[pathEnv.length()-1] != pathSep[0])
- {
+ if (!pathEnv.empty() && *pathEnv.rbegin() != pathSep) {
pathEnv += pathSep;
- }
- kwsys_stl::string::size_type start =0;
+ }
+ std::string::size_type start = 0;
bool done = false;
- while(!done)
- {
- kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
- if(endpos != kwsys_stl::string::npos)
- {
- path.push_back(pathEnv.substr(start, endpos-start));
- start = endpos+1;
- }
- else
- {
+ while (!done) {
+ std::string::size_type endpos = pathEnv.find(pathSep, start);
+ if (endpos != std::string::npos) {
+ path.push_back(pathEnv.substr(start, endpos - start));
+ start = endpos + 1;
+ } else {
done = true;
- }
}
- for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
- i != path.end(); ++i)
- {
+ }
+ for (std::vector<std::string>::iterator i = path.begin() + old_size;
+ i != path.end(); ++i) {
SystemTools::ConvertToUnixSlashes(*i);
- }
+ }
+}
+
+const char* SystemTools::GetEnvImpl(const char* key)
+{
+ const char* v = 0;
+#if defined(_WIN32)
+ std::string env;
+ if (SystemTools::GetEnv(key, env)) {
+ std::string& menv = (*SystemTools::EnvMap)[key];
+ menv = env;
+ v = menv.c_str();
+ }
+#else
+ v = getenv(key);
+#endif
+ return v;
}
const char* SystemTools::GetEnv(const char* key)
{
- return getenv(key);
+ return SystemTools::GetEnvImpl(key);
+}
+
+const char* SystemTools::GetEnv(const std::string& key)
+{
+ return SystemTools::GetEnvImpl(key.c_str());
}
-bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
+bool SystemTools::GetEnv(const char* key, std::string& result)
{
+#if defined(_WIN32)
+ const std::wstring wkey = Encoding::ToWide(key);
+ const wchar_t* wv = _wgetenv(wkey.c_str());
+ if (wv) {
+ result = Encoding::ToNarrow(wv);
+ return true;
+ }
+#else
const char* v = getenv(key);
- if(v)
- {
+ if (v) {
result = v;
return true;
- }
- else
- {
- return false;
- }
+ }
+#endif
+ return false;
}
-//----------------------------------------------------------------------------
+bool SystemTools::GetEnv(const std::string& key, std::string& result)
+{
+ return SystemTools::GetEnv(key.c_str(), result);
+}
-#if defined(__CYGWIN__) || defined(__GLIBC__)
-# define KWSYS_PUTENV_NAME /* putenv("A") removes A. */
-#elif defined(_WIN32)
-# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
+bool SystemTools::HasEnv(const char* key)
+{
+#if defined(_WIN32)
+ const std::wstring wkey = Encoding::ToWide(key);
+ const wchar_t* v = _wgetenv(wkey.c_str());
+#else
+ const char* v = getenv(key);
#endif
+ return v != 0;
+}
+
+bool SystemTools::HasEnv(const std::string& key)
+{
+ return SystemTools::HasEnv(key.c_str());
+}
#if KWSYS_CXX_HAS_UNSETENV
/* unsetenv("A") removes A from the environment.
On older platforms it returns void instead of int. */
-static int kwsysUnPutEnv(const char* env)
+static int kwsysUnPutEnv(const std::string& env)
{
- if(const char* eq = strchr(env, '='))
- {
- std::string name(env, eq-env);
+ size_t pos = env.find('=');
+ if (pos != std::string::npos) {
+ std::string name = env.substr(0, pos);
unsetenv(name.c_str());
- }
- else
- {
- unsetenv(env);
- }
+ } else {
+ unsetenv(env.c_str());
+ }
return 0;
}
-#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
-/* putenv("A=") or putenv("A") removes A from the environment. */
-static int kwsysUnPutEnv(const char* env)
+#elif defined(__CYGWIN__) || defined(__GLIBC__)
+/* putenv("A") removes A from the environment. It must not put the
+ memory in the environment because it does not have any "=" syntax. */
+static int kwsysUnPutEnv(const std::string& env)
{
int err = 0;
- const char* eq = strchr(env, '=');
- size_t const len = eq? (size_t)(eq-env) : strlen(env);
-# ifdef KWSYS_PUTENV_EMPTY
- size_t const sz = len + 2;
-# else
+ size_t pos = env.find('=');
+ size_t const len = pos == std::string::npos ? env.size() : pos;
size_t const sz = len + 1;
-# endif
char local_buf[256];
char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
- if(!buf)
- {
+ if (!buf) {
return -1;
- }
- strncpy(buf, env, len);
-# ifdef KWSYS_PUTENV_EMPTY
- buf[len] = '=';
- buf[len+1] = 0;
- if(putenv(buf) < 0)
- {
- err = errno;
- }
-# else
+ }
+ strncpy(buf, env.c_str(), len);
buf[len] = 0;
- if(putenv(buf) < 0 && errno != EINVAL)
- {
+ if (putenv(buf) < 0 && errno != EINVAL) {
err = errno;
- }
-# endif
- if(buf != local_buf)
- {
+ }
+ if (buf != local_buf) {
free(buf);
- }
- if(err)
- {
+ }
+ if (err) {
errno = err;
return -1;
- }
+ }
return 0;
}
+#elif defined(_WIN32)
+/* putenv("A=") places "A=" in the environment, which is as close to
+ removal as we can get with the putenv API. We have to leak the
+ most recent value placed in the environment for each variable name
+ on program exit in case exit routines access it. */
+
+static kwsysEnvSet kwsysUnPutEnvSet;
+
+static int kwsysUnPutEnv(std::string const& env)
+{
+ std::wstring wEnv = Encoding::ToWide(env);
+ size_t const pos = wEnv.find('=');
+ size_t const len = pos == std::string::npos ? wEnv.size() : pos;
+ wEnv.resize(len + 1, L'=');
+ wchar_t* newEnv = _wcsdup(wEnv.c_str());
+ if (!newEnv) {
+ return -1;
+ }
+ kwsysEnvSet::Free oldEnv(kwsysUnPutEnvSet.Release(newEnv));
+ kwsysUnPutEnvSet.insert(newEnv);
+ return _wputenv(newEnv);
+}
+
#else
/* Manipulate the "environ" global directly. */
-static int kwsysUnPutEnv(const char* env)
+static int kwsysUnPutEnv(const std::string& env)
{
- const char* eq = strchr(env, '=');
- size_t const len = eq? (size_t)(eq-env) : strlen(env);
+ size_t pos = env.find('=');
+ size_t const len = pos == std::string::npos ? env.size() : pos;
int in = 0;
int out = 0;
- while(environ[in])
- {
- if(strlen(environ[in]) > len &&
- environ[in][len] == '=' &&
- strncmp(env, environ[in], len) == 0)
- {
+ while (environ[in]) {
+ if (strlen(environ[in]) > len && environ[in][len] == '=' &&
+ strncmp(env.c_str(), environ[in], len) == 0) {
++in;
- }
- else
- {
+ } else {
environ[out++] = environ[in++];
- }
}
- while(out < in)
- {
+ }
+ while (out < in) {
environ[out++] = 0;
- }
+ }
return 0;
}
#endif
-//----------------------------------------------------------------------------
-
#if KWSYS_CXX_HAS_SETENV
/* setenv("A", "B", 1) will set A=B in the environment and makes its
own copies of the strings. */
-bool SystemTools::PutEnv(const char* env)
+bool SystemTools::PutEnv(const std::string& env)
{
- if(const char* eq = strchr(env, '='))
- {
- std::string name(env, eq-env);
- return setenv(name.c_str(), eq+1, 1) == 0;
- }
- else
- {
+ size_t pos = env.find('=');
+ if (pos != std::string::npos) {
+ std::string name = env.substr(0, pos);
+ return setenv(name.c_str(), env.c_str() + pos + 1, 1) == 0;
+ } else {
return kwsysUnPutEnv(env) == 0;
- }
+ }
}
-bool SystemTools::UnPutEnv(const char* env)
+bool SystemTools::UnPutEnv(const std::string& env)
{
return kwsysUnPutEnv(env) == 0;
}
@@ -501,92 +667,67 @@ bool SystemTools::UnPutEnv(const char* 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
-
-/* Order by environment key only (VAR from VAR=VALUE). */
-struct kwsysEnvCompare
-{
- bool operator() (const char* l, const char* r) const
- {
- 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);
- if(llen == rlen)
- {
- return strncmp(l,r,llen) < 0;
- }
- else
- {
- return strcmp(l,r) < 0;
- }
- }
-};
+#ifdef __INTEL_COMPILER
+#pragma warning disable 444 /* base has non-virtual destructor */
+#endif
-class kwsysEnv: public kwsys_stl::set<const char*, kwsysEnvCompare>
+class kwsysEnv : public kwsysEnvSet
{
- class Free
- {
- const char* Env;
- public:
- Free(const char* env): Env(env) {}
- ~Free() { free(const_cast<char*>(this->Env)); }
- };
public:
- typedef kwsys_stl::set<const char*, kwsysEnvCompare> derived;
~kwsysEnv()
- {
- for(derived::iterator i = this->begin(); i != this->end(); ++i)
- {
+ {
+ for (iterator i = this->begin(); i != this->end(); ++i) {
+#if defined(_WIN32)
+ const std::string s = Encoding::ToNarrow(*i);
+ kwsysUnPutEnv(s.c_str());
+#else
kwsysUnPutEnv(*i);
- free(const_cast<char*>(*i));
- }
- }
- const char* Release(const char* env)
- {
- const char* old = 0;
- derived::iterator i = this->find(env);
- if(i != this->end())
- {
- old = *i;
- this->erase(i);
- }
- return old;
+#endif
+ free(const_cast<envchar*>(*i));
}
+ }
bool Put(const char* env)
- {
- Free oldEnv(this->Release(env));
- static_cast<void>(oldEnv);
+ {
+#if defined(_WIN32)
+ const std::wstring wEnv = Encoding::ToWide(env);
+ wchar_t* newEnv = _wcsdup(wEnv.c_str());
+#else
char* newEnv = strdup(env);
+#endif
+ Free oldEnv(this->Release(newEnv));
this->insert(newEnv);
+#if defined(_WIN32)
+ return _wputenv(newEnv) == 0;
+#else
return putenv(newEnv) == 0;
- }
+#endif
+ }
bool UnPut(const char* env)
- {
+ {
+#if defined(_WIN32)
+ const std::wstring wEnv = Encoding::ToWide(env);
+ Free oldEnv(this->Release(wEnv.c_str()));
+#else
Free oldEnv(this->Release(env));
- static_cast<void>(oldEnv);
+#endif
return kwsysUnPutEnv(env) == 0;
- }
+ }
};
static kwsysEnv kwsysEnvInstance;
-bool SystemTools::PutEnv(const char* env)
+bool SystemTools::PutEnv(const std::string& env)
{
- return kwsysEnvInstance.Put(env);
+ return kwsysEnvInstance.Put(env.c_str());
}
-bool SystemTools::UnPutEnv(const char* env)
+bool SystemTools::UnPutEnv(const std::string& env)
{
- return kwsysEnvInstance.UnPut(env);
+ return kwsysEnvInstance.UnPut(env.c_str());
}
#endif
-//----------------------------------------------------------------------------
-
const char* SystemTools::GetExecutableExtension()
{
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS)
@@ -596,90 +737,111 @@ const char* SystemTools::GetExecutableExtension()
#endif
}
+FILE* SystemTools::Fopen(const std::string& file, const char* mode)
+{
+#ifdef _WIN32
+ return _wfopen(Encoding::ToWindowsExtendedPath(file).c_str(),
+ Encoding::ToWide(mode).c_str());
+#else
+ return fopen(file.c_str(), mode);
+#endif
+}
bool SystemTools::MakeDirectory(const char* path)
{
- if(!path)
- {
+ if (!path) {
return false;
- }
- if(SystemTools::FileExists(path))
- {
+ }
+ return SystemTools::MakeDirectory(std::string(path));
+}
+
+bool SystemTools::MakeDirectory(const std::string& path)
+{
+ if (SystemTools::PathExists(path)) {
return SystemTools::FileIsDirectory(path);
- }
- kwsys_stl::string dir = path;
- if(dir.size() == 0)
- {
+ }
+ if (path.empty()) {
return false;
- }
+ }
+ std::string dir = path;
SystemTools::ConvertToUnixSlashes(dir);
- kwsys_stl::string::size_type pos = 0;
- kwsys_stl::string topdir;
- while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
- {
+ std::string::size_type pos = 0;
+ std::string topdir;
+ while ((pos = dir.find('/', pos)) != std::string::npos) {
topdir = dir.substr(0, pos);
- Mkdir(topdir.c_str());
+ Mkdir(topdir);
pos++;
- }
+ }
topdir = dir;
- if(Mkdir(topdir.c_str()) != 0)
- {
+ if (Mkdir(topdir) != 0) {
// There is a bug in the Borland Run time library which makes MKDIR
// return EACCES when it should return EEXISTS
// if it is some other error besides directory exists
// then return false
- if( (errno != EEXIST)
+ if ((errno != EEXIST)
#ifdef __BORLANDC__
&& (errno != EACCES)
#endif
- )
- {
+ ) {
return false;
- }
}
+ }
return true;
}
-
// replace replace with with as many times as it shows up in source.
// write the result into source.
-void SystemTools::ReplaceString(kwsys_stl::string& source,
- const char* replace,
- const char* with)
+void SystemTools::ReplaceString(std::string& source,
+ const std::string& replace,
+ const std::string& with)
+{
+ // do while hangs if replaceSize is 0
+ if (replace.empty()) {
+ return;
+ }
+
+ SystemTools::ReplaceString(source, replace.c_str(), replace.size(), with);
+}
+
+void SystemTools::ReplaceString(std::string& source, const char* replace,
+ const char* with)
{
- const char *src = source.c_str();
- char *searchPos = const_cast<char *>(strstr(src,replace));
+ // do while hangs if replaceSize is 0
+ if (!*replace) {
+ return;
+ }
+
+ SystemTools::ReplaceString(source, replace, strlen(replace),
+ with ? with : "");
+}
+
+void SystemTools::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));
// get out quick if string is not found
- if (!searchPos)
- {
+ if (!searchPos) {
return;
- }
+ }
// perform replacements until done
- size_t replaceSize = strlen(replace);
- // do while hangs if replaceSize is 0
- if(replaceSize == 0)
- {
- return;
- }
- char *orig = strdup(src);
- char *currentPos = orig;
+ char* orig = strdup(src);
+ char* currentPos = orig;
searchPos = searchPos - src + orig;
// initialize the result
- source.erase(source.begin(),source.end());
- do
- {
+ source.erase(source.begin(), source.end());
+ do {
*searchPos = '\0';
source += currentPos;
currentPos = searchPos + replaceSize;
// replace
source += with;
- searchPos = strstr(currentPos,replace);
- }
- while (searchPos);
+ searchPos = strstr(currentPos, replace);
+ } while (searchPos);
// copy any trailing text
source += currentPos;
@@ -687,56 +849,48 @@ void SystemTools::ReplaceString(kwsys_stl::string& source,
}
#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
+#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
+#define KWSYS_ST_KEY_WOW64_32KEY 0x0200
+#define KWSYS_ST_KEY_WOW64_64KEY 0x0100
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
-static bool SystemToolsParseRegistryKey(const char* key,
- HKEY& primaryKey,
- kwsys_stl::string& second,
- kwsys_stl::string& valuename)
+static bool SystemToolsParseRegistryKey(const std::string& key,
+ HKEY& primaryKey, std::string& second,
+ std::string& valuename)
{
- kwsys_stl::string primary = key;
+ std::string primary = key;
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
- {
+ size_t start = primary.find('\\');
+ if (start == std::string::npos) {
return false;
- }
+ }
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
+ size_t valuenamepos = primary.find(';');
+ if (valuenamepos != std::string::npos) {
+ valuename = primary.substr(valuenamepos + 1);
+ }
- second = primary.substr(start+1, valuenamepos-start-1);
+ second = primary.substr(start + 1, valuenamepos - start - 1);
primary = primary.substr(0, start);
- if (primary == "HKEY_CURRENT_USER")
- {
+ if (primary == "HKEY_CURRENT_USER") {
primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
+ }
+ if (primary == "HKEY_CURRENT_CONFIG") {
primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
+ }
+ if (primary == "HKEY_CLASSES_ROOT") {
primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
+ }
+ if (primary == "HKEY_LOCAL_MACHINE") {
primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
+ }
+ if (primary == "HKEY_USERS") {
primaryKey = HKEY_USERS;
- }
+ }
return true;
}
@@ -745,69 +899,56 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode,
SystemTools::KeyWOW64 view)
{
// only add the modes when on a system that supports Wow64.
- static FARPROC wow64p = GetProcAddress(GetModuleHandle("kernel32"),
- "IsWow64Process");
- if(wow64p == NULL)
- {
+ static FARPROC wow64p =
+ GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process");
+ if (wow64p == NULL) {
return mode;
- }
+ }
- if(view == SystemTools::KeyWOW64_32)
- {
+ if (view == SystemTools::KeyWOW64_32) {
return mode | KWSYS_ST_KEY_WOW64_32KEY;
- }
- else if(view == SystemTools::KeyWOW64_64)
- {
+ } else if (view == SystemTools::KeyWOW64_64) {
return mode | KWSYS_ST_KEY_WOW64_64KEY;
- }
+ }
return mode;
}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
-bool
-SystemTools::GetRegistrySubKeys(const char *key,
- kwsys_stl::vector<kwsys_stl::string>& subkeys,
- KeyWOW64 view)
+bool SystemTools::GetRegistrySubKeys(const std::string& key,
+ std::vector<std::string>& subkeys,
+ KeyWOW64 view)
{
HKEY primaryKey = HKEY_CURRENT_USER;
- kwsys_stl::string second;
- kwsys_stl::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
- {
+ std::string second;
+ std::string valuename;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
return false;
- }
+ }
HKEY hKey;
- if(RegOpenKeyEx(primaryKey,
- second.c_str(),
- 0,
- SystemToolsMakeRegistryMode(KEY_READ, view),
- &hKey) != ERROR_SUCCESS)
- {
+ if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0,
+ SystemToolsMakeRegistryMode(KEY_READ, view),
+ &hKey) != ERROR_SUCCESS) {
return false;
- }
- else
- {
- char name[1024];
- DWORD dwNameSize = sizeof(name)/sizeof(name[0]);
+ } else {
+ wchar_t name[1024];
+ DWORD dwNameSize = sizeof(name) / sizeof(name[0]);
DWORD i = 0;
- while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
- {
- subkeys.push_back(name);
+ while (RegEnumKeyW(hKey, i, name, dwNameSize) == ERROR_SUCCESS) {
+ subkeys.push_back(Encoding::ToNarrow(name));
++i;
- }
+ }
RegCloseKey(hKey);
- }
+ }
return true;
}
#else
-bool SystemTools::GetRegistrySubKeys(const char *,
- kwsys_stl::vector<kwsys_stl::string>&,
- KeyWOW64)
+bool SystemTools::GetRegistrySubKeys(const std::string&,
+ std::vector<std::string>&, KeyWOW64)
{
return false;
}
@@ -821,70 +962,53 @@ bool SystemTools::GetRegistrySubKeys(const char *,
// => will return the data of the "Root" value of the key
#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
+bool SystemTools::ReadRegistryValue(const std::string& key, std::string& value,
KeyWOW64 view)
{
bool valueset = false;
HKEY primaryKey = HKEY_CURRENT_USER;
- kwsys_stl::string second;
- kwsys_stl::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
- {
+ std::string second;
+ std::string valuename;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
return false;
- }
+ }
HKEY hKey;
- if(RegOpenKeyEx(primaryKey,
- second.c_str(),
- 0,
- SystemToolsMakeRegistryMode(KEY_READ, view),
- &hKey) != ERROR_SUCCESS)
- {
+ if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0,
+ SystemToolsMakeRegistryMode(KEY_READ, view),
+ &hKey) != ERROR_SUCCESS) {
return false;
- }
- else
- {
+ } else {
DWORD dwType, dwSize;
dwSize = 1023;
- char data[1024];
- if(RegQueryValueEx(hKey,
- (LPTSTR)valuename.c_str(),
- NULL,
- &dwType,
- (BYTE *)data,
- &dwSize) == ERROR_SUCCESS)
- {
- if (dwType == REG_SZ)
- {
- value = data;
+ wchar_t data[1024];
+ if (RegQueryValueExW(hKey, Encoding::ToWide(valuename).c_str(), NULL,
+ &dwType, (BYTE*)data, &dwSize) == ERROR_SUCCESS) {
+ if (dwType == REG_SZ) {
+ value = Encoding::ToNarrow(data);
valueset = true;
- }
- else if (dwType == REG_EXPAND_SZ)
- {
- char expanded[1024];
- DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
- if(ExpandEnvironmentStrings(data, expanded, dwExpandedSize))
- {
- value = expanded;
+ } else if (dwType == REG_EXPAND_SZ) {
+ wchar_t expanded[1024];
+ DWORD dwExpandedSize = sizeof(expanded) / sizeof(expanded[0]);
+ if (ExpandEnvironmentStringsW(data, expanded, dwExpandedSize)) {
+ value = Encoding::ToNarrow(expanded);
valueset = true;
- }
}
}
+ }
RegCloseKey(hKey);
- }
+ }
return valueset;
}
#else
-bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
- KeyWOW64)
+bool SystemTools::ReadRegistryValue(const std::string&, std::string&, KeyWOW64)
{
return false;
}
#endif
-
// Write a registry value.
// Example :
// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
@@ -893,46 +1017,38 @@ bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
// => will set the data of the "Root" value of the key
#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::WriteRegistryValue(const char *key, const char *value,
- KeyWOW64 view)
+bool SystemTools::WriteRegistryValue(const std::string& key,
+ const std::string& value, KeyWOW64 view)
{
HKEY primaryKey = HKEY_CURRENT_USER;
- kwsys_stl::string second;
- kwsys_stl::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
- {
+ std::string second;
+ std::string valuename;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
return false;
- }
+ }
HKEY hKey;
DWORD dwDummy;
- char lpClass[] = "";
- if(RegCreateKeyEx(primaryKey,
- second.c_str(),
- 0,
- lpClass,
- REG_OPTION_NON_VOLATILE,
- SystemToolsMakeRegistryMode(KEY_WRITE, view),
- NULL,
- &hKey,
- &dwDummy) != ERROR_SUCCESS)
- {
+ wchar_t lpClass[] = L"";
+ if (RegCreateKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, lpClass,
+ REG_OPTION_NON_VOLATILE,
+ SystemToolsMakeRegistryMode(KEY_WRITE, view), NULL,
+ &hKey, &dwDummy) != ERROR_SUCCESS) {
return false;
- }
+ }
- if(RegSetValueEx(hKey,
- (LPTSTR)valuename.c_str(),
- 0,
- REG_SZ,
- (CONST BYTE *)value,
- (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
- {
+ std::wstring wvalue = Encoding::ToWide(value);
+ if (RegSetValueExW(hKey, Encoding::ToWide(valuename).c_str(), 0, REG_SZ,
+ (CONST BYTE*)wvalue.c_str(),
+ (DWORD)(sizeof(wchar_t) * (wvalue.size() + 1))) ==
+ ERROR_SUCCESS) {
return true;
- }
+ }
return false;
}
#else
-bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
+bool SystemTools::WriteRegistryValue(const std::string&, const std::string&,
+ KeyWOW64)
{
return false;
}
@@ -946,236 +1062,304 @@ bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
// => will delete the data of the "Root" value of the key
#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
+bool SystemTools::DeleteRegistryValue(const std::string& key, KeyWOW64 view)
{
HKEY primaryKey = HKEY_CURRENT_USER;
- kwsys_stl::string second;
- kwsys_stl::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
- {
+ std::string second;
+ std::string valuename;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
return false;
- }
+ }
HKEY hKey;
- if(RegOpenKeyEx(primaryKey,
- second.c_str(),
- 0,
- SystemToolsMakeRegistryMode(KEY_WRITE, view),
- &hKey) != ERROR_SUCCESS)
- {
+ if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0,
+ SystemToolsMakeRegistryMode(KEY_WRITE, view),
+ &hKey) != ERROR_SUCCESS) {
return false;
- }
- else
- {
- if(RegDeleteValue(hKey,
- (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
- {
+ } else {
+ if (RegDeleteValue(hKey, (LPTSTR)valuename.c_str()) == ERROR_SUCCESS) {
RegCloseKey(hKey);
return true;
- }
}
+ }
return false;
}
#else
-bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64)
+bool SystemTools::DeleteRegistryValue(const std::string&, KeyWOW64)
{
return false;
}
#endif
-bool SystemTools::SameFile(const char* file1, const char* file2)
+bool SystemTools::SameFile(const std::string& file1, const std::string& file2)
{
#ifdef _WIN32
HANDLE hFile1, hFile2;
- hFile1 = CreateFile( file1,
- GENERIC_READ,
- FILE_SHARE_READ ,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- NULL
- );
- hFile2 = CreateFile( file2,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- NULL
- );
- if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
- {
- if(hFile1 != INVALID_HANDLE_VALUE)
- {
+ hFile1 =
+ CreateFileW(Encoding::ToWide(file1).c_str(), GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ hFile2 =
+ CreateFileW(Encoding::ToWide(file2).c_str(), GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE) {
+ if (hFile1 != INVALID_HANDLE_VALUE) {
CloseHandle(hFile1);
- }
- if(hFile2 != INVALID_HANDLE_VALUE)
- {
+ }
+ if (hFile2 != INVALID_HANDLE_VALUE) {
CloseHandle(hFile2);
- }
- return false;
}
+ return false;
+ }
- BY_HANDLE_FILE_INFORMATION fiBuf1;
- BY_HANDLE_FILE_INFORMATION fiBuf2;
- GetFileInformationByHandle( hFile1, &fiBuf1 );
- GetFileInformationByHandle( hFile2, &fiBuf2 );
- CloseHandle(hFile1);
- CloseHandle(hFile2);
- return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
- fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
- fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
+ BY_HANDLE_FILE_INFORMATION fiBuf1;
+ BY_HANDLE_FILE_INFORMATION fiBuf2;
+ GetFileInformationByHandle(hFile1, &fiBuf1);
+ GetFileInformationByHandle(hFile2, &fiBuf2);
+ CloseHandle(hFile1);
+ CloseHandle(hFile2);
+ return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
+ fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
+ fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
#else
struct stat fileStat1, fileStat2;
- if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
- {
+ if (stat(file1.c_str(), &fileStat1) == 0 &&
+ stat(file2.c_str(), &fileStat2) == 0) {
// see if the files are the same file
// check the device inode and size
- if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
- memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
- fileStat2.st_size == fileStat1.st_size
- )
- {
+ if (memcmp(&fileStat2.st_dev, &fileStat1.st_dev,
+ sizeof(fileStat1.st_dev)) == 0 &&
+ memcmp(&fileStat2.st_ino, &fileStat1.st_ino,
+ sizeof(fileStat1.st_ino)) == 0 &&
+ fileStat2.st_size == fileStat1.st_size) {
return true;
- }
}
+ }
return false;
#endif
}
-//----------------------------------------------------------------------------
-#if defined(_WIN32) || defined(__CYGWIN__)
-static bool WindowsFileExists(const char* filename)
+bool SystemTools::PathExists(const std::string& path)
{
- WIN32_FILE_ATTRIBUTE_DATA fd;
- return GetFileAttributesExA(filename, GetFileExInfoStandard, &fd) != 0;
-}
+ if (path.empty()) {
+ return false;
+ }
+#if defined(__CYGWIN__)
+ // Convert path to native windows path if possible.
+ char winpath[MAX_PATH];
+ if (SystemTools::PathCygwinToWin32(path.c_str(), winpath)) {
+ return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES);
+ }
+ struct stat st;
+ return lstat(path.c_str(), &st) == 0;
+#elif defined(_WIN32)
+ return (GetFileAttributesW(Encoding::ToWindowsExtendedPath(path).c_str()) !=
+ INVALID_FILE_ATTRIBUTES);
+#else
+ struct stat st;
+ return lstat(path.c_str(), &st) == 0;
#endif
+}
-//----------------------------------------------------------------------------
bool SystemTools::FileExists(const char* filename)
{
- if(!(filename && *filename))
- {
+ if (!filename) {
return false;
- }
+ }
+ return SystemTools::FileExists(std::string(filename));
+}
+
+bool SystemTools::FileExists(const std::string& filename)
+{
+ if (filename.empty()) {
+ return false;
+ }
#if defined(__CYGWIN__)
// Convert filename to native windows path if possible.
char winpath[MAX_PATH];
- if(SystemTools::PathCygwinToWin32(filename, winpath))
- {
- return WindowsFileExists(winpath);
- }
- return access(filename, R_OK) == 0;
+ if (SystemTools::PathCygwinToWin32(filename.c_str(), winpath)) {
+ return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES);
+ }
+ return access(filename.c_str(), R_OK) == 0;
#elif defined(_WIN32)
- return WindowsFileExists(filename);
+ return (
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()) !=
+ INVALID_FILE_ATTRIBUTES);
+#else
+// SCO OpenServer 5.0.7/3.2's command has 711 permission.
+#if defined(_SCO_DS)
+ return access(filename.c_str(), F_OK) == 0;
#else
- return access(filename, R_OK) == 0;
+ return access(filename.c_str(), R_OK) == 0;
+#endif
#endif
}
-//----------------------------------------------------------------------------
bool SystemTools::FileExists(const char* filename, bool isFile)
{
- if(SystemTools::FileExists(filename))
- {
+ if (!filename) {
+ return false;
+ }
+ return SystemTools::FileExists(std::string(filename), isFile);
+}
+
+bool SystemTools::FileExists(const std::string& filename, bool isFile)
+{
+ if (SystemTools::FileExists(filename)) {
// If isFile is set return not FileIsDirectory,
// so this will only be true if it is a file
return !isFile || !SystemTools::FileIsDirectory(filename);
- }
+ }
return false;
}
-//----------------------------------------------------------------------------
+bool SystemTools::TestFileAccess(const char* filename,
+ TestFilePermissions permissions)
+{
+ if (!filename) {
+ return false;
+ }
+ return SystemTools::TestFileAccess(std::string(filename), permissions);
+}
+
+bool SystemTools::TestFileAccess(const std::string& filename,
+ TestFilePermissions permissions)
+{
+ if (filename.empty()) {
+ return false;
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // If execute set, change to read permission (all files on Windows
+ // are executable if they are readable). The CRT will always fail
+ // if you pass an execute bit.
+ if (permissions & TEST_FILE_EXECUTE) {
+ permissions &= ~TEST_FILE_EXECUTE;
+ permissions |= TEST_FILE_READ;
+ }
+ return _waccess(Encoding::ToWindowsExtendedPath(filename).c_str(),
+ permissions) == 0;
+#else
+ return access(filename.c_str(), permissions) == 0;
+#endif
+}
+
+int SystemTools::Stat(const char* path, SystemTools::Stat_t* buf)
+{
+ if (!path) {
+ errno = EFAULT;
+ return -1;
+ }
+ return SystemTools::Stat(std::string(path), buf);
+}
+
+int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
+{
+ if (path.empty()) {
+ errno = ENOENT;
+ return -1;
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Ideally we should use Encoding::ToWindowsExtendedPath to support
+ // long paths, but _wstat64 rejects paths with '?' in them, thinking
+ // they are wildcards.
+ std::wstring const& wpath = Encoding::ToWide(path);
+#if defined(__BORLANDC__)
+ return _wstati64(wpath.c_str(), buf);
+#else
+ return _wstat64(wpath.c_str(), buf);
+#endif
+#else
+ return stat(path.c_str(), buf);
+#endif
+}
+
#ifdef __CYGWIN__
-bool SystemTools::PathCygwinToWin32(const char *path, char *win32_path)
+bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path)
{
SystemToolsTranslationMap::iterator i =
SystemTools::Cyg2Win32Map->find(path);
- if (i != SystemTools::Cyg2Win32Map->end())
- {
+ if (i != SystemTools::Cyg2Win32Map->end()) {
strncpy(win32_path, i->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;
}
- else
- {
- cygwin_conv_to_win32_path(path, win32_path);
SystemToolsTranslationMap::value_type entry(path, win32_path);
SystemTools::Cyg2Win32Map->insert(entry);
- }
+ }
return win32_path[0] != 0;
}
#endif
-bool SystemTools::Touch(const char* filename, bool create)
+bool SystemTools::Touch(const std::string& filename, bool create)
{
- if(create && !SystemTools::FileExists(filename))
- {
- FILE* file = fopen(filename, "a+b");
- if(file)
- {
- fclose(file);
- return true;
+ if (!SystemTools::PathExists(filename)) {
+ if (create) {
+ FILE* file = Fopen(filename, "a+b");
+ if (file) {
+ fclose(file);
+ return true;
}
- return false;
+ return false;
+ } else {
+ return true;
}
+ }
#if defined(_WIN32) && !defined(__CYGWIN__)
- HANDLE h = CreateFile(filename, FILE_WRITE_ATTRIBUTES,
- FILE_SHARE_WRITE, 0, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, 0);
- if(!h)
- {
+ HANDLE h = CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+ FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+ if (!h) {
return false;
- }
+ }
FILETIME mtime;
GetSystemTimeAsFileTime(&mtime);
- if(!SetFileTime(h, 0, 0, &mtime))
- {
+ if (!SetFileTime(h, 0, 0, &mtime)) {
CloseHandle(h);
return false;
- }
+ }
CloseHandle(h);
#elif KWSYS_CXX_HAS_UTIMENSAT
- struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}};
- if(utimensat(AT_FDCWD, filename, times, 0) < 0)
- {
+ 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, &st) < 0)
- {
+ if (stat(filename.c_str(), &st) < 0) {
return false;
- }
+ }
struct timeval mtime;
gettimeofday(&mtime, 0);
-# if KWSYS_CXX_HAS_UTIMES
- struct timeval times[2] =
- {
-# if KWSYS_STAT_HAS_ST_MTIM
- {st.st_atim.tv_sec, st.st_atim.tv_nsec/1000}, /* tv_sec, tv_usec */
-# else
- {st.st_atime, 0},
-# endif
- mtime
- };
- if(utimes(filename, times) < 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) {
return false;
- }
-# else
- struct utimbuf times = {st.st_atime, mtime.tv_sec};
- if(utime(filename, &times) < 0)
- {
+ }
+#else
+ struct utimbuf times = { st.st_atime, mtime.tv_sec };
+ if (utime(filename.c_str(), &times) < 0) {
return false;
- }
-# endif
+ }
+#endif
#endif
return true;
}
-bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
+bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
int* result)
{
// Default to same time.
@@ -1183,56 +1367,55 @@ bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
#if !defined(_WIN32) || defined(__CYGWIN__)
// POSIX version. Use stat function to get file modification time.
struct stat s1;
- if(stat(f1, &s1) != 0)
- {
+ if (stat(f1.c_str(), &s1) != 0) {
return false;
- }
+ }
struct stat s2;
- if(stat(f2, &s2) != 0)
- {
+ if (stat(f2.c_str(), &s2) != 0) {
return false;
- }
-# if KWSYS_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)
- {
+ if (s1.st_mtim.tv_sec < s2.st_mtim.tv_sec) {
*result = -1;
- }
- else if(s1.st_mtim.tv_sec > s2.st_mtim.tv_sec)
- {
+ } else if (s1.st_mtim.tv_sec > s2.st_mtim.tv_sec) {
*result = 1;
- }
- else if(s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec)
- {
+ } else if (s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec) {
*result = -1;
- }
- else if(s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec)
- {
+ } else if (s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec) {
*result = 1;
- }
-# else
+ }
+#elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
+ // Compare using nanosecond resolution.
+ if (s1.st_mtimespec.tv_sec < s2.st_mtimespec.tv_sec) {
+ *result = -1;
+ } else if (s1.st_mtimespec.tv_sec > s2.st_mtimespec.tv_sec) {
+ *result = 1;
+ } else if (s1.st_mtimespec.tv_nsec < s2.st_mtimespec.tv_nsec) {
+ *result = -1;
+ } else if (s1.st_mtimespec.tv_nsec > s2.st_mtimespec.tv_nsec) {
+ *result = 1;
+ }
+#else
// Compare using 1 second resolution.
- if(s1.st_mtime < s2.st_mtime)
- {
+ if (s1.st_mtime < s2.st_mtime) {
*result = -1;
- }
- else if(s1.st_mtime > s2.st_mtime)
- {
+ } 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;
WIN32_FILE_ATTRIBUTE_DATA f2d;
- if(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d))
- {
+ if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(),
+ GetFileExInfoStandard, &f1d)) {
return false;
- }
- if(!GetFileAttributesEx(f2, GetFileExInfoStandard, &f2d))
- {
+ }
+ if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(),
+ GetFileExInfoStandard, &f2d)) {
return false;
- }
+ }
// Compare the file times using resolution provided by system call.
*result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime);
@@ -1240,32 +1423,28 @@ bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
return true;
}
-
// Return a capitalized string (i.e the first letter is uppercased, all other
// are lowercased)
-kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
+std::string SystemTools::Capitalized(const std::string& s)
{
- kwsys_stl::string n;
- if(s.size() == 0)
- {
+ std::string n;
+ if (s.empty()) {
return n;
- }
+ }
n.resize(s.size());
- n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
- for (size_t i = 1; i < s.size(); i++)
- {
- n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
- }
+ n[0] = static_cast<std::string::value_type>(toupper(s[0]));
+ for (size_t i = 1; i < s.size(); i++) {
+ n[i] = static_cast<std::string::value_type>(tolower(s[i]));
+ }
return n;
}
// Return capitalized words
-kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
+std::string SystemTools::CapitalizedWords(const std::string& s)
{
- kwsys_stl::string n(s);
- for (size_t i = 0; i < s.size(); i++)
- {
-#if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
+ std::string n(s);
+ for (size_t i = 0; i < s.size(); i++) {
+#if defined(_MSC_VER) && defined(_MT) && defined(_DEBUG)
// MS has an assert that will fail if s[i] < 0; setting
// LC_CTYPE using setlocale() does *not* help. Painful.
if ((int)s[i] >= 0 && isalpha(s[i]) &&
@@ -1273,20 +1452,19 @@ kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
#else
if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
#endif
- {
- n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
- }
+ {
+ n[i] = static_cast<std::string::value_type>(toupper(s[i]));
}
+ }
return n;
}
// Return uncapitalized words
-kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
+std::string SystemTools::UnCapitalizedWords(const std::string& s)
{
- kwsys_stl::string n(s);
- for (size_t i = 0; i < s.size(); i++)
- {
-#if defined(_MSC_VER) && defined (_MT) && defined (_DEBUG)
+ std::string n(s);
+ for (size_t i = 0; i < s.size(); i++) {
+#if defined(_MSC_VER) && defined(_MT) && defined(_DEBUG)
// MS has an assert that will fail if s[i] < 0; setting
// LC_CTYPE using setlocale() does *not* help. Painful.
if ((int)s[i] >= 0 && isalpha(s[i]) &&
@@ -1294,77 +1472,66 @@ kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
#else
if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
#endif
- {
- n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
- }
+ {
+ n[i] = static_cast<std::string::value_type>(tolower(s[i]));
}
+ }
return n;
}
// only works for words with at least two letters
-kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords(
- const kwsys_stl::string& s)
+std::string SystemTools::AddSpaceBetweenCapitalizedWords(const std::string& s)
{
- kwsys_stl::string n;
- if (s.size())
- {
+ std::string n;
+ if (!s.empty()) {
n.reserve(s.size());
n += s[0];
- for (size_t i = 1; i < s.size(); i++)
- {
- if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1]))
- {
+ for (size_t i = 1; i < s.size(); i++) {
+ if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1])) {
n += ' ';
- }
- n += s[i];
}
+ n += s[i];
}
+ }
return n;
}
char* SystemTools::AppendStrings(const char* str1, const char* str2)
{
- if (!str1)
- {
+ if (!str1) {
return SystemTools::DuplicateString(str2);
- }
- if (!str2)
- {
+ }
+ if (!str2) {
return SystemTools::DuplicateString(str1);
- }
+ }
size_t len1 = strlen(str1);
- char *newstr = new char[len1 + strlen(str2) + 1];
- if (!newstr)
- {
+ char* newstr = new char[len1 + strlen(str2) + 1];
+ if (!newstr) {
return 0;
- }
+ }
strcpy(newstr, str1);
strcat(newstr + len1, str2);
return newstr;
}
-char* SystemTools::AppendStrings(
- const char* str1, const char* str2, const char* str3)
+char* SystemTools::AppendStrings(const char* str1, const char* str2,
+ const char* str3)
{
- if (!str1)
- {
+ if (!str1) {
return SystemTools::AppendStrings(str2, str3);
- }
- if (!str2)
- {
+ }
+ if (!str2) {
return SystemTools::AppendStrings(str1, str3);
- }
- if (!str3)
- {
+ }
+ if (!str3) {
return SystemTools::AppendStrings(str1, str2);
- }
+ }
size_t len1 = strlen(str1), len2 = strlen(str2);
- char *newstr = new char[len1 + len2 + strlen(str3) + 1];
- if (!newstr)
- {
+ char* newstr = new char[len1 + len2 + strlen(str3) + 1];
+ if (!newstr) {
return 0;
- }
+ }
strcpy(newstr, str1);
strcat(newstr + len1, str2);
strcat(newstr + len1 + len2, str3);
@@ -1372,26 +1539,24 @@ char* SystemTools::AppendStrings(
}
// Return a lower case string
-kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
+std::string SystemTools::LowerCase(const std::string& s)
{
- kwsys_stl::string n;
+ std::string n;
n.resize(s.size());
- for (size_t i = 0; i < s.size(); i++)
- {
- n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
- }
+ for (size_t i = 0; i < s.size(); i++) {
+ n[i] = static_cast<std::string::value_type>(tolower(s[i]));
+ }
return n;
}
// Return a lower case string
-kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s)
+std::string SystemTools::UpperCase(const std::string& s)
{
- kwsys_stl::string n;
+ std::string n;
n.resize(s.size());
- for (size_t i = 0; i < s.size(); i++)
- {
- n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
- }
+ for (size_t i = 0; i < s.size(); i++) {
+ n[i] = static_cast<std::string::value_type>(toupper(s[i]));
+ }
return n;
}
@@ -1400,42 +1565,35 @@ size_t SystemTools::CountChar(const char* str, char c)
{
size_t count = 0;
- if (str)
- {
- while (*str)
- {
- if (*str == c)
- {
+ if (str) {
+ while (*str) {
+ if (*str == c) {
++count;
- }
- ++str;
}
+ ++str;
}
+ }
return count;
}
// Remove chars in string
-char* SystemTools::RemoveChars(const char* str, const char *toremove)
+char* SystemTools::RemoveChars(const char* str, const char* toremove)
{
- if (!str)
- {
+ if (!str) {
return NULL;
- }
- char *clean_str = new char [strlen(str) + 1];
- char *ptr = clean_str;
- while (*str)
- {
- const char *str2 = toremove;
- while (*str2 && *str != *str2)
- {
+ }
+ char* clean_str = new char[strlen(str) + 1];
+ char* ptr = clean_str;
+ while (*str) {
+ const char* str2 = toremove;
+ while (*str2 && *str != *str2) {
++str2;
- }
- if (!*str2)
- {
+ }
+ if (!*str2) {
*ptr++ = *str;
- }
- ++str;
}
+ ++str;
+ }
*ptr = '\0';
return clean_str;
}
@@ -1443,89 +1601,100 @@ char* SystemTools::RemoveChars(const char* str, const char *toremove)
// Remove chars in string
char* SystemTools::RemoveCharsButUpperHex(const char* str)
{
- if (!str)
- {
+ if (!str) {
return 0;
- }
- char *clean_str = new char [strlen(str) + 1];
- char *ptr = clean_str;
- while (*str)
- {
- if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'F'))
- {
+ }
+ char* clean_str = new char[strlen(str) + 1];
+ char* ptr = clean_str;
+ while (*str) {
+ if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'F')) {
*ptr++ = *str;
- }
- ++str;
}
+ ++str;
+ }
*ptr = '\0';
return clean_str;
}
// Replace chars in string
-char* SystemTools::ReplaceChars(char* str, const char *toreplace, char replacement)
-{
- if (str)
- {
- char *ptr = str;
- while (*ptr)
- {
- const char *ptr2 = toreplace;
- while (*ptr2)
- {
- if (*ptr == *ptr2)
- {
+char* SystemTools::ReplaceChars(char* str, const char* toreplace,
+ char replacement)
+{
+ if (str) {
+ char* ptr = str;
+ while (*ptr) {
+ const char* ptr2 = toreplace;
+ while (*ptr2) {
+ if (*ptr == *ptr2) {
*ptr = replacement;
- }
- ++ptr2;
}
- ++ptr;
+ ++ptr2;
}
+ ++ptr;
}
+ }
return str;
}
// Returns if string starts with another string
bool SystemTools::StringStartsWith(const char* str1, const char* str2)
{
- if (!str1 || !str2)
- {
+ if (!str1 || !str2) {
return false;
- }
+ }
size_t len1 = strlen(str1), len2 = strlen(str2);
return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false;
}
+// Returns if string starts with another string
+bool SystemTools::StringStartsWith(const std::string& str1, const char* str2)
+{
+ if (!str2) {
+ return false;
+ }
+ size_t len1 = str1.size(), len2 = strlen(str2);
+ return len1 >= len2 && !strncmp(str1.c_str(), str2, len2) ? true : false;
+}
+
// Returns if string ends with another string
bool SystemTools::StringEndsWith(const char* str1, const char* str2)
{
- if (!str1 || !str2)
- {
+ if (!str1 || !str2) {
return false;
- }
+ }
size_t len1 = strlen(str1), len2 = strlen(str2);
- return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false;
+ return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true
+ : false;
+}
+
+// Returns if string ends with another string
+bool SystemTools::StringEndsWith(const std::string& str1, const char* str2)
+{
+ if (!str2) {
+ return false;
+ }
+ size_t len1 = str1.size(), len2 = strlen(str2);
+ return len1 >= len2 && !strncmp(str1.c_str() + (len1 - len2), str2, len2)
+ ? true
+ : false;
}
// Returns a pointer to the last occurence of str2 in str1
const char* SystemTools::FindLastString(const char* str1, const char* str2)
{
- if (!str1 || !str2)
- {
+ if (!str1 || !str2) {
return NULL;
- }
+ }
size_t len1 = strlen(str1), len2 = strlen(str2);
- if (len1 >= len2)
- {
- const char *ptr = str1 + len1 - len2;
- do
- {
- if (!strncmp(ptr, str2, len2))
- {
+ if (len1 >= len2) {
+ const char* ptr = str1 + len1 - len2;
+ do {
+ if (!strncmp(ptr, str2, len2)) {
return ptr;
- }
- } while (ptr-- != str1);
- }
+ }
+ } while (ptr-- != str1);
+ }
return NULL;
}
@@ -1533,81 +1702,70 @@ const char* SystemTools::FindLastString(const char* str1, const char* str2)
// Duplicate string
char* SystemTools::DuplicateString(const char* str)
{
- if (str)
- {
- char *newstr = new char [strlen(str) + 1];
+ if (str) {
+ char* newstr = new char[strlen(str) + 1];
return strcpy(newstr, str);
- }
+ }
return NULL;
}
// Return a cropped string
-kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
- size_t max_len)
+std::string SystemTools::CropString(const std::string& s, size_t max_len)
{
- if (!s.size() || max_len == 0 || max_len >= s.size())
- {
+ if (!s.size() || max_len == 0 || max_len >= s.size()) {
return s;
- }
+ }
- kwsys_stl::string n;
+ std::string n;
n.reserve(max_len);
size_t middle = max_len / 2;
n += s.substr(0, middle);
- n += s.substr(s.size() - (max_len - middle), kwsys_stl::string::npos);
+ n += s.substr(s.size() - (max_len - middle));
- if (max_len > 2)
- {
+ if (max_len > 2) {
n[middle] = '.';
- if (max_len > 3)
- {
+ if (max_len > 3) {
n[middle - 1] = '.';
- if (max_len > 4)
- {
+ if (max_len > 4) {
n[middle + 1] = '.';
- }
}
}
+ }
return n;
}
-//----------------------------------------------------------------------------
-kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
+std::vector<kwsys::String> SystemTools::SplitString(const std::string& p,
+ char sep, bool isPath)
{
- kwsys_stl::string path = p;
- kwsys_stl::vector<kwsys::String> paths;
- if(path.empty())
- {
+ std::string path = p;
+ std::vector<kwsys::String> paths;
+ if (path.empty()) {
return paths;
- }
- if(isPath && path[0] == '/')
- {
+ }
+ if (isPath && path[0] == '/') {
path.erase(path.begin());
paths.push_back("/");
- }
- kwsys_stl::string::size_type pos1 = 0;
- kwsys_stl::string::size_type pos2 = path.find(sep, pos1+1);
- while(pos2 != kwsys_stl::string::npos)
- {
- paths.push_back(path.substr(pos1, pos2-pos1));
- pos1 = pos2+1;
- pos2 = path.find(sep, pos1+1);
- }
- paths.push_back(path.substr(pos1, pos2-pos1));
+ }
+ std::string::size_type pos1 = 0;
+ std::string::size_type pos2 = path.find(sep, pos1 + 1);
+ while (pos2 != std::string::npos) {
+ paths.push_back(path.substr(pos1, pos2 - pos1));
+ pos1 = pos2 + 1;
+ pos2 = path.find(sep, pos1 + 1);
+ }
+ paths.push_back(path.substr(pos1, pos2 - pos1));
return paths;
}
-//----------------------------------------------------------------------------
-int SystemTools::EstimateFormatLength(const char *format, va_list ap)
+int SystemTools::EstimateFormatLength(const char* format, va_list ap)
{
- if (!format)
- {
+ if (!format) {
return 0;
- }
+ }
// Quick-hack attempt at estimating the length of the string.
// Should never under-estimate.
@@ -1619,118 +1777,98 @@ int SystemTools::EstimateFormatLength(const char *format, va_list ap)
// Increase the length for every argument in the format.
const char* cur = format;
- while(*cur)
- {
- if(*cur++ == '%')
- {
+ while (*cur) {
+ if (*cur++ == '%') {
// Skip "%%" since it doesn't correspond to a va_arg.
- if(*cur != '%')
- {
- while(!int(isalpha(*cur)))
- {
+ if (*cur != '%') {
+ while (!int(isalpha(*cur))) {
++cur;
- }
- switch (*cur)
- {
- case 's':
- {
- // Check the length of the string.
- char* s = va_arg(ap, char*);
- if(s)
- {
- length += strlen(s);
+ }
+ switch (*cur) {
+ case 's': {
+ // Check the length of the string.
+ char* s = va_arg(ap, char*);
+ if (s) {
+ length += strlen(s);
}
} break;
case 'e':
case 'f':
- case 'g':
- {
- // Assume the argument contributes no more than 64 characters.
- length += 64;
+ case 'g': {
+ // Assume the argument contributes no more than 64 characters.
+ length += 64;
- // Eat the argument.
- static_cast<void>(va_arg(ap, double));
+ // Eat the argument.
+ static_cast<void>(va_arg(ap, double));
} break;
- default:
- {
- // Assume the argument contributes no more than 64 characters.
- length += 64;
+ default: {
+ // Assume the argument contributes no more than 64 characters.
+ length += 64;
- // Eat the argument.
- static_cast<void>(va_arg(ap, int));
+ // Eat the argument.
+ static_cast<void>(va_arg(ap, int));
} break;
- }
}
+ }
// Move past the characters just tested.
++cur;
- }
}
+ }
return static_cast<int>(length);
}
-kwsys_stl::string SystemTools::EscapeChars(
- const char *str,
- const char *chars_to_escape,
- char escape_char)
+std::string SystemTools::EscapeChars(const char* str,
+ const char* chars_to_escape,
+ char escape_char)
{
- kwsys_stl::string n;
- if (str)
- {
- if (!chars_to_escape || !*chars_to_escape)
- {
+ std::string n;
+ if (str) {
+ if (!chars_to_escape || !*chars_to_escape) {
n.append(str);
- }
- else
- {
+ } else {
n.reserve(strlen(str));
- while (*str)
- {
- const char *ptr = chars_to_escape;
- while (*ptr)
- {
- if (*str == *ptr)
- {
+ while (*str) {
+ const char* ptr = chars_to_escape;
+ while (*ptr) {
+ if (*str == *ptr) {
n += escape_char;
break;
- }
- ++ptr;
}
+ ++ptr;
+ }
n += *str;
++str;
- }
}
}
+ }
return n;
}
#ifdef __VMS
-static void ConvertVMSToUnix(kwsys_stl::string& path)
+static void ConvertVMSToUnix(std::string& path)
{
- kwsys_stl::string::size_type rootEnd = path.find(":[");
- kwsys_stl::string::size_type pathEnd = path.find("]");
- if(rootEnd != path.npos)
- {
- kwsys_stl::string root = path.substr(0, rootEnd);
- kwsys_stl::string pathPart = path.substr(rootEnd+2, pathEnd - rootEnd-2);
+ std::string::size_type rootEnd = path.find(":[");
+ std::string::size_type pathEnd = path.find("]");
+ if (rootEnd != std::string::npos) {
+ std::string root = path.substr(0, rootEnd);
+ std::string pathPart = path.substr(rootEnd + 2, pathEnd - rootEnd - 2);
const char* pathCString = pathPart.c_str();
const char* pos0 = pathCString;
- for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
- {
- if ( *pos0 == '.' )
- {
+ for (std::string::size_type pos = 0; *pos0; ++pos) {
+ if (*pos0 == '.') {
pathPart[pos] = '/';
- }
- pos0 ++;
}
- path = "/"+ root + "/" + pathPart;
+ pos0++;
}
+ path = "/" + root + "/" + pathPart;
+ }
}
#endif
// convert windows slashes to unix slashes
-void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
+void SystemTools::ConvertToUnixSlashes(std::string& path)
{
const char* pathCString = path.c_str();
bool hasDoubleSlash = false;
@@ -1738,110 +1876,104 @@ void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
ConvertVMSToUnix(path);
#else
const char* pos0 = pathCString;
- const char* pos1 = pathCString+1;
- for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos )
- {
+ 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 == '\\' && *pos1 != ' ') {
path[pos] = '/';
- }
+ }
// Also, reuse the loop to check for slash followed by another slash
- if (*pos1 == '/' && *(pos1+1) == '/' && !hasDoubleSlash)
- {
+ if (*pos1 == '/' && *(pos1 + 1) == '/' && !hasDoubleSlash) {
#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)
- {
+ if (pos > 0) {
hasDoubleSlash = true;
- }
+ }
#else
hasDoubleSlash = true;
#endif
- }
-
- pos0 ++;
- pos1 ++;
}
- if ( hasDoubleSlash )
- {
+ pos0++;
+ pos1++;
+ }
+
+ if (hasDoubleSlash) {
SystemTools::ReplaceString(path, "//", "/");
- }
+ }
#endif
// remove any trailing slash
- if(!path.empty())
- {
+ 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'))
- {
- const char* homeEnv = SystemTools::GetEnv("HOME");
- if (homeEnv)
- {
- path.replace(0,1,homeEnv);
- }
+ 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] == '~')
- {
- kwsys_stl::string::size_type idx = path.find_first_of("/\0");
- kwsys_stl::string user = path.substr(1, idx-1);
+ 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)
- {
+ 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();
- if(path.size() > 1 && *(pathCString+(path.size()-1)) == '/')
- {
+ size_t size = path.size();
+ if (size > 1 && *path.rbegin() == '/') {
// if it is c:/ then do not remove the trailing slash
- if(!((path.size() == 3 && pathCString[1] == ':')))
- {
- path = path.substr(0, path.size()-1);
- }
+ if (!((size == 3 && pathCString[1] == ':'))) {
+ path.resize(size - 1);
}
}
+ }
+}
+
+#ifdef _WIN32
+std::wstring SystemTools::ConvertToWindowsExtendedPath(
+ const std::string& source)
+{
+ return Encoding::ToWindowsExtendedPath(source);
}
+#endif
// change // to /, and escape any spaces in the path
-kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
+std::string SystemTools::ConvertToUnixOutputPath(const std::string& path)
{
- kwsys_stl::string ret = path;
+ std::string ret = path;
// remove // except at the beginning might be a cygwin drive
- kwsys_stl::string::size_type pos=1;
- while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
- {
+ std::string::size_type pos = 1;
+ while ((pos = ret.find("//", pos)) != std::string::npos) {
ret.erase(pos, 1);
- }
+ }
// escape spaces and () in the path
- if(ret.find_first_of(" ") != kwsys_stl::string::npos)
- {
- kwsys_stl::string result = "";
+ if (ret.find_first_of(" ") != std::string::npos) {
+ 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
- if((*ch == ' ') && lastch != '\\')
- {
+ for (const char* ch = ret.c_str(); *ch != '\0'; ++ch) {
+ // if it is already escaped then don't try to escape it again
+ if ((*ch == ' ') && lastch != '\\') {
result += '\\';
- }
+ }
result += *ch;
lastch = *ch;
- }
- ret = result;
}
+ ret = result;
+ }
return ret;
}
-kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
+std::string SystemTools::ConvertToOutputPath(const std::string& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
return SystemTools::ConvertToWindowsOutputPath(path);
@@ -1851,391 +1983,403 @@ kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
}
// remove double slashes not at the start
-kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
+std::string SystemTools::ConvertToWindowsOutputPath(const std::string& path)
{
- kwsys_stl::string ret;
+ std::string ret;
// make it big enough for all of path and double quotes
- ret.reserve(strlen(path)+3);
+ ret.reserve(path.size() + 3);
// put path into the string
- ret.assign(path);
ret = path;
- kwsys_stl::string::size_type pos = 0;
+ std::string::size_type pos = 0;
// first convert all of the slashes
- while((pos = ret.find('/', pos)) != kwsys_stl::string::npos)
- {
+ while ((pos = ret.find('/', pos)) != std::string::npos) {
ret[pos] = '\\';
pos++;
- }
+ }
// check for really small paths
- if(ret.size() < 2)
- {
+ if (ret.size() < 2) {
return ret;
- }
+ }
// now clean up a bit and remove double slashes
// Only if it is not the first position in the path which is a network
// path on windows
pos = 1; // start at position 1
- if(ret[0] == '\"')
- {
- pos = 2; // if the string is already quoted then start at 2
- if(ret.size() < 3)
- {
+ if (ret[0] == '\"') {
+ pos = 2; // if the string is already quoted then start at 2
+ if (ret.size() < 3) {
return ret;
- }
}
- while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos)
- {
+ }
+ while ((pos = ret.find("\\\\", pos)) != std::string::npos) {
ret.erase(pos, 1);
- }
+ }
// now double quote the path if it has spaces in it
// and is not already double quoted
- if(ret.find(' ') != kwsys_stl::string::npos
- && ret[0] != '\"')
- {
- ret.insert(static_cast<kwsys_stl::string::size_type>(0),
- static_cast<kwsys_stl::string::size_type>(1), '\"');
+ if (ret.find(' ') != std::string::npos && ret[0] != '\"') {
+ ret.insert(static_cast<std::string::size_type>(0),
+ static_cast<std::string::size_type>(1), '\"');
ret.append(1, '\"');
- }
+ }
return ret;
}
-bool SystemTools::CopyFileIfDifferent(const char* source,
- const char* destination)
+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))
- {
- kwsys_stl::string new_destination = destination;
+ if (SystemTools::FileIsDirectory(destination)) {
+ std::string new_destination = destination;
SystemTools::ConvertToUnixSlashes(new_destination);
new_destination += '/';
- kwsys_stl::string source_name = source;
+ std::string source_name = source;
new_destination += SystemTools::GetFilenameName(source_name);
- if(SystemTools::FilesDiffer(source, new_destination.c_str()))
- {
+ if (SystemTools::FilesDiffer(source, new_destination)) {
return SystemTools::CopyFileAlways(source, destination);
- }
- else
- {
+ } else {
// the files are the same so the copy is done return
// true
return true;
- }
}
+ }
// source and destination are files so do a copy if they
// are different
- if(SystemTools::FilesDiffer(source, destination))
- {
+ if (SystemTools::FilesDiffer(source, destination)) {
return SystemTools::CopyFileAlways(source, destination);
- }
+ }
// at this point the files must be the same so return true
return true;
}
#define KWSYS_ST_BUFFER 4096
-bool SystemTools::FilesDiffer(const char* source,
- const char* destination)
+bool SystemTools::FilesDiffer(const std::string& source,
+ const std::string& destination)
{
+
+#if defined(_WIN32)
+ WIN32_FILE_ATTRIBUTE_DATA statSource;
+ if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(source).c_str(),
+ GetFileExInfoStandard, &statSource) == 0) {
+ return true;
+ }
+
+ WIN32_FILE_ATTRIBUTE_DATA statDestination;
+ if (GetFileAttributesExW(
+ Encoding::ToWindowsExtendedPath(destination).c_str(),
+ GetFileExInfoStandard, &statDestination) == 0) {
+ return true;
+ }
+
+ if (statSource.nFileSizeHigh != statDestination.nFileSizeHigh ||
+ statSource.nFileSizeLow != statDestination.nFileSizeLow) {
+ return true;
+ }
+
+ if (statSource.nFileSizeHigh == 0 && statSource.nFileSizeLow == 0) {
+ return false;
+ }
+ off_t nleft =
+ ((__int64)statSource.nFileSizeHigh << 32) + statSource.nFileSizeLow;
+
+#else
+
struct stat statSource;
- if (stat(source, &statSource) != 0)
- {
+ if (stat(source.c_str(), &statSource) != 0) {
return true;
- }
+ }
struct stat statDestination;
- if (stat(destination, &statDestination) != 0)
- {
+ if (stat(destination.c_str(), &statDestination) != 0) {
return true;
- }
+ }
- if(statSource.st_size != statDestination.st_size)
- {
+ if (statSource.st_size != statDestination.st_size) {
return true;
- }
+ }
- if(statSource.st_size == 0)
- {
+ if (statSource.st_size == 0) {
return false;
- }
+ }
+ off_t nleft = statSource.st_size;
+#endif
-#if defined(_WIN32) || defined(__CYGWIN__)
- kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
- kwsys_ios::ios::in));
- kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
- kwsys_ios::ios::in));
+#if defined(_WIN32)
+ kwsys::ifstream finSource(source.c_str(), (std::ios::binary | std::ios::in));
+ kwsys::ifstream finDestination(destination.c_str(),
+ (std::ios::binary | std::ios::in));
#else
- kwsys_ios::ifstream finSource(source);
- kwsys_ios::ifstream finDestination(destination);
+ kwsys::ifstream finSource(source.c_str());
+ kwsys::ifstream finDestination(destination.c_str());
#endif
- if(!finSource || !finDestination)
- {
+ if (!finSource || !finDestination) {
return true;
- }
+ }
// Compare the files a block at a time.
char source_buf[KWSYS_ST_BUFFER];
char dest_buf[KWSYS_ST_BUFFER];
- off_t nleft = statSource.st_size;
- while(nleft > 0)
- {
+ while (nleft > 0) {
// Read a block from each file.
- kwsys_ios::streamsize nnext = (nleft > KWSYS_ST_BUFFER)? KWSYS_ST_BUFFER : static_cast<kwsys_ios::streamsize>(nleft);
+ std::streamsize nnext = (nleft > KWSYS_ST_BUFFER)
+ ? KWSYS_ST_BUFFER
+ : static_cast<std::streamsize>(nleft);
finSource.read(source_buf, nnext);
finDestination.read(dest_buf, nnext);
// If either failed to read assume they are different.
- if(static_cast<kwsys_ios::streamsize>(finSource.gcount()) != nnext ||
- static_cast<kwsys_ios::streamsize>(finDestination.gcount()) != nnext)
- {
+ if (static_cast<std::streamsize>(finSource.gcount()) != nnext ||
+ static_cast<std::streamsize>(finDestination.gcount()) != nnext) {
return true;
- }
+ }
// If this block differs the file differs.
- if(memcmp(static_cast<const void*>(source_buf),
- static_cast<const void*>(dest_buf),
- static_cast<size_t>(nnext)) != 0)
- {
+ if (memcmp(static_cast<const void*>(source_buf),
+ static_cast<const void*>(dest_buf),
+ static_cast<size_t>(nnext)) != 0) {
return true;
- }
+ }
// Update the byte count remaining.
nleft -= nnext;
- }
+ }
// No differences found.
return false;
}
-
-//----------------------------------------------------------------------------
/**
* Copy a file named by "source" to the file named by "destination".
*/
-bool SystemTools::CopyFileAlways(const char* source, const char* 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) )
- {
+ if (SystemTools::SameFile(source, destination)) {
return true;
- }
+ }
mode_t perm = 0;
bool perms = SystemTools::GetPermissions(source, perm);
+ std::string real_destination = destination;
- const int bufferSize = 4096;
- char buffer[bufferSize];
+ 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.
+ // If destination is a directory, try to create a file with the same
+ // name as the source in that directory.
- kwsys_stl::string new_destination;
- if(SystemTools::FileExists(destination) &&
- SystemTools::FileIsDirectory(destination))
- {
- new_destination = destination;
- SystemTools::ConvertToUnixSlashes(new_destination);
- new_destination += '/';
- kwsys_stl::string source_name = source;
- new_destination += SystemTools::GetFilenameName(source_name);
- destination = new_destination.c_str();
+ std::string destination_dir;
+ if (SystemTools::FileIsDirectory(destination)) {
+ destination_dir = real_destination;
+ SystemTools::ConvertToUnixSlashes(real_destination);
+ real_destination += '/';
+ std::string source_name = source;
+ real_destination += SystemTools::GetFilenameName(source_name);
+ } else {
+ destination_dir = SystemTools::GetFilenamePath(destination);
}
- // Create destination directory
+ // Create destination directory
- kwsys_stl::string destination_dir = destination;
- destination_dir = SystemTools::GetFilenamePath(destination_dir);
- SystemTools::MakeDirectory(destination_dir.c_str());
+ SystemTools::MakeDirectory(destination_dir);
- // Open files
-
-#if defined(_WIN32) || defined(__CYGWIN__)
- kwsys_ios::ifstream fin(source,
- kwsys_ios::ios::binary | kwsys_ios::ios::in);
+// Open files
+#if defined(_WIN32)
+ kwsys::ifstream fin(
+ Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(),
+ std::ios::in | std::ios::binary);
#else
- kwsys_ios::ifstream fin(source);
+ kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
#endif
- if(!fin)
- {
- return false;
+ 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);
+ // 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) || defined(__CYGWIN__)
- kwsys_ios::ofstream fout(destination,
- kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
+#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_ios::ofstream fout(destination,
- kwsys_ios::ios::out | kwsys_ios::ios::trunc);
+ kwsys::ofstream fout(real_destination.c_str(),
+ std::ios::out | std::ios::trunc | std::ios::binary);
#endif
- if(!fout)
- {
- return false;
+ 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());
+ // 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;
}
}
- // 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();
+ // 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();
+ fin.close();
+ fout.close();
- if(!fout)
- {
- return false;
+ if (!fout) {
+ return false;
}
- if ( perms )
- {
- if ( !SystemTools::SetPermissions(destination, perm) )
- {
+ }
+ if (perms) {
+ if (!SystemTools::SetPermissions(real_destination, perm)) {
return false;
- }
}
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool SystemTools::CopyAFile(const char* source, const char* destination,
- bool always)
+bool SystemTools::CopyAFile(const std::string& source,
+ const std::string& destination, bool always)
{
- if(always)
- {
+ if (always) {
return SystemTools::CopyFileAlways(source, destination);
- }
- else
- {
+ } else {
return SystemTools::CopyFileIfDifferent(source, destination);
- }
+ }
}
/**
* Copy a directory content from "source" directory to the directory named by
* "destination".
*/
-bool SystemTools::CopyADirectory(const char* source, const char* destination,
- bool always)
+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
size_t fileNum;
- if ( !SystemTools::MakeDirectory(destination) )
- {
+ if (!SystemTools::MakeDirectory(destination)) {
return false;
- }
- for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
- {
- if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
- strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
- {
- kwsys_stl::string fullPath = source;
+ }
+ for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
+ if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") &&
+ strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..")) {
+ std::string fullPath = source;
fullPath += "/";
fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if(SystemTools::FileIsDirectory(fullPath.c_str()))
- {
- kwsys_stl::string fullDestPath = destination;
+ if (SystemTools::FileIsDirectory(fullPath)) {
+ std::string fullDestPath = destination;
fullDestPath += "/";
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if (!SystemTools::CopyADirectory(fullPath.c_str(),
- fullDestPath.c_str(),
- always))
- {
+ if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) {
return false;
- }
}
- else
- {
- if(!SystemTools::CopyAFile(fullPath.c_str(), destination, always))
- {
+ } else {
+ if (!SystemTools::CopyAFile(fullPath, destination, always)) {
return false;
- }
}
}
}
+ }
return true;
}
-
// return size of file; also returns zero if no file exists
-unsigned long SystemTools::FileLength(const char* filename)
+unsigned long SystemTools::FileLength(const std::string& filename)
{
+ unsigned long length = 0;
+#ifdef _WIN32
+ WIN32_FILE_ATTRIBUTE_DATA fs;
+ if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+ GetFileExInfoStandard, &fs) != 0) {
+ /* To support the full 64-bit file size, use fs.nFileSizeHigh
+ * and fs.nFileSizeLow to construct the 64 bit size
+
+ length = ((__int64)fs.nFileSizeHigh << 32) + fs.nFileSizeLow;
+ */
+ length = static_cast<unsigned long>(fs.nFileSizeLow);
+ }
+#else
struct stat fs;
- if (stat(filename, &fs) != 0)
- {
- return 0;
- }
- else
- {
- return static_cast<unsigned long>(fs.st_size);
- }
+ if (stat(filename.c_str(), &fs) == 0) {
+ length = static_cast<unsigned long>(fs.st_size);
+ }
+#endif
+ return length;
}
-int SystemTools::Strucmp(const char *s1, const char *s2)
+int SystemTools::Strucmp(const char* l, const char* r)
{
- // lifted from Graphvis http://www.graphviz.org
- while ((*s1 != '\0')
- && (tolower(*s1) == tolower(*s2)))
- {
- s1++;
- s2++;
- }
-
- return tolower(*s1) - tolower(*s2);
+ int lc;
+ int rc;
+ do {
+ lc = tolower(*l++);
+ rc = tolower(*r++);
+ } while (lc == rc && lc);
+ return lc - rc;
}
// return file's modified time
-long int SystemTools::ModifiedTime(const char* filename)
+long int SystemTools::ModifiedTime(const std::string& filename)
{
+ long int mt = 0;
+#ifdef _WIN32
+ WIN32_FILE_ATTRIBUTE_DATA fs;
+ if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+ GetFileExInfoStandard, &fs) != 0) {
+ mt = windows_filetime_to_posix_time(fs.ftLastWriteTime);
+ }
+#else
struct stat fs;
- if (stat(filename, &fs) != 0)
- {
- return 0;
- }
- else
- {
- return static_cast<long int>(fs.st_mtime);
- }
+ if (stat(filename.c_str(), &fs) == 0) {
+ mt = static_cast<long int>(fs.st_mtime);
+ }
+#endif
+ return mt;
}
// return file's creation time
-long int SystemTools::CreationTime(const char* filename)
+long int SystemTools::CreationTime(const std::string& filename)
{
+ long int ct = 0;
+#ifdef _WIN32
+ WIN32_FILE_ATTRIBUTE_DATA fs;
+ if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+ GetFileExInfoStandard, &fs) != 0) {
+ ct = windows_filetime_to_posix_time(fs.ftCreationTime);
+ }
+#else
struct stat fs;
- if (stat(filename, &fs) != 0)
- {
- return 0;
- }
- else
- {
- return fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0;
- }
+ if (stat(filename.c_str(), &fs) == 0) {
+ ct = fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0;
+ }
+#endif
+ return ct;
}
-bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
+bool SystemTools::ConvertDateMacroString(const char* str, time_t* tmt)
{
- if (!str || !tmt || strlen(str) > 11)
- {
+ if (!str || !tmt || strlen(str) > 11) {
return false;
- }
+ }
struct tm tmt2;
@@ -2254,36 +2398,34 @@ bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
strcpy(buffer, str);
buffer[3] = 0;
- char *ptr = strstr(month_names, buffer);
- if (!ptr)
- {
+ 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;
+ 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)
+bool SystemTools::ConvertTimeStampMacroString(const char* str, time_t* tmt)
{
- if (!str || !tmt || strlen(str) > 26)
- {
+ if (!str || !tmt || strlen(str) > 26) {
return false;
- }
+ }
struct tm tmt2;
@@ -2305,11 +2447,10 @@ bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
strcpy(buffer, str);
buffer[7] = 0;
- char *ptr = strstr(month_names, buffer + 4);
- if (!ptr)
- {
+ 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);
@@ -2319,89 +2460,196 @@ bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
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;
+ 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;
}
-kwsys_stl::string SystemTools::GetLastSystemError()
+std::string SystemTools::GetLastSystemError()
{
int e = errno;
return strerror(e);
}
-bool SystemTools::RemoveFile(const char* source)
-{
#ifdef _WIN32
- mode_t mode;
- if ( !SystemTools::GetPermissions(source, mode) )
- {
+
+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;
- }
- /* Win32 unlink is stupid --- it fails if the file is read-only */
- SystemTools::SetPermissions(source, S_IWRITE);
+ }
+ 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 res = unlink(source) != 0 ? false : true;
+
+bool SystemTools::RemoveFile(const std::string& source)
+{
#ifdef _WIN32
- if ( !res )
- {
- SystemTools::SetPermissions(source, mode);
- }
+ std::wstring const& ws = Encoding::ToWindowsExtendedPath(source);
+ if (DeleteFileW(ws.c_str())) {
+ return true;
+ }
+ DWORD err = GetLastError();
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
+ return true;
+ }
+ if (err != ERROR_ACCESS_DENIED) {
+ return false;
+ }
+ /* The file may be read-only. Try adding write permission. */
+ mode_t mode;
+ if (!SystemTools::GetPermissions(source, mode) ||
+ !SystemTools::SetPermissions(source, S_IWRITE)) {
+ SetLastError(err);
+ return false;
+ }
+ if (IsJunction(ws) && DeleteJunction(ws)) {
+ return true;
+ }
+ if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND ||
+ GetLastError() == ERROR_PATH_NOT_FOUND) {
+ return true;
+ }
+ /* Try to restore the original permissions. */
+ SystemTools::SetPermissions(source, mode);
+ SetLastError(err);
+ return false;
+#else
+ return unlink(source.c_str()) == 0 || errno == ENOENT;
#endif
- return res;
}
-bool SystemTools::RemoveADirectory(const char* source)
+bool SystemTools::RemoveADirectory(const std::string& source)
{
// Add write permission to the directory so we can modify its
// content to remove files and directories from it.
mode_t mode;
- if(SystemTools::GetPermissions(source, mode))
- {
+ if (SystemTools::GetPermissions(source, mode)) {
#if defined(_WIN32) && !defined(__CYGWIN__)
mode |= S_IWRITE;
#else
mode |= S_IWUSR;
#endif
SystemTools::SetPermissions(source, mode);
- }
+ }
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)),".") &&
- strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
- {
- kwsys_stl::string fullPath = source;
+ for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
+ if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") &&
+ strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..")) {
+ std::string fullPath = source;
fullPath += "/";
fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if(SystemTools::FileIsDirectory(fullPath.c_str()) &&
- !SystemTools::FileIsSymlink(fullPath.c_str()))
- {
- if (!SystemTools::RemoveADirectory(fullPath.c_str()))
- {
+ if (SystemTools::FileIsDirectory(fullPath) &&
+ !SystemTools::FileIsSymlink(fullPath)) {
+ if (!SystemTools::RemoveADirectory(fullPath)) {
return false;
- }
}
- else
- {
- if(!SystemTools::RemoveFile(fullPath.c_str()))
- {
+ } else {
+ if (!SystemTools::RemoveFile(fullPath)) {
return false;
- }
}
}
}
+ }
return (Rmdir(source) == 0);
}
@@ -2418,50 +2666,43 @@ 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.
*/
-kwsys_stl::string SystemTools
-::FindName(const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& userPaths,
- bool no_system_path)
+std::string SystemTools::FindName(const std::string& name,
+ const std::vector<std::string>& userPaths,
+ bool no_system_path)
{
// Add the system search path to our path first
- kwsys_stl::vector<kwsys_stl::string> path;
- if (!no_system_path)
- {
+ std::vector<std::string> path;
+ if (!no_system_path) {
SystemTools::GetPath(path, "CMAKE_FILE_PATH");
SystemTools::GetPath(path);
- }
+ }
// now add the additional paths
{
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
- i != userPaths.end(); ++i)
- {
- path.push_back(*i);
+ 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(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
- i != path.end(); ++i)
- {
- kwsys_stl::string& p = *i;
- if(p.empty() || p[p.size()-1] != '/')
- {
- p += "/";
+ for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
+ ++i) {
+ std::string& p = *i;
+ if (p.empty() || *p.rbegin() != '/') {
+ p += "/";
}
}
}
// now look for the file
- kwsys_stl::string tryPath;
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
- p != path.end(); ++p)
- {
+ std::string tryPath;
+ for (std::vector<std::string>::const_iterator p = path.begin();
+ p != path.end(); ++p) {
tryPath = *p;
tryPath += name;
- if(SystemTools::FileExists(tryPath.c_str()))
- {
+ if (SystemTools::FileExists(tryPath)) {
return tryPath;
- }
}
+ }
// Couldn't find the file.
return "";
}
@@ -2471,16 +2712,14 @@ kwsys_stl::string SystemTools
* the system search path. Returns the full path to the file if it is
* found. Otherwise, the empty string is returned.
*/
-kwsys_stl::string SystemTools
-::FindFile(const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& userPaths,
- bool no_system_path)
+std::string SystemTools::FindFile(const std::string& name,
+ const std::vector<std::string>& userPaths,
+ bool no_system_path)
{
- kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
- if(tryPath != "" && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ std::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
+ if (!tryPath.empty() && !SystemTools::FileIsDirectory(tryPath)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
// Couldn't find the file.
return "";
}
@@ -2490,16 +2729,14 @@ kwsys_stl::string SystemTools
* the system search path. Returns the full path to the directory if it is
* found. Otherwise, the empty string is returned.
*/
-kwsys_stl::string SystemTools
-::FindDirectory(const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& userPaths,
- bool no_system_path)
+std::string SystemTools::FindDirectory(
+ const std::string& name, const std::vector<std::string>& userPaths,
+ bool no_system_path)
{
- kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
- if(tryPath != "" && SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ std::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
+ if (!tryPath.empty() && SystemTools::FileIsDirectory(tryPath)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
// Couldn't find the file.
return "";
}
@@ -2509,137 +2746,113 @@ kwsys_stl::string SystemTools
* the system search path. Returns the full path to the executable if it is
* found. Otherwise, the empty string is returned.
*/
-kwsys_stl::string SystemTools::FindProgram(
- const char* nameIn,
- const kwsys_stl::vector<kwsys_stl::string>& userPaths,
- bool no_system_path)
+std::string SystemTools::FindProgram(const char* nameIn,
+ const std::vector<std::string>& userPaths,
+ bool no_system_path)
{
- if(!nameIn || !*nameIn)
- {
+ if (!nameIn || !*nameIn) {
return "";
- }
- kwsys_stl::string name = nameIn;
- kwsys_stl::vector<kwsys_stl::string> extensions;
-#if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
- bool hasExtension = false;
+ }
+ return SystemTools::FindProgram(std::string(nameIn), userPaths,
+ no_system_path);
+}
+
+std::string SystemTools::FindProgram(const std::string& name,
+ const std::vector<std::string>& userPaths,
+ bool no_system_path)
+{
+ std::string tryPath;
+
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+ std::vector<std::string> extensions;
// check to see if the name already has a .xxx at
// the end of it
- if(name.size() > 3 && name[name.size()-4] == '.')
- {
- hasExtension = true;
- }
// on windows try .com then .exe
- if(!hasExtension)
- {
+ if (name.size() <= 3 || name[name.size() - 4] != '.') {
extensions.push_back(".com");
extensions.push_back(".exe");
- }
-#endif
- kwsys_stl::string tryPath;
- // first try with extensions if the os supports them
- if(extensions.size())
- {
- for(kwsys_stl::vector<kwsys_stl::string>::iterator i =
- extensions.begin(); i != extensions.end(); ++i)
- {
+ // first try with extensions if the os supports them
+ for (std::vector<std::string>::iterator i = extensions.begin();
+ i != extensions.end(); ++i) {
tryPath = name;
tryPath += *i;
- if(SystemTools::FileExists(tryPath.c_str()) &&
- !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
}
}
+ }
+#endif
+
// now try just the name
- tryPath = name;
- if(SystemTools::FileExists(tryPath.c_str()) &&
- !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(name, true)) {
+ return SystemTools::CollapseFullPath(name);
+ }
// now construct the path
- kwsys_stl::vector<kwsys_stl::string> path;
+ std::vector<std::string> path;
// Add the system search path to our path.
- if (!no_system_path)
- {
+ if (!no_system_path) {
SystemTools::GetPath(path);
- }
+ }
// now add the additional paths
{
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i =
- userPaths.begin(); i != userPaths.end(); ++i)
- {
- path.push_back(*i);
+ 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(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
- i != path.end(); ++i)
- {
- kwsys_stl::string& p = *i;
- if(p.empty() || p[p.size()-1] != '/')
- {
- p += "/";
+ for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
+ ++i) {
+ std::string& p = *i;
+ if (p.empty() || *p.rbegin() != '/') {
+ p += "/";
}
}
}
// Try each path
- for(kwsys_stl::vector<kwsys_stl::string>::iterator p = path.begin();
- p != path.end(); ++p)
- {
+ for (std::vector<std::string>::iterator p = path.begin(); p != path.end();
+ ++p) {
#ifdef _WIN32
// Remove double quotes from the path on windows
SystemTools::ReplaceString(*p, "\"", "");
#endif
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
// first try with extensions
- if(extensions.size())
- {
- for(kwsys_stl::vector<kwsys_stl::string>::iterator ext
- = extensions.begin(); ext != extensions.end(); ++ext)
- {
- tryPath = *p;
- tryPath += name;
- tryPath += *ext;
- if(SystemTools::FileExists(tryPath.c_str()) &&
- !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
- }
+ for (std::vector<std::string>::iterator ext = extensions.begin();
+ ext != extensions.end(); ++ext) {
+ tryPath = *p;
+ tryPath += name;
+ tryPath += *ext;
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
}
+ }
+#endif
// now try it without them
tryPath = *p;
tryPath += name;
- if(SystemTools::FileExists(tryPath.c_str()) &&
- !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
}
+ }
// Couldn't find the program.
return "";
}
-kwsys_stl::string SystemTools::FindProgram(
- const kwsys_stl::vector<kwsys_stl::string>& names,
- const kwsys_stl::vector<kwsys_stl::string>& path,
- bool noSystemPath)
+std::string SystemTools::FindProgram(const std::vector<std::string>& names,
+ const std::vector<std::string>& path,
+ bool noSystemPath)
{
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator it = names.begin();
- it != names.end() ; ++it)
- {
+ for (std::vector<std::string>::const_iterator it = names.begin();
+ it != names.end(); ++it) {
// Try to find the program.
- kwsys_stl::string result = SystemTools::FindProgram(it->c_str(),
- path,
- noSystemPath);
- if ( !result.empty() )
- {
+ std::string result = SystemTools::FindProgram(*it, path, noSystemPath);
+ if (!result.empty()) {
return result;
- }
}
+ }
return "";
}
@@ -2648,302 +2861,287 @@ kwsys_stl::string SystemTools::FindProgram(
* the system search path. Returns the full path to the library if it is
* found. Otherwise, the empty string is returned.
*/
-kwsys_stl::string SystemTools
-::FindLibrary(const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& userPaths)
+std::string SystemTools::FindLibrary(const std::string& name,
+ const std::vector<std::string>& userPaths)
{
// See if the executable exists as written.
- if(SystemTools::FileExists(name) &&
- !SystemTools::FileIsDirectory(name))
- {
+ if (SystemTools::FileExists(name, true)) {
return SystemTools::CollapseFullPath(name);
- }
+ }
// Add the system search path to our path.
- kwsys_stl::vector<kwsys_stl::string> path;
+ std::vector<std::string> path;
SystemTools::GetPath(path);
- // now add the additional paths
+ // now add the additional paths
{
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = userPaths.begin();
- i != userPaths.end(); ++i)
- {
- path.push_back(*i);
+ 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(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
- i != path.end(); ++i)
- {
- kwsys_stl::string& p = *i;
- if(p.empty() || p[p.size()-1] != '/')
- {
- p += "/";
+ for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
+ ++i) {
+ std::string& p = *i;
+ if (p.empty() || *p.rbegin() != '/') {
+ p += "/";
}
}
}
- kwsys_stl::string tryPath;
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
- p != path.end(); ++p)
- {
+ std::string tryPath;
+ for (std::vector<std::string>::const_iterator p = path.begin();
+ p != path.end(); ++p) {
#if defined(__APPLE__)
tryPath = *p;
tryPath += name;
tryPath += ".framework";
- if(SystemTools::FileExists(tryPath.c_str())
- && SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileIsDirectory(tryPath)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
#endif
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
tryPath = *p;
tryPath += name;
tryPath += ".lib";
- if(SystemTools::FileExists(tryPath.c_str())
- && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
#else
tryPath = *p;
tryPath += "lib";
tryPath += name;
tryPath += ".so";
- if(SystemTools::FileExists(tryPath.c_str())
- && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
tryPath = *p;
tryPath += "lib";
tryPath += name;
tryPath += ".a";
- if(SystemTools::FileExists(tryPath.c_str())
- && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
tryPath = *p;
tryPath += "lib";
tryPath += name;
tryPath += ".sl";
- if(SystemTools::FileExists(tryPath.c_str())
- && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
tryPath = *p;
tryPath += "lib";
tryPath += name;
tryPath += ".dylib";
- if(SystemTools::FileExists(tryPath.c_str())
- && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
+ }
tryPath = *p;
tryPath += "lib";
tryPath += name;
tryPath += ".dll";
- if(SystemTools::FileExists(tryPath.c_str())
- && !SystemTools::FileIsDirectory(tryPath.c_str()))
- {
- return SystemTools::CollapseFullPath(tryPath.c_str());
- }
-#endif
+ if (SystemTools::FileExists(tryPath, true)) {
+ return SystemTools::CollapseFullPath(tryPath);
}
+#endif
+ }
// Couldn't find the library.
return "";
}
-kwsys_stl::string SystemTools::GetRealPath(const char* path)
+std::string SystemTools::GetRealPath(const std::string& path,
+ std::string* errorMessage)
{
- kwsys_stl::string ret;
- Realpath(path, ret);
+ std::string ret;
+ Realpath(path, ret, errorMessage);
return ret;
}
-bool SystemTools::FileIsDirectory(const char* name)
+bool SystemTools::FileIsDirectory(const std::string& inName)
{
- size_t length = strlen(name);
- if (length == 0)
- {
+ if (inName.empty()) {
return false;
- }
+ }
+ size_t length = inName.size();
+ const char* name = inName.c_str();
// Remove any trailing slash from the name except in a root component.
char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
std::string string_buffer;
- size_t last = length-1;
- if(last > 0 && (name[last] == '/' || name[last] == '\\')
- && strcmp(name, "/") !=0 && name[last-1] != ':')
- {
- if(last < sizeof(local_buffer))
- {
+ size_t last = length - 1;
+ if (last > 0 && (name[last] == '/' || name[last] == '\\') &&
+ strcmp(name, "/") != 0 && name[last - 1] != ':') {
+ if (last < sizeof(local_buffer)) {
memcpy(local_buffer, name, last);
- local_buffer[last] = 0;
+ local_buffer[last] = '\0';
name = local_buffer;
- }
- else
- {
+ } else {
string_buffer.append(name, last);
name = string_buffer.c_str();
- }
}
+ }
- // Now check the file node type.
- struct stat fs;
- if(stat(name, &fs) == 0)
- {
-#if defined( _WIN32 ) && !defined(__CYGWIN__)
- return ((fs.st_mode & _S_IFDIR) != 0);
+// Now check the file node type.
+#if defined(_WIN32)
+ DWORD attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
+ if (attr != INVALID_FILE_ATTRIBUTES) {
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
#else
+ struct stat fs;
+ if (stat(name, &fs) == 0) {
return S_ISDIR(fs.st_mode);
#endif
- }
- else
- {
+ } else {
return false;
- }
+ }
}
-bool SystemTools::FileIsSymlink(const char* name)
+bool SystemTools::FileIsSymlink(const std::string& name)
{
-#if defined( _WIN32 )
- (void)name;
- return false;
+#if defined(_WIN32)
+ DWORD attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
+ if (attr != INVALID_FILE_ATTRIBUTES) {
+ return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+ } else {
+ return false;
+ }
#else
struct stat fs;
- if(lstat(name, &fs) == 0)
- {
+ if (lstat(name.c_str(), &fs) == 0) {
return S_ISLNK(fs.st_mode);
- }
- else
- {
+ } else {
return false;
- }
+ }
+#endif
+}
+
+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);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+ const DWORD type = GetFileType(hFile);
+ CloseHandle(hFile);
+ return type == FILE_TYPE_PIPE;
+#else
+ struct stat fs;
+ if (lstat(name.c_str(), &fs) == 0) {
+ return S_ISFIFO(fs.st_mode);
+ } else {
+ return false;
+ }
#endif
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::CreateSymlink(const char*, const char*)
+bool SystemTools::CreateSymlink(const std::string&, const std::string&)
{
return false;
}
#else
-bool SystemTools::CreateSymlink(const char* origName, const char* newName)
+bool SystemTools::CreateSymlink(const std::string& origName,
+ const std::string& newName)
{
- return symlink(origName, newName) >= 0;
+ return symlink(origName.c_str(), newName.c_str()) >= 0;
}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::ReadSymlink(const char*, kwsys_stl::string&)
+bool SystemTools::ReadSymlink(const std::string&, std::string&)
{
return false;
}
#else
-bool SystemTools::ReadSymlink(const char* newName,
- kwsys_stl::string& origName)
+bool SystemTools::ReadSymlink(const std::string& newName,
+ std::string& origName)
{
- char buf[KWSYS_SYSTEMTOOLS_MAXPATH+1];
- int count =
- static_cast<int>(readlink(newName, buf, KWSYS_SYSTEMTOOLS_MAXPATH));
- if(count >= 0)
- {
+ char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1];
+ int count = static_cast<int>(
+ readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH));
+ if (count >= 0) {
// Add null-terminator.
buf[count] = 0;
origName = buf;
return true;
- }
- else
- {
+ } else {
return false;
- }
+ }
}
#endif
-int SystemTools::ChangeDirectory(const char *dir)
+int SystemTools::ChangeDirectory(const std::string& dir)
{
return Chdir(dir);
}
-kwsys_stl::string SystemTools::GetCurrentWorkingDirectory(bool collapse)
+std::string SystemTools::GetCurrentWorkingDirectory(bool collapse)
{
char buf[2048];
const char* cwd = Getcwd(buf, 2048);
- kwsys_stl::string path;
- if ( cwd )
- {
+ std::string path;
+ if (cwd) {
path = cwd;
- }
- if(collapse)
- {
- return SystemTools::CollapseFullPath(path.c_str());
- }
+ }
+ if (collapse) {
+ return SystemTools::CollapseFullPath(path);
+ }
return path;
}
-kwsys_stl::string SystemTools::GetProgramPath(const char* in_name)
+std::string SystemTools::GetProgramPath(const std::string& in_name)
{
- kwsys_stl::string dir, file;
+ std::string dir, file;
SystemTools::SplitProgramPath(in_name, dir, file);
return dir;
}
-bool SystemTools::SplitProgramPath(const char* in_name,
- kwsys_stl::string& dir,
- kwsys_stl::string& file,
- bool)
+bool SystemTools::SplitProgramPath(const std::string& in_name,
+ std::string& dir, std::string& file, bool)
{
dir = in_name;
file = "";
SystemTools::ConvertToUnixSlashes(dir);
- if(!SystemTools::FileIsDirectory(dir.c_str()))
- {
- kwsys_stl::string::size_type slashPos = dir.rfind("/");
- if(slashPos != kwsys_stl::string::npos)
- {
- file = dir.substr(slashPos+1);
+ if (!SystemTools::FileIsDirectory(dir)) {
+ std::string::size_type slashPos = dir.rfind("/");
+ if (slashPos != std::string::npos) {
+ file = dir.substr(slashPos + 1);
dir = dir.substr(0, slashPos);
- }
- else
- {
+ } else {
file = dir;
dir = "";
- }
}
- if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str()))
- {
- kwsys_stl::string oldDir = in_name;
+ }
+ if (!(dir.empty()) && !SystemTools::FileIsDirectory(dir)) {
+ std::string oldDir = in_name;
SystemTools::ConvertToUnixSlashes(oldDir);
dir = in_name;
return false;
- }
+ }
return true;
}
-bool SystemTools::FindProgramPath(const char* argv0,
- kwsys_stl::string& pathOut,
- kwsys_stl::string& errorMsg,
- const char* exeName,
+bool SystemTools::FindProgramPath(const char* argv0, std::string& pathOut,
+ std::string& errorMsg, const char* exeName,
const char* buildDir,
- const char* installPrefix )
+ const char* installPrefix)
{
- kwsys_stl::vector<kwsys_stl::string> failures;
- kwsys_stl::string self = argv0 ? argv0 : "";
+ std::vector<std::string> failures;
+ std::string self = argv0 ? argv0 : "";
failures.push_back(self);
SystemTools::ConvertToUnixSlashes(self);
- self = SystemTools::FindProgram(self.c_str());
- if(!SystemTools::FileExists(self.c_str()))
- {
- if(buildDir)
- {
- kwsys_stl::string intdir = ".";
-#ifdef CMAKE_INTDIR
+ self = SystemTools::FindProgram(self);
+ if (!SystemTools::FileExists(self)) {
+ if (buildDir) {
+ std::string intdir = ".";
+#ifdef CMAKE_INTDIR
intdir = CMAKE_INTDIR;
#endif
self = buildDir;
@@ -2952,100 +3150,88 @@ bool SystemTools::FindProgramPath(const char* argv0,
self += "/";
self += exeName;
self += SystemTools::GetExecutableExtension();
- }
}
- if(installPrefix)
- {
- if(!SystemTools::FileExists(self.c_str()))
- {
+ }
+ if (installPrefix) {
+ if (!SystemTools::FileExists(self)) {
failures.push_back(self);
self = installPrefix;
self += "/bin/";
- self += exeName;
- }
+ self += exeName;
}
- if(!SystemTools::FileExists(self.c_str()))
- {
+ }
+ if (!SystemTools::FileExists(self)) {
failures.push_back(self);
- kwsys_ios::ostringstream msg;
+ std::ostringstream msg;
msg << "Can not find the command line program ";
- if (exeName)
- {
+ if (exeName) {
msg << exeName;
- }
+ }
msg << "\n";
- if (argv0)
- {
+ if (argv0) {
msg << " argv[0] = \"" << argv0 << "\"\n";
- }
+ }
msg << " Attempted paths:\n";
- kwsys_stl::vector<kwsys_stl::string>::iterator i;
- for(i=failures.begin(); i != failures.end(); ++i)
- {
- msg << " \"" << i->c_str() << "\"\n";
- }
+ std::vector<std::string>::iterator i;
+ for (i = failures.begin(); i != failures.end(); ++i) {
+ msg << " \"" << *i << "\"\n";
+ }
errorMsg = msg.str();
return false;
- }
+ }
pathOut = self;
return true;
}
-
-kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative)
+std::string SystemTools::CollapseFullPath(const std::string& in_relative)
{
return SystemTools::CollapseFullPath(in_relative, 0);
}
-void SystemTools::AddTranslationPath(const char * a, const char * b)
+void SystemTools::AddTranslationPath(const std::string& a,
+ const std::string& b)
{
- kwsys_stl::string path_a = a;
- kwsys_stl::string path_b = b;
+ std::string path_a = a;
+ std::string path_b = b;
SystemTools::ConvertToUnixSlashes(path_a);
SystemTools::ConvertToUnixSlashes(path_b);
// First check this is a directory path, since we don't want the table to
// grow too fat
- if( SystemTools::FileIsDirectory( path_a.c_str() ) )
- {
+ if (SystemTools::FileIsDirectory(path_a)) {
// Make sure the path is a full path and does not contain no '..'
// Ken--the following code is incorrect. .. can be in a valid path
// for example /home/martink/MyHubba...Hubba/Src
- if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..")
- == kwsys_stl::string::npos )
- {
+ if (SystemTools::FileIsFullPath(path_b) &&
+ path_b.find("..") == std::string::npos) {
// Before inserting make sure path ends with '/'
- if(path_a.size() && path_a[path_a.size() -1] != '/')
- {
+ if (!path_a.empty() && *path_a.rbegin() != '/') {
path_a += '/';
- }
- if(path_b.size() && path_b[path_b.size() -1] != '/')
- {
+ }
+ if (!path_b.empty() && *path_b.rbegin() != '/') {
path_b += '/';
- }
- if( !(path_a == path_b) )
- {
+ }
+ if (!(path_a == path_b)) {
SystemTools::TranslationMap->insert(
SystemToolsTranslationMap::value_type(path_a, path_b));
- }
}
}
+ }
}
-void SystemTools::AddKeepPath(const char* dir)
+void SystemTools::AddKeepPath(const std::string& dir)
{
- kwsys_stl::string cdir;
+ std::string cdir;
Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir);
- SystemTools::AddTranslationPath(cdir.c_str(), dir);
+ SystemTools::AddTranslationPath(cdir, dir);
}
-void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
+void SystemTools::CheckTranslationPath(std::string& path)
{
// Do not translate paths that are too short to have meaningful
// translations.
- if(path.size() < 2)
- {
+ if (path.size() < 2) {
return;
- }
+ }
// Always add a trailing slash before translation. It does not
// matter if this adds an extra slash, but we do not want to
@@ -3054,92 +3240,127 @@ void SystemTools::CheckTranslationPath(kwsys_stl::string & 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:
- kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>::const_iterator it;
- for(it = SystemTools::TranslationMap->begin();
- it != SystemTools::TranslationMap->end();
- ++it )
- {
+ std::map<std::string, std::string>::const_iterator it;
+ for (it = SystemTools::TranslationMap->begin();
+ it != SystemTools::TranslationMap->end(); ++it) {
// 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(it->first) == 0) {
+ path = path.replace(0, it->first.size(), it->second);
}
+ }
// Remove the trailing slash we added before.
- path.erase(path.end()-1, path.end());
+ path.erase(path.end() - 1, path.end());
}
-static void
-SystemToolsAppendComponents(
- kwsys_stl::vector<kwsys_stl::string>& out_components,
- kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
- kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
+static void SystemToolsAppendComponents(
+ std::vector<std::string>& out_components,
+ std::vector<std::string>::const_iterator first,
+ std::vector<std::string>::const_iterator last)
{
- for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = first;
- i != last; ++i)
- {
- if(*i == "..")
- {
- if(out_components.size() > 1)
- {
- out_components.erase(out_components.end()-1, out_components.end());
- }
+ 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) {
+ out_components.resize(out_components.size() - 1);
}
- else if(!(*i == ".") && !(*i == ""))
- {
+ } else if (!i->empty() && *i != cur) {
out_components.push_back(*i);
- }
}
+ }
}
-kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
- const char* in_base)
+std::string SystemTools::CollapseFullPath(const std::string& in_path,
+ const char* in_base)
{
// Collect the output path components.
- kwsys_stl::vector<kwsys_stl::string> out_components;
+ std::vector<std::string> out_components;
// Split the input path components.
- kwsys_stl::vector<kwsys_stl::string> 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].length() == 0)
- {
- kwsys_stl::vector<kwsys_stl::string> base_components;
- if(in_base)
- {
+ 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);
- }
- else
- {
+ } else {
// Use the current working directory as a base path.
char buf[2048];
- if(const char* cwd = Getcwd(buf, 2048))
- {
+ if (const char* cwd = Getcwd(buf, 2048)) {
SystemTools::SplitPath(cwd, base_components);
- }
- else
- {
+ } else {
base_components.push_back("");
- }
}
+ }
// Append base path components to the output path.
out_components.push_back(base_components[0]);
- SystemToolsAppendComponents(out_components,
- base_components.begin()+1,
+ 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;
+}
+
+std::string SystemTools::CollapseFullPath(const std::string& in_path,
+ const std::string& 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].length() == 0) {
+ std::vector<std::string> base_components;
+ // Use the given base path.
+ SystemTools::SplitPath(in_base, base_components);
+
+ // 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(),
+ SystemToolsAppendComponents(out_components, path_components.begin(),
path_components.end());
// Transform the path back to a string.
- kwsys_stl::string newPath = SystemTools::JoinPath(out_components);
+ 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
@@ -3153,11 +3374,11 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
// 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.c_str(), in_path);
+ // SystemTools::AddTranslationPath(newPath, in_path);
SystemTools::CheckTranslationPath(newPath);
#ifdef _WIN32
- newPath = SystemTools::GetActualCaseForPath(newPath.c_str());
+ newPath = SystemTools::GetActualCaseForPath(newPath);
SystemTools::ConvertToUnixSlashes(newPath);
#endif
// Return the reconstructed path.
@@ -3165,220 +3386,203 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
}
// compute the relative path from here to there
-kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remote)
+std::string SystemTools::RelativePath(const std::string& local,
+ const std::string& remote)
{
- if(!SystemTools::FileIsFullPath(local))
- {
+ if (!SystemTools::FileIsFullPath(local)) {
return "";
- }
- if(!SystemTools::FileIsFullPath(remote))
- {
+ }
+ if (!SystemTools::FileIsFullPath(remote)) {
return "";
- }
+ }
+
+ std::string l = SystemTools::CollapseFullPath(local);
+ std::string r = SystemTools::CollapseFullPath(remote);
// split up both paths into arrays of strings using / as a separator
- kwsys_stl::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true);
- kwsys_stl::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
- kwsys_stl::vector<kwsys::String> commonPath; // store shared parts of path in this array
- kwsys_stl::vector<kwsys::String> finalPath; // store the final relative path here
+ std::vector<kwsys::String> localSplit =
+ SystemTools::SplitString(l, '/', true);
+ std::vector<kwsys::String> remoteSplit =
+ SystemTools::SplitString(r, '/', true);
+ std::vector<kwsys::String>
+ commonPath; // store shared parts of path in this array
+ std::vector<kwsys::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)))
- &&
+ while (((sameCount <= (localSplit.size() - 1)) &&
+ (sameCount <= (remoteSplit.size() - 1))) &&
// 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
+ SystemTools::Strucmp(localSplit[sameCount].c_str(),
+ remoteSplit[sameCount].c_str()) == 0
#else
- localSplit[sameCount] == remoteSplit[sameCount]
+ 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
localSplit[sameCount] = "";
remoteSplit[sameCount] = "";
sameCount++;
- }
+ }
// If there is nothing in common at all then just return the full
// path. This is the case only on windows when the paths have
// different drive letters. On unix two full paths always at least
// have the root "/" in common so we will return a relative path
// that passes through the root directory.
- if(sameCount == 0)
- {
+ if (sameCount == 0) {
return remote;
- }
+ }
// 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].size())
- {
+ for (unsigned int i = 0; i < localSplit.size(); ++i) {
+ if (!localSplit[i].empty()) {
finalPath.push_back("../");
- }
}
+ }
// for each entry that is not common in the remote path add it
// to the final path.
- for(kwsys_stl::vector<String>::iterator vit = remoteSplit.begin();
- vit != remoteSplit.end(); ++vit)
- {
- if(vit->size())
- {
+ for (std::vector<String>::iterator vit = remoteSplit.begin();
+ vit != remoteSplit.end(); ++vit) {
+ if (!vit->empty()) {
finalPath.push_back(*vit);
- }
}
- kwsys_stl::string relativePath; // result string
+ }
+ 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(kwsys_stl::vector<String>::iterator vit1 = finalPath.begin();
- vit1 != finalPath.end(); ++vit1)
- {
- if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
- {
+ for (std::vector<String>::iterator vit1 = finalPath.begin();
+ vit1 != finalPath.end(); ++vit1) {
+ if (!relativePath.empty() && *relativePath.rbegin() != '/') {
relativePath += "/";
- }
- relativePath += *vit1;
}
+ relativePath += *vit1;
+ }
return relativePath;
}
#ifdef _WIN32
-static int GetCasePathName(const kwsys_stl::string & pathIn,
- kwsys_stl::string & casePath)
+static std::string GetCasePathName(std::string const& pathIn)
{
- kwsys_stl::vector<kwsys_stl::string> path_components;
- SystemTools::SplitPath(pathIn.c_str(), path_components);
- if(path_components[0].empty()) // First component always exists.
- {
+ 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 = "";
- return 0;
- }
+ casePath = pathIn;
+ return casePath;
+ }
// Start with root component.
- kwsys_stl::vector<kwsys_stl::string>::size_type idx = 0;
+ 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] == "//")
- {
+ if (path_components.size() > 2 && path_components[0] == "//") {
casePath += path_components[idx++];
casePath += "/";
casePath += path_components[idx++];
sep = "/";
- }
+ }
- for(; idx < path_components.size(); idx++)
- {
+ // Convert case of all components that exist.
+ bool converting = true;
+ for (; idx < path_components.size(); idx++) {
casePath += sep;
sep = "/";
- kwsys_stl::string test_str = casePath;
- test_str += path_components[idx];
- WIN32_FIND_DATA findData;
- HANDLE hFind = ::FindFirstFile(test_str.c_str(), &findData);
- if (INVALID_HANDLE_VALUE != hFind)
- {
- casePath += findData.cFileName;
- ::FindClose(hFind);
- }
- else
- {
- casePath = "";
- return 0;
+ 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;
+ }
}
}
- return (int)casePath.size();
+
+ casePath += path_components[idx];
+ }
+ return casePath;
}
#endif
-
-//----------------------------------------------------------------------------
-kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
+std::string SystemTools::GetActualCaseForPath(const std::string& p)
{
#ifndef _WIN32
return p;
#else
- kwsys_stl::string casePath = p;
- // make sure drive letter is always upper case
- if(casePath.size() > 1 && casePath[1] == ':')
- {
- casePath[0] = toupper(casePath[0]);
- }
-
// Check to see if actual case has already been called
- // for this path, and the result is stored in the LongPathMap
- SystemToolsTranslationMap::iterator i =
- SystemTools::LongPathMap->find(casePath);
- if(i != SystemTools::LongPathMap->end())
- {
+ // 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;
- }
- int len = GetCasePathName(p, casePath);
- if(len == 0 || len > MAX_PATH+1)
- {
- return p;
- }
- (*SystemTools::LongPathMap)[p] = casePath;
+ }
+ std::string casePath = GetCasePathName(p);
+ if (casePath.size() > MAX_PATH) {
+ return casePath;
+ }
+ (*SystemTools::PathCaseMap)[p] = casePath;
return casePath;
#endif
}
-//----------------------------------------------------------------------------
-const char* SystemTools::SplitPathRootComponent(const char* p,
- kwsys_stl::string* root)
+const char* SystemTools::SplitPathRootComponent(const std::string& p,
+ std::string* root)
{
// Identify the root component.
- const char* c = p;
- if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\'))
- {
+ const char* c = p.c_str();
+ if ((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\')) {
// Network path.
- if(root)
- {
+ if (root) {
*root = "//";
- }
- c += 2;
}
- else if(c[0] == '/' || c[0] == '\\')
- {
+ c += 2;
+ } else if (c[0] == '/' || c[0] == '\\') {
// Unix path (or Windows path w/out drive letter).
- if(root)
- {
+ if (root) {
*root = "/";
- }
- c += 1;
}
- else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\'))
- {
+ c += 1;
+ } else if (c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\')) {
// Windows path.
- if(root)
- {
+ if (root) {
(*root) = "_:/";
(*root)[0] = c[0];
- }
- c += 3;
}
- else if(c[0] && c[1] == ':')
- {
+ c += 3;
+ } else if (c[0] && c[1] == ':') {
// Path relative to a windows drive working directory.
- if(root)
- {
+ if (root) {
(*root) = "_:";
(*root)[0] = c[0];
- }
- c += 2;
}
- else if(c[0] == '~')
- {
+ c += 2;
+ } else if (c[0] == '~') {
// Home directory. The returned root should always have a
// trailing slash so that appending components as
// c[0]c[1]/c[2]/... works. The remaining path returned should
@@ -3391,215 +3595,186 @@ const char* SystemTools::SplitPathRootComponent(const char* p,
// "~u/" : root = "~u/", return ""
// "~u/x" : root = "~u/", return "x"
size_t n = 1;
- while(c[n] && c[n] != '/')
- {
+ while (c[n] && c[n] != '/') {
++n;
- }
- if(root)
- {
+ }
+ if (root) {
root->assign(c, n);
*root += '/';
- }
- if(c[n] == '/')
- {
+ }
+ if (c[n] == '/') {
++n;
- }
- c += n;
}
- else
- {
+ c += n;
+ } else {
// Relative path.
- if(root)
- {
+ if (root) {
*root = "";
- }
}
+ }
// Return the remaining path.
return c;
}
-//----------------------------------------------------------------------------
-void SystemTools::SplitPath(const char* p,
- kwsys_stl::vector<kwsys_stl::string>& components,
+void SystemTools::SplitPath(const std::string& p,
+ std::vector<std::string>& components,
bool expand_home_dir)
{
- const char* c = p;
+ const char* c;
components.clear();
// Identify the root component.
{
- kwsys_stl::string root;
- c = SystemTools::SplitPathRootComponent(c, &root);
-
- // Expand home directory references if requested.
- if(expand_home_dir && !root.empty() && root[0] == '~')
- {
- kwsys_stl::string homedir;
- root = root.substr(0, root.size()-1);
- if(root.size() == 1)
- {
+ std::string root;
+ c = SystemTools::SplitPathRootComponent(p, &root);
+
+ // Expand home directory references if requested.
+ if (expand_home_dir && !root.empty() && root[0] == '~') {
+ std::string homedir;
+ root = root.substr(0, root.size() - 1);
+ if (root.size() == 1) {
#if defined(_WIN32) && !defined(__CYGWIN__)
- if(const char* userp = getenv("USERPROFILE"))
- {
- homedir = userp;
- }
- else
+ if (!SystemTools::GetEnv("USERPROFILE", homedir))
#endif
- if(const char* h = getenv("HOME"))
- {
- homedir = h;
- }
+ SystemTools::GetEnv("HOME", homedir);
}
#ifdef HAVE_GETPWNAM
- else if(passwd* pw = getpwnam(root.c_str()+1))
- {
- if(pw->pw_dir)
- {
- homedir = pw->pw_dir;
+ else if (passwd* pw = getpwnam(root.c_str() + 1)) {
+ if (pw->pw_dir) {
+ homedir = pw->pw_dir;
}
}
#endif
- if(!homedir.empty() && (homedir[homedir.size()-1] == '/' ||
- homedir[homedir.size()-1] == '\\'))
- {
- homedir = homedir.substr(0, homedir.size()-1);
+ if (!homedir.empty() &&
+ (*homedir.rbegin() == '/' || *homedir.rbegin() == '\\')) {
+ homedir.resize(homedir.size() - 1);
}
- SystemTools::SplitPath(homedir.c_str(), components);
- }
- else
- {
- components.push_back(root);
+ SystemTools::SplitPath(homedir, components);
+ } else {
+ components.push_back(root);
}
}
// Parse the remaining components.
const char* first = c;
const char* last = first;
- for(;*last; ++last)
- {
- if(*last == '/' || *last == '\\')
- {
+ for (; *last; ++last) {
+ if (*last == '/' || *last == '\\') {
// End of a component. Save it.
- components.push_back(
- kwsys_stl::string(first,static_cast<kwsys_stl::string::size_type>(
- last-first)));
- first = last+1;
- }
+ components.push_back(std::string(first, last));
+ first = last + 1;
}
+ }
// Save the last component unless there were no components.
- if(last != c)
- {
- components.push_back(
- kwsys_stl::string(first,static_cast<kwsys_stl::string::size_type>(
- last-first)));
- }
+ if (last != c) {
+ components.push_back(std::string(first, last));
+ }
}
-//----------------------------------------------------------------------------
-kwsys_stl::string
-SystemTools::JoinPath(const kwsys_stl::vector<kwsys_stl::string>& components)
+std::string SystemTools::JoinPath(const std::vector<std::string>& components)
{
return SystemTools::JoinPath(components.begin(), components.end());
}
-//----------------------------------------------------------------------------
-kwsys_stl::string
-SystemTools
-::JoinPath(kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
- kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
+std::string SystemTools::JoinPath(
+ std::vector<std::string>::const_iterator first,
+ std::vector<std::string>::const_iterator last)
{
// Construct result in a single string.
- kwsys_stl::string result;
+ std::string result;
+ size_t len = 0;
+ std::vector<std::string>::const_iterator i;
+ for (i = first; i != last; ++i) {
+ len += 1 + i->size();
+ }
+ result.reserve(len);
// The first two components do not add a slash.
- if(first != last)
- {
+ if (first != last) {
result.append(*first++);
- }
- if(first != last)
- {
+ }
+ if (first != last) {
result.append(*first++);
- }
+ }
// All remaining components are always separated with a slash.
- while(first != last)
- {
+ while (first != last) {
result.append("/");
result.append((*first++));
- }
+ }
// Return the concatenated result.
return result;
}
-//----------------------------------------------------------------------------
-bool SystemTools::ComparePath(const char* c1, const char* c2)
+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
- return _stricmp(c1, c2) == 0;
-# elif defined(__APPLE__) || defined(__GNUC__)
- return strcasecmp(c1, c2) == 0;
+#ifdef _MSC_VER
+ return _stricmp(c1.c_str(), c2.c_str()) == 0;
+#elif defined(__APPLE__) || defined(__GNUC__)
+ return strcasecmp(c1.c_str(), c2.c_str()) == 0;
#else
- return SystemTools::Strucmp(c1, c2) == 0;
-# endif
+ return SystemTools::Strucmp(c1.c_str(), c2.c_str()) == 0;
+#endif
#else
- return strcmp(c1, c2) == 0;
+ return c1 == c2;
#endif
}
-//----------------------------------------------------------------------------
-bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines, char separator)
+bool SystemTools::Split(const std::string& str,
+ std::vector<std::string>& lines, char separator)
{
- kwsys_stl::string data(str);
- kwsys_stl::string::size_type lpos = 0;
- while(lpos < data.length())
- {
- kwsys_stl::string::size_type rpos = data.find_first_of(separator, lpos);
- if(rpos == kwsys_stl::string::npos)
- {
+ std::string data(str);
+ std::string::size_type lpos = 0;
+ 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.
lines.push_back(data.substr(lpos));
return false;
- }
- else
- {
+ } else {
// Line ends in a "\n", remove the character.
- lines.push_back(data.substr(lpos, rpos-lpos));
- }
- lpos = rpos+1;
+ lines.push_back(data.substr(lpos, rpos - lpos));
}
+ lpos = rpos + 1;
+ }
return true;
}
-//----------------------------------------------------------------------------
-bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines)
+bool SystemTools::Split(const std::string& str,
+ std::vector<std::string>& lines)
{
- kwsys_stl::string data(str);
- kwsys_stl::string::size_type lpos = 0;
- while(lpos < data.length())
- {
- kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos);
- if(rpos == kwsys_stl::string::npos)
- {
+ 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);
+ if (rpos == std::string::npos) {
// Line ends at end of string without a newline.
lines.push_back(data.substr(lpos));
return false;
- }
- if((rpos > lpos) && (data[rpos-1] == '\r'))
- {
+ }
+ if ((rpos > lpos) && (data[rpos - 1] == '\r')) {
// Line ends in a "\r\n" pair, remove both characters.
- lines.push_back(data.substr(lpos, (rpos-1)-lpos));
- }
- else
- {
+ lines.push_back(data.substr(lpos, (rpos - 1) - lpos));
+ } else {
// Line ends in a "\n", remove the character.
- lines.push_back(data.substr(lpos, rpos-lpos));
- }
- lpos = rpos+1;
+ lines.push_back(data.substr(lpos, rpos - lpos));
}
+ lpos = rpos + 1;
+ }
return true;
}
@@ -3607,500 +3782,440 @@ bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& l
* Return path of a full filename (no trailing slashes).
* Warning: returned path is converted to Unix slashes format.
*/
-kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename)
+std::string SystemTools::GetFilenamePath(const std::string& filename)
{
- kwsys_stl::string fn = filename;
+ std::string fn = filename;
SystemTools::ConvertToUnixSlashes(fn);
- kwsys_stl::string::size_type slash_pos = fn.rfind("/");
- if(slash_pos != kwsys_stl::string::npos)
- {
- kwsys_stl::string ret = fn.substr(0, slash_pos);
- if(ret.size() == 2 && ret[1] == ':')
- {
+ std::string::size_type slash_pos = fn.rfind("/");
+ if (slash_pos != std::string::npos) {
+ std::string ret = fn.substr(0, slash_pos);
+ if (ret.size() == 2 && ret[1] == ':') {
return ret + '/';
- }
- if(ret.size() == 0)
- {
+ }
+ if (ret.empty()) {
return "/";
- }
- return ret;
}
- else
- {
+ return ret;
+ } else {
return "";
- }
+ }
}
-
/**
* Return file name of a full filename (i.e. file name without path).
*/
-kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename)
+std::string SystemTools::GetFilenameName(const std::string& filename)
{
#if defined(_WIN32)
- kwsys_stl::string::size_type slash_pos = filename.find_last_of("/\\");
+ std::string::size_type slash_pos = filename.find_last_of("/\\");
#else
- kwsys_stl::string::size_type slash_pos = filename.find_last_of("/");
+ std::string::size_type slash_pos = filename.rfind('/');
#endif
- if(slash_pos != kwsys_stl::string::npos)
- {
+ if (slash_pos != std::string::npos) {
return filename.substr(slash_pos + 1);
- }
- else
- {
+ } else {
return filename;
- }
+ }
}
-
/**
* Return file extension of a full filename (dot included).
* Warning: this is the longest extension (for example: .tar.gz)
*/
-kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename)
+std::string SystemTools::GetFilenameExtension(const std::string& filename)
{
- kwsys_stl::string name = SystemTools::GetFilenameName(filename);
- kwsys_stl::string::size_type dot_pos = name.find(".");
- if(dot_pos != kwsys_stl::string::npos)
- {
+ std::string name = SystemTools::GetFilenameName(filename);
+ std::string::size_type dot_pos = name.find('.');
+ if (dot_pos != std::string::npos) {
return name.substr(dot_pos);
- }
- else
- {
+ } else {
return "";
- }
+ }
}
/**
* Return file extension of a full filename (dot included).
* Warning: this is the shortest extension (for example: .gz of .tar.gz)
*/
-kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename)
+std::string SystemTools::GetFilenameLastExtension(const std::string& filename)
{
- kwsys_stl::string name = SystemTools::GetFilenameName(filename);
- kwsys_stl::string::size_type dot_pos = name.rfind(".");
- if(dot_pos != kwsys_stl::string::npos)
- {
+ std::string name = SystemTools::GetFilenameName(filename);
+ std::string::size_type dot_pos = name.rfind('.');
+ if (dot_pos != std::string::npos) {
return name.substr(dot_pos);
- }
- else
- {
+ } else {
return "";
- }
+ }
}
/**
* Return file name without extension of a full filename (i.e. without path).
* Warning: it considers the longest extension (for example: .tar.gz)
*/
-kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename)
+std::string SystemTools::GetFilenameWithoutExtension(
+ const std::string& filename)
{
- kwsys_stl::string name = SystemTools::GetFilenameName(filename);
- kwsys_stl::string::size_type dot_pos = name.find(".");
- if(dot_pos != kwsys_stl::string::npos)
- {
+ std::string name = SystemTools::GetFilenameName(filename);
+ std::string::size_type dot_pos = name.find('.');
+ if (dot_pos != std::string::npos) {
return name.substr(0, dot_pos);
- }
- else
- {
+ } else {
return name;
- }
+ }
}
-
/**
* Return file name without extension of a full filename (i.e. without path).
* Warning: it considers the last extension (for example: removes .gz
* from .tar.gz)
*/
-kwsys_stl::string
-SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename)
+std::string SystemTools::GetFilenameWithoutLastExtension(
+ const std::string& filename)
{
- kwsys_stl::string name = SystemTools::GetFilenameName(filename);
- kwsys_stl::string::size_type dot_pos = name.rfind(".");
- if(dot_pos != kwsys_stl::string::npos)
- {
+ std::string name = SystemTools::GetFilenameName(filename);
+ std::string::size_type dot_pos = name.rfind('.');
+ if (dot_pos != std::string::npos) {
return name.substr(0, dot_pos);
- }
- else
- {
+ } else {
return name;
- }
+ }
}
-bool SystemTools::FileHasSignature(const char *filename,
- const char *signature,
+bool SystemTools::FileHasSignature(const char* filename, const char* signature,
long offset)
{
- if (!filename || !signature)
- {
+ if (!filename || !signature) {
return false;
- }
+ }
- FILE *fp;
- fp = fopen(filename, "rb");
- if (!fp)
- {
+ FILE* fp = Fopen(filename, "rb");
+ if (!fp) {
return false;
- }
+ }
fseek(fp, offset, SEEK_SET);
bool res = false;
size_t signature_len = strlen(signature);
- char *buffer = new char [signature_len];
+ char* buffer = new char[signature_len];
- if (fread(buffer, 1, signature_len, fp) == signature_len)
- {
+ if (fread(buffer, 1, signature_len, fp) == signature_len) {
res = (!strncmp(buffer, signature, signature_len) ? true : false);
- }
+ }
- delete [] buffer;
+ delete[] buffer;
fclose(fp);
return res;
}
-SystemTools::FileTypeEnum
-SystemTools::DetectFileType(const char *filename,
- unsigned long length,
- double percent_bin)
+SystemTools::FileTypeEnum SystemTools::DetectFileType(const char* filename,
+ unsigned long length,
+ double percent_bin)
{
- if (!filename || percent_bin < 0)
- {
+ if (!filename || percent_bin < 0) {
return SystemTools::FileTypeUnknown;
- }
+ }
- FILE *fp;
- fp = fopen(filename, "rb");
- if (!fp)
- {
+ if (SystemTools::FileIsDirectory(filename)) {
return SystemTools::FileTypeUnknown;
- }
+ }
+
+ FILE* fp = Fopen(filename, "rb");
+ if (!fp) {
+ return SystemTools::FileTypeUnknown;
+ }
// Allocate buffer and read bytes
- unsigned char *buffer = new unsigned char [length];
+ unsigned char* buffer = new unsigned char[length];
size_t read_length = fread(buffer, 1, length, fp);
fclose(fp);
- if (read_length == 0)
- {
+ if (read_length == 0) {
+ delete[] buffer;
return SystemTools::FileTypeUnknown;
- }
+ }
// Loop over contents and count
size_t text_count = 0;
- const unsigned char *ptr = buffer;
- const unsigned char *buffer_end = buffer + read_length;
+ const unsigned char* ptr = buffer;
+ const unsigned char* buffer_end = buffer + read_length;
- while (ptr != buffer_end)
- {
- if ((*ptr >= 0x20 && *ptr <= 0x7F) ||
- *ptr == '\n' ||
- *ptr == '\r' ||
- *ptr == '\t')
- {
+ while (ptr != buffer_end) {
+ if ((*ptr >= 0x20 && *ptr <= 0x7F) || *ptr == '\n' || *ptr == '\r' ||
+ *ptr == '\t') {
text_count++;
- }
- ptr++;
}
+ ptr++;
+ }
- delete [] buffer;
+ delete[] buffer;
- double current_percent_bin =
- (static_cast<double>(read_length - text_count) /
- static_cast<double>(read_length));
+ double current_percent_bin = (static_cast<double>(read_length - text_count) /
+ static_cast<double>(read_length));
- if (current_percent_bin >= percent_bin)
- {
+ if (current_percent_bin >= percent_bin) {
return SystemTools::FileTypeBinary;
- }
+ }
return SystemTools::FileTypeText;
}
-bool SystemTools::LocateFileInDir(const char *filename,
- const char *dir,
- kwsys_stl::string& filename_found,
+bool SystemTools::LocateFileInDir(const char* filename, const char* dir,
+ std::string& filename_found,
int try_filename_dirs)
{
- if (!filename || !dir)
- {
+ if (!filename || !dir) {
return false;
- }
+ }
// Get the basename of 'filename'
- kwsys_stl::string filename_base = SystemTools::GetFilenameName(filename);
+ std::string filename_base = SystemTools::GetFilenameName(filename);
// Check if 'dir' is really a directory
// If win32 and matches something like C:, accept it as a dir
- kwsys_stl::string real_dir;
- if (!SystemTools::FileIsDirectory(dir))
- {
-#if defined( _WIN32 )
+ std::string real_dir;
+ if (!SystemTools::FileIsDirectory(dir)) {
+#if defined(_WIN32)
size_t dir_len = strlen(dir);
- if (dir_len < 2 || dir[dir_len - 1] != ':')
- {
+ if (dir_len < 2 || dir[dir_len - 1] != ':') {
#endif
real_dir = SystemTools::GetFilenamePath(dir);
dir = real_dir.c_str();
-#if defined( _WIN32 )
- }
-#endif
+#if defined(_WIN32)
}
+#endif
+ }
// Try to find the file in 'dir'
bool res = false;
- if (filename_base.size() && dir)
- {
+ if (!filename_base.empty() && dir) {
size_t dir_len = strlen(dir);
int need_slash =
(dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\');
- kwsys_stl::string temp = dir;
- if (need_slash)
- {
+ std::string temp = dir;
+ if (need_slash) {
temp += "/";
- }
+ }
temp += filename_base;
- if (SystemTools::FileExists(temp.c_str()))
- {
+ if (SystemTools::FileExists(temp)) {
res = true;
filename_found = temp;
- }
+ }
// If not found, we can try harder by appending part of the file to
// to the directory to look inside.
// Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
// try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
- else if (try_filename_dirs)
- {
- kwsys_stl::string filename_dir(filename);
- kwsys_stl::string filename_dir_base;
- kwsys_stl::string filename_dir_bases;
- do
- {
+ else if (try_filename_dirs) {
+ std::string filename_dir(filename);
+ std::string filename_dir_base;
+ std::string filename_dir_bases;
+ do {
filename_dir = SystemTools::GetFilenamePath(filename_dir);
filename_dir_base = SystemTools::GetFilenameName(filename_dir);
-#if defined( _WIN32 )
- if (!filename_dir_base.size() ||
- filename_dir_base[filename_dir_base.size() - 1] == ':')
+#if defined(_WIN32)
+ if (filename_dir_base.empty() || *filename_dir_base.rbegin() == ':')
#else
- if (!filename_dir_base.size())
+ if (filename_dir_base.empty())
#endif
- {
+ {
break;
- }
+ }
filename_dir_bases = filename_dir_base + "/" + filename_dir_bases;
temp = dir;
- if (need_slash)
- {
+ if (need_slash) {
temp += "/";
- }
+ }
temp += filename_dir_bases;
- res = SystemTools::LocateFileInDir(
- filename_base.c_str(), temp.c_str(), filename_found, 0);
+ res = SystemTools::LocateFileInDir(filename_base.c_str(), temp.c_str(),
+ filename_found, 0);
- } while (!res && filename_dir_base.size());
- }
+ } while (!res && !filename_dir_base.empty());
}
+ }
return res;
}
+bool SystemTools::FileIsFullPath(const std::string& in_name)
+{
+ return SystemTools::FileIsFullPath(in_name.c_str(), in_name.size());
+}
+
bool SystemTools::FileIsFullPath(const char* in_name)
{
- kwsys_stl::string name = in_name;
+ return SystemTools::FileIsFullPath(in_name,
+ in_name[0] ? (in_name[1] ? 2 : 1) : 0);
+}
+
+bool SystemTools::FileIsFullPath(const char* in_name, size_t len)
+{
#if defined(_WIN32) || defined(__CYGWIN__)
// On Windows, the name must be at least two characters long.
- if(name.length() < 2)
- {
+ if (len < 2) {
return false;
- }
- if(name[1] == ':')
- {
+ }
+ if (in_name[1] == ':') {
return true;
- }
- if(name[0] == '\\')
- {
+ }
+ if (in_name[0] == '\\') {
return true;
- }
+ }
#else
// On UNIX, the name must be at least one character long.
- if(name.length() < 1)
- {
+ if (len < 1) {
return false;
- }
+ }
#endif
#if !defined(_WIN32)
- if(name[0] == '~')
- {
+ if (in_name[0] == '~') {
return true;
- }
+ }
#endif
// On UNIX, the name must begin in a '/'.
// On Windows, if the name begins in a '/', then it is a full
// network path.
- if(name[0] == '/')
- {
+ if (in_name[0] == '/') {
return true;
- }
+ }
return false;
}
-bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
+bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
{
-#if defined(WIN32) && !defined(__CYGWIN__)
- const int size = int(strlen(path)) +1; // size of return
- char *buffer = new char[size]; // create a buffer
- char *tempPath = new char[size]; // create a buffer
- int ret;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ std::string tempPath = path; // create a buffer
// if the path passed in has quotes around it, first remove the quotes
- if (path[0] == '"' && path[strlen(path)-1] == '"')
- {
- strcpy(tempPath,path+1);
- tempPath[strlen(tempPath)-1] = '\0';
- }
- else
- {
- strcpy(tempPath,path);
- }
+ if (!path.empty() && path[0] == '"' && *path.rbegin() == '"') {
+ tempPath = path.substr(1, path.length() - 2);
+ }
- buffer[0] = 0;
- ret = GetShortPathName(tempPath, buffer, size);
+ std::wstring wtempPath = Encoding::ToWide(tempPath);
+ DWORD ret = GetShortPathNameW(wtempPath.c_str(), NULL, 0);
+ std::vector<wchar_t> buffer(ret);
+ if (ret != 0) {
+ ret = GetShortPathNameW(wtempPath.c_str(), &buffer[0],
+ static_cast<DWORD>(buffer.size()));
+ }
- if(buffer[0] == 0 || ret > size)
- {
- delete [] buffer;
- delete [] tempPath;
+ if (ret == 0) {
return false;
- }
- else
- {
- shortPath = buffer;
- delete [] buffer;
- delete [] tempPath;
+ } else {
+ shortPath = Encoding::ToNarrow(&buffer[0]);
return true;
- }
+ }
#else
shortPath = path;
return true;
#endif
}
-void SystemTools::SplitProgramFromArgs(const char* path,
- kwsys_stl::string& program, kwsys_stl::string& args)
+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))
- {
+ 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
- kwsys_stl::vector<kwsys_stl::string> e;
- kwsys_stl::string findProg = SystemTools::FindProgram(path, e);
- if(findProg.size())
- {
+ 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
- kwsys_stl::string dir = path;
- kwsys_stl::string::size_type spacePos = dir.rfind(' ');
- while(spacePos != kwsys_stl::string::npos)
- {
- kwsys_stl::string tryProg = dir.substr(0, spacePos);
+ 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.c_str()))
- {
+ if (SystemTools::FileExists(tryProg)) {
program = tryProg;
// remove trailing spaces from program
- kwsys_stl::string::size_type pos = program.size()-1;
- while(program[pos] == ' ')
- {
+ std::string::size_type pos = program.size() - 1;
+ while (program[pos] == ' ') {
program.erase(pos);
pos--;
- }
- args = dir.substr(spacePos, dir.size()-spacePos);
- return;
}
+ args = dir.substr(spacePos, dir.size() - spacePos);
+ return;
+ }
// Now try and find the program in the path
- findProg = SystemTools::FindProgram(tryProg.c_str(), e);
- if(findProg.size())
- {
+ findProg = SystemTools::FindProgram(tryProg, e);
+ if (!findProg.empty()) {
program = findProg;
// remove trailing spaces from program
- kwsys_stl::string::size_type pos = program.size()-1;
- while(program[pos] == ' ')
- {
+ std::string::size_type pos = program.size() - 1;
+ while (program[pos] == ' ') {
program.erase(pos);
pos--;
- }
- args = dir.substr(spacePos, dir.size()-spacePos);
- return;
}
+ args = dir.substr(spacePos, dir.size() - spacePos);
+ return;
+ }
// move past the space for the next search
spacePos--;
spacePos = dir.rfind(' ', spacePos);
- }
+ }
program = "";
args = "";
}
-kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
+std::string SystemTools::GetCurrentDateTime(const char* format)
{
char buf[1024];
time_t t;
time(&t);
strftime(buf, sizeof(buf), format, localtime(&t));
- return kwsys_stl::string(buf);
+ return std::string(buf);
}
-kwsys_stl::string SystemTools::MakeCidentifier(const char* s)
+std::string SystemTools::MakeCidentifier(const std::string& s)
{
- kwsys_stl::string str(s);
- if (str.find_first_of("0123456789") == 0)
- {
+ std::string str(s);
+ if (str.find_first_of("0123456789") == 0) {
str = "_" + str;
- }
+ }
- kwsys_stl::string permited_chars("_"
+ std::string permited_chars("_"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789");
- kwsys_stl::string::size_type pos = 0;
- while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos)
- {
+ std::string::size_type pos = 0;
+ while ((pos = str.find_first_not_of(permited_chars, pos)) !=
+ std::string::npos) {
str[pos] = '_';
- }
+ }
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
// if any data were read before the end-of-file was reached.
-bool SystemTools::GetLineFromStream(kwsys_ios::istream& is,
- kwsys_stl::string& line,
+bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
bool* has_newline /* = 0 */,
long sizeLimit /* = -1 */)
{
@@ -4118,62 +4233,52 @@ bool SystemTools::GetLineFromStream(kwsys_ios::istream& is,
// false and the empty line. (Probably means caller tried to
// create a file stream with a non-existent file name...)
//
- if(!is)
- {
- if(has_newline)
- {
+ if (!is) {
+ if (has_newline) {
*has_newline = false;
- }
- return false;
}
+ 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 &&
- (is.clear(is.rdstate() & ~kwsys_ios::ios::failbit),
- is.getline(buffer, bufferSize), is.gcount() > 0))
- {
+ 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()))
- {
+ if (length < static_cast<size_t>(is.gcount())) {
haveNewline = true;
- }
+ }
// Avoid storing a carriage return character.
- if(length > 0 && buffer[length-1] == '\r')
- {
- buffer[length-1] = 0;
- }
+ if (length > 0 && buffer[length - 1] == '\r') {
+ buffer[length - 1] = 0;
+ }
// if we read too much then truncate the buffer
- if (leftToRead > 0)
- {
- if (static_cast<long>(length) > leftToRead)
- {
- buffer[leftToRead-1] = 0;
+ if (leftToRead > 0) {
+ if (static_cast<long>(length) > leftToRead) {
+ buffer[leftToRead] = 0;
leftToRead = 0;
- }
- else
- {
+ } else {
leftToRead -= static_cast<long>(length);
- }
}
+ }
// Append the data read to the line.
line.append(buffer);
- }
+ }
// Return the results.
- if(has_newline)
- {
+ if (has_newline) {
*has_newline = haveNewline;
- }
+ }
return haveData;
}
@@ -4182,88 +4287,122 @@ int SystemTools::GetTerminalWidth()
int width = -1;
#ifdef HAVE_TTY_INFO
struct winsize ws;
- char *columns; /* Unix98 environment variable */
- if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
- {
+ std::string columns; /* Unix98 environment variable */
+ if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 0 && ws.ws_row > 0) {
width = ws.ws_col;
- }
- if(!isatty(STDOUT_FILENO))
- {
+ }
+ if (!isatty(STDOUT_FILENO)) {
width = -1;
- }
- columns = getenv("COLUMNS");
- if(columns && *columns)
- {
+ }
+ if (SystemTools::GetEnv("COLUMNS", columns) && !columns.empty()) {
long t;
- char *endptr;
- t = strtol(columns, &endptr, 0);
- if(endptr && !*endptr && (t>0) && (t<1000))
- {
+ char* endptr;
+ t = strtol(columns.c_str(), &endptr, 0);
+ if (endptr && !*endptr && (t > 0) && (t < 1000)) {
width = static_cast<int>(t);
- }
}
- if ( width < 9 )
- {
+ }
+ if (width < 9) {
width = -1;
- }
+ }
#endif
return width;
}
bool SystemTools::GetPermissions(const char* file, mode_t& mode)
{
- if ( !file )
- {
+ if (!file) {
return false;
- }
+ }
+ return SystemTools::GetPermissions(std::string(file), mode);
+}
+bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
+{
+#if defined(_WIN32)
+ DWORD attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str());
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+ if ((attr & FILE_ATTRIBUTE_READONLY) != 0) {
+ mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6));
+ } else {
+ mode = (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) |
+ (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6));
+ }
+ if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ mode |= S_IFDIR | (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6));
+ } else {
+ mode |= S_IFREG;
+ }
+ 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)) {
+ mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6));
+ }
+#else
struct stat st;
- if ( stat(file, &st) < 0 )
- {
+ if (stat(file.c_str(), &st) < 0) {
return false;
- }
+ }
mode = st.st_mode;
+#endif
return true;
}
-bool SystemTools::SetPermissions(const char* file, mode_t mode)
+bool SystemTools::SetPermissions(const char* file, mode_t mode,
+ bool honor_umask)
{
- if ( !file )
- {
+ if (!file) {
return false;
- }
- if ( !SystemTools::FileExists(file) )
- {
+ }
+ return SystemTools::SetPermissions(std::string(file), mode, honor_umask);
+}
+
+bool SystemTools::SetPermissions(const std::string& file, mode_t mode,
+ bool honor_umask)
+{
+ if (!SystemTools::PathExists(file)) {
return false;
- }
- if ( chmod(file, mode) < 0 )
- {
+ }
+ if (honor_umask) {
+ mode_t currentMask = umask(0);
+ umask(currentMask);
+ mode &= ~currentMask;
+ }
+#ifdef _WIN32
+ if (_wchmod(Encoding::ToWindowsExtendedPath(file).c_str(), mode) < 0)
+#else
+ if (chmod(file.c_str(), mode) < 0)
+#endif
+ {
return false;
- }
+ }
return true;
}
-kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir)
+std::string SystemTools::GetParentDirectory(const std::string& fileOrDir)
{
return SystemTools::GetFilenamePath(fileOrDir);
}
-bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir)
+bool SystemTools::IsSubDirectory(const std::string& cSubdir,
+ const std::string& cDir)
{
- if(!*cDir)
- {
+ if (cDir.empty()) {
return false;
- }
- kwsys_stl::string subdir = cSubdir;
- kwsys_stl::string dir = cDir;
+ }
+ std::string subdir = cSubdir;
+ std::string dir = cDir;
SystemTools::ConvertToUnixSlashes(subdir);
SystemTools::ConvertToUnixSlashes(dir);
- if(subdir.size() > dir.size() && subdir[dir.size()] == '/')
- {
+ if (subdir.size() > dir.size() && subdir[dir.size()] == '/') {
std::string s = subdir.substr(0, dir.size());
- return SystemTools::ComparePath(s.c_str(), dir.c_str());
- }
+ return SystemTools::ComparePath(s, dir);
+ }
return false;
}
@@ -4279,313 +4418,194 @@ void SystemTools::Delay(unsigned int msec)
// atomically. If select is given empty sets and zero as the max
// file descriptor but a non-zero timeout it can be used to block
// for a precise amount of time.
- if(msec >= 1000)
- {
+ if (msec >= 1000) {
sleep(msec / 1000);
usleep((msec % 1000) * 1000);
- }
- else
- {
+ } else {
usleep(msec * 1000);
- }
+ }
#endif
}
-void SystemTools::ConvertWindowsCommandLineToUnixArguments(
- const char *cmd_line, int *argc, char ***argv)
+std::string SystemTools::GetOperatingSystemNameAndVersion()
{
- if (!cmd_line || !argc || !argv)
- {
- return;
- }
-
- // A space delimites an argument except when it is inside a quote
-
- (*argc) = 1;
-
- size_t cmd_line_len = strlen(cmd_line);
+ std::string res;
- size_t i;
- for (i = 0; i < cmd_line_len; i++)
- {
- while (isspace(cmd_line[i]) && i < cmd_line_len)
- {
- i++;
- }
- if (i < cmd_line_len)
- {
- if (cmd_line[i] == '\"')
- {
- i++;
- while (cmd_line[i] != '\"' && i < cmd_line_len)
- {
- i++;
- }
- (*argc)++;
- }
- else
- {
- while (!isspace(cmd_line[i]) && i < cmd_line_len)
- {
- i++;
- }
- (*argc)++;
- }
- }
- }
+#ifdef _WIN32
+ char buffer[256];
- (*argv) = new char* [(*argc) + 1];
- (*argv)[(*argc)] = NULL;
+ OSVERSIONINFOEXA osvi;
+ BOOL bOsVersionInfoEx;
- // Set the first arg to be the exec name
+ ZeroMemory(&osvi, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
- (*argv)[0] = new char [1024];
-#ifdef _WIN32
- ::GetModuleFileName(0, (*argv)[0], 1024);
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(push)
+#ifdef __INTEL_COMPILER
+#pragma warning(disable : 1478)
#else
- (*argv)[0][0] = '\0';
+#pragma warning(disable : 4996)
+#endif
+#endif
+ bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi);
+ if (!bOsVersionInfoEx) {
+ return 0;
+ }
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+#pragma warning(pop)
#endif
- // Allocate the others
-
- int j;
- for (j = 1; j < (*argc); j++)
- {
- (*argv)[j] = new char [cmd_line_len + 10];
- }
-
- // Grab the args
+ switch (osvi.dwPlatformId) {
+ // Test for the Windows NT product family.
- size_t pos;
- int argc_idx = 1;
+ case VER_PLATFORM_WIN32_NT:
- for (i = 0; i < cmd_line_len; i++)
- {
- while (isspace(cmd_line[i]) && i < cmd_line_len)
- {
- i++;
- }
- if (i < cmd_line_len)
- {
- if (cmd_line[i] == '\"')
- {
- i++;
- pos = i;
- while (cmd_line[i] != '\"' && i < cmd_line_len)
- {
- i++;
- }
- memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
- (*argv)[argc_idx][i - pos] = '\0';
- argc_idx++;
- }
- else
- {
- pos = i;
- while (!isspace(cmd_line[i]) && i < cmd_line_len)
- {
- i++;
- }
- memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos);
- (*argv)[argc_idx][i - pos] = '\0';
- argc_idx++;
+ // Test for the specific product family.
+ if (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ res += "Microsoft Windows 10";
+ } else {
+ res += "Microsoft Windows Server 2016 family";
}
}
- }
- }
-
-kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
-{
- kwsys_stl::string res;
-
-#ifdef _WIN32
- char buffer[256];
-
- OSVERSIONINFOEX osvi;
- BOOL bOsVersionInfoEx;
-
- // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
- // If that fails, try using the OSVERSIONINFO structure.
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
- if (!bOsVersionInfoEx)
- {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx((OSVERSIONINFO *)&osvi))
- {
- return 0;
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ res += "Microsoft Windows 8.1";
+ } else {
+ res += "Microsoft Windows Server 2012 R2 family";
+ }
}
- }
-
- switch (osvi.dwPlatformId)
- {
- // Test for the Windows NT product family.
- case VER_PLATFORM_WIN32_NT:
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ res += "Microsoft Windows 8";
+ } else {
+ res += "Microsoft Windows Server 2012 family";
+ }
+ }
- // Test for the specific product family.
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ res += "Microsoft Windows 7";
+ } else {
+ res += "Microsoft Windows Server 2008 R2 family";
+ }
+ }
- if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
- {
-#if (_MSC_VER >= 1300)
- if (osvi.wProductType == VER_NT_WORKSTATION)
- {
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
res += "Microsoft Windows Vista";
- }
- else
- {
+ } else {
res += "Microsoft Windows Server 2008 family";
- }
-#else
- res += "Microsoft Windows Vista or Windows Server 2008";
-#endif
}
+ }
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
- {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
res += "Microsoft Windows Server 2003 family";
- }
+ }
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
res += "Microsoft Windows XP";
- }
+ }
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
- {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
res += "Microsoft Windows 2000";
- }
+ }
- if (osvi.dwMajorVersion <= 4)
- {
+ if (osvi.dwMajorVersion <= 4) {
res += "Microsoft Windows NT";
- }
+ }
// Test for specific product on Windows NT 4.0 SP6 and later.
- if (bOsVersionInfoEx)
- {
+ if (bOsVersionInfoEx) {
// Test for the workstation type.
-#if (_MSC_VER >= 1300)
- if (osvi.wProductType == VER_NT_WORKSTATION)
- {
- if (osvi.dwMajorVersion == 4)
- {
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ if (osvi.dwMajorVersion == 4) {
res += " Workstation 4.0";
- }
- else if (osvi.dwMajorVersion == 5)
- {
- if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- {
+ } else if (osvi.dwMajorVersion == 5) {
+ if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
res += " Home Edition";
- }
- else
- {
+ } else {
res += " Professional";
- }
}
}
+ }
// Test for the server type.
- else if (osvi.wProductType == VER_NT_SERVER)
- {
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
- {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- {
+ else if (osvi.wProductType == VER_NT_SERVER) {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
res += " Datacenter Edition";
- }
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- {
+ } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
res += " Enterprise Edition";
- }
- else if (osvi.wSuiteMask == VER_SUITE_BLADE)
- {
+ } else if (osvi.wSuiteMask == VER_SUITE_BLADE) {
res += " Web Edition";
- }
- else
- {
+ } else {
res += " Standard Edition";
- }
}
+ }
- else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
- {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- {
+ else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
res += " Datacenter Server";
- }
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- {
+ } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
res += " Advanced Server";
- }
- else
- {
+ } else {
res += " Server";
- }
}
+ }
- else if (osvi.dwMajorVersion <= 4) // Windows NT 4.0
- {
- if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- {
+ else if (osvi.dwMajorVersion <= 4) // Windows NT 4.0
+ {
+ if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
res += " Server 4.0, Enterprise Edition";
- }
- else
- {
+ } else {
res += " Server 4.0";
- }
}
}
-#endif // Visual Studio 7 and up
}
+ }
// Test for specific product on Windows NT 4.0 SP5 and earlier
- else
- {
+ else {
HKEY hKey;
- #define BUFSIZE 80
- char szProductType[BUFSIZE];
- DWORD dwBufLen=BUFSIZE;
+#define BUFSIZE 80
+ wchar_t szProductType[BUFSIZE];
+ DWORD dwBufLen = BUFSIZE;
LONG lRet;
- lRet = RegOpenKeyEx(
- HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
- 0, KEY_QUERY_VALUE, &hKey);
- if (lRet != ERROR_SUCCESS)
- {
+ lRet =
+ RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
+ 0, KEY_QUERY_VALUE, &hKey);
+ if (lRet != ERROR_SUCCESS) {
return 0;
- }
+ }
- lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL,
- (LPBYTE) szProductType, &dwBufLen);
+ lRet = RegQueryValueExW(hKey, L"ProductType", NULL, NULL,
+ (LPBYTE)szProductType, &dwBufLen);
- if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
- {
+ if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE)) {
return 0;
- }
+ }
RegCloseKey(hKey);
- if (lstrcmpi("WINNT", szProductType) == 0)
- {
+ if (lstrcmpiW(L"WINNT", szProductType) == 0) {
res += " Workstation";
- }
- if (lstrcmpi("LANMANNT", szProductType) == 0)
- {
+ }
+ if (lstrcmpiW(L"LANMANNT", szProductType) == 0) {
res += " Server";
- }
- if (lstrcmpi("SERVERNT", szProductType) == 0)
- {
+ }
+ if (lstrcmpiW(L"SERVERNT", szProductType) == 0) {
res += " Advanced Server";
- }
+ }
res += " ";
sprintf(buffer, "%ld", osvi.dwMajorVersion);
@@ -4593,121 +4613,109 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion()
res += ".";
sprintf(buffer, "%ld", osvi.dwMinorVersion);
res += buffer;
- }
+ }
// Display service pack (if any) and build number.
if (osvi.dwMajorVersion == 4 &&
- lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0)
- {
+ lstrcmpiA(osvi.szCSDVersion, "Service Pack 6") == 0) {
HKEY hKey;
LONG lRet;
// Test for SP6 versus SP6a.
- lRet = RegOpenKeyEx(
+ lRet = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
- "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
0, KEY_QUERY_VALUE, &hKey);
- if (lRet == ERROR_SUCCESS)
- {
+ if (lRet == ERROR_SUCCESS) {
res += " Service Pack 6a (Build ";
sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
res += ")";
- }
- else // Windows NT 4.0 prior to SP6a
- {
+ } else // Windows NT 4.0 prior to SP6a
+ {
res += " ";
res += osvi.szCSDVersion;
res += " (Build ";
sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
res += ")";
- }
+ }
RegCloseKey(hKey);
- }
- else // Windows NT 3.51 and earlier or Windows 2000 and later
- {
+ } else // Windows NT 3.51 and earlier or Windows 2000 and later
+ {
res += " ";
res += osvi.szCSDVersion;
res += " (Build ";
sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
res += ")";
- }
+ }
break;
- // Test for the Windows 95 product family.
+ // Test for the Windows 95 product family.
case VER_PLATFORM_WIN32_WINDOWS:
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
- {
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
res += "Microsoft Windows 95";
- if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
- {
+ if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') {
res += " OSR2";
- }
}
+ }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
- {
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
res += "Microsoft Windows 98";
- if (osvi.szCSDVersion[1] == 'A')
- {
+ if (osvi.szCSDVersion[1] == 'A') {
res += " SE";
- }
}
+ }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
- {
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) {
res += "Microsoft Windows Millennium Edition";
- }
+ }
break;
case VER_PLATFORM_WIN32s:
- res += "Microsoft Win32s";
+ res += "Microsoft Win32s";
break;
- }
+ }
#endif
return res;
}
-// ----------------------------------------------------------------------
-bool SystemTools::ParseURLProtocol( const kwsys_stl::string& URL,
- kwsys_stl::string& protocol,
- kwsys_stl::string& dataglom )
+bool SystemTools::ParseURLProtocol(const std::string& URL,
+ std::string& protocol,
+ std::string& dataglom)
{
// match 0 entire url
// match 1 protocol
// match 2 dataglom following protocol://
- kwsys::RegularExpression urlRe( VTK_URL_PROTOCOL_REGEX );
+ kwsys::RegularExpression urlRe(VTK_URL_PROTOCOL_REGEX);
- if ( ! urlRe.find( URL ) ) return false;
+ if (!urlRe.find(URL))
+ return false;
- protocol = urlRe.match( 1 );
- dataglom = urlRe.match( 2 );
+ protocol = urlRe.match(1);
+ dataglom = urlRe.match(2);
return true;
}
-// ----------------------------------------------------------------------
-bool SystemTools::ParseURL( const kwsys_stl::string& URL,
- kwsys_stl::string& protocol,
- kwsys_stl::string& username,
- kwsys_stl::string& password,
- kwsys_stl::string& hostname,
- kwsys_stl::string& dataport,
- kwsys_stl::string& database )
+bool SystemTools::ParseURL(const std::string& URL, std::string& protocol,
+ std::string& username, std::string& password,
+ std::string& hostname, std::string& dataport,
+ std::string& database)
{
- kwsys::RegularExpression urlRe( VTK_URL_REGEX );
- if ( ! urlRe.find( URL ) ) return false;
+ kwsys::RegularExpression urlRe(VTK_URL_REGEX);
+ if (!urlRe.find(URL))
+ return false;
// match 0 URL
// match 1 protocol
@@ -4720,24 +4728,26 @@ bool SystemTools::ParseURL( const kwsys_stl::string& URL,
// match 8 dataport
// match 9 database name
- protocol = urlRe.match( 1 );
- username = urlRe.match( 3 );
- password = urlRe.match( 5 );
- hostname = urlRe.match( 6 );
- dataport = urlRe.match( 8 );
- database = urlRe.match( 9 );
+ protocol = urlRe.match(1);
+ username = urlRe.match(3);
+ password = urlRe.match(5);
+ hostname = urlRe.match(6);
+ dataport = urlRe.match(8);
+ database = urlRe.match(9);
return true;
}
-// ----------------------------------------------------------------------
// These must NOT be initialized. Default initialization to zero is
// necessary.
static unsigned int SystemToolsManagerCount;
-SystemToolsTranslationMap *SystemTools::TranslationMap;
-SystemToolsTranslationMap *SystemTools::LongPathMap;
+SystemToolsTranslationMap* SystemTools::TranslationMap;
+#ifdef _WIN32
+SystemToolsPathCaseMap* SystemTools::PathCaseMap;
+SystemToolsEnvMap* SystemTools::EnvMap;
+#endif
#ifdef __CYGWIN__
-SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
+SystemToolsTranslationMap* SystemTools::Cyg2Win32Map;
#endif
// SystemToolsManager manages the SystemTools singleton.
@@ -4748,24 +4758,22 @@ SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
SystemToolsManager::SystemToolsManager()
{
- if(++SystemToolsManagerCount == 1)
- {
+ if (++SystemToolsManagerCount == 1) {
SystemTools::ClassInitialize();
- }
+ }
}
SystemToolsManager::~SystemToolsManager()
{
- if(--SystemToolsManagerCount == 0)
- {
+ if (--SystemToolsManagerCount == 0) {
SystemTools::ClassFinalize();
- }
+ }
}
#if defined(__VMS)
// On VMS we configure the run time C library to be more UNIX like.
// http://h71000.www7.hp.com/doc/732final/5763/5763pro_004.html
-extern "C" int decc$feature_get_index(char *name);
+extern "C" int decc$feature_get_index(char* name);
extern "C" int decc$feature_set_value(int index, int mode, int value);
static int SetVMSFeature(char* name, int value)
{
@@ -4783,78 +4791,77 @@ void SystemTools::ClassInitialize()
#endif
// Allocate the translation map first.
SystemTools::TranslationMap = new SystemToolsTranslationMap;
- SystemTools::LongPathMap = new SystemToolsTranslationMap;
+#ifdef _WIN32
+ SystemTools::PathCaseMap = new SystemToolsPathCaseMap;
+ SystemTools::EnvMap = new SystemToolsEnvMap;
+#endif
#ifdef __CYGWIN__
SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap;
#endif
- // 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.
+// 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__)
// The tmp path is frequently a logical path so always keep it:
SystemTools::AddKeepPath("/tmp/");
// If the current working directory is a logical path then keep the
// logical name.
- if(const char* pwd = getenv("PWD"))
- {
+ std::string pwd_str;
+ if (SystemTools::GetEnv("PWD", pwd_str)) {
char buf[2048];
- if(const char* cwd = Getcwd(buf, 2048))
- {
+ if (const char* cwd = Getcwd(buf, 2048)) {
// The current working directory may be a logical path. Find
// the shortest logical path that still produces the correct
// physical path.
- kwsys_stl::string cwd_changed;
- kwsys_stl::string pwd_changed;
+ std::string cwd_changed;
+ std::string pwd_changed;
// Test progressively shorter logical-to-physical mappings.
- kwsys_stl::string pwd_str = pwd;
- kwsys_stl::string cwd_str = cwd;
- kwsys_stl::string pwd_path;
- Realpath(pwd, pwd_path);
- while(cwd_str == pwd_path && cwd_str != pwd_str)
- {
+ std::string cwd_str = cwd;
+ std::string pwd_path;
+ Realpath(pwd_str.c_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;
pwd_changed = pwd_str;
// Strip off one directory level and see if the logical
// mapping still works.
- pwd_str = SystemTools::GetFilenamePath(pwd_str.c_str());
- cwd_str = SystemTools::GetFilenamePath(cwd_str.c_str());
+ pwd_str = SystemTools::GetFilenamePath(pwd_str);
+ cwd_str = SystemTools::GetFilenamePath(cwd_str);
Realpath(pwd_str.c_str(), pwd_path);
- }
+ }
// Add the translation to keep the logical path name.
- if(!cwd_changed.empty() && !pwd_changed.empty())
- {
- SystemTools::AddTranslationPath(cwd_changed.c_str(),
- pwd_changed.c_str());
- }
+ if (!cwd_changed.empty() && !pwd_changed.empty()) {
+ SystemTools::AddTranslationPath(cwd_changed, pwd_changed);
}
}
+ }
#endif
}
void SystemTools::ClassFinalize()
{
delete SystemTools::TranslationMap;
- delete SystemTools::LongPathMap;
+#ifdef _WIN32
+ delete SystemTools::PathCaseMap;
+ delete SystemTools::EnvMap;
+#endif
#ifdef __CYGWIN__
delete SystemTools::Cyg2Win32Map;
#endif
}
-
} // namespace KWSYS_NAMESPACE
#if defined(_MSC_VER) && defined(_DEBUG)
-# include <crtdbg.h>
-# include <stdio.h>
-# include <stdlib.h>
-namespace KWSYS_NAMESPACE
-{
+#include <crtdbg.h>
+#include <stdio.h>
+#include <stdlib.h>
+namespace KWSYS_NAMESPACE {
static int SystemToolsDebugReport(int, char* message, int*)
{
@@ -4865,17 +4872,17 @@ static int SystemToolsDebugReport(int, char* message, int*)
void SystemTools::EnableMSVCDebugHook()
{
- if (getenv("DART_TEST_FROM_DART") ||
- getenv("DASHBOARD_TEST_FROM_CTEST"))
- {
+ if (SystemTools::HasEnv("DART_TEST_FROM_DART") ||
+ SystemTools::HasEnv("DASHBOARD_TEST_FROM_CTEST")) {
_CrtSetReportHook(SystemToolsDebugReport);
- }
+ }
}
} // namespace KWSYS_NAMESPACE
#else
-namespace KWSYS_NAMESPACE
+namespace KWSYS_NAMESPACE {
+void SystemTools::EnableMSVCDebugHook()
{
-void SystemTools::EnableMSVCDebugHook() {}
+}
} // namespace KWSYS_NAMESPACE
#endif
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index d6dae3986..5e091c2af 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -1,61 +1,52 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_SystemTools_hxx
#define @KWSYS_NAMESPACE@_SystemTools_hxx
-#include <@KWSYS_NAMESPACE@/ios/iosfwd>
-#include <@KWSYS_NAMESPACE@/stl/string>
-#include <@KWSYS_NAMESPACE@/stl/vector>
-#include <@KWSYS_NAMESPACE@/stl/map>
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <vector>
-#include <@KWSYS_NAMESPACE@/Configure.h>
#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()
+#endif
// Required for va_list
#include <stdarg.h>
-#if @KWSYS_NAMESPACE@_STL_HAVE_STD && !defined(va_list)
+// Required for FILE*
+#include <stdio.h>
+#if !defined(va_list)
// Some compilers move va_list into the std namespace and there is no way to
// tell that this has been done. Playing with things being included before or
// after stdarg.h does not solve things because we do not have control over
// what the user does. This hack solves this problem by moving va_list to our
// own namespace that is local for kwsys.
-namespace std {} // Required for platforms that do not have std namespace
-namespace @KWSYS_NAMESPACE@_VA_LIST
-{
- using namespace std;
- typedef va_list hack_va_list;
+namespace std {
+} // Required for platforms that do not have std namespace
+namespace @KWSYS_NAMESPACE@_VA_LIST {
+using namespace std;
+typedef va_list hack_va_list;
}
-namespace @KWSYS_NAMESPACE@
-{
- typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list;
+namespace @KWSYS_NAMESPACE@ {
+typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list;
}
#endif // va_list
-#if defined( _MSC_VER )
-typedef unsigned short mode_t;
-#endif
-
-/* Define these macros temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsys_stl @KWSYS_NAMESPACE@_stl
-# define kwsys_ios @KWSYS_NAMESPACE@_ios
-#endif
-
-namespace @KWSYS_NAMESPACE@
-{
+namespace @KWSYS_NAMESPACE@ {
class SystemToolsTranslationMap;
+class SystemToolsPathCaseMap;
+class SystemToolsEnvMap;
+
/** \class SystemToolsManager
* \brief Use to make sure SystemTools is initialized before it is used
* and is the last static object destroyed
@@ -68,17 +59,34 @@ public:
};
// This instance will show up in any translation unit that uses
-// SystemTools. It will make sure SystemTools is initialized
+// SystemTools. It will make sure SystemTools is initialized
// before it is used and is the last static object destroyed.
static SystemToolsManager SystemToolsManagerInstance;
+// Flags for use with TestFileAccess. Use a typedef in case any operating
+// system in the future needs a special type. These are flags that may be
+// combined using the | operator.
+typedef int TestFilePermissions;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+// On Windows (VC and Borland), no system header defines these constants...
+static const TestFilePermissions TEST_FILE_OK = 0;
+static const TestFilePermissions TEST_FILE_READ = 4;
+static const TestFilePermissions TEST_FILE_WRITE = 2;
+static const TestFilePermissions TEST_FILE_EXECUTE = 1;
+#else
+// Standard POSIX constants
+static const TestFilePermissions TEST_FILE_OK = F_OK;
+static const TestFilePermissions TEST_FILE_READ = R_OK;
+static const TestFilePermissions TEST_FILE_WRITE = W_OK;
+static const TestFilePermissions TEST_FILE_EXECUTE = X_OK;
+#endif
+
/** \class SystemTools
* \brief A collection of useful platform-independent system functions.
*/
class @KWSYS_NAMESPACE@_EXPORT SystemTools
{
public:
-
/** -----------------------------------------------------------------
* String Manipulation Routines
* -----------------------------------------------------------------
@@ -91,9 +99,9 @@ public:
* then an underscore is prepended. Note that this can produce
* identifiers that the standard reserves (_[A-Z].* and __.*).
*/
- static kwsys_stl::string MakeCidentifier(const char* s);
+ static std::string MakeCidentifier(const std::string& s);
- static kwsys_stl::string MakeCindentifier(const char* s)
+ static std::string MakeCindentifier(const std::string& s)
{
return MakeCidentifier(s);
}
@@ -101,118 +109,123 @@ public:
/**
* Replace replace all occurences of the string in the source string.
*/
- static void ReplaceString(kwsys_stl::string& source,
- const char* replace,
+ static void ReplaceString(std::string& source, const char* replace,
const char* with);
+ static void ReplaceString(std::string& source, const std::string& replace,
+ const std::string& with);
/**
* Return a capitalized string (i.e the first letter is uppercased,
* all other are lowercased).
*/
- static kwsys_stl::string Capitalized(const kwsys_stl::string&);
-
+ static std::string Capitalized(const std::string&);
+
/**
* Return a 'capitalized words' string (i.e the first letter of each word
* is uppercased all other are left untouched though).
*/
- static kwsys_stl::string CapitalizedWords(const kwsys_stl::string&);
-
+ static std::string CapitalizedWords(const std::string&);
+
/**
* Return a 'uncapitalized words' string (i.e the first letter of each word
* is lowercased all other are left untouched though).
*/
- static kwsys_stl::string UnCapitalizedWords(const kwsys_stl::string&);
-
+ static std::string UnCapitalizedWords(const std::string&);
+
/**
* Return a lower case string
*/
- static kwsys_stl::string LowerCase(const kwsys_stl::string&);
-
+ static std::string LowerCase(const std::string&);
+
/**
* Return a lower case string
*/
- static kwsys_stl::string UpperCase(const kwsys_stl::string&);
-
+ static std::string UpperCase(const std::string&);
+
/**
* Count char in string
*/
static size_t CountChar(const char* str, char c);
-
+
/**
* Remove some characters from a string.
* Return a pointer to the new resulting string (allocated with 'new')
*/
- static char* RemoveChars(const char* str, const char *toremove);
+ static char* RemoveChars(const char* str, const char* toremove);
/**
* Remove remove all but 0->9, A->F characters from a string.
* Return a pointer to the new resulting string (allocated with 'new')
*/
static char* RemoveCharsButUpperHex(const char* str);
-
+
/**
* Replace some characters by another character in a string (in-place)
* Return a pointer to string
*/
- static char* ReplaceChars(char* str, const char *toreplace,char replacement);
-
+ static char* ReplaceChars(char* str, const char* toreplace,
+ char replacement);
+
/**
* Returns true if str1 starts (respectively ends) with str2
*/
static bool StringStartsWith(const char* str1, const char* str2);
+ static bool StringStartsWith(const std::string& str1, const char* str2);
static bool StringEndsWith(const char* str1, const char* str2);
+ static bool StringEndsWith(const std::string& str1, const char* str2);
/**
* Returns a pointer to the last occurence of str2 in str1
*/
static const char* FindLastString(const char* str1, const char* str2);
-
+
/**
* Make a duplicate of the string similar to the strdup C function
* but use new to create the 'new' string, so one can use
* 'delete' to remove it. Returns 0 if the input is empty.
*/
static char* DuplicateString(const char* str);
-
+
/**
* Return the string cropped to a given length by removing chars in the
* center of the string and replacing them with an ellipsis (...)
*/
- static kwsys_stl::string CropString(const kwsys_stl::string&,size_t max_len);
-
+ static std::string CropString(const std::string&, size_t max_len);
+
/** split a path by separator into an array of strings, default is /.
If isPath is true then the string is treated like a path and if
s starts with a / then the first element of the returned array will
be /, so /foo/bar will be [/, foo, bar]
- */
- static kwsys_stl::vector<String> SplitString(const char* s, char separator = '/',
- bool isPath = false);
+ */
+ static std::vector<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);
+ 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);
+ 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
*/
- static bool Split(const char* s, kwsys_stl::vector<kwsys_stl::string>& l);
- static bool Split(const char* s, kwsys_stl::vector<kwsys_stl::string>& l, char separator);
-
- /**
+ static bool Split(const std::string& s, std::vector<std::string>& l);
+ static bool Split(const std::string& s, std::vector<std::string>& l,
+ char separator);
+
+ /**
* Return string with space added between capitalized words
* (i.e. EatMyShorts becomes Eat My Shorts )
- * (note that IEatShorts becomes IEat Shorts)
+ * (note that IEatShorts becomes IEat Shorts)
*/
- static kwsys_stl::string AddSpaceBetweenCapitalizedWords(
- const kwsys_stl::string&);
+ static std::string AddSpaceBetweenCapitalizedWords(const std::string&);
/**
* Append two or more strings and produce new one.
@@ -220,10 +233,9 @@ public:
* with 'new'.
* Return 0 if inputs are empty or there was an error
*/
- static char* AppendStrings(
- const char* str1, const char* str2);
- static char* AppendStrings(
- const char* str1, const char* str2, const char* str3);
+ static char* AppendStrings(const char* str1, const char* str2);
+ static char* AppendStrings(const char* str1, const char* str2,
+ const char* str3);
/**
* Estimate the length of the string that will be produced
@@ -234,13 +246,13 @@ public:
* you will not be able to use this 'ap' anymore from the beginning.
* It's up to you to call va_end though.
*/
- static int EstimateFormatLength(const char *format, va_list ap);
+ static int EstimateFormatLength(const char* format, va_list ap);
/**
* Escape specific characters in 'str'.
*/
- static kwsys_stl::string EscapeChars(
- const char *str, const char *chars_to_escape, char escape_char = '\\');
+ static std::string EscapeChars(const char* str, const char* chars_to_escape,
+ char escape_char = '\\');
/** -----------------------------------------------------------------
* Filename Manipulation Routines
@@ -250,19 +262,24 @@ public:
/**
* Replace Windows file system slashes with Unix-style slashes.
*/
- static void ConvertToUnixSlashes(kwsys_stl::string& path);
-
+ static void ConvertToUnixSlashes(std::string& path);
+
+#ifdef _WIN32
+ /** Calls Encoding::ToWindowsExtendedPath. */
+ static std::wstring ConvertToWindowsExtendedPath(const std::string&);
+#endif
+
/**
* For windows this calls ConvertToWindowsOutputPath and for unix
* it calls ConvertToUnixOutputPath
*/
- static kwsys_stl::string ConvertToOutputPath(const char*);
+ static std::string ConvertToOutputPath(const std::string&);
/**
* Convert the path to a string that can be used in a unix makefile.
* double slashes are removed, and spaces are escaped.
*/
- static kwsys_stl::string ConvertToUnixOutputPath(const char*);
+ static std::string ConvertToUnixOutputPath(const std::string&);
/**
* Convert the path to string that can be used in a windows project or
@@ -270,43 +287,88 @@ public:
* the string, the slashes are converted to windows style backslashes, and
* if there are spaces in the string it is double quoted.
*/
- static kwsys_stl::string ConvertToWindowsOutputPath(const char*);
+ static std::string ConvertToWindowsOutputPath(const std::string&);
+
+ /**
+ * Return true if a path with the given name exists in the current directory.
+ */
+ static bool PathExists(const std::string& path);
/**
* Return true if a file exists in the current directory.
- * If isFile = true, then make sure the file is a file and
+ * If isFile = true, then make sure the file is a file and
* not a directory. If isFile = false, then return true
- * if it is a file or a directory.
+ * if it is a file or a directory. Note that the file will
+ * also be checked for read access. (Currently, this check
+ * for read access is only done on POSIX systems.)
*/
static bool FileExists(const char* filename, bool isFile);
+ static bool FileExists(const std::string& filename, bool isFile);
static bool FileExists(const char* filename);
+ static bool FileExists(const std::string& filename);
/**
- * Converts Cygwin path to Win32 path. Uses dictionary container for
- * caching and calls to cygwin_conv_to_win32_path from Cygwin dll
- * for actual translation. Returns true on success, else false.
+ * Test if a file exists and can be accessed with the requested
+ * permissions. Symbolic links are followed. Returns true if
+ * the access test was successful.
+ *
+ * On POSIX systems (including Cygwin), this maps to the access
+ * function. On Windows systems, all existing files are
+ * considered readable, and writable files are considered to
+ * have the read-only file attribute cleared.
+ */
+ static bool TestFileAccess(const char* filename,
+ TestFilePermissions permissions);
+ static bool TestFileAccess(const std::string& filename,
+ TestFilePermissions permissions);
+/**
+ * Cross platform wrapper for stat struct
+ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(__BORLANDC__)
+ typedef struct stati64 Stat_t;
+#else
+ typedef struct _stat64 Stat_t;
+#endif
+#else
+ typedef struct stat Stat_t;
+#endif
+
+ /**
+ * Cross platform wrapper for stat system call
+ *
+ * On Windows this may not work for paths longer than 250 characters
+ * due to limitations of the underlying '_wstat64' call.
*/
+ static int Stat(const char* path, Stat_t* buf);
+ static int Stat(const std::string& path, Stat_t* buf);
+
+/**
+ * Converts Cygwin path to Win32 path. Uses dictionary container for
+ * caching and calls to cygwin_conv_to_win32_path from Cygwin dll
+ * for actual translation. Returns true on success, else false.
+ */
#ifdef __CYGWIN__
- static bool PathCygwinToWin32(const char *path, char *win32_path);
+ static bool PathCygwinToWin32(const char* path, char* win32_path);
#endif
/**
* Return file length
*/
- static unsigned long FileLength(const char *filename);
+ static unsigned long FileLength(const std::string& filename);
/**
Change the modification time or create a file
*/
- static bool Touch(const char* filename, bool create);
-
+ static bool Touch(const std::string& filename, bool create);
+
/**
* 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.
*/
- static bool FileTimeCompare(const char* f1, const char* f2,
+ static bool FileTimeCompare(const std::string& f1, const std::string& f2,
int* result);
/**
@@ -316,23 +378,22 @@ public:
static const char* GetExecutableExtension();
/**
- * Given a path that exists on a windows machine, return the
- * actuall case of the path as it was created. If the file
- * does not exist path is returned unchanged. This does nothing
- * on unix but return path.
+ * Given a path on a Windows machine, return the actual case of
+ * the path as it exists on disk. Path components that do not
+ * exist on disk are returned unchanged. Relative paths are always
+ * returned unchanged. Drive letters are always made upper case.
+ * This does nothing on non-Windows systems but return the path.
*/
- static kwsys_stl::string GetActualCaseForPath(const char* path);
+ static std::string GetActualCaseForPath(const std::string& path);
/**
* Given the path to a program executable, get the directory part of
* the path with the file stripped off. If there is no directory
* part, the empty string is returned.
*/
- static kwsys_stl::string GetProgramPath(const char*);
- static bool SplitProgramPath(const char* in_name,
- kwsys_stl::string& dir,
- kwsys_stl::string& file,
- bool errorReport = true);
+ static std::string GetProgramPath(const std::string&);
+ static bool SplitProgramPath(const std::string& in_name, std::string& dir,
+ std::string& file, bool errorReport = true);
/**
* Given argv[0] for a unix program find the full path to a running
@@ -341,15 +402,13 @@ public:
* to the running executable. If argv0 is not a full path,
* then this will try to find the full path. If the path is not
* found false is returned, if found true is returned. An error
- * message of the attempted paths is stored in errorMsg.
+ * message of the attempted paths is stored in errorMsg.
* exeName is the name of the executable.
* buildDir is a possibly null path to the build directory.
* installPrefix is a possibly null pointer to the install directory.
*/
- static bool FindProgramPath(const char* argv0,
- kwsys_stl::string& pathOut,
- kwsys_stl::string& errorMsg,
- const char* exeName = 0,
+ static bool FindProgramPath(const char* argv0, std::string& pathOut,
+ std::string& errorMsg, const char* exeName = 0,
const char* buildDir = 0,
const char* installPrefix = 0);
@@ -359,16 +418,21 @@ public:
* (which defaults to the current working directory). The full path
* is returned.
*/
- static kwsys_stl::string CollapseFullPath(const char* in_relative);
- static kwsys_stl::string CollapseFullPath(const char* in_relative,
- const char* in_base);
+ static std::string CollapseFullPath(const std::string& in_relative);
+ static std::string CollapseFullPath(const std::string& in_relative,
+ const char* in_base);
+ static std::string CollapseFullPath(const std::string& in_relative,
+ const std::string& in_base);
- /**
+ /**
* 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.
+ * etc.) the original path is returned if errorMessage pointer is
+ * NULL. Otherwise empty string is returned and errorMessage
+ * contains error description.
*/
- static kwsys_stl::string GetRealPath(const char* path);
+ static std::string GetRealPath(const std::string& path,
+ std::string* errorMessage = 0);
/**
* Split a path name into its root component and the rest of the
@@ -385,8 +449,8 @@ public:
* returned. The root component is stored in the "root" string if
* given.
*/
- static const char* SplitPathRootComponent(const char* p,
- kwsys_stl::string* root=0);
+ static const char* SplitPathRootComponent(const std::string& p,
+ std::string* root = 0);
/**
* Split a path name into its basic components. The first component
@@ -398,77 +462,75 @@ public:
* automatically expanded if expand_home_dir is true and this
* platform supports them.
*/
- static void SplitPath(const char* p,
- kwsys_stl::vector<kwsys_stl::string>& components,
+ static void SplitPath(const std::string& p,
+ std::vector<std::string>& components,
bool expand_home_dir = true);
/**
* Join components of a path name into a single string. See
* SplitPath for the format of the components.
*/
- static kwsys_stl::string JoinPath(
- const kwsys_stl::vector<kwsys_stl::string>& components);
- static kwsys_stl::string JoinPath(
- kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
- kwsys_stl::vector<kwsys_stl::string>::const_iterator last);
+ 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.
*/
- static bool ComparePath(const char* c1, const char* c2);
-
+ static bool ComparePath(const std::string& c1, const std::string& c2);
/**
* Return path of a full filename (no trailing slashes)
*/
- static kwsys_stl::string GetFilenamePath(const kwsys_stl::string&);
+ static std::string GetFilenamePath(const std::string&);
/**
* Return file name of a full filename (i.e. file name without path)
*/
- static kwsys_stl::string GetFilenameName(const kwsys_stl::string&);
+ static std::string GetFilenameName(const std::string&);
/**
* Split a program from its arguments and handle spaces in the paths
*/
- static void SplitProgramFromArgs(
- const char* path,
- kwsys_stl::string& program, kwsys_stl::string& args);
+ static void SplitProgramFromArgs(const std::string& path,
+ std::string& program, std::string& args);
/**
* Return longest file extension of a full filename (dot included)
*/
- static kwsys_stl::string GetFilenameExtension(const kwsys_stl::string&);
+ static std::string GetFilenameExtension(const std::string&);
/**
* Return shortest file extension of a full filename (dot included)
*/
- static kwsys_stl::string GetFilenameLastExtension(
- const kwsys_stl::string& filename);
-
+ static std::string GetFilenameLastExtension(const std::string& filename);
+
/**
* Return file name without extension of a full filename
*/
- static kwsys_stl::string GetFilenameWithoutExtension(
- const kwsys_stl::string&);
-
+ static std::string GetFilenameWithoutExtension(const std::string&);
+
/**
* Return file name without its last (shortest) extension
*/
- static kwsys_stl::string GetFilenameWithoutLastExtension(
- const kwsys_stl::string&);
-
+ static std::string GetFilenameWithoutLastExtension(const std::string&);
+
/**
* Return whether the path represents a full path (not relative)
*/
+ static bool FileIsFullPath(const std::string&);
static bool FileIsFullPath(const char*);
-
+
/**
* For windows return the short path for the given path,
* Unix just a pass through
*/
- static bool GetShortPath(const char* path, kwsys_stl::string& result);
-
+ 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
@@ -476,20 +538,19 @@ public:
* 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(kwsys_ios::istream& istr,
- kwsys_stl::string& line,
- bool* has_newline=0,
- long sizeLimit=-1);
+ static bool GetLineFromStream(std::istream& istr, std::string& line,
+ bool* has_newline = 0, long sizeLimit = -1);
/**
* Get the parent directory of the directory or file
*/
- static kwsys_stl::string GetParentDirectory(const char* fileOrDir);
+ static std::string GetParentDirectory(const std::string& fileOrDir);
/**
* Check if the given file or directory is in subdirectory of dir
*/
- static bool IsSubDirectory(const char* fileOrDir, const char* dir);
+ static bool IsSubDirectory(const std::string& fileOrDir,
+ const std::string& dir);
/** -----------------------------------------------------------------
* File Manipulation Routines
@@ -497,41 +558,49 @@ public:
*/
/**
+ * Open a file considering unicode.
+ */
+ static FILE* Fopen(const std::string& file, const char* mode);
+
+ /**
* 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.
+ * prior to calling this function.
*/
static bool MakeDirectory(const char* path);
+ static bool MakeDirectory(const std::string& path);
/**
* Copy the source file to the destination file only
* if the two files differ.
*/
- static bool CopyFileIfDifferent(const char* source,
- const char* destination);
+ static bool CopyFileIfDifferent(const std::string& source,
+ const std::string& destination);
/**
* Compare the contents of two files. Return true if different
*/
- static bool FilesDiffer(const char* source, const char* destination);
+ static bool FilesDiffer(const std::string& source,
+ const std::string& destination);
/**
* Return true if the two files are the same file
*/
- static bool SameFile(const char* file1, const char* file2);
+ static bool SameFile(const std::string& file1, const std::string& file2);
/**
* Copy a file.
*/
- static bool CopyFileAlways(const char* source, const char* destination);
+ static bool CopyFileAlways(const std::string& source,
+ const std::string& destination);
/**
* Copy a file. If the "always" argument is true the file is always
* copied. If it is false, the file is copied only if it is new or
* has changed.
*/
- static bool CopyAFile(const char* source, const char* destination,
- bool always = true);
+ static bool CopyAFile(const std::string& source,
+ const std::string& destination, bool always = true);
/**
* Copy content directory to another directory with all files and
@@ -539,18 +608,19 @@ public:
* always copied. If it is false, only files that have changed or
* are new are copied.
*/
- static bool CopyADirectory(const char* source, const char* destination,
+ static bool CopyADirectory(const std::string& source,
+ const std::string& destination,
bool always = true);
-
+
/**
* Remove a file
*/
- static bool RemoveFile(const char* source);
-
+ static bool RemoveFile(const std::string& source);
+
/**
* Remove a directory
*/
- static bool RemoveADirectory(const char* source);
+ static bool RemoveADirectory(const std::string& source);
/**
* Get the maximum full file path length
@@ -560,57 +630,61 @@ public:
/**
* Find a file in the system PATH, with optional extra paths
*/
- static kwsys_stl::string FindFile(
- const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& path =
- kwsys_stl::vector<kwsys_stl::string>(),
+ static std::string FindFile(
+ const std::string& name,
+ const std::vector<std::string>& path = std::vector<std::string>(),
bool no_system_path = false);
/**
* Find a directory in the system PATH, with optional extra paths
*/
- static kwsys_stl::string FindDirectory(
- const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& path =
- kwsys_stl::vector<kwsys_stl::string>(),
+ static std::string FindDirectory(
+ const std::string& name,
+ const std::vector<std::string>& path = std::vector<std::string>(),
bool no_system_path = false);
/**
* Find an executable in the system PATH, with optional extra paths
*/
- static kwsys_stl::string FindProgram(
+ static std::string FindProgram(
const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& path =
- kwsys_stl::vector<kwsys_stl::string>(),
+ const std::vector<std::string>& path = std::vector<std::string>(),
+ bool no_system_path = false);
+ static std::string FindProgram(
+ const std::string& name,
+ const std::vector<std::string>& path = std::vector<std::string>(),
bool no_system_path = false);
- static kwsys_stl::string FindProgram(
- const kwsys_stl::vector<kwsys_stl::string>& names,
- const kwsys_stl::vector<kwsys_stl::string>& path =
- kwsys_stl::vector<kwsys_stl::string>(),
+ static std::string FindProgram(
+ const std::vector<std::string>& names,
+ const std::vector<std::string>& path = std::vector<std::string>(),
bool no_system_path = false);
/**
* Find a library in the system PATH, with optional extra paths
*/
- static kwsys_stl::string FindLibrary(
- const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& path);
-
+ static std::string FindLibrary(const std::string& name,
+ const std::vector<std::string>& path);
+
/**
* Return true if the file is a directory
*/
- static bool FileIsDirectory(const char* name);
-
+ static bool FileIsDirectory(const std::string& name);
+
/**
* Return true if the file is a symlink
*/
- static bool FileIsSymlink(const char* name);
-
+ static bool FileIsSymlink(const std::string& name);
+
+ /**
+ * Return true if the file is a FIFO
+ */
+ static bool FileIsFIFO(const std::string& name);
+
/**
* Return true if the file has a given signature (first set of bytes)
*/
- static bool FileHasSignature(
- const char* filename, const char *signature, long offset = 0);
+ static bool FileHasSignature(const char* filename, const char* signature,
+ long offset = 0);
/**
* Attempt to detect and return the type of a file.
@@ -621,28 +695,28 @@ public:
* The algorithm is simplistic, and should probably check for usual file
* extensions, 'magic' signature, unicode, etc.
*/
- enum FileTypeEnum
- {
+ enum FileTypeEnum
+ {
FileTypeUnknown,
FileTypeBinary,
FileTypeText
};
- static SystemTools::FileTypeEnum DetectFileType(
- const char* filename,
- unsigned long length = 256,
- double percent_bin = 0.05);
+ static SystemTools::FileTypeEnum DetectFileType(const char* filename,
+ unsigned long length = 256,
+ double percent_bin = 0.05);
/**
* Create a symbolic link if the platform supports it. Returns whether
- * creation succeded.
+ * creation succeeded.
*/
- static bool CreateSymlink(const char* origName, const char* newName);
+ static bool CreateSymlink(const std::string& origName,
+ const std::string& newName);
/**
* Read the contents of a symbolic link. Returns whether reading
- * succeded.
+ * succeeded.
*/
- static bool ReadSymlink(const char* newName, kwsys_stl::string& origName);
+ static bool ReadSymlink(const std::string& newName, std::string& origName);
/**
* Try to locate the file 'filename' in the directory 'dir'.
@@ -654,41 +728,57 @@ public:
* 'filename_found' is assigned the fully qualified name/path of the file
* if it is found (not touched otherwise).
* If 'try_filename_dirs' is true, try to find the file using the
- * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt,
+ * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt,
* first look for bill.txt in 'dir', then in 'dir'/bar, then in 'dir'/foo/bar
* etc.
* Return true if the file was found, false otherwise.
*/
- static bool LocateFileInDir(const char *filename,
- const char *dir,
- kwsys_stl::string& filename_found,
+ static bool LocateFileInDir(const char* filename, const char* dir,
+ std::string& filename_found,
int try_filename_dirs = 0);
- /** compute the relative path from local to remote. local must
- be a directory. remote can be a file or a directory.
+ /** compute the relative path from local to remote. local must
+ be a directory. remote can be a file or a directory.
Both remote and local must be full paths. Basically, if
you are in directory local and you want to access the file in remote
what is the relative path to do that. For example:
/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 kwsys_stl::string RelativePath(const char* local, const char* remote);
+ static std::string RelativePath(const std::string& local,
+ const std::string& remote);
/**
* Return file's modified time
*/
- static long int ModifiedTime(const char* filename);
+ static long int ModifiedTime(const std::string& filename);
/**
* Return file's creation time (Win32: works only for NTFS, not FAT)
*/
- static long int CreationTime(const char* filename);
+ 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.
+ * 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
+ * failure.
+ *
+ * WARNING: A non-thread-safe method is currently used to get the umask
+ * if a honor_umask parameter is set to true.
*/
static bool GetPermissions(const char* file, mode_t& mode);
- static bool SetPermissions(const char* file, mode_t mode);
+ static bool GetPermissions(const std::string& file, mode_t& mode);
+ static bool SetPermissions(const char* file, mode_t mode,
+ bool honor_umask = false);
+ static bool SetPermissions(const std::string& file, mode_t mode,
+ bool honor_umask = false);
/** -----------------------------------------------------------------
* Time Manipulation Routines
@@ -701,7 +791,7 @@ public:
/**
* Get current date/time
*/
- static kwsys_stl::string GetCurrentDateTime(const char* format);
+ static std::string GetCurrentDateTime(const char* format);
/** -----------------------------------------------------------------
* Registry Manipulation Routines
@@ -713,31 +803,37 @@ public:
* registry values. The default is to match the currently running
* binary type.
*/
- enum KeyWOW64 { KeyWOW64_Default, KeyWOW64_32, KeyWOW64_64 };
+ enum KeyWOW64
+ {
+ KeyWOW64_Default,
+ KeyWOW64_32,
+ KeyWOW64_64
+ };
/**
* Get a list of subkeys.
*/
- static bool GetRegistrySubKeys(const char *key,
- kwsys_stl::vector<kwsys_stl::string>& subkeys,
+ static bool GetRegistrySubKeys(const std::string& key,
+ std::vector<std::string>& subkeys,
KeyWOW64 view = KeyWOW64_Default);
/**
* Read a registry value
*/
- static bool ReadRegistryValue(const char *key, kwsys_stl::string &value,
+ static bool ReadRegistryValue(const std::string& key, std::string& value,
KeyWOW64 view = KeyWOW64_Default);
/**
* Write a registry value
*/
- static bool WriteRegistryValue(const char *key, const char *value,
+ static bool WriteRegistryValue(const std::string& key,
+ const std::string& value,
KeyWOW64 view = KeyWOW64_Default);
/**
* Delete a registry value
*/
- static bool DeleteRegistryValue(const char *key,
+ static bool DeleteRegistryValue(const std::string& key,
KeyWOW64 view = KeyWOW64_Default);
/** -----------------------------------------------------------------
@@ -750,37 +846,40 @@ public:
* string vector passed in. If env is set then the value
* of env will be used instead of PATH.
*/
- static void GetPath(kwsys_stl::vector<kwsys_stl::string>& path,
- const char* env=0);
+ static void GetPath(std::vector<std::string>& path, const char* env = 0);
/**
* Read an environment variable
*/
static const char* GetEnv(const char* key);
- static bool GetEnv(const char* key, kwsys_stl::string& result);
+ static const char* GetEnv(const std::string& key);
+ static bool GetEnv(const char* key, std::string& result);
+ static bool GetEnv(const std::string& key, std::string& result);
+ static bool HasEnv(const char* key);
+ static bool HasEnv(const std::string& key);
/** Put a string into the environment
of the form var=value */
- static bool PutEnv(const char* env);
+ static bool PutEnv(const std::string& env);
/** Remove a string from the environment.
Input is of the form "var" or "var=value" (value is ignored). */
- static bool UnPutEnv(const char* env);
+ static bool UnPutEnv(const std::string& env);
/**
* Get current working directory CWD
*/
- static kwsys_stl::string GetCurrentWorkingDirectory(bool collapse =true);
+ static std::string GetCurrentWorkingDirectory(bool collapse = true);
/**
* Change directory to the directory specified
*/
- static int ChangeDirectory(const char* dir);
+ static int ChangeDirectory(const std::string& dir);
/**
* Get the result of strerror(errno)
*/
- static kwsys_stl::string GetLastSystemError();
+ static std::string GetLastSystemError();
/**
* When building DEBUG with MSVC, this enables a hook that prevents
@@ -799,18 +898,19 @@ public:
/**
* Add an entry in the path translation table.
*/
- static void AddTranslationPath(const char * dir, const char * refdir);
+ static void AddTranslationPath(const std::string& dir,
+ const std::string& refdir);
/**
* If dir is different after CollapseFullPath is called,
* Then insert it into the path translation table
*/
- static void AddKeepPath(const char* dir);
+ static void AddKeepPath(const std::string& dir);
/**
* Update path by going through the Path Translation table;
*/
- static void CheckTranslationPath(kwsys_stl::string & path);
+ static void CheckTranslationPath(std::string& path);
/**
* Delay the execution for a specified amount of time specified
@@ -822,16 +922,7 @@ public:
* Get the operating system name and version
* This is implemented for Win32 only for the moment
*/
- static kwsys_stl::string GetOperatingSystemNameAndVersion();
-
- /**
- * Convert windows-style arguments given as a command-line string
- * into more traditional argc/argv arguments.
- * Note that argv[0] will be assigned the executable name using
- * the GetModuleFileName() function.
- */
- static void ConvertWindowsCommandLineToUnixArguments(
- const char *cmd_line, int *argc, char ***argv);
+ static std::string GetOperatingSystemNameAndVersion();
/** -----------------------------------------------------------------
* URL Manipulation Routines
@@ -844,9 +935,8 @@ public:
* and fill protocol as appropriate.
* Return false if the URL does not have the required form, true otherwise.
*/
- static bool ParseURLProtocol( const kwsys_stl::string& URL,
- kwsys_stl::string& protocol,
- kwsys_stl::string& dataglom );
+ static bool ParseURLProtocol(const std::string& URL, std::string& protocol,
+ std::string& dataglom);
/**
* Parse a string (a URL without protocol prefix) with the form:
@@ -855,13 +945,10 @@ public:
* when values are found.
* Return true if the string matches the format; false otherwise.
*/
- static bool ParseURL( const kwsys_stl::string& URL,
- kwsys_stl::string& protocol,
- kwsys_stl::string& username,
- kwsys_stl::string& password,
- kwsys_stl::string& hostname,
- kwsys_stl::string& dataport,
- kwsys_stl::string& datapath );
+ static bool ParseURL(const std::string& URL, std::string& protocol,
+ std::string& username, std::string& password,
+ std::string& hostname, std::string& dataport,
+ std::string& datapath);
private:
/**
@@ -878,39 +965,47 @@ private:
* This method prevents warning on SGI
*/
SystemToolsManager* GetSystemToolsManager()
- {
+ {
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 kwsys_stl::string FindName(
- const char* name,
- const kwsys_stl::vector<kwsys_stl::string>& path =
- kwsys_stl::vector<kwsys_stl::string>(),
+ 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;
- static SystemToolsTranslationMap *LongPathMap;
+ static SystemToolsTranslationMap* TranslationMap;
+#ifdef _WIN32
+ static SystemToolsPathCaseMap* PathCaseMap;
+ static SystemToolsEnvMap* EnvMap;
+#endif
#ifdef __CYGWIN__
- static SystemToolsTranslationMap *Cyg2Win32Map;
+ static SystemToolsTranslationMap* Cyg2Win32Map;
#endif
friend class SystemToolsManager;
};
} // namespace @KWSYS_NAMESPACE@
-/* Undefine temporary macros. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# undef kwsys_stl
-# undef kwsys_ios
-#endif
-
#endif
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index 25832c2b1..eaa5c7d43 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -1,51 +1,39 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Terminal.h)
/* 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. */
+#include <stdarg.h> /* va_list */
#include <stdlib.h> /* getenv */
#include <string.h> /* strcmp */
-#include <stdarg.h> /* va_list */
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
-# include <windows.h> /* SetConsoleTextAttribute */
-# include <io.h> /* _get_osfhandle */
+#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,
int default_tty);
static void kwsysTerminalSetVT100Color(FILE* stream, int color);
@@ -53,11 +41,9 @@ static void kwsysTerminalSetVT100Color(FILE* stream, int color);
static HANDLE kwsysTerminalGetStreamHandle(FILE* stream);
static void kwsysTerminalSetConsoleColor(HANDLE hOut,
CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
- FILE* stream,
- int color);
+ FILE* stream, int color);
#endif
-/*--------------------------------------------------------------------------*/
void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...)
{
/* Setup the stream with the given color if possible. */
@@ -68,196 +54,191 @@ void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...)
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
HANDLE hOut = kwsysTerminalGetStreamHandle(stream);
- if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
- {
+ if (GetConsoleScreenBufferInfo(hOut, &hOutInfo)) {
pipeIsConsole = 1;
kwsysTerminalSetConsoleColor(hOut, &hOutInfo, stream, color);
- }
+ }
#endif
- if(!pipeIsConsole && kwsysTerminalStreamIsVT100(stream,
- default_vt100, default_tty))
- {
+ if (!pipeIsConsole &&
+ kwsysTerminalStreamIsVT100(stream, default_vt100, default_tty)) {
pipeIsVT100 = 1;
kwsysTerminalSetVT100Color(stream, color);
- }
+ }
/* Format the text into the stream. */
{
- va_list var_args;
- va_start(var_args, format);
- vfprintf(stream, format, var_args);
- va_end(var_args);
+ va_list var_args;
+ va_start(var_args, format);
+ vfprintf(stream, format, var_args);
+ va_end(var_args);
}
- /* Restore the normal color state for the stream. */
+/* Restore the normal color state for the stream. */
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
- if(pipeIsConsole)
- {
+ if (pipeIsConsole) {
kwsysTerminalSetConsoleColor(hOut, &hOutInfo, stream,
kwsysTerminal_Color_Normal);
- }
+ }
#endif
- if(pipeIsVT100)
- {
+ if (pipeIsVT100) {
kwsysTerminalSetVT100Color(stream, kwsysTerminal_Color_Normal);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
-/* Detect cases when a stream is definately not interactive. */
+/* Detect cases when a stream is definitely not interactive. */
#if !defined(KWSYS_TERMINAL_ISATTY_WORKS)
static int kwsysTerminalStreamIsNotInteractive(FILE* stream)
{
- /* The given stream is definately not interactive if it is a regular
+ /* The given stream is definitely not interactive if it is a regular
file. */
struct stat stream_stat;
- if(fstat(fileno(stream), &stream_stat) == 0)
- {
- if(stream_stat.st_mode & S_IFREG)
- {
+ if (fstat(fileno(stream), &stream_stat) == 0) {
+ if (stream_stat.st_mode & S_IFREG) {
return 1;
- }
}
+ }
return 0;
}
#endif
-/*--------------------------------------------------------------------------*/
/* List of terminal names known to support VT100 color escape sequences. */
-static const char* kwsysTerminalVT100Names[] =
-{
- "Eterm",
- "ansi",
- "color-xterm",
- "con132x25",
- "con132x30",
- "con132x43",
- "con132x60",
- "con80x25",
- "con80x28",
- "con80x30",
- "con80x43",
- "con80x50",
- "con80x60",
- "cons25",
- "console",
- "cygwin",
- "dtterm",
- "eterm-color",
- "gnome",
- "gnome-256color",
- "konsole",
- "konsole-256color",
- "kterm",
- "linux",
- "msys",
- "linux-c",
- "mach-color",
- "mlterm",
- "putty",
- "rxvt",
- "rxvt-256color",
- "rxvt-cygwin",
- "rxvt-cygwin-native",
- "rxvt-unicode",
- "rxvt-unicode-256color",
- "screen",
- "screen-256color",
- "screen-256color-bce",
- "screen-bce",
- "screen-w",
- "screen.linux",
- "vt100",
- "xterm",
- "xterm-16color",
- "xterm-256color",
- "xterm-88color",
- "xterm-color",
- "xterm-debian",
- 0
-};
+static const char* kwsysTerminalVT100Names[] = { "Eterm",
+ "ansi",
+ "color-xterm",
+ "con132x25",
+ "con132x30",
+ "con132x43",
+ "con132x60",
+ "con80x25",
+ "con80x28",
+ "con80x30",
+ "con80x43",
+ "con80x50",
+ "con80x60",
+ "cons25",
+ "console",
+ "cygwin",
+ "dtterm",
+ "eterm-color",
+ "gnome",
+ "gnome-256color",
+ "konsole",
+ "konsole-256color",
+ "kterm",
+ "linux",
+ "msys",
+ "linux-c",
+ "mach-color",
+ "mlterm",
+ "putty",
+ "putty-256color",
+ "rxvt",
+ "rxvt-256color",
+ "rxvt-cygwin",
+ "rxvt-cygwin-native",
+ "rxvt-unicode",
+ "rxvt-unicode-256color",
+ "screen",
+ "screen-256color",
+ "screen-256color-bce",
+ "screen-bce",
+ "screen-w",
+ "screen.linux",
+ "tmux",
+ "tmux-256color",
+ "vt100",
+ "xterm",
+ "xterm-16color",
+ "xterm-256color",
+ "xterm-88color",
+ "xterm-color",
+ "xterm-debian",
+ "xterm-termite",
+ 0 };
-/*--------------------------------------------------------------------------*/
/* Detect whether a stream is displayed in a VT100-compatible terminal. */
static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
int default_tty)
{
+ /* Force color according to http://bixense.com/clicolors/ convention. */
+ {
+ const char* clicolor_force = getenv("CLICOLOR_FORCE");
+ if (clicolor_force && *clicolor_force &&
+ strcmp(clicolor_force, "0") != 0) {
+ return 1;
+ }
+ }
+
/* If running inside emacs the terminal is not VT100. Some emacs
seem to claim the TERM is xterm even though they do not support
VT100 escapes. */
- const char* emacs = getenv("EMACS");
- if(emacs && *emacs == 't')
- {
- return 0;
+ {
+ const char* emacs = getenv("EMACS");
+ if (emacs && *emacs == 't') {
+ return 0;
}
+ }
/* Check for a valid terminal. */
- if(!default_vt100)
- {
+ if (!default_vt100) {
const char** t = 0;
const char* term = getenv("TERM");
- if(term)
- {
- for(t = kwsysTerminalVT100Names; *t && strcmp(term, *t) != 0; ++t) {}
+ if (term) {
+ for (t = kwsysTerminalVT100Names; *t && strcmp(term, *t) != 0; ++t) {
}
- if(!(t && *t))
- {
+ }
+ if (!(t && *t)) {
return 0;
- }
}
+ }
#if defined(KWSYS_TERMINAL_ISATTY_WORKS)
/* Make sure the stream is a tty. */
(void)default_tty;
- return isatty(fileno(stream))? 1:0;
+ return isatty(fileno(stream)) ? 1 : 0;
#else
- /* Check for cases in which the stream is definately not a tty. */
- if(kwsysTerminalStreamIsNotInteractive(stream))
- {
+ /* Check for cases in which the stream is definitely not a tty. */
+ if (kwsysTerminalStreamIsNotInteractive(stream)) {
return 0;
- }
+ }
/* Use the provided default for whether this is a tty. */
return default_tty;
#endif
}
-/*--------------------------------------------------------------------------*/
/* 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"
+#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"
-/*--------------------------------------------------------------------------*/
/* Write VT100 escape sequences to the stream for the given color. */
static void kwsysTerminalSetVT100Color(FILE* stream, int color)
{
- if(color == kwsysTerminal_Color_Normal)
- {
+ if (color == kwsysTerminal_Color_Normal) {
fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
return;
- }
+ }
- switch(color & kwsysTerminal_Color_ForegroundMask)
- {
+ switch (color & kwsysTerminal_Color_ForegroundMask) {
case kwsysTerminal_Color_Normal:
fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
break;
@@ -285,9 +266,8 @@ static void kwsysTerminalSetVT100Color(FILE* stream, int color)
case kwsysTerminal_Color_ForegroundWhite:
fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_WHITE);
break;
- }
- switch(color & kwsysTerminal_Color_BackgroundMask)
- {
+ }
+ switch (color & kwsysTerminal_Color_BackgroundMask) {
case kwsysTerminal_Color_BackgroundBlack:
fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLACK);
break;
@@ -312,19 +292,17 @@ static void kwsysTerminalSetVT100Color(FILE* stream, int color)
case kwsysTerminal_Color_BackgroundWhite:
fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_WHITE);
break;
- }
- if(color & kwsysTerminal_Color_ForegroundBold)
- {
+ }
+ if (color & kwsysTerminal_Color_ForegroundBold) {
fprintf(stream, KWSYS_TERMINAL_VT100_BOLD);
- }
+ }
}
-/*--------------------------------------------------------------------------*/
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
-# define KWSYS_TERMINAL_MASK_FOREGROUND \
+#define KWSYS_TERMINAL_MASK_FOREGROUND \
(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
-# define KWSYS_TERMINAL_MASK_BACKGROUND \
+#define KWSYS_TERMINAL_MASK_BACKGROUND \
(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
/* Get the Windows handle for a FILE stream. */
@@ -333,19 +311,16 @@ 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. */
- if(fd == fileno(stdout))
- {
+ if (fd == fileno(stdout)) {
return GetStdHandle(STD_OUTPUT_HANDLE);
- }
- else if(fd == fileno(stderr))
- {
+ } 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);
@@ -354,12 +329,10 @@ static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
/* Set color attributes in a Windows console. */
static void kwsysTerminalSetConsoleColor(HANDLE hOut,
CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
- FILE* stream,
- int color)
+ FILE* stream, int color)
{
WORD attributes = 0;
- switch(color & kwsysTerminal_Color_ForegroundMask)
- {
+ switch (color & kwsysTerminal_Color_ForegroundMask) {
case kwsysTerminal_Color_Normal:
attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_FOREGROUND;
break;
@@ -387,9 +360,8 @@ static void kwsysTerminalSetConsoleColor(HANDLE hOut,
case kwsysTerminal_Color_ForegroundWhite:
attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
break;
- }
- switch(color & kwsysTerminal_Color_BackgroundMask)
- {
+ }
+ switch (color & kwsysTerminal_Color_BackgroundMask) {
case kwsysTerminal_Color_Normal:
attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_BACKGROUND;
break;
@@ -417,15 +389,13 @@ static void kwsysTerminalSetConsoleColor(HANDLE hOut,
case kwsysTerminal_Color_BackgroundWhite:
attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
break;
- }
- if(color & kwsysTerminal_Color_ForegroundBold)
- {
+ }
+ if (color & kwsysTerminal_Color_ForegroundBold) {
attributes |= FOREGROUND_INTENSITY;
- }
- if(color & kwsysTerminal_Color_BackgroundBold)
- {
+ }
+ if (color & kwsysTerminal_Color_BackgroundBold) {
attributes |= BACKGROUND_INTENSITY;
- }
+ }
fflush(stream);
SetConsoleTextAttribute(hOut, attributes);
}
diff --git a/Source/kwsys/Terminal.h.in b/Source/kwsys/Terminal.h.in
index 108cba017..5d2983004 100644
--- a/Source/kwsys/Terminal.h.in
+++ b/Source/kwsys/Terminal.h.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_Terminal_h
#define @KWSYS_NAMESPACE@_Terminal_h
@@ -21,41 +12,61 @@
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)
-extern "C"
-{
+extern "C" {
#endif
/**
@@ -88,33 +99,33 @@ enum kwsysTerminal_Color_e
kwsysTerminal_Color_Normal = 0,
/* Foreground Color */
- kwsysTerminal_Color_ForegroundBlack = 0x1,
- kwsysTerminal_Color_ForegroundRed = 0x2,
- kwsysTerminal_Color_ForegroundGreen = 0x3,
- kwsysTerminal_Color_ForegroundYellow = 0x4,
- kwsysTerminal_Color_ForegroundBlue = 0x5,
+ kwsysTerminal_Color_ForegroundBlack = 0x1,
+ kwsysTerminal_Color_ForegroundRed = 0x2,
+ kwsysTerminal_Color_ForegroundGreen = 0x3,
+ kwsysTerminal_Color_ForegroundYellow = 0x4,
+ kwsysTerminal_Color_ForegroundBlue = 0x5,
kwsysTerminal_Color_ForegroundMagenta = 0x6,
- kwsysTerminal_Color_ForegroundCyan = 0x7,
- kwsysTerminal_Color_ForegroundWhite = 0x8,
- kwsysTerminal_Color_ForegroundMask = 0xF,
+ kwsysTerminal_Color_ForegroundCyan = 0x7,
+ kwsysTerminal_Color_ForegroundWhite = 0x8,
+ kwsysTerminal_Color_ForegroundMask = 0xF,
/* Background Color */
- kwsysTerminal_Color_BackgroundBlack = 0x10,
- kwsysTerminal_Color_BackgroundRed = 0x20,
- kwsysTerminal_Color_BackgroundGreen = 0x30,
- kwsysTerminal_Color_BackgroundYellow = 0x40,
- kwsysTerminal_Color_BackgroundBlue = 0x50,
+ kwsysTerminal_Color_BackgroundBlack = 0x10,
+ kwsysTerminal_Color_BackgroundRed = 0x20,
+ kwsysTerminal_Color_BackgroundGreen = 0x30,
+ kwsysTerminal_Color_BackgroundYellow = 0x40,
+ kwsysTerminal_Color_BackgroundBlue = 0x50,
kwsysTerminal_Color_BackgroundMagenta = 0x60,
- kwsysTerminal_Color_BackgroundCyan = 0x70,
- kwsysTerminal_Color_BackgroundWhite = 0x80,
- kwsysTerminal_Color_BackgroundMask = 0xF0,
+ kwsysTerminal_Color_BackgroundCyan = 0x70,
+ kwsysTerminal_Color_BackgroundWhite = 0x80,
+ kwsysTerminal_Color_BackgroundMask = 0xF0,
/* Attributes */
kwsysTerminal_Color_ForegroundBold = 0x100,
kwsysTerminal_Color_BackgroundBold = 0x200,
- kwsysTerminal_Color_AssumeTTY = 0x400,
- kwsysTerminal_Color_AssumeVT100 = 0x800,
- kwsysTerminal_Color_AttributeMask = 0xF00
+ kwsysTerminal_Color_AssumeTTY = 0x400,
+ kwsysTerminal_Color_AssumeVT100 = 0x800,
+ kwsysTerminal_Color_AttributeMask = 0xF00
};
#if defined(__cplusplus)
@@ -124,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_fun.hxx.in b/Source/kwsys/hash_fun.hxx.in
index 6f787ddc5..8626c2aa2 100644
--- a/Source/kwsys/hash_fun.hxx.in
+++ b/Source/kwsys/hash_fun.hxx.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
/*
* Copyright (c) 1996
* Silicon Graphics Computer Systems, Inc.
@@ -38,108 +29,134 @@
#define @KWSYS_NAMESPACE@_hash_fun_hxx
#include <@KWSYS_NAMESPACE@/Configure.hxx>
-#include <@KWSYS_NAMESPACE@/cstddef> // size_t
-#include <@KWSYS_NAMESPACE@/stl/string> // string
-namespace @KWSYS_NAMESPACE@
-{
+#include <stddef.h> // size_t
+#include <string>
-template <class _Key> struct hash { };
+namespace @KWSYS_NAMESPACE@ {
+
+template <class _Key>
+struct hash
+{
+};
inline size_t _stl_hash_string(const char* __s)
{
unsigned long __h = 0;
- for ( ; *__s; ++__s)
- __h = 5*__h + *__s;
+ for (; *__s; ++__s)
+ __h = 5 * __h + *__s;
return size_t(__h);
}
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<char*> {
+template <>
+struct hash<char*>
+{
size_t operator()(const char* __s) const { return _stl_hash_string(__s); }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<const char*> {
+template <>
+struct hash<const char*>
+{
size_t operator()(const char* __s) const { return _stl_hash_string(__s); }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
- struct hash<@KWSYS_NAMESPACE@_stl::string> {
- size_t operator()(const @KWSYS_NAMESPACE@_stl::string & __s) const { return _stl_hash_string(__s.c_str()); }
+template <>
+struct hash<std::string>
+{
+ size_t operator()(const std::string& __s) const
+ {
+ return _stl_hash_string(__s.c_str());
+ }
};
#if !defined(__BORLANDC__)
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
- struct hash<const @KWSYS_NAMESPACE@_stl::string> {
- size_t operator()(const @KWSYS_NAMESPACE@_stl::string & __s) const { return _stl_hash_string(__s.c_str()); }
+template <>
+struct hash<const std::string>
+{
+ size_t operator()(const std::string& __s) const
+ {
+ return _stl_hash_string(__s.c_str());
+ }
};
#endif
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<char> {
+template <>
+struct hash<char>
+{
size_t operator()(char __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<unsigned char> {
+template <>
+struct hash<unsigned char>
+{
size_t operator()(unsigned char __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<signed char> {
+template <>
+struct hash<signed char>
+{
size_t operator()(unsigned char __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<short> {
+template <>
+struct hash<short>
+{
size_t operator()(short __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<unsigned short> {
+template <>
+struct hash<unsigned short>
+{
size_t operator()(unsigned short __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<int> {
+template <>
+struct hash<int>
+{
size_t operator()(int __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<unsigned int> {
+template <>
+struct hash<unsigned int>
+{
size_t operator()(unsigned int __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<long> {
+template <>
+struct hash<long>
+{
size_t operator()(long __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<unsigned long> {
+template <>
+struct hash<unsigned long>
+{
size_t operator()(unsigned long __x) const { return __x; }
};
// use long long or __int64
#if @KWSYS_USE_LONG_LONG@
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<long long> {
+template <>
+struct hash<long long>
+{
size_t operator()(long long __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<unsigned long long> {
+template <>
+struct hash<unsigned long long>
+{
size_t operator()(unsigned long long __x) const { return __x; }
};
#elif @KWSYS_USE___INT64@
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<__int64> {
+template <>
+struct hash<__int64>
+{
size_t operator()(__int64 __x) const { return __x; }
};
-@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
-struct hash<unsigned __int64> {
+template <>
+struct hash<unsigned __int64>
+{
size_t operator()(unsigned __int64 __x) const { return __x; }
};
#endif // use long long or __int64
diff --git a/Source/kwsys/hash_map.hxx.in b/Source/kwsys/hash_map.hxx.in
index 6d4379d8e..3f9174f3b 100644
--- a/Source/kwsys/hash_map.hxx.in
+++ b/Source/kwsys/hash_map.hxx.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
/*
* Copyright (c) 1996
* Silicon Graphics Computer Systems, Inc.
@@ -38,51 +29,52 @@
#define @KWSYS_NAMESPACE@_hash_map_hxx
#include <@KWSYS_NAMESPACE@/hashtable.hxx>
+
#include <@KWSYS_NAMESPACE@/hash_fun.hxx>
-#include <@KWSYS_NAMESPACE@/stl/functional> // equal_to
+
+#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@
-{
+namespace @KWSYS_NAMESPACE@ {
// select1st is an extension: it is not part of the standard.
template <class T1, class T2>
-struct hash_select1st:
- public @KWSYS_NAMESPACE@_stl::unary_function<@KWSYS_NAMESPACE@_stl::pair<T1, T2>, T1>
+struct hash_select1st : public std::unary_function<std::pair<T1, T2>, T1>
{
- const T1& operator()(const @KWSYS_NAMESPACE@_stl::pair<T1, T2>& __x) const
- { return __x.first; }
+ const T1& operator()(const std::pair<T1, T2>& __x) const
+ {
+ return __x.first;
+ }
};
// Forward declaration of equality operator; needed for friend declaration.
-template <class _Key, class _Tp,
- class _HashFcn = hash<_Key>,
- class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Key>,
- class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) >
+template <class _Key, class _Tp, class _HashFcn = hash<_Key>,
+ class _EqualKey = std::equal_to<_Key>,
+ class _Alloc = std::allocator<char> >
class hash_map;
template <class _Key, class _Tp, class _HashFn, class _EqKey, class _Alloc>
bool operator==(const hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>&,
const hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>&);
-template <class _Key, class _Tp, class _HashFcn, class _EqualKey,
- class _Alloc>
+template <class _Key, class _Tp, class _HashFcn, class _EqualKey, class _Alloc>
class hash_map
{
private:
- typedef hashtable<@KWSYS_NAMESPACE@_stl::pair<const _Key,_Tp>,_Key,_HashFcn,
- hash_select1st<const _Key,_Tp>,_EqualKey,_Alloc> _Ht;
+ typedef hashtable<std::pair<const _Key, _Tp>, _Key, _HashFcn,
+ hash_select1st<const _Key, _Tp>, _EqualKey, _Alloc>
+ _Ht;
_Ht _M_ht;
public:
@@ -110,69 +102,51 @@ public:
allocator_type get_allocator() const { return _M_ht.get_allocator(); }
public:
- hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+ hash_map()
+ : _M_ht(100, hasher(), key_equal(), allocator_type())
+ {
+ }
explicit hash_map(size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+ : _M_ht(__n, hasher(), key_equal(), allocator_type())
+ {
+ }
hash_map(size_type __n, const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+ : _M_ht(__n, __hf, key_equal(), allocator_type())
+ {
+ }
hash_map(size_type __n, const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a) {}
+ : _M_ht(__n, __hf, __eql, __a)
+ {
+ }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
template <class _InputIterator>
hash_map(_InputIterator __f, _InputIterator __l)
: _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
template <class _InputIterator>
hash_map(_InputIterator __f, _InputIterator __l, size_type __n)
: _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
template <class _InputIterator>
hash_map(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf)
: _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
template <class _InputIterator>
hash_map(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
: _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_unique(__f, __l); }
-
-#else
- hash_map(const value_type* __f, const value_type* __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_map(const value_type* __f, const value_type* __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_map(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_map(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_unique(__f, __l); }
-
- hash_map(const_iterator __f, const_iterator __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_map(const_iterator __f, const_iterator __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_map(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_map(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_unique(__f, __l); }
-#endif
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
public:
size_type size() const { return _M_ht.size(); }
@@ -180,8 +154,7 @@ public:
bool empty() const { return _M_ht.empty(); }
void swap(hash_map& __hs) { _M_ht.swap(__hs._M_ht); }
- friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_map&,
- const hash_map&);
+ friend bool operator==<>(const hash_map&, const hash_map&);
iterator begin() { return _M_ht.begin(); }
iterator end() { return _M_ht.end(); }
@@ -189,39 +162,44 @@ public:
const_iterator end() const { return _M_ht.end(); }
public:
- @KWSYS_NAMESPACE@_stl::pair<iterator,bool> insert(const value_type& __obj)
- { return _M_ht.insert_unique(__obj); }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+ std::pair<iterator, bool> insert(const value_type& __obj)
+ {
+ return _M_ht.insert_unique(__obj);
+ }
template <class _InputIterator>
void insert(_InputIterator __f, _InputIterator __l)
- { _M_ht.insert_unique(__f,__l); }
-#else
- void insert(const value_type* __f, const value_type* __l) {
- _M_ht.insert_unique(__f,__l);
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
+ std::pair<iterator, bool> insert_noresize(const value_type& __obj)
+ {
+ return _M_ht.insert_unique_noresize(__obj);
}
- void insert(const_iterator __f, const_iterator __l)
- { _M_ht.insert_unique(__f, __l); }
-#endif
- @KWSYS_NAMESPACE@_stl::pair<iterator,bool> insert_noresize(const value_type& __obj)
- { return _M_ht.insert_unique_noresize(__obj); }
iterator find(const key_type& __key) { return _M_ht.find(__key); }
const_iterator find(const key_type& __key) const
- { return _M_ht.find(__key); }
+ {
+ return _M_ht.find(__key);
+ }
- _Tp& operator[](const key_type& __key) {
+ _Tp& operator[](const key_type& __key)
+ {
return _M_ht.find_or_insert(value_type(__key, _Tp())).second;
}
size_type count(const key_type& __key) const { return _M_ht.count(__key); }
- @KWSYS_NAMESPACE@_stl::pair<iterator, iterator> equal_range(const key_type& __key)
- { return _M_ht.equal_range(__key); }
- @KWSYS_NAMESPACE@_stl::pair<const_iterator, const_iterator>
- equal_range(const key_type& __key) const
- { return _M_ht.equal_range(__key); }
+ std::pair<iterator, iterator> equal_range(const key_type& __key)
+ {
+ return _M_ht.equal_range(__key);
+ }
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type& __key) const
+ {
+ return _M_ht.equal_range(__key);
+ }
- size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+ size_type erase(const key_type& __key) { return _M_ht.erase(__key); }
void erase(iterator __it) { _M_ht.erase(__it); }
void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
void clear() { _M_ht.clear(); }
@@ -230,53 +208,51 @@ public:
size_type bucket_count() const { return _M_ht.bucket_count(); }
size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
size_type elems_in_bucket(size_type __n) const
- { return _M_ht.elems_in_bucket(__n); }
+ {
+ return _M_ht.elems_in_bucket(__n);
+ }
};
template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
-bool
-operator==(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
- const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
+bool operator==(const hash_map<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm1,
+ const hash_map<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm2)
{
return __hm1._M_ht == __hm2._M_ht;
}
template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
-inline bool
-operator!=(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
- const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2) {
+inline bool operator!=(
+ const hash_map<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm1,
+ const hash_map<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm2)
+{
return !(__hm1 == __hm2);
}
template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
-inline void
-swap(hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
- hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
+inline void swap(hash_map<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm1,
+ hash_map<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm2)
{
__hm1.swap(__hm2);
}
// Forward declaration of equality operator; needed for friend declaration.
-template <class _Key, class _Tp,
- class _HashFcn = hash<_Key>,
- class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Key>,
- class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) >
+template <class _Key, class _Tp, class _HashFcn = hash<_Key>,
+ class _EqualKey = std::equal_to<_Key>,
+ class _Alloc = std::allocator<char> >
class hash_multimap;
template <class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
-bool
-operator==(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1,
- const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2);
+bool operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1,
+ const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2);
-template <class _Key, class _Tp, class _HashFcn, class _EqualKey,
- class _Alloc>
+template <class _Key, class _Tp, class _HashFcn, class _EqualKey, class _Alloc>
class hash_multimap
{
private:
- typedef hashtable<@KWSYS_NAMESPACE@_stl::pair<const _Key, _Tp>, _Key, _HashFcn,
+ typedef hashtable<std::pair<const _Key, _Tp>, _Key, _HashFcn,
hash_select1st<const _Key, _Tp>, _EqualKey, _Alloc>
- _Ht;
+ _Ht;
_Ht _M_ht;
public:
@@ -304,69 +280,51 @@ public:
allocator_type get_allocator() const { return _M_ht.get_allocator(); }
public:
- hash_multimap() : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+ hash_multimap()
+ : _M_ht(100, hasher(), key_equal(), allocator_type())
+ {
+ }
explicit hash_multimap(size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+ : _M_ht(__n, hasher(), key_equal(), allocator_type())
+ {
+ }
hash_multimap(size_type __n, const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+ : _M_ht(__n, __hf, key_equal(), allocator_type())
+ {
+ }
hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a) {}
+ : _M_ht(__n, __hf, __eql, __a)
+ {
+ }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
template <class _InputIterator>
hash_multimap(_InputIterator __f, _InputIterator __l)
: _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
template <class _InputIterator>
hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n)
: _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
template <class _InputIterator>
hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf)
: _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
template <class _InputIterator>
hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
: _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_equal(__f, __l); }
-
-#else
- hash_multimap(const value_type* __f, const value_type* __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multimap(const value_type* __f, const value_type* __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multimap(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multimap(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_equal(__f, __l); }
-
- hash_multimap(const_iterator __f, const_iterator __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multimap(const_iterator __f, const_iterator __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multimap(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multimap(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_equal(__f, __l); }
-#endif
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
public:
size_type size() const { return _M_ht.size(); }
@@ -374,8 +332,7 @@ public:
bool empty() const { return _M_ht.empty(); }
void swap(hash_multimap& __hs) { _M_ht.swap(__hs._M_ht); }
- friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_multimap&,
- const hash_multimap&);
+ friend bool operator==<>(const hash_multimap&, const hash_multimap&);
iterator begin() { return _M_ht.begin(); }
iterator end() { return _M_ht.end(); }
@@ -384,34 +341,38 @@ public:
public:
iterator insert(const value_type& __obj)
- { return _M_ht.insert_equal(__obj); }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+ {
+ return _M_ht.insert_equal(__obj);
+ }
template <class _InputIterator>
void insert(_InputIterator __f, _InputIterator __l)
- { _M_ht.insert_equal(__f,__l); }
-#else
- void insert(const value_type* __f, const value_type* __l) {
- _M_ht.insert_equal(__f,__l);
+ {
+ _M_ht.insert_equal(__f, __l);
}
- void insert(const_iterator __f, const_iterator __l)
- { _M_ht.insert_equal(__f, __l); }
-#endif
iterator insert_noresize(const value_type& __obj)
- { return _M_ht.insert_equal_noresize(__obj); }
+ {
+ return _M_ht.insert_equal_noresize(__obj);
+ }
iterator find(const key_type& __key) { return _M_ht.find(__key); }
const_iterator find(const key_type& __key) const
- { return _M_ht.find(__key); }
+ {
+ return _M_ht.find(__key);
+ }
size_type count(const key_type& __key) const { return _M_ht.count(__key); }
- @KWSYS_NAMESPACE@_stl::pair<iterator, iterator> equal_range(const key_type& __key)
- { return _M_ht.equal_range(__key); }
- @KWSYS_NAMESPACE@_stl::pair<const_iterator, const_iterator>
- equal_range(const key_type& __key) const
- { return _M_ht.equal_range(__key); }
+ std::pair<iterator, iterator> equal_range(const key_type& __key)
+ {
+ return _M_ht.equal_range(__key);
+ }
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type& __key) const
+ {
+ return _M_ht.equal_range(__key);
+ }
- size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+ size_type erase(const key_type& __key) { return _M_ht.erase(__key); }
void erase(iterator __it) { _M_ht.erase(__it); }
void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
void clear() { _M_ht.clear(); }
@@ -421,28 +382,29 @@ public:
size_type bucket_count() const { return _M_ht.bucket_count(); }
size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
size_type elems_in_bucket(size_type __n) const
- { return _M_ht.elems_in_bucket(__n); }
+ {
+ return _M_ht.elems_in_bucket(__n);
+ }
};
template <class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
-bool
-operator==(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1,
- const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2)
+bool operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1,
+ const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2)
{
return __hm1._M_ht == __hm2._M_ht;
}
template <class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
-inline bool
-operator!=(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1,
- const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2) {
+inline bool operator!=(
+ const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1,
+ const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2)
+{
return !(__hm1 == __hm2);
}
template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
-inline void
-swap(hash_multimap<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
- hash_multimap<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
+inline void swap(hash_multimap<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm1,
+ hash_multimap<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm2)
{
__hm1.swap(__hm2);
}
@@ -450,12 +412,12 @@ 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 5ee01a594..e3a0c6c44 100644
--- a/Source/kwsys/hash_set.hxx.in
+++ b/Source/kwsys/hash_set.hxx.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
/*
* Copyright (c) 1996
* Silicon Graphics Computer Systems, Inc.
@@ -38,49 +29,49 @@
#define @KWSYS_NAMESPACE@_hash_set_hxx
#include <@KWSYS_NAMESPACE@/hashtable.hxx>
+
#include <@KWSYS_NAMESPACE@/hash_fun.hxx>
-#include <@KWSYS_NAMESPACE@/stl/functional> // equal_to
+
+#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@
-{
+namespace @KWSYS_NAMESPACE@ {
// identity is an extension: it is not part of the standard.
template <class _Tp>
-struct _Identity : public @KWSYS_NAMESPACE@_stl::unary_function<_Tp,_Tp>
+struct _Identity : public std::unary_function<_Tp, _Tp>
{
const _Tp& operator()(const _Tp& __x) const { return __x; }
};
// Forward declaration of equality operator; needed for friend declaration.
-template <class _Value,
- class _HashFcn = hash<_Value>,
- class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Value>,
- class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) >
+template <class _Value, class _HashFcn = hash<_Value>,
+ class _EqualKey = std::equal_to<_Value>,
+ class _Alloc = std::allocator<char> >
class hash_set;
template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
-bool
-operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,
- const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2);
+bool operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2);
template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
class hash_set
{
private:
- typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>,
- _EqualKey, _Alloc> _Ht;
+ typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, _EqualKey,
+ _Alloc>
+ _Ht;
_Ht _M_ht;
public:
@@ -107,69 +98,50 @@ public:
public:
hash_set()
- : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+ : _M_ht(100, hasher(), key_equal(), allocator_type())
+ {
+ }
explicit hash_set(size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+ : _M_ht(__n, hasher(), key_equal(), allocator_type())
+ {
+ }
hash_set(size_type __n, const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+ : _M_ht(__n, __hf, key_equal(), allocator_type())
+ {
+ }
hash_set(size_type __n, const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a) {}
+ : _M_ht(__n, __hf, __eql, __a)
+ {
+ }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
template <class _InputIterator>
hash_set(_InputIterator __f, _InputIterator __l)
: _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
template <class _InputIterator>
hash_set(_InputIterator __f, _InputIterator __l, size_type __n)
: _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
template <class _InputIterator>
hash_set(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf)
: _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
template <class _InputIterator>
hash_set(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
: _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_unique(__f, __l); }
-#else
-
- hash_set(const value_type* __f, const value_type* __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_set(const value_type* __f, const value_type* __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_set(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_set(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_unique(__f, __l); }
-
- hash_set(const_iterator __f, const_iterator __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_set(const_iterator __f, const_iterator __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_set(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_unique(__f, __l); }
- hash_set(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_unique(__f, __l); }
-#endif
+ {
+ _M_ht.insert_unique(__f, __l);
+ }
public:
size_type size() const { return _M_ht.size(); }
@@ -177,46 +149,40 @@ public:
bool empty() const { return _M_ht.empty(); }
void swap(hash_set& __hs) { _M_ht.swap(__hs._M_ht); }
- friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_set&,
- const hash_set&);
+ friend bool operator==<>(const hash_set&, const hash_set&);
iterator begin() const { return _M_ht.begin(); }
iterator end() const { return _M_ht.end(); }
public:
- @KWSYS_NAMESPACE@_stl::pair<iterator, bool> insert(const value_type& __obj)
- {
- typedef typename _Ht::iterator _Ht_iterator;
- @KWSYS_NAMESPACE@_stl::pair<_Ht_iterator, bool> __p = _M_ht.insert_unique(__obj);
- return @KWSYS_NAMESPACE@_stl::pair<iterator,bool>(__p.first, __p.second);
- }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+ std::pair<iterator, bool> insert(const value_type& __obj)
+ {
+ typedef typename _Ht::iterator _Ht_iterator;
+ std::pair<_Ht_iterator, bool> __p = _M_ht.insert_unique(__obj);
+ return std::pair<iterator, bool>(__p.first, __p.second);
+ }
template <class _InputIterator>
void insert(_InputIterator __f, _InputIterator __l)
- { _M_ht.insert_unique(__f,__l); }
-#else
- void insert(const value_type* __f, const value_type* __l) {
- _M_ht.insert_unique(__f,__l);
+ {
+ _M_ht.insert_unique(__f, __l);
}
- void insert(const_iterator __f, const_iterator __l)
- {_M_ht.insert_unique(__f, __l); }
-#endif
- @KWSYS_NAMESPACE@_stl::pair<iterator, bool> insert_noresize(const value_type& __obj)
+ std::pair<iterator, bool> insert_noresize(const value_type& __obj)
{
typedef typename _Ht::iterator _Ht_iterator;
- @KWSYS_NAMESPACE@_stl::pair<_Ht_iterator, bool> __p =
- _M_ht.insert_unique_noresize(__obj);
- return @KWSYS_NAMESPACE@_stl::pair<iterator, bool>(__p.first, __p.second);
+ std::pair<_Ht_iterator, bool> __p = _M_ht.insert_unique_noresize(__obj);
+ return std::pair<iterator, bool>(__p.first, __p.second);
}
iterator find(const key_type& __key) const { return _M_ht.find(__key); }
size_type count(const key_type& __key) const { return _M_ht.count(__key); }
- @KWSYS_NAMESPACE@_stl::pair<iterator, iterator> equal_range(const key_type& __key) const
- { return _M_ht.equal_range(__key); }
+ std::pair<iterator, iterator> equal_range(const key_type& __key) const
+ {
+ return _M_ht.equal_range(__key);
+ }
- size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+ size_type erase(const key_type& __key) { return _M_ht.erase(__key); }
void erase(iterator __it) { _M_ht.erase(__it); }
void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
void clear() { _M_ht.clear(); }
@@ -226,50 +192,49 @@ public:
size_type bucket_count() const { return _M_ht.bucket_count(); }
size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
size_type elems_in_bucket(size_type __n) const
- { return _M_ht.elems_in_bucket(__n); }
+ {
+ return _M_ht.elems_in_bucket(__n);
+ }
};
template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
-bool
-operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,
- const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2)
+bool operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2)
{
return __hs1._M_ht == __hs2._M_ht;
}
template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
-inline bool
-operator!=(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,
- const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2) {
+inline bool operator!=(
+ const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2)
+{
return !(__hs1 == __hs2);
}
template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
-inline void
-swap(hash_set<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
- hash_set<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2)
+inline void swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
{
__hs1.swap(__hs2);
}
-template <class _Value,
- class _HashFcn = hash<_Value>,
- class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Value>,
- class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) >
+template <class _Value, class _HashFcn = hash<_Value>,
+ class _EqualKey = std::equal_to<_Value>,
+ class _Alloc = std::allocator<char> >
class hash_multiset;
template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
-bool
-operator==(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
- const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2);
-
+bool operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2);
template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
class hash_multiset
{
private:
- typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>,
- _EqualKey, _Alloc> _Ht;
+ typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, _EqualKey,
+ _Alloc>
+ _Ht;
_Ht _M_ht;
public:
@@ -296,69 +261,50 @@ public:
public:
hash_multiset()
- : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+ : _M_ht(100, hasher(), key_equal(), allocator_type())
+ {
+ }
explicit hash_multiset(size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+ : _M_ht(__n, hasher(), key_equal(), allocator_type())
+ {
+ }
hash_multiset(size_type __n, const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+ : _M_ht(__n, __hf, key_equal(), allocator_type())
+ {
+ }
hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a) {}
+ : _M_ht(__n, __hf, __eql, __a)
+ {
+ }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
template <class _InputIterator>
hash_multiset(_InputIterator __f, _InputIterator __l)
: _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
template <class _InputIterator>
hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n)
: _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
template <class _InputIterator>
hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf)
: _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
template <class _InputIterator>
hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n,
const hasher& __hf, const key_equal& __eql,
const allocator_type& __a = allocator_type())
: _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_equal(__f, __l); }
-#else
-
- hash_multiset(const value_type* __f, const value_type* __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multiset(const value_type* __f, const value_type* __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multiset(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multiset(const value_type* __f, const value_type* __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_equal(__f, __l); }
-
- hash_multiset(const_iterator __f, const_iterator __l)
- : _M_ht(100, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multiset(const_iterator __f, const_iterator __l, size_type __n)
- : _M_ht(__n, hasher(), key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multiset(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf)
- : _M_ht(__n, __hf, key_equal(), allocator_type())
- { _M_ht.insert_equal(__f, __l); }
- hash_multiset(const_iterator __f, const_iterator __l, size_type __n,
- const hasher& __hf, const key_equal& __eql,
- const allocator_type& __a = allocator_type())
- : _M_ht(__n, __hf, __eql, __a)
- { _M_ht.insert_equal(__f, __l); }
-#endif
+ {
+ _M_ht.insert_equal(__f, __l);
+ }
public:
size_type size() const { return _M_ht.size(); }
@@ -366,37 +312,36 @@ public:
bool empty() const { return _M_ht.empty(); }
void swap(hash_multiset& hs) { _M_ht.swap(hs._M_ht); }
- friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_multiset&,
- const hash_multiset&);
+ friend bool operator==<>(const hash_multiset&, const hash_multiset&);
iterator begin() const { return _M_ht.begin(); }
iterator end() const { return _M_ht.end(); }
public:
iterator insert(const value_type& __obj)
- { return _M_ht.insert_equal(__obj); }
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+ {
+ return _M_ht.insert_equal(__obj);
+ }
template <class _InputIterator>
void insert(_InputIterator __f, _InputIterator __l)
- { _M_ht.insert_equal(__f,__l); }
-#else
- void insert(const value_type* __f, const value_type* __l) {
- _M_ht.insert_equal(__f,__l);
+ {
+ _M_ht.insert_equal(__f, __l);
}
- void insert(const_iterator __f, const_iterator __l)
- { _M_ht.insert_equal(__f, __l); }
-#endif
iterator insert_noresize(const value_type& __obj)
- { return _M_ht.insert_equal_noresize(__obj); }
+ {
+ return _M_ht.insert_equal_noresize(__obj);
+ }
iterator find(const key_type& __key) const { return _M_ht.find(__key); }
size_type count(const key_type& __key) const { return _M_ht.count(__key); }
- @KWSYS_NAMESPACE@_stl::pair<iterator, iterator> equal_range(const key_type& __key) const
- { return _M_ht.equal_range(__key); }
+ std::pair<iterator, iterator> equal_range(const key_type& __key) const
+ {
+ return _M_ht.equal_range(__key);
+ }
- size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+ size_type erase(const key_type& __key) { return _M_ht.erase(__key); }
void erase(iterator __it) { _M_ht.erase(__it); }
void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
void clear() { _M_ht.clear(); }
@@ -406,40 +351,42 @@ public:
size_type bucket_count() const { return _M_ht.bucket_count(); }
size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
size_type elems_in_bucket(size_type __n) const
- { return _M_ht.elems_in_bucket(__n); }
+ {
+ return _M_ht.elems_in_bucket(__n);
+ }
};
template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
-bool
-operator==(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
- const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2)
+bool operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
{
return __hs1._M_ht == __hs2._M_ht;
}
template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
-inline bool
-operator!=(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
- const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) {
+inline bool operator!=(
+ const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
+{
return !(__hs1 == __hs2);
}
template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
-inline void
-swap(hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
- hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) {
+inline void swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
+ hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2)
+{
__hs1.swap(__hs2);
}
} // 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 651de82bf..dd92cb9d4 100644
--- a/Source/kwsys/hashtable.hxx.in
+++ b/Source/kwsys/hashtable.hxx.in
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
/*
* Copyright (c) 1996
* Silicon Graphics Computer Systems, Inc.
@@ -35,31 +26,31 @@
*
*/
#ifdef __BORLANDC__
-# pragma warn -8027 /* 'for' not inlined. */
-# pragma warn -8026 /* 'exception' not inlined. */
-#endif
+#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 <@KWSYS_NAMESPACE@/cstddef> // size_t
-#include <@KWSYS_NAMESPACE@/stl/algorithm> // lower_bound
-#include <@KWSYS_NAMESPACE@/stl/functional> // unary_function
-#include <@KWSYS_NAMESPACE@/stl/iterator> // iterator_traits
-#include <@KWSYS_NAMESPACE@/stl/memory> // allocator
-#include <@KWSYS_NAMESPACE@/stl/utility> // pair
-#include <@KWSYS_NAMESPACE@/stl/vector> // vector
+#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 */
+#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
+#pragma set woff 3970 /* pointer to int conversion */ 3321 3968
#endif
// In C++11, clang will warn about using dynamic exception specifications
@@ -67,278 +58,52 @@
// 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 @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE
-# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator< T >
-#elif @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE
-# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator
-#else
-# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::alloc
+#if __has_warning("-Wdeprecated")
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated"
#endif
-
-#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS
-# define @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a) _M_buckets(__a)
-# define @KWSYS_NAMESPACE@_HASH_BUCKETS_GET_ALLOCATOR(__b) , __b.get_allocator()
-#else
-# define @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a) _M_buckets()
-# define @KWSYS_NAMESPACE@_HASH_BUCKETS_GET_ALLOCATOR(__b)
#endif
-namespace @KWSYS_NAMESPACE@
-{
-
-//----------------------------------------------------------------------------
-// Define an allocator adaptor for platforms that do not provide an
-// allocator with the rebind member.
-#if !@KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND
-
-// Utility functions to convert item counts.
-inline size_t hash_sizeof(void*) { return sizeof(char); }
-inline size_t hash_sizeof(const void*) { return sizeof(char); }
-template <class TPtr> inline size_t hash_sizeof(TPtr p)
-{
- static_cast<void>(p);
- return sizeof(*p);
-}
-template <class POut, class PIn, class TSize>
-inline TSize hash_allocator_n(POut out, PIn in, TSize n)
-{
- return n*(hash_sizeof(out)/hash_sizeof(in) +
- (hash_sizeof(out)%hash_sizeof(in)>0));
-}
-
-// Define an allocation method to use the native allocator with
-// the proper signature. The following signatures of the allocate
-// method are used on various STL implementations:
-// pointer allocate(size_type, const void* hint)
-// pointer allocate(size_type)
-// static pointer allocate(size_type, const void* hint)
-// static pointer allocate(size_type)
-// Where pointer might be a real type or void*.
-// This set of overloads decodes the signature for a particular STL.
-// The extra three int/long arguments will favor certain signatures
-// over others in the case that multiple are present to avoid
-// ambiguity errors.
-template <class TAlloc, class PIn, class TSize, class THint, class POut>
-inline void hash_allocate(TAlloc* a, PIn (TAlloc::*allocate)(TSize, THint),
- TSize n_out, const void* hint, POut& out,
- int, int, int)
-{
- TSize n_in = hash_allocator_n(POut(), PIn(), n_out);
- void* vout = (a->*allocate)(n_in, const_cast<THint>(hint));
- out = static_cast<POut>(vout);
-}
-
-template <class TAlloc, class PIn, class TSize, class POut>
-inline void hash_allocate(TAlloc* a, PIn (TAlloc::*allocate)(TSize),
- TSize n_out, const void*, POut& out,
- int, int, long)
-{
- TSize n_in = hash_allocator_n(POut(), PIn(), n_out);
- void* vout = (a->*allocate)(n_in);
- out = static_cast<POut>(vout);
-}
-
-template <class PIn, class TSize, class THint, class POut>
-inline void hash_allocate(void*, PIn (*allocate)(TSize, THint),
- TSize n_out, const void* hint, POut& out,
- int, long, long)
-{
- TSize n_in = hash_allocator_n(POut(), PIn(), n_out);
- void* vout = allocate(n_in, const_cast<THint>(hint));
- out = static_cast<POut>(vout);
-}
-
-template <class PIn, class TSize, class POut>
-inline void hash_allocate(void*, PIn (*allocate)(TSize),
- TSize n_out, const void*, POut& out,
- long, long, long)
-{
- TSize n_in = hash_allocator_n(POut(), PIn(), n_out);
- void* vout = allocate(n_in);
- out = static_cast<POut>(vout);
-}
-
-// Define a deallocation method to use the native allocator with
-// the proper signature. The following signatures of the deallocate
-// method are used on various STL implementations:
-// void deallocate(pointer, size_type)
-// void deallocate(pointer)
-// static void deallocate(pointer, size_type)
-// static void deallocate(pointer)
-// Where pointer might be a real type or void*.
-// This set of overloads decodes the signature for a particular STL.
-// The extra three int/long arguments will favor certain signatures
-// over others in the case that multiple are present to avoid
-// ambiguity errors.
-template <class TAlloc, class PIn, class TSize, class PInReal, class POut>
-inline void hash_deallocate(TAlloc* a, void (TAlloc::*deallocate)(PIn, TSize),
- PInReal, POut p, TSize n_out, int, int, int)
-{
- TSize n_in = hash_allocator_n(POut(), PInReal(), n_out);
- void* vout = p;
- (a->*deallocate)(static_cast<PIn>(vout), n_in);
-}
-
-template <class TAlloc, class PIn, class TSize, class PInReal, class POut>
-inline void hash_deallocate(TAlloc* a, void (TAlloc::*deallocate)(PIn),
- PInReal, POut p, TSize, int, int, long)
-{
- void* vout = p;
- (a->*deallocate)(static_cast<PIn>(vout));
-}
-
-template <class PIn, class TSize, class PInReal, class POut>
-inline void hash_deallocate(void*, void (*deallocate)(PIn, TSize),
- PInReal, POut p, TSize n_out, int, long, long)
-{
- TSize n_in = hash_allocator_n(POut(), PInReal(), n_out);
- void* vout = p;
- deallocate(static_cast<PIn>(vout), n_in);
-}
-
-template <class PIn, class TSize, class PInReal, class POut>
-inline void hash_deallocate(void*, void (*deallocate)(PIn),
- PInReal, POut p, TSize, long, long, long)
-{
- void* vout = p;
- deallocate(static_cast<PIn>(vout));
-}
-
-// Use the same four overloads as hash_allocate to decode the type
-// really used for allocation. This is passed as PInReal to the
-// deallocate functions so that hash_allocator_n has the proper size.
-template <class TAlloc, class PIn, class TSize, class THint>
-inline PIn hash_allocate_type(PIn (TAlloc::*)(TSize, THint),
- int, int, int) { return 0; }
-template <class TAlloc, class PIn, class TSize>
-inline PIn hash_allocate_type(PIn (TAlloc::*)(TSize),
- int, int, long) { return 0; }
-template <class PIn, class TSize, class THint>
-inline PIn hash_allocate_type(PIn (*)(TSize, THint),
- int, long, long) { return 0; }
-template <class PIn, class TSize>
-inline PIn hash_allocate_type(PIn (*)(TSize),
- long, long, long) { return 0; }
-
-// Define the comparison operators in terms of a base type to avoid
-// needing templated versions.
-class hash_allocator_base {};
-inline bool operator==(const hash_allocator_base&,
- const hash_allocator_base&) throw() { return true; }
-inline bool operator!=(const hash_allocator_base&,
- const hash_allocator_base&) throw() { return false; }
-
-// Define the allocator template.
-template <class T, class Alloc>
-class hash_allocator: public hash_allocator_base
-{
-private:
- // Store the real allocator privately.
- typedef Alloc alloc_type;
- alloc_type alloc_;
-
-public:
- // Standard allocator interface.
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
-
- hash_allocator() throw(): alloc_() {}
- hash_allocator(const hash_allocator_base&) throw() : alloc_() {}
- hash_allocator(const hash_allocator& a) throw() : alloc_(a.alloc_) {}
- hash_allocator(const alloc_type& a) throw() : alloc_(a) {}
- ~hash_allocator() throw() {}
-# if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
- template <class U>
- struct rebind { typedef hash_allocator<U, alloc_type> other; };
-# endif
- pointer address(reference x) const { return &x; }
- const_pointer address(const_reference x) const { return &x; }
- typedef void* void_pointer;
- typedef const void* const_void_pointer;
- pointer allocate(size_type n=1, const_void_pointer hint = 0)
- {
- if(n)
- {
- pointer p;
- hash_allocate(&alloc_, &alloc_type::allocate, n, hint, p, 1, 1, 1);
- return p;
- }
- else
- {
- return 0;
- }
- }
- void deallocate(pointer p, size_type n=1)
- {
- if(n)
- {
- hash_deallocate(&alloc_, &alloc_type::deallocate,
- hash_allocate_type(&alloc_type::allocate, 1, 1, 1),
- p, n, 1, 1, 1);
- }
- }
-#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT
- size_type max_size(size_type s) const throw()
- {
- return alloc_.max_size(s);
- }
-#else
- size_type max_size() const throw()
- {
- size_type n = alloc_.max_size() / sizeof(value_type);
- return n>0? n:1;
- }
-#endif
- void construct(pointer p, const value_type& val) { new (p) value_type(val); }
- void destroy(pointer p) { (void)p; p->~value_type(); }
-};
-#endif
+namespace @KWSYS_NAMESPACE@ {
template <class _Val>
struct _Hashtable_node
{
_Hashtable_node* _M_next;
_Val _M_val;
+ void public_method_to_quiet_warning_about_all_methods_private();
+
+private:
+ void operator=(_Hashtable_node<_Val> const&); // poison node assignment
};
-template <class _Val, class _Key, class _HashFcn,
- class _ExtractKey, class _EqualKey,
- class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) >
+template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
+ class _EqualKey, class _Alloc = std::allocator<char> >
class hashtable;
-template <class _Val, class _Key, class _HashFcn,
- class _ExtractKey, class _EqualKey, class _Alloc>
+template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
+ class _EqualKey, class _Alloc>
struct _Hashtable_iterator;
-template <class _Val, class _Key, class _HashFcn,
- class _ExtractKey, class _EqualKey, class _Alloc>
+template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
+ class _EqualKey, class _Alloc>
struct _Hashtable_const_iterator;
-template <class _Val, class _Key, class _HashFcn,
- class _ExtractKey, class _EqualKey, class _Alloc>
-struct _Hashtable_iterator {
- typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
- _Hashtable;
- typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
- _ExtractKey, _EqualKey, _Alloc>
- iterator;
- typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
- _ExtractKey, _EqualKey, _Alloc>
- const_iterator;
+template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
+ class _EqualKey, class _Alloc>
+struct _Hashtable_iterator
+{
+ typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
+ _Hashtable;
+ typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey,
+ _Alloc>
+ iterator;
+ typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+ _EqualKey, _Alloc>
+ const_iterator;
typedef _Hashtable_node<_Val> _Node;
- typedef @KWSYS_NAMESPACE@_stl::forward_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef _Val value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
@@ -349,33 +114,34 @@ struct _Hashtable_iterator {
_Hashtable* _M_ht;
_Hashtable_iterator(_Node* __n, _Hashtable* __tab)
- : _M_cur(__n), _M_ht(__tab) {}
+ : _M_cur(__n)
+ , _M_ht(__tab)
+ {
+ }
_Hashtable_iterator() {}
reference operator*() const { return _M_cur->_M_val; }
pointer operator->() const { return &(operator*()); }
iterator& operator++();
iterator operator++(int);
- bool operator==(const iterator& __it) const
- { return _M_cur == __it._M_cur; }
- bool operator!=(const iterator& __it) const
- { return _M_cur != __it._M_cur; }
+ bool operator==(const iterator& __it) const { return _M_cur == __it._M_cur; }
+ bool operator!=(const iterator& __it) const { return _M_cur != __it._M_cur; }
};
-
-template <class _Val, class _Key, class _HashFcn,
- class _ExtractKey, class _EqualKey, class _Alloc>
-struct _Hashtable_const_iterator {
- typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
- _Hashtable;
- typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
- _ExtractKey,_EqualKey,_Alloc>
- iterator;
- typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
- _ExtractKey, _EqualKey, _Alloc>
- const_iterator;
+template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
+ class _EqualKey, class _Alloc>
+struct _Hashtable_const_iterator
+{
+ typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
+ _Hashtable;
+ typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey,
+ _Alloc>
+ iterator;
+ typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+ _EqualKey, _Alloc>
+ const_iterator;
typedef _Hashtable_node<_Val> _Node;
- typedef @KWSYS_NAMESPACE@_stl::forward_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef _Val value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
@@ -386,45 +152,59 @@ struct _Hashtable_const_iterator {
const _Hashtable* _M_ht;
_Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
- : _M_cur(__n), _M_ht(__tab) {}
+ : _M_cur(__n)
+ , _M_ht(__tab)
+ {
+ }
_Hashtable_const_iterator() {}
_Hashtable_const_iterator(const iterator& __it)
- : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
+ : _M_cur(__it._M_cur)
+ , _M_ht(__it._M_ht)
+ {
+ }
reference operator*() const { return _M_cur->_M_val; }
pointer operator->() const { return &(operator*()); }
const_iterator& operator++();
const_iterator operator++(int);
bool operator==(const const_iterator& __it) const
- { return _M_cur == __it._M_cur; }
+ {
+ return _M_cur == __it._M_cur;
+ }
bool operator!=(const const_iterator& __it) const
- { return _M_cur != __it._M_cur; }
+ {
+ return _M_cur != __it._M_cur;
+ }
};
// Note: assumes long is at least 32 bits.
-enum { _stl_num_primes = 31 };
+enum
+{
+ _stl_num_primes = 31
+};
// create a function with a static local to that function that returns
// the static
-static inline const unsigned long* get_stl_prime_list() {
-
-static const unsigned long _stl_prime_list[_stl_num_primes] =
+static inline const unsigned long* get_stl_prime_list()
{
- 5ul, 11ul, 23ul,
- 53ul, 97ul, 193ul, 389ul, 769ul,
- 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
- 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
- 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
- 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
- 1610612741ul, 3221225473ul, 4294967291ul
-};
-return &_stl_prime_list[0]; }
+ static const unsigned long _stl_prime_list[_stl_num_primes] = {
+ 5ul, 11ul, 23ul, 53ul, 97ul,
+ 193ul, 389ul, 769ul, 1543ul, 3079ul,
+ 6151ul, 12289ul, 24593ul, 49157ul, 98317ul,
+ 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul,
+ 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul,
+ 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
+ 4294967291ul
+ };
-inline size_t _stl_next_prime(size_t __n)
+ return &_stl_prime_list[0];
+}
+
+static inline size_t _stl_next_prime(size_t __n)
{
const unsigned long* __first = get_stl_prime_list();
const unsigned long* __last = get_stl_prime_list() + (int)_stl_num_primes;
- const unsigned long* pos = @KWSYS_NAMESPACE@_stl::lower_bound(__first, __last, __n);
+ const unsigned long* pos = std::lower_bound(__first, __last, __n);
return pos == __last ? *(__last - 1) : *pos;
}
@@ -434,8 +214,8 @@ template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
class hashtable;
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
- const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
+bool operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
+ const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2);
// Hashtables handle allocators a bit differently than other containers
// do. If we're using standard-conforming allocators, then a hashtable
@@ -445,20 +225,21 @@ bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
// Additionally, a base class wouldn't serve any other purposes; it
// wouldn't, for example, simplify the exception-handling code.
-template <class _Val, class _Key, class _HashFcn,
- class _ExtractKey, class _EqualKey, class _Alloc>
-class hashtable {
+template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
+ class _EqualKey, class _Alloc>
+class hashtable
+{
public:
typedef _Key key_type;
typedef _Val value_type;
typedef _HashFcn hasher;
typedef _EqualKey key_equal;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef value_type* pointer;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type* pointer;
typedef const value_type* const_pointer;
- typedef value_type& reference;
+ typedef value_type& reference;
typedef const value_type& const_reference;
hasher hash_funct() const { return _M_hash; }
@@ -467,93 +248,78 @@ public:
private:
typedef _Hashtable_node<_Val> _Node;
-#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND
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;
- typedef typename _Alloc::template rebind<_Node*>::other _M_node_ptr_allocator_type;
- typedef @KWSYS_NAMESPACE@_stl::vector<_Node*,_M_node_ptr_allocator_type> _M_buckets_type;
-#else
-public:
- typedef hash_allocator<_Val, _Alloc> allocator_type;
- allocator_type get_allocator() const { return allocator_type(); }
-private:
- typedef hash_allocator<_Node, _Alloc> _M_node_allocator_type;
-# if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS
- typedef hash_allocator<_Node*, _Alloc> _M_node_ptr_allocator_type;
-# else
- typedef _Alloc _M_node_ptr_allocator_type;
-# endif
- typedef @KWSYS_NAMESPACE@_stl::vector<_Node*,_M_node_ptr_allocator_type> _M_buckets_type;
-#endif
+ typedef
+ typename _Alloc::template rebind<_Node>::other _M_node_allocator_type;
+ typedef
+ typename _Alloc::template rebind<_Node*>::other _M_node_ptr_allocator_type;
+ typedef std::vector<_Node*, _M_node_ptr_allocator_type> _M_buckets_type;
private:
_M_node_allocator_type _M_node_allocator;
- hasher _M_hash;
- key_equal _M_equals;
- _ExtractKey _M_get_key;
- _M_buckets_type _M_buckets;
- size_type _M_num_elements;
+ hasher _M_hash;
+ key_equal _M_equals;
+ _ExtractKey _M_get_key;
+ _M_buckets_type _M_buckets;
+ size_type _M_num_elements;
_Node* _M_get_node() { return _M_node_allocator.allocate(1); }
void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
public:
- typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
- iterator;
- typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
- _Alloc>
- const_iterator;
-
- friend struct
- _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
- friend struct
- _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
+ typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey,
+ _Alloc>
+ iterator;
+ typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+ _EqualKey, _Alloc>
+ const_iterator;
+
+ friend struct _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+ _EqualKey, _Alloc>;
+ friend struct _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+ _EqualKey, _Alloc>;
public:
- hashtable(size_type __n,
- const _HashFcn& __hf,
- const _EqualKey& __eql,
+ hashtable(size_type __n, const _HashFcn& __hf, const _EqualKey& __eql,
const _ExtractKey& __ext,
const allocator_type& __a = allocator_type())
- : _M_node_allocator(__a),
- _M_hash(__hf),
- _M_equals(__eql),
- _M_get_key(__ext),
- @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a),
- _M_num_elements(0)
+ : _M_node_allocator(__a)
+ , _M_hash(__hf)
+ , _M_equals(__eql)
+ , _M_get_key(__ext)
+ , _M_buckets(__a)
+ , _M_num_elements(0)
{
_M_initialize_buckets(__n);
}
- hashtable(size_type __n,
- const _HashFcn& __hf,
- const _EqualKey& __eql,
+ hashtable(size_type __n, const _HashFcn& __hf, const _EqualKey& __eql,
const allocator_type& __a = allocator_type())
- : _M_node_allocator(__a),
- _M_hash(__hf),
- _M_equals(__eql),
- _M_get_key(_ExtractKey()),
- @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a),
- _M_num_elements(0)
+ : _M_node_allocator(__a)
+ , _M_hash(__hf)
+ , _M_equals(__eql)
+ , _M_get_key(_ExtractKey())
+ , _M_buckets(__a)
+ , _M_num_elements(0)
{
_M_initialize_buckets(__n);
}
hashtable(const hashtable& __ht)
- : _M_node_allocator(__ht.get_allocator()),
- _M_hash(__ht._M_hash),
- _M_equals(__ht._M_equals),
- _M_get_key(__ht._M_get_key),
- @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__ht.get_allocator()),
- _M_num_elements(0)
+ : _M_node_allocator(__ht.get_allocator())
+ , _M_hash(__ht._M_hash)
+ , _M_equals(__ht._M_equals)
+ , _M_get_key(__ht._M_get_key)
+ , _M_buckets(__ht.get_allocator())
+ , _M_num_elements(0)
{
_M_copy_from(__ht);
}
- hashtable& operator= (const hashtable& __ht)
+ hashtable& operator=(const hashtable& __ht)
{
if (&__ht != this) {
clear();
@@ -573,11 +339,11 @@ public:
void swap(hashtable& __ht)
{
- @KWSYS_NAMESPACE@_stl::swap(_M_hash, __ht._M_hash);
- @KWSYS_NAMESPACE@_stl::swap(_M_equals, __ht._M_equals);
- @KWSYS_NAMESPACE@_stl::swap(_M_get_key, __ht._M_get_key);
+ std::swap(_M_hash, __ht._M_hash);
+ std::swap(_M_equals, __ht._M_equals);
+ std::swap(_M_get_key, __ht._M_get_key);
_M_buckets.swap(__ht._M_buckets);
- @KWSYS_NAMESPACE@_stl::swap(_M_num_elements, __ht._M_num_elements);
+ std::swap(_M_num_elements, __ht._M_num_elements);
}
iterator begin()
@@ -600,15 +366,15 @@ public:
const_iterator end() const { return const_iterator(0, this); }
- friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hashtable&,
- const hashtable&);
+ friend bool operator==<>(const hashtable&, const hashtable&);
public:
-
size_type bucket_count() const { return _M_buckets.size(); }
size_type max_bucket_count() const
- { return get_stl_prime_list()[(int)_stl_num_primes - 1]; }
+ {
+ return get_stl_prime_list()[(int)_stl_num_primes - 1];
+ }
size_type elems_in_bucket(size_type __bucket) const
{
@@ -618,7 +384,7 @@ public:
return __result;
}
- @KWSYS_NAMESPACE@_stl::pair<iterator, bool> insert_unique(const value_type& __obj)
+ std::pair<iterator, bool> insert_unique(const value_type& __obj)
{
resize(_M_num_elements + 1);
return insert_unique_noresize(__obj);
@@ -630,119 +396,73 @@ public:
return insert_equal_noresize(__obj);
}
- @KWSYS_NAMESPACE@_stl::pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
+ std::pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
iterator insert_equal_noresize(const value_type& __obj);
-#if @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_TRAITS
-# define @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(T,I) \
- typename @KWSYS_NAMESPACE@_stl::iterator_traits< T >::iterator_category()
-#elif @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_CATEGORY
-# define @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(T,I) \
- @KWSYS_NAMESPACE@_stl::iterator_category( I )
-#elif @KWSYS_NAMESPACE@_STL_HAS___ITERATOR_CATEGORY
-# define @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(T,I) \
- @KWSYS_NAMESPACE@_stl::__iterator_category( I )
-#endif
-
-#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES && defined(@KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY)
template <class _InputIterator>
void insert_unique(_InputIterator __f, _InputIterator __l)
{
- insert_unique(__f, __l,
- @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(_InputIterator, __f));
+ insert_unique(
+ __f, __l,
+ typename std::iterator_traits<_InputIterator>::iterator_category());
}
template <class _InputIterator>
void insert_equal(_InputIterator __f, _InputIterator __l)
{
- insert_equal(__f, __l,
- @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(_InputIterator, __f));
+ insert_equal(
+ __f, __l,
+ typename std::iterator_traits<_InputIterator>::iterator_category());
}
template <class _InputIterator>
void insert_unique(_InputIterator __f, _InputIterator __l,
- @KWSYS_NAMESPACE@_stl::input_iterator_tag)
+ std::input_iterator_tag)
{
- for ( ; __f != __l; ++__f)
+ for (; __f != __l; ++__f)
insert_unique(*__f);
}
template <class _InputIterator>
void insert_equal(_InputIterator __f, _InputIterator __l,
- @KWSYS_NAMESPACE@_stl::input_iterator_tag)
+ std::input_iterator_tag)
{
- for ( ; __f != __l; ++__f)
+ for (; __f != __l; ++__f)
insert_equal(*__f);
}
template <class _ForwardIterator>
void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
- @KWSYS_NAMESPACE@_stl::forward_iterator_tag)
+ std::forward_iterator_tag)
{
size_type __n = 0;
- @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n);
+ std::distance(__f, __l, __n);
resize(_M_num_elements + __n);
- for ( ; __n > 0; --__n, ++__f)
+ for (; __n > 0; --__n, ++__f)
insert_unique_noresize(*__f);
}
template <class _ForwardIterator>
void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
- @KWSYS_NAMESPACE@_stl::forward_iterator_tag)
+ std::forward_iterator_tag)
{
size_type __n = 0;
- @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n);
- resize(_M_num_elements + __n);
- for ( ; __n > 0; --__n, ++__f)
- insert_equal_noresize(*__f);
- }
-
-#else
- void insert_unique(const value_type* __f, const value_type* __l)
- {
- size_type __n = __l - __f;
- resize(_M_num_elements + __n);
- for ( ; __n > 0; --__n, ++__f)
- insert_unique_noresize(*__f);
- }
-
- void insert_equal(const value_type* __f, const value_type* __l)
- {
- size_type __n = __l - __f;
+ std::distance(__f, __l, __n);
resize(_M_num_elements + __n);
- for ( ; __n > 0; --__n, ++__f)
+ for (; __n > 0; --__n, ++__f)
insert_equal_noresize(*__f);
}
- void insert_unique(const_iterator __f, const_iterator __l)
- {
- size_type __n = 0;
- @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n);
- resize(_M_num_elements + __n);
- for ( ; __n > 0; --__n, ++__f)
- insert_unique_noresize(*__f);
- }
-
- void insert_equal(const_iterator __f, const_iterator __l)
- {
- size_type __n = 0;
- @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n);
- resize(_M_num_elements + __n);
- for ( ; __n > 0; --__n, ++__f)
- insert_equal_noresize(*__f);
- }
-#endif
-
reference find_or_insert(const value_type& __obj);
iterator find(const key_type& __key)
{
size_type __n = _M_bkt_num_key(__key);
_Node* __first;
- for ( __first = _M_buckets[__n];
- __first && !_M_equals(_M_get_key(__first->_M_val), __key);
- __first = __first->_M_next)
- {}
+ for (__first = _M_buckets[__n];
+ __first && !_M_equals(_M_get_key(__first->_M_val), __key);
+ __first = __first->_M_next) {
+ }
return iterator(__first, this);
}
@@ -750,10 +470,10 @@ public:
{
size_type __n = _M_bkt_num_key(__key);
const _Node* __first;
- for ( __first = _M_buckets[__n];
- __first && !_M_equals(_M_get_key(__first->_M_val), __key);
- __first = __first->_M_next)
- {}
+ for (__first = _M_buckets[__n];
+ __first && !_M_equals(_M_get_key(__first->_M_val), __key);
+ __first = __first->_M_next) {
+ }
return const_iterator(__first, this);
}
@@ -768,11 +488,10 @@ public:
return __result;
}
- @KWSYS_NAMESPACE@_stl::pair<iterator, iterator>
- equal_range(const key_type& __key);
+ std::pair<iterator, iterator> equal_range(const key_type& __key);
- @KWSYS_NAMESPACE@_stl::pair<const_iterator, const_iterator>
- equal_range(const key_type& __key) const;
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type& __key) const;
size_type erase(const key_type& __key);
void erase(const iterator& __it);
@@ -785,14 +504,13 @@ public:
void clear();
private:
- size_type _M_next_size(size_type __n) const
- { return _stl_next_prime(__n); }
+ size_type _M_next_size(size_type __n) const { return _stl_next_prime(__n); }
void _M_initialize_buckets(size_type __n)
{
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*)0);
_M_num_elements = 0;
}
@@ -816,15 +534,12 @@ private:
return _M_bkt_num_key(_M_get_key(__obj), __n);
}
- void construct(_Val* p, const _Val& v)
- {
- new (p) _Val(v);
- }
+ void construct(_Val* p, const _Val& v) { new (p) _Val(v); }
void destroy(_Val* p)
- {
+ {
(void)p;
p->~_Val();
- }
+ }
_Node* _M_new_node(const value_type& __obj)
{
@@ -833,8 +548,10 @@ private:
try {
construct(&__n->_M_val, __obj);
return __n;
+ } catch (...) {
+ _M_put_node(__n);
+ throw;
}
- catch(...) {_M_put_node(__n); throw;}
}
void _M_delete_node(_Node* __n)
@@ -847,13 +564,12 @@ private:
void _M_erase_bucket(const size_type __n, _Node* __last);
void _M_copy_from(const hashtable& __ht);
-
};
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>&
+ _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
{
const _Node* __old = _M_cur;
_M_cur = _M_cur->_M_next;
@@ -867,8 +583,8 @@ _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
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)
+inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
+ _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
{
iterator __tmp = *this;
++*this;
@@ -877,8 +593,8 @@ _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
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>&
+ _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
{
const _Node* __old = _M_cur;
_M_cur = _M_cur->_M_next;
@@ -892,8 +608,8 @@ _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
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)
+inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
+ _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
{
const_iterator __tmp = *this;
++*this;
@@ -901,18 +617,18 @@ _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
- const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
+bool operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
+ const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
{
- typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
+ typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node;
if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
return false;
for (int __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
_Node* __cur1 = __ht1._M_buckets[__n];
_Node* __cur2 = __ht2._M_buckets[__n];
- for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
- __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
- {}
+ for (; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
+ __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) {
+ }
if (__cur1 || __cur2)
return false;
}
@@ -920,41 +636,43 @@ bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
- const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
+inline bool operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
+ const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
+{
return !(__ht1 == __ht2);
}
template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
class _All>
inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
- hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
+ hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2)
+{
__ht1.swap(__ht2);
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-@KWSYS_NAMESPACE@_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::insert_unique_noresize(const value_type& __obj)
+std::pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool>
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::insert_unique_noresize(
+ const value_type& __obj)
{
const size_type __n = _M_bkt_num(__obj);
_Node* __first = _M_buckets[__n];
for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
- return @KWSYS_NAMESPACE@_stl::pair<iterator, bool>(iterator(__cur, this), false);
+ return std::pair<iterator, bool>(iterator(__cur, this), false);
_Node* __tmp = _M_new_node(__obj);
__tmp->_M_next = __first;
_M_buckets[__n] = __tmp;
++_M_num_elements;
- return @KWSYS_NAMESPACE@_stl::pair<iterator, bool>(iterator(__tmp, this), true);
+ return std::pair<iterator, bool>(iterator(__tmp, this), true);
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::insert_equal_noresize(const value_type& __obj)
+typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::insert_equal_noresize(
+ const value_type& __obj)
{
const size_type __n = _M_bkt_num(__obj);
_Node* __first = _M_buckets[__n];
@@ -976,8 +694,8 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
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);
@@ -996,11 +714,11 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-@KWSYS_NAMESPACE@_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
- @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
+std::pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
+ typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator>
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::equal_range(const key_type& __key)
{
- typedef @KWSYS_NAMESPACE@_stl::pair<iterator, iterator> _Pii;
+ typedef std::pair<iterator, iterator> _Pii;
const size_type __n = _M_bkt_num_key(__key);
for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
@@ -1011,27 +729,25 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
if (_M_buckets[__m])
return _Pii(iterator(__first, this),
- iterator(_M_buckets[__m], this));
+ iterator(_M_buckets[__m], this));
return _Pii(iterator(__first, this), end());
}
return _Pii(end(), end());
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-@KWSYS_NAMESPACE@_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
- @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::equal_range(const key_type& __key) const
+std::pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator,
+ typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator>
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::equal_range(
+ const key_type& __key) const
{
- typedef @KWSYS_NAMESPACE@_stl::pair<const_iterator, const_iterator> _Pii;
+ typedef std::pair<const_iterator, const_iterator> _Pii;
const size_type __n = _M_bkt_num_key(__key);
- for (const _Node* __first = _M_buckets[__n] ;
- __first;
+ for (const _Node* __first = _M_buckets[__n]; __first;
__first = __first->_M_next) {
if (_M_equals(_M_get_key(__first->_M_val), __key)) {
- for (const _Node* __cur = __first->_M_next;
- __cur;
+ for (const _Node* __cur = __first->_M_next; __cur;
__cur = __cur->_M_next)
if (!_M_equals(_M_get_key(__cur->_M_val), __key))
return _Pii(const_iterator(__first, this),
@@ -1047,8 +763,8 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
+typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::erase(const key_type& __key)
{
const size_type __n = _M_bkt_num_key(__key);
_Node* __first = _M_buckets[__n];
@@ -1064,8 +780,7 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
__next = __cur->_M_next;
++__erased;
--_M_num_elements;
- }
- else {
+ } else {
__cur = __next;
__next = __cur->_M_next;
}
@@ -1081,7 +796,7 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::erase(const iterator& __it)
{
_Node* __p = __it._M_cur;
if (__p) {
@@ -1092,8 +807,7 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
_M_buckets[__n] = __cur->_M_next;
_M_delete_node(__cur);
--_M_num_elements;
- }
- else {
+ } else {
_Node* __next = __cur->_M_next;
while (__next) {
if (__next == __p) {
@@ -1101,8 +815,7 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
_M_delete_node(__next);
--_M_num_elements;
break;
- }
- else {
+ } else {
__cur = __next;
__next = __cur->_M_next;
}
@@ -1112,13 +825,13 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::erase(iterator __first, iterator __last)
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::erase(iterator __first,
+ iterator __last)
{
- size_type __f_bucket = __first._M_cur ?
- _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
- size_type __l_bucket = __last._M_cur ?
- _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
+ size_type __f_bucket =
+ __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
+ size_type __l_bucket =
+ __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
if (__first._M_cur == __last._M_cur)
return;
@@ -1134,9 +847,8 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-inline void
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
- const_iterator __last)
+inline void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::erase(
+ const_iterator __first, const_iterator __last)
{
erase(iterator(const_cast<_Node*>(__first._M_cur),
const_cast<hashtable*>(__first._M_ht)),
@@ -1145,24 +857,22 @@ hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-inline void
-hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
+inline void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::erase(
+ const const_iterator& __it)
{
erase(iterator(const_cast<_Node*>(__it._M_cur),
const_cast<hashtable*>(__it._M_ht)));
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::resize(size_type __num_elements_hint)
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::resize(
+ size_type __num_elements_hint)
{
const size_type __old_n = _M_buckets.size();
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)
- @KWSYS_NAMESPACE@_HASH_BUCKETS_GET_ALLOCATOR(_M_buckets));
+ _M_buckets_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
try {
for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
_Node* __first = _M_buckets[__bucket];
@@ -1175,8 +885,7 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
}
_M_buckets.swap(__tmp);
- }
- catch(...) {
+ } catch (...) {
for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
while (__tmp[__bucket]) {
_Node* __next = __tmp[__bucket]->_M_next;
@@ -1191,16 +900,15 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_M_erase_bucket(
+ const size_type __n, _Node* __first, _Node* __last)
{
_Node* __cur = _M_buckets[__n];
if (__cur == __first)
_M_erase_bucket(__n, __last);
else {
_Node* __next;
- for (__next = __cur->_M_next;
- __next != __first;
+ for (__next = __cur->_M_next; __next != __first;
__cur = __next, __next = __cur->_M_next)
;
while (__next != __last) {
@@ -1213,8 +921,8 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::_M_erase_bucket(const size_type __n, _Node* __last)
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_M_erase_bucket(
+ const size_type __n, _Node* __last)
{
_Node* __cur = _M_buckets[__n];
while (__cur != __last) {
@@ -1227,7 +935,7 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::clear()
{
for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
_Node* __cur = _M_buckets[__i];
@@ -1241,14 +949,13 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
_M_num_elements = 0;
}
-
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
- ::_M_copy_from(const hashtable& __ht)
+void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_M_copy_from(
+ const hashtable& __ht)
{
_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*)0);
try {
for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
const _Node* __cur = __ht._M_buckets[__i];
@@ -1256,8 +963,7 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
_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;
@@ -1265,29 +971,23 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
}
}
_M_num_elements = __ht._M_num_elements;
+ } catch (...) {
+ clear();
+ throw;
}
- catch(...) {clear(); throw;}
}
} // namespace @KWSYS_NAMESPACE@
-// Normally the comparison operators should be found in the @KWSYS_NAMESPACE@
-// namespace by argument dependent lookup. For compilers that do not
-// support it we must bring them into the global namespace now.
-#if !@KWSYS_NAMESPACE@_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP
-using @KWSYS_NAMESPACE@::operator==;
-using @KWSYS_NAMESPACE@::operator!=;
-#endif
-
// Undo warning suppression.
#if defined(__clang__) && defined(__has_warning)
-# if __has_warning("-Wdeprecated")
-# pragma clang diagnostic pop
-# endif
+#if __has_warning("-Wdeprecated")
+#pragma clang diagnostic pop
+#endif
#endif
#if defined(_MSC_VER)
-# pragma warning (pop)
+#pragma warning(pop)
#endif
#endif
diff --git a/Source/kwsys/kwsysHeaderDump.pl b/Source/kwsys/kwsysHeaderDump.pl
index 0dc4a5204..e3391e762 100755
--- a/Source/kwsys/kwsysHeaderDump.pl
+++ b/Source/kwsys/kwsysHeaderDump.pl
@@ -1,15 +1,6 @@
#!/usr/bin/perl
-#=============================================================================
-# KWSys - Kitware System Library
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing#kwsys for details.
if ( $#ARGV+1 < 2 )
{
diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake
index f9ee254f0..5386a49a3 100644
--- a/Source/kwsys/kwsysPlatformTests.cmake
+++ b/Source/kwsys/kwsysPlatformTests.cmake
@@ -1,19 +1,11 @@
-#=============================================================================
-# KWSys - Kitware System Library
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing#kwsys for details.
+
SET(KWSYS_PLATFORM_TEST_FILE_C kwsysPlatformTestsC.c)
SET(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx)
MACRO(KWSYS_PLATFORM_TEST lang var description invert)
- IF("${var}_COMPILED" MATCHES "^${var}_COMPILED$")
+ IF(NOT DEFINED ${var}_COMPILED)
MESSAGE(STATUS "${description}")
TRY_COMPILE(${var}_COMPILED
${CMAKE_CURRENT_BINARY_DIR}
@@ -25,42 +17,42 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert)
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"${description} compiled with the following output:\n${OUTPUT}\n\n")
- ELSE(${var}_COMPILED)
+ ELSE()
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"${description} failed to compile with the following output:\n${OUTPUT}\n\n")
- ENDIF(${var}_COMPILED)
+ ENDIF()
IF(${invert} MATCHES INVERT)
IF(${var}_COMPILED)
MESSAGE(STATUS "${description} - no")
- ELSE(${var}_COMPILED)
+ ELSE()
MESSAGE(STATUS "${description} - yes")
- ENDIF(${var}_COMPILED)
- ELSE(${invert} MATCHES INVERT)
+ ENDIF()
+ ELSE()
IF(${var}_COMPILED)
MESSAGE(STATUS "${description} - yes")
- ELSE(${var}_COMPILED)
+ ELSE()
MESSAGE(STATUS "${description} - no")
- ENDIF(${var}_COMPILED)
- ENDIF(${invert} MATCHES INVERT)
- ENDIF("${var}_COMPILED" MATCHES "^${var}_COMPILED$")
+ ENDIF()
+ ENDIF()
+ ENDIF()
IF(${invert} MATCHES INVERT)
IF(${var}_COMPILED)
SET(${var} 0)
- ELSE(${var}_COMPILED)
+ ELSE()
SET(${var} 1)
- ENDIF(${var}_COMPILED)
- ELSE(${invert} MATCHES INVERT)
+ ENDIF()
+ ELSE()
IF(${var}_COMPILED)
SET(${var} 1)
- ELSE(${var}_COMPILED)
+ ELSE()
SET(${var} 0)
- ENDIF(${var}_COMPILED)
- ENDIF(${invert} MATCHES INVERT)
-ENDMACRO(KWSYS_PLATFORM_TEST)
+ ENDIF()
+ ENDIF()
+ENDMACRO()
MACRO(KWSYS_PLATFORM_TEST_RUN lang var description invert)
- IF("${var}" MATCHES "^${var}$")
+ IF(NOT DEFINED ${var})
MESSAGE(STATUS "${description}")
TRY_RUN(${var} ${var}_COMPILED
${CMAKE_CURRENT_BINARY_DIR}
@@ -74,63 +66,63 @@ MACRO(KWSYS_PLATFORM_TEST_RUN lang var description invert)
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"${description} compiled but failed to run with the following output:\n${OUTPUT}\n\n")
- ELSE(${var})
+ ELSE()
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"${description} compiled and ran with the following output:\n${OUTPUT}\n\n")
- ENDIF(${var})
- ELSE(${var}_COMPILED)
+ ENDIF()
+ ELSE()
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"${description} failed to compile with the following output:\n${OUTPUT}\n\n")
SET(${var} -1 CACHE INTERNAL "${description} failed to compile.")
- ENDIF(${var}_COMPILED)
+ ENDIF()
IF(${invert} MATCHES INVERT)
IF(${var}_COMPILED)
IF(${var})
MESSAGE(STATUS "${description} - yes")
- ELSE(${var})
+ ELSE()
MESSAGE(STATUS "${description} - no")
- ENDIF(${var})
- ELSE(${var}_COMPILED)
+ ENDIF()
+ ELSE()
MESSAGE(STATUS "${description} - failed to compile")
- ENDIF(${var}_COMPILED)
- ELSE(${invert} MATCHES INVERT)
+ ENDIF()
+ ELSE()
IF(${var}_COMPILED)
IF(${var})
MESSAGE(STATUS "${description} - no")
- ELSE(${var})
+ ELSE()
MESSAGE(STATUS "${description} - yes")
- ENDIF(${var})
- ELSE(${var}_COMPILED)
+ ENDIF()
+ ELSE()
MESSAGE(STATUS "${description} - failed to compile")
- ENDIF(${var}_COMPILED)
- ENDIF(${invert} MATCHES INVERT)
- ENDIF("${var}" MATCHES "^${var}$")
+ ENDIF()
+ ENDIF()
+ ENDIF()
IF(${invert} MATCHES INVERT)
IF(${var}_COMPILED)
IF(${var})
SET(${var} 1)
- ELSE(${var})
+ ELSE()
SET(${var} 0)
- ENDIF(${var})
- ELSE(${var}_COMPILED)
+ ENDIF()
+ ELSE()
SET(${var} 1)
- ENDIF(${var}_COMPILED)
- ELSE(${invert} MATCHES INVERT)
+ ENDIF()
+ ELSE()
IF(${var}_COMPILED)
IF(${var})
SET(${var} 0)
- ELSE(${var})
+ ELSE()
SET(${var} 1)
- ENDIF(${var})
- ELSE(${var}_COMPILED)
+ ENDIF()
+ ELSE()
SET(${var} 0)
- ENDIF(${var}_COMPILED)
- ENDIF(${invert} MATCHES INVERT)
-ENDMACRO(KWSYS_PLATFORM_TEST_RUN)
+ ENDIF()
+ ENDIF()
+ENDMACRO()
MACRO(KWSYS_PLATFORM_C_TEST var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES})
@@ -138,7 +130,7 @@ MACRO(KWSYS_PLATFORM_C_TEST var description invert)
KWSYS_PLATFORM_TEST(C "${var}" "${description}" "${invert}")
SET(KWSYS_PLATFORM_TEST_DEFINES)
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS)
-ENDMACRO(KWSYS_PLATFORM_C_TEST)
+ENDMACRO()
MACRO(KWSYS_PLATFORM_C_TEST_RUN var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES})
@@ -146,7 +138,7 @@ MACRO(KWSYS_PLATFORM_C_TEST_RUN var description invert)
KWSYS_PLATFORM_TEST_RUN(C "${var}" "${description}" "${invert}")
SET(KWSYS_PLATFORM_TEST_DEFINES)
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS)
-ENDMACRO(KWSYS_PLATFORM_C_TEST_RUN)
+ENDMACRO()
MACRO(KWSYS_PLATFORM_CXX_TEST var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES})
@@ -156,7 +148,7 @@ MACRO(KWSYS_PLATFORM_CXX_TEST var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES)
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS)
SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES)
-ENDMACRO(KWSYS_PLATFORM_CXX_TEST)
+ENDMACRO()
MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES})
@@ -164,7 +156,7 @@ MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert)
KWSYS_PLATFORM_TEST_RUN(CXX "${var}" "${description}" "${invert}")
SET(KWSYS_PLATFORM_TEST_DEFINES)
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS)
-ENDMACRO(KWSYS_PLATFORM_CXX_TEST_RUN)
+ENDMACRO()
#-----------------------------------------------------------------------------
# KWSYS_PLATFORM_INFO_TEST(lang var description)
diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c
index e602964bb..64a361bbe 100644
--- a/Source/kwsys/kwsysPlatformTestsC.c
+++ b/Source/kwsys/kwsysPlatformTestsC.c
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
/*
Macros to define main() in a cross-platform way.
@@ -26,21 +17,22 @@
}
*/
#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) \
+#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>
-int f(ptrdiff_t n) { return n > 0; }
+int f(ptrdiff_t n)
+{
+ return n > 0;
+}
int KWSYS_PLATFORM_TEST_C_MAIN()
{
char* p = 0;
@@ -50,10 +42,12 @@ int KWSYS_PLATFORM_TEST_C_MAIN()
}
#endif
-/*--------------------------------------------------------------------------*/
#ifdef TEST_KWSYS_C_HAS_SSIZE_T
#include <unistd.h>
-int f(ssize_t n) { return (int)n; }
+int f(ssize_t n)
+{
+ return (int)n;
+}
int KWSYS_PLATFORM_TEST_C_MAIN()
{
ssize_t n = 0;
@@ -61,32 +55,31 @@ int KWSYS_PLATFORM_TEST_C_MAIN()
}
#endif
-/*--------------------------------------------------------------------------*/
#ifdef TEST_KWSYS_C_TYPE_MACROS
char* info_macros =
#if defined(__SIZEOF_SHORT__)
-"INFO:macro[__SIZEOF_SHORT__]\n"
+ "INFO:macro[__SIZEOF_SHORT__]\n"
#endif
#if defined(__SIZEOF_INT__)
-"INFO:macro[__SIZEOF_INT__]\n"
+ "INFO:macro[__SIZEOF_INT__]\n"
#endif
#if defined(__SIZEOF_LONG__)
-"INFO:macro[__SIZEOF_LONG__]\n"
+ "INFO:macro[__SIZEOF_LONG__]\n"
#endif
#if defined(__SIZEOF_LONG_LONG__)
-"INFO:macro[__SIZEOF_LONG_LONG__]\n"
+ "INFO:macro[__SIZEOF_LONG_LONG__]\n"
#endif
#if defined(__SHORT_MAX__)
-"INFO:macro[__SHORT_MAX__]\n"
+ "INFO:macro[__SHORT_MAX__]\n"
#endif
#if defined(__INT_MAX__)
-"INFO:macro[__INT_MAX__]\n"
+ "INFO:macro[__INT_MAX__]\n"
#endif
#if defined(__LONG_MAX__)
-"INFO:macro[__LONG_MAX__]\n"
+ "INFO:macro[__LONG_MAX__]\n"
#endif
#if defined(__LONG_LONG_MAX__)
-"INFO:macro[__LONG_LONG_MAX__]\n"
+ "INFO:macro[__LONG_LONG_MAX__]\n"
#endif
"";
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index be7a09ee2..01c69514c 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -1,305 +1,69 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-// Setup for tests that use result of stl namespace test.
-#if defined(KWSYS_STL_HAVE_STD)
-# if KWSYS_STL_HAVE_STD
-# define kwsys_stl std
-# else
-# define kwsys_stl
-# endif
-#endif
-
-// Setup for tests that use iostreams.
-#if defined(KWSYS_IOS_USE_ANSI) && defined(KWSYS_IOS_HAVE_STD)
-# if defined(_MSC_VER)
-# pragma warning (push,1)
-# endif
-# if KWSYS_IOS_USE_ANSI
-# include <iostream>
-# else
-# include <iostream.h>
-# endif
-# if defined(_MSC_VER)
-# pragma warning (pop)
-# endif
-# if KWSYS_IOS_HAVE_STD
-# define kwsys_ios std
-# else
-# define kwsys_ios
-# endif
-#endif
-
-#ifdef TEST_KWSYS_STL_HAVE_STD
-#include <list>
-void f(std ::list<int>*) {}
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_IOS_USE_ANSI
-#include <iosfwd>
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_IOS_HAVE_STD
-#include <iosfwd>
-void f(std ::ostream*) {}
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_IOS_USE_SSTREAM
-#include <sstream>
-#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 96
-# error "GCC 2.96 stringstream is buggy"
-#endif
-int main()
-{
- std ::ostringstream ostr;
- ostr << "hello";
- if(ostr.str().size() == 5)
- {
- return 0;
- }
- return -1;
-}
-#endif
-
-#ifdef TEST_KWSYS_IOS_USE_STRSTREAM_H
-#include <strstream.h>
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_IOS_USE_STRSTREA_H
-#include <strstrea.h>
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_STRING_HAVE_OSTREAM
-# include <iostream.h>
-# include <string>
-void f(ostream& os, const kwsys_stl::string& s) { os << s; }
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_STRING_HAVE_ISTREAM
-# include <iostream.h>
-# include <string>
-void f(istream& is, kwsys_stl::string& s) { is >> s; }
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_STRING_HAVE_NEQ_CHAR
-# include <string>
-bool f(const kwsys_stl::string& s) { return s != ""; }
-int main() { return 0; }
-#endif
-
+/* 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>
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS_CSTDDEF
-#include <cstddef>
-void f(size_t) {}
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS_LONG_LONG
-long long f(long long n) { return n; }
int main()
{
- long long n = 0;
- return static_cast<int>(f(n));
-}
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS___INT64
-__int64 f(__int64 n) { return n; }
-int main()
-{
- __int64 n = 0;
- return static_cast<int>(f(n));
-}
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS
-template <class T> class A;
-template <class T> int f(A<T>&);
-template <class T> class A
-{
-public:
- // "friend int f<>(A<T>&)" would conform
- friend int f(A<T>&);
-private:
- int x;
-};
-
-template <class T> int f(A<T>& a) { return a.x = 0; }
-template int f(A<int>&);
-
-int main()
-{
- A<int> a;
- return f(a);
-}
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS_MEMBER_TEMPLATES
-template <class U>
-class A
-{
-public:
- U u;
- A(): u(0) {}
- template <class V> V m(V* p) { return *p = u; }
-};
-
-int main()
-{
- A<short> a;
- int s = 1;
- return a.m(&s);
-}
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS_FULL_SPECIALIZATION
-template <class T> struct A {};
-template <> struct A<int*>
-{
- static int f() { return 0; }
-};
-int main() { return A<int*>::f(); }
-#endif
-
-#ifdef TEST_KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP
-namespace N
-{
- class A {};
- int f(A*) { return 0; }
-}
-void f(void*);
-int main()
-{
- N::A* a = 0;
- return f(a);
-}
-#endif
-
-#ifdef TEST_KWSYS_STL_HAS_ITERATOR_TRAITS
-#include <iterator>
-#include <list>
-void f(kwsys_stl::iterator_traits<kwsys_stl::list<int>::iterator>::iterator_category const&) {}
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_HAS_ITERATOR_CATEGORY
-#include <iterator>
-#include <list>
-void f(kwsys_stl::list<int>::iterator x) { kwsys_stl::iterator_category(x); }
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_HAS___ITERATOR_CATEGORY
-#include <iterator>
-#include <list>
-void f(kwsys_stl::list<int>::iterator x) { kwsys_stl::__iterator_category(x); }
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_TEMPLATE
-#include <memory>
-template <class Alloc>
-void f(const Alloc&)
-{
- typedef typename Alloc::size_type alloc_size_type;
-}
-int main()
-{
- f(kwsys_stl::allocator<char>());
return 0;
}
#endif
-#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE
-#include <memory>
-void f(kwsys_stl::allocator::size_type const&) {}
-int main() { return 0; }
-#endif
-
-#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_REBIND
-#include <memory>
-template <class T, class Alloc>
-void f(const T&, const Alloc&)
+#ifdef TEST_KWSYS_CXX_HAS_LONG_LONG
+long long f(long long n)
{
- typedef typename Alloc::template rebind<T>::other alloc_type;
+ return n;
}
int main()
{
- f(0, kwsys_stl::allocator<char>());
- return 0;
+ long long n = 0;
+ return static_cast<int>(f(n));
}
#endif
-#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT
-#include <memory>
-void f(kwsys_stl::allocator<char> const& a)
+#ifdef TEST_KWSYS_CXX_HAS___INT64
+__int64 f(__int64 n)
{
- a.max_size(sizeof(int));
+ return n;
}
int main()
{
- f(kwsys_stl::allocator<char>());
- return 0;
+ __int64 n = 0;
+ return static_cast<int>(f(n));
}
#endif
-#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_OBJECTS
-#include <vector>
-void f(kwsys_stl::vector<int> const& v1)
-{
- kwsys_stl::vector<int>(1, 1, v1.get_allocator());
-}
+#ifdef TEST_KWSYS_CXX_STAT_HAS_ST_MTIM
+#include <sys/types.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
int main()
{
- f(kwsys_stl::vector<int>());
+ struct stat stat1;
+ (void)stat1.st_mtim.tv_sec;
+ (void)stat1.st_mtim.tv_nsec;
return 0;
}
#endif
-#ifdef TEST_KWSYS_STAT_HAS_ST_MTIM
+#ifdef TEST_KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
#include <sys/types.h>
+
#include <sys/stat.h>
#include <unistd.h>
int main()
{
struct stat stat1;
- (void)stat1.st_mtim.tv_sec;
- (void)stat1.st_mtim.tv_nsec;
+ (void)stat1.st_mtimespec.tv_sec;
+ (void)stat1.st_mtimespec.tv_nsec;
return 0;
}
#endif
#ifdef TEST_KWSYS_CXX_SAME_LONG_AND___INT64
-void function(long**) {}
-int main()
+void function(long**)
{
- __int64** p = 0;
- function(p);
- return 0;
}
-#endif
-
-#ifdef TEST_KWSYS_CXX_SAME_LONG_LONG_AND___INT64
-void function(long long**) {}
int main()
{
__int64** p = 0;
@@ -308,86 +72,67 @@ int main()
}
#endif
-#ifdef TEST_KWSYS_CAN_CONVERT_UI64_TO_DOUBLE
-void function(double& l, unsigned __int64 const& r)
+#ifdef TEST_KWSYS_CXX_SAME_LONG_LONG_AND___INT64
+void function(long long**)
{
- l = static_cast<double>(r);
}
-
int main()
{
- double tTo = 0.0;
- unsigned __int64 tFrom = 0;
- function(tTo, tFrom);
- return 0;
-}
-#endif
-
-#ifdef TEST_KWSYS_IOS_HAVE_BINARY
-int test_binary(int, ...)
-{
+ __int64** p = 0;
+ function(p);
return 0;
}
-int main()
-{
- return test_binary(1, kwsys_ios::ios::binary);
-}
#endif
#ifdef TEST_KWSYS_IOS_HAS_ISTREAM_LONG_LONG
-int test_istream(kwsys_ios::istream& is, long long& x)
+#include <iostream>
+int test_istream(std::istream& is, long long& x)
{
- return (is >> x)? 1:0;
+ return (is >> x) ? 1 : 0;
}
int main()
{
long long x = 0;
- return test_istream(kwsys_ios::cin, x);
+ return test_istream(std::cin, x);
}
#endif
#ifdef TEST_KWSYS_IOS_HAS_OSTREAM_LONG_LONG
-int test_ostream(kwsys_ios::ostream& os, long long x)
+#include <iostream>
+int test_ostream(std::ostream& os, long long x)
{
- return (os << x)? 1:0;
+ return (os << x) ? 1 : 0;
}
int main()
{
long long x = 0;
- return test_ostream(kwsys_ios::cout, x);
+ return test_ostream(std::cout, x);
}
#endif
#ifdef TEST_KWSYS_IOS_HAS_ISTREAM___INT64
-int test_istream(kwsys_ios::istream& is, __int64& x)
+#include <iostream>
+int test_istream(std::istream& is, __int64& x)
{
- return (is >> x)? 1:0;
+ return (is >> x) ? 1 : 0;
}
int main()
{
__int64 x = 0;
- return test_istream(kwsys_ios::cin, x);
+ return test_istream(std::cin, x);
}
#endif
#ifdef TEST_KWSYS_IOS_HAS_OSTREAM___INT64
-int test_ostream(kwsys_ios::ostream& os, __int64 x)
+#include <iostream>
+int test_ostream(std::ostream& os, __int64 x)
{
- return (os << x)? 1:0;
+ return (os << x) ? 1 : 0;
}
int main()
{
__int64 x = 0;
- return test_ostream(kwsys_ios::cout, x);
-}
-#endif
-
-#ifdef TEST_KWSYS_CHAR_IS_SIGNED
-/* Return 0 for char signed and 1 for char unsigned. */
-int main()
-{
- unsigned char uc = 255;
- return (*reinterpret_cast<char*>(&uc) < 0)?0:1;
+ return test_ostream(std::cout, x);
}
#endif
@@ -398,30 +143,31 @@ int main()
#define _LARGE_FILES
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
-#include <sys/stat.h>
+
#include <assert.h>
+#include <sys/stat.h>
#if KWSYS_CXX_HAS_CSTDIO
-# include <cstdio>
+#include <cstdio>
#endif
#include <stdio.h>
-int main(int, char **argv)
+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))
+/* 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 );
+ 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 );
+ FILE* file = fopen(argv[0], "r");
+ off_t offset = ftello(file);
+ fseek(file, offset, SEEK_CUR);
+ fclose(file);
return 0;
}
#endif
@@ -448,22 +194,35 @@ int main()
int main()
{
char* e = environ[0];
- return e? 0:1;
+ return e ? 0 : 1;
+}
+#endif
+
+#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>
+int main()
+{
+ double loadavg[3] = { 0.0, 0.0, 0.0 };
+ return getloadavg(loadavg, 3);
}
#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>
+#if defined(KWSYS_HAS_LFS)
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _LARGE_FILES
+#define _FILE_OFFSET_BITS 64
+#endif
+#include <sys/resource.h>
int main()
{
struct rlimit64 rlim;
- return getrlimit64(0,&rlim);
+ return getrlimit64(0, &rlim);
}
#endif
@@ -471,7 +230,7 @@ int main()
#include <stdlib.h>
int main()
{
- const char *str="1024";
+ const char* str = "1024";
return static_cast<int>(atoll(str));
}
#endif
@@ -480,7 +239,7 @@ int main()
#include <stdlib.h>
int main()
{
- const char *str="1024";
+ const char* str = "1024";
return static_cast<int>(atol(str));
}
#endif
@@ -489,7 +248,7 @@ int main()
#include <stdlib.h>
int main()
{
- const char *str="1024";
+ const char* str = "1024";
return static_cast<int>(_atoi64(str));
}
#endif
@@ -508,146 +267,63 @@ int main()
#include <sys/stat.h>
int main()
{
- struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}};
+ struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, UTIME_NOW } };
return utimensat(AT_FDCWD, "/example", times, AT_SYMLINK_NOFOLLOW);
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE
-#if defined(__PATHSCALE__) || defined(__PATHCC__) \
- || (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
+#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
+#define _GNU_SOURCE
#endif
#include <execinfo.h>
int main()
{
- void *stackSymbols[256];
- backtrace(stackSymbols,256);
- backtrace_symbols(&stackSymbols[0],1);
+ void* stackSymbols[256];
+ backtrace(stackSymbols, 256);
+ backtrace_symbols(&stackSymbols[0], 1);
return 0;
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_DLADDR
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-# define _GNU_SOURCE
+#define _GNU_SOURCE
#endif
#include <dlfcn.h>
int main()
{
Dl_info info;
- int ierr=dladdr((void*)main,&info);
+ int ierr = dladdr((void*)main, &info);
return 0;
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_CXXABI
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-# define _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;
size_t bufferLen = 512;
- char buffer[512] = {'\0'};
- const char *function="_ZN5kwsys17SystemInformation15GetProgramStackEii";
- char *demangledFunction =
+ char buffer[512] = { '\0' };
+ const char* function = "_ZN5kwsys17SystemInformation15GetProgramStackEii";
+ char* demangledFunction =
abi::__cxa_demangle(function, buffer, &bufferLen, &status);
return status;
}
#endif
-#ifdef TEST_KWSYS_CXX_TYPE_INFO
-/* Collect fundamental type information and save it to a CMake script. */
-
-/* Include limits.h to get macros indicating long long and __int64.
- Note that certain compilers need special macros to define these
- macros in limits.h. */
-#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
-# define _MSC_EXTENSIONS
-#endif
-#if defined(__GNUC__) && __GNUC__ < 3
-# define _GNU_SOURCE
-#endif
-#include <limits.h>
-
-#include <stdio.h>
-#include <string.h>
-
-/* Due to shell differences and limitations of ADD_DEFINITIONS the
- KWSYS_CXX_TYPE_INFO_FILE macro will sometimes have double quotes
- and sometimes not. This macro will make sure the value is treated
- as a double-quoted string. */
-#define TO_STRING(x) TO_STRING0(x)
-#define TO_STRING0(x) TO_STRING1(x)
-#define TO_STRING1(x) #x
-
-void f() {}
-
-int main()
-{
- /* Construct the output file name. Some preprocessors will add an
- extra level of double quotes, so strip them. */
- char fbuf[] = TO_STRING(KWSYS_CXX_TYPE_INFO_FILE);
- char* fname = fbuf;
- if(fname[0] == '"')
- {
- ++fname;
- int len = static_cast<int>(strlen(fname));
- if(len > 0 && fname[len-1] == '"')
- {
- fname[len-1] = 0;
- }
- }
-
- /* Try to open the output file. */
- if(FILE* fout = fopen(fname, "w"))
- {
- /* Set the size of standard types. */
- fprintf(fout, "SET(KWSYS_SIZEOF_CHAR %d)\n", static_cast<int>(sizeof(char)));
- fprintf(fout, "SET(KWSYS_SIZEOF_SHORT %d)\n", static_cast<int>(sizeof(short)));
- fprintf(fout, "SET(KWSYS_SIZEOF_INT %d)\n", static_cast<int>(sizeof(int)));
- fprintf(fout, "SET(KWSYS_SIZEOF_LONG %d)\n", static_cast<int>(sizeof(long)));
-
- /* Set the size of some non-standard but common types. */
- /* Check for a limits.h macro for long long to see if the type exists. */
-#if defined(LLONG_MAX) || defined(LONG_LONG_MAX) || defined(LONGLONG_MAX)
- fprintf(fout, "SET(KWSYS_SIZEOF_LONG_LONG %d)\n", static_cast<int>(sizeof(long long)));
-#else
- fprintf(fout, "SET(KWSYS_SIZEOF_LONG_LONG 0) # No long long available.\n");
-#endif
- /* Check for a limits.h macro for __int64 to see if the type exists. */
-#if defined(_I64_MIN)
- fprintf(fout, "SET(KWSYS_SIZEOF___INT64 %d)\n", static_cast<int>(sizeof(__int64)));
-#else
- fprintf(fout, "SET(KWSYS_SIZEOF___INT64 0) # No __int64 available.\n");
-#endif
-
- /* Set the size of some pointer types. */
- fprintf(fout, "SET(KWSYS_SIZEOF_PDATA %d)\n", static_cast<int>(sizeof(void*)));
- fprintf(fout, "SET(KWSYS_SIZEOF_PFUNC %d)\n", static_cast<int>(sizeof(&f)));
-
- /* Set whether the native type "char" is signed or unsigned. */
- unsigned char uc = 255;
- fprintf(fout, "SET(KWSYS_CHAR_IS_SIGNED %d)\n",
- (*reinterpret_cast<char*>(&uc) < 0)?1:0);
-
- fclose(fout);
- return 0;
- }
- else
- {
- fprintf(stderr, "Failed to write fundamental type info to \"%s\".\n",
- fname);
- return 1;
- }
-}
-#endif
-
#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM
int main()
{
@@ -674,3 +350,22 @@ int main()
return a;
}
#endif
+
+#ifdef TEST_KWSYS_STL_HAS_WSTRING
+#include <string>
+void f(std::wstring*)
+{
+}
+int main()
+{
+ return 0;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H
+#include <ext/stdio_filebuf.h>
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/Source/kwsys/kwsysPrivate.h b/Source/kwsys/kwsysPrivate.h
index 3a26c26fb..ce1b53ed8 100644
--- a/Source/kwsys/kwsysPrivate.h
+++ b/Source/kwsys/kwsysPrivate.h
@@ -1,16 +1,7 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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
@@ -24,7 +15,9 @@
#include KWSYS_HEADER(Directory.hxx)
#include KWSYS_HEADER(std/vector)
*/
+/* 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>
@@ -37,5 +30,5 @@
#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/kwsys_cstddef.hxx.in b/Source/kwsys/kwsys_cstddef.hxx.in
deleted file mode 100644
index 925c03084..000000000
--- a/Source/kwsys/kwsys_cstddef.hxx.in
+++ /dev/null
@@ -1,35 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_cstddef
-#define @KWSYS_NAMESPACE@_cstddef
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-/* Avoid warnings in MSVC standard headers. */
-#ifdef _MSC_VER
-# pragma warning (push, 1)
-# pragma warning (disable: 4702)
-# pragma warning (disable: 4786)
-#endif
-
-/* Include the real header. */
-#if @KWSYS_NAMESPACE@_CXX_HAS_CSTDDEF
-# include <cstddef>
-#else
-# include <stddef.h>
-#endif
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-#endif
diff --git a/Source/kwsys/kwsys_ios_fstream.h.in b/Source/kwsys/kwsys_ios_fstream.h.in
deleted file mode 100644
index 4b1a8cfcc..000000000
--- a/Source/kwsys/kwsys_ios_fstream.h.in
+++ /dev/null
@@ -1,46 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_ios_fstream
-#define @KWSYS_NAMESPACE@_ios_fstream
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-#ifdef _MSC_VER
-# pragma warning (push, 1)
-# pragma warning (disable: 4702)
-# pragma warning (disable: 4995) /* Old streams are deprecated. */
-#endif
-
-#if @KWSYS_NAMESPACE@_IOS_USE_ANSI
-# include <fstream>
-#else
-# include <fstream.h>
-#endif
-
-#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-namespace @KWSYS_NAMESPACE@_ios
-{
- using @KWSYS_NAMESPACE@_ios_namespace::ostream;
- using @KWSYS_NAMESPACE@_ios_namespace::istream;
- using @KWSYS_NAMESPACE@_ios_namespace::ofstream;
- using @KWSYS_NAMESPACE@_ios_namespace::ifstream;
- using @KWSYS_NAMESPACE@_ios_namespace::ios;
- using @KWSYS_NAMESPACE@_ios_namespace::endl;
- using @KWSYS_NAMESPACE@_ios_namespace::flush;
-}
-#endif
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-#endif
diff --git a/Source/kwsys/kwsys_ios_iosfwd.h.in b/Source/kwsys/kwsys_ios_iosfwd.h.in
deleted file mode 100644
index f4fafebc2..000000000
--- a/Source/kwsys/kwsys_ios_iosfwd.h.in
+++ /dev/null
@@ -1,49 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_ios_iosfwd
-#define @KWSYS_NAMESPACE@_ios_iosfwd
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-#ifdef _MSC_VER
-#pragma warning (push, 1)
-#pragma warning (disable: 4702)
-#endif
-
-#if @KWSYS_NAMESPACE@_IOS_USE_ANSI
-# include <iosfwd>
-#else
-class fstream;
-class ifstream;
-class ios;
-class istream;
-class ofstream;
-class ostream;
-#endif
-
-#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-namespace @KWSYS_NAMESPACE@_ios
-{
- using @KWSYS_NAMESPACE@_ios_namespace::fstream;
- using @KWSYS_NAMESPACE@_ios_namespace::ifstream;
- using @KWSYS_NAMESPACE@_ios_namespace::ios;
- using @KWSYS_NAMESPACE@_ios_namespace::istream;
- using @KWSYS_NAMESPACE@_ios_namespace::ofstream;
- using @KWSYS_NAMESPACE@_ios_namespace::ostream;
-}
-#endif
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#endif
diff --git a/Source/kwsys/kwsys_ios_iostream.h.in b/Source/kwsys/kwsys_ios_iostream.h.in
deleted file mode 100644
index 43fc4d579..000000000
--- a/Source/kwsys/kwsys_ios_iostream.h.in
+++ /dev/null
@@ -1,99 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_ios_iostream
-#define @KWSYS_NAMESPACE@_ios_iostream
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-#ifdef _MSC_VER
-# pragma warning (push, 1)
-# pragma warning (disable: 4702)
-# pragma warning (disable: 4995) /* Old streams are deprecated. */
-#endif
-
-#if @KWSYS_NAMESPACE@_IOS_USE_ANSI
-# include <iostream>
-#else
-# include <iostream.h>
-#endif
-
-// The HP implementation of iostream defines cin, cout, cerr, and clog
-// as macros in order to do thread-private streams.
-// See /opt/aCC/include/iostream/iostream.h for details.
-// This block redefines the macros in a safe way that is also compatible
-// with the HP definitions and the using declarations below.
-
-#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-# if defined(__HP_aCC) && (defined(HP_THREAD_SAFE) || defined(_THREAD_SAFE))
-# if defined(cin) && !defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_CIN)
-# define @KWSYS_NAMESPACE@_IOS_HP_HACK_CIN
-# undef cin
-# define cin __tcin.ref()
-# endif
-# if defined(cout) && !defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_COUT)
-# define @KWSYS_NAMESPACE@_IOS_HP_HACK_COUT
-# undef cout
-# define cout __tcout.ref()
-# endif
-# if defined(cerr) && !defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_CERR)
-# define @KWSYS_NAMESPACE@_IOS_HP_HACK_CERR
-# undef cerr
-# define cerr __tcerr.ref()
-# endif
-# if defined(clog) && !defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_CLOG)
-# define @KWSYS_NAMESPACE@_IOS_HP_HACK_CLOG
-# undef clog
-# define clog __tclog.ref()
-# endif
-# endif
-#endif
-
-// If using our own sstream emulation code, put the standard
-// streams in the same namespace.
-#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-namespace @KWSYS_NAMESPACE@_ios
-{
- typedef int streamsize;
- typedef int streamoff;
- using @KWSYS_NAMESPACE@_ios_namespace::ostream;
- using @KWSYS_NAMESPACE@_ios_namespace::istream;
- using @KWSYS_NAMESPACE@_ios_namespace::ios;
- using @KWSYS_NAMESPACE@_ios_namespace::endl;
- using @KWSYS_NAMESPACE@_ios_namespace::flush;
-# if defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_CIN)
- using @KWSYS_NAMESPACE@_ios_namespace::__tcin;
-# else
- using @KWSYS_NAMESPACE@_ios_namespace::cin;
-# endif
-# if defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_COUT)
- using @KWSYS_NAMESPACE@_ios_namespace::__tcout;
-# else
- using @KWSYS_NAMESPACE@_ios_namespace::cout;
-# endif
-# if defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_CERR)
- using @KWSYS_NAMESPACE@_ios_namespace::__tcerr;
-# else
- using @KWSYS_NAMESPACE@_ios_namespace::cerr;
-# endif
-# if defined(@KWSYS_NAMESPACE@_IOS_HP_HACK_CLOG)
- using @KWSYS_NAMESPACE@_ios_namespace::__tclog;
-# else
- using @KWSYS_NAMESPACE@_ios_namespace::clog;
-# endif
-}
-#endif
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-#endif
diff --git a/Source/kwsys/kwsys_ios_sstream.h.in b/Source/kwsys/kwsys_ios_sstream.h.in
deleted file mode 100644
index 29d250c7a..000000000
--- a/Source/kwsys/kwsys_ios_sstream.h.in
+++ /dev/null
@@ -1,199 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_ios_sstream
-#define @KWSYS_NAMESPACE@_ios_sstream
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-/* Define this macro temporarily to keep the code readable. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsys_stl @KWSYS_NAMESPACE@_stl
-#endif
-
-#if @KWSYS_NAMESPACE@_IOS_USE_SSTREAM
-# ifdef _MSC_VER
-# pragma warning (push, 1)
-# pragma warning (disable: 4702)
-# endif
-# include <sstream>
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
-#else
-# ifdef _MSC_VER
-# pragma warning (push, 1)
-# pragma warning (disable: 4702)
-# pragma warning (disable: 4995) /* Old streams are deprecated. */
-# endif
-# if @KWSYS_NAMESPACE@_IOS_USE_ANSI
-# include <strstream>
-# elif @KWSYS_NAMESPACE@_IOS_USE_STRSTREAM_H
-# include <strstream.h>
-# elif @KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H
-# include <strstrea.h>
-# endif
-# if @KWSYS_NAMESPACE@_IOS_USE_ANSI
-# include <new> // Need placement operator new.
-# else
-# include <new.h> // Need placement operator new.
-# endif
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
-
-// Only have old std strstream classes. Wrap them to look like new
-// ostringstream and istringstream classes.
-
-# include <@KWSYS_NAMESPACE@/stl/string>
-
-namespace @KWSYS_NAMESPACE@_ios
-{
-using @KWSYS_NAMESPACE@_ios_namespace::streambuf;
-using @KWSYS_NAMESPACE@_ios_namespace::ostream;
-using @KWSYS_NAMESPACE@_ios_namespace::istream;
-using @KWSYS_NAMESPACE@_ios_namespace::strstream;
-using @KWSYS_NAMESPACE@_ios_namespace::istrstream;
-using @KWSYS_NAMESPACE@_ios_namespace::ostrstream;
-using @KWSYS_NAMESPACE@_ios_namespace::ios;
-using @KWSYS_NAMESPACE@_ios_namespace::endl;
-using @KWSYS_NAMESPACE@_ios_namespace::ends;
-using @KWSYS_NAMESPACE@_ios_namespace::flush;
-
-class stringstream_cleanup
-{
-public:
- stringstream_cleanup(strstream& str): m_StrStream(str) {}
- ~stringstream_cleanup() { m_StrStream.rdbuf()->freeze(0); }
- static void IgnoreUnusedVariable(const stringstream_cleanup&) {}
-protected:
- strstream& m_StrStream;
-private:
- void operator=(stringstream_cleanup const&);
-};
-
-class stringstream: public strstream
-{
-public:
- typedef strstream Superclass;
- stringstream() {}
- stringstream(const kwsys_stl::string& s) { *this << s.c_str(); }
- kwsys_stl::string str()
- {
- stringstream_cleanup cleanup(*this);
- stringstream_cleanup::IgnoreUnusedVariable(cleanup);
-// Visual Studio 6 has a strstream::pcount, but this is not rdbuf()->pcount()
-#if (@KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H) && defined(_MSC_VER) && (_MSC_VER == 1200)
- int count = this->pcount();
-#elif defined(__WATCOMC__)
- int count = this->rdbuf()->out_waiting();
-#else
- int count = this->rdbuf()->pcount();
-#endif
- const char* ptr = this->Superclass::str();
- return kwsys_stl::string(ptr?ptr:"", count);
- }
- void str(const kwsys_stl::string& s)
- {
- this->~stringstream();
- new (this) stringstream(s);
- }
-private:
- stringstream(const stringstream&);
- void operator=(const stringstream&);
-};
-
-class ostringstream_cleanup
-{
-public:
- ostringstream_cleanup(ostrstream& ostr): m_OStrStream(ostr) {}
- ~ostringstream_cleanup() { m_OStrStream.rdbuf()->freeze(0); }
- static void IgnoreUnusedVariable(const ostringstream_cleanup&) {}
-protected:
- ostrstream& m_OStrStream;
-private:
- void operator=(ostringstream_cleanup const&);
-};
-
-class ostringstream: public ostrstream
-{
-public:
- typedef ostrstream Superclass;
- ostringstream() {}
- ostringstream(const kwsys_stl::string& s) { *this << s.c_str(); }
- kwsys_stl::string str()
- {
- ostringstream_cleanup cleanup(*this);
- ostringstream_cleanup::IgnoreUnusedVariable(cleanup);
- int count = this->pcount();
- const char* ptr = this->Superclass::str();
- return kwsys_stl::string(ptr?ptr:"", count);
- }
- void str(const kwsys_stl::string& s)
- {
- this->~ostringstream();
- new (this) ostringstream(s);
- }
-private:
- ostringstream(const ostringstream&);
- void operator=(const ostringstream&);
-};
-
-#if defined(_MSC_VER)
-# pragma warning (push)
-# pragma warning (disable: 4097) /* typedef-name used as synonym for class */
-#endif
-#if defined(__WATCOMC__)
-// W728: class modifiers for 'A' conflict with class modifiers for 'B'
-# pragma warning 728 10
-#endif
-
-class istringstream: private kwsys_stl::string, public istrstream
-{
-public:
- typedef kwsys_stl::string StdString;
- typedef istrstream IStrStream;
- istringstream(): StdString(),
- IStrStream(const_cast<char*>(StdString::c_str())) {}
- istringstream(const kwsys_stl::string& s):
- StdString(s), IStrStream(const_cast<char*>(StdString::c_str())) {}
- kwsys_stl::string str() const { return *this; }
- void str(const kwsys_stl::string& s)
- {
- this->~istringstream();
- new (this) istringstream(s);
- }
- void clear(int flags)
- {
- this->IStrStream::clear(flags);
- }
-private:
- istringstream(const istringstream&);
- void operator=(const istringstream&);
-};
-
-#if defined(__WATCOMC__)
-# pragma warning 728 9
-#endif
-#if defined(_MSC_VER)
-# pragma warning (pop)
-#endif
-
-} // namespace @KWSYS_NAMESPACE@_ios
-
-#endif
-
-/* Undefine temporary macro. */
-#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# undef kwsys_stl
-#endif
-
-#endif
diff --git a/Source/kwsys/kwsys_stl.hxx.in b/Source/kwsys/kwsys_stl.hxx.in
deleted file mode 100644
index 610e6d471..000000000
--- a/Source/kwsys/kwsys_stl.hxx.in
+++ /dev/null
@@ -1,49 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifndef @KWSYS_NAMESPACE@_stl_@KWSYS_STL_HEADER@
-#define @KWSYS_NAMESPACE@_stl_@KWSYS_STL_HEADER@
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-/* Avoid warnings in MSVC standard headers. */
-#ifdef _MSC_VER
-# pragma warning (push, 1)
-# pragma warning (disable: 4702)
-# pragma warning (disable: 4786)
-#endif
-
-/* The HP standard library defines the functor "times" instead of
- "multiplies" as specified by C++98 20.3.2 for backward
- compatibility with earlier specifications. Defining this macro
- fixes this behavior. The name "times" also conflicts with the
- function declared in sys/times.h on that platform, so we must do
- this as a work-around anyway. */
-#if defined(__HP_aCC) && !defined(__HPACC_USING_MULTIPLIES_IN_FUNCTIONAL)
-# define __HPACC_USING_MULTIPLIES_IN_FUNCTIONAL
-# define @KWSYS_NAMESPACE@_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL
-#endif
-
-/* Include the real header. */
-#include <@KWSYS_STL_HEADER@>
-
-/* Cleanup. */
-#if defined(@KWSYS_NAMESPACE@_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL)
-# undef @KWSYS_NAMESPACE@_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL
-# undef __HPACC_USING_MULTIPLIES_IN_FUNCTIONAL
-#endif
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-@KWSYS_STL_HEADER_EXTRA@
-#endif
diff --git a/Source/kwsys/kwsys_stl_string.hxx.in b/Source/kwsys/kwsys_stl_string.hxx.in
deleted file mode 100644
index cd312cb8e..000000000
--- a/Source/kwsys/kwsys_stl_string.hxx.in
+++ /dev/null
@@ -1,123 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-
-// This header is extra code for <@KWSYS_NAMESPACE@/stl/string>.
-#if !defined(@KWSYS_NAMESPACE@_stl_string_including_hxx)
-# error "The header <@KWSYS_NAMESPACE@/stl/string.hxx> may be included only by <@KWSYS_NAMESPACE@/stl/string>."
-#endif
-
-// Provide the istream operator for the stl string if it is not
-// provided by the system or another copy of kwsys. Allow user code
-// to block this definition by defining the macro
-// @KWSYS_NAMESPACE@_STL_STRING_NO_ISTREAM
-// to avoid conflicts with other libraries. User code can test for
-// this definition by checking the macro
-// @KWSYS_NAMESPACE@_STL_STRING_ISTREAM_DEFINED
-#if !@KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM && !defined(@KWSYS_NAMESPACE@_STL_STRING_NO_ISTREAM) && !defined(KWSYS_STL_STRING_ISTREAM_DEFINED)
-# define KWSYS_STL_STRING_ISTREAM_DEFINED
-# define @KWSYS_NAMESPACE@_STL_STRING_ISTREAM_DEFINED
-# include <ctype.h> // isspace
-# include <@KWSYS_NAMESPACE@/ios/iostream>
-# if defined(__WATCOMC__)
-namespace @KWSYS_NAMESPACE@
-{
-struct ios_istream_hack: public kwsys_ios::istream
-{ void eatwhite() { this->@KWSYS_NAMESPACE@_ios::istream::eatwhite(); } };
-}
-# endif
-inline @KWSYS_NAMESPACE@_ios::istream&
-operator>>(@KWSYS_NAMESPACE@_ios::istream& is,
- @KWSYS_NAMESPACE@_stl::string& s)
-{
- // Keep track of the resulting state.
- int state = @KWSYS_NAMESPACE@_ios::ios::goodbit;
-
- // Save the width setting and set it back to zero.
- size_t n = static_cast<size_t>(is.width(0));
-
- // Clear any old contents of the output string.
- s.erase();
-
- // Skip leading whitespace.
-#if defined(__WATCOMC__)
- static_cast<@KWSYS_NAMESPACE@::ios_istream_hack&>(is).eatwhite();
-#else
- is.eatwhite();
-#endif
- @KWSYS_NAMESPACE@_ios::istream& okay = is;
-
- if(okay)
- {
- // Select a maximum possible length.
- if(n == 0 || n >= s.max_size())
- {
- n = s.max_size();
- }
-
- // Read until a space is found or the maximum length is reached.
- bool success = false;
- for(int c = is.peek(); (--n > 0 && c != EOF && !isspace(c)); c = is.peek())
- {
- s += static_cast<char>(c);
- success = true;
- is.ignore();
- }
-
- // Set flags for resulting state.
- if(is.peek() == EOF) { state |= @KWSYS_NAMESPACE@_ios::ios::eofbit; }
- if(!success) { state |= @KWSYS_NAMESPACE@_ios::ios::failbit; }
- }
-
- // Set the final result state.
- is.clear(state);
- return is;
-}
-#endif
-
-// Provide the ostream operator for the stl string if it is not
-// provided by the system or another copy of kwsys. Allow user code
-// to block this definition by defining the macro
-// @KWSYS_NAMESPACE@_STL_STRING_NO_OSTREAM
-// to avoid conflicts with other libraries. User code can test for
-// this definition by checking the macro
-// @KWSYS_NAMESPACE@_STL_STRING_OSTREAM_DEFINED
-#if !@KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM && !defined(@KWSYS_NAMESPACE@_STL_STRING_NO_OSTREAM) && !defined(KWSYS_STL_STRING_OSTREAM_DEFINED)
-# define KWSYS_STL_STRING_OSTREAM_DEFINED
-# define @KWSYS_NAMESPACE@_STL_STRING_OSTREAM_DEFINED
-# include <@KWSYS_NAMESPACE@/ios/iostream>
-inline @KWSYS_NAMESPACE@_ios::ostream&
-operator<<(@KWSYS_NAMESPACE@_ios::ostream& os,
- @KWSYS_NAMESPACE@_stl::string const& s)
-{
- return os << s.c_str();
-}
-#endif
-
-// Provide the operator!= for the stl string and char* if it is not
-// provided by the system or another copy of kwsys. Allow user code
-// to block this definition by defining the macro
-// @KWSYS_NAMESPACE@_STL_STRING_NO_NEQ_CHAR
-// to avoid conflicts with other libraries. User code can test for
-// this definition by checking the macro
-// @KWSYS_NAMESPACE@_STL_STRING_NEQ_CHAR_DEFINED
-#if !@KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR && !defined(@KWSYS_NAMESPACE@_STL_STRING_NO_NEQ_CHAR) && !defined(KWSYS_STL_STRING_NEQ_CHAR_DEFINED)
-# define KWSYS_STL_STRING_NEQ_CHAR_DEFINED
-# define @KWSYS_NAMESPACE@_STL_STRING_NEQ_CHAR_DEFINED
-inline bool operator!=(@KWSYS_NAMESPACE@_stl::string const& s, const char* c)
-{
- return !(s == c);
-}
-inline bool operator!=(const char* c, @KWSYS_NAMESPACE@_stl::string const& s)
-{
- return !(s == c);
-}
-#endif
diff --git a/Source/kwsys/testAutoPtr.cxx b/Source/kwsys/testAutoPtr.cxx
deleted file mode 100644
index ed75ff447..000000000
--- a/Source/kwsys/testAutoPtr.cxx
+++ /dev/null
@@ -1,166 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
-#ifdef __BORLANDC__
-# pragma warn -8027 /* 'for' not inlined. */
-# pragma warn -8026 /* exception not inlined. */
-#endif
-#include "kwsysPrivate.h"
-#include KWSYS_HEADER(auto_ptr.hxx)
-// Work-around CMake dependency scanning limitation. This must
-// duplicate the above list of headers.
-#if 0
-# include "auto_ptr.hxx.in"
-#endif
-
-#include <stdio.h>
-
-#define ASSERT(x,y) if (!(x)) { printf("FAIL: " y "\n"); status = 1; }
-
-int instances = 0; // don't declare as static
-
-struct A
-{
- A() { ++instances; }
- ~A() { --instances; }
- A* self() {return this; }
-};
-struct B: public A {};
-
-static int function_call(kwsys::auto_ptr<A> a)
-{
- return a.get()? 1:0;
-}
-
-static A* get_A(A& a) { return &a; }
-
-static kwsys::auto_ptr<A> generate_auto_ptr_A()
-{
- return kwsys::auto_ptr<A>(new A);
-}
-
-static kwsys::auto_ptr<B> generate_auto_ptr_B()
-{
- return kwsys::auto_ptr<B>(new B);
-}
-
-int testAutoPtr(int, char*[])
-{
- int status = 0;
-
- // Keep everything in a subscope so we can detect leaks.
- {
- kwsys::auto_ptr<A> pa0;
- kwsys::auto_ptr<A> pa1(new A());
- kwsys::auto_ptr<B> pb1(new B());
- kwsys::auto_ptr<B> pb2(new B());
- kwsys::auto_ptr<A> pa2(new B());
-
- A* ptr = get_A(*pa1);
- ASSERT(ptr == pa1.get(),
- "auto_ptr does not return correct object when dereferenced");
- ptr = pa1->self();
- ASSERT(ptr == pa1.get(),
- "auto_ptr does not return correct pointer from operator->");
-
- A* before = pa0.get();
- pa0.reset(new A());
- ASSERT(pa0.get() && pa0.get() != before,
- "auto_ptr empty after reset(new A())");
-
- before = pa0.get();
- pa0.reset(new B());
- ASSERT(pa0.get() && pa0.get() != before,
- "auto_ptr empty after reset(new B())");
-
- delete pa0.release();
- ASSERT(!pa0.get(), "auto_ptr holds an object after release()");
-
- kwsys::auto_ptr<A> pa3(pb1);
- ASSERT(!pb1.get(),
- "auto_ptr full after being used to construct another");
- ASSERT(pa3.get(),
- "auto_ptr empty after construction from another");
-
- {
- kwsys::auto_ptr<A> pa;
- pa = pa3;
- ASSERT(!pa3.get(),
- "auto_ptr full after assignment to another");
- ASSERT(pa.get(),
- "auto_ptr empty after assignment from another");
- }
-
- {
- kwsys::auto_ptr<A> pa;
- pa = pb2;
- ASSERT(!pb2.get(),
- "auto_ptr full after assignment to compatible");
- ASSERT(pa.get(),
- "auto_ptr empty after assignment from compatible");
- }
-
- {
- int receive = function_call(pa2);
- ASSERT(receive,
- "auto_ptr did not receive ownership in called function");
- ASSERT(!pa2.get(),
- "auto_ptr did not release ownership to called function");
- }
-
- {
- int received = function_call(generate_auto_ptr_A());
- ASSERT(received,
- "auto_ptr in called function did not take ownership "
- "from factory function");
- }
-
-#if 0
- // Is this allowed by the standard?
- {
- int received = function_call(generate_auto_ptr_B());
- ASSERT(received,
- "auto_ptr in called function did not take ownership "
- "from factory function with conversion");
- }
-#endif
-
- {
- kwsys::auto_ptr<A> pa(generate_auto_ptr_A());
- ASSERT(pa.get(),
- "auto_ptr empty after construction from factory function");
- }
-
- {
- kwsys::auto_ptr<A> pa;
- pa = generate_auto_ptr_A();
- ASSERT(pa.get(),
- "auto_ptr empty after assignment from factory function");
- }
-
- {
- kwsys::auto_ptr<A> pa(generate_auto_ptr_B());
- ASSERT(pa.get(),
- "auto_ptr empty after construction from compatible factory function");
- }
-
- {
- kwsys::auto_ptr<A> pa;
- pa = generate_auto_ptr_B();
- ASSERT(pa.get(),
- "auto_ptr empty after assignment from compatible factory function");
- }
- }
-
- ASSERT(instances == 0, "auto_ptr leaked an object");
-
- return status;
-}
diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx
index 72e65447b..d2215d62f 100644
--- a/Source/kwsys/testCommandLineArguments.cxx
+++ b/Source/kwsys/testCommandLineArguments.cxx
@@ -1,26 +1,17 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(CommandLineArguments.hxx)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(stl/vector)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "CommandLineArguments.hxx.in"
-# include "kwsys_ios_iostream.h.in"
+#include "CommandLineArguments.hxx.in"
#endif
+#include <iostream>
+#include <vector>
+
#include <stddef.h> /* size_t */
#include <string.h> /* strcmp */
@@ -28,33 +19,45 @@ static void* random_ptr = reinterpret_cast<void*>(0x123);
static int argument(const char* arg, const char* value, void* call_data)
{
- kwsys_ios::cout << "Got argument: \"" << arg << "\" value: \"" << (value?value:"(null)") << "\"" << kwsys_ios::endl;
- if ( call_data != random_ptr )
- {
- kwsys_ios::cerr << "Problem processing call_data" << kwsys_ios::endl;
+ std::cout << "Got argument: \"" << arg << "\" value: \""
+ << (value ? value : "(null)") << "\"" << std::endl;
+ if (call_data != random_ptr) {
+ std::cerr << "Problem processing call_data" << std::endl;
return 0;
- }
+ }
return 1;
}
static int unknown_argument(const char* argument, void* call_data)
{
- kwsys_ios::cout << "Got unknown argument: \"" << argument << "\"" << kwsys_ios::endl;
- if ( call_data != random_ptr )
- {
- kwsys_ios::cerr << "Problem processing call_data" << kwsys_ios::endl;
+ std::cout << "Got unknown argument: \"" << argument << "\"" << std::endl;
+ if (call_data != random_ptr) {
+ std::cerr << "Problem processing call_data" << std::endl;
return 0;
- }
+ }
return 1;
}
-static bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; }
-static bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; }
-static bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; }
-static bool CompareTwoItemsOnList(const char* i1,
- const char* i2) { return strcmp(i1, i2) == 0; }
-static bool CompareTwoItemsOnList(const kwsys_stl::string& i1,
- const kwsys_stl::string& i2) { return i1 == i2; }
+static bool CompareTwoItemsOnList(bool i1, bool i2)
+{
+ return i1 == i2;
+}
+static bool CompareTwoItemsOnList(int i1, int i2)
+{
+ return i1 == i2;
+}
+static bool CompareTwoItemsOnList(double i1, double i2)
+{
+ return i1 == i2;
+}
+static bool CompareTwoItemsOnList(const char* i1, const char* i2)
+{
+ return strcmp(i1, i2) == 0;
+}
+static bool CompareTwoItemsOnList(const std::string& i1, const std::string& i2)
+{
+ return i1 == i2;
+}
int testCommandLineArguments(int argc, char* argv[])
{
@@ -74,96 +77,112 @@ int testCommandLineArguments(int argc, char* argv[])
int some_int_variable = 10;
double some_double_variable = 10.10;
char* some_string_variable = 0;
- kwsys_stl::string some_stl_string_variable = "";
+ std::string some_stl_string_variable = "";
bool some_bool_variable = false;
bool some_bool_variable1 = false;
bool bool_arg1 = false;
int bool_arg2 = 0;
- kwsys_stl::vector<int> numbers_argument;
+ std::vector<int> numbers_argument;
int valid_numbers[] = { 5, 1, 8, 3, 7, 1, 3, 9, 7, 1 };
- kwsys_stl::vector<double> doubles_argument;
+ std::vector<double> doubles_argument;
double valid_doubles[] = { 12.5, 1.31, 22 };
- kwsys_stl::vector<bool> bools_argument;
+ std::vector<bool> bools_argument;
bool valid_bools[] = { true, true, false };
- kwsys_stl::vector<char*> strings_argument;
+ std::vector<char*> strings_argument;
const char* valid_strings[] = { "andy", "bill", "brad", "ken" };
- kwsys_stl::vector<kwsys_stl::string> stl_strings_argument;
- kwsys_stl::string valid_stl_strings[] = { "ken", "brad", "bill", "andy" };
+ std::vector<std::string> stl_strings_argument;
+ std::string valid_stl_strings[] = { "ken", "brad", "bill", "andy" };
typedef kwsys::CommandLineArguments argT;
- arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT, &some_int_variable, "Set some random int variable");
- arg.AddArgument("--some-double-variable", argT::CONCAT_ARGUMENT, &some_double_variable, "Set some random double variable");
- arg.AddArgument("--some-string-variable", argT::EQUAL_ARGUMENT, &some_string_variable, "Set some random string variable");
- arg.AddArgument("--some-stl-string-variable", argT::EQUAL_ARGUMENT, &some_stl_string_variable, "Set some random stl string variable");
- arg.AddArgument("--some-bool-variable", argT::EQUAL_ARGUMENT, &some_bool_variable, "Set some random bool variable");
- arg.AddArgument("--another-bool-variable", argT::NO_ARGUMENT, &some_bool_variable1, "Set some random bool variable 1");
- arg.AddBooleanArgument("--set-bool-arg1", &bool_arg1, "Test AddBooleanArgument 1");
- arg.AddBooleanArgument("--set-bool-arg2", &bool_arg2, "Test AddBooleanArgument 2");
- arg.AddArgument("--some-multi-argument", argT::MULTI_ARGUMENT, &numbers_argument, "Some multiple values variable");
- arg.AddArgument("-N", argT::SPACE_ARGUMENT, &doubles_argument, "Some explicit multiple values variable");
- arg.AddArgument("-BB", argT::CONCAT_ARGUMENT, &bools_argument, "Some explicit multiple values variable");
- arg.AddArgument("-SS", argT::EQUAL_ARGUMENT, &strings_argument, "Some explicit multiple values variable");
- arg.AddArgument("-SSS", argT::MULTI_ARGUMENT, &stl_strings_argument, "Some explicit multiple values variable");
-
- arg.AddCallback("-A", argT::NO_ARGUMENT, argument, random_ptr, "Some option -A. This option has a multiline comment. It should demonstrate how the code splits lines.");
- arg.AddCallback("-B", argT::SPACE_ARGUMENT, argument, random_ptr, "Option -B takes argument with space");
- 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");
+ arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT,
+ &some_int_variable, "Set some random int variable");
+ arg.AddArgument("--some-double-variable", argT::CONCAT_ARGUMENT,
+ &some_double_variable, "Set some random double variable");
+ arg.AddArgument("--some-string-variable", argT::EQUAL_ARGUMENT,
+ &some_string_variable, "Set some random string variable");
+ arg.AddArgument("--some-stl-string-variable", argT::EQUAL_ARGUMENT,
+ &some_stl_string_variable,
+ "Set some random stl string variable");
+ arg.AddArgument("--some-bool-variable", argT::EQUAL_ARGUMENT,
+ &some_bool_variable, "Set some random bool variable");
+ arg.AddArgument("--another-bool-variable", argT::NO_ARGUMENT,
+ &some_bool_variable1, "Set some random bool variable 1");
+ arg.AddBooleanArgument("--set-bool-arg1", &bool_arg1,
+ "Test AddBooleanArgument 1");
+ arg.AddBooleanArgument("--set-bool-arg2", &bool_arg2,
+ "Test AddBooleanArgument 2");
+ arg.AddArgument("--some-multi-argument", argT::MULTI_ARGUMENT,
+ &numbers_argument, "Some multiple values variable");
+ arg.AddArgument("-N", argT::SPACE_ARGUMENT, &doubles_argument,
+ "Some explicit multiple values variable");
+ arg.AddArgument("-BB", argT::CONCAT_ARGUMENT, &bools_argument,
+ "Some explicit multiple values variable");
+ arg.AddArgument("-SS", argT::EQUAL_ARGUMENT, &strings_argument,
+ "Some explicit multiple values variable");
+ arg.AddArgument("-SSS", argT::MULTI_ARGUMENT, &stl_strings_argument,
+ "Some explicit multiple values variable");
+
+ arg.AddCallback("-A", argT::NO_ARGUMENT, argument, random_ptr,
+ "Some option -A. This option has a multiline comment. It "
+ "should demonstrate how the code splits lines.");
+ arg.AddCallback("-B", argT::SPACE_ARGUMENT, argument, random_ptr,
+ "Option -B takes argument with space");
+ 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");
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, "Same as -C but a bit different");
- arg.AddCallback("--long4", argT::CONCAT_ARGUMENT, argument, random_ptr, "-C");
+ arg.AddCallback("--long3", argT::EQUAL_ARGUMENT, argument, random_ptr,
+ "Same as -C but a bit different");
+ arg.AddCallback("--long4", argT::CONCAT_ARGUMENT, argument, random_ptr,
+ "-C");
- if ( !arg.Parse() )
- {
- kwsys_ios::cerr << "Problem parsing arguments" << kwsys_ios::endl;
+ if (!arg.Parse()) {
+ std::cerr << "Problem parsing arguments" << std::endl;
res = 1;
- }
- kwsys_ios::cout << "Help: " << arg.GetHelp() << kwsys_ios::endl;
-
- kwsys_ios::cout << "Some int variable was set to: " << some_int_variable << kwsys_ios::endl;
- kwsys_ios::cout << "Some double variable was set to: " << some_double_variable << kwsys_ios::endl;
- if ( some_string_variable && strcmp(some_string_variable, "test string with space") == 0)
- {
- kwsys_ios::cout << "Some string variable was set to: " << some_string_variable << kwsys_ios::endl;
- delete [] some_string_variable;
- }
- else
- {
- kwsys_ios::cerr << "Problem setting string variable" << kwsys_ios::endl;
+ }
+ std::cout << "Help: " << arg.GetHelp() << std::endl;
+
+ std::cout << "Some int variable was set to: " << some_int_variable
+ << std::endl;
+ std::cout << "Some double variable was set to: " << some_double_variable
+ << std::endl;
+ if (some_string_variable &&
+ strcmp(some_string_variable, "test string with space") == 0) {
+ std::cout << "Some string variable was set to: " << some_string_variable
+ << std::endl;
+ delete[] some_string_variable;
+ } else {
+ std::cerr << "Problem setting string variable" << std::endl;
res = 1;
- }
+ }
size_t cc;
-#define CompareTwoLists(list1, list_valid, lsize) \
- if ( list1.size() != lsize ) \
- { \
- kwsys_ios::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \
- << " should be: " << lsize << kwsys_ios::endl; \
- res = 1; \
- } \
- else \
- { \
- kwsys_ios::cout << #list1 " argument set:"; \
- for ( cc =0; cc < lsize; ++ cc ) \
- { \
- kwsys_ios::cout << " " << list1[cc]; \
- if ( !CompareTwoItemsOnList(list1[cc], list_valid[cc]) ) \
- { \
- kwsys_ios::cerr << "Problem setting " #list1 ". Value of " \
- << cc << " is: [" << list1[cc] << "] <> [" \
- << list_valid[cc] << "]" << kwsys_ios::endl; \
- res = 1; \
- break; \
- } \
- } \
- kwsys_ios::cout << kwsys_ios::endl; \
- }
+#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; \
+ } \
+ } \
+ std::cout << std::endl; \
+ }
CompareTwoLists(numbers_argument, valid_numbers, 10);
CompareTwoLists(doubles_argument, valid_doubles, 3);
@@ -171,17 +190,19 @@ int testCommandLineArguments(int argc, char* argv[])
CompareTwoLists(strings_argument, valid_strings, 4);
CompareTwoLists(stl_strings_argument, valid_stl_strings, 4);
- kwsys_ios::cout << "Some STL String variable was set to: " << some_stl_string_variable.c_str() << kwsys_ios::endl;
- kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable << kwsys_ios::endl;
- kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable1 << kwsys_ios::endl;
- kwsys_ios::cout << "bool_arg1 variable was set to: " << bool_arg1 << kwsys_ios::endl;
- kwsys_ios::cout << "bool_arg2 variable was set to: " << bool_arg2 << kwsys_ios::endl;
- kwsys_ios::cout << kwsys_ios::endl;
-
- for ( cc = 0; cc < strings_argument.size(); ++ cc )
- {
- delete [] strings_argument[cc];
+ std::cout << "Some STL String variable was set to: "
+ << some_stl_string_variable << std::endl;
+ std::cout << "Some bool variable was set to: " << some_bool_variable
+ << std::endl;
+ std::cout << "Some bool variable was set to: " << some_bool_variable1
+ << std::endl;
+ std::cout << "bool_arg1 variable was set to: " << bool_arg1 << std::endl;
+ std::cout << "bool_arg2 variable was set to: " << bool_arg2 << std::endl;
+ std::cout << std::endl;
+
+ for (cc = 0; cc < strings_argument.size(); ++cc) {
+ delete[] strings_argument[cc];
strings_argument[cc] = 0;
- }
+ }
return res;
}
diff --git a/Source/kwsys/testCommandLineArguments1.cxx b/Source/kwsys/testCommandLineArguments1.cxx
index 0860c2abc..5a03401bc 100644
--- a/Source/kwsys/testCommandLineArguments1.cxx
+++ b/Source/kwsys/testCommandLineArguments1.cxx
@@ -1,26 +1,18 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(CommandLineArguments.hxx)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(stl/vector)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "CommandLineArguments.hxx.in"
-# include "kwsys_ios_iostream.h.in"
+#include "CommandLineArguments.hxx.in"
#endif
+#include <iostream>
+#include <vector>
+
+#include <assert.h> /* assert */
#include <string.h> /* strcmp */
int testCommandLineArguments1(int argc, char* argv[])
@@ -30,7 +22,7 @@ int testCommandLineArguments1(int argc, char* argv[])
int n = 0;
char* m = 0;
- kwsys_stl::string p;
+ std::string p;
int res = 0;
typedef kwsys::CommandLineArguments argT;
@@ -40,67 +32,62 @@ int testCommandLineArguments1(int argc, char* argv[])
arg.StoreUnusedArguments(true);
- if ( !arg.Parse() )
- {
- kwsys_ios::cerr << "Problem parsing arguments" << kwsys_ios::endl;
+ if (!arg.Parse()) {
+ std::cerr << "Problem parsing arguments" << std::endl;
res = 1;
- }
- if ( n != 24 )
- {
- kwsys_ios::cout << "Problem setting N. Value of N: " << n << kwsys_ios::endl;
+ }
+ if (n != 24) {
+ std::cout << "Problem setting N. Value of N: " << n << std::endl;
res = 1;
- }
- if ( !m || strcmp(m, "test value") != 0 )
- {
- kwsys_ios::cout << "Problem setting M. Value of M: " << m << kwsys_ios::endl;
+ }
+ if (!m || strcmp(m, "test value") != 0) {
+ std::cout << "Problem setting M. Value of M: " << m << std::endl;
res = 1;
- }
- if ( p != "1" )
- {
- kwsys_ios::cout << "Problem setting P. Value of P: " << p.c_str() << kwsys_ios::endl;
+ }
+ if (p != "1") {
+ std::cout << "Problem setting P. Value of P: " << p << std::endl;
res = 1;
- }
- kwsys_ios::cout << "Value of N: " << n << kwsys_ios::endl;
- kwsys_ios::cout << "Value of M: " << m << kwsys_ios::endl;
- kwsys_ios::cout << "Value of P: " << p.c_str() << kwsys_ios::endl;
- if ( m )
- {
- delete [] m;
- }
+ }
+ std::cout << "Value of N: " << n << std::endl;
+ std::cout << "Value of M: " << m << std::endl;
+ std::cout << "Value of P: " << p << std::endl;
+ if (m) {
+ delete[] m;
+ }
char** newArgv = 0;
int newArgc = 0;
arg.GetUnusedArguments(&newArgc, &newArgv);
int cc;
- const char* valid_unused_args[9] = {
- 0, "--ignored", "--second-ignored", "third-ignored",
- "some", "junk", "at", "the", "end"
- };
- if ( newArgc != 9 )
- {
- kwsys_ios::cerr << "Bad number of unused arguments: " << newArgc << kwsys_ios::endl;
+ const char* valid_unused_args[9] = { 0,
+ "--ignored",
+ "--second-ignored",
+ "third-ignored",
+ "some",
+ "junk",
+ "at",
+ "the",
+ "end" };
+ if (newArgc != 9) {
+ std::cerr << "Bad number of unused arguments: " << newArgc << std::endl;
res = 1;
- }
- for ( cc = 0; cc < newArgc; ++ cc )
- {
- kwsys_ios::cout << "Unused argument[" << cc << "] = [" << newArgv[cc] << "]"
- << kwsys_ios::endl;
- if ( cc >= 9 )
- {
- kwsys_ios::cerr << "Too many unused arguments: " << cc << kwsys_ios::endl;
+ }
+ for (cc = 0; cc < newArgc; ++cc) {
+ assert(newArgv[cc]); /* Quiet Clang scan-build. */
+ std::cout << "Unused argument[" << cc << "] = [" << newArgv[cc] << "]"
+ << std::endl;
+ if (cc >= 9) {
+ std::cerr << "Too many unused arguments: " << cc << std::endl;
res = 1;
- }
- else if ( valid_unused_args[cc] &&
- strcmp(valid_unused_args[cc], newArgv[cc]) != 0 )
- {
- kwsys_ios::cerr << "Bad unused argument [" << cc << "] \""
- << newArgv[cc] << "\" should be: \"" << valid_unused_args[cc] << "\""
- << kwsys_ios::endl;
+ } else if (valid_unused_args[cc] &&
+ strcmp(valid_unused_args[cc], newArgv[cc]) != 0) {
+ std::cerr << "Bad unused argument [" << cc << "] \"" << newArgv[cc]
+ << "\" should be: \"" << valid_unused_args[cc] << "\""
+ << std::endl;
res = 1;
- }
}
+ }
arg.DeleteRemainingArguments(newArgc, &newArgv);
return res;
}
-
diff --git a/Source/kwsys/testConsoleBuf.cxx b/Source/kwsys/testConsoleBuf.cxx
new file mode 100644
index 000000000..816a4338e
--- /dev/null
+++ b/Source/kwsys/testConsoleBuf.cxx
@@ -0,0 +1,773 @@
+/* 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"
+
+// Ignore Windows version levels defined by command-line flags. This
+// source needs access to all APIs available on the host in order for
+// the test to run properly. The test binary is not installed anyway.
+#undef _WIN32_WINNT
+#undef NTDDI_VERSION
+
+#include KWSYS_HEADER(Encoding.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#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 "testConsoleBuf.hxx"
+
+#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!";
+static UINT TestCodepage = KWSYS_ENCODING_DEFAULT_CODEPAGE;
+
+static const DWORD waitTimeout = 10 * 1000;
+static STARTUPINFO startupInfo;
+static PROCESS_INFORMATION processInfo;
+static HANDLE beforeInputEvent;
+static HANDLE afterOutputEvent;
+static std::string encodedInputTestString;
+static std::string encodedTestString;
+
+static void displayError(DWORD errorCode)
+{
+ std::cerr.setf(std::ios::hex, std::ios::basefield);
+ std::cerr << "Failed with error: 0x" << errorCode << "!" << std::endl;
+ LPWSTR message;
+ if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, errorCode, 0, (LPWSTR)&message, 0, NULL)) {
+ std::cerr << "Error message: " << kwsys::Encoding::ToNarrow(message)
+ << std::endl;
+ HeapFree(GetProcessHeap(), 0, message);
+ } else {
+ std::cerr << "FormatMessage() failed with error: 0x" << GetLastError()
+ << "!" << std::endl;
+ }
+ std::cerr.unsetf(std::ios::hex);
+}
+
+std::basic_streambuf<char>* errstream(const char* unused)
+{
+ static_cast<void>(unused);
+ return std::cerr.rdbuf();
+}
+
+std::basic_streambuf<wchar_t>* errstream(const wchar_t* unused)
+{
+ static_cast<void>(unused);
+ return std::wcerr.rdbuf();
+}
+
+template <typename T>
+static void dumpBuffers(const T* expected, const T* received, size_t size)
+{
+ std::basic_ostream<T> err(errstream(expected));
+ err << "Expected output: '" << std::basic_string<T>(expected, size) << "'"
+ << std::endl;
+ if (err.fail()) {
+ err.clear();
+ err << "--- Error while outputting ---" << std::endl;
+ }
+ err << "Received output: '" << std::basic_string<T>(received, size) << "'"
+ << std::endl;
+ if (err.fail()) {
+ err.clear();
+ err << "--- Error while outputting ---" << std::endl;
+ }
+ std::cerr << "Expected output | Received output" << std::endl;
+ for (size_t i = 0; i < size; i++) {
+ std::cerr << std::setbase(16) << std::setfill('0') << " "
+ << "0x" << std::setw(8) << static_cast<unsigned int>(expected[i])
+ << " | "
+ << "0x" << std::setw(8)
+ << static_cast<unsigned int>(received[i]);
+ if (static_cast<unsigned int>(expected[i]) !=
+ static_cast<unsigned int>(received[i])) {
+ std::cerr << " MISMATCH!";
+ }
+ std::cerr << std::endl;
+ }
+ std::cerr << std::endl;
+}
+
+static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
+{
+ BOOL bInheritHandles = FALSE;
+ DWORD dwCreationFlags = 0;
+ memset(&processInfo, 0, sizeof(processInfo));
+ memset(&startupInfo, 0, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+ startupInfo.dwFlags = STARTF_USESHOWWINDOW;
+ startupInfo.wShowWindow = SW_HIDE;
+ if (hIn || hOut || hErr) {
+ startupInfo.dwFlags |= STARTF_USESTDHANDLES;
+ startupInfo.hStdInput = hIn;
+ startupInfo.hStdOutput = hOut;
+ startupInfo.hStdError = hErr;
+ bInheritHandles = TRUE;
+ }
+
+ WCHAR cmd[MAX_PATH];
+ if (GetModuleFileNameW(NULL, cmd, MAX_PATH) == 0) {
+ std::cerr << "GetModuleFileName failed!" << std::endl;
+ return false;
+ }
+ WCHAR* p = cmd + wcslen(cmd);
+ while (p > cmd && *p != L'\\')
+ p--;
+ *(p + 1) = 0;
+ wcscat(cmd, cmdConsoleBufChild);
+ wcscat(cmd, L".exe");
+
+ bool success =
+ CreateProcessW(NULL, // No module name (use command line)
+ cmd, // Command line
+ NULL, // Process handle not inheritable
+ NULL, // Thread handle not inheritable
+ bInheritHandles, // Set handle inheritance
+ dwCreationFlags,
+ NULL, // Use parent's environment block
+ NULL, // Use parent's starting directory
+ &startupInfo, // Pointer to STARTUPINFO structure
+ &processInfo) !=
+ 0; // Pointer to PROCESS_INFORMATION structure
+ if (!success) {
+ DWORD lastError = GetLastError();
+ std::cerr << "CreateProcess(" << kwsys::Encoding::ToNarrow(cmd) << ")"
+ << std::endl;
+ displayError(lastError);
+ }
+ return success;
+}
+
+static void finishProcess(bool success)
+{
+ if (success) {
+ success =
+ WaitForSingleObject(processInfo.hProcess, waitTimeout) == WAIT_OBJECT_0;
+ };
+ if (!success) {
+ TerminateProcess(processInfo.hProcess, 1);
+ }
+ CloseHandle(processInfo.hProcess);
+ CloseHandle(processInfo.hThread);
+}
+
+static bool createPipe(PHANDLE readPipe, PHANDLE writePipe)
+{
+ SECURITY_ATTRIBUTES securityAttributes;
+ securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ securityAttributes.bInheritHandle = TRUE;
+ securityAttributes.lpSecurityDescriptor = NULL;
+ return CreatePipe(readPipe, writePipe, &securityAttributes, 0) == 0 ? false
+ : true;
+}
+
+static void finishPipe(HANDLE readPipe, HANDLE writePipe)
+{
+ if (readPipe != INVALID_HANDLE_VALUE) {
+ CloseHandle(readPipe);
+ }
+ if (writePipe != INVALID_HANDLE_VALUE) {
+ CloseHandle(writePipe);
+ }
+}
+
+static HANDLE createFile(LPCWSTR fileName)
+{
+ SECURITY_ATTRIBUTES securityAttributes;
+ securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ securityAttributes.bInheritHandle = TRUE;
+ securityAttributes.lpSecurityDescriptor = NULL;
+
+ HANDLE file =
+ CreateFileW(fileName, GENERIC_READ | GENERIC_WRITE,
+ 0, // do not share
+ &securityAttributes,
+ CREATE_ALWAYS, // overwrite existing
+ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ NULL); // no template
+ if (file == INVALID_HANDLE_VALUE) {
+ DWORD lastError = GetLastError();
+ std::cerr << "CreateFile(" << kwsys::Encoding::ToNarrow(fileName) << ")"
+ << std::endl;
+ displayError(lastError);
+ }
+ return file;
+}
+
+static void finishFile(HANDLE file)
+{
+ if (file != INVALID_HANDLE_VALUE) {
+ CloseHandle(file);
+ }
+}
+
+#ifndef MAPVK_VK_TO_VSC
+#define MAPVK_VK_TO_VSC (0)
+#endif
+
+static void writeInputKeyEvent(INPUT_RECORD inputBuffer[], WCHAR chr)
+{
+ inputBuffer[0].EventType = KEY_EVENT;
+ inputBuffer[0].Event.KeyEvent.bKeyDown = TRUE;
+ inputBuffer[0].Event.KeyEvent.wRepeatCount = 1;
+ SHORT keyCode = VkKeyScanW(chr);
+ if (keyCode == -1) {
+ // Character can't be entered with current keyboard layout
+ // Just set any, it doesn't really matter
+ keyCode = 'K';
+ }
+ inputBuffer[0].Event.KeyEvent.wVirtualKeyCode = LOBYTE(keyCode);
+ inputBuffer[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(
+ inputBuffer[0].Event.KeyEvent.wVirtualKeyCode, MAPVK_VK_TO_VSC);
+ inputBuffer[0].Event.KeyEvent.uChar.UnicodeChar = chr;
+ inputBuffer[0].Event.KeyEvent.dwControlKeyState = 0;
+ if ((HIBYTE(keyCode) & 1) == 1) {
+ inputBuffer[0].Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
+ }
+ if ((HIBYTE(keyCode) & 2) == 2) {
+ inputBuffer[0].Event.KeyEvent.dwControlKeyState |= RIGHT_CTRL_PRESSED;
+ }
+ if ((HIBYTE(keyCode) & 4) == 4) {
+ inputBuffer[0].Event.KeyEvent.dwControlKeyState |= RIGHT_ALT_PRESSED;
+ }
+ inputBuffer[1].EventType = inputBuffer[0].EventType;
+ inputBuffer[1].Event.KeyEvent.bKeyDown = FALSE;
+ inputBuffer[1].Event.KeyEvent.wRepeatCount = 1;
+ inputBuffer[1].Event.KeyEvent.wVirtualKeyCode =
+ inputBuffer[0].Event.KeyEvent.wVirtualKeyCode;
+ inputBuffer[1].Event.KeyEvent.wVirtualScanCode =
+ inputBuffer[0].Event.KeyEvent.wVirtualScanCode;
+ inputBuffer[1].Event.KeyEvent.uChar.UnicodeChar =
+ inputBuffer[0].Event.KeyEvent.uChar.UnicodeChar;
+ inputBuffer[1].Event.KeyEvent.dwControlKeyState = 0;
+}
+
+static int testPipe()
+{
+ int didFail = 1;
+ HANDLE inPipeRead = INVALID_HANDLE_VALUE;
+ HANDLE inPipeWrite = INVALID_HANDLE_VALUE;
+ HANDLE outPipeRead = INVALID_HANDLE_VALUE;
+ HANDLE outPipeWrite = INVALID_HANDLE_VALUE;
+ HANDLE errPipeRead = INVALID_HANDLE_VALUE;
+ HANDLE errPipeWrite = INVALID_HANDLE_VALUE;
+ UINT currentCodepage = GetConsoleCP();
+ char buffer[200];
+ char buffer2[200];
+ try {
+ if (!createPipe(&inPipeRead, &inPipeWrite) ||
+ !createPipe(&outPipeRead, &outPipeWrite) ||
+ !createPipe(&errPipeRead, &errPipeWrite)) {
+ throw std::runtime_error("createFile failed!");
+ }
+ if (TestCodepage == CP_ACP) {
+ TestCodepage = GetACP();
+ }
+ if (!SetConsoleCP(TestCodepage)) {
+ throw std::runtime_error("SetConsoleCP failed!");
+ }
+
+ DWORD bytesWritten = 0;
+ if (!WriteFile(inPipeWrite, encodedInputTestString.c_str(),
+ (DWORD)encodedInputTestString.size(), &bytesWritten,
+ NULL) ||
+ bytesWritten == 0) {
+ throw std::runtime_error("WriteFile failed!");
+ }
+
+ if (createProcess(inPipeRead, outPipeWrite, errPipeWrite)) {
+ try {
+ DWORD status;
+ if ((status = WaitForSingleObject(afterOutputEvent, waitTimeout)) !=
+ WAIT_OBJECT_0) {
+ std::cerr.setf(std::ios::hex, std::ios::basefield);
+ std::cerr << "WaitForSingleObject returned unexpected status 0x"
+ << status << std::endl;
+ std::cerr.unsetf(std::ios::hex);
+ throw std::runtime_error("WaitForSingleObject failed!");
+ }
+ DWORD bytesRead = 0;
+ if (!ReadFile(outPipeRead, buffer, sizeof(buffer), &bytesRead, NULL) ||
+ bytesRead == 0) {
+ throw std::runtime_error("ReadFile#1 failed!");
+ }
+ buffer[bytesRead] = 0;
+ if ((bytesRead <
+ encodedTestString.size() + 1 + encodedInputTestString.size() &&
+ !ReadFile(outPipeRead, buffer + bytesRead,
+ sizeof(buffer) - bytesRead, &bytesRead, NULL)) ||
+ bytesRead == 0) {
+ throw std::runtime_error("ReadFile#2 failed!");
+ }
+ if (memcmp(buffer, encodedTestString.c_str(),
+ encodedTestString.size()) == 0 &&
+ memcmp(buffer + encodedTestString.size() + 1,
+ encodedInputTestString.c_str(),
+ encodedInputTestString.size()) == 0) {
+ bytesRead = 0;
+ if (!ReadFile(errPipeRead, buffer2, sizeof(buffer2), &bytesRead,
+ NULL) ||
+ bytesRead == 0) {
+ throw std::runtime_error("ReadFile#3 failed!");
+ }
+ buffer2[bytesRead] = 0;
+ didFail = encodedTestString.compare(0, std::string::npos, buffer2,
+ encodedTestString.size()) == 0
+ ? 0
+ : 1;
+ }
+ if (didFail != 0) {
+ std::cerr << "Pipe's output didn't match expected output!"
+ << std::endl;
+ dumpBuffers<char>(encodedTestString.c_str(), buffer,
+ encodedTestString.size());
+ dumpBuffers<char>(encodedInputTestString.c_str(),
+ buffer + encodedTestString.size() + 1,
+ encodedInputTestString.size());
+ dumpBuffers<char>(encodedTestString.c_str(), buffer2,
+ encodedTestString.size());
+ }
+ } catch (const std::runtime_error& ex) {
+ DWORD lastError = GetLastError();
+ std::cerr << "In function testPipe, line " << __LINE__ << ": "
+ << ex.what() << std::endl;
+ displayError(lastError);
+ }
+ finishProcess(didFail == 0);
+ }
+ } catch (const std::runtime_error& ex) {
+ DWORD lastError = GetLastError();
+ std::cerr << "In function testPipe, line " << __LINE__ << ": " << ex.what()
+ << std::endl;
+ displayError(lastError);
+ }
+ finishPipe(inPipeRead, inPipeWrite);
+ finishPipe(outPipeRead, outPipeWrite);
+ finishPipe(errPipeRead, errPipeWrite);
+ SetConsoleCP(currentCodepage);
+ return didFail;
+}
+
+static int testFile()
+{
+ int didFail = 1;
+ HANDLE inFile = INVALID_HANDLE_VALUE;
+ HANDLE outFile = INVALID_HANDLE_VALUE;
+ HANDLE errFile = INVALID_HANDLE_VALUE;
+ try {
+ if ((inFile = createFile(L"stdinFile.txt")) == INVALID_HANDLE_VALUE ||
+ (outFile = createFile(L"stdoutFile.txt")) == INVALID_HANDLE_VALUE ||
+ (errFile = createFile(L"stderrFile.txt")) == INVALID_HANDLE_VALUE) {
+ throw std::runtime_error("createFile failed!");
+ }
+ DWORD bytesWritten = 0;
+ char buffer[200];
+ char buffer2[200];
+
+ int length;
+ if ((length =
+ WideCharToMultiByte(TestCodepage, 0, UnicodeInputTestString, -1,
+ buffer, sizeof(buffer), NULL, NULL)) == 0) {
+ throw std::runtime_error("WideCharToMultiByte failed!");
+ }
+ buffer[length - 1] = '\n';
+ if (!WriteFile(inFile, buffer, length, &bytesWritten, NULL) ||
+ bytesWritten == 0) {
+ throw std::runtime_error("WriteFile failed!");
+ }
+ if (SetFilePointer(inFile, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
+ throw std::runtime_error("SetFilePointer failed!");
+ }
+
+ if (createProcess(inFile, outFile, errFile)) {
+ DWORD bytesRead = 0;
+ try {
+ DWORD status;
+ if ((status = WaitForSingleObject(afterOutputEvent, waitTimeout)) !=
+ WAIT_OBJECT_0) {
+ std::cerr.setf(std::ios::hex, std::ios::basefield);
+ std::cerr << "WaitForSingleObject returned unexpected status 0x"
+ << status << std::endl;
+ std::cerr.unsetf(std::ios::hex);
+ throw std::runtime_error("WaitForSingleObject failed!");
+ }
+ if (SetFilePointer(outFile, 0, 0, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER) {
+ throw std::runtime_error("SetFilePointer#1 failed!");
+ }
+ if (!ReadFile(outFile, buffer, sizeof(buffer), &bytesRead, NULL) ||
+ bytesRead == 0) {
+ throw std::runtime_error("ReadFile#1 failed!");
+ }
+ buffer[bytesRead] = 0;
+ if (memcmp(buffer, encodedTestString.c_str(),
+ encodedTestString.size()) == 0 &&
+ memcmp(buffer + encodedTestString.size() + 1,
+ encodedInputTestString.c_str(),
+ encodedInputTestString.size()) == 0) {
+ bytesRead = 0;
+ if (SetFilePointer(errFile, 0, 0, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER) {
+ throw std::runtime_error("SetFilePointer#2 failed!");
+ }
+
+ if (!ReadFile(errFile, buffer2, sizeof(buffer2), &bytesRead, NULL) ||
+ bytesRead == 0) {
+ throw std::runtime_error("ReadFile#2 failed!");
+ }
+ buffer2[bytesRead] = 0;
+ didFail = encodedTestString.compare(0, std::string::npos, buffer2,
+ encodedTestString.size()) == 0
+ ? 0
+ : 1;
+ }
+ if (didFail != 0) {
+ std::cerr << "File's output didn't match expected output!"
+ << std::endl;
+ dumpBuffers<char>(encodedTestString.c_str(), buffer,
+ encodedTestString.size());
+ dumpBuffers<char>(encodedInputTestString.c_str(),
+ buffer + encodedTestString.size() + 1,
+ encodedInputTestString.size());
+ dumpBuffers<char>(encodedTestString.c_str(), buffer2,
+ encodedTestString.size());
+ }
+ } catch (const std::runtime_error& ex) {
+ DWORD lastError = GetLastError();
+ std::cerr << "In function testFile, line " << __LINE__ << ": "
+ << ex.what() << std::endl;
+ displayError(lastError);
+ }
+ finishProcess(didFail == 0);
+ }
+ } catch (const std::runtime_error& ex) {
+ DWORD lastError = GetLastError();
+ std::cerr << "In function testFile, line " << __LINE__ << ": " << ex.what()
+ << std::endl;
+ displayError(lastError);
+ }
+ finishFile(inFile);
+ finishFile(outFile);
+ finishFile(errFile);
+ return didFail;
+}
+
+#ifndef _WIN32_WINNT_VISTA
+#define _WIN32_WINNT_VISTA 0x0600
+#endif
+
+static int testConsole()
+{
+ int didFail = 1;
+ HANDLE parentIn = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE parentOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE parentErr = GetStdHandle(STD_ERROR_HANDLE);
+ HANDLE hIn = parentIn;
+ HANDLE hOut = parentOut;
+ DWORD consoleMode;
+ bool newConsole = false;
+ bool forceNewConsole = false;
+ bool restoreConsole = false;
+ LPCWSTR TestFaceName = L"Lucida Console";
+ const DWORD TestFontFamily = 0x00000036;
+ const DWORD TestFontSize = 0x000c0000;
+ HKEY hConsoleKey;
+ WCHAR FaceName[200];
+ FaceName[0] = 0;
+ 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
+ const bool isVistaOrGreater =
+ LOBYTE(LOWORD(GetVersion())) >= HIBYTE(_WIN32_WINNT_VISTA);
+#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
+#pragma warning(pop)
+#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,
+ (LPBYTE)&FontFamily, &dwordSize) == ERROR_SUCCESS) {
+ if (FontFamily != TestFontFamily) {
+ RegQueryValueExW(hConsoleKey, L"FaceName", NULL, NULL,
+ (LPBYTE)FaceName, &FaceNameSize);
+ RegQueryValueExW(hConsoleKey, L"FontSize", NULL, NULL,
+ (LPBYTE)&FontSize, &dwordSize);
+
+ RegSetValueExW(hConsoleKey, L"FontFamily", 0, REG_DWORD,
+ (BYTE*)&TestFontFamily, sizeof(TestFontFamily));
+ RegSetValueExW(hConsoleKey, L"FaceName", 0, REG_SZ,
+ (BYTE*)TestFaceName,
+ (DWORD)((wcslen(TestFaceName) + 1) * sizeof(WCHAR)));
+ RegSetValueExW(hConsoleKey, L"FontSize", 0, REG_DWORD,
+ (BYTE*)&TestFontSize, sizeof(TestFontSize));
+
+ restoreConsole = true;
+ forceNewConsole = true;
+ }
+ } else {
+ std::cerr << "RegGetValueW(FontFamily) failed!" << std::endl;
+ }
+ RegCloseKey(hConsoleKey);
+ } else {
+ std::cerr << "RegOpenKeyExW(HKEY_CURRENT_USER\\Console) failed!"
+ << std::endl;
+ }
+ }
+ if (forceNewConsole || GetConsoleMode(parentOut, &consoleMode) == 0) {
+ // Not a real console, let's create new one.
+ FreeConsole();
+ if (!AllocConsole()) {
+ std::cerr << "AllocConsole failed!" << std::endl;
+ return didFail;
+ }
+ SECURITY_ATTRIBUTES securityAttributes;
+ securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ securityAttributes.bInheritHandle = TRUE;
+ securityAttributes.lpSecurityDescriptor = NULL;
+ hIn = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttributes,
+ OPEN_EXISTING, 0, NULL);
+ if (hIn == INVALID_HANDLE_VALUE) {
+ DWORD lastError = GetLastError();
+ std::cerr << "CreateFile(CONIN$)" << std::endl;
+ displayError(lastError);
+ }
+ hOut = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttributes,
+ OPEN_EXISTING, 0, NULL);
+ if (hOut == INVALID_HANDLE_VALUE) {
+ DWORD lastError = GetLastError();
+ std::cerr << "CreateFile(CONOUT$)" << std::endl;
+ displayError(lastError);
+ }
+ SetStdHandle(STD_INPUT_HANDLE, hIn);
+ SetStdHandle(STD_OUTPUT_HANDLE, hOut);
+ SetStdHandle(STD_ERROR_HANDLE, hOut);
+ newConsole = true;
+ }
+
+#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (isVistaOrGreater) {
+ CONSOLE_FONT_INFOEX consoleFont;
+ memset(&consoleFont, 0, sizeof(consoleFont));
+ consoleFont.cbSize = sizeof(consoleFont);
+ HMODULE kernel32 = LoadLibraryW(L"kernel32.dll");
+ typedef BOOL(WINAPI * GetCurrentConsoleFontExFunc)(
+ HANDLE hConsoleOutput, BOOL bMaximumWindow,
+ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
+ typedef BOOL(WINAPI * SetCurrentConsoleFontExFunc)(
+ HANDLE hConsoleOutput, BOOL bMaximumWindow,
+ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
+ GetCurrentConsoleFontExFunc getConsoleFont =
+ (GetCurrentConsoleFontExFunc)GetProcAddress(kernel32,
+ "GetCurrentConsoleFontEx");
+ SetCurrentConsoleFontExFunc setConsoleFont =
+ (SetCurrentConsoleFontExFunc)GetProcAddress(kernel32,
+ "SetCurrentConsoleFontEx");
+ if (getConsoleFont(hOut, FALSE, &consoleFont)) {
+ if (consoleFont.FontFamily != TestFontFamily) {
+ consoleFont.FontFamily = TestFontFamily;
+ wcscpy(consoleFont.FaceName, TestFaceName);
+ if (!setConsoleFont(hOut, FALSE, &consoleFont)) {
+ std::cerr << "SetCurrentConsoleFontEx failed!" << std::endl;
+ }
+ }
+ } else {
+ std::cerr << "GetCurrentConsoleFontEx failed!" << std::endl;
+ }
+ } else {
+#endif
+ if (restoreConsole &&
+ RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_WRITE,
+ &hConsoleKey) == ERROR_SUCCESS) {
+ RegSetValueExW(hConsoleKey, L"FontFamily", 0, REG_DWORD,
+ (BYTE*)&FontFamily, sizeof(FontFamily));
+ if (FaceName[0] != 0) {
+ RegSetValueExW(hConsoleKey, L"FaceName", 0, REG_SZ, (BYTE*)FaceName,
+ FaceNameSize);
+ } else {
+ RegDeleteValueW(hConsoleKey, L"FaceName");
+ }
+ RegSetValueExW(hConsoleKey, L"FontSize", 0, REG_DWORD, (BYTE*)&FontSize,
+ sizeof(FontSize));
+ RegCloseKey(hConsoleKey);
+ }
+#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ }
+#endif
+
+ if (createProcess(NULL, NULL, NULL)) {
+ try {
+ DWORD status;
+ if ((status = WaitForSingleObject(beforeInputEvent, waitTimeout)) !=
+ WAIT_OBJECT_0) {
+ std::cerr.setf(std::ios::hex, std::ios::basefield);
+ std::cerr << "WaitForSingleObject returned unexpected status 0x"
+ << status << std::endl;
+ std::cerr.unsetf(std::ios::hex);
+ throw std::runtime_error("WaitForSingleObject#1 failed!");
+ }
+ INPUT_RECORD inputBuffer[(sizeof(UnicodeInputTestString) /
+ sizeof(UnicodeInputTestString[0])) *
+ 2];
+ memset(&inputBuffer, 0, sizeof(inputBuffer));
+ unsigned int i;
+ for (i = 0; i < (sizeof(UnicodeInputTestString) /
+ sizeof(UnicodeInputTestString[0]) -
+ 1);
+ i++) {
+ writeInputKeyEvent(&inputBuffer[i * 2], UnicodeInputTestString[i]);
+ }
+ writeInputKeyEvent(&inputBuffer[i * 2], VK_RETURN);
+ DWORD eventsWritten = 0;
+ // We need to wait a bit before writing to console so child process have
+ // started waiting for input on stdin.
+ Sleep(300);
+ if (!WriteConsoleInputW(hIn, inputBuffer,
+ sizeof(inputBuffer) / sizeof(inputBuffer[0]),
+ &eventsWritten) ||
+ eventsWritten == 0) {
+ throw std::runtime_error("WriteConsoleInput failed!");
+ }
+ if ((status = WaitForSingleObject(afterOutputEvent, waitTimeout)) !=
+ WAIT_OBJECT_0) {
+ std::cerr.setf(std::ios::hex, std::ios::basefield);
+ std::cerr << "WaitForSingleObject returned unexpected status 0x"
+ << status << std::endl;
+ std::cerr.unsetf(std::ios::hex);
+ throw std::runtime_error("WaitForSingleObject#2 failed!");
+ }
+ CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
+ if (!GetConsoleScreenBufferInfo(hOut, &screenBufferInfo)) {
+ throw std::runtime_error("GetConsoleScreenBufferInfo failed!");
+ }
+
+ COORD coord;
+ DWORD charsRead = 0;
+ coord.X = 0;
+ coord.Y = screenBufferInfo.dwCursorPosition.Y - 4;
+ WCHAR* outputBuffer = new WCHAR[screenBufferInfo.dwSize.X * 4];
+ if (!ReadConsoleOutputCharacterW(hOut, outputBuffer,
+ screenBufferInfo.dwSize.X * 4, coord,
+ &charsRead) ||
+ charsRead == 0) {
+ delete[] outputBuffer;
+ throw std::runtime_error("ReadConsoleOutputCharacter failed!");
+ }
+ std::wstring wideTestString = kwsys::Encoding::ToWide(encodedTestString);
+ std::replace(wideTestString.begin(), wideTestString.end(), '\0', ' ');
+ std::wstring wideInputTestString =
+ kwsys::Encoding::ToWide(encodedInputTestString);
+ if (memcmp(outputBuffer, wideTestString.c_str(),
+ wideTestString.size() * sizeof(wchar_t)) == 0 &&
+ memcmp(outputBuffer + screenBufferInfo.dwSize.X * 1,
+ wideTestString.c_str(),
+ wideTestString.size() * sizeof(wchar_t)) == 0 &&
+ memcmp(outputBuffer + screenBufferInfo.dwSize.X * 2,
+ UnicodeInputTestString,
+ sizeof(UnicodeInputTestString) - sizeof(WCHAR)) == 0 &&
+ memcmp(outputBuffer + screenBufferInfo.dwSize.X * 3,
+ wideInputTestString.c_str(),
+ (wideInputTestString.size() - 1) * sizeof(wchar_t)) == 0) {
+ didFail = 0;
+ } else {
+ std::cerr << "Console's output didn't match expected output!"
+ << std::endl;
+ dumpBuffers<wchar_t>(wideTestString.c_str(), outputBuffer,
+ wideTestString.size());
+ dumpBuffers<wchar_t>(wideTestString.c_str(),
+ outputBuffer + screenBufferInfo.dwSize.X * 1,
+ wideTestString.size());
+ dumpBuffers<wchar_t>(
+ UnicodeInputTestString, outputBuffer + screenBufferInfo.dwSize.X * 2,
+ (sizeof(UnicodeInputTestString) - 1) / sizeof(WCHAR));
+ dumpBuffers<wchar_t>(wideInputTestString.c_str(),
+ outputBuffer + screenBufferInfo.dwSize.X * 3,
+ wideInputTestString.size() - 1);
+ }
+ delete[] outputBuffer;
+ } catch (const std::runtime_error& ex) {
+ DWORD lastError = GetLastError();
+ std::cerr << "In function testConsole, line " << __LINE__ << ": "
+ << ex.what() << std::endl;
+ displayError(lastError);
+ }
+ finishProcess(didFail == 0);
+ }
+ if (newConsole) {
+ SetStdHandle(STD_INPUT_HANDLE, parentIn);
+ SetStdHandle(STD_OUTPUT_HANDLE, parentOut);
+ SetStdHandle(STD_ERROR_HANDLE, parentErr);
+ CloseHandle(hIn);
+ CloseHandle(hOut);
+ FreeConsole();
+ }
+ return didFail;
+}
+
+#endif
+
+int testConsoleBuf(int, char* [])
+{
+ int ret = 0;
+
+#if defined(_WIN32)
+ beforeInputEvent = CreateEventW(NULL,
+ FALSE, // auto-reset event
+ FALSE, // initial state is nonsignaled
+ BeforeInputEventName); // object name
+ if (!beforeInputEvent) {
+ std::cerr << "CreateEvent#1 failed " << GetLastError() << std::endl;
+ return 1;
+ }
+
+ afterOutputEvent = CreateEventW(NULL, FALSE, FALSE, AfterOutputEventName);
+ if (!afterOutputEvent) {
+ std::cerr << "CreateEvent#2 failed " << GetLastError() << std::endl;
+ return 1;
+ }
+
+ encodedTestString = kwsys::Encoding::ToNarrow(std::wstring(
+ UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1));
+ encodedInputTestString = kwsys::Encoding::ToNarrow(
+ std::wstring(UnicodeInputTestString,
+ sizeof(UnicodeInputTestString) / sizeof(wchar_t) - 1));
+ encodedInputTestString += "\n";
+
+ ret |= testPipe();
+ ret |= testFile();
+ ret |= testConsole();
+
+ CloseHandle(beforeInputEvent);
+ CloseHandle(afterOutputEvent);
+#endif
+
+ return ret;
+}
diff --git a/Source/kwsys/testConsoleBuf.hxx b/Source/kwsys/testConsoleBuf.hxx
new file mode 100644
index 000000000..e93cb4f0a
--- /dev/null
+++ b/Source/kwsys/testConsoleBuf.hxx
@@ -0,0 +1,17 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#ifndef testConsoleBuf_hxx
+#define testConsoleBuf_hxx
+
+static const wchar_t cmdConsoleBufChild[] = L"testConsoleBufChild";
+
+static const wchar_t BeforeInputEventName[] = L"BeforeInputEvent";
+static const wchar_t AfterOutputEventName[] = L"AfterOutputEvent";
+
+// यूनिकोड είναι здорово!
+static const wchar_t UnicodeTestString[] =
+ L"\u092F\u0942\u0928\u093F\u0915\u094B\u0921 "
+ L"\u03B5\u03AF\u03BD\0\u03B1\u03B9 "
+ L"\u0437\u0434\u043E\u0440\u043E\u0432\u043E!";
+
+#endif
diff --git a/Source/kwsys/testConsoleBufChild.cxx b/Source/kwsys/testConsoleBufChild.cxx
new file mode 100644
index 000000000..6a743edcd
--- /dev/null
+++ b/Source/kwsys/testConsoleBufChild.cxx
@@ -0,0 +1,55 @@
+/* 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(ConsoleBuf.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#include "ConsoleBuf.hxx.in"
+#include "Encoding.hxx.in"
+#endif
+
+#include <iostream>
+
+#include "testConsoleBuf.hxx"
+
+int main(int argc, const char* argv[])
+{
+#if defined(_WIN32)
+ kwsys::ConsoleBuf::Manager out(std::cout);
+ kwsys::ConsoleBuf::Manager err(std::cerr, true);
+ kwsys::ConsoleBuf::Manager in(std::cin);
+
+ if (argc > 1) {
+ std::cout << argv[1] << std::endl;
+ std::cerr << argv[1] << std::endl;
+ } else {
+ std::string str = kwsys::Encoding::ToNarrow(std::wstring(
+ UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1));
+ std::cout << str << std::endl;
+ std::cerr << str << std::endl;
+ }
+
+ std::string input;
+ HANDLE event = OpenEventW(EVENT_MODIFY_STATE, FALSE, BeforeInputEventName);
+ if (event) {
+ SetEvent(event);
+ CloseHandle(event);
+ }
+
+ std::cin >> input;
+ std::cout << input << std::endl;
+ event = OpenEventW(EVENT_MODIFY_STATE, FALSE, AfterOutputEventName);
+ if (event) {
+ SetEvent(event);
+ CloseHandle(event);
+ }
+#else
+ static_cast<void>(argc);
+ static_cast<void>(argv);
+#endif
+ return 0;
+}
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index dd6d60390..b52ddda8b 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -1,44 +1,30 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(DynamicLoader.hxx)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(stl/string)
-#if defined(__BEOS__)
-#include <be/kernel/OS.h> /* disable_debugger() API. */
-#endif
-
-#if defined(__HAIKU__)
-#include <os/kernel/OS.h> /* disable_debugger() API. */
+#if defined(__BEOS__) || defined(__HAIKU__)
+#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 "kwsys_ios_iostream.h.in"
-# include "kwsys_stl_string.hxx.in"
+#include "DynamicLoader.hxx.in"
#endif
+#include <iostream>
+#include <string>
+
// Include with <> instead of "" to avoid getting any in-source copy
// left on disk.
#include <testSystemTools.h>
-static kwsys_stl::string GetLibName(const char* lname)
+static std::string GetLibName(const char* lname)
{
// Construct proper name of lib
- kwsys_stl::string slname;
+ std::string slname;
slname = EXECUTABLE_OUTPUT_PATH;
#ifdef CMAKE_INTDIR
slname += "/";
@@ -58,41 +44,36 @@ static kwsys_stl::string GetLibName(const char* lname)
* r2: should GetSymbolAddress succeed ?
* r3: should CloseLibrary succeed ?
*/
-int TestDynamicLoader(const char* libname, const char* symbol, int r1, int r2, int r3)
+static int TestDynamicLoader(const char* libname, const char* symbol, int r1,
+ int r2, int r3)
{
- kwsys_ios::cerr << "Testing: " << libname << kwsys_ios::endl;
- kwsys::DynamicLoader::LibraryHandle l
- = kwsys::DynamicLoader::OpenLibrary(libname);
+ std::cerr << "Testing: " << libname << std::endl;
+ kwsys::DynamicLoader::LibraryHandle l =
+ kwsys::DynamicLoader::OpenLibrary(libname);
// If result is incompatible with expectation just fails (xor):
- if( (r1 && !l) || (!r1 && l) )
- {
- kwsys_ios::cerr
- << kwsys::DynamicLoader::LastError() << kwsys_ios::endl;
+ if ((r1 && !l) || (!r1 && l)) {
+ std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
return 1;
- }
- kwsys::DynamicLoader::SymbolPointer f
- = kwsys::DynamicLoader::GetSymbolAddress(l, symbol);
- if( (r2 && !f) || (!r2 && f) )
- {
- kwsys_ios::cerr
- << kwsys::DynamicLoader::LastError() << kwsys_ios::endl;
+ }
+ kwsys::DynamicLoader::SymbolPointer f =
+ kwsys::DynamicLoader::GetSymbolAddress(l, symbol);
+ if ((r2 && !f) || (!r2 && f)) {
+ std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
return 1;
- }
+ }
#ifndef __APPLE__
int s = kwsys::DynamicLoader::CloseLibrary(l);
- if( (r3 && !s) || (!r3 && s) )
- {
- kwsys_ios::cerr
- << kwsys::DynamicLoader::LastError() << kwsys_ios::endl;
+ if ((r3 && !s) || (!r3 && s)) {
+ std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
return 1;
- }
+ }
#else
(void)r3;
#endif
return 0;
}
-int testDynamicLoader(int argc, char *argv[])
+int testDynamicLoader(int argc, char* argv[])
{
#if defined(_WIN32)
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
@@ -100,34 +81,37 @@ int testDynamicLoader(int argc, char *argv[])
disable_debugger(1);
#endif
int res = 0;
- if( argc == 3 )
- {
+ if (argc == 3) {
// User specify a libname and symbol to check.
- res = TestDynamicLoader(argv[1], argv[2],1,1,1);
+ res = TestDynamicLoader(argv[1], argv[2], 1, 1, 1);
return res;
- }
+ }
// dlopen() on Syllable before 11/22/2007 doesn't return 0 on error
#ifndef __SYLLABLE__
// Make sure that inexistent lib is giving correct result
- res += TestDynamicLoader("azerty_", "foo_bar",0,0,0);
+ res += TestDynamicLoader("azerty_", "foo_bar", 0, 0, 0);
// Make sure that random binary file cannot be assimilated as dylib
- res += TestDynamicLoader(TEST_SYSTEMTOOLS_BIN_FILE, "wp",0,0,0);
+ res += TestDynamicLoader(TEST_SYSTEMTOOLS_SOURCE_DIR "/testSystemTools.bin",
+ "wp", 0, 0, 0);
#endif
#ifdef __linux__
- // This one is actually fun to test, since dlopen is by default loaded...wonder why :)
- res += TestDynamicLoader("foobar.lib", "dlopen",0,1,0);
- res += TestDynamicLoader("libdl.so", "dlopen",1,1,1);
- res += TestDynamicLoader("libdl.so", "TestDynamicLoader",1,0,1);
+ // This one is actually fun to test, since dlopen is by default
+ // loaded...wonder why :)
+ res += TestDynamicLoader("foobar.lib", "dlopen", 0, 1, 0);
+ res += TestDynamicLoader("libdl.so", "dlopen", 1, 1, 1);
+ res += TestDynamicLoader("libdl.so", "TestDynamicLoader", 1, 0, 1);
#endif
// Now try on the generated library
- kwsys_stl::string libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynload");
- res += TestDynamicLoader(libname.c_str(), "dummy",1,0,1);
- res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderSymbolPointer",1,1,1);
- res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderSymbolPointer",1,0,1);
- res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderData",1,1,1);
- res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderData",1,0,1);
+ std::string libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynload");
+ res += TestDynamicLoader(libname.c_str(), "dummy", 1, 0, 1);
+ res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderSymbolPointer",
+ 1, 1, 1);
+ res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderSymbolPointer",
+ 1, 0, 1);
+ res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderData", 1, 1, 1);
+ res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderData", 1, 0, 1);
return res;
}
diff --git a/Source/kwsys/testDynload.c b/Source/kwsys/testDynload.c
index ba60becbd..cdb9e5c35 100644
--- a/Source/kwsys/testDynload.c
+++ b/Source/kwsys/testDynload.c
@@ -1,16 +1,7 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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
#endif
diff --git a/Source/kwsys/testEncode.c b/Source/kwsys/testEncode.c
index 26d483b6f..a20d46fd3 100644
--- a/Source/kwsys/testEncode.c
+++ b/Source/kwsys/testEncode.c
@@ -1,29 +1,20 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(MD5.h)
/* 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>
#include <string.h>
static const unsigned char testMD5input1[] =
-" A quick brown fox jumps over the lazy dog.\n"
-" This is sample text for MD5 sum input.\n";
+ " A quick brown fox jumps over the lazy dog.\n"
+ " This is sample text for MD5 sum input.\n";
static const char testMD5output1[] = "8f146af46ed4f267921bb937d4d3500c";
static const int testMD5input2len = 28;
@@ -40,7 +31,7 @@ static int testMD5_1(kwsysMD5* md5)
printf("md5sum 1: expected [%s]\n"
" got [%s]\n",
testMD5output1, md5out);
- return (strcmp(md5out, testMD5output1) != 0)? 1:0;
+ return (strcmp(md5out, testMD5output1) != 0) ? 1 : 0;
}
static int testMD5_2(kwsysMD5* md5)
@@ -55,7 +46,7 @@ static int testMD5_2(kwsysMD5* md5)
printf("md5sum 2: expected [%s]\n"
" got [%s]\n",
testMD5output2, md5out);
- return (strcmp(md5out, testMD5output2) != 0)? 1:0;
+ return (strcmp(md5out, testMD5output2) != 0) ? 1 : 0;
}
int testEncode(int argc, char* argv[])
@@ -66,10 +57,10 @@ int testEncode(int argc, char* argv[])
/* Test MD5 digest. */
{
- kwsysMD5* md5 = kwsysMD5_New();
- result |= testMD5_1(md5);
- result |= testMD5_2(md5);
- kwsysMD5_Delete(md5);
+ kwsysMD5* md5 = kwsysMD5_New();
+ result |= testMD5_1(md5);
+ result |= testMD5_2(md5);
+ kwsysMD5_Delete(md5);
}
return result;
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
new file mode 100644
index 000000000..2c5ef46eb
--- /dev/null
+++ b/Source/kwsys/testEncoding.cxx
@@ -0,0 +1,281 @@
+/* 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"
+
+#if defined(_MSC_VER)
+#pragma warning(disable : 4786)
+#endif
+
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(Encoding.h)
+
+#include <algorithm>
+#include <iostream>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#include "Encoding.h.in"
+#include "Encoding.hxx.in"
+#endif
+
+static const unsigned char helloWorldStrings[][32] = {
+ // English
+ { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 },
+ // Japanese
+ { 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81, 0xAB, 0xE3, 0x81,
+ 0xA1, 0xE3, 0x81, 0xAF, 0xE4, 0xB8, 0x96, 0xE7, 0x95, 0x8C, 0 },
+ // Arabic
+ { 0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7, 0x20, 0xD8,
+ 0xA7, 0xD9, 0x84, 0xD8, 0xB9, 0xD8, 0xA7, 0xD9, 0x84, 0xD9, 0x85, 0 },
+ // Yiddish
+ { 0xD7, 0x94, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x90, 0x20, 0xD7,
+ 0x95, 0xD7, 0x95, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x98, 0 },
+ // Russian
+ { 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5,
+ 0xD1, 0x82, 0x20, 0xD0, 0xBC, 0xD0, 0xB8, 0xD1, 0x80, 0 },
+ // Latin
+ { 0x4D, 0x75, 0x6E, 0x64, 0x75, 0x73, 0x20, 0x73, 0x61, 0x6C, 0x76, 0x65,
+ 0 },
+ // Swahili
+ { 0x68, 0x75, 0x6A, 0x61, 0x6D, 0x62, 0x6F, 0x20, 0x44, 0x75, 0x6E, 0x69,
+ 0x61, 0 },
+ // Icelandic
+ { 0x48, 0x61, 0x6C, 0x6C, 0xC3, 0xB3, 0x20, 0x68, 0x65, 0x69, 0x6D, 0x75,
+ 0x72, 0 },
+ { 0 }
+};
+
+static int testHelloWorldEncoding()
+{
+ int ret = 0;
+ for (int i = 0; helloWorldStrings[i][0] != 0; i++) {
+ std::string str = reinterpret_cast<const char*>(helloWorldStrings[i]);
+ std::cout << str << std::endl;
+ std::wstring wstr = kwsys::Encoding::ToWide(str);
+ std::string str2 = kwsys::Encoding::ToNarrow(wstr);
+ wchar_t* c_wstr = kwsysEncoding_DupToWide(str.c_str());
+ char* c_str2 = kwsysEncoding_DupToNarrow(c_wstr);
+ if (!wstr.empty() && (str != str2 || strcmp(c_str2, str.c_str()))) {
+ std::cout << "converted string was different: " << str2 << std::endl;
+ std::cout << "converted string was different: " << c_str2 << std::endl;
+ ret++;
+ }
+ free(c_wstr);
+ free(c_str2);
+ }
+ return ret;
+}
+
+static int testRobustEncoding()
+{
+ // test that the conversion functions handle invalid
+ // unicode correctly/gracefully
+
+ int ret = 0;
+ char cstr[] = { (char)-1, 0 };
+ // this conversion could fail
+ std::wstring wstr = kwsys::Encoding::ToWide(cstr);
+
+ wstr = kwsys::Encoding::ToWide(NULL);
+ if (wstr != L"") {
+ const wchar_t* wcstr = wstr.c_str();
+ std::cout << "ToWide(NULL) returned";
+ for (size_t i = 0; i < wstr.size(); i++) {
+ std::cout << " " << std::hex << (int)wcstr[i];
+ }
+ std::cout << std::endl;
+ ret++;
+ }
+ wstr = kwsys::Encoding::ToWide("");
+ if (wstr != L"") {
+ const wchar_t* wcstr = wstr.c_str();
+ std::cout << "ToWide(\"\") returned";
+ for (size_t i = 0; i < wstr.size(); i++) {
+ std::cout << " " << std::hex << (int)wcstr[i];
+ }
+ std::cout << std::endl;
+ ret++;
+ }
+
+#ifdef _WIN32
+ // 16 bit wchar_t - we make an invalid surrogate pair
+ wchar_t cwstr[] = { 0xD801, 0xDA00, 0 };
+ // this conversion could fail
+ std::string win_str = kwsys::Encoding::ToNarrow(cwstr);
+#endif
+
+ std::string str = kwsys::Encoding::ToNarrow(NULL);
+ if (str != "") {
+ std::cout << "ToNarrow(NULL) returned " << str << std::endl;
+ ret++;
+ }
+
+ str = kwsys::Encoding::ToNarrow(L"");
+ if (wstr != L"") {
+ std::cout << "ToNarrow(\"\") returned " << str << std::endl;
+ ret++;
+ }
+
+ return ret;
+}
+
+static int testWithNulls()
+{
+ int ret = 0;
+ std::vector<std::string> strings;
+ strings.push_back(std::string("ab") + '\0' + 'c');
+ strings.push_back(std::string("d") + '\0' + '\0' + 'e');
+ strings.push_back(std::string() + '\0' + 'f');
+ strings.push_back(std::string() + '\0' + '\0' + "gh");
+ strings.push_back(std::string("ij") + '\0');
+ strings.push_back(std::string("k") + '\0' + '\0');
+ strings.push_back(std::string("\0\0\0\0", 4) + "lmn" +
+ std::string("\0\0\0\0", 4));
+ for (std::vector<std::string>::iterator it = strings.begin();
+ it != strings.end(); ++it) {
+ std::wstring wstr = kwsys::Encoding::ToWide(*it);
+ std::string str = kwsys::Encoding::ToNarrow(wstr);
+ std::string s(*it);
+ std::replace(s.begin(), s.end(), '\0', ' ');
+ std::cout << "'" << s << "' (" << it->size() << ")" << std::endl;
+ if (str != *it) {
+ std::replace(str.begin(), str.end(), '\0', ' ');
+ std::cout << "string with null was different: '" << str << "' ("
+ << str.size() << ")" << std::endl;
+ ret++;
+ }
+ }
+ return ret;
+}
+
+static int testCommandLineArguments()
+{
+ int status = 0;
+
+ char const* argv[2] = { "./app.exe", (char const*)helloWorldStrings[1] };
+
+ kwsys::Encoding::CommandLineArguments args(2, argv);
+ kwsys::Encoding::CommandLineArguments arg2 =
+ kwsys::Encoding::CommandLineArguments(args);
+
+ char const* const* u8_argv = args.argv();
+ for (int i = 0; i < args.argc(); i++) {
+ char const* u8_arg = u8_argv[i];
+ if (strcmp(argv[i], u8_arg) != 0) {
+ std::cout << "argv[" << i << "] " << argv[i] << " != " << u8_arg
+ << std::endl;
+ status++;
+ }
+ }
+
+ kwsys::Encoding::CommandLineArguments args3 =
+ kwsys::Encoding::CommandLineArguments::Main(2, argv);
+
+ return status;
+}
+
+static int testToWindowsExtendedPath()
+{
+#ifdef _WIN32
+ int ret = 0;
+ if (kwsys::Encoding::ToWindowsExtendedPath(
+ "L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
+ L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
+ << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath(
+ "L:/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+ L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath(
+ "\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
+ L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
+ << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath(
+ "//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+ L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\""
+ << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath("//") != L"//") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"//\"" << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\") != L"\\\\.\\") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"\\\\.\\\"" << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X") != L"\\\\.\\X") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"\\\\.\\X\"" << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:") != L"\\\\?\\X:") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"\\\\.\\X:\"" << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:\\") !=
+ L"\\\\?\\X:\\") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"\\\\.\\X:\\\"" << std::endl;
+ ++ret;
+ }
+
+ if (kwsys::Encoding::ToWindowsExtendedPath("NUL") != L"\\\\.\\NUL") {
+ std::cout << "Problem with ToWindowsExtendedPath "
+ << "\"NUL\"" << std::endl;
+ ++ret;
+ }
+
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+int testEncoding(int, char* [])
+{
+ const char* loc = setlocale(LC_ALL, "");
+ if (loc) {
+ std::cout << "Locale: " << loc << std::endl;
+ } else {
+ std::cout << "Locale: None" << std::endl;
+ }
+
+ int ret = 0;
+
+ ret |= testHelloWorldEncoding();
+ ret |= testRobustEncoding();
+ ret |= testCommandLineArguments();
+ ret |= testWithNulls();
+ ret |= testToWindowsExtendedPath();
+
+ return ret;
+}
diff --git a/Source/kwsys/testFStream.cxx b/Source/kwsys/testFStream.cxx
new file mode 100644
index 000000000..a92a781c3
--- /dev/null
+++ b/Source/kwsys/testFStream.cxx
@@ -0,0 +1,113 @@
+/* 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"
+
+#if defined(_MSC_VER)
+#pragma warning(disable : 4786)
+#endif
+
+#include KWSYS_HEADER(FStream.hxx)
+#include <string.h>
+#ifdef __BORLANDC__
+#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"
+#endif
+
+#include <iostream>
+
+static int testNoFile()
+{
+ kwsys::ifstream in_file("NoSuchFile.txt");
+ if (in_file) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static const int num_test_files = 7;
+static const int max_test_file_size = 45;
+
+static kwsys::FStream::BOM expected_bom[num_test_files] = {
+ kwsys::FStream::BOM_None, kwsys::FStream::BOM_None,
+ kwsys::FStream::BOM_UTF8, kwsys::FStream::BOM_UTF16LE,
+ kwsys::FStream::BOM_UTF16BE, kwsys::FStream::BOM_UTF32LE,
+ kwsys::FStream::BOM_UTF32BE
+};
+
+static unsigned char expected_bom_data[num_test_files][5] = {
+ { 0 },
+ { 0 },
+ { 3, 0xEF, 0xBB, 0xBF },
+ { 2, 0xFF, 0xFE },
+ { 2, 0xFE, 0xFF },
+ { 4, 0xFF, 0xFE, 0x00, 0x00 },
+ { 4, 0x00, 0x00, 0xFE, 0xFF },
+};
+
+static unsigned char file_data[num_test_files][max_test_file_size] = {
+ { 1, 'H' },
+ { 11, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' },
+ { 11, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' },
+ { 22, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x20,
+ 0x00, 0x57, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6C, 0x00, 0x64, 0x00 },
+ { 22, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00,
+ 0x20, 0x00, 0x57, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6C, 0x00, 0x64 },
+ { 44, 0x48, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00,
+ 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x57, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00,
+ 0x00, 0x6C, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00 },
+ { 44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x6C, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x64 },
+};
+
+static int testBOM()
+{
+ // test various encodings in binary mode
+ for (int i = 0; i < num_test_files; i++) {
+ {
+ kwsys::ofstream out("bom.txt", kwsys::ofstream::binary);
+ out.write(reinterpret_cast<const char*>(expected_bom_data[i] + 1),
+ *expected_bom_data[i]);
+ out.write(reinterpret_cast<const char*>(file_data[i] + 1),
+ file_data[i][0]);
+ }
+
+ kwsys::ifstream in("bom.txt", kwsys::ofstream::binary);
+ kwsys::FStream::BOM bom = kwsys::FStream::ReadBOM(in);
+ if (bom != expected_bom[i]) {
+ std::cout << "Unexpected BOM " << i << std::endl;
+ return 1;
+ }
+ char data[max_test_file_size];
+ in.read(data, file_data[i][0]);
+ if (!in.good()) {
+ std::cout << "Unable to read data " << i << std::endl;
+ return 1;
+ }
+
+ if (memcmp(data, file_data[i] + 1, file_data[i][0]) != 0) {
+ std::cout << "Incorrect read data " << i << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int testFStream(int, char* [])
+{
+ int ret = 0;
+
+ ret |= testNoFile();
+ ret |= testBOM();
+
+ return ret;
+}
diff --git a/Source/kwsys/testFail.c b/Source/kwsys/testFail.c
index 7e062c175..82caeac37 100644
--- a/Source/kwsys/testFail.c
+++ b/Source/kwsys/testFail.c
@@ -1,14 +1,5 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -17,19 +8,17 @@ int testFail(int argc, char* argv[])
{
char* env = getenv("DASHBOARD_TEST_FROM_CTEST");
int oldCtest = 0;
- if(env)
- {
- if(strcmp(env, "1") == 0)
- {
+ if (env) {
+ if (strcmp(env, "1") == 0) {
oldCtest = 1;
- }
- printf("DASHBOARD_TEST_FROM_CTEST = %s\n", env);
}
+ printf("DASHBOARD_TEST_FROM_CTEST = %s\n", env);
+ }
printf("%s: This test intentionally fails\n", argv[0]);
- if(oldCtest)
- {
- printf("The version of ctest is not able to handle intentionally failing tests, so pass.\n");
+ if (oldCtest) {
+ printf("The version of ctest is not able to handle intentionally failing "
+ "tests, so pass.\n");
return 0;
- }
+ }
return argc;
}
diff --git a/Source/kwsys/testHashSTL.cxx b/Source/kwsys/testHashSTL.cxx
index b861a5b32..044487473 100644
--- a/Source/kwsys/testHashSTL.cxx
+++ b/Source/kwsys/testHashSTL.cxx
@@ -1,75 +1,63 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(hash_map.hxx)
#include KWSYS_HEADER(hash_set.hxx)
-#include KWSYS_HEADER(ios/iostream)
// 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 "hashtable.hxx.in"
-# include "kwsys_ios_iostream.h.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>;
template class kwsys::hash_set<int>;
-bool test_hash_map()
+static bool test_hash_map()
{
typedef kwsys::hash_map<const char*, int> mtype;
mtype m;
- const char* keys[] = {"hello", "world"};
+ const char* keys[] = { "hello", "world" };
m[keys[0]] = 1;
m.insert(mtype::value_type(keys[1], 2));
int sum = 0;
- for(mtype::iterator mi = m.begin(); mi != m.end(); ++mi)
- {
- kwsys_ios::cout << "Found entry [" << mi->first << "," << mi->second << "]"
- << kwsys_ios::endl;
+ for (mtype::iterator mi = m.begin(); mi != m.end(); ++mi) {
+ std::cout << "Found entry [" << mi->first << "," << mi->second << "]"
+ << std::endl;
sum += mi->second;
- }
+ }
return sum == 3;
}
-bool test_hash_set()
+static bool test_hash_set()
{
typedef kwsys::hash_set<int> stype;
stype s;
s.insert(1);
s.insert(2);
int sum = 0;
- for(stype::iterator si = s.begin(); si != s.end(); ++si)
- {
- kwsys_ios::cout << "Found entry [" << *si << "]" << kwsys_ios::endl;
+ for (stype::iterator si = s.begin(); si != s.end(); ++si) {
+ std::cout << "Found entry [" << *si << "]" << std::endl;
sum += *si;
- }
+ }
return sum == 3;
}
-int testHashSTL(int, char*[])
+int testHashSTL(int, char* [])
{
bool result = true;
result = test_hash_map() && result;
result = test_hash_set() && result;
- return result? 0:1;
+ return result ? 0 : 1;
}
diff --git a/Source/kwsys/testIOS.cxx b/Source/kwsys/testIOS.cxx
index f0c7f1a7b..3e4c325c7 100644
--- a/Source/kwsys/testIOS.cxx
+++ b/Source/kwsys/testIOS.cxx
@@ -1,167 +1,139 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(stl/vector)
-#include KWSYS_HEADER(ios/sstream)
-#include KWSYS_HEADER(ios/fstream)
-#include KWSYS_HEADER(ios/iostream)
+#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 "kwsys_stl_string.hxx.in"
-# include "kwsys_stl_vector.h.in"
-# include "kwsys_ios_sstream.h.in"
-# include "kwsys_ios_fstream.h.in"
-# include "kwsys_ios_iostream.h.in"
+#include "Configure.hxx.in"
#endif
-#include <string.h> /* strlen */
-
-int testIOS(int, char*[])
+int testIOS(int, char* [])
{
- kwsys_ios::ostringstream ostr;
+ std::ostringstream ostr;
const char hello[] = "hello";
ostr << hello;
- if(ostr.str() != hello)
- {
- kwsys_ios::cerr << "failed to write hello to ostr" << kwsys_ios::endl;
+ if (ostr.str() != hello) {
+ std::cerr << "failed to write hello to ostr" << std::endl;
return 1;
- }
+ }
const char world[] = "world";
- kwsys_ios::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) )
- {
- kwsys_ios::cerr << "failed to write hello to ostr2" << kwsys_ios::endl;
+ 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 };
+ }
+ 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
- kwsys_ios::stringstream strstr;
- strstr.write( (char*)array, narray );
- //strstr.seekp( narray / 2 ); // set position of put pointer in mid string
- if(strstr.str().size() != narray )
- {
- kwsys_ios::cerr << "failed to write array to strstr" << kwsys_ios::endl;
+ 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;
- }
+ }
- kwsys_ios::istringstream istr(" 10 20 str ");
- kwsys_stl::string s;
+ std::istringstream istr(" 10 20 str ");
+ std::string s;
int x;
- if(istr >> x)
- {
- if(x != 10)
- {
- kwsys_ios::cerr << "x != 10" << kwsys_ios::endl;
+ if (istr >> x) {
+ if (x != 10) {
+ std::cerr << "x != 10" << std::endl;
return 1;
- }
}
- else
- {
- kwsys_ios::cerr << "Failed to read 10 from istr" << kwsys_ios::endl;
+ } else {
+ std::cerr << "Failed to read 10 from istr" << std::endl;
return 1;
- }
- if(istr >> x)
- {
- if(x != 20)
- {
- kwsys_ios::cerr << "x != 20" << kwsys_ios::endl;
+ }
+ if (istr >> x) {
+ if (x != 20) {
+ std::cerr << "x != 20" << std::endl;
return 1;
- }
}
- else
- {
- kwsys_ios::cerr << "Failed to read 20 from istr" << kwsys_ios::endl;
+ } else {
+ std::cerr << "Failed to read 20 from istr" << std::endl;
return 1;
- }
- if(istr >> s)
- {
- if(s != "str")
- {
- kwsys_ios::cerr << "s != \"str\"" << kwsys_ios::endl;
+ }
+ if (istr >> s) {
+ if (s != "str") {
+ std::cerr << "s != \"str\"" << std::endl;
return 1;
- }
}
- else
- {
- kwsys_ios::cerr << "Failed to read str from istr" << kwsys_ios::endl;
+ } else {
+ std::cerr << "Failed to read str from istr" << std::endl;
return 1;
- }
- if(istr >> s)
- {
- kwsys_ios::cerr << "Able to read past end of stream" << kwsys_ios::endl;
+ }
+ if (istr >> s) {
+ std::cerr << "Able to read past end of stream" << std::endl;
return 1;
- }
- else
- {
+ } else {
// Clear the failure.
- istr.clear(istr.rdstate() & ~kwsys_ios::ios::eofbit);
- istr.clear(istr.rdstate() & ~kwsys_ios::ios::failbit);
- }
+ istr.clear(istr.rdstate() & ~std::ios::eofbit);
+ istr.clear(istr.rdstate() & ~std::ios::failbit);
+ }
istr.str("30");
- if(istr >> x)
- {
- if(x != 30)
- {
- kwsys_ios::cerr << "x != 30" << kwsys_ios::endl;
+ if (istr >> x) {
+ if (x != 30) {
+ std::cerr << "x != 30" << std::endl;
return 1;
- }
}
- else
- {
- kwsys_ios::cerr << "Failed to read 30 from istr" << kwsys_ios::endl;
+ } else {
+ std::cerr << "Failed to read 30 from istr" << std::endl;
return 1;
- }
+ }
- kwsys_ios::stringstream sstr;
+ std::stringstream sstr;
sstr << "40 str2";
- if(sstr >> x)
- {
- if(x != 40)
- {
- kwsys_ios::cerr << "x != 40" << kwsys_ios::endl;
+ if (sstr >> x) {
+ if (x != 40) {
+ std::cerr << "x != 40" << std::endl;
return 1;
- }
}
- else
- {
- kwsys_ios::cerr << "Failed to read 40 from sstr" << kwsys_ios::endl;
+ } else {
+ std::cerr << "Failed to read 40 from sstr" << std::endl;
return 1;
- }
- if(sstr >> s)
- {
- if(s != "str2")
- {
- kwsys_ios::cerr << "s != \"str2\"" << kwsys_ios::endl;
+ }
+ if (sstr >> s) {
+ if (s != "str2") {
+ std::cerr << "s != \"str2\"" << std::endl;
return 1;
- }
}
- else
- {
- kwsys_ios::cerr << "Failed to read str2 from sstr" << kwsys_ios::endl;
+ } else {
+ std::cerr << "Failed to read str2 from sstr" << std::endl;
return 1;
- }
+ }
// Just try to compile this.
- if(x == 12345)
- {
- kwsys_ios::ifstream fin("/does_not_exist",
- kwsys_ios::ios::in | kwsys_ios_binary);
- }
+ if (x == 12345) {
+ std::ifstream fin("/does_not_exist", std::ios::in | std::ios::binary);
+ }
- kwsys_ios::cout << "IOS tests passed" << kwsys_ios::endl;
+ std::cout << "IOS tests passed" << std::endl;
return 0;
}
diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c
index 6d5eb71fd..092dd0347 100644
--- a/Source/kwsys/testProcess.c
+++ b/Source/kwsys/testProcess.c
@@ -1,55 +1,82 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Process.h)
+#include KWSYS_HEADER(Encoding.h)
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-# include "Process.h.in"
+#include "Encoding.h.in"
+#include "Process.h.in"
#endif
+#include <assert.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
-# include <windows.h>
+#include <windows.h>
#else
-# 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>
-static inline void testProcess_usleep(unsigned int msec)
+#include <be/kernel/OS.h>
+static inline void testProcess_usleep(unsigned int usec)
{
- snooze(msec);
+ snooze(usec);
+}
+#elif defined(_WIN32)
+/* Windows can only sleep in millisecond intervals. */
+static void testProcess_usleep(unsigned int usec)
+{
+ Sleep(usec / 1000);
}
#else
-# define testProcess_usleep usleep
+#define testProcess_usleep usleep
#endif
-int runChild(const char* cmd[], int state, int exception, int value,
- int share, int output, int delay, double timeout, int poll,
- int repeat, int disown);
+#if defined(_WIN32)
+static void testProcess_sleep(unsigned int sec)
+{
+ Sleep(sec * 1000);
+}
+#else
+static void testProcess_sleep(unsigned int sec)
+{
+ sleep(sec);
+}
+#endif
+
+int runChild(const char* cmd[], int state, int exception, int value, int share,
+ int output, int delay, double timeout, int poll, int repeat,
+ int disown, int createNewGroup, unsigned int interruptDelay);
static int test1(int argc, const char* argv[])
{
- (void)argc; (void)argv;
+ /* This is a very basic functional test of kwsysProcess. It is repeated
+ numerous times to verify that there are no resource leaks in kwsysProcess
+ that eventually lead to an error. Many versions of OS X will fail after
+ 256 leaked file handles, so 257 iterations seems to be a good test. On
+ the other hand, too many iterations will cause the test to time out -
+ especially if the test is instrumented with e.g. valgrind.
+
+ If you have problems with this test timing out on your system, or want to
+ run more than 257 iterations, you can change the number of iterations by
+ setting the KWSYS_TEST_PROCESS_1_COUNT environment variable. */
+ (void)argc;
+ (void)argv;
fprintf(stdout, "Output on stdout from test returning 0.\n");
fprintf(stderr, "Output on stderr from test returning 0.\n");
return 0;
@@ -57,7 +84,8 @@ static int test1(int argc, const char* argv[])
static int test2(int argc, const char* argv[])
{
- (void)argc; (void)argv;
+ (void)argc;
+ (void)argv;
fprintf(stdout, "Output on stdout from test returning 123.\n");
fprintf(stderr, "Output on stderr from test returning 123.\n");
return 123;
@@ -65,16 +93,13 @@ static int test2(int argc, const char* argv[])
static int test3(int argc, const char* argv[])
{
- (void)argc; (void)argv;
+ (void)argc;
+ (void)argv;
fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
fprintf(stderr, "Output before sleep on stderr from timeout test.\n");
fflush(stdout);
fflush(stderr);
-#if defined(_WIN32)
- Sleep(15000);
-#else
- sleep(15);
-#endif
+ testProcess_sleep(15);
fprintf(stdout, "Output after sleep on stdout from timeout test.\n");
fprintf(stderr, "Output after sleep on stderr from timeout test.\n");
return 0;
@@ -88,7 +113,7 @@ static int test4(int argc, const char* argv[])
optimize away the write. We hope to 'outsmart' them by using
'volatile' and a slightly larger address, based on a runtime value. */
volatile int* invalidAddress = 0;
- invalidAddress += argc?1:2;
+ invalidAddress += argc ? 1 : 2;
#if defined(_WIN32)
/* Avoid error diagnostic popups since we are crashing on purpose. */
@@ -97,11 +122,13 @@ static int test4(int argc, const char* argv[])
/* Avoid error diagnostic popups since we are crashing on purpose. */
disable_debugger(1);
#endif
- (void)argc; (void)argv;
+ (void)argc;
+ (void)argv;
fprintf(stdout, "Output before crash on stdout from crash test.\n");
- fprintf(stderr, "Output before crash on stderr from crash test.\n");
+ fprintf(stderr, "Output before crash on stderr from crash test.\n");
fflush(stdout);
fflush(stderr);
+ assert(invalidAddress); /* Quiet Clang scan-build. */
/* Provoke deliberate crash by writing to the invalid address. */
*invalidAddress = 0;
fprintf(stdout, "Output after crash on stdout from crash test.\n");
@@ -122,8 +149,8 @@ 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, 1, 1, 1, 0, 15, 0, 1, 0);
+ r = runChild(cmd, kwsysProcess_State_Exception, kwsysProcess_Exception_Fault,
+ 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");
fflush(stdout);
@@ -131,24 +158,23 @@ static int test5(int argc, const char* argv[])
return r;
}
-#define TEST6_SIZE (4096*2)
+#define TEST6_SIZE (4096 * 2)
static void test6(int argc, const char* argv[])
{
int i;
- char runaway[TEST6_SIZE+1];
- (void)argc; (void)argv;
- for(i=0;i < TEST6_SIZE;++i)
- {
+ char runaway[TEST6_SIZE + 1];
+ (void)argc;
+ (void)argv;
+ for (i = 0; i < TEST6_SIZE; ++i) {
runaway[i] = '.';
- }
+ }
runaway[TEST6_SIZE] = '\n';
/* Generate huge amounts of output to test killing. */
- for(;;)
- {
- fwrite(runaway, 1, TEST6_SIZE+1, stdout);
+ for (;;) {
+ fwrite(runaway, 1, TEST6_SIZE + 1, stdout);
fflush(stdout);
- }
+ }
}
/* Define MINPOLL to be one more than the number of times output is
@@ -158,17 +184,14 @@ static void test6(int argc, const char* argv[])
#define MAXPOLL 20
static int test7(int argc, const char* argv[])
{
- (void)argc; (void)argv;
+ (void)argc;
+ (void)argv;
fprintf(stdout, "Output on stdout before sleep.\n");
fprintf(stderr, "Output on stderr before sleep.\n");
fflush(stdout);
fflush(stderr);
/* Sleep for 1 second. */
-#if defined(_WIN32)
- Sleep(1000);
-#else
- sleep(1);
-#endif
+ testProcess_sleep(1);
fprintf(stdout, "Output on stdout after sleep.\n");
fprintf(stderr, "Output on stderr after sleep.\n");
fflush(stdout);
@@ -192,7 +215,7 @@ static int test8(int argc, const char* argv[])
fflush(stdout);
fflush(stderr);
r = runChild(cmd, kwsysProcess_State_Disowned, kwsysProcess_Exception_None,
- 1, 1, 1, 0, 10, 0, 1, 1);
+ 1, 1, 1, 0, 10, 0, 1, 1, 0, 0);
fprintf(stdout, "Output on stdout after grandchild test.\n");
fprintf(stderr, "Output on stderr after grandchild test.\n");
fflush(stdout);
@@ -202,7 +225,8 @@ static int test8(int argc, const char* argv[])
static int test8_grandchild(int argc, const char* argv[])
{
- (void)argc; (void)argv;
+ (void)argc;
+ (void)argv;
fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
fflush(stdout);
@@ -213,18 +237,135 @@ static int test8_grandchild(int argc, const char* argv[])
implemented. */
fclose(stdout);
fclose(stderr);
+ testProcess_sleep(15);
+ return 0;
+}
+
+static int test9(int argc, const char* argv[])
+{
+ /* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this
+ process. Here, we start a child process that sleeps for a long time
+ while ignoring signals. The test is successful if this process waits
+ for the child to return before exiting from the Ctrl+C handler.
+
+ WARNING: This test will falsely pass if the share parameter of runChild
+ was set to 0 when invoking the test9 process. */
+ int r;
+ const char* cmd[4];
+ (void)argc;
+ cmd[0] = argv[0];
+ cmd[1] = "run";
+ cmd[2] = "109";
+ cmd[3] = 0;
+ fprintf(stdout, "Output on stdout before grandchild test.\n");
+ fprintf(stderr, "Output on stderr before grandchild test.\n");
+ fflush(stdout);
+ fflush(stderr);
+ r = runChild(cmd, kwsysProcess_State_Exited, kwsysProcess_Exception_None, 0,
+ 1, 1, 0, 30, 0, 1, 0, 0, 0);
+ /* This sleep will avoid a race condition between this function exiting
+ normally and our Ctrl+C handler exiting abnormally after the process
+ exits. */
+ testProcess_sleep(1);
+ fprintf(stdout, "Output on stdout after grandchild test.\n");
+ fprintf(stderr, "Output on stderr after grandchild test.\n");
+ fflush(stdout);
+ fflush(stderr);
+ return r;
+}
+
#if defined(_WIN32)
- Sleep(15000);
+static BOOL WINAPI test9_grandchild_handler(DWORD dwCtrlType)
+{
+ /* Ignore all Ctrl+C/Break signals. We must use an actual handler function
+ instead of using SetConsoleCtrlHandler(NULL, TRUE) so that we can also
+ ignore Ctrl+Break in addition to Ctrl+C. */
+ (void)dwCtrlType;
+ return TRUE;
+}
+#endif
+
+static int test9_grandchild(int argc, const char* argv[])
+{
+ /* The grandchild just sleeps for a few seconds while ignoring signals. */
+ (void)argc;
+ (void)argv;
+#if defined(_WIN32)
+ if (!SetConsoleCtrlHandler(test9_grandchild_handler, TRUE)) {
+ return 1;
+ }
#else
- sleep(15);
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGINT, &sa, 0) < 0) {
+ return 1;
+ }
#endif
+ fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
+ fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
+ fflush(stdout);
+ fflush(stderr);
+ /* Sleep for 9 seconds. */
+ testProcess_sleep(9);
+ fprintf(stdout, "Output on stdout from grandchild after sleep.\n");
+ fprintf(stderr, "Output on stderr from grandchild after sleep.\n");
+ fflush(stdout);
+ fflush(stderr);
+ return 0;
+}
+
+static int test10(int argc, const char* argv[])
+{
+ /* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this
+ process. Here, we start a child process that sleeps for a long time and
+ processes signals normally. However, this grandchild is created in a new
+ process group - ensuring that Ctrl+C we receive is sent to our process
+ groups. We make sure it exits anyway. */
+ int r;
+ const char* cmd[4];
+ (void)argc;
+ cmd[0] = argv[0];
+ cmd[1] = "run";
+ cmd[2] = "110";
+ cmd[3] = 0;
+ fprintf(stdout, "Output on stdout before grandchild test.\n");
+ fprintf(stderr, "Output on stderr before grandchild test.\n");
+ fflush(stdout);
+ fflush(stderr);
+ r =
+ runChild(cmd, kwsysProcess_State_Exception,
+ kwsysProcess_Exception_Interrupt, 0, 1, 1, 0, 30, 0, 1, 0, 1, 0);
+ fprintf(stdout, "Output on stdout after grandchild test.\n");
+ fprintf(stderr, "Output on stderr after grandchild test.\n");
+ fflush(stdout);
+ fflush(stderr);
+ return r;
+}
+
+static int test10_grandchild(int argc, const char* argv[])
+{
+ /* The grandchild just sleeps for a few seconds and handles signals. */
+ (void)argc;
+ (void)argv;
+ fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
+ fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
+ fflush(stdout);
+ fflush(stderr);
+ /* Sleep for 6 seconds. */
+ testProcess_sleep(6);
+ fprintf(stdout, "Output on stdout from grandchild after sleep.\n");
+ fprintf(stderr, "Output on stderr from grandchild after sleep.\n");
+ fflush(stdout);
+ fflush(stderr);
return 0;
}
-static int runChild2(kwsysProcess* kp,
- const char* cmd[], int state, int exception, int value,
- int share, int output, int delay, double timeout,
- int poll, int disown)
+static int runChild2(kwsysProcess* kp, const char* cmd[], int state,
+ int exception, int value, int share, int output,
+ int delay, double timeout, int poll, int disown,
+ int createNewGroup, unsigned int interruptDelay)
{
int result = 0;
char* data = 0;
@@ -232,160 +373,176 @@ static int runChild2(kwsysProcess* kp,
double userTimeout = 0;
double* pUserTimeout = 0;
kwsysProcess_SetCommand(kp, cmd);
- if(timeout >= 0)
- {
+ if (timeout >= 0) {
kwsysProcess_SetTimeout(kp, timeout);
- }
- if(share)
- {
+ }
+ if (share) {
kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1);
kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDERR, 1);
- }
- if(disown)
- {
+ }
+ if (disown) {
kwsysProcess_SetOption(kp, kwsysProcess_Option_Detach, 1);
- }
+ }
+ if (createNewGroup) {
+ kwsysProcess_SetOption(kp, kwsysProcess_Option_CreateProcessGroup, 1);
+ }
kwsysProcess_Execute(kp);
- if(poll)
- {
+ if (poll) {
pUserTimeout = &userTimeout;
- }
+ }
- if(!share && !disown)
- {
+ if (interruptDelay) {
+ testProcess_sleep(interruptDelay);
+ kwsysProcess_Interrupt(kp);
+ }
+
+ if (!share && !disown) {
int p;
- while((p = kwsysProcess_WaitForData(kp, &data, &length, pUserTimeout)))
- {
- if(output)
- {
- if(poll && p == kwsysProcess_Pipe_Timeout)
- {
+ while ((p = kwsysProcess_WaitForData(kp, &data, &length, pUserTimeout))) {
+ if (output) {
+ if (poll && p == kwsysProcess_Pipe_Timeout) {
fprintf(stdout, "WaitForData timeout reached.\n");
fflush(stdout);
/* Count the number of times we polled without getting data.
If it is excessive then kill the child and fail. */
- if(++poll >= MAXPOLL)
- {
- fprintf(stdout, "Poll count reached limit %d.\n",
- MAXPOLL);
+ if (++poll >= MAXPOLL) {
+ fprintf(stdout, "Poll count reached limit %d.\n", MAXPOLL);
kwsysProcess_Kill(kp);
- }
}
- else
- {
- fwrite(data, 1, (size_t) length, stdout);
+ } else {
+ fwrite(data, 1, (size_t)length, stdout);
fflush(stdout);
- }
}
- if(poll)
- {
+ }
+ if (poll) {
/* Delay to avoid busy loop during polling. */
-#if defined(_WIN32)
- Sleep(100);
-#else
testProcess_usleep(100000);
-#endif
- }
- if(delay)
- {
- /* Purposely sleeping only on Win32 to let pipe fill up. */
+ }
+ if (delay) {
+/* Purposely sleeping only on Win32 to let pipe fill up. */
#if defined(_WIN32)
- Sleep(100);
+ testProcess_usleep(100000);
#endif
- }
}
}
+ }
- if(disown)
- {
+ if (disown) {
kwsysProcess_Disown(kp);
- }
- else
- {
+ } else {
kwsysProcess_WaitForExit(kp, 0);
- }
+ }
- switch (kwsysProcess_GetState(kp))
- {
+ switch (kwsysProcess_GetState(kp)) {
case kwsysProcess_State_Starting:
- printf("No process has been executed.\n"); break;
+ printf("No process has been executed.\n");
+ break;
case kwsysProcess_State_Executing:
- printf("The process is still executing.\n"); break;
+ printf("The process is still executing.\n");
+ break;
case kwsysProcess_State_Expired:
- printf("Child was killed when timeout expired.\n"); break;
+ printf("Child was killed when timeout expired.\n");
+ break;
case kwsysProcess_State_Exited:
- printf("Child exited with value = %d\n",
- kwsysProcess_GetExitValue(kp));
+ printf("Child exited with value = %d\n", kwsysProcess_GetExitValue(kp));
result = ((exception != kwsysProcess_GetExitException(kp)) ||
- (value != kwsysProcess_GetExitValue(kp))); break;
+ (value != kwsysProcess_GetExitValue(kp)));
+ break;
case kwsysProcess_State_Killed:
- printf("Child was killed by parent.\n"); break;
+ printf("Child was killed by parent.\n");
+ break;
case kwsysProcess_State_Exception:
printf("Child terminated abnormally: %s\n",
kwsysProcess_GetExceptionString(kp));
result = ((exception != kwsysProcess_GetExitException(kp)) ||
- (value != kwsysProcess_GetExitValue(kp))); break;
+ (value != kwsysProcess_GetExitValue(kp)));
+ break;
case kwsysProcess_State_Disowned:
- printf("Child was disowned.\n"); break;
+ printf("Child was disowned.\n");
+ break;
case kwsysProcess_State_Error:
printf("Error in administrating child process: [%s]\n",
- kwsysProcess_GetErrorString(kp)); break;
- };
-
- if(result)
- {
- if(exception != kwsysProcess_GetExitException(kp))
- {
+ kwsysProcess_GetErrorString(kp));
+ break;
+ };
+
+ if (result) {
+ if (exception != kwsysProcess_GetExitException(kp)) {
fprintf(stderr, "Mismatch in exit exception. "
- "Should have been %d, was %d.\n",
+ "Should have been %d, was %d.\n",
exception, kwsysProcess_GetExitException(kp));
- }
- if(value != kwsysProcess_GetExitValue(kp))
- {
+ }
+ if (value != kwsysProcess_GetExitValue(kp)) {
fprintf(stderr, "Mismatch in exit value. "
- "Should have been %d, was %d.\n",
+ "Should have been %d, was %d.\n",
value, kwsysProcess_GetExitValue(kp));
- }
}
-
- if(kwsysProcess_GetState(kp) != state)
- {
+ }
+
+ if (kwsysProcess_GetState(kp) != state) {
fprintf(stderr, "Mismatch in state. "
- "Should have been %d, was %d.\n",
+ "Should have been %d, was %d.\n",
state, kwsysProcess_GetState(kp));
result = 1;
- }
+ }
/* We should have polled more times than there were data if polling
was enabled. */
- if(poll && poll < MINPOLL)
- {
- fprintf(stderr, "Poll count is %d, which is less than %d.\n",
- poll, MINPOLL);
+ if (poll && poll < MINPOLL) {
+ fprintf(stderr, "Poll count is %d, which is less than %d.\n", poll,
+ MINPOLL);
result = 1;
- }
+ }
return result;
}
-int runChild(const char* cmd[], int state, int exception, int value,
- int share, int output, int delay, double timeout,
- int poll, int repeat, int disown)
+/**
+ * Runs a child process and blocks until it returns. Arguments as follows:
+ *
+ * cmd = Command line to run.
+ * state = Expected return value of kwsysProcess_GetState after exit.
+ * exception = Expected return value of kwsysProcess_GetExitException.
+ * value = Expected return value of kwsysProcess_GetExitValue.
+ * share = Whether to share stdout/stderr child pipes with our pipes
+ * by way of kwsysProcess_SetPipeShared. If false, new pipes
+ * are created.
+ * output = If !share && !disown, whether to write the child's stdout
+ * and stderr output to our stdout.
+ * delay = If !share && !disown, adds an additional short delay to
+ * the pipe loop to allow the pipes to fill up; Windows only.
+ * timeout = Non-zero to sets a timeout in seconds via
+ * kwsysProcess_SetTimeout.
+ * poll = If !share && !disown, we count the number of 0.1 second
+ * intervals where the child pipes had no new data. We fail
+ * if not in the bounds of MINPOLL/MAXPOLL.
+ * repeat = Number of times to run the process.
+ * disown = If set, the process is disowned.
+ * createNewGroup = If set, the process is created in a new process group.
+ * interruptDelay = If non-zero, number of seconds to delay before
+ * interrupting the process. Note that this delay will occur
+ * BEFORE any reading/polling of pipes occurs and before any
+ * detachment occurs.
+ */
+int runChild(const char* cmd[], int state, int exception, int value, int share,
+ int output, int delay, double timeout, int poll, int repeat,
+ int disown, int createNewGroup, unsigned int interruptDelay)
{
int result = 1;
kwsysProcess* kp = kwsysProcess_New();
- if(!kp)
- {
+ if (!kp) {
fprintf(stderr, "kwsysProcess_New returned NULL!\n");
return 1;
+ }
+ while (repeat-- > 0) {
+ result = runChild2(kp, cmd, state, exception, value, share, output, delay,
+ timeout, poll, disown, createNewGroup, interruptDelay);
+ if (result) {
+ break;
}
- while(repeat-- > 0)
- {
- result = runChild2(kp, cmd, state, exception, value, share,
- output, delay, timeout, poll, disown);
- }
+ }
kwsysProcess_Delete(kp);
return result;
}
@@ -393,6 +550,18 @@ int runChild(const char* cmd[], int state, int exception, int value,
int main(int argc, const char* argv[])
{
int n = 0;
+
+#ifdef _WIN32
+ int i;
+ char new_args[10][_MAX_PATH];
+ LPWSTR* w_av = CommandLineToArgvW(GetCommandLineW(), &argc);
+ for (i = 0; i < argc; i++) {
+ kwsysEncoding_wcstombs(new_args[i], w_av[i], _MAX_PATH);
+ argv[i] = new_args[i];
+ }
+ LocalFree(w_av);
+#endif
+
#if 0
{
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -409,85 +578,96 @@ int main(int argc, const char* argv[])
SetStdHandle(STD_ERROR_HANDLE, out);
}
#endif
- if(argc == 2)
- {
+ if (argc == 2) {
n = atoi(argv[1]);
- }
- else if(argc == 3 && strcmp(argv[1], "run") == 0)
- {
+ } else if (argc == 3 && strcmp(argv[1], "run") == 0) {
n = atoi(argv[2]);
- }
+ }
/* Check arguments. */
- if(((n >= 1 && n <= 8) || n == 108) && argc == 3)
- {
+ if (((n >= 1 && n <= 10) || n == 108 || n == 109 || n == 110) && argc == 3) {
/* This is the child process for a requested test number. */
- switch (n)
- {
- case 1: return test1(argc, argv);
- case 2: return test2(argc, argv);
- case 3: return test3(argc, argv);
- case 4: return test4(argc, argv);
- case 5: return test5(argc, argv);
- case 6: test6(argc, argv); return 0;
- case 7: return test7(argc, argv);
- case 8: return test8(argc, argv);
- case 108: return test8_grandchild(argc, argv);
- }
+ switch (n) {
+ case 1:
+ return test1(argc, argv);
+ case 2:
+ return test2(argc, argv);
+ case 3:
+ return test3(argc, argv);
+ case 4:
+ return test4(argc, argv);
+ case 5:
+ return test5(argc, argv);
+ case 6:
+ test6(argc, argv);
+ return 0;
+ case 7:
+ return test7(argc, argv);
+ case 8:
+ return test8(argc, argv);
+ case 9:
+ return test9(argc, argv);
+ case 10:
+ return test10(argc, argv);
+ case 108:
+ return test8_grandchild(argc, argv);
+ case 109:
+ return test9_grandchild(argc, argv);
+ case 110:
+ return test10_grandchild(argc, argv);
+ }
fprintf(stderr, "Invalid test number %d.\n", n);
return 1;
- }
- else if(n >= 1 && n <= 8)
- {
+ } else if (n >= 1 && n <= 10) {
/* This is the parent process for a requested test number. */
- int states[8] =
- {
- kwsysProcess_State_Exited,
- kwsysProcess_State_Exited,
- kwsysProcess_State_Expired,
- kwsysProcess_State_Exception,
- kwsysProcess_State_Exited,
- kwsysProcess_State_Expired,
- kwsysProcess_State_Exited,
- kwsysProcess_State_Exited
+ int states[10] = {
+ kwsysProcess_State_Exited, kwsysProcess_State_Exited,
+ kwsysProcess_State_Expired, kwsysProcess_State_Exception,
+ kwsysProcess_State_Exited, kwsysProcess_State_Expired,
+ kwsysProcess_State_Exited, kwsysProcess_State_Exited,
+ kwsysProcess_State_Expired, /* Ctrl+C handler test */
+ kwsysProcess_State_Exception /* Process group test */
};
- int exceptions[8] =
- {
- kwsysProcess_Exception_None,
- kwsysProcess_Exception_None,
- kwsysProcess_Exception_None,
- kwsysProcess_Exception_Fault,
- kwsysProcess_Exception_None,
- kwsysProcess_Exception_None,
- kwsysProcess_Exception_None,
- kwsysProcess_Exception_None
+ 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
};
- int values[8] = {0, 123, 1, 1, 0, 0, 0, 0};
- int outputs[8] = {1, 1, 1, 1, 1, 0, 1, 1};
- int delays[8] = {0, 0, 0, 0, 0, 1, 0, 0};
- double timeouts[8] = {10, 10, 10, 30, 30, 10, -1, 10};
- int polls[8] = {0, 0, 0, 0, 0, 0, 1, 0};
- int repeat[8] = {2, 1, 1, 1, 1, 1, 1, 1};
+ 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 };
+ int outputs[10] = { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 };
+ int delays[10] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 };
+ double timeouts[10] = { 10, 10, 10, 30, 30, 10, -1, 10, 6, 4 };
+ int polls[10] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
+ int repeat[10] = { 257, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+ int createNewGroups[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
+ unsigned int interruptDelays[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 };
int r;
const char* cmd[4];
#ifdef _WIN32
char* argv0 = 0;
- if(n == 0 && (argv0 = strdup(argv[0])))
- {
+#endif
+ char* test1IterationsStr = getenv("KWSYS_TEST_PROCESS_1_COUNT");
+ if (test1IterationsStr) {
+ long int test1Iterations = strtol(test1IterationsStr, 0, 10);
+ if (test1Iterations > 10 && test1Iterations != LONG_MAX) {
+ repeat[0] = (int)test1Iterations;
+ }
+ }
+#ifdef _WIN32
+ if (n == 0 && (argv0 = strdup(argv[0]))) {
/* Try converting to forward slashes to see if it works. */
char* c;
- for(c=argv0; *c; ++c)
- {
- if(*c == '\\')
- {
+ for (c = argv0; *c; ++c) {
+ if (*c == '\\') {
*c = '/';
- }
}
- cmd[0] = argv0;
}
- else
- {
+ cmd[0] = argv0;
+ } else {
cmd[0] = argv[0];
- }
+ }
#else
cmd[0] = argv[0];
#endif
@@ -498,34 +678,34 @@ int main(int argc, const char* argv[])
fprintf(stderr, "Output on stderr before test %d.\n", n);
fflush(stdout);
fflush(stderr);
- r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0,
- outputs[n-1], delays[n-1], timeouts[n-1],
- polls[n-1], repeat[n-1], 0);
+ r = runChild(cmd, states[n - 1], exceptions[n - 1], values[n - 1],
+ shares[n - 1], outputs[n - 1], delays[n - 1], timeouts[n - 1],
+ polls[n - 1], repeat[n - 1], 0, createNewGroups[n - 1],
+ interruptDelays[n - 1]);
fprintf(stdout, "Output on stdout after test %d.\n", n);
fprintf(stderr, "Output on stderr after test %d.\n", n);
fflush(stdout);
fflush(stderr);
#if defined(_WIN32)
- if(argv0) { free(argv0); }
+ if (argv0) {
+ free(argv0);
+ }
#endif
return r;
- }
- else if(argc > 2 && strcmp(argv[1], "0") == 0)
- {
+ } else if (argc > 2 && strcmp(argv[1], "0") == 0) {
/* This is the special debugging test to run a given command
line. */
- const char** cmd = argv+2;
+ const char** cmd = argv + 2;
int state = kwsysProcess_State_Exited;
int exception = kwsysProcess_Exception_None;
int value = 0;
double timeout = 0;
- int r = runChild(cmd, state, exception, value, 0, 1, 0, timeout, 0, 1, 0);
+ int r =
+ runChild(cmd, state, exception, value, 0, 1, 0, timeout, 0, 1, 0, 0, 0);
return r;
- }
- else
- {
+ } else {
/* Improper usage. */
fprintf(stdout, "Usage: %s <test number>\n", argv[0]);
return 1;
- }
+ }
}
diff --git a/Source/kwsys/testSharedForward.c.in b/Source/kwsys/testSharedForward.c.in
index ee753efa3..9a0c0c061 100644
--- a/Source/kwsys/testSharedForward.c.in
+++ b/Source/kwsys/testSharedForward.c.in
@@ -1,33 +1,24 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL 0
-#define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD \
+#define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD \
CONFIG_DIR_PRE "@KWSYS_NAMESPACE@TestProcess"
-#define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL \
+#define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL \
"@KWSYS_NAMESPACE@TestProcess"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND "--command"
#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 53d51ac40..3a9217f2c 100644
--- a/Source/kwsys/testSystemInformation.cxx
+++ b/Source/kwsys/testSystemInformation.cxx
@@ -1,53 +1,43 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(SystemInformation.hxx)
-#include KWSYS_HEADER(ios/iostream)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "SystemInformation.hxx.in"
-# include "kwsys_ios_iostream.h.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)
-# else
-# define iostreamLongLong(x) ((long)x)
-# endif
+#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+#define iostreamLongLong(x) (x)
#else
-# error "No Long Long"
+#define iostreamLongLong(x) ((long)x)
+#endif
+#else
+#error "No Long Long"
#endif
-#define printMethod(info, m) kwsys_ios::cout << #m << ": " \
-<< info.m() << "\n"
+#define printMethod(info, m) std::cout << #m << ": " << info.m() << "\n"
-#define printMethod2(info, m, unit) kwsys_ios::cout << #m << ": " \
-<< info.m() << " " << unit << "\n"
+#define printMethod2(info, m, unit) \
+ std::cout << #m << ": " << info.m() << " " << unit << "\n"
-#define printMethod3(info, m, unit) kwsys_ios::cout << #m << ": " \
-<< iostreamLongLong(info.m) << " " << unit << "\n"
+#define printMethod3(info, m, unit) \
+ std::cout << #m << ": " << iostreamLongLong(info.m) << " " << unit << "\n"
-int testSystemInformation(int, char*[])
+int testSystemInformation(int, char* [])
{
- kwsys_ios::cout << "CTEST_FULL_OUTPUT\n"; // avoid truncation
+ std::cout << "CTEST_FULL_OUTPUT\n"; // avoid truncation
kwsys::SystemInformation info;
info.RunCPUCheck();
@@ -62,6 +52,7 @@ int testSystemInformation(int, char*[])
printMethod(info, GetOSRelease);
printMethod(info, GetOSVersion);
printMethod(info, GetOSPlatform);
+ printMethod(info, Is64Bits);
printMethod(info, GetVendorString);
printMethod(info, GetVendorID);
printMethod(info, GetTypeID);
@@ -73,7 +64,6 @@ int testSystemInformation(int, char*[])
printMethod2(info, GetProcessorCacheSize, "KB");
printMethod(info, GetLogicalProcessorsPerPhysical);
printMethod2(info, GetProcessorClockFrequency, "MHz");
- printMethod(info, Is64Bits);
printMethod(info, GetNumberOfLogicalCPU);
printMethod(info, GetNumberOfPhysicalCPU);
printMethod(info, DoesCPUSupportCPUID);
@@ -84,24 +74,22 @@ int testSystemInformation(int, char*[])
printMethod2(info, GetAvailablePhysicalMemory, "MB");
printMethod3(info, GetHostMemoryTotal(), "KiB");
printMethod3(info, GetHostMemoryAvailable("KWSHL"), "KiB");
- printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB");
+ printMethod3(info, GetProcMemoryAvailable("KWSHL", "KWSPL"), "KiB");
printMethod3(info, GetHostMemoryUsed(), "KiB");
printMethod3(info, GetProcMemoryUsed(), "KiB");
+ printMethod(info, GetLoadAverage);
- for (long int i = 0; i <= 31; i++)
- {
- if (info.DoesCPUSupportFeature(static_cast<long int>(1) << i))
- {
- kwsys_ios::cout << "CPU feature " << i << "\n";
- }
+ for (long int i = 0; i <= 31; i++) {
+ if (info.DoesCPUSupportFeature(static_cast<long int>(1) << i)) {
+ std::cout << "CPU feature " << i << "\n";
}
+ }
/* test stack trace
*/
- kwsys_ios::cout
- << "Program Stack:" << kwsys_ios::endl
- << kwsys::SystemInformation::GetProgramStack(0,0) << kwsys_ios::endl
- << kwsys_ios::endl;
+ std::cout << "Program Stack:" << std::endl
+ << kwsys::SystemInformation::GetProgramStack(0, 0) << std::endl
+ << std::endl;
/* test segv handler
info.SetStackTraceOnError(1);
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 1690fd51a..e6fbf6cda 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -1,367 +1,645 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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"
#if defined(_MSC_VER)
-# pragma warning (disable:4786)
+#pragma warning(disable : 4786)
#endif
+#include KWSYS_HEADER(FStream.hxx)
#include KWSYS_HEADER(SystemTools.hxx)
-#include KWSYS_HEADER(ios/iostream)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-# include "SystemTools.hxx.in"
-# include "kwsys_ios_iostream.h.in"
+#include "FStream.hxx.in"
+#include "SystemTools.hxx.in"
#endif
// Include with <> instead of "" to avoid getting any in-source copy
// left on disk.
#include <testSystemTools.h>
+#include <iostream>
+#include <sstream>
#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
+#endif
+#include <sys/stat.h> /* umask (POSIX), _S_I* constants (Windows) */
+// Visual C++ does not define mode_t (note that Borland does, however).
+#if defined(_MSC_VER)
+typedef unsigned short mode_t;
+#endif
-//----------------------------------------------------------------------------
-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" },
- { "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" },
- { "\\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" },
- { "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" },
- { "\\\\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}
+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" },
+ { "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" },
+ { "\\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" },
+ { "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" },
+ { "\\\\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 }
};
-static bool CheckConvertToUnixSlashes(kwsys_stl::string input,
- kwsys_stl::string output)
+static bool CheckConvertToUnixSlashes(std::string const& input,
+ std::string const& output)
{
- kwsys_stl::string result = input;
+ std::string result = input;
kwsys::SystemTools::ConvertToUnixSlashes(result);
- if ( result != output )
- {
- kwsys_ios::cerr
- << "Problem with ConvertToUnixSlashes - input: " << input.c_str()
- << " output: " << result.c_str() << " expected: " << output.c_str()
- << kwsys_ios::endl;
+ if (result != output) {
+ std::cerr << "Problem with ConvertToUnixSlashes - input: " << input
+ << " output: " << result << " expected: " << output << std::endl;
return false;
- }
+ }
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" },
+ { " {} ", "{}", "#", " #{#} " },
+ { 0, 0, 0, 0 } };
-static bool CheckEscapeChars(kwsys_stl::string input,
- const char *chars_to_escape,
- char escape_char,
- kwsys_stl::string output)
+static bool CheckEscapeChars(std::string const& input,
+ const char* chars_to_escape, char escape_char,
+ std::string const& output)
{
- kwsys_stl::string result = kwsys::SystemTools::EscapeChars(
+ std::string result = kwsys::SystemTools::EscapeChars(
input.c_str(), chars_to_escape, escape_char);
- if (result != output)
- {
- kwsys_ios::cerr
- << "Problem with CheckEscapeChars - input: " << input.c_str()
- << " output: " << result.c_str() << " expected: " << output.c_str()
- << kwsys_ios::endl;
+ if (result != output) {
+ std::cerr << "Problem with CheckEscapeChars - input: " << input
+ << " output: " << result << " expected: " << output << std::endl;
return false;
- }
+ }
return true;
}
-//----------------------------------------------------------------------------
static bool CheckFileOperations()
{
bool res = true;
+ const std::string testNonExistingFile(TEST_SYSTEMTOOLS_SOURCE_DIR
+ "/testSystemToolsNonExistingFile");
+ const std::string testDotFile(TEST_SYSTEMTOOLS_SOURCE_DIR "/.");
+ const std::string testBinFile(TEST_SYSTEMTOOLS_SOURCE_DIR
+ "/testSystemTools.bin");
+ const std::string testTxtFile(TEST_SYSTEMTOOLS_SOURCE_DIR
+ "/testSystemTools.cxx");
+ const std::string testNewDir(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/testSystemToolsNewDir");
+ const std::string testNewFile(testNewDir + "/testNewFile.txt");
+
+ if (kwsys::SystemTools::DetectFileType(testNonExistingFile.c_str()) !=
+ kwsys::SystemTools::FileTypeUnknown) {
+ std::cerr << "Problem with DetectFileType - failed to detect type of: "
+ << testNonExistingFile << std::endl;
+ res = false;
+ }
- if (kwsys::SystemTools::DetectFileType(TEST_SYSTEMTOOLS_BIN_FILE) !=
- kwsys::SystemTools::FileTypeBinary)
- {
- kwsys_ios::cerr
- << "Problem with DetectFileType - failed to detect type of: "
- << TEST_SYSTEMTOOLS_BIN_FILE << kwsys_ios::endl;
+ if (kwsys::SystemTools::DetectFileType(testDotFile.c_str()) !=
+ kwsys::SystemTools::FileTypeUnknown) {
+ std::cerr << "Problem with DetectFileType - failed to detect type of: "
+ << testDotFile << std::endl;
res = false;
- }
+ }
- if (kwsys::SystemTools::DetectFileType(TEST_SYSTEMTOOLS_SRC_FILE) !=
- kwsys::SystemTools::FileTypeText)
- {
- kwsys_ios::cerr
- << "Problem with DetectFileType - failed to detect type of: "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
+ if (kwsys::SystemTools::DetectFileType(testBinFile.c_str()) !=
+ kwsys::SystemTools::FileTypeBinary) {
+ std::cerr << "Problem with DetectFileType - failed to detect type of: "
+ << testBinFile << std::endl;
res = false;
- }
-
- if (kwsys::SystemTools::FileLength(TEST_SYSTEMTOOLS_BIN_FILE) != 766)
- {
- kwsys_ios::cerr
- << "Problem with FileLength - incorrect length for: "
- << TEST_SYSTEMTOOLS_BIN_FILE << kwsys_ios::endl;
- res = false;
- }
+ }
+
+ if (kwsys::SystemTools::DetectFileType(testTxtFile.c_str()) !=
+ kwsys::SystemTools::FileTypeText) {
+ std::cerr << "Problem with DetectFileType - failed to detect type of: "
+ << testTxtFile << std::endl;
+ res = false;
+ }
+
+ if (kwsys::SystemTools::FileLength(testBinFile) != 766) {
+ std::cerr << "Problem with FileLength - incorrect length for: "
+ << testBinFile << std::endl;
+ res = false;
+ }
+
+ kwsys::SystemTools::Stat_t buf;
+ if (kwsys::SystemTools::Stat(testTxtFile.c_str(), &buf) != 0) {
+ std::cerr << "Problem with Stat - unable to stat text file: "
+ << testTxtFile << std::endl;
+ res = false;
+ }
+
+ if (kwsys::SystemTools::Stat(testBinFile, &buf) != 0) {
+ std::cerr << "Problem with Stat - unable to stat bin file: " << testBinFile
+ << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::MakeDirectory(testNewDir)) {
+ std::cerr << "Problem with MakeDirectory for: " << testNewDir << std::endl;
+ res = false;
+ }
+ // calling it again should just return true
+ if (!kwsys::SystemTools::MakeDirectory(testNewDir)) {
+ std::cerr << "Problem with second call to MakeDirectory for: "
+ << testNewDir << std::endl;
+ res = false;
+ }
+ // calling with 0 pointer should return false
+ if (kwsys::SystemTools::MakeDirectory(0)) {
+ std::cerr << "Problem with MakeDirectory(0)" << std::endl;
+ res = false;
+ }
+ // calling with an empty string should return false
+ if (kwsys::SystemTools::MakeDirectory(std::string())) {
+ std::cerr << "Problem with MakeDirectory(std::string())" << std::endl;
+ res = false;
+ }
+ // check existence
+ if (!kwsys::SystemTools::FileExists(testNewDir.c_str(), false)) {
+ std::cerr << "Problem with FileExists as C string and not file for: "
+ << testNewDir << std::endl;
+ res = false;
+ }
+ // check existence
+ if (!kwsys::SystemTools::PathExists(testNewDir)) {
+ std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
+ res = false;
+ }
+ // remove it
+ if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
+ std::cerr << "Problem with RemoveADirectory for: " << testNewDir
+ << std::endl;
+ res = false;
+ }
+ // check existence
+ if (kwsys::SystemTools::FileExists(testNewDir.c_str(), false)) {
+ std::cerr << "After RemoveADirectory: "
+ << "Problem with FileExists as C string and not file for: "
+ << testNewDir << std::endl;
+ res = false;
+ }
+ // check existence
+ if (kwsys::SystemTools::PathExists(testNewDir)) {
+ std::cerr << "After RemoveADirectory: "
+ << "Problem with PathExists for: " << testNewDir << std::endl;
+ res = false;
+ }
+ // create it using the char* version
+ if (!kwsys::SystemTools::MakeDirectory(testNewDir.c_str())) {
+ std::cerr << "Problem with second call to MakeDirectory as C string for: "
+ << testNewDir << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::Touch(testNewFile.c_str(), true)) {
+ std::cerr << "Problem with Touch for: " << testNewFile << std::endl;
+ res = false;
+ }
+ // calling MakeDirectory with something that is no file should fail
+ if (kwsys::SystemTools::MakeDirectory(testNewFile)) {
+ std::cerr << "Problem with to MakeDirectory for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ // calling with 0 pointer should return false
+ if (kwsys::SystemTools::FileExists(0)) {
+ std::cerr << "Problem with FileExists(0)" << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::FileExists(0, true)) {
+ std::cerr << "Problem with FileExists(0) as file" << std::endl;
+ res = false;
+ }
+ // calling with an empty string should return false
+ if (kwsys::SystemTools::FileExists(std::string())) {
+ std::cerr << "Problem with FileExists(std::string())" << std::endl;
+ res = false;
+ }
+ // FileExists(x, true) should return false on a directory
+ if (kwsys::SystemTools::FileExists(testNewDir, true)) {
+ std::cerr << "Problem with FileExists as file for: " << testNewDir
+ << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::FileExists(testNewDir.c_str(), true)) {
+ std::cerr << "Problem with FileExists as C string and file for: "
+ << testNewDir << std::endl;
+ res = false;
+ }
+ // FileExists(x, false) should return true even on a directory
+ if (!kwsys::SystemTools::FileExists(testNewDir, false)) {
+ std::cerr << "Problem with FileExists as not file for: " << testNewDir
+ << std::endl;
+ res = false;
+ }
+ if (!kwsys::SystemTools::FileExists(testNewDir.c_str(), false)) {
+ std::cerr << "Problem with FileExists as C string and not file for: "
+ << testNewDir << std::endl;
+ res = false;
+ }
+ // should work, was created as new file before
+ if (!kwsys::SystemTools::FileExists(testNewFile)) {
+ std::cerr << "Problem with FileExists for: " << testNewDir << std::endl;
+ res = false;
+ }
+ if (!kwsys::SystemTools::FileExists(testNewFile.c_str())) {
+ std::cerr << "Problem with FileExists as C string for: " << testNewDir
+ << std::endl;
+ res = false;
+ }
+ if (!kwsys::SystemTools::FileExists(testNewFile, true)) {
+ std::cerr << "Problem with FileExists as file for: " << testNewDir
+ << 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;
+ res = false;
+ }
+
+ // calling with an empty string should return false
+ if (kwsys::SystemTools::PathExists(std::string())) {
+ std::cerr << "Problem with PathExists(std::string())" << std::endl;
+ res = false;
+ }
+ // PathExists(x) should return true on a directory
+ if (!kwsys::SystemTools::PathExists(testNewDir)) {
+ std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
+ res = false;
+ }
+ // should work, was created as new file before
+ if (!kwsys::SystemTools::PathExists(testNewFile)) {
+ std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
+ res = false;
+ }
+
+// Reset umask
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // NOTE: Windows doesn't support toggling _S_IREAD.
+ mode_t fullMask = _S_IWRITE;
+#else
+ // On a normal POSIX platform, we can toggle all permissions.
+ mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO;
+#endif
+ mode_t orig_umask = umask(fullMask);
+
+ // Test file permissions without umask
+ mode_t origPerm, thisPerm;
+ if (!kwsys::SystemTools::GetPermissions(testNewFile, origPerm)) {
+ std::cerr << "Problem with GetPermissions (1) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::SetPermissions(testNewFile, 0)) {
+ std::cerr << "Problem with SetPermissions (1) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::GetPermissions(testNewFile, thisPerm)) {
+ std::cerr << "Problem with GetPermissions (2) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if ((thisPerm & fullMask) != 0) {
+ std::cerr << "SetPermissions failed to set permissions (1) for: "
+ << testNewFile << ": actual = " << thisPerm
+ << "; expected = " << 0 << std::endl;
+ res = false;
+ }
+
+ // While we're at it, check proper TestFileAccess functionality.
+ if (kwsys::SystemTools::TestFileAccess(testNewFile,
+ kwsys::TEST_FILE_WRITE)) {
+ std::cerr
+ << "TestFileAccess incorrectly indicated that this is a writable file:"
+ << testNewFile << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::TestFileAccess(testNewFile, kwsys::TEST_FILE_OK)) {
+ std::cerr
+ << "TestFileAccess incorrectly indicated that this file does not exist:"
+ << testNewFile << std::endl;
+ res = false;
+ }
+
+ // Test restoring/setting full permissions.
+ if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask)) {
+ std::cerr << "Problem with SetPermissions (2) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::GetPermissions(testNewFile, thisPerm)) {
+ std::cerr << "Problem with GetPermissions (3) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if ((thisPerm & fullMask) != fullMask) {
+ std::cerr << "SetPermissions failed to set permissions (2) for: "
+ << testNewFile << ": actual = " << thisPerm
+ << "; expected = " << fullMask << std::endl;
+ res = false;
+ }
+
+ // Test setting file permissions while honoring umask
+ if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask, true)) {
+ std::cerr << "Problem with SetPermissions (3) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::GetPermissions(testNewFile, thisPerm)) {
+ std::cerr << "Problem with GetPermissions (4) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ if ((thisPerm & fullMask) != 0) {
+ std::cerr << "SetPermissions failed to honor umask for: " << testNewFile
+ << ": actual = " << thisPerm << "; expected = " << 0
+ << std::endl;
+ res = false;
+ }
+
+ // Restore umask
+ umask(orig_umask);
+
+ // Restore file permissions
+ if (!kwsys::SystemTools::SetPermissions(testNewFile, origPerm)) {
+ std::cerr << "Problem with SetPermissions (4) for: " << testNewFile
+ << std::endl;
+ res = false;
+ }
+
+ // Remove the test file
+ if (!kwsys::SystemTools::RemoveFile(testNewFile)) {
+ std::cerr << "Problem with RemoveFile: " << testNewFile << std::endl;
+ res = false;
+ }
+
+ std::string const testFileMissing(testNewDir + "/testMissingFile.txt");
+ if (!kwsys::SystemTools::RemoveFile(testFileMissing)) {
+ std::string const& msg = kwsys::SystemTools::GetLastSystemError();
+ std::cerr << "RemoveFile(\"" << testFileMissing << "\") failed: " << msg
+ << "\n";
+ res = false;
+ }
+
+ std::string const testFileMissingDir(testNewDir + "/missing/file.txt");
+ if (!kwsys::SystemTools::RemoveFile(testFileMissingDir)) {
+ std::string const& msg = kwsys::SystemTools::GetLastSystemError();
+ std::cerr << "RemoveFile(\"" << testFileMissingDir << "\") failed: " << msg
+ << "\n";
+ res = false;
+ }
+
+ kwsys::SystemTools::Touch(testNewFile.c_str(), true);
+ if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
+ std::cerr << "Problem with RemoveADirectory for: " << testNewDir
+ << std::endl;
+ res = false;
+ }
+
+#ifdef KWSYS_TEST_SYSTEMTOOLS_LONG_PATHS
+ // Perform the same file and directory creation and deletion tests but
+ // with paths > 256 characters in length.
+
+ const std::string testNewLongDir(
+ TEST_SYSTEMTOOLS_BINARY_DIR
+ "/"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "01234567890123");
+ const std::string testNewLongFile(
+ testNewLongDir +
+ "/"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890123456789012345678901234567890123456789"
+ "0123456789.txt");
+
+ if (!kwsys::SystemTools::MakeDirectory(testNewLongDir)) {
+ std::cerr << "Problem with MakeDirectory for: " << testNewLongDir
+ << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::Touch(testNewLongFile.c_str(), true)) {
+ std::cerr << "Problem with Touch for: " << testNewLongFile << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::RemoveFile(testNewLongFile)) {
+ std::cerr << "Problem with RemoveFile: " << testNewLongFile << std::endl;
+ res = false;
+ }
+
+ kwsys::SystemTools::Touch(testNewLongFile.c_str(), true);
+ if (!kwsys::SystemTools::RemoveADirectory(testNewLongDir)) {
+ std::cerr << "Problem with RemoveADirectory for: " << testNewLongDir
+ << std::endl;
+ res = false;
+ }
+#endif
return res;
}
-//----------------------------------------------------------------------------
static bool CheckStringOperations()
{
bool res = true;
- kwsys_stl::string test = "mary had a little lamb.";
- if (kwsys::SystemTools::CapitalizedWords(test) != "Mary Had A Little Lamb.")
- {
- kwsys_ios::cerr
- << "Problem with CapitalizedWords "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
+ std::string test = "mary had a little lamb.";
+ if (kwsys::SystemTools::CapitalizedWords(test) !=
+ "Mary Had A Little Lamb.") {
+ std::cerr << "Problem with CapitalizedWords " << '"' << test << '"'
+ << std::endl;
+ res = false;
+ }
test = "Mary Had A Little Lamb.";
- if (kwsys::SystemTools::UnCapitalizedWords(test) !=
- "mary had a little lamb.")
- {
- kwsys_ios::cerr
- << "Problem with UnCapitalizedWords "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
+ if (kwsys::SystemTools::UnCapitalizedWords(test) !=
+ "mary had a little lamb.") {
+ std::cerr << "Problem with UnCapitalizedWords " << '"' << test << '"'
+ << std::endl;
+ res = false;
+ }
test = "MaryHadTheLittleLamb.";
- if (kwsys::SystemTools::AddSpaceBetweenCapitalizedWords(test) !=
- "Mary Had The Little Lamb.")
- {
- kwsys_ios::cerr
- << "Problem with AddSpaceBetweenCapitalizedWords "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
+ if (kwsys::SystemTools::AddSpaceBetweenCapitalizedWords(test) !=
+ "Mary Had The Little Lamb.") {
+ std::cerr << "Problem with AddSpaceBetweenCapitalizedWords " << '"' << test
+ << '"' << std::endl;
+ res = false;
+ }
- char * cres =
- kwsys::SystemTools::AppendStrings("Mary Had A"," Little Lamb.");
- if (strcmp(cres,"Mary Had A Little Lamb."))
- {
- kwsys_ios::cerr
- << "Problem with AppendStrings "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- delete [] cres;
-
- cres =
- kwsys::SystemTools::AppendStrings("Mary Had"," A ","Little Lamb.");
- if (strcmp(cres,"Mary Had A Little Lamb."))
- {
- kwsys_ios::cerr
- << "Problem with AppendStrings "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- delete [] cres;
-
- if (kwsys::SystemTools::CountChar("Mary Had A Little Lamb.",'a') != 3)
- {
- kwsys_ios::cerr
- << "Problem with CountChar "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
+ char* cres =
+ kwsys::SystemTools::AppendStrings("Mary Had A", " Little Lamb.");
+ if (strcmp(cres, "Mary Had A Little Lamb.")) {
+ std::cerr << "Problem with AppendStrings "
+ << "\"Mary Had A\" \" Little Lamb.\"" << std::endl;
+ res = false;
+ }
+ delete[] cres;
- cres =
- kwsys::SystemTools::RemoveChars("Mary Had A Little Lamb.","aeiou");
- if (strcmp(cres,"Mry Hd A Lttl Lmb."))
- {
- kwsys_ios::cerr
- << "Problem with RemoveChars "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- delete [] cres;
-
- cres =
- kwsys::SystemTools::RemoveCharsButUpperHex("Mary Had A Little Lamb.");
- if (strcmp(cres,"A"))
- {
- kwsys_ios::cerr
- << "Problem with RemoveCharsButUpperHex "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- delete [] cres;
-
- char *cres2 = new char [strlen("Mary Had A Little Lamb.")+1];
- strcpy(cres2,"Mary Had A Little Lamb.");
- kwsys::SystemTools::ReplaceChars(cres2,"aeiou",'X');
- if (strcmp(cres2,"MXry HXd A LXttlX LXmb."))
- {
- kwsys_ios::cerr
- << "Problem with ReplaceChars "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- delete [] cres2;
+ cres = kwsys::SystemTools::AppendStrings("Mary Had", " A ", "Little Lamb.");
+ if (strcmp(cres, "Mary Had A Little Lamb.")) {
+ std::cerr << "Problem with AppendStrings "
+ << "\"Mary Had\" \" A \" \"Little Lamb.\"" << std::endl;
+ res = false;
+ }
+ delete[] cres;
+
+ if (kwsys::SystemTools::CountChar("Mary Had A Little Lamb.", 'a') != 3) {
+ std::cerr << "Problem with CountChar "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
+
+ cres = kwsys::SystemTools::RemoveChars("Mary Had A Little Lamb.", "aeiou");
+ if (strcmp(cres, "Mry Hd A Lttl Lmb.")) {
+ std::cerr << "Problem with RemoveChars "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
+ delete[] cres;
+
+ cres = kwsys::SystemTools::RemoveCharsButUpperHex("Mary Had A Little Lamb.");
+ if (strcmp(cres, "A")) {
+ std::cerr << "Problem with RemoveCharsButUpperHex "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
+ delete[] cres;
+
+ char* cres2 = new char[strlen("Mary Had A Little Lamb.") + 1];
+ strcpy(cres2, "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;
if (!kwsys::SystemTools::StringStartsWith("Mary Had A Little Lamb.",
- "Mary "))
- {
- kwsys_ios::cerr
- << "Problem with StringStartsWith "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
+ "Mary ")) {
+ std::cerr << "Problem with StringStartsWith "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
if (!kwsys::SystemTools::StringEndsWith("Mary Had A Little Lamb.",
- " Lamb."))
- {
- kwsys_ios::cerr
- << "Problem with StringEndsWith "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
+ " Lamb.")) {
+ std::cerr << "Problem with StringEndsWith "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
cres = kwsys::SystemTools::DuplicateString("Mary Had A Little Lamb.");
- if (strcmp(cres,"Mary Had A Little Lamb."))
- {
- kwsys_ios::cerr
- << "Problem with DuplicateString "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- delete [] cres;
+ if (strcmp(cres, "Mary Had A Little Lamb.")) {
+ std::cerr << "Problem with DuplicateString "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
+ delete[] cres;
test = "Mary Had A Little Lamb.";
- if (kwsys::SystemTools::CropString(test,13) !=
- "Mary ...Lamb.")
- {
- kwsys_ios::cerr
- << "Problem with CropString "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
-
- kwsys_stl::vector<kwsys_stl::string> lines;
- kwsys::SystemTools::Split("Mary Had A Little Lamb.",lines,' ');
- if (lines[0] != "Mary" || lines[1] != "Had" ||
- lines[2] != "A" || lines[3] != "Little" || lines[4] != "Lamb.")
- {
- kwsys_ios::cerr
- << "Problem with Split "
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
-
- if (kwsys::SystemTools::ConvertToWindowsOutputPath
- ("L://Local Mojo/Hex Power Pack/Iffy Voodoo") !=
- "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"")
- {
- kwsys_ios::cerr
- << "Problem with ConvertToWindowsOutputPath "
- << kwsys_ios::endl;
- res = false;
- }
-
- if (kwsys::SystemTools::ConvertToWindowsOutputPath
- ("//grayson/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
- "\"\\\\grayson\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"")
- {
- kwsys_ios::cerr
- << "Problem with ConvertToWindowsOutputPath "
- << kwsys_ios::endl;
- res = false;
- }
+ if (kwsys::SystemTools::CropString(test, 13) != "Mary ...Lamb.") {
+ std::cerr << "Problem with CropString "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
+
+ std::vector<std::string> lines;
+ kwsys::SystemTools::Split("Mary Had A Little Lamb.", lines, ' ');
+ if (lines[0] != "Mary" || lines[1] != "Had" || lines[2] != "A" ||
+ lines[3] != "Little" || lines[4] != "Lamb.") {
+ std::cerr << "Problem with Split "
+ << "\"Mary Had A Little Lamb.\"" << std::endl;
+ res = false;
+ }
- if (kwsys::SystemTools::ConvertToUnixOutputPath
- ("//Local Mojo/Hex Power Pack/Iffy Voodoo") !=
- "//Local\\ Mojo/Hex\\ Power\\ Pack/Iffy\\ Voodoo")
- {
- kwsys_ios::cerr
- << "Problem with ConvertToUnixOutputPath "
- << kwsys_ios::endl;
- res = false;
- }
+ if (kwsys::SystemTools::ConvertToWindowsOutputPath(
+ "L://Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+ "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
+ std::cerr << "Problem with ConvertToWindowsOutputPath "
+ << "\"L://Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
+ res = false;
+ }
+
+ if (kwsys::SystemTools::ConvertToWindowsOutputPath(
+ "//grayson/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+ "\"\\\\grayson\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
+ std::cerr << "Problem with ConvertToWindowsOutputPath "
+ << "\"//grayson/Local Mojo/Hex Power Pack/Iffy Voodoo\""
+ << std::endl;
+ res = false;
+ }
- int targc;
- char **targv;
- kwsys::SystemTools::ConvertWindowsCommandLineToUnixArguments
- ("\"Local Mojo\\Voodoo.asp\" -CastHex \"D:\\My Secret Mojo\\Voodoo.mp3\"", &targc, &targv);
- if (targc != 4 || strcmp(targv[1],"Local Mojo\\Voodoo.asp") ||
- strcmp(targv[2],"-CastHex") ||
- strcmp(targv[3],"D:\\My Secret Mojo\\Voodoo.mp3"))
- {
- kwsys_ios::cerr
- << "Problem with ConvertWindowsCommandLineToUnixArguments"
- << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl;
- res = false;
- }
- for (;targc >=0; --targc)
- {
- delete [] targv[targc];
- }
- delete [] targv;
+ if (kwsys::SystemTools::ConvertToUnixOutputPath(
+ "//Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+ "//Local\\ Mojo/Hex\\ Power\\ Pack/Iffy\\ Voodoo") {
+ std::cerr << "Problem with ConvertToUnixOutputPath "
+ << "\"//Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
+ res = false;
+ }
return res;
}
-//----------------------------------------------------------------------------
-
-static bool CheckPutEnv(const char* env, const char* name, const char* value)
+static bool CheckPutEnv(const std::string& env, const char* name,
+ const char* value)
{
- if(!kwsys::SystemTools::PutEnv(env))
- {
- kwsys_ios::cerr << "PutEnv(\"" << env
- << "\") failed!" << kwsys_ios::endl;
+ if (!kwsys::SystemTools::PutEnv(env)) {
+ std::cerr << "PutEnv(\"" << env << "\") failed!" << std::endl;
return false;
- }
- const char* v = kwsys::SystemTools::GetEnv(name);
- v = v? v : "(null)";
- if(strcmp(v, value) != 0)
- {
- kwsys_ios::cerr << "GetEnv(\"" << name << "\") returned \""
- << v << "\", not \"" << value << "\"!" << kwsys_ios::endl;
+ }
+ std::string v = "(null)";
+ kwsys::SystemTools::GetEnv(name, v);
+ if (v != value) {
+ std::cerr << "GetEnv(\"" << name << "\") returned \"" << v << "\", not \""
+ << value << "\"!" << std::endl;
return false;
- }
+ }
return true;
}
static bool CheckUnPutEnv(const char* env, const char* name)
{
- if(!kwsys::SystemTools::UnPutEnv(env))
- {
- kwsys_ios::cerr << "UnPutEnv(\"" << env << "\") failed!"
- << kwsys_ios::endl;
+ if (!kwsys::SystemTools::UnPutEnv(env)) {
+ std::cerr << "UnPutEnv(\"" << env << "\") failed!" << std::endl;
return false;
- }
- if(const char* v = kwsys::SystemTools::GetEnv(name))
- {
- kwsys_ios::cerr << "GetEnv(\"" << name << "\") returned \""
- << v << "\", not (null)!" << kwsys_ios::endl;
+ }
+ std::string v;
+ if (kwsys::SystemTools::GetEnv(name, v)) {
+ std::cerr << "GetEnv(\"" << name << "\") returned \"" << v
+ << "\", not (null)!" << std::endl;
return false;
- }
+ }
return true;
}
@@ -379,30 +657,207 @@ static bool CheckEnvironmentOperations()
return res;
}
-//----------------------------------------------------------------------------
-int testSystemTools(int, char*[])
+static bool CheckRelativePath(const std::string& local,
+ const std::string& remote,
+ const std::string& expected)
+{
+ std::string result = kwsys::SystemTools::RelativePath(local, remote);
+ if (!kwsys::SystemTools::ComparePath(expected, result)) {
+ std::cerr << "RelativePath(" << local << ", " << remote << ") yielded "
+ << result << " instead of " << expected << std::endl;
+ return false;
+ }
+ return true;
+}
+
+static bool CheckRelativePaths()
+{
+ bool res = true;
+ res &= CheckRelativePath("/usr/share", "/bin/bash", "../../bin/bash");
+ res &= CheckRelativePath("/usr/./share/", "/bin/bash", "../../bin/bash");
+ res &= CheckRelativePath("/usr//share/", "/bin/bash", "../../bin/bash");
+ res &=
+ CheckRelativePath("/usr/share/../bin/", "/bin/bash", "../../bin/bash");
+ res &= CheckRelativePath("/usr/share", "/usr/share//bin", "bin");
+ return res;
+}
+
+static bool CheckCollapsePath(const std::string& path,
+ const std::string& expected)
+{
+ std::string result = kwsys::SystemTools::CollapseFullPath(path);
+ if (!kwsys::SystemTools::ComparePath(expected, result)) {
+ std::cerr << "CollapseFullPath(" << path << ") yielded " << result
+ << " instead of " << expected << std::endl;
+ return false;
+ }
+ return true;
+}
+
+static bool CheckCollapsePath()
+{
+ bool res = true;
+ res &= CheckCollapsePath("/usr/share/*", "/usr/share/*");
+ res &= CheckCollapsePath("C:/Windows/*", "C:/Windows/*");
+ return res;
+}
+
+static std::string StringVectorToString(const std::vector<std::string>& vec)
+{
+ std::stringstream ss;
+ ss << "vector(";
+ for (std::vector<std::string>::const_iterator i = vec.begin();
+ i != vec.end(); ++i) {
+ if (i != vec.begin()) {
+ ss << ", ";
+ }
+ ss << *i;
+ }
+ ss << ")";
+ return ss.str();
+}
+
+static bool CheckGetPath()
+{
+ const char* envName = "S";
+#ifdef _WIN32
+ const char* envValue = "C:\\Somewhere\\something;D:\\Temp";
+#else
+ const char* envValue = "/Somewhere/something:/tmp";
+#endif
+ const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]";
+
+ std::vector<std::string> originalPathes;
+ originalPathes.push_back(registryPath);
+
+ std::vector<std::string> expectedPathes;
+ expectedPathes.push_back(registryPath);
+#ifdef _WIN32
+ expectedPathes.push_back("C:/Somewhere/something");
+ expectedPathes.push_back("D:/Temp");
+#else
+ expectedPathes.push_back("/Somewhere/something");
+ expectedPathes.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);
+
+ if (pathes != expectedPathes) {
+ std::cerr << "GetPath(" << StringVectorToString(originalPathes) << ", "
+ << envName << ") yielded " << StringVectorToString(pathes)
+ << " instead of " << StringVectorToString(expectedPathes)
+ << std::endl;
+ res = false;
+ }
+
+ res &= CheckUnPutEnv(envName, envName);
+ return res;
+}
+
+static bool CheckFind()
+{
+ bool res = true;
+ const std::string testFindFileName("testFindFile.txt");
+ const std::string testFindFile(TEST_SYSTEMTOOLS_BINARY_DIR "/" +
+ testFindFileName);
+
+ if (!kwsys::SystemTools::Touch(testFindFile.c_str(), 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;
+ }
+
+ std::vector<std::string> searchPaths;
+ searchPaths.push_back(TEST_SYSTEMTOOLS_BINARY_DIR);
+ if (kwsys::SystemTools::FindFile(testFindFileName, searchPaths, true)
+ .empty()) {
+ std::cerr << "Problem with FindFile without system paths for: "
+ << testFindFileName << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::FindFile(testFindFileName, searchPaths, false)
+ .empty()) {
+ std::cerr << "Problem with FindFile with system paths for: "
+ << testFindFileName << std::endl;
+ res = false;
+ }
+
+ return res;
+}
+
+static bool CheckGetLineFromStream()
+{
+ const std::string fileWithFiveCharsOnFirstLine(TEST_SYSTEMTOOLS_SOURCE_DIR
+ "/README.rst");
+
+ kwsys::ifstream file(fileWithFiveCharsOnFirstLine.c_str(), std::ios::in);
+
+ if (!file) {
+ std::cerr << "Problem opening: " << fileWithFiveCharsOnFirstLine
+ << std::endl;
+ return false;
+ }
+
+ std::string line;
+ bool has_newline = false;
+ bool result;
+
+ file.seekg(0, std::ios::beg);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line.size() != 5) {
+ std::cerr << "First line does not have five characters: " << line.size()
+ << std::endl;
+ return false;
+ }
+
+ file.seekg(0, std::ios::beg);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line.size() != 5) {
+ std::cerr << "First line does not have five characters after rewind: "
+ << line.size() << std::endl;
+ return false;
+ }
+
+ bool ret = true;
+
+ for (size_t size = 1; size <= 5; ++size) {
+ file.seekg(0, std::ios::beg);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
+ static_cast<long>(size));
+ if (!result || line.size() != size) {
+ std::cerr << "Should have read " << size << " characters but got "
+ << line.size() << std::endl;
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+int testSystemTools(int, char* [])
{
bool res = true;
int cc;
- for ( cc = 0; toUnixPaths[cc][0]; cc ++ )
- {
+ for (cc = 0; toUnixPaths[cc][0]; cc++) {
res &= CheckConvertToUnixSlashes(toUnixPaths[cc][0], toUnixPaths[cc][1]);
- }
+ }
// Special check for ~
- kwsys_stl::string output;
- if(kwsys::SystemTools::GetEnv("HOME", output))
- {
+ std::string output;
+ if (kwsys::SystemTools::GetEnv("HOME", output)) {
output += "/foo bar/lala";
res &= CheckConvertToUnixSlashes("~/foo bar/lala", output);
- }
+ }
- for (cc = 0; checkEscapeChars[cc][0]; cc ++ )
- {
- res &= CheckEscapeChars(checkEscapeChars[cc][0], checkEscapeChars[cc][1],
+ for (cc = 0; checkEscapeChars[cc][0]; cc++) {
+ res &= CheckEscapeChars(checkEscapeChars[cc][0], checkEscapeChars[cc][1],
*checkEscapeChars[cc][2], checkEscapeChars[cc][3]);
- }
+ }
res &= CheckFileOperations();
@@ -410,5 +865,15 @@ int testSystemTools(int, char*[])
res &= CheckEnvironmentOperations();
+ res &= CheckRelativePaths();
+
+ res &= CheckCollapsePath();
+
+ res &= CheckGetPath();
+
+ res &= CheckFind();
+
+ res &= CheckGetLineFromStream();
+
return res ? 0 : 1;
}
diff --git a/Source/kwsys/testSystemTools.h.in b/Source/kwsys/testSystemTools.h.in
index 4b94bb6af..022e36e2f 100644
--- a/Source/kwsys/testSystemTools.h.in
+++ b/Source/kwsys/testSystemTools.h.in
@@ -1,20 +1,12 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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@_testSystemtools_h
#define @KWSYS_NAMESPACE@_testSystemtools_h
#define EXECUTABLE_OUTPUT_PATH "@CMAKE_CURRENT_BINARY_DIR@"
-#define TEST_SYSTEMTOOLS_BIN_FILE "@TEST_SYSTEMTOOLS_BIN_FILE@"
-#define TEST_SYSTEMTOOLS_SRC_FILE "@TEST_SYSTEMTOOLS_SRC_FILE@"
+#define TEST_SYSTEMTOOLS_SOURCE_DIR "@TEST_SYSTEMTOOLS_SOURCE_DIR@"
+#define TEST_SYSTEMTOOLS_BINARY_DIR "@TEST_SYSTEMTOOLS_BINARY_DIR@"
+#cmakedefine KWSYS_TEST_SYSTEMTOOLS_LONG_PATHS
#endif
diff --git a/Source/kwsys/testTerminal.c b/Source/kwsys/testTerminal.c
index 0d2d7a77b..f6c1eddb7 100644
--- a/Source/kwsys/testTerminal.c
+++ b/Source/kwsys/testTerminal.c
@@ -1,21 +1,12 @@
-/*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
-============================================================================*/
+/* 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(Terminal.h)
/* 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[])
@@ -23,8 +14,8 @@ int testTerminal(int argc, char* argv[])
(void)argc;
(void)argv;
kwsysTerminal_cfprintf(kwsysTerminal_Color_ForegroundYellow |
- kwsysTerminal_Color_BackgroundBlue |
- kwsysTerminal_Color_AssumeTTY,
+ kwsysTerminal_Color_BackgroundBlue |
+ kwsysTerminal_Color_AssumeTTY,
stdout, "Hello %s!", "World");
fprintf(stdout, "\n");
return 0;